[media] stk1160: Remove stk1160-mixer and setup internal AC97 codec automatically
authorMarcel Hasler <mahasler@gmail.com>
Thu, 15 Dec 2016 22:17:26 +0000 (20:17 -0200)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Fri, 3 Feb 2017 13:25:51 +0000 (11:25 -0200)
Exposing all the channels of the device's internal AC97 codec to
userspace is unnecessary and confusing. Instead the driver should setup
the codec with proper values. This patch removes the mixer and sets up
the codec using optimal values, i.e. the same values set by the Windows
driver. This also makes the device work out-of-the-box, without the need
for the user to reconfigure the device every time it's plugged in.

Signed-off-by: Marcel Hasler <mahasler@gmail.com>
Acked-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/usb/stk1160/Kconfig
drivers/media/usb/stk1160/Makefile
drivers/media/usb/stk1160/stk1160-ac97.c
drivers/media/usb/stk1160/stk1160-core.c
drivers/media/usb/stk1160/stk1160.h

index 95584c15dc5aa7813444a3d51408142b8032b357..22dff4f3b921c56dbdae5facc486d91c3c8492e6 100644 (file)
@@ -8,17 +8,9 @@ config VIDEO_STK1160_COMMON
          To compile this driver as a module, choose M here: the
          module will be called stk1160
 
-config VIDEO_STK1160_AC97
-       bool "STK1160 AC97 codec support"
-       depends on VIDEO_STK1160_COMMON && SND
-
-       ---help---
-         Enables AC97 codec support for stk1160 driver.
-
 config VIDEO_STK1160
        tristate
-       depends on (!VIDEO_STK1160_AC97 || (SND='n') || SND) && VIDEO_STK1160_COMMON
+       depends on VIDEO_STK1160_COMMON
        default y
        select VIDEOBUF2_VMALLOC
        select VIDEO_SAA711X
-       select SND_AC97_CODEC if SND
index dfe3e90ff392fb3e0e7b17f30dc3bf58180e408e..42d05463b353d5b2b1e3f66dc88bbaa2b00ab0a8 100644 (file)
@@ -1,10 +1,8 @@
-obj-stk1160-ac97-$(CONFIG_VIDEO_STK1160_AC97) := stk1160-ac97.o
-
 stk1160-y :=   stk1160-core.o \
                stk1160-v4l.o \
                stk1160-video.o \
                stk1160-i2c.o \
-               $(obj-stk1160-ac97-y)
+               stk1160-ac97.o
 
 obj-$(CONFIG_VIDEO_STK1160) += stk1160.o
 
index 2dd308f9541f469b719adf7d53f01901f4525b3e..502fc8ee9a975980b2cbbdfae6db4538ac74c2f1 100644 (file)
@@ -4,6 +4,9 @@
  * Copyright (C) 2012 Ezequiel Garcia
  * <elezegarcia--a.t--gmail.com>
  *
+ * Copyright (C) 2016 Marcel Hasler
+ * <mahasler--a.t--gmail.com>
+ *
  * Based on Easycap driver by R.M. Thomas
  *     Copyright (C) 2010 R.M. Thomas
  *     <rmthomas--a.t--sciolus.org>
  *
  */
 
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/ac97_codec.h>
-
 #include "stk1160.h"
 #include "stk1160-reg.h"
 
-static struct snd_ac97 *stk1160_ac97;
-
-static void stk1160_write_ac97(struct snd_ac97 *ac97, u16 reg, u16 value)
+static void stk1160_write_ac97(struct stk1160 *dev, u16 reg, u16 value)
 {
-       struct stk1160 *dev = ac97->private_data;
-
        /* Set codec register address */
        stk1160_write_reg(dev, STK1160_AC97_ADDR, reg);
 
@@ -48,9 +42,9 @@ static void stk1160_write_ac97(struct snd_ac97 *ac97, u16 reg, u16 value)
        stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c);
 }
 
-static u16 stk1160_read_ac97(struct snd_ac97 *ac97, u16 reg)
+#ifdef DEBUG
+static u16 stk1160_read_ac97(struct stk1160 *dev, u16 reg)
 {
-       struct stk1160 *dev = ac97->private_data;
        u8 vall = 0;
        u8 valh = 0;
 
@@ -70,81 +64,53 @@ static u16 stk1160_read_ac97(struct snd_ac97 *ac97, u16 reg)
        return (valh << 8) | vall;
 }
 
-static void stk1160_reset_ac97(struct snd_ac97 *ac97)
+void stk1160_ac97_dump_regs(struct stk1160 *dev)
 {
-       struct stk1160 *dev = ac97->private_data;
-       /* Two-step reset AC97 interface and hardware codec */
-       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94);
-       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x88);
+       u16 value;
 
-       /* Set 16-bit audio data and choose L&R channel*/
-       stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01);
-}
+       value = stk1160_read_ac97(dev, 0x12); /* CD volume */
+       stk1160_dbg("0x12 == 0x%04x", value);
 
-static struct snd_ac97_bus_ops stk1160_ac97_ops = {
-       .read   = stk1160_read_ac97,
-       .write  = stk1160_write_ac97,
-       .reset  = stk1160_reset_ac97,
-};
+       value = stk1160_read_ac97(dev, 0x10); /* Line-in volume */
+       stk1160_dbg("0x10 == 0x%04x", value);
 
-int stk1160_ac97_register(struct stk1160 *dev)
-{
-       struct snd_card *card = NULL;
-       struct snd_ac97_bus *ac97_bus;
-       struct snd_ac97_template ac97_template;
-       int rc;
+       value = stk1160_read_ac97(dev, 0x0e); /* MIC volume (mono) */
+       stk1160_dbg("0x0e == 0x%04x", value);
 
-       /*
-        * Just want a card to access ac96 controls,
-        * the actual capture interface will be handled by snd-usb-audio
-        */
-       rc = snd_card_new(dev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-                         THIS_MODULE, 0, &card);
-       if (rc < 0)
-               return rc;
-
-       /* TODO: I'm not sure where should I get these names :-( */
-       snprintf(card->shortname, sizeof(card->shortname),
-                "stk1160-mixer");
-       snprintf(card->longname, sizeof(card->longname),
-                "stk1160 ac97 codec mixer control");
-       strlcpy(card->driver, dev->dev->driver->name, sizeof(card->driver));
-
-       rc = snd_ac97_bus(card, 0, &stk1160_ac97_ops, NULL, &ac97_bus);
-       if (rc)
-               goto err;
-
-       /* We must set private_data before calling snd_ac97_mixer */
-       memset(&ac97_template, 0, sizeof(ac97_template));
-       ac97_template.private_data = dev;
-       ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
-       rc = snd_ac97_mixer(ac97_bus, &ac97_template, &stk1160_ac97);
-       if (rc)
-               goto err;
-
-       dev->snd_card = card;
-       rc = snd_card_register(card);
-       if (rc)
-               goto err;
-
-       return 0;
-
-err:
-       dev->snd_card = NULL;
-       snd_card_free(card);
-       return rc;
+       value = stk1160_read_ac97(dev, 0x16); /* Aux volume */
+       stk1160_dbg("0x16 == 0x%04x", value);
+
+       value = stk1160_read_ac97(dev, 0x1a); /* Record select */
+       stk1160_dbg("0x1a == 0x%04x", value);
+
+       value = stk1160_read_ac97(dev, 0x02); /* Master volume */
+       stk1160_dbg("0x02 == 0x%04x", value);
+
+       value = stk1160_read_ac97(dev, 0x1c); /* Record gain */
+       stk1160_dbg("0x1c == 0x%04x", value);
 }
+#endif
 
-int stk1160_ac97_unregister(struct stk1160 *dev)
+void stk1160_ac97_setup(struct stk1160 *dev)
 {
-       struct snd_card *card = dev->snd_card;
-
-       /*
-        * We need to check usb_device,
-        * because ac97 release attempts to communicate with codec
-        */
-       if (card && dev->udev)
-               snd_card_free(card);
+       /* Two-step reset AC97 interface and hardware codec */
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94);
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c);
 
-       return 0;
+       /* Set 16-bit audio data and choose L&R channel*/
+       stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01);
+       stk1160_write_reg(dev, STK1160_AC97CTL_1 + 3, 0x00);
+
+       /* Setup channels */
+       stk1160_write_ac97(dev, 0x12, 0x8808); /* CD volume */
+       stk1160_write_ac97(dev, 0x10, 0x0808); /* Line-in volume */
+       stk1160_write_ac97(dev, 0x0e, 0x0008); /* MIC volume (mono) */
+       stk1160_write_ac97(dev, 0x16, 0x0808); /* Aux volume */
+       stk1160_write_ac97(dev, 0x1a, 0x0404); /* Record select */
+       stk1160_write_ac97(dev, 0x02, 0x0000); /* Master volume */
+       stk1160_write_ac97(dev, 0x1c, 0x0808); /* Record gain */
+
+#ifdef DEBUG
+       stk1160_ac97_dump_regs(dev);
+#endif
 }
index bc029478065a0f9c029dd024fca1ef4c0b6788fe..f3c9b8a2c6e8d4fd6cfccee84a39097c4b794f66 100644 (file)
@@ -373,7 +373,7 @@ static int stk1160_probe(struct usb_interface *interface,
        /* select default input */
        stk1160_select_input(dev);
 
-       stk1160_ac97_register(dev);
+       stk1160_ac97_setup(dev);
 
        rc = stk1160_video_register(dev);
        if (rc < 0)
@@ -411,9 +411,6 @@ static void stk1160_disconnect(struct usb_interface *interface)
        /* Here is the only place where isoc get released */
        stk1160_uninit_isoc(dev);
 
-       /* ac97 unregister needs to be done before usb_device is cleared */
-       stk1160_ac97_unregister(dev);
-
        stk1160_clear_queue(dev);
 
        video_unregister_device(&dev->vdev);
index 1ed1cc43cdb268106fee45fdcb61b63fefe02ae0..e85e12eedcd29f55124a29eec51c8ceea728c5f2 100644 (file)
@@ -197,11 +197,4 @@ int stk1160_read_reg_req_len(struct stk1160 *dev, u8 req, u16 reg,
 void stk1160_select_input(struct stk1160 *dev);
 
 /* Provided by stk1160-ac97.c */
-#ifdef CONFIG_VIDEO_STK1160_AC97
-int stk1160_ac97_register(struct stk1160 *dev);
-int stk1160_ac97_unregister(struct stk1160 *dev);
-#else
-static inline int stk1160_ac97_register(struct stk1160 *dev) { return 0; }
-static inline int stk1160_ac97_unregister(struct stk1160 *dev) { return 0; }
-#endif
-
+void stk1160_ac97_setup(struct stk1160 *dev);