1 /* 2 * bebob_focusrite.c - a part of driver for BeBoB based devices 3 * 4 * Copyright (c) 2013-2014 Takashi Sakamoto 5 * 6 * Licensed under the terms of the GNU General Public License, version 2. 7 */ 8 9 #include "./bebob.h" 10 11 #define ANA_IN "Analog In" 12 #define DIG_IN "Digital In" 13 #define ANA_OUT "Analog Out" 14 #define DIG_OUT "Digital Out" 15 #define STM_IN "Stream In" 16 17 #define SAFFIRE_ADDRESS_BASE 0x000100000000ULL 18 19 #define SAFFIRE_OFFSET_CLOCK_SOURCE 0x00f8 20 #define SAFFIREPRO_OFFSET_CLOCK_SOURCE 0x0174 21 22 /* whether sync to external device or not */ 23 #define SAFFIRE_OFFSET_CLOCK_SYNC_EXT 0x013c 24 #define SAFFIRE_LE_OFFSET_CLOCK_SYNC_EXT 0x0432 25 #define SAFFIREPRO_OFFSET_CLOCK_SYNC_EXT 0x0164 26 27 #define SAFFIRE_CLOCK_SOURCE_INTERNAL 0 28 #define SAFFIRE_CLOCK_SOURCE_SPDIF 1 29 30 /* clock sources as returned from register of Saffire Pro 10 and 26 */ 31 #define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0 32 #define SAFFIREPRO_CLOCK_SOURCE_SKIP 1 /* never used on hardware */ 33 #define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2 34 #define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 /* not used on s.pro. 10 */ 35 #define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 /* not used on s.pro. 10 */ 36 #define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5 37 #define SAFFIREPRO_CLOCK_SOURCE_COUNT 6 38 39 /* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */ 40 #define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4 41 42 /* saffirepro has its own parameter for sampling frequency */ 43 #define SAFFIREPRO_RATE_NOREBOOT 0x01cc 44 /* index is the value for this register */ 45 static const unsigned int rates[] = { 46 [0] = 0, 47 [1] = 44100, 48 [2] = 48000, 49 [3] = 88200, 50 [4] = 96000, 51 [5] = 176400, 52 [6] = 192000 53 }; 54 55 /* saffire(no label)/saffire LE has metering */ 56 #define SAFFIRE_OFFSET_METER 0x0100 57 #define SAFFIRE_LE_OFFSET_METER 0x0168 58 59 static inline int 60 saffire_read_block(struct snd_bebob *bebob, u64 offset, 61 u32 *buf, unsigned int size) 62 { 63 unsigned int i; 64 int err; 65 __be32 *tmp = (__be32 *)buf; 66 67 err = snd_fw_transaction(bebob->unit, TCODE_READ_BLOCK_REQUEST, 68 SAFFIRE_ADDRESS_BASE + offset, 69 tmp, size, 0); 70 if (err < 0) 71 goto end; 72 73 for (i = 0; i < size / sizeof(u32); i++) 74 buf[i] = be32_to_cpu(tmp[i]); 75 end: 76 return err; 77 } 78 79 static inline int 80 saffire_read_quad(struct snd_bebob *bebob, u64 offset, u32 *value) 81 { 82 int err; 83 __be32 tmp; 84 85 err = snd_fw_transaction(bebob->unit, TCODE_READ_QUADLET_REQUEST, 86 SAFFIRE_ADDRESS_BASE + offset, 87 &tmp, sizeof(__be32), 0); 88 if (err < 0) 89 goto end; 90 91 *value = be32_to_cpu(tmp); 92 end: 93 return err; 94 } 95 96 static inline int 97 saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value) 98 { 99 __be32 data = cpu_to_be32(value); 100 101 return snd_fw_transaction(bebob->unit, TCODE_WRITE_QUADLET_REQUEST, 102 SAFFIRE_ADDRESS_BASE + offset, 103 &data, sizeof(__be32), 0); 104 } 105 106 static const enum snd_bebob_clock_type saffirepro_10_clk_src_types[] = { 107 SND_BEBOB_CLOCK_TYPE_INTERNAL, 108 SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ 109 SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ 110 }; 111 static const enum snd_bebob_clock_type saffirepro_26_clk_src_types[] = { 112 SND_BEBOB_CLOCK_TYPE_INTERNAL, 113 SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ 114 SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT1 */ 115 SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* ADAT2 */ 116 SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* Word Clock */ 117 }; 118 /* Value maps between registers and labels for SaffirePro 10/26. */ 119 static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = { 120 /* SaffirePro 10 */ 121 [0] = { 122 [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0, 123 [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */ 124 [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1, 125 [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = -1, /* not supported */ 126 [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = -1, /* not supported */ 127 [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 2, 128 }, 129 /* SaffirePro 26 */ 130 [1] = { 131 [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0, 132 [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */ 133 [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1, 134 [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = 2, 135 [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = 3, 136 [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 4, 137 } 138 }; 139 140 static int 141 saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate) 142 { 143 u32 id; 144 int err; 145 146 err = saffire_read_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, &id); 147 if (err < 0) 148 goto end; 149 if (id >= ARRAY_SIZE(rates)) 150 err = -EIO; 151 else 152 *rate = rates[id]; 153 end: 154 return err; 155 } 156 static int 157 saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate) 158 { 159 u32 id; 160 161 for (id = 0; id < ARRAY_SIZE(rates); id++) { 162 if (rates[id] == rate) 163 break; 164 } 165 if (id == ARRAY_SIZE(rates)) 166 return -EINVAL; 167 168 return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id); 169 } 170 171 /* 172 * query hardware for current clock source, return our internally 173 * used clock index in *id, depending on hardware. 174 */ 175 static int 176 saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) 177 { 178 int err; 179 u32 value; /* clock source read from hw register */ 180 const signed char *map; 181 182 err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value); 183 if (err < 0) 184 goto end; 185 186 /* depending on hardware, use a different mapping */ 187 if (bebob->spec->clock->types == saffirepro_10_clk_src_types) 188 map = saffirepro_clk_maps[0]; 189 else 190 map = saffirepro_clk_maps[1]; 191 192 /* In a case that this driver cannot handle the value of register. */ 193 if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) { 194 err = -EIO; 195 goto end; 196 } 197 198 *id = (unsigned int)map[value]; 199 end: 200 return err; 201 } 202 203 const struct snd_bebob_spec saffire_le_spec; 204 static const enum snd_bebob_clock_type saffire_both_clk_src_types[] = { 205 SND_BEBOB_CLOCK_TYPE_INTERNAL, 206 SND_BEBOB_CLOCK_TYPE_EXTERNAL, 207 }; 208 static int 209 saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) 210 { 211 int err; 212 u32 value; 213 214 err = saffire_read_quad(bebob, SAFFIRE_OFFSET_CLOCK_SOURCE, &value); 215 if (err >= 0) 216 *id = 0xff & value; 217 218 return err; 219 }; 220 static const char *const saffire_le_meter_labels[] = { 221 ANA_IN, ANA_IN, DIG_IN, 222 ANA_OUT, ANA_OUT, ANA_OUT, ANA_OUT, 223 STM_IN, STM_IN 224 }; 225 static const char *const saffire_meter_labels[] = { 226 ANA_IN, ANA_IN, 227 STM_IN, STM_IN, STM_IN, STM_IN, STM_IN, 228 }; 229 static int 230 saffire_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size) 231 { 232 const struct snd_bebob_meter_spec *spec = bebob->spec->meter; 233 unsigned int channels; 234 u64 offset; 235 int err; 236 237 if (spec->labels == saffire_le_meter_labels) 238 offset = SAFFIRE_LE_OFFSET_METER; 239 else 240 offset = SAFFIRE_OFFSET_METER; 241 242 channels = spec->num * 2; 243 if (size < channels * sizeof(u32)) 244 return -EIO; 245 246 err = saffire_read_block(bebob, offset, buf, size); 247 if (err >= 0 && spec->labels == saffire_le_meter_labels) { 248 swap(buf[1], buf[3]); 249 swap(buf[2], buf[3]); 250 swap(buf[3], buf[4]); 251 252 swap(buf[7], buf[10]); 253 swap(buf[8], buf[10]); 254 swap(buf[9], buf[11]); 255 swap(buf[11], buf[12]); 256 257 swap(buf[15], buf[16]); 258 } 259 260 return err; 261 } 262 263 static const struct snd_bebob_rate_spec saffirepro_both_rate_spec = { 264 .get = &saffirepro_both_clk_freq_get, 265 .set = &saffirepro_both_clk_freq_set, 266 }; 267 /* Saffire Pro 26 I/O */ 268 static const struct snd_bebob_clock_spec saffirepro_26_clk_spec = { 269 .num = ARRAY_SIZE(saffirepro_26_clk_src_types), 270 .types = saffirepro_26_clk_src_types, 271 .get = &saffirepro_both_clk_src_get, 272 }; 273 const struct snd_bebob_spec saffirepro_26_spec = { 274 .clock = &saffirepro_26_clk_spec, 275 .rate = &saffirepro_both_rate_spec, 276 .meter = NULL 277 }; 278 /* Saffire Pro 10 I/O */ 279 static const struct snd_bebob_clock_spec saffirepro_10_clk_spec = { 280 .num = ARRAY_SIZE(saffirepro_10_clk_src_types), 281 .types = saffirepro_10_clk_src_types, 282 .get = &saffirepro_both_clk_src_get, 283 }; 284 const struct snd_bebob_spec saffirepro_10_spec = { 285 .clock = &saffirepro_10_clk_spec, 286 .rate = &saffirepro_both_rate_spec, 287 .meter = NULL 288 }; 289 290 static const struct snd_bebob_rate_spec saffire_both_rate_spec = { 291 .get = &snd_bebob_stream_get_rate, 292 .set = &snd_bebob_stream_set_rate, 293 }; 294 static const struct snd_bebob_clock_spec saffire_both_clk_spec = { 295 .num = ARRAY_SIZE(saffire_both_clk_src_types), 296 .types = saffire_both_clk_src_types, 297 .get = &saffire_both_clk_src_get, 298 }; 299 /* Saffire LE */ 300 static const struct snd_bebob_meter_spec saffire_le_meter_spec = { 301 .num = ARRAY_SIZE(saffire_le_meter_labels), 302 .labels = saffire_le_meter_labels, 303 .get = &saffire_meter_get, 304 }; 305 const struct snd_bebob_spec saffire_le_spec = { 306 .clock = &saffire_both_clk_spec, 307 .rate = &saffire_both_rate_spec, 308 .meter = &saffire_le_meter_spec 309 }; 310 /* Saffire */ 311 static const struct snd_bebob_meter_spec saffire_meter_spec = { 312 .num = ARRAY_SIZE(saffire_meter_labels), 313 .labels = saffire_meter_labels, 314 .get = &saffire_meter_get, 315 }; 316 const struct snd_bebob_spec saffire_spec = { 317 .clock = &saffire_both_clk_spec, 318 .rate = &saffire_both_rate_spec, 319 .meter = &saffire_meter_spec 320 }; 321