Loading sound/pci/ca0106/ca0106_mixer.c +3 −1 Original line number Diff line number Diff line Loading @@ -472,10 +472,12 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, #define CA_VOLUME(xname,chid,reg) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ .info = snd_ca0106_volume_info, \ .get = snd_ca0106_volume_get, \ .put = snd_ca0106_volume_put, \ .tlv = snd_ca0106_db_scale, \ .tlv.p = snd_ca0106_db_scale, \ .private_value = ((chid) << 8) | (reg) \ } Loading sound/pci/hda/hda_codec.c +33 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <sound/core.h> #include "hda_codec.h" #include <sound/asoundef.h> #include <sound/tlv.h> #include <sound/initval.h> #include "hda_local.h" Loading Loading @@ -841,6 +842,38 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e return change; } int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *_tlv) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = get_amp_nid(kcontrol); int dir = get_amp_direction(kcontrol); u32 caps, val1, val2; if (size < 4 * sizeof(unsigned int)) return -ENOMEM; caps = query_amp_caps(codec, nid, dir); val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25; val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); val1 = ((int)val1) * ((int)val2); if (caps & AC_AMPCAP_MUTE) val2 |= 0x10000; if ((val2 & 0x10000) == 0 && dir == HDA_OUTPUT) { caps = query_amp_caps(codec, nid, HDA_INPUT); if (caps & AC_AMPCAP_MUTE) val2 |= 0x10000; } if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) return -EFAULT; if (put_user(2 * sizeof(unsigned int), _tlv + 1)) return -EFAULT; if (put_user(val1, _tlv + 2)) return -EFAULT; if (put_user(val2, _tlv + 3)) return -EFAULT; return 0; } /* switch */ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { Loading sound/pci/hda/hda_local.h +5 −0 Original line number Diff line number Diff line Loading @@ -30,9 +30,13 @@ /* mono volume with index (index=0,1,...) (channel=1,2) */ #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ .info = snd_hda_mixer_amp_volume_info, \ .get = snd_hda_mixer_amp_volume_get, \ .put = snd_hda_mixer_amp_volume_put, \ .tlv.c = snd_hda_mixer_amp_tlv, \ .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } /* stereo volume with index */ #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ Loading Loading @@ -63,6 +67,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv); int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); Loading sound/pci/hda/patch_analog.c +17 −0 Original line number Diff line number Diff line Loading @@ -452,6 +452,19 @@ static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl return change; } static int ad1986a_pcm_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *_tlv) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *ad = codec->spec; mutex_lock(&ad->amp_mutex); snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, _tlv); mutex_unlock(&ad->amp_mutex); return 0; } #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) Loading Loading @@ -488,9 +501,13 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, .info = ad1986a_pcm_amp_vol_info, .get = ad1986a_pcm_amp_vol_get, .put = ad1986a_pcm_amp_vol_put, .tlv.c = ad1986a_pcm_amp_tlv, .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) }, { Loading Loading
sound/pci/ca0106/ca0106_mixer.c +3 −1 Original line number Diff line number Diff line Loading @@ -472,10 +472,12 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, #define CA_VOLUME(xname,chid,reg) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ .info = snd_ca0106_volume_info, \ .get = snd_ca0106_volume_get, \ .put = snd_ca0106_volume_put, \ .tlv = snd_ca0106_db_scale, \ .tlv.p = snd_ca0106_db_scale, \ .private_value = ((chid) << 8) | (reg) \ } Loading
sound/pci/hda/hda_codec.c +33 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <sound/core.h> #include "hda_codec.h" #include <sound/asoundef.h> #include <sound/tlv.h> #include <sound/initval.h> #include "hda_local.h" Loading Loading @@ -841,6 +842,38 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e return change; } int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *_tlv) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = get_amp_nid(kcontrol); int dir = get_amp_direction(kcontrol); u32 caps, val1, val2; if (size < 4 * sizeof(unsigned int)) return -ENOMEM; caps = query_amp_caps(codec, nid, dir); val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25; val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); val1 = ((int)val1) * ((int)val2); if (caps & AC_AMPCAP_MUTE) val2 |= 0x10000; if ((val2 & 0x10000) == 0 && dir == HDA_OUTPUT) { caps = query_amp_caps(codec, nid, HDA_INPUT); if (caps & AC_AMPCAP_MUTE) val2 |= 0x10000; } if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) return -EFAULT; if (put_user(2 * sizeof(unsigned int), _tlv + 1)) return -EFAULT; if (put_user(val1, _tlv + 2)) return -EFAULT; if (put_user(val2, _tlv + 3)) return -EFAULT; return 0; } /* switch */ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { Loading
sound/pci/hda/hda_local.h +5 −0 Original line number Diff line number Diff line Loading @@ -30,9 +30,13 @@ /* mono volume with index (index=0,1,...) (channel=1,2) */ #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ .info = snd_hda_mixer_amp_volume_info, \ .get = snd_hda_mixer_amp_volume_get, \ .put = snd_hda_mixer_amp_volume_put, \ .tlv.c = snd_hda_mixer_amp_tlv, \ .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } /* stereo volume with index */ #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ Loading Loading @@ -63,6 +67,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv); int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); Loading
sound/pci/hda/patch_analog.c +17 −0 Original line number Diff line number Diff line Loading @@ -452,6 +452,19 @@ static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl return change; } static int ad1986a_pcm_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *_tlv) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *ad = codec->spec; mutex_lock(&ad->amp_mutex); snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, _tlv); mutex_unlock(&ad->amp_mutex); return 0; } #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) Loading Loading @@ -488,9 +501,13 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, .info = ad1986a_pcm_amp_vol_info, .get = ad1986a_pcm_amp_vol_get, .put = ad1986a_pcm_amp_vol_put, .tlv.c = ad1986a_pcm_amp_tlv, .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) }, { Loading