diff options
author | Antti Palosaari <crope@iki.fi> | 2013-12-03 16:19:39 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-03-05 13:39:17 -0500 |
commit | 0ea872d43e9a68d1b540f382d139e9d99d9f8301 (patch) | |
tree | 6fa487c49a7af13b6afee2b140beadd0fd0506c7 /drivers/media/dvb-frontends/rtl2832.c | |
parent | 8823f0288d345a26b27502c71f8ca3d05b4ac013 (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.c | 71 |
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 | ||
898 | static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) | 899 | static 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 | ||
904 | static 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; | ||
940 | err: | ||
941 | dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); | ||
942 | return -EREMOTEIO; | ||
908 | } | 943 | } |
909 | 944 | ||
910 | struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe) | 945 | struct 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 | } |
915 | EXPORT_SYMBOL(rtl2832_get_i2c_adapter); | 950 | EXPORT_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; |
955 | err: | 996 | err: |
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 | } |