public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Liam Girdwood <Liam.Girdwood@wolfsonmicro.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>,
	Jeff Garzik <jgarzik@pobox.com>,
	lkml <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] AC97 support for low power codecs
Date: Tue, 04 Jan 2005 16:47:32 +0100	[thread overview]
Message-ID: <s5hacrpgprf.wl@alsa2.suse.de> (raw)
In-Reply-To: <1104852422.9143.348.camel@cearnarfon>

At Tue, 04 Jan 2005 15:27:02 +0000,
Liam Girdwood wrote:
> 
> On Tue, 2005-01-04 at 15:08, Takashi Iwai wrote:
> > 
> > Does writing RESET on such a codec must be avoided always?
> > Or can one power up again by writing some values on POWER register?
> > 
> 
> Writing RESET causes an AC97 codec to return to it's default state. On
> some codecs this is state is "power down" and therefore undesirable
> during a call to probe.
> 
> The only way to wake such a codec is via an AC97 warm reset.

Understood.  Thanks for explanation.

I have also a patch for ALSA about this as attached below.  It's
to the very latest ALSA CVS version (and untested, of course ;)


Takashi


--- linux/include/sound/ac97_codec.h	4 Jan 2005 03:27:54 -0000	1.61
+++ linux/include/sound/ac97_codec.h	4 Jan 2005 14:43:24 -0000
@@ -366,7 +366,9 @@
 #define AC97_DOUBLE_RATE	(1<<5)	/* supports double rate playback */
 #define AC97_HAS_NO_MASTER_VOL	(1<<6)	/* no Master volume */
 #define AC97_HAS_NO_PCM_VOL	(1<<7)	/* no PCM volume */
+#define AC97_DEFAULT_POWER_OFF	(1<<8)	/* no RESET write */
+#define AC97_MODEM_PATCH	(1<<9)	/* modem patch */
 
 /* rates indexes */
 #define AC97_RATES_FRONT_DAC	0
 #define CONFIG_SND_DATE ""
--- linux/sound/pci/ac97/ac97_codec.c	4 Jan 2005 11:08:31 -0000	1.159
+++ linux/sound/pci/ac97/ac97_codec.c	4 Jan 2005 15:07:17 -0000
@@ -55,127 +55,128 @@
 	unsigned int mask;
 	const char *name;
 	int (*patch)(ac97_t *ac97);
-	int (*mpatch)(ac97_t *ac97);
+	unsigned int flags;
 } ac97_codec_id_t;
 
 static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = {
-{ 0x414b4d00, 0xffffff00, "Asahi Kasei",	NULL,	NULL },
-{ 0x41445300, 0xffffff00, "Analog Devices",	NULL,	NULL },
-{ 0x414c4300, 0xffffff00, "Realtek",		NULL,	NULL },
-{ 0x414c4700, 0xffffff00, "Realtek",		NULL,	NULL },
-{ 0x434d4900, 0xffffff00, "C-Media Electronics", NULL,	NULL },
-{ 0x43525900, 0xffffff00, "Cirrus Logic",	NULL,	NULL },
-{ 0x43585400, 0xffffff00, "Conexant",           NULL,	NULL },
-{ 0x44543000, 0xffffff00, "Diamond Technology", NULL,	NULL },
-{ 0x454d4300, 0xffffff00, "eMicro",		NULL,	NULL },
-{ 0x45838300, 0xffffff00, "ESS Technology",	NULL,	NULL },
-{ 0x48525300, 0xffffff00, "Intersil",		NULL,	NULL },
-{ 0x49434500, 0xffffff00, "ICEnsemble",		NULL,	NULL },
-{ 0x49544500, 0xffffff00, "ITE Tech.Inc",	NULL,	NULL },
-{ 0x4e534300, 0xffffff00, "National Semiconductor", NULL, NULL },
-{ 0x50534300, 0xffffff00, "Philips",		NULL,	NULL },
-{ 0x53494c00, 0xffffff00, "Silicon Laboratory",	NULL,	NULL },
-{ 0x54524100, 0xffffff00, "TriTech",		NULL,	NULL },
-{ 0x54584e00, 0xffffff00, "Texas Instruments",	NULL,	NULL },
-{ 0x56494100, 0xffffff00, "VIA Technologies",   NULL,	NULL },
-{ 0x57454300, 0xffffff00, "Winbond",		NULL,	NULL },
-{ 0x574d4c00, 0xffffff00, "Wolfson",		NULL,	NULL },
-{ 0x594d4800, 0xffffff00, "Yamaha",		NULL,	NULL },
-{ 0x83847600, 0xffffff00, "SigmaTel",		NULL,	NULL },
-{ 0,	      0, 	  NULL,			NULL,	NULL }
+{ 0x414b4d00, 0xffffff00, "Asahi Kasei" },
+{ 0x41445300, 0xffffff00, "Analog Devices" },
+{ 0x414c4300, 0xffffff00, "Realtek" },
+{ 0x414c4700, 0xffffff00, "Realtek" },
+{ 0x434d4900, 0xffffff00, "C-Media Electronics" },
+{ 0x43525900, 0xffffff00, "Cirrus Logic" },
+{ 0x43585400, 0xffffff00, "Conexant" },
+{ 0x44543000, 0xffffff00, "Diamond Technology" },
+{ 0x454d4300, 0xffffff00, "eMicro" },
+{ 0x45838300, 0xffffff00, "ESS Technology" },
+{ 0x48525300, 0xffffff00, "Intersil" },
+{ 0x49434500, 0xffffff00, "ICEnsemble" },
+{ 0x49544500, 0xffffff00, "ITE Tech.Inc" },
+{ 0x4e534300, 0xffffff00, "National Semiconductor" },
+{ 0x50534300, 0xffffff00, "Philips" },
+{ 0x53494c00, 0xffffff00, "Silicon Laboratory" },
+{ 0x54524100, 0xffffff00, "TriTech" },
+{ 0x54584e00, 0xffffff00, "Texas Instruments" },
+{ 0x56494100, 0xffffff00, "VIA Technologies" },
+{ 0x57454300, 0xffffff00, "Winbond" },
+{ 0x574d4c00, 0xffffff00, "Wolfson" },
+{ 0x594d4800, 0xffffff00, "Yamaha" },
+{ 0x83847600, 0xffffff00, "SigmaTel" },
+{ 0 } /* terminator */
 };
 
 static const ac97_codec_id_t snd_ac97_codec_ids[] = {
-{ 0x414b4d00, 0xffffffff, "AK4540",		NULL,		NULL },
-{ 0x414b4d01, 0xffffffff, "AK4542",		NULL,		NULL },
-{ 0x414b4d02, 0xffffffff, "AK4543",		NULL,		NULL },
-{ 0x414b4d06, 0xffffffff, "AK4544A",		NULL,		NULL },
-{ 0x414b4d07, 0xffffffff, "AK4545",		NULL,		NULL },
-{ 0x41445303, 0xffffffff, "AD1819",		patch_ad1819,	NULL },
-{ 0x41445340, 0xffffffff, "AD1881",		patch_ad1881,	NULL },
-{ 0x41445348, 0xffffffff, "AD1881A",		patch_ad1881,	NULL },
-{ 0x41445360, 0xffffffff, "AD1885",		patch_ad1885,	NULL },
-{ 0x41445361, 0xffffffff, "AD1886",		patch_ad1886,	NULL },
-{ 0x41445362, 0xffffffff, "AD1887",		patch_ad1881,	NULL },
-{ 0x41445363, 0xffffffff, "AD1886A",		patch_ad1881,	NULL },
-{ 0x41445368, 0xffffffff, "AD1888",		patch_ad1888,	NULL },
-{ 0x41445370, 0xffffffff, "AD1980",		patch_ad1980,	NULL },
-{ 0x41445372, 0xffffffff, "AD1981A",		patch_ad1981a,	NULL },
-{ 0x41445374, 0xffffffff, "AD1981B",		patch_ad1981b,	NULL },
-{ 0x41445375, 0xffffffff, "AD1985",		patch_ad1985,	NULL },
-{ 0x414c4300, 0xffffff00, "ALC100/100P", 	NULL,		NULL },
-{ 0x414c4710, 0xfffffff0, "ALC200/200P",	NULL,		NULL },
-{ 0x414c4721, 0xffffffff, "ALC650D",		NULL,	NULL }, /* already patched */
-{ 0x414c4722, 0xffffffff, "ALC650E",		NULL,	NULL }, /* already patched */
-{ 0x414c4723, 0xffffffff, "ALC650F",		NULL,	NULL }, /* already patched */
-{ 0x414c4720, 0xfffffff0, "ALC650",		patch_alc650,	NULL },
-{ 0x414c4760, 0xfffffff0, "ALC655",		patch_alc655,	NULL },
-{ 0x414c4780, 0xfffffff0, "ALC658",		patch_alc655,	NULL },
-{ 0x414c4790, 0xfffffff0, "ALC850",		patch_alc850,	NULL },
-{ 0x414c4730, 0xffffffff, "ALC101",		NULL,		NULL },
-{ 0x414c4740, 0xfffffff0, "ALC202",		NULL,		NULL },
-{ 0x414c4750, 0xfffffff0, "ALC250",		NULL,		NULL },
-{ 0x414c4770, 0xfffffff0, "ALC203",		NULL,		NULL },
-{ 0x434d4941, 0xffffffff, "CMI9738",		patch_cm9738,	NULL },
-{ 0x434d4961, 0xffffffff, "CMI9739",		patch_cm9739,	NULL },
-{ 0x434d4978, 0xffffffff, "CMI9761",		patch_cm9761,	NULL },
-{ 0x434d4982, 0xffffffff, "CMI9761",		patch_cm9761,	NULL },
-{ 0x434d4983, 0xffffffff, "CMI9761",		patch_cm9761,	NULL },
-{ 0x43525900, 0xfffffff8, "CS4297",		NULL,		NULL },
-{ 0x43525910, 0xfffffff8, "CS4297A",		patch_cirrus_spdif,	NULL },
-{ 0x43525920, 0xfffffff8, "CS4298",		patch_cirrus_spdif,		NULL },
-{ 0x43525928, 0xfffffff8, "CS4294",		NULL,		NULL },
-{ 0x43525930, 0xfffffff8, "CS4299",		patch_cirrus_cs4299,	NULL },
-{ 0x43525948, 0xfffffff8, "CS4201",		NULL,		NULL },
-{ 0x43525958, 0xfffffff8, "CS4205",		patch_cirrus_spdif,	NULL },
-{ 0x43525960, 0xfffffff8, "CS4291",		NULL,		NULL },
-{ 0x43525970, 0xfffffff8, "CS4202",		NULL,		NULL },
-{ 0x43585421, 0xffffffff, "HSD11246",		NULL,		NULL },	// SmartMC II
-{ 0x43585428, 0xfffffff8, "Cx20468",		patch_conexant,	NULL }, // SmartAMC fixme: the mask might be different
-{ 0x44543031, 0xfffffff0, "DT0398",		NULL,		NULL },
-{ 0x454d4328, 0xffffffff, "28028",		NULL,		NULL },  // same as TR28028?
-{ 0x45838308, 0xffffffff, "ESS1988",		NULL,		NULL },
-{ 0x48525300, 0xffffff00, "HMP9701",		NULL,		NULL },
-{ 0x49434501, 0xffffffff, "ICE1230",		NULL,		NULL },
-{ 0x49434511, 0xffffffff, "ICE1232",		NULL,		NULL }, // alias VIA VT1611A?
-{ 0x49434514, 0xffffffff, "ICE1232A",		NULL,		NULL },
-{ 0x49434551, 0xffffffff, "VT1616", 		patch_vt1616,	NULL }, 
-{ 0x49434552, 0xffffffff, "VT1616i",		patch_vt1616,	NULL }, // VT1616 compatible (chipset integrated)
-{ 0x49544520, 0xffffffff, "IT2226E",		NULL,		NULL },
-{ 0x49544561, 0xffffffff, "IT2646E",		patch_it2646,	NULL },
-{ 0x4e534300, 0xffffffff, "LM4540/43/45/46/48",	NULL,		NULL }, // only guess --jk
-{ 0x4e534331, 0xffffffff, "LM4549",		NULL,		NULL },
-{ 0x4e534350, 0xffffffff, "LM4550",		NULL,		NULL },
-{ 0x50534304, 0xffffffff, "UCB1400",		NULL,		NULL },
-{ 0x53494c20, 0xffffffe0, "Si3036/8",		NULL,		mpatch_si3036 },
-{ 0x54524102, 0xffffffff, "TR28022",		NULL,		NULL },
-{ 0x54524106, 0xffffffff, "TR28026",		NULL,		NULL },
-{ 0x54524108, 0xffffffff, "TR28028",		patch_tritech_tr28028,	NULL }, // added by xin jin [07/09/99]
-{ 0x54524123, 0xffffffff, "TR28602",		NULL,		NULL }, // only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
-{ 0x54584e20, 0xffffffff, "TLC320AD9xC",	NULL,		NULL },
-{ 0x56494161, 0xffffffff, "VIA1612A",		NULL,		NULL }, // modified ICE1232 with S/PDIF
-{ 0x57454301, 0xffffffff, "W83971D",		NULL,		NULL },
-{ 0x574d4c00, 0xffffffff, "WM9701A",		NULL,		NULL },
-{ 0x574d4C03, 0xffffffff, "WM9703/WM9707/WM9708/WM9717", patch_wolfson03, NULL},
-{ 0x574d4C04, 0xffffffff, "WM9704M/WM9704Q",	patch_wolfson04, NULL},
-{ 0x574d4C05, 0xffffffff, "WM9705/WM9710",	patch_wolfson05, NULL},
-{ 0x574d4C09, 0xffffffff, "WM9709",		NULL,		NULL},
-{ 0x574d4C12, 0xffffffff, "WM9711/WM9712",	patch_wolfson11, NULL},
-{ 0x594d4800, 0xffffffff, "YMF743",		NULL,		NULL },
-{ 0x594d4802, 0xffffffff, "YMF752",		NULL,		NULL },
-{ 0x594d4803, 0xffffffff, "YMF753",		patch_yamaha_ymf753,	NULL },
-{ 0x83847600, 0xffffffff, "STAC9700/83/84",	patch_sigmatel_stac9700,	NULL },
-{ 0x83847604, 0xffffffff, "STAC9701/3/4/5",	NULL,		NULL },
-{ 0x83847605, 0xffffffff, "STAC9704",		NULL,		NULL },
-{ 0x83847608, 0xffffffff, "STAC9708/11",	patch_sigmatel_stac9708,	NULL },
-{ 0x83847609, 0xffffffff, "STAC9721/23",	patch_sigmatel_stac9721,	NULL },
-{ 0x83847644, 0xffffffff, "STAC9744",		patch_sigmatel_stac9744,	NULL },
-{ 0x83847650, 0xffffffff, "STAC9750/51",	NULL,		NULL },	// patch?
-{ 0x83847652, 0xffffffff, "STAC9752/53",	NULL,		NULL }, // patch?
-{ 0x83847656, 0xffffffff, "STAC9756/57",	patch_sigmatel_stac9756,	NULL },
-{ 0x83847658, 0xffffffff, "STAC9758/59",	patch_sigmatel_stac9758,	NULL },
-{ 0x83847666, 0xffffffff, "STAC9766/67",	NULL,		NULL }, // patch?
-{ 0, 	      0,	  NULL,			NULL,		NULL }
+{ 0x414b4d00, 0xffffffff, "AK4540",		NULL },
+{ 0x414b4d01, 0xffffffff, "AK4542",		NULL },
+{ 0x414b4d02, 0xffffffff, "AK4543",		NULL },
+{ 0x414b4d06, 0xffffffff, "AK4544A",		NULL },
+{ 0x414b4d07, 0xffffffff, "AK4545",		NULL },
+{ 0x41445303, 0xffffffff, "AD1819",		patch_ad1819 },
+{ 0x41445340, 0xffffffff, "AD1881",		patch_ad1881 },
+{ 0x41445348, 0xffffffff, "AD1881A",		patch_ad1881 },
+{ 0x41445360, 0xffffffff, "AD1885",		patch_ad1885 },
+{ 0x41445361, 0xffffffff, "AD1886",		patch_ad1886 },
+{ 0x41445362, 0xffffffff, "AD1887",		patch_ad1881 },
+{ 0x41445363, 0xffffffff, "AD1886A",		patch_ad1881 },
+{ 0x41445368, 0xffffffff, "AD1888",		patch_ad1888 },
+{ 0x41445370, 0xffffffff, "AD1980",		patch_ad1980 },
+{ 0x41445372, 0xffffffff, "AD1981A",		patch_ad1981a },
+{ 0x41445374, 0xffffffff, "AD1981B",		patch_ad1981b },
+{ 0x41445375, 0xffffffff, "AD1985",		patch_ad1985 },
+{ 0x414c4300, 0xffffff00, "ALC100/100P", 	NULL },
+{ 0x414c4710, 0xfffffff0, "ALC200/200P",	NULL },
+{ 0x414c4721, 0xffffffff, "ALC650D",		NULL }, /* already patched */
+{ 0x414c4722, 0xffffffff, "ALC650E",		NULL }, /* already patched */
+{ 0x414c4723, 0xffffffff, "ALC650F",		NULL }, /* already patched */
+{ 0x414c4720, 0xfffffff0, "ALC650",		patch_alc650 },
+{ 0x414c4760, 0xfffffff0, "ALC655",		patch_alc655 },
+{ 0x414c4780, 0xfffffff0, "ALC658",		patch_alc655 },
+{ 0x414c4790, 0xfffffff0, "ALC850",		patch_alc850 },
+{ 0x414c4730, 0xffffffff, "ALC101",		NULL },
+{ 0x414c4740, 0xfffffff0, "ALC202",		NULL },
+{ 0x414c4750, 0xfffffff0, "ALC250",		NULL },
+{ 0x414c4770, 0xfffffff0, "ALC203",		NULL },
+{ 0x434d4941, 0xffffffff, "CMI9738",		patch_cm9738 },
+{ 0x434d4961, 0xffffffff, "CMI9739",		patch_cm9739 },
+{ 0x434d4978, 0xffffffff, "CMI9761",		patch_cm9761 },
+{ 0x434d4982, 0xffffffff, "CMI9761",		patch_cm9761 },
+{ 0x434d4983, 0xffffffff, "CMI9761",		patch_cm9761 },
+{ 0x43525900, 0xfffffff8, "CS4297",		NULL },
+{ 0x43525910, 0xfffffff8, "CS4297A",		patch_cirrus_spdif },
+{ 0x43525920, 0xfffffff8, "CS4298",		patch_cirrus_spdif },
+{ 0x43525928, 0xfffffff8, "CS4294",		NULL },
+{ 0x43525930, 0xfffffff8, "CS4299",		patch_cirrus_cs4299 },
+{ 0x43525948, 0xfffffff8, "CS4201",		NULL },
+{ 0x43525958, 0xfffffff8, "CS4205",		patch_cirrus_spdif },
+{ 0x43525960, 0xfffffff8, "CS4291",		NULL },
+{ 0x43525970, 0xfffffff8, "CS4202",		NULL },
+{ 0x43585421, 0xffffffff, "HSD11246",		NULL },	// SmartMC II
+{ 0x43585428, 0xfffffff8, "Cx20468",		patch_conexant }, // SmartAMC fixme: the mask might be different
+{ 0x44543031, 0xfffffff0, "DT0398",		NULL },
+{ 0x454d4328, 0xffffffff, "28028",		NULL },  // same as TR28028?
+{ 0x45838308, 0xffffffff, "ESS1988",		NULL },
+{ 0x48525300, 0xffffff00, "HMP9701",		NULL },
+{ 0x49434501, 0xffffffff, "ICE1230",		NULL },
+{ 0x49434511, 0xffffffff, "ICE1232",		NULL }, // alias VIA VT1611A?
+{ 0x49434514, 0xffffffff, "ICE1232A",		NULL },
+{ 0x49434551, 0xffffffff, "VT1616", 		patch_vt1616 }, 
+{ 0x49434552, 0xffffffff, "VT1616i",		patch_vt1616 }, // VT1616 compatible (chipset integrated)
+{ 0x49544520, 0xffffffff, "IT2226E",		NULL },
+{ 0x49544561, 0xffffffff, "IT2646E",		patch_it2646 },
+{ 0x4e534300, 0xffffffff, "LM4540/43/45/46/48",	NULL }, // only guess --jk
+{ 0x4e534331, 0xffffffff, "LM4549",		NULL },
+{ 0x4e534350, 0xffffffff, "LM4550",		NULL },
+{ 0x50534304, 0xffffffff, "UCB1400",		NULL },
+{ 0x53494c20, 0xffffffe0, "Si3036/8",		mpatch_si3036,		AC97_MODEM_PATCH },
+{ 0x54524102, 0xffffffff, "TR28022",		NULL },
+{ 0x54524106, 0xffffffff, "TR28026",		NULL },
+{ 0x54524108, 0xffffffff, "TR28028",		patch_tritech_tr28028 }, // added by xin jin [07/09/99]
+{ 0x54524123, 0xffffffff, "TR28602",		NULL }, // only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
+{ 0x54584e20, 0xffffffff, "TLC320AD9xC",	NULL },
+{ 0x56494161, 0xffffffff, "VIA1612A",		NULL }, // modified ICE1232 with S/PDIF
+{ 0x57454301, 0xffffffff, "W83971D",		NULL },
+{ 0x574d4c00, 0xffffffff, "WM9701A",		NULL },
+{ 0x574d4c03, 0xffffffff, "WM9703/WM9707/WM9708/WM9717", patch_wolfson03 },
+{ 0x574d4c04, 0xffffffff, "WM9704M/WM9704Q",	patch_wolfson04 },
+{ 0x574d4c05, 0xffffffff, "WM9705/WM9710",	patch_wolfson05 },
+{ 0x574d4c09, 0xffffffff, "WM9709",		NULL },
+{ 0x574d4c12, 0xffffffff, "WM9711/WM9712",	patch_wolfson11 },
+{ 0x574d4c13, 0xffffffff, "WM9713",		patch_wolfson13,	AC97_DEFAULT_POWER_OFF }, /* warm start */
+{ 0x594d4800, 0xffffffff, "YMF743",		NULL },
+{ 0x594d4802, 0xffffffff, "YMF752",		NULL },
+{ 0x594d4803, 0xffffffff, "YMF753",		patch_yamaha_ymf753 },
+{ 0x83847600, 0xffffffff, "STAC9700/83/84",	patch_sigmatel_stac9700 },
+{ 0x83847604, 0xffffffff, "STAC9701/3/4/5",	NULL },
+{ 0x83847605, 0xffffffff, "STAC9704",		NULL },
+{ 0x83847608, 0xffffffff, "STAC9708/11",	patch_sigmatel_stac9708 },
+{ 0x83847609, 0xffffffff, "STAC9721/23",	patch_sigmatel_stac9721 },
+{ 0x83847644, 0xffffffff, "STAC9744",		patch_sigmatel_stac9744 },
+{ 0x83847650, 0xffffffff, "STAC9750/51",	NULL },	// patch?
+{ 0x83847652, 0xffffffff, "STAC9752/53",	NULL }, // patch?
+{ 0x83847656, 0xffffffff, "STAC9756/57",	patch_sigmatel_stac9756 },
+{ 0x83847658, 0xffffffff, "STAC9758/59",	patch_sigmatel_stac9758 },
+{ 0x83847666, 0xffffffff, "STAC9766/67",	NULL }, // patch?
+{ 0 } /* terminator */
 };
 
 const char *snd_ac97_stereo_enhancements[] =
@@ -1663,6 +1664,18 @@
 	return result;
 }
 
+/* look for the codec id table matching with the given id */
+static const ac97_codec_id_t *look_for_codec_id(const ac97_codec_id_t *table,
+						unsigned int id)
+{
+	const ac97_codec_id_t *pid;
+
+	for (pid = table; pid->id; pid++)
+		if (pid->id == (id & pid->mask))
+			return pid;
+	return NULL;
+}
+
 void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
 {
 	const ac97_codec_id_t *pid;
@@ -1671,35 +1684,30 @@
 		printable(id >> 24),
 		printable(id >> 16),
 		printable(id >> 8));
-	for (pid = snd_ac97_codec_id_vendors; pid->id; pid++)
-		if (pid->id == (id & pid->mask)) {
-			strcpy(name, pid->name);
-			if (ac97) {
-				if (!modem && pid->patch)
-					pid->patch(ac97);
-				else if (modem && pid->mpatch)
-					pid->mpatch(ac97);
-			} 
-			goto __vendor_ok;
-		}
-	return;
+	pid = look_for_codec_id(snd_ac97_codec_id_vendors, id);
+	if (! pid)
+		return;
 
-      __vendor_ok:
-	for (pid = snd_ac97_codec_ids; pid->id; pid++)
-		if (pid->id == (id & pid->mask)) {
-			strcat(name, " ");
-			strcat(name, pid->name);
-			if (pid->mask != 0xffffffff)
-				sprintf(name + strlen(name), " rev %d", id & ~pid->mask);
-			if (ac97) {
-				if (!modem && pid->patch)
-					pid->patch(ac97);
-				else if (modem && pid->mpatch)
-					pid->mpatch(ac97);
-			}
-			return;
+	strcpy(name, pid->name);
+	if (ac97 && pid->patch) {
+		if ((modem && (pid->flags & AC97_MODEM_PATCH)) ||
+		    (! modem && ! (pid->flags & AC97_MODEM_PATCH)))
+			pid->patch(ac97);
+	} 
+
+	pid = look_for_codec_id(snd_ac97_codec_ids, id);
+	if (pid) {
+		strcat(name, " ");
+		strcat(name, pid->name);
+		if (pid->mask != 0xffffffff)
+			sprintf(name + strlen(name), " rev %d", id & ~pid->mask);
+		if (ac97 && pid->patch) {
+			if ((modem && (pid->flags & AC97_MODEM_PATCH)) ||
+			    (! modem && ! (pid->flags & AC97_MODEM_PATCH)))
+				pid->patch(ac97);
 		}
-	sprintf(name + strlen(name), " id %x", id & 0xff);
+	} else
+		sprintf(name + strlen(name), " id %x", id & 0xff);
 }
 
 /**
@@ -1838,6 +1846,7 @@
 	char name[64];
 	unsigned long end_time;
 	unsigned int reg;
+	const ac97_codec_id_t *pid;
 	static snd_device_ops_t ops = {
 		.dev_free =	snd_ac97_dev_free,
 	};
@@ -1888,6 +1897,14 @@
 		goto __access_ok;
 	}
 
+	ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
+	ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
+	if (ac97->id && ac97->id != (unsigned int)-1) {
+		pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id);
+		if (pid && (pid->flags & AC97_DEFAULT_POWER_OFF))
+			goto __access_ok;
+	}
+
 	snd_ac97_write(ac97, AC97_RESET, 0);	/* reset to defaults */
 	if (bus->ops->wait)
 		bus->ops->wait(ac97);
@@ -1914,6 +1931,9 @@
 		snd_ac97_free(ac97);
 		return -EIO;
 	}
+	pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id);
+	if (pid)
+		ac97->flags |= pid->flags;
 	
 	/* test for AC'97 */
 	if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) {
@@ -1952,10 +1972,12 @@
 	if (ac97_is_audio(ac97)) {
 		/* nothing should be in powerdown mode */
 		snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
-		snd_ac97_write_cache(ac97, AC97_RESET, 0);		/* reset to defaults */
-		udelay(100);
+		if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) {
+			snd_ac97_write_cache(ac97, AC97_RESET, 0); /* reset to defaults */
+			udelay(100);
+			snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
+		}
 		/* nothing should be in powerdown mode */
-		snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
 		snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0);
 		end_time = jiffies + (HZ / 10);
 		do {
@@ -2217,9 +2239,11 @@
 	}
 
 	snd_ac97_write(ac97, AC97_POWERDOWN, 0);
-	snd_ac97_write(ac97, AC97_RESET, 0);
-	udelay(100);
-	snd_ac97_write(ac97, AC97_POWERDOWN, 0);
+	if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) {
+		snd_ac97_write(ac97, AC97_RESET, 0);
+		udelay(100);
+		snd_ac97_write(ac97, AC97_POWERDOWN, 0);
+	}
 	snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0);
 
 	snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]);
--- linux/sound/pci/ac97/ac97_patch.c	4 Jan 2005 10:58:12 -0000	1.67
+++ linux/sound/pci/ac97/ac97_patch.c	4 Jan 2005 14:51:36 -0000
@@ -305,6 +305,24 @@
 	return 0;
 }
 
+int patch_wolfson13(ac97_t * ac97)
+{
+	/* WM9713 */
+	static unsigned short inits[] = {
+		AC97_REC_GAIN,		0x00a0,
+		AC97_EXTENDED_MID,	0xda00,
+		AC97_EXTENDED_MSTATUS,	0x3810,
+		AC97_PHONE,		0x0808,
+		AC97_PC_BEEP,		0x0808,
+	};
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(inits); i += 2)
+		snd_ac97_write_cache(ac97, inits[0], inits[1]);
+
+	return 0;
+}
+
 /*
  * Tritech codec
  */
--- linux/sound/pci/ac97/ac97_patch.h	29 Sep 2004 09:44:11 -0000	1.17
+++ linux/sound/pci/ac97/ac97_patch.h	4 Jan 2005 14:43:57 -0000
@@ -28,6 +28,7 @@
 int patch_wolfson04(ac97_t * ac97);
 int patch_wolfson05(ac97_t * ac97);
 int patch_wolfson11(ac97_t * ac97);
+int patch_wolfson13(ac97_t * ac97);
 int patch_tritech_tr28028(ac97_t * ac97);
 int patch_sigmatel_stac9700(ac97_t * ac97);
 int patch_sigmatel_stac9708(ac97_t * ac97);


  reply	other threads:[~2005-01-04 15:48 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-01-04 11:34 [PATCH] AC97 support for low power codecs Liam Girdwood
2005-01-04 15:08 ` Takashi Iwai
2005-01-04 15:27   ` Liam Girdwood
2005-01-04 15:47     ` Takashi Iwai [this message]
2005-01-04 16:24       ` Liam Girdwood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s5hacrpgprf.wl@alsa2.suse.de \
    --to=tiwai@suse.de \
    --cc=Liam.Girdwood@wolfsonmicro.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=jgarzik@pobox.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox