1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * C-Media CMI8788 driver for C-Media's reference design and similar models |
4 | * |
5 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
6 | */ |
7 | |
8 | /* |
9 | * CMI8788: |
10 | * |
11 | * SPI 0 -> 1st AK4396 (front) |
12 | * SPI 1 -> 2nd AK4396 (surround) |
13 | * SPI 2 -> 3rd AK4396 (center/LFE) |
14 | * SPI 3 -> WM8785 |
15 | * SPI 4 -> 4th AK4396 (back) |
16 | * |
17 | * GPIO 0 -> DFS0 of AK5385 |
18 | * GPIO 1 -> DFS1 of AK5385 |
19 | * |
20 | * X-Meridian models: |
21 | * GPIO 4 -> enable extension S/PDIF input |
22 | * GPIO 6 -> enable on-board S/PDIF input |
23 | * |
24 | * Claro models: |
25 | * GPIO 6 -> S/PDIF from optical (0) or coaxial (1) input |
26 | * GPIO 8 -> enable headphone amplifier |
27 | * |
28 | * CM9780: |
29 | * |
30 | * LINE_OUT -> input of ADC |
31 | * |
32 | * AUX_IN <- aux |
33 | * CD_IN <- CD |
34 | * MIC_IN <- mic |
35 | * |
36 | * GPO 0 -> route line-in (0) or AC97 output (1) to ADC input |
37 | */ |
38 | |
39 | #include <linux/delay.h> |
40 | #include <linux/mutex.h> |
41 | #include <linux/pci.h> |
42 | #include <linux/module.h> |
43 | #include <sound/ac97_codec.h> |
44 | #include <sound/control.h> |
45 | #include <sound/core.h> |
46 | #include <sound/info.h> |
47 | #include <sound/initval.h> |
48 | #include <sound/pcm.h> |
49 | #include <sound/pcm_params.h> |
50 | #include <sound/tlv.h> |
51 | #include "oxygen.h" |
52 | #include "xonar_dg.h" |
53 | #include "ak4396.h" |
54 | #include "wm8785.h" |
55 | |
56 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>" ); |
57 | MODULE_DESCRIPTION("C-Media CMI8788 driver" ); |
58 | MODULE_LICENSE("GPL v2" ); |
59 | |
60 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
61 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
62 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; |
63 | |
64 | module_param_array(index, int, NULL, 0444); |
65 | MODULE_PARM_DESC(index, "card index" ); |
66 | module_param_array(id, charp, NULL, 0444); |
67 | MODULE_PARM_DESC(id, "ID string" ); |
68 | module_param_array(enable, bool, NULL, 0444); |
69 | MODULE_PARM_DESC(enable, "enable card" ); |
70 | |
71 | enum { |
72 | MODEL_CMEDIA_REF, |
73 | MODEL_MERIDIAN, |
74 | MODEL_MERIDIAN_2G, |
75 | MODEL_CLARO, |
76 | MODEL_CLARO_HALO, |
77 | MODEL_FANTASIA, |
78 | MODEL_SERENADE, |
79 | MODEL_2CH_OUTPUT, |
80 | MODEL_HG2PCI, |
81 | MODEL_XONAR_DG, |
82 | MODEL_XONAR_DGX, |
83 | }; |
84 | |
85 | static const struct pci_device_id oxygen_ids[] = { |
86 | /* C-Media's reference design */ |
87 | { OXYGEN_PCI_SUBID(0x10b0, 0x0216), .driver_data = MODEL_CMEDIA_REF }, |
88 | { OXYGEN_PCI_SUBID(0x10b0, 0x0217), .driver_data = MODEL_CMEDIA_REF }, |
89 | { OXYGEN_PCI_SUBID(0x10b0, 0x0218), .driver_data = MODEL_CMEDIA_REF }, |
90 | { OXYGEN_PCI_SUBID(0x10b0, 0x0219), .driver_data = MODEL_CMEDIA_REF }, |
91 | { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, |
92 | { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, |
93 | { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, |
94 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, |
95 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, |
96 | /* Asus Xonar DG */ |
97 | { OXYGEN_PCI_SUBID(0x1043, 0x8467), .driver_data = MODEL_XONAR_DG }, |
98 | /* Asus Xonar DGX */ |
99 | { OXYGEN_PCI_SUBID(0x1043, 0x8521), .driver_data = MODEL_XONAR_DGX }, |
100 | /* PCI 2.0 HD Audio */ |
101 | { OXYGEN_PCI_SUBID(0x13f6, 0x8782), .driver_data = MODEL_2CH_OUTPUT }, |
102 | /* Kuroutoshikou CMI8787-HG2PCI */ |
103 | { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_HG2PCI }, |
104 | /* TempoTec HiFier Fantasia */ |
105 | { OXYGEN_PCI_SUBID(0x14c3, 0x1710), .driver_data = MODEL_FANTASIA }, |
106 | /* TempoTec HiFier Serenade */ |
107 | { OXYGEN_PCI_SUBID(0x14c3, 0x1711), .driver_data = MODEL_SERENADE }, |
108 | /* AuzenTech X-Meridian */ |
109 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, |
110 | /* AuzenTech X-Meridian 2G */ |
111 | { OXYGEN_PCI_SUBID(0x5431, 0x017a), .driver_data = MODEL_MERIDIAN_2G }, |
112 | /* HT-Omega Claro */ |
113 | { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, |
114 | /* HT-Omega Claro halo */ |
115 | { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, |
116 | { } |
117 | }; |
118 | MODULE_DEVICE_TABLE(pci, oxygen_ids); |
119 | |
120 | |
121 | #define GPIO_AK5385_DFS_MASK 0x0003 |
122 | #define GPIO_AK5385_DFS_NORMAL 0x0000 |
123 | #define GPIO_AK5385_DFS_DOUBLE 0x0001 |
124 | #define GPIO_AK5385_DFS_QUAD 0x0002 |
125 | |
126 | #define GPIO_MERIDIAN_DIG_MASK 0x0050 |
127 | #define GPIO_MERIDIAN_DIG_EXT 0x0010 |
128 | #define GPIO_MERIDIAN_DIG_BOARD 0x0040 |
129 | |
130 | #define GPIO_CLARO_DIG_COAX 0x0040 |
131 | #define GPIO_CLARO_HP 0x0100 |
132 | |
133 | struct generic_data { |
134 | unsigned int dacs; |
135 | u8 ak4396_regs[4][5]; |
136 | u16 wm8785_regs[3]; |
137 | }; |
138 | |
139 | static void ak4396_write(struct oxygen *chip, unsigned int codec, |
140 | u8 reg, u8 value) |
141 | { |
142 | /* maps ALSA channel pair number to SPI output */ |
143 | static const u8 codec_spi_map[4] = { |
144 | 0, 1, 2, 4 |
145 | }; |
146 | struct generic_data *data = chip->model_data; |
147 | |
148 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | |
149 | OXYGEN_SPI_DATA_LENGTH_2 | |
150 | OXYGEN_SPI_CLOCK_160 | |
151 | (codec_spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) | |
152 | OXYGEN_SPI_CEN_LATCH_CLOCK_HI, |
153 | AK4396_WRITE | (reg << 8) | value); |
154 | data->ak4396_regs[codec][reg] = value; |
155 | } |
156 | |
157 | static void ak4396_write_cached(struct oxygen *chip, unsigned int codec, |
158 | u8 reg, u8 value) |
159 | { |
160 | struct generic_data *data = chip->model_data; |
161 | |
162 | if (value != data->ak4396_regs[codec][reg]) |
163 | ak4396_write(chip, codec, reg, value); |
164 | } |
165 | |
166 | static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value) |
167 | { |
168 | struct generic_data *data = chip->model_data; |
169 | |
170 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | |
171 | OXYGEN_SPI_DATA_LENGTH_2 | |
172 | OXYGEN_SPI_CLOCK_160 | |
173 | (3 << OXYGEN_SPI_CODEC_SHIFT) | |
174 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, |
175 | data: (reg << 9) | value); |
176 | if (reg < ARRAY_SIZE(data->wm8785_regs)) |
177 | data->wm8785_regs[reg] = value; |
178 | } |
179 | |
180 | static void ak4396_registers_init(struct oxygen *chip) |
181 | { |
182 | struct generic_data *data = chip->model_data; |
183 | unsigned int i; |
184 | |
185 | for (i = 0; i < data->dacs; ++i) { |
186 | ak4396_write(chip, codec: i, AK4396_CONTROL_1, |
187 | AK4396_DIF_24_MSB | AK4396_RSTN); |
188 | ak4396_write(chip, codec: i, AK4396_CONTROL_2, |
189 | value: data->ak4396_regs[0][AK4396_CONTROL_2]); |
190 | ak4396_write(chip, codec: i, AK4396_CONTROL_3, |
191 | AK4396_PCM); |
192 | ak4396_write(chip, codec: i, AK4396_LCH_ATT, |
193 | value: chip->dac_volume[i * 2]); |
194 | ak4396_write(chip, codec: i, AK4396_RCH_ATT, |
195 | value: chip->dac_volume[i * 2 + 1]); |
196 | } |
197 | } |
198 | |
199 | static void ak4396_init(struct oxygen *chip) |
200 | { |
201 | struct generic_data *data = chip->model_data; |
202 | |
203 | data->dacs = chip->model.dac_channels_pcm / 2; |
204 | data->ak4396_regs[0][AK4396_CONTROL_2] = |
205 | AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; |
206 | ak4396_registers_init(chip); |
207 | snd_component_add(card: chip->card, component: "AK4396" ); |
208 | } |
209 | |
210 | static void ak5385_init(struct oxygen *chip) |
211 | { |
212 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_AK5385_DFS_MASK); |
213 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_AK5385_DFS_MASK); |
214 | snd_component_add(card: chip->card, component: "AK5385" ); |
215 | } |
216 | |
217 | static void wm8785_registers_init(struct oxygen *chip) |
218 | { |
219 | struct generic_data *data = chip->model_data; |
220 | |
221 | wm8785_write(chip, WM8785_R7, value: 0); |
222 | wm8785_write(chip, WM8785_R0, value: data->wm8785_regs[0]); |
223 | wm8785_write(chip, WM8785_R2, value: data->wm8785_regs[2]); |
224 | } |
225 | |
226 | static void wm8785_init(struct oxygen *chip) |
227 | { |
228 | struct generic_data *data = chip->model_data; |
229 | |
230 | data->wm8785_regs[0] = |
231 | WM8785_MCR_SLAVE | WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST; |
232 | data->wm8785_regs[2] = WM8785_HPFR | WM8785_HPFL; |
233 | wm8785_registers_init(chip); |
234 | snd_component_add(card: chip->card, component: "WM8785" ); |
235 | } |
236 | |
237 | static void generic_init(struct oxygen *chip) |
238 | { |
239 | ak4396_init(chip); |
240 | wm8785_init(chip); |
241 | } |
242 | |
243 | static void meridian_init(struct oxygen *chip) |
244 | { |
245 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, |
246 | GPIO_MERIDIAN_DIG_MASK); |
247 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, |
248 | GPIO_MERIDIAN_DIG_BOARD, GPIO_MERIDIAN_DIG_MASK); |
249 | ak4396_init(chip); |
250 | ak5385_init(chip); |
251 | } |
252 | |
253 | static void claro_enable_hp(struct oxygen *chip) |
254 | { |
255 | msleep(msecs: 300); |
256 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_HP); |
257 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); |
258 | } |
259 | |
260 | static void claro_init(struct oxygen *chip) |
261 | { |
262 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); |
263 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); |
264 | ak4396_init(chip); |
265 | wm8785_init(chip); |
266 | claro_enable_hp(chip); |
267 | } |
268 | |
269 | static void claro_halo_init(struct oxygen *chip) |
270 | { |
271 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); |
272 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); |
273 | ak4396_init(chip); |
274 | ak5385_init(chip); |
275 | claro_enable_hp(chip); |
276 | } |
277 | |
278 | static void fantasia_init(struct oxygen *chip) |
279 | { |
280 | ak4396_init(chip); |
281 | snd_component_add(card: chip->card, component: "CS5340" ); |
282 | } |
283 | |
284 | static void stereo_output_init(struct oxygen *chip) |
285 | { |
286 | ak4396_init(chip); |
287 | } |
288 | |
289 | static void generic_cleanup(struct oxygen *chip) |
290 | { |
291 | } |
292 | |
293 | static void claro_disable_hp(struct oxygen *chip) |
294 | { |
295 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); |
296 | } |
297 | |
298 | static void claro_cleanup(struct oxygen *chip) |
299 | { |
300 | claro_disable_hp(chip); |
301 | } |
302 | |
303 | static void claro_suspend(struct oxygen *chip) |
304 | { |
305 | claro_disable_hp(chip); |
306 | } |
307 | |
308 | static void generic_resume(struct oxygen *chip) |
309 | { |
310 | ak4396_registers_init(chip); |
311 | wm8785_registers_init(chip); |
312 | } |
313 | |
314 | static void meridian_resume(struct oxygen *chip) |
315 | { |
316 | ak4396_registers_init(chip); |
317 | } |
318 | |
319 | static void claro_resume(struct oxygen *chip) |
320 | { |
321 | ak4396_registers_init(chip); |
322 | claro_enable_hp(chip); |
323 | } |
324 | |
325 | static void stereo_resume(struct oxygen *chip) |
326 | { |
327 | ak4396_registers_init(chip); |
328 | } |
329 | |
330 | static void set_ak4396_params(struct oxygen *chip, |
331 | struct snd_pcm_hw_params *params) |
332 | { |
333 | struct generic_data *data = chip->model_data; |
334 | unsigned int i; |
335 | u8 value; |
336 | |
337 | value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_DFS_MASK; |
338 | if (params_rate(p: params) <= 54000) |
339 | value |= AK4396_DFS_NORMAL; |
340 | else if (params_rate(p: params) <= 108000) |
341 | value |= AK4396_DFS_DOUBLE; |
342 | else |
343 | value |= AK4396_DFS_QUAD; |
344 | |
345 | msleep(msecs: 1); /* wait for the new MCLK to become stable */ |
346 | |
347 | if (value != data->ak4396_regs[0][AK4396_CONTROL_2]) { |
348 | for (i = 0; i < data->dacs; ++i) { |
349 | ak4396_write(chip, codec: i, AK4396_CONTROL_1, |
350 | AK4396_DIF_24_MSB); |
351 | ak4396_write(chip, codec: i, AK4396_CONTROL_2, value); |
352 | ak4396_write(chip, codec: i, AK4396_CONTROL_1, |
353 | AK4396_DIF_24_MSB | AK4396_RSTN); |
354 | } |
355 | } |
356 | } |
357 | |
358 | static void update_ak4396_volume(struct oxygen *chip) |
359 | { |
360 | struct generic_data *data = chip->model_data; |
361 | unsigned int i; |
362 | |
363 | for (i = 0; i < data->dacs; ++i) { |
364 | ak4396_write_cached(chip, codec: i, AK4396_LCH_ATT, |
365 | value: chip->dac_volume[i * 2]); |
366 | ak4396_write_cached(chip, codec: i, AK4396_RCH_ATT, |
367 | value: chip->dac_volume[i * 2 + 1]); |
368 | } |
369 | } |
370 | |
371 | static void update_ak4396_mute(struct oxygen *chip) |
372 | { |
373 | struct generic_data *data = chip->model_data; |
374 | unsigned int i; |
375 | u8 value; |
376 | |
377 | value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE; |
378 | if (chip->dac_mute) |
379 | value |= AK4396_SMUTE; |
380 | for (i = 0; i < data->dacs; ++i) |
381 | ak4396_write_cached(chip, codec: i, AK4396_CONTROL_2, value); |
382 | } |
383 | |
384 | static void set_wm8785_params(struct oxygen *chip, |
385 | struct snd_pcm_hw_params *params) |
386 | { |
387 | struct generic_data *data = chip->model_data; |
388 | unsigned int value; |
389 | |
390 | value = WM8785_MCR_SLAVE | WM8785_FORMAT_LJUST; |
391 | if (params_rate(p: params) <= 48000) |
392 | value |= WM8785_OSR_SINGLE; |
393 | else if (params_rate(p: params) <= 96000) |
394 | value |= WM8785_OSR_DOUBLE; |
395 | else |
396 | value |= WM8785_OSR_QUAD; |
397 | if (value != data->wm8785_regs[0]) { |
398 | wm8785_write(chip, WM8785_R7, value: 0); |
399 | wm8785_write(chip, WM8785_R0, value); |
400 | wm8785_write(chip, WM8785_R2, value: data->wm8785_regs[2]); |
401 | } |
402 | } |
403 | |
404 | static void set_ak5385_params(struct oxygen *chip, |
405 | struct snd_pcm_hw_params *params) |
406 | { |
407 | unsigned int value; |
408 | |
409 | if (params_rate(p: params) <= 54000) |
410 | value = GPIO_AK5385_DFS_NORMAL; |
411 | else if (params_rate(p: params) <= 108000) |
412 | value = GPIO_AK5385_DFS_DOUBLE; |
413 | else |
414 | value = GPIO_AK5385_DFS_QUAD; |
415 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, |
416 | value, GPIO_AK5385_DFS_MASK); |
417 | } |
418 | |
419 | static void set_no_params(struct oxygen *chip, struct snd_pcm_hw_params *params) |
420 | { |
421 | } |
422 | |
423 | static int rolloff_info(struct snd_kcontrol *ctl, |
424 | struct snd_ctl_elem_info *info) |
425 | { |
426 | static const char *const names[2] = { |
427 | "Sharp Roll-off" , "Slow Roll-off" |
428 | }; |
429 | |
430 | return snd_ctl_enum_info(info, channels: 1, items: 2, names); |
431 | } |
432 | |
433 | static int rolloff_get(struct snd_kcontrol *ctl, |
434 | struct snd_ctl_elem_value *value) |
435 | { |
436 | struct oxygen *chip = ctl->private_data; |
437 | struct generic_data *data = chip->model_data; |
438 | |
439 | value->value.enumerated.item[0] = |
440 | (data->ak4396_regs[0][AK4396_CONTROL_2] & AK4396_SLOW) != 0; |
441 | return 0; |
442 | } |
443 | |
444 | static int rolloff_put(struct snd_kcontrol *ctl, |
445 | struct snd_ctl_elem_value *value) |
446 | { |
447 | struct oxygen *chip = ctl->private_data; |
448 | struct generic_data *data = chip->model_data; |
449 | unsigned int i; |
450 | int changed; |
451 | u8 reg; |
452 | |
453 | mutex_lock(&chip->mutex); |
454 | reg = data->ak4396_regs[0][AK4396_CONTROL_2]; |
455 | if (value->value.enumerated.item[0]) |
456 | reg |= AK4396_SLOW; |
457 | else |
458 | reg &= ~AK4396_SLOW; |
459 | changed = reg != data->ak4396_regs[0][AK4396_CONTROL_2]; |
460 | if (changed) { |
461 | for (i = 0; i < data->dacs; ++i) |
462 | ak4396_write(chip, codec: i, AK4396_CONTROL_2, value: reg); |
463 | } |
464 | mutex_unlock(lock: &chip->mutex); |
465 | return changed; |
466 | } |
467 | |
468 | static const struct snd_kcontrol_new rolloff_control = { |
469 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
470 | .name = "DAC Filter Playback Enum" , |
471 | .info = rolloff_info, |
472 | .get = rolloff_get, |
473 | .put = rolloff_put, |
474 | }; |
475 | |
476 | static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) |
477 | { |
478 | static const char *const names[2] = { |
479 | "None" , "High-pass Filter" |
480 | }; |
481 | |
482 | return snd_ctl_enum_info(info, channels: 1, items: 2, names); |
483 | } |
484 | |
485 | static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) |
486 | { |
487 | struct oxygen *chip = ctl->private_data; |
488 | struct generic_data *data = chip->model_data; |
489 | |
490 | value->value.enumerated.item[0] = |
491 | (data->wm8785_regs[WM8785_R2] & WM8785_HPFR) != 0; |
492 | return 0; |
493 | } |
494 | |
495 | static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) |
496 | { |
497 | struct oxygen *chip = ctl->private_data; |
498 | struct generic_data *data = chip->model_data; |
499 | unsigned int reg; |
500 | int changed; |
501 | |
502 | mutex_lock(&chip->mutex); |
503 | reg = data->wm8785_regs[WM8785_R2] & ~(WM8785_HPFR | WM8785_HPFL); |
504 | if (value->value.enumerated.item[0]) |
505 | reg |= WM8785_HPFR | WM8785_HPFL; |
506 | changed = reg != data->wm8785_regs[WM8785_R2]; |
507 | if (changed) |
508 | wm8785_write(chip, WM8785_R2, value: reg); |
509 | mutex_unlock(lock: &chip->mutex); |
510 | return changed; |
511 | } |
512 | |
513 | static const struct snd_kcontrol_new hpf_control = { |
514 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
515 | .name = "ADC Filter Capture Enum" , |
516 | .info = hpf_info, |
517 | .get = hpf_get, |
518 | .put = hpf_put, |
519 | }; |
520 | |
521 | static int meridian_dig_source_info(struct snd_kcontrol *ctl, |
522 | struct snd_ctl_elem_info *info) |
523 | { |
524 | static const char *const names[2] = { "On-board" , "Extension" }; |
525 | |
526 | return snd_ctl_enum_info(info, channels: 1, items: 2, names); |
527 | } |
528 | |
529 | static int claro_dig_source_info(struct snd_kcontrol *ctl, |
530 | struct snd_ctl_elem_info *info) |
531 | { |
532 | static const char *const names[2] = { "Optical" , "Coaxial" }; |
533 | |
534 | return snd_ctl_enum_info(info, channels: 1, items: 2, names); |
535 | } |
536 | |
537 | static int meridian_dig_source_get(struct snd_kcontrol *ctl, |
538 | struct snd_ctl_elem_value *value) |
539 | { |
540 | struct oxygen *chip = ctl->private_data; |
541 | |
542 | value->value.enumerated.item[0] = |
543 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & |
544 | GPIO_MERIDIAN_DIG_EXT); |
545 | return 0; |
546 | } |
547 | |
548 | static int claro_dig_source_get(struct snd_kcontrol *ctl, |
549 | struct snd_ctl_elem_value *value) |
550 | { |
551 | struct oxygen *chip = ctl->private_data; |
552 | |
553 | value->value.enumerated.item[0] = |
554 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & |
555 | GPIO_CLARO_DIG_COAX); |
556 | return 0; |
557 | } |
558 | |
559 | static int meridian_dig_source_put(struct snd_kcontrol *ctl, |
560 | struct snd_ctl_elem_value *value) |
561 | { |
562 | struct oxygen *chip = ctl->private_data; |
563 | u16 old_reg, new_reg; |
564 | int changed; |
565 | |
566 | mutex_lock(&chip->mutex); |
567 | old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); |
568 | new_reg = old_reg & ~GPIO_MERIDIAN_DIG_MASK; |
569 | if (value->value.enumerated.item[0] == 0) |
570 | new_reg |= GPIO_MERIDIAN_DIG_BOARD; |
571 | else |
572 | new_reg |= GPIO_MERIDIAN_DIG_EXT; |
573 | changed = new_reg != old_reg; |
574 | if (changed) |
575 | oxygen_write16(chip, OXYGEN_GPIO_DATA, value: new_reg); |
576 | mutex_unlock(lock: &chip->mutex); |
577 | return changed; |
578 | } |
579 | |
580 | static int claro_dig_source_put(struct snd_kcontrol *ctl, |
581 | struct snd_ctl_elem_value *value) |
582 | { |
583 | struct oxygen *chip = ctl->private_data; |
584 | u16 old_reg, new_reg; |
585 | int changed; |
586 | |
587 | mutex_lock(&chip->mutex); |
588 | old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); |
589 | new_reg = old_reg & ~GPIO_CLARO_DIG_COAX; |
590 | if (value->value.enumerated.item[0]) |
591 | new_reg |= GPIO_CLARO_DIG_COAX; |
592 | changed = new_reg != old_reg; |
593 | if (changed) |
594 | oxygen_write16(chip, OXYGEN_GPIO_DATA, value: new_reg); |
595 | mutex_unlock(lock: &chip->mutex); |
596 | return changed; |
597 | } |
598 | |
599 | static const struct snd_kcontrol_new meridian_dig_source_control = { |
600 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
601 | .name = "IEC958 Source Capture Enum" , |
602 | .info = meridian_dig_source_info, |
603 | .get = meridian_dig_source_get, |
604 | .put = meridian_dig_source_put, |
605 | }; |
606 | |
607 | static const struct snd_kcontrol_new claro_dig_source_control = { |
608 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
609 | .name = "IEC958 Source Capture Enum" , |
610 | .info = claro_dig_source_info, |
611 | .get = claro_dig_source_get, |
612 | .put = claro_dig_source_put, |
613 | }; |
614 | |
615 | static int generic_mixer_init(struct oxygen *chip) |
616 | { |
617 | return snd_ctl_add(card: chip->card, kcontrol: snd_ctl_new1(kcontrolnew: &rolloff_control, private_data: chip)); |
618 | } |
619 | |
620 | static int generic_wm8785_mixer_init(struct oxygen *chip) |
621 | { |
622 | int err; |
623 | |
624 | err = generic_mixer_init(chip); |
625 | if (err < 0) |
626 | return err; |
627 | err = snd_ctl_add(card: chip->card, kcontrol: snd_ctl_new1(kcontrolnew: &hpf_control, private_data: chip)); |
628 | if (err < 0) |
629 | return err; |
630 | return 0; |
631 | } |
632 | |
633 | static int meridian_mixer_init(struct oxygen *chip) |
634 | { |
635 | int err; |
636 | |
637 | err = generic_mixer_init(chip); |
638 | if (err < 0) |
639 | return err; |
640 | err = snd_ctl_add(card: chip->card, |
641 | kcontrol: snd_ctl_new1(kcontrolnew: &meridian_dig_source_control, private_data: chip)); |
642 | if (err < 0) |
643 | return err; |
644 | return 0; |
645 | } |
646 | |
647 | static int claro_mixer_init(struct oxygen *chip) |
648 | { |
649 | int err; |
650 | |
651 | err = generic_wm8785_mixer_init(chip); |
652 | if (err < 0) |
653 | return err; |
654 | err = snd_ctl_add(card: chip->card, |
655 | kcontrol: snd_ctl_new1(kcontrolnew: &claro_dig_source_control, private_data: chip)); |
656 | if (err < 0) |
657 | return err; |
658 | return 0; |
659 | } |
660 | |
661 | static int claro_halo_mixer_init(struct oxygen *chip) |
662 | { |
663 | int err; |
664 | |
665 | err = generic_mixer_init(chip); |
666 | if (err < 0) |
667 | return err; |
668 | err = snd_ctl_add(card: chip->card, |
669 | kcontrol: snd_ctl_new1(kcontrolnew: &claro_dig_source_control, private_data: chip)); |
670 | if (err < 0) |
671 | return err; |
672 | return 0; |
673 | } |
674 | |
675 | static void dump_ak4396_registers(struct oxygen *chip, |
676 | struct snd_info_buffer *buffer) |
677 | { |
678 | struct generic_data *data = chip->model_data; |
679 | unsigned int dac, i; |
680 | |
681 | for (dac = 0; dac < data->dacs; ++dac) { |
682 | snd_iprintf(buffer, "\nAK4396 %u:" , dac + 1); |
683 | for (i = 0; i < 5; ++i) |
684 | snd_iprintf(buffer, " %02x" , data->ak4396_regs[dac][i]); |
685 | } |
686 | snd_iprintf(buffer, "\n" ); |
687 | } |
688 | |
689 | static void dump_wm8785_registers(struct oxygen *chip, |
690 | struct snd_info_buffer *buffer) |
691 | { |
692 | struct generic_data *data = chip->model_data; |
693 | unsigned int i; |
694 | |
695 | snd_iprintf(buffer, "\nWM8785:" ); |
696 | for (i = 0; i < 3; ++i) |
697 | snd_iprintf(buffer, " %03x" , data->wm8785_regs[i]); |
698 | snd_iprintf(buffer, "\n" ); |
699 | } |
700 | |
701 | static void dump_oxygen_registers(struct oxygen *chip, |
702 | struct snd_info_buffer *buffer) |
703 | { |
704 | dump_ak4396_registers(chip, buffer); |
705 | dump_wm8785_registers(chip, buffer); |
706 | } |
707 | |
708 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); |
709 | |
710 | static const struct oxygen_model model_generic = { |
711 | .shortname = "C-Media CMI8788" , |
712 | .longname = "C-Media Oxygen HD Audio" , |
713 | .chip = "CMI8788" , |
714 | .init = generic_init, |
715 | .mixer_init = generic_wm8785_mixer_init, |
716 | .cleanup = generic_cleanup, |
717 | .resume = generic_resume, |
718 | .set_dac_params = set_ak4396_params, |
719 | .set_adc_params = set_wm8785_params, |
720 | .update_dac_volume = update_ak4396_volume, |
721 | .update_dac_mute = update_ak4396_mute, |
722 | .dump_registers = dump_oxygen_registers, |
723 | .dac_tlv = ak4396_db_scale, |
724 | .model_data_size = sizeof(struct generic_data), |
725 | .device_config = PLAYBACK_0_TO_I2S | |
726 | PLAYBACK_1_TO_SPDIF | |
727 | PLAYBACK_2_TO_AC97_1 | |
728 | CAPTURE_0_FROM_I2S_1 | |
729 | CAPTURE_1_FROM_SPDIF | |
730 | CAPTURE_2_FROM_AC97_1 | |
731 | AC97_CD_INPUT, |
732 | .dac_channels_pcm = 8, |
733 | .dac_channels_mixer = 8, |
734 | .dac_volume_min = 0, |
735 | .dac_volume_max = 255, |
736 | .function_flags = OXYGEN_FUNCTION_SPI | |
737 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, |
738 | .dac_mclks = OXYGEN_MCLKS(256, 128, 128), |
739 | .adc_mclks = OXYGEN_MCLKS(256, 256, 128), |
740 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
741 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
742 | }; |
743 | |
744 | static int get_oxygen_model(struct oxygen *chip, |
745 | const struct pci_device_id *id) |
746 | { |
747 | static const char *const names[] = { |
748 | [MODEL_MERIDIAN] = "AuzenTech X-Meridian" , |
749 | [MODEL_MERIDIAN_2G] = "AuzenTech X-Meridian 2G" , |
750 | [MODEL_CLARO] = "HT-Omega Claro" , |
751 | [MODEL_CLARO_HALO] = "HT-Omega Claro halo" , |
752 | [MODEL_FANTASIA] = "TempoTec HiFier Fantasia" , |
753 | [MODEL_SERENADE] = "TempoTec HiFier Serenade" , |
754 | [MODEL_HG2PCI] = "CMI8787-HG2PCI" , |
755 | [MODEL_XONAR_DG] = "Xonar DG" , |
756 | [MODEL_XONAR_DGX] = "Xonar DGX" , |
757 | }; |
758 | |
759 | chip->model = model_generic; |
760 | switch (id->driver_data) { |
761 | case MODEL_MERIDIAN: |
762 | case MODEL_MERIDIAN_2G: |
763 | chip->model.init = meridian_init; |
764 | chip->model.mixer_init = meridian_mixer_init; |
765 | chip->model.resume = meridian_resume; |
766 | chip->model.set_adc_params = set_ak5385_params; |
767 | chip->model.dump_registers = dump_ak4396_registers; |
768 | chip->model.device_config = PLAYBACK_0_TO_I2S | |
769 | PLAYBACK_1_TO_SPDIF | |
770 | CAPTURE_0_FROM_I2S_2 | |
771 | CAPTURE_1_FROM_SPDIF; |
772 | if (id->driver_data == MODEL_MERIDIAN) |
773 | chip->model.device_config |= AC97_CD_INPUT; |
774 | break; |
775 | case MODEL_CLARO: |
776 | chip->model.init = claro_init; |
777 | chip->model.mixer_init = claro_mixer_init; |
778 | chip->model.cleanup = claro_cleanup; |
779 | chip->model.suspend = claro_suspend; |
780 | chip->model.resume = claro_resume; |
781 | break; |
782 | case MODEL_CLARO_HALO: |
783 | chip->model.init = claro_halo_init; |
784 | chip->model.mixer_init = claro_halo_mixer_init; |
785 | chip->model.cleanup = claro_cleanup; |
786 | chip->model.suspend = claro_suspend; |
787 | chip->model.resume = claro_resume; |
788 | chip->model.set_adc_params = set_ak5385_params; |
789 | chip->model.dump_registers = dump_ak4396_registers; |
790 | chip->model.device_config = PLAYBACK_0_TO_I2S | |
791 | PLAYBACK_1_TO_SPDIF | |
792 | CAPTURE_0_FROM_I2S_2 | |
793 | CAPTURE_1_FROM_SPDIF; |
794 | break; |
795 | case MODEL_FANTASIA: |
796 | case MODEL_SERENADE: |
797 | case MODEL_2CH_OUTPUT: |
798 | case MODEL_HG2PCI: |
799 | chip->model.shortname = "C-Media CMI8787" ; |
800 | chip->model.chip = "CMI8787" ; |
801 | if (id->driver_data == MODEL_FANTASIA) |
802 | chip->model.init = fantasia_init; |
803 | else |
804 | chip->model.init = stereo_output_init; |
805 | chip->model.resume = stereo_resume; |
806 | chip->model.mixer_init = generic_mixer_init; |
807 | chip->model.set_adc_params = set_no_params; |
808 | chip->model.dump_registers = dump_ak4396_registers; |
809 | chip->model.device_config = PLAYBACK_0_TO_I2S | |
810 | PLAYBACK_1_TO_SPDIF; |
811 | if (id->driver_data == MODEL_FANTASIA) { |
812 | chip->model.device_config |= CAPTURE_0_FROM_I2S_1; |
813 | chip->model.adc_mclks = OXYGEN_MCLKS(256, 128, 128); |
814 | } |
815 | chip->model.dac_channels_pcm = 2; |
816 | chip->model.dac_channels_mixer = 2; |
817 | break; |
818 | case MODEL_XONAR_DG: |
819 | case MODEL_XONAR_DGX: |
820 | chip->model = model_xonar_dg; |
821 | break; |
822 | } |
823 | if (id->driver_data == MODEL_MERIDIAN || |
824 | id->driver_data == MODEL_MERIDIAN_2G || |
825 | id->driver_data == MODEL_CLARO_HALO) { |
826 | chip->model.misc_flags = OXYGEN_MISC_MIDI; |
827 | chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; |
828 | } |
829 | if (id->driver_data < ARRAY_SIZE(names) && names[id->driver_data]) |
830 | chip->model.shortname = names[id->driver_data]; |
831 | return 0; |
832 | } |
833 | |
834 | static int generic_oxygen_probe(struct pci_dev *pci, |
835 | const struct pci_device_id *pci_id) |
836 | { |
837 | static int dev; |
838 | int err; |
839 | |
840 | if (dev >= SNDRV_CARDS) |
841 | return -ENODEV; |
842 | if (!enable[dev]) { |
843 | ++dev; |
844 | return -ENOENT; |
845 | } |
846 | err = oxygen_pci_probe(pci, index: index[dev], id: id[dev], THIS_MODULE, |
847 | ids: oxygen_ids, get_model: get_oxygen_model); |
848 | if (err >= 0) |
849 | ++dev; |
850 | return err; |
851 | } |
852 | |
853 | static struct pci_driver oxygen_driver = { |
854 | .name = KBUILD_MODNAME, |
855 | .id_table = oxygen_ids, |
856 | .probe = generic_oxygen_probe, |
857 | #ifdef CONFIG_PM_SLEEP |
858 | .driver = { |
859 | .pm = &oxygen_pci_pm, |
860 | }, |
861 | #endif |
862 | }; |
863 | |
864 | module_pci_driver(oxygen_driver); |
865 | |