]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.drivers/alsa-hda-add-volume-offset
Revert "Move xen patchset to new version's subdir."
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / alsa-hda-add-volume-offset
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