X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=sound%2Fpci%2Fac97%2Fac97_codec.c;h=20cb60afb200c4661b26cdc87a5e76d7604805b1;hb=5779191e0efd851fb0d54698c13cb4f5325caca6;hp=bd8cfdcfbdf1f24aed53abb5e90d4cc1920220c9;hpb=67e9f4b68c9d1820132c559c0f9b296dafdf631e;p=safe%2Fjmp%2Flinux-2.6 diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index bd8cfdc..20cb60a 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) by Jaroslav Kysela + * Copyright (c) by Jaroslav Kysela * Universal interface for Audio Codec '97 * * For more details look to AC '97 component specification revision 2.2 @@ -22,7 +22,6 @@ * */ -#include #include #include #include @@ -35,11 +34,11 @@ #include #include #include -#include "ac97_local.h" #include "ac97_id.h" -#include "ac97_patch.h" -MODULE_AUTHOR("Jaroslav Kysela "); +#include "ac97_patch.c" + +MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Universal interface for Audio Codec '97"); MODULE_LICENSE("GPL"); @@ -49,9 +48,10 @@ module_param(enable_loopback, bool, 0444); MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control"); #ifdef CONFIG_SND_AC97_POWER_SAVE -static int power_save; -module_param(power_save, bool, 0644); -MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control"); +static int power_save = CONFIG_SND_AC97_POWER_SAVE_DEFAULT; +module_param(power_save, int, 0644); +MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " + "(in second, 0 = disable)."); #endif /* @@ -67,8 +67,8 @@ struct ac97_codec_id { }; static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = { -{ 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL }, { 0x41445300, 0xffffff00, "Analog Devices", NULL, NULL }, +{ 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL }, { 0x414c4300, 0xffffff00, "Realtek", NULL, NULL }, { 0x414c4700, 0xffffff00, "Realtek", NULL, NULL }, { 0x434d4900, 0xffffff00, "C-Media Electronics", NULL, NULL }, @@ -94,11 +94,6 @@ static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = { }; static const struct ac97_codec_id 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 }, @@ -112,20 +107,25 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 0x41445374, 0xffffffff, "AD1981B", patch_ad1981b, NULL }, { 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL }, { 0x41445378, 0xffffffff, "AD1986", patch_ad1986, NULL }, +{ 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 }, { 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 }, +{ 0x414c4730, 0xffffffff, "ALC101", NULL, NULL }, +{ 0x414c4740, 0xfffffff0, "ALC202", NULL, NULL }, +{ 0x414c4750, 0xfffffff0, "ALC250", NULL, NULL }, { 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL }, +{ 0x414c4770, 0xfffffff0, "ALC203", patch_alc203, NULL }, { 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */ { 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 }, { 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL }, @@ -143,6 +143,8 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 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 +{ 0x43585430, 0xffffffff, "Cx20468-31", patch_conexant, NULL }, +{ 0x43585431, 0xffffffff, "Cx20551", patch_cx20551, NULL }, { 0x44543031, 0xfffffff0, "DT0398", NULL, NULL }, { 0x454d4328, 0xffffffff, "EM28028", NULL, NULL }, // same as TR28028? { 0x45838308, 0xffffffff, "ESS1988", NULL, NULL }, @@ -160,22 +162,23 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL }, { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, +{ 0x54524103, 0xffffffff, "TR28023", 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 { 0x56494170, 0xffffffff, "VIA1617A", patch_vt1617a, NULL }, // modified VT1616 with S/PDIF -{ 0x56494182, 0xffffffff, "VIA1618", NULL, NULL }, +{ 0x56494182, 0xffffffff, "VIA1618", patch_vt1618, NULL }, { 0x57454301, 0xffffffff, "W83971D", NULL, NULL }, -{ 0x574d4c00, 0xffffffff, "WM9701A", NULL, NULL }, +{ 0x574d4c00, 0xffffffff, "WM9701,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}, +{ 0x574d4C12, 0xffffffff, "WM9711,WM9712,WM9715", patch_wolfson11, NULL}, { 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, -{ 0x594d4800, 0xffffffff, "YMF743", NULL, NULL }, +{ 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL }, { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, { 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL }, { 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL }, @@ -381,7 +384,7 @@ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned sho EXPORT_SYMBOL(snd_ac97_update_bits); -/* no lock version - see snd_ac97_updat_bits() */ +/* no lock version - see snd_ac97_update_bits() */ int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value) { @@ -431,7 +434,8 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns * Controls */ -int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +static int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; @@ -445,7 +449,8 @@ int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem return 0; } -int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; @@ -461,7 +466,8 @@ int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ return 0; } -int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; @@ -507,7 +513,8 @@ static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save) } /* volume and switch controls */ -int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +static int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { int mask = (kcontrol->private_value >> 16) & 0xff; int shift = (kcontrol->private_value >> 8) & 0x0f; @@ -520,7 +527,8 @@ int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info return 0; } -int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; @@ -543,7 +551,8 @@ int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value return 0; } -int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; @@ -594,8 +603,8 @@ AC97_SINGLE("Tone Control - Treble", AC97_MASTER_TONE, 0, 15, 1) }; static const struct snd_kcontrol_new snd_ac97_controls_pc_beep[2] = { -AC97_SINGLE("PC Speaker Playback Switch", AC97_PC_BEEP, 15, 1, 1), -AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1) +AC97_SINGLE("Beep Playback Switch", AC97_PC_BEEP, 15, 1, 1), +AC97_SINGLE("Beep Playback Volume", AC97_PC_BEEP, 1, 15, 1) }; static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = @@ -645,7 +654,7 @@ AC97_ENUM("Mic Select", std_enum[3]), AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) }; -const struct snd_kcontrol_new snd_ac97_controls_3d[2] = { +static const struct snd_kcontrol_new snd_ac97_controls_3d[2] = { AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0), AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0) }; @@ -772,6 +781,12 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC, AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, v); + } else if (ac97->id == AC97_ID_YMF743) { + change |= snd_ac97_update_bits_nolock(ac97, + AC97_YMF7X3_DIT_CTRL, + 0xff38, + ((val << 4) & 0xff00) | + ((val << 2) & 0x0038)); } else { unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ @@ -816,7 +831,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ return change; } -const struct snd_kcontrol_new snd_ac97_controls_spdif[5] = { +static const struct snd_kcontrol_new snd_ac97_controls_spdif[5] = { { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -990,6 +1005,7 @@ static int snd_ac97_free(struct snd_ac97 *ac97) if (ac97) { #ifdef CONFIG_SND_AC97_POWER_SAVE cancel_delayed_work(&ac97->power_work); + flush_scheduled_work(); #endif snd_ac97_proc_done(ac97); if (ac97->bus) @@ -1081,7 +1097,7 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha unsigned short val; snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8)); /* Do the read twice due to buffers on some ac97 codecs. - * e.g. The STAC9704 returns exactly what you wrote the the register + * e.g. The STAC9704 returns exactly what you wrote to the register * if you read it immediately. This causes the detect routine to fail. */ val = snd_ac97_read(ac97, reg); @@ -1095,7 +1111,7 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha } } -int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit) +static int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit) { unsigned short mask, val, orig, res; @@ -1135,7 +1151,8 @@ static inline int printable(unsigned int x) return x; } -struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, struct snd_ac97 * ac97) +static struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, + struct snd_ac97 * ac97) { struct snd_kcontrol_new template; memcpy(&template, _template, sizeof(template)); @@ -1190,13 +1207,13 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, /* * set dB information */ -static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); -static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); +static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); -static unsigned int *find_db_scale(unsigned int maxval) +static const unsigned int *find_db_scale(unsigned int maxval) { switch (maxval) { case 0x0f: return db_scale_4bit; @@ -1206,8 +1223,8 @@ static unsigned int *find_db_scale(unsigned int maxval) return NULL; } -static void set_tlv_db_scale(struct snd_kcontrol *kctl, unsigned int *tlv) -{ +static void set_tlv_db_scale(struct snd_kcontrol *kctl, const unsigned int *tlv) +{ kctl->tlv.p = tlv; if (tlv) kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; @@ -1366,7 +1383,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) for (idx = 0; idx < 2; idx++) { if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0) return err; - if (ac97->id == AC97_ID_YMF753) { + if (ac97->id == AC97_ID_YMF743 || + ac97->id == AC97_ID_YMF753) { kctl->private_value &= ~(0xff << 16); kctl->private_value |= 7 << 16; } @@ -1375,7 +1393,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) } } - /* build PC Speaker controls */ + /* build Beep controls */ if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) && ((ac97->flags & AC97_HAS_PC_BEEP) || snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { @@ -1626,7 +1644,10 @@ static int snd_ac97_modem_build(struct snd_card *card, struct snd_ac97 * ac97) { int err, idx; - //printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG)); + /* + printk(KERN_DEBUG "AC97_GPIO_CFG = %x\n", + snd_ac97_read(ac97,AC97_GPIO_CFG)); + */ snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH)); snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH)); snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff); @@ -1873,8 +1894,8 @@ int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops, .dev_free = snd_ac97_bus_dev_free, }; - snd_assert(card != NULL, return -EINVAL); - snd_assert(rbus != NULL, return -EINVAL); + if (snd_BUG_ON(!card)) + return -EINVAL; bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (bus == NULL) return -ENOMEM; @@ -1889,7 +1910,8 @@ int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops, snd_ac97_bus_free(bus); return err; } - *rbus = bus; + if (rbus) + *rbus = bus; return 0; } @@ -1909,9 +1931,9 @@ static int snd_ac97_dev_register(struct snd_device *device) ac97->dev.bus = &ac97_bus_type; ac97->dev.parent = ac97->bus->card->dev; ac97->dev.release = ac97_device_release; - snprintf(ac97->dev.bus_id, BUS_ID_SIZE, "%d-%d:%s", - ac97->bus->card->number, ac97->num, - snd_ac97_get_short_name(ac97)); + dev_set_name(&ac97->dev, "%d-%d:%s", + ac97->bus->card->number, ac97->num, + snd_ac97_get_short_name(ac97)); if ((err = device_register(&ac97->dev)) < 0) { snd_printk(KERN_ERR "Can't register ac97 bus\n"); ac97->dev.bus = NULL; @@ -1974,10 +1996,14 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, .dev_disconnect = snd_ac97_dev_disconnect, }; - snd_assert(rac97 != NULL, return -EINVAL); - *rac97 = NULL; - snd_assert(bus != NULL && template != NULL, return -EINVAL); - snd_assert(template->num < 4 && bus->codec[template->num] == NULL, return -EINVAL); + if (rac97) + *rac97 = NULL; + if (snd_BUG_ON(!bus || !template)) + return -EINVAL; + if (snd_BUG_ON(template->num >= 4)) + return -EINVAL; + if (bus->codec[template->num]) + return -EBUSY; card = bus->card; ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL); @@ -2027,11 +2053,12 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, else { udelay(50); if (ac97->scaps & AC97_SCAP_SKIP_AUDIO) - err = ac97_reset_wait(ac97, HZ/2, 1); + err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 1); else { - err = ac97_reset_wait(ac97, HZ/2, 0); + err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 0); if (err < 0) - err = ac97_reset_wait(ac97, HZ/2, 1); + err = ac97_reset_wait(ac97, + msecs_to_jiffies(500), 1); } if (err < 0) { snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num); @@ -2095,7 +2122,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, } /* nothing should be in powerdown mode */ snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0); - end_time = jiffies + (HZ / 10); + end_time = jiffies + msecs_to_jiffies(120); do { if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) goto __ready_ok; @@ -2127,7 +2154,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, udelay(100); /* nothing should be in powerdown mode */ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); - end_time = jiffies + (HZ / 10); + end_time = jiffies + msecs_to_jiffies(100); do { if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) goto __ready_ok; @@ -2278,9 +2305,11 @@ static void snd_ac97_powerdown(struct snd_ac97 *ac97) power |= AC97_PD_PR0 | AC97_PD_PR1; /* ADC & DAC powerdown */ snd_ac97_write(ac97, AC97_POWERDOWN, power); udelay(100); - power |= AC97_PD_PR2 | AC97_PD_PR3; /* Analog Mixer powerdown */ + power |= AC97_PD_PR2; /* Analog Mixer powerdown (Vref on) */ snd_ac97_write(ac97, AC97_POWERDOWN, power); if (ac97_is_power_save_mode(ac97)) { + power |= AC97_PD_PR3; /* Analog Mixer powerdown */ + snd_ac97_write(ac97, AC97_POWERDOWN, power); udelay(100); /* AC-link powerdown, internal Clk disable */ /* FIXME: this may cause click noises on some boards */ @@ -2345,7 +2374,8 @@ int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup) * (for avoiding loud click noises for many (OSS) apps * that open/close frequently) */ - schedule_delayed_work(&ac97->power_work, HZ*2); + schedule_delayed_work(&ac97->power_work, + msecs_to_jiffies(power_save * 1000)); else { cancel_delayed_work(&ac97->power_work); update_power_regs(ac97); @@ -2415,6 +2445,10 @@ void snd_ac97_suspend(struct snd_ac97 *ac97) return; if (ac97->build_ops->suspend) ac97->build_ops->suspend(ac97); +#ifdef CONFIG_SND_AC97_POWER_SAVE + cancel_delayed_work(&ac97->power_work); + flush_scheduled_work(); +#endif snd_ac97_powerdown(ac97); } @@ -2423,7 +2457,7 @@ EXPORT_SYMBOL(snd_ac97_suspend); /* * restore ac97 status */ -void snd_ac97_restore_status(struct snd_ac97 *ac97) +static void snd_ac97_restore_status(struct snd_ac97 *ac97) { int i; @@ -2444,7 +2478,7 @@ void snd_ac97_restore_status(struct snd_ac97 *ac97) /* * restore IEC958 status */ -void snd_ac97_restore_iec958(struct snd_ac97 *ac97) +static void snd_ac97_restore_iec958(struct snd_ac97 *ac97) { if (ac97->ext_id & AC97_EI_SPDIF) { if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) { @@ -2481,7 +2515,10 @@ void snd_ac97_resume(struct snd_ac97 *ac97) snd_ac97_write(ac97, AC97_POWERDOWN, 0); if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) { - snd_ac97_write(ac97, AC97_RESET, 0); + if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO)) + snd_ac97_write(ac97, AC97_RESET, 0); + else if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM)) + snd_ac97_write(ac97, AC97_EXTENDED_MID, 0); udelay(100); snd_ac97_write(ac97, AC97_POWERDOWN, 0); } @@ -2538,7 +2575,8 @@ static void set_ctl_name(char *dst, const char *src, const char *suffix) } /* remove the control with the given name and optional suffix */ -int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, const char *suffix) +static int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, + const char *suffix) { struct snd_ctl_elem_id id; memset(&id, 0, sizeof(id)); @@ -2557,7 +2595,8 @@ static struct snd_kcontrol *ctl_find(struct snd_ac97 *ac97, const char *name, co } /* rename the control with the given name and optional suffix */ -int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst, const char *suffix) +static int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, + const char *dst, const char *suffix) { struct snd_kcontrol *kctl = ctl_find(ac97, src, suffix); if (kctl) { @@ -2568,14 +2607,16 @@ int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst, } /* rename both Volume and Switch controls - don't check the return value */ -void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, const char *dst) +static void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, + const char *dst) { snd_ac97_rename_ctl(ac97, src, dst, "Switch"); snd_ac97_rename_ctl(ac97, src, dst, "Volume"); } /* swap controls */ -int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, const char *s2, const char *suffix) +static int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, + const char *s2, const char *suffix) { struct snd_kcontrol *kctl1, *kctl2; kctl1 = ctl_find(ac97, s1, suffix);