aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorWei Ni <wni@nvidia.com>2010-03-03 02:11:40 -0500
committerTakashi Iwai <tiwai@suse.de>2010-03-04 09:54:12 -0500
commit25045705d4053925a617ed71c5e4b6888e468765 (patch)
treea2d0d9fb458e6ec8b8126439694e75ed4141a603 /sound
parent7445dfc159f90b4bc82fd7d898b53d74520e2f83 (diff)
ALSA: hda - Support NVIDIA MCP89 and GT21x hdmi audio
Support nvidia MCP89 and GT21x 8ch hdmi audio. Add some eld support. Signed-off-by: Wei Ni <wni@nvidia.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/Kconfig2
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/patch_nvhdmi.c1038
3 files changed, 990 insertions, 52 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 556cff937be7..567348b05b5a 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI
157 157
158config SND_HDA_ELD 158config SND_HDA_ELD
159 def_bool y 159 def_bool y
160 depends on SND_HDA_CODEC_INTELHDMI 160 depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
161 161
162config SND_HDA_CODEC_CIRRUS 162config SND_HDA_CODEC_CIRRUS
163 bool "Build Cirrus Logic codec support" 163 bool "Build Cirrus Logic codec support"
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 315a1c4f8998..199f4405b3ad 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -17,7 +17,7 @@ snd-hda-codec-cirrus-objs := patch_cirrus.o
17snd-hda-codec-ca0110-objs := patch_ca0110.o 17snd-hda-codec-ca0110-objs := patch_ca0110.o
18snd-hda-codec-conexant-objs := patch_conexant.o 18snd-hda-codec-conexant-objs := patch_conexant.o
19snd-hda-codec-via-objs := patch_via.o 19snd-hda-codec-via-objs := patch_via.o
20snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o 20snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o hda_eld.o
21snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o 21snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o
22 22
23# common driver 23# common driver
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 6afdab09bab7..1c774f942407 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -32,10 +32,11 @@
32/* define below to restrict the supported rates and formats */ 32/* define below to restrict the supported rates and formats */
33/* #define LIMITED_RATE_FMT_SUPPORT */ 33/* #define LIMITED_RATE_FMT_SUPPORT */
34 34
35struct nvhdmi_spec { 35enum HDACodec {
36 struct hda_multi_out multiout; 36 HDA_CODEC_NVIDIA_MCP7X,
37 37 HDA_CODEC_NVIDIA_MCP89,
38 struct hda_pcm pcm_rec; 38 HDA_CODEC_NVIDIA_GT21X,
39 HDA_CODEC_INVALID
39}; 40};
40 41
41#define Nv_VERB_SET_Channel_Allocation 0xF79 42#define Nv_VERB_SET_Channel_Allocation 0xF79
@@ -43,15 +44,18 @@ struct nvhdmi_spec {
43#define Nv_VERB_SET_Audio_Protection_On 0xF98 44#define Nv_VERB_SET_Audio_Protection_On 0xF98
44#define Nv_VERB_SET_Audio_Protection_Off 0xF99 45#define Nv_VERB_SET_Audio_Protection_Off 0xF99
45 46
46#define Nv_Master_Convert_nid 0x04 47#define nvhdmi_master_con_nid_7x 0x04
47#define Nv_Master_Pin_nid 0x05 48#define nvhdmi_master_pin_nid_7x 0x05
48 49
49static hda_nid_t nvhdmi_convert_nids[4] = { 50#define nvhdmi_master_con_nid_89 0x04
51#define nvhdmi_master_pin_nid_89 0x05
52
53static hda_nid_t nvhdmi_con_nids_7x[4] = {
50 /*front, rear, clfe, rear_surr */ 54 /*front, rear, clfe, rear_surr */
51 0x6, 0x8, 0xa, 0xc, 55 0x6, 0x8, 0xa, 0xc,
52}; 56};
53 57
54static struct hda_verb nvhdmi_basic_init[] = { 58static struct hda_verb nvhdmi_basic_init_7x[] = {
55 /* set audio protect on */ 59 /* set audio protect on */
56 { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, 60 { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
57 /* enable digital output on pin widget */ 61 /* enable digital output on pin widget */
@@ -79,6 +83,796 @@ static struct hda_verb nvhdmi_basic_init[] = {
79 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) 83 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
80#endif 84#endif
81 85
86#define NVIDIA_89_HDMI_CVTS 1
87#define NVIDIA_89_HDMI_PINS 1
88
89static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = {
90 "NVIDIA HDMI",
91};
92
93struct nvhdmi_spec {
94 int num_cvts;
95 int num_pins;
96 hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1]; /* audio sources */
97 hda_nid_t pin[NVIDIA_89_HDMI_PINS+1]; /* audio sinks */
98 hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1];
99 struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS];
100 struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS];
101 struct hda_multi_out multiout;
102 unsigned int codec_type;
103};
104
105struct hdmi_audio_infoframe {
106 u8 type; /* 0x84 */
107 u8 ver; /* 0x01 */
108 u8 len; /* 0x0a */
109
110 u8 checksum; /* PB0 */
111 u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
112 u8 SS01_SF24;
113 u8 CXT04;
114 u8 CA;
115 u8 LFEPBL01_LSV36_DM_INH7;
116};
117
118/*
119 * CEA speaker placement:
120 *
121 * FLH FCH FRH
122 * FLW FL FLC FC FRC FR FRW
123 *
124 * LFE
125 * TC
126 *
127 * RL RLC RC RRC RR
128 *
129 * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
130 * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
131 */
132enum cea_speaker_placement {
133 FL = (1 << 0), /* Front Left */
134 FC = (1 << 1), /* Front Center */
135 FR = (1 << 2), /* Front Right */
136 FLC = (1 << 3), /* Front Left Center */
137 FRC = (1 << 4), /* Front Right Center */
138 RL = (1 << 5), /* Rear Left */
139 RC = (1 << 6), /* Rear Center */
140 RR = (1 << 7), /* Rear Right */
141 RLC = (1 << 8), /* Rear Left Center */
142 RRC = (1 << 9), /* Rear Right Center */
143 LFE = (1 << 10), /* Low Frequency Effect */
144 FLW = (1 << 11), /* Front Left Wide */
145 FRW = (1 << 12), /* Front Right Wide */
146 FLH = (1 << 13), /* Front Left High */
147 FCH = (1 << 14), /* Front Center High */
148 FRH = (1 << 15), /* Front Right High */
149 TC = (1 << 16), /* Top Center */
150};
151
152/*
153 * ELD SA bits in the CEA Speaker Allocation data block
154 */
155static int eld_speaker_allocation_bits[] = {
156 [0] = FL | FR,
157 [1] = LFE,
158 [2] = FC,
159 [3] = RL | RR,
160 [4] = RC,
161 [5] = FLC | FRC,
162 [6] = RLC | RRC,
163 /* the following are not defined in ELD yet */
164 [7] = FLW | FRW,
165 [8] = FLH | FRH,
166 [9] = TC,
167 [10] = FCH,
168};
169
170struct cea_channel_speaker_allocation {
171 int ca_index;
172 int speakers[8];
173
174 /* derived values, just for convenience */
175 int channels;
176 int spk_mask;
177};
178
179/*
180 * ALSA sequence is:
181 *
182 * surround40 surround41 surround50 surround51 surround71
183 * ch0 front left = = = =
184 * ch1 front right = = = =
185 * ch2 rear left = = = =
186 * ch3 rear right = = = =
187 * ch4 LFE center center center
188 * ch5 LFE LFE
189 * ch6 side left
190 * ch7 side right
191 *
192 * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
193 */
194static int hdmi_channel_mapping[0x32][8] = {
195 /* stereo */
196 [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
197 /* 2.1 */
198 [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
199 /* Dolby Surround */
200 [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
201 /* surround40 */
202 [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
203 /* 4ch */
204 [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
205 /* surround41 */
206 [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
207 /* surround50 */
208 [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
209 /* surround51 */
210 [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
211 /* 7.1 */
212 [0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
213};
214
215/*
216 * This is an ordered list!
217 *
218 * The preceding ones have better chances to be selected by
219 * hdmi_setup_channel_allocation().
220 */
221static struct cea_channel_speaker_allocation channel_allocations[] = {
222/* channel: 7 6 5 4 3 2 1 0 */
223{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
224 /* 2.1 */
225{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
226 /* Dolby Surround */
227{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
228 /* surround40 */
229{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
230 /* surround41 */
231{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
232 /* surround50 */
233{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
234 /* surround51 */
235{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
236 /* 6.1 */
237{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
238 /* surround71 */
239{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
240
241{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
242{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
243{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
244{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
245{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
246{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
247{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
248{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
249{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
250{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
251{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
252{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
253{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
254{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
255{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
256{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
257{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
258{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
259{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
260{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
261{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
262{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
263{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
264{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
265{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
266{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
267{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
268{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
269{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
270{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
271{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
272{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
273{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
274{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
275{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
276{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
277{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
278{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
279{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
280{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
281{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
282};
283
284/*
285 * HDA/HDMI auto parsing
286 */
287
288static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
289{
290 int i;
291
292 for (i = 0; nids[i]; i++)
293 if (nids[i] == nid)
294 return i;
295
296 snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
297 return -EINVAL;
298}
299
300static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
301{
302 struct nvhdmi_spec *spec = codec->spec;
303 hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
304 int conn_len, curr;
305 int index;
306
307 if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
308 snd_printk(KERN_WARNING
309 "HDMI: pin %d wcaps %#x "
310 "does not support connection list\n",
311 pin_nid, get_wcaps(codec, pin_nid));
312 return -EINVAL;
313 }
314
315 conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
316 HDA_MAX_CONNECTIONS);
317 if (conn_len > 1)
318 curr = snd_hda_codec_read(codec, pin_nid, 0,
319 AC_VERB_GET_CONNECT_SEL, 0);
320 else
321 curr = 0;
322
323 index = hda_node_index(spec->pin, pin_nid);
324 if (index < 0)
325 return -EINVAL;
326
327 spec->pin_cvt[index] = conn_list[curr];
328
329 return 0;
330}
331
332static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
333 struct hdmi_eld *eld)
334{
335 if (!snd_hdmi_get_eld(eld, codec, pin_nid))
336 snd_hdmi_show_eld(eld);
337}
338
339static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
340 struct hdmi_eld *eld)
341{
342 int present = snd_hda_pin_sense(codec, pin_nid);
343
344 eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
345 eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
346
347 if (present & AC_PINSENSE_ELDV)
348 hdmi_get_show_eld(codec, pin_nid, eld);
349}
350
351static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
352{
353 struct nvhdmi_spec *spec = codec->spec;
354
355 if (spec->num_pins >= NVIDIA_89_HDMI_PINS) {
356 snd_printk(KERN_WARNING
357 "HDMI: no space for pin %d \n", pin_nid);
358 return -EINVAL;
359 }
360
361 hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
362
363 spec->pin[spec->num_pins] = pin_nid;
364 spec->num_pins++;
365
366 /*
367 * It is assumed that converter nodes come first in the node list and
368 * hence have been registered and usable now.
369 */
370 return nvhdmi_read_pin_conn(codec, pin_nid);
371}
372
373static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
374{
375 struct nvhdmi_spec *spec = codec->spec;
376
377 if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) {
378 snd_printk(KERN_WARNING
379 "HDMI: no space for converter %d \n", nid);
380 return -EINVAL;
381 }
382
383 spec->cvt[spec->num_cvts] = nid;
384 spec->num_cvts++;
385
386 return 0;
387}
388
389
390static int nvhdmi_parse_codec(struct hda_codec *codec)
391{
392 hda_nid_t nid;
393 int i, nodes;
394
395 nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
396 if (!nid || nodes < 0) {
397 snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
398 return -EINVAL;
399 }
400
401 for (i = 0; i < nodes; i++, nid++) {
402 unsigned int caps;
403 unsigned int type;
404
405 caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
406 type = get_wcaps_type(caps);
407
408 if (!(caps & AC_WCAP_DIGITAL))
409 continue;
410
411 switch (type) {
412 case AC_WID_AUD_OUT:
413 if (nvhdmi_add_cvt(codec, nid) < 0)
414 return -EINVAL;
415 break;
416 case AC_WID_PIN:
417 caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
418 if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
419 continue;
420 if (nvhdmi_add_pin(codec, nid) < 0)
421 return -EINVAL;
422 break;
423 }
424 }
425
426 /*
427 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
428 * can be lost and presence sense verb will become inaccurate if the
429 * HDA link is powered off at hot plug or hw initialization time.
430 */
431#ifdef CONFIG_SND_HDA_POWER_SAVE
432 if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
433 AC_PWRST_EPSS))
434 codec->bus->power_keep_link_on = 1;
435#endif
436
437 return 0;
438}
439
440/*
441 * HDMI routines
442 */
443
444#ifdef BE_PARANOID
445static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
446 int *packet_index, int *byte_index)
447{
448 int val;
449
450 val = snd_hda_codec_read(codec, pin_nid, 0,
451 AC_VERB_GET_HDMI_DIP_INDEX, 0);
452
453 *packet_index = val >> 5;
454 *byte_index = val & 0x1f;
455}
456#endif
457
458static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
459 int packet_index, int byte_index)
460{
461 int val;
462
463 val = (packet_index << 5) | (byte_index & 0x1f);
464
465 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
466}
467
468static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
469 unsigned char val)
470{
471 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
472}
473
474static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
475{
476 /* Unmute */
477 if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
478 snd_hda_codec_write(codec, pin_nid, 0,
479 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
480 /* Enable pin out */
481 snd_hda_codec_write(codec, pin_nid, 0,
482 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
483}
484
485/*
486 * Enable Audio InfoFrame Transmission
487 */
488static void hdmi_start_infoframe_trans(struct hda_codec *codec,
489 hda_nid_t pin_nid)
490{
491 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
492 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
493 AC_DIPXMIT_BEST);
494}
495
496/*
497 * Disable Audio InfoFrame Transmission
498 */
499static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
500 hda_nid_t pin_nid)
501{
502 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
503 snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
504 AC_DIPXMIT_DISABLE);
505}
506
507static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
508{
509 return 1 + snd_hda_codec_read(codec, nid, 0,
510 AC_VERB_GET_CVT_CHAN_COUNT, 0);
511}
512
513static void hdmi_set_channel_count(struct hda_codec *codec,
514 hda_nid_t nid, int chs)
515{
516 if (chs != hdmi_get_channel_count(codec, nid))
517 snd_hda_codec_write(codec, nid, 0,
518 AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
519}
520
521static void hdmi_debug_channel_mapping(struct hda_codec *codec,
522 hda_nid_t pin_nid)
523{
524#ifdef CONFIG_SND_DEBUG_VERBOSE
525 int i;
526 int slot;
527
528 for (i = 0; i < 8; i++) {
529 slot = snd_hda_codec_read(codec, pin_nid, 0,
530 AC_VERB_GET_HDMI_CHAN_SLOT, i);
531 printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
532 slot >> 4, slot & 0xf);
533 }
534#endif
535}
536
537
538/*
539 * Audio InfoFrame routines
540 */
541
542static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
543{
544#ifdef CONFIG_SND_DEBUG_VERBOSE
545 int i;
546 int size;
547
548 size = snd_hdmi_get_eld_size(codec, pin_nid);
549 printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
550
551 for (i = 0; i < 8; i++) {
552 size = snd_hda_codec_read(codec, pin_nid, 0,
553 AC_VERB_GET_HDMI_DIP_SIZE, i);
554 printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
555 }
556#endif
557}
558
559static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
560{
561#ifdef BE_PARANOID
562 int i, j;
563 int size;
564 int pi, bi;
565 for (i = 0; i < 8; i++) {
566 size = snd_hda_codec_read(codec, pin_nid, 0,
567 AC_VERB_GET_HDMI_DIP_SIZE, i);
568 if (size == 0)
569 continue;
570
571 hdmi_set_dip_index(codec, pin_nid, i, 0x0);
572 for (j = 1; j < 1000; j++) {
573 hdmi_write_dip_byte(codec, pin_nid, 0x0);
574 hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
575 if (pi != i)
576 snd_printd(KERN_INFO "dip index %d: %d != %d\n",
577 bi, pi, i);
578 if (bi == 0) /* byte index wrapped around */
579 break;
580 }
581 snd_printd(KERN_INFO
582 "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
583 i, size, j);
584 }
585#endif
586}
587
588static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
589{
590 ai->checksum = 0;
591}
592
593static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
594 hda_nid_t pin_nid,
595 struct hdmi_audio_infoframe *ai)
596{
597 u8 *bytes = (u8 *)ai;
598 int i;
599
600 hdmi_debug_dip_size(codec, pin_nid);
601 hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
602
603 hdmi_checksum_audio_infoframe(ai);
604
605 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
606 for (i = 0; i < sizeof(*ai); i++)
607 hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
608}
609
610/*
611 * Compute derived values in channel_allocations[].
612 */
613static void init_channel_allocations(void)
614{
615 int i, j;
616 struct cea_channel_speaker_allocation *p;
617
618 for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
619 p = channel_allocations + i;
620 p->channels = 0;
621 p->spk_mask = 0;
622 for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
623 if (p->speakers[j]) {
624 p->channels++;
625 p->spk_mask |= p->speakers[j];
626 }
627 }
628}
629
630/*
631 * The transformation takes two steps:
632 *
633 * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
634 * spk_mask => (channel_allocations[]) => ai->CA
635 *
636 * TODO: it could select the wrong CA from multiple candidates.
637*/
638static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
639 struct hdmi_audio_infoframe *ai)
640{
641 struct nvhdmi_spec *spec = codec->spec;
642 struct hdmi_eld *eld;
643 int i;
644 int spk_mask = 0;
645 int channels = 1 + (ai->CC02_CT47 & 0x7);
646 char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
647
648 /*
649 * CA defaults to 0 for basic stereo audio
650 */
651 if (channels <= 2)
652 return 0;
653
654 i = hda_node_index(spec->pin_cvt, nid);
655 if (i < 0)
656 return 0;
657 eld = &spec->sink_eld[i];
658
659 /*
660 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
661 * in console or for audio devices. Assume the highest speakers
662 * configuration, to _not_ prohibit multi-channel audio playback.
663 */
664 if (!eld->spk_alloc)
665 eld->spk_alloc = 0xffff;
666
667 /*
668 * expand ELD's speaker allocation mask
669 *
670 * ELD tells the speaker mask in a compact(paired) form,
671 * expand ELD's notions to match the ones used by Audio InfoFrame.
672 */
673 for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
674 if (eld->spk_alloc & (1 << i))
675 spk_mask |= eld_speaker_allocation_bits[i];
676 }
677
678 /* search for the first working match in the CA table */
679 for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
680 if (channels == channel_allocations[i].channels &&
681 (spk_mask & channel_allocations[i].spk_mask) ==
682 channel_allocations[i].spk_mask) {
683 ai->CA = channel_allocations[i].ca_index;
684 break;
685 }
686 }
687
688 snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
689 snd_printdd(KERN_INFO
690 "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
691 ai->CA, channels, buf);
692
693 return ai->CA;
694}
695
696static void hdmi_setup_channel_mapping(struct hda_codec *codec,
697 hda_nid_t pin_nid,
698 struct hdmi_audio_infoframe *ai)
699{
700 int i;
701 int ca = ai->CA;
702 int err;
703
704 if (hdmi_channel_mapping[ca][1] == 0) {
705 for (i = 0; i < channel_allocations[ca].channels; i++)
706 hdmi_channel_mapping[ca][i] = i | (i << 4);
707 for (; i < 8; i++)
708 hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
709 }
710
711 for (i = 0; i < 8; i++) {
712 err = snd_hda_codec_write(codec, pin_nid, 0,
713 AC_VERB_SET_HDMI_CHAN_SLOT,
714 hdmi_channel_mapping[ca][i]);
715 if (err) {
716 snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
717 break;
718 }
719 }
720
721 hdmi_debug_channel_mapping(codec, pin_nid);
722}
723
724static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
725 struct hdmi_audio_infoframe *ai)
726{
727 u8 *bytes = (u8 *)ai;
728 u8 val;
729 int i;
730
731 if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
732 != AC_DIPXMIT_BEST)
733 return false;
734
735 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
736 for (i = 0; i < sizeof(*ai); i++) {
737 val = snd_hda_codec_read(codec, pin_nid, 0,
738 AC_VERB_GET_HDMI_DIP_DATA, 0);
739 if (val != bytes[i])
740 return false;
741 }
742
743 return true;
744}
745
746static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
747 struct snd_pcm_substream *substream)
748{
749 struct nvhdmi_spec *spec = codec->spec;
750 hda_nid_t pin_nid;
751 int i;
752 struct hdmi_audio_infoframe ai = {
753 .type = 0x84,
754 .ver = 0x01,
755 .len = 0x0a,
756 .CC02_CT47 = substream->runtime->channels - 1,
757 };
758
759 hdmi_setup_channel_allocation(codec, nid, &ai);
760
761 for (i = 0; i < spec->num_pins; i++) {
762 if (spec->pin_cvt[i] != nid)
763 continue;
764 if (!spec->sink_eld[i].monitor_present)
765 continue;
766
767 pin_nid = spec->pin[i];
768 if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
769 hdmi_setup_channel_mapping(codec, pin_nid, &ai);
770 hdmi_stop_infoframe_trans(codec, pin_nid);
771 hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
772 hdmi_start_infoframe_trans(codec, pin_nid);
773 }
774 }
775}
776
777/*
778 * Unsolicited events
779 */
780
781static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
782{
783 struct nvhdmi_spec *spec = codec->spec;
784 int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
785 int pind = !!(res & AC_UNSOL_RES_PD);
786 int eldv = !!(res & AC_UNSOL_RES_ELDV);
787 int index;
788
789 printk(KERN_INFO
790 "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
791 tag, pind, eldv);
792
793 index = hda_node_index(spec->pin, tag);
794 if (index < 0)
795 return;
796
797 spec->sink_eld[index].monitor_present = pind;
798 spec->sink_eld[index].eld_valid = eldv;
799
800 if (eldv) {
801 spec->sink_eld[index].monitor_present = 1;
802 hdmi_get_show_eld(codec, spec->pin[index],
803 &spec->sink_eld[index]);
804 /* TODO: do real things about ELD */
805 }
806}
807
808static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
809{
810 int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
811 int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
812 int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
813 int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
814
815 printk(KERN_INFO
816 "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
817 tag,
818 subtag,
819 cp_state,
820 cp_ready);
821
822 /* TODO */
823 if (cp_state)
824 ;
825 if (cp_ready)
826 ;
827}
828
829static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res)
830{
831 struct nvhdmi_spec *spec = codec->spec;
832 int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
833 int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
834
835 if (hda_node_index(spec->pin, tag) < 0) {
836 snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
837 return;
838 }
839
840 if (subtag == 0)
841 hdmi_intrinsic_event(codec, res);
842 else
843 hdmi_non_intrinsic_event(codec, res);
844}
845
846/*
847 * Callbacks
848 */
849
850static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
851 u32 stream_tag, int format)
852{
853 int tag;
854 int fmt;
855
856 tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
857 fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
858
859 snd_printdd("hdmi_setup_stream: "
860 "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
861 nid,
862 tag == stream_tag ? "" : "new-",
863 stream_tag,
864 fmt == format ? "" : "new-",
865 format);
866
867 if (tag != stream_tag)
868 snd_hda_codec_write(codec, nid, 0,
869 AC_VERB_SET_CHANNEL_STREAMID,
870 stream_tag << 4);
871 if (fmt != format)
872 snd_hda_codec_write(codec, nid, 0,
873 AC_VERB_SET_STREAM_FORMAT, format);
874}
875
82/* 876/*
83 * Controls 877 * Controls
84 */ 878 */
@@ -86,20 +880,58 @@ static int nvhdmi_build_controls(struct hda_codec *codec)
86{ 880{
87 struct nvhdmi_spec *spec = codec->spec; 881 struct nvhdmi_spec *spec = codec->spec;
88 int err; 882 int err;
883 int i;
89 884
90 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); 885 if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
91 if (err < 0) 886 || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
92 return err; 887 for (i = 0; i < codec->num_pcms; i++) {
888 err = snd_hda_create_spdif_out_ctls(codec,
889 spec->cvt[i]);
890 if (err < 0)
891 return err;
892 }
893 } else {
894 err = snd_hda_create_spdif_out_ctls(codec,
895 spec->multiout.dig_out_nid);
896 if (err < 0)
897 return err;
898 }
93 899
94 return 0; 900 return 0;
95} 901}
96 902
97static int nvhdmi_init(struct hda_codec *codec) 903static int nvhdmi_init(struct hda_codec *codec)
98{ 904{
99 snd_hda_sequence_write(codec, nvhdmi_basic_init); 905 struct nvhdmi_spec *spec = codec->spec;
906 int i;
907 if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
908 || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
909 for (i = 0; spec->pin[i]; i++) {
910 hdmi_enable_output(codec, spec->pin[i]);
911 snd_hda_codec_write(codec, spec->pin[i], 0,
912 AC_VERB_SET_UNSOLICITED_ENABLE,
913 AC_USRSP_EN | spec->pin[i]);
914 }
915 } else {
916 snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
917 }
100 return 0; 918 return 0;
101} 919}
102 920
921static void nvhdmi_free(struct hda_codec *codec)
922{
923 struct nvhdmi_spec *spec = codec->spec;
924 int i;
925
926 if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
927 || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
928 for (i = 0; i < spec->num_pins; i++)
929 snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
930 }
931
932 kfree(spec);
933}
934
103/* 935/*
104 * Digital out 936 * Digital out
105 */ 937 */
@@ -111,21 +943,21 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
111 return snd_hda_multi_out_dig_open(codec, &spec->multiout); 943 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
112} 944}
113 945
114static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo, 946static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo,
115 struct hda_codec *codec, 947 struct hda_codec *codec,
116 struct snd_pcm_substream *substream) 948 struct snd_pcm_substream *substream)
117{ 949{
118 struct nvhdmi_spec *spec = codec->spec; 950 struct nvhdmi_spec *spec = codec->spec;
119 int i; 951 int i;
120 952
121 snd_hda_codec_write(codec, Nv_Master_Convert_nid, 953 snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
122 0, AC_VERB_SET_CHANNEL_STREAMID, 0); 954 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
123 for (i = 0; i < 4; i++) { 955 for (i = 0; i < 4; i++) {
124 /* set the stream id */ 956 /* set the stream id */
125 snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, 957 snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
126 AC_VERB_SET_CHANNEL_STREAMID, 0); 958 AC_VERB_SET_CHANNEL_STREAMID, 0);
127 /* set the stream format */ 959 /* set the stream format */
128 snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, 960 snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
129 AC_VERB_SET_STREAM_FORMAT, 0); 961 AC_VERB_SET_STREAM_FORMAT, 0);
130 } 962 }
131 963
@@ -140,6 +972,21 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
140 return snd_hda_multi_out_dig_close(codec, &spec->multiout); 972 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
141} 973}
142 974
975static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
976 struct hda_codec *codec,
977 unsigned int stream_tag,
978 unsigned int format,
979 struct snd_pcm_substream *substream)
980{
981 hdmi_set_channel_count(codec, hinfo->nid,
982 substream->runtime->channels);
983
984 hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
985
986 hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
987 return 0;
988}
989
143static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, 990static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
144 struct hda_codec *codec, 991 struct hda_codec *codec,
145 unsigned int stream_tag, 992 unsigned int stream_tag,
@@ -181,29 +1028,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
181 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ 1028 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
182 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) 1029 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
183 snd_hda_codec_write(codec, 1030 snd_hda_codec_write(codec,
184 Nv_Master_Convert_nid, 1031 nvhdmi_master_con_nid_7x,
185 0, 1032 0,
186 AC_VERB_SET_DIGI_CONVERT_1, 1033 AC_VERB_SET_DIGI_CONVERT_1,
187 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); 1034 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
188 1035
189 /* set the stream id */ 1036 /* set the stream id */
190 snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, 1037 snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
191 AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); 1038 AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
192 1039
193 /* set the stream format */ 1040 /* set the stream format */
194 snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, 1041 snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
195 AC_VERB_SET_STREAM_FORMAT, format); 1042 AC_VERB_SET_STREAM_FORMAT, format);
196 1043
197 /* turn on again (if needed) */ 1044 /* turn on again (if needed) */
198 /* enable and set the channel status audio/data flag */ 1045 /* enable and set the channel status audio/data flag */
199 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { 1046 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
200 snd_hda_codec_write(codec, 1047 snd_hda_codec_write(codec,
201 Nv_Master_Convert_nid, 1048 nvhdmi_master_con_nid_7x,
202 0, 1049 0,
203 AC_VERB_SET_DIGI_CONVERT_1, 1050 AC_VERB_SET_DIGI_CONVERT_1,
204 codec->spdif_ctls & 0xff); 1051 codec->spdif_ctls & 0xff);
205 snd_hda_codec_write(codec, 1052 snd_hda_codec_write(codec,
206 Nv_Master_Convert_nid, 1053 nvhdmi_master_con_nid_7x,
207 0, 1054 0,
208 AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); 1055 AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
209 } 1056 }
@@ -220,19 +1067,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
220 if (codec->spdif_status_reset && 1067 if (codec->spdif_status_reset &&
221 (codec->spdif_ctls & AC_DIG1_ENABLE)) 1068 (codec->spdif_ctls & AC_DIG1_ENABLE))
222 snd_hda_codec_write(codec, 1069 snd_hda_codec_write(codec,
223 nvhdmi_convert_nids[i], 1070 nvhdmi_con_nids_7x[i],
224 0, 1071 0,
225 AC_VERB_SET_DIGI_CONVERT_1, 1072 AC_VERB_SET_DIGI_CONVERT_1,
226 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); 1073 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
227 /* set the stream id */ 1074 /* set the stream id */
228 snd_hda_codec_write(codec, 1075 snd_hda_codec_write(codec,
229 nvhdmi_convert_nids[i], 1076 nvhdmi_con_nids_7x[i],
230 0, 1077 0,
231 AC_VERB_SET_CHANNEL_STREAMID, 1078 AC_VERB_SET_CHANNEL_STREAMID,
232 (stream_tag << 4) | channel_id); 1079 (stream_tag << 4) | channel_id);
233 /* set the stream format */ 1080 /* set the stream format */
234 snd_hda_codec_write(codec, 1081 snd_hda_codec_write(codec,
235 nvhdmi_convert_nids[i], 1082 nvhdmi_con_nids_7x[i],
236 0, 1083 0,
237 AC_VERB_SET_STREAM_FORMAT, 1084 AC_VERB_SET_STREAM_FORMAT,
238 format); 1085 format);
@@ -241,12 +1088,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
241 if (codec->spdif_status_reset && 1088 if (codec->spdif_status_reset &&
242 (codec->spdif_ctls & AC_DIG1_ENABLE)) { 1089 (codec->spdif_ctls & AC_DIG1_ENABLE)) {
243 snd_hda_codec_write(codec, 1090 snd_hda_codec_write(codec,
244 nvhdmi_convert_nids[i], 1091 nvhdmi_con_nids_7x[i],
245 0, 1092 0,
246 AC_VERB_SET_DIGI_CONVERT_1, 1093 AC_VERB_SET_DIGI_CONVERT_1,
247 codec->spdif_ctls & 0xff); 1094 codec->spdif_ctls & 0xff);
248 snd_hda_codec_write(codec, 1095 snd_hda_codec_write(codec,
249 nvhdmi_convert_nids[i], 1096 nvhdmi_con_nids_7x[i],
250 0, 1097 0,
251 AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); 1098 AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
252 } 1099 }
@@ -261,6 +1108,13 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
261 return 0; 1108 return 0;
262} 1109}
263 1110
1111static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
1112 struct hda_codec *codec,
1113 struct snd_pcm_substream *substream)
1114{
1115 return 0;
1116}
1117
264static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, 1118static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
265 struct hda_codec *codec, 1119 struct hda_codec *codec,
266 unsigned int stream_tag, 1120 unsigned int stream_tag,
@@ -272,17 +1126,29 @@ static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
272 format, substream); 1126 format, substream);
273} 1127}
274 1128
275static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = { 1129static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
1130 .substreams = 1,
1131 .channels_min = 2,
1132 .rates = SUPPORTED_RATES,
1133 .maxbps = SUPPORTED_MAXBPS,
1134 .formats = SUPPORTED_FORMATS,
1135 .ops = {
1136 .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
1137 .cleanup = nvhdmi_playback_pcm_cleanup,
1138 },
1139};
1140
1141static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = {
276 .substreams = 1, 1142 .substreams = 1,
277 .channels_min = 2, 1143 .channels_min = 2,
278 .channels_max = 8, 1144 .channels_max = 8,
279 .nid = Nv_Master_Convert_nid, 1145 .nid = nvhdmi_master_con_nid_7x,
280 .rates = SUPPORTED_RATES, 1146 .rates = SUPPORTED_RATES,
281 .maxbps = SUPPORTED_MAXBPS, 1147 .maxbps = SUPPORTED_MAXBPS,
282 .formats = SUPPORTED_FORMATS, 1148 .formats = SUPPORTED_FORMATS,
283 .ops = { 1149 .ops = {
284 .open = nvhdmi_dig_playback_pcm_open, 1150 .open = nvhdmi_dig_playback_pcm_open,
285 .close = nvhdmi_dig_playback_pcm_close_8ch, 1151 .close = nvhdmi_dig_playback_pcm_close_8ch_7x,
286 .prepare = nvhdmi_dig_playback_pcm_prepare_8ch 1152 .prepare = nvhdmi_dig_playback_pcm_prepare_8ch
287 }, 1153 },
288}; 1154};
@@ -291,7 +1157,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
291 .substreams = 1, 1157 .substreams = 1,
292 .channels_min = 2, 1158 .channels_min = 2,
293 .channels_max = 2, 1159 .channels_max = 2,
294 .nid = Nv_Master_Convert_nid, 1160 .nid = nvhdmi_master_con_nid_7x,
295 .rates = SUPPORTED_RATES, 1161 .rates = SUPPORTED_RATES,
296 .maxbps = SUPPORTED_MAXBPS, 1162 .maxbps = SUPPORTED_MAXBPS,
297 .formats = SUPPORTED_FORMATS, 1163 .formats = SUPPORTED_FORMATS,
@@ -302,10 +1168,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
302 }, 1168 },
303}; 1169};
304 1170
305static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) 1171static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
1172{
1173 struct nvhdmi_spec *spec = codec->spec;
1174 struct hda_pcm *info = spec->pcm_rec;
1175 int i;
1176
1177 codec->num_pcms = spec->num_cvts;
1178 codec->pcm_info = info;
1179
1180 for (i = 0; i < codec->num_pcms; i++, info++) {
1181 unsigned int chans;
1182
1183 chans = get_wcaps(codec, spec->cvt[i]);
1184 chans = get_wcaps_channels(chans);
1185
1186 info->name = nvhdmi_pcm_names[i];
1187 info->pcm_type = HDA_PCM_TYPE_HDMI;
1188 info->stream[SNDRV_PCM_STREAM_PLAYBACK]
1189 = nvhdmi_pcm_digital_playback_8ch_89;
1190 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
1191 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
1192 }
1193
1194 return 0;
1195}
1196
1197static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
306{ 1198{
307 struct nvhdmi_spec *spec = codec->spec; 1199 struct nvhdmi_spec *spec = codec->spec;
308 struct hda_pcm *info = &spec->pcm_rec; 1200 struct hda_pcm *info = spec->pcm_rec;
309 1201
310 codec->num_pcms = 1; 1202 codec->num_pcms = 1;
311 codec->pcm_info = info; 1203 codec->pcm_info = info;
@@ -313,7 +1205,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
313 info->name = "NVIDIA HDMI"; 1205 info->name = "NVIDIA HDMI";
314 info->pcm_type = HDA_PCM_TYPE_HDMI; 1206 info->pcm_type = HDA_PCM_TYPE_HDMI;
315 info->stream[SNDRV_PCM_STREAM_PLAYBACK] 1207 info->stream[SNDRV_PCM_STREAM_PLAYBACK]
316 = nvhdmi_pcm_digital_playback_8ch; 1208 = nvhdmi_pcm_digital_playback_8ch_7x;
317 1209
318 return 0; 1210 return 0;
319} 1211}
@@ -321,7 +1213,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
321static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) 1213static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
322{ 1214{
323 struct nvhdmi_spec *spec = codec->spec; 1215 struct nvhdmi_spec *spec = codec->spec;
324 struct hda_pcm *info = &spec->pcm_rec; 1216 struct hda_pcm *info = spec->pcm_rec;
325 1217
326 codec->num_pcms = 1; 1218 codec->num_pcms = 1;
327 codec->pcm_info = info; 1219 codec->pcm_info = info;
@@ -334,14 +1226,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
334 return 0; 1226 return 0;
335} 1227}
336 1228
337static void nvhdmi_free(struct hda_codec *codec) 1229static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
338{ 1230 .build_controls = nvhdmi_build_controls,
339 kfree(codec->spec); 1231 .build_pcms = nvhdmi_build_pcms_8ch_89,
340} 1232 .init = nvhdmi_init,
1233 .free = nvhdmi_free,
1234 .unsol_event = nvhdmi_unsol_event,
1235};
341 1236
342static struct hda_codec_ops nvhdmi_patch_ops_8ch = { 1237static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
343 .build_controls = nvhdmi_build_controls, 1238 .build_controls = nvhdmi_build_controls,
344 .build_pcms = nvhdmi_build_pcms_8ch, 1239 .build_pcms = nvhdmi_build_pcms_8ch_7x,
345 .init = nvhdmi_init, 1240 .init = nvhdmi_init,
346 .free = nvhdmi_free, 1241 .free = nvhdmi_free,
347}; 1242};
@@ -353,7 +1248,34 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
353 .free = nvhdmi_free, 1248 .free = nvhdmi_free,
354}; 1249};
355 1250
356static int patch_nvhdmi_8ch(struct hda_codec *codec) 1251static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
1252{
1253 struct nvhdmi_spec *spec;
1254 int i;
1255
1256 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1257 if (spec == NULL)
1258 return -ENOMEM;
1259
1260 codec->spec = spec;
1261 spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
1262
1263 if (nvhdmi_parse_codec(codec) < 0) {
1264 codec->spec = NULL;
1265 kfree(spec);
1266 return -EINVAL;
1267 }
1268 codec->patch_ops = nvhdmi_patch_ops_8ch_89;
1269
1270 for (i = 0; i < spec->num_pins; i++)
1271 snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
1272
1273 init_channel_allocations();
1274
1275 return 0;
1276}
1277
1278static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
357{ 1279{
358 struct nvhdmi_spec *spec; 1280 struct nvhdmi_spec *spec;
359 1281
@@ -365,9 +1287,10 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec)
365 1287
366 spec->multiout.num_dacs = 0; /* no analog */ 1288 spec->multiout.num_dacs = 0; /* no analog */
367 spec->multiout.max_channels = 8; 1289 spec->multiout.max_channels = 8;
368 spec->multiout.dig_out_nid = Nv_Master_Convert_nid; 1290 spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
1291 spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
369 1292
370 codec->patch_ops = nvhdmi_patch_ops_8ch; 1293 codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
371 1294
372 return 0; 1295 return 0;
373} 1296}
@@ -384,7 +1307,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
384 1307
385 spec->multiout.num_dacs = 0; /* no analog */ 1308 spec->multiout.num_dacs = 0; /* no analog */
386 spec->multiout.max_channels = 2; 1309 spec->multiout.max_channels = 2;
387 spec->multiout.dig_out_nid = Nv_Master_Convert_nid; 1310 spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
1311 spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
388 1312
389 codec->patch_ops = nvhdmi_patch_ops_2ch; 1313 codec->patch_ops = nvhdmi_patch_ops_2ch;
390 1314
@@ -395,13 +1319,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
395 * patch entries 1319 * patch entries
396 */ 1320 */
397static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { 1321static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
398 { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
399 { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
400 { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
401 { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
402 { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
403 { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, 1322 { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
404 { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, 1323 { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
1324 { .id = 0x10de0002, .name = "MCP77/78 HDMI",
1325 .patch = patch_nvhdmi_8ch_7x },
1326 { .id = 0x10de0003, .name = "MCP77/78 HDMI",
1327 .patch = patch_nvhdmi_8ch_7x },
1328 { .id = 0x10de0005, .name = "MCP77/78 HDMI",
1329 .patch = patch_nvhdmi_8ch_7x },
1330 { .id = 0x10de0006, .name = "MCP77/78 HDMI",
1331 .patch = patch_nvhdmi_8ch_7x },
1332 { .id = 0x10de0007, .name = "MCP79/7A HDMI",
1333 .patch = patch_nvhdmi_8ch_7x },
1334 { .id = 0x10de000c, .name = "MCP89 HDMI",
1335 .patch = patch_nvhdmi_8ch_89 },
1336 { .id = 0x10de000b, .name = "GT21x HDMI",
1337 .patch = patch_nvhdmi_8ch_89 },
1338 { .id = 0x10de000d, .name = "GT240 HDMI",
1339 .patch = patch_nvhdmi_8ch_89 },
405 {} /* terminator */ 1340 {} /* terminator */
406}; 1341};
407 1342
@@ -412,9 +1347,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006");
412MODULE_ALIAS("snd-hda-codec-id:10de0007"); 1347MODULE_ALIAS("snd-hda-codec-id:10de0007");
413MODULE_ALIAS("snd-hda-codec-id:10de0067"); 1348MODULE_ALIAS("snd-hda-codec-id:10de0067");
414MODULE_ALIAS("snd-hda-codec-id:10de8001"); 1349MODULE_ALIAS("snd-hda-codec-id:10de8001");
1350MODULE_ALIAS("snd-hda-codec-id:10de000c");
1351MODULE_ALIAS("snd-hda-codec-id:10de000b");
1352MODULE_ALIAS("snd-hda-codec-id:10de000d");
415 1353
416MODULE_LICENSE("GPL"); 1354MODULE_LICENSE("GPL");
417MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec"); 1355MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
418 1356
419static struct hda_codec_preset_list nvhdmi_list = { 1357static struct hda_codec_preset_list nvhdmi_list = {
420 .preset = snd_hda_preset_nvhdmi, 1358 .preset = snd_hda_preset_nvhdmi,