]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/pci/hda/patch_intelhdmi.c
ALSA: hda - vectorize intelhdmi
[karo-tx-linux.git] / sound / pci / hda / patch_intelhdmi.c
1 /*
2  *
3  *  patch_intelhdmi.c - Patch for Intel HDMI codecs
4  *
5  *  Copyright(c) 2008 Intel Corporation. All rights reserved.
6  *
7  *  Authors:
8  *                      Jiang Zhe <zhe.jiang@intel.com>
9  *                      Wu Fengguang <wfg@linux.intel.com>
10  *
11  *  Maintained by:
12  *                      Wu Fengguang <wfg@linux.intel.com>
13  *
14  *  This program is free software; you can redistribute it and/or modify it
15  *  under the terms of the GNU General Public License as published by the Free
16  *  Software Foundation; either version 2 of the License, or (at your option)
17  *  any later version.
18  *
19  *  This program is distributed in the hope that it will be useful, but
20  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21  *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
22  *  for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software Foundation,
26  *  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #include <linux/init.h>
30 #include <linux/delay.h>
31 #include <linux/slab.h>
32 #include <sound/core.h>
33 #include "hda_codec.h"
34 #include "hda_local.h"
35
36 /*
37  * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
38  * could support two independent pipes, each of them can be connected to one or
39  * more ports (DVI, HDMI or DisplayPort).
40  *
41  * The HDA correspondence of pipes/ports are converter/pin nodes.
42  */
43 #define INTEL_HDMI_CVTS 2
44 #define INTEL_HDMI_PINS 3
45
46 static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = {
47         "INTEL HDMI 0",
48         "INTEL HDMI 1",
49 };
50
51 struct intel_hdmi_spec {
52         int num_cvts;
53         int num_pins;
54         hda_nid_t cvt[INTEL_HDMI_CVTS+1];  /* audio sources */
55         hda_nid_t pin[INTEL_HDMI_PINS+1];  /* audio sinks */
56
57         /*
58          * source connection for each pin
59          */
60         hda_nid_t pin_cvt[INTEL_HDMI_PINS+1];
61
62         /*
63          * HDMI sink attached to each pin
64          */
65         bool            sink_present[INTEL_HDMI_PINS];
66         bool            sink_eldv[INTEL_HDMI_PINS];
67         struct hdmi_eld sink_eld[INTEL_HDMI_PINS];
68
69         /*
70          * export one pcm per pipe
71          */
72         struct hda_pcm  pcm_rec[INTEL_HDMI_CVTS];
73 };
74
75 struct hdmi_audio_infoframe {
76         u8 type; /* 0x84 */
77         u8 ver;  /* 0x01 */
78         u8 len;  /* 0x0a */
79
80         u8 checksum;    /* PB0 */
81         u8 CC02_CT47;   /* CC in bits 0:2, CT in 4:7 */
82         u8 SS01_SF24;
83         u8 CXT04;
84         u8 CA;
85         u8 LFEPBL01_LSV36_DM_INH7;
86         u8 reserved[5]; /* PB6 - PB10 */
87 };
88
89 /*
90  * CEA speaker placement:
91  *
92  *        FLH       FCH        FRH
93  *  FLW    FL  FLC   FC   FRC   FR   FRW
94  *
95  *                                  LFE
96  *                     TC
97  *
98  *          RL  RLC   RC   RRC   RR
99  *
100  * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
101  * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
102  */
103 enum cea_speaker_placement {
104         FL  = (1 <<  0),        /* Front Left           */
105         FC  = (1 <<  1),        /* Front Center         */
106         FR  = (1 <<  2),        /* Front Right          */
107         FLC = (1 <<  3),        /* Front Left Center    */
108         FRC = (1 <<  4),        /* Front Right Center   */
109         RL  = (1 <<  5),        /* Rear Left            */
110         RC  = (1 <<  6),        /* Rear Center          */
111         RR  = (1 <<  7),        /* Rear Right           */
112         RLC = (1 <<  8),        /* Rear Left Center     */
113         RRC = (1 <<  9),        /* Rear Right Center    */
114         LFE = (1 << 10),        /* Low Frequency Effect */
115         FLW = (1 << 11),        /* Front Left Wide      */
116         FRW = (1 << 12),        /* Front Right Wide     */
117         FLH = (1 << 13),        /* Front Left High      */
118         FCH = (1 << 14),        /* Front Center High    */
119         FRH = (1 << 15),        /* Front Right High     */
120         TC  = (1 << 16),        /* Top Center           */
121 };
122
123 /*
124  * ELD SA bits in the CEA Speaker Allocation data block
125  */
126 static int eld_speaker_allocation_bits[] = {
127         [0] = FL | FR,
128         [1] = LFE,
129         [2] = FC,
130         [3] = RL | RR,
131         [4] = RC,
132         [5] = FLC | FRC,
133         [6] = RLC | RRC,
134         /* the following are not defined in ELD yet */
135         [7] = FLW | FRW,
136         [8] = FLH | FRH,
137         [9] = TC,
138         [10] = FCH,
139 };
140
141 struct cea_channel_speaker_allocation {
142         int ca_index;
143         int speakers[8];
144
145         /* derived values, just for convenience */
146         int channels;
147         int spk_mask;
148 };
149
150 /*
151  * This is an ordered list!
152  *
153  * The preceding ones have better chances to be selected by
154  * hdmi_setup_channel_allocation().
155  */
156 static struct cea_channel_speaker_allocation channel_allocations[] = {
157 /*                        channel:   8     7    6    5    4     3    2    1  */
158 { .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
159                                  /* 2.1 */
160 { .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
161                                  /* Dolby Surround */
162 { .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
163 { .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
164 { .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
165 { .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
166 { .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
167 { .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
168 { .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
169 { .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
170 { .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
171                                  /* 5.1 */
172 { .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
173 { .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
174 { .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
175 { .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
176                                  /* 6.1 */
177 { .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
178 { .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
179 { .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
180 { .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
181                                  /* 7.1 */
182 { .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
183 { .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
184 { .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
185 { .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
186 { .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
187 { .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
188 { .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
189 { .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
190 { .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
191 { .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
192 { .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
193 { .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
194 { .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
195 { .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
196 { .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
197 { .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
198 { .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
199 { .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
200 { .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
201 { .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
202 { .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
203 { .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
204 { .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
205 { .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
206 { .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
207 { .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
208 { .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
209 { .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
210 { .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
211 { .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
212 { .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
213 };
214
215
216 static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
217 {
218         int i;
219
220         for (i = 0; nids[i]; i++)
221                 if (nids[i] == nid)
222                         return i;
223
224         snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
225         return -EINVAL;
226 }
227
228 /*
229  * HDMI routines
230  */
231
232 #ifdef BE_PARANOID
233 static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
234                                 int *packet_index, int *byte_index)
235 {
236         int val;
237
238         val = snd_hda_codec_read(codec, pin_nid, 0,
239                                  AC_VERB_GET_HDMI_DIP_INDEX, 0);
240
241         *packet_index = val >> 5;
242         *byte_index = val & 0x1f;
243 }
244 #endif
245
246 static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
247                                 int packet_index, int byte_index)
248 {
249         int val;
250
251         val = (packet_index << 5) | (byte_index & 0x1f);
252
253         snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
254 }
255
256 static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
257                                 unsigned char val)
258 {
259         snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
260 }
261
262 static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
263 {
264         /* Unmute */
265         if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
266                 snd_hda_codec_write(codec, pin_nid, 0,
267                                 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
268         /* Enable pin out */
269         snd_hda_codec_write(codec, pin_nid, 0,
270                             AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
271 }
272
273 /*
274  * Enable Audio InfoFrame Transmission
275  */
276 static void hdmi_start_infoframe_trans(struct hda_codec *codec,
277                                        hda_nid_t pin_nid)
278 {
279         hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
280         snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
281                                                 AC_DIPXMIT_BEST);
282 }
283
284 /*
285  * Disable Audio InfoFrame Transmission
286  */
287 static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
288                                       hda_nid_t pin_nid)
289 {
290         hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
291         snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
292                                                 AC_DIPXMIT_DISABLE);
293 }
294
295 static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
296 {
297         return 1 + snd_hda_codec_read(codec, nid, 0,
298                                         AC_VERB_GET_CVT_CHAN_COUNT, 0);
299 }
300
301 static void hdmi_set_channel_count(struct hda_codec *codec,
302                                    hda_nid_t nid, int chs)
303 {
304         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
305
306 #ifdef CONFIG_SND_DEBUG_VERBOSE
307         if (chs != hdmi_get_channel_count(codec, nid))
308                 snd_printd(KERN_INFO "HDMI channel count: expect %d, get %d\n",
309                            chs, hdmi_get_channel_count(codec, nid));
310 #endif
311 }
312
313 static void hdmi_debug_channel_mapping(struct hda_codec *codec, hda_nid_t nid)
314 {
315 #ifdef CONFIG_SND_DEBUG_VERBOSE
316         int i;
317         int slot;
318
319         for (i = 0; i < 8; i++) {
320                 slot = snd_hda_codec_read(codec, nid, 0,
321                                                 AC_VERB_GET_HDMI_CHAN_SLOT, i);
322                 printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
323                                                 slot >> 4, slot & 0x7);
324         }
325 #endif
326 }
327
328 static void hdmi_parse_eld(struct hda_codec *codec, int index)
329 {
330         struct intel_hdmi_spec *spec = codec->spec;
331         struct hdmi_eld *eld = &spec->sink_eld[index];
332
333         if (!snd_hdmi_get_eld(eld, codec, spec->pin[index]))
334                 snd_hdmi_show_eld(eld);
335 }
336
337
338 /*
339  * Audio InfoFrame routines
340  */
341
342 static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
343 {
344 #ifdef CONFIG_SND_DEBUG_VERBOSE
345         int i;
346         int size;
347
348         size = snd_hdmi_get_eld_size(codec, pin_nid);
349         printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
350
351         for (i = 0; i < 8; i++) {
352                 size = snd_hda_codec_read(codec, pin_nid, 0,
353                                                 AC_VERB_GET_HDMI_DIP_SIZE, i);
354                 printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
355         }
356 #endif
357 }
358
359 static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
360 {
361 #ifdef BE_PARANOID
362         int i, j;
363         int size;
364         int pi, bi;
365         for (i = 0; i < 8; i++) {
366                 size = snd_hda_codec_read(codec, pin_nid, 0,
367                                                 AC_VERB_GET_HDMI_DIP_SIZE, i);
368                 if (size == 0)
369                         continue;
370
371                 hdmi_set_dip_index(codec, pin_nid, i, 0x0);
372                 for (j = 1; j < 1000; j++) {
373                         hdmi_write_dip_byte(codec, pin_nid, 0x0);
374                         hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
375                         if (pi != i)
376                                 snd_printd(KERN_INFO "dip index %d: %d != %d\n",
377                                                 bi, pi, i);
378                         if (bi == 0) /* byte index wrapped around */
379                                 break;
380                 }
381                 snd_printd(KERN_INFO
382                         "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
383                         i, size, j);
384         }
385 #endif
386 }
387
388 static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
389                                       hda_nid_t pin_nid,
390                                       struct hdmi_audio_infoframe *ai)
391 {
392         u8 *params = (u8 *)ai;
393         u8 sum = 0;
394         int i;
395
396         hdmi_debug_dip_size(codec, pin_nid);
397         hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
398
399         for (i = 0; i < sizeof(ai); i++)
400                 sum += params[i];
401         ai->checksum = - sum;
402
403         hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
404         for (i = 0; i < sizeof(ai); i++)
405                 hdmi_write_dip_byte(codec, pin_nid, params[i]);
406 }
407
408 /*
409  * Compute derived values in channel_allocations[].
410  */
411 static void init_channel_allocations(void)
412 {
413         int i, j;
414         struct cea_channel_speaker_allocation *p;
415
416         for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
417                 p = channel_allocations + i;
418                 p->channels = 0;
419                 p->spk_mask = 0;
420                 for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
421                         if (p->speakers[j]) {
422                                 p->channels++;
423                                 p->spk_mask |= p->speakers[j];
424                         }
425         }
426 }
427
428 /*
429  * The transformation takes two steps:
430  *
431  *      eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
432  *            spk_mask => (channel_allocations[])         => ai->CA
433  *
434  * TODO: it could select the wrong CA from multiple candidates.
435 */
436 static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
437                                          struct hdmi_audio_infoframe *ai)
438 {
439         struct intel_hdmi_spec *spec = codec->spec;
440         struct hdmi_eld *eld;
441         int i;
442         int spk_mask = 0;
443         int channels = 1 + (ai->CC02_CT47 & 0x7);
444         char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
445
446         /*
447          * CA defaults to 0 for basic stereo audio
448          */
449         if (channels <= 2)
450                 return 0;
451
452         i = hda_node_index(spec->pin_cvt, nid);
453         if (i < 0)
454                 return 0;
455         eld = &spec->sink_eld[i];
456
457         /*
458          * HDMI sink's ELD info cannot always be retrieved for now, e.g.
459          * in console or for audio devices. Assume the highest speakers
460          * configuration, to _not_ prohibit multi-channel audio playback.
461          */
462         if (!eld->spk_alloc)
463                 eld->spk_alloc = 0xffff;
464
465         /*
466          * expand ELD's speaker allocation mask
467          *
468          * ELD tells the speaker mask in a compact(paired) form,
469          * expand ELD's notions to match the ones used by Audio InfoFrame.
470          */
471         for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
472                 if (eld->spk_alloc & (1 << i))
473                         spk_mask |= eld_speaker_allocation_bits[i];
474         }
475
476         /* search for the first working match in the CA table */
477         for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
478                 if (channels == channel_allocations[i].channels &&
479                     (spk_mask & channel_allocations[i].spk_mask) ==
480                                 channel_allocations[i].spk_mask) {
481                         ai->CA = channel_allocations[i].ca_index;
482                         break;
483                 }
484         }
485
486         snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
487         snd_printdd(KERN_INFO
488                         "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
489                         ai->CA, channels, buf);
490
491         return ai->CA;
492 }
493
494 static void hdmi_setup_channel_mapping(struct hda_codec *codec, hda_nid_t nid,
495                                        struct hdmi_audio_infoframe *ai)
496 {
497         int i;
498
499         if (!ai->CA)
500                 return;
501
502         /*
503          * TODO: adjust channel mapping if necessary
504          * ALSA sequence is front/surr/clfe/side?
505          */
506
507         for (i = 0; i < 8; i++)
508                 snd_hda_codec_write(codec, nid, 0,
509                                     AC_VERB_SET_HDMI_CHAN_SLOT,
510                                     (i << 4) | i);
511
512         hdmi_debug_channel_mapping(codec, nid);
513 }
514
515
516 static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
517                                         struct snd_pcm_substream *substream)
518 {
519         struct intel_hdmi_spec *spec = codec->spec;
520         hda_nid_t pin_nid;
521         int i;
522         struct hdmi_audio_infoframe ai = {
523                 .type           = 0x84,
524                 .ver            = 0x01,
525                 .len            = 0x0a,
526                 .CC02_CT47      = substream->runtime->channels - 1,
527         };
528
529         hdmi_setup_channel_allocation(codec, nid, &ai);
530         hdmi_setup_channel_mapping(codec, nid, &ai);
531
532         for (i = 0; i < spec->num_pins; i++) {
533                 if (spec->pin_cvt[i] != nid)
534                         continue;
535                 if (spec->sink_present[i] != true)
536                         continue;
537
538                 pin_nid = spec->pin[i];
539                 hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
540                 hdmi_start_infoframe_trans(codec, pin_nid);
541         }
542 }
543
544
545 /*
546  * Unsolicited events
547  */
548
549 static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
550 {
551         struct intel_hdmi_spec *spec = codec->spec;
552         int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
553         int pind = !!(res & AC_UNSOL_RES_PD);
554         int eldv = !!(res & AC_UNSOL_RES_ELDV);
555         int index;
556
557         printk(KERN_INFO
558                 "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
559                 tag, pind, eldv);
560
561         index = hda_node_index(spec->pin, tag);
562         if (index < 0)
563                 return;
564
565         spec->sink_present[index] = pind;
566         spec->sink_eldv[index] = eldv;
567
568         if (pind && eldv) {
569                 hdmi_parse_eld(codec, index);
570                 /* TODO: do real things about ELD */
571         }
572 }
573
574 static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
575 {
576         int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
577         int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
578         int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
579         int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
580
581         printk(KERN_INFO
582                 "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
583                 tag,
584                 subtag,
585                 cp_state,
586                 cp_ready);
587
588         /* TODO */
589         if (cp_state)
590                 ;
591         if (cp_ready)
592                 ;
593 }
594
595
596 static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
597 {
598         struct intel_hdmi_spec *spec = codec->spec;
599         int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
600         int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
601
602         if (hda_node_index(spec->pin, tag) < 0) {
603                 snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
604                 return;
605         }
606
607         if (subtag == 0)
608                 hdmi_intrinsic_event(codec, res);
609         else
610                 hdmi_non_intrinsic_event(codec, res);
611 }
612
613 /*
614  * Callbacks
615  */
616
617 static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
618                                            struct hda_codec *codec,
619                                            unsigned int stream_tag,
620                                            unsigned int format,
621                                            struct snd_pcm_substream *substream)
622 {
623         hdmi_set_channel_count(codec, hinfo->nid,
624                                substream->runtime->channels);
625
626         hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
627
628         snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
629         return 0;
630 }
631
632 static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
633                                            struct hda_codec *codec,
634                                            struct snd_pcm_substream *substream)
635 {
636         struct intel_hdmi_spec *spec = codec->spec;
637         int i;
638
639         for (i = 0; i < spec->num_pins; i++) {
640                 if (spec->pin_cvt[i] != hinfo->nid)
641                         continue;
642
643                 hdmi_stop_infoframe_trans(codec, spec->pin[i]);
644         }
645
646         snd_hda_codec_cleanup_stream(codec, hinfo->nid);
647         return 0;
648 }
649
650 static struct hda_pcm_stream intel_hdmi_pcm_playback = {
651         .substreams = 1,
652         .channels_min = 2,
653         .channels_max = 8,
654         .ops = {
655                 .prepare = intel_hdmi_playback_pcm_prepare,
656                 .cleanup = intel_hdmi_playback_pcm_cleanup,
657         },
658 };
659
660 static int intel_hdmi_build_pcms(struct hda_codec *codec)
661 {
662         struct intel_hdmi_spec *spec = codec->spec;
663         struct hda_pcm *info = spec->pcm_rec;
664         int i;
665
666         codec->num_pcms = spec->num_cvts;
667         codec->pcm_info = info;
668
669         for (i = 0; i < codec->num_pcms; i++, info++) {
670                 info->name = intel_hdmi_pcm_names[i];
671                 info->pcm_type = HDA_PCM_TYPE_HDMI;
672                 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
673                                                         intel_hdmi_pcm_playback;
674                 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
675         }
676
677         return 0;
678 }
679
680 static int intel_hdmi_build_controls(struct hda_codec *codec)
681 {
682         struct intel_hdmi_spec *spec = codec->spec;
683         int err;
684         int i;
685
686         for (i = 0; i < codec->num_pcms; i++) {
687                 err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]);
688                 if (err < 0)
689                         return err;
690         }
691
692         return 0;
693 }
694
695 static int intel_hdmi_init(struct hda_codec *codec)
696 {
697         struct intel_hdmi_spec *spec = codec->spec;
698         int i;
699
700         for (i = 0; spec->pin[i]; i++) {
701                 hdmi_enable_output(codec, spec->pin[i]);
702                 snd_hda_codec_write(codec, spec->pin[i], 0,
703                                     AC_VERB_SET_UNSOLICITED_ENABLE,
704                                     AC_USRSP_EN | spec->pin[i]);
705         }
706         return 0;
707 }
708
709 static void intel_hdmi_free(struct hda_codec *codec)
710 {
711         struct intel_hdmi_spec *spec = codec->spec;
712         int i;
713
714         for (i = 0; i < spec->num_pins; i++)
715                 snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
716
717         kfree(spec);
718 }
719
720 static struct hda_codec_ops intel_hdmi_patch_ops = {
721         .init                   = intel_hdmi_init,
722         .free                   = intel_hdmi_free,
723         .build_pcms             = intel_hdmi_build_pcms,
724         .build_controls         = intel_hdmi_build_controls,
725         .unsol_event            = intel_hdmi_unsol_event,
726 };
727
728 static struct intel_hdmi_spec static_specs[] = {
729         {
730                 .num_cvts = 1,
731                 .num_pins = 1,
732                 .cvt      = { 0x2 },
733                 .pin      = { 0x3 },
734                 .pin_cvt  = { 0x2 },
735         },
736         {
737                 .num_cvts = 2,
738                 .num_pins = 3,
739                 .cvt      = { 0x2, 0x3 },
740                 .pin      = { 0x4, 0x5, 0x6 },
741                 .pin_cvt  = { 0x2, 0x2, 0x2 },
742         },
743 };
744
745 static int do_patch_intel_hdmi(struct hda_codec *codec, int spec_id)
746 {
747         struct intel_hdmi_spec *spec;
748         int i;
749
750         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
751         if (spec == NULL)
752                 return -ENOMEM;
753
754         *spec = static_specs[spec_id];
755         codec->spec = spec;
756         codec->patch_ops = intel_hdmi_patch_ops;
757
758         for (i = 0; i < spec->num_pins; i++)
759                 snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
760
761         init_channel_allocations();
762
763         return 0;
764 }
765
766 static int patch_intel_hdmi(struct hda_codec *codec)
767 {
768         return do_patch_intel_hdmi(codec, 0);
769 }
770
771 static int patch_intel_hdmi_ibexpeak(struct hda_codec *codec)
772 {
773         return do_patch_intel_hdmi(codec, 1);
774 }
775
776 static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
777         { .id = 0x808629fb, .name = "G45 DEVCL",  .patch = patch_intel_hdmi },
778         { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi },
779         { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi },
780         { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi },
781         { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi_ibexpeak },
782         { .id = 0x80860054, .name = "Q57 DEVIBX", .patch = patch_intel_hdmi_ibexpeak },
783         { .id = 0x10951392, .name = "SiI1392 HDMI",     .patch = patch_intel_hdmi },
784         {} /* terminator */
785 };
786
787 MODULE_ALIAS("snd-hda-codec-id:808629fb");
788 MODULE_ALIAS("snd-hda-codec-id:80862801");
789 MODULE_ALIAS("snd-hda-codec-id:80862802");
790 MODULE_ALIAS("snd-hda-codec-id:80862803");
791 MODULE_ALIAS("snd-hda-codec-id:80862804");
792 MODULE_ALIAS("snd-hda-codec-id:80860054");
793 MODULE_ALIAS("snd-hda-codec-id:10951392");
794
795 MODULE_LICENSE("GPL");
796 MODULE_DESCRIPTION("Intel HDMI HD-audio codec");
797
798 static struct hda_codec_preset_list intel_list = {
799         .preset = snd_hda_preset_intelhdmi,
800         .owner = THIS_MODULE,
801 };
802
803 static int __init patch_intelhdmi_init(void)
804 {
805         return snd_hda_add_codec_preset(&intel_list);
806 }
807
808 static void __exit patch_intelhdmi_exit(void)
809 {
810         snd_hda_delete_codec_preset(&intel_list);
811 }
812
813 module_init(patch_intelhdmi_init)
814 module_exit(patch_intelhdmi_exit)