summaryrefslogtreecommitdiff
path: root/sound/pci/ctxfi/ctmixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/ctxfi/ctmixer.c')
-rw-r--r--sound/pci/ctxfi/ctmixer.c111
1 files changed, 88 insertions, 23 deletions
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c
index 48fe0e39c2be..fc9fde284fb3 100644
--- a/sound/pci/ctxfi/ctmixer.c
+++ b/sound/pci/ctxfi/ctmixer.c
@@ -1,10 +1,7 @@
-/**
+// SPDX-License-Identifier: GPL-2.0-only
+/*
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
*
- * This source file is released under GPL v2 license (no other versions).
- * See the COPYING file included in the main directory of this source
- * distribution for the license terms and conditions.
- *
* @File ctmixer.c
*
* @Brief
@@ -12,7 +9,6 @@
*
* @Author Liu Chun
* @Date May 28 2008
- *
*/
@@ -551,8 +547,14 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
atc->mic_unmute(atc, state);
else if (MIXER_SPDIFI_C_S == type)
atc->spdif_in_unmute(atc, state);
- else if (MIXER_WAVEF_P_S == type)
- atc->line_front_unmute(atc, state);
+ else if (MIXER_WAVEF_P_S == type) {
+ if (cap.dedicated_rca) {
+ atc->rca_unmute(atc, atc->rca_state ? 0 : state);
+ atc->line_front_unmute(atc, atc->rca_state ? state : 0);
+ } else {
+ atc->line_front_unmute(atc, state);
+ }
+ }
else if (MIXER_WAVES_P_S == type)
atc->line_surround_unmute(atc, state);
else if (MIXER_WAVEC_P_S == type)
@@ -616,6 +618,57 @@ static struct snd_kcontrol_new swh_ctl = {
.put = ct_alsa_mix_switch_put
};
+static int dedicated_rca_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *info)
+{
+ static const char *const names[2] = {
+ "RCA", "Front"
+ };
+
+ return snd_ctl_enum_info(info, 1, 2, names);
+}
+
+static int dedicated_rca_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = atc->rca_state;
+ return 0;
+}
+
+static int dedicated_rca_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
+ unsigned int rca_state = ucontrol->value.enumerated.item[0];
+ unsigned char state;
+
+ if (rca_state > 1)
+ return -EINVAL;
+
+ if (rca_state == atc->rca_state)
+ return 0;
+
+ state = get_switch_state(atc->mixer, MIXER_WAVEF_P_S);
+ do_switch(atc, MIXER_WAVEF_P_S, 0);
+
+ atc->rca_state = rca_state;
+ atc->dedicated_rca_select(atc);
+
+ do_switch(atc, MIXER_WAVEF_P_S, state);
+
+ return 1;
+}
+
+static struct snd_kcontrol_new rca_ctl = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Route",
+ .info = dedicated_rca_info,
+ .get = dedicated_rca_get,
+ .put = dedicated_rca_put,
+};
+
static int ct_spdif_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -788,7 +841,17 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
if (err)
return err;
}
- atc->line_front_unmute(atc, 1);
+
+ if (cap.dedicated_rca) {
+ err = ct_mixer_kcontrol_new(mixer, &rca_ctl);
+ if (err)
+ return err;
+
+ atc->line_front_unmute(atc, 0);
+ atc->rca_unmute(atc, 1);
+ } else {
+ atc->line_front_unmute(atc, 1);
+ }
set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
atc->line_surround_unmute(atc, 0);
set_switch_state(mixer, MIXER_WAVES_P_S, 0);
@@ -854,8 +917,8 @@ static int ct_mixer_get_resources(struct ct_mixer *mixer)
for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum);
if (err) {
- printk(KERN_ERR "ctxfi:Failed to get sum resources for "
- "front output!\n");
+ dev_err(mixer->atc->card->dev,
+ "Failed to get sum resources for front output!\n");
break;
}
mixer->sums[i] = sum;
@@ -869,8 +932,8 @@ static int ct_mixer_get_resources(struct ct_mixer *mixer)
for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer);
if (err) {
- printk(KERN_ERR "ctxfi:Failed to get amixer resources "
- "for mixer obj!\n");
+ dev_err(mixer->atc->card->dev,
+ "Failed to get amixer resources for mixer obj!\n");
break;
}
mixer->amixers[i] = amixer;
@@ -910,13 +973,14 @@ static int ct_mixer_get_mem(struct ct_mixer **rmixer)
if (!mixer)
return -ENOMEM;
- mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM),
+ mixer->amixers = kcalloc(NUM_CT_AMIXERS * CHN_NUM, sizeof(void *),
GFP_KERNEL);
if (!mixer->amixers) {
err = -ENOMEM;
goto error1;
}
- mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL);
+ mixer->sums = kcalloc(NUM_CT_SUMS * CHN_NUM, sizeof(void *),
+ GFP_KERNEL);
if (!mixer->sums) {
err = -ENOMEM;
goto error2;
@@ -937,17 +1001,18 @@ static int ct_mixer_topology_build(struct ct_mixer *mixer)
struct sum *sum;
struct amixer *amix_d, *amix_s;
enum CT_AMIXER_CTL i, j;
+ enum CT_SUM_CTL k;
/* Build topology from destination to source */
/* Set up Master mixer */
- for (i = AMIXER_MASTER_F, j = SUM_IN_F;
- i <= AMIXER_MASTER_S; i++, j++) {
+ for (i = AMIXER_MASTER_F, k = SUM_IN_F;
+ i <= AMIXER_MASTER_S; i++, k++) {
amix_d = mixer->amixers[i*CHN_NUM];
- sum = mixer->sums[j*CHN_NUM];
+ sum = mixer->sums[k*CHN_NUM];
amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
amix_d = mixer->amixers[i*CHN_NUM+1];
- sum = mixer->sums[j*CHN_NUM+1];
+ sum = mixer->sums[k*CHN_NUM+1];
amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
}
@@ -971,12 +1036,12 @@ static int ct_mixer_topology_build(struct ct_mixer *mixer)
amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
/* Set up PCM-in mixer */
- for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) {
+ for (i = AMIXER_PCM_F, k = SUM_IN_F; i <= AMIXER_PCM_S; i++, k++) {
amix_d = mixer->amixers[i*CHN_NUM];
- sum = mixer->sums[j*CHN_NUM];
+ sum = mixer->sums[k*CHN_NUM];
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
amix_d = mixer->amixers[i*CHN_NUM+1];
- sum = mixer->sums[j*CHN_NUM+1];
+ sum = mixer->sums[k*CHN_NUM+1];
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
}
@@ -1221,7 +1286,7 @@ int ct_alsa_mix_create(struct ct_atc *atc,
if (err)
return err;
- strcpy(atc->card->mixername, device_name);
+ strscpy(atc->card->mixername, device_name);
return 0;
}