aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Hofman <pavel.hofman@ivitera.com>2009-09-16 16:25:36 -0400
committerTakashi Iwai <tiwai@suse.de>2009-09-21 09:44:51 -0400
commit8f34692f63d66805b51ff408f4067748d3c1c3fd (patch)
treedc2bd50fb2743b862c97bac848200bb8e26f0f53
parentc0a9eedf9acafb083adf3ddbff0a1e4d6d9a6949 (diff)
ALSA: ak4620 support, codec regs listed in proc
* complete support for ak4620 * codec regs listed in proc for all codecs/chips * adding total regs for each codec * fixing nb. of steps in input attenuation controls Signed-off-by: Pavel Hofman <pavel.hofman@ivitera.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--include/sound/ak4xxx-adda.h5
-rw-r--r--sound/i2c/other/ak4xxx-adda.c136
-rw-r--r--sound/pci/ice1712/juli.c21
3 files changed, 108 insertions, 54 deletions
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index 891cf1aea8b1..030b87c2f6d4 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, SND_AK4620,
72 } type; 72 } type;
73 73
74 /* (array) information of combined codecs */ 74 /* (array) information of combined codecs */
@@ -76,6 +76,9 @@ struct snd_akm4xxx {
76 const struct snd_akm4xxx_adc_channel *adc_info; 76 const struct snd_akm4xxx_adc_channel *adc_info;
77 77
78 struct snd_ak4xxx_ops ops; 78 struct snd_ak4xxx_ops ops;
79 unsigned int num_chips;
80 unsigned int total_regs;
81 const char *name;
79}; 82};
80 83
81void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, 84void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg,
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index ee47abab764e..1adb8a3c2b62 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -19,7 +19,7 @@
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * 21 *
22 */ 22 */
23 23
24#include <asm/io.h> 24#include <asm/io.h>
25#include <linux/delay.h> 25#include <linux/delay.h>
@@ -29,6 +29,7 @@
29#include <sound/control.h> 29#include <sound/control.h>
30#include <sound/tlv.h> 30#include <sound/tlv.h>
31#include <sound/ak4xxx-adda.h> 31#include <sound/ak4xxx-adda.h>
32#include <sound/info.h>
32 33
33MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); 34MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");
34MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); 35MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters");
@@ -52,26 +53,21 @@ EXPORT_SYMBOL(snd_akm4xxx_write);
52static void ak4524_reset(struct snd_akm4xxx *ak, int state) 53static void ak4524_reset(struct snd_akm4xxx *ak, int state)
53{ 54{
54 unsigned int chip; 55 unsigned int chip;
55 unsigned char reg, maxreg; 56 unsigned char reg;
56 57
57 if (ak->type == SND_AK4528)
58 maxreg = 0x06;
59 else
60 maxreg = 0x08;
61 for (chip = 0; chip < ak->num_dacs/2; chip++) { 58 for (chip = 0; chip < ak->num_dacs/2; chip++) {
62 snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); 59 snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03);
63 if (state) 60 if (state)
64 continue; 61 continue;
65 /* DAC volumes */ 62 /* DAC volumes */
66 for (reg = 0x04; reg < maxreg; reg++) 63 for (reg = 0x04; reg < ak->total_regs; reg++)
67 snd_akm4xxx_write(ak, chip, reg, 64 snd_akm4xxx_write(ak, chip, reg,
68 snd_akm4xxx_get(ak, chip, reg)); 65 snd_akm4xxx_get(ak, chip, reg));
69 } 66 }
70} 67}
71 68
72/* reset procedure for AK4355 and AK4358 */ 69/* reset procedure for AK4355 and AK4358 */
73static void ak435X_reset(struct snd_akm4xxx *ak, int state, 70static void ak435X_reset(struct snd_akm4xxx *ak, int state)
74 unsigned char total_regs)
75{ 71{
76 unsigned char reg; 72 unsigned char reg;
77 73
@@ -79,7 +75,7 @@ static void ak435X_reset(struct snd_akm4xxx *ak, int state,
79 snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ 75 snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
80 return; 76 return;
81 } 77 }
82 for (reg = 0x00; reg < total_regs; reg++) 78 for (reg = 0x00; reg < ak->total_regs; reg++)
83 if (reg != 0x01) 79 if (reg != 0x01)
84 snd_akm4xxx_write(ak, 0, reg, 80 snd_akm4xxx_write(ak, 0, reg,
85 snd_akm4xxx_get(ak, 0, reg)); 81 snd_akm4xxx_get(ak, 0, reg));
@@ -91,12 +87,11 @@ static void ak4381_reset(struct snd_akm4xxx *ak, int state)
91{ 87{
92 unsigned int chip; 88 unsigned int chip;
93 unsigned char reg; 89 unsigned char reg;
94
95 for (chip = 0; chip < ak->num_dacs/2; chip++) { 90 for (chip = 0; chip < ak->num_dacs/2; chip++) {
96 snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); 91 snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f);
97 if (state) 92 if (state)
98 continue; 93 continue;
99 for (reg = 0x01; reg < 0x05; reg++) 94 for (reg = 0x01; reg < ak->total_regs; reg++)
100 snd_akm4xxx_write(ak, chip, reg, 95 snd_akm4xxx_write(ak, chip, reg,
101 snd_akm4xxx_get(ak, chip, reg)); 96 snd_akm4xxx_get(ak, chip, reg));
102 } 97 }
@@ -113,16 +108,17 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
113 switch (ak->type) { 108 switch (ak->type) {
114 case SND_AK4524: 109 case SND_AK4524:
115 case SND_AK4528: 110 case SND_AK4528:
111 case SND_AK4620:
116 ak4524_reset(ak, state); 112 ak4524_reset(ak, state);
117 break; 113 break;
118 case SND_AK4529: 114 case SND_AK4529:
119 /* FIXME: needed for ak4529? */ 115 /* FIXME: needed for ak4529? */
120 break; 116 break;
121 case SND_AK4355: 117 case SND_AK4355:
122 ak435X_reset(ak, state, 0x0b); 118 ak435X_reset(ak, state);
123 break; 119 break;
124 case SND_AK4358: 120 case SND_AK4358:
125 ak435X_reset(ak, state, 0x10); 121 ak435X_reset(ak, state);
126 break; 122 break;
127 case SND_AK4381: 123 case SND_AK4381:
128 ak4381_reset(ak, state); 124 ak4381_reset(ak, state);
@@ -139,7 +135,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset);
139 * Volume conversion table for non-linear volumes 135 * Volume conversion table for non-linear volumes
140 * from -63.5dB (mute) to 0dB step 0.5dB 136 * from -63.5dB (mute) to 0dB step 0.5dB
141 * 137 *
142 * Used for AK4524 input/ouput attenuation, AK4528, and 138 * Used for AK4524/AK4620 input/ouput attenuation, AK4528, and
143 * AK5365 input attenuation 139 * AK5365 input attenuation
144 */ 140 */
145static const unsigned char vol_cvt_datt[128] = { 141static const unsigned char vol_cvt_datt[128] = {
@@ -259,8 +255,22 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
259 0x00, 0x0f, /* 0: power-up, un-reset */ 255 0x00, 0x0f, /* 0: power-up, un-reset */
260 0xff, 0xff 256 0xff, 0xff
261 }; 257 };
258 static const unsigned char inits_ak4620[] = {
259 0x00, 0x07, /* 0: normal */
260 0x01, 0x00, /* 0: reset */
261 0x01, 0x02, /* 1: RSTAD */
262 0x01, 0x03, /* 1: RSTDA */
263 0x01, 0x0f, /* 1: normal */
264 0x02, 0x60, /* 2: 24bit I2S */
265 0x03, 0x01, /* 3: deemphasis off */
266 0x04, 0x00, /* 4: LIN muted */
267 0x05, 0x00, /* 5: RIN muted */
268 0x06, 0x00, /* 6: LOUT muted */
269 0x07, 0x00, /* 7: ROUT muted */
270 0xff, 0xff
271 };
262 272
263 int chip, num_chips; 273 int chip;
264 const unsigned char *ptr, *inits; 274 const unsigned char *ptr, *inits;
265 unsigned char reg, data; 275 unsigned char reg, data;
266 276
@@ -270,42 +280,64 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
270 switch (ak->type) { 280 switch (ak->type) {
271 case SND_AK4524: 281 case SND_AK4524:
272 inits = inits_ak4524; 282 inits = inits_ak4524;
273 num_chips = ak->num_dacs / 2; 283 ak->num_chips = ak->num_dacs / 2;
284 ak->name = "ak4524";
285 ak->total_regs = 0x08;
274 break; 286 break;
275 case SND_AK4528: 287 case SND_AK4528:
276 inits = inits_ak4528; 288 inits = inits_ak4528;
277 num_chips = ak->num_dacs / 2; 289 ak->num_chips = ak->num_dacs / 2;
290 ak->name = "ak4528";
291 ak->total_regs = 0x06;
278 break; 292 break;
279 case SND_AK4529: 293 case SND_AK4529:
280 inits = inits_ak4529; 294 inits = inits_ak4529;
281 num_chips = 1; 295 ak->num_chips = 1;
296 ak->name = "ak4529";
297 ak->total_regs = 0x0d;
282 break; 298 break;
283 case SND_AK4355: 299 case SND_AK4355:
284 inits = inits_ak4355; 300 inits = inits_ak4355;
285 num_chips = 1; 301 ak->num_chips = 1;
302 ak->name = "ak4355";
303 ak->total_regs = 0x0b;
286 break; 304 break;
287 case SND_AK4358: 305 case SND_AK4358:
288 inits = inits_ak4358; 306 inits = inits_ak4358;
289 num_chips = 1; 307 ak->num_chips = 1;
308 ak->name = "ak4358";
309 ak->total_regs = 0x10;
290 break; 310 break;
291 case SND_AK4381: 311 case SND_AK4381:
292 inits = inits_ak4381; 312 inits = inits_ak4381;
293 num_chips = ak->num_dacs / 2; 313 ak->num_chips = ak->num_dacs / 2;
314 ak->name = "ak4381";
315 ak->total_regs = 0x05;
294 break; 316 break;
295 case SND_AK5365: 317 case SND_AK5365:
296 /* FIXME: any init sequence? */ 318 /* FIXME: any init sequence? */
319 ak->num_chips = 1;
320 ak->name = "ak5365";
321 ak->total_regs = 0x08;
297 return; 322 return;
323 case SND_AK4620:
324 inits = inits_ak4620;
325 ak->num_chips = ak->num_dacs / 2;
326 ak->name = "ak4620";
327 ak->total_regs = 0x08;
328 break;
298 default: 329 default:
299 snd_BUG(); 330 snd_BUG();
300 return; 331 return;
301 } 332 }
302 333
303 for (chip = 0; chip < num_chips; chip++) { 334 for (chip = 0; chip < ak->num_chips; chip++) {
304 ptr = inits; 335 ptr = inits;
305 while (*ptr != 0xff) { 336 while (*ptr != 0xff) {
306 reg = *ptr++; 337 reg = *ptr++;
307 data = *ptr++; 338 data = *ptr++;
308 snd_akm4xxx_write(ak, chip, reg, data); 339 snd_akm4xxx_write(ak, chip, reg, data);
340 udelay(10);
309 } 341 }
310 } 342 }
311} 343}
@@ -688,6 +720,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
688 AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); 720 AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255);
689 knew.tlv.p = db_scale_linear; 721 knew.tlv.p = db_scale_linear;
690 break; 722 break;
723 case SND_AK4620:
724 /* register 6 & 7 */
725 knew.private_value =
726 AK_COMPOSE(idx/2, (idx%2) + 6, 0, 255);
727 knew.tlv.p = db_scale_linear;
728 break;
691 default: 729 default:
692 return -EINVAL; 730 return -EINVAL;
693 } 731 }
@@ -704,10 +742,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
704 742
705static int build_adc_controls(struct snd_akm4xxx *ak) 743static int build_adc_controls(struct snd_akm4xxx *ak)
706{ 744{
707 int idx, err, mixer_ch, num_stereo; 745 int idx, err, mixer_ch, num_stereo, max_steps;
708 struct snd_kcontrol_new knew; 746 struct snd_kcontrol_new knew;
709 747
710 mixer_ch = 0; 748 mixer_ch = 0;
749 if (ak->type == SND_AK4528)
750 return 0; /* no controls */
711 for (idx = 0; idx < ak->num_adcs;) { 751 for (idx = 0; idx < ak->num_adcs;) {
712 memset(&knew, 0, sizeof(knew)); 752 memset(&knew, 0, sizeof(knew));
713 if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { 753 if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) {
@@ -733,13 +773,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak)
733 } 773 }
734 /* register 4 & 5 */ 774 /* register 4 & 5 */
735 if (ak->type == SND_AK5365) 775 if (ak->type == SND_AK5365)
736 knew.private_value = 776 max_steps = 152;
737 AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) |
738 AK_VOL_CVT | AK_IPGA;
739 else 777 else
740 knew.private_value = 778 max_steps = 164;
741 AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | 779 knew.private_value =
742 AK_VOL_CVT | AK_IPGA; 780 AK_COMPOSE(idx/2, (idx%2) + 4, 0, max_steps) |
781 AK_VOL_CVT | AK_IPGA;
743 knew.tlv.p = db_scale_vol_datt; 782 knew.tlv.p = db_scale_vol_datt;
744 err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); 783 err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
745 if (err < 0) 784 if (err < 0)
@@ -808,6 +847,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
808 switch (ak->type) { 847 switch (ak->type) {
809 case SND_AK4524: 848 case SND_AK4524:
810 case SND_AK4528: 849 case SND_AK4528:
850 case SND_AK4620:
811 /* register 3 */ 851 /* register 3 */
812 knew.private_value = AK_COMPOSE(idx, 3, 0, 0); 852 knew.private_value = AK_COMPOSE(idx, 3, 0, 0);
813 break; 853 break;
@@ -834,6 +874,35 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
834 return 0; 874 return 0;
835} 875}
836 876
877#ifdef CONFIG_PROC_FS
878static void proc_regs_read(struct snd_info_entry *entry,
879 struct snd_info_buffer *buffer)
880{
881 struct snd_akm4xxx *ak = (struct snd_akm4xxx *)entry->private_data;
882 int reg, val, chip;
883 for (chip = 0; chip < ak->num_chips; chip++) {
884 for (reg = 0; reg < ak->total_regs; reg++) {
885 val = snd_akm4xxx_get(ak, chip, reg);
886 snd_iprintf(buffer, "chip %d: 0x%02x = 0x%02x\n", chip,
887 reg, val);
888 }
889 }
890}
891
892static int proc_init(struct snd_akm4xxx *ak)
893{
894 struct snd_info_entry *entry;
895 int err;
896 err = snd_card_proc_new(ak->card, ak->name, &entry);
897 if (err < 0)
898 return err;
899 snd_info_set_text_ops(entry, ak, proc_regs_read);
900 return 0;
901}
902#else /* !CONFIG_PROC_FS */
903static int proc_init(struct snd_akm4xxx *ak) {}
904#endif
905
837int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) 906int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
838{ 907{
839 int err, num_emphs; 908 int err, num_emphs;
@@ -845,18 +914,21 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
845 err = build_adc_controls(ak); 914 err = build_adc_controls(ak);
846 if (err < 0) 915 if (err < 0)
847 return err; 916 return err;
848
849 if (ak->type == SND_AK4355 || ak->type == SND_AK4358) 917 if (ak->type == SND_AK4355 || ak->type == SND_AK4358)
850 num_emphs = 1; 918 num_emphs = 1;
919 else if (ak->type == SND_AK4620)
920 num_emphs = 0;
851 else 921 else
852 num_emphs = ak->num_dacs / 2; 922 num_emphs = ak->num_dacs / 2;
853 err = build_deemphasis(ak, num_emphs); 923 err = build_deemphasis(ak, num_emphs);
854 if (err < 0) 924 if (err < 0)
855 return err; 925 return err;
926 err = proc_init(ak);
927 if (err < 0)
928 return err;
856 929
857 return 0; 930 return 0;
858} 931}
859
860EXPORT_SYMBOL(snd_akm4xxx_build_controls); 932EXPORT_SYMBOL(snd_akm4xxx_build_controls);
861 933
862static int __init alsa_akm4xxx_module_init(void) 934static int __init alsa_akm4xxx_module_init(void)
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index fd948bfd9aef..4789e8bfdc17 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -412,25 +412,6 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
412 }, 412 },
413}; 413};
414 414
415
416static void ak4358_proc_regs_read(struct snd_info_entry *entry,
417 struct snd_info_buffer *buffer)
418{
419 struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
420 int reg, val;
421 for (reg = 0; reg <= 0xf; reg++) {
422 val = snd_akm4xxx_get(ice->akm, 0, reg);
423 snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
424 }
425}
426
427static void ak4358_proc_init(struct snd_ice1712 *ice)
428{
429 struct snd_info_entry *entry;
430 if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry))
431 snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read);
432}
433
434static char *slave_vols[] __devinitdata = { 415static char *slave_vols[] __devinitdata = {
435 PCM_VOLUME, 416 PCM_VOLUME,
436 MONITOR_AN_IN_VOLUME, 417 MONITOR_AN_IN_VOLUME,
@@ -496,8 +477,6 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
496 /* only capture SPDIF over AK4114 */ 477 /* only capture SPDIF over AK4114 */
497 err = snd_ak4114_build(spec->ak4114, NULL, 478 err = snd_ak4114_build(spec->ak4114, NULL,
498 ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); 479 ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
499
500 ak4358_proc_init(ice);
501 if (err < 0) 480 if (err < 0)
502 return err; 481 return err;
503 return 0; 482 return 0;