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>
* em28xx_write_ac97()
* 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;
u8 addr = reg & 0x7f;
return 0;
}
+int em28xx_set_audio_source(struct em28xx *dev)
+{
+ static char *enable = "\x08\x08";
+ static char *disable = "\x08\x88";
+ char *video = enable, *line = disable;
+ int ret, no_ac97;
+ u8 input;
+
+ 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;
- return em28xx_write_ac97(dev, MASTER_AC97, s);
-}
+ 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)
{
/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
- em28xx_audio_usb_mute(dev, 1);
dev->mute = 1; /* maybe not the right place... */
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_setup(dev);
em28xx_outfmt_set_yuv422(dev);
em28xx_colorlevels_set_default(dev);
em28xx_compression_disable(dev);
static void video_mux(struct em28xx *dev, int index)
{
- int ainput;
struct v4l2_routing route;
route.input = INPUT(index)->vmux;
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
/* Note: this is msp3400 specific */
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 */
case V4L2_CID_AUDIO_MUTE:
if (ctrl->value != dev->mute) {
dev->mute = ctrl->value;
- em28xx_audio_usb_mute(dev, ctrl->value);
return em28xx_audio_analog_set(dev);
}
return 0;
EM28XX_RADIO,
};
+enum em28xx_amux {
+ EM28XX_AMUX_VIDEO,
+ EM28XX_AMUX_LINE_IN,
+ EM28XX_AMUX_AC97_VIDEO,
+ EM28XX_AMUX_AC97_LINE_IN,
+};
+
struct em28xx_input {
enum enum28xx_itype type;
unsigned int vmux;
- unsigned int amux;
+ enum em28xx_amux amux;
};
#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
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,
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_colorlevels_set_default(struct em28xx *dev);
int em28xx_capture_start(struct em28xx *dev, int start);
int em28xx_outfmt_set_yuv422(struct em28xx *dev);
/* em202 registers */
#define MASTER_AC97 0x02
+#define LINE_IN_AC97 0x10
#define VIDEO_AC97 0x14
/* register settings */
printk(KERN_WARNING "%s: "fmt,\
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)
{
/* side effect of disabling scaler and mixer */