Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1add5b5 authored by Devin Heitmueller's avatar Devin Heitmueller Committed by Mauro Carvalho Chehab
Browse files

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 <mkrufky@linuxtv.org> for providing information on
the various ways different Hauppauge boards can be configured.

Signed-off-by: default avatarDevin Heitmueller <dheitmueller@linuxtv.org>
Signed-off-by: default avatarMichael Krufky <mkrufky@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 4ff5ed44
Loading
Loading
Loading
Loading
+42 −3
Original line number Diff line number Diff line
@@ -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:
+6 −5
Original line number Diff line number Diff line
@@ -146,6 +146,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
	/* Digital TV */
	au0828_dvb_unregister(dev);

	if (dev->board.input != NULL)
		au0828_analog_unregister(dev);

	/* I2C */
@@ -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 */
	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;
}
+1 −1
Original line number Diff line number Diff line
@@ -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,
+16 −24
Original line number Diff line number Diff line
@@ -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);
+5 −2
Original line number Diff line number Diff line
@@ -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 */