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 */