aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/tuners
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2015-04-14 18:52:16 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-05-18 14:45:06 -0400
commit6802fc0b8126d8e2e5e982a9772d757e61e47c72 (patch)
tree5f34b4eb4bfb282c31d0efc8ce1fdefb59d7115f /drivers/media/tuners
parent0fae1997f09796aca8ada5edc028aef587f6716c (diff)
[media] fc2580: implement I2C client bindings
Add I2C client bindings to driver. Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/tuners')
-rw-r--r--drivers/media/tuners/fc2580.c101
-rw-r--r--drivers/media/tuners/fc2580.h15
-rw-r--r--drivers/media/tuners/fc2580_priv.h4
3 files changed, 110 insertions, 10 deletions
diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
index f0c9c42867de..d01fba8df3c0 100644
--- a/drivers/media/tuners/fc2580.c
+++ b/drivers/media/tuners/fc2580.c
@@ -47,7 +47,7 @@ static int fc2580_wr_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
47 u8 buf[MAX_XFER_SIZE]; 47 u8 buf[MAX_XFER_SIZE];
48 struct i2c_msg msg[1] = { 48 struct i2c_msg msg[1] = {
49 { 49 {
50 .addr = priv->cfg->i2c_addr, 50 .addr = priv->i2c_addr,
51 .flags = 0, 51 .flags = 0,
52 .len = 1 + len, 52 .len = 1 + len,
53 .buf = buf, 53 .buf = buf,
@@ -82,12 +82,12 @@ static int fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
82 u8 buf[MAX_XFER_SIZE]; 82 u8 buf[MAX_XFER_SIZE];
83 struct i2c_msg msg[2] = { 83 struct i2c_msg msg[2] = {
84 { 84 {
85 .addr = priv->cfg->i2c_addr, 85 .addr = priv->i2c_addr,
86 .flags = 0, 86 .flags = 0,
87 .len = 1, 87 .len = 1,
88 .buf = &reg, 88 .buf = &reg,
89 }, { 89 }, {
90 .addr = priv->cfg->i2c_addr, 90 .addr = priv->i2c_addr,
91 .flags = I2C_M_RD, 91 .flags = I2C_M_RD,
92 .len = len, 92 .len = len,
93 .buf = buf, 93 .buf = buf,
@@ -182,10 +182,10 @@ static int fc2580_set_params(struct dvb_frontend *fe)
182 if (ret < 0) 182 if (ret < 0)
183 goto err; 183 goto err;
184 184
185 if (f_vco >= 2UL * 76 * priv->cfg->clock) { 185 if (f_vco >= 2UL * 76 * priv->clk) {
186 r_val = 1; 186 r_val = 1;
187 r18_val = 0x00; 187 r18_val = 0x00;
188 } else if (f_vco >= 1UL * 76 * priv->cfg->clock) { 188 } else if (f_vco >= 1UL * 76 * priv->clk) {
189 r_val = 2; 189 r_val = 2;
190 r18_val = 0x10; 190 r18_val = 0x10;
191 } else { 191 } else {
@@ -193,7 +193,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
193 r18_val = 0x20; 193 r18_val = 0x20;
194 } 194 }
195 195
196 f_ref = 2UL * priv->cfg->clock / r_val; 196 f_ref = 2UL * priv->clk / r_val;
197 n_val = div_u64_rem(f_vco, f_ref, &k_val); 197 n_val = div_u64_rem(f_vco, f_ref, &k_val);
198 k_val_reg = div_u64(1ULL * k_val * (1 << 20), f_ref); 198 k_val_reg = div_u64(1ULL * k_val * (1 << 20), f_ref);
199 199
@@ -213,7 +213,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
213 if (ret < 0) 213 if (ret < 0)
214 goto err; 214 goto err;
215 215
216 if (priv->cfg->clock >= 28000000) { 216 if (priv->clk >= 28000000) {
217 ret = fc2580_wr_reg(priv, 0x4b, 0x22); 217 ret = fc2580_wr_reg(priv, 0x4b, 0x22);
218 if (ret < 0) 218 if (ret < 0)
219 goto err; 219 goto err;
@@ -348,7 +348,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
348 if (ret < 0) 348 if (ret < 0)
349 goto err; 349 goto err;
350 350
351 ret = fc2580_wr_reg(priv, 0x37, div_u64(1ULL * priv->cfg->clock * 351 ret = fc2580_wr_reg(priv, 0x37, div_u64(1ULL * priv->clk *
352 fc2580_if_filter_lut[i].mul, 1000000000)); 352 fc2580_if_filter_lut[i].mul, 1000000000));
353 if (ret < 0) 353 if (ret < 0)
354 goto err; 354 goto err;
@@ -510,8 +510,9 @@ struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
510 goto err; 510 goto err;
511 } 511 }
512 512
513 priv->cfg = cfg; 513 priv->clk = cfg->clock;
514 priv->i2c = i2c; 514 priv->i2c = i2c;
515 priv->i2c_addr = cfg->i2c_addr;
515 516
516 /* check if the tuner is there */ 517 /* check if the tuner is there */
517 ret = fc2580_rd_reg(priv, 0x01, &chip_id); 518 ret = fc2580_rd_reg(priv, 0x01, &chip_id);
@@ -550,6 +551,88 @@ err:
550} 551}
551EXPORT_SYMBOL(fc2580_attach); 552EXPORT_SYMBOL(fc2580_attach);
552 553
554static int fc2580_probe(struct i2c_client *client,
555 const struct i2c_device_id *id)
556{
557 struct fc2580_priv *dev;
558 struct fc2580_platform_data *pdata = client->dev.platform_data;
559 struct dvb_frontend *fe = pdata->dvb_frontend;
560 int ret;
561 u8 chip_id;
562
563 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
564 if (!dev) {
565 ret = -ENOMEM;
566 goto err;
567 }
568
569 if (pdata->clk)
570 dev->clk = pdata->clk;
571 else
572 dev->clk = 16384000; /* internal clock */
573 dev->client = client;
574 dev->i2c = client->adapter;
575 dev->i2c_addr = client->addr;
576
577 /* check if the tuner is there */
578 ret = fc2580_rd_reg(dev, 0x01, &chip_id);
579 if (ret < 0)
580 goto err_kfree;
581
582 dev_dbg(&client->dev, "chip_id=%02x\n", chip_id);
583
584 switch (chip_id) {
585 case 0x56:
586 case 0x5a:
587 break;
588 default:
589 goto err_kfree;
590 }
591
592 fe->tuner_priv = dev;
593 memcpy(&fe->ops.tuner_ops, &fc2580_tuner_ops,
594 sizeof(struct dvb_tuner_ops));
595 fe->ops.tuner_ops.release = NULL;
596 i2c_set_clientdata(client, dev);
597
598 dev_info(&client->dev, "FCI FC2580 successfully identified\n");
599 return 0;
600err_kfree:
601 kfree(dev);
602err:
603 dev_dbg(&client->dev, "failed=%d\n", ret);
604 return ret;
605}
606
607static int fc2580_remove(struct i2c_client *client)
608{
609 struct fc2580_priv *dev = i2c_get_clientdata(client);
610
611 dev_dbg(&client->dev, "\n");
612
613 kfree(dev);
614 return 0;
615}
616
617static const struct i2c_device_id fc2580_id_table[] = {
618 {"fc2580", 0},
619 {}
620};
621MODULE_DEVICE_TABLE(i2c, fc2580_id_table);
622
623static struct i2c_driver fc2580_driver = {
624 .driver = {
625 .owner = THIS_MODULE,
626 .name = "fc2580",
627 .suppress_bind_attrs = true,
628 },
629 .probe = fc2580_probe,
630 .remove = fc2580_remove,
631 .id_table = fc2580_id_table,
632};
633
634module_i2c_driver(fc2580_driver);
635
553MODULE_DESCRIPTION("FCI FC2580 silicon tuner driver"); 636MODULE_DESCRIPTION("FCI FC2580 silicon tuner driver");
554MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 637MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
555MODULE_LICENSE("GPL"); 638MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/fc2580.h b/drivers/media/tuners/fc2580.h
index b1ce6770f88e..5679e44980f9 100644
--- a/drivers/media/tuners/fc2580.h
+++ b/drivers/media/tuners/fc2580.h
@@ -24,6 +24,21 @@
24#include <linux/kconfig.h> 24#include <linux/kconfig.h>
25#include "dvb_frontend.h" 25#include "dvb_frontend.h"
26 26
27/*
28 * I2C address
29 * 0x56, ...
30 */
31
32/**
33 * struct fc2580_platform_data - Platform data for the fc2580 driver
34 * @clk: Clock frequency (0 = internal clock).
35 * @dvb_frontend: DVB frontend.
36 */
37struct fc2580_platform_data {
38 u32 clk;
39 struct dvb_frontend *dvb_frontend;
40};
41
27struct fc2580_config { 42struct fc2580_config {
28 /* 43 /*
29 * I2C address 44 * I2C address
diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h
index 646c99452136..a22ffc63749f 100644
--- a/drivers/media/tuners/fc2580_priv.h
+++ b/drivers/media/tuners/fc2580_priv.h
@@ -128,8 +128,10 @@ static const struct fc2580_freq_regs fc2580_freq_regs_lut[] = {
128}; 128};
129 129
130struct fc2580_priv { 130struct fc2580_priv {
131 const struct fc2580_config *cfg; 131 u32 clk;
132 struct i2c_client *client;
132 struct i2c_adapter *i2c; 133 struct i2c_adapter *i2c;
134 u8 i2c_addr;
133}; 135};
134 136
135#endif 137#endif