• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/sound/pci/hda/
1/*
2 *
3 *  patch_hdmi.c - routines for HDMI/DisplayPort codecs
4 *
5 *  Copyright(c) 2008-2010 Intel Corporation. All rights reserved.
6 *
7 *  Authors:
8 *			Wu Fengguang <wfg@linux.intel.com>
9 *
10 *  Maintained by:
11 *			Wu Fengguang <wfg@linux.intel.com>
12 *
13 *  This program is free software; you can redistribute it and/or modify it
14 *  under the terms of the GNU General Public License as published by the Free
15 *  Software Foundation; either version 2 of the License, or (at your option)
16 *  any later version.
17 *
18 *  This program is distributed in the hope that it will be useful, but
19 *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 *  for more details.
22 *
23 *  You should have received a copy of the GNU General Public License
24 *  along with this program; if not, write to the Free Software Foundation,
25 *  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26 */
27
28
29struct hdmi_spec {
30	int num_cvts;
31	int num_pins;
32	hda_nid_t cvt[MAX_HDMI_CVTS+1];  /* audio sources */
33	hda_nid_t pin[MAX_HDMI_PINS+1];  /* audio sinks */
34
35	/*
36	 * source connection for each pin
37	 */
38	hda_nid_t pin_cvt[MAX_HDMI_PINS+1];
39
40	/*
41	 * HDMI sink attached to each pin
42	 */
43	struct hdmi_eld sink_eld[MAX_HDMI_PINS];
44
45	/*
46	 * export one pcm per pipe
47	 */
48	struct hda_pcm	pcm_rec[MAX_HDMI_CVTS];
49	struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS];
50
51	/*
52	 * nvhdmi specific
53	 */
54	struct hda_multi_out multiout;
55	unsigned int codec_type;
56
57	/* misc flags */
58	/* PD bit indicates only the update, not the current state */
59	unsigned int old_pin_detect:1;
60};
61
62
63struct hdmi_audio_infoframe {
64	u8 type; /* 0x84 */
65	u8 ver;  /* 0x01 */
66	u8 len;  /* 0x0a */
67
68	u8 checksum;	/* PB0 */
69	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
70	u8 SS01_SF24;
71	u8 CXT04;
72	u8 CA;
73	u8 LFEPBL01_LSV36_DM_INH7;
74	u8 reserved[5];	/* PB6 - PB10 */
75};
76
77/*
78 * CEA speaker placement:
79 *
80 *        FLH       FCH        FRH
81 *  FLW    FL  FLC   FC   FRC   FR   FRW
82 *
83 *                                  LFE
84 *                     TC
85 *
86 *          RL  RLC   RC   RRC   RR
87 *
88 * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
89 * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
90 */
91enum cea_speaker_placement {
92	FL  = (1 <<  0),	/* Front Left           */
93	FC  = (1 <<  1),	/* Front Center         */
94	FR  = (1 <<  2),	/* Front Right          */
95	FLC = (1 <<  3),	/* Front Left Center    */
96	FRC = (1 <<  4),	/* Front Right Center   */
97	RL  = (1 <<  5),	/* Rear Left            */
98	RC  = (1 <<  6),	/* Rear Center          */
99	RR  = (1 <<  7),	/* Rear Right           */
100	RLC = (1 <<  8),	/* Rear Left Center     */
101	RRC = (1 <<  9),	/* Rear Right Center    */
102	LFE = (1 << 10),	/* Low Frequency Effect */
103	FLW = (1 << 11),	/* Front Left Wide      */
104	FRW = (1 << 12),	/* Front Right Wide     */
105	FLH = (1 << 13),	/* Front Left High      */
106	FCH = (1 << 14),	/* Front Center High    */
107	FRH = (1 << 15),	/* Front Right High     */
108	TC  = (1 << 16),	/* Top Center           */
109};
110
111/*
112 * ELD SA bits in the CEA Speaker Allocation data block
113 */
114static int eld_speaker_allocation_bits[] = {
115	[0] = FL | FR,
116	[1] = LFE,
117	[2] = FC,
118	[3] = RL | RR,
119	[4] = RC,
120	[5] = FLC | FRC,
121	[6] = RLC | RRC,
122	/* the following are not defined in ELD yet */
123	[7] = FLW | FRW,
124	[8] = FLH | FRH,
125	[9] = TC,
126	[10] = FCH,
127};
128
129struct cea_channel_speaker_allocation {
130	int ca_index;
131	int speakers[8];
132
133	/* derived values, just for convenience */
134	int channels;
135	int spk_mask;
136};
137
138/*
139 * ALSA sequence is:
140 *
141 *       surround40   surround41   surround50   surround51   surround71
142 * ch0   front left   =            =            =            =
143 * ch1   front right  =            =            =            =
144 * ch2   rear left    =            =            =            =
145 * ch3   rear right   =            =            =            =
146 * ch4                LFE          center       center       center
147 * ch5                                          LFE          LFE
148 * ch6                                                       side left
149 * ch7                                                       side right
150 *
151 * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
152 */
153static int hdmi_channel_mapping[0x32][8] = {
154	/* stereo */
155	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
156	/* 2.1 */
157	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
158	/* Dolby Surround */
159	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
160	/* surround40 */
161	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
162	/* 4ch */
163	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
164	/* surround41 */
165	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
166	/* surround50 */
167	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
168	/* surround51 */
169	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
170	/* 7.1 */
171	[0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
172};
173
174/*
175 * This is an ordered list!
176 *
177 * The preceding ones have better chances to be selected by
178 * hdmi_setup_channel_allocation().
179 */
180static struct cea_channel_speaker_allocation channel_allocations[] = {
181/*			  channel:   7     6    5    4    3     2    1    0  */
182{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
183				 /* 2.1 */
184{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
185				 /* Dolby Surround */
186{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
187				 /* surround40 */
188{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
189				 /* surround41 */
190{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
191				 /* surround50 */
192{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
193				 /* surround51 */
194{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
195				 /* 6.1 */
196{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
197				 /* surround71 */
198{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
199
200{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
201{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
202{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
203{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
204{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
205{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
206{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
207{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
208{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
209{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
210{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
211{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
212{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
213{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
214{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
215{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
216{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
217{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
218{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
219{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
220{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
221{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
222{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
223{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
224{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
225{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
226{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
227{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
228{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
229{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
230{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
231{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
232{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
233{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
234{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
235{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
236{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
237{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
238{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
239{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
240{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
241};
242
243
244/*
245 * HDMI routines
246 */
247
248static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
249{
250	int i;
251
252	for (i = 0; nids[i]; i++)
253		if (nids[i] == nid)
254			return i;
255
256	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
257	return -EINVAL;
258}
259
260static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
261			      struct hdmi_eld *eld)
262{
263	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
264		snd_hdmi_show_eld(eld);
265}
266
267#ifdef BE_PARANOID
268static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
269				int *packet_index, int *byte_index)
270{
271	int val;
272
273	val = snd_hda_codec_read(codec, pin_nid, 0,
274				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
275
276	*packet_index = val >> 5;
277	*byte_index = val & 0x1f;
278}
279#endif
280
281static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
282				int packet_index, int byte_index)
283{
284	int val;
285
286	val = (packet_index << 5) | (byte_index & 0x1f);
287
288	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
289}
290
291static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
292				unsigned char val)
293{
294	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
295}
296
297static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
298{
299	/* Unmute */
300	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
301		snd_hda_codec_write(codec, pin_nid, 0,
302				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
303	/* Enable pin out */
304	snd_hda_codec_write(codec, pin_nid, 0,
305			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
306}
307
308static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
309{
310	return 1 + snd_hda_codec_read(codec, nid, 0,
311					AC_VERB_GET_CVT_CHAN_COUNT, 0);
312}
313
314static void hdmi_set_channel_count(struct hda_codec *codec,
315				   hda_nid_t nid, int chs)
316{
317	if (chs != hdmi_get_channel_count(codec, nid))
318		snd_hda_codec_write(codec, nid, 0,
319				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
320}
321
322
323/*
324 * Channel mapping routines
325 */
326
327/*
328 * Compute derived values in channel_allocations[].
329 */
330static void init_channel_allocations(void)
331{
332	int i, j;
333	struct cea_channel_speaker_allocation *p;
334
335	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
336		p = channel_allocations + i;
337		p->channels = 0;
338		p->spk_mask = 0;
339		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
340			if (p->speakers[j]) {
341				p->channels++;
342				p->spk_mask |= p->speakers[j];
343			}
344	}
345}
346
347/*
348 * The transformation takes two steps:
349 *
350 *	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
351 *	      spk_mask => (channel_allocations[])         => ai->CA
352 *
353 * TODO: it could select the wrong CA from multiple candidates.
354*/
355static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
356					 struct hdmi_audio_infoframe *ai)
357{
358	struct hdmi_spec *spec = codec->spec;
359	struct hdmi_eld *eld;
360	int i;
361	int spk_mask = 0;
362	int channels = 1 + (ai->CC02_CT47 & 0x7);
363	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
364
365	/*
366	 * CA defaults to 0 for basic stereo audio
367	 */
368	if (channels <= 2)
369		return 0;
370
371	i = hda_node_index(spec->pin_cvt, nid);
372	if (i < 0)
373		return 0;
374	eld = &spec->sink_eld[i];
375
376	/*
377	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
378	 * in console or for audio devices. Assume the highest speakers
379	 * configuration, to _not_ prohibit multi-channel audio playback.
380	 */
381	if (!eld->spk_alloc)
382		eld->spk_alloc = 0xffff;
383
384	/*
385	 * expand ELD's speaker allocation mask
386	 *
387	 * ELD tells the speaker mask in a compact(paired) form,
388	 * expand ELD's notions to match the ones used by Audio InfoFrame.
389	 */
390	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
391		if (eld->spk_alloc & (1 << i))
392			spk_mask |= eld_speaker_allocation_bits[i];
393	}
394
395	/* search for the first working match in the CA table */
396	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
397		if (channels == channel_allocations[i].channels &&
398		    (spk_mask & channel_allocations[i].spk_mask) ==
399				channel_allocations[i].spk_mask) {
400			ai->CA = channel_allocations[i].ca_index;
401			break;
402		}
403	}
404
405	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
406	snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
407		    ai->CA, channels, buf);
408
409	return ai->CA;
410}
411
412static void hdmi_debug_channel_mapping(struct hda_codec *codec,
413				       hda_nid_t pin_nid)
414{
415#ifdef CONFIG_SND_DEBUG_VERBOSE
416	int i;
417	int slot;
418
419	for (i = 0; i < 8; i++) {
420		slot = snd_hda_codec_read(codec, pin_nid, 0,
421						AC_VERB_GET_HDMI_CHAN_SLOT, i);
422		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
423						slot >> 4, slot & 0xf);
424	}
425#endif
426}
427
428
429static void hdmi_setup_channel_mapping(struct hda_codec *codec,
430				       hda_nid_t pin_nid,
431				       struct hdmi_audio_infoframe *ai)
432{
433	int i;
434	int ca = ai->CA;
435	int err;
436
437	if (hdmi_channel_mapping[ca][1] == 0) {
438		for (i = 0; i < channel_allocations[ca].channels; i++)
439			hdmi_channel_mapping[ca][i] = i | (i << 4);
440		for (; i < 8; i++)
441			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
442	}
443
444	for (i = 0; i < 8; i++) {
445		err = snd_hda_codec_write(codec, pin_nid, 0,
446					  AC_VERB_SET_HDMI_CHAN_SLOT,
447					  hdmi_channel_mapping[ca][i]);
448		if (err) {
449			snd_printdd(KERN_NOTICE
450				    "HDMI: channel mapping failed\n");
451			break;
452		}
453	}
454
455	hdmi_debug_channel_mapping(codec, pin_nid);
456}
457
458
459/*
460 * Audio InfoFrame routines
461 */
462
463/*
464 * Enable Audio InfoFrame Transmission
465 */
466static void hdmi_start_infoframe_trans(struct hda_codec *codec,
467				       hda_nid_t pin_nid)
468{
469	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
470	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
471						AC_DIPXMIT_BEST);
472}
473
474/*
475 * Disable Audio InfoFrame Transmission
476 */
477static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
478				      hda_nid_t pin_nid)
479{
480	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
481	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
482						AC_DIPXMIT_DISABLE);
483}
484
485static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
486{
487#ifdef CONFIG_SND_DEBUG_VERBOSE
488	int i;
489	int size;
490
491	size = snd_hdmi_get_eld_size(codec, pin_nid);
492	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
493
494	for (i = 0; i < 8; i++) {
495		size = snd_hda_codec_read(codec, pin_nid, 0,
496						AC_VERB_GET_HDMI_DIP_SIZE, i);
497		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
498	}
499#endif
500}
501
502static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
503{
504#ifdef BE_PARANOID
505	int i, j;
506	int size;
507	int pi, bi;
508	for (i = 0; i < 8; i++) {
509		size = snd_hda_codec_read(codec, pin_nid, 0,
510						AC_VERB_GET_HDMI_DIP_SIZE, i);
511		if (size == 0)
512			continue;
513
514		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
515		for (j = 1; j < 1000; j++) {
516			hdmi_write_dip_byte(codec, pin_nid, 0x0);
517			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
518			if (pi != i)
519				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
520						bi, pi, i);
521			if (bi == 0) /* byte index wrapped around */
522				break;
523		}
524		snd_printd(KERN_INFO
525			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
526			i, size, j);
527	}
528#endif
529}
530
531static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
532{
533	u8 *bytes = (u8 *)ai;
534	u8 sum = 0;
535	int i;
536
537	ai->checksum = 0;
538
539	for (i = 0; i < sizeof(*ai); i++)
540		sum += bytes[i];
541
542	ai->checksum = -sum;
543}
544
545static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
546				      hda_nid_t pin_nid,
547				      struct hdmi_audio_infoframe *ai)
548{
549	u8 *bytes = (u8 *)ai;
550	int i;
551
552	hdmi_debug_dip_size(codec, pin_nid);
553	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
554
555	hdmi_checksum_audio_infoframe(ai);
556
557	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
558	for (i = 0; i < sizeof(*ai); i++)
559		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
560}
561
562static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
563				    struct hdmi_audio_infoframe *ai)
564{
565	u8 *bytes = (u8 *)ai;
566	u8 val;
567	int i;
568
569	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
570							    != AC_DIPXMIT_BEST)
571		return false;
572
573	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
574	for (i = 0; i < sizeof(*ai); i++) {
575		val = snd_hda_codec_read(codec, pin_nid, 0,
576					 AC_VERB_GET_HDMI_DIP_DATA, 0);
577		if (val != bytes[i])
578			return false;
579	}
580
581	return true;
582}
583
584static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
585					struct snd_pcm_substream *substream)
586{
587	struct hdmi_spec *spec = codec->spec;
588	hda_nid_t pin_nid;
589	int i;
590	struct hdmi_audio_infoframe ai = {
591		.type		= 0x84,
592		.ver		= 0x01,
593		.len		= 0x0a,
594		.CC02_CT47	= substream->runtime->channels - 1,
595	};
596
597	hdmi_setup_channel_allocation(codec, nid, &ai);
598
599	for (i = 0; i < spec->num_pins; i++) {
600		if (spec->pin_cvt[i] != nid)
601			continue;
602		if (!spec->sink_eld[i].monitor_present)
603			continue;
604
605		pin_nid = spec->pin[i];
606		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
607			snd_printdd("hdmi_setup_audio_infoframe: "
608				    "cvt=%d pin=%d channels=%d\n",
609				    nid, pin_nid,
610				    substream->runtime->channels);
611			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
612			hdmi_stop_infoframe_trans(codec, pin_nid);
613			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
614			hdmi_start_infoframe_trans(codec, pin_nid);
615		}
616	}
617}
618
619
620/*
621 * Unsolicited events
622 */
623
624static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
625			       struct hdmi_eld *eld);
626
627static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
628{
629	struct hdmi_spec *spec = codec->spec;
630	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
631	int pind = !!(res & AC_UNSOL_RES_PD);
632	int eldv = !!(res & AC_UNSOL_RES_ELDV);
633	int index;
634
635	printk(KERN_INFO
636		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
637		tag, pind, eldv);
638
639	index = hda_node_index(spec->pin, tag);
640	if (index < 0)
641		return;
642
643	if (spec->old_pin_detect) {
644		if (pind)
645			hdmi_present_sense(codec, tag, &spec->sink_eld[index]);
646		pind = spec->sink_eld[index].monitor_present;
647	}
648
649	spec->sink_eld[index].monitor_present = pind;
650	spec->sink_eld[index].eld_valid = eldv;
651
652	if (pind && eldv) {
653		hdmi_get_show_eld(codec, spec->pin[index],
654				  &spec->sink_eld[index]);
655		/* TODO: do real things about ELD */
656	}
657}
658
659static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
660{
661	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
662	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
663	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
664	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
665
666	printk(KERN_INFO
667		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
668		tag,
669		subtag,
670		cp_state,
671		cp_ready);
672
673	/* TODO */
674	if (cp_state)
675		;
676	if (cp_ready)
677		;
678}
679
680
681static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
682{
683	struct hdmi_spec *spec = codec->spec;
684	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
685	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
686
687	if (hda_node_index(spec->pin, tag) < 0) {
688		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
689		return;
690	}
691
692	if (subtag == 0)
693		hdmi_intrinsic_event(codec, res);
694	else
695		hdmi_non_intrinsic_event(codec, res);
696}
697
698/*
699 * Callbacks
700 */
701
702/* HBR should be Non-PCM, 8 channels */
703#define is_hbr_format(format) \
704	((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7)
705
706static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
707			      u32 stream_tag, int format)
708{
709	struct hdmi_spec *spec = codec->spec;
710	int pinctl;
711	int new_pinctl = 0;
712	int i;
713
714	for (i = 0; i < spec->num_pins; i++) {
715		if (spec->pin_cvt[i] != nid)
716			continue;
717		if (!(snd_hda_query_pin_caps(codec, spec->pin[i]) & AC_PINCAP_HBR))
718			continue;
719
720		pinctl = snd_hda_codec_read(codec, spec->pin[i], 0,
721					    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
722
723		new_pinctl = pinctl & ~AC_PINCTL_EPT;
724		if (is_hbr_format(format))
725			new_pinctl |= AC_PINCTL_EPT_HBR;
726		else
727			new_pinctl |= AC_PINCTL_EPT_NATIVE;
728
729		snd_printdd("hdmi_setup_stream: "
730			    "NID=0x%x, %spinctl=0x%x\n",
731			    spec->pin[i],
732			    pinctl == new_pinctl ? "" : "new-",
733			    new_pinctl);
734
735		if (pinctl != new_pinctl)
736			snd_hda_codec_write(codec, spec->pin[i], 0,
737					    AC_VERB_SET_PIN_WIDGET_CONTROL,
738					    new_pinctl);
739	}
740
741	if (is_hbr_format(format) && !new_pinctl) {
742		snd_printdd("hdmi_setup_stream: HBR is not supported\n");
743		return -EINVAL;
744	}
745
746	snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
747	return 0;
748}
749
750/*
751 * HDA PCM callbacks
752 */
753static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
754			 struct hda_codec *codec,
755			 struct snd_pcm_substream *substream)
756{
757	struct hdmi_spec *spec = codec->spec;
758	struct hdmi_eld *eld;
759	struct hda_pcm_stream *codec_pars;
760	unsigned int idx;
761
762	for (idx = 0; idx < spec->num_cvts; idx++)
763		if (hinfo->nid == spec->cvt[idx])
764			break;
765	if (snd_BUG_ON(idx >= spec->num_cvts) ||
766	    snd_BUG_ON(idx >= spec->num_pins))
767		return -EINVAL;
768
769	/* save the PCM info the codec provides */
770	codec_pars = &spec->codec_pcm_pars[idx];
771	if (!codec_pars->rates)
772		*codec_pars = *hinfo;
773
774	eld = &spec->sink_eld[idx];
775	if (eld->sad_count > 0) {
776		hdmi_eld_update_pcm_info(eld, hinfo, codec_pars);
777		if (hinfo->channels_min > hinfo->channels_max ||
778		    !hinfo->rates || !hinfo->formats)
779			return -ENODEV;
780	} else {
781		/* fallback to the codec default */
782		hinfo->channels_max = codec_pars->channels_max;
783		hinfo->rates = codec_pars->rates;
784		hinfo->formats = codec_pars->formats;
785		hinfo->maxbps = codec_pars->maxbps;
786	}
787	return 0;
788}
789
790/*
791 * HDA/HDMI auto parsing
792 */
793
794static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
795{
796	struct hdmi_spec *spec = codec->spec;
797	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
798	int conn_len, curr;
799	int index;
800
801	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
802		snd_printk(KERN_WARNING
803			   "HDMI: pin %d wcaps %#x "
804			   "does not support connection list\n",
805			   pin_nid, get_wcaps(codec, pin_nid));
806		return -EINVAL;
807	}
808
809	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
810					   HDA_MAX_CONNECTIONS);
811	if (conn_len > 1)
812		curr = snd_hda_codec_read(codec, pin_nid, 0,
813					  AC_VERB_GET_CONNECT_SEL, 0);
814	else
815		curr = 0;
816
817	index = hda_node_index(spec->pin, pin_nid);
818	if (index < 0)
819		return -EINVAL;
820
821	spec->pin_cvt[index] = conn_list[curr];
822
823	return 0;
824}
825
826static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
827			       struct hdmi_eld *eld)
828{
829	int present = snd_hda_pin_sense(codec, pin_nid);
830
831	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
832	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
833
834	if (present & AC_PINSENSE_ELDV)
835		hdmi_get_show_eld(codec, pin_nid, eld);
836}
837
838static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
839{
840	struct hdmi_spec *spec = codec->spec;
841
842	if (spec->num_pins >= MAX_HDMI_PINS) {
843		snd_printk(KERN_WARNING
844			   "HDMI: no space for pin %d\n", pin_nid);
845		return -E2BIG;
846	}
847
848	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
849
850	spec->pin[spec->num_pins] = pin_nid;
851	spec->num_pins++;
852
853	/*
854	 * It is assumed that converter nodes come first in the node list and
855	 * hence have been registered and usable now.
856	 */
857	return hdmi_read_pin_conn(codec, pin_nid);
858}
859
860static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
861{
862	struct hdmi_spec *spec = codec->spec;
863
864	if (spec->num_cvts >= MAX_HDMI_CVTS) {
865		snd_printk(KERN_WARNING
866			   "HDMI: no space for converter %d\n", nid);
867		return -E2BIG;
868	}
869
870	spec->cvt[spec->num_cvts] = nid;
871	spec->num_cvts++;
872
873	return 0;
874}
875
876static int hdmi_parse_codec(struct hda_codec *codec)
877{
878	hda_nid_t nid;
879	int i, nodes;
880
881	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
882	if (!nid || nodes < 0) {
883		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
884		return -EINVAL;
885	}
886
887	for (i = 0; i < nodes; i++, nid++) {
888		unsigned int caps;
889		unsigned int type;
890
891		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
892		type = get_wcaps_type(caps);
893
894		if (!(caps & AC_WCAP_DIGITAL))
895			continue;
896
897		switch (type) {
898		case AC_WID_AUD_OUT:
899			hdmi_add_cvt(codec, nid);
900			break;
901		case AC_WID_PIN:
902			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
903			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
904				continue;
905			hdmi_add_pin(codec, nid);
906			break;
907		}
908	}
909
910	/*
911	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
912	 * can be lost and presence sense verb will become inaccurate if the
913	 * HDA link is powered off at hot plug or hw initialization time.
914	 */
915#ifdef CONFIG_SND_HDA_POWER_SAVE
916	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
917	      AC_PWRST_EPSS))
918		codec->bus->power_keep_link_on = 1;
919#endif
920
921	return 0;
922}
923