mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 15:18:19 +00:00
[ALSA] Enable capture from line-in and CD on Revolution 5.1
Enable capture from line-in and CD on the Revolution 5.1 card. This patch adds support for switching between the 5 input channels of the AK5365 ADC and modifies the Revolution 5.1 driver to make use of this facility. Previously the capture channel was fixed to channel 0 (microphone on the Revolution 5.1 card). Signed-off-by: Jochen Voss <voss@seehuhn.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
parent
e4f8e656d8
commit
a58e7cb16d
3 changed files with 94 additions and 3 deletions
|
@ -50,6 +50,8 @@ struct snd_akm4xxx_adc_channel {
|
||||||
char *name; /* capture gain volume label */
|
char *name; /* capture gain volume label */
|
||||||
char *switch_name; /* capture switch */
|
char *switch_name; /* capture switch */
|
||||||
unsigned int num_channels;
|
unsigned int num_channels;
|
||||||
|
char *selector_name; /* capture source select label */
|
||||||
|
const char **input_names; /* capture source names (NULL terminated) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct snd_akm4xxx {
|
struct snd_akm4xxx {
|
||||||
|
|
|
@ -513,6 +513,66 @@ static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol,
|
||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define AK5365_NUM_INPUTS 5
|
||||||
|
|
||||||
|
static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo)
|
||||||
|
{
|
||||||
|
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
|
||||||
|
int mixer_ch = AK_GET_SHIFT(kcontrol->private_value);
|
||||||
|
const char **input_names;
|
||||||
|
int num_names, idx;
|
||||||
|
|
||||||
|
input_names = ak->adc_info[mixer_ch].input_names;
|
||||||
|
|
||||||
|
num_names = 0;
|
||||||
|
while (num_names < AK5365_NUM_INPUTS && input_names[num_names])
|
||||||
|
++num_names;
|
||||||
|
|
||||||
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||||
|
uinfo->count = 1;
|
||||||
|
uinfo->value.enumerated.items = num_names;
|
||||||
|
idx = uinfo->value.enumerated.item;
|
||||||
|
if (idx >= num_names)
|
||||||
|
return -EINVAL;
|
||||||
|
strncpy(uinfo->value.enumerated.name, input_names[idx],
|
||||||
|
sizeof(uinfo->value.enumerated.name));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ak4xxx_capture_source_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
|
||||||
|
int chip = AK_GET_CHIP(kcontrol->private_value);
|
||||||
|
int addr = AK_GET_ADDR(kcontrol->private_value);
|
||||||
|
int mask = AK_GET_MASK(kcontrol->private_value);
|
||||||
|
unsigned char val;
|
||||||
|
|
||||||
|
val = snd_akm4xxx_get(ak, chip, addr) & mask;
|
||||||
|
ucontrol->value.enumerated.item[0] = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ak4xxx_capture_source_put(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
|
||||||
|
int chip = AK_GET_CHIP(kcontrol->private_value);
|
||||||
|
int addr = AK_GET_ADDR(kcontrol->private_value);
|
||||||
|
int mask = AK_GET_MASK(kcontrol->private_value);
|
||||||
|
unsigned char oval, val;
|
||||||
|
|
||||||
|
oval = snd_akm4xxx_get(ak, chip, addr);
|
||||||
|
val = oval & ~mask;
|
||||||
|
val |= ucontrol->value.enumerated.item[0] & mask;
|
||||||
|
if (val != oval) {
|
||||||
|
snd_akm4xxx_write(ak, chip, addr, val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* build AK4xxx controls
|
* build AK4xxx controls
|
||||||
*/
|
*/
|
||||||
|
@ -647,9 +707,10 @@ static int build_adc_controls(struct snd_akm4xxx *ak)
|
||||||
|
|
||||||
if (ak->type == SND_AK5365 && (idx % 2) == 0) {
|
if (ak->type == SND_AK5365 && (idx % 2) == 0) {
|
||||||
if (! ak->adc_info ||
|
if (! ak->adc_info ||
|
||||||
! ak->adc_info[mixer_ch].switch_name)
|
! ak->adc_info[mixer_ch].switch_name) {
|
||||||
knew.name = "Capture Switch";
|
knew.name = "Capture Switch";
|
||||||
else
|
knew.index = mixer_ch + ak->idx_offset * 2;
|
||||||
|
} else
|
||||||
knew.name = ak->adc_info[mixer_ch].switch_name;
|
knew.name = ak->adc_info[mixer_ch].switch_name;
|
||||||
knew.info = ak4xxx_switch_info;
|
knew.info = ak4xxx_switch_info;
|
||||||
knew.get = ak4xxx_switch_get;
|
knew.get = ak4xxx_switch_get;
|
||||||
|
@ -662,6 +723,26 @@ static int build_adc_controls(struct snd_akm4xxx *ak)
|
||||||
err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
|
err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
memset(&knew, 0, sizeof(knew));
|
||||||
|
knew.name = ak->adc_info[mixer_ch].selector_name;
|
||||||
|
if (!knew.name) {
|
||||||
|
knew.name = "Capture Channel";
|
||||||
|
knew.index = mixer_ch + ak->idx_offset * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||||
|
knew.info = ak4xxx_capture_source_info;
|
||||||
|
knew.get = ak4xxx_capture_source_get;
|
||||||
|
knew.put = ak4xxx_capture_source_put;
|
||||||
|
knew.access = 0;
|
||||||
|
/* input selector control: reg. 1, bits 0-2.
|
||||||
|
* mis-use 'shift' to pass mixer_ch */
|
||||||
|
knew.private_value
|
||||||
|
= AK_COMPOSE(idx/2, 1, mixer_ch, 0x07);
|
||||||
|
err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx += num_stereo;
|
idx += num_stereo;
|
||||||
|
|
|
@ -107,11 +107,19 @@ static struct snd_akm4xxx_dac_channel revo51_dac[] = {
|
||||||
AK_DAC("PCM Rear Playback Volume", 2),
|
AK_DAC("PCM Rear Playback Volume", 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *revo51_adc_input_names[] = {
|
||||||
|
"Mic",
|
||||||
|
"Line",
|
||||||
|
"CD",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static struct snd_akm4xxx_adc_channel revo51_adc[] = {
|
static struct snd_akm4xxx_adc_channel revo51_adc[] = {
|
||||||
{
|
{
|
||||||
.name = "PCM Capture Volume",
|
.name = "PCM Capture Volume",
|
||||||
.switch_name = "PCM Capture Switch",
|
.switch_name = "PCM Capture Switch",
|
||||||
.num_channels = 2
|
.num_channels = 2,
|
||||||
|
.input_names = revo51_adc_input_names
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue