diff options
-rw-r--r-- | include/sound/ak4xxx-adda.h | 37 | ||||
-rw-r--r-- | sound/i2c/other/ak4xxx-adda.c | 203 |
2 files changed, 161 insertions, 79 deletions
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h index acf8cc1292e0..3d9888492026 100644 --- a/include/sound/ak4xxx-adda.h +++ b/include/sound/ak4xxx-adda.h @@ -32,8 +32,8 @@ struct snd_akm4xxx; struct snd_ak4xxx_ops { void (*lock)(struct snd_akm4xxx *ak, int chip); void (*unlock)(struct snd_akm4xxx *ak, int chip); - void (*write)(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val); - // unsigned char (*read)(struct snd_akm4xxx *ak, int chip, unsigned char reg); + void (*write)(struct snd_akm4xxx *ak, int chip, unsigned char reg, + unsigned char val); void (*set_rate_val)(struct snd_akm4xxx *ak, unsigned int rate); }; @@ -41,31 +41,40 @@ struct snd_ak4xxx_ops { struct snd_akm4xxx { struct snd_card *card; - unsigned int num_adcs; /* AK4524 or AK4528 ADCs */ - unsigned int num_dacs; /* AK4524 or AK4528 DACs */ - unsigned char images[AK4XXX_IMAGE_SIZE]; /* saved register image */ - unsigned char ipga_gain[AK4XXX_MAX_CHIPS][2]; /* saved register image for IPGA (AK4528) */ + unsigned int num_adcs; /* AK4524 or AK4528 ADCs */ + unsigned int num_dacs; /* AK4524 or AK4528 DACs */ + unsigned char images[AK4XXX_IMAGE_SIZE]; /* saved register image */ + unsigned char ipga_gain[AK4XXX_MAX_CHIPS][2]; /* saved register image + * for IPGA (AK4528) + */ unsigned long private_value[AK4XXX_MAX_CHIPS]; /* helper for driver */ void *private_data[AK4XXX_MAX_CHIPS]; /* helper for driver */ /* template should fill the following fields */ - unsigned int idx_offset; /* control index offset */ + unsigned int idx_offset; /* control index offset */ enum { SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4355, SND_AK4358, SND_AK4381 } type; - unsigned int *num_stereo; /* array of combined counts for the mixer */ - char **channel_names; /* array of mixer channel names */ + unsigned int *num_stereo; /* array of combined counts + * for the mixer + */ + char **channel_names; /* array of mixer channel names */ struct snd_ak4xxx_ops ops; }; -void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val); +void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, + unsigned char val); void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state); void snd_akm4xxx_init(struct snd_akm4xxx *ak); int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak); -#define snd_akm4xxx_get(ak,chip,reg) (ak)->images[(chip) * 16 + (reg)] -#define snd_akm4xxx_set(ak,chip,reg,val) ((ak)->images[(chip) * 16 + (reg)] = (val)) -#define snd_akm4xxx_get_ipga(ak,chip,reg) (ak)->ipga_gain[chip][(reg)-4] -#define snd_akm4xxx_set_ipga(ak,chip,reg,val) ((ak)->ipga_gain[chip][(reg)-4] = (val)) +#define snd_akm4xxx_get(ak,chip,reg) \ + (ak)->images[(chip) * 16 + (reg)] +#define snd_akm4xxx_set(ak,chip,reg,val) \ + ((ak)->images[(chip) * 16 + (reg)] = (val)) +#define snd_akm4xxx_get_ipga(ak,chip,reg) \ + (ak)->ipga_gain[chip][(reg)-4] +#define snd_akm4xxx_set_ipga(ak,chip,reg,val) \ + ((ak)->ipga_gain[chip][(reg)-4] = (val)) #endif /* __SOUND_AK4XXX_ADDA_H */ diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index f68bd740e1a1..dc7cc2001b74 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c @@ -34,7 +34,8 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>"); MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); MODULE_LICENSE("GPL"); -void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val) +void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, + unsigned char val) { ak->ops.lock(ak, chip); ak->ops.write(ak, chip, reg, val); @@ -52,6 +53,67 @@ void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsi ak->ops.unlock(ak, chip); } +EXPORT_SYMBOL(snd_akm4xxx_write); + +/* reset procedure for AK4524 and AK4528 */ +static void ak4524_reset(struct snd_akm4xxx *ak, int state) +{ + unsigned int chip; + unsigned char reg, maxreg; + + if (ak->type == SND_AK4528) + maxreg = 0x06; + else + maxreg = 0x08; + for (chip = 0; chip < ak->num_dacs/2; chip++) { + snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); + if (state) + continue; + /* DAC volumes */ + for (reg = 0x04; reg < maxreg; reg++) + snd_akm4xxx_write(ak, chip, reg, + snd_akm4xxx_get(ak, chip, reg)); + if (ak->type == SND_AK4528) + continue; + /* IPGA */ + for (reg = 0x04; reg < 0x06; reg++) + snd_akm4xxx_write(ak, chip, reg, + snd_akm4xxx_get_ipga(ak, chip, reg)); + } +} + +/* reset procedure for AK4355 and AK4358 */ +static void ak4355_reset(struct snd_akm4xxx *ak, int state) +{ + unsigned char reg; + + if (state) { + snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ + return; + } + for (reg = 0x00; reg < 0x0b; reg++) + if (reg != 0x01) + snd_akm4xxx_write(ak, 0, reg, + snd_akm4xxx_get(ak, 0, reg)); + snd_akm4xxx_write(ak, 0, 0x01, 0x01); /* un-reset, unmute */ +} + +/* reset procedure for AK4381 */ +static void ak4381_reset(struct snd_akm4xxx *ak, int state) +{ + unsigned int chip; + unsigned char reg; + + for (chip = 0; chip < ak->num_dacs/2; chip++) { + snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); + if (state) + continue; + for (reg = 0x01; reg < 0x05; reg++) + snd_akm4xxx_write(ak, chip, reg, + snd_akm4xxx_get(ak, chip, reg)); + } +} + /* * reset the AKM codecs * @state: 1 = reset codec, 0 = restore the registers @@ -60,52 +122,26 @@ void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsi */ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state) { - unsigned int chip; - unsigned char reg; - switch (ak->type) { case SND_AK4524: case SND_AK4528: - for (chip = 0; chip < ak->num_dacs/2; chip++) { - snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); - if (state) - continue; - /* DAC volumes */ - for (reg = 0x04; reg < (ak->type == SND_AK4528 ? 0x06 : 0x08); reg++) - snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_get(ak, chip, reg)); - if (ak->type == SND_AK4528) - continue; - /* IPGA */ - for (reg = 0x04; reg < 0x06; reg++) - snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_get_ipga(ak, chip, reg)); - } + ak4524_reset(ak, state); break; case SND_AK4529: /* FIXME: needed for ak4529? */ break; case SND_AK4355: case SND_AK4358: - if (state) { - snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ - return; - } - for (reg = 0x00; reg < 0x0b; reg++) - if (reg != 0x01) - snd_akm4xxx_write(ak, 0, reg, snd_akm4xxx_get(ak, 0, reg)); - snd_akm4xxx_write(ak, 0, 0x01, 0x01); /* un-reset, unmute */ + ak4355_reset(ak, state); break; case SND_AK4381: - for (chip = 0; chip < ak->num_dacs/2; chip++) { - snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); - if (state) - continue; - for (reg = 0x01; reg < 0x05; reg++) - snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_get(ak, chip, reg)); - } + ak4381_reset(ak, state); break; } } +EXPORT_SYMBOL(snd_akm4xxx_reset); + /* * initialize all the ak4xxx chips */ @@ -153,7 +189,8 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) }; static unsigned char inits_ak4355[] = { 0x01, 0x02, /* 1: reset and soft-mute */ - 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */ + 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, + * disable DZF, sharp roll-off, RSTN#=0 */ 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */ // 0x02, 0x2e, /* quad speed */ 0x03, 0x01, /* 3: de-emphasis off */ @@ -169,7 +206,8 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) }; static unsigned char inits_ak4358[] = { 0x01, 0x02, /* 1: reset and soft-mute */ - 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */ + 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, + * disable DZF, sharp roll-off, RSTN#=0 */ 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */ // 0x02, 0x2e, /* quad speed */ 0x03, 0x01, /* 3: de-emphasis off */ @@ -187,7 +225,8 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) }; static unsigned char inits_ak4381[] = { 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */ - 0x01, 0x02, /* 1: de-emphasis off, normal speed, sharp roll-off, DZF off */ + 0x01, 0x02, /* 1: de-emphasis off, normal speed, + * sharp roll-off, DZF off */ // 0x01, 0x12, /* quad speed */ 0x02, 0x00, /* 2: DZF disabled */ 0x03, 0x00, /* 3: LATT 0 */ @@ -239,12 +278,15 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) } } +EXPORT_SYMBOL(snd_akm4xxx_init); + #define AK_GET_CHIP(val) (((val) >> 8) & 0xff) #define AK_GET_ADDR(val) ((val) & 0xff) #define AK_GET_SHIFT(val) (((val) >> 16) & 0x7f) #define AK_GET_INVERT(val) (((val) >> 23) & 1) #define AK_GET_MASK(val) (((val) >> 24) & 0xff) -#define AK_COMPOSE(chip,addr,shift,mask) (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) +#define AK_COMPOSE(chip,addr,shift,mask) \ + (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) #define AK_INVERT (1<<23) static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol, @@ -293,7 +335,7 @@ static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, } static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) + struct snd_ctl_elem_info *uinfo) { unsigned int mask = AK_GET_MASK(kcontrol->private_value); @@ -305,7 +347,7 @@ static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, } static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); int chip = AK_GET_CHIP(kcontrol->private_value); @@ -323,7 +365,7 @@ static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol, } static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); int chip = AK_GET_CHIP(kcontrol->private_value); @@ -366,7 +408,8 @@ static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol, struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); - ucontrol->value.integer.value[0] = snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f; + ucontrol->value.integer.value[0] = + snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f; return 0; } @@ -394,7 +437,8 @@ static int snd_akm4xxx_deemphasis_info(struct snd_kcontrol *kcontrol, uinfo->value.enumerated.items = 4; if (uinfo->value.enumerated.item >= 4) uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + strcpy(uinfo->value.enumerated.name, + texts[uinfo->value.enumerated.item]); return 0; } @@ -405,7 +449,8 @@ static int snd_akm4xxx_deemphasis_get(struct snd_kcontrol *kcontrol, int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); int shift = AK_GET_SHIFT(kcontrol->private_value); - ucontrol->value.enumerated.item[0] = (snd_akm4xxx_get(ak, chip, addr) >> shift) & 3; + ucontrol->value.enumerated.item[0] = + (snd_akm4xxx_get(ak, chip, addr) >> shift) & 3; return 0; } @@ -419,7 +464,8 @@ static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol, unsigned char nval = ucontrol->value.enumerated.item[0] & 3; int change; - nval = (nval << shift) | (snd_akm4xxx_get(ak, chip, addr) & ~(3 << shift)); + nval = (nval << shift) | + (snd_akm4xxx_get(ak, chip, addr) & ~(3 << shift)); change = snd_akm4xxx_get(ak, chip, addr) != nval; if (change) snd_akm4xxx_write(ak, chip, addr, nval); @@ -451,7 +497,7 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) } else { strcpy(ctl->id.name, ak->channel_names[mixer_ch]); num_stereo = ak->num_stereo[mixer_ch]; - ctl->id.index = 0; //mixer_ch + ak->idx_offset * 2; + ctl->id.index = 0; } ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; ctl->count = 1; @@ -466,27 +512,40 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) } switch (ak->type) { case SND_AK4524: - ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */ + /* register 6 & 7 */ + ctl->private_value = + AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); break; case SND_AK4528: - ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */ + /* register 4 & 5 */ + ctl->private_value = + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); break; case SND_AK4529: { - int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; /* registers 2-7 and b,c */ - ctl->private_value = AK_COMPOSE(0, val, 0, 255) | AK_INVERT; + /* registers 2-7 and b,c */ + int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; + ctl->private_value = + AK_COMPOSE(0, val, 0, 255) | AK_INVERT; break; } case SND_AK4355: - ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */ + /* register 4-9, chip #0 only */ + ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); break; case SND_AK4358: if (idx >= 6) - ctl->private_value = AK_COMPOSE(0, idx + 5, 0, 255); /* register 4-9, chip #0 only */ + /* register 4-9, chip #0 only */ + ctl->private_value = + AK_COMPOSE(0, idx + 5, 0, 255); else - ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */ + /* register 4-9, chip #0 only */ + ctl->private_value = + AK_COMPOSE(0, idx + 4, 0, 255); break; case SND_AK4381: - ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); /* register 3 & 4 */ + /* register 3 & 4 */ + ctl->private_value = + AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); break; default: err = -EINVAL; @@ -494,7 +553,10 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) } ctl->private_data = ak; - if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) + err = snd_ctl_add(ak->card, + snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| + SNDRV_CTL_ELEM_ACCESS_WRITE)); + if (err < 0) goto __error; idx += num_stereo; @@ -509,9 +571,14 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) ctl->info = snd_akm4xxx_volume_info; ctl->get = snd_akm4xxx_volume_get; ctl->put = snd_akm4xxx_volume_put; - ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */ + /* register 4 & 5 */ + ctl->private_value = + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); ctl->private_data = ak; - if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) + err = snd_ctl_add(ak->card, + snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| + SNDRV_CTL_ELEM_ACCESS_WRITE)); + if (err < 0) goto __error; memset(ctl, 0, sizeof(*ctl)); @@ -522,9 +589,13 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) ctl->info = snd_akm4xxx_ipga_gain_info; ctl->get = snd_akm4xxx_ipga_gain_get; ctl->put = snd_akm4xxx_ipga_gain_put; - ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); /* register 4 & 5 */ + /* register 4 & 5 */ + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); ctl->private_data = ak; - if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) + err = snd_ctl_add(ak->card, + snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| + SNDRV_CTL_ELEM_ACCESS_WRITE)); + if (err < 0) goto __error; } if (ak->type == SND_AK4355 || ak->type == SND_AK4358) @@ -543,11 +614,13 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) switch (ak->type) { case SND_AK4524: case SND_AK4528: - ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); /* register 3 */ + /* register 3 */ + ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); break; case SND_AK4529: { int shift = idx == 3 ? 6 : (2 - idx) * 2; - ctl->private_value = AK_COMPOSE(0, 8, shift, 0); /* register 8 with shift */ + /* register 8 with shift */ + ctl->private_value = AK_COMPOSE(0, 8, shift, 0); break; } case SND_AK4355: @@ -559,7 +632,10 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) break; } ctl->private_data = ak; - if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) + err = snd_ctl_add(ak->card, + snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| + SNDRV_CTL_ELEM_ACCESS_WRITE)); + if (err < 0) goto __error; } err = 0; @@ -569,6 +645,8 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) return err; } +EXPORT_SYMBOL(snd_akm4xxx_build_controls); + static int __init alsa_akm4xxx_module_init(void) { return 0; @@ -580,8 +658,3 @@ static void __exit alsa_akm4xxx_module_exit(void) module_init(alsa_akm4xxx_module_init) module_exit(alsa_akm4xxx_module_exit) - -EXPORT_SYMBOL(snd_akm4xxx_write); -EXPORT_SYMBOL(snd_akm4xxx_reset); -EXPORT_SYMBOL(snd_akm4xxx_init); -EXPORT_SYMBOL(snd_akm4xxx_build_controls); |