Commit e879b8eb authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

V4L/DVB (9672): Allow opening more than one output at the same time



Some devices use more than one AC97 outputs. This patch allows such
devices to properly work.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 209acc02
Loading
Loading
Loading
Loading
+20 −13
Original line number Diff line number Diff line
@@ -304,12 +304,12 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val)
	return 0;
}

struct em28xx_input_table {
	enum em28xx_amux amux;
struct em28xx_vol_table {
	enum em28xx_amux mux;
	u8		 reg;
};

static struct em28xx_input_table inputs[] = {
static struct em28xx_vol_table inputs[] = {
	{ EM28XX_AMUX_VIDEO, 	AC97_VIDEO_VOL   },
	{ EM28XX_AMUX_LINE_IN,	AC97_LINEIN_VOL  },
	{ EM28XX_AMUX_PHONE,	AC97_PHONE_VOL   },
@@ -332,7 +332,7 @@ static int set_ac97_input(struct em28xx *dev)

	/* Mute all entres but the one that were selected */
	for (i = 0; i < ARRAY_SIZE(inputs); i++) {
		if (amux == inputs[i].amux)
		if (amux == inputs[i].mux)
			ret = em28xx_write_ac97(dev, inputs[i].reg, 0x0808);
		else
			ret = em28xx_write_ac97(dev, inputs[i].reg, 0x8000);
@@ -388,12 +388,12 @@ static int em28xx_set_audio_source(struct em28xx *dev)
	return ret;
}

static int outputs[] = {
	[EM28XX_AOUT_MASTER] = AC97_MASTER_VOL,
	[EM28XX_AOUT_LINE]   = AC97_LINE_LEVEL_VOL,
	[EM28XX_AOUT_MONO]   = AC97_MASTER_MONO_VOL,
	[EM28XX_AOUT_LFE]    = AC97_LFE_MASTER_VOL,
	[EM28XX_AOUT_SURR]   = AC97_SURR_MASTER_VOL,
struct em28xx_vol_table outputs[] = {
	{ EM28XX_AOUT_MASTER, AC97_MASTER_VOL      },
	{ EM28XX_AOUT_LINE,   AC97_LINE_LEVEL_VOL  },
	{ EM28XX_AOUT_MONO,   AC97_MASTER_MONO_VOL },
	{ EM28XX_AOUT_LFE,    AC97_LFE_MASTER_VOL  },
	{ EM28XX_AOUT_SURR,   AC97_SURR_MASTER_VOL },
};

int em28xx_audio_analog_set(struct em28xx *dev)
@@ -410,10 +410,10 @@ int em28xx_audio_analog_set(struct em28xx *dev)
	if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
		/* Mute all outputs */
		for (i = 0; i < ARRAY_SIZE(outputs); i++) {
			ret = em28xx_write_ac97(dev, outputs[i], 0x8000);
			ret = em28xx_write_ac97(dev, outputs[i].reg, 0x8000);
			if (ret < 0)
				em28xx_warn("couldn't setup AC97 register %d\n",
				     outputs[i]);
				     outputs[i].reg);
		}
	}

@@ -443,7 +443,14 @@ int em28xx_audio_analog_set(struct em28xx *dev)
			vol |= 0x8000;

		/* Sets volume */
		ret = em28xx_write_ac97(dev, outputs[dev->ctl_aoutput], vol);
		for (i = 0; i < ARRAY_SIZE(outputs); i++) {
			if (dev->ctl_aoutput & outputs[i].mux)
				ret = em28xx_write_ac97(dev, outputs[i].reg,
							vol);
			if (ret < 0)
				em28xx_warn("couldn't setup AC97 register %d\n",
				     outputs[i].reg);
		}
	}

	return ret;
+6 −0
Original line number Diff line number Diff line
@@ -568,6 +568,9 @@ static void video_mux(struct em28xx *dev, int index)
	dev->ctl_ainput = INPUT(index)->amux;
	dev->ctl_aoutput = INPUT(index)->aout;

	if (!dev->ctl_aoutput)
		dev->ctl_aoutput = EM28XX_AOUT_MASTER;

	em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);

	if (dev->has_msp34xx) {
@@ -972,6 +975,9 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)

	dev->ctl_ainput = INPUT(a->index)->amux;
	dev->ctl_aoutput = INPUT(a->index)->aout;

	if (!dev->ctl_aoutput)
		dev->ctl_aoutput = EM28XX_AOUT_MASTER;
	return 0;
}

+5 −5
Original line number Diff line number Diff line
@@ -297,11 +297,11 @@ enum em28xx_amux {
};

enum em28xx_aout {
	EM28XX_AOUT_MASTER = 0,	/* should be the default */
	EM28XX_AOUT_LINE,
	EM28XX_AOUT_MONO,
	EM28XX_AOUT_LFE,
	EM28XX_AOUT_SURR,
	EM28XX_AOUT_MASTER = 1 << 0,
	EM28XX_AOUT_LINE   = 1 << 1,
	EM28XX_AOUT_MONO   = 1 << 2,
	EM28XX_AOUT_LFE    = 1 << 3,
	EM28XX_AOUT_SURR   = 1 << 4,
};

struct em28xx_input {