diff options
Diffstat (limited to 'sound/pci/ca0106/ca0106_mixer.c')
-rw-r--r-- | sound/pci/ca0106/ca0106_mixer.c | 417 |
1 files changed, 101 insertions, 316 deletions
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index c10e4a54301b..0730dc7c66e5 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -125,18 +125,11 @@ static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol, return change; } -static snd_kcontrol_new_t snd_ca0106_shared_spdif __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "SPDIF Out", - .info = snd_ca0106_shared_spdif_info, - .get = snd_ca0106_shared_spdif_get, - .put = snd_ca0106_shared_spdif_put -}; - static int snd_ca0106_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { - static char *texts[6] = { "SPDIF out", "i2s mixer out", "SPDIF in", "i2s in", "AC97 in", "SRC out" }; + static char *texts[6] = { + "SPDIF out", "i2s mixer out", "SPDIF in", "i2s in", "AC97 in", "SRC out" + }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; @@ -176,15 +169,6 @@ static int snd_ca0106_capture_source_put(snd_kcontrol_t * kcontrol, return change; } -static snd_kcontrol_new_t snd_ca0106_capture_source __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_ca0106_capture_source_info, - .get = snd_ca0106_capture_source_get, - .put = snd_ca0106_capture_source_put -}; - static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { static char *texts[2] = { "Line in", "Mic in" }; @@ -294,26 +278,6 @@ static int snd_ca0106_spdif_put(snd_kcontrol_t * kcontrol, return change; } -static snd_kcontrol_new_t snd_ca0106_spdif_mask_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .count = 4, - .info = snd_ca0106_spdif_info, - .get = snd_ca0106_spdif_get_mask -}; - -static snd_kcontrol_new_t snd_ca0106_spdif_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .count = 4, - .info = snd_ca0106_spdif_info, - .get = snd_ca0106_spdif_get, - .put = snd_ca0106_spdif_put -}; - static int snd_ca0106_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; @@ -324,10 +288,14 @@ static int snd_ca0106_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t } static int snd_ca0106_volume_get(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol, int reg, int channel_id) + snd_ctl_elem_value_t * ucontrol) { ca0106_t *emu = snd_kcontrol_chip(kcontrol); unsigned int value; + int channel_id, reg; + + channel_id = (kcontrol->private_value >> 8) & 0xff; + reg = kcontrol->private_value & 0xff; value = snd_ca0106_ptr_read(emu, reg, channel_id); ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */ @@ -335,226 +303,92 @@ static int snd_ca0106_volume_get(snd_kcontrol_t * kcontrol, return 0; } -static int snd_ca0106_volume_get_spdif_front(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_FRONT_CHANNEL; - int reg = PLAYBACK_VOLUME1; - return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id); -} - -static int snd_ca0106_volume_get_spdif_center_lfe(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_CENTER_LFE_CHANNEL; - int reg = PLAYBACK_VOLUME1; - return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_get_spdif_unknown(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_UNKNOWN_CHANNEL; - int reg = PLAYBACK_VOLUME1; - return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_get_spdif_rear(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_REAR_CHANNEL; - int reg = PLAYBACK_VOLUME1; - return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_get_analog_front(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_FRONT_CHANNEL; - int reg = PLAYBACK_VOLUME2; - return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id); -} - -static int snd_ca0106_volume_get_analog_center_lfe(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_CENTER_LFE_CHANNEL; - int reg = PLAYBACK_VOLUME2; - return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_get_analog_unknown(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_UNKNOWN_CHANNEL; - int reg = PLAYBACK_VOLUME2; - return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_get_analog_rear(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_REAR_CHANNEL; - int reg = PLAYBACK_VOLUME2; - return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id); -} - -static int snd_ca0106_volume_get_feedback(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = 1; - int reg = CAPTURE_CONTROL; - return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id); -} - static int snd_ca0106_volume_put(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol, int reg, int channel_id) + snd_ctl_elem_value_t * ucontrol) { ca0106_t *emu = snd_kcontrol_chip(kcontrol); - unsigned int value; - //value = snd_ca0106_ptr_read(emu, reg, channel_id); - //value = value & 0xffff; - value = ((0xff - ucontrol->value.integer.value[0]) << 24) | ((0xff - ucontrol->value.integer.value[1]) << 16); - value = value | ((0xff - ucontrol->value.integer.value[0]) << 8) | ((0xff - ucontrol->value.integer.value[1]) ); - snd_ca0106_ptr_write(emu, reg, channel_id, value); - return 1; -} -static int snd_ca0106_volume_put_spdif_front(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_FRONT_CHANNEL; - int reg = PLAYBACK_VOLUME1; - return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_put_spdif_center_lfe(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_CENTER_LFE_CHANNEL; - int reg = PLAYBACK_VOLUME1; - return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_put_spdif_unknown(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_UNKNOWN_CHANNEL; - int reg = PLAYBACK_VOLUME1; - return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_put_spdif_rear(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_REAR_CHANNEL; - int reg = PLAYBACK_VOLUME1; - return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_put_analog_front(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_FRONT_CHANNEL; - int reg = PLAYBACK_VOLUME2; - return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_put_analog_center_lfe(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_CENTER_LFE_CHANNEL; - int reg = PLAYBACK_VOLUME2; - return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_put_analog_unknown(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_UNKNOWN_CHANNEL; - int reg = PLAYBACK_VOLUME2; - return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); -} -static int snd_ca0106_volume_put_analog_rear(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = CONTROL_REAR_CHANNEL; - int reg = PLAYBACK_VOLUME2; - return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); -} - -static int snd_ca0106_volume_put_feedback(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) -{ - int channel_id = 1; - int reg = CAPTURE_CONTROL; - return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); -} - -static snd_kcontrol_new_t snd_ca0106_volume_control_analog_front = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Front Playback Volume", - .info = snd_ca0106_volume_info, - .get = snd_ca0106_volume_get_analog_front, - .put = snd_ca0106_volume_put_analog_front -}; -static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Center/LFE Playback Volume", - .info = snd_ca0106_volume_info, - .get = snd_ca0106_volume_get_analog_center_lfe, - .put = snd_ca0106_volume_put_analog_center_lfe -}; -static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Side Playback Volume", - .info = snd_ca0106_volume_info, - .get = snd_ca0106_volume_get_analog_unknown, - .put = snd_ca0106_volume_put_analog_unknown -}; -static snd_kcontrol_new_t snd_ca0106_volume_control_analog_rear = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Rear Playback Volume", - .info = snd_ca0106_volume_info, - .get = snd_ca0106_volume_get_analog_rear, - .put = snd_ca0106_volume_put_analog_rear -}; -static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_front = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "SPDIF Front Playback Volume", - .info = snd_ca0106_volume_info, - .get = snd_ca0106_volume_get_spdif_front, - .put = snd_ca0106_volume_put_spdif_front -}; -static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_center_lfe = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "SPDIF Center/LFE Playback Volume", - .info = snd_ca0106_volume_info, - .get = snd_ca0106_volume_get_spdif_center_lfe, - .put = snd_ca0106_volume_put_spdif_center_lfe -}; -static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_unknown = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "SPDIF Unknown Playback Volume", - .info = snd_ca0106_volume_info, - .get = snd_ca0106_volume_get_spdif_unknown, - .put = snd_ca0106_volume_put_spdif_unknown -}; -static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_rear = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "SPDIF Rear Playback Volume", - .info = snd_ca0106_volume_info, - .get = snd_ca0106_volume_get_spdif_rear, - .put = snd_ca0106_volume_put_spdif_rear -}; - -static snd_kcontrol_new_t snd_ca0106_volume_control_feedback = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "CAPTURE feedback Playback Volume", - .info = snd_ca0106_volume_info, - .get = snd_ca0106_volume_get_feedback, - .put = snd_ca0106_volume_put_feedback + unsigned int oval, nval; + int channel_id, reg; + + channel_id = (kcontrol->private_value >> 8) & 0xff; + reg = kcontrol->private_value & 0xff; + + oval = snd_ca0106_ptr_read(emu, reg, channel_id); + nval = ((0xff - ucontrol->value.integer.value[0]) << 24) | + ((0xff - ucontrol->value.integer.value[1]) << 16); + nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) | + ((0xff - ucontrol->value.integer.value[1]) ); + if (oval == nval) + return 0; + snd_ca0106_ptr_write(emu, reg, channel_id, nval); + return 1; +} + +#define CA_VOLUME(xname,chid,reg) \ +{ \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_ca0106_volume_info, \ + .get = snd_ca0106_volume_get, \ + .put = snd_ca0106_volume_put, \ + .private_value = ((chid) << 8) | (reg) \ +} + + +static snd_kcontrol_new_t snd_ca0106_volume_ctls[] __devinitdata = { + CA_VOLUME("Analog Front Playback Volume", + CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2), + CA_VOLUME("Analog Rear Playback Volume", + CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2), + CA_VOLUME("Analog Center/LFE Playback Volume", + CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2), + CA_VOLUME("Analog Side Playback Volume", + CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2), + + CA_VOLUME("SPDIF Front Playback Volume", + CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1), + CA_VOLUME("SPDIF Rear Playback Volume", + CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1), + CA_VOLUME("SPDIF Center/LFE Playback Volume", + CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1), + CA_VOLUME("SPDIF Unknown Playback Volume", + CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1), + + CA_VOLUME("CAPTURE feedback Playback Volume", + 1, CAPTURE_CONTROL), + + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), + .count = 4, + .info = snd_ca0106_spdif_info, + .get = snd_ca0106_spdif_get_mask + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "SPDIF Out", + .info = snd_ca0106_shared_spdif_info, + .get = snd_ca0106_shared_spdif_get, + .put = snd_ca0106_shared_spdif_put + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = snd_ca0106_capture_source_info, + .get = snd_ca0106_capture_source_get, + .put = snd_ca0106_capture_source_put + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .count = 4, + .info = snd_ca0106_spdif_info, + .get = snd_ca0106_spdif_get, + .put = snd_ca0106_spdif_put + }, }; - -static int remove_ctl(snd_card_t *card, const char *name) +static int __devinit remove_ctl(snd_card_t *card, const char *name) { snd_ctl_elem_id_t id; memset(&id, 0, sizeof(id)); @@ -563,7 +397,7 @@ static int remove_ctl(snd_card_t *card, const char *name) return snd_ctl_remove_id(card, &id); } -static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name) +static snd_kcontrol_t __devinit *ctl_find(snd_card_t *card, const char *name) { snd_ctl_elem_id_t sid; memset(&sid, 0, sizeof(sid)); @@ -573,7 +407,7 @@ static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name) return snd_ctl_find_id(card, &sid); } -static int rename_ctl(snd_card_t *card, const char *src, const char *dst) +static int __devinit rename_ctl(snd_card_t *card, const char *src, const char *dst) { snd_kcontrol_t *kctl = ctl_find(card, src); if (kctl) { @@ -585,8 +419,7 @@ static int rename_ctl(snd_card_t *card, const char *src, const char *dst) int __devinit snd_ca0106_mixer(ca0106_t *emu) { - int err; - snd_kcontrol_t *kctl; + int i, err; snd_card_t *card = emu->card; char **c; static char *ca0106_remove_ctls[] = { @@ -627,70 +460,22 @@ int __devinit snd_ca0106_mixer(ca0106_t *emu) NULL }; #if 1 - for (c=ca0106_remove_ctls; *c; c++) + for (c = ca0106_remove_ctls; *c; c++) remove_ctl(card, *c); - for (c=ca0106_rename_ctls; *c; c += 2) + for (c = ca0106_rename_ctls; *c; c += 2) rename_ctl(card, c[0], c[1]); #endif - if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_front, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_rear, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_center_lfe, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_unknown, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_front, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_rear, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_center_lfe, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_unknown, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_feedback, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_mask_control, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_shared_spdif, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_ca0106_capture_source, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; + for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_ctls); i++) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_ctls[i], emu)); + if (err < 0) + return err; + } if (emu->details->i2c_adc == 1) { - if ((kctl = snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); + if (err < 0) return err; } - if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; return 0; } |