Messages in this thread Patch in this message | | | Date | Tue, 04 Jan 2005 16:47:32 +0100 | From | Takashi Iwai <> | Subject | Re: [PATCH] AC97 support for low power codecs |
| |
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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |