summaryrefslogtreecommitdiff
path: root/drivers/media/video/em28xx/em28xx-dvb.c
diff options
context:
space:
mode:
authorEddi De Pieri <eddi@depieri.net>2011-11-19 11:37:14 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-11-20 11:24:20 -0200
commit82e7dbbd4a16274b0a7038978734fc11bbf9f4b6 (patch)
tree34ff839a8bb00c75d319c9b0f0216fb7c766783b /drivers/media/video/em28xx/em28xx-dvb.c
parent35621030c0bd5cb4f1a345cf2b4a97e290bc244a (diff)
[media] em28xx: initial support for HAUPPAUGE HVR-930C again
With this patch I try again to add initial support for HVR930C. Tested only DVB-T, since in Italy Analog service is stopped. Actually "scan -a0 -f1", find only about 50 channel while 400 should be available. [mchehab@redhat.com: Tested with DVB-C and fixed a few whitespace issues] Tested-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Eddi De Pieri <eddi@depieri.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-dvb.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c136
1 files changed, 135 insertions, 1 deletions
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index cef7a2d409cb..d19939b04ec3 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -316,6 +316,14 @@ struct drxk_config terratec_h5_drxk = {
.microcode_name = "dvb-usb-terratec-h5-drxk.fw",
};
+struct drxk_config hauppauge_930c_drxk = {
+ .adr = 0x29,
+ .single_master = 1,
+ .no_i2c_bridge = 1,
+ .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
+ .chunk_size = 56,
+};
+
static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct em28xx_dvb *dvb = fe->sec_priv;
@@ -334,6 +342,90 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
return status;
}
+static void hauppauge_hvr930c_init(struct em28xx *dev)
+{
+ int i;
+
+ struct em28xx_reg_seq hauppauge_hvr930c_init[] = {
+ {EM2874_R80_GPIO, 0xff, 0xff, 101}, //11111111
+// {0xd , 0xff, 0xff, 101}, //11111111
+ {EM2874_R80_GPIO, 0xfb, 0xff, 50}, //11111011 init bit 3
+ {EM2874_R80_GPIO, 0xff, 0xff, 184}, //11111111
+ { -1, -1, -1, -1},
+ };
+ struct em28xx_reg_seq hauppauge_hvr930c_end[] = {
+ {EM2874_R80_GPIO, 0xef, 0xff, 1}, //11101111
+ {EM2874_R80_GPIO, 0xaf, 0xff, 101}, //10101111 init bit 7
+ {EM2874_R80_GPIO, 0xef, 0xff, 118}, //11101111
+
+
+//per il tuner?
+ {EM2874_R80_GPIO, 0xef, 0xff, 1}, //11101111
+ {EM2874_R80_GPIO, 0xcf, 0xff, 11}, //11001111 init bit 6
+ {EM2874_R80_GPIO, 0xef, 0xff, 64}, //11101111
+
+ {EM2874_R80_GPIO, 0xcf, 0xff, 101}, //11001111 init bit 6
+ {EM2874_R80_GPIO, 0xef, 0xff, 101}, //11101111
+ {EM2874_R80_GPIO, 0xcf, 0xff, 11}, //11001111 init bit 6
+ {EM2874_R80_GPIO, 0xef, 0xff, 101}, //11101111
+
+// {EM2874_R80_GPIO, 0x6f, 0xff, 10}, //01101111
+// {EM2874_R80_GPIO, 0x6d, 0xff, 100}, //01101101 init bit 2
+ { -1, -1, -1, -1},
+ };
+
+ struct em28xx_reg_seq hauppauge_hvr930c_end2[] = {
+// {EM2874_R80_GPIO, 0x6f, 0xff, 124}, //01101111
+// {EM2874_R80_GPIO, 0x4f, 0xff, 11}, //01001111 init bit 6
+// {EM2874_R80_GPIO, 0x6f, 0xff, 1}, //01101111
+// {EM2874_R80_GPIO, 0x4f, 0xff, 10}, //01001111 init bit 6
+// {EM2874_R80_GPIO, 0x6f, 0xff, 100}, //01101111
+// {0xd , 0x42, 0xff, 101}, //11111111
+ { -1, -1, -1, -1},
+ };
+ struct {
+ unsigned char r[4];
+ int len;
+ } regs[] = {
+ {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+ {{ 0x01, 0x02 }, 2},
+ {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+ {{ 0x01, 0x00 }, 2},
+ {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+ {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+ {{ 0x01, 0x00 }, 2},
+ {{ 0x01, 0x00, 0x73, 0xaf }, 4},
+ {{ 0x04, 0x00 }, 2},
+ {{ 0x00, 0x04 }, 2},
+ {{ 0x00, 0x04, 0x00, 0x0a }, 4},
+ {{ 0x04, 0x14 }, 2},
+ {{ 0x04, 0x14, 0x00, 0x00 }, 4},
+ };
+
+ em28xx_gpio_set(dev, hauppauge_hvr930c_init);
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+ msleep(10);
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+ msleep(10);
+
+ dev->i2c_client.addr = 0x82 >> 1;
+
+ for (i = 0; i < ARRAY_SIZE(regs); i++)
+ i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+ em28xx_gpio_set(dev, hauppauge_hvr930c_end);
+
+ msleep(100);
+
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+ msleep(30);
+
+ em28xx_gpio_set(dev, hauppauge_hvr930c_end2);
+ msleep(10);
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
+ msleep(10);
+
+}
+
static void terratec_h5_init(struct em28xx *dev)
{
int i;
@@ -788,6 +880,47 @@ static int em28xx_dvb_init(struct em28xx *dev)
mfe_shared = 1;
}
break;
+ case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
+ hauppauge_hvr930c_init(dev);
+
+ dvb->dont_attach_fe1 = 1;
+
+ dvb->fe[0] = dvb_attach(drxk_attach, &hauppauge_930c_drxk, &dev->i2c_adap, &dvb->fe[1]);
+ if (!dvb->fe[0]) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ /* FIXME: do we need a pll semaphore? */
+ dvb->fe[0]->sec_priv = dvb;
+ sema_init(&dvb->pll_mutex, 1);
+ dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
+ dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+ dvb->fe[1]->id = 1;
+
+ /* Attach xc5000 */
+ struct xc5000_config cfg;
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.i2c_address = 0x61;
+ //cfg.if_khz = 4570; //FIXME
+ cfg.if_khz = 4000; //FIXME (should be ok) read from i2c traffic
+
+ if (dvb->fe[0]->ops.i2c_gate_ctrl)
+ dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
+ if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap, &cfg)) {
+ result = -EINVAL;
+ goto out_free;
+ }
+
+ if (dvb->fe[0]->ops.i2c_gate_ctrl)
+ dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
+
+ /* Hack - needed by drxk/tda18271c2dd */
+ dvb->fe[1]->tuner_priv = dvb->fe[0]->tuner_priv;
+ memcpy(&dvb->fe[1]->ops.tuner_ops,
+ &dvb->fe[0]->ops.tuner_ops,
+ sizeof(dvb->fe[0]->ops.tuner_ops));
+
+ break;
case EM2884_BOARD_TERRATEC_H5:
terratec_h5_init(dev);
@@ -798,7 +931,6 @@ static int em28xx_dvb_init(struct em28xx *dev)
result = -EINVAL;
goto out_free;
}
-
/* FIXME: do we need a pll semaphore? */
dvb->fe[0]->sec_priv = dvb;
sema_init(&dvb->pll_mutex, 1);
@@ -845,6 +977,8 @@ static int em28xx_dvb_init(struct em28xx *dev)
}
/* define general-purpose callback pointer */
dvb->fe[0]->callback = em28xx_tuner_callback;
+ if (dvb->fe[1])
+ dvb->fe[1]->callback = em28xx_tuner_callback;
/* register everything */
result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);