diff options
Diffstat (limited to 'sound/i2c/other/ak4xxx-adda.c')
-rw-r--r-- | sound/i2c/other/ak4xxx-adda.c | 501 |
1 files changed, 296 insertions, 205 deletions
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index dc7cc2001b74..5da49e2eb350 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,7 @@ 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 | snd_akm4xxx_set(ak, chip, reg, val); |
45 | if ((reg != 0x04 && reg != 0x05) || (val & 0x80) == 0) | ||
46 | snd_akm4xxx_set(ak, chip, reg, val); | ||
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); | ||
52 | } | ||
53 | ak->ops.unlock(ak, chip); | 47 | ak->ops.unlock(ak, chip); |
54 | } | 48 | } |
55 | 49 | ||
@@ -73,12 +67,6 @@ static void ak4524_reset(struct snd_akm4xxx *ak, int state) | |||
73 | for (reg = 0x04; reg < maxreg; reg++) | 67 | for (reg = 0x04; reg < maxreg; reg++) |
74 | snd_akm4xxx_write(ak, chip, reg, | 68 | snd_akm4xxx_write(ak, chip, reg, |
75 | snd_akm4xxx_get(ak, chip, reg)); | 69 | snd_akm4xxx_get(ak, chip, reg)); |
76 | if (ak->type == SND_AK4528) | ||
77 | continue; | ||
78 | /* IPGA */ | ||
79 | for (reg = 0x04; reg < 0x06; reg++) | ||
80 | snd_akm4xxx_write(ak, chip, reg, | ||
81 | snd_akm4xxx_get_ipga(ak, chip, reg)); | ||
82 | } | 70 | } |
83 | } | 71 | } |
84 | 72 | ||
@@ -137,11 +125,48 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state) | |||
137 | case SND_AK4381: | 125 | case SND_AK4381: |
138 | ak4381_reset(ak, state); | 126 | ak4381_reset(ak, state); |
139 | break; | 127 | break; |
128 | default: | ||
129 | break; | ||
140 | } | 130 | } |
141 | } | 131 | } |
142 | 132 | ||
143 | EXPORT_SYMBOL(snd_akm4xxx_reset); | 133 | EXPORT_SYMBOL(snd_akm4xxx_reset); |
144 | 134 | ||
135 | |||
136 | /* | ||
137 | * Volume conversion table for non-linear volumes | ||
138 | * from -63.5dB (mute) to 0dB step 0.5dB | ||
139 | * | ||
140 | * Used for AK4524 input/ouput attenuation, AK4528, and | ||
141 | * AK5365 input attenuation | ||
142 | */ | ||
143 | static unsigned char vol_cvt_datt[128] = { | ||
144 | 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, | ||
145 | 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, | ||
146 | 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a, | ||
147 | 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, | ||
148 | 0x10, 0x10, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14, | ||
149 | 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1c, | ||
150 | 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x23, | ||
151 | 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2d, | ||
152 | 0x2e, 0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, | ||
153 | 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x3f, 0x40, | ||
154 | 0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4a, | ||
155 | 0x4b, 0x4d, 0x4e, 0x50, 0x51, 0x52, 0x53, 0x54, | ||
156 | 0x55, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x5f, | ||
157 | 0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x69, | ||
158 | 0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x72, 0x73, | ||
159 | 0x75, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f, | ||
160 | }; | ||
161 | |||
162 | /* | ||
163 | * dB tables | ||
164 | */ | ||
165 | static DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1); | ||
166 | static DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1); | ||
167 | static DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1); | ||
168 | static DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0); | ||
169 | |||
145 | /* | 170 | /* |
146 | * initialize all the ak4xxx chips | 171 | * initialize all the ak4xxx chips |
147 | */ | 172 | */ |
@@ -155,8 +180,6 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
155 | 0x01, 0x03, /* 1: ADC/DAC enable */ | 180 | 0x01, 0x03, /* 1: ADC/DAC enable */ |
156 | 0x04, 0x00, /* 4: ADC left muted */ | 181 | 0x04, 0x00, /* 4: ADC left muted */ |
157 | 0x05, 0x00, /* 5: ADC right muted */ | 182 | 0x05, 0x00, /* 5: ADC right muted */ |
158 | 0x04, 0x80, /* 4: ADC IPGA gain 0dB */ | ||
159 | 0x05, 0x80, /* 5: ADC IPGA gain 0dB */ | ||
160 | 0x06, 0x00, /* 6: DAC left muted */ | 183 | 0x06, 0x00, /* 6: DAC left muted */ |
161 | 0x07, 0x00, /* 7: DAC right muted */ | 184 | 0x07, 0x00, /* 7: DAC right muted */ |
162 | 0xff, 0xff | 185 | 0xff, 0xff |
@@ -238,6 +261,9 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
238 | int chip, num_chips; | 261 | int chip, num_chips; |
239 | unsigned char *ptr, reg, data, *inits; | 262 | unsigned char *ptr, reg, data, *inits; |
240 | 263 | ||
264 | memset(ak->images, 0, sizeof(ak->images)); | ||
265 | memset(ak->volumes, 0, sizeof(ak->volumes)); | ||
266 | |||
241 | switch (ak->type) { | 267 | switch (ak->type) { |
242 | case SND_AK4524: | 268 | case SND_AK4524: |
243 | inits = inits_ak4524; | 269 | inits = inits_ak4524; |
@@ -263,6 +289,9 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
263 | inits = inits_ak4381; | 289 | inits = inits_ak4381; |
264 | num_chips = ak->num_dacs / 2; | 290 | num_chips = ak->num_dacs / 2; |
265 | break; | 291 | break; |
292 | case SND_AK5365: | ||
293 | /* FIXME: any init sequence? */ | ||
294 | return; | ||
266 | default: | 295 | default: |
267 | snd_BUG(); | 296 | snd_BUG(); |
268 | return; | 297 | return; |
@@ -280,14 +309,23 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
280 | 309 | ||
281 | EXPORT_SYMBOL(snd_akm4xxx_init); | 310 | EXPORT_SYMBOL(snd_akm4xxx_init); |
282 | 311 | ||
312 | /* | ||
313 | * Mixer callbacks | ||
314 | */ | ||
315 | #define AK_IPGA (1<<20) /* including IPGA */ | ||
316 | #define AK_VOL_CVT (1<<21) /* need dB conversion */ | ||
317 | #define AK_NEEDSMSB (1<<22) /* need MSB update bit */ | ||
318 | #define AK_INVERT (1<<23) /* data is inverted */ | ||
283 | #define AK_GET_CHIP(val) (((val) >> 8) & 0xff) | 319 | #define AK_GET_CHIP(val) (((val) >> 8) & 0xff) |
284 | #define AK_GET_ADDR(val) ((val) & 0xff) | 320 | #define AK_GET_ADDR(val) ((val) & 0xff) |
285 | #define AK_GET_SHIFT(val) (((val) >> 16) & 0x7f) | 321 | #define AK_GET_SHIFT(val) (((val) >> 16) & 0x0f) |
322 | #define AK_GET_VOL_CVT(val) (((val) >> 21) & 1) | ||
323 | #define AK_GET_IPGA(val) (((val) >> 20) & 1) | ||
324 | #define AK_GET_NEEDSMSB(val) (((val) >> 22) & 1) | ||
286 | #define AK_GET_INVERT(val) (((val) >> 23) & 1) | 325 | #define AK_GET_INVERT(val) (((val) >> 23) & 1) |
287 | #define AK_GET_MASK(val) (((val) >> 24) & 0xff) | 326 | #define AK_GET_MASK(val) (((val) >> 24) & 0xff) |
288 | #define AK_COMPOSE(chip,addr,shift,mask) \ | 327 | #define AK_COMPOSE(chip,addr,shift,mask) \ |
289 | (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) | 328 | (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) |
290 | #define AK_INVERT (1<<23) | ||
291 | 329 | ||
292 | static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol, | 330 | static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol, |
293 | struct snd_ctl_elem_info *uinfo) | 331 | struct snd_ctl_elem_info *uinfo) |
@@ -307,31 +345,39 @@ static int snd_akm4xxx_volume_get(struct snd_kcontrol *kcontrol, | |||
307 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | 345 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); |
308 | int chip = AK_GET_CHIP(kcontrol->private_value); | 346 | int chip = AK_GET_CHIP(kcontrol->private_value); |
309 | int addr = AK_GET_ADDR(kcontrol->private_value); | 347 | int addr = AK_GET_ADDR(kcontrol->private_value); |
310 | int invert = AK_GET_INVERT(kcontrol->private_value); | 348 | |
311 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); | 349 | ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); |
312 | unsigned char val = snd_akm4xxx_get(ak, chip, addr); | ||
313 | |||
314 | ucontrol->value.integer.value[0] = invert ? mask - val : val; | ||
315 | return 0; | 350 | return 0; |
316 | } | 351 | } |
317 | 352 | ||
318 | static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, | 353 | static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr, |
319 | struct snd_ctl_elem_value *ucontrol) | 354 | unsigned char nval) |
320 | { | 355 | { |
321 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | 356 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); |
322 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
323 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
324 | int invert = AK_GET_INVERT(kcontrol->private_value); | ||
325 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); | 357 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); |
326 | unsigned char nval = ucontrol->value.integer.value[0] % (mask+1); | 358 | int chip = AK_GET_CHIP(kcontrol->private_value); |
327 | int change; | ||
328 | 359 | ||
329 | if (invert) | 360 | if (snd_akm4xxx_get_vol(ak, chip, addr) == nval) |
361 | return 0; | ||
362 | |||
363 | snd_akm4xxx_set_vol(ak, chip, addr, nval); | ||
364 | if (AK_GET_VOL_CVT(kcontrol->private_value) && nval < 128) | ||
365 | nval = vol_cvt_datt[nval]; | ||
366 | if (AK_GET_IPGA(kcontrol->private_value) && nval >= 128) | ||
367 | nval++; /* need to correct + 1 since both 127 and 128 are 0dB */ | ||
368 | if (AK_GET_INVERT(kcontrol->private_value)) | ||
330 | nval = mask - nval; | 369 | nval = mask - nval; |
331 | change = snd_akm4xxx_get(ak, chip, addr) != nval; | 370 | if (AK_GET_NEEDSMSB(kcontrol->private_value)) |
332 | if (change) | 371 | nval |= 0x80; |
333 | snd_akm4xxx_write(ak, chip, addr, nval); | 372 | snd_akm4xxx_write(ak, chip, addr, nval); |
334 | return change; | 373 | return 1; |
374 | } | ||
375 | |||
376 | static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, | ||
377 | struct snd_ctl_elem_value *ucontrol) | ||
378 | { | ||
379 | return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), | ||
380 | ucontrol->value.integer.value[0]); | ||
335 | } | 381 | } |
336 | 382 | ||
337 | static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, | 383 | static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, |
@@ -352,77 +398,21 @@ static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol, | |||
352 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | 398 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); |
353 | int chip = AK_GET_CHIP(kcontrol->private_value); | 399 | int chip = AK_GET_CHIP(kcontrol->private_value); |
354 | int addr = AK_GET_ADDR(kcontrol->private_value); | 400 | int addr = AK_GET_ADDR(kcontrol->private_value); |
355 | int invert = AK_GET_INVERT(kcontrol->private_value); | ||
356 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); | ||
357 | unsigned char val = snd_akm4xxx_get(ak, chip, addr); | ||
358 | |||
359 | ucontrol->value.integer.value[0] = invert ? mask - val : val; | ||
360 | |||
361 | val = snd_akm4xxx_get(ak, chip, addr+1); | ||
362 | ucontrol->value.integer.value[1] = invert ? mask - val : val; | ||
363 | 401 | ||
402 | ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); | ||
403 | ucontrol->value.integer.value[1] = snd_akm4xxx_get_vol(ak, chip, addr+1); | ||
364 | return 0; | 404 | return 0; |
365 | } | 405 | } |
366 | 406 | ||
367 | static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, | 407 | static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, |
368 | struct snd_ctl_elem_value *ucontrol) | 408 | struct snd_ctl_elem_value *ucontrol) |
369 | { | 409 | { |
370 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
371 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
372 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
373 | int invert = AK_GET_INVERT(kcontrol->private_value); | ||
374 | unsigned int mask = AK_GET_MASK(kcontrol->private_value); | ||
375 | unsigned char nval = ucontrol->value.integer.value[0] % (mask+1); | ||
376 | int change0, change1; | ||
377 | |||
378 | if (invert) | ||
379 | nval = mask - nval; | ||
380 | change0 = snd_akm4xxx_get(ak, chip, addr) != nval; | ||
381 | if (change0) | ||
382 | snd_akm4xxx_write(ak, chip, addr, nval); | ||
383 | |||
384 | nval = ucontrol->value.integer.value[1] % (mask+1); | ||
385 | if (invert) | ||
386 | nval = mask - nval; | ||
387 | change1 = snd_akm4xxx_get(ak, chip, addr+1) != nval; | ||
388 | if (change1) | ||
389 | snd_akm4xxx_write(ak, chip, addr+1, nval); | ||
390 | |||
391 | |||
392 | return change0 || change1; | ||
393 | } | ||
394 | |||
395 | static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol, | ||
396 | struct snd_ctl_elem_info *uinfo) | ||
397 | { | ||
398 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
399 | uinfo->count = 1; | ||
400 | uinfo->value.integer.min = 0; | ||
401 | uinfo->value.integer.max = 36; | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol, | ||
406 | struct snd_ctl_elem_value *ucontrol) | ||
407 | { | ||
408 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
409 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
410 | int addr = AK_GET_ADDR(kcontrol->private_value); | 410 | int addr = AK_GET_ADDR(kcontrol->private_value); |
411 | ucontrol->value.integer.value[0] = | 411 | int change; |
412 | snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f; | ||
413 | return 0; | ||
414 | } | ||
415 | 412 | ||
416 | static int snd_akm4xxx_ipga_gain_put(struct snd_kcontrol *kcontrol, | 413 | change = put_ak_reg(kcontrol, addr, ucontrol->value.integer.value[0]); |
417 | struct snd_ctl_elem_value *ucontrol) | 414 | change |= put_ak_reg(kcontrol, addr + 1, |
418 | { | 415 | ucontrol->value.integer.value[1]); |
419 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
420 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
421 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
422 | unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80; | ||
423 | int change = snd_akm4xxx_get_ipga(ak, chip, addr) != nval; | ||
424 | if (change) | ||
425 | snd_akm4xxx_write(ak, chip, addr, nval); | ||
426 | return change; | 416 | return change; |
427 | } | 417 | } |
428 | 418 | ||
@@ -472,179 +462,280 @@ static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol, | |||
472 | return change; | 462 | return change; |
473 | } | 463 | } |
474 | 464 | ||
465 | static int ak4xxx_switch_info(struct snd_kcontrol *kcontrol, | ||
466 | struct snd_ctl_elem_info *uinfo) | ||
467 | { | ||
468 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
469 | uinfo->count = 1; | ||
470 | uinfo->value.integer.min = 0; | ||
471 | uinfo->value.integer.max = 1; | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol, | ||
476 | struct snd_ctl_elem_value *ucontrol) | ||
477 | { | ||
478 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
479 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
480 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
481 | int shift = AK_GET_SHIFT(kcontrol->private_value); | ||
482 | int invert = AK_GET_INVERT(kcontrol->private_value); | ||
483 | unsigned char val = snd_akm4xxx_get(ak, chip, addr); | ||
484 | |||
485 | if (invert) | ||
486 | val = ! val; | ||
487 | ucontrol->value.integer.value[0] = (val & (1<<shift)) != 0; | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol, | ||
492 | struct snd_ctl_elem_value *ucontrol) | ||
493 | { | ||
494 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
495 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
496 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
497 | int shift = AK_GET_SHIFT(kcontrol->private_value); | ||
498 | int invert = AK_GET_INVERT(kcontrol->private_value); | ||
499 | long flag = ucontrol->value.integer.value[0]; | ||
500 | unsigned char val, oval; | ||
501 | int change; | ||
502 | |||
503 | if (invert) | ||
504 | flag = ! flag; | ||
505 | oval = snd_akm4xxx_get(ak, chip, addr); | ||
506 | if (flag) | ||
507 | val = oval | (1<<shift); | ||
508 | else | ||
509 | val = oval & ~(1<<shift); | ||
510 | change = (oval != val); | ||
511 | if (change) | ||
512 | snd_akm4xxx_write(ak, chip, addr, val); | ||
513 | return change; | ||
514 | } | ||
515 | |||
475 | /* | 516 | /* |
476 | * build AK4xxx controls | 517 | * build AK4xxx controls |
477 | */ | 518 | */ |
478 | 519 | ||
479 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) | 520 | static int build_dac_controls(struct snd_akm4xxx *ak) |
480 | { | 521 | { |
481 | unsigned int idx, num_emphs; | 522 | int idx, err, mixer_ch, num_stereo; |
482 | struct snd_kcontrol *ctl; | 523 | struct snd_kcontrol_new knew; |
483 | int err; | ||
484 | int mixer_ch = 0; | ||
485 | int num_stereo; | ||
486 | |||
487 | ctl = kmalloc(sizeof(*ctl), GFP_KERNEL); | ||
488 | if (! ctl) | ||
489 | return -ENOMEM; | ||
490 | 524 | ||
525 | mixer_ch = 0; | ||
491 | for (idx = 0; idx < ak->num_dacs; ) { | 526 | for (idx = 0; idx < ak->num_dacs; ) { |
492 | memset(ctl, 0, sizeof(*ctl)); | 527 | memset(&knew, 0, sizeof(knew)); |
493 | if (ak->channel_names == NULL) { | 528 | if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) { |
494 | strcpy(ctl->id.name, "DAC Volume"); | 529 | knew.name = "DAC Volume"; |
530 | knew.index = mixer_ch + ak->idx_offset * 2; | ||
495 | num_stereo = 1; | 531 | num_stereo = 1; |
496 | ctl->id.index = mixer_ch + ak->idx_offset * 2; | ||
497 | } else { | 532 | } else { |
498 | strcpy(ctl->id.name, ak->channel_names[mixer_ch]); | 533 | knew.name = ak->dac_info[mixer_ch].name; |
499 | num_stereo = ak->num_stereo[mixer_ch]; | 534 | num_stereo = ak->dac_info[mixer_ch].num_channels; |
500 | ctl->id.index = 0; | ||
501 | } | 535 | } |
502 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 536 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
503 | ctl->count = 1; | 537 | knew.count = 1; |
538 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
539 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
504 | if (num_stereo == 2) { | 540 | if (num_stereo == 2) { |
505 | ctl->info = snd_akm4xxx_stereo_volume_info; | 541 | knew.info = snd_akm4xxx_stereo_volume_info; |
506 | ctl->get = snd_akm4xxx_stereo_volume_get; | 542 | knew.get = snd_akm4xxx_stereo_volume_get; |
507 | ctl->put = snd_akm4xxx_stereo_volume_put; | 543 | knew.put = snd_akm4xxx_stereo_volume_put; |
508 | } else { | 544 | } else { |
509 | ctl->info = snd_akm4xxx_volume_info; | 545 | knew.info = snd_akm4xxx_volume_info; |
510 | ctl->get = snd_akm4xxx_volume_get; | 546 | knew.get = snd_akm4xxx_volume_get; |
511 | ctl->put = snd_akm4xxx_volume_put; | 547 | knew.put = snd_akm4xxx_volume_put; |
512 | } | 548 | } |
513 | switch (ak->type) { | 549 | switch (ak->type) { |
514 | case SND_AK4524: | 550 | case SND_AK4524: |
515 | /* register 6 & 7 */ | 551 | /* register 6 & 7 */ |
516 | ctl->private_value = | 552 | knew.private_value = |
517 | AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); | 553 | AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127) | |
554 | AK_VOL_CVT; | ||
555 | knew.tlv.p = db_scale_vol_datt; | ||
518 | break; | 556 | break; |
519 | case SND_AK4528: | 557 | case SND_AK4528: |
520 | /* register 4 & 5 */ | 558 | /* register 4 & 5 */ |
521 | ctl->private_value = | 559 | knew.private_value = |
522 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); | 560 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | |
561 | AK_VOL_CVT; | ||
562 | knew.tlv.p = db_scale_vol_datt; | ||
523 | break; | 563 | break; |
524 | case SND_AK4529: { | 564 | case SND_AK4529: { |
525 | /* registers 2-7 and b,c */ | 565 | /* registers 2-7 and b,c */ |
526 | int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; | 566 | int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; |
527 | ctl->private_value = | 567 | knew.private_value = |
528 | AK_COMPOSE(0, val, 0, 255) | AK_INVERT; | 568 | AK_COMPOSE(0, val, 0, 255) | AK_INVERT; |
569 | knew.tlv.p = db_scale_8bit; | ||
529 | break; | 570 | break; |
530 | } | 571 | } |
531 | case SND_AK4355: | 572 | case SND_AK4355: |
532 | /* register 4-9, chip #0 only */ | 573 | /* register 4-9, chip #0 only */ |
533 | ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); | 574 | knew.private_value = AK_COMPOSE(0, idx + 4, 0, 255); |
575 | knew.tlv.p = db_scale_8bit; | ||
534 | break; | 576 | break; |
535 | case SND_AK4358: | 577 | case SND_AK4358: { |
536 | if (idx >= 6) | 578 | /* register 4-9 and 11-12, chip #0 only */ |
537 | /* register 4-9, chip #0 only */ | 579 | int addr = idx < 6 ? idx + 4 : idx + 5; |
538 | ctl->private_value = | 580 | knew.private_value = |
539 | AK_COMPOSE(0, idx + 5, 0, 255); | 581 | AK_COMPOSE(0, addr, 0, 127) | AK_NEEDSMSB; |
540 | else | 582 | knew.tlv.p = db_scale_7bit; |
541 | /* register 4-9, chip #0 only */ | ||
542 | ctl->private_value = | ||
543 | AK_COMPOSE(0, idx + 4, 0, 255); | ||
544 | break; | 583 | break; |
584 | } | ||
545 | case SND_AK4381: | 585 | case SND_AK4381: |
546 | /* register 3 & 4 */ | 586 | /* register 3 & 4 */ |
547 | ctl->private_value = | 587 | knew.private_value = |
548 | AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); | 588 | AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); |
589 | knew.tlv.p = db_scale_linear; | ||
549 | break; | 590 | break; |
550 | default: | 591 | default: |
551 | err = -EINVAL; | 592 | return -EINVAL; |
552 | goto __error; | ||
553 | } | 593 | } |
554 | 594 | ||
555 | ctl->private_data = ak; | 595 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); |
556 | err = snd_ctl_add(ak->card, | ||
557 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | ||
558 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | ||
559 | if (err < 0) | 596 | if (err < 0) |
560 | goto __error; | 597 | return err; |
561 | 598 | ||
562 | idx += num_stereo; | 599 | idx += num_stereo; |
563 | mixer_ch++; | 600 | mixer_ch++; |
564 | } | 601 | } |
565 | for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) { | 602 | return 0; |
566 | memset(ctl, 0, sizeof(*ctl)); | 603 | } |
567 | strcpy(ctl->id.name, "ADC Volume"); | 604 | |
568 | ctl->id.index = idx + ak->idx_offset * 2; | 605 | static int build_adc_controls(struct snd_akm4xxx *ak) |
569 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 606 | { |
570 | ctl->count = 1; | 607 | int idx, err, mixer_ch, num_stereo; |
571 | ctl->info = snd_akm4xxx_volume_info; | 608 | struct snd_kcontrol_new knew; |
572 | ctl->get = snd_akm4xxx_volume_get; | 609 | |
573 | ctl->put = snd_akm4xxx_volume_put; | 610 | mixer_ch = 0; |
574 | /* register 4 & 5 */ | 611 | for (idx = 0; idx < ak->num_adcs;) { |
575 | ctl->private_value = | 612 | memset(&knew, 0, sizeof(knew)); |
576 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); | 613 | if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { |
577 | ctl->private_data = ak; | 614 | knew.name = "ADC Volume"; |
578 | err = snd_ctl_add(ak->card, | 615 | knew.index = mixer_ch + ak->idx_offset * 2; |
579 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | 616 | num_stereo = 1; |
580 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | 617 | } else { |
581 | if (err < 0) | 618 | knew.name = ak->adc_info[mixer_ch].name; |
582 | goto __error; | 619 | num_stereo = ak->adc_info[mixer_ch].num_channels; |
583 | 620 | } | |
584 | memset(ctl, 0, sizeof(*ctl)); | 621 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
585 | strcpy(ctl->id.name, "IPGA Analog Capture Volume"); | 622 | knew.count = 1; |
586 | ctl->id.index = idx + ak->idx_offset * 2; | 623 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
587 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 624 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
588 | ctl->count = 1; | 625 | if (num_stereo == 2) { |
589 | ctl->info = snd_akm4xxx_ipga_gain_info; | 626 | knew.info = snd_akm4xxx_stereo_volume_info; |
590 | ctl->get = snd_akm4xxx_ipga_gain_get; | 627 | knew.get = snd_akm4xxx_stereo_volume_get; |
591 | ctl->put = snd_akm4xxx_ipga_gain_put; | 628 | knew.put = snd_akm4xxx_stereo_volume_put; |
629 | } else { | ||
630 | knew.info = snd_akm4xxx_volume_info; | ||
631 | knew.get = snd_akm4xxx_volume_get; | ||
632 | knew.put = snd_akm4xxx_volume_put; | ||
633 | } | ||
592 | /* register 4 & 5 */ | 634 | /* register 4 & 5 */ |
593 | ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); | 635 | if (ak->type == SND_AK5365) |
594 | ctl->private_data = ak; | 636 | knew.private_value = |
595 | err = snd_ctl_add(ak->card, | 637 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) | |
596 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | 638 | AK_VOL_CVT | AK_IPGA; |
597 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | 639 | else |
640 | knew.private_value = | ||
641 | AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | | ||
642 | AK_VOL_CVT | AK_IPGA; | ||
643 | knew.tlv.p = db_scale_vol_datt; | ||
644 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | ||
598 | if (err < 0) | 645 | if (err < 0) |
599 | goto __error; | 646 | return err; |
647 | |||
648 | if (ak->type == SND_AK5365 && (idx % 2) == 0) { | ||
649 | if (! ak->adc_info || | ||
650 | ! ak->adc_info[mixer_ch].switch_name) | ||
651 | knew.name = "Capture Switch"; | ||
652 | else | ||
653 | knew.name = ak->adc_info[mixer_ch].switch_name; | ||
654 | knew.info = ak4xxx_switch_info; | ||
655 | knew.get = ak4xxx_switch_get; | ||
656 | knew.put = ak4xxx_switch_put; | ||
657 | knew.access = 0; | ||
658 | /* register 2, bit 0 (SMUTE): 0 = normal operation, | ||
659 | 1 = mute */ | ||
660 | knew.private_value = | ||
661 | AK_COMPOSE(idx/2, 2, 0, 0) | AK_INVERT; | ||
662 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | ||
663 | if (err < 0) | ||
664 | return err; | ||
665 | } | ||
666 | |||
667 | idx += num_stereo; | ||
668 | mixer_ch++; | ||
600 | } | 669 | } |
601 | if (ak->type == SND_AK4355 || ak->type == SND_AK4358) | 670 | return 0; |
602 | num_emphs = 1; | 671 | } |
603 | else | 672 | |
604 | num_emphs = ak->num_dacs / 2; | 673 | static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) |
674 | { | ||
675 | int idx, err; | ||
676 | struct snd_kcontrol_new knew; | ||
677 | |||
605 | for (idx = 0; idx < num_emphs; idx++) { | 678 | for (idx = 0; idx < num_emphs; idx++) { |
606 | memset(ctl, 0, sizeof(*ctl)); | 679 | memset(&knew, 0, sizeof(knew)); |
607 | strcpy(ctl->id.name, "Deemphasis"); | 680 | knew.name = "Deemphasis"; |
608 | ctl->id.index = idx + ak->idx_offset; | 681 | knew.index = idx + ak->idx_offset; |
609 | ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 682 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
610 | ctl->count = 1; | 683 | knew.count = 1; |
611 | ctl->info = snd_akm4xxx_deemphasis_info; | 684 | knew.info = snd_akm4xxx_deemphasis_info; |
612 | ctl->get = snd_akm4xxx_deemphasis_get; | 685 | knew.get = snd_akm4xxx_deemphasis_get; |
613 | ctl->put = snd_akm4xxx_deemphasis_put; | 686 | knew.put = snd_akm4xxx_deemphasis_put; |
614 | switch (ak->type) { | 687 | switch (ak->type) { |
615 | case SND_AK4524: | 688 | case SND_AK4524: |
616 | case SND_AK4528: | 689 | case SND_AK4528: |
617 | /* register 3 */ | 690 | /* register 3 */ |
618 | ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); | 691 | knew.private_value = AK_COMPOSE(idx, 3, 0, 0); |
619 | break; | 692 | break; |
620 | case SND_AK4529: { | 693 | case SND_AK4529: { |
621 | int shift = idx == 3 ? 6 : (2 - idx) * 2; | 694 | int shift = idx == 3 ? 6 : (2 - idx) * 2; |
622 | /* register 8 with shift */ | 695 | /* register 8 with shift */ |
623 | ctl->private_value = AK_COMPOSE(0, 8, shift, 0); | 696 | knew.private_value = AK_COMPOSE(0, 8, shift, 0); |
624 | break; | 697 | break; |
625 | } | 698 | } |
626 | case SND_AK4355: | 699 | case SND_AK4355: |
627 | case SND_AK4358: | 700 | case SND_AK4358: |
628 | ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); | 701 | knew.private_value = AK_COMPOSE(idx, 3, 0, 0); |
629 | break; | 702 | break; |
630 | case SND_AK4381: | 703 | case SND_AK4381: |
631 | ctl->private_value = AK_COMPOSE(idx, 1, 1, 0); | 704 | knew.private_value = AK_COMPOSE(idx, 1, 1, 0); |
632 | break; | 705 | break; |
706 | default: | ||
707 | return -EINVAL; | ||
633 | } | 708 | } |
634 | ctl->private_data = ak; | 709 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); |
635 | err = snd_ctl_add(ak->card, | ||
636 | snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| | ||
637 | SNDRV_CTL_ELEM_ACCESS_WRITE)); | ||
638 | if (err < 0) | 710 | if (err < 0) |
639 | goto __error; | 711 | return err; |
640 | } | 712 | } |
641 | err = 0; | 713 | return 0; |
642 | |||
643 | __error: | ||
644 | kfree(ctl); | ||
645 | return err; | ||
646 | } | 714 | } |
647 | 715 | ||
716 | int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) | ||
717 | { | ||
718 | int err, num_emphs; | ||
719 | |||
720 | err = build_dac_controls(ak); | ||
721 | if (err < 0) | ||
722 | return err; | ||
723 | |||
724 | err = build_adc_controls(ak); | ||
725 | if (err < 0) | ||
726 | return err; | ||
727 | |||
728 | if (ak->type == SND_AK4355 || ak->type == SND_AK4358) | ||
729 | num_emphs = 1; | ||
730 | else | ||
731 | num_emphs = ak->num_dacs / 2; | ||
732 | err = build_deemphasis(ak, num_emphs); | ||
733 | if (err < 0) | ||
734 | return err; | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
648 | EXPORT_SYMBOL(snd_akm4xxx_build_controls); | 739 | EXPORT_SYMBOL(snd_akm4xxx_build_controls); |
649 | 740 | ||
650 | static int __init alsa_akm4xxx_module_init(void) | 741 | static int __init alsa_akm4xxx_module_init(void) |