diff options
author | Jaroslav Kysela <perex@suse.cz> | 2005-01-03 13:35:15 +0100 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2005-01-03 13:35:15 +0100 |
commit | 394bc51614e417e10ed1f9fd2665f487e751e388 (patch) | |
tree | 704b6e083b54c9c134eed080fb469fb204b80e37 /sound | |
parent | abe503c19acf0775bfa7a8fcdbc28c7ba3ec8877 (diff) | |
download | history-394bc51614e417e10ed1f9fd2665f487e751e388.tar.gz |
[ALSA] Unify ac97 control callbacks
AC97 Codec Core
Unified single_* and double_* control callbacks.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/ac97/ac97_codec.c | 135 | ||||
-rw-r--r-- | sound/pci/ac97/ac97_local.h | 22 | ||||
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 14 |
3 files changed, 65 insertions, 106 deletions
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index f6ae0bf6f8bd85..efab10980e2d8e 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -537,103 +537,69 @@ static int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift); } -int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { int mask = (kcontrol->private_value >> 16) & 0xff; + int shift = (kcontrol->private_value >> 8) & 0x0f; + int rshift = (kcontrol->private_value >> 12) & 0x0f; uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; + uinfo->count = shift == rshift ? 1 : 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = mask; return 0; } -int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; + int shift = (kcontrol->private_value >> 8) & 0x0f; + int rshift = (kcontrol->private_value >> 12) & 0x0f; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0x01; ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask; - if (invert) + if (shift != rshift) + ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> rshift) & mask; + if (invert) { ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; + if (shift != rshift) + ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; + } return 0; } -int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; + int shift = (kcontrol->private_value >> 8) & 0x0f; + int rshift = (kcontrol->private_value >> 12) & 0x0f; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0x01; - unsigned short val; + unsigned short val, val2, val_mask; val = (ucontrol->value.integer.value[0] & mask); if (invert) val = mask - val; - return snd_ac97_update_bits(ac97, reg, mask << shift, val << shift); + val_mask = mask << shift; + val = val << shift; + if (shift != rshift) { + val2 = (ucontrol->value.integer.value[1] & mask); + if (invert) + val2 = mask - val2; + val_mask |= mask << rshift; + val |= val2 << rshift; + } + return snd_ac97_update_bits(ac97, reg, val_mask, val); } #define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_double, \ - .get = snd_ac97_get_double, .put = snd_ac97_put_double, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_volsw, \ + .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) } -static int snd_ac97_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ac97_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) -{ - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock(&ac97->reg_lock); - ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift_left) & mask; - ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> shift_right) & mask; - spin_unlock(&ac97->reg_lock); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_ac97_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) -{ - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - return snd_ac97_update_bits(ac97, reg, - (mask << shift_left) | (mask << shift_right), - (val1 << shift_left) | (val2 << shift_right)); -} - static int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, int (*func)(snd_kcontrol_t *, snd_ctl_elem_value_t *)) { @@ -657,15 +623,15 @@ static int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * } /* for rev2.3 paging */ -int snd_ac97_page_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +int snd_ac97_page_get_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { - return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_single); + return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_volsw); } /* for rev2.3 paging */ -int snd_ac97_page_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +int snd_ac97_page_put_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { - return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_single); + return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_volsw); } static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = { @@ -875,7 +841,7 @@ static int snd_ac97_put_spsa(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; + int shift = (kcontrol->private_value >> 8) & 0x0f; /* single only */ int mask = (kcontrol->private_value >> 16) & 0xff; // int invert = (kcontrol->private_value >> 24) & 0xff; unsigned short value, old, new; @@ -928,8 +894,8 @@ const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", - .info = snd_ac97_info_single, - .get = snd_ac97_get_single, + .info = snd_ac97_info_volsw, + .get = snd_ac97_get_volsw, .put = snd_ac97_put_spsa, .private_value = AC97_SINGLE_VALUE(AC97_EXTENDED_STATUS, 4, 3, 0) }, @@ -2430,24 +2396,20 @@ static int tune_inv_eapd(ac97_t *ac97) return 0; } -static int master_mute_sw_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - int err = snd_ac97_put_single(kcontrol, ucontrol); - if (err > 0) { - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, - ac97->regs[AC97_MASTER] & 0x8000); - } - return err; -} - -static int master_mute_sw_put_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int master_mute_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { - int err = snd_ac97_put_double(kcontrol, ucontrol); + int err = snd_ac97_put_volsw(kcontrol, ucontrol); if (err > 0) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + int shift = (kcontrol->private_value >> 8) & 0x0f; + int rshift = (kcontrol->private_value >> 12) & 0x0f; + unsigned short mask; + if (shift != rshift) + mask = 0x8080; + else + mask = 0x8000; snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, - (ac97->regs[AC97_MASTER] & 0x8080) == 0x8080 ? + (ac97->regs[AC97_MASTER] & mask) == mask ? 0x8000 : 0); } return err; @@ -2458,10 +2420,7 @@ static int tune_mute_led(ac97_t *ac97) snd_kcontrol_t *msw = ctl_find(ac97, "Master Playback Switch", NULL); if (! msw) return -ENOENT; - if (msw->put == snd_ac97_put_double) - msw->put = master_mute_sw_put_double; - else - msw->put = master_mute_sw_put_single; + msw->put = master_mute_sw_put; snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */ return 0; diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h index de412dbe988a23..d6f0b275e5ff39 100644 --- a/sound/pci/ac97/ac97_local.h +++ b/sound/pci/ac97/ac97_local.h @@ -22,15 +22,15 @@ * */ -#define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24)) -#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) | ((page) << 25)) +#define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | ((invert) << 24)) +#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | ((page) << 25)) #define AC97_SINGLE(xname, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \ - .get = snd_ac97_get_single, .put = snd_ac97_put_single, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \ + .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ .private_value = AC97_SINGLE_VALUE(reg, shift, mask, invert) } #define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \ - .get = snd_ac97_page_get_single, .put = snd_ac97_page_put_single, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \ + .get = snd_ac97_page_get_volsw, .put = snd_ac97_page_put_volsw, \ .private_value = AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) } /* ac97_codec.c */ @@ -39,11 +39,11 @@ extern const snd_kcontrol_new_t snd_ac97_controls_3d[]; extern const snd_kcontrol_new_t snd_ac97_controls_spdif[]; snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97); void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem); -int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo); -int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); -int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); -int snd_ac97_page_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); -int snd_ac97_page_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); +int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo); +int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); +int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); +int snd_ac97_page_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); +int snd_ac97_page_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit); int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix); int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix); diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 6fcc7769581983..3b59b15bd6546c 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1403,7 +1403,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .info = snd_ac97_info_volsw, .get = snd_ac97_alc650_mic_get, .put = snd_ac97_alc650_mic_put, .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ @@ -1515,7 +1515,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .info = snd_ac97_info_volsw, .get = snd_ac97_alc655_mic_get, .put = snd_ac97_alc655_mic_put, .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ @@ -1668,7 +1668,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line-In As Surround", - .info = snd_ac97_info_single, + .info = snd_ac97_info_volsw, .get = ac97_alc850_surround_get, .put = ac97_alc850_surround_put, .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ @@ -1676,7 +1676,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .info = snd_ac97_info_volsw, .get = ac97_alc850_mic_get, .put = ac97_alc850_mic_put, .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ @@ -1831,7 +1831,7 @@ static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .info = snd_ac97_info_volsw, .get = snd_ac97_cm9739_center_mic_get, .put = snd_ac97_cm9739_center_mic_put, .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ @@ -1945,7 +1945,7 @@ static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line-In As Surround", - .info = snd_ac97_info_single, + .info = snd_ac97_info_volsw, .get = snd_ac97_cm9761_linein_rear_get, .put = snd_ac97_cm9761_linein_rear_put, .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ @@ -1953,7 +1953,7 @@ static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .info = snd_ac97_info_volsw, .get = snd_ac97_cm9761_center_mic_get, .put = snd_ac97_cm9761_center_mic_put, .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ |