static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr, unsigned char nval) { struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); unsigned int mask = AK_GET_MASK(kcontrol->private_value); int chip = AK_GET_CHIP(kcontrol->private_value); if (snd_akm4xxx_get_vol(ak, chip, addr) == nval) return 0; snd_akm4xxx_set_vol(ak, chip, addr, nval); if (AK_GET_VOL_CVT(kcontrol->private_value) && nval < 128) nval = vol_cvt_datt[nval]; if (AK_GET_IPGA(kcontrol->private_value) && nval >= 128) nval++; /* need to correct + 1 since both 127 and 128 are 0dB */ if (AK_GET_INVERT(kcontrol->private_value)) nval = mask - nval; if (AK_GET_NEEDSMSB(kcontrol->private_value)) nval |= 0x80; /* printk(KERN_DEBUG "DEBUG - AK writing reg: chip %x addr %x, nval %x\n", chip, addr, nval); */ snd_akm4xxx_write(ak, chip, addr, nval); return 1; }
static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr, unsigned char nval) { struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); unsigned int mask = AK_GET_MASK(kcontrol->private_value); int chip = AK_GET_CHIP(kcontrol->private_value); if (snd_akm4xxx_get_vol(ak, chip, addr) == nval) return 0; snd_akm4xxx_set_vol(ak, chip, addr, nval); if (AK_GET_VOL_CVT(kcontrol->private_value) && nval < 128) nval = vol_cvt_datt[nval]; if (AK_GET_IPGA(kcontrol->private_value) && nval >= 128) nval++; /* need to correct + 1 since both 127 and 128 are 0dB */ if (AK_GET_INVERT(kcontrol->private_value)) nval = mask - nval; if (AK_GET_NEEDSMSB(kcontrol->private_value)) nval |= 0x80; #ifdef CONFIG_DEBUG_PRINTK /* printk(KERN_DEBUG "DEBUG - AK writing reg: chip %x addr %x, nval %x\n", chip, addr, nval); */ #else /* ; #endif snd_akm4xxx_write(ak, chip, addr, nval); return 1; } static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { unsigned int mask = AK_GET_MASK(kcontrol->private_value); unsigned int val = ucontrol->value.integer.value[0]; if (val > mask) return -EINVAL; return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), val); } static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { unsigned int mask = AK_GET_MASK(kcontrol->private_value); uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = mask; return 0; } static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { 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_vol(ak, chip, addr); ucontrol->value.integer.value[1] = snd_akm4xxx_get_vol(ak, chip, addr+1); return 0; } static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int addr = AK_GET_ADDR(kcontrol->private_value); unsigned int mask = AK_GET_MASK(kcontrol->private_value); unsigned int val[2]; int change; val[0] = ucontrol->value.integer.value[0]; val[1] = ucontrol->value.integer.value[1]; if (val[0] > mask || val[1] > mask) return -EINVAL; change = put_ak_reg(kcontrol, addr, val[0]); change |= put_ak_reg(kcontrol, addr + 1, val[1]); return change; } static int snd_akm4xxx_deemphasis_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[4] = { "44.1kHz", "Off", "48kHz", "32kHz", }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; 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]); return 0; } static int snd_akm4xxx_deemphasis_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_akm4xxx *ak = snd_kcontrol_chip(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; return 0; } static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_akm4xxx *ak = snd_kcontrol_chip(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); unsigned char nval = ucontrol->value.enumerated.item[0] & 3; int change; 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); return change; } #define ak4xxx_switch_info snd_ctl_boolean_mono_info static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_akm4xxx *ak = snd_kcontrol_chip(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); int invert = AK_GET_INVERT(kcontrol->private_value); /* we observe the (1<<shift) bit only */ unsigned char val = snd_akm4xxx_get(ak, chip, addr) & (1<<shift); if (invert) val = ! val; ucontrol->value.integer.value[0] = (val & (1<<shift)) != 0; return 0; }