All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] azx/realtek: Unify and parameterize code for ALC880/260 codecs, take 2
@ 2004-12-16 21:11 Stephen Warren
  2004-12-17 14:18 ` Takashi Iwai
  0 siblings, 1 reply; 2+ messages in thread
From: Stephen Warren @ 2004-12-16 21:11 UTC (permalink / raw)
  To: alsa-devel

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

This patch updates the HD-Audio ALC880/260 code driver such
that all board-specific decisions are made in a single function,
which sets variables that all other code simply uses directly
without decision making.

Also, tweak snd_hda_add_new_ctls and snd_hda_resume_ctls so they
use a sentinel value in the array of controls, and hence don't have
to be passed an explicit array-size argument.

This has the benefits of:

* Isolating board-specific code to a single location
* Simplifying the rest of the code
* Unifying the code for ALC880/ALC260, which was previously separate.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---

Note: This patch was generated by "cvs diff -u". Hopefully, that's a
useful format - there are some extra lines of gunk that single-file
regular "diff -u" doesn't generate...

This is an updated version of the patch I sent yesterday, that also
tweaks the tweak snd_hda_add_new_ctls/snd_hda_resume_ctls API.

For now, I think I'm done with generic changes to the AZX codec, so the
patch is complete, unless you find any problems with it.

I'm punting on making patch_alc880/260 use pre-initialized data
structures for codec->spec for now - the code isn't too hairy yet, and
it'll be something very easily added later on if we decide to do it.

-- 
Stephen Warren, Software Engineer, NVIDIA, Fort Collins, CO
swarren@nvidia.com        http://www.nvidia.com/
swarren@wwwdotorg.org     http://www.wwwdotorg.org/pgp.html

[-- Attachment #2: realtek.cvs.7.diff --]
[-- Type: application/octet-stream, Size: 32392 bytes --]

? patch_realtek.c.0
? patch_realtek.c.1
? patch_realtek.c.2
? patch_realtek.c.3
? patch_realtek.c.4
? patch_realtek.c.5
? patch_realtek.c.6
? patch_realtek.c.6.w810
? patch_realtek.c.7
? patch_realtek.c.7.w810
? realtek.1.diff
? realtek.2.diff
? realtek.3.diff
? realtek.4.diff
? realtek.5.diff
? realtek.cvs.7.diff
? realtek.full.6.diff
? xxx
Index: hda_codec.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pci/azx/hda_codec.c,v
retrieving revision 1.5
diff -u -r1.5 hda_codec.c
--- hda_codec.c	15 Dec 2004 15:42:39 -0000	1.5
+++ hda_codec.c	16 Dec 2004 21:05:55 -0000
@@ -89,7 +89,7 @@
  * @direct: direct flag
  * @verb: the verb to send
  * @parm: the parameter for the verb
- * 
+ *
  * Send a single command without waiting for response.
  *
  * Returns 0 if successful, or a negative error code.
@@ -121,7 +121,7 @@
 /**
  * snd_hda_get_sub_nodes - get the range of sub nodes
  * @codec: the HDA codec
- * @nid: NID to parse 
+ * @nid: NID to parse
  * @start_id: the pointer to store the start NID
  *
  * Parse the NID and store the start NID of its sub-nodes.
@@ -139,7 +139,7 @@
 /**
  * snd_hda_get_connections - get connection list
  * @codec: the HDA codec
- * @nid: NID to parse 
+ * @nid: NID to parse
  * @conn_list: connection list array
  * @max_conns: max. number of connections to store
  *
@@ -398,7 +398,7 @@
 		snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
 		return -ENOMEM;
 	}
-		
+
 	codec->bus = bus;
 	codec->addr = codec_addr;
 	init_MUTEX(&codec->spdif_mutex);
@@ -431,7 +431,7 @@
 		snd_hda_codec_free(codec);
 		return err;
 	}
-	
+
 	snd_hda_codec_proc_new(codec);
 
 	sprintf(component, "HDA%08x", codec->vendor_id);
@@ -569,7 +569,7 @@
 	get_vol_mute(codec, info, nid, ch, direction, index);
 	return info->vol[ch];
 }
-		
+
 int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val)
 {
 	struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
@@ -730,7 +730,7 @@
 					   IEC958_AES1_CON_ORIGINAL;
 	return 0;
 }
-                        
+
 static int snd_hda_spdif_pmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
@@ -750,7 +750,7 @@
 
 	return 0;
 }
-                        
+
 static int snd_hda_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -812,7 +812,7 @@
 
 	ucontrol->value.integer.value[0] = codec->spdif_status & 1;
 	return 0;
-}	
+}
 
 static int snd_hda_spdif_out_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
@@ -863,6 +863,7 @@
 		.get = snd_hda_spdif_out_switch_get,
 		.put = snd_hda_spdif_out_switch_put,
 	},
+	{ } /* end */
 };
 
 /**
@@ -900,7 +901,7 @@
  * @bus: the BUS
  *
  * Creates mixer controls for each codec included in the bus.
- * 
+ *
  * Returns 0 if successful, otherwise a negative error code.
  */
 int snd_hda_build_controls(struct hda_bus *bus)
@@ -1027,7 +1028,7 @@
 	unsigned int val, streams;
 
 	val = 0;
-	if (nid != codec->afg && 
+	if (nid != codec->afg &&
 	    snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_FORMAT_OVRD) {
 		val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
 		if (val == -1)
@@ -1119,7 +1120,7 @@
 	int i;
 	unsigned int val = 0, rate;
 
-	if (nid != codec->afg && 
+	if (nid != codec->afg &&
 	    snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_FORMAT_OVRD) {
 		val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
 		if (val == -1)
@@ -1261,7 +1262,7 @@
  * ops.prepare should be called in the prepare or hw_params callback
  * with the proper parameters for set up.
  * ops.cleanup should be called in hw_free for clean up of streams.
- * 
+ *
  * This function returns 0 if successfull, or a negative error code.
  */
 int snd_hda_build_pcms(struct hda_bus *bus)
@@ -1340,12 +1341,12 @@
  * This helper function creates and add new controls in the given array.
  * Returns 0 if successful, or a negative error code.
  */
-int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew, int num_counts)
+int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew)
 {
-	int i, err;
+	int err;
 
-	for (i = 0; i < num_counts; i++) {
-		err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew[i], codec));
+	for (; knew->name; knew++) {
+		err = snd_ctl_add(codec->bus->card, snd_ctl_new1(knew, codec));
 		if (err < 0)
 			return err;
 	}
@@ -1551,16 +1552,15 @@
  * This function resumes the mixer controls in the snd_kcontrol_new_t array,
  * originally for snd_hda_add_new_ctls().
  */
-int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew, int num_counts)
+int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew)
 {
-	int i;
 	snd_ctl_elem_value_t *val;
 
 	val = kmalloc(sizeof(*val), GFP_KERNEL);
 	if (! val)
 		return -ENOMEM;
 	codec->in_resume = 1;
-	for (i = 0; i < num_counts; i++) {
+	for (; knew->name; knew++) {
 		int i, count;
 		count = knew->count ? knew->count : 1;
 		for (i = 0; i < count; i++) {
@@ -1589,7 +1589,7 @@
  */
 int snd_hda_resume_spdif_out(struct hda_codec *codec)
 {
-	return snd_hda_resume_ctls(codec, dig_mixes, ARRAY_SIZE(dig_mixes));
+	return snd_hda_resume_ctls(codec, dig_mixes);
 }
 #endif
 
Index: hda_local.h
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pci/azx/hda_local.h,v
retrieving revision 1.1
diff -u -r1.1 hda_local.h
--- hda_local.h	15 Dec 2004 15:42:39 -0000	1.1
+++ hda_local.h	16 Dec 2004 21:05:55 -0000
@@ -2,7 +2,7 @@
  * Universal Interface for Intel High Definition Audio Codec
  *
  * Local helper functions
- * 
+ *
  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
  *
  *  This program is free software; you can redistribute it and/or modify it
@@ -130,13 +130,13 @@
 };
 
 int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl);
-int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew, int num_counts);
+int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
 
 /*
  * power management
  */
 #ifdef CONFIG_PM
-int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew, int num_counts);
+int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
 int snd_hda_resume_spdif_out(struct hda_codec *codec);
 #endif
 
Index: patch_cmedia.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pci/azx/patch_cmedia.c,v
retrieving revision 1.3
diff -u -r1.3 patch_cmedia.c
--- patch_cmedia.c	15 Dec 2004 15:42:40 -0000	1.3
+++ patch_cmedia.c	16 Dec 2004 21:05:59 -0000
@@ -1,10 +1,10 @@
 /*
  * Universal Interface for Intel High Definition Audio Codec
- * 
+ *
  * HD audio interface patch for C-Media CMI9880
  *
  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
- *                    
+ *
  *
  *  This driver is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -214,6 +214,7 @@
 	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT),
 	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x23, 0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x23, 0, HDA_OUTPUT),
+	{ } /* end */
 };
 
 /*
@@ -227,6 +228,7 @@
 		.get = cmi_ch_mode_get,
 		.put = cmi_ch_mode_put,
 	},
+	{ } /* end */
 };
 
 /* AUD-in selections:
@@ -241,7 +243,7 @@
 		{ "CD", 0x7 },
 	}
 };
-       
+
 static struct hda_input_mux cmi9880_no_line_mux = {
 	.num_items = 3,
 	.items = {
@@ -250,7 +252,7 @@
 		{ "CD", 0x7 },
 	}
 };
-       
+
 /* front, rear, clfe, rear_surr */
 static hda_nid_t cmi9880_dac_nids[4] = {
 	0x03, 0x04, 0x05, 0x06
@@ -324,13 +326,11 @@
 	struct cmi_spec *spec = codec->spec;
 	int err;
 
-	err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer,
-				   ARRAY_SIZE(cmi9880_basic_mixer));
+	err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
 	if (err < 0)
 		return err;
 	if (spec->surr_switch) {
-		err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer,
-					   ARRAY_SIZE(cmi9880_ch_mode_mixer));
+		err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer);
 		if (err < 0)
 			return err;
 	}
@@ -362,9 +362,9 @@
 	struct cmi_spec *spec = codec->spec;
 
 	cmi9880_init(codec);
-	snd_hda_resume_ctls(codec, cmi9880_basic_mixer, ARRAY_SIZE(cmi9880_basic_mixer));
+	snd_hda_resume_ctls(codec, cmi9880_basic_mixer);
 	if (spec->surr_switch)
-		snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer, ARRAY_SIZE(cmi9880_ch_mode_mixer));
+		snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer);
 	if (spec->multiout.dig_out_nid)
 		snd_hda_resume_spdif_out(codec);
 
Index: patch_realtek.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/pci/azx/patch_realtek.c,v
retrieving revision 1.3
diff -u -r1.3 patch_realtek.c
--- patch_realtek.c	15 Dec 2004 15:42:40 -0000	1.3
+++ patch_realtek.c	16 Dec 2004 21:06:00 -0000
@@ -1,6 +1,6 @@
 /*
  * Universal Interface for Intel High Definition Audio Codec
- * 
+ *
  * HD audio interface patch for ALC 260/880 codecs
  *
  * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw>
@@ -38,13 +38,26 @@
 	ALC880_3ST_DIG,
 	ALC880_5ST,
 	ALC880_5ST_DIG,
+	ALC880_W810,
 };
 
 struct alc_spec {
-	int board_config;
-	unsigned int five_stack: 1;
+	/* codec parameterization */
 	unsigned int front_panel: 1;
 
+	snd_kcontrol_new_t* mixers[2];
+	unsigned int num_mixers;
+
+	struct hda_verb *init_verbs;
+
+	char* stream_name_analog;
+	struct hda_pcm_stream *stream_analog_playback;
+	struct hda_pcm_stream *stream_analog_capture;
+
+	char* stream_name_digital;
+	struct hda_pcm_stream *stream_digital_playback;
+	struct hda_pcm_stream *stream_digital_capture;
+
 	/* playback */
 	struct hda_multi_out multiout;
 
@@ -59,15 +72,24 @@
 
 	/* channel model */
 	const struct alc_channel_mode *channel_mode;
+	int num_channel_mode;
 
-	struct hda_pcm pcm_rec[2];	/* PCM information */
+	/* PCM information */
+	struct hda_pcm pcm_rec[2];
 };
 
 /* DAC/ADC assignment */
+
 static hda_nid_t alc880_dac_nids[4] = {
 	/* front, rear, clfe, rear_surr */
 	0x02, 0x05, 0x04, 0x03
 };
+
+static hda_nid_t alc880_w810_dac_nids[4] = {
+	/* front, rear/surround, clfe */
+	0x02, 0x03, 0x04
+};
+
 static hda_nid_t alc880_adc_nids[3] = {
 	/* ADC0-2 */
 	0x07, 0x08, 0x09,
@@ -76,12 +98,11 @@
 #define ALC880_DIGOUT_NID	0x06
 #define ALC880_DIGIN_NID	0x0a
 
-#if 0
 static hda_nid_t alc260_dac_nids[1] = {
 	/* front */
 	0x02,
 };
-#endif
+
 static hda_nid_t alc260_adc_nids[2] = {
 	/* ADC0-1 */
 	0x04, 0x05,
@@ -118,7 +139,7 @@
 	struct alc_spec *spec = codec->spec;
 	return snd_hda_input_mux_info(spec->input_mux, uinfo);
 }
- 
+
 static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -155,7 +176,7 @@
  * set the path ways for 2 channel output
  * need to set the codec line out and mic 1 pin widgets to inputs
  */
-static struct hda_verb threestack_ch2_init[] = {
+static struct hda_verb alc880_threestack_ch2_init[] = {
 	/* set pin widget 1Ah (line in) for input */
 	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
 	/* set pin widget 18h (mic1) for input, for mic also enable the vref */
@@ -171,7 +192,7 @@
  * 6ch mode
  * need to set the codec line out and mic 1 pin widgets to outputs
  */
-static struct hda_verb threestack_ch6_init[] = {
+static struct hda_verb alc880_threestack_ch6_init[] = {
 	/* set pin widget 1Ah (line in) for output */
 	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 	/* set pin widget 18h (mic1) for output */
@@ -211,9 +232,9 @@
 	{ } /* end */
 };
 
-static struct alc_channel_mode threestack_modes[2] = {
-	{ 2, threestack_ch2_init },
-	{ 6, threestack_ch6_init },
+static struct alc_channel_mode alc880_threestack_modes[2] = {
+	{ 2, alc880_threestack_ch2_init },
+	{ 6, alc880_threestack_ch6_init },
 };
 
 
@@ -224,7 +245,7 @@
 /* set the path ways for 6 channel output
  * need to set the codec line out and mic 1 pin widgets to inputs
  */
-static struct hda_verb fivestack_ch6_init[] = {
+static struct hda_verb alc880_fivestack_ch6_init[] = {
 	/* set pin widget 1Ah (line in) for input */
 	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
 	/* mute the output for Line In PW */
@@ -233,7 +254,7 @@
 };
 
 /* need to set the codec line out and mic 1 pin widgets to outputs */
-static struct hda_verb fivestack_ch8_init[] = {
+static struct hda_verb alc880_fivestack_ch8_init[] = {
 	/* set pin widget 1Ah (line in) for output */
 	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 	/* unmute the output for Line In PW */
@@ -250,10 +271,31 @@
 	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
 	{ } /* end */
 };
-	
-static struct alc_channel_mode fivestack_modes[2] = {
-	{ 6, fivestack_ch6_init },
-	{ 8, fivestack_ch8_init },
+
+static struct alc_channel_mode alc880_fivestack_modes[2] = {
+	{ 6, alc880_fivestack_ch6_init },
+	{ 8, alc880_fivestack_ch8_init },
+};
+
+/*
+ * channel source setting (6/8 channel selection for W810)
+ *
+ * W810 has rear IO for:
+ * Front (DAC 02)
+ * Surround (DAC 03)
+ * Center/LFE (DAC 04)
+ * Digital out (06)
+ *
+ * It also has a pair of internal speakers, and a headphone jack,
+ * both connected to Line2 on the codec. This output has a hardware
+ * volume control (variable resistor - no software API).
+ *
+ * For input, there's a microphone jack, and an "audio in" jack.
+ * These may not do anything useful with this driver yet.
+ */
+
+static struct alc_channel_mode alc880_w810_modes[2] = {
+	{ 6, 0 }
 };
 
 /*
@@ -353,30 +395,60 @@
 		.get = alc880_ch_mode_get,
 		.put = alc880_ch_mode_put,
 	},
+	{ } /* end */
 };
 
 static snd_kcontrol_new_t alc880_side_mixer[] = {
 	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Side Playback Switch", 0x19, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 * FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 3,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{ } /* end */
 };
 
 /*
  */
-static int alc880_build_controls(struct hda_codec *codec)
+static int alc_build_controls(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	int err;
+	int i;
 
-	err = snd_hda_add_new_ctls(codec, alc880_base_mixer,
-				   ARRAY_SIZE(alc880_base_mixer));
-	if (err < 0)
-		return err;
-	if (spec->five_stack) {
-		err = snd_hda_add_new_ctls(codec, alc880_side_mixer,
-					   ARRAY_SIZE(alc880_side_mixer));
+	for (i = 0; i < spec->num_mixers; i++) {
+		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
 		if (err < 0)
 			return err;
 	}
+
 	if (spec->multiout.dig_out_nid) {
 		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
 		if (err < 0)
@@ -389,7 +461,7 @@
  * initialize the codec volumes, etc
  */
 
-static struct hda_verb alc880_three_stack_volume[] = {
+static struct hda_verb alc880_init_verbs_three_stack[] = {
 	/* Line In pin widget(nid=0x14) for input */
 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
 	/* CD pin widget(nid=0x1C) for input */
@@ -464,7 +536,7 @@
 	{ }
 };
 
-static struct hda_verb alc880_five_stack_volume[] = {
+static struct hda_verb alc880_init_verbs_five_stack[] = {
 	/* Line In pin widget(nid=0x14) for input */
 	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
 	/* CD pin widget(nid=0x1C) for input */
@@ -540,13 +612,83 @@
 	{ }
 };
 
-static int alc880_init(struct hda_codec *codec)
+static struct hda_verb alc880_w810_init_verbs[] = {
+	/* front channel selector/amp: input 0: DAC: Unmuted, (no volume selection) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+	/* front channel selector/amp: input 1: Capture mix: Unmuted, (no volume selection) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+
+	/* front channel selector/amp: output 0: Unmuted, max volume */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb040},
+
+	/* front out pin: unmuted, (no volume selection)  */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+	/* front out pin: headphone enable, out enable, vref disabled */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+	/* surround channel selector/amp: input 0: DAC: Unmuted, (no volume selection) */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+	/* surround channel selector/amp: input 1: Capture mix: Unmuted, (no volume selection) */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+
+	/* surround channel selector/amp: output 0: Unmuted, max volume */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb040},
+
+	/* surround out pin: unmuted, (no volume selection)  */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+	/* surround out pin: headphone enable, out enable, vref disabled */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+	/* c/lfe channel selector/amp: input 0: DAC: Unmuted, (no volume selection) */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+	/* c/lfe channel selector/amp: input 1: Capture mix: Unmuted, (no volume selection) */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+
+	/* c/lfe channel selector/amp: output 0: Unmuted, max volume */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb040},
+
+	/* c/lfe out pin: unmuted, (no volume selection)  */
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+	/* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+	/* hphone/speaker input selector: front DAC */
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
+
+	/* hphone/speaker out pin: unmuted, (no volume selection)  */
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+	/* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+#if 0
+	/* gpio direction: gpio0 input, gpio1 output */
+	{0x01, 0x717, 2},
+
+	/* gpio data: gpio0: 0, gpio1: 1 */
+	{0x01, 0x715, 2},
+
+	/* gpio enable: gpio0 no, gpio1 yes */
+	{0x01, 0x716, 2},
+#endif
+
+	{ }
+};
+
+static int alc_init(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	if (spec->five_stack)
-		snd_hda_sequence_write(codec, alc880_five_stack_volume);
-	else
-		snd_hda_sequence_write(codec, alc880_three_stack_volume);
+	snd_hda_sequence_write(codec, spec->init_verbs);
 	return 0;
 }
 
@@ -554,14 +696,15 @@
 /*
  * resume
  */
-static int alc880_resume(struct hda_codec *codec, unsigned int state)
+static int alc_resume(struct hda_codec *codec, unsigned int state)
 {
 	struct alc_spec *spec = codec->spec;
+	int i;
 
-	alc880_init(codec);
-	snd_hda_resume_ctls(codec, alc880_base_mixer, ARRAY_SIZE(alc880_base_mixer));
-	if (spec->five_stack)
-		snd_hda_resume_ctls(codec, alc880_side_mixer, ARRAY_SIZE(alc880_side_mixer));
+	alc_init(codec);
+	for (i = 0; i < spec->num_mixers; i++) {
+		snd_hda_resume_ctls(codec, spec->mixers[i]);
+	}
 	if (spec->multiout.dig_out_nid)
 		snd_hda_resume_spdif_out(codec);
 
@@ -674,7 +817,7 @@
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
-	/* NID is set in alc880_build_pcms */
+	/* NID is set in alc_build_pcms */
 	.ops = {
 		.open = alc880_dig_playback_pcm_open,
 		.close = alc880_dig_playback_pcm_close
@@ -685,36 +828,39 @@
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
-	/* NID is set in alc880_build_pcms */
+	/* NID is set in alc_build_pcms */
 };
 
-static int alc880_build_pcms(struct hda_codec *codec)
+static int alc_build_pcms(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
+	int i;
 
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
 
-	info->name = "ALC880 Analog";
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc880_pcm_analog_playback;
-	info->stream[SNDRV_PCM_STREAM_CAPTURE] = alc880_pcm_analog_capture;
-
-	if (spec->five_stack)
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 8;
-	else
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 6;
+	info->name = spec->stream_name_analog;
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
+	info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
+
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
+	for (i = 0; i < spec->num_channel_mode; i++) {
+		if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
+		    info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
+		}
+	}
 
 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
 		codec->num_pcms++;
 		info++;
-		info->name = "ALC880 Digital";
+		info->name = spec->stream_name_digital;
 		if (spec->multiout.dig_out_nid) {
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc880_pcm_digital_playback;
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
 		}
 		if (spec->dig_in_nid) {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] = alc880_pcm_digital_capture;
+			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
 		}
 	}
@@ -722,20 +868,20 @@
 	return 0;
 }
 
-static void alc880_free(struct hda_codec *codec)
+static void alc_free(struct hda_codec *codec)
 {
 	kfree(codec->spec);
 }
 
 /*
  */
-static struct hda_codec_ops alc880_patch_ops = {
-	.build_controls = alc880_build_controls,
-	.build_pcms = alc880_build_pcms,
-	.init = alc880_init,
-	.free = alc880_free,
+static struct hda_codec_ops alc_patch_ops = {
+	.build_controls = alc_build_controls,
+	.build_pcms = alc_build_pcms,
+	.init = alc_init,
+	.free = alc_free,
 #ifdef CONFIG_PM
-	.resume = alc880_resume,
+	.resume = alc_resume,
 #endif
 };
 
@@ -748,19 +894,19 @@
 	{ .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST }, 
+	{ .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST }, 
+	{ .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST }, 
+	{ .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST }, 
+	{ .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
@@ -772,11 +918,11 @@
 	{ .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
 	{ .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
 	{ .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },   	
+	{ .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
 	{ .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
 	{ .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
 	{ .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST }, 
+	{ .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
 
 	/* Back 3 jack, front 2 jack (Internal add Aux-In) */
 	{ .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
@@ -807,61 +953,128 @@
 	{ .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
 	{ .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
 
+	{ .modelname = "w810", .config = ALC880_W810 },
+	{ .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
+
 	{}
 };
 
 static int patch_alc880(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
+	int board_config;
 
 	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
 	codec->spec = spec;
-	spec->board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
-	if (spec->board_config < 0) {
+
+	board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
+	if (board_config < 0) {
 		snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
-		spec->board_config = ALC880_MINIMAL;
+		board_config = ALC880_MINIMAL;
+	}
+
+	switch (board_config) {
+	case ALC880_W810:
+		spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
+		spec->num_mixers++;
+		break;
+	default:
+		spec->mixers[spec->num_mixers] = alc880_base_mixer;
+		spec->num_mixers++;
+		break;
 	}
-	switch (spec->board_config) {
+
+	switch (board_config) {
 	case ALC880_3ST_DIG:
 	case ALC880_5ST_DIG:
 		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
-		spec->front_panel = 1;
 		break;
+	default:
+		break;
+	}
+
+	switch (board_config) {
 	case ALC880_3ST:
+	case ALC880_3ST_DIG:
 	case ALC880_5ST:
+	case ALC880_5ST_DIG:
+	case ALC880_W810:
 		spec->front_panel = 1;
 		break;
+	default:
+		break;
 	}
-	if (spec->board_config == ALC880_5ST || spec->board_config == ALC880_5ST_DIG) {
-		spec->five_stack = 1;
-		spec->multiout.max_channels = 6;
-		spec->channel_mode = fivestack_modes;
-	} else {
-		spec->multiout.max_channels = 2;
-		spec->channel_mode = threestack_modes;
+
+	switch (board_config) {
+	case ALC880_5ST:
+	case ALC880_5ST_DIG:
+		spec->mixers[spec->num_mixers] = alc880_side_mixer;
+		spec->num_mixers++;
+		spec->init_verbs = alc880_init_verbs_five_stack;
+		spec->channel_mode = alc880_fivestack_modes;
+		spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
+		break;
+	case ALC880_W810:
+		spec->init_verbs = alc880_w810_init_verbs;
+		spec->channel_mode = alc880_w810_modes;
+		spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
+		break;
+	default:
+		spec->init_verbs = alc880_init_verbs_three_stack;
+		spec->channel_mode = alc880_threestack_modes;
+		spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
+		break;
 	}
 
-	spec->multiout.num_dacs = 4;
-	spec->multiout.dac_nids = alc880_dac_nids;
-	spec->multiout.hp_nid = 0x03; /* rear-surround NID */
+	spec->stream_name_analog = "ALC880 Analog";
+	spec->stream_analog_playback = &alc880_pcm_analog_playback;
+	spec->stream_analog_capture = &alc880_pcm_analog_capture;
+
+	spec->stream_name_digital = "ALC880 Digital";
+	spec->stream_digital_playback = &alc880_pcm_digital_playback;
+	spec->stream_digital_capture = &alc880_pcm_digital_capture;
+
+	spec->multiout.max_channels = spec->channel_mode[0].channels;
+
+	switch (board_config) {
+	case ALC880_W810:
+		spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
+		spec->multiout.dac_nids = alc880_w810_dac_nids;
+		// No dedicated headphone socket - it's shared with built-in speakers.
+		break;
+	default:
+		spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
+		spec->multiout.dac_nids = alc880_dac_nids;
+		spec->multiout.hp_nid = 0x03; /* rear-surround NID */
+		break;
+	}
 
 	spec->input_mux = &alc880_capture_source;
 	spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
 	spec->adc_nids = alc880_adc_nids;
 
-	codec->patch_ops = alc880_patch_ops;
+	codec->patch_ops = alc_patch_ops;
 
 	return 0;
 }
 
-
 /*
  * ALC260 support
  */
 
+/*
+ * This is just place-holder, so there's something for alc_build_pcms to look
+ * at when it calculates the maximum number of channels. ALC260 has no mixer
+ * element which allows changing the channel mode, so the verb list is
+ * never used.
+ */
+static struct alc_channel_mode alc260_modes[1] = {
+	{ 2, 0 },
+};
+
 snd_kcontrol_new_t alc260_base_mixer[] = {
 	HDA_CODEC_VOLUME("PCM Playback Volume", 0x08, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("PCM Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
@@ -884,14 +1097,9 @@
 		.get = alc_mux_enum_get,
 		.put = alc_mux_enum_put,
 	},
+	{ } /* end */
 };
 
-static int alc260_build_controls(struct hda_codec *codec)
-{
-	return snd_hda_add_new_ctls(codec, alc260_base_mixer,
-				    ARRAY_SIZE(alc260_base_mixer));
-}
-
 static struct hda_verb alc260_init_verbs[] = {
 	/* Line In pin widget(nid=0x14) for input */
 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
@@ -930,21 +1138,6 @@
 	{ }
 };
 
-static int alc260_init(struct hda_codec *codec)
-{
-	snd_hda_sequence_write(codec, alc260_init_verbs);
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int alc260_resume(struct hda_codec *codec, unsigned int state)
-{
-	alc260_init(codec);
-	snd_hda_resume_ctls(codec, alc260_base_mixer, ARRAY_SIZE(alc260_base_mixer));
-	return 0;
-}
-#endif
-
 static struct hda_pcm_stream alc260_pcm_analog_playback = {
 	.substreams = 1,
 	.channels_min = 2,
@@ -959,38 +1152,6 @@
 	.nid = 0x4,
 };
 
-static int alc260_build_pcms(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
-
-	codec->num_pcms = 1;
-	codec->pcm_info = info;
-
-	info->name = "ALC260 Analog";
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc260_pcm_analog_playback;
-	info->stream[SNDRV_PCM_STREAM_CAPTURE] = alc260_pcm_analog_capture;
-
-	/* any boards with digital I/O ? */
-
-	return 0;
-}
-
-static void alc260_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
-
-static struct hda_codec_ops alc260_patch_ops = {
-	.build_controls = alc260_build_controls,
-	.build_pcms = alc260_build_pcms,
-	.init = alc260_init,
-	.free = alc260_free,
-#ifdef CONFIG_PM
-	.resume = alc260_resume,
-#endif
-};
-
 static int patch_alc260(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
@@ -1000,13 +1161,27 @@
 		return -ENOMEM;
 
 	codec->spec = spec;
-	spec->multiout.max_channels = 2;
+
+	spec->mixers[spec->num_mixers] = alc260_base_mixer;
+	spec->num_mixers++;
+
+	spec->init_verbs = alc260_init_verbs;
+	spec->channel_mode = alc260_modes;
+	spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
+
+	spec->stream_name_analog = "ALC260 Analog";
+	spec->stream_analog_playback = &alc260_pcm_analog_playback;
+	spec->stream_analog_capture = &alc260_pcm_analog_capture;
+
+	spec->multiout.max_channels = spec->channel_mode[0].channels;
+	spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
+	spec->multiout.dac_nids = alc260_dac_nids;
 
 	spec->input_mux = &alc260_capture_source;
 	spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
 	spec->adc_nids = alc260_adc_nids;
 
-	codec->patch_ops = alc260_patch_ops;
+	codec->patch_ops = alc_patch_ops;
 
 	return 0;
 }

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

* Re: [PATCH] azx/realtek: Unify and parameterize code for ALC880/260 codecs, take 2
  2004-12-16 21:11 [PATCH] azx/realtek: Unify and parameterize code for ALC880/260 codecs, take 2 Stephen Warren
@ 2004-12-17 14:18 ` Takashi Iwai
  0 siblings, 0 replies; 2+ messages in thread
From: Takashi Iwai @ 2004-12-17 14:18 UTC (permalink / raw)
  To: Stephen Warren; +Cc: alsa-devel

At Thu, 16 Dec 2004 13:11:06 -0800,
Stephen Warren wrote:
> 
> This patch updates the HD-Audio ALC880/260 code driver such
> that all board-specific decisions are made in a single function,
> which sets variables that all other code simply uses directly
> without decision making.
> 
> Also, tweak snd_hda_add_new_ctls and snd_hda_resume_ctls so they
> use a sentinel value in the array of controls, and hence don't have
> to be passed an explicit array-size argument.
> 
> This has the benefits of:
> 
> * Isolating board-specific code to a single location
> * Simplifying the rest of the code
> * Unifying the code for ALC880/ALC260, which was previously separate.
> 
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
> ---
> 
> Note: This patch was generated by "cvs diff -u". Hopefully, that's a
> useful format - there are some extra lines of gunk that single-file
> regular "diff -u" doesn't generate...

Thanks for the patch.  That's no problem.  Patch is clever enough ;)

> This is an updated version of the patch I sent yesterday, that also
> tweaks the tweak snd_hda_add_new_ctls/snd_hda_resume_ctls API.
> 
> For now, I think I'm done with generic changes to the AZX codec, so the
> patch is complete, unless you find any problems with it.

I applied to CVS now.  Additionally, I put new comments about the
array termination for snd_hda_add_new_ctls() and
snd_hda_resume_ctls().

> 
> I'm punting on making patch_alc880/260 use pre-initialized data
> structures for codec->spec for now - the code isn't too hairy yet, and
> it'll be something very easily added later on if we decide to do it.

This sounds nice.

Also, we can merge many codes between patch_realtek.c and
patch_cmedia.c.  It would help for codecs from other vendors in
future.


Takashi


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now. 
http://productguide.itmanagersjournal.com/

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

end of thread, other threads:[~2004-12-17 14:18 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-16 21:11 [PATCH] azx/realtek: Unify and parameterize code for ALC880/260 codecs, take 2 Stephen Warren
2004-12-17 14:18 ` Takashi Iwai

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.