[media] au8522: build ATV/DTV demodulators as separate modules
authorMichael Krufky <mkrufky@kernellabs.com>
Fri, 27 Jan 2012 16:18:29 +0000 (13:18 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 19 Apr 2012 12:49:06 +0000 (09:49 -0300)
au8522_dig.o and au8522_decoder.o function independentantly
of each other, each for a different hardware function using
a different software subsystem api, each with its own set
of subsystem module dependencies.

Since these drivers do not depend on each other, and it is
in fact possible to build hardware designs using one function
and not the other, lets split this module into two, allowing
system integrators to enable the hardware without dragging in
undesired dependencies.

Signed-off-by: Michael Krufky <mkrufky@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/au8522_common.c [new file with mode: 0644]
drivers/media/dvb/frontends/au8522_dig.c
drivers/media/dvb/frontends/au8522_priv.h
drivers/media/video/au0828/Kconfig

index e11adb64e9e6d43004a5034c49a4d68dbdbe1531..f47983472aede1cfa34dc16810bc10293d81e875 100644 (file)
@@ -540,12 +540,26 @@ config DVB_S5H1409
          to support this frontend.
 
 config DVB_AU8522
-       tristate "Auvitek AU8522 based"
-       depends on DVB_CORE && I2C && VIDEO_V4L2
+       depends on I2C
+       tristate
+
+config DVB_AU8522_DTV
+       tristate "Auvitek AU8522 based DTV demod"
+       depends on DVB_CORE && I2C
+       select DVB_AU8522
        default m if DVB_FE_CUSTOMISE
        help
-         An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
-         to support this frontend.
+         An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
+         you want to enable DTV demodulation support for this frontend.
+
+config DVB_AU8522_V4L
+       tristate "Auvitek AU8522 based ATV demod"
+       depends on VIDEO_V4L2 && I2C
+       select DVB_AU8522
+       default m if DVB_FE_CUSTOMISE
+       help
+         An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
+         you want to enable ATV demodulation support for this frontend.
 
 config DVB_S5H1411
        tristate "Samsung S5H1411 based"
index 6ca75578ecacd639c7d0a271212e62019f1794f7..b0381dc8e1763d4abb13d12ce113b7c8bbe4ac62 100644 (file)
@@ -7,7 +7,6 @@ ccflags-y += -I$(srctree)/drivers/media/common/tuners/
 
 stb0899-objs = stb0899_drv.o stb0899_algo.o
 stv0900-objs = stv0900_core.o stv0900_sw.o
-au8522-objs = au8522_dig.o au8522_decoder.o
 drxd-objs = drxd_firm.o drxd_hard.o
 cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
 drxk-objs := drxk_hard.o
@@ -63,7 +62,9 @@ obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
 obj-$(CONFIG_DVB_TUA6100) += tua6100.o
 obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
 obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
-obj-$(CONFIG_DVB_AU8522) += au8522.o
+obj-$(CONFIG_DVB_AU8522) += au8522_common.o
+obj-$(CONFIG_DVB_AU8522_DTV) += au8522_dig.o
+obj-$(CONFIG_DVB_AU8522_V4L) += au8522_decoder.o
 obj-$(CONFIG_DVB_TDA10048) += tda10048.o
 obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
 obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
diff --git a/drivers/media/dvb/frontends/au8522_common.c b/drivers/media/dvb/frontends/au8522_common.c
new file mode 100644 (file)
index 0000000..befdff9
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+    Auvitek AU8522 QAM/8VSB demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
+    Copyright (C) 2008 Devin Heitmueller <dheitmueller@linuxtv.org>
+    Copyright (C) 2005-2008 Auvitek International, Ltd.
+    Copyright (C) 2012 Michael Krufky <mkrufky@linuxtv.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+#include "au8522_priv.h"
+
+static int debug;
+
+#define dprintk(arg...)\
+  do { if (debug)\
+        printk(arg);\
+  } while (0)
+
+/* Despite the name "hybrid_tuner", the framework works just as well for
+   hybrid demodulators as well... */
+static LIST_HEAD(hybrid_tuner_instance_list);
+static DEFINE_MUTEX(au8522_list_mutex);
+
+/* 16 bit registers, 8 bit values */
+int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
+{
+       int ret;
+       u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
+
+       struct i2c_msg msg = { .addr = state->config->demod_address,
+                              .flags = 0, .buf = buf, .len = 3 };
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+                      "ret == %i)\n", __func__, reg, data, ret);
+
+       return (ret != 1) ? -1 : 0;
+}
+EXPORT_SYMBOL(au8522_writereg);
+
+u8 au8522_readreg(struct au8522_state *state, u16 reg)
+{
+       int ret;
+       u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
+       u8 b1[] = { 0 };
+
+       struct i2c_msg msg[] = {
+               { .addr = state->config->demod_address, .flags = 0,
+                 .buf = b0, .len = 2 },
+               { .addr = state->config->demod_address, .flags = I2C_M_RD,
+                 .buf = b1, .len = 1 } };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+                      __func__, ret);
+       return b1[0];
+}
+EXPORT_SYMBOL(au8522_readreg);
+
+int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       if (state->operational_mode == AU8522_ANALOG_MODE) {
+               /* We're being asked to manage the gate even though we're
+                  not in digital mode.  This can occur if we get switched
+                  over to analog mode before the dvb_frontend kernel thread
+                  has completely shutdown */
+               return 0;
+       }
+
+       if (enable)
+               return au8522_writereg(state, 0x106, 1);
+       else
+               return au8522_writereg(state, 0x106, 0);
+}
+EXPORT_SYMBOL(au8522_i2c_gate_ctrl);
+
+/* Reset the demod hardware and reset all of the configuration registers
+   to a default state. */
+int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
+                    u8 client_address)
+{
+       int ret;
+
+       mutex_lock(&au8522_list_mutex);
+       ret = hybrid_tuner_request_state(struct au8522_state, (*state),
+                                        hybrid_tuner_instance_list,
+                                        i2c, client_address, "au8522");
+       mutex_unlock(&au8522_list_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL(au8522_get_state);
+
+void au8522_release_state(struct au8522_state *state)
+{
+       mutex_lock(&au8522_list_mutex);
+       if (state != NULL)
+               hybrid_tuner_release_state(state);
+       mutex_unlock(&au8522_list_mutex);
+}
+EXPORT_SYMBOL(au8522_release_state);
+
+int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
+{
+       struct au8522_led_config *led_config = state->config->led_cfg;
+       u8 val;
+
+       /* bail out if we can't control an LED */
+       if (!led_config || !led_config->gpio_output ||
+           !led_config->gpio_output_enable || !led_config->gpio_output_disable)
+               return 0;
+
+       val = au8522_readreg(state, 0x4000 |
+                            (led_config->gpio_output & ~0xc000));
+       if (onoff) {
+               /* enable GPIO output */
+               val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
+               val |=  (led_config->gpio_output_enable & 0xff);
+       } else {
+               /* disable GPIO output */
+               val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
+               val |=  (led_config->gpio_output_disable & 0xff);
+       }
+       return au8522_writereg(state, 0x8000 |
+                              (led_config->gpio_output & ~0xc000), val);
+}
+EXPORT_SYMBOL(au8522_led_gpio_enable);
+
+/* led = 0 | off
+ * led = 1 | signal ok
+ * led = 2 | signal strong
+ * led < 0 | only light led if leds are currently off
+ */
+int au8522_led_ctrl(struct au8522_state *state, int led)
+{
+       struct au8522_led_config *led_config = state->config->led_cfg;
+       int i, ret = 0;
+
+       /* bail out if we can't control an LED */
+       if (!led_config || !led_config->gpio_leds ||
+           !led_config->num_led_states || !led_config->led_states)
+               return 0;
+
+       if (led < 0) {
+               /* if LED is already lit, then leave it as-is */
+               if (state->led_state)
+                       return 0;
+               else
+                       led *= -1;
+       }
+
+       /* toggle LED if changing state */
+       if (state->led_state != led) {
+               u8 val;
+
+               dprintk("%s: %d\n", __func__, led);
+
+               au8522_led_gpio_enable(state, 1);
+
+               val = au8522_readreg(state, 0x4000 |
+                                    (led_config->gpio_leds & ~0xc000));
+
+               /* start with all leds off */
+               for (i = 0; i < led_config->num_led_states; i++)
+                       val &= ~led_config->led_states[i];
+
+               /* set selected LED state */
+               if (led < led_config->num_led_states)
+                       val |= led_config->led_states[led];
+               else if (led_config->num_led_states)
+                       val |=
+                       led_config->led_states[led_config->num_led_states - 1];
+
+               ret = au8522_writereg(state, 0x8000 |
+                                     (led_config->gpio_leds & ~0xc000), val);
+               if (ret < 0)
+                       return ret;
+
+               state->led_state = led;
+
+               if (led == 0)
+                       au8522_led_gpio_enable(state, 0);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(au8522_led_ctrl);
+
+int au8522_init(struct dvb_frontend *fe)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       dprintk("%s()\n", __func__);
+
+       state->operational_mode = AU8522_DIGITAL_MODE;
+
+       /* Clear out any state associated with the digital side of the
+          chip, so that when it gets powered back up it won't think
+          that it is already tuned */
+       state->current_frequency = 0;
+
+       au8522_writereg(state, 0xa4, 1 << 5);
+
+       au8522_i2c_gate_ctrl(fe, 1);
+
+       return 0;
+}
+EXPORT_SYMBOL(au8522_init);
+
+int au8522_sleep(struct dvb_frontend *fe)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       dprintk("%s()\n", __func__);
+
+       /* Only power down if the digital side is currently using the chip */
+       if (state->operational_mode == AU8522_ANALOG_MODE) {
+               /* We're not in one of the expected power modes, which means
+                  that the DVB thread is probably telling us to go to sleep
+                  even though the analog frontend has already started using
+                  the chip.  So ignore the request */
+               return 0;
+       }
+
+       /* turn off led */
+       au8522_led_ctrl(state, 0);
+
+       /* Power down the chip */
+       au8522_writereg(state, 0xa4, 1 << 5);
+
+       state->current_frequency = 0;
+
+       return 0;
+}
+EXPORT_SYMBOL(au8522_sleep);
index 25f650934c736345d9cb0879f177358042484190..5fc70d6cd04fad4e813d94c736d599d1cf22b3d3 100644 (file)
 
 static int debug;
 
-/* Despite the name "hybrid_tuner", the framework works just as well for
-   hybrid demodulators as well... */
-static LIST_HEAD(hybrid_tuner_instance_list);
-static DEFINE_MUTEX(au8522_list_mutex);
-
 #define dprintk(arg...)\
        do { if (debug)\
                printk(arg);\
        } while (0)
 
-/* 16 bit registers, 8 bit values */
-int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
-{
-       int ret;
-       u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
-
-       struct i2c_msg msg = { .addr = state->config->demod_address,
-                              .flags = 0, .buf = buf, .len = 3 };
-
-       ret = i2c_transfer(state->i2c, &msg, 1);
-
-       if (ret != 1)
-               printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
-                      "ret == %i)\n", __func__, reg, data, ret);
-
-       return (ret != 1) ? -1 : 0;
-}
-
-u8 au8522_readreg(struct au8522_state *state, u16 reg)
-{
-       int ret;
-       u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
-       u8 b1[] = { 0 };
-
-       struct i2c_msg msg[] = {
-               { .addr = state->config->demod_address, .flags = 0,
-                 .buf = b0, .len = 2 },
-               { .addr = state->config->demod_address, .flags = I2C_M_RD,
-                 .buf = b1, .len = 1 } };
-
-       ret = i2c_transfer(state->i2c, msg, 2);
-
-       if (ret != 2)
-               printk(KERN_ERR "%s: readreg error (ret == %i)\n",
-                      __func__, ret);
-       return b1[0];
-}
-
-static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-       struct au8522_state *state = fe->demodulator_priv;
-
-       dprintk("%s(%d)\n", __func__, enable);
-
-       if (state->operational_mode == AU8522_ANALOG_MODE) {
-               /* We're being asked to manage the gate even though we're
-                  not in digital mode.  This can occur if we get switched
-                  over to analog mode before the dvb_frontend kernel thread
-                  has completely shutdown */
-               return 0;
-       }
-
-       if (enable)
-               return au8522_writereg(state, 0x106, 1);
-       else
-               return au8522_writereg(state, 0x106, 0);
-}
-
 struct mse2snr_tab {
        u16 val;
        u16 data;
@@ -609,136 +546,6 @@ static int au8522_set_frontend(struct dvb_frontend *fe)
        return 0;
 }
 
-/* Reset the demod hardware and reset all of the configuration registers
-   to a default state. */
-int au8522_init(struct dvb_frontend *fe)
-{
-       struct au8522_state *state = fe->demodulator_priv;
-       dprintk("%s()\n", __func__);
-
-       state->operational_mode = AU8522_DIGITAL_MODE;
-
-       /* Clear out any state associated with the digital side of the
-          chip, so that when it gets powered back up it won't think
-          that it is already tuned */
-       state->current_frequency = 0;
-
-       au8522_writereg(state, 0xa4, 1 << 5);
-
-       au8522_i2c_gate_ctrl(fe, 1);
-
-       return 0;
-}
-
-static int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
-{
-       struct au8522_led_config *led_config = state->config->led_cfg;
-       u8 val;
-
-       /* bail out if we can't control an LED */
-       if (!led_config || !led_config->gpio_output ||
-           !led_config->gpio_output_enable || !led_config->gpio_output_disable)
-               return 0;
-
-       val = au8522_readreg(state, 0x4000 |
-                            (led_config->gpio_output & ~0xc000));
-       if (onoff) {
-               /* enable GPIO output */
-               val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
-               val |=  (led_config->gpio_output_enable & 0xff);
-       } else {
-               /* disable GPIO output */
-               val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
-               val |=  (led_config->gpio_output_disable & 0xff);
-       }
-       return au8522_writereg(state, 0x8000 |
-                              (led_config->gpio_output & ~0xc000), val);
-}
-
-/* led = 0 | off
- * led = 1 | signal ok
- * led = 2 | signal strong
- * led < 0 | only light led if leds are currently off
- */
-static int au8522_led_ctrl(struct au8522_state *state, int led)
-{
-       struct au8522_led_config *led_config = state->config->led_cfg;
-       int i, ret = 0;
-
-       /* bail out if we can't control an LED */
-       if (!led_config || !led_config->gpio_leds ||
-           !led_config->num_led_states || !led_config->led_states)
-               return 0;
-
-       if (led < 0) {
-               /* if LED is already lit, then leave it as-is */
-               if (state->led_state)
-                       return 0;
-               else
-                       led *= -1;
-       }
-
-       /* toggle LED if changing state */
-       if (state->led_state != led) {
-               u8 val;
-
-               dprintk("%s: %d\n", __func__, led);
-
-               au8522_led_gpio_enable(state, 1);
-
-               val = au8522_readreg(state, 0x4000 |
-                                    (led_config->gpio_leds & ~0xc000));
-
-               /* start with all leds off */
-               for (i = 0; i < led_config->num_led_states; i++)
-                       val &= ~led_config->led_states[i];
-
-               /* set selected LED state */
-               if (led < led_config->num_led_states)
-                       val |= led_config->led_states[led];
-               else if (led_config->num_led_states)
-                       val |=
-                       led_config->led_states[led_config->num_led_states - 1];
-
-               ret = au8522_writereg(state, 0x8000 |
-                                     (led_config->gpio_leds & ~0xc000), val);
-               if (ret < 0)
-                       return ret;
-
-               state->led_state = led;
-
-               if (led == 0)
-                       au8522_led_gpio_enable(state, 0);
-       }
-
-       return 0;
-}
-
-int au8522_sleep(struct dvb_frontend *fe)
-{
-       struct au8522_state *state = fe->demodulator_priv;
-       dprintk("%s()\n", __func__);
-
-       /* Only power down if the digital side is currently using the chip */
-       if (state->operational_mode == AU8522_ANALOG_MODE) {
-               /* We're not in one of the expected power modes, which means
-                  that the DVB thread is probably telling us to go to sleep
-                  even though the analog frontend has already started using
-                  the chip.  So ignore the request */
-               return 0;
-       }
-
-       /* turn off led */
-       au8522_led_ctrl(state, 0);
-
-       /* Power down the chip */
-       au8522_writereg(state, 0xa4, 1 << 5);
-
-       state->current_frequency = 0;
-
-       return 0;
-}
-
 static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
        struct au8522_state *state = fe->demodulator_priv;
@@ -931,28 +738,6 @@ static int au8522_get_tune_settings(struct dvb_frontend *fe,
 
 static struct dvb_frontend_ops au8522_ops;
 
-int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
-                    u8 client_address)
-{
-       int ret;
-
-       mutex_lock(&au8522_list_mutex);
-       ret = hybrid_tuner_request_state(struct au8522_state, (*state),
-                                        hybrid_tuner_instance_list,
-                                        i2c, client_address, "au8522");
-       mutex_unlock(&au8522_list_mutex);
-
-       return ret;
-}
-
-void au8522_release_state(struct au8522_state *state)
-{
-       mutex_lock(&au8522_list_mutex);
-       if (state != NULL)
-               hybrid_tuner_release_state(state);
-       mutex_unlock(&au8522_list_mutex);
-}
-
 
 static void au8522_release(struct dvb_frontend *fe)
 {
index 751e17d692a90aee5763885ee644e7f09a0dfc7c..6e4a438732b569717a8f9e89bf78e6a532ab8c36 100644 (file)
@@ -81,6 +81,8 @@ int au8522_sleep(struct dvb_frontend *fe);
 int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
                     u8 client_address);
 void au8522_release_state(struct au8522_state *state);
+int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
+int au8522_led_ctrl(struct au8522_state *state, int led);
 
 /* REGISTERS */
 #define AU8522_INPUT_CONTROL_REG081H                   0x081
index 81ba9d9d1b52c2024d1777e0ff4e730393063124..23f7fd22f0eb508ecf5a32f8c3653e3bc51d8ff8 100644 (file)
@@ -6,7 +6,8 @@ config VIDEO_AU0828
        select I2C_ALGOBIT
        select VIDEO_TVEEPROM
        select VIDEOBUF_VMALLOC
-       select DVB_AU8522 if !DVB_FE_CUSTOMISE
+       select DVB_AU8522_DTV if !DVB_FE_CUSTOMISE
+       select DVB_AU8522_V4L if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE