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 */ 45static 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 59static inline int 60saffire_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]); 75end: 76 return err; 77} 78 79static inline int 80saffire_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); 92end: 93 return err; 94} 95 96static inline int 97saffire_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 106static const char *const saffirepro_10_clk_src_labels[] = { 107 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" 108}; 109static const char *const saffirepro_26_clk_src_labels[] = { 110 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" 111}; 112/* Value maps between registers and labels for SaffirePro 10/26. */ 113static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = { 114 /* SaffirePro 10 */ 115 [0] = { 116 [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0, 117 [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */ 118 [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1, 119 [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = -1, /* not supported */ 120 [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = -1, /* not supported */ 121 [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 2, 122 }, 123 /* SaffirePro 26 */ 124 [1] = { 125 [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0, 126 [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */ 127 [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1, 128 [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = 2, 129 [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = 3, 130 [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 4, 131 } 132}; 133 134static int 135saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate) 136{ 137 u32 id; 138 int err; 139 140 err = saffire_read_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, &id); 141 if (err < 0) 142 goto end; 143 if (id >= ARRAY_SIZE(rates)) 144 err = -EIO; 145 else 146 *rate = rates[id]; 147end: 148 return err; 149} 150static int 151saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate) 152{ 153 u32 id; 154 155 for (id = 0; id < ARRAY_SIZE(rates); id++) { 156 if (rates[id] == rate) 157 break; 158 } 159 if (id == ARRAY_SIZE(rates)) 160 return -EINVAL; 161 162 return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id); 163} 164 165/* 166 * query hardware for current clock source, return our internally 167 * used clock index in *id, depending on hardware. 168 */ 169static int 170saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) 171{ 172 int err; 173 u32 value; /* clock source read from hw register */ 174 const signed char *map; 175 176 err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value); 177 if (err < 0) 178 goto end; 179 180 /* depending on hardware, use a different mapping */ 181 if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) 182 map = saffirepro_clk_maps[0]; 183 else 184 map = saffirepro_clk_maps[1]; 185 186 /* In a case that this driver cannot handle the value of register. */ 187 if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) { 188 err = -EIO; 189 goto end; 190 } 191 192 *id = (unsigned int)map[value]; 193end: 194 return err; 195} 196 197struct snd_bebob_spec saffire_le_spec; 198static const char *const saffire_both_clk_src_labels[] = { 199 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF" 200}; 201static int 202saffire_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) 203{ 204 int err; 205 u32 value; 206 207 err = saffire_read_quad(bebob, SAFFIRE_OFFSET_CLOCK_SOURCE, &value); 208 if (err >= 0) 209 *id = 0xff & value; 210 211 return err; 212}; 213static const char *const saffire_le_meter_labels[] = { 214 ANA_IN, ANA_IN, DIG_IN, 215 ANA_OUT, ANA_OUT, ANA_OUT, ANA_OUT, 216 STM_IN, STM_IN 217}; 218static const char *const saffire_meter_labels[] = { 219 ANA_IN, ANA_IN, 220 STM_IN, STM_IN, STM_IN, STM_IN, STM_IN, 221}; 222static int 223saffire_meter_get(struct snd_bebob *bebob, u32 *buf, unsigned int size) 224{ 225 struct snd_bebob_meter_spec *spec = bebob->spec->meter; 226 unsigned int channels; 227 u64 offset; 228 int err; 229 230 if (spec->labels == saffire_le_meter_labels) 231 offset = SAFFIRE_LE_OFFSET_METER; 232 else 233 offset = SAFFIRE_OFFSET_METER; 234 235 channels = spec->num * 2; 236 if (size < channels * sizeof(u32)) 237 return -EIO; 238 239 err = saffire_read_block(bebob, offset, buf, size); 240 if (err >= 0 && spec->labels == saffire_le_meter_labels) { 241 swap(buf[1], buf[3]); 242 swap(buf[2], buf[3]); 243 swap(buf[3], buf[4]); 244 245 swap(buf[7], buf[10]); 246 swap(buf[8], buf[10]); 247 swap(buf[9], buf[11]); 248 swap(buf[11], buf[12]); 249 250 swap(buf[15], buf[16]); 251 } 252 253 return err; 254} 255 256static struct snd_bebob_rate_spec saffirepro_both_rate_spec = { 257 .get = &saffirepro_both_clk_freq_get, 258 .set = &saffirepro_both_clk_freq_set, 259}; 260/* Saffire Pro 26 I/O */ 261static struct snd_bebob_clock_spec saffirepro_26_clk_spec = { 262 .num = ARRAY_SIZE(saffirepro_26_clk_src_labels), 263 .labels = saffirepro_26_clk_src_labels, 264 .get = &saffirepro_both_clk_src_get, 265}; 266struct snd_bebob_spec saffirepro_26_spec = { 267 .clock = &saffirepro_26_clk_spec, 268 .rate = &saffirepro_both_rate_spec, 269 .meter = NULL 270}; 271/* Saffire Pro 10 I/O */ 272static struct snd_bebob_clock_spec saffirepro_10_clk_spec = { 273 .num = ARRAY_SIZE(saffirepro_10_clk_src_labels), 274 .labels = saffirepro_10_clk_src_labels, 275 .get = &saffirepro_both_clk_src_get, 276}; 277struct snd_bebob_spec saffirepro_10_spec = { 278 .clock = &saffirepro_10_clk_spec, 279 .rate = &saffirepro_both_rate_spec, 280 .meter = NULL 281}; 282 283static struct snd_bebob_rate_spec saffire_both_rate_spec = { 284 .get = &snd_bebob_stream_get_rate, 285 .set = &snd_bebob_stream_set_rate, 286}; 287static struct snd_bebob_clock_spec saffire_both_clk_spec = { 288 .num = ARRAY_SIZE(saffire_both_clk_src_labels), 289 .labels = saffire_both_clk_src_labels, 290 .get = &saffire_both_clk_src_get, 291}; 292/* Saffire LE */ 293static struct snd_bebob_meter_spec saffire_le_meter_spec = { 294 .num = ARRAY_SIZE(saffire_le_meter_labels), 295 .labels = saffire_le_meter_labels, 296 .get = &saffire_meter_get, 297}; 298struct snd_bebob_spec saffire_le_spec = { 299 .clock = &saffire_both_clk_spec, 300 .rate = &saffire_both_rate_spec, 301 .meter = &saffire_le_meter_spec 302}; 303/* Saffire */ 304static struct snd_bebob_meter_spec saffire_meter_spec = { 305 .num = ARRAY_SIZE(saffire_meter_labels), 306 .labels = saffire_meter_labels, 307 .get = &saffire_meter_get, 308}; 309struct snd_bebob_spec saffire_spec = { 310 .clock = &saffire_both_clk_spec, 311 .rate = &saffire_both_rate_spec, 312 .meter = &saffire_meter_spec 313}; 314