Commit 00d2c3e5 authored by 薛德章's avatar 薛德章

ioctl support for input selection. fix bug 4716

Improve input selection in OSS driver. add ioctl() support.
parent 5198fffc
......@@ -544,6 +544,21 @@ typedef struct {
/********************************************
* IOCTL commands for /dev/dsp and /dev/audio
*/
#define OSS_ENUM_MAXVALUE 255
/*
* Description:
* http://manuals.opensound.com/developer/SNDCTL_MIX_ENUMINFO.html
*/
typedef struct oss_mixer_enuminfo
{
int dev;
int ctrl;
int nvalues;
int version;
short strindex[OSS_ENUM_MAXVALUE];
char strings[3000];
} oss_mixer_enuminfo;
#define SNDCTL_DSP_RESET _SIO ('P', 0)
#define SNDCTL_DSP_SYNC _SIO ('P', 1)
......@@ -697,6 +712,13 @@ typedef struct buffmem_desc {
#define SOUND_PCM_MAPINBUF SNDCTL_DSP_MAPINBUF
#define SOUND_PCM_MAPOUTBUF SNDCTL_DSP_MAPOUTBUF
/*
* Interface for selecting recording sources and playback output routings.
*/
#define SNDCTL_DSP_GET_RECSRC_NAMES _IOR ('P', 37, oss_mixer_enuminfo)
#define SNDCTL_DSP_GET_RECSRC _IOR ('P', 38, int)
#define SNDCTL_DSP_SET_RECSRC _IOWR('P', 38, int)
/*
* ioctl calls to be used in communication with coprocessors and
* DSP chips.
......
......@@ -35,6 +35,8 @@
#define MIC3_TO_RIGHT_ADC_CTRL_REG 18
#define LINE1L_TO_LEFT_ADC_CTRL_REG 19
#define LINE1R_TO_RIGHT_ADC_CTRL_REG 22
#define LINE2L_TO_LEFT_ADC_CTRL_REG 20
#define LINE2R_TO_RIGHT_ADC_CTRL_REG 23
#define MCBIAS_CTRL_REG 25
......@@ -99,6 +101,12 @@
#define LINE1R_NOT_CONNECT 0x78
#define RIGHT_ADC_POWER_UP 0x04
/* used by register 20 */
#define LINE2_LEFT_ADC_NOT_CONNECT 0x78
/* used by register 23 */
#define LINE2_RIGHT_ADC_NOT_CONNECT 0x78
/* MICBIAS control register 25 */
#define MICBIAS_OUTPUT_2_0V 0x40
#define MICBIAS_OUTPUT_2_5V 0x80
......
......@@ -268,6 +268,57 @@ static __inline__ void audio_aic32_write(u8 address, u16 data)
printk(KERN_INFO "aic32 write failed for reg = %d\n", address);
}
static void enable_adc(void)
{
audio_aic32_write(LINE1L_TO_LEFT_ADC_CTRL_REG,
LINE1L_NOT_CONNECT | LEFT_ADC_POWER_UP);
audio_aic32_write(LINE1R_TO_RIGHT_ADC_CTRL_REG,
LINE1R_NOT_CONNECT | RIGHT_ADC_POWER_UP);
}
/* enable ADC and enable line1 input*/
static void enable_line1_input(void)
{
audio_aic32_write(LINE1L_TO_LEFT_ADC_CTRL_REG,
LEFT_ADC_POWER_UP);
audio_aic32_write(LINE1R_TO_RIGHT_ADC_CTRL_REG,
RIGHT_ADC_POWER_UP);
}
/* enable ADC and disable line1 input */
static void disable_line1_input(void)
{
audio_aic32_write(LINE1L_TO_LEFT_ADC_CTRL_REG,
LINE1L_NOT_CONNECT | LEFT_ADC_POWER_UP);
audio_aic32_write(LINE1R_TO_RIGHT_ADC_CTRL_REG,
LINE1R_NOT_CONNECT | RIGHT_ADC_POWER_UP);
}
/* enable line2 input*/
static void enable_line2_input(void)
{
audio_aic32_write(LINE2L_TO_LEFT_ADC_CTRL_REG, 0x0);
audio_aic32_write(LINE2R_TO_RIGHT_ADC_CTRL_REG, 0x0);
}
static void disable_line2_input(void)
{
audio_aic32_write(LINE2L_TO_LEFT_ADC_CTRL_REG,
LINE2_LEFT_ADC_NOT_CONNECT);
audio_aic32_write(LINE2R_TO_RIGHT_ADC_CTRL_REG,
LINE2_RIGHT_ADC_NOT_CONNECT);
}
/* enable mic/line3 input*/
static void enable_mic_input(void)
{
audio_aic32_write(MIC3_TO_LEFT_ADC_CTRL_REG, 0x0);
audio_aic32_write(MIC3_TO_RIGHT_ADC_CTRL_REG, 0x0);
}
static void disable_mic_input(void)
{
audio_aic32_write(MIC3_TO_LEFT_ADC_CTRL_REG,
MIC3L_LEFT_ADC_NOT_CONNECT | MIC3R_LEFT_ADC_NOT_CONNECT);
audio_aic32_write(MIC3_TO_RIGHT_ADC_CTRL_REG,
MIC3L_RIGHT_ADC_NOT_CONNECT | MIC3R_RIGHT_ADC_NOT_CONNECT);
}
static int aic32_update(int flag, int val)
{
u16 volume;
......@@ -456,6 +507,90 @@ static int mixer_release(struct inode *inode, struct file *file)
return 0;
}
int oss_recsrc_enum (oss_mixer_enuminfo * ei, const char *s)
{
int n = 1, l;
int i;
memset (ei, 0, sizeof (*ei));
strncpy (ei->strings, s, sizeof (ei->strings) - 1);
ei->strings[sizeof (ei->strings) - 1] = 0;
ei->strindex[0] = 0;
l = strlen (ei->strings);
for (i = 0; i < l; i++)
{
if (ei->strings[i] == ' ')
{
ei->strindex[n++] = i + 1;
ei->strings[i] = 0;
}
}
ei->nvalues = n;
return 0;
}
static int mixer_get_recnames(ulong arg)
{
oss_mixer_enuminfo ei;
char *s = "line1 line2 line3";
oss_recsrc_enum(&ei, s);
return copy_to_user((int *)arg, &ei, sizeof(ei));
}
static int mixer_get_recroute(ulong arg)
{
return copy_to_user((int *)arg, &(aic32_local.recsrc),sizeof(int));
}
static int mixer_set_recroute(ulong arg)
{
long val;
int ret;
ret = get_user(val, (long *)arg);
if(ret)
return -ENOTTY;
switch(val)
{
case 0:
printk("LINE1 audio input selected\n");
enable_line1_input();
disable_line2_input();
disable_mic_input();
aic32_local.recsrc = val;
ret = 0;
break;
case 1:
printk("LINE2 audio input selected\n");
disable_line1_input();
enable_line2_input();
disable_mic_input();
aic32_local.recsrc = val;
ret = 0;
break;
case 2:
printk("LINE3 audio input selected\n");
disable_line1_input();
disable_line2_input();
enable_mic_input();
aic32_local.recsrc = val;
ret = 0;
break;
default:
printk("Invalid Record Source\n");
ret = -ENOTTY;
break;
}
return ret;
}
static int
mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
{
......@@ -463,6 +598,22 @@ mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
int ret = 0;
int nr = _IOC_NR(cmd);
/*
* choose which input source to use
*/
switch(cmd)
{
case SNDCTL_DSP_GET_RECSRC_NAMES:
ret = mixer_get_recnames(arg);
return ret;
case SNDCTL_DSP_SET_RECSRC:
ret = mixer_set_recroute(arg);
return ret;
case SNDCTL_DSP_GET_RECSRC:
ret = mixer_get_recroute(arg);
return ret;
}
/*
* We only accept mixer (type 'M') ioctls.
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment