All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-01 11:27 Wei Ni
  2010-03-02  5:43 ` [alsa-devel] " Wu Fengguang
  2010-03-02  7:59   ` Takashi Iwai
  0 siblings, 2 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-01 11:27 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

[-- Attachment #1: Type: text/plain, Size: 703 bytes --]

Hi, Takashi
I developed the hdmi audio driver for new chipset MCP89 and GT21x.
The new HAD controller and codec support standard HDMI operation.

I attached the patch file, please check it.


Thanks
Wei.


-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

[-- Attachment #2: 0001-Support-MCP89-and-GT21x-hdmi-audio.patch --]
[-- Type: application/octet-stream, Size: 39429 bytes --]

From 11ad56dda31098d90f28f595c0ad23879c92f452 Mon Sep 17 00:00:00 2001
From: Wei Ni <wni@nvidia.com>
Date: Mon, 1 Mar 2010 19:17:08 +0800
Subject: [PATCH] Support MCP89 and GT21x hdmi audio

1. Support MCP89 and GT21x 8ch hdmi audio
2. Add some eld support
3. Change AZX_MAX_CODECS from 4 to 8, since there are some codecs
connect to SDATA_IN[4,7].

Signed-off-by: Wei Ni <wni@nvidia.com>
---
 sound/pci/hda/hda_intel.c    |    2 +-
 sound/pci/hda/patch_nvhdmi.c | 1038 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 989 insertions(+), 51 deletions(-)

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d5c93ad..fbf2c29 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -267,7 +267,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define RIRB_INT_MASK		0x05
 
 /* STATESTS int mask: S3,SD2,SD1,SD0 */
-#define AZX_MAX_CODECS		4
+#define AZX_MAX_CODECS		8
 #define STATESTS_INT_MASK	((1 << AZX_MAX_CODECS) - 1)
 
 /* SD_CTL bits */
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 6afdab0..1c774f9 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -32,10 +32,11 @@
 /* define below to restrict the supported rates and formats */
 /* #define LIMITED_RATE_FMT_SUPPORT */
 
-struct nvhdmi_spec {
-	struct hda_multi_out multiout;
-
-	struct hda_pcm pcm_rec;
+enum HDACodec {
+	HDA_CODEC_NVIDIA_MCP7X,
+	HDA_CODEC_NVIDIA_MCP89,
+	HDA_CODEC_NVIDIA_GT21X,
+	HDA_CODEC_INVALID
 };
 
 #define Nv_VERB_SET_Channel_Allocation          0xF79
@@ -43,15 +44,18 @@ struct nvhdmi_spec {
 #define Nv_VERB_SET_Audio_Protection_On         0xF98
 #define Nv_VERB_SET_Audio_Protection_Off        0xF99
 
-#define Nv_Master_Convert_nid   0x04
-#define Nv_Master_Pin_nid       0x05
+#define nvhdmi_master_con_nid_7x	0x04
+#define nvhdmi_master_pin_nid_7x	0x05
 
-static hda_nid_t nvhdmi_convert_nids[4] = {
+#define nvhdmi_master_con_nid_89	0x04
+#define nvhdmi_master_pin_nid_89	0x05
+
+static hda_nid_t nvhdmi_con_nids_7x[4] = {
 	/*front, rear, clfe, rear_surr */
 	0x6, 0x8, 0xa, 0xc,
 };
 
-static struct hda_verb nvhdmi_basic_init[] = {
+static struct hda_verb nvhdmi_basic_init_7x[] = {
 	/* set audio protect on */
 	{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
 	/* enable digital output on pin widget */
@@ -79,6 +83,796 @@ static struct hda_verb nvhdmi_basic_init[] = {
 	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 #endif
 
+#define NVIDIA_89_HDMI_CVTS	1
+#define NVIDIA_89_HDMI_PINS	1
+
+static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = {
+	"NVIDIA HDMI",
+};
+
+struct nvhdmi_spec {
+	int num_cvts;
+	int num_pins;
+	hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1];  /* audio sources */
+	hda_nid_t pin[NVIDIA_89_HDMI_PINS+1];  /* audio sinks */
+	hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1];
+	struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS];
+	struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS];
+	struct hda_multi_out multiout;
+	unsigned int codec_type;
+};
+
+struct hdmi_audio_infoframe {
+	u8 type; /* 0x84 */
+	u8 ver;  /* 0x01 */
+	u8 len;  /* 0x0a */
+
+	u8 checksum;	/* PB0 */
+	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
+	u8 SS01_SF24;
+	u8 CXT04;
+	u8 CA;
+	u8 LFEPBL01_LSV36_DM_INH7;
+};
+
+/*
+ * CEA speaker placement:
+ *
+ *        FLH       FCH        FRH
+ *  FLW    FL  FLC   FC   FRC   FR   FRW
+ *
+ *                                  LFE
+ *                     TC
+ *
+ *          RL  RLC   RC   RRC   RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+	FL  = (1 <<  0),	/* Front Left           */
+	FC  = (1 <<  1),	/* Front Center         */
+	FR  = (1 <<  2),	/* Front Right          */
+	FLC = (1 <<  3),	/* Front Left Center    */
+	FRC = (1 <<  4),	/* Front Right Center   */
+	RL  = (1 <<  5),	/* Rear Left            */
+	RC  = (1 <<  6),	/* Rear Center          */
+	RR  = (1 <<  7),	/* Rear Right           */
+	RLC = (1 <<  8),	/* Rear Left Center     */
+	RRC = (1 <<  9),	/* Rear Right Center    */
+	LFE = (1 << 10),	/* Low Frequency Effect */
+	FLW = (1 << 11),	/* Front Left Wide      */
+	FRW = (1 << 12),	/* Front Right Wide     */
+	FLH = (1 << 13),	/* Front Left High      */
+	FCH = (1 << 14),	/* Front Center High    */
+	FRH = (1 << 15),	/* Front Right High     */
+	TC  = (1 << 16),	/* Top Center           */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+	[0] = FL | FR,
+	[1] = LFE,
+	[2] = FC,
+	[3] = RL | RR,
+	[4] = RC,
+	[5] = FLC | FRC,
+	[6] = RLC | RRC,
+	/* the following are not defined in ELD yet */
+	[7] = FLW | FRW,
+	[8] = FLH | FRH,
+	[9] = TC,
+	[10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+	int ca_index;
+	int speakers[8];
+
+	/* derived values, just for convenience */
+	int channels;
+	int spk_mask;
+};
+
+/*
+ * ALSA sequence is:
+ *
+ *       surround40   surround41   surround50   surround51   surround71
+ * ch0   front left   =            =            =            =
+ * ch1   front right  =            =            =            =
+ * ch2   rear left    =            =            =            =
+ * ch3   rear right   =            =            =            =
+ * ch4                LFE          center       center       center
+ * ch5                                          LFE          LFE
+ * ch6                                                       side left
+ * ch7                                                       side right
+ *
+ * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
+ */
+static int hdmi_channel_mapping[0x32][8] = {
+	/* stereo */
+	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* 2.1 */
+	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* Dolby Surround */
+	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* surround40 */
+	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
+	/* 4ch */
+	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
+	/* surround41 */
+	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround50 */
+	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround51 */
+	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
+	/* 7.1 */
+	[0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/* 			  channel:   7     6    5    4    3     2    1    0  */
+{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
+				 /* 2.1 */
+{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
+				 /* Dolby Surround */
+{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
+				 /* surround40 */
+{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
+				 /* surround41 */
+{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
+				 /* surround50 */
+{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+				 /* surround51 */
+{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* 6.1 */
+{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* surround71 */
+{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+
+{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
+{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
+};
+
+/*
+ * HDA/HDMI auto parsing
+ */
+
+static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+{
+	int i;
+
+	for (i = 0; nids[i]; i++)
+		if (nids[i] == nid)
+			return i;
+
+	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+	return -EINVAL;
+}
+
+static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+	int conn_len, curr;
+	int index;
+
+	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
+		snd_printk(KERN_WARNING
+			   "HDMI: pin %d wcaps %#x "
+			   "does not support connection list\n",
+			   pin_nid, get_wcaps(codec, pin_nid));
+		return -EINVAL;
+	}
+
+	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
+					   HDA_MAX_CONNECTIONS);
+	if (conn_len > 1)
+		curr = snd_hda_codec_read(codec, pin_nid, 0,
+					  AC_VERB_GET_CONNECT_SEL, 0);
+	else
+		curr = 0;
+
+	index = hda_node_index(spec->pin, pin_nid);
+	if (index < 0)
+		return -EINVAL;
+
+	spec->pin_cvt[index] = conn_list[curr];
+
+	return 0;
+}
+
+static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
+			      struct hdmi_eld *eld)
+{
+	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+		snd_hdmi_show_eld(eld);
+}
+
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+			       struct hdmi_eld *eld)
+{
+	int present = snd_hda_pin_sense(codec, pin_nid);
+
+	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
+	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
+
+	if (present & AC_PINSENSE_ELDV)
+		hdmi_get_show_eld(codec, pin_nid, eld);
+}
+
+static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+
+	if (spec->num_pins >= NVIDIA_89_HDMI_PINS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for pin %d \n", pin_nid);
+		return -EINVAL;
+	}
+
+	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+
+	spec->pin[spec->num_pins] = pin_nid;
+	spec->num_pins++;
+
+	/*
+	 * It is assumed that converter nodes come first in the node list and
+	 * hence have been registered and usable now.
+	 */
+	return nvhdmi_read_pin_conn(codec, pin_nid);
+}
+
+static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+
+	if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for converter %d \n", nid);
+		return -EINVAL;
+	}
+
+	spec->cvt[spec->num_cvts] = nid;
+	spec->num_cvts++;
+
+	return 0;
+}
+
+
+static int nvhdmi_parse_codec(struct hda_codec *codec)
+{
+	hda_nid_t nid;
+	int i, nodes;
+
+	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+	if (!nid || nodes < 0) {
+		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nodes; i++, nid++) {
+		unsigned int caps;
+		unsigned int type;
+
+		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+		type = get_wcaps_type(caps);
+
+		if (!(caps & AC_WCAP_DIGITAL))
+			continue;
+
+		switch (type) {
+		case AC_WID_AUD_OUT:
+			if (nvhdmi_add_cvt(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		case AC_WID_PIN:
+			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+				continue;
+			if (nvhdmi_add_pin(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		}
+	}
+
+	/*
+	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
+	 * can be lost and presence sense verb will become inaccurate if the
+	 * HDA link is powered off at hot plug or hw initialization time.
+	 */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+	      AC_PWRST_EPSS))
+		codec->bus->power_keep_link_on = 1;
+#endif
+
+	return 0;
+}
+
+/*
+ * HDMI routines
+ */
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int *packet_index, int *byte_index)
+{
+	int val;
+
+	val = snd_hda_codec_read(codec, pin_nid, 0,
+				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+	*packet_index = val >> 5;
+	*byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int packet_index, int byte_index)
+{
+	int val;
+
+	val = (packet_index << 5) | (byte_index & 0x1f);
+
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
+				unsigned char val)
+{
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	/* Unmute */
+	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
+		snd_hda_codec_write(codec, pin_nid, 0,
+				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	/* Enable pin out */
+	snd_hda_codec_write(codec, pin_nid, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+}
+
+/*
+ * Enable Audio InfoFrame Transmission
+ */
+static void hdmi_start_infoframe_trans(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_BEST);
+}
+
+/*
+ * Disable Audio InfoFrame Transmission
+ */
+static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
+				      hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_DISABLE);
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+{
+	return 1 + snd_hda_codec_read(codec, nid, 0,
+					AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec,
+				   hda_nid_t nid, int chs)
+{
+	if (chs != hdmi_get_channel_count(codec, nid))
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int slot;
+
+	for (i = 0; i < 8; i++) {
+		slot = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_CHAN_SLOT, i);
+		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+						slot >> 4, slot & 0xf);
+	}
+#endif
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int size;
+
+	size = snd_hdmi_get_eld_size(codec, pin_nid);
+	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+	}
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef BE_PARANOID
+	int i, j;
+	int size;
+	int pi, bi;
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		if (size == 0)
+			continue;
+
+		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
+		for (j = 1; j < 1000; j++) {
+			hdmi_write_dip_byte(codec, pin_nid, 0x0);
+			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
+			if (pi != i)
+				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+						bi, pi, i);
+			if (bi == 0) /* byte index wrapped around */
+				break;
+		}
+		snd_printd(KERN_INFO
+			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+			i, size, j);
+	}
+#endif
+}
+
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+{
+	ai->checksum = 0;
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+				      hda_nid_t pin_nid,
+				      struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	int i;
+
+	hdmi_debug_dip_size(codec, pin_nid);
+	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
+
+	hdmi_checksum_audio_infoframe(ai);
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++)
+		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+}
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+	int i, j;
+	struct cea_channel_speaker_allocation *p;
+
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		p = channel_allocations + i;
+		p->channels = 0;
+		p->spk_mask = 0;
+		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+			if (p->speakers[j]) {
+				p->channels++;
+				p->spk_mask |= p->speakers[j];
+			}
+	}
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ * 	      spk_mask => (channel_allocations[])         => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+					 struct hdmi_audio_infoframe *ai)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_eld *eld;
+	int i;
+	int spk_mask = 0;
+	int channels = 1 + (ai->CC02_CT47 & 0x7);
+	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+	/*
+	 * CA defaults to 0 for basic stereo audio
+	 */
+	if (channels <= 2)
+		return 0;
+
+	i = hda_node_index(spec->pin_cvt, nid);
+	if (i < 0)
+		return 0;
+	eld = &spec->sink_eld[i];
+
+	/*
+	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+	 * in console or for audio devices. Assume the highest speakers
+	 * configuration, to _not_ prohibit multi-channel audio playback.
+	 */
+	if (!eld->spk_alloc)
+		eld->spk_alloc = 0xffff;
+
+	/*
+	 * expand ELD's speaker allocation mask
+	 *
+	 * ELD tells the speaker mask in a compact(paired) form,
+	 * expand ELD's notions to match the ones used by Audio InfoFrame.
+	 */
+	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+		if (eld->spk_alloc & (1 << i))
+			spk_mask |= eld_speaker_allocation_bits[i];
+	}
+
+	/* search for the first working match in the CA table */
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		if (channels == channel_allocations[i].channels &&
+		    (spk_mask & channel_allocations[i].spk_mask) ==
+				channel_allocations[i].spk_mask) {
+			ai->CA = channel_allocations[i].ca_index;
+			break;
+		}
+	}
+
+	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+	snd_printdd(KERN_INFO
+			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+			ai->CA, channels, buf);
+
+	return ai->CA;
+}
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid,
+				       struct hdmi_audio_infoframe *ai)
+{
+	int i;
+	int ca = ai->CA;
+	int err;
+
+	if (hdmi_channel_mapping[ca][1] == 0) {
+		for (i = 0; i < channel_allocations[ca].channels; i++)
+			hdmi_channel_mapping[ca][i] = i | (i << 4);
+		for (; i < 8; i++)
+			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+	}
+
+	for (i = 0; i < 8; i++) {
+		err = snd_hda_codec_write(codec, pin_nid, 0,
+					  AC_VERB_SET_HDMI_CHAN_SLOT,
+					  hdmi_channel_mapping[ca][i]);
+		if (err) {
+			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
+			break;
+		}
+	}
+
+	hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
+				    struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	u8 val;
+	int i;
+
+	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
+							    != AC_DIPXMIT_BEST)
+		return false;
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++) {
+		val = snd_hda_codec_read(codec, pin_nid, 0,
+					 AC_VERB_GET_HDMI_DIP_DATA, 0);
+		if (val != bytes[i])
+			return false;
+	}
+
+	return true;
+}
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+					struct snd_pcm_substream *substream)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	hda_nid_t pin_nid;
+	int i;
+	struct hdmi_audio_infoframe ai = {
+		.type		= 0x84,
+		.ver		= 0x01,
+		.len		= 0x0a,
+		.CC02_CT47	= substream->runtime->channels - 1,
+	};
+
+	hdmi_setup_channel_allocation(codec, nid, &ai);
+
+	for (i = 0; i < spec->num_pins; i++) {
+		if (spec->pin_cvt[i] != nid)
+			continue;
+		if (!spec->sink_eld[i].monitor_present)
+			continue;
+
+		pin_nid = spec->pin[i];
+		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+			hdmi_stop_infoframe_trans(codec, pin_nid);
+			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+			hdmi_start_infoframe_trans(codec, pin_nid);
+		}
+	}
+}
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int pind = !!(res & AC_UNSOL_RES_PD);
+	int eldv = !!(res & AC_UNSOL_RES_ELDV);
+	int index;
+
+	printk(KERN_INFO
+		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+		tag, pind, eldv);
+
+	index = hda_node_index(spec->pin, tag);
+	if (index < 0)
+		return;
+
+	spec->sink_eld[index].monitor_present = pind;
+	spec->sink_eld[index].eld_valid = eldv;
+
+	if (eldv) {
+		spec->sink_eld[index].monitor_present = 1;
+		hdmi_get_show_eld(codec, spec->pin[index],
+				 &spec->sink_eld[index]);
+		/* TODO: do real things about ELD */
+	}
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+	printk(KERN_INFO
+		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+		tag,
+		subtag,
+		cp_state,
+		cp_ready);
+
+	/* TODO */
+	if (cp_state)
+		;
+	if (cp_ready)
+		;
+}
+
+static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+	if (hda_node_index(spec->pin, tag) < 0) {
+		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+		return;
+	}
+
+	if (subtag == 0)
+		hdmi_intrinsic_event(codec, res);
+	else
+		hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+			      u32 stream_tag, int format)
+{
+	int tag;
+	int fmt;
+
+	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
+	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
+
+	snd_printdd("hdmi_setup_stream: "
+		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
+		    nid,
+		    tag == stream_tag ? "" : "new-",
+		    stream_tag,
+		    fmt == format ? "" : "new-",
+		    format);
+
+	if (tag != stream_tag)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CHANNEL_STREAMID,
+				    stream_tag << 4);
+	if (fmt != format)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_STREAM_FORMAT, format);
+}
+
 /*
  * Controls
  */
@@ -86,20 +880,58 @@ static int nvhdmi_build_controls(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec = codec->spec;
 	int err;
+	int i;
 
-	err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
-	if (err < 0)
-		return err;
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; i < codec->num_pcms; i++) {
+			err = snd_hda_create_spdif_out_ctls(codec,
+							    spec->cvt[i]);
+			if (err < 0)
+				return err;
+		}
+	} else {
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+	}
 
 	return 0;
 }
 
 static int nvhdmi_init(struct hda_codec *codec)
 {
-	snd_hda_sequence_write(codec, nvhdmi_basic_init);
+	struct nvhdmi_spec *spec = codec->spec;
+	int i;
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; spec->pin[i]; i++) {
+			hdmi_enable_output(codec, spec->pin[i]);
+			snd_hda_codec_write(codec, spec->pin[i], 0,
+					    AC_VERB_SET_UNSOLICITED_ENABLE,
+					    AC_USRSP_EN | spec->pin[i]);
+		}
+	} else {
+		snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
+	}
 	return 0;
 }
 
+static void nvhdmi_free(struct hda_codec *codec)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	int i;
+
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; i < spec->num_pins; i++)
+			snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
+	}
+
+	kfree(spec);
+}
+
 /*
  * Digital out
  */
@@ -111,21 +943,21 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 }
 
-static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
+static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
 	struct nvhdmi_spec *spec = codec->spec;
 	int i;
 
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
 			0, AC_VERB_SET_CHANNEL_STREAMID, 0);
 	for (i = 0; i < 4; i++) {
 		/* set the stream id */
-		snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
 				AC_VERB_SET_CHANNEL_STREAMID, 0);
 		/* set the stream format */
-		snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
 				AC_VERB_SET_STREAM_FORMAT, 0);
 	}
 
@@ -140,6 +972,21 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					unsigned int stream_tag,
+					unsigned int format,
+					struct snd_pcm_substream *substream)
+{
+	hdmi_set_channel_count(codec, hinfo->nid,
+			       substream->runtime->channels);
+
+	hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
+
+	hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
+	return 0;
+}
+
 static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					unsigned int stream_tag,
@@ -181,29 +1028,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
 
 	/* set the stream id */
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
 			AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
 
 	/* set the stream format */
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
 			AC_VERB_SET_STREAM_FORMAT, format);
 
 	/* turn on again (if needed) */
 	/* enable and set the channel status audio/data flag */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & 0xff);
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
 	}
@@ -220,19 +1067,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 		if (codec->spdif_status_reset &&
 		(codec->spdif_ctls & AC_DIG1_ENABLE))
 			snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
 		/* set the stream id */
 		snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_CHANNEL_STREAMID,
 				(stream_tag << 4) | channel_id);
 		/* set the stream format */
 		snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_STREAM_FORMAT,
 				format);
@@ -241,12 +1088,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 		if (codec->spdif_status_reset &&
 		(codec->spdif_ctls & AC_DIG1_ENABLE)) {
 			snd_hda_codec_write(codec,
-					nvhdmi_convert_nids[i],
+					nvhdmi_con_nids_7x[i],
 					0,
 					AC_VERB_SET_DIGI_CONVERT_1,
 					codec->spdif_ctls & 0xff);
 			snd_hda_codec_write(codec,
-					nvhdmi_convert_nids[i],
+					nvhdmi_con_nids_7x[i],
 					0,
 					AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
 		}
@@ -261,6 +1108,13 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 	return 0;
 }
 
+static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
 static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					unsigned int stream_tag,
@@ -272,17 +1126,29 @@ static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
 					format, substream);
 }
 
-static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
+	.substreams = 1,
+	.channels_min = 2,
+	.rates = SUPPORTED_RATES,
+	.maxbps = SUPPORTED_MAXBPS,
+	.formats = SUPPORTED_FORMATS,
+	.ops = {
+		.prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
+		.cleanup = nvhdmi_playback_pcm_cleanup,
+	},
+};
+
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 8,
-	.nid = Nv_Master_Convert_nid,
+	.nid = nvhdmi_master_con_nid_7x,
 	.rates = SUPPORTED_RATES,
 	.maxbps = SUPPORTED_MAXBPS,
 	.formats = SUPPORTED_FORMATS,
 	.ops = {
 		.open = nvhdmi_dig_playback_pcm_open,
-		.close = nvhdmi_dig_playback_pcm_close_8ch,
+		.close = nvhdmi_dig_playback_pcm_close_8ch_7x,
 		.prepare = nvhdmi_dig_playback_pcm_prepare_8ch
 	},
 };
@@ -291,7 +1157,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
-	.nid = Nv_Master_Convert_nid,
+	.nid = nvhdmi_master_con_nid_7x,
 	.rates = SUPPORTED_RATES,
 	.maxbps = SUPPORTED_MAXBPS,
 	.formats = SUPPORTED_FORMATS,
@@ -302,10 +1168,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
 	},
 };
 
-static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
+static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+	int i;
+
+	codec->num_pcms = spec->num_cvts;
+	codec->pcm_info = info;
+
+	for (i = 0; i < codec->num_pcms; i++, info++) {
+		unsigned int chans;
+
+		chans = get_wcaps(codec, spec->cvt[i]);
+		chans = get_wcaps_channels(chans);
+
+		info->name = nvhdmi_pcm_names[i];
+		info->pcm_type = HDA_PCM_TYPE_HDMI;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK]
+					= nvhdmi_pcm_digital_playback_8ch_89;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
+	}
+
+	return 0;
+}
+
+static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = &spec->pcm_rec;
+	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
@@ -313,7 +1205,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
 	info->name = "NVIDIA HDMI";
 	info->pcm_type = HDA_PCM_TYPE_HDMI;
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK]
-					= nvhdmi_pcm_digital_playback_8ch;
+					= nvhdmi_pcm_digital_playback_8ch_7x;
 
 	return 0;
 }
@@ -321,7 +1213,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
 static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = &spec->pcm_rec;
+	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
@@ -334,14 +1226,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 	return 0;
 }
 
-static void nvhdmi_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
+	.build_controls = nvhdmi_build_controls,
+	.build_pcms = nvhdmi_build_pcms_8ch_89,
+	.init = nvhdmi_init,
+	.free = nvhdmi_free,
+	.unsol_event = nvhdmi_unsol_event,
+};
 
-static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
 	.build_controls = nvhdmi_build_controls,
-	.build_pcms = nvhdmi_build_pcms_8ch,
+	.build_pcms = nvhdmi_build_pcms_8ch_7x,
 	.init = nvhdmi_init,
 	.free = nvhdmi_free,
 };
@@ -353,7 +1248,34 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
 	.free = nvhdmi_free,
 };
 
-static int patch_nvhdmi_8ch(struct hda_codec *codec)
+static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
+{
+	struct nvhdmi_spec *spec;
+	int i;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
+
+	if (nvhdmi_parse_codec(codec) < 0) {
+		codec->spec = NULL;
+		kfree(spec);
+		return -EINVAL;
+	}
+	codec->patch_ops = nvhdmi_patch_ops_8ch_89;
+
+	for (i = 0; i < spec->num_pins; i++)
+		snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
+
+	init_channel_allocations();
+
+	return 0;
+}
+
+static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec;
 
@@ -365,9 +1287,10 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec)
 
 	spec->multiout.num_dacs = 0;  /* no analog */
 	spec->multiout.max_channels = 8;
-	spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+	spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
 
-	codec->patch_ops = nvhdmi_patch_ops_8ch;
+	codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
 
 	return 0;
 }
@@ -384,7 +1307,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
 
 	spec->multiout.num_dacs = 0;  /* no analog */
 	spec->multiout.max_channels = 2;
-	spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+	spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
 
 	codec->patch_ops = nvhdmi_patch_ops_2ch;
 
@@ -395,13 +1319,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
  * patch entries
  */
 static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
-	{ .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
 	{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
 	{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
+	{ .id = 0x10de0002, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0003, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0005, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0006, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0007, .name = "MCP79/7A HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de000c, .name = "MCP89 HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
+	{ .id = 0x10de000b, .name = "GT21x HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
+	{ .id = 0x10de000d, .name = "GT240 HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
 	{} /* terminator */
 };
 
@@ -412,9 +1347,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006");
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:10de000c");
+MODULE_ALIAS("snd-hda-codec-id:10de000b");
+MODULE_ALIAS("snd-hda-codec-id:10de000d");
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
+MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
 
 static struct hda_codec_preset_list nvhdmi_list = {
 	.preset = snd_hda_preset_nvhdmi,
-- 
1.5.6


[-- Attachment #3: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* Re: [alsa-devel]  [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-01 11:27 [PATCH]Support MCP89 and GT21x hdmi audio Wei Ni
@ 2010-03-02  5:43 ` Wu Fengguang
  2010-03-03  3:33     ` Wei Ni
  2010-03-03  6:46     ` Takashi Iwai
  2010-03-02  7:59   ` Takashi Iwai
  1 sibling, 2 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-02  5:43 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Takashi Iwai', 'akpm', 'alsa-devel',
	'linux-kernel', 'Pavel Hofman'

On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> Hi, Takashi
> I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> The new HAD controller and codec support standard HDMI operation.
> 
> I attached the patch file, please check it.

Wei Ni,

Can we avoid the big copy&paste and do more code reuse?
This benefits all of us in long term.

Thanks,
Fengguang

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-01 11:27 [PATCH]Support MCP89 and GT21x hdmi audio Wei Ni
@ 2010-03-02  7:59   ` Takashi Iwai
  2010-03-02  7:59   ` Takashi Iwai
  1 sibling, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-02  7:59 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

At Mon, 1 Mar 2010 19:27:53 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> The new HAD controller and codec support standard HDMI operation.
> 
> I attached the patch file, please check it.

Thanks.  A brief review comments below.


> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> index d5c93ad..fbf2c29 100644
> --- a/sound/pci/hda/hda_intel.c
> +++ b/sound/pci/hda/hda_intel.c
> @@ -267,7 +267,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
>  #define RIRB_INT_MASK		0x05
>  
>  /* STATESTS int mask: S3,SD2,SD1,SD0 */
> -#define AZX_MAX_CODECS		4
> +#define AZX_MAX_CODECS		8

Changing this blindly to all codecs seems a bit dangerous.
We have bad experiences regarding the codec probing, and probing more
codec slots may result in unexpected behavior with the older chip.

Do you know which controller chip supports more than 4 slots?
 

> +struct hdmi_audio_infoframe {
> +	u8 type; /* 0x84 */
> +	u8 ver;  /* 0x01 */
> +	u8 len;  /* 0x0a */
> +
> +	u8 checksum;	/* PB0 */
> +	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
> +	u8 SS01_SF24;
> +	u8 CXT04;
> +	u8 CA;
> +	u8 LFEPBL01_LSV36_DM_INH7;
...

Let's merge the stuff with patch_intelhdmi.c later...


> +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
> +			      struct hdmi_eld *eld)
> +{
> +	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
> +		snd_hdmi_show_eld(eld);

So, now this module depends on the ELD helper?
Then we need to change Makefile and Kconfig as well.
Right now, the eld helper is built into intel-hdmi module.  Now this
is needed to be individual or built-in snd-hda-codec.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-02  7:59   ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-02  7:59 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

At Mon, 1 Mar 2010 19:27:53 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> The new HAD controller and codec support standard HDMI operation.
> 
> I attached the patch file, please check it.

Thanks.  A brief review comments below.


> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> index d5c93ad..fbf2c29 100644
> --- a/sound/pci/hda/hda_intel.c
> +++ b/sound/pci/hda/hda_intel.c
> @@ -267,7 +267,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
>  #define RIRB_INT_MASK		0x05
>  
>  /* STATESTS int mask: S3,SD2,SD1,SD0 */
> -#define AZX_MAX_CODECS		4
> +#define AZX_MAX_CODECS		8

Changing this blindly to all codecs seems a bit dangerous.
We have bad experiences regarding the codec probing, and probing more
codec slots may result in unexpected behavior with the older chip.

Do you know which controller chip supports more than 4 slots?
 

> +struct hdmi_audio_infoframe {
> +	u8 type; /* 0x84 */
> +	u8 ver;  /* 0x01 */
> +	u8 len;  /* 0x0a */
> +
> +	u8 checksum;	/* PB0 */
> +	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
> +	u8 SS01_SF24;
> +	u8 CXT04;
> +	u8 CA;
> +	u8 LFEPBL01_LSV36_DM_INH7;
...

Let's merge the stuff with patch_intelhdmi.c later...


> +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
> +			      struct hdmi_eld *eld)
> +{
> +	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
> +		snd_hdmi_show_eld(eld);

So, now this module depends on the ELD helper?
Then we need to change Makefile and Kconfig as well.
Right now, the eld helper is built into intel-hdmi module.  Now this
is needed to be individual or built-in snd-hda-codec.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-02  7:59   ` Takashi Iwai
@ 2010-03-02  9:43     ` Wei Ni
  -1 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-02  9:43 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

Hi, Takashi
1. About AZX_MAX_CODECS, on our new chipset, the codec_mask=0x31, it means
the codec connect on the slot0, slot4, slot5, and on some GT2xx, the codec
will connect to slot6 or slot7, although these chip at most have 4 codecs.
So I change the AZX_MAX_CODECS to 8 directly.
In hda_intel.c, the azx_command_addr(), azx_response_addr(), and
azx_codec_create() use the AZX_MAX_CODECS, if it set as 4, the driver will
not detect the codecs which connect to slot4~7.

2. yes, it's better to merge the hdmi common codes.

3. About ELD, yes, we need to change the Makefile and Kconfig as well.
Could you help me to change it.

Thanks
Wei.

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Tuesday, March 02, 2010 4:00 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Mon, 1 Mar 2010 19:27:53 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> The new HAD controller and codec support standard HDMI operation.
> 
> I attached the patch file, please check it.

Thanks.  A brief review comments below.


> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> index d5c93ad..fbf2c29 100644
> --- a/sound/pci/hda/hda_intel.c
> +++ b/sound/pci/hda/hda_intel.c
> @@ -267,7 +267,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
>  #define RIRB_INT_MASK		0x05
>  
>  /* STATESTS int mask: S3,SD2,SD1,SD0 */
> -#define AZX_MAX_CODECS		4
> +#define AZX_MAX_CODECS		8

Changing this blindly to all codecs seems a bit dangerous.
We have bad experiences regarding the codec probing, and probing more
codec slots may result in unexpected behavior with the older chip.

Do you know which controller chip supports more than 4 slots?
 

> +struct hdmi_audio_infoframe {
> +	u8 type; /* 0x84 */
> +	u8 ver;  /* 0x01 */
> +	u8 len;  /* 0x0a */
> +
> +	u8 checksum;	/* PB0 */
> +	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
> +	u8 SS01_SF24;
> +	u8 CXT04;
> +	u8 CA;
> +	u8 LFEPBL01_LSV36_DM_INH7;
...

Let's merge the stuff with patch_intelhdmi.c later...


> +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
> +			      struct hdmi_eld *eld)
> +{
> +	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
> +		snd_hdmi_show_eld(eld);

So, now this module depends on the ELD helper?
Then we need to change Makefile and Kconfig as well.
Right now, the eld helper is built into intel-hdmi module.  Now this
is needed to be individual or built-in snd-hda-codec.


thanks,

Takashi
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-02  9:43     ` Wei Ni
  0 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-02  9:43 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

Hi, Takashi
1. About AZX_MAX_CODECS, on our new chipset, the codec_mask=0x31, it means
the codec connect on the slot0, slot4, slot5, and on some GT2xx, the codec
will connect to slot6 or slot7, although these chip at most have 4 codecs.
So I change the AZX_MAX_CODECS to 8 directly.
In hda_intel.c, the azx_command_addr(), azx_response_addr(), and
azx_codec_create() use the AZX_MAX_CODECS, if it set as 4, the driver will
not detect the codecs which connect to slot4~7.

2. yes, it's better to merge the hdmi common codes.

3. About ELD, yes, we need to change the Makefile and Kconfig as well.
Could you help me to change it.

Thanks
Wei.

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Tuesday, March 02, 2010 4:00 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Mon, 1 Mar 2010 19:27:53 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> The new HAD controller and codec support standard HDMI operation.
> 
> I attached the patch file, please check it.

Thanks.  A brief review comments below.


> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> index d5c93ad..fbf2c29 100644
> --- a/sound/pci/hda/hda_intel.c
> +++ b/sound/pci/hda/hda_intel.c
> @@ -267,7 +267,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
>  #define RIRB_INT_MASK		0x05
>  
>  /* STATESTS int mask: S3,SD2,SD1,SD0 */
> -#define AZX_MAX_CODECS		4
> +#define AZX_MAX_CODECS		8

Changing this blindly to all codecs seems a bit dangerous.
We have bad experiences regarding the codec probing, and probing more
codec slots may result in unexpected behavior with the older chip.

Do you know which controller chip supports more than 4 slots?
 

> +struct hdmi_audio_infoframe {
> +	u8 type; /* 0x84 */
> +	u8 ver;  /* 0x01 */
> +	u8 len;  /* 0x0a */
> +
> +	u8 checksum;	/* PB0 */
> +	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
> +	u8 SS01_SF24;
> +	u8 CXT04;
> +	u8 CA;
> +	u8 LFEPBL01_LSV36_DM_INH7;
...

Let's merge the stuff with patch_intelhdmi.c later...


> +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
> +			      struct hdmi_eld *eld)
> +{
> +	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
> +		snd_hdmi_show_eld(eld);

So, now this module depends on the ELD helper?
Then we need to change Makefile and Kconfig as well.
Right now, the eld helper is built into intel-hdmi module.  Now this
is needed to be individual or built-in snd-hda-codec.


thanks,

Takashi
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-02  9:43     ` Wei Ni
@ 2010-03-02  9:55       ` Takashi Iwai
  -1 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-02  9:55 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

At Tue, 2 Mar 2010 17:43:28 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> 1. About AZX_MAX_CODECS, on our new chipset, the codec_mask=0x31, it means
> the codec connect on the slot0, slot4, slot5, and on some GT2xx, the codec
> will connect to slot6 or slot7, although these chip at most have 4 codecs.
> So I change the AZX_MAX_CODECS to 8 directly.
> In hda_intel.c, the azx_command_addr(), azx_response_addr(), and
> azx_codec_create() use the AZX_MAX_CODECS, if it set as 4, the driver will
> not detect the codecs which connect to slot4~7.

Yeah, I understand it.  But, as mentioned, changing this to *all*
controller chips is dangerous.
We have already a quirk for controller chips to set max codecs depending
on the chip model.  Right now, only teradici chip sets to 1.

So, add "#define AZX_DEFAULT_CODECS 4", and use this value unless
azx_max_codecs[] is defined.  And, for the new controller chip
supporting more than 4, it can has 8 in azx_max_codecs[].

Is it feasible?

> 2. yes, it's better to merge the hdmi common codes.
> 3. About ELD, yes, we need to change the Makefile and Kconfig as well.
> Could you help me to change it.

In sound/pci/hda/Makefile, hda_eld.c is built into snd-hda-codec-intelhdmi
by the following rule:

snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o

Since now hda_eld.c is used in two modules, this has to be in the common
place, such as snd-hda-codec.  For this, uncomment the line:

# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o

and remove hda_eld.o from snd-hda-codec-intelhdmi-objs line.

For Kconfig, right now we have the definition

config SND_HDA_ELD
	def_bool y
	depends on SND_HDA_CODEC_INTELHDMI

Change depends on like

	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI

This can be done via "select" instead.  But, we'd merge all hdmi codes
later, so which way to choose is no big matter.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-02  9:55       ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-02  9:55 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

At Tue, 2 Mar 2010 17:43:28 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> 1. About AZX_MAX_CODECS, on our new chipset, the codec_mask=0x31, it means
> the codec connect on the slot0, slot4, slot5, and on some GT2xx, the codec
> will connect to slot6 or slot7, although these chip at most have 4 codecs.
> So I change the AZX_MAX_CODECS to 8 directly.
> In hda_intel.c, the azx_command_addr(), azx_response_addr(), and
> azx_codec_create() use the AZX_MAX_CODECS, if it set as 4, the driver will
> not detect the codecs which connect to slot4~7.

Yeah, I understand it.  But, as mentioned, changing this to *all*
controller chips is dangerous.
We have already a quirk for controller chips to set max codecs depending
on the chip model.  Right now, only teradici chip sets to 1.

So, add "#define AZX_DEFAULT_CODECS 4", and use this value unless
azx_max_codecs[] is defined.  And, for the new controller chip
supporting more than 4, it can has 8 in azx_max_codecs[].

Is it feasible?

> 2. yes, it's better to merge the hdmi common codes.
> 3. About ELD, yes, we need to change the Makefile and Kconfig as well.
> Could you help me to change it.

In sound/pci/hda/Makefile, hda_eld.c is built into snd-hda-codec-intelhdmi
by the following rule:

snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o

Since now hda_eld.c is used in two modules, this has to be in the common
place, such as snd-hda-codec.  For this, uncomment the line:

# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o

and remove hda_eld.o from snd-hda-codec-intelhdmi-objs line.

For Kconfig, right now we have the definition

config SND_HDA_ELD
	def_bool y
	depends on SND_HDA_CODEC_INTELHDMI

Change depends on like

	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI

This can be done via "select" instead.  But, we'd merge all hdmi codes
later, so which way to choose is no big matter.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-02  9:55       ` Takashi Iwai
  (?)
@ 2010-03-02 10:03       ` Wei Ni
  2010-03-02 10:42           ` Takashi Iwai
  -1 siblings, 1 reply; 80+ messages in thread
From: Wei Ni @ 2010-03-02 10:03 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

Yes, you are right. We should use quirk to set max codecs.

Thanks a lot
Wei.


-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Tuesday, March 02, 2010 5:55 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Tue, 2 Mar 2010 17:43:28 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> 1. About AZX_MAX_CODECS, on our new chipset, the codec_mask=0x31, it means
> the codec connect on the slot0, slot4, slot5, and on some GT2xx, the codec
> will connect to slot6 or slot7, although these chip at most have 4 codecs.
> So I change the AZX_MAX_CODECS to 8 directly.
> In hda_intel.c, the azx_command_addr(), azx_response_addr(), and
> azx_codec_create() use the AZX_MAX_CODECS, if it set as 4, the driver will
> not detect the codecs which connect to slot4~7.

Yeah, I understand it.  But, as mentioned, changing this to *all*
controller chips is dangerous.
We have already a quirk for controller chips to set max codecs depending
on the chip model.  Right now, only teradici chip sets to 1.

So, add "#define AZX_DEFAULT_CODECS 4", and use this value unless
azx_max_codecs[] is defined.  And, for the new controller chip
supporting more than 4, it can has 8 in azx_max_codecs[].

Is it feasible?

> 2. yes, it's better to merge the hdmi common codes.
> 3. About ELD, yes, we need to change the Makefile and Kconfig as well.
> Could you help me to change it.

In sound/pci/hda/Makefile, hda_eld.c is built into snd-hda-codec-intelhdmi
by the following rule:

snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o

Since now hda_eld.c is used in two modules, this has to be in the common
place, such as snd-hda-codec.  For this, uncomment the line:

# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o

and remove hda_eld.o from snd-hda-codec-intelhdmi-objs line.

For Kconfig, right now we have the definition

config SND_HDA_ELD
	def_bool y
	depends on SND_HDA_CODEC_INTELHDMI

Change depends on like

	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI

This can be done via "select" instead.  But, we'd merge all hdmi codes
later, so which way to choose is no big matter.


thanks,

Takashi
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-02 10:03       ` [alsa-devel] " Wei Ni
@ 2010-03-02 10:42           ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-02 10:42 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

At Tue, 2 Mar 2010 18:03:15 +0800,
Wei Ni wrote:
> 
> Yes, you are right. We should use quirk to set max codecs.

Also, could you split to two patches, one for extending max codecs for
the new controller and one for the new HDMI codec support?


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-02 10:42           ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-02 10:42 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

At Tue, 2 Mar 2010 18:03:15 +0800,
Wei Ni wrote:
> 
> Yes, you are right. We should use quirk to set max codecs.

Also, could you split to two patches, one for extending max codecs for
the new controller and one for the new HDMI codec support?


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-02 10:42           ` Takashi Iwai
  (?)
@ 2010-03-02 10:44           ` Wei Ni
  -1 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-02 10:44 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

Ok, it's no problems.

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Tuesday, March 02, 2010 6:43 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Tue, 2 Mar 2010 18:03:15 +0800,
Wei Ni wrote:
> 
> Yes, you are right. We should use quirk to set max codecs.

Also, could you split to two patches, one for extending max codecs for
the new controller and one for the new HDMI codec support?


thanks,

Takashi
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-02  9:55       ` Takashi Iwai
  (?)
  (?)
@ 2010-03-03  3:28       ` Wei Ni
  2010-03-03  4:06         ` Wei Ni
  -1 siblings, 1 reply; 80+ messages in thread
From: Wei Ni @ 2010-03-03  3:28 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

Hi, Takashi
I still have a question about AZX_MAX_CODECS.
In azx_command_addr() and azx_response_addr(), they use AZX_MAX_CODECS like
If (addr >= AZX_MAX_CODECS) {
    snd_BUG();
    addr = 0;
}
The azx_max_codes[] could not be used in these functions.
How could we do in these functions?

Thanks
Wei.

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Tuesday, March 02, 2010 5:55 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Tue, 2 Mar 2010 17:43:28 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> 1. About AZX_MAX_CODECS, on our new chipset, the codec_mask=0x31, it means
> the codec connect on the slot0, slot4, slot5, and on some GT2xx, the codec
> will connect to slot6 or slot7, although these chip at most have 4 codecs.
> So I change the AZX_MAX_CODECS to 8 directly.
> In hda_intel.c, the azx_command_addr(), azx_response_addr(), and
> azx_codec_create() use the AZX_MAX_CODECS, if it set as 4, the driver will
> not detect the codecs which connect to slot4~7.

Yeah, I understand it.  But, as mentioned, changing this to *all*
controller chips is dangerous.
We have already a quirk for controller chips to set max codecs depending
on the chip model.  Right now, only teradici chip sets to 1.

So, add "#define AZX_DEFAULT_CODECS 4", and use this value unless
azx_max_codecs[] is defined.  And, for the new controller chip
supporting more than 4, it can has 8 in azx_max_codecs[].

Is it feasible?

> 2. yes, it's better to merge the hdmi common codes.
> 3. About ELD, yes, we need to change the Makefile and Kconfig as well.
> Could you help me to change it.

In sound/pci/hda/Makefile, hda_eld.c is built into snd-hda-codec-intelhdmi
by the following rule:

snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o

Since now hda_eld.c is used in two modules, this has to be in the common
place, such as snd-hda-codec.  For this, uncomment the line:

# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o

and remove hda_eld.o from snd-hda-codec-intelhdmi-objs line.

For Kconfig, right now we have the definition

config SND_HDA_ELD
	def_bool y
	depends on SND_HDA_CODEC_INTELHDMI

Change depends on like

	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI

This can be done via "select" instead.  But, we'd merge all hdmi codes
later, so which way to choose is no big matter.


thanks,

Takashi
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel]  [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-02  5:43 ` [alsa-devel] " Wu Fengguang
@ 2010-03-03  3:33     ` Wei Ni
  2010-03-03  6:46     ` Takashi Iwai
  1 sibling, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-03  3:33 UTC (permalink / raw)
  To: 'Wu Fengguang'
  Cc: 'Takashi Iwai', 'akpm', 'alsa-devel',
	'linux-kernel', 'Pavel Hofman'

Hi,
Because there have no common codes for standard HDMI operation,
So in my patch file, there have some codes same as patch_intelhdmi.c
I think we could merge them later.

Thanks
Wei.

-----Original Message-----
From: Wu Fengguang [mailto:fengguang.wu@intel.com] 
Sent: Tuesday, March 02, 2010 1:43 PM
To: Wei Ni
Cc: 'Takashi Iwai'; 'akpm'; 'alsa-devel'; 'linux-kernel'; 'Pavel Hofman'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> Hi, Takashi
> I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> The new HAD controller and codec support standard HDMI operation.
> 
> I attached the patch file, please check it.

Wei Ni,

Can we avoid the big copy&paste and do more code reuse?
This benefits all of us in long term.

Thanks,
Fengguang
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-03  3:33     ` Wei Ni
  0 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-03  3:33 UTC (permalink / raw)
  To: 'Wu Fengguang'
  Cc: 'Takashi Iwai', 'akpm', 'alsa-devel',
	'Pavel Hofman', 'linux-kernel'

Hi,
Because there have no common codes for standard HDMI operation,
So in my patch file, there have some codes same as patch_intelhdmi.c
I think we could merge them later.

Thanks
Wei.

-----Original Message-----
From: Wu Fengguang [mailto:fengguang.wu@intel.com] 
Sent: Tuesday, March 02, 2010 1:43 PM
To: Wei Ni
Cc: 'Takashi Iwai'; 'akpm'; 'alsa-devel'; 'linux-kernel'; 'Pavel Hofman'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> Hi, Takashi
> I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> The new HAD controller and codec support standard HDMI operation.
> 
> I attached the patch file, please check it.

Wei Ni,

Can we avoid the big copy&paste and do more code reuse?
This benefits all of us in long term.

Thanks,
Fengguang
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-03  3:28       ` Wei Ni
@ 2010-03-03  4:06         ` Wei Ni
  2010-03-03  6:44             ` Takashi Iwai
  0 siblings, 1 reply; 80+ messages in thread
From: Wei Ni @ 2010-03-03  4:06 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

Hi, Takashi
Could we add a new "#define AZX_MAX_SLOTS 8", and use it in the function
azx_command_addr() and azx_response_addr() to instead of AZX_MAX_CODECS

Thanks
Wei.

-----Original Message-----
From: Wei Ni 
Sent: Wednesday, March 03, 2010 11:28 AM
To: 'Takashi Iwai'
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

Hi, Takashi
I still have a question about AZX_MAX_CODECS.
In azx_command_addr() and azx_response_addr(), they use AZX_MAX_CODECS like
If (addr >= AZX_MAX_CODECS) {
    snd_BUG();
    addr = 0;
}
The azx_max_codes[] could not be used in these functions.
How could we do in these functions?

Thanks
Wei.

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Tuesday, March 02, 2010 5:55 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Tue, 2 Mar 2010 17:43:28 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> 1. About AZX_MAX_CODECS, on our new chipset, the codec_mask=0x31, it means
> the codec connect on the slot0, slot4, slot5, and on some GT2xx, the codec
> will connect to slot6 or slot7, although these chip at most have 4 codecs.
> So I change the AZX_MAX_CODECS to 8 directly.
> In hda_intel.c, the azx_command_addr(), azx_response_addr(), and
> azx_codec_create() use the AZX_MAX_CODECS, if it set as 4, the driver will
> not detect the codecs which connect to slot4~7.

Yeah, I understand it.  But, as mentioned, changing this to *all*
controller chips is dangerous.
We have already a quirk for controller chips to set max codecs depending
on the chip model.  Right now, only teradici chip sets to 1.

So, add "#define AZX_DEFAULT_CODECS 4", and use this value unless
azx_max_codecs[] is defined.  And, for the new controller chip
supporting more than 4, it can has 8 in azx_max_codecs[].

Is it feasible?

> 2. yes, it's better to merge the hdmi common codes.
> 3. About ELD, yes, we need to change the Makefile and Kconfig as well.
> Could you help me to change it.

In sound/pci/hda/Makefile, hda_eld.c is built into snd-hda-codec-intelhdmi
by the following rule:

snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o

Since now hda_eld.c is used in two modules, this has to be in the common
place, such as snd-hda-codec.  For this, uncomment the line:

# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o

and remove hda_eld.o from snd-hda-codec-intelhdmi-objs line.

For Kconfig, right now we have the definition

config SND_HDA_ELD
	def_bool y
	depends on SND_HDA_CODEC_INTELHDMI

Change depends on like

	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI

This can be done via "select" instead.  But, we'd merge all hdmi codes
later, so which way to choose is no big matter.


thanks,

Takashi
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-03  4:06         ` Wei Ni
@ 2010-03-03  6:44             ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-03  6:44 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

At Wed, 3 Mar 2010 12:06:11 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> Could we add a new "#define AZX_MAX_SLOTS 8", and use it in the function
> azx_command_addr() and azx_response_addr() to instead of AZX_MAX_CODECS

Simpler would be to change AZX_MAX_CODECS to 8, define
AZX_DEFAULT_CODECS 4 and use it in azx_codec_create() like:

	max_slots = azx_max_codecs[chip->driver_type];
	if (!max_slots)
		max_slots = AZX_DEFAULT_CODECS;


Takashi

> Thanks
> Wei.
> 
> -----Original Message-----
> From: Wei Ni 
> Sent: Wednesday, March 03, 2010 11:28 AM
> To: 'Takashi Iwai'
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> Hi, Takashi
> I still have a question about AZX_MAX_CODECS.
> In azx_command_addr() and azx_response_addr(), they use AZX_MAX_CODECS like
> If (addr >= AZX_MAX_CODECS) {
>     snd_BUG();
>     addr = 0;
> }
> The azx_max_codes[] could not be used in these functions.
> How could we do in these functions?
> 
> Thanks
> Wei.
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Tuesday, March 02, 2010 5:55 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Tue, 2 Mar 2010 17:43:28 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > 1. About AZX_MAX_CODECS, on our new chipset, the codec_mask=0x31, it means
> > the codec connect on the slot0, slot4, slot5, and on some GT2xx, the codec
> > will connect to slot6 or slot7, although these chip at most have 4 codecs.
> > So I change the AZX_MAX_CODECS to 8 directly.
> > In hda_intel.c, the azx_command_addr(), azx_response_addr(), and
> > azx_codec_create() use the AZX_MAX_CODECS, if it set as 4, the driver will
> > not detect the codecs which connect to slot4~7.
> 
> Yeah, I understand it.  But, as mentioned, changing this to *all*
> controller chips is dangerous.
> We have already a quirk for controller chips to set max codecs depending
> on the chip model.  Right now, only teradici chip sets to 1.
> 
> So, add "#define AZX_DEFAULT_CODECS 4", and use this value unless
> azx_max_codecs[] is defined.  And, for the new controller chip
> supporting more than 4, it can has 8 in azx_max_codecs[].
> 
> Is it feasible?
> 
> > 2. yes, it's better to merge the hdmi common codes.
> > 3. About ELD, yes, we need to change the Makefile and Kconfig as well.
> > Could you help me to change it.
> 
> In sound/pci/hda/Makefile, hda_eld.c is built into snd-hda-codec-intelhdmi
> by the following rule:
> 
> snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o
> 
> Since now hda_eld.c is used in two modules, this has to be in the common
> place, such as snd-hda-codec.  For this, uncomment the line:
> 
> # snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
> 
> and remove hda_eld.o from snd-hda-codec-intelhdmi-objs line.
> 
> For Kconfig, right now we have the definition
> 
> config SND_HDA_ELD
> 	def_bool y
> 	depends on SND_HDA_CODEC_INTELHDMI
> 
> Change depends on like
> 
> 	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
> 
> This can be done via "select" instead.  But, we'd merge all hdmi codes
> later, so which way to choose is no big matter.
> 
> 
> thanks,
> 
> Takashi
> -----------------------------------------------------------------------------------
> This email message is for the sole use of the intended recipient(s) and may contain
> confidential information.  Any unauthorized review, use, disclosure or distribution
> is prohibited.  If you are not the intended recipient, please contact the sender by
> reply email and destroy all copies of the original message.
> -----------------------------------------------------------------------------------
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-03  6:44             ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-03  6:44 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

At Wed, 3 Mar 2010 12:06:11 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> Could we add a new "#define AZX_MAX_SLOTS 8", and use it in the function
> azx_command_addr() and azx_response_addr() to instead of AZX_MAX_CODECS

Simpler would be to change AZX_MAX_CODECS to 8, define
AZX_DEFAULT_CODECS 4 and use it in azx_codec_create() like:

	max_slots = azx_max_codecs[chip->driver_type];
	if (!max_slots)
		max_slots = AZX_DEFAULT_CODECS;


Takashi

> Thanks
> Wei.
> 
> -----Original Message-----
> From: Wei Ni 
> Sent: Wednesday, March 03, 2010 11:28 AM
> To: 'Takashi Iwai'
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> Hi, Takashi
> I still have a question about AZX_MAX_CODECS.
> In azx_command_addr() and azx_response_addr(), they use AZX_MAX_CODECS like
> If (addr >= AZX_MAX_CODECS) {
>     snd_BUG();
>     addr = 0;
> }
> The azx_max_codes[] could not be used in these functions.
> How could we do in these functions?
> 
> Thanks
> Wei.
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Tuesday, March 02, 2010 5:55 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Tue, 2 Mar 2010 17:43:28 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > 1. About AZX_MAX_CODECS, on our new chipset, the codec_mask=0x31, it means
> > the codec connect on the slot0, slot4, slot5, and on some GT2xx, the codec
> > will connect to slot6 or slot7, although these chip at most have 4 codecs.
> > So I change the AZX_MAX_CODECS to 8 directly.
> > In hda_intel.c, the azx_command_addr(), azx_response_addr(), and
> > azx_codec_create() use the AZX_MAX_CODECS, if it set as 4, the driver will
> > not detect the codecs which connect to slot4~7.
> 
> Yeah, I understand it.  But, as mentioned, changing this to *all*
> controller chips is dangerous.
> We have already a quirk for controller chips to set max codecs depending
> on the chip model.  Right now, only teradici chip sets to 1.
> 
> So, add "#define AZX_DEFAULT_CODECS 4", and use this value unless
> azx_max_codecs[] is defined.  And, for the new controller chip
> supporting more than 4, it can has 8 in azx_max_codecs[].
> 
> Is it feasible?
> 
> > 2. yes, it's better to merge the hdmi common codes.
> > 3. About ELD, yes, we need to change the Makefile and Kconfig as well.
> > Could you help me to change it.
> 
> In sound/pci/hda/Makefile, hda_eld.c is built into snd-hda-codec-intelhdmi
> by the following rule:
> 
> snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o
> 
> Since now hda_eld.c is used in two modules, this has to be in the common
> place, such as snd-hda-codec.  For this, uncomment the line:
> 
> # snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
> 
> and remove hda_eld.o from snd-hda-codec-intelhdmi-objs line.
> 
> For Kconfig, right now we have the definition
> 
> config SND_HDA_ELD
> 	def_bool y
> 	depends on SND_HDA_CODEC_INTELHDMI
> 
> Change depends on like
> 
> 	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
> 
> This can be done via "select" instead.  But, we'd merge all hdmi codes
> later, so which way to choose is no big matter.
> 
> 
> thanks,
> 
> Takashi
> -----------------------------------------------------------------------------------
> This email message is for the sole use of the intended recipient(s) and may contain
> confidential information.  Any unauthorized review, use, disclosure or distribution
> is prohibited.  If you are not the intended recipient, please contact the sender by
> reply email and destroy all copies of the original message.
> -----------------------------------------------------------------------------------
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel]  [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-02  5:43 ` [alsa-devel] " Wu Fengguang
@ 2010-03-03  6:46     ` Takashi Iwai
  2010-03-03  6:46     ` Takashi Iwai
  1 sibling, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-03  6:46 UTC (permalink / raw)
  To: Wu Fengguang
  Cc: Wei Ni, 'akpm', 'alsa-devel',
	'linux-kernel', 'Pavel Hofman'

At Tue, 2 Mar 2010 13:43:07 +0800,
Wu Fengguang wrote:
> 
> On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> > Hi, Takashi
> > I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> > The new HAD controller and codec support standard HDMI operation.
> > 
> > I attached the patch file, please check it.
> 
> Wei Ni,
> 
> Can we avoid the big copy&paste and do more code reuse?
> This benefits all of us in long term.

The plan is to merge all current patch_*hdmi.c into one.
But this can be done later once after we get the working driver
for the new Nvidia codecs.

The new Nvidia HDMI codec is a bit tricky (which has 4 separate
codec slots), so I'd like to get it working first.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-03  6:46     ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-03  6:46 UTC (permalink / raw)
  To: Wu Fengguang
  Cc: 'Pavel Hofman', Wei Ni, 'akpm',
	'alsa-devel', 'linux-kernel'

At Tue, 2 Mar 2010 13:43:07 +0800,
Wu Fengguang wrote:
> 
> On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> > Hi, Takashi
> > I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> > The new HAD controller and codec support standard HDMI operation.
> > 
> > I attached the patch file, please check it.
> 
> Wei Ni,
> 
> Can we avoid the big copy&paste and do more code reuse?
> This benefits all of us in long term.

The plan is to merge all current patch_*hdmi.c into one.
But this can be done later once after we get the working driver
for the new Nvidia codecs.

The new Nvidia HDMI codec is a bit tricky (which has 4 separate
codec slots), so I'd like to get it working first.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-03  6:44             ` Takashi Iwai
@ 2010-03-03  7:21               ` Wei Ni
  -1 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-03  7:21 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

[-- Attachment #1: Type: text/plain, Size: 90 bytes --]

Hi, Takashi
I generate the new patch file, please check it.


Thanks
Wei.
nvpublic

[-- Attachment #2: 0001-Support-max-codecs-to-8-for-nvidia-hda-controller.patch --]
[-- Type: application/octet-stream, Size: 1613 bytes --]

From bfc6d52051d2d56956d01692f0ab9320d1e23fd3 Mon Sep 17 00:00:00 2001
From: Wei Ni <wni@nvidia.com>
Date: Wed, 3 Mar 2010 15:05:53 +0800
Subject: [PATCH] Support max codecs to 8 for nvidia hda controller

Support max codecs to 8 for nvidia hda controller.
Change AZX_MAX_CODECS to 8, and add
"#define AZX_DEFAULT_CODECS 4" for default driver.
Set azx_max_codecs to 8 for nvidia controller.

Signed-off-by: Wei Ni <wni@nvidia.com>
---
 sound/pci/hda/hda_intel.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d5c93ad..29f4195 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -267,7 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define RIRB_INT_MASK		0x05
 
 /* STATESTS int mask: S3,SD2,SD1,SD0 */
-#define AZX_MAX_CODECS		4
+#define AZX_MAX_CODECS		8
+#define AZX_DEFAULT_CODECS	4
 #define STATESTS_INT_MASK	((1 << AZX_MAX_CODECS) - 1)
 
 /* SD_CTL bits */
@@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus)
 
 /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
 static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
+	[AZX_DRIVER_NVIDIA] = 8,
 	[AZX_DRIVER_TERA] = 1,
 };
 
@@ -1399,7 +1401,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
 	codecs = 0;
 	max_slots = azx_max_codecs[chip->driver_type];
 	if (!max_slots)
-		max_slots = AZX_MAX_CODECS;
+		max_slots = AZX_DEFAULT_CODECS;
 
 	/* First try to probe all given codec slots */
 	for (c = 0; c < max_slots; c++) {
-- 
1.5.6


[-- Attachment #3: 0002-Support-NVIDIA-MCP89-and-GT21x-hdmi-audio.patch --]
[-- Type: application/octet-stream, Size: 39873 bytes --]

From 1ca5174cf1d814b64c2ea150223bd7eebdf6c76d Mon Sep 17 00:00:00 2001
From: Wei Ni <wni@nvidia.com>
Date: Wed, 3 Mar 2010 15:11:40 +0800
Subject: [PATCH] Support NVIDIA MCP89 and GT21x hdmi audio

Support nvidia MCP89 and GT21x 8ch hdmi audio.
Add some eld support.

Signed-off-by: Wei Ni <wni@nvidia.com>
---
 sound/pci/hda/Kconfig        |    2 +-
 sound/pci/hda/Makefile       |    2 +-
 sound/pci/hda/patch_nvhdmi.c | 1038 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 990 insertions(+), 52 deletions(-)

diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 556cff9..567348b 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI
 
 config SND_HDA_ELD
 	def_bool y
-	depends on SND_HDA_CODEC_INTELHDMI
+	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
 
 config SND_HDA_CODEC_CIRRUS
 	bool "Build Cirrus Logic codec support"
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 315a1c4..199f440 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -17,7 +17,7 @@ snd-hda-codec-cirrus-objs :=	patch_cirrus.o
 snd-hda-codec-ca0110-objs :=	patch_ca0110.o
 snd-hda-codec-conexant-objs :=	patch_conexant.o
 snd-hda-codec-via-objs :=	patch_via.o
-snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o
+snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o hda_eld.o
 snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o
 
 # common driver
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 6afdab0..1c774f9 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -32,10 +32,11 @@
 /* define below to restrict the supported rates and formats */
 /* #define LIMITED_RATE_FMT_SUPPORT */
 
-struct nvhdmi_spec {
-	struct hda_multi_out multiout;
-
-	struct hda_pcm pcm_rec;
+enum HDACodec {
+	HDA_CODEC_NVIDIA_MCP7X,
+	HDA_CODEC_NVIDIA_MCP89,
+	HDA_CODEC_NVIDIA_GT21X,
+	HDA_CODEC_INVALID
 };
 
 #define Nv_VERB_SET_Channel_Allocation          0xF79
@@ -43,15 +44,18 @@ struct nvhdmi_spec {
 #define Nv_VERB_SET_Audio_Protection_On         0xF98
 #define Nv_VERB_SET_Audio_Protection_Off        0xF99
 
-#define Nv_Master_Convert_nid   0x04
-#define Nv_Master_Pin_nid       0x05
+#define nvhdmi_master_con_nid_7x	0x04
+#define nvhdmi_master_pin_nid_7x	0x05
 
-static hda_nid_t nvhdmi_convert_nids[4] = {
+#define nvhdmi_master_con_nid_89	0x04
+#define nvhdmi_master_pin_nid_89	0x05
+
+static hda_nid_t nvhdmi_con_nids_7x[4] = {
 	/*front, rear, clfe, rear_surr */
 	0x6, 0x8, 0xa, 0xc,
 };
 
-static struct hda_verb nvhdmi_basic_init[] = {
+static struct hda_verb nvhdmi_basic_init_7x[] = {
 	/* set audio protect on */
 	{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
 	/* enable digital output on pin widget */
@@ -79,6 +83,796 @@ static struct hda_verb nvhdmi_basic_init[] = {
 	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 #endif
 
+#define NVIDIA_89_HDMI_CVTS	1
+#define NVIDIA_89_HDMI_PINS	1
+
+static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = {
+	"NVIDIA HDMI",
+};
+
+struct nvhdmi_spec {
+	int num_cvts;
+	int num_pins;
+	hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1];  /* audio sources */
+	hda_nid_t pin[NVIDIA_89_HDMI_PINS+1];  /* audio sinks */
+	hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1];
+	struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS];
+	struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS];
+	struct hda_multi_out multiout;
+	unsigned int codec_type;
+};
+
+struct hdmi_audio_infoframe {
+	u8 type; /* 0x84 */
+	u8 ver;  /* 0x01 */
+	u8 len;  /* 0x0a */
+
+	u8 checksum;	/* PB0 */
+	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
+	u8 SS01_SF24;
+	u8 CXT04;
+	u8 CA;
+	u8 LFEPBL01_LSV36_DM_INH7;
+};
+
+/*
+ * CEA speaker placement:
+ *
+ *        FLH       FCH        FRH
+ *  FLW    FL  FLC   FC   FRC   FR   FRW
+ *
+ *                                  LFE
+ *                     TC
+ *
+ *          RL  RLC   RC   RRC   RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+	FL  = (1 <<  0),	/* Front Left           */
+	FC  = (1 <<  1),	/* Front Center         */
+	FR  = (1 <<  2),	/* Front Right          */
+	FLC = (1 <<  3),	/* Front Left Center    */
+	FRC = (1 <<  4),	/* Front Right Center   */
+	RL  = (1 <<  5),	/* Rear Left            */
+	RC  = (1 <<  6),	/* Rear Center          */
+	RR  = (1 <<  7),	/* Rear Right           */
+	RLC = (1 <<  8),	/* Rear Left Center     */
+	RRC = (1 <<  9),	/* Rear Right Center    */
+	LFE = (1 << 10),	/* Low Frequency Effect */
+	FLW = (1 << 11),	/* Front Left Wide      */
+	FRW = (1 << 12),	/* Front Right Wide     */
+	FLH = (1 << 13),	/* Front Left High      */
+	FCH = (1 << 14),	/* Front Center High    */
+	FRH = (1 << 15),	/* Front Right High     */
+	TC  = (1 << 16),	/* Top Center           */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+	[0] = FL | FR,
+	[1] = LFE,
+	[2] = FC,
+	[3] = RL | RR,
+	[4] = RC,
+	[5] = FLC | FRC,
+	[6] = RLC | RRC,
+	/* the following are not defined in ELD yet */
+	[7] = FLW | FRW,
+	[8] = FLH | FRH,
+	[9] = TC,
+	[10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+	int ca_index;
+	int speakers[8];
+
+	/* derived values, just for convenience */
+	int channels;
+	int spk_mask;
+};
+
+/*
+ * ALSA sequence is:
+ *
+ *       surround40   surround41   surround50   surround51   surround71
+ * ch0   front left   =            =            =            =
+ * ch1   front right  =            =            =            =
+ * ch2   rear left    =            =            =            =
+ * ch3   rear right   =            =            =            =
+ * ch4                LFE          center       center       center
+ * ch5                                          LFE          LFE
+ * ch6                                                       side left
+ * ch7                                                       side right
+ *
+ * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
+ */
+static int hdmi_channel_mapping[0x32][8] = {
+	/* stereo */
+	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* 2.1 */
+	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* Dolby Surround */
+	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* surround40 */
+	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
+	/* 4ch */
+	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
+	/* surround41 */
+	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround50 */
+	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround51 */
+	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
+	/* 7.1 */
+	[0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/* 			  channel:   7     6    5    4    3     2    1    0  */
+{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
+				 /* 2.1 */
+{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
+				 /* Dolby Surround */
+{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
+				 /* surround40 */
+{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
+				 /* surround41 */
+{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
+				 /* surround50 */
+{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+				 /* surround51 */
+{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* 6.1 */
+{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* surround71 */
+{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+
+{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
+{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
+};
+
+/*
+ * HDA/HDMI auto parsing
+ */
+
+static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+{
+	int i;
+
+	for (i = 0; nids[i]; i++)
+		if (nids[i] == nid)
+			return i;
+
+	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+	return -EINVAL;
+}
+
+static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+	int conn_len, curr;
+	int index;
+
+	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
+		snd_printk(KERN_WARNING
+			   "HDMI: pin %d wcaps %#x "
+			   "does not support connection list\n",
+			   pin_nid, get_wcaps(codec, pin_nid));
+		return -EINVAL;
+	}
+
+	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
+					   HDA_MAX_CONNECTIONS);
+	if (conn_len > 1)
+		curr = snd_hda_codec_read(codec, pin_nid, 0,
+					  AC_VERB_GET_CONNECT_SEL, 0);
+	else
+		curr = 0;
+
+	index = hda_node_index(spec->pin, pin_nid);
+	if (index < 0)
+		return -EINVAL;
+
+	spec->pin_cvt[index] = conn_list[curr];
+
+	return 0;
+}
+
+static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
+			      struct hdmi_eld *eld)
+{
+	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+		snd_hdmi_show_eld(eld);
+}
+
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+			       struct hdmi_eld *eld)
+{
+	int present = snd_hda_pin_sense(codec, pin_nid);
+
+	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
+	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
+
+	if (present & AC_PINSENSE_ELDV)
+		hdmi_get_show_eld(codec, pin_nid, eld);
+}
+
+static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+
+	if (spec->num_pins >= NVIDIA_89_HDMI_PINS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for pin %d \n", pin_nid);
+		return -EINVAL;
+	}
+
+	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+
+	spec->pin[spec->num_pins] = pin_nid;
+	spec->num_pins++;
+
+	/*
+	 * It is assumed that converter nodes come first in the node list and
+	 * hence have been registered and usable now.
+	 */
+	return nvhdmi_read_pin_conn(codec, pin_nid);
+}
+
+static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+
+	if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for converter %d \n", nid);
+		return -EINVAL;
+	}
+
+	spec->cvt[spec->num_cvts] = nid;
+	spec->num_cvts++;
+
+	return 0;
+}
+
+
+static int nvhdmi_parse_codec(struct hda_codec *codec)
+{
+	hda_nid_t nid;
+	int i, nodes;
+
+	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+	if (!nid || nodes < 0) {
+		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nodes; i++, nid++) {
+		unsigned int caps;
+		unsigned int type;
+
+		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+		type = get_wcaps_type(caps);
+
+		if (!(caps & AC_WCAP_DIGITAL))
+			continue;
+
+		switch (type) {
+		case AC_WID_AUD_OUT:
+			if (nvhdmi_add_cvt(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		case AC_WID_PIN:
+			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+				continue;
+			if (nvhdmi_add_pin(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		}
+	}
+
+	/*
+	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
+	 * can be lost and presence sense verb will become inaccurate if the
+	 * HDA link is powered off at hot plug or hw initialization time.
+	 */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+	      AC_PWRST_EPSS))
+		codec->bus->power_keep_link_on = 1;
+#endif
+
+	return 0;
+}
+
+/*
+ * HDMI routines
+ */
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int *packet_index, int *byte_index)
+{
+	int val;
+
+	val = snd_hda_codec_read(codec, pin_nid, 0,
+				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+	*packet_index = val >> 5;
+	*byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int packet_index, int byte_index)
+{
+	int val;
+
+	val = (packet_index << 5) | (byte_index & 0x1f);
+
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
+				unsigned char val)
+{
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	/* Unmute */
+	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
+		snd_hda_codec_write(codec, pin_nid, 0,
+				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	/* Enable pin out */
+	snd_hda_codec_write(codec, pin_nid, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+}
+
+/*
+ * Enable Audio InfoFrame Transmission
+ */
+static void hdmi_start_infoframe_trans(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_BEST);
+}
+
+/*
+ * Disable Audio InfoFrame Transmission
+ */
+static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
+				      hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_DISABLE);
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+{
+	return 1 + snd_hda_codec_read(codec, nid, 0,
+					AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec,
+				   hda_nid_t nid, int chs)
+{
+	if (chs != hdmi_get_channel_count(codec, nid))
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int slot;
+
+	for (i = 0; i < 8; i++) {
+		slot = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_CHAN_SLOT, i);
+		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+						slot >> 4, slot & 0xf);
+	}
+#endif
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int size;
+
+	size = snd_hdmi_get_eld_size(codec, pin_nid);
+	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+	}
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef BE_PARANOID
+	int i, j;
+	int size;
+	int pi, bi;
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		if (size == 0)
+			continue;
+
+		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
+		for (j = 1; j < 1000; j++) {
+			hdmi_write_dip_byte(codec, pin_nid, 0x0);
+			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
+			if (pi != i)
+				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+						bi, pi, i);
+			if (bi == 0) /* byte index wrapped around */
+				break;
+		}
+		snd_printd(KERN_INFO
+			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+			i, size, j);
+	}
+#endif
+}
+
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+{
+	ai->checksum = 0;
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+				      hda_nid_t pin_nid,
+				      struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	int i;
+
+	hdmi_debug_dip_size(codec, pin_nid);
+	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
+
+	hdmi_checksum_audio_infoframe(ai);
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++)
+		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+}
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+	int i, j;
+	struct cea_channel_speaker_allocation *p;
+
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		p = channel_allocations + i;
+		p->channels = 0;
+		p->spk_mask = 0;
+		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+			if (p->speakers[j]) {
+				p->channels++;
+				p->spk_mask |= p->speakers[j];
+			}
+	}
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ * 	      spk_mask => (channel_allocations[])         => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+					 struct hdmi_audio_infoframe *ai)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_eld *eld;
+	int i;
+	int spk_mask = 0;
+	int channels = 1 + (ai->CC02_CT47 & 0x7);
+	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+	/*
+	 * CA defaults to 0 for basic stereo audio
+	 */
+	if (channels <= 2)
+		return 0;
+
+	i = hda_node_index(spec->pin_cvt, nid);
+	if (i < 0)
+		return 0;
+	eld = &spec->sink_eld[i];
+
+	/*
+	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+	 * in console or for audio devices. Assume the highest speakers
+	 * configuration, to _not_ prohibit multi-channel audio playback.
+	 */
+	if (!eld->spk_alloc)
+		eld->spk_alloc = 0xffff;
+
+	/*
+	 * expand ELD's speaker allocation mask
+	 *
+	 * ELD tells the speaker mask in a compact(paired) form,
+	 * expand ELD's notions to match the ones used by Audio InfoFrame.
+	 */
+	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+		if (eld->spk_alloc & (1 << i))
+			spk_mask |= eld_speaker_allocation_bits[i];
+	}
+
+	/* search for the first working match in the CA table */
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		if (channels == channel_allocations[i].channels &&
+		    (spk_mask & channel_allocations[i].spk_mask) ==
+				channel_allocations[i].spk_mask) {
+			ai->CA = channel_allocations[i].ca_index;
+			break;
+		}
+	}
+
+	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+	snd_printdd(KERN_INFO
+			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+			ai->CA, channels, buf);
+
+	return ai->CA;
+}
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid,
+				       struct hdmi_audio_infoframe *ai)
+{
+	int i;
+	int ca = ai->CA;
+	int err;
+
+	if (hdmi_channel_mapping[ca][1] == 0) {
+		for (i = 0; i < channel_allocations[ca].channels; i++)
+			hdmi_channel_mapping[ca][i] = i | (i << 4);
+		for (; i < 8; i++)
+			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+	}
+
+	for (i = 0; i < 8; i++) {
+		err = snd_hda_codec_write(codec, pin_nid, 0,
+					  AC_VERB_SET_HDMI_CHAN_SLOT,
+					  hdmi_channel_mapping[ca][i]);
+		if (err) {
+			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
+			break;
+		}
+	}
+
+	hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
+				    struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	u8 val;
+	int i;
+
+	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
+							    != AC_DIPXMIT_BEST)
+		return false;
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++) {
+		val = snd_hda_codec_read(codec, pin_nid, 0,
+					 AC_VERB_GET_HDMI_DIP_DATA, 0);
+		if (val != bytes[i])
+			return false;
+	}
+
+	return true;
+}
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+					struct snd_pcm_substream *substream)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	hda_nid_t pin_nid;
+	int i;
+	struct hdmi_audio_infoframe ai = {
+		.type		= 0x84,
+		.ver		= 0x01,
+		.len		= 0x0a,
+		.CC02_CT47	= substream->runtime->channels - 1,
+	};
+
+	hdmi_setup_channel_allocation(codec, nid, &ai);
+
+	for (i = 0; i < spec->num_pins; i++) {
+		if (spec->pin_cvt[i] != nid)
+			continue;
+		if (!spec->sink_eld[i].monitor_present)
+			continue;
+
+		pin_nid = spec->pin[i];
+		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+			hdmi_stop_infoframe_trans(codec, pin_nid);
+			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+			hdmi_start_infoframe_trans(codec, pin_nid);
+		}
+	}
+}
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int pind = !!(res & AC_UNSOL_RES_PD);
+	int eldv = !!(res & AC_UNSOL_RES_ELDV);
+	int index;
+
+	printk(KERN_INFO
+		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+		tag, pind, eldv);
+
+	index = hda_node_index(spec->pin, tag);
+	if (index < 0)
+		return;
+
+	spec->sink_eld[index].monitor_present = pind;
+	spec->sink_eld[index].eld_valid = eldv;
+
+	if (eldv) {
+		spec->sink_eld[index].monitor_present = 1;
+		hdmi_get_show_eld(codec, spec->pin[index],
+				 &spec->sink_eld[index]);
+		/* TODO: do real things about ELD */
+	}
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+	printk(KERN_INFO
+		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+		tag,
+		subtag,
+		cp_state,
+		cp_ready);
+
+	/* TODO */
+	if (cp_state)
+		;
+	if (cp_ready)
+		;
+}
+
+static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+	if (hda_node_index(spec->pin, tag) < 0) {
+		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+		return;
+	}
+
+	if (subtag == 0)
+		hdmi_intrinsic_event(codec, res);
+	else
+		hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+			      u32 stream_tag, int format)
+{
+	int tag;
+	int fmt;
+
+	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
+	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
+
+	snd_printdd("hdmi_setup_stream: "
+		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
+		    nid,
+		    tag == stream_tag ? "" : "new-",
+		    stream_tag,
+		    fmt == format ? "" : "new-",
+		    format);
+
+	if (tag != stream_tag)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CHANNEL_STREAMID,
+				    stream_tag << 4);
+	if (fmt != format)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_STREAM_FORMAT, format);
+}
+
 /*
  * Controls
  */
@@ -86,20 +880,58 @@ static int nvhdmi_build_controls(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec = codec->spec;
 	int err;
+	int i;
 
-	err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
-	if (err < 0)
-		return err;
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; i < codec->num_pcms; i++) {
+			err = snd_hda_create_spdif_out_ctls(codec,
+							    spec->cvt[i]);
+			if (err < 0)
+				return err;
+		}
+	} else {
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+	}
 
 	return 0;
 }
 
 static int nvhdmi_init(struct hda_codec *codec)
 {
-	snd_hda_sequence_write(codec, nvhdmi_basic_init);
+	struct nvhdmi_spec *spec = codec->spec;
+	int i;
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; spec->pin[i]; i++) {
+			hdmi_enable_output(codec, spec->pin[i]);
+			snd_hda_codec_write(codec, spec->pin[i], 0,
+					    AC_VERB_SET_UNSOLICITED_ENABLE,
+					    AC_USRSP_EN | spec->pin[i]);
+		}
+	} else {
+		snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
+	}
 	return 0;
 }
 
+static void nvhdmi_free(struct hda_codec *codec)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	int i;
+
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; i < spec->num_pins; i++)
+			snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
+	}
+
+	kfree(spec);
+}
+
 /*
  * Digital out
  */
@@ -111,21 +943,21 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 }
 
-static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
+static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
 	struct nvhdmi_spec *spec = codec->spec;
 	int i;
 
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
 			0, AC_VERB_SET_CHANNEL_STREAMID, 0);
 	for (i = 0; i < 4; i++) {
 		/* set the stream id */
-		snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
 				AC_VERB_SET_CHANNEL_STREAMID, 0);
 		/* set the stream format */
-		snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
 				AC_VERB_SET_STREAM_FORMAT, 0);
 	}
 
@@ -140,6 +972,21 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					unsigned int stream_tag,
+					unsigned int format,
+					struct snd_pcm_substream *substream)
+{
+	hdmi_set_channel_count(codec, hinfo->nid,
+			       substream->runtime->channels);
+
+	hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
+
+	hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
+	return 0;
+}
+
 static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					unsigned int stream_tag,
@@ -181,29 +1028,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
 
 	/* set the stream id */
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
 			AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
 
 	/* set the stream format */
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
 			AC_VERB_SET_STREAM_FORMAT, format);
 
 	/* turn on again (if needed) */
 	/* enable and set the channel status audio/data flag */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & 0xff);
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
 	}
@@ -220,19 +1067,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 		if (codec->spdif_status_reset &&
 		(codec->spdif_ctls & AC_DIG1_ENABLE))
 			snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
 		/* set the stream id */
 		snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_CHANNEL_STREAMID,
 				(stream_tag << 4) | channel_id);
 		/* set the stream format */
 		snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_STREAM_FORMAT,
 				format);
@@ -241,12 +1088,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 		if (codec->spdif_status_reset &&
 		(codec->spdif_ctls & AC_DIG1_ENABLE)) {
 			snd_hda_codec_write(codec,
-					nvhdmi_convert_nids[i],
+					nvhdmi_con_nids_7x[i],
 					0,
 					AC_VERB_SET_DIGI_CONVERT_1,
 					codec->spdif_ctls & 0xff);
 			snd_hda_codec_write(codec,
-					nvhdmi_convert_nids[i],
+					nvhdmi_con_nids_7x[i],
 					0,
 					AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
 		}
@@ -261,6 +1108,13 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 	return 0;
 }
 
+static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
 static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					unsigned int stream_tag,
@@ -272,17 +1126,29 @@ static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
 					format, substream);
 }
 
-static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
+	.substreams = 1,
+	.channels_min = 2,
+	.rates = SUPPORTED_RATES,
+	.maxbps = SUPPORTED_MAXBPS,
+	.formats = SUPPORTED_FORMATS,
+	.ops = {
+		.prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
+		.cleanup = nvhdmi_playback_pcm_cleanup,
+	},
+};
+
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 8,
-	.nid = Nv_Master_Convert_nid,
+	.nid = nvhdmi_master_con_nid_7x,
 	.rates = SUPPORTED_RATES,
 	.maxbps = SUPPORTED_MAXBPS,
 	.formats = SUPPORTED_FORMATS,
 	.ops = {
 		.open = nvhdmi_dig_playback_pcm_open,
-		.close = nvhdmi_dig_playback_pcm_close_8ch,
+		.close = nvhdmi_dig_playback_pcm_close_8ch_7x,
 		.prepare = nvhdmi_dig_playback_pcm_prepare_8ch
 	},
 };
@@ -291,7 +1157,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
-	.nid = Nv_Master_Convert_nid,
+	.nid = nvhdmi_master_con_nid_7x,
 	.rates = SUPPORTED_RATES,
 	.maxbps = SUPPORTED_MAXBPS,
 	.formats = SUPPORTED_FORMATS,
@@ -302,10 +1168,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
 	},
 };
 
-static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
+static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+	int i;
+
+	codec->num_pcms = spec->num_cvts;
+	codec->pcm_info = info;
+
+	for (i = 0; i < codec->num_pcms; i++, info++) {
+		unsigned int chans;
+
+		chans = get_wcaps(codec, spec->cvt[i]);
+		chans = get_wcaps_channels(chans);
+
+		info->name = nvhdmi_pcm_names[i];
+		info->pcm_type = HDA_PCM_TYPE_HDMI;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK]
+					= nvhdmi_pcm_digital_playback_8ch_89;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
+	}
+
+	return 0;
+}
+
+static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = &spec->pcm_rec;
+	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
@@ -313,7 +1205,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
 	info->name = "NVIDIA HDMI";
 	info->pcm_type = HDA_PCM_TYPE_HDMI;
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK]
-					= nvhdmi_pcm_digital_playback_8ch;
+					= nvhdmi_pcm_digital_playback_8ch_7x;
 
 	return 0;
 }
@@ -321,7 +1213,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
 static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = &spec->pcm_rec;
+	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
@@ -334,14 +1226,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 	return 0;
 }
 
-static void nvhdmi_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
+	.build_controls = nvhdmi_build_controls,
+	.build_pcms = nvhdmi_build_pcms_8ch_89,
+	.init = nvhdmi_init,
+	.free = nvhdmi_free,
+	.unsol_event = nvhdmi_unsol_event,
+};
 
-static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
 	.build_controls = nvhdmi_build_controls,
-	.build_pcms = nvhdmi_build_pcms_8ch,
+	.build_pcms = nvhdmi_build_pcms_8ch_7x,
 	.init = nvhdmi_init,
 	.free = nvhdmi_free,
 };
@@ -353,7 +1248,34 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
 	.free = nvhdmi_free,
 };
 
-static int patch_nvhdmi_8ch(struct hda_codec *codec)
+static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
+{
+	struct nvhdmi_spec *spec;
+	int i;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
+
+	if (nvhdmi_parse_codec(codec) < 0) {
+		codec->spec = NULL;
+		kfree(spec);
+		return -EINVAL;
+	}
+	codec->patch_ops = nvhdmi_patch_ops_8ch_89;
+
+	for (i = 0; i < spec->num_pins; i++)
+		snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
+
+	init_channel_allocations();
+
+	return 0;
+}
+
+static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec;
 
@@ -365,9 +1287,10 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec)
 
 	spec->multiout.num_dacs = 0;  /* no analog */
 	spec->multiout.max_channels = 8;
-	spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+	spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
 
-	codec->patch_ops = nvhdmi_patch_ops_8ch;
+	codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
 
 	return 0;
 }
@@ -384,7 +1307,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
 
 	spec->multiout.num_dacs = 0;  /* no analog */
 	spec->multiout.max_channels = 2;
-	spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+	spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
 
 	codec->patch_ops = nvhdmi_patch_ops_2ch;
 
@@ -395,13 +1319,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
  * patch entries
  */
 static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
-	{ .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
 	{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
 	{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
+	{ .id = 0x10de0002, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0003, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0005, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0006, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0007, .name = "MCP79/7A HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de000c, .name = "MCP89 HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
+	{ .id = 0x10de000b, .name = "GT21x HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
+	{ .id = 0x10de000d, .name = "GT240 HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
 	{} /* terminator */
 };
 
@@ -412,9 +1347,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006");
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:10de000c");
+MODULE_ALIAS("snd-hda-codec-id:10de000b");
+MODULE_ALIAS("snd-hda-codec-id:10de000d");
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
+MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
 
 static struct hda_codec_preset_list nvhdmi_list = {
 	.preset = snd_hda_preset_nvhdmi,
-- 
1.5.6


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-03  7:21               ` Wei Ni
  0 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-03  7:21 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

[-- Attachment #1: Type: text/plain, Size: 90 bytes --]

Hi, Takashi
I generate the new patch file, please check it.


Thanks
Wei.
nvpublic

[-- Attachment #2: 0001-Support-max-codecs-to-8-for-nvidia-hda-controller.patch --]
[-- Type: application/octet-stream, Size: 1613 bytes --]

From bfc6d52051d2d56956d01692f0ab9320d1e23fd3 Mon Sep 17 00:00:00 2001
From: Wei Ni <wni@nvidia.com>
Date: Wed, 3 Mar 2010 15:05:53 +0800
Subject: [PATCH] Support max codecs to 8 for nvidia hda controller

Support max codecs to 8 for nvidia hda controller.
Change AZX_MAX_CODECS to 8, and add
"#define AZX_DEFAULT_CODECS 4" for default driver.
Set azx_max_codecs to 8 for nvidia controller.

Signed-off-by: Wei Ni <wni@nvidia.com>
---
 sound/pci/hda/hda_intel.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d5c93ad..29f4195 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -267,7 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define RIRB_INT_MASK		0x05
 
 /* STATESTS int mask: S3,SD2,SD1,SD0 */
-#define AZX_MAX_CODECS		4
+#define AZX_MAX_CODECS		8
+#define AZX_DEFAULT_CODECS	4
 #define STATESTS_INT_MASK	((1 << AZX_MAX_CODECS) - 1)
 
 /* SD_CTL bits */
@@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus)
 
 /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
 static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
+	[AZX_DRIVER_NVIDIA] = 8,
 	[AZX_DRIVER_TERA] = 1,
 };
 
@@ -1399,7 +1401,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
 	codecs = 0;
 	max_slots = azx_max_codecs[chip->driver_type];
 	if (!max_slots)
-		max_slots = AZX_MAX_CODECS;
+		max_slots = AZX_DEFAULT_CODECS;
 
 	/* First try to probe all given codec slots */
 	for (c = 0; c < max_slots; c++) {
-- 
1.5.6


[-- Attachment #3: 0002-Support-NVIDIA-MCP89-and-GT21x-hdmi-audio.patch --]
[-- Type: application/octet-stream, Size: 39873 bytes --]

From 1ca5174cf1d814b64c2ea150223bd7eebdf6c76d Mon Sep 17 00:00:00 2001
From: Wei Ni <wni@nvidia.com>
Date: Wed, 3 Mar 2010 15:11:40 +0800
Subject: [PATCH] Support NVIDIA MCP89 and GT21x hdmi audio

Support nvidia MCP89 and GT21x 8ch hdmi audio.
Add some eld support.

Signed-off-by: Wei Ni <wni@nvidia.com>
---
 sound/pci/hda/Kconfig        |    2 +-
 sound/pci/hda/Makefile       |    2 +-
 sound/pci/hda/patch_nvhdmi.c | 1038 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 990 insertions(+), 52 deletions(-)

diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 556cff9..567348b 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI
 
 config SND_HDA_ELD
 	def_bool y
-	depends on SND_HDA_CODEC_INTELHDMI
+	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
 
 config SND_HDA_CODEC_CIRRUS
 	bool "Build Cirrus Logic codec support"
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 315a1c4..199f440 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -17,7 +17,7 @@ snd-hda-codec-cirrus-objs :=	patch_cirrus.o
 snd-hda-codec-ca0110-objs :=	patch_ca0110.o
 snd-hda-codec-conexant-objs :=	patch_conexant.o
 snd-hda-codec-via-objs :=	patch_via.o
-snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o
+snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o hda_eld.o
 snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o
 
 # common driver
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 6afdab0..1c774f9 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -32,10 +32,11 @@
 /* define below to restrict the supported rates and formats */
 /* #define LIMITED_RATE_FMT_SUPPORT */
 
-struct nvhdmi_spec {
-	struct hda_multi_out multiout;
-
-	struct hda_pcm pcm_rec;
+enum HDACodec {
+	HDA_CODEC_NVIDIA_MCP7X,
+	HDA_CODEC_NVIDIA_MCP89,
+	HDA_CODEC_NVIDIA_GT21X,
+	HDA_CODEC_INVALID
 };
 
 #define Nv_VERB_SET_Channel_Allocation          0xF79
@@ -43,15 +44,18 @@ struct nvhdmi_spec {
 #define Nv_VERB_SET_Audio_Protection_On         0xF98
 #define Nv_VERB_SET_Audio_Protection_Off        0xF99
 
-#define Nv_Master_Convert_nid   0x04
-#define Nv_Master_Pin_nid       0x05
+#define nvhdmi_master_con_nid_7x	0x04
+#define nvhdmi_master_pin_nid_7x	0x05
 
-static hda_nid_t nvhdmi_convert_nids[4] = {
+#define nvhdmi_master_con_nid_89	0x04
+#define nvhdmi_master_pin_nid_89	0x05
+
+static hda_nid_t nvhdmi_con_nids_7x[4] = {
 	/*front, rear, clfe, rear_surr */
 	0x6, 0x8, 0xa, 0xc,
 };
 
-static struct hda_verb nvhdmi_basic_init[] = {
+static struct hda_verb nvhdmi_basic_init_7x[] = {
 	/* set audio protect on */
 	{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
 	/* enable digital output on pin widget */
@@ -79,6 +83,796 @@ static struct hda_verb nvhdmi_basic_init[] = {
 	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 #endif
 
+#define NVIDIA_89_HDMI_CVTS	1
+#define NVIDIA_89_HDMI_PINS	1
+
+static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = {
+	"NVIDIA HDMI",
+};
+
+struct nvhdmi_spec {
+	int num_cvts;
+	int num_pins;
+	hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1];  /* audio sources */
+	hda_nid_t pin[NVIDIA_89_HDMI_PINS+1];  /* audio sinks */
+	hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1];
+	struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS];
+	struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS];
+	struct hda_multi_out multiout;
+	unsigned int codec_type;
+};
+
+struct hdmi_audio_infoframe {
+	u8 type; /* 0x84 */
+	u8 ver;  /* 0x01 */
+	u8 len;  /* 0x0a */
+
+	u8 checksum;	/* PB0 */
+	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
+	u8 SS01_SF24;
+	u8 CXT04;
+	u8 CA;
+	u8 LFEPBL01_LSV36_DM_INH7;
+};
+
+/*
+ * CEA speaker placement:
+ *
+ *        FLH       FCH        FRH
+ *  FLW    FL  FLC   FC   FRC   FR   FRW
+ *
+ *                                  LFE
+ *                     TC
+ *
+ *          RL  RLC   RC   RRC   RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+	FL  = (1 <<  0),	/* Front Left           */
+	FC  = (1 <<  1),	/* Front Center         */
+	FR  = (1 <<  2),	/* Front Right          */
+	FLC = (1 <<  3),	/* Front Left Center    */
+	FRC = (1 <<  4),	/* Front Right Center   */
+	RL  = (1 <<  5),	/* Rear Left            */
+	RC  = (1 <<  6),	/* Rear Center          */
+	RR  = (1 <<  7),	/* Rear Right           */
+	RLC = (1 <<  8),	/* Rear Left Center     */
+	RRC = (1 <<  9),	/* Rear Right Center    */
+	LFE = (1 << 10),	/* Low Frequency Effect */
+	FLW = (1 << 11),	/* Front Left Wide      */
+	FRW = (1 << 12),	/* Front Right Wide     */
+	FLH = (1 << 13),	/* Front Left High      */
+	FCH = (1 << 14),	/* Front Center High    */
+	FRH = (1 << 15),	/* Front Right High     */
+	TC  = (1 << 16),	/* Top Center           */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+	[0] = FL | FR,
+	[1] = LFE,
+	[2] = FC,
+	[3] = RL | RR,
+	[4] = RC,
+	[5] = FLC | FRC,
+	[6] = RLC | RRC,
+	/* the following are not defined in ELD yet */
+	[7] = FLW | FRW,
+	[8] = FLH | FRH,
+	[9] = TC,
+	[10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+	int ca_index;
+	int speakers[8];
+
+	/* derived values, just for convenience */
+	int channels;
+	int spk_mask;
+};
+
+/*
+ * ALSA sequence is:
+ *
+ *       surround40   surround41   surround50   surround51   surround71
+ * ch0   front left   =            =            =            =
+ * ch1   front right  =            =            =            =
+ * ch2   rear left    =            =            =            =
+ * ch3   rear right   =            =            =            =
+ * ch4                LFE          center       center       center
+ * ch5                                          LFE          LFE
+ * ch6                                                       side left
+ * ch7                                                       side right
+ *
+ * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
+ */
+static int hdmi_channel_mapping[0x32][8] = {
+	/* stereo */
+	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* 2.1 */
+	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* Dolby Surround */
+	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* surround40 */
+	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
+	/* 4ch */
+	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
+	/* surround41 */
+	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround50 */
+	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround51 */
+	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
+	/* 7.1 */
+	[0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/* 			  channel:   7     6    5    4    3     2    1    0  */
+{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
+				 /* 2.1 */
+{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
+				 /* Dolby Surround */
+{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
+				 /* surround40 */
+{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
+				 /* surround41 */
+{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
+				 /* surround50 */
+{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+				 /* surround51 */
+{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* 6.1 */
+{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* surround71 */
+{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+
+{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
+{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
+};
+
+/*
+ * HDA/HDMI auto parsing
+ */
+
+static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+{
+	int i;
+
+	for (i = 0; nids[i]; i++)
+		if (nids[i] == nid)
+			return i;
+
+	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+	return -EINVAL;
+}
+
+static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+	int conn_len, curr;
+	int index;
+
+	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
+		snd_printk(KERN_WARNING
+			   "HDMI: pin %d wcaps %#x "
+			   "does not support connection list\n",
+			   pin_nid, get_wcaps(codec, pin_nid));
+		return -EINVAL;
+	}
+
+	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
+					   HDA_MAX_CONNECTIONS);
+	if (conn_len > 1)
+		curr = snd_hda_codec_read(codec, pin_nid, 0,
+					  AC_VERB_GET_CONNECT_SEL, 0);
+	else
+		curr = 0;
+
+	index = hda_node_index(spec->pin, pin_nid);
+	if (index < 0)
+		return -EINVAL;
+
+	spec->pin_cvt[index] = conn_list[curr];
+
+	return 0;
+}
+
+static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
+			      struct hdmi_eld *eld)
+{
+	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+		snd_hdmi_show_eld(eld);
+}
+
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+			       struct hdmi_eld *eld)
+{
+	int present = snd_hda_pin_sense(codec, pin_nid);
+
+	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
+	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
+
+	if (present & AC_PINSENSE_ELDV)
+		hdmi_get_show_eld(codec, pin_nid, eld);
+}
+
+static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+
+	if (spec->num_pins >= NVIDIA_89_HDMI_PINS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for pin %d \n", pin_nid);
+		return -EINVAL;
+	}
+
+	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+
+	spec->pin[spec->num_pins] = pin_nid;
+	spec->num_pins++;
+
+	/*
+	 * It is assumed that converter nodes come first in the node list and
+	 * hence have been registered and usable now.
+	 */
+	return nvhdmi_read_pin_conn(codec, pin_nid);
+}
+
+static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+
+	if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for converter %d \n", nid);
+		return -EINVAL;
+	}
+
+	spec->cvt[spec->num_cvts] = nid;
+	spec->num_cvts++;
+
+	return 0;
+}
+
+
+static int nvhdmi_parse_codec(struct hda_codec *codec)
+{
+	hda_nid_t nid;
+	int i, nodes;
+
+	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+	if (!nid || nodes < 0) {
+		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nodes; i++, nid++) {
+		unsigned int caps;
+		unsigned int type;
+
+		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+		type = get_wcaps_type(caps);
+
+		if (!(caps & AC_WCAP_DIGITAL))
+			continue;
+
+		switch (type) {
+		case AC_WID_AUD_OUT:
+			if (nvhdmi_add_cvt(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		case AC_WID_PIN:
+			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+				continue;
+			if (nvhdmi_add_pin(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		}
+	}
+
+	/*
+	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
+	 * can be lost and presence sense verb will become inaccurate if the
+	 * HDA link is powered off at hot plug or hw initialization time.
+	 */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+	      AC_PWRST_EPSS))
+		codec->bus->power_keep_link_on = 1;
+#endif
+
+	return 0;
+}
+
+/*
+ * HDMI routines
+ */
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int *packet_index, int *byte_index)
+{
+	int val;
+
+	val = snd_hda_codec_read(codec, pin_nid, 0,
+				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+	*packet_index = val >> 5;
+	*byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int packet_index, int byte_index)
+{
+	int val;
+
+	val = (packet_index << 5) | (byte_index & 0x1f);
+
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
+				unsigned char val)
+{
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	/* Unmute */
+	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
+		snd_hda_codec_write(codec, pin_nid, 0,
+				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	/* Enable pin out */
+	snd_hda_codec_write(codec, pin_nid, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+}
+
+/*
+ * Enable Audio InfoFrame Transmission
+ */
+static void hdmi_start_infoframe_trans(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_BEST);
+}
+
+/*
+ * Disable Audio InfoFrame Transmission
+ */
+static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
+				      hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_DISABLE);
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+{
+	return 1 + snd_hda_codec_read(codec, nid, 0,
+					AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec,
+				   hda_nid_t nid, int chs)
+{
+	if (chs != hdmi_get_channel_count(codec, nid))
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int slot;
+
+	for (i = 0; i < 8; i++) {
+		slot = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_CHAN_SLOT, i);
+		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+						slot >> 4, slot & 0xf);
+	}
+#endif
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int size;
+
+	size = snd_hdmi_get_eld_size(codec, pin_nid);
+	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+	}
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef BE_PARANOID
+	int i, j;
+	int size;
+	int pi, bi;
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		if (size == 0)
+			continue;
+
+		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
+		for (j = 1; j < 1000; j++) {
+			hdmi_write_dip_byte(codec, pin_nid, 0x0);
+			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
+			if (pi != i)
+				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+						bi, pi, i);
+			if (bi == 0) /* byte index wrapped around */
+				break;
+		}
+		snd_printd(KERN_INFO
+			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+			i, size, j);
+	}
+#endif
+}
+
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+{
+	ai->checksum = 0;
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+				      hda_nid_t pin_nid,
+				      struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	int i;
+
+	hdmi_debug_dip_size(codec, pin_nid);
+	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
+
+	hdmi_checksum_audio_infoframe(ai);
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++)
+		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+}
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+	int i, j;
+	struct cea_channel_speaker_allocation *p;
+
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		p = channel_allocations + i;
+		p->channels = 0;
+		p->spk_mask = 0;
+		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+			if (p->speakers[j]) {
+				p->channels++;
+				p->spk_mask |= p->speakers[j];
+			}
+	}
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ * 	      spk_mask => (channel_allocations[])         => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+					 struct hdmi_audio_infoframe *ai)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_eld *eld;
+	int i;
+	int spk_mask = 0;
+	int channels = 1 + (ai->CC02_CT47 & 0x7);
+	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+	/*
+	 * CA defaults to 0 for basic stereo audio
+	 */
+	if (channels <= 2)
+		return 0;
+
+	i = hda_node_index(spec->pin_cvt, nid);
+	if (i < 0)
+		return 0;
+	eld = &spec->sink_eld[i];
+
+	/*
+	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+	 * in console or for audio devices. Assume the highest speakers
+	 * configuration, to _not_ prohibit multi-channel audio playback.
+	 */
+	if (!eld->spk_alloc)
+		eld->spk_alloc = 0xffff;
+
+	/*
+	 * expand ELD's speaker allocation mask
+	 *
+	 * ELD tells the speaker mask in a compact(paired) form,
+	 * expand ELD's notions to match the ones used by Audio InfoFrame.
+	 */
+	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+		if (eld->spk_alloc & (1 << i))
+			spk_mask |= eld_speaker_allocation_bits[i];
+	}
+
+	/* search for the first working match in the CA table */
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		if (channels == channel_allocations[i].channels &&
+		    (spk_mask & channel_allocations[i].spk_mask) ==
+				channel_allocations[i].spk_mask) {
+			ai->CA = channel_allocations[i].ca_index;
+			break;
+		}
+	}
+
+	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+	snd_printdd(KERN_INFO
+			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+			ai->CA, channels, buf);
+
+	return ai->CA;
+}
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid,
+				       struct hdmi_audio_infoframe *ai)
+{
+	int i;
+	int ca = ai->CA;
+	int err;
+
+	if (hdmi_channel_mapping[ca][1] == 0) {
+		for (i = 0; i < channel_allocations[ca].channels; i++)
+			hdmi_channel_mapping[ca][i] = i | (i << 4);
+		for (; i < 8; i++)
+			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+	}
+
+	for (i = 0; i < 8; i++) {
+		err = snd_hda_codec_write(codec, pin_nid, 0,
+					  AC_VERB_SET_HDMI_CHAN_SLOT,
+					  hdmi_channel_mapping[ca][i]);
+		if (err) {
+			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
+			break;
+		}
+	}
+
+	hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
+				    struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	u8 val;
+	int i;
+
+	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
+							    != AC_DIPXMIT_BEST)
+		return false;
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++) {
+		val = snd_hda_codec_read(codec, pin_nid, 0,
+					 AC_VERB_GET_HDMI_DIP_DATA, 0);
+		if (val != bytes[i])
+			return false;
+	}
+
+	return true;
+}
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+					struct snd_pcm_substream *substream)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	hda_nid_t pin_nid;
+	int i;
+	struct hdmi_audio_infoframe ai = {
+		.type		= 0x84,
+		.ver		= 0x01,
+		.len		= 0x0a,
+		.CC02_CT47	= substream->runtime->channels - 1,
+	};
+
+	hdmi_setup_channel_allocation(codec, nid, &ai);
+
+	for (i = 0; i < spec->num_pins; i++) {
+		if (spec->pin_cvt[i] != nid)
+			continue;
+		if (!spec->sink_eld[i].monitor_present)
+			continue;
+
+		pin_nid = spec->pin[i];
+		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+			hdmi_stop_infoframe_trans(codec, pin_nid);
+			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+			hdmi_start_infoframe_trans(codec, pin_nid);
+		}
+	}
+}
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int pind = !!(res & AC_UNSOL_RES_PD);
+	int eldv = !!(res & AC_UNSOL_RES_ELDV);
+	int index;
+
+	printk(KERN_INFO
+		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+		tag, pind, eldv);
+
+	index = hda_node_index(spec->pin, tag);
+	if (index < 0)
+		return;
+
+	spec->sink_eld[index].monitor_present = pind;
+	spec->sink_eld[index].eld_valid = eldv;
+
+	if (eldv) {
+		spec->sink_eld[index].monitor_present = 1;
+		hdmi_get_show_eld(codec, spec->pin[index],
+				 &spec->sink_eld[index]);
+		/* TODO: do real things about ELD */
+	}
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+	printk(KERN_INFO
+		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+		tag,
+		subtag,
+		cp_state,
+		cp_ready);
+
+	/* TODO */
+	if (cp_state)
+		;
+	if (cp_ready)
+		;
+}
+
+static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+	if (hda_node_index(spec->pin, tag) < 0) {
+		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+		return;
+	}
+
+	if (subtag == 0)
+		hdmi_intrinsic_event(codec, res);
+	else
+		hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+			      u32 stream_tag, int format)
+{
+	int tag;
+	int fmt;
+
+	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
+	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
+
+	snd_printdd("hdmi_setup_stream: "
+		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
+		    nid,
+		    tag == stream_tag ? "" : "new-",
+		    stream_tag,
+		    fmt == format ? "" : "new-",
+		    format);
+
+	if (tag != stream_tag)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CHANNEL_STREAMID,
+				    stream_tag << 4);
+	if (fmt != format)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_STREAM_FORMAT, format);
+}
+
 /*
  * Controls
  */
@@ -86,20 +880,58 @@ static int nvhdmi_build_controls(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec = codec->spec;
 	int err;
+	int i;
 
-	err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
-	if (err < 0)
-		return err;
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; i < codec->num_pcms; i++) {
+			err = snd_hda_create_spdif_out_ctls(codec,
+							    spec->cvt[i]);
+			if (err < 0)
+				return err;
+		}
+	} else {
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+	}
 
 	return 0;
 }
 
 static int nvhdmi_init(struct hda_codec *codec)
 {
-	snd_hda_sequence_write(codec, nvhdmi_basic_init);
+	struct nvhdmi_spec *spec = codec->spec;
+	int i;
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; spec->pin[i]; i++) {
+			hdmi_enable_output(codec, spec->pin[i]);
+			snd_hda_codec_write(codec, spec->pin[i], 0,
+					    AC_VERB_SET_UNSOLICITED_ENABLE,
+					    AC_USRSP_EN | spec->pin[i]);
+		}
+	} else {
+		snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
+	}
 	return 0;
 }
 
+static void nvhdmi_free(struct hda_codec *codec)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	int i;
+
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; i < spec->num_pins; i++)
+			snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
+	}
+
+	kfree(spec);
+}
+
 /*
  * Digital out
  */
@@ -111,21 +943,21 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 }
 
-static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
+static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
 	struct nvhdmi_spec *spec = codec->spec;
 	int i;
 
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
 			0, AC_VERB_SET_CHANNEL_STREAMID, 0);
 	for (i = 0; i < 4; i++) {
 		/* set the stream id */
-		snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
 				AC_VERB_SET_CHANNEL_STREAMID, 0);
 		/* set the stream format */
-		snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
 				AC_VERB_SET_STREAM_FORMAT, 0);
 	}
 
@@ -140,6 +972,21 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					unsigned int stream_tag,
+					unsigned int format,
+					struct snd_pcm_substream *substream)
+{
+	hdmi_set_channel_count(codec, hinfo->nid,
+			       substream->runtime->channels);
+
+	hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
+
+	hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
+	return 0;
+}
+
 static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					unsigned int stream_tag,
@@ -181,29 +1028,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
 
 	/* set the stream id */
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
 			AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
 
 	/* set the stream format */
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
 			AC_VERB_SET_STREAM_FORMAT, format);
 
 	/* turn on again (if needed) */
 	/* enable and set the channel status audio/data flag */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & 0xff);
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
 	}
@@ -220,19 +1067,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 		if (codec->spdif_status_reset &&
 		(codec->spdif_ctls & AC_DIG1_ENABLE))
 			snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
 		/* set the stream id */
 		snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_CHANNEL_STREAMID,
 				(stream_tag << 4) | channel_id);
 		/* set the stream format */
 		snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_STREAM_FORMAT,
 				format);
@@ -241,12 +1088,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 		if (codec->spdif_status_reset &&
 		(codec->spdif_ctls & AC_DIG1_ENABLE)) {
 			snd_hda_codec_write(codec,
-					nvhdmi_convert_nids[i],
+					nvhdmi_con_nids_7x[i],
 					0,
 					AC_VERB_SET_DIGI_CONVERT_1,
 					codec->spdif_ctls & 0xff);
 			snd_hda_codec_write(codec,
-					nvhdmi_convert_nids[i],
+					nvhdmi_con_nids_7x[i],
 					0,
 					AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
 		}
@@ -261,6 +1108,13 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 	return 0;
 }
 
+static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
 static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					unsigned int stream_tag,
@@ -272,17 +1126,29 @@ static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
 					format, substream);
 }
 
-static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
+	.substreams = 1,
+	.channels_min = 2,
+	.rates = SUPPORTED_RATES,
+	.maxbps = SUPPORTED_MAXBPS,
+	.formats = SUPPORTED_FORMATS,
+	.ops = {
+		.prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
+		.cleanup = nvhdmi_playback_pcm_cleanup,
+	},
+};
+
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 8,
-	.nid = Nv_Master_Convert_nid,
+	.nid = nvhdmi_master_con_nid_7x,
 	.rates = SUPPORTED_RATES,
 	.maxbps = SUPPORTED_MAXBPS,
 	.formats = SUPPORTED_FORMATS,
 	.ops = {
 		.open = nvhdmi_dig_playback_pcm_open,
-		.close = nvhdmi_dig_playback_pcm_close_8ch,
+		.close = nvhdmi_dig_playback_pcm_close_8ch_7x,
 		.prepare = nvhdmi_dig_playback_pcm_prepare_8ch
 	},
 };
@@ -291,7 +1157,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
-	.nid = Nv_Master_Convert_nid,
+	.nid = nvhdmi_master_con_nid_7x,
 	.rates = SUPPORTED_RATES,
 	.maxbps = SUPPORTED_MAXBPS,
 	.formats = SUPPORTED_FORMATS,
@@ -302,10 +1168,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
 	},
 };
 
-static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
+static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
+{
+	struct nvhdmi_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+	int i;
+
+	codec->num_pcms = spec->num_cvts;
+	codec->pcm_info = info;
+
+	for (i = 0; i < codec->num_pcms; i++, info++) {
+		unsigned int chans;
+
+		chans = get_wcaps(codec, spec->cvt[i]);
+		chans = get_wcaps_channels(chans);
+
+		info->name = nvhdmi_pcm_names[i];
+		info->pcm_type = HDA_PCM_TYPE_HDMI;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK]
+					= nvhdmi_pcm_digital_playback_8ch_89;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
+	}
+
+	return 0;
+}
+
+static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = &spec->pcm_rec;
+	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
@@ -313,7 +1205,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
 	info->name = "NVIDIA HDMI";
 	info->pcm_type = HDA_PCM_TYPE_HDMI;
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK]
-					= nvhdmi_pcm_digital_playback_8ch;
+					= nvhdmi_pcm_digital_playback_8ch_7x;
 
 	return 0;
 }
@@ -321,7 +1213,7 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
 static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = &spec->pcm_rec;
+	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
@@ -334,14 +1226,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 	return 0;
 }
 
-static void nvhdmi_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
+	.build_controls = nvhdmi_build_controls,
+	.build_pcms = nvhdmi_build_pcms_8ch_89,
+	.init = nvhdmi_init,
+	.free = nvhdmi_free,
+	.unsol_event = nvhdmi_unsol_event,
+};
 
-static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
 	.build_controls = nvhdmi_build_controls,
-	.build_pcms = nvhdmi_build_pcms_8ch,
+	.build_pcms = nvhdmi_build_pcms_8ch_7x,
 	.init = nvhdmi_init,
 	.free = nvhdmi_free,
 };
@@ -353,7 +1248,34 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
 	.free = nvhdmi_free,
 };
 
-static int patch_nvhdmi_8ch(struct hda_codec *codec)
+static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
+{
+	struct nvhdmi_spec *spec;
+	int i;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
+
+	if (nvhdmi_parse_codec(codec) < 0) {
+		codec->spec = NULL;
+		kfree(spec);
+		return -EINVAL;
+	}
+	codec->patch_ops = nvhdmi_patch_ops_8ch_89;
+
+	for (i = 0; i < spec->num_pins; i++)
+		snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
+
+	init_channel_allocations();
+
+	return 0;
+}
+
+static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
 {
 	struct nvhdmi_spec *spec;
 
@@ -365,9 +1287,10 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec)
 
 	spec->multiout.num_dacs = 0;  /* no analog */
 	spec->multiout.max_channels = 8;
-	spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+	spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
 
-	codec->patch_ops = nvhdmi_patch_ops_8ch;
+	codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
 
 	return 0;
 }
@@ -384,7 +1307,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
 
 	spec->multiout.num_dacs = 0;  /* no analog */
 	spec->multiout.max_channels = 2;
-	spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+	spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
 
 	codec->patch_ops = nvhdmi_patch_ops_2ch;
 
@@ -395,13 +1319,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
  * patch entries
  */
 static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
-	{ .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
 	{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
 	{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
+	{ .id = 0x10de0002, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0003, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0005, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0006, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0007, .name = "MCP79/7A HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de000c, .name = "MCP89 HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
+	{ .id = 0x10de000b, .name = "GT21x HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
+	{ .id = 0x10de000d, .name = "GT240 HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
 	{} /* terminator */
 };
 
@@ -412,9 +1347,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006");
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:10de000c");
+MODULE_ALIAS("snd-hda-codec-id:10de000b");
+MODULE_ALIAS("snd-hda-codec-id:10de000d");
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
+MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
 
 static struct hda_codec_preset_list nvhdmi_list = {
 	.preset = snd_hda_preset_nvhdmi,
-- 
1.5.6


[-- Attachment #4: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-03  7:21               ` Wei Ni
@ 2010-03-03 21:49                 ` Takashi Iwai
  -1 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-03 21:49 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

At Wed, 3 Mar 2010 15:21:12 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I generate the new patch file, please check it.

Thanks.  Review comments below:

> @@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus)
>  
>  /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
>  static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
> +	[AZX_DRIVER_NVIDIA] = 8,

Are you sure that this works for all Nvidia controller chips including
the old nForce chipset?

 
> diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
> index 315a1c4..199f440 100644
> --- a/sound/pci/hda/Makefile
> +++ b/sound/pci/hda/Makefile
> @@ -17,7 +17,7 @@ snd-hda-codec-cirrus-objs :=	patch_cirrus.o
>  snd-hda-codec-ca0110-objs :=	patch_ca0110.o
>  snd-hda-codec-conexant-objs :=	patch_conexant.o
>  snd-hda-codec-via-objs :=	patch_via.o
> -snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o
> +snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o hda_eld.o
>  snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o

This is buggy.  You cannot create multiple modules containing the
same *.o file that exports symbols.

Instead, put hda_eld.o to snd-hda-codec-* (currently commented out),
and remove hda_eld.o from snd-hda-codec-intelhdmi-objs.


Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-03 21:49                 ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-03 21:49 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

At Wed, 3 Mar 2010 15:21:12 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I generate the new patch file, please check it.

Thanks.  Review comments below:

> @@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus)
>  
>  /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
>  static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
> +	[AZX_DRIVER_NVIDIA] = 8,

Are you sure that this works for all Nvidia controller chips including
the old nForce chipset?

 
> diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
> index 315a1c4..199f440 100644
> --- a/sound/pci/hda/Makefile
> +++ b/sound/pci/hda/Makefile
> @@ -17,7 +17,7 @@ snd-hda-codec-cirrus-objs :=	patch_cirrus.o
>  snd-hda-codec-ca0110-objs :=	patch_ca0110.o
>  snd-hda-codec-conexant-objs :=	patch_conexant.o
>  snd-hda-codec-via-objs :=	patch_via.o
> -snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o
> +snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o hda_eld.o
>  snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o

This is buggy.  You cannot create multiple modules containing the
same *.o file that exports symbols.

Instead, put hda_eld.o to snd-hda-codec-* (currently commented out),
and remove hda_eld.o from snd-hda-codec-intelhdmi-objs.


Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel]  [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-03  6:46     ` Takashi Iwai
@ 2010-03-04  1:17       ` Wu Fengguang
  -1 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-04  1:17 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Wei Ni, 'akpm', 'alsa-devel',
	'linux-kernel', 'Pavel Hofman'

On Wed, Mar 03, 2010 at 02:46:25PM +0800, Takashi Iwai wrote:
> At Tue, 2 Mar 2010 13:43:07 +0800,
> Wu Fengguang wrote:
> > 
> > On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> > > Hi, Takashi
> > > I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> > > The new HAD controller and codec support standard HDMI operation.
> > > 
> > > I attached the patch file, please check it.
> > 
> > Wei Ni,
> > 
> > Can we avoid the big copy&paste and do more code reuse?
> > This benefits all of us in long term.
> 
> The plan is to merge all current patch_*hdmi.c into one.
> But this can be done later once after we get the working driver
> for the new Nvidia codecs.
> 
> The new Nvidia HDMI codec is a bit tricky (which has 4 separate
> codec slots), so I'd like to get it working first.

OK, it makes sense to solve one problem at a time.

Wei Ni, would you ensure these naming rules:

- unmodified functions: keep the original function name hdmi_*
  (if the original function name is intelhdmi_*, rename it to hdmi_*)

- modified function: rename function name to nvhdmi_*
  (if the original function name is hdmi_*, rename it to intel_hdmi_*)

And do the same for data structures, enums, variables, etc.

This hopefully will make it easier to do the future merge.

Thanks,
Fengguang

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-04  1:17       ` Wu Fengguang
  0 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-04  1:17 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: 'Pavel Hofman', Wei Ni, 'akpm',
	'alsa-devel', 'linux-kernel'

On Wed, Mar 03, 2010 at 02:46:25PM +0800, Takashi Iwai wrote:
> At Tue, 2 Mar 2010 13:43:07 +0800,
> Wu Fengguang wrote:
> > 
> > On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> > > Hi, Takashi
> > > I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> > > The new HAD controller and codec support standard HDMI operation.
> > > 
> > > I attached the patch file, please check it.
> > 
> > Wei Ni,
> > 
> > Can we avoid the big copy&paste and do more code reuse?
> > This benefits all of us in long term.
> 
> The plan is to merge all current patch_*hdmi.c into one.
> But this can be done later once after we get the working driver
> for the new Nvidia codecs.
> 
> The new Nvidia HDMI codec is a bit tricky (which has 4 separate
> codec slots), so I'd like to get it working first.

OK, it makes sense to solve one problem at a time.

Wei Ni, would you ensure these naming rules:

- unmodified functions: keep the original function name hdmi_*
  (if the original function name is intelhdmi_*, rename it to hdmi_*)

- modified function: rename function name to nvhdmi_*
  (if the original function name is hdmi_*, rename it to intel_hdmi_*)

And do the same for data structures, enums, variables, etc.

This hopefully will make it easier to do the future merge.

Thanks,
Fengguang

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel]  [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-03  6:46     ` Takashi Iwai
  (?)
  (?)
@ 2010-03-04  2:18     ` Wu Fengguang
  2010-03-04  5:44       ` Wu Fengguang
  -1 siblings, 1 reply; 80+ messages in thread
From: Wu Fengguang @ 2010-03-04  2:18 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Wei Ni, 'akpm', 'alsa-devel',
	'linux-kernel', 'Pavel Hofman'

On Wed, Mar 03, 2010 at 02:46:25PM +0800, Takashi Iwai wrote:
> At Tue, 2 Mar 2010 13:43:07 +0800,
> Wu Fengguang wrote:
> > 
> > On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> > > Hi, Takashi
> > > I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> > > The new HAD controller and codec support standard HDMI operation.
> > > 
> > > I attached the patch file, please check it.
> > 
> > Wei Ni,
> > 
> > Can we avoid the big copy&paste and do more code reuse?
> > This benefits all of us in long term.
> 
> The plan is to merge all current patch_*hdmi.c into one.
> But this can be done later once after we get the working driver
> for the new Nvidia codecs.
> 
> The new Nvidia HDMI codec is a bit tricky (which has 4 separate
> codec slots), so I'd like to get it working first.

Here is the patch to merge common code in a simple way.
This is compile tested only, need double check.

What puzzled me is that Wei Ni reused the same dynamic parsing code,
even though the Intel/Nvidia codecs have vastly different pin/cvt
layouts..

Thanks,
Fengguang
---
hdmi - create patch_hdmi.c common hdmi code 

For now the patch_hdmi.c file is not a real codec patch, but simply
included by patch_intelhdmi.c and patch_nvhdmi.c.

CC: Wei Ni <wni@nvidia.com>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
---
 sound/pci/hda/patch_hdmi.c      |  811 +++++++++++++++++++++++++++++
 sound/pci/hda/patch_intelhdmi.c |  575 ---------------------
 sound/pci/hda/patch_nvhdmi.c    |  817 ------------------------------
 3 files changed, 839 insertions(+), 1364 deletions(-)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ sound-2.6/sound/pci/hda/patch_hdmi.c	2010-03-04 09:58:52.000000000 +0800
@@ -0,0 +1,811 @@
+/*
+ * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
+ * could support two independent pipes, each of them can be connected to one or
+ * more ports (DVI, HDMI or DisplayPort).
+ *
+ * The HDA correspondence of pipes/ports are converter/pin nodes.
+ */
+#define MAX_HDMI_CVTS	2
+#define MAX_HDMI_PINS	3
+
+
+struct hdmi_spec {
+	int num_cvts;
+	int num_pins;
+	hda_nid_t cvt[MAX_HDMI_CVTS+1];  /* audio sources */
+	hda_nid_t pin[MAX_HDMI_PINS+1];  /* audio sinks */
+
+	/*
+	 * source connection for each pin
+	 */
+	hda_nid_t pin_cvt[MAX_HDMI_PINS+1];
+
+	/*
+	 * HDMI sink attached to each pin
+	 */
+	struct hdmi_eld sink_eld[MAX_HDMI_PINS];
+
+	/*
+	 * export one pcm per pipe
+	 */
+	struct hda_pcm	pcm_rec[MAX_HDMI_CVTS];
+
+	/*
+	 * nvhdmi specific
+	 */
+	struct hda_multi_out multiout;
+	unsigned int codec_type;
+};
+
+
+struct hdmi_audio_infoframe {
+	u8 type; /* 0x84 */
+	u8 ver;  /* 0x01 */
+	u8 len;  /* 0x0a */
+
+	u8 checksum;	/* PB0 */
+	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
+	u8 SS01_SF24;
+	u8 CXT04;
+	u8 CA;
+	u8 LFEPBL01_LSV36_DM_INH7;
+};
+
+/*
+ * CEA speaker placement:
+ *
+ *        FLH       FCH        FRH
+ *  FLW    FL  FLC   FC   FRC   FR   FRW
+ *
+ *                                  LFE
+ *                     TC
+ *
+ *          RL  RLC   RC   RRC   RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+	FL  = (1 <<  0),	/* Front Left           */
+	FC  = (1 <<  1),	/* Front Center         */
+	FR  = (1 <<  2),	/* Front Right          */
+	FLC = (1 <<  3),	/* Front Left Center    */
+	FRC = (1 <<  4),	/* Front Right Center   */
+	RL  = (1 <<  5),	/* Rear Left            */
+	RC  = (1 <<  6),	/* Rear Center          */
+	RR  = (1 <<  7),	/* Rear Right           */
+	RLC = (1 <<  8),	/* Rear Left Center     */
+	RRC = (1 <<  9),	/* Rear Right Center    */
+	LFE = (1 << 10),	/* Low Frequency Effect */
+	FLW = (1 << 11),	/* Front Left Wide      */
+	FRW = (1 << 12),	/* Front Right Wide     */
+	FLH = (1 << 13),	/* Front Left High      */
+	FCH = (1 << 14),	/* Front Center High    */
+	FRH = (1 << 15),	/* Front Right High     */
+	TC  = (1 << 16),	/* Top Center           */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+	[0] = FL | FR,
+	[1] = LFE,
+	[2] = FC,
+	[3] = RL | RR,
+	[4] = RC,
+	[5] = FLC | FRC,
+	[6] = RLC | RRC,
+	/* the following are not defined in ELD yet */
+	[7] = FLW | FRW,
+	[8] = FLH | FRH,
+	[9] = TC,
+	[10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+	int ca_index;
+	int speakers[8];
+
+	/* derived values, just for convenience */
+	int channels;
+	int spk_mask;
+};
+
+/*
+ * ALSA sequence is:
+ *
+ *       surround40   surround41   surround50   surround51   surround71
+ * ch0   front left   =            =            =            =
+ * ch1   front right  =            =            =            =
+ * ch2   rear left    =            =            =            =
+ * ch3   rear right   =            =            =            =
+ * ch4                LFE          center       center       center
+ * ch5                                          LFE          LFE
+ * ch6                                                       side left
+ * ch7                                                       side right
+ *
+ * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
+ */
+static int hdmi_channel_mapping[0x32][8] = {
+	/* stereo */
+	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* 2.1 */
+	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* Dolby Surround */
+	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* surround40 */
+	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
+	/* 4ch */
+	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
+	/* surround41 */
+	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround50 */
+	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround51 */
+	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
+	/* 7.1 */
+	[0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/* 			  channel:   7     6    5    4    3     2    1    0  */
+{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
+				 /* 2.1 */
+{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
+				 /* Dolby Surround */
+{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
+				 /* surround40 */
+{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
+				 /* surround41 */
+{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
+				 /* surround50 */
+{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+				 /* surround51 */
+{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* 6.1 */
+{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* surround71 */
+{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+
+{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
+{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
+};
+
+/*
+ * HDA/HDMI auto parsing
+ */
+
+static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+{
+	int i;
+
+	for (i = 0; nids[i]; i++)
+		if (nids[i] == nid)
+			return i;
+
+	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+	return -EINVAL;
+}
+
+static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct hdmi_spec *spec = codec->spec;
+	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+	int conn_len, curr;
+	int index;
+
+	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
+		snd_printk(KERN_WARNING
+			   "HDMI: pin %d wcaps %#x "
+			   "does not support connection list\n",
+			   pin_nid, get_wcaps(codec, pin_nid));
+		return -EINVAL;
+	}
+
+	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
+					   HDA_MAX_CONNECTIONS);
+	if (conn_len > 1)
+		curr = snd_hda_codec_read(codec, pin_nid, 0,
+					  AC_VERB_GET_CONNECT_SEL, 0);
+	else
+		curr = 0;
+
+	index = hda_node_index(spec->pin, pin_nid);
+	if (index < 0)
+		return -EINVAL;
+
+	spec->pin_cvt[index] = conn_list[curr];
+
+	return 0;
+}
+
+static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
+			      struct hdmi_eld *eld)
+{
+	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+		snd_hdmi_show_eld(eld);
+}
+
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+			       struct hdmi_eld *eld)
+{
+	int present = snd_hda_pin_sense(codec, pin_nid);
+
+	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
+	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
+
+	if (present & AC_PINSENSE_ELDV)
+		hdmi_get_show_eld(codec, pin_nid, eld);
+}
+
+/*
+ * HDMI routines
+ */
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int *packet_index, int *byte_index)
+{
+	int val;
+
+	val = snd_hda_codec_read(codec, pin_nid, 0,
+				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+	*packet_index = val >> 5;
+	*byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int packet_index, int byte_index)
+{
+	int val;
+
+	val = (packet_index << 5) | (byte_index & 0x1f);
+
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
+				unsigned char val)
+{
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	/* Unmute */
+	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
+		snd_hda_codec_write(codec, pin_nid, 0,
+				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	/* Enable pin out */
+	snd_hda_codec_write(codec, pin_nid, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+}
+
+/*
+ * Enable Audio InfoFrame Transmission
+ */
+static void hdmi_start_infoframe_trans(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_BEST);
+}
+
+/*
+ * Disable Audio InfoFrame Transmission
+ */
+static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
+				      hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_DISABLE);
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+{
+	return 1 + snd_hda_codec_read(codec, nid, 0,
+					AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec,
+				   hda_nid_t nid, int chs)
+{
+	if (chs != hdmi_get_channel_count(codec, nid))
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int slot;
+
+	for (i = 0; i < 8; i++) {
+		slot = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_CHAN_SLOT, i);
+		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+						slot >> 4, slot & 0xf);
+	}
+#endif
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int size;
+
+	size = snd_hdmi_get_eld_size(codec, pin_nid);
+	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+	}
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef BE_PARANOID
+	int i, j;
+	int size;
+	int pi, bi;
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		if (size == 0)
+			continue;
+
+		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
+		for (j = 1; j < 1000; j++) {
+			hdmi_write_dip_byte(codec, pin_nid, 0x0);
+			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
+			if (pi != i)
+				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+						bi, pi, i);
+			if (bi == 0) /* byte index wrapped around */
+				break;
+		}
+		snd_printd(KERN_INFO
+			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+			i, size, j);
+	}
+#endif
+}
+
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+{
+	ai->checksum = 0;
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+				      hda_nid_t pin_nid,
+				      struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	int i;
+
+	hdmi_debug_dip_size(codec, pin_nid);
+	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
+
+	hdmi_checksum_audio_infoframe(ai);
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++)
+		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+}
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+	int i, j;
+	struct cea_channel_speaker_allocation *p;
+
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		p = channel_allocations + i;
+		p->channels = 0;
+		p->spk_mask = 0;
+		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+			if (p->speakers[j]) {
+				p->channels++;
+				p->spk_mask |= p->speakers[j];
+			}
+	}
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ * 	      spk_mask => (channel_allocations[])         => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+					 struct hdmi_audio_infoframe *ai)
+{
+	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_eld *eld;
+	int i;
+	int spk_mask = 0;
+	int channels = 1 + (ai->CC02_CT47 & 0x7);
+	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+	/*
+	 * CA defaults to 0 for basic stereo audio
+	 */
+	if (channels <= 2)
+		return 0;
+
+	i = hda_node_index(spec->pin_cvt, nid);
+	if (i < 0)
+		return 0;
+	eld = &spec->sink_eld[i];
+
+	/*
+	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+	 * in console or for audio devices. Assume the highest speakers
+	 * configuration, to _not_ prohibit multi-channel audio playback.
+	 */
+	if (!eld->spk_alloc)
+		eld->spk_alloc = 0xffff;
+
+	/*
+	 * expand ELD's speaker allocation mask
+	 *
+	 * ELD tells the speaker mask in a compact(paired) form,
+	 * expand ELD's notions to match the ones used by Audio InfoFrame.
+	 */
+	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+		if (eld->spk_alloc & (1 << i))
+			spk_mask |= eld_speaker_allocation_bits[i];
+	}
+
+	/* search for the first working match in the CA table */
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		if (channels == channel_allocations[i].channels &&
+		    (spk_mask & channel_allocations[i].spk_mask) ==
+				channel_allocations[i].spk_mask) {
+			ai->CA = channel_allocations[i].ca_index;
+			break;
+		}
+	}
+
+	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+	snd_printdd(KERN_INFO
+			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+			ai->CA, channels, buf);
+
+	return ai->CA;
+}
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid,
+				       struct hdmi_audio_infoframe *ai)
+{
+	int i;
+	int ca = ai->CA;
+	int err;
+
+	if (hdmi_channel_mapping[ca][1] == 0) {
+		for (i = 0; i < channel_allocations[ca].channels; i++)
+			hdmi_channel_mapping[ca][i] = i | (i << 4);
+		for (; i < 8; i++)
+			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+	}
+
+	for (i = 0; i < 8; i++) {
+		err = snd_hda_codec_write(codec, pin_nid, 0,
+					  AC_VERB_SET_HDMI_CHAN_SLOT,
+					  hdmi_channel_mapping[ca][i]);
+		if (err) {
+			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
+			break;
+		}
+	}
+
+	hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
+				    struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	u8 val;
+	int i;
+
+	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
+							    != AC_DIPXMIT_BEST)
+		return false;
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++) {
+		val = snd_hda_codec_read(codec, pin_nid, 0,
+					 AC_VERB_GET_HDMI_DIP_DATA, 0);
+		if (val != bytes[i])
+			return false;
+	}
+
+	return true;
+}
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+					struct snd_pcm_substream *substream)
+{
+	struct hdmi_spec *spec = codec->spec;
+	hda_nid_t pin_nid;
+	int i;
+	struct hdmi_audio_infoframe ai = {
+		.type		= 0x84,
+		.ver		= 0x01,
+		.len		= 0x0a,
+		.CC02_CT47	= substream->runtime->channels - 1,
+	};
+
+	hdmi_setup_channel_allocation(codec, nid, &ai);
+
+	for (i = 0; i < spec->num_pins; i++) {
+		if (spec->pin_cvt[i] != nid)
+			continue;
+		if (!spec->sink_eld[i].monitor_present)
+			continue;
+
+		pin_nid = spec->pin[i];
+		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+			hdmi_stop_infoframe_trans(codec, pin_nid);
+			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+			hdmi_start_infoframe_trans(codec, pin_nid);
+		}
+	}
+}
+
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int pind = !!(res & AC_UNSOL_RES_PD);
+	int eldv = !!(res & AC_UNSOL_RES_ELDV);
+	int index;
+
+	printk(KERN_INFO
+		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+		tag, pind, eldv);
+
+	index = hda_node_index(spec->pin, tag);
+	if (index < 0)
+		return;
+
+	spec->sink_eld[index].monitor_present = pind;
+	spec->sink_eld[index].eld_valid = eldv;
+
+	if (pind && eldv) {
+		hdmi_get_show_eld(codec, spec->pin[index],
+				  &spec->sink_eld[index]);
+		/* TODO: do real things about ELD */
+	}
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+	printk(KERN_INFO
+		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+		tag,
+		subtag,
+		cp_state,
+		cp_ready);
+
+	/* TODO */
+	if (cp_state)
+		;
+	if (cp_ready)
+		;
+}
+
+
+static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+	if (hda_node_index(spec->pin, tag) < 0) {
+		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+		return;
+	}
+
+	if (subtag == 0)
+		hdmi_intrinsic_event(codec, res);
+	else
+		hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+			      u32 stream_tag, int format)
+{
+	int tag;
+	int fmt;
+
+	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
+	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
+
+	snd_printdd("hdmi_setup_stream: "
+		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
+		    nid,
+		    tag == stream_tag ? "" : "new-",
+		    stream_tag,
+		    fmt == format ? "" : "new-",
+		    format);
+
+	if (tag != stream_tag)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CHANNEL_STREAMID,
+				    stream_tag << 4);
+	if (fmt != format)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_STREAM_FORMAT, format);
+}
+
+static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct hdmi_spec *spec = codec->spec;
+
+	if (spec->num_pins >= MAX_HDMI_PINS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for pin %d \n", pin_nid);
+		return -EINVAL;
+	}
+
+	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+
+	spec->pin[spec->num_pins] = pin_nid;
+	spec->num_pins++;
+
+	/*
+	 * It is assumed that converter nodes come first in the node list and
+	 * hence have been registered and usable now.
+	 */
+	return hdmi_read_pin_conn(codec, pin_nid);
+}
+
+static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct hdmi_spec *spec = codec->spec;
+
+	if (spec->num_cvts >= MAX_HDMI_CVTS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for converter %d \n", nid);
+		return -EINVAL;
+	}
+
+	spec->cvt[spec->num_cvts] = nid;
+	spec->num_cvts++;
+
+	return 0;
+}
+
+static int hdmi_parse_codec(struct hda_codec *codec)
+{
+	hda_nid_t nid;
+	int i, nodes;
+
+	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+	if (!nid || nodes < 0) {
+		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nodes; i++, nid++) {
+		unsigned int caps;
+		unsigned int type;
+
+		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+		type = get_wcaps_type(caps);
+
+		if (!(caps & AC_WCAP_DIGITAL))
+			continue;
+
+		switch (type) {
+		case AC_WID_AUD_OUT:
+			if (hdmi_add_cvt(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		case AC_WID_PIN:
+			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+				continue;
+			if (hdmi_add_pin(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		}
+	}
+
+	/*
+	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
+	 * can be lost and presence sense verb will become inaccurate if the
+	 * HDA link is powered off at hot plug or hw initialization time.
+	 */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+	      AC_PWRST_EPSS))
+		codec->bus->power_keep_link_on = 1;
+#endif
+
+	return 0;
+}
+
--- sound-2.6.orig/sound/pci/hda/patch_intelhdmi.c	2010-03-04 09:47:39.000000000 +0800
+++ sound-2.6/sound/pci/hda/patch_intelhdmi.c	2010-03-04 10:00:29.000000000 +0800
@@ -33,575 +33,20 @@
 #include "hda_codec.h"
 #include "hda_local.h"
 
-/*
- * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
- * could support two independent pipes, each of them can be connected to one or
- * more ports (DVI, HDMI or DisplayPort).
- *
- * The HDA correspondence of pipes/ports are converter/pin nodes.
- */
+#include "patch_hdmi.c"
+
 #define INTEL_HDMI_CVTS	2
 #define INTEL_HDMI_PINS	3
 
-static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = {
+static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
 	"INTEL HDMI 0",
 	"INTEL HDMI 1",
 };
 
-struct intel_hdmi_spec {
-	int num_cvts;
-	int num_pins;
-	hda_nid_t cvt[INTEL_HDMI_CVTS+1];  /* audio sources */
-	hda_nid_t pin[INTEL_HDMI_PINS+1];  /* audio sinks */
-
-	/*
-	 * source connection for each pin
-	 */
-	hda_nid_t pin_cvt[INTEL_HDMI_PINS+1];
-
-	/*
-	 * HDMI sink attached to each pin
-	 */
-	struct hdmi_eld sink_eld[INTEL_HDMI_PINS];
-
-	/*
-	 * export one pcm per pipe
-	 */
-	struct hda_pcm	pcm_rec[INTEL_HDMI_CVTS];
-};
-
-static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-
-	if (spec->num_pins >= INTEL_HDMI_PINS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for pin %d \n", pin_nid);
-		return -EINVAL;
-	}
-
-	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
-
-	spec->pin[spec->num_pins] = pin_nid;
-	spec->num_pins++;
-
-	/*
-	 * It is assumed that converter nodes come first in the node list and
-	 * hence have been registered and usable now.
-	 */
-	return intel_hdmi_read_pin_conn(codec, pin_nid);
-}
-
-static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-
-	if (spec->num_cvts >= INTEL_HDMI_CVTS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for converter %d \n", nid);
-		return -EINVAL;
-	}
-
-	spec->cvt[spec->num_cvts] = nid;
-	spec->num_cvts++;
-
-	return 0;
-}
-
-static int intel_hdmi_parse_codec(struct hda_codec *codec)
-{
-	hda_nid_t nid;
-	int i, nodes;
-
-	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
-	if (!nid || nodes < 0) {
-		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < nodes; i++, nid++) {
-		unsigned int caps;
-		unsigned int type;
-
-		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
-		type = get_wcaps_type(caps);
-
-		if (!(caps & AC_WCAP_DIGITAL))
-			continue;
-
-		switch (type) {
-		case AC_WID_AUD_OUT:
-			if (intel_hdmi_add_cvt(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		case AC_WID_PIN:
-			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
-				continue;
-			if (intel_hdmi_add_pin(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		}
-	}
-
-	/*
-	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
-	 * can be lost and presence sense verb will become inaccurate if the
-	 * HDA link is powered off at hot plug or hw initialization time.
-	 */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
-	      AC_PWRST_EPSS))
-		codec->bus->power_keep_link_on = 1;
-#endif
-
-	return 0;
-}
-
 /*
  * HDMI routines
  */
 
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int *packet_index, int *byte_index)
-{
-	int val;
-
-	val = snd_hda_codec_read(codec, pin_nid, 0,
-				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
-	*packet_index = val >> 5;
-	*byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int packet_index, int byte_index)
-{
-	int val;
-
-	val = (packet_index << 5) | (byte_index & 0x1f);
-
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
-				unsigned char val)
-{
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	/* Unmute */
-	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
-		snd_hda_codec_write(codec, pin_nid, 0,
-				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-	/* Enable pin out */
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
-				      hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_DISABLE);
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
-{
-	return 1 + snd_hda_codec_read(codec, nid, 0,
-					AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec,
-				   hda_nid_t nid, int chs)
-{
-	if (chs != hdmi_get_channel_count(codec, nid))
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int slot;
-
-	for (i = 0; i < 8; i++) {
-		slot = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_CHAN_SLOT, i);
-		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
-						slot >> 4, slot & 0xf);
-	}
-#endif
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int size;
-
-	size = snd_hdmi_get_eld_size(codec, pin_nid);
-	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
-	}
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
-	int i, j;
-	int size;
-	int pi, bi;
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		if (size == 0)
-			continue;
-
-		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
-		for (j = 1; j < 1000; j++) {
-			hdmi_write_dip_byte(codec, pin_nid, 0x0);
-			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
-			if (pi != i)
-				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
-						bi, pi, i);
-			if (bi == 0) /* byte index wrapped around */
-				break;
-		}
-		snd_printd(KERN_INFO
-			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
-			i, size, j);
-	}
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	u8 sum = 0;
-	int i;
-
-	ai->checksum = 0;
-
-	for (i = 0; i < sizeof(*ai); i++)
-		sum += bytes[i];
-
-	ai->checksum = - sum;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
-				      hda_nid_t pin_nid,
-				      struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	int i;
-
-	hdmi_debug_dip_size(codec, pin_nid);
-	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
-	hdmi_checksum_audio_infoframe(ai);
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++)
-		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
-	int i, j;
-	struct cea_channel_speaker_allocation *p;
-
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		p = channel_allocations + i;
-		p->channels = 0;
-		p->spk_mask = 0;
-		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-			if (p->speakers[j]) {
-				p->channels++;
-				p->spk_mask |= p->speakers[j];
-			}
-	}
-}
-
-/*
- * The transformation takes two steps:
- *
- * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- * 	      spk_mask => (channel_allocations[])         => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
-					 struct hdmi_audio_infoframe *ai)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	struct hdmi_eld *eld;
-	int i;
-	int spk_mask = 0;
-	int channels = 1 + (ai->CC02_CT47 & 0x7);
-	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
-	/*
-	 * CA defaults to 0 for basic stereo audio
-	 */
-	if (channels <= 2)
-		return 0;
-
-	i = hda_node_index(spec->pin_cvt, nid);
-	if (i < 0)
-		return 0;
-	eld = &spec->sink_eld[i];
-
-	/*
-	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-	 * in console or for audio devices. Assume the highest speakers
-	 * configuration, to _not_ prohibit multi-channel audio playback.
-	 */
-	if (!eld->spk_alloc)
-		eld->spk_alloc = 0xffff;
-
-	/*
-	 * expand ELD's speaker allocation mask
-	 *
-	 * ELD tells the speaker mask in a compact(paired) form,
-	 * expand ELD's notions to match the ones used by Audio InfoFrame.
-	 */
-	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-		if (eld->spk_alloc & (1 << i))
-			spk_mask |= eld_speaker_allocation_bits[i];
-	}
-
-	/* search for the first working match in the CA table */
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if (channels == channel_allocations[i].channels &&
-		    (spk_mask & channel_allocations[i].spk_mask) ==
-				channel_allocations[i].spk_mask) {
-			ai->CA = channel_allocations[i].ca_index;
-			break;
-		}
-	}
-
-	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
-	snd_printdd(KERN_INFO
-			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
-			ai->CA, channels, buf);
-
-	return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid,
-				       struct hdmi_audio_infoframe *ai)
-{
-	int i;
-	int ca = ai->CA;
-	int err;
-
-	if (hdmi_channel_mapping[ca][1] == 0) {
-		for (i = 0; i < channel_allocations[ca].channels; i++)
-			hdmi_channel_mapping[ca][i] = i | (i << 4);
-		for (; i < 8; i++)
-			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
-	}
-
-	for (i = 0; i < 8; i++) {
-		err = snd_hda_codec_write(codec, pin_nid, 0,
-					  AC_VERB_SET_HDMI_CHAN_SLOT,
-					  hdmi_channel_mapping[ca][i]);
-		if (err) {
-			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
-			break;
-		}
-	}
-
-	hdmi_debug_channel_mapping(codec, pin_nid);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
-				    struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	u8 val;
-	int i;
-
-	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
-							    != AC_DIPXMIT_BEST)
-		return false;
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++) {
-		val = snd_hda_codec_read(codec, pin_nid, 0,
-					 AC_VERB_GET_HDMI_DIP_DATA, 0);
-		if (val != bytes[i])
-			return false;
-	}
-
-	return true;
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
-					struct snd_pcm_substream *substream)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	hda_nid_t pin_nid;
-	int i;
-	struct hdmi_audio_infoframe ai = {
-		.type		= 0x84,
-		.ver		= 0x01,
-		.len		= 0x0a,
-		.CC02_CT47	= substream->runtime->channels - 1,
-	};
-
-	hdmi_setup_channel_allocation(codec, nid, &ai);
-
-	for (i = 0; i < spec->num_pins; i++) {
-		if (spec->pin_cvt[i] != nid)
-			continue;
-		if (!spec->sink_eld[i].monitor_present)
-			continue;
-
-		pin_nid = spec->pin[i];
-		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
-			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
-			hdmi_stop_infoframe_trans(codec, pin_nid);
-			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
-			hdmi_start_infoframe_trans(codec, pin_nid);
-		}
-	}
-}
-
-
-/*
- * Unsolicited events
- */
-
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int pind = !!(res & AC_UNSOL_RES_PD);
-	int eldv = !!(res & AC_UNSOL_RES_ELDV);
-	int index;
-
-	printk(KERN_INFO
-		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-		tag, pind, eldv);
-
-	index = hda_node_index(spec->pin, tag);
-	if (index < 0)
-		return;
-
-	spec->sink_eld[index].monitor_present = pind;
-	spec->sink_eld[index].eld_valid = eldv;
-
-	if (pind && eldv) {
-		hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]);
-		/* TODO: do real things about ELD */
-	}
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
-	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
-	printk(KERN_INFO
-		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
-		tag,
-		subtag,
-		cp_state,
-		cp_ready);
-
-	/* TODO */
-	if (cp_state)
-		;
-	if (cp_ready)
-		;
-}
-
-
-static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
-	if (hda_node_index(spec->pin, tag) < 0) {
-		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
-		return;
-	}
-
-	if (subtag == 0)
-		hdmi_intrinsic_event(codec, res);
-	else
-		hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-			      u32 stream_tag, int format)
-{
-	int tag;
-	int fmt;
-
-	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
-	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
-	snd_printdd("hdmi_setup_stream: "
-		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
-		    nid,
-		    tag == stream_tag ? "" : "new-",
-		    stream_tag,
-		    fmt == format ? "" : "new-",
-		    format);
-
-	if (tag != stream_tag)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4);
-	if (fmt != format)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_STREAM_FORMAT, format);
-}
-
 static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 					   struct hda_codec *codec,
 					   unsigned int stream_tag,
@@ -635,7 +80,7 @@ static struct hda_pcm_stream intel_hdmi_
 
 static int intel_hdmi_build_pcms(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
 	int i;
 
@@ -661,7 +106,7 @@ static int intel_hdmi_build_pcms(struct 
 
 static int intel_hdmi_build_controls(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int err;
 	int i;
 
@@ -676,7 +121,7 @@ static int intel_hdmi_build_controls(str
 
 static int intel_hdmi_init(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	for (i = 0; spec->pin[i]; i++) {
@@ -690,7 +135,7 @@ static int intel_hdmi_init(struct hda_co
 
 static void intel_hdmi_free(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	for (i = 0; i < spec->num_pins; i++)
@@ -704,12 +149,12 @@ static struct hda_codec_ops intel_hdmi_p
 	.free			= intel_hdmi_free,
 	.build_pcms		= intel_hdmi_build_pcms,
 	.build_controls 	= intel_hdmi_build_controls,
-	.unsol_event		= intel_hdmi_unsol_event,
+	.unsol_event		= hdmi_unsol_event,
 };
 
 static int patch_intel_hdmi(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec;
+	struct hdmi_spec *spec;
 	int i;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -717,7 +162,7 @@ static int patch_intel_hdmi(struct hda_c
 		return -ENOMEM;
 
 	codec->spec = spec;
-	if (intel_hdmi_parse_codec(codec) < 0) {
+	if (hdmi_parse_codec(codec) < 0) {
 		codec->spec = NULL;
 		kfree(spec);
 		return -EINVAL;
--- sound-2.6.orig/sound/pci/hda/patch_nvhdmi.c	2010-03-04 09:47:48.000000000 +0800
+++ sound-2.6/sound/pci/hda/patch_nvhdmi.c	2010-03-04 10:01:04.000000000 +0800
@@ -29,6 +29,8 @@
 #include "hda_codec.h"
 #include "hda_local.h"
 
+#include "patch_hdmi.c"
+
 /* define below to restrict the supported rates and formats */
 /* #define LIMITED_RATE_FMT_SUPPORT */
 
@@ -86,799 +88,16 @@ static struct hda_verb nvhdmi_basic_init
 #define NVIDIA_89_HDMI_CVTS	1
 #define NVIDIA_89_HDMI_PINS	1
 
-static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = {
+static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
 	"NVIDIA HDMI",
 };
 
-struct nvhdmi_spec {
-	int num_cvts;
-	int num_pins;
-	hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1];  /* audio sources */
-	hda_nid_t pin[NVIDIA_89_HDMI_PINS+1];  /* audio sinks */
-	hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1];
-	struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS];
-	struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS];
-	struct hda_multi_out multiout;
-	unsigned int codec_type;
-};
-
-struct hdmi_audio_infoframe {
-	u8 type; /* 0x84 */
-	u8 ver;  /* 0x01 */
-	u8 len;  /* 0x0a */
-
-	u8 checksum;	/* PB0 */
-	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
-	u8 SS01_SF24;
-	u8 CXT04;
-	u8 CA;
-	u8 LFEPBL01_LSV36_DM_INH7;
-};
-
-/*
- * CEA speaker placement:
- *
- *        FLH       FCH        FRH
- *  FLW    FL  FLC   FC   FRC   FR   FRW
- *
- *                                  LFE
- *                     TC
- *
- *          RL  RLC   RC   RRC   RR
- *
- * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
- * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
- */
-enum cea_speaker_placement {
-	FL  = (1 <<  0),	/* Front Left           */
-	FC  = (1 <<  1),	/* Front Center         */
-	FR  = (1 <<  2),	/* Front Right          */
-	FLC = (1 <<  3),	/* Front Left Center    */
-	FRC = (1 <<  4),	/* Front Right Center   */
-	RL  = (1 <<  5),	/* Rear Left            */
-	RC  = (1 <<  6),	/* Rear Center          */
-	RR  = (1 <<  7),	/* Rear Right           */
-	RLC = (1 <<  8),	/* Rear Left Center     */
-	RRC = (1 <<  9),	/* Rear Right Center    */
-	LFE = (1 << 10),	/* Low Frequency Effect */
-	FLW = (1 << 11),	/* Front Left Wide      */
-	FRW = (1 << 12),	/* Front Right Wide     */
-	FLH = (1 << 13),	/* Front Left High      */
-	FCH = (1 << 14),	/* Front Center High    */
-	FRH = (1 << 15),	/* Front Right High     */
-	TC  = (1 << 16),	/* Top Center           */
-};
-
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static int eld_speaker_allocation_bits[] = {
-	[0] = FL | FR,
-	[1] = LFE,
-	[2] = FC,
-	[3] = RL | RR,
-	[4] = RC,
-	[5] = FLC | FRC,
-	[6] = RLC | RRC,
-	/* the following are not defined in ELD yet */
-	[7] = FLW | FRW,
-	[8] = FLH | FRH,
-	[9] = TC,
-	[10] = FCH,
-};
-
-struct cea_channel_speaker_allocation {
-	int ca_index;
-	int speakers[8];
-
-	/* derived values, just for convenience */
-	int channels;
-	int spk_mask;
-};
-
-/*
- * ALSA sequence is:
- *
- *       surround40   surround41   surround50   surround51   surround71
- * ch0   front left   =            =            =            =
- * ch1   front right  =            =            =            =
- * ch2   rear left    =            =            =            =
- * ch3   rear right   =            =            =            =
- * ch4                LFE          center       center       center
- * ch5                                          LFE          LFE
- * ch6                                                       side left
- * ch7                                                       side right
- *
- * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
- */
-static int hdmi_channel_mapping[0x32][8] = {
-	/* stereo */
-	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* 2.1 */
-	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* Dolby Surround */
-	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* surround40 */
-	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
-	/* 4ch */
-	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
-	/* surround41 */
-	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
-	/* surround50 */
-	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
-	/* surround51 */
-	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
-	/* 7.1 */
-	[0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/* 			  channel:   7     6    5    4    3     2    1    0  */
-{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
-				 /* 2.1 */
-{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
-				 /* Dolby Surround */
-{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
-				 /* surround40 */
-{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
-				 /* surround41 */
-{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
-				 /* surround50 */
-{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-				 /* surround51 */
-{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* 6.1 */
-{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* surround71 */
-{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-
-{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
-{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
-};
-
-/*
- * HDA/HDMI auto parsing
- */
-
-static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
-{
-	int i;
-
-	for (i = 0; nids[i]; i++)
-		if (nids[i] == nid)
-			return i;
-
-	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
-	return -EINVAL;
-}
-
-static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
-	int conn_len, curr;
-	int index;
-
-	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
-		snd_printk(KERN_WARNING
-			   "HDMI: pin %d wcaps %#x "
-			   "does not support connection list\n",
-			   pin_nid, get_wcaps(codec, pin_nid));
-		return -EINVAL;
-	}
-
-	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
-					   HDA_MAX_CONNECTIONS);
-	if (conn_len > 1)
-		curr = snd_hda_codec_read(codec, pin_nid, 0,
-					  AC_VERB_GET_CONNECT_SEL, 0);
-	else
-		curr = 0;
-
-	index = hda_node_index(spec->pin, pin_nid);
-	if (index < 0)
-		return -EINVAL;
-
-	spec->pin_cvt[index] = conn_list[curr];
-
-	return 0;
-}
-
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
-			      struct hdmi_eld *eld)
-{
-	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
-		snd_hdmi_show_eld(eld);
-}
-
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
-			       struct hdmi_eld *eld)
-{
-	int present = snd_hda_pin_sense(codec, pin_nid);
-
-	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
-	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
-
-	if (present & AC_PINSENSE_ELDV)
-		hdmi_get_show_eld(codec, pin_nid, eld);
-}
-
-static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-
-	if (spec->num_pins >= NVIDIA_89_HDMI_PINS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for pin %d \n", pin_nid);
-		return -EINVAL;
-	}
-
-	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
-
-	spec->pin[spec->num_pins] = pin_nid;
-	spec->num_pins++;
-
-	/*
-	 * It is assumed that converter nodes come first in the node list and
-	 * hence have been registered and usable now.
-	 */
-	return nvhdmi_read_pin_conn(codec, pin_nid);
-}
-
-static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-
-	if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for converter %d \n", nid);
-		return -EINVAL;
-	}
-
-	spec->cvt[spec->num_cvts] = nid;
-	spec->num_cvts++;
-
-	return 0;
-}
-
-
-static int nvhdmi_parse_codec(struct hda_codec *codec)
-{
-	hda_nid_t nid;
-	int i, nodes;
-
-	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
-	if (!nid || nodes < 0) {
-		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < nodes; i++, nid++) {
-		unsigned int caps;
-		unsigned int type;
-
-		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
-		type = get_wcaps_type(caps);
-
-		if (!(caps & AC_WCAP_DIGITAL))
-			continue;
-
-		switch (type) {
-		case AC_WID_AUD_OUT:
-			if (nvhdmi_add_cvt(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		case AC_WID_PIN:
-			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
-				continue;
-			if (nvhdmi_add_pin(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		}
-	}
-
-	/*
-	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
-	 * can be lost and presence sense verb will become inaccurate if the
-	 * HDA link is powered off at hot plug or hw initialization time.
-	 */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
-	      AC_PWRST_EPSS))
-		codec->bus->power_keep_link_on = 1;
-#endif
-
-	return 0;
-}
-
-/*
- * HDMI routines
- */
-
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int *packet_index, int *byte_index)
-{
-	int val;
-
-	val = snd_hda_codec_read(codec, pin_nid, 0,
-				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
-	*packet_index = val >> 5;
-	*byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int packet_index, int byte_index)
-{
-	int val;
-
-	val = (packet_index << 5) | (byte_index & 0x1f);
-
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
-				unsigned char val)
-{
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	/* Unmute */
-	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
-		snd_hda_codec_write(codec, pin_nid, 0,
-				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-	/* Enable pin out */
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
-				      hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_DISABLE);
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
-{
-	return 1 + snd_hda_codec_read(codec, nid, 0,
-					AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec,
-				   hda_nid_t nid, int chs)
-{
-	if (chs != hdmi_get_channel_count(codec, nid))
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int slot;
-
-	for (i = 0; i < 8; i++) {
-		slot = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_CHAN_SLOT, i);
-		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
-						slot >> 4, slot & 0xf);
-	}
-#endif
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int size;
-
-	size = snd_hdmi_get_eld_size(codec, pin_nid);
-	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
-	}
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
-	int i, j;
-	int size;
-	int pi, bi;
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		if (size == 0)
-			continue;
-
-		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
-		for (j = 1; j < 1000; j++) {
-			hdmi_write_dip_byte(codec, pin_nid, 0x0);
-			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
-			if (pi != i)
-				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
-						bi, pi, i);
-			if (bi == 0) /* byte index wrapped around */
-				break;
-		}
-		snd_printd(KERN_INFO
-			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
-			i, size, j);
-	}
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
-{
-	ai->checksum = 0;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
-				      hda_nid_t pin_nid,
-				      struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	int i;
-
-	hdmi_debug_dip_size(codec, pin_nid);
-	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
-	hdmi_checksum_audio_infoframe(ai);
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++)
-		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
-	int i, j;
-	struct cea_channel_speaker_allocation *p;
-
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		p = channel_allocations + i;
-		p->channels = 0;
-		p->spk_mask = 0;
-		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-			if (p->speakers[j]) {
-				p->channels++;
-				p->spk_mask |= p->speakers[j];
-			}
-	}
-}
-
-/*
- * The transformation takes two steps:
- *
- * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- * 	      spk_mask => (channel_allocations[])         => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
-					 struct hdmi_audio_infoframe *ai)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	struct hdmi_eld *eld;
-	int i;
-	int spk_mask = 0;
-	int channels = 1 + (ai->CC02_CT47 & 0x7);
-	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
-	/*
-	 * CA defaults to 0 for basic stereo audio
-	 */
-	if (channels <= 2)
-		return 0;
-
-	i = hda_node_index(spec->pin_cvt, nid);
-	if (i < 0)
-		return 0;
-	eld = &spec->sink_eld[i];
-
-	/*
-	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-	 * in console or for audio devices. Assume the highest speakers
-	 * configuration, to _not_ prohibit multi-channel audio playback.
-	 */
-	if (!eld->spk_alloc)
-		eld->spk_alloc = 0xffff;
-
-	/*
-	 * expand ELD's speaker allocation mask
-	 *
-	 * ELD tells the speaker mask in a compact(paired) form,
-	 * expand ELD's notions to match the ones used by Audio InfoFrame.
-	 */
-	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-		if (eld->spk_alloc & (1 << i))
-			spk_mask |= eld_speaker_allocation_bits[i];
-	}
-
-	/* search for the first working match in the CA table */
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if (channels == channel_allocations[i].channels &&
-		    (spk_mask & channel_allocations[i].spk_mask) ==
-				channel_allocations[i].spk_mask) {
-			ai->CA = channel_allocations[i].ca_index;
-			break;
-		}
-	}
-
-	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
-	snd_printdd(KERN_INFO
-			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
-			ai->CA, channels, buf);
-
-	return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid,
-				       struct hdmi_audio_infoframe *ai)
-{
-	int i;
-	int ca = ai->CA;
-	int err;
-
-	if (hdmi_channel_mapping[ca][1] == 0) {
-		for (i = 0; i < channel_allocations[ca].channels; i++)
-			hdmi_channel_mapping[ca][i] = i | (i << 4);
-		for (; i < 8; i++)
-			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
-	}
-
-	for (i = 0; i < 8; i++) {
-		err = snd_hda_codec_write(codec, pin_nid, 0,
-					  AC_VERB_SET_HDMI_CHAN_SLOT,
-					  hdmi_channel_mapping[ca][i]);
-		if (err) {
-			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
-			break;
-		}
-	}
-
-	hdmi_debug_channel_mapping(codec, pin_nid);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
-				    struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	u8 val;
-	int i;
-
-	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
-							    != AC_DIPXMIT_BEST)
-		return false;
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++) {
-		val = snd_hda_codec_read(codec, pin_nid, 0,
-					 AC_VERB_GET_HDMI_DIP_DATA, 0);
-		if (val != bytes[i])
-			return false;
-	}
-
-	return true;
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
-					struct snd_pcm_substream *substream)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	hda_nid_t pin_nid;
-	int i;
-	struct hdmi_audio_infoframe ai = {
-		.type		= 0x84,
-		.ver		= 0x01,
-		.len		= 0x0a,
-		.CC02_CT47	= substream->runtime->channels - 1,
-	};
-
-	hdmi_setup_channel_allocation(codec, nid, &ai);
-
-	for (i = 0; i < spec->num_pins; i++) {
-		if (spec->pin_cvt[i] != nid)
-			continue;
-		if (!spec->sink_eld[i].monitor_present)
-			continue;
-
-		pin_nid = spec->pin[i];
-		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
-			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
-			hdmi_stop_infoframe_trans(codec, pin_nid);
-			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
-			hdmi_start_infoframe_trans(codec, pin_nid);
-		}
-	}
-}
-
-/*
- * Unsolicited events
- */
-
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int pind = !!(res & AC_UNSOL_RES_PD);
-	int eldv = !!(res & AC_UNSOL_RES_ELDV);
-	int index;
-
-	printk(KERN_INFO
-		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-		tag, pind, eldv);
-
-	index = hda_node_index(spec->pin, tag);
-	if (index < 0)
-		return;
-
-	spec->sink_eld[index].monitor_present = pind;
-	spec->sink_eld[index].eld_valid = eldv;
-
-	if (eldv) {
-		spec->sink_eld[index].monitor_present = 1;
-		hdmi_get_show_eld(codec, spec->pin[index],
-				 &spec->sink_eld[index]);
-		/* TODO: do real things about ELD */
-	}
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
-	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
-	printk(KERN_INFO
-		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
-		tag,
-		subtag,
-		cp_state,
-		cp_ready);
-
-	/* TODO */
-	if (cp_state)
-		;
-	if (cp_ready)
-		;
-}
-
-static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
-	if (hda_node_index(spec->pin, tag) < 0) {
-		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
-		return;
-	}
-
-	if (subtag == 0)
-		hdmi_intrinsic_event(codec, res);
-	else
-		hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-			      u32 stream_tag, int format)
-{
-	int tag;
-	int fmt;
-
-	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
-	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
-	snd_printdd("hdmi_setup_stream: "
-		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
-		    nid,
-		    tag == stream_tag ? "" : "new-",
-		    stream_tag,
-		    fmt == format ? "" : "new-",
-		    format);
-
-	if (tag != stream_tag)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CHANNEL_STREAMID,
-				    stream_tag << 4);
-	if (fmt != format)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_STREAM_FORMAT, format);
-}
-
 /*
  * Controls
  */
 static int nvhdmi_build_controls(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int err;
 	int i;
 
@@ -902,7 +121,7 @@ static int nvhdmi_build_controls(struct 
 
 static int nvhdmi_init(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
 	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
@@ -920,7 +139,7 @@ static int nvhdmi_init(struct hda_codec 
 
 static void nvhdmi_free(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
@@ -939,7 +158,7 @@ static int nvhdmi_dig_playback_pcm_open(
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 }
 
@@ -947,7 +166,7 @@ static int nvhdmi_dig_playback_pcm_close
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
@@ -968,7 +187,7 @@ static int nvhdmi_dig_playback_pcm_close
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
@@ -1121,7 +340,7 @@ static int nvhdmi_dig_playback_pcm_prepa
 					unsigned int format,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
 					format, substream);
 }
@@ -1170,7 +389,7 @@ static struct hda_pcm_stream nvhdmi_pcm_
 
 static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
 	int i;
 
@@ -1196,7 +415,7 @@ static int nvhdmi_build_pcms_8ch_89(stru
 
 static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
@@ -1212,7 +431,7 @@ static int nvhdmi_build_pcms_8ch_7x(stru
 
 static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
@@ -1231,7 +450,7 @@ static struct hda_codec_ops nvhdmi_patch
 	.build_pcms = nvhdmi_build_pcms_8ch_89,
 	.init = nvhdmi_init,
 	.free = nvhdmi_free,
-	.unsol_event = nvhdmi_unsol_event,
+	.unsol_event = hdmi_unsol_event,
 };
 
 static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
@@ -1250,7 +469,7 @@ static struct hda_codec_ops nvhdmi_patch
 
 static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec;
+	struct hdmi_spec *spec;
 	int i;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -1260,7 +479,7 @@ static int patch_nvhdmi_8ch_89(struct hd
 	codec->spec = spec;
 	spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
 
-	if (nvhdmi_parse_codec(codec) < 0) {
+	if (hdmi_parse_codec(codec) < 0) {
 		codec->spec = NULL;
 		kfree(spec);
 		return -EINVAL;
@@ -1277,7 +496,7 @@ static int patch_nvhdmi_8ch_89(struct hd
 
 static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec;
+	struct hdmi_spec *spec;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -1297,7 +516,7 @@ static int patch_nvhdmi_8ch_7x(struct hd
 
 static int patch_nvhdmi_2ch(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec;
+	struct hdmi_spec *spec;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-03 21:49                 ` Takashi Iwai
  (?)
@ 2010-03-04  2:21                 ` Wei Ni
  2010-03-04  9:46                     ` Takashi Iwai
  -1 siblings, 1 reply; 80+ messages in thread
From: Wei Ni @ 2010-03-04  2:21 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

Hi, Takashi
1. Yes, it can works for all Nvidia controller.
2. The hda_eld.o doesn't export any symbols.
I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
from snd-had-codec-intelhdmi-objs, but it will build error. It need
to modify hda_eld.c to export symbols, it will add many changes.

Thanks
Wei.
nvpublic

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Thursday, March 04, 2010 5:49 AM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Wed, 3 Mar 2010 15:21:12 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I generate the new patch file, please check it.

Thanks.  Review comments below:

> @@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus)
>  
>  /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
>  static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
> +	[AZX_DRIVER_NVIDIA] = 8,

Are you sure that this works for all Nvidia controller chips including
the old nForce chipset?

 
> diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
> index 315a1c4..199f440 100644
> --- a/sound/pci/hda/Makefile
> +++ b/sound/pci/hda/Makefile
> @@ -17,7 +17,7 @@ snd-hda-codec-cirrus-objs :=	patch_cirrus.o
>  snd-hda-codec-ca0110-objs :=	patch_ca0110.o
>  snd-hda-codec-conexant-objs :=	patch_conexant.o
>  snd-hda-codec-via-objs :=	patch_via.o
> -snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o
> +snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o hda_eld.o
>  snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o

This is buggy.  You cannot create multiple modules containing the
same *.o file that exports symbols.

Instead, put hda_eld.o to snd-hda-codec-* (currently commented out),
and remove hda_eld.o from snd-hda-codec-intelhdmi-objs.


Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel]  [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04  2:18     ` [alsa-devel] " Wu Fengguang
@ 2010-03-04  5:44       ` Wu Fengguang
  2010-03-04  5:52         ` Wei Ni
  0 siblings, 1 reply; 80+ messages in thread
From: Wu Fengguang @ 2010-03-04  5:44 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Wei Ni, 'akpm', 'alsa-devel',
	'linux-kernel', 'Pavel Hofman'

On Thu, Mar 04, 2010 at 10:18:39AM +0800, Wu Fengguang wrote:
> On Wed, Mar 03, 2010 at 02:46:25PM +0800, Takashi Iwai wrote:
> > At Tue, 2 Mar 2010 13:43:07 +0800,
> > Wu Fengguang wrote:
> > > 
> > > On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> > > > Hi, Takashi
> > > > I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> > > > The new HAD controller and codec support standard HDMI operation.
> > > > 
> > > > I attached the patch file, please check it.
> > > 
> > > Wei Ni,
> > > 
> > > Can we avoid the big copy&paste and do more code reuse?
> > > This benefits all of us in long term.
> > 
> > The plan is to merge all current patch_*hdmi.c into one.
> > But this can be done later once after we get the working driver
> > for the new Nvidia codecs.
> > 
> > The new Nvidia HDMI codec is a bit tricky (which has 4 separate
> > codec slots), so I'd like to get it working first.
> 
> Here is the patch to merge common code in a simple way.
> This is compile tested only, need double check.
> 
> What puzzled me is that Wei Ni reused the same dynamic parsing code,
> even though the Intel/Nvidia codecs have vastly different pin/cvt
> layouts..

WeiNi, some more questions.

- why change hdmi_channel_mapping[0x32][8] from
        [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
  to
        [0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },

- why remove "u8 reserved[5]; /* PB6 - PB10 */" from struct
  hdmi_audio_infoframe?

- why change
        static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
        {                                               
                u8 *bytes = (u8 *)ai;
                u8 sum = 0;
                int i;
               
                ai->checksum = 0;             
                                              
                for (i = 0; i < sizeof(*ai); i++)
                        sum += bytes[i];
                
                ai->checksum = - sum;
        }       
  to
        static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
        {       
                ai->checksum = 0;
        }       


Those are very dirty changes. Either the original code is correct, or
they are wrong and should be changed as well. If you submit code like
this now, we'll have to resolve conflicts and do pointless retests at
the perceived future merge time.

Would you stop hacking things around like that?

I'd recommend to base your future work on top of the following patch.
It's based on your previous patches.

Note that I reverted the above 3 changes. If they are good changes,
you can still submit standalone patches, and let's discuss and test
them case by case. 

Thanks,
Fengguang
---
hdmi - create patch_hdmi.c for common hdmi code

For now the patch_hdmi.c file is simply included by patch_intelhdmi.c
and patch_nvhdmi.c, and does not represent a real codec.

CC: Wei Ni <wni@nvidia.com>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
---
 sound/pci/hda/patch_hdmi.c      |  828 ++++++++++++++++++++++++++++++
 sound/pci/hda/patch_intelhdmi.c |  822 -----------------------------
 sound/pci/hda/patch_nvhdmi.c    |  817 -----------------------------
 3 files changed, 856 insertions(+), 1611 deletions(-)

--- sound-2.6.orig/sound/pci/hda/patch_intelhdmi.c	2010-03-04 13:14:54.000000000 +0800
+++ sound-2.6/sound/pci/hda/patch_intelhdmi.c	2010-03-04 13:14:56.000000000 +0800
@@ -33,822 +33,20 @@
 #include "hda_codec.h"
 #include "hda_local.h"
 
-/*
- * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
- * could support two independent pipes, each of them can be connected to one or
- * more ports (DVI, HDMI or DisplayPort).
- *
- * The HDA correspondence of pipes/ports are converter/pin nodes.
- */
+#include "patch_hdmi.c"
+
 #define INTEL_HDMI_CVTS	2
 #define INTEL_HDMI_PINS	3
 
-static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = {
+static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
 	"INTEL HDMI 0",
 	"INTEL HDMI 1",
 };
 
-struct intel_hdmi_spec {
-	int num_cvts;
-	int num_pins;
-	hda_nid_t cvt[INTEL_HDMI_CVTS+1];  /* audio sources */
-	hda_nid_t pin[INTEL_HDMI_PINS+1];  /* audio sinks */
-
-	/*
-	 * source connection for each pin
-	 */
-	hda_nid_t pin_cvt[INTEL_HDMI_PINS+1];
-
-	/*
-	 * HDMI sink attached to each pin
-	 */
-	struct hdmi_eld sink_eld[INTEL_HDMI_PINS];
-
-	/*
-	 * export one pcm per pipe
-	 */
-	struct hda_pcm	pcm_rec[INTEL_HDMI_CVTS];
-};
-
-struct hdmi_audio_infoframe {
-	u8 type; /* 0x84 */
-	u8 ver;  /* 0x01 */
-	u8 len;  /* 0x0a */
-
-	u8 checksum;	/* PB0 */
-	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
-	u8 SS01_SF24;
-	u8 CXT04;
-	u8 CA;
-	u8 LFEPBL01_LSV36_DM_INH7;
-	u8 reserved[5];	/* PB6 - PB10 */
-};
-
-/*
- * CEA speaker placement:
- *
- *        FLH       FCH        FRH
- *  FLW    FL  FLC   FC   FRC   FR   FRW
- *
- *                                  LFE
- *                     TC
- *
- *          RL  RLC   RC   RRC   RR
- *
- * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
- * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
- */
-enum cea_speaker_placement {
-	FL  = (1 <<  0),	/* Front Left           */
-	FC  = (1 <<  1),	/* Front Center         */
-	FR  = (1 <<  2),	/* Front Right          */
-	FLC = (1 <<  3),	/* Front Left Center    */
-	FRC = (1 <<  4),	/* Front Right Center   */
-	RL  = (1 <<  5),	/* Rear Left            */
-	RC  = (1 <<  6),	/* Rear Center          */
-	RR  = (1 <<  7),	/* Rear Right           */
-	RLC = (1 <<  8),	/* Rear Left Center     */
-	RRC = (1 <<  9),	/* Rear Right Center    */
-	LFE = (1 << 10),	/* Low Frequency Effect */
-	FLW = (1 << 11),	/* Front Left Wide      */
-	FRW = (1 << 12),	/* Front Right Wide     */
-	FLH = (1 << 13),	/* Front Left High      */
-	FCH = (1 << 14),	/* Front Center High    */
-	FRH = (1 << 15),	/* Front Right High     */
-	TC  = (1 << 16),	/* Top Center           */
-};
-
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static int eld_speaker_allocation_bits[] = {
-	[0] = FL | FR,
-	[1] = LFE,
-	[2] = FC,
-	[3] = RL | RR,
-	[4] = RC,
-	[5] = FLC | FRC,
-	[6] = RLC | RRC,
-	/* the following are not defined in ELD yet */
-	[7] = FLW | FRW,
-	[8] = FLH | FRH,
-	[9] = TC,
-	[10] = FCH,
-};
-
-struct cea_channel_speaker_allocation {
-	int ca_index;
-	int speakers[8];
-
-	/* derived values, just for convenience */
-	int channels;
-	int spk_mask;
-};
-
-/*
- * ALSA sequence is:
- *
- *       surround40   surround41   surround50   surround51   surround71
- * ch0   front left   =            =            =            =
- * ch1   front right  =            =            =            =
- * ch2   rear left    =            =            =            =
- * ch3   rear right   =            =            =            =
- * ch4                LFE          center       center       center
- * ch5                                          LFE          LFE
- * ch6                                                       side left
- * ch7                                                       side right
- *
- * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
- */
-static int hdmi_channel_mapping[0x32][8] = {
-	/* stereo */
-	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* 2.1 */
-	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* Dolby Surround */
-	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* surround40 */
-	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
-	/* 4ch */
-	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
-	/* surround41 */
-	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
-	/* surround50 */
-	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
-	/* surround51 */
-	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
-	/* 7.1 */
-	[0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/* 			  channel:   7     6    5    4    3     2    1    0  */
-{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
-				 /* 2.1 */
-{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
-				 /* Dolby Surround */
-{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
-				 /* surround40 */
-{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
-				 /* surround41 */
-{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
-				 /* surround50 */
-{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-				 /* surround51 */
-{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* 6.1 */
-{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* surround71 */
-{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-
-{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
-{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
-};
-
-/*
- * HDA/HDMI auto parsing
- */
-
-static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
-{
-	int i;
-
-	for (i = 0; nids[i]; i++)
-		if (nids[i] == nid)
-			return i;
-
-	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
-	return -EINVAL;
-}
-
-static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
-	int conn_len, curr;
-	int index;
-
-	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
-		snd_printk(KERN_WARNING
-			   "HDMI: pin %d wcaps %#x "
-			   "does not support connection list\n",
-			   pin_nid, get_wcaps(codec, pin_nid));
-		return -EINVAL;
-	}
-
-	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
-					   HDA_MAX_CONNECTIONS);
-	if (conn_len > 1)
-		curr = snd_hda_codec_read(codec, pin_nid, 0,
-					  AC_VERB_GET_CONNECT_SEL, 0);
-	else
-		curr = 0;
-
-	index = hda_node_index(spec->pin, pin_nid);
-	if (index < 0)
-		return -EINVAL;
-
-	spec->pin_cvt[index] = conn_list[curr];
-
-	return 0;
-}
-
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
-			      struct hdmi_eld *eld)
-{
-	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
-		snd_hdmi_show_eld(eld);
-}
-
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
-			       struct hdmi_eld *eld)
-{
-	int present = snd_hda_pin_sense(codec, pin_nid);
-
-	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
-	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
-
-	if (present & AC_PINSENSE_ELDV)
-		hdmi_get_show_eld(codec, pin_nid, eld);
-}
-
-static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-
-	if (spec->num_pins >= INTEL_HDMI_PINS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for pin %d \n", pin_nid);
-		return -EINVAL;
-	}
-
-	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
-
-	spec->pin[spec->num_pins] = pin_nid;
-	spec->num_pins++;
-
-	/*
-	 * It is assumed that converter nodes come first in the node list and
-	 * hence have been registered and usable now.
-	 */
-	return intel_hdmi_read_pin_conn(codec, pin_nid);
-}
-
-static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-
-	if (spec->num_cvts >= INTEL_HDMI_CVTS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for converter %d \n", nid);
-		return -EINVAL;
-	}
-
-	spec->cvt[spec->num_cvts] = nid;
-	spec->num_cvts++;
-
-	return 0;
-}
-
-static int intel_hdmi_parse_codec(struct hda_codec *codec)
-{
-	hda_nid_t nid;
-	int i, nodes;
-
-	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
-	if (!nid || nodes < 0) {
-		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < nodes; i++, nid++) {
-		unsigned int caps;
-		unsigned int type;
-
-		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
-		type = get_wcaps_type(caps);
-
-		if (!(caps & AC_WCAP_DIGITAL))
-			continue;
-
-		switch (type) {
-		case AC_WID_AUD_OUT:
-			if (intel_hdmi_add_cvt(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		case AC_WID_PIN:
-			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
-				continue;
-			if (intel_hdmi_add_pin(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		}
-	}
-
-	/*
-	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
-	 * can be lost and presence sense verb will become inaccurate if the
-	 * HDA link is powered off at hot plug or hw initialization time.
-	 */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
-	      AC_PWRST_EPSS))
-		codec->bus->power_keep_link_on = 1;
-#endif
-
-	return 0;
-}
-
 /*
  * HDMI routines
  */
 
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int *packet_index, int *byte_index)
-{
-	int val;
-
-	val = snd_hda_codec_read(codec, pin_nid, 0,
-				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
-	*packet_index = val >> 5;
-	*byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int packet_index, int byte_index)
-{
-	int val;
-
-	val = (packet_index << 5) | (byte_index & 0x1f);
-
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
-				unsigned char val)
-{
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	/* Unmute */
-	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
-		snd_hda_codec_write(codec, pin_nid, 0,
-				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-	/* Enable pin out */
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
-				      hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_DISABLE);
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
-{
-	return 1 + snd_hda_codec_read(codec, nid, 0,
-					AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec,
-				   hda_nid_t nid, int chs)
-{
-	if (chs != hdmi_get_channel_count(codec, nid))
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int slot;
-
-	for (i = 0; i < 8; i++) {
-		slot = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_CHAN_SLOT, i);
-		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
-						slot >> 4, slot & 0xf);
-	}
-#endif
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int size;
-
-	size = snd_hdmi_get_eld_size(codec, pin_nid);
-	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
-	}
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
-	int i, j;
-	int size;
-	int pi, bi;
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		if (size == 0)
-			continue;
-
-		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
-		for (j = 1; j < 1000; j++) {
-			hdmi_write_dip_byte(codec, pin_nid, 0x0);
-			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
-			if (pi != i)
-				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
-						bi, pi, i);
-			if (bi == 0) /* byte index wrapped around */
-				break;
-		}
-		snd_printd(KERN_INFO
-			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
-			i, size, j);
-	}
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	u8 sum = 0;
-	int i;
-
-	ai->checksum = 0;
-
-	for (i = 0; i < sizeof(*ai); i++)
-		sum += bytes[i];
-
-	ai->checksum = - sum;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
-				      hda_nid_t pin_nid,
-				      struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	int i;
-
-	hdmi_debug_dip_size(codec, pin_nid);
-	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
-	hdmi_checksum_audio_infoframe(ai);
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++)
-		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
-	int i, j;
-	struct cea_channel_speaker_allocation *p;
-
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		p = channel_allocations + i;
-		p->channels = 0;
-		p->spk_mask = 0;
-		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-			if (p->speakers[j]) {
-				p->channels++;
-				p->spk_mask |= p->speakers[j];
-			}
-	}
-}
-
-/*
- * The transformation takes two steps:
- *
- * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- * 	      spk_mask => (channel_allocations[])         => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
-					 struct hdmi_audio_infoframe *ai)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	struct hdmi_eld *eld;
-	int i;
-	int spk_mask = 0;
-	int channels = 1 + (ai->CC02_CT47 & 0x7);
-	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
-	/*
-	 * CA defaults to 0 for basic stereo audio
-	 */
-	if (channels <= 2)
-		return 0;
-
-	i = hda_node_index(spec->pin_cvt, nid);
-	if (i < 0)
-		return 0;
-	eld = &spec->sink_eld[i];
-
-	/*
-	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-	 * in console or for audio devices. Assume the highest speakers
-	 * configuration, to _not_ prohibit multi-channel audio playback.
-	 */
-	if (!eld->spk_alloc)
-		eld->spk_alloc = 0xffff;
-
-	/*
-	 * expand ELD's speaker allocation mask
-	 *
-	 * ELD tells the speaker mask in a compact(paired) form,
-	 * expand ELD's notions to match the ones used by Audio InfoFrame.
-	 */
-	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-		if (eld->spk_alloc & (1 << i))
-			spk_mask |= eld_speaker_allocation_bits[i];
-	}
-
-	/* search for the first working match in the CA table */
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if (channels == channel_allocations[i].channels &&
-		    (spk_mask & channel_allocations[i].spk_mask) ==
-				channel_allocations[i].spk_mask) {
-			ai->CA = channel_allocations[i].ca_index;
-			break;
-		}
-	}
-
-	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
-	snd_printdd(KERN_INFO
-			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
-			ai->CA, channels, buf);
-
-	return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid,
-				       struct hdmi_audio_infoframe *ai)
-{
-	int i;
-	int ca = ai->CA;
-	int err;
-
-	if (hdmi_channel_mapping[ca][1] == 0) {
-		for (i = 0; i < channel_allocations[ca].channels; i++)
-			hdmi_channel_mapping[ca][i] = i | (i << 4);
-		for (; i < 8; i++)
-			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
-	}
-
-	for (i = 0; i < 8; i++) {
-		err = snd_hda_codec_write(codec, pin_nid, 0,
-					  AC_VERB_SET_HDMI_CHAN_SLOT,
-					  hdmi_channel_mapping[ca][i]);
-		if (err) {
-			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
-			break;
-		}
-	}
-
-	hdmi_debug_channel_mapping(codec, pin_nid);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
-				    struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	u8 val;
-	int i;
-
-	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
-							    != AC_DIPXMIT_BEST)
-		return false;
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++) {
-		val = snd_hda_codec_read(codec, pin_nid, 0,
-					 AC_VERB_GET_HDMI_DIP_DATA, 0);
-		if (val != bytes[i])
-			return false;
-	}
-
-	return true;
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
-					struct snd_pcm_substream *substream)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	hda_nid_t pin_nid;
-	int i;
-	struct hdmi_audio_infoframe ai = {
-		.type		= 0x84,
-		.ver		= 0x01,
-		.len		= 0x0a,
-		.CC02_CT47	= substream->runtime->channels - 1,
-	};
-
-	hdmi_setup_channel_allocation(codec, nid, &ai);
-
-	for (i = 0; i < spec->num_pins; i++) {
-		if (spec->pin_cvt[i] != nid)
-			continue;
-		if (!spec->sink_eld[i].monitor_present)
-			continue;
-
-		pin_nid = spec->pin[i];
-		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
-			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
-			hdmi_stop_infoframe_trans(codec, pin_nid);
-			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
-			hdmi_start_infoframe_trans(codec, pin_nid);
-		}
-	}
-}
-
-
-/*
- * Unsolicited events
- */
-
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int pind = !!(res & AC_UNSOL_RES_PD);
-	int eldv = !!(res & AC_UNSOL_RES_ELDV);
-	int index;
-
-	printk(KERN_INFO
-		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-		tag, pind, eldv);
-
-	index = hda_node_index(spec->pin, tag);
-	if (index < 0)
-		return;
-
-	spec->sink_eld[index].monitor_present = pind;
-	spec->sink_eld[index].eld_valid = eldv;
-
-	if (pind && eldv) {
-		hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]);
-		/* TODO: do real things about ELD */
-	}
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
-	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
-	printk(KERN_INFO
-		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
-		tag,
-		subtag,
-		cp_state,
-		cp_ready);
-
-	/* TODO */
-	if (cp_state)
-		;
-	if (cp_ready)
-		;
-}
-
-
-static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
-	if (hda_node_index(spec->pin, tag) < 0) {
-		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
-		return;
-	}
-
-	if (subtag == 0)
-		hdmi_intrinsic_event(codec, res);
-	else
-		hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-			      u32 stream_tag, int format)
-{
-	int tag;
-	int fmt;
-
-	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
-	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
-	snd_printdd("hdmi_setup_stream: "
-		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
-		    nid,
-		    tag == stream_tag ? "" : "new-",
-		    stream_tag,
-		    fmt == format ? "" : "new-",
-		    format);
-
-	if (tag != stream_tag)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4);
-	if (fmt != format)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_STREAM_FORMAT, format);
-}
-
 static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 					   struct hda_codec *codec,
 					   unsigned int stream_tag,
@@ -882,7 +80,7 @@ static struct hda_pcm_stream intel_hdmi_
 
 static int intel_hdmi_build_pcms(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
 	int i;
 
@@ -908,7 +106,7 @@ static int intel_hdmi_build_pcms(struct 
 
 static int intel_hdmi_build_controls(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int err;
 	int i;
 
@@ -923,7 +121,7 @@ static int intel_hdmi_build_controls(str
 
 static int intel_hdmi_init(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	for (i = 0; spec->pin[i]; i++) {
@@ -937,7 +135,7 @@ static int intel_hdmi_init(struct hda_co
 
 static void intel_hdmi_free(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	for (i = 0; i < spec->num_pins; i++)
@@ -951,12 +149,12 @@ static struct hda_codec_ops intel_hdmi_p
 	.free			= intel_hdmi_free,
 	.build_pcms		= intel_hdmi_build_pcms,
 	.build_controls 	= intel_hdmi_build_controls,
-	.unsol_event		= intel_hdmi_unsol_event,
+	.unsol_event		= hdmi_unsol_event,
 };
 
 static int patch_intel_hdmi(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec;
+	struct hdmi_spec *spec;
 	int i;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -964,7 +162,7 @@ static int patch_intel_hdmi(struct hda_c
 		return -ENOMEM;
 
 	codec->spec = spec;
-	if (intel_hdmi_parse_codec(codec) < 0) {
+	if (hdmi_parse_codec(codec) < 0) {
 		codec->spec = NULL;
 		kfree(spec);
 		return -EINVAL;
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ sound-2.6/sound/pci/hda/patch_hdmi.c	2010-03-04 13:30:14.000000000 +0800
@@ -0,0 +1,828 @@
+/*
+ * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
+ * could support two independent pipes, each of them can be connected to one or
+ * more ports (DVI, HDMI or DisplayPort).
+ *
+ * The HDA correspondence of pipes/ports are converter/pin nodes.
+ */
+#define MAX_HDMI_CVTS	2
+#define MAX_HDMI_PINS	3
+
+
+struct hdmi_spec {
+	int num_cvts;
+	int num_pins;
+	hda_nid_t cvt[MAX_HDMI_CVTS+1];  /* audio sources */
+	hda_nid_t pin[MAX_HDMI_PINS+1];  /* audio sinks */
+
+	/*
+	 * source connection for each pin
+	 */
+	hda_nid_t pin_cvt[MAX_HDMI_PINS+1];
+
+	/*
+	 * HDMI sink attached to each pin
+	 */
+	struct hdmi_eld sink_eld[MAX_HDMI_PINS];
+
+	/*
+	 * export one pcm per pipe
+	 */
+	struct hda_pcm	pcm_rec[MAX_HDMI_CVTS];
+
+	/*
+	 * nvhdmi specific
+	 */
+	struct hda_multi_out multiout;
+	unsigned int codec_type;
+};
+
+
+struct hdmi_audio_infoframe {
+	u8 type; /* 0x84 */
+	u8 ver;  /* 0x01 */
+	u8 len;  /* 0x0a */
+
+	u8 checksum;	/* PB0 */
+	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
+	u8 SS01_SF24;
+	u8 CXT04;
+	u8 CA;
+	u8 LFEPBL01_LSV36_DM_INH7;
+	u8 reserved[5];	/* PB6 - PB10 */
+};
+
+/*
+ * CEA speaker placement:
+ *
+ *        FLH       FCH        FRH
+ *  FLW    FL  FLC   FC   FRC   FR   FRW
+ *
+ *                                  LFE
+ *                     TC
+ *
+ *          RL  RLC   RC   RRC   RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+	FL  = (1 <<  0),	/* Front Left           */
+	FC  = (1 <<  1),	/* Front Center         */
+	FR  = (1 <<  2),	/* Front Right          */
+	FLC = (1 <<  3),	/* Front Left Center    */
+	FRC = (1 <<  4),	/* Front Right Center   */
+	RL  = (1 <<  5),	/* Rear Left            */
+	RC  = (1 <<  6),	/* Rear Center          */
+	RR  = (1 <<  7),	/* Rear Right           */
+	RLC = (1 <<  8),	/* Rear Left Center     */
+	RRC = (1 <<  9),	/* Rear Right Center    */
+	LFE = (1 << 10),	/* Low Frequency Effect */
+	FLW = (1 << 11),	/* Front Left Wide      */
+	FRW = (1 << 12),	/* Front Right Wide     */
+	FLH = (1 << 13),	/* Front Left High      */
+	FCH = (1 << 14),	/* Front Center High    */
+	FRH = (1 << 15),	/* Front Right High     */
+	TC  = (1 << 16),	/* Top Center           */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+	[0] = FL | FR,
+	[1] = LFE,
+	[2] = FC,
+	[3] = RL | RR,
+	[4] = RC,
+	[5] = FLC | FRC,
+	[6] = RLC | RRC,
+	/* the following are not defined in ELD yet */
+	[7] = FLW | FRW,
+	[8] = FLH | FRH,
+	[9] = TC,
+	[10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+	int ca_index;
+	int speakers[8];
+
+	/* derived values, just for convenience */
+	int channels;
+	int spk_mask;
+};
+
+/*
+ * ALSA sequence is:
+ *
+ *       surround40   surround41   surround50   surround51   surround71
+ * ch0   front left   =            =            =            =
+ * ch1   front right  =            =            =            =
+ * ch2   rear left    =            =            =            =
+ * ch3   rear right   =            =            =            =
+ * ch4                LFE          center       center       center
+ * ch5                                          LFE          LFE
+ * ch6                                                       side left
+ * ch7                                                       side right
+ *
+ * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
+ */
+static int hdmi_channel_mapping[0x32][8] = {
+	/* stereo */
+	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* 2.1 */
+	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* Dolby Surround */
+	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* surround40 */
+	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
+	/* 4ch */
+	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
+	/* surround41 */
+	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround50 */
+	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround51 */
+	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
+	/* 7.1 */
+	[0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/* 			  channel:   7     6    5    4    3     2    1    0  */
+{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
+				 /* 2.1 */
+{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
+				 /* Dolby Surround */
+{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
+				 /* surround40 */
+{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
+				 /* surround41 */
+{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
+				 /* surround50 */
+{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+				 /* surround51 */
+{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* 6.1 */
+{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* surround71 */
+{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+
+{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
+{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
+};
+
+
+/*
+ * HDMI routines
+ */
+
+static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+{
+	int i;
+
+	for (i = 0; nids[i]; i++)
+		if (nids[i] == nid)
+			return i;
+
+	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+	return -EINVAL;
+}
+
+static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
+			      struct hdmi_eld *eld)
+{
+	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+		snd_hdmi_show_eld(eld);
+}
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int *packet_index, int *byte_index)
+{
+	int val;
+
+	val = snd_hda_codec_read(codec, pin_nid, 0,
+				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+	*packet_index = val >> 5;
+	*byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int packet_index, int byte_index)
+{
+	int val;
+
+	val = (packet_index << 5) | (byte_index & 0x1f);
+
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
+				unsigned char val)
+{
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	/* Unmute */
+	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
+		snd_hda_codec_write(codec, pin_nid, 0,
+				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	/* Enable pin out */
+	snd_hda_codec_write(codec, pin_nid, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+{
+	return 1 + snd_hda_codec_read(codec, nid, 0,
+					AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec,
+				   hda_nid_t nid, int chs)
+{
+	if (chs != hdmi_get_channel_count(codec, nid))
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+}
+
+
+/*
+ * Channel mapping routines
+ */
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+	int i, j;
+	struct cea_channel_speaker_allocation *p;
+
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		p = channel_allocations + i;
+		p->channels = 0;
+		p->spk_mask = 0;
+		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+			if (p->speakers[j]) {
+				p->channels++;
+				p->spk_mask |= p->speakers[j];
+			}
+	}
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ * 	      spk_mask => (channel_allocations[])         => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+					 struct hdmi_audio_infoframe *ai)
+{
+	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_eld *eld;
+	int i;
+	int spk_mask = 0;
+	int channels = 1 + (ai->CC02_CT47 & 0x7);
+	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+	/*
+	 * CA defaults to 0 for basic stereo audio
+	 */
+	if (channels <= 2)
+		return 0;
+
+	i = hda_node_index(spec->pin_cvt, nid);
+	if (i < 0)
+		return 0;
+	eld = &spec->sink_eld[i];
+
+	/*
+	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+	 * in console or for audio devices. Assume the highest speakers
+	 * configuration, to _not_ prohibit multi-channel audio playback.
+	 */
+	if (!eld->spk_alloc)
+		eld->spk_alloc = 0xffff;
+
+	/*
+	 * expand ELD's speaker allocation mask
+	 *
+	 * ELD tells the speaker mask in a compact(paired) form,
+	 * expand ELD's notions to match the ones used by Audio InfoFrame.
+	 */
+	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+		if (eld->spk_alloc & (1 << i))
+			spk_mask |= eld_speaker_allocation_bits[i];
+	}
+
+	/* search for the first working match in the CA table */
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		if (channels == channel_allocations[i].channels &&
+		    (spk_mask & channel_allocations[i].spk_mask) ==
+				channel_allocations[i].spk_mask) {
+			ai->CA = channel_allocations[i].ca_index;
+			break;
+		}
+	}
+
+	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+	snd_printdd(KERN_INFO
+			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+			ai->CA, channels, buf);
+
+	return ai->CA;
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int slot;
+
+	for (i = 0; i < 8; i++) {
+		slot = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_CHAN_SLOT, i);
+		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+						slot >> 4, slot & 0xf);
+	}
+#endif
+}
+
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid,
+				       struct hdmi_audio_infoframe *ai)
+{
+	int i;
+	int ca = ai->CA;
+	int err;
+
+	if (hdmi_channel_mapping[ca][1] == 0) {
+		for (i = 0; i < channel_allocations[ca].channels; i++)
+			hdmi_channel_mapping[ca][i] = i | (i << 4);
+		for (; i < 8; i++)
+			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+	}
+
+	for (i = 0; i < 8; i++) {
+		err = snd_hda_codec_write(codec, pin_nid, 0,
+					  AC_VERB_SET_HDMI_CHAN_SLOT,
+					  hdmi_channel_mapping[ca][i]);
+		if (err) {
+			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
+			break;
+		}
+	}
+
+	hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+/*
+ * Enable Audio InfoFrame Transmission
+ */
+static void hdmi_start_infoframe_trans(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_BEST);
+}
+
+/*
+ * Disable Audio InfoFrame Transmission
+ */
+static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
+				      hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_DISABLE);
+}
+
+static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int size;
+
+	size = snd_hdmi_get_eld_size(codec, pin_nid);
+	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+	}
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef BE_PARANOID
+	int i, j;
+	int size;
+	int pi, bi;
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		if (size == 0)
+			continue;
+
+		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
+		for (j = 1; j < 1000; j++) {
+			hdmi_write_dip_byte(codec, pin_nid, 0x0);
+			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
+			if (pi != i)
+				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+						bi, pi, i);
+			if (bi == 0) /* byte index wrapped around */
+				break;
+		}
+		snd_printd(KERN_INFO
+			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+			i, size, j);
+	}
+#endif
+}
+
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	u8 sum = 0;
+	int i;
+
+	ai->checksum = 0;
+
+	for (i = 0; i < sizeof(*ai); i++)
+		sum += bytes[i];
+
+	ai->checksum = - sum;
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+				      hda_nid_t pin_nid,
+				      struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	int i;
+
+	hdmi_debug_dip_size(codec, pin_nid);
+	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
+
+	hdmi_checksum_audio_infoframe(ai);
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++)
+		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+}
+
+static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
+				    struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	u8 val;
+	int i;
+
+	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
+							    != AC_DIPXMIT_BEST)
+		return false;
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++) {
+		val = snd_hda_codec_read(codec, pin_nid, 0,
+					 AC_VERB_GET_HDMI_DIP_DATA, 0);
+		if (val != bytes[i])
+			return false;
+	}
+
+	return true;
+}
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+					struct snd_pcm_substream *substream)
+{
+	struct hdmi_spec *spec = codec->spec;
+	hda_nid_t pin_nid;
+	int i;
+	struct hdmi_audio_infoframe ai = {
+		.type		= 0x84,
+		.ver		= 0x01,
+		.len		= 0x0a,
+		.CC02_CT47	= substream->runtime->channels - 1,
+	};
+
+	hdmi_setup_channel_allocation(codec, nid, &ai);
+
+	for (i = 0; i < spec->num_pins; i++) {
+		if (spec->pin_cvt[i] != nid)
+			continue;
+		if (!spec->sink_eld[i].monitor_present)
+			continue;
+
+		pin_nid = spec->pin[i];
+		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+			hdmi_stop_infoframe_trans(codec, pin_nid);
+			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+			hdmi_start_infoframe_trans(codec, pin_nid);
+		}
+	}
+}
+
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int pind = !!(res & AC_UNSOL_RES_PD);
+	int eldv = !!(res & AC_UNSOL_RES_ELDV);
+	int index;
+
+	printk(KERN_INFO
+		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+		tag, pind, eldv);
+
+	index = hda_node_index(spec->pin, tag);
+	if (index < 0)
+		return;
+
+	spec->sink_eld[index].monitor_present = pind;
+	spec->sink_eld[index].eld_valid = eldv;
+
+	if (pind && eldv) {
+		hdmi_get_show_eld(codec, spec->pin[index],
+				  &spec->sink_eld[index]);
+		/* TODO: do real things about ELD */
+	}
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+	printk(KERN_INFO
+		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+		tag,
+		subtag,
+		cp_state,
+		cp_ready);
+
+	/* TODO */
+	if (cp_state)
+		;
+	if (cp_ready)
+		;
+}
+
+
+static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+	if (hda_node_index(spec->pin, tag) < 0) {
+		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+		return;
+	}
+
+	if (subtag == 0)
+		hdmi_intrinsic_event(codec, res);
+	else
+		hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+			      u32 stream_tag, int format)
+{
+	int tag;
+	int fmt;
+
+	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
+	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
+
+	snd_printdd("hdmi_setup_stream: "
+		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
+		    nid,
+		    tag == stream_tag ? "" : "new-",
+		    stream_tag,
+		    fmt == format ? "" : "new-",
+		    format);
+
+	if (tag != stream_tag)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CHANNEL_STREAMID,
+				    stream_tag << 4);
+	if (fmt != format)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_STREAM_FORMAT, format);
+}
+
+/*
+ * HDA/HDMI auto parsing
+ */
+
+static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct hdmi_spec *spec = codec->spec;
+	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+	int conn_len, curr;
+	int index;
+
+	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
+		snd_printk(KERN_WARNING
+			   "HDMI: pin %d wcaps %#x "
+			   "does not support connection list\n",
+			   pin_nid, get_wcaps(codec, pin_nid));
+		return -EINVAL;
+	}
+
+	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
+					   HDA_MAX_CONNECTIONS);
+	if (conn_len > 1)
+		curr = snd_hda_codec_read(codec, pin_nid, 0,
+					  AC_VERB_GET_CONNECT_SEL, 0);
+	else
+		curr = 0;
+
+	index = hda_node_index(spec->pin, pin_nid);
+	if (index < 0)
+		return -EINVAL;
+
+	spec->pin_cvt[index] = conn_list[curr];
+
+	return 0;
+}
+
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+			       struct hdmi_eld *eld)
+{
+	int present = snd_hda_pin_sense(codec, pin_nid);
+
+	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
+	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
+
+	if (present & AC_PINSENSE_ELDV)
+		hdmi_get_show_eld(codec, pin_nid, eld);
+}
+
+static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct hdmi_spec *spec = codec->spec;
+
+	if (spec->num_pins >= MAX_HDMI_PINS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for pin %d \n", pin_nid);
+		return -EINVAL;
+	}
+
+	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+
+	spec->pin[spec->num_pins] = pin_nid;
+	spec->num_pins++;
+
+	/*
+	 * It is assumed that converter nodes come first in the node list and
+	 * hence have been registered and usable now.
+	 */
+	return hdmi_read_pin_conn(codec, pin_nid);
+}
+
+static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct hdmi_spec *spec = codec->spec;
+
+	if (spec->num_cvts >= MAX_HDMI_CVTS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for converter %d \n", nid);
+		return -EINVAL;
+	}
+
+	spec->cvt[spec->num_cvts] = nid;
+	spec->num_cvts++;
+
+	return 0;
+}
+
+static int hdmi_parse_codec(struct hda_codec *codec)
+{
+	hda_nid_t nid;
+	int i, nodes;
+
+	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+	if (!nid || nodes < 0) {
+		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nodes; i++, nid++) {
+		unsigned int caps;
+		unsigned int type;
+
+		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+		type = get_wcaps_type(caps);
+
+		if (!(caps & AC_WCAP_DIGITAL))
+			continue;
+
+		switch (type) {
+		case AC_WID_AUD_OUT:
+			if (hdmi_add_cvt(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		case AC_WID_PIN:
+			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+				continue;
+			if (hdmi_add_pin(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		}
+	}
+
+	/*
+	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
+	 * can be lost and presence sense verb will become inaccurate if the
+	 * HDA link is powered off at hot plug or hw initialization time.
+	 */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+	      AC_PWRST_EPSS))
+		codec->bus->power_keep_link_on = 1;
+#endif
+
+	return 0;
+}
+
--- sound-2.6.orig/sound/pci/hda/patch_nvhdmi.c	2010-03-04 13:14:54.000000000 +0800
+++ sound-2.6/sound/pci/hda/patch_nvhdmi.c	2010-03-04 13:14:56.000000000 +0800
@@ -29,6 +29,8 @@
 #include "hda_codec.h"
 #include "hda_local.h"
 
+#include "patch_hdmi.c"
+
 /* define below to restrict the supported rates and formats */
 /* #define LIMITED_RATE_FMT_SUPPORT */
 
@@ -86,799 +88,16 @@ static struct hda_verb nvhdmi_basic_init
 #define NVIDIA_89_HDMI_CVTS	1
 #define NVIDIA_89_HDMI_PINS	1
 
-static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = {
+static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
 	"NVIDIA HDMI",
 };
 
-struct nvhdmi_spec {
-	int num_cvts;
-	int num_pins;
-	hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1];  /* audio sources */
-	hda_nid_t pin[NVIDIA_89_HDMI_PINS+1];  /* audio sinks */
-	hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1];
-	struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS];
-	struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS];
-	struct hda_multi_out multiout;
-	unsigned int codec_type;
-};
-
-struct hdmi_audio_infoframe {
-	u8 type; /* 0x84 */
-	u8 ver;  /* 0x01 */
-	u8 len;  /* 0x0a */
-
-	u8 checksum;	/* PB0 */
-	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
-	u8 SS01_SF24;
-	u8 CXT04;
-	u8 CA;
-	u8 LFEPBL01_LSV36_DM_INH7;
-};
-
-/*
- * CEA speaker placement:
- *
- *        FLH       FCH        FRH
- *  FLW    FL  FLC   FC   FRC   FR   FRW
- *
- *                                  LFE
- *                     TC
- *
- *          RL  RLC   RC   RRC   RR
- *
- * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
- * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
- */
-enum cea_speaker_placement {
-	FL  = (1 <<  0),	/* Front Left           */
-	FC  = (1 <<  1),	/* Front Center         */
-	FR  = (1 <<  2),	/* Front Right          */
-	FLC = (1 <<  3),	/* Front Left Center    */
-	FRC = (1 <<  4),	/* Front Right Center   */
-	RL  = (1 <<  5),	/* Rear Left            */
-	RC  = (1 <<  6),	/* Rear Center          */
-	RR  = (1 <<  7),	/* Rear Right           */
-	RLC = (1 <<  8),	/* Rear Left Center     */
-	RRC = (1 <<  9),	/* Rear Right Center    */
-	LFE = (1 << 10),	/* Low Frequency Effect */
-	FLW = (1 << 11),	/* Front Left Wide      */
-	FRW = (1 << 12),	/* Front Right Wide     */
-	FLH = (1 << 13),	/* Front Left High      */
-	FCH = (1 << 14),	/* Front Center High    */
-	FRH = (1 << 15),	/* Front Right High     */
-	TC  = (1 << 16),	/* Top Center           */
-};
-
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static int eld_speaker_allocation_bits[] = {
-	[0] = FL | FR,
-	[1] = LFE,
-	[2] = FC,
-	[3] = RL | RR,
-	[4] = RC,
-	[5] = FLC | FRC,
-	[6] = RLC | RRC,
-	/* the following are not defined in ELD yet */
-	[7] = FLW | FRW,
-	[8] = FLH | FRH,
-	[9] = TC,
-	[10] = FCH,
-};
-
-struct cea_channel_speaker_allocation {
-	int ca_index;
-	int speakers[8];
-
-	/* derived values, just for convenience */
-	int channels;
-	int spk_mask;
-};
-
-/*
- * ALSA sequence is:
- *
- *       surround40   surround41   surround50   surround51   surround71
- * ch0   front left   =            =            =            =
- * ch1   front right  =            =            =            =
- * ch2   rear left    =            =            =            =
- * ch3   rear right   =            =            =            =
- * ch4                LFE          center       center       center
- * ch5                                          LFE          LFE
- * ch6                                                       side left
- * ch7                                                       side right
- *
- * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
- */
-static int hdmi_channel_mapping[0x32][8] = {
-	/* stereo */
-	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* 2.1 */
-	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* Dolby Surround */
-	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* surround40 */
-	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
-	/* 4ch */
-	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
-	/* surround41 */
-	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
-	/* surround50 */
-	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
-	/* surround51 */
-	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
-	/* 7.1 */
-	[0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/* 			  channel:   7     6    5    4    3     2    1    0  */
-{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
-				 /* 2.1 */
-{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
-				 /* Dolby Surround */
-{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
-				 /* surround40 */
-{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
-				 /* surround41 */
-{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
-				 /* surround50 */
-{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-				 /* surround51 */
-{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* 6.1 */
-{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* surround71 */
-{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-
-{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
-{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
-};
-
-/*
- * HDA/HDMI auto parsing
- */
-
-static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
-{
-	int i;
-
-	for (i = 0; nids[i]; i++)
-		if (nids[i] == nid)
-			return i;
-
-	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
-	return -EINVAL;
-}
-
-static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
-	int conn_len, curr;
-	int index;
-
-	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
-		snd_printk(KERN_WARNING
-			   "HDMI: pin %d wcaps %#x "
-			   "does not support connection list\n",
-			   pin_nid, get_wcaps(codec, pin_nid));
-		return -EINVAL;
-	}
-
-	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
-					   HDA_MAX_CONNECTIONS);
-	if (conn_len > 1)
-		curr = snd_hda_codec_read(codec, pin_nid, 0,
-					  AC_VERB_GET_CONNECT_SEL, 0);
-	else
-		curr = 0;
-
-	index = hda_node_index(spec->pin, pin_nid);
-	if (index < 0)
-		return -EINVAL;
-
-	spec->pin_cvt[index] = conn_list[curr];
-
-	return 0;
-}
-
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
-			      struct hdmi_eld *eld)
-{
-	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
-		snd_hdmi_show_eld(eld);
-}
-
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
-			       struct hdmi_eld *eld)
-{
-	int present = snd_hda_pin_sense(codec, pin_nid);
-
-	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
-	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
-
-	if (present & AC_PINSENSE_ELDV)
-		hdmi_get_show_eld(codec, pin_nid, eld);
-}
-
-static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-
-	if (spec->num_pins >= NVIDIA_89_HDMI_PINS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for pin %d \n", pin_nid);
-		return -EINVAL;
-	}
-
-	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
-
-	spec->pin[spec->num_pins] = pin_nid;
-	spec->num_pins++;
-
-	/*
-	 * It is assumed that converter nodes come first in the node list and
-	 * hence have been registered and usable now.
-	 */
-	return nvhdmi_read_pin_conn(codec, pin_nid);
-}
-
-static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-
-	if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for converter %d \n", nid);
-		return -EINVAL;
-	}
-
-	spec->cvt[spec->num_cvts] = nid;
-	spec->num_cvts++;
-
-	return 0;
-}
-
-
-static int nvhdmi_parse_codec(struct hda_codec *codec)
-{
-	hda_nid_t nid;
-	int i, nodes;
-
-	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
-	if (!nid || nodes < 0) {
-		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < nodes; i++, nid++) {
-		unsigned int caps;
-		unsigned int type;
-
-		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
-		type = get_wcaps_type(caps);
-
-		if (!(caps & AC_WCAP_DIGITAL))
-			continue;
-
-		switch (type) {
-		case AC_WID_AUD_OUT:
-			if (nvhdmi_add_cvt(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		case AC_WID_PIN:
-			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
-				continue;
-			if (nvhdmi_add_pin(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		}
-	}
-
-	/*
-	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
-	 * can be lost and presence sense verb will become inaccurate if the
-	 * HDA link is powered off at hot plug or hw initialization time.
-	 */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
-	      AC_PWRST_EPSS))
-		codec->bus->power_keep_link_on = 1;
-#endif
-
-	return 0;
-}
-
-/*
- * HDMI routines
- */
-
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int *packet_index, int *byte_index)
-{
-	int val;
-
-	val = snd_hda_codec_read(codec, pin_nid, 0,
-				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
-	*packet_index = val >> 5;
-	*byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int packet_index, int byte_index)
-{
-	int val;
-
-	val = (packet_index << 5) | (byte_index & 0x1f);
-
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
-				unsigned char val)
-{
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	/* Unmute */
-	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
-		snd_hda_codec_write(codec, pin_nid, 0,
-				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-	/* Enable pin out */
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
-				      hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_DISABLE);
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
-{
-	return 1 + snd_hda_codec_read(codec, nid, 0,
-					AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec,
-				   hda_nid_t nid, int chs)
-{
-	if (chs != hdmi_get_channel_count(codec, nid))
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int slot;
-
-	for (i = 0; i < 8; i++) {
-		slot = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_CHAN_SLOT, i);
-		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
-						slot >> 4, slot & 0xf);
-	}
-#endif
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int size;
-
-	size = snd_hdmi_get_eld_size(codec, pin_nid);
-	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
-	}
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
-	int i, j;
-	int size;
-	int pi, bi;
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		if (size == 0)
-			continue;
-
-		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
-		for (j = 1; j < 1000; j++) {
-			hdmi_write_dip_byte(codec, pin_nid, 0x0);
-			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
-			if (pi != i)
-				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
-						bi, pi, i);
-			if (bi == 0) /* byte index wrapped around */
-				break;
-		}
-		snd_printd(KERN_INFO
-			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
-			i, size, j);
-	}
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
-{
-	ai->checksum = 0;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
-				      hda_nid_t pin_nid,
-				      struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	int i;
-
-	hdmi_debug_dip_size(codec, pin_nid);
-	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
-	hdmi_checksum_audio_infoframe(ai);
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++)
-		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
-	int i, j;
-	struct cea_channel_speaker_allocation *p;
-
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		p = channel_allocations + i;
-		p->channels = 0;
-		p->spk_mask = 0;
-		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-			if (p->speakers[j]) {
-				p->channels++;
-				p->spk_mask |= p->speakers[j];
-			}
-	}
-}
-
-/*
- * The transformation takes two steps:
- *
- * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- * 	      spk_mask => (channel_allocations[])         => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
-					 struct hdmi_audio_infoframe *ai)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	struct hdmi_eld *eld;
-	int i;
-	int spk_mask = 0;
-	int channels = 1 + (ai->CC02_CT47 & 0x7);
-	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
-	/*
-	 * CA defaults to 0 for basic stereo audio
-	 */
-	if (channels <= 2)
-		return 0;
-
-	i = hda_node_index(spec->pin_cvt, nid);
-	if (i < 0)
-		return 0;
-	eld = &spec->sink_eld[i];
-
-	/*
-	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-	 * in console or for audio devices. Assume the highest speakers
-	 * configuration, to _not_ prohibit multi-channel audio playback.
-	 */
-	if (!eld->spk_alloc)
-		eld->spk_alloc = 0xffff;
-
-	/*
-	 * expand ELD's speaker allocation mask
-	 *
-	 * ELD tells the speaker mask in a compact(paired) form,
-	 * expand ELD's notions to match the ones used by Audio InfoFrame.
-	 */
-	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-		if (eld->spk_alloc & (1 << i))
-			spk_mask |= eld_speaker_allocation_bits[i];
-	}
-
-	/* search for the first working match in the CA table */
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if (channels == channel_allocations[i].channels &&
-		    (spk_mask & channel_allocations[i].spk_mask) ==
-				channel_allocations[i].spk_mask) {
-			ai->CA = channel_allocations[i].ca_index;
-			break;
-		}
-	}
-
-	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
-	snd_printdd(KERN_INFO
-			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
-			ai->CA, channels, buf);
-
-	return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid,
-				       struct hdmi_audio_infoframe *ai)
-{
-	int i;
-	int ca = ai->CA;
-	int err;
-
-	if (hdmi_channel_mapping[ca][1] == 0) {
-		for (i = 0; i < channel_allocations[ca].channels; i++)
-			hdmi_channel_mapping[ca][i] = i | (i << 4);
-		for (; i < 8; i++)
-			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
-	}
-
-	for (i = 0; i < 8; i++) {
-		err = snd_hda_codec_write(codec, pin_nid, 0,
-					  AC_VERB_SET_HDMI_CHAN_SLOT,
-					  hdmi_channel_mapping[ca][i]);
-		if (err) {
-			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
-			break;
-		}
-	}
-
-	hdmi_debug_channel_mapping(codec, pin_nid);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
-				    struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	u8 val;
-	int i;
-
-	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
-							    != AC_DIPXMIT_BEST)
-		return false;
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++) {
-		val = snd_hda_codec_read(codec, pin_nid, 0,
-					 AC_VERB_GET_HDMI_DIP_DATA, 0);
-		if (val != bytes[i])
-			return false;
-	}
-
-	return true;
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
-					struct snd_pcm_substream *substream)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	hda_nid_t pin_nid;
-	int i;
-	struct hdmi_audio_infoframe ai = {
-		.type		= 0x84,
-		.ver		= 0x01,
-		.len		= 0x0a,
-		.CC02_CT47	= substream->runtime->channels - 1,
-	};
-
-	hdmi_setup_channel_allocation(codec, nid, &ai);
-
-	for (i = 0; i < spec->num_pins; i++) {
-		if (spec->pin_cvt[i] != nid)
-			continue;
-		if (!spec->sink_eld[i].monitor_present)
-			continue;
-
-		pin_nid = spec->pin[i];
-		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
-			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
-			hdmi_stop_infoframe_trans(codec, pin_nid);
-			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
-			hdmi_start_infoframe_trans(codec, pin_nid);
-		}
-	}
-}
-
-/*
- * Unsolicited events
- */
-
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int pind = !!(res & AC_UNSOL_RES_PD);
-	int eldv = !!(res & AC_UNSOL_RES_ELDV);
-	int index;
-
-	printk(KERN_INFO
-		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-		tag, pind, eldv);
-
-	index = hda_node_index(spec->pin, tag);
-	if (index < 0)
-		return;
-
-	spec->sink_eld[index].monitor_present = pind;
-	spec->sink_eld[index].eld_valid = eldv;
-
-	if (eldv) {
-		spec->sink_eld[index].monitor_present = 1;
-		hdmi_get_show_eld(codec, spec->pin[index],
-				 &spec->sink_eld[index]);
-		/* TODO: do real things about ELD */
-	}
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
-	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
-	printk(KERN_INFO
-		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
-		tag,
-		subtag,
-		cp_state,
-		cp_ready);
-
-	/* TODO */
-	if (cp_state)
-		;
-	if (cp_ready)
-		;
-}
-
-static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	struct nvhdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
-	if (hda_node_index(spec->pin, tag) < 0) {
-		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
-		return;
-	}
-
-	if (subtag == 0)
-		hdmi_intrinsic_event(codec, res);
-	else
-		hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-			      u32 stream_tag, int format)
-{
-	int tag;
-	int fmt;
-
-	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
-	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
-	snd_printdd("hdmi_setup_stream: "
-		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
-		    nid,
-		    tag == stream_tag ? "" : "new-",
-		    stream_tag,
-		    fmt == format ? "" : "new-",
-		    format);
-
-	if (tag != stream_tag)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CHANNEL_STREAMID,
-				    stream_tag << 4);
-	if (fmt != format)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_STREAM_FORMAT, format);
-}
-
 /*
  * Controls
  */
 static int nvhdmi_build_controls(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int err;
 	int i;
 
@@ -902,7 +121,7 @@ static int nvhdmi_build_controls(struct 
 
 static int nvhdmi_init(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
 	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
@@ -920,7 +139,7 @@ static int nvhdmi_init(struct hda_codec 
 
 static void nvhdmi_free(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
@@ -939,7 +158,7 @@ static int nvhdmi_dig_playback_pcm_open(
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 }
 
@@ -947,7 +166,7 @@ static int nvhdmi_dig_playback_pcm_close
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
@@ -968,7 +187,7 @@ static int nvhdmi_dig_playback_pcm_close
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
@@ -1121,7 +340,7 @@ static int nvhdmi_dig_playback_pcm_prepa
 					unsigned int format,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
 					format, substream);
 }
@@ -1170,7 +389,7 @@ static struct hda_pcm_stream nvhdmi_pcm_
 
 static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
 	int i;
 
@@ -1196,7 +415,7 @@ static int nvhdmi_build_pcms_8ch_89(stru
 
 static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
@@ -1212,7 +431,7 @@ static int nvhdmi_build_pcms_8ch_7x(stru
 
 static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
@@ -1231,7 +450,7 @@ static struct hda_codec_ops nvhdmi_patch
 	.build_pcms = nvhdmi_build_pcms_8ch_89,
 	.init = nvhdmi_init,
 	.free = nvhdmi_free,
-	.unsol_event = nvhdmi_unsol_event,
+	.unsol_event = hdmi_unsol_event,
 };
 
 static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
@@ -1250,7 +469,7 @@ static struct hda_codec_ops nvhdmi_patch
 
 static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec;
+	struct hdmi_spec *spec;
 	int i;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -1260,7 +479,7 @@ static int patch_nvhdmi_8ch_89(struct hd
 	codec->spec = spec;
 	spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
 
-	if (nvhdmi_parse_codec(codec) < 0) {
+	if (hdmi_parse_codec(codec) < 0) {
 		codec->spec = NULL;
 		kfree(spec);
 		return -EINVAL;
@@ -1277,7 +496,7 @@ static int patch_nvhdmi_8ch_89(struct hd
 
 static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec;
+	struct hdmi_spec *spec;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -1297,7 +516,7 @@ static int patch_nvhdmi_8ch_7x(struct hd
 
 static int patch_nvhdmi_2ch(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec;
+	struct hdmi_spec *spec;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel]  [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04  5:44       ` Wu Fengguang
@ 2010-03-04  5:52         ` Wei Ni
  2010-03-04  6:09           ` Wu Fengguang
  0 siblings, 1 reply; 80+ messages in thread
From: Wei Ni @ 2010-03-04  5:52 UTC (permalink / raw)
  To: 'Wu Fengguang', Takashi Iwai
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

Hi, Wu Fengguang
These changes only for Nvidia controller.
1. for hdmi_channel_mapping[0x2[8]
Because our controller's channel_mapping has some different with
patch_intelhdmi.c. If don't change, the 8ch has some wrong.
2. for remove "u8 reserved[5]"
Because our controller doesn't support it yet.
3. for hdmi_checksum_audio_infoframe()
Because our controller only support the checkum=0 now.

Thanks
Wei.
nvpublic

-----Original Message-----
From: Wu Fengguang [mailto:fengguang.wu@intel.com]
Sent: Thursday, March 04, 2010 1:44 PM
To: Takashi Iwai
Cc: Wei Ni; 'akpm'; 'alsa-devel'; 'linux-kernel'; 'Pavel Hofman'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

On Thu, Mar 04, 2010 at 10:18:39AM +0800, Wu Fengguang wrote:
> On Wed, Mar 03, 2010 at 02:46:25PM +0800, Takashi Iwai wrote:
> > At Tue, 2 Mar 2010 13:43:07 +0800,
> > Wu Fengguang wrote:
> > >
> > > On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> > > > Hi, Takashi
> > > > I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> > > > The new HAD controller and codec support standard HDMI operation.
> > > >
> > > > I attached the patch file, please check it.
> > >
> > > Wei Ni,
> > >
> > > Can we avoid the big copy&paste and do more code reuse?
> > > This benefits all of us in long term.
> >
> > The plan is to merge all current patch_*hdmi.c into one.
> > But this can be done later once after we get the working driver
> > for the new Nvidia codecs.
> >
> > The new Nvidia HDMI codec is a bit tricky (which has 4 separate
> > codec slots), so I'd like to get it working first.
>
> Here is the patch to merge common code in a simple way.
> This is compile tested only, need double check.
>
> What puzzled me is that Wei Ni reused the same dynamic parsing code,
> even though the Intel/Nvidia codecs have vastly different pin/cvt
> layouts..

WeiNi, some more questions.

- why change hdmi_channel_mapping[0x32][8] from
        [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
  to
        [0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },

- why remove "u8 reserved[5]; /* PB6 - PB10 */" from struct
  hdmi_audio_infoframe?

- why change
        static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
        {
                u8 *bytes = (u8 *)ai;
                u8 sum = 0;
                int i;

                ai->checksum = 0;

                for (i = 0; i < sizeof(*ai); i++)
                        sum += bytes[i];

                ai->checksum = - sum;
        }
  to
        static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
        {
                ai->checksum = 0;
        }


Those are very dirty changes. Either the original code is correct, or
they are wrong and should be changed as well. If you submit code like
this now, we'll have to resolve conflicts and do pointless retests at
the perceived future merge time.

Would you stop hacking things around like that?

I'd recommend to base your future work on top of the following patch.
It's based on your previous patches.

Note that I reverted the above 3 changes. If they are good changes,
you can still submit standalone patches, and let's discuss and test
them case by case.

Thanks,
Fengguang
---
hdmi - create patch_hdmi.c for common hdmi code

For now the patch_hdmi.c file is simply included by patch_intelhdmi.c
and patch_nvhdmi.c, and does not represent a real codec.

CC: Wei Ni <wni@nvidia.com>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
---
 sound/pci/hda/patch_hdmi.c      |  828 ++++++++++++++++++++++++++++++
 sound/pci/hda/patch_intelhdmi.c |  822 -----------------------------
 sound/pci/hda/patch_nvhdmi.c    |  817 -----------------------------
 3 files changed, 856 insertions(+), 1611 deletions(-)

--- sound-2.6.orig/sound/pci/hda/patch_intelhdmi.c      2010-03-04 13:14:54.000000000 +0800
+++ sound-2.6/sound/pci/hda/patch_intelhdmi.c   2010-03-04 13:14:56.000000000 +0800
@@ -33,822 +33,20 @@
 #include "hda_codec.h"
 #include "hda_local.h"

-/*
- * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
- * could support two independent pipes, each of them can be connected to one or
- * more ports (DVI, HDMI or DisplayPort).
- *
- * The HDA correspondence of pipes/ports are converter/pin nodes.
- */
+#include "patch_hdmi.c"
+
 #define INTEL_HDMI_CVTS        2
 #define INTEL_HDMI_PINS        3

-static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = {
+static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
        "INTEL HDMI 0",
        "INTEL HDMI 1",
 };

-struct intel_hdmi_spec {
-       int num_cvts;
-       int num_pins;
-       hda_nid_t cvt[INTEL_HDMI_CVTS+1];  /* audio sources */
-       hda_nid_t pin[INTEL_HDMI_PINS+1];  /* audio sinks */
-
-       /*
-        * source connection for each pin
-        */
-       hda_nid_t pin_cvt[INTEL_HDMI_PINS+1];
-
-       /*
-        * HDMI sink attached to each pin
-        */
-       struct hdmi_eld sink_eld[INTEL_HDMI_PINS];
-
-       /*
-        * export one pcm per pipe
-        */
-       struct hda_pcm  pcm_rec[INTEL_HDMI_CVTS];
-};
-
-struct hdmi_audio_infoframe {
-       u8 type; /* 0x84 */
-       u8 ver;  /* 0x01 */
-       u8 len;  /* 0x0a */
-
-       u8 checksum;    /* PB0 */
-       u8 CC02_CT47;   /* CC in bits 0:2, CT in 4:7 */
-       u8 SS01_SF24;
-       u8 CXT04;
-       u8 CA;
-       u8 LFEPBL01_LSV36_DM_INH7;
-       u8 reserved[5]; /* PB6 - PB10 */
-};
-
-/*
- * CEA speaker placement:
- *
- *        FLH       FCH        FRH
- *  FLW    FL  FLC   FC   FRC   FR   FRW
- *
- *                                  LFE
- *                     TC
- *
- *          RL  RLC   RC   RRC   RR
- *
- * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
- * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
- */
-enum cea_speaker_placement {
-       FL  = (1 <<  0),        /* Front Left           */
-       FC  = (1 <<  1),        /* Front Center         */
-       FR  = (1 <<  2),        /* Front Right          */
-       FLC = (1 <<  3),        /* Front Left Center    */
-       FRC = (1 <<  4),        /* Front Right Center   */
-       RL  = (1 <<  5),        /* Rear Left            */
-       RC  = (1 <<  6),        /* Rear Center          */
-       RR  = (1 <<  7),        /* Rear Right           */
-       RLC = (1 <<  8),        /* Rear Left Center     */
-       RRC = (1 <<  9),        /* Rear Right Center    */
-       LFE = (1 << 10),        /* Low Frequency Effect */
-       FLW = (1 << 11),        /* Front Left Wide      */
-       FRW = (1 << 12),        /* Front Right Wide     */
-       FLH = (1 << 13),        /* Front Left High      */
-       FCH = (1 << 14),        /* Front Center High    */
-       FRH = (1 << 15),        /* Front Right High     */
-       TC  = (1 << 16),        /* Top Center           */
-};
-
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static int eld_speaker_allocation_bits[] = {
-       [0] = FL | FR,
-       [1] = LFE,
-       [2] = FC,
-       [3] = RL | RR,
-       [4] = RC,
-       [5] = FLC | FRC,
-       [6] = RLC | RRC,
-       /* the following are not defined in ELD yet */
-       [7] = FLW | FRW,
-       [8] = FLH | FRH,
-       [9] = TC,
-       [10] = FCH,
-};
-
-struct cea_channel_speaker_allocation {
-       int ca_index;
-       int speakers[8];
-
-       /* derived values, just for convenience */
-       int channels;
-       int spk_mask;
-};
-
-/*
- * ALSA sequence is:
- *
- *       surround40   surround41   surround50   surround51   surround71
- * ch0   front left   =            =            =            =
- * ch1   front right  =            =            =            =
- * ch2   rear left    =            =            =            =
- * ch3   rear right   =            =            =            =
- * ch4                LFE          center       center       center
- * ch5                                          LFE          LFE
- * ch6                                                       side left
- * ch7                                                       side right
- *
- * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
- */
-static int hdmi_channel_mapping[0x32][8] = {
-       /* stereo */
-       [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-       /* 2.1 */
-       [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-       /* Dolby Surround */
-       [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
-       /* surround40 */
-       [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
-       /* 4ch */
-       [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
-       /* surround41 */
-       [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
-       /* surround50 */
-       [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
-       /* surround51 */
-       [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
-       /* 7.1 */
-       [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/*                       channel:   7     6    5    4    3     2    1    0  */
-{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
-                                /* 2.1 */
-{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
-                                /* Dolby Surround */
-{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
-                                /* surround40 */
-{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
-                                /* surround41 */
-{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
-                                /* surround50 */
-{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-                                /* surround51 */
-{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-                                /* 6.1 */
-{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-                                /* surround71 */
-{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-
-{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
-{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
-};
-
-/*
- * HDA/HDMI auto parsing
- */
-
-static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
-{
-       int i;
-
-       for (i = 0; nids[i]; i++)
-               if (nids[i] == nid)
-                       return i;
-
-       snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
-       return -EINVAL;
-}
-
-static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-       struct intel_hdmi_spec *spec = codec->spec;
-       hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
-       int conn_len, curr;
-       int index;
-
-       if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
-               snd_printk(KERN_WARNING
-                          "HDMI: pin %d wcaps %#x "
-                          "does not support connection list\n",
-                          pin_nid, get_wcaps(codec, pin_nid));
-               return -EINVAL;
-       }
-
-       conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
-                                          HDA_MAX_CONNECTIONS);
-       if (conn_len > 1)
-               curr = snd_hda_codec_read(codec, pin_nid, 0,
-                                         AC_VERB_GET_CONNECT_SEL, 0);
-       else
-               curr = 0;
-
-       index = hda_node_index(spec->pin, pin_nid);
-       if (index < 0)
-               return -EINVAL;
-
-       spec->pin_cvt[index] = conn_list[curr];
-
-       return 0;
-}
-
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
-                             struct hdmi_eld *eld)
-{
-       if (!snd_hdmi_get_eld(eld, codec, pin_nid))
-               snd_hdmi_show_eld(eld);
-}
-
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
-                              struct hdmi_eld *eld)
-{
-       int present = snd_hda_pin_sense(codec, pin_nid);
-
-       eld->monitor_present    = !!(present & AC_PINSENSE_PRESENCE);
-       eld->eld_valid          = !!(present & AC_PINSENSE_ELDV);
-
-       if (present & AC_PINSENSE_ELDV)
-               hdmi_get_show_eld(codec, pin_nid, eld);
-}
-
-static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-       struct intel_hdmi_spec *spec = codec->spec;
-
-       if (spec->num_pins >= INTEL_HDMI_PINS) {
-               snd_printk(KERN_WARNING
-                          "HDMI: no space for pin %d \n", pin_nid);
-               return -EINVAL;
-       }
-
-       hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
-
-       spec->pin[spec->num_pins] = pin_nid;
-       spec->num_pins++;
-
-       /*
-        * It is assumed that converter nodes come first in the node list and
-        * hence have been registered and usable now.
-        */
-       return intel_hdmi_read_pin_conn(codec, pin_nid);
-}
-
-static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
-{
-       struct intel_hdmi_spec *spec = codec->spec;
-
-       if (spec->num_cvts >= INTEL_HDMI_CVTS) {
-               snd_printk(KERN_WARNING
-                          "HDMI: no space for converter %d \n", nid);
-               return -EINVAL;
-       }
-
-       spec->cvt[spec->num_cvts] = nid;
-       spec->num_cvts++;
-
-       return 0;
-}
-
-static int intel_hdmi_parse_codec(struct hda_codec *codec)
-{
-       hda_nid_t nid;
-       int i, nodes;
-
-       nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
-       if (!nid || nodes < 0) {
-               snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
-               return -EINVAL;
-       }
-
-       for (i = 0; i < nodes; i++, nid++) {
-               unsigned int caps;
-               unsigned int type;
-
-               caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
-               type = get_wcaps_type(caps);
-
-               if (!(caps & AC_WCAP_DIGITAL))
-                       continue;
-
-               switch (type) {
-               case AC_WID_AUD_OUT:
-                       if (intel_hdmi_add_cvt(codec, nid) < 0)
-                               return -EINVAL;
-                       break;
-               case AC_WID_PIN:
-                       caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-                       if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
-                               continue;
-                       if (intel_hdmi_add_pin(codec, nid) < 0)
-                               return -EINVAL;
-                       break;
-               }
-       }
-
-       /*
-        * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
-        * can be lost and presence sense verb will become inaccurate if the
-        * HDA link is powered off at hot plug or hw initialization time.
-        */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-       if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
-             AC_PWRST_EPSS))
-               codec->bus->power_keep_link_on = 1;
-#endif
-
-       return 0;
-}
-
 /*
  * HDMI routines
  */

-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-                               int *packet_index, int *byte_index)
-{
-       int val;
-
-       val = snd_hda_codec_read(codec, pin_nid, 0,
-                                AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
-       *packet_index = val >> 5;
-       *byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-                               int packet_index, int byte_index)
-{
-       int val;
-
-       val = (packet_index << 5) | (byte_index & 0x1f);
-
-       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
-                               unsigned char val)
-{
-       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-       /* Unmute */
-       if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
-               snd_hda_codec_write(codec, pin_nid, 0,
-                               AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-       /* Enable pin out */
-       snd_hda_codec_write(codec, pin_nid, 0,
-                           AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
-                                      hda_nid_t pin_nid)
-{
-       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-                                               AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
-                                     hda_nid_t pin_nid)
-{
-       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-                                               AC_DIPXMIT_DISABLE);
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
-{
-       return 1 + snd_hda_codec_read(codec, nid, 0,
-                                       AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec,
-                                  hda_nid_t nid, int chs)
-{
-       if (chs != hdmi_get_channel_count(codec, nid))
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec,
-                                      hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-       int i;
-       int slot;
-
-       for (i = 0; i < 8; i++) {
-               slot = snd_hda_codec_read(codec, pin_nid, 0,
-                                               AC_VERB_GET_HDMI_CHAN_SLOT, i);
-               printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
-                                               slot >> 4, slot & 0xf);
-       }
-#endif
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-       int i;
-       int size;
-
-       size = snd_hdmi_get_eld_size(codec, pin_nid);
-       printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
-       for (i = 0; i < 8; i++) {
-               size = snd_hda_codec_read(codec, pin_nid, 0,
-                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
-               printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
-       }
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
-       int i, j;
-       int size;
-       int pi, bi;
-       for (i = 0; i < 8; i++) {
-               size = snd_hda_codec_read(codec, pin_nid, 0,
-                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
-               if (size == 0)
-                       continue;
-
-               hdmi_set_dip_index(codec, pin_nid, i, 0x0);
-               for (j = 1; j < 1000; j++) {
-                       hdmi_write_dip_byte(codec, pin_nid, 0x0);
-                       hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
-                       if (pi != i)
-                               snd_printd(KERN_INFO "dip index %d: %d != %d\n",
-                                               bi, pi, i);
-                       if (bi == 0) /* byte index wrapped around */
-                               break;
-               }
-               snd_printd(KERN_INFO
-                       "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
-                       i, size, j);
-       }
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
-{
-       u8 *bytes = (u8 *)ai;
-       u8 sum = 0;
-       int i;
-
-       ai->checksum = 0;
-
-       for (i = 0; i < sizeof(*ai); i++)
-               sum += bytes[i];
-
-       ai->checksum = - sum;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
-                                     hda_nid_t pin_nid,
-                                     struct hdmi_audio_infoframe *ai)
-{
-       u8 *bytes = (u8 *)ai;
-       int i;
-
-       hdmi_debug_dip_size(codec, pin_nid);
-       hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
-       hdmi_checksum_audio_infoframe(ai);
-
-       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       for (i = 0; i < sizeof(*ai); i++)
-               hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
-       int i, j;
-       struct cea_channel_speaker_allocation *p;
-
-       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-               p = channel_allocations + i;
-               p->channels = 0;
-               p->spk_mask = 0;
-               for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-                       if (p->speakers[j]) {
-                               p->channels++;
-                               p->spk_mask |= p->speakers[j];
-                       }
-       }
-}
-
-/*
- * The transformation takes two steps:
- *
- *     eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- *           spk_mask => (channel_allocations[])         => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
-                                        struct hdmi_audio_infoframe *ai)
-{
-       struct intel_hdmi_spec *spec = codec->spec;
-       struct hdmi_eld *eld;
-       int i;
-       int spk_mask = 0;
-       int channels = 1 + (ai->CC02_CT47 & 0x7);
-       char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
-       /*
-        * CA defaults to 0 for basic stereo audio
-        */
-       if (channels <= 2)
-               return 0;
-
-       i = hda_node_index(spec->pin_cvt, nid);
-       if (i < 0)
-               return 0;
-       eld = &spec->sink_eld[i];
-
-       /*
-        * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-        * in console or for audio devices. Assume the highest speakers
-        * configuration, to _not_ prohibit multi-channel audio playback.
-        */
-       if (!eld->spk_alloc)
-               eld->spk_alloc = 0xffff;
-
-       /*
-        * expand ELD's speaker allocation mask
-        *
-        * ELD tells the speaker mask in a compact(paired) form,
-        * expand ELD's notions to match the ones used by Audio InfoFrame.
-        */
-       for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-               if (eld->spk_alloc & (1 << i))
-                       spk_mask |= eld_speaker_allocation_bits[i];
-       }
-
-       /* search for the first working match in the CA table */
-       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-               if (channels == channel_allocations[i].channels &&
-                   (spk_mask & channel_allocations[i].spk_mask) ==
-                               channel_allocations[i].spk_mask) {
-                       ai->CA = channel_allocations[i].ca_index;
-                       break;
-               }
-       }
-
-       snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
-       snd_printdd(KERN_INFO
-                       "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
-                       ai->CA, channels, buf);
-
-       return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
-                                      hda_nid_t pin_nid,
-                                      struct hdmi_audio_infoframe *ai)
-{
-       int i;
-       int ca = ai->CA;
-       int err;
-
-       if (hdmi_channel_mapping[ca][1] == 0) {
-               for (i = 0; i < channel_allocations[ca].channels; i++)
-                       hdmi_channel_mapping[ca][i] = i | (i << 4);
-               for (; i < 8; i++)
-                       hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
-       }
-
-       for (i = 0; i < 8; i++) {
-               err = snd_hda_codec_write(codec, pin_nid, 0,
-                                         AC_VERB_SET_HDMI_CHAN_SLOT,
-                                         hdmi_channel_mapping[ca][i]);
-               if (err) {
-                       snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
-                       break;
-               }
-       }
-
-       hdmi_debug_channel_mapping(codec, pin_nid);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
-                                   struct hdmi_audio_infoframe *ai)
-{
-       u8 *bytes = (u8 *)ai;
-       u8 val;
-       int i;
-
-       if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
-                                                           != AC_DIPXMIT_BEST)
-               return false;
-
-       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       for (i = 0; i < sizeof(*ai); i++) {
-               val = snd_hda_codec_read(codec, pin_nid, 0,
-                                        AC_VERB_GET_HDMI_DIP_DATA, 0);
-               if (val != bytes[i])
-                       return false;
-       }
-
-       return true;
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
-                                       struct snd_pcm_substream *substream)
-{
-       struct intel_hdmi_spec *spec = codec->spec;
-       hda_nid_t pin_nid;
-       int i;
-       struct hdmi_audio_infoframe ai = {
-               .type           = 0x84,
-               .ver            = 0x01,
-               .len            = 0x0a,
-               .CC02_CT47      = substream->runtime->channels - 1,
-       };
-
-       hdmi_setup_channel_allocation(codec, nid, &ai);
-
-       for (i = 0; i < spec->num_pins; i++) {
-               if (spec->pin_cvt[i] != nid)
-                       continue;
-               if (!spec->sink_eld[i].monitor_present)
-                       continue;
-
-               pin_nid = spec->pin[i];
-               if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
-                       hdmi_setup_channel_mapping(codec, pin_nid, &ai);
-                       hdmi_stop_infoframe_trans(codec, pin_nid);
-                       hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
-                       hdmi_start_infoframe_trans(codec, pin_nid);
-               }
-       }
-}
-
-
-/*
- * Unsolicited events
- */
-
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-       struct intel_hdmi_spec *spec = codec->spec;
-       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int pind = !!(res & AC_UNSOL_RES_PD);
-       int eldv = !!(res & AC_UNSOL_RES_ELDV);
-       int index;
-
-       printk(KERN_INFO
-               "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-               tag, pind, eldv);
-
-       index = hda_node_index(spec->pin, tag);
-       if (index < 0)
-               return;
-
-       spec->sink_eld[index].monitor_present = pind;
-       spec->sink_eld[index].eld_valid = eldv;
-
-       if (pind && eldv) {
-               hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]);
-               /* TODO: do real things about ELD */
-       }
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-       int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
-       int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
-       printk(KERN_INFO
-               "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
-               tag,
-               subtag,
-               cp_state,
-               cp_ready);
-
-       /* TODO */
-       if (cp_state)
-               ;
-       if (cp_ready)
-               ;
-}
-
-
-static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-       struct intel_hdmi_spec *spec = codec->spec;
-       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
-       if (hda_node_index(spec->pin, tag) < 0) {
-               snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
-               return;
-       }
-
-       if (subtag == 0)
-               hdmi_intrinsic_event(codec, res);
-       else
-               hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-                             u32 stream_tag, int format)
-{
-       int tag;
-       int fmt;
-
-       tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
-       fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
-       snd_printdd("hdmi_setup_stream: "
-                   "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
-                   nid,
-                   tag == stream_tag ? "" : "new-",
-                   stream_tag,
-                   fmt == format ? "" : "new-",
-                   format);
-
-       if (tag != stream_tag)
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4);
-       if (fmt != format)
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_STREAM_FORMAT, format);
-}
-
 static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
                                           struct hda_codec *codec,
                                           unsigned int stream_tag,
@@ -882,7 +80,7 @@ static struct hda_pcm_stream intel_hdmi_

 static int intel_hdmi_build_pcms(struct hda_codec *codec)
 {
-       struct intel_hdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        struct hda_pcm *info = spec->pcm_rec;
        int i;

@@ -908,7 +106,7 @@ static int intel_hdmi_build_pcms(struct

 static int intel_hdmi_build_controls(struct hda_codec *codec)
 {
-       struct intel_hdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        int err;
        int i;

@@ -923,7 +121,7 @@ static int intel_hdmi_build_controls(str

 static int intel_hdmi_init(struct hda_codec *codec)
 {
-       struct intel_hdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        int i;

        for (i = 0; spec->pin[i]; i++) {
@@ -937,7 +135,7 @@ static int intel_hdmi_init(struct hda_co

 static void intel_hdmi_free(struct hda_codec *codec)
 {
-       struct intel_hdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        int i;

        for (i = 0; i < spec->num_pins; i++)
@@ -951,12 +149,12 @@ static struct hda_codec_ops intel_hdmi_p
        .free                   = intel_hdmi_free,
        .build_pcms             = intel_hdmi_build_pcms,
        .build_controls         = intel_hdmi_build_controls,
-       .unsol_event            = intel_hdmi_unsol_event,
+       .unsol_event            = hdmi_unsol_event,
 };

 static int patch_intel_hdmi(struct hda_codec *codec)
 {
-       struct intel_hdmi_spec *spec;
+       struct hdmi_spec *spec;
        int i;

        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -964,7 +162,7 @@ static int patch_intel_hdmi(struct hda_c
                return -ENOMEM;

        codec->spec = spec;
-       if (intel_hdmi_parse_codec(codec) < 0) {
+       if (hdmi_parse_codec(codec) < 0) {
                codec->spec = NULL;
                kfree(spec);
                return -EINVAL;
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ sound-2.6/sound/pci/hda/patch_hdmi.c        2010-03-04 13:30:14.000000000 +0800
@@ -0,0 +1,828 @@
+/*
+ * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
+ * could support two independent pipes, each of them can be connected to one or
+ * more ports (DVI, HDMI or DisplayPort).
+ *
+ * The HDA correspondence of pipes/ports are converter/pin nodes.
+ */
+#define MAX_HDMI_CVTS  2
+#define MAX_HDMI_PINS  3
+
+
+struct hdmi_spec {
+       int num_cvts;
+       int num_pins;
+       hda_nid_t cvt[MAX_HDMI_CVTS+1];  /* audio sources */
+       hda_nid_t pin[MAX_HDMI_PINS+1];  /* audio sinks */
+
+       /*
+        * source connection for each pin
+        */
+       hda_nid_t pin_cvt[MAX_HDMI_PINS+1];
+
+       /*
+        * HDMI sink attached to each pin
+        */
+       struct hdmi_eld sink_eld[MAX_HDMI_PINS];
+
+       /*
+        * export one pcm per pipe
+        */
+       struct hda_pcm  pcm_rec[MAX_HDMI_CVTS];
+
+       /*
+        * nvhdmi specific
+        */
+       struct hda_multi_out multiout;
+       unsigned int codec_type;
+};
+
+
+struct hdmi_audio_infoframe {
+       u8 type; /* 0x84 */
+       u8 ver;  /* 0x01 */
+       u8 len;  /* 0x0a */
+
+       u8 checksum;    /* PB0 */
+       u8 CC02_CT47;   /* CC in bits 0:2, CT in 4:7 */
+       u8 SS01_SF24;
+       u8 CXT04;
+       u8 CA;
+       u8 LFEPBL01_LSV36_DM_INH7;
+       u8 reserved[5]; /* PB6 - PB10 */
+};
+
+/*
+ * CEA speaker placement:
+ *
+ *        FLH       FCH        FRH
+ *  FLW    FL  FLC   FC   FRC   FR   FRW
+ *
+ *                                  LFE
+ *                     TC
+ *
+ *          RL  RLC   RC   RRC   RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+       FL  = (1 <<  0),        /* Front Left           */
+       FC  = (1 <<  1),        /* Front Center         */
+       FR  = (1 <<  2),        /* Front Right          */
+       FLC = (1 <<  3),        /* Front Left Center    */
+       FRC = (1 <<  4),        /* Front Right Center   */
+       RL  = (1 <<  5),        /* Rear Left            */
+       RC  = (1 <<  6),        /* Rear Center          */
+       RR  = (1 <<  7),        /* Rear Right           */
+       RLC = (1 <<  8),        /* Rear Left Center     */
+       RRC = (1 <<  9),        /* Rear Right Center    */
+       LFE = (1 << 10),        /* Low Frequency Effect */
+       FLW = (1 << 11),        /* Front Left Wide      */
+       FRW = (1 << 12),        /* Front Right Wide     */
+       FLH = (1 << 13),        /* Front Left High      */
+       FCH = (1 << 14),        /* Front Center High    */
+       FRH = (1 << 15),        /* Front Right High     */
+       TC  = (1 << 16),        /* Top Center           */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+       [0] = FL | FR,
+       [1] = LFE,
+       [2] = FC,
+       [3] = RL | RR,
+       [4] = RC,
+       [5] = FLC | FRC,
+       [6] = RLC | RRC,
+       /* the following are not defined in ELD yet */
+       [7] = FLW | FRW,
+       [8] = FLH | FRH,
+       [9] = TC,
+       [10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+       int ca_index;
+       int speakers[8];
+
+       /* derived values, just for convenience */
+       int channels;
+       int spk_mask;
+};
+
+/*
+ * ALSA sequence is:
+ *
+ *       surround40   surround41   surround50   surround51   surround71
+ * ch0   front left   =            =            =            =
+ * ch1   front right  =            =            =            =
+ * ch2   rear left    =            =            =            =
+ * ch3   rear right   =            =            =            =
+ * ch4                LFE          center       center       center
+ * ch5                                          LFE          LFE
+ * ch6                                                       side left
+ * ch7                                                       side right
+ *
+ * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
+ */
+static int hdmi_channel_mapping[0x32][8] = {
+       /* stereo */
+       [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+       /* 2.1 */
+       [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+       /* Dolby Surround */
+       [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
+       /* surround40 */
+       [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
+       /* 4ch */
+       [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
+       /* surround41 */
+       [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+       /* surround50 */
+       [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
+       /* surround51 */
+       [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
+       /* 7.1 */
+       [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/*                       channel:   7     6    5    4    3     2    1    0  */
+{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
+                                /* 2.1 */
+{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
+                                /* Dolby Surround */
+{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
+                                /* surround40 */
+{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
+                                /* surround41 */
+{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
+                                /* surround50 */
+{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+                                /* surround51 */
+{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+                                /* 6.1 */
+{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+                                /* surround71 */
+{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+
+{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
+{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
+};
+
+
+/*
+ * HDMI routines
+ */
+
+static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+{
+       int i;
+
+       for (i = 0; nids[i]; i++)
+               if (nids[i] == nid)
+                       return i;
+
+       snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+       return -EINVAL;
+}
+
+static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
+                             struct hdmi_eld *eld)
+{
+       if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+               snd_hdmi_show_eld(eld);
+}
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+                               int *packet_index, int *byte_index)
+{
+       int val;
+
+       val = snd_hda_codec_read(codec, pin_nid, 0,
+                                AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+       *packet_index = val >> 5;
+       *byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+                               int packet_index, int byte_index)
+{
+       int val;
+
+       val = (packet_index << 5) | (byte_index & 0x1f);
+
+       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
+                               unsigned char val)
+{
+       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+       /* Unmute */
+       if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
+               snd_hda_codec_write(codec, pin_nid, 0,
+                               AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+       /* Enable pin out */
+       snd_hda_codec_write(codec, pin_nid, 0,
+                           AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+{
+       return 1 + snd_hda_codec_read(codec, nid, 0,
+                                       AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec,
+                                  hda_nid_t nid, int chs)
+{
+       if (chs != hdmi_get_channel_count(codec, nid))
+               snd_hda_codec_write(codec, nid, 0,
+                                   AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+}
+
+
+/*
+ * Channel mapping routines
+ */
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+       int i, j;
+       struct cea_channel_speaker_allocation *p;
+
+       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+               p = channel_allocations + i;
+               p->channels = 0;
+               p->spk_mask = 0;
+               for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+                       if (p->speakers[j]) {
+                               p->channels++;
+                               p->spk_mask |= p->speakers[j];
+                       }
+       }
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ *     eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ *           spk_mask => (channel_allocations[])         => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+                                        struct hdmi_audio_infoframe *ai)
+{
+       struct hdmi_spec *spec = codec->spec;
+       struct hdmi_eld *eld;
+       int i;
+       int spk_mask = 0;
+       int channels = 1 + (ai->CC02_CT47 & 0x7);
+       char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+       /*
+        * CA defaults to 0 for basic stereo audio
+        */
+       if (channels <= 2)
+               return 0;
+
+       i = hda_node_index(spec->pin_cvt, nid);
+       if (i < 0)
+               return 0;
+       eld = &spec->sink_eld[i];
+
+       /*
+        * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+        * in console or for audio devices. Assume the highest speakers
+        * configuration, to _not_ prohibit multi-channel audio playback.
+        */
+       if (!eld->spk_alloc)
+               eld->spk_alloc = 0xffff;
+
+       /*
+        * expand ELD's speaker allocation mask
+        *
+        * ELD tells the speaker mask in a compact(paired) form,
+        * expand ELD's notions to match the ones used by Audio InfoFrame.
+        */
+       for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+               if (eld->spk_alloc & (1 << i))
+                       spk_mask |= eld_speaker_allocation_bits[i];
+       }
+
+       /* search for the first working match in the CA table */
+       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+               if (channels == channel_allocations[i].channels &&
+                   (spk_mask & channel_allocations[i].spk_mask) ==
+                               channel_allocations[i].spk_mask) {
+                       ai->CA = channel_allocations[i].ca_index;
+                       break;
+               }
+       }
+
+       snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+       snd_printdd(KERN_INFO
+                       "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+                       ai->CA, channels, buf);
+
+       return ai->CA;
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec,
+                                      hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+       int i;
+       int slot;
+
+       for (i = 0; i < 8; i++) {
+               slot = snd_hda_codec_read(codec, pin_nid, 0,
+                                               AC_VERB_GET_HDMI_CHAN_SLOT, i);
+               printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+                                               slot >> 4, slot & 0xf);
+       }
+#endif
+}
+
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+                                      hda_nid_t pin_nid,
+                                      struct hdmi_audio_infoframe *ai)
+{
+       int i;
+       int ca = ai->CA;
+       int err;
+
+       if (hdmi_channel_mapping[ca][1] == 0) {
+               for (i = 0; i < channel_allocations[ca].channels; i++)
+                       hdmi_channel_mapping[ca][i] = i | (i << 4);
+               for (; i < 8; i++)
+                       hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+       }
+
+       for (i = 0; i < 8; i++) {
+               err = snd_hda_codec_write(codec, pin_nid, 0,
+                                         AC_VERB_SET_HDMI_CHAN_SLOT,
+                                         hdmi_channel_mapping[ca][i]);
+               if (err) {
+                       snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
+                       break;
+               }
+       }
+
+       hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+/*
+ * Enable Audio InfoFrame Transmission
+ */
+static void hdmi_start_infoframe_trans(struct hda_codec *codec,
+                                      hda_nid_t pin_nid)
+{
+       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+                                               AC_DIPXMIT_BEST);
+}
+
+/*
+ * Disable Audio InfoFrame Transmission
+ */
+static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
+                                     hda_nid_t pin_nid)
+{
+       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+                                               AC_DIPXMIT_DISABLE);
+}
+
+static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+       int i;
+       int size;
+
+       size = snd_hdmi_get_eld_size(codec, pin_nid);
+       printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+       for (i = 0; i < 8; i++) {
+               size = snd_hda_codec_read(codec, pin_nid, 0,
+                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
+               printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+       }
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef BE_PARANOID
+       int i, j;
+       int size;
+       int pi, bi;
+       for (i = 0; i < 8; i++) {
+               size = snd_hda_codec_read(codec, pin_nid, 0,
+                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
+               if (size == 0)
+                       continue;
+
+               hdmi_set_dip_index(codec, pin_nid, i, 0x0);
+               for (j = 1; j < 1000; j++) {
+                       hdmi_write_dip_byte(codec, pin_nid, 0x0);
+                       hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
+                       if (pi != i)
+                               snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+                                               bi, pi, i);
+                       if (bi == 0) /* byte index wrapped around */
+                               break;
+               }
+               snd_printd(KERN_INFO
+                       "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+                       i, size, j);
+       }
+#endif
+}
+
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+{
+       u8 *bytes = (u8 *)ai;
+       u8 sum = 0;
+       int i;
+
+       ai->checksum = 0;
+
+       for (i = 0; i < sizeof(*ai); i++)
+               sum += bytes[i];
+
+       ai->checksum = - sum;
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+                                     hda_nid_t pin_nid,
+                                     struct hdmi_audio_infoframe *ai)
+{
+       u8 *bytes = (u8 *)ai;
+       int i;
+
+       hdmi_debug_dip_size(codec, pin_nid);
+       hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
+
+       hdmi_checksum_audio_infoframe(ai);
+
+       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+       for (i = 0; i < sizeof(*ai); i++)
+               hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+}
+
+static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
+                                   struct hdmi_audio_infoframe *ai)
+{
+       u8 *bytes = (u8 *)ai;
+       u8 val;
+       int i;
+
+       if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
+                                                           != AC_DIPXMIT_BEST)
+               return false;
+
+       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+       for (i = 0; i < sizeof(*ai); i++) {
+               val = snd_hda_codec_read(codec, pin_nid, 0,
+                                        AC_VERB_GET_HDMI_DIP_DATA, 0);
+               if (val != bytes[i])
+                       return false;
+       }
+
+       return true;
+}
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+                                       struct snd_pcm_substream *substream)
+{
+       struct hdmi_spec *spec = codec->spec;
+       hda_nid_t pin_nid;
+       int i;
+       struct hdmi_audio_infoframe ai = {
+               .type           = 0x84,
+               .ver            = 0x01,
+               .len            = 0x0a,
+               .CC02_CT47      = substream->runtime->channels - 1,
+       };
+
+       hdmi_setup_channel_allocation(codec, nid, &ai);
+
+       for (i = 0; i < spec->num_pins; i++) {
+               if (spec->pin_cvt[i] != nid)
+                       continue;
+               if (!spec->sink_eld[i].monitor_present)
+                       continue;
+
+               pin_nid = spec->pin[i];
+               if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+                       hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+                       hdmi_stop_infoframe_trans(codec, pin_nid);
+                       hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+                       hdmi_start_infoframe_trans(codec, pin_nid);
+               }
+       }
+}
+
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+       struct hdmi_spec *spec = codec->spec;
+       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+       int pind = !!(res & AC_UNSOL_RES_PD);
+       int eldv = !!(res & AC_UNSOL_RES_ELDV);
+       int index;
+
+       printk(KERN_INFO
+               "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+               tag, pind, eldv);
+
+       index = hda_node_index(spec->pin, tag);
+       if (index < 0)
+               return;
+
+       spec->sink_eld[index].monitor_present = pind;
+       spec->sink_eld[index].eld_valid = eldv;
+
+       if (pind && eldv) {
+               hdmi_get_show_eld(codec, spec->pin[index],
+                                 &spec->sink_eld[index]);
+               /* TODO: do real things about ELD */
+       }
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+       int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+       int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+       printk(KERN_INFO
+               "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+               tag,
+               subtag,
+               cp_state,
+               cp_ready);
+
+       /* TODO */
+       if (cp_state)
+               ;
+       if (cp_ready)
+               ;
+}
+
+
+static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       struct hdmi_spec *spec = codec->spec;
+       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+       if (hda_node_index(spec->pin, tag) < 0) {
+               snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+               return;
+       }
+
+       if (subtag == 0)
+               hdmi_intrinsic_event(codec, res);
+       else
+               hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+                             u32 stream_tag, int format)
+{
+       int tag;
+       int fmt;
+
+       tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
+       fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
+
+       snd_printdd("hdmi_setup_stream: "
+                   "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
+                   nid,
+                   tag == stream_tag ? "" : "new-",
+                   stream_tag,
+                   fmt == format ? "" : "new-",
+                   format);
+
+       if (tag != stream_tag)
+               snd_hda_codec_write(codec, nid, 0,
+                                   AC_VERB_SET_CHANNEL_STREAMID,
+                                   stream_tag << 4);
+       if (fmt != format)
+               snd_hda_codec_write(codec, nid, 0,
+                                   AC_VERB_SET_STREAM_FORMAT, format);
+}
+
+/*
+ * HDA/HDMI auto parsing
+ */
+
+static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+       struct hdmi_spec *spec = codec->spec;
+       hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+       int conn_len, curr;
+       int index;
+
+       if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
+               snd_printk(KERN_WARNING
+                          "HDMI: pin %d wcaps %#x "
+                          "does not support connection list\n",
+                          pin_nid, get_wcaps(codec, pin_nid));
+               return -EINVAL;
+       }
+
+       conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
+                                          HDA_MAX_CONNECTIONS);
+       if (conn_len > 1)
+               curr = snd_hda_codec_read(codec, pin_nid, 0,
+                                         AC_VERB_GET_CONNECT_SEL, 0);
+       else
+               curr = 0;
+
+       index = hda_node_index(spec->pin, pin_nid);
+       if (index < 0)
+               return -EINVAL;
+
+       spec->pin_cvt[index] = conn_list[curr];
+
+       return 0;
+}
+
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+                              struct hdmi_eld *eld)
+{
+       int present = snd_hda_pin_sense(codec, pin_nid);
+
+       eld->monitor_present    = !!(present & AC_PINSENSE_PRESENCE);
+       eld->eld_valid          = !!(present & AC_PINSENSE_ELDV);
+
+       if (present & AC_PINSENSE_ELDV)
+               hdmi_get_show_eld(codec, pin_nid, eld);
+}
+
+static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+       struct hdmi_spec *spec = codec->spec;
+
+       if (spec->num_pins >= MAX_HDMI_PINS) {
+               snd_printk(KERN_WARNING
+                          "HDMI: no space for pin %d \n", pin_nid);
+               return -EINVAL;
+       }
+
+       hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+
+       spec->pin[spec->num_pins] = pin_nid;
+       spec->num_pins++;
+
+       /*
+        * It is assumed that converter nodes come first in the node list and
+        * hence have been registered and usable now.
+        */
+       return hdmi_read_pin_conn(codec, pin_nid);
+}
+
+static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+{
+       struct hdmi_spec *spec = codec->spec;
+
+       if (spec->num_cvts >= MAX_HDMI_CVTS) {
+               snd_printk(KERN_WARNING
+                          "HDMI: no space for converter %d \n", nid);
+               return -EINVAL;
+       }
+
+       spec->cvt[spec->num_cvts] = nid;
+       spec->num_cvts++;
+
+       return 0;
+}
+
+static int hdmi_parse_codec(struct hda_codec *codec)
+{
+       hda_nid_t nid;
+       int i, nodes;
+
+       nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+       if (!nid || nodes < 0) {
+               snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < nodes; i++, nid++) {
+               unsigned int caps;
+               unsigned int type;
+
+               caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+               type = get_wcaps_type(caps);
+
+               if (!(caps & AC_WCAP_DIGITAL))
+                       continue;
+
+               switch (type) {
+               case AC_WID_AUD_OUT:
+                       if (hdmi_add_cvt(codec, nid) < 0)
+                               return -EINVAL;
+                       break;
+               case AC_WID_PIN:
+                       caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+                       if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+                               continue;
+                       if (hdmi_add_pin(codec, nid) < 0)
+                               return -EINVAL;
+                       break;
+               }
+       }
+
+       /*
+        * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
+        * can be lost and presence sense verb will become inaccurate if the
+        * HDA link is powered off at hot plug or hw initialization time.
+        */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+             AC_PWRST_EPSS))
+               codec->bus->power_keep_link_on = 1;
+#endif
+
+       return 0;
+}
+
--- sound-2.6.orig/sound/pci/hda/patch_nvhdmi.c 2010-03-04 13:14:54.000000000 +0800
+++ sound-2.6/sound/pci/hda/patch_nvhdmi.c      2010-03-04 13:14:56.000000000 +0800
@@ -29,6 +29,8 @@
 #include "hda_codec.h"
 #include "hda_local.h"

+#include "patch_hdmi.c"
+
 /* define below to restrict the supported rates and formats */
 /* #define LIMITED_RATE_FMT_SUPPORT */

@@ -86,799 +88,16 @@ static struct hda_verb nvhdmi_basic_init
 #define NVIDIA_89_HDMI_CVTS    1
 #define NVIDIA_89_HDMI_PINS    1

-static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = {
+static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
        "NVIDIA HDMI",
 };

-struct nvhdmi_spec {
-       int num_cvts;
-       int num_pins;
-       hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1];  /* audio sources */
-       hda_nid_t pin[NVIDIA_89_HDMI_PINS+1];  /* audio sinks */
-       hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1];
-       struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS];
-       struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS];
-       struct hda_multi_out multiout;
-       unsigned int codec_type;
-};
-
-struct hdmi_audio_infoframe {
-       u8 type; /* 0x84 */
-       u8 ver;  /* 0x01 */
-       u8 len;  /* 0x0a */
-
-       u8 checksum;    /* PB0 */
-       u8 CC02_CT47;   /* CC in bits 0:2, CT in 4:7 */
-       u8 SS01_SF24;
-       u8 CXT04;
-       u8 CA;
-       u8 LFEPBL01_LSV36_DM_INH7;
-};
-
-/*
- * CEA speaker placement:
- *
- *        FLH       FCH        FRH
- *  FLW    FL  FLC   FC   FRC   FR   FRW
- *
- *                                  LFE
- *                     TC
- *
- *          RL  RLC   RC   RRC   RR
- *
- * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
- * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
- */
-enum cea_speaker_placement {
-       FL  = (1 <<  0),        /* Front Left           */
-       FC  = (1 <<  1),        /* Front Center         */
-       FR  = (1 <<  2),        /* Front Right          */
-       FLC = (1 <<  3),        /* Front Left Center    */
-       FRC = (1 <<  4),        /* Front Right Center   */
-       RL  = (1 <<  5),        /* Rear Left            */
-       RC  = (1 <<  6),        /* Rear Center          */
-       RR  = (1 <<  7),        /* Rear Right           */
-       RLC = (1 <<  8),        /* Rear Left Center     */
-       RRC = (1 <<  9),        /* Rear Right Center    */
-       LFE = (1 << 10),        /* Low Frequency Effect */
-       FLW = (1 << 11),        /* Front Left Wide      */
-       FRW = (1 << 12),        /* Front Right Wide     */
-       FLH = (1 << 13),        /* Front Left High      */
-       FCH = (1 << 14),        /* Front Center High    */
-       FRH = (1 << 15),        /* Front Right High     */
-       TC  = (1 << 16),        /* Top Center           */
-};
-
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static int eld_speaker_allocation_bits[] = {
-       [0] = FL | FR,
-       [1] = LFE,
-       [2] = FC,
-       [3] = RL | RR,
-       [4] = RC,
-       [5] = FLC | FRC,
-       [6] = RLC | RRC,
-       /* the following are not defined in ELD yet */
-       [7] = FLW | FRW,
-       [8] = FLH | FRH,
-       [9] = TC,
-       [10] = FCH,
-};
-
-struct cea_channel_speaker_allocation {
-       int ca_index;
-       int speakers[8];
-
-       /* derived values, just for convenience */
-       int channels;
-       int spk_mask;
-};
-
-/*
- * ALSA sequence is:
- *
- *       surround40   surround41   surround50   surround51   surround71
- * ch0   front left   =            =            =            =
- * ch1   front right  =            =            =            =
- * ch2   rear left    =            =            =            =
- * ch3   rear right   =            =            =            =
- * ch4                LFE          center       center       center
- * ch5                                          LFE          LFE
- * ch6                                                       side left
- * ch7                                                       side right
- *
- * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
- */
-static int hdmi_channel_mapping[0x32][8] = {
-       /* stereo */
-       [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-       /* 2.1 */
-       [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-       /* Dolby Surround */
-       [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
-       /* surround40 */
-       [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
-       /* 4ch */
-       [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
-       /* surround41 */
-       [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
-       /* surround50 */
-       [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
-       /* surround51 */
-       [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
-       /* 7.1 */
-       [0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/*                       channel:   7     6    5    4    3     2    1    0  */
-{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
-                                /* 2.1 */
-{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
-                                /* Dolby Surround */
-{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
-                                /* surround40 */
-{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
-                                /* surround41 */
-{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
-                                /* surround50 */
-{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-                                /* surround51 */
-{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-                                /* 6.1 */
-{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-                                /* surround71 */
-{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-
-{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
-{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
-};
-
-/*
- * HDA/HDMI auto parsing
- */
-
-static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
-{
-       int i;
-
-       for (i = 0; nids[i]; i++)
-               if (nids[i] == nid)
-                       return i;
-
-       snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
-       return -EINVAL;
-}
-
-static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-       struct nvhdmi_spec *spec = codec->spec;
-       hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
-       int conn_len, curr;
-       int index;
-
-       if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
-               snd_printk(KERN_WARNING
-                          "HDMI: pin %d wcaps %#x "
-                          "does not support connection list\n",
-                          pin_nid, get_wcaps(codec, pin_nid));
-               return -EINVAL;
-       }
-
-       conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
-                                          HDA_MAX_CONNECTIONS);
-       if (conn_len > 1)
-               curr = snd_hda_codec_read(codec, pin_nid, 0,
-                                         AC_VERB_GET_CONNECT_SEL, 0);
-       else
-               curr = 0;
-
-       index = hda_node_index(spec->pin, pin_nid);
-       if (index < 0)
-               return -EINVAL;
-
-       spec->pin_cvt[index] = conn_list[curr];
-
-       return 0;
-}
-
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
-                             struct hdmi_eld *eld)
-{
-       if (!snd_hdmi_get_eld(eld, codec, pin_nid))
-               snd_hdmi_show_eld(eld);
-}
-
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
-                              struct hdmi_eld *eld)
-{
-       int present = snd_hda_pin_sense(codec, pin_nid);
-
-       eld->monitor_present    = !!(present & AC_PINSENSE_PRESENCE);
-       eld->eld_valid          = !!(present & AC_PINSENSE_ELDV);
-
-       if (present & AC_PINSENSE_ELDV)
-               hdmi_get_show_eld(codec, pin_nid, eld);
-}
-
-static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-       struct nvhdmi_spec *spec = codec->spec;
-
-       if (spec->num_pins >= NVIDIA_89_HDMI_PINS) {
-               snd_printk(KERN_WARNING
-                          "HDMI: no space for pin %d \n", pin_nid);
-               return -EINVAL;
-       }
-
-       hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
-
-       spec->pin[spec->num_pins] = pin_nid;
-       spec->num_pins++;
-
-       /*
-        * It is assumed that converter nodes come first in the node list and
-        * hence have been registered and usable now.
-        */
-       return nvhdmi_read_pin_conn(codec, pin_nid);
-}
-
-static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
-{
-       struct nvhdmi_spec *spec = codec->spec;
-
-       if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) {
-               snd_printk(KERN_WARNING
-                          "HDMI: no space for converter %d \n", nid);
-               return -EINVAL;
-       }
-
-       spec->cvt[spec->num_cvts] = nid;
-       spec->num_cvts++;
-
-       return 0;
-}
-
-
-static int nvhdmi_parse_codec(struct hda_codec *codec)
-{
-       hda_nid_t nid;
-       int i, nodes;
-
-       nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
-       if (!nid || nodes < 0) {
-               snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
-               return -EINVAL;
-       }
-
-       for (i = 0; i < nodes; i++, nid++) {
-               unsigned int caps;
-               unsigned int type;
-
-               caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
-               type = get_wcaps_type(caps);
-
-               if (!(caps & AC_WCAP_DIGITAL))
-                       continue;
-
-               switch (type) {
-               case AC_WID_AUD_OUT:
-                       if (nvhdmi_add_cvt(codec, nid) < 0)
-                               return -EINVAL;
-                       break;
-               case AC_WID_PIN:
-                       caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-                       if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
-                               continue;
-                       if (nvhdmi_add_pin(codec, nid) < 0)
-                               return -EINVAL;
-                       break;
-               }
-       }
-
-       /*
-        * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
-        * can be lost and presence sense verb will become inaccurate if the
-        * HDA link is powered off at hot plug or hw initialization time.
-        */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-       if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
-             AC_PWRST_EPSS))
-               codec->bus->power_keep_link_on = 1;
-#endif
-
-       return 0;
-}
-
-/*
- * HDMI routines
- */
-
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-                               int *packet_index, int *byte_index)
-{
-       int val;
-
-       val = snd_hda_codec_read(codec, pin_nid, 0,
-                                AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
-       *packet_index = val >> 5;
-       *byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-                               int packet_index, int byte_index)
-{
-       int val;
-
-       val = (packet_index << 5) | (byte_index & 0x1f);
-
-       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
-                               unsigned char val)
-{
-       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-       /* Unmute */
-       if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
-               snd_hda_codec_write(codec, pin_nid, 0,
-                               AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-       /* Enable pin out */
-       snd_hda_codec_write(codec, pin_nid, 0,
-                           AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
-                                      hda_nid_t pin_nid)
-{
-       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-                                               AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
-                                     hda_nid_t pin_nid)
-{
-       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-                                               AC_DIPXMIT_DISABLE);
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
-{
-       return 1 + snd_hda_codec_read(codec, nid, 0,
-                                       AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec,
-                                  hda_nid_t nid, int chs)
-{
-       if (chs != hdmi_get_channel_count(codec, nid))
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec,
-                                      hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-       int i;
-       int slot;
-
-       for (i = 0; i < 8; i++) {
-               slot = snd_hda_codec_read(codec, pin_nid, 0,
-                                               AC_VERB_GET_HDMI_CHAN_SLOT, i);
-               printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
-                                               slot >> 4, slot & 0xf);
-       }
-#endif
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-       int i;
-       int size;
-
-       size = snd_hdmi_get_eld_size(codec, pin_nid);
-       printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
-       for (i = 0; i < 8; i++) {
-               size = snd_hda_codec_read(codec, pin_nid, 0,
-                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
-               printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
-       }
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
-       int i, j;
-       int size;
-       int pi, bi;
-       for (i = 0; i < 8; i++) {
-               size = snd_hda_codec_read(codec, pin_nid, 0,
-                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
-               if (size == 0)
-                       continue;
-
-               hdmi_set_dip_index(codec, pin_nid, i, 0x0);
-               for (j = 1; j < 1000; j++) {
-                       hdmi_write_dip_byte(codec, pin_nid, 0x0);
-                       hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
-                       if (pi != i)
-                               snd_printd(KERN_INFO "dip index %d: %d != %d\n",
-                                               bi, pi, i);
-                       if (bi == 0) /* byte index wrapped around */
-                               break;
-               }
-               snd_printd(KERN_INFO
-                       "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
-                       i, size, j);
-       }
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
-{
-       ai->checksum = 0;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
-                                     hda_nid_t pin_nid,
-                                     struct hdmi_audio_infoframe *ai)
-{
-       u8 *bytes = (u8 *)ai;
-       int i;
-
-       hdmi_debug_dip_size(codec, pin_nid);
-       hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
-       hdmi_checksum_audio_infoframe(ai);
-
-       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       for (i = 0; i < sizeof(*ai); i++)
-               hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
-       int i, j;
-       struct cea_channel_speaker_allocation *p;
-
-       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-               p = channel_allocations + i;
-               p->channels = 0;
-               p->spk_mask = 0;
-               for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-                       if (p->speakers[j]) {
-                               p->channels++;
-                               p->spk_mask |= p->speakers[j];
-                       }
-       }
-}
-
-/*
- * The transformation takes two steps:
- *
- *     eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- *           spk_mask => (channel_allocations[])         => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
-                                        struct hdmi_audio_infoframe *ai)
-{
-       struct nvhdmi_spec *spec = codec->spec;
-       struct hdmi_eld *eld;
-       int i;
-       int spk_mask = 0;
-       int channels = 1 + (ai->CC02_CT47 & 0x7);
-       char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
-       /*
-        * CA defaults to 0 for basic stereo audio
-        */
-       if (channels <= 2)
-               return 0;
-
-       i = hda_node_index(spec->pin_cvt, nid);
-       if (i < 0)
-               return 0;
-       eld = &spec->sink_eld[i];
-
-       /*
-        * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-        * in console or for audio devices. Assume the highest speakers
-        * configuration, to _not_ prohibit multi-channel audio playback.
-        */
-       if (!eld->spk_alloc)
-               eld->spk_alloc = 0xffff;
-
-       /*
-        * expand ELD's speaker allocation mask
-        *
-        * ELD tells the speaker mask in a compact(paired) form,
-        * expand ELD's notions to match the ones used by Audio InfoFrame.
-        */
-       for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-               if (eld->spk_alloc & (1 << i))
-                       spk_mask |= eld_speaker_allocation_bits[i];
-       }
-
-       /* search for the first working match in the CA table */
-       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-               if (channels == channel_allocations[i].channels &&
-                   (spk_mask & channel_allocations[i].spk_mask) ==
-                               channel_allocations[i].spk_mask) {
-                       ai->CA = channel_allocations[i].ca_index;
-                       break;
-               }
-       }
-
-       snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
-       snd_printdd(KERN_INFO
-                       "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
-                       ai->CA, channels, buf);
-
-       return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
-                                      hda_nid_t pin_nid,
-                                      struct hdmi_audio_infoframe *ai)
-{
-       int i;
-       int ca = ai->CA;
-       int err;
-
-       if (hdmi_channel_mapping[ca][1] == 0) {
-               for (i = 0; i < channel_allocations[ca].channels; i++)
-                       hdmi_channel_mapping[ca][i] = i | (i << 4);
-               for (; i < 8; i++)
-                       hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
-       }
-
-       for (i = 0; i < 8; i++) {
-               err = snd_hda_codec_write(codec, pin_nid, 0,
-                                         AC_VERB_SET_HDMI_CHAN_SLOT,
-                                         hdmi_channel_mapping[ca][i]);
-               if (err) {
-                       snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
-                       break;
-               }
-       }
-
-       hdmi_debug_channel_mapping(codec, pin_nid);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
-                                   struct hdmi_audio_infoframe *ai)
-{
-       u8 *bytes = (u8 *)ai;
-       u8 val;
-       int i;
-
-       if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
-                                                           != AC_DIPXMIT_BEST)
-               return false;
-
-       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       for (i = 0; i < sizeof(*ai); i++) {
-               val = snd_hda_codec_read(codec, pin_nid, 0,
-                                        AC_VERB_GET_HDMI_DIP_DATA, 0);
-               if (val != bytes[i])
-                       return false;
-       }
-
-       return true;
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
-                                       struct snd_pcm_substream *substream)
-{
-       struct nvhdmi_spec *spec = codec->spec;
-       hda_nid_t pin_nid;
-       int i;
-       struct hdmi_audio_infoframe ai = {
-               .type           = 0x84,
-               .ver            = 0x01,
-               .len            = 0x0a,
-               .CC02_CT47      = substream->runtime->channels - 1,
-       };
-
-       hdmi_setup_channel_allocation(codec, nid, &ai);
-
-       for (i = 0; i < spec->num_pins; i++) {
-               if (spec->pin_cvt[i] != nid)
-                       continue;
-               if (!spec->sink_eld[i].monitor_present)
-                       continue;
-
-               pin_nid = spec->pin[i];
-               if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
-                       hdmi_setup_channel_mapping(codec, pin_nid, &ai);
-                       hdmi_stop_infoframe_trans(codec, pin_nid);
-                       hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
-                       hdmi_start_infoframe_trans(codec, pin_nid);
-               }
-       }
-}
-
-/*
- * Unsolicited events
- */
-
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-       struct nvhdmi_spec *spec = codec->spec;
-       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int pind = !!(res & AC_UNSOL_RES_PD);
-       int eldv = !!(res & AC_UNSOL_RES_ELDV);
-       int index;
-
-       printk(KERN_INFO
-               "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-               tag, pind, eldv);
-
-       index = hda_node_index(spec->pin, tag);
-       if (index < 0)
-               return;
-
-       spec->sink_eld[index].monitor_present = pind;
-       spec->sink_eld[index].eld_valid = eldv;
-
-       if (eldv) {
-               spec->sink_eld[index].monitor_present = 1;
-               hdmi_get_show_eld(codec, spec->pin[index],
-                                &spec->sink_eld[index]);
-               /* TODO: do real things about ELD */
-       }
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-       int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
-       int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
-       printk(KERN_INFO
-               "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
-               tag,
-               subtag,
-               cp_state,
-               cp_ready);
-
-       /* TODO */
-       if (cp_state)
-               ;
-       if (cp_ready)
-               ;
-}
-
-static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-       struct nvhdmi_spec *spec = codec->spec;
-       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
-       if (hda_node_index(spec->pin, tag) < 0) {
-               snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
-               return;
-       }
-
-       if (subtag == 0)
-               hdmi_intrinsic_event(codec, res);
-       else
-               hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-                             u32 stream_tag, int format)
-{
-       int tag;
-       int fmt;
-
-       tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
-       fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
-       snd_printdd("hdmi_setup_stream: "
-                   "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
-                   nid,
-                   tag == stream_tag ? "" : "new-",
-                   stream_tag,
-                   fmt == format ? "" : "new-",
-                   format);
-
-       if (tag != stream_tag)
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_CHANNEL_STREAMID,
-                                   stream_tag << 4);
-       if (fmt != format)
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_STREAM_FORMAT, format);
-}
-
 /*
  * Controls
  */
 static int nvhdmi_build_controls(struct hda_codec *codec)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        int err;
        int i;

@@ -902,7 +121,7 @@ static int nvhdmi_build_controls(struct

 static int nvhdmi_init(struct hda_codec *codec)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        int i;
        if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
        || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
@@ -920,7 +139,7 @@ static int nvhdmi_init(struct hda_codec

 static void nvhdmi_free(struct hda_codec *codec)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        int i;

        if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
@@ -939,7 +158,7 @@ static int nvhdmi_dig_playback_pcm_open(
                                        struct hda_codec *codec,
                                        struct snd_pcm_substream *substream)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 }

@@ -947,7 +166,7 @@ static int nvhdmi_dig_playback_pcm_close
                                        struct hda_codec *codec,
                                        struct snd_pcm_substream *substream)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        int i;

        snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
@@ -968,7 +187,7 @@ static int nvhdmi_dig_playback_pcm_close
                                        struct hda_codec *codec,
                                        struct snd_pcm_substream *substream)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }

@@ -1121,7 +340,7 @@ static int nvhdmi_dig_playback_pcm_prepa
                                        unsigned int format,
                                        struct snd_pcm_substream *substream)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
                                        format, substream);
 }
@@ -1170,7 +389,7 @@ static struct hda_pcm_stream nvhdmi_pcm_

 static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        struct hda_pcm *info = spec->pcm_rec;
        int i;

@@ -1196,7 +415,7 @@ static int nvhdmi_build_pcms_8ch_89(stru

 static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        struct hda_pcm *info = spec->pcm_rec;

        codec->num_pcms = 1;
@@ -1212,7 +431,7 @@ static int nvhdmi_build_pcms_8ch_7x(stru

 static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 {
-       struct nvhdmi_spec *spec = codec->spec;
+       struct hdmi_spec *spec = codec->spec;
        struct hda_pcm *info = spec->pcm_rec;

        codec->num_pcms = 1;
@@ -1231,7 +450,7 @@ static struct hda_codec_ops nvhdmi_patch
        .build_pcms = nvhdmi_build_pcms_8ch_89,
        .init = nvhdmi_init,
        .free = nvhdmi_free,
-       .unsol_event = nvhdmi_unsol_event,
+       .unsol_event = hdmi_unsol_event,
 };

 static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
@@ -1250,7 +469,7 @@ static struct hda_codec_ops nvhdmi_patch

 static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
 {
-       struct nvhdmi_spec *spec;
+       struct hdmi_spec *spec;
        int i;

        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -1260,7 +479,7 @@ static int patch_nvhdmi_8ch_89(struct hd
        codec->spec = spec;
        spec->codec_type = HDA_CODEC_NVIDIA_MCP89;

-       if (nvhdmi_parse_codec(codec) < 0) {
+       if (hdmi_parse_codec(codec) < 0) {
                codec->spec = NULL;
                kfree(spec);
                return -EINVAL;
@@ -1277,7 +496,7 @@ static int patch_nvhdmi_8ch_89(struct hd

 static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
 {
-       struct nvhdmi_spec *spec;
+       struct hdmi_spec *spec;

        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
@@ -1297,7 +516,7 @@ static int patch_nvhdmi_8ch_7x(struct hd

 static int patch_nvhdmi_2ch(struct hda_codec *codec)
 {
-       struct nvhdmi_spec *spec;
+       struct hdmi_spec *spec;

        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel]  [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04  5:52         ` Wei Ni
@ 2010-03-04  6:09           ` Wu Fengguang
  0 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-04  6:09 UTC (permalink / raw)
  To: Wei Ni
  Cc: Takashi Iwai, 'akpm', 'alsa-devel',
	'linux-kernel', 'Pavel Hofman'

Oh.. I expected these to be standard for HDMI.

On Thu, Mar 04, 2010 at 01:52:40PM +0800, Wei Ni wrote:
> Hi, Wu Fengguang
> These changes only for Nvidia controller.
> 1. for hdmi_channel_mapping[0x2[8]
> Because our controller's channel_mapping has some different with
> patch_intelhdmi.c. If don't change, the 8ch has some wrong.

Maybe I got it wrong. Do you have Intel hardware (G45 or IbexPeak) at
hand?  I cannot test it for now.

> 2. for remove "u8 reserved[5]"
> Because our controller doesn't support it yet.

Have you tried reduce the number to 4 or 3?

> 3. for hdmi_checksum_audio_infoframe()
> Because our controller only support the checkum=0 now.

In fact I'm not absolutely sure if the checksum field
- should be leave 0 and filled by hardware
- or should not exist at all and handled transparently by hardware

Thanks,
Fengguang

> 
> -----Original Message-----
> From: Wu Fengguang [mailto:fengguang.wu@intel.com]
> Sent: Thursday, March 04, 2010 1:44 PM
> To: Takashi Iwai
> Cc: Wei Ni; 'akpm'; 'alsa-devel'; 'linux-kernel'; 'Pavel Hofman'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> On Thu, Mar 04, 2010 at 10:18:39AM +0800, Wu Fengguang wrote:
> > On Wed, Mar 03, 2010 at 02:46:25PM +0800, Takashi Iwai wrote:
> > > At Tue, 2 Mar 2010 13:43:07 +0800,
> > > Wu Fengguang wrote:
> > > >
> > > > On Mon, Mar 01, 2010 at 07:27:53PM +0800, Wei Ni wrote:
> > > > > Hi, Takashi
> > > > > I developed the hdmi audio driver for new chipset MCP89 and GT21x.
> > > > > The new HAD controller and codec support standard HDMI operation.
> > > > >
> > > > > I attached the patch file, please check it.
> > > >
> > > > Wei Ni,
> > > >
> > > > Can we avoid the big copy&paste and do more code reuse?
> > > > This benefits all of us in long term.
> > >
> > > The plan is to merge all current patch_*hdmi.c into one.
> > > But this can be done later once after we get the working driver
> > > for the new Nvidia codecs.
> > >
> > > The new Nvidia HDMI codec is a bit tricky (which has 4 separate
> > > codec slots), so I'd like to get it working first.
> >
> > Here is the patch to merge common code in a simple way.
> > This is compile tested only, need double check.
> >
> > What puzzled me is that Wei Ni reused the same dynamic parsing code,
> > even though the Intel/Nvidia codecs have vastly different pin/cvt
> > layouts..
> 
> WeiNi, some more questions.
> 
> - why change hdmi_channel_mapping[0x32][8] from
>         [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
>   to
>         [0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
> 
> - why remove "u8 reserved[5]; /* PB6 - PB10 */" from struct
>   hdmi_audio_infoframe?
> 
> - why change
>         static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
>         {
>                 u8 *bytes = (u8 *)ai;
>                 u8 sum = 0;
>                 int i;
> 
>                 ai->checksum = 0;
> 
>                 for (i = 0; i < sizeof(*ai); i++)
>                         sum += bytes[i];
> 
>                 ai->checksum = - sum;
>         }
>   to
>         static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
>         {
>                 ai->checksum = 0;
>         }
> 
> 
> Those are very dirty changes. Either the original code is correct, or
> they are wrong and should be changed as well. If you submit code like
> this now, we'll have to resolve conflicts and do pointless retests at
> the perceived future merge time.
> 
> Would you stop hacking things around like that?
> 
> I'd recommend to base your future work on top of the following patch.
> It's based on your previous patches.
> 
> Note that I reverted the above 3 changes. If they are good changes,
> you can still submit standalone patches, and let's discuss and test
> them case by case.
> 
> Thanks,
> Fengguang
> ---
> hdmi - create patch_hdmi.c for common hdmi code
> 
> For now the patch_hdmi.c file is simply included by patch_intelhdmi.c
> and patch_nvhdmi.c, and does not represent a real codec.
> 
> CC: Wei Ni <wni@nvidia.com>
> Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
> ---
>  sound/pci/hda/patch_hdmi.c      |  828 ++++++++++++++++++++++++++++++
>  sound/pci/hda/patch_intelhdmi.c |  822 -----------------------------
>  sound/pci/hda/patch_nvhdmi.c    |  817 -----------------------------
>  3 files changed, 856 insertions(+), 1611 deletions(-)
> 
> --- sound-2.6.orig/sound/pci/hda/patch_intelhdmi.c      2010-03-04 13:14:54.000000000 +0800
> +++ sound-2.6/sound/pci/hda/patch_intelhdmi.c   2010-03-04 13:14:56.000000000 +0800
> @@ -33,822 +33,20 @@
>  #include "hda_codec.h"
>  #include "hda_local.h"
> 
> -/*
> - * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
> - * could support two independent pipes, each of them can be connected to one or
> - * more ports (DVI, HDMI or DisplayPort).
> - *
> - * The HDA correspondence of pipes/ports are converter/pin nodes.
> - */
> +#include "patch_hdmi.c"
> +
>  #define INTEL_HDMI_CVTS        2
>  #define INTEL_HDMI_PINS        3
> 
> -static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = {
> +static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
>         "INTEL HDMI 0",
>         "INTEL HDMI 1",
>  };
> 
> -struct intel_hdmi_spec {
> -       int num_cvts;
> -       int num_pins;
> -       hda_nid_t cvt[INTEL_HDMI_CVTS+1];  /* audio sources */
> -       hda_nid_t pin[INTEL_HDMI_PINS+1];  /* audio sinks */
> -
> -       /*
> -        * source connection for each pin
> -        */
> -       hda_nid_t pin_cvt[INTEL_HDMI_PINS+1];
> -
> -       /*
> -        * HDMI sink attached to each pin
> -        */
> -       struct hdmi_eld sink_eld[INTEL_HDMI_PINS];
> -
> -       /*
> -        * export one pcm per pipe
> -        */
> -       struct hda_pcm  pcm_rec[INTEL_HDMI_CVTS];
> -};
> -
> -struct hdmi_audio_infoframe {
> -       u8 type; /* 0x84 */
> -       u8 ver;  /* 0x01 */
> -       u8 len;  /* 0x0a */
> -
> -       u8 checksum;    /* PB0 */
> -       u8 CC02_CT47;   /* CC in bits 0:2, CT in 4:7 */
> -       u8 SS01_SF24;
> -       u8 CXT04;
> -       u8 CA;
> -       u8 LFEPBL01_LSV36_DM_INH7;
> -       u8 reserved[5]; /* PB6 - PB10 */
> -};
> -
> -/*
> - * CEA speaker placement:
> - *
> - *        FLH       FCH        FRH
> - *  FLW    FL  FLC   FC   FRC   FR   FRW
> - *
> - *                                  LFE
> - *                     TC
> - *
> - *          RL  RLC   RC   RRC   RR
> - *
> - * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
> - * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
> - */
> -enum cea_speaker_placement {
> -       FL  = (1 <<  0),        /* Front Left           */
> -       FC  = (1 <<  1),        /* Front Center         */
> -       FR  = (1 <<  2),        /* Front Right          */
> -       FLC = (1 <<  3),        /* Front Left Center    */
> -       FRC = (1 <<  4),        /* Front Right Center   */
> -       RL  = (1 <<  5),        /* Rear Left            */
> -       RC  = (1 <<  6),        /* Rear Center          */
> -       RR  = (1 <<  7),        /* Rear Right           */
> -       RLC = (1 <<  8),        /* Rear Left Center     */
> -       RRC = (1 <<  9),        /* Rear Right Center    */
> -       LFE = (1 << 10),        /* Low Frequency Effect */
> -       FLW = (1 << 11),        /* Front Left Wide      */
> -       FRW = (1 << 12),        /* Front Right Wide     */
> -       FLH = (1 << 13),        /* Front Left High      */
> -       FCH = (1 << 14),        /* Front Center High    */
> -       FRH = (1 << 15),        /* Front Right High     */
> -       TC  = (1 << 16),        /* Top Center           */
> -};
> -
> -/*
> - * ELD SA bits in the CEA Speaker Allocation data block
> - */
> -static int eld_speaker_allocation_bits[] = {
> -       [0] = FL | FR,
> -       [1] = LFE,
> -       [2] = FC,
> -       [3] = RL | RR,
> -       [4] = RC,
> -       [5] = FLC | FRC,
> -       [6] = RLC | RRC,
> -       /* the following are not defined in ELD yet */
> -       [7] = FLW | FRW,
> -       [8] = FLH | FRH,
> -       [9] = TC,
> -       [10] = FCH,
> -};
> -
> -struct cea_channel_speaker_allocation {
> -       int ca_index;
> -       int speakers[8];
> -
> -       /* derived values, just for convenience */
> -       int channels;
> -       int spk_mask;
> -};
> -
> -/*
> - * ALSA sequence is:
> - *
> - *       surround40   surround41   surround50   surround51   surround71
> - * ch0   front left   =            =            =            =
> - * ch1   front right  =            =            =            =
> - * ch2   rear left    =            =            =            =
> - * ch3   rear right   =            =            =            =
> - * ch4                LFE          center       center       center
> - * ch5                                          LFE          LFE
> - * ch6                                                       side left
> - * ch7                                                       side right
> - *
> - * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
> - */
> -static int hdmi_channel_mapping[0x32][8] = {
> -       /* stereo */
> -       [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
> -       /* 2.1 */
> -       [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
> -       /* Dolby Surround */
> -       [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
> -       /* surround40 */
> -       [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
> -       /* 4ch */
> -       [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
> -       /* surround41 */
> -       [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
> -       /* surround50 */
> -       [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
> -       /* surround51 */
> -       [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
> -       /* 7.1 */
> -       [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
> -};
> -
> -/*
> - * This is an ordered list!
> - *
> - * The preceding ones have better chances to be selected by
> - * hdmi_setup_channel_allocation().
> - */
> -static struct cea_channel_speaker_allocation channel_allocations[] = {
> -/*                       channel:   7     6    5    4    3     2    1    0  */
> -{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
> -                                /* 2.1 */
> -{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
> -                                /* Dolby Surround */
> -{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
> -                                /* surround40 */
> -{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
> -                                /* surround41 */
> -{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
> -                                /* surround50 */
> -{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
> -                                /* surround51 */
> -{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -                                /* 6.1 */
> -{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -                                /* surround71 */
> -{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -
> -{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -};
> -
> -/*
> - * HDA/HDMI auto parsing
> - */
> -
> -static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
> -{
> -       int i;
> -
> -       for (i = 0; nids[i]; i++)
> -               if (nids[i] == nid)
> -                       return i;
> -
> -       snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
> -       return -EINVAL;
> -}
> -
> -static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -       struct intel_hdmi_spec *spec = codec->spec;
> -       hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
> -       int conn_len, curr;
> -       int index;
> -
> -       if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
> -               snd_printk(KERN_WARNING
> -                          "HDMI: pin %d wcaps %#x "
> -                          "does not support connection list\n",
> -                          pin_nid, get_wcaps(codec, pin_nid));
> -               return -EINVAL;
> -       }
> -
> -       conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
> -                                          HDA_MAX_CONNECTIONS);
> -       if (conn_len > 1)
> -               curr = snd_hda_codec_read(codec, pin_nid, 0,
> -                                         AC_VERB_GET_CONNECT_SEL, 0);
> -       else
> -               curr = 0;
> -
> -       index = hda_node_index(spec->pin, pin_nid);
> -       if (index < 0)
> -               return -EINVAL;
> -
> -       spec->pin_cvt[index] = conn_list[curr];
> -
> -       return 0;
> -}
> -
> -static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
> -                             struct hdmi_eld *eld)
> -{
> -       if (!snd_hdmi_get_eld(eld, codec, pin_nid))
> -               snd_hdmi_show_eld(eld);
> -}
> -
> -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
> -                              struct hdmi_eld *eld)
> -{
> -       int present = snd_hda_pin_sense(codec, pin_nid);
> -
> -       eld->monitor_present    = !!(present & AC_PINSENSE_PRESENCE);
> -       eld->eld_valid          = !!(present & AC_PINSENSE_ELDV);
> -
> -       if (present & AC_PINSENSE_ELDV)
> -               hdmi_get_show_eld(codec, pin_nid, eld);
> -}
> -
> -static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -       struct intel_hdmi_spec *spec = codec->spec;
> -
> -       if (spec->num_pins >= INTEL_HDMI_PINS) {
> -               snd_printk(KERN_WARNING
> -                          "HDMI: no space for pin %d \n", pin_nid);
> -               return -EINVAL;
> -       }
> -
> -       hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
> -
> -       spec->pin[spec->num_pins] = pin_nid;
> -       spec->num_pins++;
> -
> -       /*
> -        * It is assumed that converter nodes come first in the node list and
> -        * hence have been registered and usable now.
> -        */
> -       return intel_hdmi_read_pin_conn(codec, pin_nid);
> -}
> -
> -static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
> -{
> -       struct intel_hdmi_spec *spec = codec->spec;
> -
> -       if (spec->num_cvts >= INTEL_HDMI_CVTS) {
> -               snd_printk(KERN_WARNING
> -                          "HDMI: no space for converter %d \n", nid);
> -               return -EINVAL;
> -       }
> -
> -       spec->cvt[spec->num_cvts] = nid;
> -       spec->num_cvts++;
> -
> -       return 0;
> -}
> -
> -static int intel_hdmi_parse_codec(struct hda_codec *codec)
> -{
> -       hda_nid_t nid;
> -       int i, nodes;
> -
> -       nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
> -       if (!nid || nodes < 0) {
> -               snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
> -               return -EINVAL;
> -       }
> -
> -       for (i = 0; i < nodes; i++, nid++) {
> -               unsigned int caps;
> -               unsigned int type;
> -
> -               caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
> -               type = get_wcaps_type(caps);
> -
> -               if (!(caps & AC_WCAP_DIGITAL))
> -                       continue;
> -
> -               switch (type) {
> -               case AC_WID_AUD_OUT:
> -                       if (intel_hdmi_add_cvt(codec, nid) < 0)
> -                               return -EINVAL;
> -                       break;
> -               case AC_WID_PIN:
> -                       caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
> -                       if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
> -                               continue;
> -                       if (intel_hdmi_add_pin(codec, nid) < 0)
> -                               return -EINVAL;
> -                       break;
> -               }
> -       }
> -
> -       /*
> -        * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
> -        * can be lost and presence sense verb will become inaccurate if the
> -        * HDA link is powered off at hot plug or hw initialization time.
> -        */
> -#ifdef CONFIG_SND_HDA_POWER_SAVE
> -       if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
> -             AC_PWRST_EPSS))
> -               codec->bus->power_keep_link_on = 1;
> -#endif
> -
> -       return 0;
> -}
> -
>  /*
>   * HDMI routines
>   */
> 
> -#ifdef BE_PARANOID
> -static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
> -                               int *packet_index, int *byte_index)
> -{
> -       int val;
> -
> -       val = snd_hda_codec_read(codec, pin_nid, 0,
> -                                AC_VERB_GET_HDMI_DIP_INDEX, 0);
> -
> -       *packet_index = val >> 5;
> -       *byte_index = val & 0x1f;
> -}
> -#endif
> -
> -static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
> -                               int packet_index, int byte_index)
> -{
> -       int val;
> -
> -       val = (packet_index << 5) | (byte_index & 0x1f);
> -
> -       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
> -}
> -
> -static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
> -                               unsigned char val)
> -{
> -       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
> -}
> -
> -static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -       /* Unmute */
> -       if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
> -               snd_hda_codec_write(codec, pin_nid, 0,
> -                               AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
> -       /* Enable pin out */
> -       snd_hda_codec_write(codec, pin_nid, 0,
> -                           AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
> -}
> -
> -/*
> - * Enable Audio InfoFrame Transmission
> - */
> -static void hdmi_start_infoframe_trans(struct hda_codec *codec,
> -                                      hda_nid_t pin_nid)
> -{
> -       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> -       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
> -                                               AC_DIPXMIT_BEST);
> -}
> -
> -/*
> - * Disable Audio InfoFrame Transmission
> - */
> -static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
> -                                     hda_nid_t pin_nid)
> -{
> -       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> -       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
> -                                               AC_DIPXMIT_DISABLE);
> -}
> -
> -static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
> -{
> -       return 1 + snd_hda_codec_read(codec, nid, 0,
> -                                       AC_VERB_GET_CVT_CHAN_COUNT, 0);
> -}
> -
> -static void hdmi_set_channel_count(struct hda_codec *codec,
> -                                  hda_nid_t nid, int chs)
> -{
> -       if (chs != hdmi_get_channel_count(codec, nid))
> -               snd_hda_codec_write(codec, nid, 0,
> -                                   AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
> -}
> -
> -static void hdmi_debug_channel_mapping(struct hda_codec *codec,
> -                                      hda_nid_t pin_nid)
> -{
> -#ifdef CONFIG_SND_DEBUG_VERBOSE
> -       int i;
> -       int slot;
> -
> -       for (i = 0; i < 8; i++) {
> -               slot = snd_hda_codec_read(codec, pin_nid, 0,
> -                                               AC_VERB_GET_HDMI_CHAN_SLOT, i);
> -               printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
> -                                               slot >> 4, slot & 0xf);
> -       }
> -#endif
> -}
> -
> -
> -/*
> - * Audio InfoFrame routines
> - */
> -
> -static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -#ifdef CONFIG_SND_DEBUG_VERBOSE
> -       int i;
> -       int size;
> -
> -       size = snd_hdmi_get_eld_size(codec, pin_nid);
> -       printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
> -
> -       for (i = 0; i < 8; i++) {
> -               size = snd_hda_codec_read(codec, pin_nid, 0,
> -                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
> -               printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
> -       }
> -#endif
> -}
> -
> -static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -#ifdef BE_PARANOID
> -       int i, j;
> -       int size;
> -       int pi, bi;
> -       for (i = 0; i < 8; i++) {
> -               size = snd_hda_codec_read(codec, pin_nid, 0,
> -                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
> -               if (size == 0)
> -                       continue;
> -
> -               hdmi_set_dip_index(codec, pin_nid, i, 0x0);
> -               for (j = 1; j < 1000; j++) {
> -                       hdmi_write_dip_byte(codec, pin_nid, 0x0);
> -                       hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
> -                       if (pi != i)
> -                               snd_printd(KERN_INFO "dip index %d: %d != %d\n",
> -                                               bi, pi, i);
> -                       if (bi == 0) /* byte index wrapped around */
> -                               break;
> -               }
> -               snd_printd(KERN_INFO
> -                       "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
> -                       i, size, j);
> -       }
> -#endif
> -}
> -
> -static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
> -{
> -       u8 *bytes = (u8 *)ai;
> -       u8 sum = 0;
> -       int i;
> -
> -       ai->checksum = 0;
> -
> -       for (i = 0; i < sizeof(*ai); i++)
> -               sum += bytes[i];
> -
> -       ai->checksum = - sum;
> -}
> -
> -static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
> -                                     hda_nid_t pin_nid,
> -                                     struct hdmi_audio_infoframe *ai)
> -{
> -       u8 *bytes = (u8 *)ai;
> -       int i;
> -
> -       hdmi_debug_dip_size(codec, pin_nid);
> -       hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
> -
> -       hdmi_checksum_audio_infoframe(ai);
> -
> -       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> -       for (i = 0; i < sizeof(*ai); i++)
> -               hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
> -}
> -
> -/*
> - * Compute derived values in channel_allocations[].
> - */
> -static void init_channel_allocations(void)
> -{
> -       int i, j;
> -       struct cea_channel_speaker_allocation *p;
> -
> -       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
> -               p = channel_allocations + i;
> -               p->channels = 0;
> -               p->spk_mask = 0;
> -               for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
> -                       if (p->speakers[j]) {
> -                               p->channels++;
> -                               p->spk_mask |= p->speakers[j];
> -                       }
> -       }
> -}
> -
> -/*
> - * The transformation takes two steps:
> - *
> - *     eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
> - *           spk_mask => (channel_allocations[])         => ai->CA
> - *
> - * TODO: it could select the wrong CA from multiple candidates.
> -*/
> -static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
> -                                        struct hdmi_audio_infoframe *ai)
> -{
> -       struct intel_hdmi_spec *spec = codec->spec;
> -       struct hdmi_eld *eld;
> -       int i;
> -       int spk_mask = 0;
> -       int channels = 1 + (ai->CC02_CT47 & 0x7);
> -       char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
> -
> -       /*
> -        * CA defaults to 0 for basic stereo audio
> -        */
> -       if (channels <= 2)
> -               return 0;
> -
> -       i = hda_node_index(spec->pin_cvt, nid);
> -       if (i < 0)
> -               return 0;
> -       eld = &spec->sink_eld[i];
> -
> -       /*
> -        * HDMI sink's ELD info cannot always be retrieved for now, e.g.
> -        * in console or for audio devices. Assume the highest speakers
> -        * configuration, to _not_ prohibit multi-channel audio playback.
> -        */
> -       if (!eld->spk_alloc)
> -               eld->spk_alloc = 0xffff;
> -
> -       /*
> -        * expand ELD's speaker allocation mask
> -        *
> -        * ELD tells the speaker mask in a compact(paired) form,
> -        * expand ELD's notions to match the ones used by Audio InfoFrame.
> -        */
> -       for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
> -               if (eld->spk_alloc & (1 << i))
> -                       spk_mask |= eld_speaker_allocation_bits[i];
> -       }
> -
> -       /* search for the first working match in the CA table */
> -       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
> -               if (channels == channel_allocations[i].channels &&
> -                   (spk_mask & channel_allocations[i].spk_mask) ==
> -                               channel_allocations[i].spk_mask) {
> -                       ai->CA = channel_allocations[i].ca_index;
> -                       break;
> -               }
> -       }
> -
> -       snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
> -       snd_printdd(KERN_INFO
> -                       "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
> -                       ai->CA, channels, buf);
> -
> -       return ai->CA;
> -}
> -
> -static void hdmi_setup_channel_mapping(struct hda_codec *codec,
> -                                      hda_nid_t pin_nid,
> -                                      struct hdmi_audio_infoframe *ai)
> -{
> -       int i;
> -       int ca = ai->CA;
> -       int err;
> -
> -       if (hdmi_channel_mapping[ca][1] == 0) {
> -               for (i = 0; i < channel_allocations[ca].channels; i++)
> -                       hdmi_channel_mapping[ca][i] = i | (i << 4);
> -               for (; i < 8; i++)
> -                       hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
> -       }
> -
> -       for (i = 0; i < 8; i++) {
> -               err = snd_hda_codec_write(codec, pin_nid, 0,
> -                                         AC_VERB_SET_HDMI_CHAN_SLOT,
> -                                         hdmi_channel_mapping[ca][i]);
> -               if (err) {
> -                       snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
> -                       break;
> -               }
> -       }
> -
> -       hdmi_debug_channel_mapping(codec, pin_nid);
> -}
> -
> -static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
> -                                   struct hdmi_audio_infoframe *ai)
> -{
> -       u8 *bytes = (u8 *)ai;
> -       u8 val;
> -       int i;
> -
> -       if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
> -                                                           != AC_DIPXMIT_BEST)
> -               return false;
> -
> -       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> -       for (i = 0; i < sizeof(*ai); i++) {
> -               val = snd_hda_codec_read(codec, pin_nid, 0,
> -                                        AC_VERB_GET_HDMI_DIP_DATA, 0);
> -               if (val != bytes[i])
> -                       return false;
> -       }
> -
> -       return true;
> -}
> -
> -static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
> -                                       struct snd_pcm_substream *substream)
> -{
> -       struct intel_hdmi_spec *spec = codec->spec;
> -       hda_nid_t pin_nid;
> -       int i;
> -       struct hdmi_audio_infoframe ai = {
> -               .type           = 0x84,
> -               .ver            = 0x01,
> -               .len            = 0x0a,
> -               .CC02_CT47      = substream->runtime->channels - 1,
> -       };
> -
> -       hdmi_setup_channel_allocation(codec, nid, &ai);
> -
> -       for (i = 0; i < spec->num_pins; i++) {
> -               if (spec->pin_cvt[i] != nid)
> -                       continue;
> -               if (!spec->sink_eld[i].monitor_present)
> -                       continue;
> -
> -               pin_nid = spec->pin[i];
> -               if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
> -                       hdmi_setup_channel_mapping(codec, pin_nid, &ai);
> -                       hdmi_stop_infoframe_trans(codec, pin_nid);
> -                       hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
> -                       hdmi_start_infoframe_trans(codec, pin_nid);
> -               }
> -       }
> -}
> -
> -
> -/*
> - * Unsolicited events
> - */
> -
> -static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
> -{
> -       struct intel_hdmi_spec *spec = codec->spec;
> -       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
> -       int pind = !!(res & AC_UNSOL_RES_PD);
> -       int eldv = !!(res & AC_UNSOL_RES_ELDV);
> -       int index;
> -
> -       printk(KERN_INFO
> -               "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
> -               tag, pind, eldv);
> -
> -       index = hda_node_index(spec->pin, tag);
> -       if (index < 0)
> -               return;
> -
> -       spec->sink_eld[index].monitor_present = pind;
> -       spec->sink_eld[index].eld_valid = eldv;
> -
> -       if (pind && eldv) {
> -               hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]);
> -               /* TODO: do real things about ELD */
> -       }
> -}
> -
> -static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
> -{
> -       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
> -       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
> -       int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
> -       int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
> -
> -       printk(KERN_INFO
> -               "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
> -               tag,
> -               subtag,
> -               cp_state,
> -               cp_ready);
> -
> -       /* TODO */
> -       if (cp_state)
> -               ;
> -       if (cp_ready)
> -               ;
> -}
> -
> -
> -static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
> -{
> -       struct intel_hdmi_spec *spec = codec->spec;
> -       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
> -       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
> -
> -       if (hda_node_index(spec->pin, tag) < 0) {
> -               snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
> -               return;
> -       }
> -
> -       if (subtag == 0)
> -               hdmi_intrinsic_event(codec, res);
> -       else
> -               hdmi_non_intrinsic_event(codec, res);
> -}
> -
> -/*
> - * Callbacks
> - */
> -
> -static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
> -                             u32 stream_tag, int format)
> -{
> -       int tag;
> -       int fmt;
> -
> -       tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
> -       fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
> -
> -       snd_printdd("hdmi_setup_stream: "
> -                   "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
> -                   nid,
> -                   tag == stream_tag ? "" : "new-",
> -                   stream_tag,
> -                   fmt == format ? "" : "new-",
> -                   format);
> -
> -       if (tag != stream_tag)
> -               snd_hda_codec_write(codec, nid, 0,
> -                                   AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4);
> -       if (fmt != format)
> -               snd_hda_codec_write(codec, nid, 0,
> -                                   AC_VERB_SET_STREAM_FORMAT, format);
> -}
> -
>  static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
>                                            struct hda_codec *codec,
>                                            unsigned int stream_tag,
> @@ -882,7 +80,7 @@ static struct hda_pcm_stream intel_hdmi_
> 
>  static int intel_hdmi_build_pcms(struct hda_codec *codec)
>  {
> -       struct intel_hdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         struct hda_pcm *info = spec->pcm_rec;
>         int i;
> 
> @@ -908,7 +106,7 @@ static int intel_hdmi_build_pcms(struct
> 
>  static int intel_hdmi_build_controls(struct hda_codec *codec)
>  {
> -       struct intel_hdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         int err;
>         int i;
> 
> @@ -923,7 +121,7 @@ static int intel_hdmi_build_controls(str
> 
>  static int intel_hdmi_init(struct hda_codec *codec)
>  {
> -       struct intel_hdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         int i;
> 
>         for (i = 0; spec->pin[i]; i++) {
> @@ -937,7 +135,7 @@ static int intel_hdmi_init(struct hda_co
> 
>  static void intel_hdmi_free(struct hda_codec *codec)
>  {
> -       struct intel_hdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         int i;
> 
>         for (i = 0; i < spec->num_pins; i++)
> @@ -951,12 +149,12 @@ static struct hda_codec_ops intel_hdmi_p
>         .free                   = intel_hdmi_free,
>         .build_pcms             = intel_hdmi_build_pcms,
>         .build_controls         = intel_hdmi_build_controls,
> -       .unsol_event            = intel_hdmi_unsol_event,
> +       .unsol_event            = hdmi_unsol_event,
>  };
> 
>  static int patch_intel_hdmi(struct hda_codec *codec)
>  {
> -       struct intel_hdmi_spec *spec;
> +       struct hdmi_spec *spec;
>         int i;
> 
>         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
> @@ -964,7 +162,7 @@ static int patch_intel_hdmi(struct hda_c
>                 return -ENOMEM;
> 
>         codec->spec = spec;
> -       if (intel_hdmi_parse_codec(codec) < 0) {
> +       if (hdmi_parse_codec(codec) < 0) {
>                 codec->spec = NULL;
>                 kfree(spec);
>                 return -EINVAL;
> --- /dev/null   1970-01-01 00:00:00.000000000 +0000
> +++ sound-2.6/sound/pci/hda/patch_hdmi.c        2010-03-04 13:30:14.000000000 +0800
> @@ -0,0 +1,828 @@
> +/*
> + * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
> + * could support two independent pipes, each of them can be connected to one or
> + * more ports (DVI, HDMI or DisplayPort).
> + *
> + * The HDA correspondence of pipes/ports are converter/pin nodes.
> + */
> +#define MAX_HDMI_CVTS  2
> +#define MAX_HDMI_PINS  3
> +
> +
> +struct hdmi_spec {
> +       int num_cvts;
> +       int num_pins;
> +       hda_nid_t cvt[MAX_HDMI_CVTS+1];  /* audio sources */
> +       hda_nid_t pin[MAX_HDMI_PINS+1];  /* audio sinks */
> +
> +       /*
> +        * source connection for each pin
> +        */
> +       hda_nid_t pin_cvt[MAX_HDMI_PINS+1];
> +
> +       /*
> +        * HDMI sink attached to each pin
> +        */
> +       struct hdmi_eld sink_eld[MAX_HDMI_PINS];
> +
> +       /*
> +        * export one pcm per pipe
> +        */
> +       struct hda_pcm  pcm_rec[MAX_HDMI_CVTS];
> +
> +       /*
> +        * nvhdmi specific
> +        */
> +       struct hda_multi_out multiout;
> +       unsigned int codec_type;
> +};
> +
> +
> +struct hdmi_audio_infoframe {
> +       u8 type; /* 0x84 */
> +       u8 ver;  /* 0x01 */
> +       u8 len;  /* 0x0a */
> +
> +       u8 checksum;    /* PB0 */
> +       u8 CC02_CT47;   /* CC in bits 0:2, CT in 4:7 */
> +       u8 SS01_SF24;
> +       u8 CXT04;
> +       u8 CA;
> +       u8 LFEPBL01_LSV36_DM_INH7;
> +       u8 reserved[5]; /* PB6 - PB10 */
> +};
> +
> +/*
> + * CEA speaker placement:
> + *
> + *        FLH       FCH        FRH
> + *  FLW    FL  FLC   FC   FRC   FR   FRW
> + *
> + *                                  LFE
> + *                     TC
> + *
> + *          RL  RLC   RC   RRC   RR
> + *
> + * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
> + * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
> + */
> +enum cea_speaker_placement {
> +       FL  = (1 <<  0),        /* Front Left           */
> +       FC  = (1 <<  1),        /* Front Center         */
> +       FR  = (1 <<  2),        /* Front Right          */
> +       FLC = (1 <<  3),        /* Front Left Center    */
> +       FRC = (1 <<  4),        /* Front Right Center   */
> +       RL  = (1 <<  5),        /* Rear Left            */
> +       RC  = (1 <<  6),        /* Rear Center          */
> +       RR  = (1 <<  7),        /* Rear Right           */
> +       RLC = (1 <<  8),        /* Rear Left Center     */
> +       RRC = (1 <<  9),        /* Rear Right Center    */
> +       LFE = (1 << 10),        /* Low Frequency Effect */
> +       FLW = (1 << 11),        /* Front Left Wide      */
> +       FRW = (1 << 12),        /* Front Right Wide     */
> +       FLH = (1 << 13),        /* Front Left High      */
> +       FCH = (1 << 14),        /* Front Center High    */
> +       FRH = (1 << 15),        /* Front Right High     */
> +       TC  = (1 << 16),        /* Top Center           */
> +};
> +
> +/*
> + * ELD SA bits in the CEA Speaker Allocation data block
> + */
> +static int eld_speaker_allocation_bits[] = {
> +       [0] = FL | FR,
> +       [1] = LFE,
> +       [2] = FC,
> +       [3] = RL | RR,
> +       [4] = RC,
> +       [5] = FLC | FRC,
> +       [6] = RLC | RRC,
> +       /* the following are not defined in ELD yet */
> +       [7] = FLW | FRW,
> +       [8] = FLH | FRH,
> +       [9] = TC,
> +       [10] = FCH,
> +};
> +
> +struct cea_channel_speaker_allocation {
> +       int ca_index;
> +       int speakers[8];
> +
> +       /* derived values, just for convenience */
> +       int channels;
> +       int spk_mask;
> +};
> +
> +/*
> + * ALSA sequence is:
> + *
> + *       surround40   surround41   surround50   surround51   surround71
> + * ch0   front left   =            =            =            =
> + * ch1   front right  =            =            =            =
> + * ch2   rear left    =            =            =            =
> + * ch3   rear right   =            =            =            =
> + * ch4                LFE          center       center       center
> + * ch5                                          LFE          LFE
> + * ch6                                                       side left
> + * ch7                                                       side right
> + *
> + * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
> + */
> +static int hdmi_channel_mapping[0x32][8] = {
> +       /* stereo */
> +       [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
> +       /* 2.1 */
> +       [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
> +       /* Dolby Surround */
> +       [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
> +       /* surround40 */
> +       [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
> +       /* 4ch */
> +       [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
> +       /* surround41 */
> +       [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
> +       /* surround50 */
> +       [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
> +       /* surround51 */
> +       [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
> +       /* 7.1 */
> +       [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
> +};
> +
> +/*
> + * This is an ordered list!
> + *
> + * The preceding ones have better chances to be selected by
> + * hdmi_setup_channel_allocation().
> + */
> +static struct cea_channel_speaker_allocation channel_allocations[] = {
> +/*                       channel:   7     6    5    4    3     2    1    0  */
> +{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
> +                                /* 2.1 */
> +{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
> +                                /* Dolby Surround */
> +{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
> +                                /* surround40 */
> +{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
> +                                /* surround41 */
> +{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
> +                                /* surround50 */
> +{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
> +                                /* surround51 */
> +{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +                                /* 6.1 */
> +{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +                                /* surround71 */
> +{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +
> +{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
> +{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
> +{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
> +{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
> +{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
> +{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
> +{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
> +{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
> +{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
> +{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
> +{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
> +{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
> +{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
> +{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
> +{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
> +{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
> +{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
> +{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
> +};
> +
> +
> +/*
> + * HDMI routines
> + */
> +
> +static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
> +{
> +       int i;
> +
> +       for (i = 0; nids[i]; i++)
> +               if (nids[i] == nid)
> +                       return i;
> +
> +       snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
> +       return -EINVAL;
> +}
> +
> +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
> +                             struct hdmi_eld *eld)
> +{
> +       if (!snd_hdmi_get_eld(eld, codec, pin_nid))
> +               snd_hdmi_show_eld(eld);
> +}
> +
> +#ifdef BE_PARANOID
> +static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
> +                               int *packet_index, int *byte_index)
> +{
> +       int val;
> +
> +       val = snd_hda_codec_read(codec, pin_nid, 0,
> +                                AC_VERB_GET_HDMI_DIP_INDEX, 0);
> +
> +       *packet_index = val >> 5;
> +       *byte_index = val & 0x1f;
> +}
> +#endif
> +
> +static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
> +                               int packet_index, int byte_index)
> +{
> +       int val;
> +
> +       val = (packet_index << 5) | (byte_index & 0x1f);
> +
> +       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
> +}
> +
> +static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
> +                               unsigned char val)
> +{
> +       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
> +}
> +
> +static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
> +{
> +       /* Unmute */
> +       if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
> +               snd_hda_codec_write(codec, pin_nid, 0,
> +                               AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
> +       /* Enable pin out */
> +       snd_hda_codec_write(codec, pin_nid, 0,
> +                           AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
> +}
> +
> +static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
> +{
> +       return 1 + snd_hda_codec_read(codec, nid, 0,
> +                                       AC_VERB_GET_CVT_CHAN_COUNT, 0);
> +}
> +
> +static void hdmi_set_channel_count(struct hda_codec *codec,
> +                                  hda_nid_t nid, int chs)
> +{
> +       if (chs != hdmi_get_channel_count(codec, nid))
> +               snd_hda_codec_write(codec, nid, 0,
> +                                   AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
> +}
> +
> +
> +/*
> + * Channel mapping routines
> + */
> +
> +/*
> + * Compute derived values in channel_allocations[].
> + */
> +static void init_channel_allocations(void)
> +{
> +       int i, j;
> +       struct cea_channel_speaker_allocation *p;
> +
> +       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
> +               p = channel_allocations + i;
> +               p->channels = 0;
> +               p->spk_mask = 0;
> +               for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
> +                       if (p->speakers[j]) {
> +                               p->channels++;
> +                               p->spk_mask |= p->speakers[j];
> +                       }
> +       }
> +}
> +
> +/*
> + * The transformation takes two steps:
> + *
> + *     eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
> + *           spk_mask => (channel_allocations[])         => ai->CA
> + *
> + * TODO: it could select the wrong CA from multiple candidates.
> +*/
> +static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
> +                                        struct hdmi_audio_infoframe *ai)
> +{
> +       struct hdmi_spec *spec = codec->spec;
> +       struct hdmi_eld *eld;
> +       int i;
> +       int spk_mask = 0;
> +       int channels = 1 + (ai->CC02_CT47 & 0x7);
> +       char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
> +
> +       /*
> +        * CA defaults to 0 for basic stereo audio
> +        */
> +       if (channels <= 2)
> +               return 0;
> +
> +       i = hda_node_index(spec->pin_cvt, nid);
> +       if (i < 0)
> +               return 0;
> +       eld = &spec->sink_eld[i];
> +
> +       /*
> +        * HDMI sink's ELD info cannot always be retrieved for now, e.g.
> +        * in console or for audio devices. Assume the highest speakers
> +        * configuration, to _not_ prohibit multi-channel audio playback.
> +        */
> +       if (!eld->spk_alloc)
> +               eld->spk_alloc = 0xffff;
> +
> +       /*
> +        * expand ELD's speaker allocation mask
> +        *
> +        * ELD tells the speaker mask in a compact(paired) form,
> +        * expand ELD's notions to match the ones used by Audio InfoFrame.
> +        */
> +       for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
> +               if (eld->spk_alloc & (1 << i))
> +                       spk_mask |= eld_speaker_allocation_bits[i];
> +       }
> +
> +       /* search for the first working match in the CA table */
> +       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
> +               if (channels == channel_allocations[i].channels &&
> +                   (spk_mask & channel_allocations[i].spk_mask) ==
> +                               channel_allocations[i].spk_mask) {
> +                       ai->CA = channel_allocations[i].ca_index;
> +                       break;
> +               }
> +       }
> +
> +       snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
> +       snd_printdd(KERN_INFO
> +                       "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
> +                       ai->CA, channels, buf);
> +
> +       return ai->CA;
> +}
> +
> +static void hdmi_debug_channel_mapping(struct hda_codec *codec,
> +                                      hda_nid_t pin_nid)
> +{
> +#ifdef CONFIG_SND_DEBUG_VERBOSE
> +       int i;
> +       int slot;
> +
> +       for (i = 0; i < 8; i++) {
> +               slot = snd_hda_codec_read(codec, pin_nid, 0,
> +                                               AC_VERB_GET_HDMI_CHAN_SLOT, i);
> +               printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
> +                                               slot >> 4, slot & 0xf);
> +       }
> +#endif
> +}
> +
> +
> +static void hdmi_setup_channel_mapping(struct hda_codec *codec,
> +                                      hda_nid_t pin_nid,
> +                                      struct hdmi_audio_infoframe *ai)
> +{
> +       int i;
> +       int ca = ai->CA;
> +       int err;
> +
> +       if (hdmi_channel_mapping[ca][1] == 0) {
> +               for (i = 0; i < channel_allocations[ca].channels; i++)
> +                       hdmi_channel_mapping[ca][i] = i | (i << 4);
> +               for (; i < 8; i++)
> +                       hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
> +       }
> +
> +       for (i = 0; i < 8; i++) {
> +               err = snd_hda_codec_write(codec, pin_nid, 0,
> +                                         AC_VERB_SET_HDMI_CHAN_SLOT,
> +                                         hdmi_channel_mapping[ca][i]);
> +               if (err) {
> +                       snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
> +                       break;
> +               }
> +       }
> +
> +       hdmi_debug_channel_mapping(codec, pin_nid);
> +}
> +
> +
> +/*
> + * Audio InfoFrame routines
> + */
> +
> +/*
> + * Enable Audio InfoFrame Transmission
> + */
> +static void hdmi_start_infoframe_trans(struct hda_codec *codec,
> +                                      hda_nid_t pin_nid)
> +{
> +       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> +       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
> +                                               AC_DIPXMIT_BEST);
> +}
> +
> +/*
> + * Disable Audio InfoFrame Transmission
> + */
> +static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
> +                                     hda_nid_t pin_nid)
> +{
> +       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> +       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
> +                                               AC_DIPXMIT_DISABLE);
> +}
> +
> +static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
> +{
> +#ifdef CONFIG_SND_DEBUG_VERBOSE
> +       int i;
> +       int size;
> +
> +       size = snd_hdmi_get_eld_size(codec, pin_nid);
> +       printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
> +
> +       for (i = 0; i < 8; i++) {
> +               size = snd_hda_codec_read(codec, pin_nid, 0,
> +                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
> +               printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
> +       }
> +#endif
> +}
> +
> +static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
> +{
> +#ifdef BE_PARANOID
> +       int i, j;
> +       int size;
> +       int pi, bi;
> +       for (i = 0; i < 8; i++) {
> +               size = snd_hda_codec_read(codec, pin_nid, 0,
> +                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
> +               if (size == 0)
> +                       continue;
> +
> +               hdmi_set_dip_index(codec, pin_nid, i, 0x0);
> +               for (j = 1; j < 1000; j++) {
> +                       hdmi_write_dip_byte(codec, pin_nid, 0x0);
> +                       hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
> +                       if (pi != i)
> +                               snd_printd(KERN_INFO "dip index %d: %d != %d\n",
> +                                               bi, pi, i);
> +                       if (bi == 0) /* byte index wrapped around */
> +                               break;
> +               }
> +               snd_printd(KERN_INFO
> +                       "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
> +                       i, size, j);
> +       }
> +#endif
> +}
> +
> +static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
> +{
> +       u8 *bytes = (u8 *)ai;
> +       u8 sum = 0;
> +       int i;
> +
> +       ai->checksum = 0;
> +
> +       for (i = 0; i < sizeof(*ai); i++)
> +               sum += bytes[i];
> +
> +       ai->checksum = - sum;
> +}
> +
> +static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
> +                                     hda_nid_t pin_nid,
> +                                     struct hdmi_audio_infoframe *ai)
> +{
> +       u8 *bytes = (u8 *)ai;
> +       int i;
> +
> +       hdmi_debug_dip_size(codec, pin_nid);
> +       hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
> +
> +       hdmi_checksum_audio_infoframe(ai);
> +
> +       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> +       for (i = 0; i < sizeof(*ai); i++)
> +               hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
> +}
> +
> +static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
> +                                   struct hdmi_audio_infoframe *ai)
> +{
> +       u8 *bytes = (u8 *)ai;
> +       u8 val;
> +       int i;
> +
> +       if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
> +                                                           != AC_DIPXMIT_BEST)
> +               return false;
> +
> +       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> +       for (i = 0; i < sizeof(*ai); i++) {
> +               val = snd_hda_codec_read(codec, pin_nid, 0,
> +                                        AC_VERB_GET_HDMI_DIP_DATA, 0);
> +               if (val != bytes[i])
> +                       return false;
> +       }
> +
> +       return true;
> +}
> +
> +static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
> +                                       struct snd_pcm_substream *substream)
> +{
> +       struct hdmi_spec *spec = codec->spec;
> +       hda_nid_t pin_nid;
> +       int i;
> +       struct hdmi_audio_infoframe ai = {
> +               .type           = 0x84,
> +               .ver            = 0x01,
> +               .len            = 0x0a,
> +               .CC02_CT47      = substream->runtime->channels - 1,
> +       };
> +
> +       hdmi_setup_channel_allocation(codec, nid, &ai);
> +
> +       for (i = 0; i < spec->num_pins; i++) {
> +               if (spec->pin_cvt[i] != nid)
> +                       continue;
> +               if (!spec->sink_eld[i].monitor_present)
> +                       continue;
> +
> +               pin_nid = spec->pin[i];
> +               if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
> +                       hdmi_setup_channel_mapping(codec, pin_nid, &ai);
> +                       hdmi_stop_infoframe_trans(codec, pin_nid);
> +                       hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
> +                       hdmi_start_infoframe_trans(codec, pin_nid);
> +               }
> +       }
> +}
> +
> +
> +/*
> + * Unsolicited events
> + */
> +
> +static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
> +{
> +       struct hdmi_spec *spec = codec->spec;
> +       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
> +       int pind = !!(res & AC_UNSOL_RES_PD);
> +       int eldv = !!(res & AC_UNSOL_RES_ELDV);
> +       int index;
> +
> +       printk(KERN_INFO
> +               "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
> +               tag, pind, eldv);
> +
> +       index = hda_node_index(spec->pin, tag);
> +       if (index < 0)
> +               return;
> +
> +       spec->sink_eld[index].monitor_present = pind;
> +       spec->sink_eld[index].eld_valid = eldv;
> +
> +       if (pind && eldv) {
> +               hdmi_get_show_eld(codec, spec->pin[index],
> +                                 &spec->sink_eld[index]);
> +               /* TODO: do real things about ELD */
> +       }
> +}
> +
> +static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
> +{
> +       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
> +       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
> +       int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
> +       int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
> +
> +       printk(KERN_INFO
> +               "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
> +               tag,
> +               subtag,
> +               cp_state,
> +               cp_ready);
> +
> +       /* TODO */
> +       if (cp_state)
> +               ;
> +       if (cp_ready)
> +               ;
> +}
> +
> +
> +static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
> +{
> +       struct hdmi_spec *spec = codec->spec;
> +       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
> +       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
> +
> +       if (hda_node_index(spec->pin, tag) < 0) {
> +               snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
> +               return;
> +       }
> +
> +       if (subtag == 0)
> +               hdmi_intrinsic_event(codec, res);
> +       else
> +               hdmi_non_intrinsic_event(codec, res);
> +}
> +
> +/*
> + * Callbacks
> + */
> +
> +static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
> +                             u32 stream_tag, int format)
> +{
> +       int tag;
> +       int fmt;
> +
> +       tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
> +       fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
> +
> +       snd_printdd("hdmi_setup_stream: "
> +                   "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
> +                   nid,
> +                   tag == stream_tag ? "" : "new-",
> +                   stream_tag,
> +                   fmt == format ? "" : "new-",
> +                   format);
> +
> +       if (tag != stream_tag)
> +               snd_hda_codec_write(codec, nid, 0,
> +                                   AC_VERB_SET_CHANNEL_STREAMID,
> +                                   stream_tag << 4);
> +       if (fmt != format)
> +               snd_hda_codec_write(codec, nid, 0,
> +                                   AC_VERB_SET_STREAM_FORMAT, format);
> +}
> +
> +/*
> + * HDA/HDMI auto parsing
> + */
> +
> +static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
> +{
> +       struct hdmi_spec *spec = codec->spec;
> +       hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
> +       int conn_len, curr;
> +       int index;
> +
> +       if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
> +               snd_printk(KERN_WARNING
> +                          "HDMI: pin %d wcaps %#x "
> +                          "does not support connection list\n",
> +                          pin_nid, get_wcaps(codec, pin_nid));
> +               return -EINVAL;
> +       }
> +
> +       conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
> +                                          HDA_MAX_CONNECTIONS);
> +       if (conn_len > 1)
> +               curr = snd_hda_codec_read(codec, pin_nid, 0,
> +                                         AC_VERB_GET_CONNECT_SEL, 0);
> +       else
> +               curr = 0;
> +
> +       index = hda_node_index(spec->pin, pin_nid);
> +       if (index < 0)
> +               return -EINVAL;
> +
> +       spec->pin_cvt[index] = conn_list[curr];
> +
> +       return 0;
> +}
> +
> +static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
> +                              struct hdmi_eld *eld)
> +{
> +       int present = snd_hda_pin_sense(codec, pin_nid);
> +
> +       eld->monitor_present    = !!(present & AC_PINSENSE_PRESENCE);
> +       eld->eld_valid          = !!(present & AC_PINSENSE_ELDV);
> +
> +       if (present & AC_PINSENSE_ELDV)
> +               hdmi_get_show_eld(codec, pin_nid, eld);
> +}
> +
> +static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
> +{
> +       struct hdmi_spec *spec = codec->spec;
> +
> +       if (spec->num_pins >= MAX_HDMI_PINS) {
> +               snd_printk(KERN_WARNING
> +                          "HDMI: no space for pin %d \n", pin_nid);
> +               return -EINVAL;
> +       }
> +
> +       hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
> +
> +       spec->pin[spec->num_pins] = pin_nid;
> +       spec->num_pins++;
> +
> +       /*
> +        * It is assumed that converter nodes come first in the node list and
> +        * hence have been registered and usable now.
> +        */
> +       return hdmi_read_pin_conn(codec, pin_nid);
> +}
> +
> +static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
> +{
> +       struct hdmi_spec *spec = codec->spec;
> +
> +       if (spec->num_cvts >= MAX_HDMI_CVTS) {
> +               snd_printk(KERN_WARNING
> +                          "HDMI: no space for converter %d \n", nid);
> +               return -EINVAL;
> +       }
> +
> +       spec->cvt[spec->num_cvts] = nid;
> +       spec->num_cvts++;
> +
> +       return 0;
> +}
> +
> +static int hdmi_parse_codec(struct hda_codec *codec)
> +{
> +       hda_nid_t nid;
> +       int i, nodes;
> +
> +       nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
> +       if (!nid || nodes < 0) {
> +               snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
> +               return -EINVAL;
> +       }
> +
> +       for (i = 0; i < nodes; i++, nid++) {
> +               unsigned int caps;
> +               unsigned int type;
> +
> +               caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
> +               type = get_wcaps_type(caps);
> +
> +               if (!(caps & AC_WCAP_DIGITAL))
> +                       continue;
> +
> +               switch (type) {
> +               case AC_WID_AUD_OUT:
> +                       if (hdmi_add_cvt(codec, nid) < 0)
> +                               return -EINVAL;
> +                       break;
> +               case AC_WID_PIN:
> +                       caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
> +                       if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
> +                               continue;
> +                       if (hdmi_add_pin(codec, nid) < 0)
> +                               return -EINVAL;
> +                       break;
> +               }
> +       }
> +
> +       /*
> +        * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
> +        * can be lost and presence sense verb will become inaccurate if the
> +        * HDA link is powered off at hot plug or hw initialization time.
> +        */
> +#ifdef CONFIG_SND_HDA_POWER_SAVE
> +       if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
> +             AC_PWRST_EPSS))
> +               codec->bus->power_keep_link_on = 1;
> +#endif
> +
> +       return 0;
> +}
> +
> --- sound-2.6.orig/sound/pci/hda/patch_nvhdmi.c 2010-03-04 13:14:54.000000000 +0800
> +++ sound-2.6/sound/pci/hda/patch_nvhdmi.c      2010-03-04 13:14:56.000000000 +0800
> @@ -29,6 +29,8 @@
>  #include "hda_codec.h"
>  #include "hda_local.h"
> 
> +#include "patch_hdmi.c"
> +
>  /* define below to restrict the supported rates and formats */
>  /* #define LIMITED_RATE_FMT_SUPPORT */
> 
> @@ -86,799 +88,16 @@ static struct hda_verb nvhdmi_basic_init
>  #define NVIDIA_89_HDMI_CVTS    1
>  #define NVIDIA_89_HDMI_PINS    1
> 
> -static char *nvhdmi_pcm_names[NVIDIA_89_HDMI_CVTS] = {
> +static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
>         "NVIDIA HDMI",
>  };
> 
> -struct nvhdmi_spec {
> -       int num_cvts;
> -       int num_pins;
> -       hda_nid_t cvt[NVIDIA_89_HDMI_CVTS+1];  /* audio sources */
> -       hda_nid_t pin[NVIDIA_89_HDMI_PINS+1];  /* audio sinks */
> -       hda_nid_t pin_cvt[NVIDIA_89_HDMI_PINS+1];
> -       struct hda_pcm pcm_rec[NVIDIA_89_HDMI_CVTS];
> -       struct hdmi_eld sink_eld[NVIDIA_89_HDMI_PINS];
> -       struct hda_multi_out multiout;
> -       unsigned int codec_type;
> -};
> -
> -struct hdmi_audio_infoframe {
> -       u8 type; /* 0x84 */
> -       u8 ver;  /* 0x01 */
> -       u8 len;  /* 0x0a */
> -
> -       u8 checksum;    /* PB0 */
> -       u8 CC02_CT47;   /* CC in bits 0:2, CT in 4:7 */
> -       u8 SS01_SF24;
> -       u8 CXT04;
> -       u8 CA;
> -       u8 LFEPBL01_LSV36_DM_INH7;
> -};
> -
> -/*
> - * CEA speaker placement:
> - *
> - *        FLH       FCH        FRH
> - *  FLW    FL  FLC   FC   FRC   FR   FRW
> - *
> - *                                  LFE
> - *                     TC
> - *
> - *          RL  RLC   RC   RRC   RR
> - *
> - * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
> - * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
> - */
> -enum cea_speaker_placement {
> -       FL  = (1 <<  0),        /* Front Left           */
> -       FC  = (1 <<  1),        /* Front Center         */
> -       FR  = (1 <<  2),        /* Front Right          */
> -       FLC = (1 <<  3),        /* Front Left Center    */
> -       FRC = (1 <<  4),        /* Front Right Center   */
> -       RL  = (1 <<  5),        /* Rear Left            */
> -       RC  = (1 <<  6),        /* Rear Center          */
> -       RR  = (1 <<  7),        /* Rear Right           */
> -       RLC = (1 <<  8),        /* Rear Left Center     */
> -       RRC = (1 <<  9),        /* Rear Right Center    */
> -       LFE = (1 << 10),        /* Low Frequency Effect */
> -       FLW = (1 << 11),        /* Front Left Wide      */
> -       FRW = (1 << 12),        /* Front Right Wide     */
> -       FLH = (1 << 13),        /* Front Left High      */
> -       FCH = (1 << 14),        /* Front Center High    */
> -       FRH = (1 << 15),        /* Front Right High     */
> -       TC  = (1 << 16),        /* Top Center           */
> -};
> -
> -/*
> - * ELD SA bits in the CEA Speaker Allocation data block
> - */
> -static int eld_speaker_allocation_bits[] = {
> -       [0] = FL | FR,
> -       [1] = LFE,
> -       [2] = FC,
> -       [3] = RL | RR,
> -       [4] = RC,
> -       [5] = FLC | FRC,
> -       [6] = RLC | RRC,
> -       /* the following are not defined in ELD yet */
> -       [7] = FLW | FRW,
> -       [8] = FLH | FRH,
> -       [9] = TC,
> -       [10] = FCH,
> -};
> -
> -struct cea_channel_speaker_allocation {
> -       int ca_index;
> -       int speakers[8];
> -
> -       /* derived values, just for convenience */
> -       int channels;
> -       int spk_mask;
> -};
> -
> -/*
> - * ALSA sequence is:
> - *
> - *       surround40   surround41   surround50   surround51   surround71
> - * ch0   front left   =            =            =            =
> - * ch1   front right  =            =            =            =
> - * ch2   rear left    =            =            =            =
> - * ch3   rear right   =            =            =            =
> - * ch4                LFE          center       center       center
> - * ch5                                          LFE          LFE
> - * ch6                                                       side left
> - * ch7                                                       side right
> - *
> - * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
> - */
> -static int hdmi_channel_mapping[0x32][8] = {
> -       /* stereo */
> -       [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
> -       /* 2.1 */
> -       [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
> -       /* Dolby Surround */
> -       [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
> -       /* surround40 */
> -       [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
> -       /* 4ch */
> -       [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
> -       /* surround41 */
> -       [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
> -       /* surround50 */
> -       [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
> -       /* surround51 */
> -       [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
> -       /* 7.1 */
> -       [0x13] = { 0x00, 0x11, 0x32, 0x23, 0x64, 0x75, 0x46, 0x57 },
> -};
> -
> -/*
> - * This is an ordered list!
> - *
> - * The preceding ones have better chances to be selected by
> - * hdmi_setup_channel_allocation().
> - */
> -static struct cea_channel_speaker_allocation channel_allocations[] = {
> -/*                       channel:   7     6    5    4    3     2    1    0  */
> -{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
> -                                /* 2.1 */
> -{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
> -                                /* Dolby Surround */
> -{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
> -                                /* surround40 */
> -{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
> -                                /* surround41 */
> -{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
> -                                /* surround50 */
> -{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
> -                                /* surround51 */
> -{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -                                /* 6.1 */
> -{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -                                /* surround71 */
> -{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -
> -{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
> -{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
> -{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
> -{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
> -};
> -
> -/*
> - * HDA/HDMI auto parsing
> - */
> -
> -static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
> -{
> -       int i;
> -
> -       for (i = 0; nids[i]; i++)
> -               if (nids[i] == nid)
> -                       return i;
> -
> -       snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
> -       return -EINVAL;
> -}
> -
> -static int nvhdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -       struct nvhdmi_spec *spec = codec->spec;
> -       hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
> -       int conn_len, curr;
> -       int index;
> -
> -       if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
> -               snd_printk(KERN_WARNING
> -                          "HDMI: pin %d wcaps %#x "
> -                          "does not support connection list\n",
> -                          pin_nid, get_wcaps(codec, pin_nid));
> -               return -EINVAL;
> -       }
> -
> -       conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
> -                                          HDA_MAX_CONNECTIONS);
> -       if (conn_len > 1)
> -               curr = snd_hda_codec_read(codec, pin_nid, 0,
> -                                         AC_VERB_GET_CONNECT_SEL, 0);
> -       else
> -               curr = 0;
> -
> -       index = hda_node_index(spec->pin, pin_nid);
> -       if (index < 0)
> -               return -EINVAL;
> -
> -       spec->pin_cvt[index] = conn_list[curr];
> -
> -       return 0;
> -}
> -
> -static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
> -                             struct hdmi_eld *eld)
> -{
> -       if (!snd_hdmi_get_eld(eld, codec, pin_nid))
> -               snd_hdmi_show_eld(eld);
> -}
> -
> -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
> -                              struct hdmi_eld *eld)
> -{
> -       int present = snd_hda_pin_sense(codec, pin_nid);
> -
> -       eld->monitor_present    = !!(present & AC_PINSENSE_PRESENCE);
> -       eld->eld_valid          = !!(present & AC_PINSENSE_ELDV);
> -
> -       if (present & AC_PINSENSE_ELDV)
> -               hdmi_get_show_eld(codec, pin_nid, eld);
> -}
> -
> -static int nvhdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -       struct nvhdmi_spec *spec = codec->spec;
> -
> -       if (spec->num_pins >= NVIDIA_89_HDMI_PINS) {
> -               snd_printk(KERN_WARNING
> -                          "HDMI: no space for pin %d \n", pin_nid);
> -               return -EINVAL;
> -       }
> -
> -       hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
> -
> -       spec->pin[spec->num_pins] = pin_nid;
> -       spec->num_pins++;
> -
> -       /*
> -        * It is assumed that converter nodes come first in the node list and
> -        * hence have been registered and usable now.
> -        */
> -       return nvhdmi_read_pin_conn(codec, pin_nid);
> -}
> -
> -static int nvhdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
> -{
> -       struct nvhdmi_spec *spec = codec->spec;
> -
> -       if (spec->num_cvts >= NVIDIA_89_HDMI_CVTS) {
> -               snd_printk(KERN_WARNING
> -                          "HDMI: no space for converter %d \n", nid);
> -               return -EINVAL;
> -       }
> -
> -       spec->cvt[spec->num_cvts] = nid;
> -       spec->num_cvts++;
> -
> -       return 0;
> -}
> -
> -
> -static int nvhdmi_parse_codec(struct hda_codec *codec)
> -{
> -       hda_nid_t nid;
> -       int i, nodes;
> -
> -       nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
> -       if (!nid || nodes < 0) {
> -               snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
> -               return -EINVAL;
> -       }
> -
> -       for (i = 0; i < nodes; i++, nid++) {
> -               unsigned int caps;
> -               unsigned int type;
> -
> -               caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
> -               type = get_wcaps_type(caps);
> -
> -               if (!(caps & AC_WCAP_DIGITAL))
> -                       continue;
> -
> -               switch (type) {
> -               case AC_WID_AUD_OUT:
> -                       if (nvhdmi_add_cvt(codec, nid) < 0)
> -                               return -EINVAL;
> -                       break;
> -               case AC_WID_PIN:
> -                       caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
> -                       if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
> -                               continue;
> -                       if (nvhdmi_add_pin(codec, nid) < 0)
> -                               return -EINVAL;
> -                       break;
> -               }
> -       }
> -
> -       /*
> -        * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
> -        * can be lost and presence sense verb will become inaccurate if the
> -        * HDA link is powered off at hot plug or hw initialization time.
> -        */
> -#ifdef CONFIG_SND_HDA_POWER_SAVE
> -       if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
> -             AC_PWRST_EPSS))
> -               codec->bus->power_keep_link_on = 1;
> -#endif
> -
> -       return 0;
> -}
> -
> -/*
> - * HDMI routines
> - */
> -
> -#ifdef BE_PARANOID
> -static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
> -                               int *packet_index, int *byte_index)
> -{
> -       int val;
> -
> -       val = snd_hda_codec_read(codec, pin_nid, 0,
> -                                AC_VERB_GET_HDMI_DIP_INDEX, 0);
> -
> -       *packet_index = val >> 5;
> -       *byte_index = val & 0x1f;
> -}
> -#endif
> -
> -static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
> -                               int packet_index, int byte_index)
> -{
> -       int val;
> -
> -       val = (packet_index << 5) | (byte_index & 0x1f);
> -
> -       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
> -}
> -
> -static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
> -                               unsigned char val)
> -{
> -       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
> -}
> -
> -static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -       /* Unmute */
> -       if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
> -               snd_hda_codec_write(codec, pin_nid, 0,
> -                               AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
> -       /* Enable pin out */
> -       snd_hda_codec_write(codec, pin_nid, 0,
> -                           AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
> -}
> -
> -/*
> - * Enable Audio InfoFrame Transmission
> - */
> -static void hdmi_start_infoframe_trans(struct hda_codec *codec,
> -                                      hda_nid_t pin_nid)
> -{
> -       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> -       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
> -                                               AC_DIPXMIT_BEST);
> -}
> -
> -/*
> - * Disable Audio InfoFrame Transmission
> - */
> -static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
> -                                     hda_nid_t pin_nid)
> -{
> -       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> -       snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
> -                                               AC_DIPXMIT_DISABLE);
> -}
> -
> -static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
> -{
> -       return 1 + snd_hda_codec_read(codec, nid, 0,
> -                                       AC_VERB_GET_CVT_CHAN_COUNT, 0);
> -}
> -
> -static void hdmi_set_channel_count(struct hda_codec *codec,
> -                                  hda_nid_t nid, int chs)
> -{
> -       if (chs != hdmi_get_channel_count(codec, nid))
> -               snd_hda_codec_write(codec, nid, 0,
> -                                   AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
> -}
> -
> -static void hdmi_debug_channel_mapping(struct hda_codec *codec,
> -                                      hda_nid_t pin_nid)
> -{
> -#ifdef CONFIG_SND_DEBUG_VERBOSE
> -       int i;
> -       int slot;
> -
> -       for (i = 0; i < 8; i++) {
> -               slot = snd_hda_codec_read(codec, pin_nid, 0,
> -                                               AC_VERB_GET_HDMI_CHAN_SLOT, i);
> -               printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
> -                                               slot >> 4, slot & 0xf);
> -       }
> -#endif
> -}
> -
> -
> -/*
> - * Audio InfoFrame routines
> - */
> -
> -static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -#ifdef CONFIG_SND_DEBUG_VERBOSE
> -       int i;
> -       int size;
> -
> -       size = snd_hdmi_get_eld_size(codec, pin_nid);
> -       printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
> -
> -       for (i = 0; i < 8; i++) {
> -               size = snd_hda_codec_read(codec, pin_nid, 0,
> -                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
> -               printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
> -       }
> -#endif
> -}
> -
> -static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
> -{
> -#ifdef BE_PARANOID
> -       int i, j;
> -       int size;
> -       int pi, bi;
> -       for (i = 0; i < 8; i++) {
> -               size = snd_hda_codec_read(codec, pin_nid, 0,
> -                                               AC_VERB_GET_HDMI_DIP_SIZE, i);
> -               if (size == 0)
> -                       continue;
> -
> -               hdmi_set_dip_index(codec, pin_nid, i, 0x0);
> -               for (j = 1; j < 1000; j++) {
> -                       hdmi_write_dip_byte(codec, pin_nid, 0x0);
> -                       hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
> -                       if (pi != i)
> -                               snd_printd(KERN_INFO "dip index %d: %d != %d\n",
> -                                               bi, pi, i);
> -                       if (bi == 0) /* byte index wrapped around */
> -                               break;
> -               }
> -               snd_printd(KERN_INFO
> -                       "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
> -                       i, size, j);
> -       }
> -#endif
> -}
> -
> -static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
> -{
> -       ai->checksum = 0;
> -}
> -
> -static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
> -                                     hda_nid_t pin_nid,
> -                                     struct hdmi_audio_infoframe *ai)
> -{
> -       u8 *bytes = (u8 *)ai;
> -       int i;
> -
> -       hdmi_debug_dip_size(codec, pin_nid);
> -       hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
> -
> -       hdmi_checksum_audio_infoframe(ai);
> -
> -       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> -       for (i = 0; i < sizeof(*ai); i++)
> -               hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
> -}
> -
> -/*
> - * Compute derived values in channel_allocations[].
> - */
> -static void init_channel_allocations(void)
> -{
> -       int i, j;
> -       struct cea_channel_speaker_allocation *p;
> -
> -       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
> -               p = channel_allocations + i;
> -               p->channels = 0;
> -               p->spk_mask = 0;
> -               for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
> -                       if (p->speakers[j]) {
> -                               p->channels++;
> -                               p->spk_mask |= p->speakers[j];
> -                       }
> -       }
> -}
> -
> -/*
> - * The transformation takes two steps:
> - *
> - *     eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
> - *           spk_mask => (channel_allocations[])         => ai->CA
> - *
> - * TODO: it could select the wrong CA from multiple candidates.
> -*/
> -static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
> -                                        struct hdmi_audio_infoframe *ai)
> -{
> -       struct nvhdmi_spec *spec = codec->spec;
> -       struct hdmi_eld *eld;
> -       int i;
> -       int spk_mask = 0;
> -       int channels = 1 + (ai->CC02_CT47 & 0x7);
> -       char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
> -
> -       /*
> -        * CA defaults to 0 for basic stereo audio
> -        */
> -       if (channels <= 2)
> -               return 0;
> -
> -       i = hda_node_index(spec->pin_cvt, nid);
> -       if (i < 0)
> -               return 0;
> -       eld = &spec->sink_eld[i];
> -
> -       /*
> -        * HDMI sink's ELD info cannot always be retrieved for now, e.g.
> -        * in console or for audio devices. Assume the highest speakers
> -        * configuration, to _not_ prohibit multi-channel audio playback.
> -        */
> -       if (!eld->spk_alloc)
> -               eld->spk_alloc = 0xffff;
> -
> -       /*
> -        * expand ELD's speaker allocation mask
> -        *
> -        * ELD tells the speaker mask in a compact(paired) form,
> -        * expand ELD's notions to match the ones used by Audio InfoFrame.
> -        */
> -       for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
> -               if (eld->spk_alloc & (1 << i))
> -                       spk_mask |= eld_speaker_allocation_bits[i];
> -       }
> -
> -       /* search for the first working match in the CA table */
> -       for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
> -               if (channels == channel_allocations[i].channels &&
> -                   (spk_mask & channel_allocations[i].spk_mask) ==
> -                               channel_allocations[i].spk_mask) {
> -                       ai->CA = channel_allocations[i].ca_index;
> -                       break;
> -               }
> -       }
> -
> -       snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
> -       snd_printdd(KERN_INFO
> -                       "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
> -                       ai->CA, channels, buf);
> -
> -       return ai->CA;
> -}
> -
> -static void hdmi_setup_channel_mapping(struct hda_codec *codec,
> -                                      hda_nid_t pin_nid,
> -                                      struct hdmi_audio_infoframe *ai)
> -{
> -       int i;
> -       int ca = ai->CA;
> -       int err;
> -
> -       if (hdmi_channel_mapping[ca][1] == 0) {
> -               for (i = 0; i < channel_allocations[ca].channels; i++)
> -                       hdmi_channel_mapping[ca][i] = i | (i << 4);
> -               for (; i < 8; i++)
> -                       hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
> -       }
> -
> -       for (i = 0; i < 8; i++) {
> -               err = snd_hda_codec_write(codec, pin_nid, 0,
> -                                         AC_VERB_SET_HDMI_CHAN_SLOT,
> -                                         hdmi_channel_mapping[ca][i]);
> -               if (err) {
> -                       snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
> -                       break;
> -               }
> -       }
> -
> -       hdmi_debug_channel_mapping(codec, pin_nid);
> -}
> -
> -static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
> -                                   struct hdmi_audio_infoframe *ai)
> -{
> -       u8 *bytes = (u8 *)ai;
> -       u8 val;
> -       int i;
> -
> -       if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
> -                                                           != AC_DIPXMIT_BEST)
> -               return false;
> -
> -       hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
> -       for (i = 0; i < sizeof(*ai); i++) {
> -               val = snd_hda_codec_read(codec, pin_nid, 0,
> -                                        AC_VERB_GET_HDMI_DIP_DATA, 0);
> -               if (val != bytes[i])
> -                       return false;
> -       }
> -
> -       return true;
> -}
> -
> -static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
> -                                       struct snd_pcm_substream *substream)
> -{
> -       struct nvhdmi_spec *spec = codec->spec;
> -       hda_nid_t pin_nid;
> -       int i;
> -       struct hdmi_audio_infoframe ai = {
> -               .type           = 0x84,
> -               .ver            = 0x01,
> -               .len            = 0x0a,
> -               .CC02_CT47      = substream->runtime->channels - 1,
> -       };
> -
> -       hdmi_setup_channel_allocation(codec, nid, &ai);
> -
> -       for (i = 0; i < spec->num_pins; i++) {
> -               if (spec->pin_cvt[i] != nid)
> -                       continue;
> -               if (!spec->sink_eld[i].monitor_present)
> -                       continue;
> -
> -               pin_nid = spec->pin[i];
> -               if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
> -                       hdmi_setup_channel_mapping(codec, pin_nid, &ai);
> -                       hdmi_stop_infoframe_trans(codec, pin_nid);
> -                       hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
> -                       hdmi_start_infoframe_trans(codec, pin_nid);
> -               }
> -       }
> -}
> -
> -/*
> - * Unsolicited events
> - */
> -
> -static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
> -{
> -       struct nvhdmi_spec *spec = codec->spec;
> -       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
> -       int pind = !!(res & AC_UNSOL_RES_PD);
> -       int eldv = !!(res & AC_UNSOL_RES_ELDV);
> -       int index;
> -
> -       printk(KERN_INFO
> -               "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
> -               tag, pind, eldv);
> -
> -       index = hda_node_index(spec->pin, tag);
> -       if (index < 0)
> -               return;
> -
> -       spec->sink_eld[index].monitor_present = pind;
> -       spec->sink_eld[index].eld_valid = eldv;
> -
> -       if (eldv) {
> -               spec->sink_eld[index].monitor_present = 1;
> -               hdmi_get_show_eld(codec, spec->pin[index],
> -                                &spec->sink_eld[index]);
> -               /* TODO: do real things about ELD */
> -       }
> -}
> -
> -static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
> -{
> -       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
> -       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
> -       int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
> -       int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
> -
> -       printk(KERN_INFO
> -               "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
> -               tag,
> -               subtag,
> -               cp_state,
> -               cp_ready);
> -
> -       /* TODO */
> -       if (cp_state)
> -               ;
> -       if (cp_ready)
> -               ;
> -}
> -
> -static void nvhdmi_unsol_event(struct hda_codec *codec, unsigned int res)
> -{
> -       struct nvhdmi_spec *spec = codec->spec;
> -       int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
> -       int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
> -
> -       if (hda_node_index(spec->pin, tag) < 0) {
> -               snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
> -               return;
> -       }
> -
> -       if (subtag == 0)
> -               hdmi_intrinsic_event(codec, res);
> -       else
> -               hdmi_non_intrinsic_event(codec, res);
> -}
> -
> -/*
> - * Callbacks
> - */
> -
> -static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
> -                             u32 stream_tag, int format)
> -{
> -       int tag;
> -       int fmt;
> -
> -       tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
> -       fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
> -
> -       snd_printdd("hdmi_setup_stream: "
> -                   "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
> -                   nid,
> -                   tag == stream_tag ? "" : "new-",
> -                   stream_tag,
> -                   fmt == format ? "" : "new-",
> -                   format);
> -
> -       if (tag != stream_tag)
> -               snd_hda_codec_write(codec, nid, 0,
> -                                   AC_VERB_SET_CHANNEL_STREAMID,
> -                                   stream_tag << 4);
> -       if (fmt != format)
> -               snd_hda_codec_write(codec, nid, 0,
> -                                   AC_VERB_SET_STREAM_FORMAT, format);
> -}
> -
>  /*
>   * Controls
>   */
>  static int nvhdmi_build_controls(struct hda_codec *codec)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         int err;
>         int i;
> 
> @@ -902,7 +121,7 @@ static int nvhdmi_build_controls(struct
> 
>  static int nvhdmi_init(struct hda_codec *codec)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         int i;
>         if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
>         || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
> @@ -920,7 +139,7 @@ static int nvhdmi_init(struct hda_codec
> 
>  static void nvhdmi_free(struct hda_codec *codec)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         int i;
> 
>         if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
> @@ -939,7 +158,7 @@ static int nvhdmi_dig_playback_pcm_open(
>                                         struct hda_codec *codec,
>                                         struct snd_pcm_substream *substream)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
>  }
> 
> @@ -947,7 +166,7 @@ static int nvhdmi_dig_playback_pcm_close
>                                         struct hda_codec *codec,
>                                         struct snd_pcm_substream *substream)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         int i;
> 
>         snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
> @@ -968,7 +187,7 @@ static int nvhdmi_dig_playback_pcm_close
>                                         struct hda_codec *codec,
>                                         struct snd_pcm_substream *substream)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
>  }
> 
> @@ -1121,7 +340,7 @@ static int nvhdmi_dig_playback_pcm_prepa
>                                         unsigned int format,
>                                         struct snd_pcm_substream *substream)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
>                                         format, substream);
>  }
> @@ -1170,7 +389,7 @@ static struct hda_pcm_stream nvhdmi_pcm_
> 
>  static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         struct hda_pcm *info = spec->pcm_rec;
>         int i;
> 
> @@ -1196,7 +415,7 @@ static int nvhdmi_build_pcms_8ch_89(stru
> 
>  static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         struct hda_pcm *info = spec->pcm_rec;
> 
>         codec->num_pcms = 1;
> @@ -1212,7 +431,7 @@ static int nvhdmi_build_pcms_8ch_7x(stru
> 
>  static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
>  {
> -       struct nvhdmi_spec *spec = codec->spec;
> +       struct hdmi_spec *spec = codec->spec;
>         struct hda_pcm *info = spec->pcm_rec;
> 
>         codec->num_pcms = 1;
> @@ -1231,7 +450,7 @@ static struct hda_codec_ops nvhdmi_patch
>         .build_pcms = nvhdmi_build_pcms_8ch_89,
>         .init = nvhdmi_init,
>         .free = nvhdmi_free,
> -       .unsol_event = nvhdmi_unsol_event,
> +       .unsol_event = hdmi_unsol_event,
>  };
> 
>  static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
> @@ -1250,7 +469,7 @@ static struct hda_codec_ops nvhdmi_patch
> 
>  static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
>  {
> -       struct nvhdmi_spec *spec;
> +       struct hdmi_spec *spec;
>         int i;
> 
>         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
> @@ -1260,7 +479,7 @@ static int patch_nvhdmi_8ch_89(struct hd
>         codec->spec = spec;
>         spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
> 
> -       if (nvhdmi_parse_codec(codec) < 0) {
> +       if (hdmi_parse_codec(codec) < 0) {
>                 codec->spec = NULL;
>                 kfree(spec);
>                 return -EINVAL;
> @@ -1277,7 +496,7 @@ static int patch_nvhdmi_8ch_89(struct hd
> 
>  static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
>  {
> -       struct nvhdmi_spec *spec;
> +       struct hdmi_spec *spec;
> 
>         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
>         if (spec == NULL)
> @@ -1297,7 +516,7 @@ static int patch_nvhdmi_8ch_7x(struct hd
> 
>  static int patch_nvhdmi_2ch(struct hda_codec *codec)
>  {
> -       struct nvhdmi_spec *spec;
> +       struct hdmi_spec *spec;
> 
>         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
>         if (spec == NULL)

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04  2:21                 ` [alsa-devel] " Wei Ni
@ 2010-03-04  9:46                     ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-04  9:46 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

At Thu, 4 Mar 2010 10:21:39 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> 1. Yes, it can works for all Nvidia controller.

OK.

> 2. The hda_eld.o doesn't export any symbols.
> I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> from snd-had-codec-intelhdmi-objs, but it will build error. It need
> to modify hda_eld.c to export symbols, it will add many changes.

Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
appropriately.

We can reduce them again once after all HDMI stuff is merged into
one.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-04  9:46                     ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-04  9:46 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

At Thu, 4 Mar 2010 10:21:39 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> 1. Yes, it can works for all Nvidia controller.

OK.

> 2. The hda_eld.o doesn't export any symbols.
> I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> from snd-had-codec-intelhdmi-objs, but it will build error. It need
> to modify hda_eld.c to export symbols, it will add many changes.

Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
appropriately.

We can reduce them again once after all HDMI stuff is merged into
one.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04  9:46                     ` Takashi Iwai
@ 2010-03-04 10:46                       ` Wei Ni
  -1 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-04 10:46 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

Hi, Takashi
I think we can submit my patch first, then generate another patch
to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
hda_eld.o from snd-hda-codec-xxhdmi-objs.

Thanks
Wei.
nvpublic

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Thursday, March 04, 2010 5:47 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Thu, 4 Mar 2010 10:21:39 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> 1. Yes, it can works for all Nvidia controller.

OK.

> 2. The hda_eld.o doesn't export any symbols.
> I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> from snd-had-codec-intelhdmi-objs, but it will build error. It need
> to modify hda_eld.c to export symbols, it will add many changes.

Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
appropriately.

We can reduce them again once after all HDMI stuff is merged into
one.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-04 10:46                       ` Wei Ni
  0 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-04 10:46 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

Hi, Takashi
I think we can submit my patch first, then generate another patch
to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
hda_eld.o from snd-hda-codec-xxhdmi-objs.

Thanks
Wei.
nvpublic

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Thursday, March 04, 2010 5:47 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Thu, 4 Mar 2010 10:21:39 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> 1. Yes, it can works for all Nvidia controller.

OK.

> 2. The hda_eld.o doesn't export any symbols.
> I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> from snd-had-codec-intelhdmi-objs, but it will build error. It need
> to modify hda_eld.c to export symbols, it will add many changes.

Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
appropriately.

We can reduce them again once after all HDMI stuff is merged into
one.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04 10:46                       ` Wei Ni
@ 2010-03-04 10:56                         ` Takashi Iwai
  -1 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-04 10:56 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

At Thu, 4 Mar 2010 18:46:59 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I think we can submit my patch first,

But your patch breaks the build when CONFIG_SND_HDA_*=y.
So, it should be fixed in your patch.


thanks,

Takashi

> then generate another patch
> to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> hda_eld.o from snd-hda-codec-xxhdmi-objs.
> 
> Thanks
> Wei.
> nvpublic
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 5:47 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 10:21:39 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > 1. Yes, it can works for all Nvidia controller.
> 
> OK.
> 
> > 2. The hda_eld.o doesn't export any symbols.
> > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > to modify hda_eld.c to export symbols, it will add many changes.
> 
> Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> appropriately.
> 
> We can reduce them again once after all HDMI stuff is merged into
> one.
> 
> 
> thanks,
> 
> Takashi
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-04 10:56                         ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-04 10:56 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

At Thu, 4 Mar 2010 18:46:59 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I think we can submit my patch first,

But your patch breaks the build when CONFIG_SND_HDA_*=y.
So, it should be fixed in your patch.


thanks,

Takashi

> then generate another patch
> to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> hda_eld.o from snd-hda-codec-xxhdmi-objs.
> 
> Thanks
> Wei.
> nvpublic
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 5:47 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 10:21:39 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > 1. Yes, it can works for all Nvidia controller.
> 
> OK.
> 
> > 2. The hda_eld.o doesn't export any symbols.
> > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > to modify hda_eld.c to export symbols, it will add many changes.
> 
> Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> appropriately.
> 
> We can reduce them again once after all HDMI stuff is merged into
> one.
> 
> 
> thanks,
> 
> Takashi
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04 10:56                         ` Takashi Iwai
  (?)
@ 2010-03-04 11:09                         ` Wei Ni
  2010-03-04 11:31                             ` Takashi Iwai
  -1 siblings, 1 reply; 80+ messages in thread
From: Wei Ni @ 2010-03-04 11:09 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

Hi, Takashi
I test my patch, it build successful when CONFIG_SND_HDA_*=y.
Could you give me your build error messages?

Thanks
Wei.
nvpublic

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Thursday, March 04, 2010 6:57 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Thu, 4 Mar 2010 18:46:59 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I think we can submit my patch first,

But your patch breaks the build when CONFIG_SND_HDA_*=y.
So, it should be fixed in your patch.


thanks,

Takashi

> then generate another patch
> to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> hda_eld.o from snd-hda-codec-xxhdmi-objs.
> 
> Thanks
> Wei.
> nvpublic
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 5:47 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 10:21:39 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > 1. Yes, it can works for all Nvidia controller.
> 
> OK.
> 
> > 2. The hda_eld.o doesn't export any symbols.
> > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > to modify hda_eld.c to export symbols, it will add many changes.
> 
> Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> appropriately.
> 
> We can reduce them again once after all HDMI stuff is merged into
> one.
> 
> 
> thanks,
> 
> Takashi
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04 11:09                         ` [alsa-devel] " Wei Ni
@ 2010-03-04 11:31                             ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-04 11:31 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

At Thu, 4 Mar 2010 19:09:29 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I test my patch, it build successful when CONFIG_SND_HDA_*=y.
> Could you give me your build error messages?

Sorry, it's CONFIG_SND_HDA*=m.  Then load two modules, so you'll have
two identical objects in different modules.

OTOH, if it's no exported symbol, it might coexist.  Hmm.

If you get no errors with it, then it's fine as an intermediate state.
Please give the additional patch on them for further fixes.


thanks,

Takashi

> 
> Thanks
> Wei.
> nvpublic
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 6:57 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 18:46:59 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > I think we can submit my patch first,
> 
> But your patch breaks the build when CONFIG_SND_HDA_*=y.
> So, it should be fixed in your patch.
> 
> 
> thanks,
> 
> Takashi
> 
> > then generate another patch
> > to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> > hda_eld.o from snd-hda-codec-xxhdmi-objs.
> > 
> > Thanks
> > Wei.
> > nvpublic
> > 
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > Sent: Thursday, March 04, 2010 5:47 PM
> > To: Wei Ni
> > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > 
> > At Thu, 4 Mar 2010 10:21:39 +0800,
> > Wei Ni wrote:
> > > 
> > > Hi, Takashi
> > > 1. Yes, it can works for all Nvidia controller.
> > 
> > OK.
> > 
> > > 2. The hda_eld.o doesn't export any symbols.
> > > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > > to modify hda_eld.c to export symbols, it will add many changes.
> > 
> > Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> > appropriately.
> > 
> > We can reduce them again once after all HDMI stuff is merged into
> > one.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-04 11:31                             ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-04 11:31 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'akpm', 'alsa-devel', 'linux-kernel',
	'Pavel Hofman'

At Thu, 4 Mar 2010 19:09:29 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I test my patch, it build successful when CONFIG_SND_HDA_*=y.
> Could you give me your build error messages?

Sorry, it's CONFIG_SND_HDA*=m.  Then load two modules, so you'll have
two identical objects in different modules.

OTOH, if it's no exported symbol, it might coexist.  Hmm.

If you get no errors with it, then it's fine as an intermediate state.
Please give the additional patch on them for further fixes.


thanks,

Takashi

> 
> Thanks
> Wei.
> nvpublic
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 6:57 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 18:46:59 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > I think we can submit my patch first,
> 
> But your patch breaks the build when CONFIG_SND_HDA_*=y.
> So, it should be fixed in your patch.
> 
> 
> thanks,
> 
> Takashi
> 
> > then generate another patch
> > to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> > hda_eld.o from snd-hda-codec-xxhdmi-objs.
> > 
> > Thanks
> > Wei.
> > nvpublic
> > 
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > Sent: Thursday, March 04, 2010 5:47 PM
> > To: Wei Ni
> > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > 
> > At Thu, 4 Mar 2010 10:21:39 +0800,
> > Wei Ni wrote:
> > > 
> > > Hi, Takashi
> > > 1. Yes, it can works for all Nvidia controller.
> > 
> > OK.
> > 
> > > 2. The hda_eld.o doesn't export any symbols.
> > > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > > to modify hda_eld.c to export symbols, it will add many changes.
> > 
> > Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> > appropriately.
> > 
> > We can reduce them again once after all HDMI stuff is merged into
> > one.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04 11:31                             ` Takashi Iwai
  (?)
@ 2010-03-04 11:37                             ` Wei Ni
  2010-03-04 11:43                                 ` Takashi Iwai
  -1 siblings, 1 reply; 80+ messages in thread
From: Wei Ni @ 2010-03-04 11:37 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm'

Do you mean you will check in my patch first, and then I give you the
additional patch for adding EXPORT_SYMBOL() in hda_eld.c?

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Thursday, March 04, 2010 7:31 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Thu, 4 Mar 2010 19:09:29 +0800,
Wei Ni wrote:
> 
> Hi, Takashi
> I test my patch, it build successful when CONFIG_SND_HDA_*=y.
> Could you give me your build error messages?

Sorry, it's CONFIG_SND_HDA*=m.  Then load two modules, so you'll have
two identical objects in different modules.

OTOH, if it's no exported symbol, it might coexist.  Hmm.

If you get no errors with it, then it's fine as an intermediate state.
Please give the additional patch on them for further fixes.


thanks,

Takashi

> 
> Thanks
> Wei.
> nvpublic
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 6:57 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 18:46:59 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > I think we can submit my patch first,
> 
> But your patch breaks the build when CONFIG_SND_HDA_*=y.
> So, it should be fixed in your patch.
> 
> 
> thanks,
> 
> Takashi
> 
> > then generate another patch
> > to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> > hda_eld.o from snd-hda-codec-xxhdmi-objs.
> > 
> > Thanks
> > Wei.
> > nvpublic
> > 
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > Sent: Thursday, March 04, 2010 5:47 PM
> > To: Wei Ni
> > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > 
> > At Thu, 4 Mar 2010 10:21:39 +0800,
> > Wei Ni wrote:
> > > 
> > > Hi, Takashi
> > > 1. Yes, it can works for all Nvidia controller.
> > 
> > OK.
> > 
> > > 2. The hda_eld.o doesn't export any symbols.
> > > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > > to modify hda_eld.c to export symbols, it will add many changes.
> > 
> > Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> > appropriately.
> > 
> > We can reduce them again once after all HDMI stuff is merged into
> > one.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04 11:37                             ` [alsa-devel] " Wei Ni
@ 2010-03-04 11:43                                 ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-04 11:43 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm',
	Wu Fengguang

At Thu, 4 Mar 2010 19:37:52 +0800,
Wei Ni wrote:
> 
> Do you mean you will check in my patch first, and then I give you the
> additional patch for adding EXPORT_SYMBOL() in hda_eld.c?

Yes.  I need the integration tests first.
Meanwhile, prepare your patch on the top of your current patches.
Feel free to post it at any time.

After that, we can merge Fengguang's patch_hdmi.c change on that.


thanks,

Takashi


> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 7:31 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 19:09:29 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > I test my patch, it build successful when CONFIG_SND_HDA_*=y.
> > Could you give me your build error messages?
> 
> Sorry, it's CONFIG_SND_HDA*=m.  Then load two modules, so you'll have
> two identical objects in different modules.
> 
> OTOH, if it's no exported symbol, it might coexist.  Hmm.
> 
> If you get no errors with it, then it's fine as an intermediate state.
> Please give the additional patch on them for further fixes.
> 
> 
> thanks,
> 
> Takashi
> 
> > 
> > Thanks
> > Wei.
> > nvpublic
> > 
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > Sent: Thursday, March 04, 2010 6:57 PM
> > To: Wei Ni
> > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > 
> > At Thu, 4 Mar 2010 18:46:59 +0800,
> > Wei Ni wrote:
> > > 
> > > Hi, Takashi
> > > I think we can submit my patch first,
> > 
> > But your patch breaks the build when CONFIG_SND_HDA_*=y.
> > So, it should be fixed in your patch.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> > > then generate another patch
> > > to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> > > hda_eld.o from snd-hda-codec-xxhdmi-objs.
> > > 
> > > Thanks
> > > Wei.
> > > nvpublic
> > > 
> > > -----Original Message-----
> > > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > > Sent: Thursday, March 04, 2010 5:47 PM
> > > To: Wei Ni
> > > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > > 
> > > At Thu, 4 Mar 2010 10:21:39 +0800,
> > > Wei Ni wrote:
> > > > 
> > > > Hi, Takashi
> > > > 1. Yes, it can works for all Nvidia controller.
> > > 
> > > OK.
> > > 
> > > > 2. The hda_eld.o doesn't export any symbols.
> > > > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > > > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > > > to modify hda_eld.c to export symbols, it will add many changes.
> > > 
> > > Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> > > appropriately.
> > > 
> > > We can reduce them again once after all HDMI stuff is merged into
> > > one.
> > > 
> > > 
> > > thanks,
> > > 
> > > Takashi
> > > 
> > 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-04 11:43                                 ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-04 11:43 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'akpm', 'alsa-devel',
	Wu Fengguang, 'linux-kernel', 'Pavel Hofman'

At Thu, 4 Mar 2010 19:37:52 +0800,
Wei Ni wrote:
> 
> Do you mean you will check in my patch first, and then I give you the
> additional patch for adding EXPORT_SYMBOL() in hda_eld.c?

Yes.  I need the integration tests first.
Meanwhile, prepare your patch on the top of your current patches.
Feel free to post it at any time.

After that, we can merge Fengguang's patch_hdmi.c change on that.


thanks,

Takashi


> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 7:31 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 19:09:29 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > I test my patch, it build successful when CONFIG_SND_HDA_*=y.
> > Could you give me your build error messages?
> 
> Sorry, it's CONFIG_SND_HDA*=m.  Then load two modules, so you'll have
> two identical objects in different modules.
> 
> OTOH, if it's no exported symbol, it might coexist.  Hmm.
> 
> If you get no errors with it, then it's fine as an intermediate state.
> Please give the additional patch on them for further fixes.
> 
> 
> thanks,
> 
> Takashi
> 
> > 
> > Thanks
> > Wei.
> > nvpublic
> > 
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > Sent: Thursday, March 04, 2010 6:57 PM
> > To: Wei Ni
> > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > 
> > At Thu, 4 Mar 2010 18:46:59 +0800,
> > Wei Ni wrote:
> > > 
> > > Hi, Takashi
> > > I think we can submit my patch first,
> > 
> > But your patch breaks the build when CONFIG_SND_HDA_*=y.
> > So, it should be fixed in your patch.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> > > then generate another patch
> > > to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> > > hda_eld.o from snd-hda-codec-xxhdmi-objs.
> > > 
> > > Thanks
> > > Wei.
> > > nvpublic
> > > 
> > > -----Original Message-----
> > > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > > Sent: Thursday, March 04, 2010 5:47 PM
> > > To: Wei Ni
> > > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > > 
> > > At Thu, 4 Mar 2010 10:21:39 +0800,
> > > Wei Ni wrote:
> > > > 
> > > > Hi, Takashi
> > > > 1. Yes, it can works for all Nvidia controller.
> > > 
> > > OK.
> > > 
> > > > 2. The hda_eld.o doesn't export any symbols.
> > > > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > > > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > > > to modify hda_eld.c to export symbols, it will add many changes.
> > > 
> > > Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> > > appropriately.
> > > 
> > > We can reduce them again once after all HDMI stuff is merged into
> > > one.
> > > 
> > > 
> > > thanks,
> > > 
> > > Takashi
> > > 
> > 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04 11:43                                 ` Takashi Iwai
  (?)
@ 2010-03-04 11:46                                 ` Wei Ni
  2010-03-04 15:34                                   ` Takashi Iwai
  -1 siblings, 1 reply; 80+ messages in thread
From: Wei Ni @ 2010-03-04 11:46 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm',
	Wu Fengguang

Ok, I will give you the patch tomorrow.


-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Thursday, March 04, 2010 7:44 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'; Wu Fengguang
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Thu, 4 Mar 2010 19:37:52 +0800,
Wei Ni wrote:
> 
> Do you mean you will check in my patch first, and then I give you the
> additional patch for adding EXPORT_SYMBOL() in hda_eld.c?

Yes.  I need the integration tests first.
Meanwhile, prepare your patch on the top of your current patches.
Feel free to post it at any time.

After that, we can merge Fengguang's patch_hdmi.c change on that.


thanks,

Takashi


> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 7:31 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 19:09:29 +0800,
> Wei Ni wrote:
> > 
> > Hi, Takashi
> > I test my patch, it build successful when CONFIG_SND_HDA_*=y.
> > Could you give me your build error messages?
> 
> Sorry, it's CONFIG_SND_HDA*=m.  Then load two modules, so you'll have
> two identical objects in different modules.
> 
> OTOH, if it's no exported symbol, it might coexist.  Hmm.
> 
> If you get no errors with it, then it's fine as an intermediate state.
> Please give the additional patch on them for further fixes.
> 
> 
> thanks,
> 
> Takashi
> 
> > 
> > Thanks
> > Wei.
> > nvpublic
> > 
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > Sent: Thursday, March 04, 2010 6:57 PM
> > To: Wei Ni
> > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > 
> > At Thu, 4 Mar 2010 18:46:59 +0800,
> > Wei Ni wrote:
> > > 
> > > Hi, Takashi
> > > I think we can submit my patch first,
> > 
> > But your patch breaks the build when CONFIG_SND_HDA_*=y.
> > So, it should be fixed in your patch.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> > > then generate another patch
> > > to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> > > hda_eld.o from snd-hda-codec-xxhdmi-objs.
> > > 
> > > Thanks
> > > Wei.
> > > nvpublic
> > > 
> > > -----Original Message-----
> > > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > > Sent: Thursday, March 04, 2010 5:47 PM
> > > To: Wei Ni
> > > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > > 
> > > At Thu, 4 Mar 2010 10:21:39 +0800,
> > > Wei Ni wrote:
> > > > 
> > > > Hi, Takashi
> > > > 1. Yes, it can works for all Nvidia controller.
> > > 
> > > OK.
> > > 
> > > > 2. The hda_eld.o doesn't export any symbols.
> > > > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > > > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > > > to modify hda_eld.c to export symbols, it will add many changes.
> > > 
> > > Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> > > appropriately.
> > > 
> > > We can reduce them again once after all HDMI stuff is merged into
> > > one.
> > > 
> > > 
> > > thanks,
> > > 
> > > Takashi
> > > 
> > 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04 11:46                                 ` [alsa-devel] " Wei Ni
@ 2010-03-04 15:34                                   ` Takashi Iwai
  2010-03-05  2:41                                       ` Wei Ni
  0 siblings, 1 reply; 80+ messages in thread
From: Takashi Iwai @ 2010-03-04 15:34 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm',
	Wu Fengguang

At Thu, 4 Mar 2010 19:46:17 +0800,
Wei Ni wrote:
> 
> Ok, I will give you the patch tomorrow.

In the end, I fixed it by myself :)
If you have more other fixes, please take topic/hda branch of sound
git tree as basis.
  git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git topic/hda

Fengguang, could you rework your patch later for that version?


thanks,

Takashi

> 
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 7:44 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'; Wu Fengguang
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 19:37:52 +0800,
> Wei Ni wrote:
> > 
> > Do you mean you will check in my patch first, and then I give you the
> > additional patch for adding EXPORT_SYMBOL() in hda_eld.c?
> 
> Yes.  I need the integration tests first.
> Meanwhile, prepare your patch on the top of your current patches.
> Feel free to post it at any time.
> 
> After that, we can merge Fengguang's patch_hdmi.c change on that.
> 
> 
> thanks,
> 
> Takashi
> 
> 
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > Sent: Thursday, March 04, 2010 7:31 PM
> > To: Wei Ni
> > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > 
> > At Thu, 4 Mar 2010 19:09:29 +0800,
> > Wei Ni wrote:
> > > 
> > > Hi, Takashi
> > > I test my patch, it build successful when CONFIG_SND_HDA_*=y.
> > > Could you give me your build error messages?
> > 
> > Sorry, it's CONFIG_SND_HDA*=m.  Then load two modules, so you'll have
> > two identical objects in different modules.
> > 
> > OTOH, if it's no exported symbol, it might coexist.  Hmm.
> > 
> > If you get no errors with it, then it's fine as an intermediate state.
> > Please give the additional patch on them for further fixes.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> > > 
> > > Thanks
> > > Wei.
> > > nvpublic
> > > 
> > > -----Original Message-----
> > > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > > Sent: Thursday, March 04, 2010 6:57 PM
> > > To: Wei Ni
> > > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > > 
> > > At Thu, 4 Mar 2010 18:46:59 +0800,
> > > Wei Ni wrote:
> > > > 
> > > > Hi, Takashi
> > > > I think we can submit my patch first,
> > > 
> > > But your patch breaks the build when CONFIG_SND_HDA_*=y.
> > > So, it should be fixed in your patch.
> > > 
> > > 
> > > thanks,
> > > 
> > > Takashi
> > > 
> > > > then generate another patch
> > > > to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> > > > hda_eld.o from snd-hda-codec-xxhdmi-objs.
> > > > 
> > > > Thanks
> > > > Wei.
> > > > nvpublic
> > > > 
> > > > -----Original Message-----
> > > > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > > > Sent: Thursday, March 04, 2010 5:47 PM
> > > > To: Wei Ni
> > > > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > > > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > > > 
> > > > At Thu, 4 Mar 2010 10:21:39 +0800,
> > > > Wei Ni wrote:
> > > > > 
> > > > > Hi, Takashi
> > > > > 1. Yes, it can works for all Nvidia controller.
> > > > 
> > > > OK.
> > > > 
> > > > > 2. The hda_eld.o doesn't export any symbols.
> > > > > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > > > > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > > > > to modify hda_eld.c to export symbols, it will add many changes.
> > > > 
> > > > Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> > > > appropriately.
> > > > 
> > > > We can reduce them again once after all HDMI stuff is merged into
> > > > one.
> > > > 
> > > > 
> > > > thanks,
> > > > 
> > > > Takashi
> > > > 
> > > 
> > 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-04 15:34                                   ` Takashi Iwai
@ 2010-03-05  2:41                                       ` Wei Ni
  0 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-05  2:41 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'Pavel Hofman', 'alsa-devel',
	'linux-kernel', 'akpm',
	Wu Fengguang

Hi,Takashi
Oh, it's great.
In actually, I have lots of other work to do.

Thanks for your help.
Wei.
nvpublic

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Thursday, March 04, 2010 11:35 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'; Wu Fengguang
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Thu, 4 Mar 2010 19:46:17 +0800,
Wei Ni wrote:
> 
> Ok, I will give you the patch tomorrow.

In the end, I fixed it by myself :)
If you have more other fixes, please take topic/hda branch of sound
git tree as basis.
  git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git topic/hda

Fengguang, could you rework your patch later for that version?


thanks,

Takashi

> 
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 7:44 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'; Wu Fengguang
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 19:37:52 +0800,
> Wei Ni wrote:
> > 
> > Do you mean you will check in my patch first, and then I give you the
> > additional patch for adding EXPORT_SYMBOL() in hda_eld.c?
> 
> Yes.  I need the integration tests first.
> Meanwhile, prepare your patch on the top of your current patches.
> Feel free to post it at any time.
> 
> After that, we can merge Fengguang's patch_hdmi.c change on that.
> 
> 
> thanks,
> 
> Takashi
> 
> 
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > Sent: Thursday, March 04, 2010 7:31 PM
> > To: Wei Ni
> > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > 
> > At Thu, 4 Mar 2010 19:09:29 +0800,
> > Wei Ni wrote:
> > > 
> > > Hi, Takashi
> > > I test my patch, it build successful when CONFIG_SND_HDA_*=y.
> > > Could you give me your build error messages?
> > 
> > Sorry, it's CONFIG_SND_HDA*=m.  Then load two modules, so you'll have
> > two identical objects in different modules.
> > 
> > OTOH, if it's no exported symbol, it might coexist.  Hmm.
> > 
> > If you get no errors with it, then it's fine as an intermediate state.
> > Please give the additional patch on them for further fixes.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> > > 
> > > Thanks
> > > Wei.
> > > nvpublic
> > > 
> > > -----Original Message-----
> > > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > > Sent: Thursday, March 04, 2010 6:57 PM
> > > To: Wei Ni
> > > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > > 
> > > At Thu, 4 Mar 2010 18:46:59 +0800,
> > > Wei Ni wrote:
> > > > 
> > > > Hi, Takashi
> > > > I think we can submit my patch first,
> > > 
> > > But your patch breaks the build when CONFIG_SND_HDA_*=y.
> > > So, it should be fixed in your patch.
> > > 
> > > 
> > > thanks,
> > > 
> > > Takashi
> > > 
> > > > then generate another patch
> > > > to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> > > > hda_eld.o from snd-hda-codec-xxhdmi-objs.
> > > > 
> > > > Thanks
> > > > Wei.
> > > > nvpublic
> > > > 
> > > > -----Original Message-----
> > > > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > > > Sent: Thursday, March 04, 2010 5:47 PM
> > > > To: Wei Ni
> > > > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > > > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > > > 
> > > > At Thu, 4 Mar 2010 10:21:39 +0800,
> > > > Wei Ni wrote:
> > > > > 
> > > > > Hi, Takashi
> > > > > 1. Yes, it can works for all Nvidia controller.
> > > > 
> > > > OK.
> > > > 
> > > > > 2. The hda_eld.o doesn't export any symbols.
> > > > > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > > > > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > > > > to modify hda_eld.c to export symbols, it will add many changes.
> > > > 
> > > > Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> > > > appropriately.
> > > > 
> > > > We can reduce them again once after all HDMI stuff is merged into
> > > > one.
> > > > 
> > > > 
> > > > thanks,
> > > > 
> > > > Takashi
> > > > 
> > > 
> > 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-05  2:41                                       ` Wei Ni
  0 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-05  2:41 UTC (permalink / raw)
  To: 'Takashi Iwai'
  Cc: 'akpm', 'alsa-devel',
	Wu Fengguang, 'linux-kernel', 'Pavel Hofman'

Hi,Takashi
Oh, it's great.
In actually, I have lots of other work to do.

Thanks for your help.
Wei.
nvpublic

-----Original Message-----
From: Takashi Iwai [mailto:tiwai@suse.de] 
Sent: Thursday, March 04, 2010 11:35 PM
To: Wei Ni
Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'; Wu Fengguang
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

At Thu, 4 Mar 2010 19:46:17 +0800,
Wei Ni wrote:
> 
> Ok, I will give you the patch tomorrow.

In the end, I fixed it by myself :)
If you have more other fixes, please take topic/hda branch of sound
git tree as basis.
  git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git topic/hda

Fengguang, could you rework your patch later for that version?


thanks,

Takashi

> 
> 
> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai@suse.de] 
> Sent: Thursday, March 04, 2010 7:44 PM
> To: Wei Ni
> Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'; Wu Fengguang
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> At Thu, 4 Mar 2010 19:37:52 +0800,
> Wei Ni wrote:
> > 
> > Do you mean you will check in my patch first, and then I give you the
> > additional patch for adding EXPORT_SYMBOL() in hda_eld.c?
> 
> Yes.  I need the integration tests first.
> Meanwhile, prepare your patch on the top of your current patches.
> Feel free to post it at any time.
> 
> After that, we can merge Fengguang's patch_hdmi.c change on that.
> 
> 
> thanks,
> 
> Takashi
> 
> 
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > Sent: Thursday, March 04, 2010 7:31 PM
> > To: Wei Ni
> > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > 
> > At Thu, 4 Mar 2010 19:09:29 +0800,
> > Wei Ni wrote:
> > > 
> > > Hi, Takashi
> > > I test my patch, it build successful when CONFIG_SND_HDA_*=y.
> > > Could you give me your build error messages?
> > 
> > Sorry, it's CONFIG_SND_HDA*=m.  Then load two modules, so you'll have
> > two identical objects in different modules.
> > 
> > OTOH, if it's no exported symbol, it might coexist.  Hmm.
> > 
> > If you get no errors with it, then it's fine as an intermediate state.
> > Please give the additional patch on them for further fixes.
> > 
> > 
> > thanks,
> > 
> > Takashi
> > 
> > > 
> > > Thanks
> > > Wei.
> > > nvpublic
> > > 
> > > -----Original Message-----
> > > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > > Sent: Thursday, March 04, 2010 6:57 PM
> > > To: Wei Ni
> > > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > > 
> > > At Thu, 4 Mar 2010 18:46:59 +0800,
> > > Wei Ni wrote:
> > > > 
> > > > Hi, Takashi
> > > > I think we can submit my patch first,
> > > 
> > > But your patch breaks the build when CONFIG_SND_HDA_*=y.
> > > So, it should be fixed in your patch.
> > > 
> > > 
> > > thanks,
> > > 
> > > Takashi
> > > 
> > > > then generate another patch
> > > > to add EXPORT_SYMBOL() in hda_eld.c, and change Makefile to remove
> > > > hda_eld.o from snd-hda-codec-xxhdmi-objs.
> > > > 
> > > > Thanks
> > > > Wei.
> > > > nvpublic
> > > > 
> > > > -----Original Message-----
> > > > From: Takashi Iwai [mailto:tiwai@suse.de] 
> > > > Sent: Thursday, March 04, 2010 5:47 PM
> > > > To: Wei Ni
> > > > Cc: 'Pavel Hofman'; 'alsa-devel'; 'linux-kernel'; 'akpm'
> > > > Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> > > > 
> > > > At Thu, 4 Mar 2010 10:21:39 +0800,
> > > > Wei Ni wrote:
> > > > > 
> > > > > Hi, Takashi
> > > > > 1. Yes, it can works for all Nvidia controller.
> > > > 
> > > > OK.
> > > > 
> > > > > 2. The hda_eld.o doesn't export any symbols.
> > > > > I tried to put hda_eld.o to snd-had-codec-*, and remove had_eldo.o
> > > > > from snd-had-codec-intelhdmi-objs, but it will build error. It need
> > > > > to modify hda_eld.c to export symbols, it will add many changes.
> > > > 
> > > > Yes, this is unavoidable.  Please add EXPORT_SYMBOL()'s
> > > > appropriately.
> > > > 
> > > > We can reduce them again once after all HDMI stuff is merged into
> > > > one.
> > > > 
> > > > 
> > > > thanks,
> > > > 
> > > > Takashi
> > > > 
> > > 
> > 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-05  2:41                                       ` Wei Ni
@ 2010-03-07 19:21                                         ` VDR User
  -1 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-07 19:21 UTC (permalink / raw)
  To: Wei Ni
  Cc: Takashi Iwai, akpm, alsa-devel, Wu Fengguang, linux-kernel, Pavel Hofman

I think this may be relevant to this subject, if not then my apologies.

I've just installed a GT220 card and was able to get audio-over-hdmi
working by compiling the snapshot drivers from 20100307 which contain
Wei's new code.  I further had to patch the driver to recognize my
card with:

--- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
18:00:12.000000000 -0800
+++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
18:02:00.000000000 -0800
@@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
          .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000b, .name = "GT21x HDMI",
          .patch = patch_nvhdmi_8ch_89 },
+       { .id = 0x10de000a, .name = "GT220 HDMI",
+         .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000d, .name = "GT240 HDMI",
          .patch = patch_nvhdmi_8ch_89 },
        {} /* terminator */
@@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:10de000a");
 MODULE_ALIAS("snd-hda-codec-id:10de000c");
 MODULE_ALIAS("snd-hda-codec-id:10de000b");
 MODULE_ALIAS("snd-hda-codec-id:10de000d");

This seems to work fine when running VDR but if I do anything else
like upgrade packages, compile something, or maybe create a bz2, then
I start to see _a lot_ of the following in my xine log:

pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.

With the old code this didn't happen.  However, my setup was an 8400gs
using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
a dvi->hdmi cable into the tv.

Again, I apologize if I'm posting this in the wrong place.

Best regards.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-07 19:21                                         ` VDR User
  0 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-07 19:21 UTC (permalink / raw)
  To: Wei Ni
  Cc: alsa-devel, Takashi Iwai, linux-kernel, akpm, Wu Fengguang, Pavel Hofman

I think this may be relevant to this subject, if not then my apologies.

I've just installed a GT220 card and was able to get audio-over-hdmi
working by compiling the snapshot drivers from 20100307 which contain
Wei's new code.  I further had to patch the driver to recognize my
card with:

--- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
18:00:12.000000000 -0800
+++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
18:02:00.000000000 -0800
@@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
          .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000b, .name = "GT21x HDMI",
          .patch = patch_nvhdmi_8ch_89 },
+       { .id = 0x10de000a, .name = "GT220 HDMI",
+         .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000d, .name = "GT240 HDMI",
          .patch = patch_nvhdmi_8ch_89 },
        {} /* terminator */
@@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:10de000a");
 MODULE_ALIAS("snd-hda-codec-id:10de000c");
 MODULE_ALIAS("snd-hda-codec-id:10de000b");
 MODULE_ALIAS("snd-hda-codec-id:10de000d");

This seems to work fine when running VDR but if I do anything else
like upgrade packages, compile something, or maybe create a bz2, then
I start to see _a lot_ of the following in my xine log:

pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.

With the old code this didn't happen.  However, my setup was an 8400gs
using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
a dvi->hdmi cable into the tv.

Again, I apologize if I'm posting this in the wrong place.

Best regards.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* RE: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-07 19:21                                         ` VDR User
@ 2010-03-08  4:35                                           ` Wei Ni
  -1 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-08  4:35 UTC (permalink / raw)
  To: 'VDR User'
  Cc: Takashi Iwai, akpm, alsa-devel, Wu Fengguang, linux-kernel, Pavel Hofman

Hi,
Because I don't have GT220 card on hand, I didn't test it yet.
So I didn't add this card to the patch file. I think you could add it after
you test it.

About the warning messages, I don't know why.
May be some others can answer.

Thanks
Wei.
nvpublic

-----Original Message-----
From: VDR User [mailto:user.vdr@gmail.com] 
Sent: Monday, March 08, 2010 3:22 AM
To: Wei Ni
Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

I think this may be relevant to this subject, if not then my apologies.

I've just installed a GT220 card and was able to get audio-over-hdmi
working by compiling the snapshot drivers from 20100307 which contain
Wei's new code.  I further had to patch the driver to recognize my
card with:

--- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
18:00:12.000000000 -0800
+++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
18:02:00.000000000 -0800
@@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
          .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000b, .name = "GT21x HDMI",
          .patch = patch_nvhdmi_8ch_89 },
+       { .id = 0x10de000a, .name = "GT220 HDMI",
+         .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000d, .name = "GT240 HDMI",
          .patch = patch_nvhdmi_8ch_89 },
        {} /* terminator */
@@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:10de000a");
 MODULE_ALIAS("snd-hda-codec-id:10de000c");
 MODULE_ALIAS("snd-hda-codec-id:10de000b");
 MODULE_ALIAS("snd-hda-codec-id:10de000d");

This seems to work fine when running VDR but if I do anything else
like upgrade packages, compile something, or maybe create a bz2, then
I start to see _a lot_ of the following in my xine log:

pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.

With the old code this didn't happen.  However, my setup was an 8400gs
using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
a dvi->hdmi cable into the tv.

Again, I apologize if I'm posting this in the wrong place.

Best regards.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-08  4:35                                           ` Wei Ni
  0 siblings, 0 replies; 80+ messages in thread
From: Wei Ni @ 2010-03-08  4:35 UTC (permalink / raw)
  To: 'VDR User'
  Cc: alsa-devel, Takashi Iwai, linux-kernel, akpm, Wu Fengguang, Pavel Hofman

Hi,
Because I don't have GT220 card on hand, I didn't test it yet.
So I didn't add this card to the patch file. I think you could add it after
you test it.

About the warning messages, I don't know why.
May be some others can answer.

Thanks
Wei.
nvpublic

-----Original Message-----
From: VDR User [mailto:user.vdr@gmail.com] 
Sent: Monday, March 08, 2010 3:22 AM
To: Wei Ni
Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio

I think this may be relevant to this subject, if not then my apologies.

I've just installed a GT220 card and was able to get audio-over-hdmi
working by compiling the snapshot drivers from 20100307 which contain
Wei's new code.  I further had to patch the driver to recognize my
card with:

--- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
18:00:12.000000000 -0800
+++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
18:02:00.000000000 -0800
@@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
          .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000b, .name = "GT21x HDMI",
          .patch = patch_nvhdmi_8ch_89 },
+       { .id = 0x10de000a, .name = "GT220 HDMI",
+         .patch = patch_nvhdmi_8ch_89 },
        { .id = 0x10de000d, .name = "GT240 HDMI",
          .patch = patch_nvhdmi_8ch_89 },
        {} /* terminator */
@@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:10de000a");
 MODULE_ALIAS("snd-hda-codec-id:10de000c");
 MODULE_ALIAS("snd-hda-codec-id:10de000b");
 MODULE_ALIAS("snd-hda-codec-id:10de000d");

This seems to work fine when running VDR but if I do anything else
like upgrade packages, compile something, or maybe create a bz2, then
I start to see _a lot_ of the following in my xine log:

pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.

With the old code this didn't happen.  However, my setup was an 8400gs
using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
a dvi->hdmi cable into the tv.

Again, I apologize if I'm posting this in the wrong place.

Best regards.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-08  4:35                                           ` Wei Ni
@ 2010-03-08  4:46                                             ` Wu Fengguang
  -1 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-08  4:46 UTC (permalink / raw)
  To: Wei Ni
  Cc: 'VDR User',
	Takashi Iwai, akpm, alsa-devel, linux-kernel, Pavel Hofman,
	Jaroslav Kysela

CC Jaroslav, maybe he has some idea on

        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.

On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
> Hi,
> Because I don't have GT220 card on hand, I didn't test it yet.
> So I didn't add this card to the patch file. I think you could add it after
> you test it.
> 
> About the warning messages, I don't know why.
> May be some others can answer.
> 
> Thanks
> Wei.
> nvpublic
> 
> -----Original Message-----
> From: VDR User [mailto:user.vdr@gmail.com] 
> Sent: Monday, March 08, 2010 3:22 AM
> To: Wei Ni
> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> I think this may be relevant to this subject, if not then my apologies.
> 
> I've just installed a GT220 card and was able to get audio-over-hdmi
> working by compiling the snapshot drivers from 20100307 which contain
> Wei's new code.  I further had to patch the driver to recognize my
> card with:
> 
> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
> 18:00:12.000000000 -0800
> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
> 18:02:00.000000000 -0800
> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
>           .patch = patch_nvhdmi_8ch_89 },
>         { .id = 0x10de000b, .name = "GT21x HDMI",
>           .patch = patch_nvhdmi_8ch_89 },
> +       { .id = 0x10de000a, .name = "GT220 HDMI",
> +         .patch = patch_nvhdmi_8ch_89 },
>         { .id = 0x10de000d, .name = "GT240 HDMI",
>           .patch = patch_nvhdmi_8ch_89 },
>         {} /* terminator */
> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
> 
> This seems to work fine when running VDR but if I do anything else
> like upgrade packages, compile something, or maybe create a bz2, then
> I start to see _a lot_ of the following in my xine log:
> 
> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
> 
> With the old code this didn't happen.  However, my setup was an 8400gs
> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
> a dvi->hdmi cable into the tv.
> 
> Again, I apologize if I'm posting this in the wrong place.
> 
> Best regards.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-08  4:46                                             ` Wu Fengguang
  0 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-08  4:46 UTC (permalink / raw)
  To: Wei Ni
  Cc: alsa-devel, Takashi Iwai, linux-kernel, Jaroslav Kysela,
	'VDR User',
	akpm, Pavel Hofman

CC Jaroslav, maybe he has some idea on

        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.

On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
> Hi,
> Because I don't have GT220 card on hand, I didn't test it yet.
> So I didn't add this card to the patch file. I think you could add it after
> you test it.
> 
> About the warning messages, I don't know why.
> May be some others can answer.
> 
> Thanks
> Wei.
> nvpublic
> 
> -----Original Message-----
> From: VDR User [mailto:user.vdr@gmail.com] 
> Sent: Monday, March 08, 2010 3:22 AM
> To: Wei Ni
> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> 
> I think this may be relevant to this subject, if not then my apologies.
> 
> I've just installed a GT220 card and was able to get audio-over-hdmi
> working by compiling the snapshot drivers from 20100307 which contain
> Wei's new code.  I further had to patch the driver to recognize my
> card with:
> 
> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
> 18:00:12.000000000 -0800
> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
> 18:02:00.000000000 -0800
> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
>           .patch = patch_nvhdmi_8ch_89 },
>         { .id = 0x10de000b, .name = "GT21x HDMI",
>           .patch = patch_nvhdmi_8ch_89 },
> +       { .id = 0x10de000a, .name = "GT220 HDMI",
> +         .patch = patch_nvhdmi_8ch_89 },
>         { .id = 0x10de000d, .name = "GT240 HDMI",
>           .patch = patch_nvhdmi_8ch_89 },
>         {} /* terminator */
> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
> 
> This seems to work fine when running VDR but if I do anything else
> like upgrade packages, compile something, or maybe create a bz2, then
> I start to see _a lot_ of the following in my xine log:
> 
> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
> 
> With the old code this didn't happen.  However, my setup was an 8400gs
> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
> a dvi->hdmi cable into the tv.
> 
> Again, I apologize if I'm posting this in the wrong place.
> 
> Best regards.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-08  4:46                                             ` Wu Fengguang
@ 2010-03-10  5:42                                               ` VDR User
  -1 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-10  5:42 UTC (permalink / raw)
  To: Wu Fengguang
  Cc: Wei Ni, Takashi Iwai, akpm, alsa-devel, linux-kernel,
	Pavel Hofman, Jaroslav Kysela

On Sun, Mar 7, 2010 at 8:46 PM, Wu Fengguang <fengguang.wu@intel.com> wrote:
> CC Jaroslav, maybe he has some idea on
>
>        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>
> On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
>> Hi,
>> Because I don't have GT220 card on hand, I didn't test it yet.
>> So I didn't add this card to the patch file. I think you could add it after
>> you test it.
>>
>> About the warning messages, I don't know why.
>> May be some others can answer.
>>
>> Thanks
>> Wei.
>> nvpublic
>>
>> -----Original Message-----
>> From: VDR User [mailto:user.vdr@gmail.com]
>> Sent: Monday, March 08, 2010 3:22 AM
>> To: Wei Ni
>> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
>> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
>>
>> I think this may be relevant to this subject, if not then my apologies.
>>
>> I've just installed a GT220 card and was able to get audio-over-hdmi
>> working by compiling the snapshot drivers from 20100307 which contain
>> Wei's new code.  I further had to patch the driver to recognize my
>> card with:
>>
>> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
>> 18:00:12.000000000 -0800
>> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
>> 18:02:00.000000000 -0800
>> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
>>           .patch = patch_nvhdmi_8ch_89 },
>>         { .id = 0x10de000b, .name = "GT21x HDMI",
>>           .patch = patch_nvhdmi_8ch_89 },
>> +       { .id = 0x10de000a, .name = "GT220 HDMI",
>> +         .patch = patch_nvhdmi_8ch_89 },
>>         { .id = 0x10de000d, .name = "GT240 HDMI",
>>           .patch = patch_nvhdmi_8ch_89 },
>>         {} /* terminator */
>> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
>>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
>>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
>>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
>> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
>>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
>>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
>>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
>>
>> This seems to work fine when running VDR but if I do anything else
>> like upgrade packages, compile something, or maybe create a bz2, then
>> I start to see _a lot_ of the following in my xine log:
>>
>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>
>> With the old code this didn't happen.  However, my setup was an 8400gs
>> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
>> a dvi->hdmi cable into the tv.
>>
>> Again, I apologize if I'm posting this in the wrong place.
>>
>> Best regards.

So nobody has any ideas at all?  This is turning out to be a big
problem and I've discovered it will occur even without anything else
happening on the system.  (originally I thought you needed to do some
other activity.)  I've checked with some other devs I know and
everyone has said the problem is with alsa so it would seem there is a
serious bug somewhere since eventually those errors will happen and
the audio will start skipping like crazy.

Please let me know if there's anything I can do within my ability to help.

Best regards,
Derek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-10  5:42                                               ` VDR User
  0 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-10  5:42 UTC (permalink / raw)
  To: Wu Fengguang
  Cc: Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela, linux-kernel,
	akpm, Pavel Hofman

On Sun, Mar 7, 2010 at 8:46 PM, Wu Fengguang <fengguang.wu@intel.com> wrote:
> CC Jaroslav, maybe he has some idea on
>
>        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>
> On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
>> Hi,
>> Because I don't have GT220 card on hand, I didn't test it yet.
>> So I didn't add this card to the patch file. I think you could add it after
>> you test it.
>>
>> About the warning messages, I don't know why.
>> May be some others can answer.
>>
>> Thanks
>> Wei.
>> nvpublic
>>
>> -----Original Message-----
>> From: VDR User [mailto:user.vdr@gmail.com]
>> Sent: Monday, March 08, 2010 3:22 AM
>> To: Wei Ni
>> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
>> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
>>
>> I think this may be relevant to this subject, if not then my apologies.
>>
>> I've just installed a GT220 card and was able to get audio-over-hdmi
>> working by compiling the snapshot drivers from 20100307 which contain
>> Wei's new code.  I further had to patch the driver to recognize my
>> card with:
>>
>> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
>> 18:00:12.000000000 -0800
>> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
>> 18:02:00.000000000 -0800
>> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
>>           .patch = patch_nvhdmi_8ch_89 },
>>         { .id = 0x10de000b, .name = "GT21x HDMI",
>>           .patch = patch_nvhdmi_8ch_89 },
>> +       { .id = 0x10de000a, .name = "GT220 HDMI",
>> +         .patch = patch_nvhdmi_8ch_89 },
>>         { .id = 0x10de000d, .name = "GT240 HDMI",
>>           .patch = patch_nvhdmi_8ch_89 },
>>         {} /* terminator */
>> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
>>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
>>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
>>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
>> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
>>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
>>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
>>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
>>
>> This seems to work fine when running VDR but if I do anything else
>> like upgrade packages, compile something, or maybe create a bz2, then
>> I start to see _a lot_ of the following in my xine log:
>>
>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>
>> With the old code this didn't happen.  However, my setup was an 8400gs
>> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
>> a dvi->hdmi cable into the tv.
>>
>> Again, I apologize if I'm posting this in the wrong place.
>>
>> Best regards.

So nobody has any ideas at all?  This is turning out to be a big
problem and I've discovered it will occur even without anything else
happening on the system.  (originally I thought you needed to do some
other activity.)  I've checked with some other devs I know and
everyone has said the problem is with alsa so it would seem there is a
serious bug somewhere since eventually those errors will happen and
the audio will start skipping like crazy.

Please let me know if there's anything I can do within my ability to help.

Best regards,
Derek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-10  5:42                                               ` VDR User
@ 2010-03-10  6:01                                                 ` Wu Fengguang
  -1 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-10  6:01 UTC (permalink / raw)
  To: VDR User
  Cc: Wei Ni, Takashi Iwai, akpm, alsa-devel, linux-kernel,
	Pavel Hofman, Jaroslav Kysela

On Wed, Mar 10, 2010 at 01:42:05PM +0800, VDR User wrote:
> On Sun, Mar 7, 2010 at 8:46 PM, Wu Fengguang <fengguang.wu@intel.com> wrote:
> > CC Jaroslav, maybe he has some idea on
> >
> >        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
> >
> > On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
> >> Hi,
> >> Because I don't have GT220 card on hand, I didn't test it yet.
> >> So I didn't add this card to the patch file. I think you could add it after
> >> you test it.
> >>
> >> About the warning messages, I don't know why.
> >> May be some others can answer.
> >>
> >> Thanks
> >> Wei.
> >> nvpublic
> >>
> >> -----Original Message-----
> >> From: VDR User [mailto:user.vdr@gmail.com]
> >> Sent: Monday, March 08, 2010 3:22 AM
> >> To: Wei Ni
> >> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
> >> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> >>
> >> I think this may be relevant to this subject, if not then my apologies.
> >>
> >> I've just installed a GT220 card and was able to get audio-over-hdmi
> >> working by compiling the snapshot drivers from 20100307 which contain
> >> Wei's new code.  I further had to patch the driver to recognize my
> >> card with:
> >>
> >> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
> >> 18:00:12.000000000 -0800
> >> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
> >> 18:02:00.000000000 -0800
> >> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
> >>           .patch = patch_nvhdmi_8ch_89 },
> >>         { .id = 0x10de000b, .name = "GT21x HDMI",
> >>           .patch = patch_nvhdmi_8ch_89 },
> >> +       { .id = 0x10de000a, .name = "GT220 HDMI",
> >> +         .patch = patch_nvhdmi_8ch_89 },
> >>         { .id = 0x10de000d, .name = "GT240 HDMI",
> >>           .patch = patch_nvhdmi_8ch_89 },
> >>         {} /* terminator */
> >> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
> >>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
> >> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
> >>
> >> This seems to work fine when running VDR but if I do anything else
> >> like upgrade packages, compile something, or maybe create a bz2, then
> >> I start to see _a lot_ of the following in my xine log:
> >>
> >> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
> >>
> >> With the old code this didn't happen.  However, my setup was an 8400gs
> >> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
> >> a dvi->hdmi cable into the tv.
> >>
> >> Again, I apologize if I'm posting this in the wrong place.
> >>
> >> Best regards.
> 
> So nobody has any ideas at all?  This is turning out to be a big
> problem and I've discovered it will occur even without anything else
> happening on the system.  (originally I thought you needed to do some
> other activity.)  I've checked with some other devs I know and
> everyone has said the problem is with alsa so it would seem there is a
> serious bug somewhere since eventually those errors will happen and
> the audio will start skipping like crazy.
> 
> Please let me know if there's anything I can do within my ability to help.

The first step would be to run vanilla 2.6.33 with Wei Ni's patch,
in order to tell whether the bug is internal to the HDMI code, or is
introduced by bleeding edge ALSA development.

Thanks,
Fengguang

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-10  6:01                                                 ` Wu Fengguang
  0 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-10  6:01 UTC (permalink / raw)
  To: VDR User
  Cc: Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela, linux-kernel,
	akpm, Pavel Hofman

On Wed, Mar 10, 2010 at 01:42:05PM +0800, VDR User wrote:
> On Sun, Mar 7, 2010 at 8:46 PM, Wu Fengguang <fengguang.wu@intel.com> wrote:
> > CC Jaroslav, maybe he has some idea on
> >
> >        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
> >
> > On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
> >> Hi,
> >> Because I don't have GT220 card on hand, I didn't test it yet.
> >> So I didn't add this card to the patch file. I think you could add it after
> >> you test it.
> >>
> >> About the warning messages, I don't know why.
> >> May be some others can answer.
> >>
> >> Thanks
> >> Wei.
> >> nvpublic
> >>
> >> -----Original Message-----
> >> From: VDR User [mailto:user.vdr@gmail.com]
> >> Sent: Monday, March 08, 2010 3:22 AM
> >> To: Wei Ni
> >> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
> >> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> >>
> >> I think this may be relevant to this subject, if not then my apologies.
> >>
> >> I've just installed a GT220 card and was able to get audio-over-hdmi
> >> working by compiling the snapshot drivers from 20100307 which contain
> >> Wei's new code.  I further had to patch the driver to recognize my
> >> card with:
> >>
> >> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
> >> 18:00:12.000000000 -0800
> >> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
> >> 18:02:00.000000000 -0800
> >> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
> >>           .patch = patch_nvhdmi_8ch_89 },
> >>         { .id = 0x10de000b, .name = "GT21x HDMI",
> >>           .patch = patch_nvhdmi_8ch_89 },
> >> +       { .id = 0x10de000a, .name = "GT220 HDMI",
> >> +         .patch = patch_nvhdmi_8ch_89 },
> >>         { .id = 0x10de000d, .name = "GT240 HDMI",
> >>           .patch = patch_nvhdmi_8ch_89 },
> >>         {} /* terminator */
> >> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
> >>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
> >> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
> >>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
> >>
> >> This seems to work fine when running VDR but if I do anything else
> >> like upgrade packages, compile something, or maybe create a bz2, then
> >> I start to see _a lot_ of the following in my xine log:
> >>
> >> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
> >>
> >> With the old code this didn't happen.  However, my setup was an 8400gs
> >> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
> >> a dvi->hdmi cable into the tv.
> >>
> >> Again, I apologize if I'm posting this in the wrong place.
> >>
> >> Best regards.
> 
> So nobody has any ideas at all?  This is turning out to be a big
> problem and I've discovered it will occur even without anything else
> happening on the system.  (originally I thought you needed to do some
> other activity.)  I've checked with some other devs I know and
> everyone has said the problem is with alsa so it would seem there is a
> serious bug somewhere since eventually those errors will happen and
> the audio will start skipping like crazy.
> 
> Please let me know if there's anything I can do within my ability to help.

The first step would be to run vanilla 2.6.33 with Wei Ni's patch,
in order to tell whether the bug is internal to the HDMI code, or is
introduced by bleeding edge ALSA development.

Thanks,
Fengguang
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-10  5:42                                               ` VDR User
@ 2010-03-10  7:58                                                 ` Jaroslav Kysela
  -1 siblings, 0 replies; 80+ messages in thread
From: Jaroslav Kysela @ 2010-03-10  7:58 UTC (permalink / raw)
  To: VDR User
  Cc: Wu Fengguang, Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela,
	linux-kernel, akpm, Pavel Hofman

[-- Attachment #1: Type: TEXT/PLAIN, Size: 3705 bytes --]

On Tue, 9 Mar 2010, VDR User wrote:

> On Sun, Mar 7, 2010 at 8:46 PM, Wu Fengguang <fengguang.wu@intel.com> wrote:
>> CC Jaroslav, maybe he has some idea on
>>
>>        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>
>> On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
>>> Hi,
>>> Because I don't have GT220 card on hand, I didn't test it yet.
>>> So I didn't add this card to the patch file. I think you could add it after
>>> you test it.
>>>
>>> About the warning messages, I don't know why.
>>> May be some others can answer.
>>>
>>> Thanks
>>> Wei.
>>> nvpublic
>>>
>>> -----Original Message-----
>>> From: VDR User [mailto:user.vdr@gmail.com]
>>> Sent: Monday, March 08, 2010 3:22 AM
>>> To: Wei Ni
>>> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
>>> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
>>>
>>> I think this may be relevant to this subject, if not then my apologies.
>>>
>>> I've just installed a GT220 card and was able to get audio-over-hdmi
>>> working by compiling the snapshot drivers from 20100307 which contain
>>> Wei's new code.  I further had to patch the driver to recognize my
>>> card with:
>>>
>>> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
>>> 18:00:12.000000000 -0800
>>> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
>>> 18:02:00.000000000 -0800
>>> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
>>>           .patch = patch_nvhdmi_8ch_89 },
>>>         { .id = 0x10de000b, .name = "GT21x HDMI",
>>>           .patch = patch_nvhdmi_8ch_89 },
>>> +       { .id = 0x10de000a, .name = "GT220 HDMI",
>>> +         .patch = patch_nvhdmi_8ch_89 },
>>>         { .id = 0x10de000d, .name = "GT240 HDMI",
>>>           .patch = patch_nvhdmi_8ch_89 },
>>>         {} /* terminator */
>>> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
>>>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
>>> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
>>>
>>> This seems to work fine when running VDR but if I do anything else
>>> like upgrade packages, compile something, or maybe create a bz2, then
>>> I start to see _a lot_ of the following in my xine log:
>>>
>>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>>
>>> With the old code this didn't happen.  However, my setup was an 8400gs
>>> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
>>> a dvi->hdmi cable into the tv.
>>>
>>> Again, I apologize if I'm posting this in the wrong place.
>>>
>>> Best regards.
>
> So nobody has any ideas at all?  This is turning out to be a big
> problem and I've discovered it will occur even without anything else
> happening on the system.  (originally I thought you needed to do some
> other activity.)  I've checked with some other devs I know and
> everyone has said the problem is with alsa so it would seem there is a
> serious bug somewhere since eventually those errors will happen and
> the audio will start skipping like crazy.
>
> Please let me know if there's anything I can do within my ability to help.

Could you do strace for ALSA ioctls? At least having the error code might 
help to identify this issue.

 					Jaroslav

-----
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-10  7:58                                                 ` Jaroslav Kysela
  0 siblings, 0 replies; 80+ messages in thread
From: Jaroslav Kysela @ 2010-03-10  7:58 UTC (permalink / raw)
  To: VDR User
  Cc: Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela, linux-kernel,
	akpm, Wu Fengguang, Pavel Hofman

[-- Attachment #1: Type: TEXT/PLAIN, Size: 3705 bytes --]

On Tue, 9 Mar 2010, VDR User wrote:

> On Sun, Mar 7, 2010 at 8:46 PM, Wu Fengguang <fengguang.wu@intel.com> wrote:
>> CC Jaroslav, maybe he has some idea on
>>
>>        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>
>> On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
>>> Hi,
>>> Because I don't have GT220 card on hand, I didn't test it yet.
>>> So I didn't add this card to the patch file. I think you could add it after
>>> you test it.
>>>
>>> About the warning messages, I don't know why.
>>> May be some others can answer.
>>>
>>> Thanks
>>> Wei.
>>> nvpublic
>>>
>>> -----Original Message-----
>>> From: VDR User [mailto:user.vdr@gmail.com]
>>> Sent: Monday, March 08, 2010 3:22 AM
>>> To: Wei Ni
>>> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel Hofman
>>> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
>>>
>>> I think this may be relevant to this subject, if not then my apologies.
>>>
>>> I've just installed a GT220 card and was able to get audio-over-hdmi
>>> working by compiling the snapshot drivers from 20100307 which contain
>>> Wei's new code.  I further had to patch the driver to recognize my
>>> card with:
>>>
>>> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
>>> 18:00:12.000000000 -0800
>>> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
>>> 18:02:00.000000000 -0800
>>> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
>>>           .patch = patch_nvhdmi_8ch_89 },
>>>         { .id = 0x10de000b, .name = "GT21x HDMI",
>>>           .patch = patch_nvhdmi_8ch_89 },
>>> +       { .id = 0x10de000a, .name = "GT220 HDMI",
>>> +         .patch = patch_nvhdmi_8ch_89 },
>>>         { .id = 0x10de000d, .name = "GT240 HDMI",
>>>           .patch = patch_nvhdmi_8ch_89 },
>>>         {} /* terminator */
>>> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
>>>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
>>> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
>>>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
>>>
>>> This seems to work fine when running VDR but if I do anything else
>>> like upgrade packages, compile something, or maybe create a bz2, then
>>> I start to see _a lot_ of the following in my xine log:
>>>
>>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>>
>>> With the old code this didn't happen.  However, my setup was an 8400gs
>>> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
>>> a dvi->hdmi cable into the tv.
>>>
>>> Again, I apologize if I'm posting this in the wrong place.
>>>
>>> Best regards.
>
> So nobody has any ideas at all?  This is turning out to be a big
> problem and I've discovered it will occur even without anything else
> happening on the system.  (originally I thought you needed to do some
> other activity.)  I've checked with some other devs I know and
> everyone has said the problem is with alsa so it would seem there is a
> serious bug somewhere since eventually those errors will happen and
> the audio will start skipping like crazy.
>
> Please let me know if there's anything I can do within my ability to help.

Could you do strace for ALSA ioctls? At least having the error code might 
help to identify this issue.

 					Jaroslav

-----
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-10  7:58                                                 ` Jaroslav Kysela
  (?)
@ 2010-03-10  8:05                                                 ` VDR User
  2010-03-10  8:17                                                   ` Jaroslav Kysela
  2010-03-10 12:54                                                     ` Wu Fengguang
  -1 siblings, 2 replies; 80+ messages in thread
From: VDR User @ 2010-03-10  8:05 UTC (permalink / raw)
  To: Jaroslav Kysela
  Cc: Wu Fengguang, Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela,
	linux-kernel, akpm, Pavel Hofman

On Tue, Mar 9, 2010 at 11:58 PM, Jaroslav Kysela <perex@perex.cz> wrote:
> On Tue, 9 Mar 2010, VDR User wrote:
>
>> On Sun, Mar 7, 2010 at 8:46 PM, Wu Fengguang <fengguang.wu@intel.com>
>> wrote:
>>>
>>> CC Jaroslav, maybe he has some idea on
>>>
>>>        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>>
>>> On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
>>>>
>>>> Hi,
>>>> Because I don't have GT220 card on hand, I didn't test it yet.
>>>> So I didn't add this card to the patch file. I think you could add it
>>>> after
>>>> you test it.
>>>>
>>>> About the warning messages, I don't know why.
>>>> May be some others can answer.
>>>>
>>>> Thanks
>>>> Wei.
>>>> nvpublic
>>>>
>>>> -----Original Message-----
>>>> From: VDR User [mailto:user.vdr@gmail.com]
>>>> Sent: Monday, March 08, 2010 3:22 AM
>>>> To: Wei Ni
>>>> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel
>>>> Hofman
>>>> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
>>>>
>>>> I think this may be relevant to this subject, if not then my apologies.
>>>>
>>>> I've just installed a GT220 card and was able to get audio-over-hdmi
>>>> working by compiling the snapshot drivers from 20100307 which contain
>>>> Wei's new code.  I further had to patch the driver to recognize my
>>>> card with:
>>>>
>>>> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
>>>> 18:00:12.000000000 -0800
>>>> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
>>>> 18:02:00.000000000 -0800
>>>> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
>>>>           .patch = patch_nvhdmi_8ch_89 },
>>>>         { .id = 0x10de000b, .name = "GT21x HDMI",
>>>>           .patch = patch_nvhdmi_8ch_89 },
>>>> +       { .id = 0x10de000a, .name = "GT220 HDMI",
>>>> +         .patch = patch_nvhdmi_8ch_89 },
>>>>         { .id = 0x10de000d, .name = "GT240 HDMI",
>>>>           .patch = patch_nvhdmi_8ch_89 },
>>>>         {} /* terminator */
>>>> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
>>>>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
>>>>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
>>>>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
>>>> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
>>>>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
>>>>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
>>>>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
>>>>
>>>> This seems to work fine when running VDR but if I do anything else
>>>> like upgrade packages, compile something, or maybe create a bz2, then
>>>> I start to see _a lot_ of the following in my xine log:
>>>>
>>>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>>>
>>>> With the old code this didn't happen.  However, my setup was an 8400gs
>>>> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
>>>> a dvi->hdmi cable into the tv.
>>>>
>>>> Again, I apologize if I'm posting this in the wrong place.
>>>>
>>>> Best regards.
>>
>> So nobody has any ideas at all?  This is turning out to be a big
>> problem and I've discovered it will occur even without anything else
>> happening on the system.  (originally I thought you needed to do some
>> other activity.)  I've checked with some other devs I know and
>> everyone has said the problem is with alsa so it would seem there is a
>> serious bug somewhere since eventually those errors will happen and
>> the audio will start skipping like crazy.
>>
>> Please let me know if there's anything I can do within my ability to help.
>
> Could you do strace for ALSA ioctls? At least having the error code might
> help to identify this issue.

I don't know how but I'm willing to try if you want to tell me how to
do it.  Please keep in mind, I'm just an end-user -- not a developer
or even c coder.  The most I've done is run xine in gdb to help supply
bug info to those devs.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-10  8:05                                                 ` [alsa-devel] " VDR User
@ 2010-03-10  8:17                                                   ` Jaroslav Kysela
  2010-03-10  9:44                                                     ` Takashi Iwai
  2010-03-10 12:54                                                     ` Wu Fengguang
  1 sibling, 1 reply; 80+ messages in thread
From: Jaroslav Kysela @ 2010-03-10  8:17 UTC (permalink / raw)
  To: VDR User; +Cc: alsa-devel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 4308 bytes --]

On Wed, 10 Mar 2010, VDR User wrote:

> On Tue, Mar 9, 2010 at 11:58 PM, Jaroslav Kysela <perex@perex.cz> wrote:
>> On Tue, 9 Mar 2010, VDR User wrote:
>>
>>> On Sun, Mar 7, 2010 at 8:46 PM, Wu Fengguang <fengguang.wu@intel.com>
>>> wrote:
>>>>
>>>> CC Jaroslav, maybe he has some idea on
>>>>
>>>>        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>>>
>>>> On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
>>>>>
>>>>> Hi,
>>>>> Because I don't have GT220 card on hand, I didn't test it yet.
>>>>> So I didn't add this card to the patch file. I think you could add it
>>>>> after
>>>>> you test it.
>>>>>
>>>>> About the warning messages, I don't know why.
>>>>> May be some others can answer.
>>>>>
>>>>> Thanks
>>>>> Wei.
>>>>> nvpublic
>>>>>
>>>>> -----Original Message-----
>>>>> From: VDR User [mailto:user.vdr@gmail.com]
>>>>> Sent: Monday, March 08, 2010 3:22 AM
>>>>> To: Wei Ni
>>>>> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel
>>>>> Hofman
>>>>> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
>>>>>
>>>>> I think this may be relevant to this subject, if not then my apologies.
>>>>>
>>>>> I've just installed a GT220 card and was able to get audio-over-hdmi
>>>>> working by compiling the snapshot drivers from 20100307 which contain
>>>>> Wei's new code.  I further had to patch the driver to recognize my
>>>>> card with:
>>>>>
>>>>> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
>>>>> 18:00:12.000000000 -0800
>>>>> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
>>>>> 18:02:00.000000000 -0800
>>>>> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
>>>>>           .patch = patch_nvhdmi_8ch_89 },
>>>>>         { .id = 0x10de000b, .name = "GT21x HDMI",
>>>>>           .patch = patch_nvhdmi_8ch_89 },
>>>>> +       { .id = 0x10de000a, .name = "GT220 HDMI",
>>>>> +         .patch = patch_nvhdmi_8ch_89 },
>>>>>         { .id = 0x10de000d, .name = "GT240 HDMI",
>>>>>           .patch = patch_nvhdmi_8ch_89 },
>>>>>         {} /* terminator */
>>>>> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
>>>>>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
>>>>>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
>>>>>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
>>>>> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
>>>>>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
>>>>>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
>>>>>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
>>>>>
>>>>> This seems to work fine when running VDR but if I do anything else
>>>>> like upgrade packages, compile something, or maybe create a bz2, then
>>>>> I start to see _a lot_ of the following in my xine log:
>>>>>
>>>>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>>>>
>>>>> With the old code this didn't happen.  However, my setup was an 8400gs
>>>>> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
>>>>> a dvi->hdmi cable into the tv.
>>>>>
>>>>> Again, I apologize if I'm posting this in the wrong place.
>>>>>
>>>>> Best regards.
>>>
>>> So nobody has any ideas at all?  This is turning out to be a big
>>> problem and I've discovered it will occur even without anything else
>>> happening on the system.  (originally I thought you needed to do some
>>> other activity.)  I've checked with some other devs I know and
>>> everyone has said the problem is with alsa so it would seem there is a
>>> serious bug somewhere since eventually those errors will happen and
>>> the audio will start skipping like crazy.
>>>
>>> Please let me know if there's anything I can do within my ability to help.
>>
>> Could you do strace for ALSA ioctls? At least having the error code might
>> help to identify this issue.
>
> I don't know how but I'm willing to try if you want to tell me how to
> do it.  Please keep in mind, I'm just an end-user -- not a developer
> or even c coder.  The most I've done is run xine in gdb to help supply
> bug info to those devs.

strace -e trace=open,ioctl <xine>

 					Jaroslav

-----
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-10  8:17                                                   ` Jaroslav Kysela
@ 2010-03-10  9:44                                                     ` Takashi Iwai
  0 siblings, 0 replies; 80+ messages in thread
From: Takashi Iwai @ 2010-03-10  9:44 UTC (permalink / raw)
  To: Jaroslav Kysela; +Cc: VDR User, alsa-devel

At Wed, 10 Mar 2010 09:17:16 +0100 (CET),
Jaroslav Kysela wrote:
> 
> On Wed, 10 Mar 2010, VDR User wrote:
> 
> > On Tue, Mar 9, 2010 at 11:58 PM, Jaroslav Kysela <perex@perex.cz> wrote:
> >> On Tue, 9 Mar 2010, VDR User wrote:
> >>
> >>> On Sun, Mar 7, 2010 at 8:46 PM, Wu Fengguang <fengguang.wu@intel.com>
> >>> wrote:
> >>>>
> >>>> CC Jaroslav, maybe he has some idea on
> >>>>
> >>>>        pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
> >>>>
> >>>> On Mon, Mar 08, 2010 at 12:35:37PM +0800, Wei Ni wrote:
> >>>>>
> >>>>> Hi,
> >>>>> Because I don't have GT220 card on hand, I didn't test it yet.
> >>>>> So I didn't add this card to the patch file. I think you could add it
> >>>>> after
> >>>>> you test it.
> >>>>>
> >>>>> About the warning messages, I don't know why.
> >>>>> May be some others can answer.
> >>>>>
> >>>>> Thanks
> >>>>> Wei.
> >>>>> nvpublic
> >>>>>
> >>>>> -----Original Message-----
> >>>>> From: VDR User [mailto:user.vdr@gmail.com]
> >>>>> Sent: Monday, March 08, 2010 3:22 AM
> >>>>> To: Wei Ni
> >>>>> Cc: Takashi Iwai; akpm; alsa-devel; Wu Fengguang; linux-kernel; Pavel
> >>>>> Hofman
> >>>>> Subject: Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
> >>>>>
> >>>>> I think this may be relevant to this subject, if not then my apologies.
> >>>>>
> >>>>> I've just installed a GT220 card and was able to get audio-over-hdmi
> >>>>> working by compiling the snapshot drivers from 20100307 which contain
> >>>>> Wei's new code.  I further had to patch the driver to recognize my
> >>>>> card with:
> >>>>>
> >>>>> --- alsa-driver-orig/alsa-kernel/pci/hda/patch_nvhdmi.c 2010-03-06
> >>>>> 18:00:12.000000000 -0800
> >>>>> +++ alsa-driver/alsa-kernel/pci/hda/patch_nvhdmi.c      2010-03-06
> >>>>> 18:02:00.000000000 -0800
> >>>>> @@ -1335,6 +1335,8 @@ static struct hda_codec_preset snd_hda_p
> >>>>>           .patch = patch_nvhdmi_8ch_89 },
> >>>>>         { .id = 0x10de000b, .name = "GT21x HDMI",
> >>>>>           .patch = patch_nvhdmi_8ch_89 },
> >>>>> +       { .id = 0x10de000a, .name = "GT220 HDMI",
> >>>>> +         .patch = patch_nvhdmi_8ch_89 },
> >>>>>         { .id = 0x10de000d, .name = "GT240 HDMI",
> >>>>>           .patch = patch_nvhdmi_8ch_89 },
> >>>>>         {} /* terminator */
> >>>>> @@ -1347,6 +1349,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"
> >>>>>  MODULE_ALIAS("snd-hda-codec-id:10de0007");
> >>>>>  MODULE_ALIAS("snd-hda-codec-id:10de0067");
> >>>>>  MODULE_ALIAS("snd-hda-codec-id:10de8001");
> >>>>> +MODULE_ALIAS("snd-hda-codec-id:10de000a");
> >>>>>  MODULE_ALIAS("snd-hda-codec-id:10de000c");
> >>>>>  MODULE_ALIAS("snd-hda-codec-id:10de000b");
> >>>>>  MODULE_ALIAS("snd-hda-codec-id:10de000d");
> >>>>>
> >>>>> This seems to work fine when running VDR but if I do anything else
> >>>>> like upgrade packages, compile something, or maybe create a bz2, then
> >>>>> I start to see _a lot_ of the following in my xine log:
> >>>>>
> >>>>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
> >>>>>
> >>>>> With the old code this didn't happen.  However, my setup was an 8400gs
> >>>>> using SPDIF OUT from my mainboard to SPDIF IN on the card.  Then using
> >>>>> a dvi->hdmi cable into the tv.
> >>>>>
> >>>>> Again, I apologize if I'm posting this in the wrong place.
> >>>>>
> >>>>> Best regards.
> >>>
> >>> So nobody has any ideas at all?  This is turning out to be a big
> >>> problem and I've discovered it will occur even without anything else
> >>> happening on the system.  (originally I thought you needed to do some
> >>> other activity.)  I've checked with some other devs I know and
> >>> everyone has said the problem is with alsa so it would seem there is a
> >>> serious bug somewhere since eventually those errors will happen and
> >>> the audio will start skipping like crazy.
> >>>
> >>> Please let me know if there's anything I can do within my ability to help.
> >>
> >> Could you do strace for ALSA ioctls? At least having the error code might
> >> help to identify this issue.
> >
> > I don't know how but I'm willing to try if you want to tell me how to
> > do it.  Please keep in mind, I'm just an end-user -- not a developer
> > or even c coder.  The most I've done is run xine in gdb to help supply
> > bug info to those devs.
> 
> strace -e trace=open,ioctl <xine>

Better to add -f, too, for a program like xine.


Takashi
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-10  8:05                                                 ` [alsa-devel] " VDR User
@ 2010-03-10 12:54                                                     ` Wu Fengguang
  2010-03-10 12:54                                                     ` Wu Fengguang
  1 sibling, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-10 12:54 UTC (permalink / raw)
  To: VDR User
  Cc: Jaroslav Kysela, Wei Ni, Takashi Iwai, alsa-devel,
	Jaroslav Kysela, linux-kernel, akpm, Pavel Hofman

> > Could you do strace for ALSA ioctls? At least having the error code might
> > help to identify this issue.
> 
> I don't know how but I'm willing to try if you want to tell me how to
> do it.  Please keep in mind, I'm just an end-user -- not a developer
> or even c coder.  The most I've done is run xine in gdb to help supply
> bug info to those devs.

strace -o alsa-strace  speaker-test -Dhw:0,3 -t wav -c2 -l1                

Or 

strace -o alsa-strace  mplayer -ao alsa:device=hw=0.3 XXXXXXXX.mp3


Do you see error messages when playing via other audio devices, eg.

        mplayer -ao alsa:device=hw=0.0 XXXXXXXX.mp3

?

Thanks,
Fengguang

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-10 12:54                                                     ` Wu Fengguang
  0 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-10 12:54 UTC (permalink / raw)
  To: VDR User
  Cc: Wei Ni, alsa-devel, Takashi Iwai, linux-kernel, Jaroslav Kysela,
	akpm, Pavel Hofman

> > Could you do strace for ALSA ioctls? At least having the error code might
> > help to identify this issue.
> 
> I don't know how but I'm willing to try if you want to tell me how to
> do it.  Please keep in mind, I'm just an end-user -- not a developer
> or even c coder.  The most I've done is run xine in gdb to help supply
> bug info to those devs.

strace -o alsa-strace  speaker-test -Dhw:0,3 -t wav -c2 -l1                

Or 

strace -o alsa-strace  mplayer -ao alsa:device=hw=0.3 XXXXXXXX.mp3


Do you see error messages when playing via other audio devices, eg.

        mplayer -ao alsa:device=hw=0.0 XXXXXXXX.mp3

?

Thanks,
Fengguang

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-10 12:54                                                     ` Wu Fengguang
@ 2010-03-10 17:38                                                       ` VDR User
  -1 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-10 17:38 UTC (permalink / raw)
  To: Wu Fengguang
  Cc: Jaroslav Kysela, Wei Ni, Takashi Iwai, alsa-devel,
	Jaroslav Kysela, linux-kernel, akpm, Pavel Hofman

Ok, I'm not sure what I'm supposed to be looking for so I'll paste
some lines that include everything I see:

pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
[pid 22651] ioctl(21, 0x806c4120, 0xb439d230) = 0
[pid 22651] ioctl(21, 0x400c4150, 0xb439d1a4) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22652] ioctl(18, 0xc0104652 <unfinished ...>
[pid 22649] ioctl(10, 0xc0104652 <unfinished ...>
[pid 22652] <... ioctl resumed> , 0xb37b2590) = 0
[pid 22649] <... ioctl resumed> , 0xb547df00) = 0
[pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
[pid 22651] ioctl(21, 0x806c4120, 0xb439d230) = 0
[pid 22651] ioctl(21, 0x400c4150, 0xb439d1a4) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22649] ioctl(4, 0xc020462a, 0xb547e030) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
[pid 22651] ioctl(21, 0x806c4120, 0xb439d230) = 0
[pid 22651] ioctl(21, 0x400c4150, 0xb439d1a4) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
[pid 22651] ioctl(21, 0x806c4120, 0xb439d230) = 0
[pid 22651] ioctl(21, 0x400c4150, 0xb439d1a4) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22649] ioctl(10, 0xc0104652 <unfinished ...>
[pid 22652] ioctl(18, 0xc0104652 <unfinished ...>
[pid 22649] <... ioctl resumed> , 0xb547df00) = 0
[pid 22652] <... ioctl resumed> , 0xb37b2590) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22649] ioctl(4, 0xc020462a, 0xb547e030) = 0
[pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)

This is with starting xine with:
strace -f -e trace=open,ioctl xine -A alsa -V vdpau --post vdr_video
--post vdr_audio vdr://tmp/vdr-xine/stream#demux:mpeg_pes --verbose=2
--fullscreen --no-gui --no-mouse --deinterlace --no-logo --no-splash &

Hopefully this helps!..(?)

Best regards,
Derek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-10 17:38                                                       ` VDR User
  0 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-10 17:38 UTC (permalink / raw)
  To: Wu Fengguang
  Cc: Wei Ni, alsa-devel, Takashi Iwai, linux-kernel, Jaroslav Kysela,
	akpm, Pavel Hofman

Ok, I'm not sure what I'm supposed to be looking for so I'll paste
some lines that include everything I see:

pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
[pid 22651] ioctl(21, 0x806c4120, 0xb439d230) = 0
[pid 22651] ioctl(21, 0x400c4150, 0xb439d1a4) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22652] ioctl(18, 0xc0104652 <unfinished ...>
[pid 22649] ioctl(10, 0xc0104652 <unfinished ...>
[pid 22652] <... ioctl resumed> , 0xb37b2590) = 0
[pid 22649] <... ioctl resumed> , 0xb547df00) = 0
[pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
[pid 22651] ioctl(21, 0x806c4120, 0xb439d230) = 0
[pid 22651] ioctl(21, 0x400c4150, 0xb439d1a4) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22649] ioctl(4, 0xc020462a, 0xb547e030) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
[pid 22651] ioctl(21, 0x806c4120, 0xb439d230) = 0
[pid 22651] ioctl(21, 0x400c4150, 0xb439d1a4) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
[pid 22651] ioctl(21, 0x806c4120, 0xb439d230) = 0
[pid 22651] ioctl(21, 0x400c4150, 0xb439d1a4) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22649] ioctl(10, 0xc0104652 <unfinished ...>
[pid 22652] ioctl(18, 0xc0104652 <unfinished ...>
[pid 22649] <... ioctl resumed> , 0xb547df00) = 0
[pid 22652] <... ioctl resumed> , 0xb37b2590) = 0
[pid 22652] ioctl(18, 0xc0104652, 0xb37b2590) = 0
[pid 22649] ioctl(4, 0xc020462a, 0xb547e030) = 0
[pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)

This is with starting xine with:
strace -f -e trace=open,ioctl xine -A alsa -V vdpau --post vdr_video
--post vdr_audio vdr://tmp/vdr-xine/stream#demux:mpeg_pes --verbose=2
--fullscreen --no-gui --no-mouse --deinterlace --no-logo --no-splash &

Hopefully this helps!..(?)

Best regards,
Derek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-10 17:38                                                       ` VDR User
  (?)
@ 2010-03-11  7:30                                                       ` Jaroslav Kysela
  2010-03-11 18:15                                                           ` VDR User
  -1 siblings, 1 reply; 80+ messages in thread
From: Jaroslav Kysela @ 2010-03-11  7:30 UTC (permalink / raw)
  To: VDR User
  Cc: Wu Fengguang, Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela,
	linux-kernel, akpm, Pavel Hofman

On Wed, 10 Mar 2010, VDR User wrote:

> [pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.

-EPIPE means underrun condition.

Try 'echo 101 > /proc/asound/card0/pcm0p/xrun_debug' and send dmesg 
output to check if the ring buffer pointer in the hda-intel driver does 
not return wrong values. Replace card0 and pcm0p with right identifiers 
(look to 'aplay -l' for right numbers).

More info: http://www.alsa-project.org/main/index.php/XRUN_Debug

 					Jaroslav

-----
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-11  7:30                                                       ` [alsa-devel] " Jaroslav Kysela
@ 2010-03-11 18:15                                                           ` VDR User
  0 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-11 18:15 UTC (permalink / raw)
  To: Jaroslav Kysela
  Cc: Wu Fengguang, Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela,
	linux-kernel, akpm, Pavel Hofman

On Wed, Mar 10, 2010 at 11:30 PM, Jaroslav Kysela <perex@perex.cz> wrote:
> On Wed, 10 Mar 2010, VDR User wrote:
>
>> [pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>
> -EPIPE means underrun condition.
>
> Try 'echo 101 > /proc/asound/card0/pcm0p/xrun_debug' and send dmesg output
> to check if the ring buffer pointer in the hda-intel driver does not return
> wrong values. Replace card0 and pcm0p with right identifiers (look to 'aplay
> -l' for right numbers).
>
> More info: http://www.alsa-project.org/main/index.php/XRUN_Debug

Hi, thanks for your further reply.  However, I don't see
"CONFIG_SND_PCM_XRUN_DEBUG" anywhere in the kernel config (both in
menuconfig or .config).  Also, in order to use the snapshot I had to
disable ALSA in my kernel anyways.  I did try to enable it just to see
if that option would appear somewhere but it did not.  I am using
stable kernel 2.6.33 btw.  I don't see how I can create
/proc/asound/card1/pcm3p/xrun_debug!

Best regards,
Derek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-11 18:15                                                           ` VDR User
  0 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-11 18:15 UTC (permalink / raw)
  To: Jaroslav Kysela
  Cc: Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela, linux-kernel,
	akpm, Wu Fengguang, Pavel Hofman

On Wed, Mar 10, 2010 at 11:30 PM, Jaroslav Kysela <perex@perex.cz> wrote:
> On Wed, 10 Mar 2010, VDR User wrote:
>
>> [pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>
> -EPIPE means underrun condition.
>
> Try 'echo 101 > /proc/asound/card0/pcm0p/xrun_debug' and send dmesg output
> to check if the ring buffer pointer in the hda-intel driver does not return
> wrong values. Replace card0 and pcm0p with right identifiers (look to 'aplay
> -l' for right numbers).
>
> More info: http://www.alsa-project.org/main/index.php/XRUN_Debug

Hi, thanks for your further reply.  However, I don't see
"CONFIG_SND_PCM_XRUN_DEBUG" anywhere in the kernel config (both in
menuconfig or .config).  Also, in order to use the snapshot I had to
disable ALSA in my kernel anyways.  I did try to enable it just to see
if that option would appear somewhere but it did not.  I am using
stable kernel 2.6.33 btw.  I don't see how I can create
/proc/asound/card1/pcm3p/xrun_debug!

Best regards,
Derek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-11 18:15                                                           ` VDR User
@ 2010-03-11 18:32                                                             ` Jaroslav Kysela
  -1 siblings, 0 replies; 80+ messages in thread
From: Jaroslav Kysela @ 2010-03-11 18:32 UTC (permalink / raw)
  To: VDR User
  Cc: Wu Fengguang, Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela,
	linux-kernel, akpm, Pavel Hofman

On Thu, 11 Mar 2010, VDR User wrote:

> On Wed, Mar 10, 2010 at 11:30 PM, Jaroslav Kysela <perex@perex.cz> wrote:
>> On Wed, 10 Mar 2010, VDR User wrote:
>>
>>> [pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
>>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>
>> -EPIPE means underrun condition.
>>
>> Try 'echo 101 > /proc/asound/card0/pcm0p/xrun_debug' and send dmesg output
>> to check if the ring buffer pointer in the hda-intel driver does not return
>> wrong values. Replace card0 and pcm0p with right identifiers (look to 'aplay
>> -l' for right numbers).
>>
>> More info: http://www.alsa-project.org/main/index.php/XRUN_Debug
>
> Hi, thanks for your further reply.  However, I don't see
> "CONFIG_SND_PCM_XRUN_DEBUG" anywhere in the kernel config (both in
> menuconfig or .config).

All these parameters should be set: CONFIG_SND_PCM_XRUN_DEBUG, 
CONFIG_SND_VERBOSE_PROCFS, CONFIG_SND_DEBUG . I updated wiki.

 					Jaroslav

-----
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-11 18:32                                                             ` Jaroslav Kysela
  0 siblings, 0 replies; 80+ messages in thread
From: Jaroslav Kysela @ 2010-03-11 18:32 UTC (permalink / raw)
  To: VDR User
  Cc: Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela, linux-kernel,
	akpm, Wu Fengguang, Pavel Hofman

On Thu, 11 Mar 2010, VDR User wrote:

> On Wed, Mar 10, 2010 at 11:30 PM, Jaroslav Kysela <perex@perex.cz> wrote:
>> On Wed, 10 Mar 2010, VDR User wrote:
>>
>>> [pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
>>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>
>> -EPIPE means underrun condition.
>>
>> Try 'echo 101 > /proc/asound/card0/pcm0p/xrun_debug' and send dmesg output
>> to check if the ring buffer pointer in the hda-intel driver does not return
>> wrong values. Replace card0 and pcm0p with right identifiers (look to 'aplay
>> -l' for right numbers).
>>
>> More info: http://www.alsa-project.org/main/index.php/XRUN_Debug
>
> Hi, thanks for your further reply.  However, I don't see
> "CONFIG_SND_PCM_XRUN_DEBUG" anywhere in the kernel config (both in
> menuconfig or .config).

All these parameters should be set: CONFIG_SND_PCM_XRUN_DEBUG, 
CONFIG_SND_VERBOSE_PROCFS, CONFIG_SND_DEBUG . I updated wiki.

 					Jaroslav

-----
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-11 18:32                                                             ` Jaroslav Kysela
  (?)
@ 2010-03-11 19:24                                                             ` VDR User
  -1 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-11 19:24 UTC (permalink / raw)
  To: Jaroslav Kysela
  Cc: Wu Fengguang, Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela,
	linux-kernel, akpm, Pavel Hofman

[-- Attachment #1: Type: text/plain, Size: 1397 bytes --]

On Thu, Mar 11, 2010 at 10:32 AM, Jaroslav Kysela <perex@perex.cz> wrote:
>>>> [pid 22651] ioctl(21, 0x80044121, 0xb439d2cc) = -1 EPIPE (Broken pipe)
>>>> pcm_hw.c: snd_pcm_hw_delay() SNDRV_PCM_IOCTL_DELAY failed.
>>>
>>> -EPIPE means underrun condition.
>>>
>>> Try 'echo 101 > /proc/asound/card0/pcm0p/xrun_debug' and send dmesg
>>> output
>>> to check if the ring buffer pointer in the hda-intel driver does not
>>> return
>>> wrong values. Replace card0 and pcm0p with right identifiers (look to
>>> 'aplay
>>> -l' for right numbers).
>>>
>>> More info: http://www.alsa-project.org/main/index.php/XRUN_Debug
>>
>> Hi, thanks for your further reply.  However, I don't see
>> "CONFIG_SND_PCM_XRUN_DEBUG" anywhere in the kernel config (both in
>> menuconfig or .config).
>
> All these parameters should be set: CONFIG_SND_PCM_XRUN_DEBUG,
> CONFIG_SND_VERBOSE_PROCFS, CONFIG_SND_DEBUG . I updated wiki.

Ok, I have now compiled the alsa snapshot with the following:

./configure --with-cards=hda-intel
--with-card-options=hda-hwdep,hda-reconfig,hda-codec-realtek,hda-codec-nvhdmi,hda-generic,pcm-xrun-debug
--with-debug=verbose --enable-verbose-procfs --with-isapnp=no
--with-sequencer=no --with-oss=no --with-pcm-oss-plugins=no

Attached are samples of my dmesg and /var/log/syslog files.  Hopefully
there is some useful information there?

Best regards,
Derek

[-- Attachment #2: dmesg --]
[-- Type: application/octet-stream, Size: 39850 bytes --]

[    0.000000] Linux version 2.6.33.amd64-x2.030210.1 (root@test) (gcc version 4.4.3 20100108 (prerelease) (Debian 4.4.2-9) ) #1 SMP Tue Mar 2 09:24:03 PST 2010
[    0.000000] BIOS-provided physical RAM map:
[    0.000000]  BIOS-e820: 0000000000000000 - 000000000009fc00 (usable)
[    0.000000]  BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved)
[    0.000000]  BIOS-e820: 00000000000e6000 - 0000000000100000 (reserved)
[    0.000000]  BIOS-e820: 0000000000100000 - 000000007ffd0000 (usable)
[    0.000000]  BIOS-e820: 000000007ffd0000 - 000000007ffde000 (ACPI data)
[    0.000000]  BIOS-e820: 000000007ffde000 - 0000000080000000 (ACPI NVS)
[    0.000000]  BIOS-e820: 00000000fec00000 - 00000000fec01000 (reserved)
[    0.000000]  BIOS-e820: 00000000fee00000 - 00000000fef00000 (reserved)
[    0.000000]  BIOS-e820: 00000000fff80000 - 0000000100000000 (reserved)
[    0.000000] Notice: NX (Execute Disable) protection cannot be enabled: non-PAE kernel!
[    0.000000] DMI present.
[    0.000000] last_pfn = 0x7ffd0 max_arch_pfn = 0x100000
[    0.000000] MTRR default type: uncachable
[    0.000000] MTRR fixed ranges enabled:
[    0.000000]   00000-9FFFF write-back
[    0.000000]   A0000-EFFFF uncachable
[    0.000000]   F0000-FFFFF write-protect
[    0.000000] MTRR variable ranges enabled:
[    0.000000]   0 base 0000000000 mask FF80000000 write-back
[    0.000000]   1 disabled
[    0.000000]   2 disabled
[    0.000000]   3 disabled
[    0.000000]   4 disabled
[    0.000000]   5 disabled
[    0.000000]   6 disabled
[    0.000000]   7 disabled
[    0.000000] x86 PAT enabled: cpu 0, old 0x7040600070406, new 0x7010600070106
[    0.000000] initial memory mapped : 0 - 01800000
[    0.000000] init_memory_mapping: 0000000000000000-00000000377fe000
[    0.000000]  0000000000 - 0000400000 page 4k
[    0.000000]  0000400000 - 0037400000 page 2M
[    0.000000]  0037400000 - 00377fe000 page 4k
[    0.000000] kernel direct mapping tables up to 377fe000 @ 7000-c000
[    0.000000] ACPI: RSDP 000f93e0 00014 (v00 ACPIAM)
[    0.000000] ACPI: RSDT 7ffd0000 0003C (v01 A M I  OEMRSDT  08000731 MSFT 00000097)
[    0.000000] ACPI: FACP 7ffd0200 00084 (v02 A M I  OEMFACP  08000731 MSFT 00000097)
[    0.000000] ACPI: DSDT 7ffd0440 04395 (v01  1ADMB 1ADMB006 00000006 INTL 20051117)
[    0.000000] ACPI: FACS 7ffde000 00040
[    0.000000] ACPI: APIC 7ffd0390 00070 (v01 A M I  OEMAPIC  08000731 MSFT 00000097)
[    0.000000] ACPI: MCFG 7ffd0400 0003C (v01 A M I  OEMMCFG  08000731 MSFT 00000097)
[    0.000000] ACPI: OEMB 7ffde040 00060 (v01 A M I  AMI_OEM  08000731 MSFT 00000097)
[    0.000000] ACPI: HPET 7ffd47e0 00038 (v01 A M I  OEMHPET0 08000731 MSFT 00000097)
[    0.000000] ACPI: SSDT 7ffd4820 00248 (v01 A M I  POWERNOW 00000001 AMD  00000001)
[    0.000000] ACPI: Local APIC address 0xfee00000
[    0.000000] 1159MB HIGHMEM available.
[    0.000000] 887MB LOWMEM available.
[    0.000000]   mapped low ram: 0 - 377fe000
[    0.000000]   low ram: 0 - 377fe000
[    0.000000]   node 0 low ram: 00000000 - 377fe000
[    0.000000]   node 0 bootmap 00008000 - 0000ef00
[    0.000000] (9 early reservations) ==> bootmem [0000000000 - 00377fe000]
[    0.000000]   #0 [0000000000 - 0000001000]   BIOS data page ==> [0000000000 - 0000001000]
[    0.000000]   #1 [0000001000 - 0000002000]    EX TRAMPOLINE ==> [0000001000 - 0000002000]
[    0.000000]   #2 [0001000000 - 0001437fb0]    TEXT DATA BSS ==> [0001000000 - 0001437fb0]
[    0.000000]   #3 [000009fc00 - 0000100000]    BIOS reserved ==> [000009fc00 - 0000100000]
[    0.000000]   #4 [0001438000 - 000143e16c]              BRK ==> [0001438000 - 000143e16c]
[    0.000000]   #5 [0000002000 - 0000003000]       TRAMPOLINE ==> [0000002000 - 0000003000]
[    0.000000]   #6 [0000003000 - 0000007000]      ACPI WAKEUP ==> [0000003000 - 0000007000]
[    0.000000]   #7 [0000007000 - 0000008000]          PGTABLE ==> [0000007000 - 0000008000]
[    0.000000]   #8 [0000008000 - 000000f000]          BOOTMAP ==> [0000008000 - 000000f000]
[    0.000000] Zone PFN ranges:
[    0.000000]   DMA      0x00000000 -> 0x00001000
[    0.000000]   Normal   0x00001000 -> 0x000377fe
[    0.000000]   HighMem  0x000377fe -> 0x0007ffd0
[    0.000000] Movable zone start PFN for each node
[    0.000000] early_node_map[2] active PFN ranges
[    0.000000]     0: 0x00000000 -> 0x0000009f
[    0.000000]     0: 0x00000100 -> 0x0007ffd0
[    0.000000] On node 0 totalpages: 524143
[    0.000000] free_area_init_node: node 0, pgdat c139f800, node_mem_map c1440000
[    0.000000]   DMA zone: 32 pages used for memmap
[    0.000000]   DMA zone: 0 pages reserved
[    0.000000]   DMA zone: 3967 pages, LIFO batch:0
[    0.000000]   Normal zone: 1744 pages used for memmap
[    0.000000]   Normal zone: 221486 pages, LIFO batch:31
[    0.000000]   HighMem zone: 2320 pages used for memmap
[    0.000000]   HighMem zone: 294594 pages, LIFO batch:31
[    0.000000] Using APIC driver default
[    0.000000] Detected use of extended apic ids on hypertransport bus
[    0.000000] ACPI: PM-Timer IO Port: 0x4008
[    0.000000] ACPI: Local APIC address 0xfee00000
[    0.000000] ACPI: LAPIC (acpi_id[0x01] lapic_id[0x00] enabled)
[    0.000000] ACPI: LAPIC (acpi_id[0x02] lapic_id[0x01] enabled)
[    0.000000] ACPI: IOAPIC (id[0x02] address[0xfec00000] gsi_base[0])
[    0.000000] IOAPIC[0]: apic_id 2, version 17, address 0xfec00000, GSI 0-23
[    0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
[    0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
[    0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 14 global_irq 14 high edge)
[    0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 15 global_irq 15 high edge)
[    0.000000] ACPI: IRQ0 used by override.
[    0.000000] ACPI: IRQ2 used by override.
[    0.000000] ACPI: IRQ9 used by override.
[    0.000000] ACPI: IRQ14 used by override.
[    0.000000] ACPI: IRQ15 used by override.
[    0.000000] Using ACPI (MADT) for SMP configuration information
[    0.000000] ACPI: HPET id: 0x10de8201 base: 0xfeff0000
[    0.000000] SMP: Allowing 2 CPUs, 0 hotplug CPUs
[    0.000000] nr_irqs_gsi: 24
[    0.000000] Allocating PCI resources starting at 80000000 (gap: 80000000:7ec00000)
[    0.000000] setup_percpu: NR_CPUS:8 nr_cpumask_bits:8 nr_cpu_ids:2 nr_node_ids:1
[    0.000000] PERCPU: Embedded 12 pages/cpu @c2800000 s26008 r0 d23144 u2097152
[    0.000000] pcpu-alloc: s26008 r0 d23144 u2097152 alloc=1*4194304
[    0.000000] pcpu-alloc: [0] 0 1 
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 520047
[    0.000000] Kernel command line: BOOT_IMAGE=//vmlinuz-2.6.33.amd64-x2.030210.1 root=/dev/sda3 ro quiet
[    0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[    0.000000] Enabling fast FPU save and restore... done.
[    0.000000] Enabling unmasked SIMD FPU exception support... done.
[    0.000000] Initializing CPU#0
[    0.000000] Initializing HighMem for node 0 (000377fe:0007ffd0)
[    0.000000] Memory: 2073804k/2096960k available (2552k kernel code, 21696k reserved, 1176k data, 288k init, 1187656k highmem)
[    0.000000] virtual kernel memory layout:
[    0.000000]     fixmap  : 0xfff1f000 - 0xfffff000   ( 896 kB)
[    0.000000]     pkmap   : 0xff800000 - 0xffc00000   (4096 kB)
[    0.000000]     vmalloc : 0xf7ffe000 - 0xff7fe000   ( 120 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xf77fe000   ( 887 MB)
[    0.000000]       .init : 0xc13a5000 - 0xc13ed000   ( 288 kB)
[    0.000000]       .data : 0xc127e2b4 - 0xc13a4318   (1176 kB)
[    0.000000]       .text : 0xc1000000 - 0xc127e2b4   (2552 kB)
[    0.000000] Checking if this processor honours the WP bit even in supervisor mode...Ok.
[    0.000000] Hierarchical RCU implementation.
[    0.000000] NR_IRQS:512
[    0.000000] spurious 8259A interrupt: IRQ7.
[    0.000000] Console: colour VGA+ 80x25
[    0.000000] console [tty0] enabled
[    0.000000] hpet clockevent registered
[    0.000000] Fast TSC calibration using PIT
[    0.000000] Detected 2310.462 MHz processor.
[    0.001003] Calibrating delay loop (skipped), value calculated using timer frequency.. 4620.92 BogoMIPS (lpj=2310462)
[    0.001045] Mount-cache hash table entries: 512
[    0.001139] CPU: Physical Processor ID: 0
[    0.001141] CPU: Processor Core ID: 0
[    0.001143] using C1E aware idle routine
[    0.001150] Performance Events: AMD PMU driver.
[    0.001154] ... version:                0
[    0.001156] ... bit width:              48
[    0.001157] ... generic registers:      4
[    0.001158] ... value mask:             0000ffffffffffff
[    0.001160] ... max period:             00007fffffffffff
[    0.001162] ... fixed-purpose events:   0
[    0.001163] ... event mask:             000000000000000f
[    0.001167] Checking 'hlt' instruction... OK.
[    0.005161] ACPI: Core revision 20091214
[    0.010797] Enabling APIC mode:  Flat.  Using 1 I/O APICs
[    0.011260] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
[    0.021271] CPU0: AMD Athlon(tm) 64 X2 Dual Core Processor 4400+ stepping 01
[    0.021999] Booting Node   0, Processors  #1 Ok.
[    0.001999] Initializing CPU#1
[    0.092098] Brought up 2 CPUs
[    0.092100] Total of 2 processors activated (9241.96 BogoMIPS).
[    0.092696] NET: Registered protocol family 16
[    0.093049] ACPI: bus type pci registered
[    0.093145] PCI: MMCONFIG for domain 0000 [bus 00-ff] at [mem 0xe0000000-0xefffffff] (base 0xe0000000)
[    0.093145] PCI: not using MMCONFIG
[    0.093644] PCI: PCI BIOS revision 3.00 entry at 0xf0031, last bus=4
[    0.093646] PCI: Using configuration type 1 for base access
[    0.097419] bio: create slab <bio-0> at 0
[    0.098355] ACPI: EC: Look up EC in DSDT
[    0.101268] ACPI: Executed 1 blocks of module-level executable AML code
[    0.105490] ACPI: Interpreter enabled
[    0.105494] ACPI: (supports S0 S1 S5)
[    0.105507] ACPI: Using IOAPIC for interrupt routing
[    0.105552] PCI: MMCONFIG for domain 0000 [bus 00-ff] at [mem 0xe0000000-0xefffffff] (base 0xe0000000)
[    0.109390] PCI: MMCONFIG at [mem 0xe0000000-0xefffffff] reserved in ACPI motherboard resources
[    0.109392] PCI: Using MMCONFIG for extended config space
[    0.118053] ACPI Warning: Incorrect checksum in table [OEMB] - 85, should be 80 (20091214/tbutils-314)
[    0.118158] ACPI: No dock devices found.
[    0.118258] ACPI: PCI Root Bridge [PCI0] (0000:00)
[    0.118392] pci_root PNP0A03:00: ignoring host bridge windows from ACPI; boot with "pci=use_crs" to use them
[    0.118568] pci_root PNP0A03:00: host bridge window [io  0x0000-0x0cf7] (ignored)
[    0.118571] pci_root PNP0A03:00: host bridge window [io  0x0d00-0xffff] (ignored)
[    0.118574] pci_root PNP0A03:00: host bridge window [mem 0x000a0000-0x000bffff] (ignored)
[    0.118577] pci_root PNP0A03:00: host bridge window [mem 0x000d0000-0x000dffff] (ignored)
[    0.118579] pci_root PNP0A03:00: host bridge window [mem 0x80000000-0xffffffff] (ignored)
[    0.118716] pci 0000:00:01.0: reg 10: [io  0x4f00-0x4fff]
[    0.118748] pci 0000:00:01.1: reg 10: [io  0xdc00-0xdc3f]
[    0.118758] pci 0000:00:01.1: reg 20: [io  0x5000-0x503f]
[    0.118762] pci 0000:00:01.1: reg 24: [io  0x6000-0x603f]
[    0.118780] pci 0000:00:01.1: PME# supported from D3hot D3cold
[    0.118786] pci 0000:00:01.1: PME# disabled
[    0.118829] pci 0000:00:02.0: reg 10: [mem 0xdedfb000-0xdedfbfff]
[    0.118849] pci 0000:00:02.0: supports D1 D2
[    0.118851] pci 0000:00:02.0: PME# supported from D0 D1 D2 D3hot D3cold
[    0.118854] pci 0000:00:02.0: PME# disabled
[    0.118873] pci 0000:00:02.1: reg 10: [mem 0xdedfac00-0xdedfacff]
[    0.118897] pci 0000:00:02.1: supports D1 D2
[    0.118899] pci 0000:00:02.1: PME# supported from D0 D1 D2 D3hot D3cold
[    0.118903] pci 0000:00:02.1: PME# disabled
[    0.118955] pci 0000:00:05.0: reg 10: [mem 0xdedf4000-0xdedf7fff]
[    0.118979] pci 0000:00:05.0: PME# supported from D3hot D3cold
[    0.118982] pci 0000:00:05.0: PME# disabled
[    0.119024] pci 0000:00:06.0: reg 20: [io  0xffa0-0xffaf]
[    0.119053] pci 0000:00:07.0: reg 10: [mem 0xdedf9000-0xdedf9fff]
[    0.119057] pci 0000:00:07.0: reg 14: [io  0xd480-0xd487]
[    0.119077] pci 0000:00:07.0: supports D1 D2
[    0.119079] pci 0000:00:07.0: PME# supported from D0 D1 D2 D3hot D3cold
[    0.119083] pci 0000:00:07.0: PME# disabled
[    0.119100] pci 0000:00:08.0: reg 10: [io  0xd400-0xd407]
[    0.119104] pci 0000:00:08.0: reg 14: [io  0xd080-0xd083]
[    0.119107] pci 0000:00:08.0: reg 18: [io  0xd000-0xd007]
[    0.119111] pci 0000:00:08.0: reg 1c: [io  0xcc00-0xcc03]
[    0.119115] pci 0000:00:08.0: reg 20: [io  0xc880-0xc88f]
[    0.119119] pci 0000:00:08.0: reg 24: [mem 0xdedf8000-0xdedf8fff]
[    0.119161] pci 0000:00:09.0: PME# supported from D0 D1 D2 D3hot D3cold
[    0.119164] pci 0000:00:09.0: PME# disabled
[    0.119191] pci 0000:00:0b.0: PME# supported from D0 D1 D2 D3hot D3cold
[    0.119193] pci 0000:00:0b.0: PME# disabled
[    0.119220] pci 0000:00:0c.0: PME# supported from D0 D1 D2 D3hot D3cold
[    0.119222] pci 0000:00:0c.0: PME# disabled
[    0.119318] pci 0000:01:09.0: reg 10: [mem 0xdeeffc00-0xdeeffdff]
[    0.119362] pci 0000:00:04.0: PCI bridge to [bus 01-01] (subtractive decode)
[    0.119367] pci 0000:00:04.0:   bridge window [mem 0xdee00000-0xdeefffff]
[    0.119386] pci 0000:02:00.0: reg 10: [mem 0xdf000000-0xdfffffff]
[    0.119393] pci 0000:02:00.0: reg 14: [mem 0xc0000000-0xcfffffff 64bit pref]
[    0.119401] pci 0000:02:00.0: reg 1c: [mem 0xdc000000-0xddffffff 64bit pref]
[    0.119406] pci 0000:02:00.0: reg 24: [io  0xec00-0xec7f]
[    0.119411] pci 0000:02:00.0: reg 30: [mem 0xdef80000-0xdeffffff pref]
[    0.119448] pci 0000:02:00.1: reg 10: [mem 0xdef7c000-0xdef7ffff]
[    0.119511] pci 0000:00:09.0: PCI bridge to [bus 02-02]
[    0.119514] pci 0000:00:09.0:   bridge window [io  0xe000-0xefff]
[    0.119517] pci 0000:00:09.0:   bridge window [mem 0xdef00000-0xdfffffff]
[    0.119521] pci 0000:00:09.0:   bridge window [mem 0xc0000000-0xddffffff 64bit pref]
[    0.119554] pci 0000:00:0b.0: PCI bridge to [bus 03-03]
[    0.119589] pci 0000:00:0c.0: PCI bridge to [bus 04-04]
[    0.119600] pci_bus 0000:00: on NUMA node 0
[    0.119604] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
[    0.119746] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.P0P1._PRT]
[    0.119821] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.BR10._PRT]
[    0.119870] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.BR11._PRT]
[    0.119919] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.BR12._PRT]
[    0.126868] ACPI: PCI Interrupt Link [LNKA] (IRQs 16 17 18 19) *0, disabled.
[    0.127033] ACPI: PCI Interrupt Link [LNKB] (IRQs 16 17 18 19) *10
[    0.127190] ACPI: PCI Interrupt Link [LNKC] (IRQs 16 17 18 19) *0, disabled.
[    0.127347] ACPI: PCI Interrupt Link [LNKD] (IRQs 16 17 18 19) *0, disabled.
[    0.127504] ACPI: PCI Interrupt Link [LNEA] (IRQs 16 17 18 19) *0, disabled.
[    0.127661] ACPI: PCI Interrupt Link [LNEB] (IRQs 16 17 18 19) *0, disabled.
[    0.127818] ACPI: PCI Interrupt Link [LNEC] (IRQs 16 17 18 19) *0, disabled.
[    0.127975] ACPI: PCI Interrupt Link [LNED] (IRQs 16 17 18 19) *10
[    0.128138] ACPI: PCI Interrupt Link [LUB0] (IRQs 20 21 22 23) *5
[    0.128294] ACPI: PCI Interrupt Link [LUB2] (IRQs 20 21 22 23) *10
[    0.128451] ACPI: PCI Interrupt Link [LMAC] (IRQs 20 21 22 23) *5
[    0.128609] ACPI: PCI Interrupt Link [LAZA] (IRQs 20 21 22 23) *11
[    0.128766] ACPI: PCI Interrupt Link [LACI] (IRQs 20 21 22 23) *0, disabled.
[    0.128923] ACPI: PCI Interrupt Link [LMC9] (IRQs 20 21 22 23) *0, disabled.
[    0.129084] ACPI: PCI Interrupt Link [LSMB] (IRQs 20 21 22 23) *11
[    0.129242] ACPI: PCI Interrupt Link [LPMU] (IRQs 20 21 22 23) *0, disabled.
[    0.129399] ACPI: PCI Interrupt Link [LSA0] (IRQs 20 21 22 23) *10
[    0.129556] ACPI: PCI Interrupt Link [LSA1] (IRQs 20 21 22 23) *0, disabled.
[    0.129743] ACPI: PCI Interrupt Link [LATA] (IRQs 20 21 22 23) *0, disabled.
[    0.129930] vgaarb: device added: PCI:0000:02:00.0,decodes=io+mem,owns=io+mem,locks=none
[    0.129933] vgaarb: loaded
[    0.130104] SCSI subsystem initialized
[    0.130169] libata version 3.00 loaded.
[    0.130256] usbcore: registered new interface driver usbfs
[    0.130329] usbcore: registered new interface driver hub
[    0.130381] usbcore: registered new device driver usb
[    0.130564] PCI: Using ACPI for IRQ routing
[    0.130564] PCI: pci_cache_line_size set to 64 bytes
[    0.130727] Switching to clocksource hpet
[    0.130810] pnp: PnP ACPI init
[    0.130810] ACPI: bus type pnp registered
[    0.134664] pnp: PnP ACPI: found 14 devices
[    0.134666] ACPI: ACPI bus type pnp unregistered
[    0.134680] system 00:07: [io  0x04d0-0x04d1] has been reserved
[    0.134683] system 00:07: [io  0x0800-0x080f] has been reserved
[    0.134686] system 00:07: [io  0x4000-0x407f] has been reserved
[    0.134688] system 00:07: [io  0x4080-0x40ff] has been reserved
[    0.134691] system 00:07: [io  0x4400-0x447f] has been reserved
[    0.134694] system 00:07: [io  0x4480-0x44ff] has been reserved
[    0.134697] system 00:07: [io  0x4800-0x487f] has been reserved
[    0.134700] system 00:07: [io  0x4880-0x48ff] has been reserved
[    0.134703] system 00:07: [io  0x2000-0x207f] has been reserved
[    0.134705] system 00:07: [io  0x2080-0x20ff] has been reserved
[    0.134709] system 00:07: [mem 0xfefe0000-0xfefe01ff] has been reserved
[    0.134712] system 00:07: [mem 0xfefe1000-0xfefe1fff] has been reserved
[    0.134715] system 00:07: [mem 0xfee01000-0xfeefffff] has been reserved
[    0.134718] system 00:07: [mem 0xffb80000-0xffffffff] could not be reserved
[    0.134724] system 00:09: [mem 0xfec00000-0xfec00fff] could not be reserved
[    0.134727] system 00:09: [mem 0xfee00000-0xfee00fff] has been reserved
[    0.134732] system 00:0b: [io  0x0a00-0x0adf] has been reserved
[    0.134735] system 00:0b: [io  0x0ae0-0x0aef] has been reserved
[    0.134741] system 00:0c: [mem 0xe0000000-0xefffffff] has been reserved
[    0.134746] system 00:0d: [mem 0x00000000-0x0009ffff] could not be reserved
[    0.134749] system 00:0d: [mem 0x000c0000-0x000cffff] could not be reserved
[    0.134752] system 00:0d: [mem 0x000e0000-0x000fffff] could not be reserved
[    0.134755] system 00:0d: [mem 0x00100000-0x7fffffff] could not be reserved
[    0.170014] pci 0000:00:04.0: PCI bridge to [bus 01-01]
[    0.170017] pci 0000:00:04.0:   bridge window [io  disabled]
[    0.170020] pci 0000:00:04.0:   bridge window [mem 0xdee00000-0xdeefffff]
[    0.170023] pci 0000:00:04.0:   bridge window [mem pref disabled]
[    0.170027] pci 0000:00:09.0: PCI bridge to [bus 02-02]
[    0.170030] pci 0000:00:09.0:   bridge window [io  0xe000-0xefff]
[    0.170033] pci 0000:00:09.0:   bridge window [mem 0xdef00000-0xdfffffff]
[    0.170037] pci 0000:00:09.0:   bridge window [mem 0xc0000000-0xddffffff 64bit pref]
[    0.170040] pci 0000:00:0b.0: PCI bridge to [bus 03-03]
[    0.170042] pci 0000:00:0b.0:   bridge window [io  disabled]
[    0.170044] pci 0000:00:0b.0:   bridge window [mem disabled]
[    0.170047] pci 0000:00:0b.0:   bridge window [mem pref disabled]
[    0.170050] pci 0000:00:0c.0: PCI bridge to [bus 04-04]
[    0.170051] pci 0000:00:0c.0:   bridge window [io  disabled]
[    0.170054] pci 0000:00:0c.0:   bridge window [mem disabled]
[    0.170056] pci 0000:00:0c.0:   bridge window [mem pref disabled]
[    0.170063] pci 0000:00:04.0: setting latency timer to 64
[    0.170068] pci 0000:00:09.0: setting latency timer to 64
[    0.170072] pci 0000:00:0b.0: setting latency timer to 64
[    0.170077] pci 0000:00:0c.0: setting latency timer to 64
[    0.170080] pci_bus 0000:00: resource 0 [io  0x0000-0xffff]
[    0.170082] pci_bus 0000:00: resource 1 [mem 0x00000000-0xffffffff]
[    0.170085] pci_bus 0000:01: resource 1 [mem 0xdee00000-0xdeefffff]
[    0.170087] pci_bus 0000:01: resource 3 [io  0x0000-0xffff]
[    0.170090] pci_bus 0000:01: resource 4 [mem 0x00000000-0xffffffff]
[    0.170093] pci_bus 0000:02: resource 0 [io  0xe000-0xefff]
[    0.170095] pci_bus 0000:02: resource 1 [mem 0xdef00000-0xdfffffff]
[    0.170098] pci_bus 0000:02: resource 2 [mem 0xc0000000-0xddffffff 64bit pref]
[    0.170128] NET: Registered protocol family 2
[    0.170157] IP route cache hash table entries: 32768 (order: 5, 131072 bytes)
[    0.170315] TCP established hash table entries: 131072 (order: 8, 1048576 bytes)
[    0.170932] TCP bind hash table entries: 65536 (order: 7, 524288 bytes)
[    0.171239] TCP: Hash tables configured (established 131072 bind 65536)
[    0.171241] TCP reno registered
[    0.171244] UDP hash table entries: 512 (order: 2, 16384 bytes)
[    0.171267] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[    0.171336] NET: Registered protocol family 1
[    0.192877] pci 0000:02:00.0: Boot video device
[    0.192881] PCI: CLS 64 bytes, default 64
[    0.193966] highmem bounce pool size: 64 pages
[    0.194191] Slow work thread pool: Starting up
[    0.194226] Slow work thread pool: Ready
[    0.194286] fuse init (API version 7.13)
[    0.194356] SGI XFS with security attributes, realtime, large block/inode numbers, no debug enabled
[    0.194587] msgmni has been set to 1732
[    0.194740] alg: No test for stdrng (krng)
[    0.194750] io scheduler noop registered
[    0.194752] io scheduler deadline registered (default)
[    0.194840] pcieport 0000:00:09.0: setting latency timer to 64
[    0.194902] pcieport 0000:00:0b.0: setting latency timer to 64
[    0.194960] pcieport 0000:00:0c.0: setting latency timer to 64
[    0.195275] input: Power Button as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input0
[    0.195282] ACPI: Power Button [PWRB]
[    0.195369] input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input1
[    0.195372] ACPI: Power Button [PWRF]
[    0.201604] Real Time Clock Driver v1.12b
[    0.201607] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.201720] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[    0.202153] 00:05: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[    0.202519] sata_nv 0000:00:08.0: version 3.5
[    0.202765] ACPI: PCI Interrupt Link [LSA0] enabled at IRQ 23
[    0.202776] sata_nv 0000:00:08.0: PCI INT A -> Link[LSA0] -> GSI 23 (level, low) -> IRQ 23
[    0.202820] sata_nv 0000:00:08.0: setting latency timer to 64
[    0.202871] scsi0 : sata_nv
[    0.203029] scsi1 : sata_nv
[    0.203211] ata1: SATA max UDMA/133 cmd 0xd400 ctl 0xd080 bmdma 0xc880 irq 23
[    0.203214] ata2: SATA max UDMA/133 cmd 0xd000 ctl 0xcc00 bmdma 0xc888 irq 23
[    0.203266] pata_amd 0000:00:06.0: version 0.4.1
[    0.203303] pata_amd 0000:00:06.0: setting latency timer to 64
[    0.203364] scsi2 : pata_amd
[    0.203471] scsi3 : pata_amd
[    0.204484] ata3: PATA max UDMA/133 cmd 0x1f0 ctl 0x3f6 bmdma 0xffa0 irq 14
[    0.204487] ata4: PATA max UDMA/133 cmd 0x170 ctl 0x376 bmdma 0xffa8 irq 15
[    0.204701] forcedeth: Reverse Engineered nForce ethernet driver. Version 0.64.
[    0.204918] ACPI: PCI Interrupt Link [LMAC] enabled at IRQ 22
[    0.204925] forcedeth 0000:00:07.0: PCI INT A -> Link[LMAC] -> GSI 22 (level, low) -> IRQ 22
[    0.204929] forcedeth 0000:00:07.0: setting latency timer to 64
[    0.358291] ata3.00: ATAPI: PIONEER DVD-RW  DVR-107D, 1.09, max UDMA/33
[    0.358313] ata3: nv_mode_filter: 0x739f&0x739f->0x739f, BIOS=0x7000 (0xc0000000) ACPI=0x701f (60:900:0x11)
[    0.361235] ata3.00: configured for UDMA/33
[    0.657277] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
[    0.660607] ata1.00: ATA-5: Maxtor 91301U3, FA570HD0, max UDMA/66
[    0.660610] ata1.00: 25410672 sectors, multi 16: LBA 
[    0.660619] ata1.00: applying bridge limits
[    0.666618] ata1.00: configured for UDMA/66
[    0.666726] scsi 0:0:0:0: Direct-Access     ATA      Maxtor 91301U3   FA57 PQ: 0 ANSI: 5
[    0.666928] sd 0:0:0:0: [sda] 25410672 512-byte logical blocks: (13.0 GB/12.1 GiB)
[    0.666978] sd 0:0:0:0: [sda] Write Protect is off
[    0.666981] sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
[    0.666998] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[    0.667094]  sda: sda1 sda2 sda3
[    0.675515] sd 0:0:0:0: [sda] Attached SCSI disk
[    0.717509] forcedeth 0000:00:07.0: ifname eth0, PHY OUI 0x732 @ 1, addr 00:19:db:e5:a7:c0
[    0.717512] forcedeth 0000:00:07.0: highdma pwrctl mgmt lnktim msi desc-v3
[    0.717638] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    0.717860] ACPI: PCI Interrupt Link [LUB2] enabled at IRQ 21
[    0.717868] ehci_hcd 0000:00:02.1: PCI INT B -> Link[LUB2] -> GSI 21 (level, low) -> IRQ 21
[    0.717878] ehci_hcd 0000:00:02.1: setting latency timer to 64
[    0.717881] ehci_hcd 0000:00:02.1: EHCI Host Controller
[    0.717902] ehci_hcd 0000:00:02.1: new USB bus registered, assigned bus number 1
[    0.717926] ehci_hcd 0000:00:02.1: debug port 1
[    0.717933] ehci_hcd 0000:00:02.1: cache line size of 64 is not supported
[    0.717951] ehci_hcd 0000:00:02.1: irq 21, io mem 0xdedfac00
[    0.723011] ehci_hcd 0000:00:02.1: USB 2.0 started, EHCI 1.00
[    0.723163] hub 1-0:1.0: USB hub found
[    0.723167] hub 1-0:1.0: 8 ports detected
[    0.723296] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    0.723512] ACPI: PCI Interrupt Link [LUB0] enabled at IRQ 20
[    0.723520] ohci_hcd 0000:00:02.0: PCI INT A -> Link[LUB0] -> GSI 20 (level, low) -> IRQ 20
[    0.723528] ohci_hcd 0000:00:02.0: setting latency timer to 64
[    0.723531] ohci_hcd 0000:00:02.0: OHCI Host Controller
[    0.723539] ohci_hcd 0000:00:02.0: new USB bus registered, assigned bus number 2
[    0.723560] ohci_hcd 0000:00:02.0: irq 20, io mem 0xdedfb000
[    0.776139] hub 2-0:1.0: USB hub found
[    0.776144] hub 2-0:1.0: 8 ports detected
[    0.776257] Initializing USB Mass Storage driver...
[    0.776307] usbcore: registered new interface driver usb-storage
[    0.776310] USB Mass Storage support registered.
[    0.776360] usbcore: registered new interface driver libusual
[    0.776443] usbcore: registered new interface driver usbserial
[    0.776445] usbserial: USB Serial Driver core
[    0.776483] USB Serial support registered for FTDI USB Serial Device
[    0.776535] usbcore: registered new interface driver ftdi_sio
[    0.776538] ftdi_sio: v1.5.0:USB FTDI Serial Converters Driver
[    0.776630] PNP: PS/2 Controller [PNP0303:PS2K] at 0x60,0x64 irq 1
[    0.776632] PNP: PS/2 appears to have AUX port disabled, if this is incorrect please boot with i8042.nopnp
[    0.777161] serio: i8042 KBD port at 0x60,0x64 irq 1
[    0.777300] mice: PS/2 mouse device common for all mice
[    0.777497] i2c /dev entries driver
[    0.777665] i2c i2c-0: nForce2 SMBus adapter at 0x5000
[    0.777753] i2c i2c-1: nForce2 SMBus adapter at 0x6000
[    0.777846] f71882fg: Found f71882fg chip at 0xa00, revision 32
[    0.778108] f71882fg f71882fg.2560: Fan: 1 is in duty-cycle mode
[    0.778110] f71882fg f71882fg.2560: Fan: 2 is in duty-cycle mode
[    0.778112] f71882fg f71882fg.2560: Fan: 3 is in duty-cycle mode
[    0.778115] f71882fg f71882fg.2560: Fan: 4 is in duty-cycle mode
[    0.778166] k8temp 0000:00:18.3: Temperature readouts might be wrong - check erratum #141
[    0.778260] cpuidle: using governor ladder
[    0.779337] usbcore: registered new interface driver usbhid
[    0.779339] usbhid: USB HID core driver
[    0.779375] TCP cubic registered
[    0.779378] NET: Registered protocol family 17
[    0.779386] Using IPI No-Shortcut mode
[    0.979341] ata2: SATA link down (SStatus 0 SControl 300)
[    0.985665] scsi 2:0:0:0: CD-ROM            PIONEER  DVD-RW  DVR-107D 1.09 PQ: 0 ANSI: 5
[    0.985837] ata4: port disabled. ignoring.
[    1.028364] kjournald starting.  Commit interval 5 seconds
[    1.028379] EXT3-fs (sda3): mounted filesystem with writeback data mode
[    1.028390] VFS: Mounted root (ext3 filesystem) readonly on device 8:3.
[    1.028409] Freeing unused kernel memory: 288k freed
[    1.031264] usb 1-4: new high speed USB device using ehci_hcd and address 2
[    1.272011] usb 1-5: new high speed USB device using ehci_hcd and address 3
[    1.388705] scsi4 : usb-storage 1-5:1.0
[    6.388663] scsi 4:0:0:0: Direct-Access     Generic  USB SD Reader    1.00 PQ: 0 ANSI: 0
[    6.389370] scsi 4:0:0:1: Direct-Access     Generic  USB CF Reader    1.01 PQ: 0 ANSI: 0
[    6.390871] scsi 4:0:0:2: Direct-Access     Generic  USB SM Reader    1.02 PQ: 0 ANSI: 0
[    6.644477] sd 4:0:0:0: [sdb] Attached SCSI removable disk
[    6.644987] scsi 4:0:0:3: Direct-Access     Generic  USB MS Reader    1.03 PQ: 0 ANSI: 0
[    6.647856] sd 4:0:0:2: [sdd] Attached SCSI removable disk
[    6.648229] sd 4:0:0:1: [sdc] 8027712 512-byte logical blocks: (4.11 GB/3.82 GiB)
[    6.648849] sd 4:0:0:3: [sde] Attached SCSI removable disk
[    6.649725] sd 4:0:0:1: [sdc] Write Protect is off
[    6.649727] sd 4:0:0:1: [sdc] Mode Sense: 03 00 00 00
[    6.649729] sd 4:0:0:1: [sdc] Assuming drive cache: write through
[    6.652475] sd 4:0:0:1: [sdc] Assuming drive cache: write through
[    6.652518]  sdc: sdc1 sdc2
[    6.656350] sd 4:0:0:1: [sdc] Assuming drive cache: write through
[    6.656393] sd 4:0:0:1: [sdc] Attached SCSI removable disk
[    8.866713] nvidia: module license 'NVIDIA' taints kernel.
[    8.866718] Disabling lock debugging due to kernel taint
[    9.709300] ACPI: PCI Interrupt Link [LAZA] enabled at IRQ 23
[    9.709306] HDA Intel 0000:00:05.0: PCI INT B -> Link[LAZA] -> GSI 23 (level, low) -> IRQ 23
[    9.709309] hda_intel: codec_mask forced to 0xff
[    9.709330] HDA Intel 0000:00:05.0: setting latency timer to 64
[    9.709333] ALSA hda_intel.c:2503: chipset global capabilities = 0x4401
[    9.720259] ALSA hda_intel.c:1338: codec #0 probed OK
[    9.827074] ACPI: PCI Interrupt Link [LNED] enabled at IRQ 19
[    9.827084] nvidia 0000:02:00.0: PCI INT A -> Link[LNED] -> GSI 19 (level, low) -> IRQ 19
[    9.827091] nvidia 0000:02:00.0: setting latency timer to 64
[    9.827313] NVRM: loading NVIDIA UNIX x86 Kernel Module  195.30  Fri Dec 18 13:34:49 PST 2009
[   10.722259] ALSA hda_intel.c:702: azx_get_response timeout, polling the codec once: last cmd=0x100f0000
[   11.724260] ALSA hda_intel.c:702: azx_get_response timeout, polling the codec once: last cmd=0x100f0000
[   12.726010] ALSA hda_intel.c:712: azx_get_response timeout, switching to polling mode: last cmd=0x100f0000
[   13.728261] ALSA hda_intel.c:1416: Codec #1 probe error; disabling it...
[   14.738010] ALSA hda_intel.c:1416: Codec #2 probe error; disabling it...
[   15.748010] ALSA hda_intel.c:1416: Codec #3 probe error; disabling it...
[   16.758260] ALSA hda_intel.c:1416: Codec #4 probe error; disabling it...
[   17.768261] ALSA hda_intel.c:1416: Codec #5 probe error; disabling it...
[   18.778011] ALSA hda_intel.c:1416: Codec #6 probe error; disabling it...
[   19.788263] ALSA hda_intel.c:1416: Codec #7 probe error; disabling it...
[   20.038014] hda_codec: ALC883: BIOS auto-probing.
[   20.038021] ALSA hda_codec.c:4356: autoconfig: line_outs=4 (0x14/0x15/0x16/0x17/0x0)
[   20.038026] ALSA hda_codec.c:4360:    speaker_outs=0 (0x0/0x0/0x0/0x0/0x0)
[   20.038029] ALSA hda_codec.c:4364:    hp_outs=1 (0x1b/0x0/0x0/0x0/0x0)
[   20.038032] ALSA hda_codec.c:4365:    mono: mono_out=0x0
[   20.038035] ALSA hda_codec.c:4368:    dig-out=0x1e/0x0
[   20.038037] ALSA hda_codec.c:4376:    inputs: mic=0x18, fmic=0x19, line=0x1a, fline=0x0, cd=0x1c, aux=0x0
[   20.155009] ALSA patch_realtek.c:1298: realtek: Enabling init ASM_ID=0xf603 CODEC_ID=10ec0883
[   20.248018] ALSA hda_codec.c:1966: Cannot find slave Headphone Playback Volume, skipped
[   20.248021] ALSA hda_codec.c:1966: Cannot find slave Speaker Playback Volume, skipped
[   20.248024] ALSA hda_codec.c:1966: Cannot find slave Mono Playback Volume, skipped
[   20.248028] ALSA hda_codec.c:1966: Cannot find slave Line-Out Playback Volume, skipped
[   20.248031] ALSA hda_codec.c:1966: Cannot find slave PCM Playback Volume, skipped
[   20.248045] ALSA hda_codec.c:1966: Cannot find slave Speaker Playback Switch, skipped
[   20.248048] ALSA hda_codec.c:1966: Cannot find slave Mono Playback Switch, skipped
[   20.248053] ALSA hda_codec.c:1966: Cannot find slave Line-Out Playback Switch, skipped
[   20.248056] ALSA hda_codec.c:1966: Cannot find slave PCM Playback Switch, skipped
[   20.248281] HDA Intel 0000:02:00.1: PCI INT A -> Link[LNED] -> GSI 19 (level, low) -> IRQ 19
[   20.248285] hda_intel: codec_mask forced to 0xf2
[   20.248318] HDA Intel 0000:02:00.1: setting latency timer to 64
[   20.248321] ALSA hda_intel.c:2503: chipset global capabilities = 0x2403
[   20.257259] ALSA hda_intel.c:1338: codec #1 probed OK
[   21.259009] ALSA hda_intel.c:702: azx_get_response timeout, polling the codec once: last cmd=0x400f0000
[   22.261010] ALSA hda_intel.c:702: azx_get_response timeout, polling the codec once: last cmd=0x400f0000
[   23.263010] ALSA hda_intel.c:712: azx_get_response timeout, switching to polling mode: last cmd=0x400f0000
[   24.265011] ALSA hda_intel.c:1416: Codec #4 probe error; disabling it...
[   25.275010] ALSA hda_intel.c:1416: Codec #5 probe error; disabling it...
[   26.285010] ALSA hda_intel.c:1416: Codec #6 probe error; disabling it...
[   27.295010] ALSA hda_intel.c:1416: Codec #7 probe error; disabling it...
[   30.572405] Adding 979956k swap on /dev/sda2.  Priority:-1 extents:1 across:979956k 
[   30.953859] EXT3-fs (sda3): using internal journal
[   32.607318] kjournald starting.  Commit interval 5 seconds
[   32.607538] EXT3-fs (sda1): using internal journal
[   32.607543] EXT3-fs (sda1): mounted filesystem with writeback data mode

[  161.813187] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  161.822267] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, new-stream=0x6, format=0x11
[  162.234348] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  162.243261] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  162.738656] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  162.747260] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  163.305021] hda-intel: IRQ timing workaround is activated for card #1. Suggest a bigger bdl_pos_adj.
[  166.311964] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  166.320267] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  168.027272] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  168.036014] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  169.511862] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  169.520261] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  169.885729] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  169.894017] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  311.463327] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
[  311.500325] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  311.515655] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  366.557739] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
[  369.134290] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  369.143264] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  386.338642] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
[  386.744571] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  386.753017] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11

[  493.801846] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  493.810266] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  495.284022] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  495.293262] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  495.634785] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
[  495.693766] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  495.706179] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  506.608048] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  506.617270] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  508.137182] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  508.146263] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  508.196537] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  508.205262] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  509.447914] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  509.456012] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  509.622689] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  509.631259] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  509.906574] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  509.915261] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[  554.005997] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253874, pos=0/2048/16384, hwptr=1980418/1966080
[  554.006003] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253874, pos=0/2048/16384, hwptr=1982464/1982464
[  554.006007] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253874, pos=1/2048/16384, hwptr=1982464/1982464
[  554.006011] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253874, pos=1/2048/16384, hwptr=1982465/1982464
[  554.006015] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2153/2048/16384, hwptr=1982465/1982464
[  554.006019] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2156/2048/16384, hwptr=1984617/1982464
[  554.006023] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2156/2048/16384, hwptr=1984620/1982464
[  554.006026] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2157/2048/16384, hwptr=1984620/1982464
[  554.006030] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2157/2048/16384, hwptr=1984621/1982464
[  554.006034] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=254005, pos=6307/2048/16384, hwptr=1984621/1982464
[  554.006038] ALSA pcm_lib.c:429: PCM: Lost interrupts? [Q] (stream=0, delta=4150, new_hw_ptr=1988771, old_hw_ptr=1984621)
[  957.643428] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
[  957.843913] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[  957.852281] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11

I did some disk access and then dmesg again:

[ 1180.623232] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
[ 1186.186365] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[ 1186.195014] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[ 1192.728324] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
[ 1193.945282] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[ 1193.954014] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[ 1225.955241] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
[ 1228.129086] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[ 1228.138017] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
[ 1313.943815] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
[ 1314.455770] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
[ 1314.464265] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11


[-- Attachment #3: syslog --]
[-- Type: application/octet-stream, Size: 5619 bytes --]

Mar 11 11:05:05 test kernel: [  493.801846] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:05:05 test kernel: [  493.810266] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:05:07 test kernel: [  495.284022] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:05:07 test kernel: [  495.293262] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:05:07 test kernel: [  495.634785] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
Mar 11 11:05:07 test kernel: [  495.693766] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:05:07 test kernel: [  495.706179] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:05:18 test kernel: [  506.608048] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:05:18 test kernel: [  506.617270] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:05:20 test kernel: [  508.137182] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:05:20 test kernel: [  508.146263] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:05:20 test kernel: [  508.196537] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:05:20 test kernel: [  508.205262] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:05:21 test kernel: [  509.447914] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:05:21 test kernel: [  509.456012] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:05:21 test kernel: [  509.622689] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:05:21 test kernel: [  509.631259] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:05:21 test kernel: [  509.906574] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:05:21 test kernel: [  509.915261] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:06:05 test kernel: [  554.005997] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253874, pos=0/2048/16384, hwptr=1980418/1966080
Mar 11 11:06:05 test kernel: [  554.006003] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253874, pos=0/2048/16384, hwptr=1982464/1982464
Mar 11 11:06:05 test kernel: [  554.006007] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253874, pos=1/2048/16384, hwptr=1982464/1982464
Mar 11 11:06:05 test kernel: [  554.006011] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253874, pos=1/2048/16384, hwptr=1982465/1982464
Mar 11 11:06:05 test kernel: [  554.006015] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2153/2048/16384, hwptr=1982465/1982464
Mar 11 11:06:05 test kernel: [  554.006019] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2156/2048/16384, hwptr=1984617/1982464
Mar 11 11:06:05 test kernel: [  554.006023] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2156/2048/16384, hwptr=1984620/1982464
Mar 11 11:06:05 test kernel: [  554.006026] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2157/2048/16384, hwptr=1984620/1982464
Mar 11 11:06:05 test kernel: [  554.006030] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=253919, pos=2157/2048/16384, hwptr=1984621/1982464
Mar 11 11:06:05 test kernel: [  554.006034] ALSA pcm_lib.c:249: hwptr log: pcmC1D3p:0: j=254005, pos=6307/2048/16384, hwptr=1984621/1982464
Mar 11 11:06:05 test kernel: [  554.006038] ALSA pcm_lib.c:429: PCM: Lost interrupts? [Q] (stream=0, delta=4150, new_hw_ptr=1988771, old_hw_ptr=1984621)
Mar 11 11:12:49 test kernel: [  957.643428] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
Mar 11 11:12:49 test kernel: [  957.843913] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:12:49 test kernel: [  957.852281] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:16:32 test kernel: [ 1180.623232] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
Mar 11 11:16:38 test kernel: [ 1186.186365] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:16:38 test kernel: [ 1186.195014] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:16:44 test kernel: [ 1192.728324] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
Mar 11 11:16:45 test kernel: [ 1193.945282] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:16:45 test kernel: [ 1193.954014] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:17:17 test kernel: [ 1225.955241] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
Mar 11 11:17:20 test kernel: [ 1228.129086] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:17:20 test kernel: [ 1228.138017] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:18:45 test kernel: [ 1313.943815] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
Mar 11 11:18:46 test kernel: [ 1314.455770] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:18:46 test kernel: [ 1314.464265] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11
Mar 11 11:19:28 test kernel: [ 1356.664030] ALSA pcm_lib.c:167: XRUN: pcmC1D3p:0
Mar 11 11:19:28 test kernel: [ 1356.664128] ALSA hda_intel.c:1661: azx_pcm_prepare: bufsize=0x10000, format=0x11
Mar 11 11:19:28 test kernel: [ 1356.673264] ALSA patch_nvhdmi.c:865: hdmi_setup_stream: NID=0x4, stream=0x6, format=0x11


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-11 18:32                                                             ` Jaroslav Kysela
@ 2010-03-12  4:32                                                               ` VDR User
  -1 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-12  4:32 UTC (permalink / raw)
  To: Jaroslav Kysela
  Cc: Wu Fengguang, Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela,
	linux-kernel, akpm, Pavel Hofman

On Thu, Mar 11, 2010 at 10:32 AM, Jaroslav Kysela <perex@perex.cz> wrote:
> All these parameters should be set: CONFIG_SND_PCM_XRUN_DEBUG,
> CONFIG_SND_VERBOSE_PROCFS, CONFIG_SND_DEBUG . I updated wiki.

I have replied with both the result of my dmesg and syslog.  However,
the mailing list seems to have rejected the message due to size (62k,
but 60k is the limit).  Please let me know if you've received that
post or if I have to repost and split dmesg + syslog into two.

Thanks,
Derek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-12  4:32                                                               ` VDR User
  0 siblings, 0 replies; 80+ messages in thread
From: VDR User @ 2010-03-12  4:32 UTC (permalink / raw)
  To: Jaroslav Kysela
  Cc: Wei Ni, Takashi Iwai, alsa-devel, Jaroslav Kysela, linux-kernel,
	akpm, Wu Fengguang, Pavel Hofman

On Thu, Mar 11, 2010 at 10:32 AM, Jaroslav Kysela <perex@perex.cz> wrote:
> All these parameters should be set: CONFIG_SND_PCM_XRUN_DEBUG,
> CONFIG_SND_VERBOSE_PROCFS, CONFIG_SND_DEBUG . I updated wiki.

I have replied with both the result of my dmesg and syslog.  However,
the mailing list seems to have rejected the message due to size (62k,
but 60k is the limit).  Please let me know if you've received that
post or if I have to repost and split dmesg + syslog into two.

Thanks,
Derek

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [alsa-devel] [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-12  4:32                                                               ` VDR User
@ 2010-03-12  4:37                                                                 ` Wu Fengguang
  -1 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-12  4:37 UTC (permalink / raw)
  To: VDR User
  Cc: Jaroslav Kysela, Wei Ni, Takashi Iwai, alsa-devel,
	Jaroslav Kysela, linux-kernel, akpm, Pavel Hofman

On Fri, Mar 12, 2010 at 12:32:51PM +0800, VDR User wrote:
> On Thu, Mar 11, 2010 at 10:32 AM, Jaroslav Kysela <perex@perex.cz> wrote:
> > All these parameters should be set: CONFIG_SND_PCM_XRUN_DEBUG,
> > CONFIG_SND_VERBOSE_PROCFS, CONFIG_SND_DEBUG . I updated wiki.
> 
> I have replied with both the result of my dmesg and syslog.  However,
> the mailing list seems to have rejected the message due to size (62k,
> but 60k is the limit).  Please let me know if you've received that
> post or if I have to repost and split dmesg + syslog into two.

Never mind, the CC'ed users should be able to receive it.

Thanks,
Fengguang


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
@ 2010-03-12  4:37                                                                 ` Wu Fengguang
  0 siblings, 0 replies; 80+ messages in thread
From: Wu Fengguang @ 2010-03-12  4:37 UTC (permalink / raw)
  To: VDR User
  Cc: Wei Ni, alsa-devel, Takashi Iwai, linux-kernel, Jaroslav Kysela,
	akpm, Pavel Hofman

On Fri, Mar 12, 2010 at 12:32:51PM +0800, VDR User wrote:
> On Thu, Mar 11, 2010 at 10:32 AM, Jaroslav Kysela <perex@perex.cz> wrote:
> > All these parameters should be set: CONFIG_SND_PCM_XRUN_DEBUG,
> > CONFIG_SND_VERBOSE_PROCFS, CONFIG_SND_DEBUG . I updated wiki.
> 
> I have replied with both the result of my dmesg and syslog.  However,
> the mailing list seems to have rejected the message due to size (62k,
> but 60k is the limit).  Please let me know if you've received that
> post or if I have to repost and split dmesg + syslog into two.

Never mind, the CC'ed users should be able to receive it.

Thanks,
Fengguang

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-12  4:32                                                               ` VDR User
  (?)
  (?)
@ 2010-03-12  8:08                                                               ` Jaroslav Kysela
       [not found]                                                                 ` <a3ef07921003121120h7b2b3289q7863de625f50e5d@mail.gmail.com>
  -1 siblings, 1 reply; 80+ messages in thread
From: Jaroslav Kysela @ 2010-03-12  8:08 UTC (permalink / raw)
  To: VDR User; +Cc: ALSA development

On Thu, 11 Mar 2010, VDR User wrote:

> On Thu, Mar 11, 2010 at 10:32 AM, Jaroslav Kysela <perex@perex.cz> wrote:
>> All these parameters should be set: CONFIG_SND_PCM_XRUN_DEBUG,
>> CONFIG_SND_VERBOSE_PROCFS, CONFIG_SND_DEBUG . I updated wiki.
>
> I have replied with both the result of my dmesg and syslog.  However,
> the mailing list seems to have rejected the message due to size (62k,
> but 60k is the limit).  Please let me know if you've received that
> post or if I have to repost and split dmesg + syslog into two.

I received that. Please, stop cross posting.

I don't see the problem (the ring buffer positions were dumped too early 
when one interrupt was missed). Try value 37 for xrun_debug proc file and 
send log files directly to me or send only an URL to obtain them 
(http://pastebin.ca works ok).

 					Thanks,
 						Jaroslav

-----
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
       [not found]                                                                         ` <a3ef07921003131222i121a8d54nba5dd3fbcdae3ac0@mail.gmail.com>
@ 2010-03-14  8:29                                                                           ` Jaroslav Kysela
  0 siblings, 0 replies; 80+ messages in thread
From: Jaroslav Kysela @ 2010-03-14  8:29 UTC (permalink / raw)
  To: VDR User; +Cc: ALSA development

On Sat, 13 Mar 2010, VDR User wrote:

> [pid  9629] 1268511516.215224 ioctl(18, 0x400c4150, 0xb43631a4) = 0

^^^^ here xine feeds new samples to the ALSA driver 
(0x400c4150 == SNDRV_PCM_IOCTL_WRITEI_FRAMES)

> [pid  9629] 1268511516.215275 ioctl(18, 0x80044121, 0xb43632cc) = 0
> [pid  9627] 1268511520.700109 ioctl(10, 0xc0104652, 0xb5443f00) = 0
> [pid  9629] 1268511520.700340 ioctl(18, 0x80044121, 0xb43632cc) = -1
> EPIPE (Broken pipe)

^^^^ next iteration (0x80044121 == SNDRV_PCM_IOCTL_DELAY) - see time 
difference - 4.485 seconds from last WRITEI

It seems like a xine bug or the system scheduler bug or any kernel bug 
affecting the system scheduler. The ALSA subsystem is not reponsible for 
this behaviour - the ring buffer in your case is for about 0.372 seconds 
of samples. This limit must not be crossed for the click-free playback.

Ask the xine developers for more help or try another player.

 					Jaroslav

-----
Jaroslav Kysela <perex@perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
  2010-03-05  2:41                                       ` Wei Ni
  (?)
  (?)
@ 2010-04-07  0:39                                       ` globalillo
  2010-04-07  1:23                                         ` globalillo
  -1 siblings, 1 reply; 80+ messages in thread
From: globalillo @ 2010-04-07  0:39 UTC (permalink / raw)
  To: Wei Ni; +Cc: alsa-devel

Hi Wei, what about mobile chipsets? any plans? GT240M, etc.

Regards

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH]Support MCP89 and GT21x hdmi audio
  2010-04-07  0:39                                       ` globalillo
@ 2010-04-07  1:23                                         ` globalillo
  0 siblings, 0 replies; 80+ messages in thread
From: globalillo @ 2010-04-07  1:23 UTC (permalink / raw)
  To: Wei Ni; +Cc: alsa-devel

I test your patch and although it's recognized as GT220, hdmi output
works correctly on hw:1,7

Thanks and sorry for the inconvenience.

^ permalink raw reply	[flat|nested] 80+ messages in thread

end of thread, other threads:[~2010-04-07  1:23 UTC | newest]

Thread overview: 80+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-01 11:27 [PATCH]Support MCP89 and GT21x hdmi audio Wei Ni
2010-03-02  5:43 ` [alsa-devel] " Wu Fengguang
2010-03-03  3:33   ` Wei Ni
2010-03-03  3:33     ` Wei Ni
2010-03-03  6:46   ` [alsa-devel] " Takashi Iwai
2010-03-03  6:46     ` Takashi Iwai
2010-03-04  1:17     ` [alsa-devel] " Wu Fengguang
2010-03-04  1:17       ` Wu Fengguang
2010-03-04  2:18     ` [alsa-devel] " Wu Fengguang
2010-03-04  5:44       ` Wu Fengguang
2010-03-04  5:52         ` Wei Ni
2010-03-04  6:09           ` Wu Fengguang
2010-03-02  7:59 ` Takashi Iwai
2010-03-02  7:59   ` Takashi Iwai
2010-03-02  9:43   ` [alsa-devel] " Wei Ni
2010-03-02  9:43     ` Wei Ni
2010-03-02  9:55     ` [alsa-devel] " Takashi Iwai
2010-03-02  9:55       ` Takashi Iwai
2010-03-02 10:03       ` [alsa-devel] " Wei Ni
2010-03-02 10:42         ` Takashi Iwai
2010-03-02 10:42           ` Takashi Iwai
2010-03-02 10:44           ` [alsa-devel] " Wei Ni
2010-03-03  3:28       ` Wei Ni
2010-03-03  4:06         ` Wei Ni
2010-03-03  6:44           ` Takashi Iwai
2010-03-03  6:44             ` Takashi Iwai
2010-03-03  7:21             ` [alsa-devel] " Wei Ni
2010-03-03  7:21               ` Wei Ni
2010-03-03 21:49               ` [alsa-devel] " Takashi Iwai
2010-03-03 21:49                 ` Takashi Iwai
2010-03-04  2:21                 ` [alsa-devel] " Wei Ni
2010-03-04  9:46                   ` Takashi Iwai
2010-03-04  9:46                     ` Takashi Iwai
2010-03-04 10:46                     ` [alsa-devel] " Wei Ni
2010-03-04 10:46                       ` Wei Ni
2010-03-04 10:56                       ` [alsa-devel] " Takashi Iwai
2010-03-04 10:56                         ` Takashi Iwai
2010-03-04 11:09                         ` [alsa-devel] " Wei Ni
2010-03-04 11:31                           ` Takashi Iwai
2010-03-04 11:31                             ` Takashi Iwai
2010-03-04 11:37                             ` [alsa-devel] " Wei Ni
2010-03-04 11:43                               ` Takashi Iwai
2010-03-04 11:43                                 ` Takashi Iwai
2010-03-04 11:46                                 ` [alsa-devel] " Wei Ni
2010-03-04 15:34                                   ` Takashi Iwai
2010-03-05  2:41                                     ` Wei Ni
2010-03-05  2:41                                       ` Wei Ni
2010-03-07 19:21                                       ` [alsa-devel] " VDR User
2010-03-07 19:21                                         ` VDR User
2010-03-08  4:35                                         ` [alsa-devel] " Wei Ni
2010-03-08  4:35                                           ` Wei Ni
2010-03-08  4:46                                           ` [alsa-devel] " Wu Fengguang
2010-03-08  4:46                                             ` Wu Fengguang
2010-03-10  5:42                                             ` [alsa-devel] " VDR User
2010-03-10  5:42                                               ` VDR User
2010-03-10  6:01                                               ` [alsa-devel] " Wu Fengguang
2010-03-10  6:01                                                 ` Wu Fengguang
2010-03-10  7:58                                               ` [alsa-devel] " Jaroslav Kysela
2010-03-10  7:58                                                 ` Jaroslav Kysela
2010-03-10  8:05                                                 ` [alsa-devel] " VDR User
2010-03-10  8:17                                                   ` Jaroslav Kysela
2010-03-10  9:44                                                     ` Takashi Iwai
2010-03-10 12:54                                                   ` [alsa-devel] " Wu Fengguang
2010-03-10 12:54                                                     ` Wu Fengguang
2010-03-10 17:38                                                     ` [alsa-devel] " VDR User
2010-03-10 17:38                                                       ` VDR User
2010-03-11  7:30                                                       ` [alsa-devel] " Jaroslav Kysela
2010-03-11 18:15                                                         ` VDR User
2010-03-11 18:15                                                           ` VDR User
2010-03-11 18:32                                                           ` [alsa-devel] " Jaroslav Kysela
2010-03-11 18:32                                                             ` Jaroslav Kysela
2010-03-11 19:24                                                             ` [alsa-devel] " VDR User
2010-03-12  4:32                                                             ` VDR User
2010-03-12  4:32                                                               ` VDR User
2010-03-12  4:37                                                               ` [alsa-devel] " Wu Fengguang
2010-03-12  4:37                                                                 ` Wu Fengguang
2010-03-12  8:08                                                               ` Jaroslav Kysela
     [not found]                                                                 ` <a3ef07921003121120h7b2b3289q7863de625f50e5d@mail.gmail.com>
     [not found]                                                                   ` <alpine.LNX.2.00.1003131410550.4672@eeebox2.perex-int.cz>
     [not found]                                                                     ` <a3ef07921003131037q21ad995fwd046dba0e9fa1ef7@mail.gmail.com>
     [not found]                                                                       ` <alpine.LNX.2.00.1003131955590.4672@eeebox2.perex-int.cz>
     [not found]                                                                         ` <a3ef07921003131222i121a8d54nba5dd3fbcdae3ac0@mail.gmail.com>
2010-03-14  8:29                                                                           ` Jaroslav Kysela
2010-04-07  0:39                                       ` globalillo
2010-04-07  1:23                                         ` globalillo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.