aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb-frontends/rtl2832.c
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2013-12-03 16:19:39 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-03-05 13:39:17 -0500
commit0ea872d43e9a68d1b540f382d139e9d99d9f8301 (patch)
tree6fa487c49a7af13b6afee2b140beadd0fd0506c7 /drivers/media/dvb-frontends/rtl2832.c
parent8823f0288d345a26b27502c71f8ca3d05b4ac013 (diff)
[media] rtl2832: add muxed I2C adapter for demod itself
There was a deadlock between master I2C adapter and muxed I2C adapter. Implement two I2C muxed I2C adapters and leave master alone, just only for offering I2C adapter for these mux adapters. Reported-by: Luis Alves <ljalvs@gmail.com> Reported-by: Benjamin Larsson <benjamin@southpole.se> Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/dvb-frontends/rtl2832.c')
-rw-r--r--drivers/media/dvb-frontends/rtl2832.c71
1 files changed, 57 insertions, 14 deletions
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index dc46cf0841e0..c0366a8640c7 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -180,7 +180,7 @@ static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
180 buf[0] = reg; 180 buf[0] = reg;
181 memcpy(&buf[1], val, len); 181 memcpy(&buf[1], val, len);
182 182
183 ret = i2c_transfer(priv->i2c, msg, 1); 183 ret = i2c_transfer(priv->i2c_adapter, msg, 1);
184 if (ret == 1) { 184 if (ret == 1) {
185 ret = 0; 185 ret = 0;
186 } else { 186 } else {
@@ -210,7 +210,7 @@ static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
210 } 210 }
211 }; 211 };
212 212
213 ret = i2c_transfer(priv->i2c, msg, 2); 213 ret = i2c_transfer(priv->i2c_adapter, msg, 2);
214 if (ret == 2) { 214 if (ret == 2) {
215 ret = 0; 215 ret = 0;
216 } else { 216 } else {
@@ -891,26 +891,61 @@ static void rtl2832_release(struct dvb_frontend *fe)
891 struct rtl2832_priv *priv = fe->demodulator_priv; 891 struct rtl2832_priv *priv = fe->demodulator_priv;
892 892
893 dev_dbg(&priv->i2c->dev, "%s:\n", __func__); 893 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
894 i2c_del_mux_adapter(priv->i2c_adapter_tuner);
894 i2c_del_mux_adapter(priv->i2c_adapter); 895 i2c_del_mux_adapter(priv->i2c_adapter);
895 kfree(priv); 896 kfree(priv);
896} 897}
897 898
898static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) 899static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
899{ 900{
900 struct rtl2832_priv *priv = mux_priv; 901 struct rtl2832_priv *priv = mux_priv;
901 return rtl2832_i2c_gate_ctrl(&priv->fe, 1); 902 int ret;
902} 903 u8 buf[2];
904 struct i2c_msg msg[1] = {
905 {
906 .addr = priv->cfg.i2c_addr,
907 .flags = 0,
908 .len = sizeof(buf),
909 .buf = buf,
910 }
911 };
903 912
904static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) 913 if (priv->i2c_gate_state == chan_id)
905{ 914 return 0;
906 struct rtl2832_priv *priv = mux_priv; 915
907 return rtl2832_i2c_gate_ctrl(&priv->fe, 0); 916 /* select reg bank 1 */
917 buf[0] = 0x00;
918 buf[1] = 0x01;
919
920 ret = i2c_transfer(adap, msg, 1);
921 if (ret != 1)
922 goto err;
923
924 priv->page = 1;
925
926 /* open or close I2C repeater gate */
927 buf[0] = 0x01;
928 if (chan_id == 1)
929 buf[1] = 0x18; /* open */
930 else
931 buf[1] = 0x10; /* close */
932
933 ret = i2c_transfer(adap, msg, 1);
934 if (ret != 1)
935 goto err;
936
937 priv->i2c_gate_state = chan_id;
938
939 return 0;
940err:
941 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
942 return -EREMOTEIO;
908} 943}
909 944
910struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe) 945struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
911{ 946{
912 struct rtl2832_priv *priv = fe->demodulator_priv; 947 struct rtl2832_priv *priv = fe->demodulator_priv;
913 return priv->i2c_adapter; 948 return priv->i2c_adapter_tuner;
914} 949}
915EXPORT_SYMBOL(rtl2832_get_i2c_adapter); 950EXPORT_SYMBOL(rtl2832_get_i2c_adapter);
916 951
@@ -933,15 +968,21 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
933 priv->tuner = cfg->tuner; 968 priv->tuner = cfg->tuner;
934 memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config)); 969 memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
935 970
971 /* create muxed i2c adapter for demod itself */
972 priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
973 rtl2832_select, NULL);
974 if (priv->i2c_adapter == NULL)
975 goto err;
976
936 /* check if the demod is there */ 977 /* check if the demod is there */
937 ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp); 978 ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
938 if (ret) 979 if (ret)
939 goto err; 980 goto err;
940 981
941 /* create muxed i2c adapter */ 982 /* create muxed i2c adapter for demod tuner bus */
942 priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0, 983 priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv,
943 rtl2832_select, rtl2832_deselect); 984 0, 1, 0, rtl2832_select, NULL);
944 if (priv->i2c_adapter == NULL) 985 if (priv->i2c_adapter_tuner == NULL)
945 goto err; 986 goto err;
946 987
947 /* create dvb_frontend */ 988 /* create dvb_frontend */
@@ -954,6 +995,8 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
954 return &priv->fe; 995 return &priv->fe;
955err: 996err:
956 dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); 997 dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
998 if (priv && priv->i2c_adapter)
999 i2c_del_mux_adapter(priv->i2c_adapter);
957 kfree(priv); 1000 kfree(priv);
958 return NULL; 1001 return NULL;
959} 1002}