diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 2842ddf6ddac0cdb1eeeb662959dd94bc183e745..8aead5e84d0f1ab2523eb03e15818d29621f6194 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -388,9 +388,17 @@ 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,
+};
+
 int em28xx_audio_analog_set(struct em28xx *dev)
 {
-	int ret;
+	int ret, i;
 	u8 xclk = 0x07;
 
 	if (!dev->audio_mode.has_audio)
@@ -400,11 +408,13 @@ int em28xx_audio_analog_set(struct em28xx *dev)
 	   It would be possible to use also line output.
 	 */
 	if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
-		/* Mute */
-		ret = em28xx_write_ac97(dev, AC97_MASTER_VOL, 0x8000);
-
-		if (ret < 0)
-			return ret;
+		/* Mute all outputs */
+		for (i = 0; i < ARRAY_SIZE(outputs); i++) {
+			ret = em28xx_write_ac97(dev, outputs[i], 0x8000);
+			if (ret < 0)
+				em28xx_warn("couldn't setup AC97 register %d\n",
+				     outputs[i]);
+		}
 	}
 
 	if (dev->has_12mhz_i2s)
@@ -433,7 +443,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
 			vol |= 0x8000;
 
 		/* Sets volume */
-		ret = em28xx_write_ac97(dev, AC97_MASTER_VOL, vol);
+		ret = em28xx_write_ac97(dev, outputs[dev->ctl_aoutput], vol);
 	}
 
 	return ret;
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 6b7d44a7117fb0e3b1f6bdfbba548cc6d6142c3f..bea74fd9a5205917d88f0117eb71dc52c2effd1e 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -566,6 +566,7 @@ static void video_mux(struct em28xx *dev, int index)
 	route.output = 0;
 	dev->ctl_input = index;
 	dev->ctl_ainput = INPUT(index)->amux;
+	dev->ctl_aoutput = INPUT(index)->aout;
 
 	em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
 
@@ -928,20 +929,38 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
 	struct em28xx_fh   *fh    = priv;
 	struct em28xx      *dev   = fh->dev;
-	unsigned int        index = a->index;
 
-	if (a->index > 1)
-		return -EINVAL;
-
-	index = dev->ctl_ainput;
-
-	if (index == 0)
+	switch (a->index) {
+	case EM28XX_AMUX_VIDEO:
 		strcpy(a->name, "Television");
-	else
+		break;
+	case EM28XX_AMUX_LINE_IN:
 		strcpy(a->name, "Line In");
+		break;
+	case EM28XX_AMUX_VIDEO2:
+		strcpy(a->name, "Television alt");
+		break;
+	case EM28XX_AMUX_PHONE:
+		strcpy(a->name, "Phone");
+		break;
+	case EM28XX_AMUX_MIC:
+		strcpy(a->name, "Mic");
+		break;
+	case EM28XX_AMUX_CD:
+		strcpy(a->name, "CD");
+		break;
+	case EM28XX_AMUX_AUX:
+		strcpy(a->name, "Aux");
+		break;
+	case EM28XX_AMUX_PCM_OUT:
+		strcpy(a->name, "PCM");
+		break;
+	default:
+		return -EINVAL;
+	}
 
+	a->index = dev->ctl_ainput;
 	a->capability = V4L2_AUDCAP_STEREO;
-	a->index = index;
 
 	return 0;
 }
@@ -951,9 +970,8 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
 	struct em28xx_fh   *fh  = priv;
 	struct em28xx      *dev = fh->dev;
 
-	if (a->index != dev->ctl_ainput)
-		return -EINVAL;
-
+	dev->ctl_ainput = INPUT(a->index)->amux;
+	dev->ctl_aoutput = INPUT(a->index)->aout;
 	return 0;
 }
 
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 4fde52bd7e97b63189072da48934b03b51d57468..89e13c599f8dde45dc84fbcf9ce30ee31c5a0d5c 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -295,10 +295,19 @@ enum em28xx_amux {
 	EM28XX_AMUX_PCM_OUT,
 };
 
+enum em28xx_aout {
+	EM28XX_AOUT_MASTER = 0,	/* should be the default */
+	EM28XX_AOUT_LINE,
+	EM28XX_AOUT_MONO,
+	EM28XX_AOUT_LFE,
+	EM28XX_AOUT_SURR,
+};
+
 struct em28xx_input {
 	enum enum28xx_itype type;
 	unsigned int vmux;
 	enum em28xx_amux amux;
+	enum em28xx_aout aout;
 };
 
 #define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
@@ -450,6 +459,7 @@ struct em28xx {
 	int ctl_freq;		/* selected frequency */
 	unsigned int ctl_input;	/* selected input */
 	unsigned int ctl_ainput;/* selected audio input */
+	unsigned int ctl_aoutput;/* selected audio output */
 	int mute;
 	int volume;
 	/* frame properties */