Skip to content

Commit

Permalink
V4L/DVB (7753): saa7134: fix tuner setup
Browse files Browse the repository at this point in the history
Tuner setup were happening during i2c attach callback. This means that it would
happen on two conditions:

        1) if tuner module weren't load, it will happen at request_module("tuner");

        2) if tuner is not compiled as a module, or it is already loaded
           (for example, on setups with more than one tuner), it will happen
           when saa7134 registers I2C bus.

Due to that, if tuner were loaded, tuner setup will happen _before_ reading
the proper values at tuner eeprom. Since set_addr refuses to change for a tuner
that were previously defined (except if the tuner_addr is set), this were
making eeprom tuner detection useless.

This patch removes tuner type setup from saa7134-i2c, moving it to the proper
place, after taking eeprom into account.

Reviewed-by: Hermann Pitton <hermann-pitton@arcor.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
  • Loading branch information
Mauro Carvalho Chehab committed Apr 29, 2008
1 parent 397be5c commit c117d05
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 143 deletions.
218 changes: 117 additions & 101 deletions drivers/media/video/saa7134/saa7134-cards.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ static char name_svideo[] = "S-Video";
/* ------------------------------------------------------------------ */
/* board config info */

/* If radio_type !=UNSET, radio_addr should be specified
*/

struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_UNKNOWN] = {
.name = "UNKNOWN/GENERIC",
Expand Down Expand Up @@ -3087,7 +3090,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_type = TUNER_PHILIPS_TD1316, /* untested */
.radio_type = TUNER_TEA5767, /* untested */
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.radio_addr = 0x60,
.tda9887_conf = TDA9887_PRESENT,
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
Expand Down Expand Up @@ -5577,20 +5580,87 @@ int saa7134_board_init1(struct saa7134_dev *dev)
return 0;
}

static void saa7134_tuner_setup(struct saa7134_dev *dev)
{
struct tuner_setup tun_setup;
unsigned int mode_mask = T_RADIO |
T_ANALOG_TV |
T_DIGITAL_TV;

memset(&tun_setup, 0, sizeof(tun_setup));
tun_setup.tuner_callback = saa7134_tuner_callback;

if (saa7134_boards[dev->board].radio_type != UNSET) {
tun_setup.type = saa7134_boards[dev->board].radio_type;
tun_setup.addr = saa7134_boards[dev->board].radio_addr;

tun_setup.mode_mask = T_RADIO;

saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
mode_mask &= ~T_RADIO;
}

if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type != UNSET)) {
tun_setup.type = dev->tuner_type;
tun_setup.addr = dev->tuner_addr;
tun_setup.config = saa7134_boards[dev->board].tuner_config;
tun_setup.tuner_callback = saa7134_tuner_callback;

tun_setup.mode_mask = mode_mask;

saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
}

if (dev->tda9887_conf) {
struct v4l2_priv_tun_config tda9887_cfg;

tda9887_cfg.tuner = TUNER_TDA9887;
tda9887_cfg.priv = &dev->tda9887_conf;

saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
&tda9887_cfg);
}

if (dev->tuner_type == TUNER_XC2028) {
struct v4l2_priv_tun_config xc2028_cfg;
struct xc2028_ctrl ctl;

memset(&xc2028_cfg, 0, sizeof(ctl));
memset(&ctl, 0, sizeof(ctl));

ctl.fname = XC2028_DEFAULT_FIRMWARE;
ctl.max_len = 64;

switch (dev->board) {
case SAA7134_BOARD_AVERMEDIA_A16D:
ctl.demod = XC3028_FE_ZARLINK456;
break;
default:
ctl.demod = XC3028_FE_OREN538;
ctl.mts = 1;
}

xc2028_cfg.tuner = TUNER_XC2028;
xc2028_cfg.priv = &ctl;

saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
}
}

/* stuff which needs working i2c */
int saa7134_board_init2(struct saa7134_dev *dev)
{
unsigned char buf;
int board;
struct tuner_setup tun_setup;
tun_setup.config = 0;
tun_setup.tuner_callback = saa7134_tuner_callback;

dev->tuner_type = saa7134_boards[dev->board].tuner_type;
dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;

switch (dev->board) {
case SAA7134_BOARD_BMK_MPEX_NOTUNER:
case SAA7134_BOARD_BMK_MPEX_TUNER:
dev->i2c_client.addr = 0x60;
board = (i2c_master_recv(&dev->i2c_client,&buf,0) < 0)
board = (i2c_master_recv(&dev->i2c_client, &buf, 0) < 0)
? SAA7134_BOARD_BMK_MPEX_NOTUNER
: SAA7134_BOARD_BMK_MPEX_TUNER;
if (board == dev->board)
Expand All @@ -5600,21 +5670,9 @@ int saa7134_board_init2(struct saa7134_dev *dev)
saa7134_boards[dev->board].name);
dev->tuner_type = saa7134_boards[dev->board].tuner_type;

if (TUNER_ABSENT != dev->tuner_type) {
tun_setup.mode_mask = T_RADIO |
T_ANALOG_TV |
T_DIGITAL_TV;
tun_setup.type = dev->tuner_type;
tun_setup.addr = ADDR_UNSET;
tun_setup.tuner_callback = saa7134_tuner_callback;

saa7134_i2c_call_clients(dev,
TUNER_SET_TYPE_ADDR,
&tun_setup);
}
break;
case SAA7134_BOARD_MD7134:
{
{
u8 subaddr;
u8 data[3];
int ret, tuner_t;
Expand Down Expand Up @@ -5667,30 +5725,8 @@ int saa7134_board_init2(struct saa7134_dev *dev)
}

printk(KERN_INFO "%s Tuner type is %d\n", dev->name, dev->tuner_type);
if (dev->tuner_type == TUNER_PHILIPS_FMD1216ME_MK3) {
struct v4l2_priv_tun_config tda9887_cfg;

tda9887_cfg.tuner = TUNER_TDA9887;
tda9887_cfg.priv = &dev->tda9887_conf;

dev->tda9887_conf = TDA9887_PRESENT |
TDA9887_PORT1_ACTIVE |
TDA9887_PORT2_ACTIVE;

saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
&tda9887_cfg);
}

tun_setup.mode_mask = T_RADIO |
T_ANALOG_TV |
T_DIGITAL_TV;
tun_setup.type = dev->tuner_type;
tun_setup.addr = ADDR_UNSET;

saa7134_i2c_call_clients(dev,
TUNER_SET_TYPE_ADDR, &tun_setup);
}
break;
}
case SAA7134_BOARD_PHILIPS_EUROPA:
if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) {
/* Reconfigure board as Snake reference design */
Expand All @@ -5702,43 +5738,43 @@ int saa7134_board_init2(struct saa7134_dev *dev)
}
case SAA7134_BOARD_VIDEOMATE_DVBT_300:
case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
{

/* The Philips EUROPA based hybrid boards have the tuner connected through
* the channel decoder. We have to make it transparent to find it
*/
{
u8 data[] = { 0x07, 0x02};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);

tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
tun_setup.type = dev->tuner_type;
tun_setup.addr = dev->tuner_addr;

saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
}
break;
}
case SAA7134_BOARD_PHILIPS_TIGER:
case SAA7134_BOARD_PHILIPS_TIGER_S:
{
{
u8 data[] = { 0x3c, 0x33, 0x60};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
if(dev->autodetected && (dev->eedata[0x49] == 0x50)) {
if (dev->autodetected && (dev->eedata[0x49] == 0x50)) {
dev->board = SAA7134_BOARD_PHILIPS_TIGER_S;
printk(KERN_INFO "%s: Reconfigured board as %s\n",
dev->name, saa7134_boards[dev->board].name);
}
if(dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
tun_setup.type = TUNER_PHILIPS_TDA8290;
tun_setup.addr = 0x4b;
tun_setup.config = 2;
if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
dev->tuner_type = TUNER_PHILIPS_TDA8290;

saa7134_tuner_setup(dev);

saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
data[2] = 0x68;
i2c_transfer(&dev->i2c_adap, &msg, 1);

/* Tuner setup is handled before I2C transfer.
Due to that, there's no need to do it later
*/
return 0;
}
i2c_transfer(&dev->i2c_adap, &msg, 1);
}
break;
}
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
hauppauge_eeprom(dev, dev->eedata+0x80);
/* break intentionally omitted */
Expand All @@ -5751,52 +5787,55 @@ int saa7134_board_init2(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_SUPER_007:
case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
case SAA7134_BOARD_CREATIX_CTX953:
{
/* this is a hybrid board, initialize to analog mode
* and configure firmware eeprom address
*/
{
u8 data[] = { 0x3c, 0x33, 0x60};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);
}
break;
}
case SAA7134_BOARD_FLYDVB_TRIO:
{
{
u8 data[] = { 0x3c, 0x33, 0x62};
struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);
}
break;
}
case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
{
/* initialize analog mode */
{
u8 data[] = { 0x3c, 0x33, 0x6a};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);
}
break;
}
case SAA7134_BOARD_CINERGY_HT_PCMCIA:
case SAA7134_BOARD_CINERGY_HT_PCI:
{
/* initialize analog mode */
{
u8 data[] = { 0x3c, 0x33, 0x68};
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
i2c_transfer(&dev->i2c_adap, &msg, 1);
}
break;
}
case SAA7134_BOARD_KWORLD_ATSC110:
{
/* enable tuner */
int i;
static const u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 };
dev->i2c_client.addr = 0x0a;
for (i = 0; i < 5; i++)
if (2 != i2c_master_send(&dev->i2c_client,&buffer[i*2],2))
printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n",
dev->name, i);
}
{
/* enable tuner */
int i;
static const u8 buffer [] = { 0x10, 0x12, 0x13, 0x04, 0x16,
0x00, 0x14, 0x04, 0x17, 0x00 };
dev->i2c_client.addr = 0x0a;
for (i = 0; i < 5; i++)
if (2 != i2c_master_send(&dev->i2c_client,
&buffer[i*2], 2))
printk(KERN_WARNING
"%s: Unable to enable tuner(%i).\n",
dev->name, i);
break;
}
case SAA7134_BOARD_VIDEOMATE_DVBT_200:
case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
/* The T200 and the T200A share the same pci id. Consequently,
Expand All @@ -5821,7 +5860,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
{
{
struct v4l2_priv_tun_config tea5767_cfg;
struct tea5767_ctrl ctl;

Expand All @@ -5832,34 +5871,11 @@ int saa7134_board_init2(struct saa7134_dev *dev)
tea5767_cfg.tuner = TUNER_TEA5767;
tea5767_cfg.priv = &ctl;
saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg);
}
break;
}
} /* switch() */

if (dev->tuner_type == TUNER_XC2028) {
struct v4l2_priv_tun_config xc2028_cfg;
struct xc2028_ctrl ctl;

memset(&xc2028_cfg, 0, sizeof(ctl));
memset(&ctl, 0, sizeof(ctl));

ctl.fname = XC2028_DEFAULT_FIRMWARE;
ctl.max_len = 64;

switch (dev->board) {
case SAA7134_BOARD_AVERMEDIA_A16D:
ctl.demod = XC3028_FE_ZARLINK456;
break;
default:
ctl.demod = XC3028_FE_OREN538;
ctl.mts = 1;
}

xc2028_cfg.tuner = TUNER_XC2028;
xc2028_cfg.priv = &ctl;

saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
}
saa7134_tuner_setup(dev);

return 0;
}
Loading

0 comments on commit c117d05

Please sign in to comment.