V4L/DVB (6947): Improve audio setup handling
It is possible to select audio inputs via em28xx or via ac97 functions. This patch allows configuring a board to use either one way. It also do some cleanups at audio setup configurations. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
6596a4f603
commit
539c96d0fd
3 changed files with 100 additions and 47 deletions
|
@ -252,7 +252,7 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
|
||||||
* em28xx_write_ac97()
|
* em28xx_write_ac97()
|
||||||
* write a 16 bit value to the specified AC97 address (LSB first!)
|
* write a 16 bit value to the specified AC97 address (LSB first!)
|
||||||
*/
|
*/
|
||||||
int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val)
|
static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u8 addr = reg & 0x7f;
|
u8 addr = reg & 0x7f;
|
||||||
|
@ -268,16 +268,91 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int em28xx_audio_analog_set(struct em28xx *dev)
|
int em28xx_set_audio_source(struct em28xx *dev)
|
||||||
{
|
{
|
||||||
char s[2] = { 0x00, 0x00 };
|
static char *enable = "\x08\x08";
|
||||||
s[0] |= 0x1f - dev->volume;
|
static char *disable = "\x08\x88";
|
||||||
s[1] |= 0x1f - dev->volume;
|
char *video = enable, *line = disable;
|
||||||
if (dev->mute)
|
int ret, no_ac97;
|
||||||
s[1] |= 0x80;
|
u8 input;
|
||||||
return em28xx_write_ac97(dev, MASTER_AC97, s);
|
|
||||||
|
if (dev->is_em2800) {
|
||||||
|
if (dev->ctl_ainput)
|
||||||
|
input = EM2800_AUDIO_SRC_LINE;
|
||||||
|
else
|
||||||
|
input = EM2800_AUDIO_SRC_TUNER;
|
||||||
|
|
||||||
|
ret = em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &input, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->has_msp34xx)
|
||||||
|
input = EM28XX_AUDIO_SRC_TUNER;
|
||||||
|
else {
|
||||||
|
switch (dev->ctl_ainput) {
|
||||||
|
case EM28XX_AMUX_VIDEO:
|
||||||
|
input = EM28XX_AUDIO_SRC_TUNER;
|
||||||
|
no_ac97 = 1;
|
||||||
|
break;
|
||||||
|
case EM28XX_AMUX_LINE_IN:
|
||||||
|
input = EM28XX_AUDIO_SRC_LINE;
|
||||||
|
no_ac97 = 1;
|
||||||
|
break;
|
||||||
|
case EM28XX_AMUX_AC97_VIDEO:
|
||||||
|
input = EM28XX_AUDIO_SRC_LINE;
|
||||||
|
break;
|
||||||
|
case EM28XX_AMUX_AC97_LINE_IN:
|
||||||
|
input = EM28XX_AUDIO_SRC_LINE;
|
||||||
|
video = disable;
|
||||||
|
line = enable;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (no_ac97)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Sets AC97 mixer registers */
|
||||||
|
|
||||||
|
ret = em28xx_write_ac97(dev, VIDEO_AC97, video);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = em28xx_write_ac97(dev, LINE_IN_AC97, line);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int em28xx_audio_analog_set(struct em28xx *dev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char s[2] = { 0x00, 0x00 };
|
||||||
|
|
||||||
|
s[0] |= 0x1f - dev->volume;
|
||||||
|
s[1] |= 0x1f - dev->volume;
|
||||||
|
|
||||||
|
if (dev->mute)
|
||||||
|
s[1] |= 0x80;
|
||||||
|
ret = em28xx_write_ac97(dev, MASTER_AC97, s);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = em28xx_write_reg_bits(dev, XCLK_REG,
|
||||||
|
dev->mute ? 0x00 : 0x80, 0x80);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Selects the proper audio input */
|
||||||
|
ret = em28xx_set_audio_source(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
|
||||||
|
|
||||||
int em28xx_colorlevels_set_default(struct em28xx *dev)
|
int em28xx_colorlevels_set_default(struct em28xx *dev)
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,11 +122,13 @@ static int em28xx_config(struct em28xx *dev)
|
||||||
/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
|
/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
|
||||||
em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
|
em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
|
||||||
|
|
||||||
em28xx_audio_usb_mute(dev, 1);
|
|
||||||
dev->mute = 1; /* maybe not the right place... */
|
dev->mute = 1; /* maybe not the right place... */
|
||||||
dev->volume = 0x1f;
|
dev->volume = 0x1f;
|
||||||
|
|
||||||
|
/* Init XCLK_REG, audio muted */
|
||||||
|
dev->em28xx_write_regs(dev, XCLK_REG, "\x87", 1);
|
||||||
|
|
||||||
em28xx_audio_analog_set(dev);
|
em28xx_audio_analog_set(dev);
|
||||||
em28xx_audio_analog_setup(dev);
|
|
||||||
em28xx_outfmt_set_yuv422(dev);
|
em28xx_outfmt_set_yuv422(dev);
|
||||||
em28xx_colorlevels_set_default(dev);
|
em28xx_colorlevels_set_default(dev);
|
||||||
em28xx_compression_disable(dev);
|
em28xx_compression_disable(dev);
|
||||||
|
@ -168,7 +170,6 @@ static void em28xx_empty_framequeues(struct em28xx *dev)
|
||||||
|
|
||||||
static void video_mux(struct em28xx *dev, int index)
|
static void video_mux(struct em28xx *dev, int index)
|
||||||
{
|
{
|
||||||
int ainput;
|
|
||||||
struct v4l2_routing route;
|
struct v4l2_routing route;
|
||||||
|
|
||||||
route.input = INPUT(index)->vmux;
|
route.input = INPUT(index)->vmux;
|
||||||
|
@ -185,18 +186,9 @@ static void video_mux(struct em28xx *dev, int index)
|
||||||
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
|
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
|
||||||
/* Note: this is msp3400 specific */
|
/* Note: this is msp3400 specific */
|
||||||
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
|
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
|
||||||
ainput = EM28XX_AUDIO_SRC_TUNER;
|
|
||||||
em28xx_audio_source(dev, ainput);
|
|
||||||
} else {
|
|
||||||
switch (dev->ctl_ainput) {
|
|
||||||
case 0:
|
|
||||||
ainput = EM28XX_AUDIO_SRC_TUNER;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ainput = EM28XX_AUDIO_SRC_LINE;
|
|
||||||
}
|
|
||||||
em28xx_audio_source(dev, ainput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
em28xx_set_audio_source(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Usage lock check functions */
|
/* Usage lock check functions */
|
||||||
|
@ -292,7 +284,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
|
||||||
case V4L2_CID_AUDIO_MUTE:
|
case V4L2_CID_AUDIO_MUTE:
|
||||||
if (ctrl->value != dev->mute) {
|
if (ctrl->value != dev->mute) {
|
||||||
dev->mute = ctrl->value;
|
dev->mute = ctrl->value;
|
||||||
em28xx_audio_usb_mute(dev, ctrl->value);
|
|
||||||
return em28xx_audio_analog_set(dev);
|
return em28xx_audio_analog_set(dev);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -151,10 +151,17 @@ enum enum28xx_itype {
|
||||||
EM28XX_RADIO,
|
EM28XX_RADIO,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum em28xx_amux {
|
||||||
|
EM28XX_AMUX_VIDEO,
|
||||||
|
EM28XX_AMUX_LINE_IN,
|
||||||
|
EM28XX_AMUX_AC97_VIDEO,
|
||||||
|
EM28XX_AMUX_AC97_LINE_IN,
|
||||||
|
};
|
||||||
|
|
||||||
struct em28xx_input {
|
struct em28xx_input {
|
||||||
enum enum28xx_itype type;
|
enum enum28xx_itype type;
|
||||||
unsigned int vmux;
|
unsigned int vmux;
|
||||||
unsigned int amux;
|
enum em28xx_amux amux;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
|
#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
|
||||||
|
@ -321,8 +328,9 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
|
||||||
int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
|
int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
|
||||||
int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
|
int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
|
||||||
u8 bitmask);
|
u8 bitmask);
|
||||||
int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val);
|
int em28xx_set_audio_source(struct em28xx *dev);
|
||||||
int em28xx_audio_analog_set(struct em28xx *dev);
|
int em28xx_audio_analog_set(struct em28xx *dev);
|
||||||
|
|
||||||
int em28xx_colorlevels_set_default(struct em28xx *dev);
|
int em28xx_colorlevels_set_default(struct em28xx *dev);
|
||||||
int em28xx_capture_start(struct em28xx *dev, int start);
|
int em28xx_capture_start(struct em28xx *dev, int start);
|
||||||
int em28xx_outfmt_set_yuv422(struct em28xx *dev);
|
int em28xx_outfmt_set_yuv422(struct em28xx *dev);
|
||||||
|
@ -394,6 +402,7 @@ extern const unsigned int em28xx_bcount;
|
||||||
|
|
||||||
/* em202 registers */
|
/* em202 registers */
|
||||||
#define MASTER_AC97 0x02
|
#define MASTER_AC97 0x02
|
||||||
|
#define LINE_IN_AC97 0x10
|
||||||
#define VIDEO_AC97 0x14
|
#define VIDEO_AC97 0x14
|
||||||
|
|
||||||
/* register settings */
|
/* register settings */
|
||||||
|
@ -418,28 +427,6 @@ extern const unsigned int em28xx_bcount;
|
||||||
printk(KERN_WARNING "%s: "fmt,\
|
printk(KERN_WARNING "%s: "fmt,\
|
||||||
dev->name , ##arg); } while (0)
|
dev->name , ##arg); } while (0)
|
||||||
|
|
||||||
inline static int em28xx_audio_source(struct em28xx *dev, int input)
|
|
||||||
{
|
|
||||||
if(dev->is_em2800){
|
|
||||||
u8 tmp = EM2800_AUDIO_SRC_TUNER;
|
|
||||||
if(input == EM28XX_AUDIO_SRC_LINE)
|
|
||||||
tmp = EM2800_AUDIO_SRC_LINE;
|
|
||||||
em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &tmp, 1);
|
|
||||||
}
|
|
||||||
return em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int em28xx_audio_usb_mute(struct em28xx *dev, int mute)
|
|
||||||
{
|
|
||||||
return em28xx_write_reg_bits(dev, XCLK_REG, mute ? 0x00 : 0x80, 0x80);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int em28xx_audio_analog_setup(struct em28xx *dev)
|
|
||||||
{
|
|
||||||
/* unmute video mixer with default volume level */
|
|
||||||
return em28xx_write_ac97(dev, VIDEO_AC97, "\x08\x08");
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int em28xx_compression_disable(struct em28xx *dev)
|
inline static int em28xx_compression_disable(struct em28xx *dev)
|
||||||
{
|
{
|
||||||
/* side effect of disabling scaler and mixer */
|
/* side effect of disabling scaler and mixer */
|
||||||
|
|
Loading…
Add table
Reference in a new issue