From f1add5b5ec2a6efaa0f5648d0dc2c56d83a3ecf8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:47 -0300 Subject: [PATCH] V4L/DVB (11070): au0828: Rework the way the analog video binding occurs 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 for providing information on the various ways different Hauppauge boards can be configured. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 45 +++++++++++++++++++++-- drivers/media/video/au0828/au0828-core.c | 11 +++--- drivers/media/video/au0828/au0828-dvb.c | 2 +- drivers/media/video/au0828/au0828-video.c | 40 ++++++++------------ drivers/media/video/au0828/au0828.h | 7 +++- 5 files changed, 70 insertions(+), 35 deletions(-) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 8b7ad43ed57c..e10b1b9221e0 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -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: diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 680e88f61397..0bc85b7d67d4 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -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; } diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index a882cf546d0a..14baffc22192 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -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, diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index e34464f81f36..064de23a3ce1 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -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); diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 3b8e3e913475..2f48ec2136bf 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -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 */