Skip to content

Commit

Permalink
V4L/DVB (11070): au0828: Rework the way the analog video binding occurs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Devin Heitmueller authored and Mauro Carvalho Chehab committed Mar 30, 2009
1 parent 4ff5ed4 commit f1add5b
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 35 deletions.
45 changes: 42 additions & 3 deletions drivers/media/video/au0828/au0828-cards.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
},
};

Expand All @@ -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:
Expand Down Expand Up @@ -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) {
Expand All @@ -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:
Expand All @@ -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);
}
}

/*
Expand All @@ -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:
Expand Down
11 changes: 6 additions & 5 deletions drivers/media/video/au0828/au0828-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/video/au0828/au0828-dvb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
40 changes: 16 additions & 24 deletions drivers/media/video/au0828/au0828-video.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions drivers/media/video/au0828/au0828.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];

};
Expand All @@ -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 {
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit f1add5b

Please sign in to comment.