linux/sound/pci/hda/patch_intelhdmi.c
<<
>>
Prefs
   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
  36static hda_nid_t cvt_nid;       /* audio converter */
  37static hda_nid_t pin_nid;       /* HDMI output pin */
  38
  39#define INTEL_HDMI_EVENT_TAG            0x08
  40
  41struct intel_hdmi_spec {
  42        struct hda_multi_out multiout;
  43        struct hda_pcm pcm_rec;
  44        struct hdmi_eld sink_eld;
  45};
  46
  47struct 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 */
  75enum 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 */
  98static 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
 113struct 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 */
 128static 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
 192static 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
 204static 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
 214static 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
 220static 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 */
 234static 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 */
 244static 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
 251static 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
 257static 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
 267static 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
 282static 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
 296static 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
 313static 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
 342static 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 */
 364static 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*/
 389static 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
 442static 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
 464static 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
 486static 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
 501static 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
 521static 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
 541static 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
 550static 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
 561static 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
 579static 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
 590static 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
 608static 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
 620static 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
 630static 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
 638static 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
 646static 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
 668static 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
 675static 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
 682static 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
 693MODULE_ALIAS("snd-hda-codec-id:808629fb");
 694MODULE_ALIAS("snd-hda-codec-id:80862801");
 695MODULE_ALIAS("snd-hda-codec-id:80862802");
 696MODULE_ALIAS("snd-hda-codec-id:80862803");
 697MODULE_ALIAS("snd-hda-codec-id:80862804");
 698MODULE_ALIAS("snd-hda-codec-id:80860054");
 699MODULE_ALIAS("snd-hda-codec-id:10951392");
 700
 701MODULE_LICENSE("GPL");
 702MODULE_DESCRIPTION("Intel HDMI HD-audio codec");
 703
 704static struct hda_codec_preset_list intel_list = {
 705        .preset = snd_hda_preset_intelhdmi,
 706        .owner = THIS_MODULE,
 707};
 708
 709static int __init patch_intelhdmi_init(void)
 710{
 711        return snd_hda_add_codec_preset(&intel_list);
 712}
 713
 714static void __exit patch_intelhdmi_exit(void)
 715{
 716        snd_hda_delete_codec_preset(&intel_list);
 717}
 718
 719module_init(patch_intelhdmi_init)
 720module_exit(patch_intelhdmi_exit)
 721