diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-08-30 10:49:54 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-09-23 04:45:08 -0400 |
commit | 723b2b0d36fa7cea81a962af2d40d88520d5a5f1 (patch) | |
tree | 0020b109e0792aba552c99cff7b6576b81a5c2b6 /sound/i2c | |
parent | d0ae48471570c680333cbe28c143bbab887a4ec2 (diff) |
[ALSA] Clean up and add TLV support to AK4xxx i2c driver
- Clean up the code in AK4xxx-ADDA i2c code.
- Fix capture gain controls for AK5365
- Changed the static table for DAC/ADC mixer labels to use
structs
- Implemented TLV entries for each AK codec
The volumes in AK4524, AK4528 and AK5365 are corrected with
a table to be suitable for dB conversion.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/i2c')
-rw-r--r-- | sound/i2c/other/ak4xxx-adda.c | 523 |
1 files changed, 294 insertions, 229 deletions
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index 89fc3cbc2356..c34cb4684607 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -28,12 +28,14 @@ | |||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include <sound/control.h> | 30 | #include <sound/control.h> |
31 | #include <sound/tlv.h> | ||
31 | #include <sound/ak4xxx-adda.h> | 32 | #include <sound/ak4xxx-adda.h> |
32 | 33 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>"); |
34 | MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); | 35 | MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); |
35 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
36 | 37 | ||
38 | /* write the given register and save the data to the cache */ | ||
37 | void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, | 39 | void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, |
38 | unsigned char val) | 40 | unsigned char val) |
39 | { | 41 | { |
@@ -41,15 +43,10 @@ void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, | |||
41 | ak->ops.write(ak, chip, reg, val); | 43 | ak->ops.write(ak, chip, reg, val); |
42 | 44 | ||
43 | /* save the data */ | 45 | /* save the data */ |
44 | if (ak->type == SND_AK4524 || ak->type == SND_AK4528) { | 46 | /* don't overwrite with IPGA data */ |
45 | if ((reg != 0x04 && reg != 0x05) || (val & 0x80) == 0) | 47 | if ((ak->type != SND_AK4524 && ak->type != SND_AK5365) || |
46 | snd_akm4xxx_set(ak, chip, reg, val); | 48 | (reg != 0x04 && reg != 0x05) || (val & 0x80) == 0) |
47 | else | ||
48 | snd_akm4xxx_set_ipga(ak, chip, reg, val); | ||
49 | } else { | ||
50 | /* AK4529, or else */ | ||
51 | snd_akm4xxx_set(ak, chip, reg, val); | 49 | snd_akm4xxx_set(ak, chip, reg, val); |
52 | } | ||
53 | ak->ops.unlock(ak, chip); | 50 | ak->ops.unlock(ak, chip); |
54 | } | 51 | } |
55 | 52 | ||
@@ -78,7 +75,7 @@ static void ak4524_reset(struct snd_akm4xxx *ak, int state) | |||
78 | /* IPGA */ | 75 | /* IPGA */ |
79 | for (reg = 0x04; reg < 0x06; reg++) | 76 | for (reg = 0x04; reg < 0x06; reg++) |
80 | snd_akm4xxx_write(ak, chip, reg, | 77 | snd_akm4xxx_write(ak, chip, reg, |
81 | snd_akm4xxx_get_ipga(ak, chip, reg)); | 78 | snd_akm4xxx_get_ipga(ak, chip, reg) | 0x80); |
82 | } | 79 | } |
83 | } | 80 | } |
84 | 81 | ||
@@ -144,6 +141,42 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state) | |||
144 | 141 | ||
145 | EXPORT_SYMBOL(snd_akm4xxx_reset); | 142 | EXPORT_SYMBOL(snd_akm4xxx_reset); |
146 | 143 | ||
144 | |||
145 | /* | ||
146 | * Volume conversion table for non-linear volumes | ||
147 | * from -63.5dB (mute) to 0dB step 0.5dB | ||
148 | * | ||
149 | * Used for AK4524 input/ouput attenuation, AK4528, and | ||
150 | * AK5365 input attenuation | ||
151 | */ | ||
152 | static unsigned char vol_cvt_datt[128] = { | ||
153 | 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, | ||
154 | 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, | ||
155 | 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a, | ||
156 | 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, | ||
157 | 0x10, 0x10, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14, | ||
158 | 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1c, | ||
159 | 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x23, | ||
160 | 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2d, | ||
161 | 0x2e, 0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, | ||
162 | 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x3f, 0x40, | ||
163 | 0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4a, | ||
164 | 0x4b, 0x4d, 0x4e, 0x50, 0x51, 0x52, 0x53, 0x54, | ||
165 | 0x55, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x5f, | ||
166 | 0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x69, | ||
167 | 0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x72, 0x73, | ||
168 | 0x75, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f, | ||
169 | }; | ||
170 | |||
171 | /* | ||
172 | * dB tables | ||
173 | */ | ||
174 | static DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1); | ||
175 | static DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1); | ||
176 | static DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1); | ||
177 | static DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0); | ||
178 | static DECLARE_TLV_DB_SCALE(db_scale_ipga, 0, 50, 0); | ||
179 | |||
147 | /* | 180 | /* |
148 | * initialize all the ak4xxx chips | 181 | * initialize all the ak4xxx chips |
149 | */ | 182 | */ |
@@ -240,6 +273,9 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
240 | int chip, num_chips; | 273 | int chip, num_chips; |
241 | unsigned char *ptr, reg, data, *inits; | 274 | unsigned char *ptr, reg, data, *inits; |
242 | 275 | ||
276 | memset(ak->images, 0, sizeof(ak->images)); | ||
277 | memset(ak->volumes, 0, sizeof(ak->volumes)); | ||
278 | |||
243 | switch (ak->type) { | 279 | switch (ak->type) { |
244 | case SND_AK4524: | 280 | case SND_AK4524: |
245 | inits = inits_ak4524; | 281 | inits = inits_ak4524; |
@@ -265,6 +301,9 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
265 | inits = inits_ak4381; | 301 | inits = inits_ak4381; |
266 | num_chips = ak->num_dacs / 2; | 302 | num_chips = ak->num_dacs / 2; |
267 | break; | 303 | break; |
304 | case SND_AK5365: | ||
305 | /* FIXME: any init sequence? */ | ||
306 | return; | ||
268 | default: | 307 | default: |
269 | snd_BUG(); | 308 | snd_BUG(); |
270 | return; | 309 | return; |
@@ -282,16 +321,21 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
282 | 321 | ||
283 | EXPORT_SYMBOL(snd_akm4xxx_init); | 322 | EXPORT_SYMBOL(snd_akm4xxx_init); |
284 | 323 | ||
324 | /* | ||
325 | * Mixer callbacks | ||
326 | */ | ||
327 | #define AK_VOL_CVT (1<<21) /* need dB conversion */ | ||
328 | #define AK_NEEDSMSB (1<<22) /* need MSB update bit */ | ||
329 | #define AK_INVERT (1<<23) /* data is inverted */ | ||
285 | #define AK_GET_CHIP(val) (((val) >> 8) & 0xff) | 330 | #define AK_GET_CHIP(val) (((val) >> 8) & 0xff) |
286 | #define AK_GET_ADDR(val) ((val) & 0xff) | 331 | #define AK_GET_ADDR(val) ((val) & 0xff) |
287 | #define AK_GET_SHIFT(val) (((val) >> 16) & 0x3f) | 332 | #define AK_GET_SHIFT(val) (((val) >> 16) & 0x1f) |
333 | #define AK_GET_VOL_CVT(val) (((val) >> 21) & 1) | ||
288 | #define AK_GET_NEEDSMSB(val) (((val) >> 22) & 1) | 334 | #define AK_GET_NEEDSMSB(val) (((val) >> 22) & 1) |
289 | #define AK_GET_INVERT(val) (((val) >> 23) & 1) | 335 | #define AK_GET_INVERT(val) (((val) >> 23) & 1) |
290 | #define AK_GET_MASK(val) (((val) >> 24) & 0xff) | 336 | #define AK_GET_MASK(val) (((val) >> 24) & 0xff) |
291 | #define AK_COMPOSE(chip,addr,shift,mask) \ | 337 | #define AK_COMPOSE(chip,addr,shift,mask) \ |
292 | (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) | 338 | (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) |
293 | #define AK_NEEDSMSB (1<<22) | ||
294 | #define AK_INVERT (1<<23) | ||
295 | 339 | ||
296 | static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol, | 340 | static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol, |
297 | struct snd_ctl_elem_info *uinfo) | 341 | struct snd_ctl_elem_info *uinfo) |
@@ -311,37 +355,37 @@ static int snd_akm4xxx_volume_get(struct snd_kcontrol *kcontrol, | |||
311 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | 355 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); |
312 | int chip = AK_GET_CHIP(kcontrol->private_value); | 356 | int chip = AK_GET_CHIP(kcontrol->private_value); |
313 | int addr = AK_GET_ADDR(kcontrol->private_value); | 357 | int addr = AK_GET_ADDR(kcontrol->private_value); |
314 | int needsmsb = AK_GET_NEEDSMSB(kcontrol->private_value); | ||
315 | int invert = AK_GET_INVERT(kcontrol->private_value); | ||
316 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); | ||
317 | unsigned char val = snd_akm4xxx_get(ak, chip, addr); | ||
318 | 358 | ||
319 | if (needsmsb) | 359 | ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); |
320 | val &= 0x7f; | ||
321 | ucontrol->value.integer.value[0] = invert ? mask - val : val; | ||
322 | return 0; | 360 | return 0; |
323 | } | 361 | } |
324 | 362 | ||
325 | static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, | 363 | static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr, |
326 | struct snd_ctl_elem_value *ucontrol) | 364 | unsigned char nval) |
327 | { | 365 | { |
328 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | 366 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); |
329 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
330 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
331 | int needsmsb = AK_GET_NEEDSMSB(kcontrol->private_value); | ||
332 | int invert = AK_GET_INVERT(kcontrol->private_value); | ||
333 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); | 367 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); |
334 | unsigned char nval = ucontrol->value.integer.value[0] % (mask+1); | 368 | int chip = AK_GET_CHIP(kcontrol->private_value); |
335 | int change; | ||
336 | 369 | ||
337 | if (invert) | 370 | if (snd_akm4xxx_get_vol(ak, chip, addr) == nval) |
371 | return 0; | ||
372 | |||
373 | snd_akm4xxx_set_vol(ak, chip, addr, nval); | ||
374 | if (AK_GET_VOL_CVT(kcontrol->private_value)) | ||
375 | nval = vol_cvt_datt[nval]; | ||
376 | if (AK_GET_INVERT(kcontrol->private_value)) | ||
338 | nval = mask - nval; | 377 | nval = mask - nval; |
339 | if (needsmsb) | 378 | if (AK_GET_NEEDSMSB(kcontrol->private_value)) |
340 | nval |= 0x80; | 379 | nval |= 0x80; |
341 | change = snd_akm4xxx_get(ak, chip, addr) != nval; | 380 | snd_akm4xxx_write(ak, chip, addr, nval); |
342 | if (change) | 381 | return 1; |
343 | snd_akm4xxx_write(ak, chip, addr, nval); | 382 | } |
344 | return change; | 383 | |
384 | static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, | ||
385 | struct snd_ctl_elem_value *ucontrol) | ||
386 | { | ||
387 | return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), | ||
388 | ucontrol->value.integer.value[0]); | ||
345 | } | 389 | } |
346 | 390 | ||
347 | static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, | 391 | static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, |
@@ -362,66 +406,25 @@ static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol, | |||
362 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | 406 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); |
363 | int chip = AK_GET_CHIP(kcontrol->private_value); | 407 | int chip = AK_GET_CHIP(kcontrol->private_value); |
364 | int addr = AK_GET_ADDR(kcontrol->private_value); | 408 | int addr = AK_GET_ADDR(kcontrol->private_value); |
365 | int needsmsb = AK_GET_NEEDSMSB(kcontrol->private_value); | ||
366 | int invert = AK_GET_INVERT(kcontrol->private_value); | ||
367 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); | ||
368 | unsigned char val; | ||
369 | |||
370 | val = snd_akm4xxx_get(ak, chip, addr); | ||
371 | if (needsmsb) | ||
372 | val &= 0x7f; | ||
373 | ucontrol->value.integer.value[0] = invert ? mask - val : val; | ||
374 | |||
375 | val = snd_akm4xxx_get(ak, chip, addr+1); | ||
376 | if (needsmsb) | ||
377 | val &= 0x7f; | ||
378 | ucontrol->value.integer.value[1] = invert ? mask - val : val; | ||
379 | 409 | ||
410 | ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); | ||
411 | ucontrol->value.integer.value[1] = snd_akm4xxx_get_vol(ak, chip, addr+1); | ||
380 | return 0; | 412 | return 0; |
381 | } | 413 | } |
382 | 414 | ||
383 | static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, | 415 | static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, |
384 | struct snd_ctl_elem_value *ucontrol) | 416 | struct snd_ctl_elem_value *ucontrol) |
385 | { | 417 | { |
386 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
387 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
388 | int addr = AK_GET_ADDR(kcontrol->private_value); | 418 | int addr = AK_GET_ADDR(kcontrol->private_value); |
389 | int needsmsb = AK_GET_NEEDSMSB(kcontrol->private_value); | 419 | int change; |
390 | int invert = AK_GET_INVERT(kcontrol->private_value); | ||
391 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); | ||
392 | unsigned char nval = ucontrol->value.integer.value[0] % (mask+1); | ||
393 | int change0, change1; | ||
394 | |||
395 | if (invert) | ||
396 | nval = mask - nval; | ||
397 | if (needsmsb) | ||
398 | nval |= 0x80; | ||
399 | change0 = snd_akm4xxx_get(ak, chip, addr) != nval; | ||
400 | if (change0) | ||
401 | snd_akm4xxx_write(ak, chip, addr, nval); | ||
402 | |||
403 | nval = ucontrol->value.integer.value[1] % (mask+1); | ||
404 | if (invert) | ||
405 | nval = mask - nval; | ||
406 | if (needsmsb) | ||
407 | nval |= 0x80; | ||
408 | change1 = snd_akm4xxx_get(ak, chip, addr+1) != nval; | ||
409 | if (change1) | ||
410 | snd_akm4xxx_write(ak, chip, addr+1, nval); | ||
411 | |||
412 | 420 | ||
413 | return change0 || change1; | 421 | change = put_ak_reg(kcontrol, addr, ucontrol->value.integer.value[0]); |
422 | change |= put_ak_reg(kcontrol, addr + 1, | ||
423 | ucontrol->value.integer.value[1]); | ||
424 | return change; | ||
414 | } | 425 | } |
415 | 426 | ||
416 | static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol, | 427 | #define snd_akm4xxx_ipga_gain_info snd_akm4xxx_volume_info |
417 | struct snd_ctl_elem_info *uinfo) | ||
418 | { | ||
419 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
420 | uinfo->count = 1; | ||
421 | uinfo->value.integer.min = 0; | ||
422 | uinfo->value.integer.max = 36; | ||
423 | return 0; | ||
424 | } | ||
425 | 428 | ||
426 | static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol, | 429 | static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol, |
427 | struct snd_ctl_elem_value *ucontrol) | 430 | struct snd_ctl_elem_value *ucontrol) |
@@ -429,21 +432,57 @@ static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol, | |||
429 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | 432 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); |
430 | int chip = AK_GET_CHIP(kcontrol->private_value); | 433 | int chip = AK_GET_CHIP(kcontrol->private_value); |
431 | int addr = AK_GET_ADDR(kcontrol->private_value); | 434 | int addr = AK_GET_ADDR(kcontrol->private_value); |
435 | |||
432 | ucontrol->value.integer.value[0] = | 436 | ucontrol->value.integer.value[0] = |
433 | snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f; | 437 | snd_akm4xxx_get_ipga(ak, chip, addr); |
434 | return 0; | 438 | return 0; |
435 | } | 439 | } |
436 | 440 | ||
441 | static int put_ak_ipga(struct snd_kcontrol *kcontrol, int addr, | ||
442 | unsigned char nval) | ||
443 | { | ||
444 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
445 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
446 | |||
447 | if (snd_akm4xxx_get_ipga(ak, chip, addr) == nval) | ||
448 | return 0; | ||
449 | snd_akm4xxx_set_ipga(ak, chip, addr, nval); | ||
450 | snd_akm4xxx_write(ak, chip, addr, nval | 0x80); /* need MSB */ | ||
451 | return 1; | ||
452 | } | ||
453 | |||
437 | static int snd_akm4xxx_ipga_gain_put(struct snd_kcontrol *kcontrol, | 454 | static int snd_akm4xxx_ipga_gain_put(struct snd_kcontrol *kcontrol, |
438 | struct snd_ctl_elem_value *ucontrol) | 455 | struct snd_ctl_elem_value *ucontrol) |
439 | { | 456 | { |
457 | return put_ak_ipga(kcontrol, AK_GET_ADDR(kcontrol->private_value), | ||
458 | ucontrol->value.integer.value[0]); | ||
459 | } | ||
460 | |||
461 | #define snd_akm4xxx_stereo_gain_info snd_akm4xxx_stereo_volume_info | ||
462 | |||
463 | static int snd_akm4xxx_stereo_gain_get(struct snd_kcontrol *kcontrol, | ||
464 | struct snd_ctl_elem_value *ucontrol) | ||
465 | { | ||
440 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | 466 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); |
441 | int chip = AK_GET_CHIP(kcontrol->private_value); | 467 | int chip = AK_GET_CHIP(kcontrol->private_value); |
442 | int addr = AK_GET_ADDR(kcontrol->private_value); | 468 | int addr = AK_GET_ADDR(kcontrol->private_value); |
443 | unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80; | 469 | |
444 | int change = snd_akm4xxx_get_ipga(ak, chip, addr) != nval; | 470 | ucontrol->value.integer.value[0] = |
445 | if (change) | 471 | snd_akm4xxx_get_ipga(ak, chip, addr); |
446 | snd_akm4xxx_write(ak, chip, addr, nval); | 472 | ucontrol->value.integer.value[1] = |
473 | snd_akm4xxx_get_ipga(ak, chip, addr + 1); | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int snd_akm4xxx_stereo_gain_put(struct snd_kcontrol *kcontrol, | ||
478 | struct snd_ctl_elem_value *ucontrol) | ||
479 | { | ||
480 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
481 | int change; | ||
482 | |||
483 | change = put_ak_ipga(kcontrol, addr, ucontrol->value.integer.value[0]); | ||
484 | change |= put_ak_ipga(kcontrol, addr + 1, | ||
485 | ucontrol->value.integer.value[1]); | ||
447 | return change; | 486 | return change; |
448 | } | 487 | } |
449 | 488 | ||
@@ -548,221 +587,247 @@ static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol, | |||
548 | * build AK4xxx controls | 587 | * build AK4xxx controls |
549 | */ | 588 | */ |
550 | 589 | ||
551 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) | 590 | static int build_dac_controls(struct snd_akm4xxx *ak) |
552 | { | 591 | { |
553 | unsigned int idx, num_emphs; | 592 | int idx, err, mixer_ch, num_stereo; |
554 | struct snd_kcontrol *ctl; | 593 | struct snd_kcontrol_new knew; |
555 | int err; | ||
556 | int mixer_ch = 0; | ||
557 | int num_stereo; | ||
558 | |||
559 | ctl = kmalloc(sizeof(*ctl), GFP_KERNEL); | ||
560 | if (! ctl) | ||
561 | return -ENOMEM; | ||
562 | 594 | ||
595 | mixer_ch = 0; | ||
563 | for (idx = 0; idx < ak->num_dacs; ) { | 596 | for (idx = 0; idx < ak->num_dacs; ) { |
564 | memset(ctl, 0, sizeof(*ctl)); | 597 | memset(&knew, 0, sizeof(knew)); |
565 | if (ak->channel_names == NULL) { | 598 | if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) { |
566 | strcpy(ctl->id.name, "DAC Volume"); | 599 | knew.name = "DAC Volume"; |
600 | knew.index = mixer_ch + ak->idx_offset * 2; | ||
567 | num_stereo = 1; | 601 | num_stereo = 1; |
568 | ctl->id.index = mixer_ch + ak->idx_offset * 2; | ||
569 | } else { | 602 | } else { |
570 | strcpy(ctl->id.name, ak->channel_names[mixer_ch]); | 603 | knew.name = ak->dac_info[mixer_ch].name; |
571 | num_stereo = ak->num_stereo[mixer_ch]; | 604 | num_stereo = ak->dac_info[mixer_ch].num_channels; |
572 | ctl->id.index = 0; | ||
573 | } | 605 | } |
574 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 606 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
575 | ctl->count = 1; | 607 | knew.count = 1; |
608 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
609 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
576 | if (num_stereo == 2) { | 610 | if (num_stereo == 2) { |
577 | ctl->info = snd_akm4xxx_stereo_volume_info; | 611 | knew.info = snd_akm4xxx_stereo_volume_info; |
578 | ctl->get = snd_akm4xxx_stereo_volume_get; | 612 | knew.get = snd_akm4xxx_stereo_volume_get; |
579 | ctl->put = snd_akm4xxx_stereo_volume_put; | 613 | knew.put = snd_akm4xxx_stereo_volume_put; |
580 | } else { | 614 | } else { |
581 | ctl->info = snd_akm4xxx_volume_info; | 615 | knew.info = snd_akm4xxx_volume_info; |
582 | ctl->get = snd_akm4xxx_volume_get; | 616 | knew.get = snd_akm4xxx_volume_get; |
583 | ctl->put = snd_akm4xxx_volume_put; | 617 | knew.put = snd_akm4xxx_volume_put; |
584 | } | 618 | } |
585 | switch (ak->type) { | 619 | switch (ak->type) { |
586 | case SND_AK4524: | 620 | case SND_AK4524: |
587 | /* register 6 & 7 */ | 621 | /* register 6 & 7 */ |
588 | ctl->private_value = | 622 | knew.private_value = |
589 | AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); | 623 | AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127) | |
624 | AK_VOL_CVT; | ||
625 | knew.tlv.p = db_scale_vol_datt; | ||
590 | break; | 626 | break; |
591 | case SND_AK4528: | 627 | case SND_AK4528: |
592 | /* register 4 & 5 */ | 628 | /* register 4 & 5 */ |
593 | ctl->private_value = | 629 | knew.private_value = |
594 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); | 630 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | |
631 | AK_VOL_CVT; | ||
632 | knew.tlv.p = db_scale_vol_datt; | ||
595 | break; | 633 | break; |
596 | case SND_AK4529: { | 634 | case SND_AK4529: { |
597 | /* registers 2-7 and b,c */ | 635 | /* registers 2-7 and b,c */ |
598 | int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; | 636 | int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; |
599 | ctl->private_value = | 637 | knew.private_value = |
600 | AK_COMPOSE(0, val, 0, 255) | AK_INVERT; | 638 | AK_COMPOSE(0, val, 0, 255) | AK_INVERT; |
639 | knew.tlv.p = db_scale_8bit; | ||
601 | break; | 640 | break; |
602 | } | 641 | } |
603 | case SND_AK4355: | 642 | case SND_AK4355: |
604 | /* register 4-9, chip #0 only */ | 643 | /* register 4-9, chip #0 only */ |
605 | ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); | 644 | knew.private_value = AK_COMPOSE(0, idx + 4, 0, 255); |
645 | knew.tlv.p = db_scale_8bit; | ||
606 | break; | 646 | break; |
607 | case SND_AK4358: { | 647 | case SND_AK4358: { |
608 | /* register 4-9 and 11-12, chip #0 only */ | 648 | /* register 4-9 and 11-12, chip #0 only */ |
609 | int addr = idx < 6 ? idx + 4 : idx + 5; | 649 | int addr = idx < 6 ? idx + 4 : idx + 5; |
610 | ctl->private_value = | 650 | knew.private_value = |
611 | AK_COMPOSE(0, addr, 0, 127) | AK_NEEDSMSB; | 651 | AK_COMPOSE(0, addr, 0, 127) | AK_NEEDSMSB; |
652 | knew.tlv.p = db_scale_7bit; | ||
612 | break; | 653 | break; |
613 | } | 654 | } |
614 | case SND_AK4381: | 655 | case SND_AK4381: |
615 | /* register 3 & 4 */ | 656 | /* register 3 & 4 */ |
616 | ctl->private_value = | 657 | knew.private_value = |
617 | AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); | 658 | AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); |
659 | knew.tlv.p = db_scale_linear; | ||
618 | break; | 660 | break; |
619 | default: | 661 | default: |
620 | err = -EINVAL; | 662 | return -EINVAL; |
621 | goto __error; | ||
622 | } | 663 | } |
623 | 664 | ||
624 | ctl->private_data = ak; | 665 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); |
625 | err = snd_ctl_add(ak->card, | ||
626 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | ||
627 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | ||
628 | if (err < 0) | 666 | if (err < 0) |
629 | goto __error; | 667 | return err; |
630 | 668 | ||
631 | idx += num_stereo; | 669 | idx += num_stereo; |
632 | mixer_ch++; | 670 | mixer_ch++; |
633 | } | 671 | } |
634 | for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) { | 672 | return 0; |
635 | memset(ctl, 0, sizeof(*ctl)); | 673 | } |
636 | strcpy(ctl->id.name, "ADC Volume"); | 674 | |
637 | ctl->id.index = idx + ak->idx_offset * 2; | 675 | static int build_adc_controls(struct snd_akm4xxx *ak) |
638 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 676 | { |
639 | ctl->count = 1; | 677 | int idx, err, mixer_ch, num_stereo; |
640 | ctl->info = snd_akm4xxx_volume_info; | 678 | struct snd_kcontrol_new knew; |
641 | ctl->get = snd_akm4xxx_volume_get; | 679 | |
642 | ctl->put = snd_akm4xxx_volume_put; | 680 | mixer_ch = 0; |
643 | /* register 4 & 5 */ | 681 | for (idx = 0; idx < ak->num_adcs;) { |
644 | ctl->private_value = | 682 | memset(&knew, 0, sizeof(knew)); |
645 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); | 683 | if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { |
646 | ctl->private_data = ak; | 684 | knew.name = "ADC Volume"; |
647 | err = snd_ctl_add(ak->card, | 685 | knew.index = mixer_ch + ak->idx_offset * 2; |
648 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | 686 | num_stereo = 1; |
649 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | 687 | } else { |
650 | if (err < 0) | 688 | knew.name = ak->adc_info[mixer_ch].name; |
651 | goto __error; | 689 | num_stereo = ak->adc_info[mixer_ch].num_channels; |
652 | 690 | } | |
653 | memset(ctl, 0, sizeof(*ctl)); | 691 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
654 | strcpy(ctl->id.name, "IPGA Analog Capture Volume"); | 692 | knew.count = 1; |
655 | ctl->id.index = idx + ak->idx_offset * 2; | 693 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
656 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 694 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
657 | ctl->count = 1; | 695 | if (num_stereo == 2) { |
658 | ctl->info = snd_akm4xxx_ipga_gain_info; | 696 | knew.info = snd_akm4xxx_stereo_volume_info; |
659 | ctl->get = snd_akm4xxx_ipga_gain_get; | 697 | knew.get = snd_akm4xxx_stereo_volume_get; |
660 | ctl->put = snd_akm4xxx_ipga_gain_put; | 698 | knew.put = snd_akm4xxx_stereo_volume_put; |
699 | } else { | ||
700 | knew.info = snd_akm4xxx_volume_info; | ||
701 | knew.get = snd_akm4xxx_volume_get; | ||
702 | knew.put = snd_akm4xxx_volume_put; | ||
703 | } | ||
661 | /* register 4 & 5 */ | 704 | /* register 4 & 5 */ |
662 | ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); | 705 | knew.private_value = |
663 | ctl->private_data = ak; | 706 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | |
664 | err = snd_ctl_add(ak->card, | 707 | AK_VOL_CVT; |
665 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | 708 | knew.tlv.p = db_scale_vol_datt; |
666 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | 709 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); |
667 | if (err < 0) | 710 | if (err < 0) |
668 | goto __error; | 711 | return err; |
669 | } | ||
670 | 712 | ||
671 | if (ak->type == SND_AK5365) { | 713 | if (! ak->adc_info || ! ak->adc_info[mixer_ch].gain_name) |
672 | memset(ctl, 0, sizeof(*ctl)); | 714 | knew.name = "IPGA Analog Capture Volume"; |
673 | if (ak->channel_names == NULL) | ||
674 | strcpy(ctl->id.name, "Capture Volume"); | ||
675 | else | 715 | else |
676 | strcpy(ctl->id.name, ak->channel_names[0]); | 716 | knew.name = ak->adc_info[mixer_ch].gain_name; |
677 | ctl->id.index = ak->idx_offset * 2; | 717 | if (num_stereo == 2) { |
678 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 718 | knew.info = snd_akm4xxx_stereo_gain_info; |
679 | ctl->count = 1; | 719 | knew.get = snd_akm4xxx_stereo_gain_get; |
680 | ctl->info = snd_akm4xxx_stereo_volume_info; | 720 | knew.put = snd_akm4xxx_stereo_gain_put; |
681 | ctl->get = snd_akm4xxx_stereo_volume_get; | 721 | } else { |
682 | ctl->put = snd_akm4xxx_stereo_volume_put; | 722 | knew.info = snd_akm4xxx_ipga_gain_info; |
683 | /* Registers 4 & 5 (see AK5365 data sheet, pages 34 and 35): | 723 | knew.get = snd_akm4xxx_ipga_gain_get; |
684 | * valid values are from 0x00 (mute) to 0x98 (+12dB). */ | 724 | knew.put = snd_akm4xxx_ipga_gain_put; |
685 | ctl->private_value = | 725 | } |
686 | AK_COMPOSE(0, 4, 0, 0x98); | 726 | /* register 4 & 5 */ |
687 | ctl->private_data = ak; | 727 | if (ak->type == SND_AK4524) |
688 | err = snd_ctl_add(ak->card, | 728 | knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, |
689 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | 729 | 24); |
690 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | 730 | else /* AK5365 */ |
731 | knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, | ||
732 | 36); | ||
733 | knew.tlv.p = db_scale_ipga; | ||
734 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | ||
691 | if (err < 0) | 735 | if (err < 0) |
692 | goto __error; | 736 | return err; |
737 | |||
738 | if (ak->type == SND_AK5365 && (idx % 2) == 0) { | ||
739 | if (! ak->adc_info || | ||
740 | ! ak->adc_info[mixer_ch].switch_name) | ||
741 | knew.name = "Capture Switch"; | ||
742 | else | ||
743 | knew.name = ak->adc_info[mixer_ch].switch_name; | ||
744 | knew.info = ak4xxx_switch_info; | ||
745 | knew.get = ak4xxx_switch_get; | ||
746 | knew.put = ak4xxx_switch_put; | ||
747 | knew.access = 0; | ||
748 | /* register 2, bit 0 (SMUTE): 0 = normal operation, | ||
749 | 1 = mute */ | ||
750 | knew.private_value = | ||
751 | AK_COMPOSE(idx/2, 2, 0, 0) | AK_INVERT; | ||
752 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | ||
753 | if (err < 0) | ||
754 | return err; | ||
755 | } | ||
693 | 756 | ||
694 | memset(ctl, 0, sizeof(*ctl)); | 757 | idx += num_stereo; |
695 | if (ak->channel_names == NULL) | 758 | mixer_ch++; |
696 | strcpy(ctl->id.name, "Capture Switch"); | ||
697 | else | ||
698 | strcpy(ctl->id.name, ak->channel_names[1]); | ||
699 | ctl->id.index = ak->idx_offset * 2; | ||
700 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
701 | ctl->count = 1; | ||
702 | ctl->info = ak4xxx_switch_info; | ||
703 | ctl->get = ak4xxx_switch_get; | ||
704 | ctl->put = ak4xxx_switch_put; | ||
705 | /* register 2, bit 0 (SMUTE): 0 = normal operation, 1 = mute */ | ||
706 | ctl->private_value = | ||
707 | AK_COMPOSE(0, 2, 0, 0) | AK_INVERT; | ||
708 | ctl->private_data = ak; | ||
709 | err = snd_ctl_add(ak->card, | ||
710 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | ||
711 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | ||
712 | if (err < 0) | ||
713 | goto __error; | ||
714 | } | 759 | } |
760 | return 0; | ||
761 | } | ||
762 | |||
763 | static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) | ||
764 | { | ||
765 | int idx, err; | ||
766 | struct snd_kcontrol_new knew; | ||
715 | 767 | ||
716 | if (ak->type == SND_AK4355 || ak->type == SND_AK4358) | ||
717 | num_emphs = 1; | ||
718 | else | ||
719 | num_emphs = ak->num_dacs / 2; | ||
720 | for (idx = 0; idx < num_emphs; idx++) { | 768 | for (idx = 0; idx < num_emphs; idx++) { |
721 | memset(ctl, 0, sizeof(*ctl)); | 769 | memset(&knew, 0, sizeof(knew)); |
722 | strcpy(ctl->id.name, "Deemphasis"); | 770 | knew.name = "Deemphasis"; |
723 | ctl->id.index = idx + ak->idx_offset; | 771 | knew.index = idx + ak->idx_offset; |
724 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 772 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
725 | ctl->count = 1; | 773 | knew.count = 1; |
726 | ctl->info = snd_akm4xxx_deemphasis_info; | 774 | knew.info = snd_akm4xxx_deemphasis_info; |
727 | ctl->get = snd_akm4xxx_deemphasis_get; | 775 | knew.get = snd_akm4xxx_deemphasis_get; |
728 | ctl->put = snd_akm4xxx_deemphasis_put; | 776 | knew.put = snd_akm4xxx_deemphasis_put; |
729 | switch (ak->type) { | 777 | switch (ak->type) { |
730 | case SND_AK4524: | 778 | case SND_AK4524: |
731 | case SND_AK4528: | 779 | case SND_AK4528: |
732 | /* register 3 */ | 780 | /* register 3 */ |
733 | ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); | 781 | knew.private_value = AK_COMPOSE(idx, 3, 0, 0); |
734 | break; | 782 | break; |
735 | case SND_AK4529: { | 783 | case SND_AK4529: { |
736 | int shift = idx == 3 ? 6 : (2 - idx) * 2; | 784 | int shift = idx == 3 ? 6 : (2 - idx) * 2; |
737 | /* register 8 with shift */ | 785 | /* register 8 with shift */ |
738 | ctl->private_value = AK_COMPOSE(0, 8, shift, 0); | 786 | knew.private_value = AK_COMPOSE(0, 8, shift, 0); |
739 | break; | 787 | break; |
740 | } | 788 | } |
741 | case SND_AK4355: | 789 | case SND_AK4355: |
742 | case SND_AK4358: | 790 | case SND_AK4358: |
743 | ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); | 791 | knew.private_value = AK_COMPOSE(idx, 3, 0, 0); |
744 | break; | 792 | break; |
745 | case SND_AK4381: | 793 | case SND_AK4381: |
746 | ctl->private_value = AK_COMPOSE(idx, 1, 1, 0); | 794 | knew.private_value = AK_COMPOSE(idx, 1, 1, 0); |
747 | break; | 795 | break; |
748 | default: | 796 | default: |
749 | err = -EINVAL; | 797 | return -EINVAL; |
750 | goto __error; | ||
751 | } | 798 | } |
752 | ctl->private_data = ak; | 799 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); |
753 | err = snd_ctl_add(ak->card, | ||
754 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | ||
755 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | ||
756 | if (err < 0) | 800 | if (err < 0) |
757 | goto __error; | 801 | return err; |
758 | } | 802 | } |
759 | err = 0; | 803 | return 0; |
760 | |||
761 | __error: | ||
762 | kfree(ctl); | ||
763 | return err; | ||
764 | } | 804 | } |
765 | 805 | ||
806 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) | ||
807 | { | ||
808 | int err, num_emphs; | ||
809 | |||
810 | err = build_dac_controls(ak); | ||
811 | if (err < 0) | ||
812 | return err; | ||
813 | |||
814 | if (ak->type == SND_AK4524 || ak->type == SND_AK5365) { | ||
815 | err = build_adc_controls(ak); | ||
816 | if (err < 0) | ||
817 | return err; | ||
818 | } | ||
819 | |||
820 | if (ak->type == SND_AK4355 || ak->type == SND_AK4358) | ||
821 | num_emphs = 1; | ||
822 | else | ||
823 | num_emphs = ak->num_dacs / 2; | ||
824 | err = build_deemphasis(ak, num_emphs); | ||
825 | if (err < 0) | ||
826 | return err; | ||
827 | |||
828 | return 0; | ||
829 | } | ||
830 | |||
766 | EXPORT_SYMBOL(snd_akm4xxx_build_controls); | 831 | EXPORT_SYMBOL(snd_akm4xxx_build_controls); |
767 | 832 | ||
768 | static int __init alsa_akm4xxx_module_init(void) | 833 | static int __init alsa_akm4xxx_module_init(void) |