Skip to content

Commit dc245a5

Browse files
palosaarimchehab
authored andcommitted
[media] ts2020: implement I2C client bindings
Implement I2C binding model. Signed-off-by: Antti Palosaari <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent abd9025 commit dc245a5

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

drivers/media/dvb-frontends/ts2020.c

+161
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define FREQ_OFFSET_LOW_SYM_RATE 3000
2727

2828
struct ts2020_priv {
29+
struct dvb_frontend *fe;
2930
/* i2c details */
3031
int i2c_address;
3132
struct i2c_adapter *i2c;
@@ -428,6 +429,7 @@ struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe,
428429
priv->clk_out = config->clk_out;
429430
priv->clk_out_div = config->clk_out_div;
430431
priv->frequency_div = config->frequency_div;
432+
priv->fe = fe;
431433
fe->tuner_priv = priv;
432434

433435
if (!priv->frequency_div)
@@ -463,6 +465,165 @@ struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe,
463465
}
464466
EXPORT_SYMBOL(ts2020_attach);
465467

468+
static int ts2020_probe(struct i2c_client *client,
469+
const struct i2c_device_id *id)
470+
{
471+
struct ts2020_config *pdata = client->dev.platform_data;
472+
struct dvb_frontend *fe = pdata->fe;
473+
struct ts2020_priv *dev;
474+
int ret;
475+
u8 u8tmp;
476+
unsigned int utmp;
477+
char *chip_str;
478+
479+
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
480+
if (!dev) {
481+
ret = -ENOMEM;
482+
goto err;
483+
}
484+
485+
dev->i2c = client->adapter;
486+
dev->i2c_address = client->addr;
487+
dev->clk_out = pdata->clk_out;
488+
dev->clk_out_div = pdata->clk_out_div;
489+
dev->frequency_div = pdata->frequency_div;
490+
dev->fe = fe;
491+
fe->tuner_priv = dev;
492+
493+
/* check if the tuner is there */
494+
ret = ts2020_readreg(fe, 0x00);
495+
if (ret < 0)
496+
goto err;
497+
utmp = ret;
498+
499+
if ((utmp & 0x03) == 0x00) {
500+
ret = ts2020_writereg(fe, 0x00, 0x01);
501+
if (ret)
502+
goto err;
503+
504+
usleep_range(2000, 50000);
505+
}
506+
507+
ret = ts2020_writereg(fe, 0x00, 0x03);
508+
if (ret)
509+
goto err;
510+
511+
usleep_range(2000, 50000);
512+
513+
ret = ts2020_readreg(fe, 0x00);
514+
if (ret < 0)
515+
goto err;
516+
utmp = ret;
517+
518+
dev_dbg(&client->dev, "chip_id=%02x\n", utmp);
519+
520+
switch (utmp) {
521+
case 0x01:
522+
case 0x41:
523+
case 0x81:
524+
dev->tuner = TS2020_M88TS2020;
525+
chip_str = "TS2020";
526+
if (!dev->frequency_div)
527+
dev->frequency_div = 1060000;
528+
break;
529+
case 0xc3:
530+
case 0x83:
531+
dev->tuner = TS2020_M88TS2022;
532+
chip_str = "TS2022";
533+
if (!dev->frequency_div)
534+
dev->frequency_div = 1103000;
535+
break;
536+
default:
537+
ret = -ENODEV;
538+
goto err;
539+
}
540+
541+
if (dev->tuner == TS2020_M88TS2022) {
542+
switch (dev->clk_out) {
543+
case TS2020_CLK_OUT_DISABLED:
544+
u8tmp = 0x60;
545+
break;
546+
case TS2020_CLK_OUT_ENABLED:
547+
u8tmp = 0x70;
548+
ret = ts2020_writereg(fe, 0x05, dev->clk_out_div);
549+
if (ret)
550+
goto err;
551+
break;
552+
case TS2020_CLK_OUT_ENABLED_XTALOUT:
553+
u8tmp = 0x6c;
554+
break;
555+
default:
556+
ret = -EINVAL;
557+
goto err;
558+
}
559+
560+
ret = ts2020_writereg(fe, 0x42, u8tmp);
561+
if (ret)
562+
goto err;
563+
564+
if (dev->loop_through)
565+
u8tmp = 0xec;
566+
else
567+
u8tmp = 0x6c;
568+
569+
ret = ts2020_writereg(fe, 0x62, u8tmp);
570+
if (ret)
571+
goto err;
572+
}
573+
574+
/* sleep */
575+
ret = ts2020_writereg(fe, 0x00, 0x00);
576+
if (ret)
577+
goto err;
578+
579+
dev_info(&client->dev,
580+
"Montage Technology %s successfully identified\n", chip_str);
581+
582+
memcpy(&fe->ops.tuner_ops, &ts2020_tuner_ops,
583+
sizeof(struct dvb_tuner_ops));
584+
fe->ops.tuner_ops.release = NULL;
585+
586+
i2c_set_clientdata(client, dev);
587+
return 0;
588+
err:
589+
dev_dbg(&client->dev, "failed=%d\n", ret);
590+
kfree(dev);
591+
return ret;
592+
}
593+
594+
static int ts2020_remove(struct i2c_client *client)
595+
{
596+
struct ts2020_priv *dev = i2c_get_clientdata(client);
597+
struct dvb_frontend *fe = dev->fe;
598+
599+
dev_dbg(&client->dev, "\n");
600+
601+
memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
602+
fe->tuner_priv = NULL;
603+
kfree(dev);
604+
605+
return 0;
606+
}
607+
608+
static const struct i2c_device_id ts2020_id_table[] = {
609+
{"ts2020", 0},
610+
{"ts2022", 0},
611+
{}
612+
};
613+
MODULE_DEVICE_TABLE(i2c, ts2020_id_table);
614+
615+
static struct i2c_driver ts2020_driver = {
616+
.driver = {
617+
.owner = THIS_MODULE,
618+
.name = "ts2020",
619+
},
620+
.probe = ts2020_probe,
621+
.remove = ts2020_remove,
622+
.id_table = ts2020_id_table,
623+
};
624+
625+
module_i2c_driver(ts2020_driver);
626+
466627
MODULE_AUTHOR("Konstantin Dimitrov <[email protected]>");
467628
MODULE_DESCRIPTION("Montage Technology TS2020 - Silicon tuner driver module");
468629
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)