diff options
-rw-r--r-- | sound/pci/ca0106/ca0106_mixer.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 33 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 5 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 17 |
4 files changed, 58 insertions, 1 deletions
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 35309b3ed8c0..df75270939ac 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -472,10 +472,12 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, | |||
472 | #define CA_VOLUME(xname,chid,reg) \ | 472 | #define CA_VOLUME(xname,chid,reg) \ |
473 | { \ | 473 | { \ |
474 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 474 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
475 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
476 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | ||
475 | .info = snd_ca0106_volume_info, \ | 477 | .info = snd_ca0106_volume_info, \ |
476 | .get = snd_ca0106_volume_get, \ | 478 | .get = snd_ca0106_volume_get, \ |
477 | .put = snd_ca0106_volume_put, \ | 479 | .put = snd_ca0106_volume_put, \ |
478 | .tlv = snd_ca0106_db_scale, \ | 480 | .tlv.p = snd_ca0106_db_scale, \ |
479 | .private_value = ((chid) << 8) | (reg) \ | 481 | .private_value = ((chid) << 8) | (reg) \ |
480 | } | 482 | } |
481 | 483 | ||
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 23201f3eeb12..78ff4575699d 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
31 | #include <sound/asoundef.h> | 31 | #include <sound/asoundef.h> |
32 | #include <sound/tlv.h> | ||
32 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
33 | #include "hda_local.h" | 34 | #include "hda_local.h" |
34 | 35 | ||
@@ -841,6 +842,38 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
841 | return change; | 842 | return change; |
842 | } | 843 | } |
843 | 844 | ||
845 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
846 | unsigned int size, unsigned int __user *_tlv) | ||
847 | { | ||
848 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
849 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
850 | int dir = get_amp_direction(kcontrol); | ||
851 | u32 caps, val1, val2; | ||
852 | |||
853 | if (size < 4 * sizeof(unsigned int)) | ||
854 | return -ENOMEM; | ||
855 | caps = query_amp_caps(codec, nid, dir); | ||
856 | val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25; | ||
857 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | ||
858 | val1 = ((int)val1) * ((int)val2); | ||
859 | if (caps & AC_AMPCAP_MUTE) | ||
860 | val2 |= 0x10000; | ||
861 | if ((val2 & 0x10000) == 0 && dir == HDA_OUTPUT) { | ||
862 | caps = query_amp_caps(codec, nid, HDA_INPUT); | ||
863 | if (caps & AC_AMPCAP_MUTE) | ||
864 | val2 |= 0x10000; | ||
865 | } | ||
866 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | ||
867 | return -EFAULT; | ||
868 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) | ||
869 | return -EFAULT; | ||
870 | if (put_user(val1, _tlv + 2)) | ||
871 | return -EFAULT; | ||
872 | if (put_user(val2, _tlv + 3)) | ||
873 | return -EFAULT; | ||
874 | return 0; | ||
875 | } | ||
876 | |||
844 | /* switch */ | 877 | /* switch */ |
845 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 878 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
846 | { | 879 | { |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 14e8aa2806ed..0f0ae685a9c1 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -30,9 +30,13 @@ | |||
30 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 30 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
31 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 31 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
32 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 32 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
33 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
34 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | ||
35 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | ||
33 | .info = snd_hda_mixer_amp_volume_info, \ | 36 | .info = snd_hda_mixer_amp_volume_info, \ |
34 | .get = snd_hda_mixer_amp_volume_get, \ | 37 | .get = snd_hda_mixer_amp_volume_get, \ |
35 | .put = snd_hda_mixer_amp_volume_put, \ | 38 | .put = snd_hda_mixer_amp_volume_put, \ |
39 | .tlv.c = snd_hda_mixer_amp_tlv, \ | ||
36 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } | 40 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } |
37 | /* stereo volume with index */ | 41 | /* stereo volume with index */ |
38 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ | 42 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ |
@@ -63,6 +67,7 @@ | |||
63 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 67 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); |
64 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 68 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
65 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 69 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
70 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv); | ||
66 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 71 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); |
67 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 72 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
68 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 73 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 6823f2bc10b3..54506d4e57d5 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -452,6 +452,19 @@ static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
452 | return change; | 452 | return change; |
453 | } | 453 | } |
454 | 454 | ||
455 | static int ad1986a_pcm_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
456 | unsigned int size, unsigned int __user *_tlv) | ||
457 | { | ||
458 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
459 | struct ad198x_spec *ad = codec->spec; | ||
460 | |||
461 | mutex_lock(&ad->amp_mutex); | ||
462 | snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, _tlv); | ||
463 | mutex_unlock(&ad->amp_mutex); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | |||
455 | #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info | 468 | #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info |
456 | 469 | ||
457 | static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 470 | static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
@@ -488,9 +501,13 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { | |||
488 | { | 501 | { |
489 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 502 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
490 | .name = "PCM Playback Volume", | 503 | .name = "PCM Playback Volume", |
504 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
505 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
506 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | ||
491 | .info = ad1986a_pcm_amp_vol_info, | 507 | .info = ad1986a_pcm_amp_vol_info, |
492 | .get = ad1986a_pcm_amp_vol_get, | 508 | .get = ad1986a_pcm_amp_vol_get, |
493 | .put = ad1986a_pcm_amp_vol_put, | 509 | .put = ad1986a_pcm_amp_vol_put, |
510 | .tlv.c = ad1986a_pcm_amp_tlv, | ||
494 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) | 511 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) |
495 | }, | 512 | }, |
496 | { | 513 | { |