]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.drivers/alsa-hda-spdif-slave
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / alsa-hda-spdif-slave
1 From: Takashi Iwai <tiwai@suse.de>
2 Subject: ALSA: hda - Slave SPDIF support
3 Patch-mainline: 2.6.28-rc1
4 References:
5
6 Add the support of slave SPDIF outputs for multiple SPDIF devices.
7
8 Signed-off-by: Takashi Iwai <tiwai@suse.de>
9
10 ---
11 ---
12 sound/pci/hda/hda_codec.c | 72 ++++++++++++++++++++++++++-----------
13 sound/pci/hda/hda_codec.h | 89 +++++++++++++++++++++++++++++++++++++++++++---
14 sound/pci/hda/hda_local.h | 15 ++++---
15 3 files changed, 146 insertions(+), 30 deletions(-)
16
17 --- a/sound/pci/hda/hda_codec.c
18 +++ b/sound/pci/hda/hda_codec.c
19 @@ -1430,6 +1430,29 @@ static unsigned int convert_to_spdif_sta
20 return sbits;
21 }
22
23 +/* set digital convert verbs both for the given NID and its slaves */
24 +static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
25 + int verb, int val)
26 +{
27 + hda_nid_t *d;
28 +
29 + snd_hda_codec_write(codec, nid, 0, verb, val);
30 + d = codec->slave_dig_outs;
31 + if (!d)
32 + return;
33 + for (; *d; d++)
34 + snd_hda_codec_write(codec, *d, 0, verb, val);
35 +}
36 +
37 +static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
38 + int dig1, int dig2)
39 +{
40 + if (dig1 != -1)
41 + set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1);
42 + if (dig2 != -1)
43 + set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2);
44 +}
45 +
46 static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
47 struct snd_ctl_elem_value *ucontrol)
48 {
49 @@ -1448,14 +1471,8 @@ static int snd_hda_spdif_default_put(str
50 change = codec->spdif_ctls != val;
51 codec->spdif_ctls = val;
52
53 - if (change) {
54 - snd_hda_codec_write_cache(codec, nid, 0,
55 - AC_VERB_SET_DIGI_CONVERT_1,
56 - val & 0xff);
57 - snd_hda_codec_write_cache(codec, nid, 0,
58 - AC_VERB_SET_DIGI_CONVERT_2,
59 - val >> 8);
60 - }
61 + if (change)
62 + set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
63
64 mutex_unlock(&codec->spdif_mutex);
65 return change;
66 @@ -1487,9 +1504,7 @@ static int snd_hda_spdif_out_switch_put(
67 change = codec->spdif_ctls != val;
68 if (change) {
69 codec->spdif_ctls = val;
70 - snd_hda_codec_write_cache(codec, nid, 0,
71 - AC_VERB_SET_DIGI_CONVERT_1,
72 - val & 0xff);
73 + set_dig_out_convert(codec, nid, val & 0xff, -1);
74 /* unmute amp switch (if any) */
75 if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
76 (val & AC_DIG1_ENABLE))
77 @@ -2583,14 +2598,31 @@ static void setup_dig_out_stream(struct
78 unsigned int stream_tag, unsigned int format)
79 {
80 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
81 - if (codec->spdif_ctls & AC_DIG1_ENABLE)
82 - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
83 - codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
84 + if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
85 + set_dig_out_convert(codec, nid,
86 + codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
87 + -1);
88 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
89 + if (codec->slave_dig_outs) {
90 + hda_nid_t *d;
91 + for (d = codec->slave_dig_outs; *d; d++)
92 + snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
93 + format);
94 + }
95 /* turn on again (if needed) */
96 - if (codec->spdif_ctls & AC_DIG1_ENABLE)
97 - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
98 - codec->spdif_ctls & 0xff);
99 + if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
100 + set_dig_out_convert(codec, nid,
101 + codec->spdif_ctls & 0xff, -1);
102 +}
103 +
104 +static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
105 +{
106 + snd_hda_codec_cleanup_stream(codec, nid);
107 + if (codec->slave_dig_outs) {
108 + hda_nid_t *d;
109 + for (d = codec->slave_dig_outs; *d; d++)
110 + snd_hda_codec_cleanup_stream(codec, *d);
111 + }
112 }
113
114 /*
115 @@ -2602,7 +2634,7 @@ int snd_hda_multi_out_dig_open(struct hd
116 mutex_lock(&codec->spdif_mutex);
117 if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
118 /* already opened as analog dup; reset it once */
119 - snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
120 + cleanup_dig_out_stream(codec, mout->dig_out_nid);
121 mout->dig_out_used = HDA_DIG_EXCLUSIVE;
122 mutex_unlock(&codec->spdif_mutex);
123 return 0;
124 @@ -2697,7 +2729,7 @@ int snd_hda_multi_out_analog_prepare(str
125 stream_tag, format);
126 } else {
127 mout->dig_out_used = 0;
128 - snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
129 + cleanup_dig_out_stream(codec, mout->dig_out_nid);
130 }
131 }
132 mutex_unlock(&codec->spdif_mutex);
133 @@ -2748,7 +2780,7 @@ int snd_hda_multi_out_analog_cleanup(str
134 mout->extra_out_nid[i]);
135 mutex_lock(&codec->spdif_mutex);
136 if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
137 - snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
138 + cleanup_dig_out_stream(codec, mout->dig_out_nid);
139 mout->dig_out_used = 0;
140 }
141 mutex_unlock(&codec->spdif_mutex);
142 --- a/sound/pci/hda/hda_codec.h
143 +++ b/sound/pci/hda/hda_codec.h
144 @@ -90,6 +90,14 @@ enum {
145 #define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c
146 /* f20: AFG/MFG */
147 #define AC_VERB_GET_SUBSYSTEM_ID 0x0f20
148 +#define AC_VERB_GET_CVT_CHAN_COUNT 0x0f2d
149 +#define AC_VERB_GET_HDMI_DIP_SIZE 0x0f2e
150 +#define AC_VERB_GET_HDMI_ELDD 0x0f2f
151 +#define AC_VERB_GET_HDMI_DIP_INDEX 0x0f30
152 +#define AC_VERB_GET_HDMI_DIP_DATA 0x0f31
153 +#define AC_VERB_GET_HDMI_DIP_XMIT 0x0f32
154 +#define AC_VERB_GET_HDMI_CP_CTRL 0x0f33
155 +#define AC_VERB_GET_HDMI_CHAN_SLOT 0x0f34
156
157 /*
158 * SET verbs
159 @@ -121,7 +129,14 @@ enum {
160 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d
161 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e
162 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f
163 +#define AC_VERB_SET_EAPD 0x788
164 #define AC_VERB_SET_CODEC_RESET 0x7ff
165 +#define AC_VERB_SET_CVT_CHAN_COUNT 0x72d
166 +#define AC_VERB_SET_HDMI_DIP_INDEX 0x730
167 +#define AC_VERB_SET_HDMI_DIP_DATA 0x731
168 +#define AC_VERB_SET_HDMI_DIP_XMIT 0x732
169 +#define AC_VERB_SET_HDMI_CP_CTRL 0x733
170 +#define AC_VERB_SET_HDMI_CHAN_SLOT 0x734
171
172 /*
173 * Parameter IDs
174 @@ -143,6 +158,7 @@ enum {
175 #define AC_PAR_GPIO_CAP 0x11
176 #define AC_PAR_AMP_OUT_CAP 0x12
177 #define AC_PAR_VOL_KNB_CAP 0x13
178 +#define AC_PAR_HDMI_LPCM_CAP 0x20
179
180 /*
181 * AC_VERB_PARAMETERS results (32bit)
182 @@ -171,6 +187,8 @@ enum {
183 #define AC_WCAP_DIGITAL (1<<9) /* digital I/O */
184 #define AC_WCAP_POWER (1<<10) /* power control */
185 #define AC_WCAP_LR_SWAP (1<<11) /* L/R swap */
186 +#define AC_WCAP_CP_CAPS (1<<12) /* content protection */
187 +#define AC_WCAP_CHAN_CNT_EXT (7<<13) /* channel count ext */
188 #define AC_WCAP_DELAY (0xf<<16)
189 #define AC_WCAP_DELAY_SHIFT 16
190 #define AC_WCAP_TYPE (0xf<<20)
191 @@ -206,9 +224,20 @@ enum {
192 /* Input converter SDI select */
193 #define AC_SDI_SELECT (0xf<<0)
194
195 -/* Unsolicited response */
196 +/* Unsolicited response control */
197 #define AC_UNSOL_TAG (0x3f<<0)
198 #define AC_UNSOL_ENABLED (1<<7)
199 +#define AC_USRSP_EN AC_UNSOL_ENABLED
200 +
201 +/* Unsolicited responses */
202 +#define AC_UNSOL_RES_TAG (0x3f<<26)
203 +#define AC_UNSOL_RES_TAG_SHIFT 26
204 +#define AC_UNSOL_RES_SUBTAG (0x1f<<21)
205 +#define AC_UNSOL_RES_SUBTAG_SHIFT 21
206 +#define AC_UNSOL_RES_ELDV (1<<1) /* ELD Data valid (for HDMI) */
207 +#define AC_UNSOL_RES_PD (1<<0) /* pinsense detect */
208 +#define AC_UNSOL_RES_CP_STATE (1<<1) /* content protection */
209 +#define AC_UNSOL_RES_CP_READY (1<<0) /* content protection */
210
211 /* Pin widget capabilies */
212 #define AC_PINCAP_IMP_SENSE (1<<0) /* impedance sense capable */
213 @@ -222,6 +251,10 @@ enum {
214 * but is marked reserved in the Intel HDA specification.
215 */
216 #define AC_PINCAP_LR_SWAP (1<<7) /* L/R swap */
217 +/* Note: The same bit as LR_SWAP is newly defined as HDMI capability
218 + * in HD-audio specification
219 + */
220 +#define AC_PINCAP_HDMI (1<<7) /* HDMI pin */
221 #define AC_PINCAP_VREF (0x37<<8)
222 #define AC_PINCAP_VREF_SHIFT 8
223 #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */
224 @@ -272,6 +305,22 @@ enum {
225 #define AC_KNBCAP_NUM_STEPS (0x7f<<0)
226 #define AC_KNBCAP_DELTA (1<<7)
227
228 +/* HDMI LPCM capabilities */
229 +#define AC_LPCMCAP_48K_CP_CHNS (0x0f<<0) /* max channels w/ CP-on */
230 +#define AC_LPCMCAP_48K_NO_CHNS (0x0f<<4) /* max channels w/o CP-on */
231 +#define AC_LPCMCAP_48K_20BIT (1<<8) /* 20b bitrate supported */
232 +#define AC_LPCMCAP_48K_24BIT (1<<9) /* 24b bitrate supported */
233 +#define AC_LPCMCAP_96K_CP_CHNS (0x0f<<10) /* max channels w/ CP-on */
234 +#define AC_LPCMCAP_96K_NO_CHNS (0x0f<<14) /* max channels w/o CP-on */
235 +#define AC_LPCMCAP_96K_20BIT (1<<18) /* 20b bitrate supported */
236 +#define AC_LPCMCAP_96K_24BIT (1<<19) /* 24b bitrate supported */
237 +#define AC_LPCMCAP_192K_CP_CHNS (0x0f<<20) /* max channels w/ CP-on */
238 +#define AC_LPCMCAP_192K_NO_CHNS (0x0f<<24) /* max channels w/o CP-on */
239 +#define AC_LPCMCAP_192K_20BIT (1<<28) /* 20b bitrate supported */
240 +#define AC_LPCMCAP_192K_24BIT (1<<29) /* 24b bitrate supported */
241 +#define AC_LPCMCAP_44K (1<<30) /* 44.1kHz support */
242 +#define AC_LPCMCAP_44K_MS (1<<31) /* 44.1kHz-multiplies support */
243 +
244 /*
245 * Control Parameters
246 */
247 @@ -317,18 +366,44 @@ enum {
248 #define AC_PINCTL_OUT_EN (1<<6)
249 #define AC_PINCTL_HP_EN (1<<7)
250
251 -/* Unsolicited response - 8bit */
252 -#define AC_USRSP_EN (1<<7)
253 -
254 /* Pin sense - 32bit */
255 #define AC_PINSENSE_IMPEDANCE_MASK (0x7fffffff)
256 #define AC_PINSENSE_PRESENCE (1<<31)
257 +#define AC_PINSENSE_ELDV (1<<30) /* ELD valid (HDMI) */
258
259 /* EAPD/BTL enable - 32bit */
260 #define AC_EAPDBTL_BALANCED (1<<0)
261 #define AC_EAPDBTL_EAPD (1<<1)
262 #define AC_EAPDBTL_LR_SWAP (1<<2)
263
264 +/* HDMI ELD data */
265 +#define AC_ELDD_ELD_VALID (1<<31)
266 +#define AC_ELDD_ELD_DATA 0xff
267 +
268 +/* HDMI DIP size */
269 +#define AC_DIPSIZE_ELD_BUF (1<<3) /* ELD buf size of packet size */
270 +#define AC_DIPSIZE_PACK_IDX (0x07<<0) /* packet index */
271 +
272 +/* HDMI DIP index */
273 +#define AC_DIPIDX_PACK_IDX (0x07<<5) /* packet idnex */
274 +#define AC_DIPIDX_BYTE_IDX (0x1f<<0) /* byte index */
275 +
276 +/* HDMI DIP xmit (transmit) control */
277 +#define AC_DIPXMIT_MASK (0x3<<6)
278 +#define AC_DIPXMIT_DISABLE (0x0<<6) /* disable xmit */
279 +#define AC_DIPXMIT_ONCE (0x2<<6) /* xmit once then disable */
280 +#define AC_DIPXMIT_BEST (0x3<<6) /* best effort */
281 +
282 +/* HDMI content protection (CP) control */
283 +#define AC_CPCTRL_CES (1<<9) /* current encryption state */
284 +#define AC_CPCTRL_READY (1<<8) /* ready bit */
285 +#define AC_CPCTRL_SUBTAG (0x1f<<3) /* subtag for unsol-resp */
286 +#define AC_CPCTRL_STATE (3<<0) /* current CP request state */
287 +
288 +/* Converter channel <-> HDMI slot mapping */
289 +#define AC_CVTMAP_HDMI_SLOT (0xf<<0) /* HDMI slot number */
290 +#define AC_CVTMAP_CHAN (0xf<<4) /* converter channel number */
291 +
292 /* configuration default - 32bit */
293 #define AC_DEFCFG_SEQUENCE (0xf<<0)
294 #define AC_DEFCFG_DEF_ASSOC (0xf<<4)
295 @@ -650,9 +725,15 @@ struct hda_codec {
296 unsigned int spdif_status; /* IEC958 status bits */
297 unsigned short spdif_ctls; /* SPDIF control bits */
298 unsigned int spdif_in_enable; /* SPDIF input enable? */
299 + hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
300
301 struct snd_hwdep *hwdep; /* assigned hwdep device */
302
303 + /* misc flags */
304 + unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each
305 + * status change
306 + * (e.g. Realtek codecs)
307 + */
308 #ifdef CONFIG_SND_HDA_POWER_SAVE
309 unsigned int power_on :1; /* current (global) power-state */
310 unsigned int power_transition :1; /* power-state in transition */
311 --- a/sound/pci/hda/hda_local.h
312 +++ b/sound/pci/hda/hda_local.h
313 @@ -368,12 +368,15 @@ int snd_hda_parse_pin_def_config(struct
314 #define AMP_OUT_UNMUTE 0xb000
315 #define AMP_OUT_ZERO 0xb000
316 /* pinctl values */
317 -#define PIN_IN 0x20
318 -#define PIN_VREF80 0x24
319 -#define PIN_VREF50 0x21
320 -#define PIN_OUT 0x40
321 -#define PIN_HP 0xc0
322 -#define PIN_HP_AMP 0x80
323 +#define PIN_IN (AC_PINCTL_IN_EN)
324 +#define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ)
325 +#define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50)
326 +#define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD)
327 +#define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80)
328 +#define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100)
329 +#define PIN_OUT (AC_PINCTL_OUT_EN)
330 +#define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
331 +#define PIN_HP_AMP (AC_PINCTL_HP_EN)
332
333 /*
334 * get widget capabilities