]> git.openfabrics.org - ~shefty/rdma-dev.git/blob - sound/pci/hda/patch_intelhdmi.c
Merge branch 'fix/hda' into topic/hda
[~shefty/rdma-dev.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 static hda_nid_t cvt_nid;       /* audio converter */
37 static hda_nid_t pin_nid;       /* HDMI output pin */
38
39 #define INTEL_HDMI_EVENT_TAG            0x08
40
41 struct intel_hdmi_spec {
42         struct hda_multi_out multiout;
43         struct hda_pcm pcm_rec;
44         struct hdmi_eld sink_eld;
45 };
46
47 struct hdmi_audio_infoframe {
48         u8 type; /* 0x84 */
49         u8 ver;  /* 0x01 */
50         u8 len;  /* 0x0a */
51
52         u8 checksum;    /* PB0 */
53         u8 CC02_CT47;   /* CC in bits 0:2, CT in 4:7 */
54         u8 SS01_SF24;
55         u8 CXT04;
56         u8 CA;
57         u8 LFEPBL01_LSV36_DM_INH7;
58         u8 reserved[5]; /* PB6 - PB10 */
59 };
60
61 /*
62  * CEA speaker placement:
63  *
64  *        FLH       FCH        FRH
65  *  FLW    FL  FLC   FC   FRC   FR   FRW
66  *
67  *                                  LFE
68  *                     TC
69  *
70  *          RL  RLC   RC   RRC   RR
71  *
72  * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
73  * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
74  */
75 enum cea_speaker_placement {
76         FL  = (1 <<  0),        /* Front Left           */
77         FC  = (1 <<  1),        /* Front Center         */
78         FR  = (1 <<  2),        /* Front Right          */
79         FLC = (1 <<  3),        /* Front Left Center    */
80         FRC = (1 <<  4),        /* Front Right Center   */
81         RL  = (1 <<  5),        /* Rear Left            */
82         RC  = (1 <<  6),        /* Rear Center          */
83         RR  = (1 <<  7),        /* Rear Right           */
84         RLC = (1 <<  8),        /* Rear Left Center     */
85         RRC = (1 <<  9),        /* Rear Right Center    */
86         LFE = (1 << 10),        /* Low Frequency Effect */
87         FLW = (1 << 11),        /* Front Left Wide      */
88         FRW = (1 << 12),        /* Front Right Wide     */
89         FLH = (1 << 13),        /* Front Left High      */
90         FCH = (1 << 14),        /* Front Center High    */
91         FRH = (1 << 15),        /* Front Right High     */
92         TC  = (1 << 16),        /* Top Center           */
93 };
94
95 /*
96  * ELD SA bits in the CEA Speaker Allocation data block
97  */
98 static int eld_speaker_allocation_bits[] = {
99         [0] = FL | FR,
100         [1] = LFE,
101         [2] = FC,
102         [3] = RL | RR,
103         [4] = RC,
104         [5] = FLC | FRC,
105         [6] = RLC | RRC,
106         /* the following are not defined in ELD yet */
107         [7] = FLW | FRW,
108         [8] = FLH | FRH,
109         [9] = TC,
110         [10] = FCH,
111 };
112
113 struct cea_channel_speaker_allocation {
114         int ca_index;
115         int speakers[8];
116
117         /* derived values, just for convenience */
118         int channels;
119         int spk_mask;
120 };
121
122 /*
123  * This is an ordered list!
124  *
125  * The preceding ones have better chances to be selected by
126  * hdmi_setup_channel_allocation().
127  */
128 static struct cea_channel_speaker_allocation channel_allocations[] = {
129 /*                        channel:   8     7    6    5    4     3    2    1  */
130 { .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
131                                  /* 2.1 */
132 { .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
133                                  /* Dolby Surround */
134 { .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
135 { .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
136 { .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
137 { .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
138 { .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
139 { .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
140 { .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
141 { .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
142 { .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
143                                  /* 5.1 */
144 { .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
145 { .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
146 { .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
147 { .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
148                                  /* 6.1 */
149 { .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
150 { .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
151 { .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
152 { .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
153                                  /* 7.1 */
154 { .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
155 { .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
156 { .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
157 { .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
158 { .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
159 { .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
160 { .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
161 { .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
162 { .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
163 { .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
164 { .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
165 { .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
166 { .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
167 { .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
168 { .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
169 { .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
170 { .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
171 { .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
172 { .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
173 { .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
174 { .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
175 { .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
176 { .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
177 { .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
178 { .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
179 { .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
180 { .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
181 { .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
182 { .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
183 { .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
184 { .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
185 };
186
187 /*
188  * HDMI routines
189  */
190
191 #ifdef BE_PARANOID
192 static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t nid,
193                                 int *packet_index, int *byte_index)
194 {
195         int val;
196
197         val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_INDEX, 0);
198
199         *packet_index = val >> 5;
200         *byte_index = val & 0x1f;
201 }
202 #endif
203
204 static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t nid,
205                                 int packet_index, int byte_index)
206 {
207         int val;
208
209         val = (packet_index << 5) | (byte_index & 0x1f);
210
211         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
212 }
213
214 static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t nid,
215                                 unsigned char val)
216 {
217         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
218 }
219
220 static void hdmi_enable_output(struct hda_codec *codec)
221 {
222         /* Unmute */
223         if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
224                 snd_hda_codec_write(codec, pin_nid, 0,
225                                 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
226         /* Enable pin out */
227         snd_hda_codec_write(codec, pin_nid, 0,
228                             AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
229 }
230
231 /*
232  * Enable Audio InfoFrame Transmission
233  */
234 static void hdmi_start_infoframe_trans(struct hda_codec *codec)
235 {
236         hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
237         snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
238                                                 AC_DIPXMIT_BEST);
239 }
240
241 /*
242  * Disable Audio InfoFrame Transmission
243  */
244 static void hdmi_stop_infoframe_trans(struct hda_codec *codec)
245 {
246         hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
247         snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
248                                                 AC_DIPXMIT_DISABLE);
249 }
250
251 static int hdmi_get_channel_count(struct hda_codec *codec)
252 {
253         return 1 + snd_hda_codec_read(codec, cvt_nid, 0,
254                                         AC_VERB_GET_CVT_CHAN_COUNT, 0);
255 }
256
257 static void hdmi_set_channel_count(struct hda_codec *codec, int chs)
258 {
259         snd_hda_codec_write(codec, cvt_nid, 0,
260                                         AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
261
262         if (chs != hdmi_get_channel_count(codec))
263                 snd_printd(KERN_INFO "HDMI channel count: expect %d, get %d\n",
264                                         chs, hdmi_get_channel_count(codec));
265 }
266
267 static void hdmi_debug_channel_mapping(struct hda_codec *codec)
268 {
269 #ifdef CONFIG_SND_DEBUG_VERBOSE
270         int i;
271         int slot;
272
273         for (i = 0; i < 8; i++) {
274                 slot = snd_hda_codec_read(codec, cvt_nid, 0,
275                                                 AC_VERB_GET_HDMI_CHAN_SLOT, i);
276                 printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
277                                                 slot >> 4, slot & 0x7);
278         }
279 #endif
280 }
281
282 static void hdmi_parse_eld(struct hda_codec *codec)
283 {
284         struct intel_hdmi_spec *spec = codec->spec;
285         struct hdmi_eld *eld = &spec->sink_eld;
286
287         if (!snd_hdmi_get_eld(eld, codec, pin_nid))
288                 snd_hdmi_show_eld(eld);
289 }
290
291
292 /*
293  * Audio InfoFrame routines
294  */
295
296 static void hdmi_debug_dip_size(struct hda_codec *codec)
297 {
298 #ifdef CONFIG_SND_DEBUG_VERBOSE
299         int i;
300         int size;
301
302         size = snd_hdmi_get_eld_size(codec, pin_nid);
303         printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
304
305         for (i = 0; i < 8; i++) {
306                 size = snd_hda_codec_read(codec, pin_nid, 0,
307                                                 AC_VERB_GET_HDMI_DIP_SIZE, i);
308                 printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
309         }
310 #endif
311 }
312
313 static void hdmi_clear_dip_buffers(struct hda_codec *codec)
314 {
315 #ifdef BE_PARANOID
316         int i, j;
317         int size;
318         int pi, bi;
319         for (i = 0; i < 8; i++) {
320                 size = snd_hda_codec_read(codec, pin_nid, 0,
321                                                 AC_VERB_GET_HDMI_DIP_SIZE, i);
322                 if (size == 0)
323                         continue;
324
325                 hdmi_set_dip_index(codec, pin_nid, i, 0x0);
326                 for (j = 1; j < 1000; j++) {
327                         hdmi_write_dip_byte(codec, pin_nid, 0x0);
328                         hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
329                         if (pi != i)
330                                 snd_printd(KERN_INFO "dip index %d: %d != %d\n",
331                                                 bi, pi, i);
332                         if (bi == 0) /* byte index wrapped around */
333                                 break;
334                 }
335                 snd_printd(KERN_INFO
336                         "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
337                         i, size, j);
338         }
339 #endif
340 }
341
342 static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
343                                         struct hdmi_audio_infoframe *ai)
344 {
345         u8 *params = (u8 *)ai;
346         u8 sum = 0;
347         int i;
348
349         hdmi_debug_dip_size(codec);
350         hdmi_clear_dip_buffers(codec); /* be paranoid */
351
352         for (i = 0; i < sizeof(ai); i++)
353                 sum += params[i];
354         ai->checksum = - sum;
355
356         hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
357         for (i = 0; i < sizeof(ai); i++)
358                 hdmi_write_dip_byte(codec, pin_nid, params[i]);
359 }
360
361 /*
362  * Compute derived values in channel_allocations[].
363  */
364 static void init_channel_allocations(void)
365 {
366         int i, j;
367         struct cea_channel_speaker_allocation *p;
368
369         for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
370                 p = channel_allocations + i;
371                 p->channels = 0;
372                 p->spk_mask = 0;
373                 for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
374                         if (p->speakers[j]) {
375                                 p->channels++;
376                                 p->spk_mask |= p->speakers[j];
377                         }
378         }
379 }
380
381 /*
382  * The transformation takes two steps:
383  *
384  *      eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
385  *            spk_mask => (channel_allocations[])         => ai->CA
386  *
387  * TODO: it could select the wrong CA from multiple candidates.
388 */
389 static int hdmi_setup_channel_allocation(struct hda_codec *codec,
390                                          struct hdmi_audio_infoframe *ai)
391 {
392         struct intel_hdmi_spec *spec = codec->spec;
393         struct hdmi_eld *eld = &spec->sink_eld;
394         int i;
395         int spk_mask = 0;
396         int channels = 1 + (ai->CC02_CT47 & 0x7);
397         char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
398
399         /*
400          * CA defaults to 0 for basic stereo audio
401          */
402         if (channels <= 2)
403                 return 0;
404
405         /*
406          * HDMI sink's ELD info cannot always be retrieved for now, e.g.
407          * in console or for audio devices. Assume the highest speakers
408          * configuration, to _not_ prohibit multi-channel audio playback.
409          */
410         if (!eld->spk_alloc)
411                 eld->spk_alloc = 0xffff;
412
413         /*
414          * expand ELD's speaker allocation mask
415          *
416          * ELD tells the speaker mask in a compact(paired) form,
417          * expand ELD's notions to match the ones used by Audio InfoFrame.
418          */
419         for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
420                 if (eld->spk_alloc & (1 << i))
421                         spk_mask |= eld_speaker_allocation_bits[i];
422         }
423
424         /* search for the first working match in the CA table */
425         for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
426                 if (channels == channel_allocations[i].channels &&
427                     (spk_mask & channel_allocations[i].spk_mask) ==
428                                 channel_allocations[i].spk_mask) {
429                         ai->CA = channel_allocations[i].ca_index;
430                         break;
431                 }
432         }
433
434         snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
435         snd_printdd(KERN_INFO
436                         "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
437                         ai->CA, channels, buf);
438
439         return ai->CA;
440 }
441
442 static void hdmi_setup_channel_mapping(struct hda_codec *codec,
443                                         struct hdmi_audio_infoframe *ai)
444 {
445         int i;
446
447         if (!ai->CA)
448                 return;
449
450         /*
451          * TODO: adjust channel mapping if necessary
452          * ALSA sequence is front/surr/clfe/side?
453          */
454
455         for (i = 0; i < 8; i++)
456                 snd_hda_codec_write(codec, cvt_nid, 0,
457                                     AC_VERB_SET_HDMI_CHAN_SLOT,
458                                     (i << 4) | i);
459
460         hdmi_debug_channel_mapping(codec);
461 }
462
463
464 static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
465                                         struct snd_pcm_substream *substream)
466 {
467         struct hdmi_audio_infoframe ai = {
468                 .type           = 0x84,
469                 .ver            = 0x01,
470                 .len            = 0x0a,
471                 .CC02_CT47      = substream->runtime->channels - 1,
472         };
473
474         hdmi_setup_channel_allocation(codec, &ai);
475         hdmi_setup_channel_mapping(codec, &ai);
476
477         hdmi_fill_audio_infoframe(codec, &ai);
478         hdmi_start_infoframe_trans(codec);
479 }
480
481
482 /*
483  * Unsolicited events
484  */
485
486 static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
487 {
488         int pind = !!(res & AC_UNSOL_RES_PD);
489         int eldv = !!(res & AC_UNSOL_RES_ELDV);
490
491         printk(KERN_INFO
492                 "HDMI hot plug event: Presence_Detect=%d ELD_Valid=%d\n",
493                 pind, eldv);
494
495         if (pind && eldv) {
496                 hdmi_parse_eld(codec);
497                 /* TODO: do real things about ELD */
498         }
499 }
500
501 static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
502 {
503         int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
504         int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
505         int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
506
507         printk(KERN_INFO
508                 "HDMI content protection event: SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
509                 subtag,
510                 cp_state,
511                 cp_ready);
512
513         /* TODO */
514         if (cp_state)
515                 ;
516         if (cp_ready)
517                 ;
518 }
519
520
521 static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
522 {
523         int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
524         int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
525
526         if (tag != INTEL_HDMI_EVENT_TAG) {
527                 snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
528                 return;
529         }
530
531         if (subtag == 0)
532                 hdmi_intrinsic_event(codec, res);
533         else
534                 hdmi_non_intrinsic_event(codec, res);
535 }
536
537 /*
538  * Callbacks
539  */
540
541 static int intel_hdmi_playback_pcm_open(struct hda_pcm_stream *hinfo,
542                                         struct hda_codec *codec,
543                                         struct snd_pcm_substream *substream)
544 {
545         struct intel_hdmi_spec *spec = codec->spec;
546
547         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
548 }
549
550 static int intel_hdmi_playback_pcm_close(struct hda_pcm_stream *hinfo,
551                                          struct hda_codec *codec,
552                                          struct snd_pcm_substream *substream)
553 {
554         struct intel_hdmi_spec *spec = codec->spec;
555
556         hdmi_stop_infoframe_trans(codec);
557
558         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
559 }
560
561 static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
562                                            struct hda_codec *codec,
563                                            unsigned int stream_tag,
564                                            unsigned int format,
565                                            struct snd_pcm_substream *substream)
566 {
567         struct intel_hdmi_spec *spec = codec->spec;
568
569         snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
570                                              format, substream);
571
572         hdmi_set_channel_count(codec, substream->runtime->channels);
573
574         hdmi_setup_audio_infoframe(codec, substream);
575
576         return 0;
577 }
578
579 static struct hda_pcm_stream intel_hdmi_pcm_playback = {
580         .substreams = 1,
581         .channels_min = 2,
582         .channels_max = 8,
583         .ops = {
584                 .open    = intel_hdmi_playback_pcm_open,
585                 .close   = intel_hdmi_playback_pcm_close,
586                 .prepare = intel_hdmi_playback_pcm_prepare
587         },
588 };
589
590 static int intel_hdmi_build_pcms(struct hda_codec *codec)
591 {
592         struct intel_hdmi_spec *spec = codec->spec;
593         struct hda_pcm *info = &spec->pcm_rec;
594
595         codec->num_pcms = 1;
596         codec->pcm_info = info;
597
598         /* NID to query formats and rates and setup streams */
599         intel_hdmi_pcm_playback.nid = cvt_nid;
600
601         info->name = "INTEL HDMI";
602         info->pcm_type = HDA_PCM_TYPE_HDMI;
603         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = intel_hdmi_pcm_playback;
604
605         return 0;
606 }
607
608 static int intel_hdmi_build_controls(struct hda_codec *codec)
609 {
610         struct intel_hdmi_spec *spec = codec->spec;
611         int err;
612
613         err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
614         if (err < 0)
615                 return err;
616
617         return 0;
618 }
619
620 static int intel_hdmi_init(struct hda_codec *codec)
621 {
622         hdmi_enable_output(codec);
623
624         snd_hda_codec_write(codec, pin_nid, 0,
625                             AC_VERB_SET_UNSOLICITED_ENABLE,
626                             AC_USRSP_EN | INTEL_HDMI_EVENT_TAG);
627         return 0;
628 }
629
630 static void intel_hdmi_free(struct hda_codec *codec)
631 {
632         struct intel_hdmi_spec *spec = codec->spec;
633
634         snd_hda_eld_proc_free(codec, &spec->sink_eld);
635         kfree(spec);
636 }
637
638 static struct hda_codec_ops intel_hdmi_patch_ops = {
639         .init                   = intel_hdmi_init,
640         .free                   = intel_hdmi_free,
641         .build_pcms             = intel_hdmi_build_pcms,
642         .build_controls         = intel_hdmi_build_controls,
643         .unsol_event            = intel_hdmi_unsol_event,
644 };
645
646 static int do_patch_intel_hdmi(struct hda_codec *codec)
647 {
648         struct intel_hdmi_spec *spec;
649
650         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
651         if (spec == NULL)
652                 return -ENOMEM;
653
654         spec->multiout.num_dacs = 0;      /* no analog */
655         spec->multiout.max_channels = 8;
656         spec->multiout.dig_out_nid = cvt_nid;
657
658         codec->spec = spec;
659         codec->patch_ops = intel_hdmi_patch_ops;
660
661         snd_hda_eld_proc_new(codec, &spec->sink_eld);
662
663         init_channel_allocations();
664
665         return 0;
666 }
667
668 static int patch_intel_hdmi(struct hda_codec *codec)
669 {
670         cvt_nid = 0x02;
671         pin_nid = 0x03;
672         return do_patch_intel_hdmi(codec);
673 }
674
675 static int patch_intel_hdmi_ibexpeak(struct hda_codec *codec)
676 {
677         cvt_nid = 0x02;
678         pin_nid = 0x04;
679         return do_patch_intel_hdmi(codec);
680 }
681
682 static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
683         { .id = 0x808629fb, .name = "G45 DEVCL",  .patch = patch_intel_hdmi },
684         { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi },
685         { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi },
686         { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi },
687         { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi },
688         { .id = 0x80860054, .name = "Q57 DEVIBX", .patch = patch_intel_hdmi_ibexpeak },
689         { .id = 0x10951392, .name = "SiI1392 HDMI",     .patch = patch_intel_hdmi },
690         {} /* terminator */
691 };
692
693 MODULE_ALIAS("snd-hda-codec-id:808629fb");
694 MODULE_ALIAS("snd-hda-codec-id:80862801");
695 MODULE_ALIAS("snd-hda-codec-id:80862802");
696 MODULE_ALIAS("snd-hda-codec-id:80862803");
697 MODULE_ALIAS("snd-hda-codec-id:80862804");
698 MODULE_ALIAS("snd-hda-codec-id:80860054");
699 MODULE_ALIAS("snd-hda-codec-id:10951392");
700
701 MODULE_LICENSE("GPL");
702 MODULE_DESCRIPTION("Intel HDMI HD-audio codec");
703
704 static struct hda_codec_preset_list intel_list = {
705         .preset = snd_hda_preset_intelhdmi,
706         .owner = THIS_MODULE,
707 };
708
709 static int __init patch_intelhdmi_init(void)
710 {
711         return snd_hda_add_codec_preset(&intel_list);
712 }
713
714 static void __exit patch_intelhdmi_exit(void)
715 {
716         snd_hda_delete_codec_preset(&intel_list);
717 }
718
719 module_init(patch_intelhdmi_init)
720 module_exit(patch_intelhdmi_exit)