0001
0002
0003
0004
0005
0006
0007
0008 #include "dice.h"
0009
0010
0011
0012 #define DICE_EXT_APP_SPACE 0xffffe0200000uLL
0013
0014 #define DICE_EXT_APP_CAPS_OFFSET 0x00
0015 #define DICE_EXT_APP_CAPS_SIZE 0x04
0016 #define DICE_EXT_APP_CMD_OFFSET 0x08
0017 #define DICE_EXT_APP_CMD_SIZE 0x0c
0018 #define DICE_EXT_APP_MIXER_OFFSET 0x10
0019 #define DICE_EXT_APP_MIXER_SIZE 0x14
0020 #define DICE_EXT_APP_PEAK_OFFSET 0x18
0021 #define DICE_EXT_APP_PEAK_SIZE 0x1c
0022 #define DICE_EXT_APP_ROUTER_OFFSET 0x20
0023 #define DICE_EXT_APP_ROUTER_SIZE 0x24
0024 #define DICE_EXT_APP_STREAM_OFFSET 0x28
0025 #define DICE_EXT_APP_STREAM_SIZE 0x2c
0026 #define DICE_EXT_APP_CURRENT_OFFSET 0x30
0027 #define DICE_EXT_APP_CURRENT_SIZE 0x34
0028 #define DICE_EXT_APP_STANDALONE_OFFSET 0x38
0029 #define DICE_EXT_APP_STANDALONE_SIZE 0x3c
0030 #define DICE_EXT_APP_APPLICATION_OFFSET 0x40
0031 #define DICE_EXT_APP_APPLICATION_SIZE 0x44
0032
0033 #define EXT_APP_STREAM_TX_NUMBER 0x0000
0034 #define EXT_APP_STREAM_RX_NUMBER 0x0004
0035 #define EXT_APP_STREAM_ENTRIES 0x0008
0036 #define EXT_APP_STREAM_ENTRY_SIZE 0x010c
0037 #define EXT_APP_NUMBER_AUDIO 0x0000
0038 #define EXT_APP_NUMBER_MIDI 0x0004
0039 #define EXT_APP_NAMES 0x0008
0040 #define EXT_APP_NAMES_SIZE 256
0041 #define EXT_APP_AC3 0x0108
0042
0043 #define EXT_APP_CONFIG_LOW_ROUTER 0x0000
0044 #define EXT_APP_CONFIG_LOW_STREAM 0x1000
0045 #define EXT_APP_CONFIG_MIDDLE_ROUTER 0x2000
0046 #define EXT_APP_CONFIG_MIDDLE_STREAM 0x3000
0047 #define EXT_APP_CONFIG_HIGH_ROUTER 0x4000
0048 #define EXT_APP_CONFIG_HIGH_STREAM 0x5000
0049
0050 static inline int read_transaction(struct snd_dice *dice, u64 section_addr,
0051 u32 offset, void *buf, size_t len)
0052 {
0053 return snd_fw_transaction(dice->unit,
0054 len == 4 ? TCODE_READ_QUADLET_REQUEST :
0055 TCODE_READ_BLOCK_REQUEST,
0056 section_addr + offset, buf, len, 0);
0057 }
0058
0059 static int read_stream_entries(struct snd_dice *dice, u64 section_addr,
0060 u32 base_offset, unsigned int stream_count,
0061 unsigned int mode,
0062 unsigned int pcm_channels[MAX_STREAMS][3],
0063 unsigned int midi_ports[MAX_STREAMS])
0064 {
0065 u32 entry_offset;
0066 __be32 reg[2];
0067 int err;
0068 int i;
0069
0070 for (i = 0; i < stream_count; ++i) {
0071 entry_offset = base_offset + i * EXT_APP_STREAM_ENTRY_SIZE;
0072 err = read_transaction(dice, section_addr,
0073 entry_offset + EXT_APP_NUMBER_AUDIO,
0074 reg, sizeof(reg));
0075 if (err < 0)
0076 return err;
0077 pcm_channels[i][mode] = be32_to_cpu(reg[0]);
0078 midi_ports[i] = max(midi_ports[i], be32_to_cpu(reg[1]));
0079 }
0080
0081 return 0;
0082 }
0083
0084 static int detect_stream_formats(struct snd_dice *dice, u64 section_addr)
0085 {
0086 u32 base_offset;
0087 __be32 reg[2];
0088 unsigned int stream_count;
0089 int mode;
0090 int err = 0;
0091
0092 for (mode = 0; mode < SND_DICE_RATE_MODE_COUNT; ++mode) {
0093 unsigned int cap;
0094
0095
0096
0097
0098
0099 if (mode == 2) {
0100 cap = CLOCK_CAP_RATE_176400 | CLOCK_CAP_RATE_192000;
0101 } else if (mode == 1) {
0102 cap = CLOCK_CAP_RATE_88200 | CLOCK_CAP_RATE_96000;
0103 } else {
0104 cap = CLOCK_CAP_RATE_32000 | CLOCK_CAP_RATE_44100 |
0105 CLOCK_CAP_RATE_48000;
0106 }
0107 if (!(cap & dice->clock_caps))
0108 continue;
0109
0110 base_offset = 0x2000 * mode + 0x1000;
0111
0112 err = read_transaction(dice, section_addr,
0113 base_offset + EXT_APP_STREAM_TX_NUMBER,
0114 ®, sizeof(reg));
0115 if (err < 0)
0116 break;
0117
0118 base_offset += EXT_APP_STREAM_ENTRIES;
0119 stream_count = be32_to_cpu(reg[0]);
0120 err = read_stream_entries(dice, section_addr, base_offset,
0121 stream_count, mode,
0122 dice->tx_pcm_chs,
0123 dice->tx_midi_ports);
0124 if (err < 0)
0125 break;
0126
0127 base_offset += stream_count * EXT_APP_STREAM_ENTRY_SIZE;
0128 stream_count = be32_to_cpu(reg[1]);
0129 err = read_stream_entries(dice, section_addr, base_offset,
0130 stream_count,
0131 mode, dice->rx_pcm_chs,
0132 dice->rx_midi_ports);
0133 if (err < 0)
0134 break;
0135 }
0136
0137 return err;
0138 }
0139
0140 int snd_dice_detect_extension_formats(struct snd_dice *dice)
0141 {
0142 __be32 *pointers;
0143 unsigned int i;
0144 u64 section_addr;
0145 int err;
0146
0147 pointers = kmalloc_array(9, sizeof(__be32) * 2, GFP_KERNEL);
0148 if (pointers == NULL)
0149 return -ENOMEM;
0150
0151 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
0152 DICE_EXT_APP_SPACE, pointers,
0153 9 * sizeof(__be32) * 2, 0);
0154 if (err < 0)
0155 goto end;
0156
0157
0158 for (i = 0; i < 9; ++i) {
0159 int j;
0160
0161 for (j = i + 1; j < 9; ++j) {
0162 if (pointers[i * 2] == pointers[j * 2]) {
0163
0164 err = -ENXIO;
0165 goto end;
0166 }
0167 }
0168 }
0169
0170 section_addr = DICE_EXT_APP_SPACE + be32_to_cpu(pointers[12]) * 4;
0171 err = detect_stream_formats(dice, section_addr);
0172 end:
0173 kfree(pointers);
0174 return err;
0175 }