Re: [PATCH] AC97 support for low power codecs

From: Takashi Iwai
Date: Tue Jan 04 2005 - 10:49:50 EST


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);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/