]> git.karo-electronics.de Git - mv-sheeva.git/blob - sound/pci/oxygen/xonar_dg.c
mtd: add "platform:" prefix for platform modalias
[mv-sheeva.git] / sound / pci / oxygen / xonar_dg.c
1 /*
2  * card driver for the Xonar DG
3  *
4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5  *
6  *
7  *  This driver is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License, version 2.
9  *
10  *  This driver is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this driver; if not, see <http://www.gnu.org/licenses/>.
17  */
18
19 /*
20  * Xonar DG
21  * --------
22  *
23  * CMI8788:
24  *
25  *   SPI 0 -> CS4245
26  *
27  *   GPIO 3 <- ?
28  *   GPIO 4 <- headphone detect
29  *   GPIO 5 -> route input jack to line-in (0) or mic-in (1)
30  *   GPIO 6 -> route input jack to line-in (0) or mic-in (1)
31  *   GPIO 7 -> enable rear headphone amp
32  *   GPIO 8 -> enable output to speakers
33  *
34  * CS4245:
35  *
36  *   input 1 <- aux
37  *   input 2 <- front mic
38  *   input 4 <- line/mic
39  *   aux out -> front panel headphones
40  */
41
42 #include <linux/pci.h>
43 #include <linux/delay.h>
44 #include <sound/control.h>
45 #include <sound/core.h>
46 #include <sound/info.h>
47 #include <sound/pcm.h>
48 #include <sound/tlv.h>
49 #include "oxygen.h"
50 #include "xonar_dg.h"
51 #include "cs4245.h"
52
53 #define GPIO_MAGIC              0x0008
54 #define GPIO_HP_DETECT          0x0010
55 #define GPIO_INPUT_ROUTE        0x0060
56 #define GPIO_HP_REAR            0x0080
57 #define GPIO_OUTPUT_ENABLE      0x0100
58
59 struct dg {
60         unsigned int output_sel;
61         s8 input_vol[4][2];
62         unsigned int input_sel;
63         u8 hp_vol_att;
64         u8 cs4245_regs[0x11];
65 };
66
67 static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value)
68 {
69         struct dg *data = chip->model_data;
70
71         oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
72                          OXYGEN_SPI_DATA_LENGTH_3 |
73                          OXYGEN_SPI_CLOCK_1280 |
74                          (0 << OXYGEN_SPI_CODEC_SHIFT) |
75                          OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
76                          CS4245_SPI_ADDRESS |
77                          CS4245_SPI_WRITE |
78                          (reg << 8) | value);
79         data->cs4245_regs[reg] = value;
80 }
81
82 static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value)
83 {
84         struct dg *data = chip->model_data;
85
86         if (value != data->cs4245_regs[reg])
87                 cs4245_write(chip, reg, value);
88 }
89
90 static void cs4245_registers_init(struct oxygen *chip)
91 {
92         struct dg *data = chip->model_data;
93
94         cs4245_write(chip, CS4245_POWER_CTRL, CS4245_PDN);
95         cs4245_write(chip, CS4245_DAC_CTRL_1,
96                      data->cs4245_regs[CS4245_DAC_CTRL_1]);
97         cs4245_write(chip, CS4245_ADC_CTRL,
98                      data->cs4245_regs[CS4245_ADC_CTRL]);
99         cs4245_write(chip, CS4245_SIGNAL_SEL,
100                      data->cs4245_regs[CS4245_SIGNAL_SEL]);
101         cs4245_write(chip, CS4245_PGA_B_CTRL,
102                      data->cs4245_regs[CS4245_PGA_B_CTRL]);
103         cs4245_write(chip, CS4245_PGA_A_CTRL,
104                      data->cs4245_regs[CS4245_PGA_A_CTRL]);
105         cs4245_write(chip, CS4245_ANALOG_IN,
106                      data->cs4245_regs[CS4245_ANALOG_IN]);
107         cs4245_write(chip, CS4245_DAC_A_CTRL,
108                      data->cs4245_regs[CS4245_DAC_A_CTRL]);
109         cs4245_write(chip, CS4245_DAC_B_CTRL,
110                      data->cs4245_regs[CS4245_DAC_B_CTRL]);
111         cs4245_write(chip, CS4245_DAC_CTRL_2,
112                      CS4245_DAC_SOFT | CS4245_DAC_ZERO | CS4245_INVERT_DAC);
113         cs4245_write(chip, CS4245_INT_MASK, 0);
114         cs4245_write(chip, CS4245_POWER_CTRL, 0);
115 }
116
117 static void cs4245_init(struct oxygen *chip)
118 {
119         struct dg *data = chip->model_data;
120
121         data->cs4245_regs[CS4245_DAC_CTRL_1] =
122                 CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST;
123         data->cs4245_regs[CS4245_ADC_CTRL] =
124                 CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST;
125         data->cs4245_regs[CS4245_SIGNAL_SEL] =
126                 CS4245_A_OUT_SEL_HIZ | CS4245_ASYNCH;
127         data->cs4245_regs[CS4245_PGA_B_CTRL] = 0;
128         data->cs4245_regs[CS4245_PGA_A_CTRL] = 0;
129         data->cs4245_regs[CS4245_ANALOG_IN] =
130                 CS4245_PGA_SOFT | CS4245_PGA_ZERO | CS4245_SEL_INPUT_4;
131         data->cs4245_regs[CS4245_DAC_A_CTRL] = 0;
132         data->cs4245_regs[CS4245_DAC_B_CTRL] = 0;
133         cs4245_registers_init(chip);
134         snd_component_add(chip->card, "CS4245");
135 }
136
137 static void dg_output_enable(struct oxygen *chip)
138 {
139         msleep(2500);
140         oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
141 }
142
143 static void dg_init(struct oxygen *chip)
144 {
145         struct dg *data = chip->model_data;
146
147         data->output_sel = 0;
148         data->input_sel = 3;
149         data->hp_vol_att = 2 * 16;
150
151         cs4245_init(chip);
152
153         oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
154                             GPIO_MAGIC | GPIO_HP_DETECT);
155         oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
156                           GPIO_INPUT_ROUTE | GPIO_HP_REAR | GPIO_OUTPUT_ENABLE);
157         oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
158                             GPIO_INPUT_ROUTE | GPIO_HP_REAR);
159         dg_output_enable(chip);
160 }
161
162 static void dg_cleanup(struct oxygen *chip)
163 {
164         oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
165 }
166
167 static void dg_suspend(struct oxygen *chip)
168 {
169         dg_cleanup(chip);
170 }
171
172 static void dg_resume(struct oxygen *chip)
173 {
174         cs4245_registers_init(chip);
175         dg_output_enable(chip);
176 }
177
178 static void set_cs4245_dac_params(struct oxygen *chip,
179                                   struct snd_pcm_hw_params *params)
180 {
181         struct dg *data = chip->model_data;
182         u8 value;
183
184         value = data->cs4245_regs[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK;
185         if (params_rate(params) <= 50000)
186                 value |= CS4245_DAC_FM_SINGLE;
187         else if (params_rate(params) <= 100000)
188                 value |= CS4245_DAC_FM_DOUBLE;
189         else
190                 value |= CS4245_DAC_FM_QUAD;
191         cs4245_write_cached(chip, CS4245_DAC_CTRL_1, value);
192 }
193
194 static void set_cs4245_adc_params(struct oxygen *chip,
195                                   struct snd_pcm_hw_params *params)
196 {
197         struct dg *data = chip->model_data;
198         u8 value;
199
200         value = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK;
201         if (params_rate(params) <= 50000)
202                 value |= CS4245_ADC_FM_SINGLE;
203         else if (params_rate(params) <= 100000)
204                 value |= CS4245_ADC_FM_DOUBLE;
205         else
206                 value |= CS4245_ADC_FM_QUAD;
207         cs4245_write_cached(chip, CS4245_ADC_CTRL, value);
208 }
209
210 static int output_switch_info(struct snd_kcontrol *ctl,
211                               struct snd_ctl_elem_info *info)
212 {
213         static const char *const names[3] = {
214                 "Speakers", "Headphones", "FP Headphones"
215         };
216
217         return snd_ctl_enum_info(info, 1, 3, names);
218 }
219
220 static int output_switch_get(struct snd_kcontrol *ctl,
221                              struct snd_ctl_elem_value *value)
222 {
223         struct oxygen *chip = ctl->private_data;
224         struct dg *data = chip->model_data;
225
226         mutex_lock(&chip->mutex);
227         value->value.enumerated.item[0] = data->output_sel;
228         mutex_unlock(&chip->mutex);
229         return 0;
230 }
231
232 static int output_switch_put(struct snd_kcontrol *ctl,
233                              struct snd_ctl_elem_value *value)
234 {
235         struct oxygen *chip = ctl->private_data;
236         struct dg *data = chip->model_data;
237         u8 reg;
238         int changed;
239
240         if (value->value.enumerated.item[0] > 2)
241                 return -EINVAL;
242
243         mutex_lock(&chip->mutex);
244         changed = value->value.enumerated.item[0] != data->output_sel;
245         if (changed) {
246                 data->output_sel = value->value.enumerated.item[0];
247
248                 reg = data->cs4245_regs[CS4245_SIGNAL_SEL] &
249                                                 ~CS4245_A_OUT_SEL_MASK;
250                 reg |= data->output_sel == 2 ?
251                                 CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ;
252                 cs4245_write_cached(chip, CS4245_SIGNAL_SEL, reg);
253
254                 cs4245_write_cached(chip, CS4245_DAC_A_CTRL,
255                                     data->output_sel ? data->hp_vol_att : 0);
256                 cs4245_write_cached(chip, CS4245_DAC_B_CTRL,
257                                     data->output_sel ? data->hp_vol_att : 0);
258
259                 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
260                                       data->output_sel == 1 ? GPIO_HP_REAR : 0,
261                                       GPIO_HP_REAR);
262         }
263         mutex_unlock(&chip->mutex);
264         return changed;
265 }
266
267 static int hp_volume_offset_info(struct snd_kcontrol *ctl,
268                                  struct snd_ctl_elem_info *info)
269 {
270         static const char *const names[3] = {
271                 "< 64 ohms", "64-150 ohms", "150-300 ohms"
272         };
273
274         return snd_ctl_enum_info(info, 1, 3, names);
275 }
276
277 static int hp_volume_offset_get(struct snd_kcontrol *ctl,
278                                 struct snd_ctl_elem_value *value)
279 {
280         struct oxygen *chip = ctl->private_data;
281         struct dg *data = chip->model_data;
282
283         mutex_lock(&chip->mutex);
284         if (data->hp_vol_att > 2 * 7)
285                 value->value.enumerated.item[0] = 0;
286         else if (data->hp_vol_att > 0)
287                 value->value.enumerated.item[0] = 1;
288         else
289                 value->value.enumerated.item[0] = 2;
290         mutex_unlock(&chip->mutex);
291         return 0;
292 }
293
294 static int hp_volume_offset_put(struct snd_kcontrol *ctl,
295                                 struct snd_ctl_elem_value *value)
296 {
297         static const s8 atts[3] = { 2 * 16, 2 * 7, 0 };
298         struct oxygen *chip = ctl->private_data;
299         struct dg *data = chip->model_data;
300         s8 att;
301         int changed;
302
303         if (value->value.enumerated.item[0] > 2)
304                 return -EINVAL;
305         att = atts[value->value.enumerated.item[0]];
306         mutex_lock(&chip->mutex);
307         changed = att != data->hp_vol_att;
308         if (changed) {
309                 data->hp_vol_att = att;
310                 if (data->output_sel) {
311                         cs4245_write_cached(chip, CS4245_DAC_A_CTRL, att);
312                         cs4245_write_cached(chip, CS4245_DAC_B_CTRL, att);
313                 }
314         }
315         mutex_unlock(&chip->mutex);
316         return changed;
317 }
318
319 static int input_vol_info(struct snd_kcontrol *ctl,
320                           struct snd_ctl_elem_info *info)
321 {
322         info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
323         info->count = 2;
324         info->value.integer.min = 2 * -12;
325         info->value.integer.max = 2 * 12;
326         return 0;
327 }
328
329 static int input_vol_get(struct snd_kcontrol *ctl,
330                          struct snd_ctl_elem_value *value)
331 {
332         struct oxygen *chip = ctl->private_data;
333         struct dg *data = chip->model_data;
334         unsigned int idx = ctl->private_value;
335
336         mutex_lock(&chip->mutex);
337         value->value.integer.value[0] = data->input_vol[idx][0];
338         value->value.integer.value[1] = data->input_vol[idx][1];
339         mutex_unlock(&chip->mutex);
340         return 0;
341 }
342
343 static int input_vol_put(struct snd_kcontrol *ctl,
344                          struct snd_ctl_elem_value *value)
345 {
346         struct oxygen *chip = ctl->private_data;
347         struct dg *data = chip->model_data;
348         unsigned int idx = ctl->private_value;
349         int changed = 0;
350
351         if (value->value.integer.value[0] < 2 * -12 ||
352             value->value.integer.value[0] > 2 * 12 ||
353             value->value.integer.value[1] < 2 * -12 ||
354             value->value.integer.value[1] > 2 * 12)
355                 return -EINVAL;
356         mutex_lock(&chip->mutex);
357         changed = data->input_vol[idx][0] != value->value.integer.value[0] ||
358                   data->input_vol[idx][1] != value->value.integer.value[1];
359         if (changed) {
360                 data->input_vol[idx][0] = value->value.integer.value[0];
361                 data->input_vol[idx][1] = value->value.integer.value[1];
362                 if (idx == data->input_sel) {
363                         cs4245_write_cached(chip, CS4245_PGA_A_CTRL,
364                                             data->input_vol[idx][0]);
365                         cs4245_write_cached(chip, CS4245_PGA_B_CTRL,
366                                             data->input_vol[idx][1]);
367                 }
368         }
369         mutex_unlock(&chip->mutex);
370         return changed;
371 }
372
373 static DECLARE_TLV_DB_SCALE(cs4245_pga_db_scale, -1200, 50, 0);
374
375 static int input_sel_info(struct snd_kcontrol *ctl,
376                           struct snd_ctl_elem_info *info)
377 {
378         static const char *const names[4] = {
379                 "Mic", "Aux", "Front Mic", "Line"
380         };
381
382         return snd_ctl_enum_info(info, 1, 4, names);
383 }
384
385 static int input_sel_get(struct snd_kcontrol *ctl,
386                          struct snd_ctl_elem_value *value)
387 {
388         struct oxygen *chip = ctl->private_data;
389         struct dg *data = chip->model_data;
390
391         mutex_lock(&chip->mutex);
392         value->value.enumerated.item[0] = data->input_sel;
393         mutex_unlock(&chip->mutex);
394         return 0;
395 }
396
397 static int input_sel_put(struct snd_kcontrol *ctl,
398                          struct snd_ctl_elem_value *value)
399 {
400         static const u8 sel_values[4] = {
401                 CS4245_SEL_MIC,
402                 CS4245_SEL_INPUT_1,
403                 CS4245_SEL_INPUT_2,
404                 CS4245_SEL_INPUT_4
405         };
406         struct oxygen *chip = ctl->private_data;
407         struct dg *data = chip->model_data;
408         int changed;
409
410         if (value->value.enumerated.item[0] > 3)
411                 return -EINVAL;
412
413         mutex_lock(&chip->mutex);
414         changed = value->value.enumerated.item[0] != data->input_sel;
415         if (changed) {
416                 data->input_sel = value->value.enumerated.item[0];
417
418                 cs4245_write(chip, CS4245_ANALOG_IN,
419                              (data->cs4245_regs[CS4245_ANALOG_IN] &
420                                                         ~CS4245_SEL_MASK) |
421                              sel_values[data->input_sel]);
422
423                 cs4245_write_cached(chip, CS4245_PGA_A_CTRL,
424                                     data->input_vol[data->input_sel][0]);
425                 cs4245_write_cached(chip, CS4245_PGA_B_CTRL,
426                                     data->input_vol[data->input_sel][1]);
427
428                 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
429                                       data->input_sel ? 0 : GPIO_INPUT_ROUTE,
430                                       GPIO_INPUT_ROUTE);
431         }
432         mutex_unlock(&chip->mutex);
433         return changed;
434 }
435
436 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
437 {
438         static const char *const names[2] = { "Active", "Frozen" };
439
440         return snd_ctl_enum_info(info, 1, 2, names);
441 }
442
443 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
444 {
445         struct oxygen *chip = ctl->private_data;
446         struct dg *data = chip->model_data;
447
448         value->value.enumerated.item[0] =
449                 !!(data->cs4245_regs[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE);
450         return 0;
451 }
452
453 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
454 {
455         struct oxygen *chip = ctl->private_data;
456         struct dg *data = chip->model_data;
457         u8 reg;
458         int changed;
459
460         mutex_lock(&chip->mutex);
461         reg = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE;
462         if (value->value.enumerated.item[0])
463                 reg |= CS4245_HPF_FREEZE;
464         changed = reg != data->cs4245_regs[CS4245_ADC_CTRL];
465         if (changed)
466                 cs4245_write(chip, CS4245_ADC_CTRL, reg);
467         mutex_unlock(&chip->mutex);
468         return changed;
469 }
470
471 #define INPUT_VOLUME(xname, index) { \
472         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
473         .name = xname, \
474         .info = input_vol_info, \
475         .get = input_vol_get, \
476         .put = input_vol_put, \
477         .tlv = { .p = cs4245_pga_db_scale }, \
478         .private_value = index, \
479 }
480 static const struct snd_kcontrol_new dg_controls[] = {
481         {
482                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
483                 .name = "Analog Output Playback Enum",
484                 .info = output_switch_info,
485                 .get = output_switch_get,
486                 .put = output_switch_put,
487         },
488         {
489                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
490                 .name = "Headphones Impedance Playback Enum",
491                 .info = hp_volume_offset_info,
492                 .get = hp_volume_offset_get,
493                 .put = hp_volume_offset_put,
494         },
495         INPUT_VOLUME("Mic Capture Volume", 0),
496         INPUT_VOLUME("Aux Capture Volume", 1),
497         INPUT_VOLUME("Front Mic Capture Volume", 2),
498         INPUT_VOLUME("Line Capture Volume", 3),
499         {
500                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
501                 .name = "Capture Source",
502                 .info = input_sel_info,
503                 .get = input_sel_get,
504                 .put = input_sel_put,
505         },
506         {
507                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
508                 .name = "ADC High-pass Filter Capture Enum",
509                 .info = hpf_info,
510                 .get = hpf_get,
511                 .put = hpf_put,
512         },
513 };
514
515 static int dg_control_filter(struct snd_kcontrol_new *template)
516 {
517         if (!strncmp(template->name, "Master Playback ", 16))
518                 return 1;
519         return 0;
520 }
521
522 static int dg_mixer_init(struct oxygen *chip)
523 {
524         unsigned int i;
525         int err;
526
527         for (i = 0; i < ARRAY_SIZE(dg_controls); ++i) {
528                 err = snd_ctl_add(chip->card,
529                                   snd_ctl_new1(&dg_controls[i], chip));
530                 if (err < 0)
531                         return err;
532         }
533         return 0;
534 }
535
536 static void dump_cs4245_registers(struct oxygen *chip,
537                                   struct snd_info_buffer *buffer)
538 {
539         struct dg *data = chip->model_data;
540         unsigned int i;
541
542         snd_iprintf(buffer, "\nCS4245:");
543         for (i = 1; i <= 0x10; ++i)
544                 snd_iprintf(buffer, " %02x", data->cs4245_regs[i]);
545         snd_iprintf(buffer, "\n");
546 }
547
548 struct oxygen_model model_xonar_dg = {
549         .shortname = "Xonar DG",
550         .longname = "C-Media Oxygen HD Audio",
551         .chip = "CMI8786",
552         .init = dg_init,
553         .control_filter = dg_control_filter,
554         .mixer_init = dg_mixer_init,
555         .cleanup = dg_cleanup,
556         .suspend = dg_suspend,
557         .resume = dg_resume,
558         .set_dac_params = set_cs4245_dac_params,
559         .set_adc_params = set_cs4245_adc_params,
560         .dump_registers = dump_cs4245_registers,
561         .model_data_size = sizeof(struct dg),
562         .device_config = PLAYBACK_0_TO_I2S |
563                          PLAYBACK_1_TO_SPDIF |
564                          CAPTURE_0_FROM_I2S_2,
565         .dac_channels_pcm = 6,
566         .dac_channels_mixer = 0,
567         .function_flags = OXYGEN_FUNCTION_SPI,
568         .dac_mclks = OXYGEN_MCLKS(256, 128, 128),
569         .adc_mclks = OXYGEN_MCLKS(256, 128, 128),
570         .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
571         .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
572 };