V4L/DVB (11070): au0828: Rework the way the analog video binding occurs
authorDevin Heitmueller <dheitmueller@linuxtv.org>
Wed, 11 Mar 2009 06:00:47 +0000 (03:00 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:43:25 +0000 (12:43 -0300)
Rework the way boards are managed so that we can change the board description
based on the Hauppauge eeprom (modeled after cx88-cards.c).

Also, make sure that we don't load the analog stack if there are no analog
inputs defined in the board profile.

Thanks to Michael Krufky <mkrufky@linuxtv.org> for providing information on
the various ways different Hauppauge boards can be configured.

Signed-off-by: Devin Heitmueller <dheitmueller@linuxtv.org>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/au0828/au0828-cards.c
drivers/media/video/au0828/au0828-core.c
drivers/media/video/au0828/au0828-dvb.c
drivers/media/video/au0828/au0828-video.c
drivers/media/video/au0828/au0828.h

index 8b7ad43ed57c1c7d2bc6f54679974d7e1fe36d06..e10b1b9221e0fed582b097fcc66f2dc08eeb6a70 100644 (file)
@@ -22,6 +22,8 @@
 #include "au0828.h"
 #include "au0828-cards.h"
 #include "au8522.h"
+#include "media/tuner.h"
+#include "media/v4l2-common.h"
 
 void hvr950q_cs5340_audio(void *priv, int enable)
 {
@@ -37,9 +39,13 @@ void hvr950q_cs5340_audio(void *priv, int enable)
 struct au0828_board au0828_boards[] = {
        [AU0828_BOARD_UNKNOWN] = {
                .name   = "Unknown board",
+               .tuner_type = UNSET,
+               .tuner_addr = ADDR_UNSET,
        },
        [AU0828_BOARD_HAUPPAUGE_HVR850] = {
                .name   = "Hauppauge HVR850",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
                .input = {
                        {
                                .type = AU0828_VMUX_TELEVISION,
@@ -62,6 +68,8 @@ struct au0828_board au0828_boards[] = {
        },
        [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
                .name   = "Hauppauge HVR950Q",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
                .input = {
                        {
                                .type = AU0828_VMUX_TELEVISION,
@@ -84,12 +92,18 @@ struct au0828_board au0828_boards[] = {
        },
        [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
                .name   = "Hauppauge HVR950Q rev xxF8",
+               .tuner_type = UNSET,
+               .tuner_addr = ADDR_UNSET,
        },
        [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
                .name   = "DViCO FusionHDTV USB",
+               .tuner_type = UNSET,
+               .tuner_addr = ADDR_UNSET,
        },
        [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
                .name = "Hauppauge Woodbury",
+               .tuner_type = UNSET,
+               .tuner_addr = ADDR_UNSET,
        },
 };
 
@@ -102,7 +116,7 @@ int au0828_tuner_callback(void *priv, int component, int command, int arg)
 
        dprintk(1, "%s()\n", __func__);
 
-       switch (dev->board) {
+       switch (dev->boardnr) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
@@ -131,6 +145,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
        struct tveeprom tv;
 
        tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
+       dev->board.tuner_type = tv.tuner_type;
 
        /* Make sure we support the board model */
        switch (tv.model) {
@@ -157,15 +172,20 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
 void au0828_card_setup(struct au0828_dev *dev)
 {
        static u8 eeprom[256];
+       struct tuner_setup tun_setup;
+       unsigned int mode_mask = T_ANALOG_TV |
+                                T_DIGITAL_TV;
 
        dprintk(1, "%s()\n", __func__);
 
+       memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board));
+
        if (dev->i2c_rc == 0) {
                dev->i2c_client.addr = 0xa0 >> 1;
                tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
        }
 
-       switch (dev->board) {
+       switch (dev->boardnr) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
@@ -174,6 +194,25 @@ void au0828_card_setup(struct au0828_dev *dev)
                        hauppauge_eeprom(dev, eeprom+0xa0);
                break;
        }
+
+       if (dev->board.input != NULL) {
+               /* Load the analog demodulator driver (note this would need to
+                  be abstracted out if we ever need to support a different
+                  demod) */
+               request_module("au8522");
+       }
+
+       /* Setup tuners */
+       if (dev->board.tuner_type != TUNER_ABSENT) {
+               /* Load the tuner module, which does the attach */
+               request_module("tuner");
+
+               tun_setup.mode_mask      = mode_mask;
+               tun_setup.type           = dev->board.tuner_type;
+               tun_setup.addr           = dev->board.tuner_addr;
+               tun_setup.tuner_callback = au0828_tuner_callback;
+               au0828_call_i2c_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+       }
 }
 
 /*
@@ -185,7 +224,7 @@ void au0828_gpio_setup(struct au0828_dev *dev)
 {
        dprintk(1, "%s()\n", __func__);
 
-       switch (dev->board) {
+       switch (dev->boardnr) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
index 680e88f613972089c8d1473cba7907b123835bdc..0bc85b7d67d4eaa42c2851160ab08ccf32739343 100644 (file)
@@ -146,7 +146,8 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
        /* Digital TV */
        au0828_dvb_unregister(dev);
 
-       au0828_analog_unregister(dev);
+       if (dev->board.input != NULL)
+               au0828_analog_unregister(dev);
 
        /* I2C */
        au0828_i2c_unregister(dev);
@@ -189,7 +190,7 @@ static int au0828_usb_probe(struct usb_interface *interface,
        mutex_init(&dev->mutex);
        mutex_init(&dev->dvb.lock);
        dev->usbdev = usbdev;
-       dev->board = id->driver_info;
+       dev->boardnr = id->driver_info;
 
        usb_set_intfdata(interface, dev);
 
@@ -230,14 +231,14 @@ static int au0828_usb_probe(struct usb_interface *interface,
        au0828_card_setup(dev);
 
        /* Analog TV */
-       au0828_analog_register(dev);
+       if (dev->board.input != NULL)
+               au0828_analog_register(dev);
 
        /* Digital TV */
        au0828_dvb_register(dev);
 
        printk(KERN_INFO "Registered device AU0828 [%s]\n",
-               au0828_boards[dev->board].name == NULL ? "Unset" :
-               au0828_boards[dev->board].name);
+               dev->board.name == NULL ? "Unset" : dev->board.name);
 
        return 0;
 }
index a882cf546d0aa5a0e0c1ff798a0b0b7f109d3c9e..14baffc221920d87febcffe22a65caebe062ffd6 100644 (file)
@@ -378,7 +378,7 @@ int au0828_dvb_register(struct au0828_dev *dev)
        dprintk(1, "%s()\n", __func__);
 
        /* init frontend */
-       switch (dev->board) {
+       switch (dev->boardnr) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
                dvb->frontend = dvb_attach(au8522_attach,
index e34464f81f3649a2d9845a63402ec30857ff7509..064de23a3ce16bf1e41d311671fdb2eae2d41ed1 100644 (file)
@@ -1013,7 +1013,7 @@ static int vidioc_querycap(struct file *file, void  *priv,
 
        memset(cap, 0, sizeof(*cap));
        strlcpy(cap->driver, "au0828", sizeof(cap->driver));
-       strlcpy(cap->card, au0828_boards[dev->board].name, sizeof(cap->card));
+       strlcpy(cap->card, dev->board.name, sizeof(cap->card));
        strlcpy(cap->bus_info, dev->usbdev->dev.bus_id, sizeof(cap->bus_info));
 
        cap->version = AU0828_VERSION_CODE;
@@ -1127,14 +1127,14 @@ static int vidioc_enum_input(struct file *file, void *priv,
 
        if(tmp > AU0828_MAX_INPUT)
                return -EINVAL;
-       if(AUVI_INPUT(tmp)->type == 0)
+       if(AUVI_INPUT(tmp).type == 0)
                return -EINVAL;
 
        memset(input, 0, sizeof(*input));
        input->index = tmp;
-       strcpy(input->name, inames[AUVI_INPUT(tmp)->type]);
-       if((AUVI_INPUT(tmp)->type == AU0828_VMUX_TELEVISION) ||
-          (AUVI_INPUT(tmp)->type == AU0828_VMUX_CABLE))
+       strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
+       if((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
+          (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
                input->type |= V4L2_INPUT_TYPE_TUNER;
        else
                input->type |= V4L2_INPUT_TYPE_CAMERA;
@@ -1163,11 +1163,11 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
                index);
        if(index >= AU0828_MAX_INPUT)
                return -EINVAL;
-       if(AUVI_INPUT(index)->type == 0)
+       if(AUVI_INPUT(index).type == 0)
                return -EINVAL;
        dev->ctrl_input = index;
 
-       switch(AUVI_INPUT(index)->type) {
+       switch(AUVI_INPUT(index).type) {
        case AU0828_VMUX_SVIDEO:
        {
                dev->input_type = AU0828_VMUX_SVIDEO;
@@ -1187,13 +1187,13 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
                ;
        }
 
-       route.input = AUVI_INPUT(index)->vmux;
+       route.input = AUVI_INPUT(index).vmux;
        route.output = 0;
        au0828_call_i2c_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
 
        for (i = 0; i < AU0828_MAX_INPUT; i++) {
                int enable = 0;
-               if (AUVI_INPUT(i)->audio_setup == NULL) {
+               if (AUVI_INPUT(i).audio_setup == NULL) {
                        continue;
                }
 
@@ -1202,18 +1202,18 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
                else
                        enable = 0;
                if (enable) {
-                       (AUVI_INPUT(i)->audio_setup)(dev, enable);
+                       (AUVI_INPUT(i).audio_setup)(dev, enable);
                } else {
                        /* Make sure we leave it turned on if some
                           other input is routed to this callback */
-                       if ((AUVI_INPUT(i)->audio_setup) !=
-                           ((AUVI_INPUT(index)->audio_setup))) {
-                               (AUVI_INPUT(i)->audio_setup)(dev, enable);
+                       if ((AUVI_INPUT(i).audio_setup) !=
+                           ((AUVI_INPUT(index).audio_setup))) {
+                               (AUVI_INPUT(i).audio_setup)(dev, enable);
                        }
                }
        }
 
-       route.input = AUVI_INPUT(index)->amux;
+       route.input = AUVI_INPUT(index).amux;
        au0828_call_i2c_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
                                &route);
        return 0;
@@ -1419,10 +1419,10 @@ static int vidioc_streamoff(struct file *file, void *priv,
        }
 
        for (i = 0; i < AU0828_MAX_INPUT; i++) {
-               if (AUVI_INPUT(i)->audio_setup == NULL) {
+               if (AUVI_INPUT(i).audio_setup == NULL) {
                        continue;
                }
-               (AUVI_INPUT(i)->audio_setup)(dev, 0);
+               (AUVI_INPUT(i).audio_setup)(dev, 0);
        }
 
        mutex_lock(&dev->lock);
@@ -1603,14 +1603,6 @@ int au0828_analog_register(struct au0828_dev *dev)
 
        dprintk(1, "au0828_analog_register called!\n");
 
-       /* Load the analog demodulator driver (note this would need to be
-          abstracted out if we ever need to support a different demod) */
-       request_module("au8522");
-
-       /* Load the tuner module, which results in i2c enumeration and
-          attachment of whatever tuner is on the bus */
-       request_module("tuner");
-
        init_waitqueue_head(&dev->open);
        spin_lock_init(&dev->slock);
        mutex_init(&dev->lock);
index 3b8e3e9134753db7aaff5fd3a4cbd914adafd158..2f48ec2136bfd421fce17eaf87e241c6bd766b16 100644 (file)
@@ -83,6 +83,8 @@ struct au0828_input {
 
 struct au0828_board {
        char *name;
+       unsigned int tuner_type;
+       unsigned char tuner_addr;
        struct au0828_input input[AU0828_MAX_INPUT];
 
 };
@@ -105,7 +107,7 @@ enum au0828_stream_state {
        STREAM_ON
 };
 
-#define AUVI_INPUT(nr) (&au0828_boards[dev->board].input[nr])
+#define AUVI_INPUT(nr) (dev->board.input[nr])
 
 /* device state */
 enum au0828_dev_state {
@@ -179,7 +181,8 @@ struct au0828_dmaqueue {
 struct au0828_dev {
        struct mutex mutex;
        struct usb_device       *usbdev;
-       int                     board;
+       int                     boardnr;
+       struct au0828_board     board;
        u8                      ctrlmsg[64];
 
        /* I2C */