X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fpci%2Fac97%2Fac97_codec.c;h=3020ca2b602bd10d16d575d7c011bd792e7a762a;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=fcb00c2a26820f2d761383cb4814b50b2bd49a2a;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index fcb00c2a2..3020ca2b6 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -150,7 +149,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 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", patch_lm4550, NULL }, // volume wrap fix +{ 0x4e534350, 0xffffffff, "LM4550", NULL, NULL }, { 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, @@ -160,7 +159,6 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 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 }, { 0x57454301, 0xffffffff, "W83971D", NULL, NULL }, { 0x574d4c00, 0xffffffff, "WM9701A", NULL, NULL }, { 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL}, @@ -193,6 +191,9 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg) { + if (ac97->limited_regs && ! test_bit(reg, ac97->reg_accessed)) + return 0; + /* filter some registers for buggy codecs */ switch (ac97->id) { case AC97_ID_AK4540: @@ -295,11 +296,11 @@ void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned sh { if (!snd_ac97_valid_reg(ac97, reg)) return; - mutex_lock(&ac97->reg_mutex); + down(&ac97->reg_mutex); ac97->regs[reg] = value; ac97->bus->ops->write(ac97, reg, value); set_bit(reg, ac97->reg_accessed); - mutex_unlock(&ac97->reg_mutex); + up(&ac97->reg_mutex); } /** @@ -320,14 +321,14 @@ int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short va if (!snd_ac97_valid_reg(ac97, reg)) return -EINVAL; - mutex_lock(&ac97->reg_mutex); + down(&ac97->reg_mutex); change = ac97->regs[reg] != value; if (change) { ac97->regs[reg] = value; ac97->bus->ops->write(ac97, reg, value); } set_bit(reg, ac97->reg_accessed); - mutex_unlock(&ac97->reg_mutex); + up(&ac97->reg_mutex); return change; } @@ -350,9 +351,9 @@ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned sho if (!snd_ac97_valid_reg(ac97, reg)) return -EINVAL; - mutex_lock(&ac97->reg_mutex); + down(&ac97->reg_mutex); change = snd_ac97_update_bits_nolock(ac97, reg, mask, value); - mutex_unlock(&ac97->reg_mutex); + up(&ac97->reg_mutex); return change; } @@ -379,12 +380,12 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns int change; unsigned short old, new, cfg; - mutex_lock(&ac97->page_mutex); + down(&ac97->page_mutex); old = ac97->spec.ad18xx.pcmreg[codec]; new = (old & ~mask) | value; change = old != new; if (change) { - mutex_lock(&ac97->reg_mutex); + down(&ac97->reg_mutex); cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG); ac97->spec.ad18xx.pcmreg[codec] = new; /* select single codec */ @@ -396,9 +397,9 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns /* select all codecs */ ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, cfg | 0x7000); - mutex_unlock(&ac97->reg_mutex); + up(&ac97->reg_mutex); } - mutex_unlock(&ac97->page_mutex); + up(&ac97->page_mutex); return change; } @@ -466,7 +467,7 @@ static int snd_ac97_page_save(struct snd_ac97 *ac97, int reg, struct snd_kcontro (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 && (reg >= 0x60 && reg < 0x70)) { unsigned short page = (kcontrol->private_value >> 26) & 0x0f; - mutex_lock(&ac97->page_mutex); /* lock paging */ + down(&ac97->page_mutex); /* lock paging */ page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); } @@ -477,7 +478,7 @@ static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save) { if (page_save >= 0) { snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - mutex_unlock(&ac97->page_mutex); /* unlock paging */ + up(&ac97->page_mutex); /* unlock paging */ } } @@ -673,12 +674,12 @@ static int snd_ac97_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - mutex_lock(&ac97->reg_mutex); + down(&ac97->reg_mutex); ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff; ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff; ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff; ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff; - mutex_unlock(&ac97->reg_mutex); + up(&ac97->reg_mutex); return 0; } @@ -717,7 +718,7 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ } } - mutex_lock(&ac97->reg_mutex); + down(&ac97->reg_mutex); change = ac97->spdif_status != new; ac97->spdif_status = new; @@ -745,7 +746,7 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ } } - mutex_unlock(&ac97->reg_mutex); + up(&ac97->reg_mutex); return change; } @@ -762,7 +763,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ value = (ucontrol->value.integer.value[0] & mask); - mutex_lock(&ac97->reg_mutex); + down(&ac97->reg_mutex); mask <<= shift; value <<= shift; old = snd_ac97_read_cache(ac97, reg); @@ -776,7 +777,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ if (extst & AC97_EA_SPDIF) snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ } - mutex_unlock(&ac97->reg_mutex); + up(&ac97->reg_mutex); return change; } @@ -887,10 +888,10 @@ static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int codec = kcontrol->private_value & 3; - mutex_lock(&ac97->page_mutex); + down(&ac97->page_mutex); ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); - mutex_unlock(&ac97->page_mutex); + up(&ac97->page_mutex); return 0; } @@ -1006,6 +1007,9 @@ static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg) break; } + if (ac97->limited_regs && test_bit(reg, ac97->reg_accessed)) + return 1; /* allow without check */ + val = snd_ac97_read(ac97, reg); if (!(val & mask)) { /* nothing seems to be here - mute flag is not set */ @@ -1025,18 +1029,6 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha unsigned char max[3] = { 63, 31, 15 }; int i; - /* first look up the static resolution table */ - if (ac97->res_table) { - const struct snd_ac97_res_table *tbl; - for (tbl = ac97->res_table; tbl->reg; tbl++) { - if (tbl->reg == reg) { - *lo_max = tbl->bits & 0xff; - *hi_max = (tbl->bits >> 8) & 0xff; - return; - } - } - } - *lo_max = *hi_max = 0; for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { unsigned short val; @@ -1204,20 +1196,6 @@ static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, int static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97); -static void snd_ctl_elem_remove(struct snd_card *card, - struct snd_kcontrol *kcontrol) -{ - struct snd_kcontrol *kct; - struct snd_ctl_elem_id id = kcontrol->id; - - down_write(&card->controls_rwsem); - - if ((kct = snd_ctl_find_id(card, &id))) - snd_ctl_remove(card, kct); - - up_write(&card->controls_rwsem); -} - static int snd_ac97_mixer_build(struct snd_ac97 * ac97) { struct snd_card *card = ac97->bus->card; @@ -1361,35 +1339,23 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) init_val = 0x9f9f; else init_val = 0x9f1f; - for (idx = 0; idx < 2; idx++) { - struct snd_kcontrol *kctrl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97); - snd_ctl_elem_remove(card, kctrl); - if ((err = snd_ctl_add(card, kctrl)) < 0) + for (idx = 0; idx < 2; idx++) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0) return err; - } ac97->spec.ad18xx.pcmreg[0] = init_val; if (ac97->scaps & AC97_SCAP_SURROUND_DAC) { - for (idx = 0; idx < 2; idx++) { - struct snd_kcontrol *kctrl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97); - snd_ctl_elem_remove(card, kctrl); - if ((err = snd_ctl_add(card, kctrl)) < 0) + for (idx = 0; idx < 2; idx++) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0) return err; - } ac97->spec.ad18xx.pcmreg[1] = init_val; } if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) { - for (idx = 0; idx < 2; idx++) { - struct snd_kcontrol *kctrl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97); - snd_ctl_elem_remove(card, kctrl); - if ((err = snd_ctl_add(card, kctrl)) < 0) + for (idx = 0; idx < 2; idx++) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0) return err; - } - for (idx = 0; idx < 2; idx++) { - struct snd_kcontrol *kctrl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97); - snd_ctl_elem_remove(card, kctrl); - if ((err = snd_ctl_add(card, kctrl)) < 0) + for (idx = 0; idx < 2; idx++) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0) return err; - } ac97->spec.ad18xx.pcmreg[2] = init_val; } snd_ac97_write_cache(ac97, AC97_PCM, init_val); @@ -1887,10 +1853,11 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, ac97->num = template->num; ac97->addr = template->addr; ac97->scaps = template->scaps; - ac97->res_table = template->res_table; + ac97->limited_regs = template->limited_regs; + memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed)); bus->codec[ac97->num] = ac97; - mutex_init(&ac97->reg_mutex); - mutex_init(&ac97->page_mutex); + init_MUTEX(&ac97->reg_mutex); + init_MUTEX(&ac97->page_mutex); #ifdef CONFIG_PCI if (ac97->pci) {