aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/bebob/bebob_focusrite.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire/bebob/bebob_focusrite.c')
-rw-r--r--sound/firewire/bebob/bebob_focusrite.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/sound/firewire/bebob/bebob_focusrite.c b/sound/firewire/bebob/bebob_focusrite.c
index 45a0eed6d5b1..3b052ed0fbf5 100644
--- a/sound/firewire/bebob/bebob_focusrite.c
+++ b/sound/firewire/bebob/bebob_focusrite.c
@@ -27,12 +27,14 @@
27#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0 27#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0
28#define SAFFIRE_CLOCK_SOURCE_SPDIF 1 28#define SAFFIRE_CLOCK_SOURCE_SPDIF 1
29 29
30/* '1' is absent, why... */ 30/* clock sources as returned from register of Saffire Pro 10 and 26 */
31#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0 31#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0
32#define SAFFIREPRO_CLOCK_SOURCE_SKIP 1 /* never used on hardware */
32#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2 33#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2
33#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 34#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 /* not used on s.pro. 10 */
34#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 35#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 /* not used on s.pro. 10 */
35#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5 36#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5
37#define SAFFIREPRO_CLOCK_SOURCE_COUNT 6
36 38
37/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */ 39/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
38#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4 40#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4
@@ -101,13 +103,34 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value)
101 &data, sizeof(__be32), 0); 103 &data, sizeof(__be32), 0);
102} 104}
103 105
106static char *const saffirepro_10_clk_src_labels[] = {
107 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
108};
104static char *const saffirepro_26_clk_src_labels[] = { 109static char *const saffirepro_26_clk_src_labels[] = {
105 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" 110 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock"
106}; 111};
107 112/* Value maps between registers and labels for SaffirePro 10/26. */
108static char *const saffirepro_10_clk_src_labels[] = { 113static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = {
109 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" 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 }
110}; 132};
133
111static int 134static int
112saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate) 135saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
113{ 136{
@@ -138,24 +161,35 @@ saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate)
138 161
139 return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id); 162 return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
140} 163}
164
165/*
166 * query hardware for current clock source, return our internally
167 * used clock index in *id, depending on hardware.
168 */
141static int 169static int
142saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) 170saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
143{ 171{
144 int err; 172 int err;
145 u32 value; 173 u32 value; /* clock source read from hw register */
174 const signed char *map;
146 175
147 err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value); 176 err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
148 if (err < 0) 177 if (err < 0)
149 goto end; 178 goto end;
150 179
151 if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) { 180 /* depending on hardware, use a different mapping */
152 if (value == SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK) 181 if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels)
153 *id = 2; 182 map = saffirepro_clk_maps[0];
154 else if (value == SAFFIREPRO_CLOCK_SOURCE_SPDIF) 183 else
155 *id = 1; 184 map = saffirepro_clk_maps[1];
156 } else if (value > 1) { 185
157 *id = value - 1; 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;
158 } 190 }
191
192 *id = (unsigned int)map[value];
159end: 193end:
160 return err; 194 return err;
161} 195}