aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2011-08-04 19:27:19 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-02-28 16:42:23 -0500
commit0485a7089b8d6c11fe2db1123a1ed39a2676592f (patch)
tree261da4a1082977e6ea3fdcfd668995764cb3fd98 /drivers/media/dvb
parent34ec2933485b6b047245ccbb7fa2b3513bed46af (diff)
[media] rtl2830: correct I2C functionality
Implement I2C functionality according to real RTL2830 demod. Do not send register page in first byte of each I2C write, instead use logic to set page using own write when needed. Page register is physical register 0 as generally used. Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/frontends/rtl2830.c67
-rw-r--r--drivers/media/dvb/frontends/rtl2830_priv.h2
2 files changed, 52 insertions, 17 deletions
diff --git a/drivers/media/dvb/frontends/rtl2830.c b/drivers/media/dvb/frontends/rtl2830.c
index 37a9fa29874e..f036701c12ee 100644
--- a/drivers/media/dvb/frontends/rtl2830.c
+++ b/drivers/media/dvb/frontends/rtl2830.c
@@ -31,45 +31,43 @@ int rtl2830_debug;
31module_param_named(debug, rtl2830_debug, int, 0644); 31module_param_named(debug, rtl2830_debug, int, 0644);
32MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 32MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
33 33
34/* write multiple registers */ 34/* write multiple hardware registers */
35static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) 35static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
36{ 36{
37 int ret; 37 int ret;
38 u8 buf[2+len]; 38 u8 buf[1+len];
39 struct i2c_msg msg[1] = { 39 struct i2c_msg msg[1] = {
40 { 40 {
41 .addr = priv->cfg.i2c_addr, 41 .addr = priv->cfg.i2c_addr,
42 .flags = 0, 42 .flags = 0,
43 .len = sizeof(buf), 43 .len = 1+len,
44 .buf = buf, 44 .buf = buf,
45 } 45 }
46 }; 46 };
47 47
48 buf[0] = (reg >> 8) & 0xff; 48 buf[0] = reg;
49 buf[1] = (reg >> 0) & 0xff; 49 memcpy(&buf[1], val, len);
50 memcpy(&buf[2], val, len);
51 50
52 ret = i2c_transfer(priv->i2c, msg, 1); 51 ret = i2c_transfer(priv->i2c, msg, 1);
53 if (ret == 1) { 52 if (ret == 1) {
54 ret = 0; 53 ret = 0;
55 } else { 54 } else {
56 warn("i2c wr failed=%d reg=%04x len=%d", ret, reg, len); 55 warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
57 ret = -EREMOTEIO; 56 ret = -EREMOTEIO;
58 } 57 }
59 return ret; 58 return ret;
60} 59}
61 60
62/* read multiple registers */ 61/* read multiple hardware registers */
63static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) 62static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
64{ 63{
65 int ret; 64 int ret;
66 u8 buf[2];
67 struct i2c_msg msg[2] = { 65 struct i2c_msg msg[2] = {
68 { 66 {
69 .addr = priv->cfg.i2c_addr, 67 .addr = priv->cfg.i2c_addr,
70 .flags = 0, 68 .flags = 0,
71 .len = sizeof(buf), 69 .len = 1,
72 .buf = buf, 70 .buf = &reg,
73 }, { 71 }, {
74 .addr = priv->cfg.i2c_addr, 72 .addr = priv->cfg.i2c_addr,
75 .flags = I2C_M_RD, 73 .flags = I2C_M_RD,
@@ -78,19 +76,54 @@ static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
78 } 76 }
79 }; 77 };
80 78
81 buf[0] = (reg >> 8) & 0xff;
82 buf[1] = (reg >> 0) & 0xff;
83
84 ret = i2c_transfer(priv->i2c, msg, 2); 79 ret = i2c_transfer(priv->i2c, msg, 2);
85 if (ret == 2) { 80 if (ret == 2) {
86 ret = 0; 81 ret = 0;
87 } else { 82 } else {
88 warn("i2c rd failed=%d reg=%04x len=%d", ret, reg, len); 83 warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
89 ret = -EREMOTEIO; 84 ret = -EREMOTEIO;
90 } 85 }
91 return ret; 86 return ret;
92} 87}
93 88
89/* write multiple registers */
90static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
91{
92 int ret;
93 u8 reg2 = (reg >> 0) & 0xff;
94 u8 page = (reg >> 8) & 0xff;
95
96 /* switch bank if needed */
97 if (page != priv->page) {
98 ret = rtl2830_wr(priv, 0x00, &page, 1);
99 if (ret)
100 return ret;
101
102 priv->page = page;
103 }
104
105 return rtl2830_wr(priv, reg2, val, len);
106}
107
108/* read multiple registers */
109static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
110{
111 int ret;
112 u8 reg2 = (reg >> 0) & 0xff;
113 u8 page = (reg >> 8) & 0xff;
114
115 /* switch bank if needed */
116 if (page != priv->page) {
117 ret = rtl2830_wr(priv, 0x00, &page, 1);
118 if (ret)
119 return ret;
120
121 priv->page = page;
122 }
123
124 return rtl2830_rd(priv, reg2, val, len);
125}
126
94#if 0 /* currently not used */ 127#if 0 /* currently not used */
95/* write single register */ 128/* write single register */
96static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val) 129static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val)
diff --git a/drivers/media/dvb/frontends/rtl2830_priv.h b/drivers/media/dvb/frontends/rtl2830_priv.h
index 2bc662ee87a0..49de01dd5e83 100644
--- a/drivers/media/dvb/frontends/rtl2830_priv.h
+++ b/drivers/media/dvb/frontends/rtl2830_priv.h
@@ -42,6 +42,8 @@ struct rtl2830_priv {
42 struct dvb_frontend fe; 42 struct dvb_frontend fe;
43 struct rtl2830_config cfg; 43 struct rtl2830_config cfg;
44 struct i2c_adapter tuner_i2c_adapter; 44 struct i2c_adapter tuner_i2c_adapter;
45
46 u8 page; /* active register page */
45}; 47};
46 48
47struct rtl2830_reg_val_mask { 49struct rtl2830_reg_val_mask {