Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 539c96d0 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

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: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 6596a4f6
Loading
Loading
Loading
Loading
+78 −3
Original line number Diff line number Diff line
@@ -252,7 +252,7 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
 * 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;
@@ -268,16 +268,91 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val)
	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)
{
+6 −15
Original line number Diff line number Diff line
@@ -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,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);
@@ -168,7 +170,6 @@ static void em28xx_empty_framequeues(struct em28xx *dev)

static void video_mux(struct em28xx *dev, int index)
{
	int ainput;
	struct v4l2_routing route;

	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);
		/* 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 */
@@ -292,7 +284,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
	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;
+11 −24
Original line number Diff line number Diff line
@@ -151,10 +151,17 @@ enum enum28xx_itype {
	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])
@@ -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_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);
@@ -394,6 +402,7 @@ extern const unsigned int em28xx_bcount;

/* em202 registers */
#define MASTER_AC97	0x02
#define LINE_IN_AC97    0x10
#define VIDEO_AC97	0x14

/* register settings */
@@ -418,28 +427,6 @@ extern const unsigned int em28xx_bcount;
	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 */