]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From 29fdbec2dcb1ce364812778271056aa9516ff3ed Mon Sep 17 00:00:00 2001 |
2 | From: Takashi Iwai <tiwai@suse.de> | |
3 | Date: Tue, 20 Jan 2009 13:07:55 +0100 | |
4 | Subject: ALSA: hda - Add extra volume offset to standard volume amp macros | |
5 | Patch-mainline: | |
6 | References: bnc#466428 | |
7 | ||
8 | ||
9 | Added the volume offset to base for the standard volume controls | |
10 | to handle elements with too big volume scales like -96dB..0dB. | |
11 | For such elements, you can set the base volume to reduce the range. | |
12 | ||
13 | Signed-off-by: Takashi Iwai <tiwai@suse.de> | |
14 | ||
15 | --- | |
16 | sound/pci/hda/hda_codec.c | 45 +++++++++++++++++++++++++++++++++++++-------- | |
17 | sound/pci/hda/hda_local.h | 5 ++++- | |
18 | 2 files changed, 41 insertions(+), 9 deletions(-) | |
19 | ||
20 | diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c | |
21 | index b7bba7d..0cf2424 100644 | |
22 | --- a/sound/pci/hda/hda_codec.c | |
23 | +++ b/sound/pci/hda/hda_codec.c | |
24 | @@ -967,6 +967,7 @@ int snd_hda_mixer_amp_volume_info(struct | |
25 | u16 nid = get_amp_nid(kcontrol); | |
26 | u8 chs = get_amp_channels(kcontrol); | |
27 | int dir = get_amp_direction(kcontrol); | |
28 | + unsigned int ofs = get_amp_offset(kcontrol); | |
29 | u32 caps; | |
30 | ||
31 | caps = query_amp_caps(codec, nid, dir); | |
32 | @@ -978,6 +979,8 @@ int snd_hda_mixer_amp_volume_info(struct | |
33 | kcontrol->id.name); | |
34 | return -EINVAL; | |
35 | } | |
36 | + if (ofs < caps) | |
37 | + caps -= ofs; | |
38 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
39 | uinfo->count = chs == 3 ? 2 : 1; | |
40 | uinfo->value.integer.min = 0; | |
41 | @@ -985,6 +988,32 @@ int snd_hda_mixer_amp_volume_info(struct | |
42 | return 0; | |
43 | } | |
44 | ||
45 | + | |
46 | +static inline unsigned int | |
47 | +read_amp_value(struct hda_codec *codec, hda_nid_t nid, | |
48 | + int ch, int dir, int idx, unsigned int ofs) | |
49 | +{ | |
50 | + unsigned int val; | |
51 | + val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx); | |
52 | + val &= HDA_AMP_VOLMASK; | |
53 | + if (val >= ofs) | |
54 | + val -= ofs; | |
55 | + else | |
56 | + val = 0; | |
57 | + return val; | |
58 | +} | |
59 | + | |
60 | +static inline int | |
61 | +update_amp_value(struct hda_codec *codec, hda_nid_t nid, | |
62 | + int ch, int dir, int idx, unsigned int ofs, | |
63 | + unsigned int val) | |
64 | +{ | |
65 | + if (val > 0) | |
66 | + val += ofs; | |
67 | + return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, | |
68 | + HDA_AMP_VOLMASK, val); | |
69 | +} | |
70 | + | |
71 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, | |
72 | struct snd_ctl_elem_value *ucontrol) | |
73 | { | |
74 | @@ -993,14 +1022,13 @@ int snd_hda_mixer_amp_volume_get(struct | |
75 | int chs = get_amp_channels(kcontrol); | |
76 | int dir = get_amp_direction(kcontrol); | |
77 | int idx = get_amp_index(kcontrol); | |
78 | + unsigned int ofs = get_amp_offset(kcontrol); | |
79 | long *valp = ucontrol->value.integer.value; | |
80 | ||
81 | if (chs & 1) | |
82 | - *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) | |
83 | - & HDA_AMP_VOLMASK; | |
84 | + *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs); | |
85 | if (chs & 2) | |
86 | - *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) | |
87 | - & HDA_AMP_VOLMASK; | |
88 | + *valp = read_amp_value(codec, nid, 1, dir, idx, ofs); | |
89 | return 0; | |
90 | } | |
91 | ||
92 | @@ -1012,18 +1040,17 @@ int snd_hda_mixer_amp_volume_put(struct | |
93 | int chs = get_amp_channels(kcontrol); | |
94 | int dir = get_amp_direction(kcontrol); | |
95 | int idx = get_amp_index(kcontrol); | |
96 | + unsigned int ofs = get_amp_offset(kcontrol); | |
97 | long *valp = ucontrol->value.integer.value; | |
98 | int change = 0; | |
99 | ||
100 | snd_hda_power_up(codec); | |
101 | if (chs & 1) { | |
102 | - change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | |
103 | - 0x7f, *valp); | |
104 | + change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp); | |
105 | valp++; | |
106 | } | |
107 | if (chs & 2) | |
108 | - change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | |
109 | - 0x7f, *valp); | |
110 | + change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp); | |
111 | snd_hda_power_down(codec); | |
112 | return change; | |
113 | } | |
114 | @@ -1034,6 +1061,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kco | |
115 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | |
116 | hda_nid_t nid = get_amp_nid(kcontrol); | |
117 | int dir = get_amp_direction(kcontrol); | |
118 | + unsigned int ofs = get_amp_offset(kcontrol); | |
119 | u32 caps, val1, val2; | |
120 | ||
121 | if (size < 4 * sizeof(unsigned int)) | |
122 | @@ -1042,6 +1070,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kco | |
123 | val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; | |
124 | val2 = (val2 + 1) * 25; | |
125 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | |
126 | + val1 += ofs; | |
127 | val1 = ((int)val1) * ((int)val2); | |
128 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | |
129 | return -EFAULT; | |
130 | diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h | |
131 | index 1dd8716..d53ce1f 100644 | |
132 | --- a/sound/pci/hda/hda_local.h | |
133 | +++ b/sound/pci/hda/hda_local.h | |
134 | @@ -26,8 +26,10 @@ | |
135 | /* | |
136 | * for mixer controls | |
137 | */ | |
138 | +#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ | |
139 | + ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) | |
140 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ | |
141 | - ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) | |
142 | + HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) | |
143 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | |
144 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | |
145 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | |
146 | @@ -432,5 +434,6 @@ int snd_hda_check_amp_list_power(struct | |
147 | #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) | |
148 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) | |
149 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) | |
150 | +#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) | |
151 | ||
152 | #endif /* __SOUND_HDA_LOCAL_H */ | |
153 | -- | |
154 | 1.6.1 | |
155 |