aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Hofman <dustin@seznam.cz>2007-12-03 06:44:28 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:30 -0500
commit6632d64b0b596b9588b607806ac6d36c8c2c9696 (patch)
tree0e8126af6c2c47e2b981c7ab7d8cf29aaaee8360
parentacec30ffffe1eee07e3202cff03e7ca8350d250f (diff)
[ALSA] switching rate in STAC9460 codec of Prodigy192
* support for switching rate in STAC9460 - using set_rate_val of the akm infrastructure * listing all STAC9460 registers in proc * disabling mpu401 device for Prodigy192 - otherwise the currently flawed mpu401 code hangs kernel when opening the midi device * removing old unused commented-out code Signed-off-by: Pavel Hofman <dustin@seznam.cz> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--include/sound/ak4xxx-adda.h2
-rw-r--r--sound/i2c/other/ak4xxx-adda.c5
-rw-r--r--sound/pci/ice1712/ice1712.h2
-rw-r--r--sound/pci/ice1712/prodigy192.c271
4 files changed, 124 insertions, 156 deletions
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index 891cf1aea8b1..6153b91cdc3e 100644
--- a/include/sound/ak4xxx-adda.h
+++ b/include/sound/ak4xxx-adda.h
@@ -68,7 +68,7 @@ struct snd_akm4xxx {
68 enum { 68 enum {
69 SND_AK4524, SND_AK4528, SND_AK4529, 69 SND_AK4524, SND_AK4528, SND_AK4529,
70 SND_AK4355, SND_AK4358, SND_AK4381, 70 SND_AK4355, SND_AK4358, SND_AK4381,
71 SND_AK5365 71 SND_AK5365, NON_AKM
72 } type; 72 } type;
73 73
74 /* (array) information of combined codecs */ 74 /* (array) information of combined codecs */
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 39bb03add7e1..fefa1ae57ad9 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -293,6 +293,11 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
293 case SND_AK5365: 293 case SND_AK5365:
294 /* FIXME: any init sequence? */ 294 /* FIXME: any init sequence? */
295 return; 295 return;
296 case NON_AKM:
297 /* fake value for non-akm codecs using akm infrastructure
298 * (e.g. of ice1724) - certainly FIXME
299 */
300 return;
296 default: 301 default:
297 snd_BUG(); 302 snd_BUG();
298 return; 303 return;
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 3c3cac3dc08b..4dc576af506f 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -399,6 +399,8 @@ struct snd_ice1712 {
399 } juli; 399 } juli;
400 struct { 400 struct {
401 struct ak4114 *ak4114; 401 struct ak4114 *ak4114;
402 /* rate change needs atomic mute/unmute of all dacs*/
403 struct mutex mute_mutex;
402 } prodigy192; 404 } prodigy192;
403 struct { 405 struct {
404 struct { 406 struct {
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 4b21d5c1c4ff..6d81a1c61d41 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -81,6 +81,24 @@ static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
81/* 81/*
82 * DAC mute control 82 * DAC mute control
83 */ 83 */
84
85/*
86 * idx = STAC9460 volume register number, mute: 0 = mute, 1 = unmute
87 */
88static int stac9460_dac_mute(struct snd_ice1712 *ice, int idx,
89 unsigned char mute)
90{
91 unsigned char new, old;
92 int change;
93 old = stac9460_get(ice, idx);
94 new = (~mute << 7 & 0x80) | (old & ~0x80);
95 change = (new != old);
96 if (change)
97 /*printk ("Volume register 0x%02x: 0x%02x\n", idx, new);*/
98 stac9460_put(ice, idx, new);
99 return change;
100}
101
84#define stac9460_dac_mute_info snd_ctl_boolean_mono_info 102#define stac9460_dac_mute_info snd_ctl_boolean_mono_info
85 103
86static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 104static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
@@ -101,20 +119,18 @@ static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
101static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 119static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
102{ 120{
103 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 121 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
104 unsigned char new, old; 122 int idx, change;
105 int idx;
106 int change;
107 123
108 if (kcontrol->private_value) 124 if (kcontrol->private_value)
109 idx = STAC946X_MASTER_VOLUME; 125 idx = STAC946X_MASTER_VOLUME;
110 else 126 else
111 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; 127 idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
112 old = stac9460_get(ice, idx); 128 /* due to possible conflicts with stac9460_set_rate_val, mutexing */
113 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80); 129 mutex_lock(&ice->spec.prodigy192.mute_mutex);
114 change = (new != old); 130 /*printk("Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx,
115 if (change) 131 ucontrol->value.integer.value[0]);*/
116 stac9460_put(ice, idx, new); 132 change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]);
117 133 mutex_unlock(&ice->spec.prodigy192.mute_mutex);
118 return change; 134 return change;
119} 135}
120 136
@@ -162,6 +178,8 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
162 ovol = 0x7f - (tmp & 0x7f); 178 ovol = 0x7f - (tmp & 0x7f);
163 change = (ovol != nvol); 179 change = (ovol != nvol);
164 if (change) { 180 if (change) {
181 ovol = (0x7f - nvol) | (tmp & 0x80);
182 /*printk("DAC Volume: reg 0x%02x: 0x%02x\n", idx, ovol);*/
165 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); 183 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
166 } 184 }
167 return change; 185 return change;
@@ -251,121 +269,6 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
251 return change; 269 return change;
252} 270}
253 271
254#if 0
255/*
256 * Headphone Amplifier
257 */
258static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
259{
260 unsigned int tmp, tmp2;
261
262 tmp2 = tmp = snd_ice1712_gpio_read(ice);
263 if (enable)
264 tmp |= AUREON_HP_SEL;
265 else
266 tmp &= ~ AUREON_HP_SEL;
267 if (tmp != tmp2) {
268 snd_ice1712_gpio_write(ice, tmp);
269 return 1;
270 }
271 return 0;
272}
273
274static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
275{
276 unsigned int tmp = snd_ice1712_gpio_read(ice);
277
278 return ( tmp & AUREON_HP_SEL )!= 0;
279}
280
281#define aureon_bool_info snd_ctl_boolean_mono_info
282
283static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
284{
285 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
286
287 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
288 return 0;
289}
290
291
292static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
293{
294 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
295
296 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
297}
298
299/*
300 * Deemphasis
301 */
302static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
303{
304 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
305 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
306 return 0;
307}
308
309static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
310{
311 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
312 int temp, temp2;
313 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
314 if (ucontrol->value.integer.value[0])
315 temp |= 0xf;
316 else
317 temp &= ~0xf;
318 if (temp != temp2) {
319 wm_put(ice, WM_DAC_CTRL2, temp);
320 return 1;
321 }
322 return 0;
323}
324
325/*
326 * ADC Oversampling
327 */
328static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
329{
330 static char *texts[2] = { "128x", "64x" };
331
332 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
333 uinfo->count = 1;
334 uinfo->value.enumerated.items = 2;
335
336 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
337 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
338 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
339
340 return 0;
341}
342
343static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
344{
345 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
346 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
347 return 0;
348}
349
350static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
351{
352 int temp, temp2;
353 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
354
355 temp2 = temp = wm_get(ice, WM_MASTER);
356
357 if (ucontrol->value.enumerated.item[0])
358 temp |= 0x8;
359 else
360 temp &= ~0x8;
361
362 if (temp != temp2) {
363 wm_put(ice, WM_MASTER, temp);
364 return 1;
365 }
366 return 0;
367}
368#endif
369static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, 272static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
370 struct snd_ctl_elem_info *uinfo) 273 struct snd_ctl_elem_info *uinfo)
371{ 274{
@@ -407,6 +310,56 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
407 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); 310 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
408 return change; 311 return change;
409} 312}
313/*
314 * Handler for setting correct codec rate - called when rate change is detected
315 */
316static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
317{
318 unsigned char old, new;
319 int idx;
320 unsigned char changed[7];
321 struct snd_ice1712 *ice = ak->private_data[0];
322
323 if (rate == 0) /* no hint - S/PDIF input is master, simply return */
324 return;
325 else if (rate <= 48000)
326 new = 0x08; /* 256x, base rate mode */
327 else if (rate <= 96000)
328 new = 0x11; /* 256x, mid rate mode */
329 else
330 new = 0x12; /* 128x, high rate mode */
331 old = stac9460_get(ice, STAC946X_MASTER_CLOCKING);
332 if (old == new)
333 return;
334 /* change detected, setting master clock, muting first */
335 /* due to possible conflicts with mute controls - mutexing */
336 mutex_lock(&ice->spec.prodigy192.mute_mutex);
337 /* we have to remember current mute status for each DAC */
338 for (idx = 0; idx < 7 ; ++idx)
339 changed[idx] = stac9460_dac_mute(ice,
340 STAC946X_MASTER_VOLUME + idx, 0);
341 /*printk("Rate change: %d, new MC: 0x%02x\n", rate, new);*/
342 stac9460_put(ice, STAC946X_MASTER_CLOCKING, new);
343 udelay(10);
344 /* unmuting - only originally unmuted dacs -
345 * i.e. those changed when muting */
346 for (idx = 0; idx < 7 ; ++idx) {
347 if (changed[idx])
348 stac9460_dac_mute(ice, STAC946X_MASTER_VOLUME + idx, 1);
349 }
350 mutex_unlock(&ice->spec.prodigy192.mute_mutex);
351}
352
353/* using akm infrastructure for setting rate of the codec */
354static struct snd_akm4xxx akmlike_stac9460 __devinitdata = {
355 .type = NON_AKM, /* special value */
356 .num_adcs = 6, /* not used in any way, just for completeness */
357 .num_dacs = 2,
358 .ops = {
359 .set_rate_val = stac9460_set_rate_val
360 }
361};
362
410 363
411static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); 364static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
412static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); 365static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
@@ -483,39 +436,8 @@ static struct snd_kcontrol_new stac_controls[] __devinitdata = {
483 .put = stac9460_mic_sw_put, 436 .put = stac9460_mic_sw_put,
484 437
485 }, 438 },
486#if 0
487 {
488 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
489 .name = "Capture Route",
490 .info = wm_adc_mux_info,
491 .get = wm_adc_mux_get,
492 .put = wm_adc_mux_put,
493 },
494 {
495 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
496 .name = "Headphone Amplifier Switch",
497 .info = aureon_bool_info,
498 .get = aureon_hpamp_get,
499 .put = aureon_hpamp_put
500 },
501 {
502 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
503 .name = "DAC Deemphasis Switch",
504 .info = aureon_bool_info,
505 .get = aureon_deemp_get,
506 .put = aureon_deemp_put
507 },
508 {
509 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
510 .name = "ADC Oversampling",
511 .info = aureon_oversampling_info,
512 .get = aureon_oversampling_get,
513 .put = aureon_oversampling_put
514 },
515#endif
516}; 439};
517 440
518
519/* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */ 441/* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */
520/* CDTO (pin 32) -- GPIO11 pin 86 442/* CDTO (pin 32) -- GPIO11 pin 86
521 * CDTI (pin 33) -- GPIO10 pin 77 443 * CDTI (pin 33) -- GPIO10 pin 77
@@ -720,6 +642,27 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
720 ice, &ice->spec.prodigy192.ak4114); 642 ice, &ice->spec.prodigy192.ak4114);
721} 643}
722 644
645static void stac9460_proc_regs_read(struct snd_info_entry *entry,
646 struct snd_info_buffer *buffer)
647{
648 struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
649 int reg, val;
650 /* registers 0x0 - 0x14 */
651 for (reg = 0; reg <= 0x15; reg++) {
652 val = stac9460_get(ice, reg);
653 snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
654 }
655}
656
657
658static void stac9460_proc_init(struct snd_ice1712 *ice)
659{
660 struct snd_info_entry *entry;
661 if (!snd_card_proc_new(ice->card, "stac9460_codec", &entry))
662 snd_info_set_text_ops(entry, ice, stac9460_proc_regs_read);
663}
664
665
723static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice) 666static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
724{ 667{
725 unsigned int i; 668 unsigned int i;
@@ -746,6 +689,7 @@ static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
746 if (err < 0) 689 if (err < 0)
747 return err; 690 return err;
748 } 691 }
692 stac9460_proc_init(ice);
749 return 0; 693 return 0;
750} 694}
751 695
@@ -778,6 +722,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
778{ 722{
779 static const unsigned short stac_inits_prodigy[] = { 723 static const unsigned short stac_inits_prodigy[] = {
780 STAC946X_RESET, 0, 724 STAC946X_RESET, 0,
725 STAC946X_MASTER_CLOCKING, 0x11,
781/* STAC946X_MASTER_VOLUME, 0, 726/* STAC946X_MASTER_VOLUME, 0,
782 STAC946X_LF_VOLUME, 0, 727 STAC946X_LF_VOLUME, 0,
783 STAC946X_RF_VOLUME, 0, 728 STAC946X_RF_VOLUME, 0,
@@ -789,6 +734,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
789 }; 734 };
790 const unsigned short *p; 735 const unsigned short *p;
791 int err = 0; 736 int err = 0;
737 struct snd_akm4xxx *ak;
792 738
793 /* prodigy 192 */ 739 /* prodigy 192 */
794 ice->num_total_dacs = 6; 740 ice->num_total_dacs = 6;
@@ -799,6 +745,15 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
799 p = stac_inits_prodigy; 745 p = stac_inits_prodigy;
800 for (; *p != (unsigned short)-1; p += 2) 746 for (; *p != (unsigned short)-1; p += 2)
801 stac9460_put(ice, p[0], p[1]); 747 stac9460_put(ice, p[0], p[1]);
748 /* reusing the akm codecs infrastructure,
749 * for setting rate on stac9460 */
750 ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
751 if (!ak)
752 return -ENOMEM;
753 ice->akm_codecs = 1;
754 err = snd_ice1712_akm4xxx_init(ak, &akmlike_stac9460, NULL, ice);
755 if (err < 0)
756 return err;
802 757
803 /* MI/ODI/O add on card with AK4114 */ 758 /* MI/ODI/O add on card with AK4114 */
804 if (prodigy192_miodio_exists(ice)) { 759 if (prodigy192_miodio_exists(ice)) {
@@ -812,6 +767,8 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
812 if (err < 0) 767 if (err < 0)
813 return err; 768 return err;
814 769
770 mutex_init(&ice->spec.prodigy192.mute_mutex);
771
815 return 0; 772 return 0;
816} 773}
817 774
@@ -854,6 +811,10 @@ struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
854 .build_controls = prodigy192_add_controls, 811 .build_controls = prodigy192_add_controls,
855 .eeprom_size = sizeof(prodigy71_eeprom), 812 .eeprom_size = sizeof(prodigy71_eeprom),
856 .eeprom_data = prodigy71_eeprom, 813 .eeprom_data = prodigy71_eeprom,
814 /* the current MPU401 code loops infinitely
815 * when opening midi device
816 */
817 .no_mpu401 = 1,
857 }, 818 },
858 { } /* terminator */ 819 { } /* terminator */
859}; 820};