diff options
author | Luis Alves <ljalvs@gmail.com> | 2013-10-03 07:33:47 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-10-03 06:40:12 -0400 |
commit | d10e8280c4c2513d3e7350c27d8e6f0fa03a5f71 (patch) | |
tree | 71416e674be5b5c3490fc77885effd07f8dc776c /drivers/media/dvb-frontends | |
parent | e6001482d49ffe1554f55c47a4ed903e86fe69a5 (diff) |
[media] cx24117: use hybrid_tuner_request/release_state to share state between multiple instances
...and remove the frontend pointer param from cx24117_attach()
Signed-off-by: Luis Alves <ljalvs@gmail.com>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/dvb-frontends')
-rw-r--r-- | drivers/media/dvb-frontends/cx24117.c | 72 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24117.h | 4 |
2 files changed, 53 insertions, 23 deletions
diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c index 3b6391352918..908730959e38 100644 --- a/drivers/media/dvb-frontends/cx24117.c +++ b/drivers/media/dvb-frontends/cx24117.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/firmware.h> | 32 | #include <linux/firmware.h> |
33 | 33 | ||
34 | #include "tuner-i2c.h" | ||
34 | #include "dvb_frontend.h" | 35 | #include "dvb_frontend.h" |
35 | #include "cx24117.h" | 36 | #include "cx24117.h" |
36 | 37 | ||
@@ -145,6 +146,9 @@ enum cmds { | |||
145 | CMD_TUNERSLEEP = 0x36, | 146 | CMD_TUNERSLEEP = 0x36, |
146 | }; | 147 | }; |
147 | 148 | ||
149 | static LIST_HEAD(hybrid_tuner_instance_list); | ||
150 | static DEFINE_MUTEX(cx24117_list_mutex); | ||
151 | |||
148 | /* The Demod/Tuner can't easily provide these, we cache them */ | 152 | /* The Demod/Tuner can't easily provide these, we cache them */ |
149 | struct cx24117_tuning { | 153 | struct cx24117_tuning { |
150 | u32 frequency; | 154 | u32 frequency; |
@@ -176,9 +180,11 @@ struct cx24117_priv { | |||
176 | u8 demod_address; | 180 | u8 demod_address; |
177 | struct i2c_adapter *i2c; | 181 | struct i2c_adapter *i2c; |
178 | u8 skip_fw_load; | 182 | u8 skip_fw_load; |
179 | |||
180 | struct mutex fe_lock; | 183 | struct mutex fe_lock; |
181 | atomic_t fe_nr; | 184 | |
185 | /* Used for sharing this struct between demods */ | ||
186 | struct tuner_i2c_props i2c_props; | ||
187 | struct list_head hybrid_tuner_instance_list; | ||
182 | }; | 188 | }; |
183 | 189 | ||
184 | /* one per each fe */ | 190 | /* one per each fe */ |
@@ -536,7 +542,7 @@ static int cx24117_load_firmware(struct dvb_frontend *fe, | |||
536 | dev_dbg(&state->priv->i2c->dev, | 542 | dev_dbg(&state->priv->i2c->dev, |
537 | "%s() demod%d FW is %zu bytes (%02x %02x .. %02x %02x)\n", | 543 | "%s() demod%d FW is %zu bytes (%02x %02x .. %02x %02x)\n", |
538 | __func__, state->demod, fw->size, fw->data[0], fw->data[1], | 544 | __func__, state->demod, fw->size, fw->data[0], fw->data[1], |
539 | fw->data[fw->size-2], fw->data[fw->size-1]); | 545 | fw->data[fw->size - 2], fw->data[fw->size - 1]); |
540 | 546 | ||
541 | cx24117_writereg(state, 0xea, 0x00); | 547 | cx24117_writereg(state, 0xea, 0x00); |
542 | cx24117_writereg(state, 0xea, 0x01); | 548 | cx24117_writereg(state, 0xea, 0x01); |
@@ -1116,37 +1122,64 @@ static int cx24117_diseqc_send_burst(struct dvb_frontend *fe, | |||
1116 | return 0; | 1122 | return 0; |
1117 | } | 1123 | } |
1118 | 1124 | ||
1125 | static int cx24117_get_priv(struct cx24117_priv **priv, | ||
1126 | struct i2c_adapter *i2c, u8 client_address) | ||
1127 | { | ||
1128 | int ret; | ||
1129 | |||
1130 | mutex_lock(&cx24117_list_mutex); | ||
1131 | ret = hybrid_tuner_request_state(struct cx24117_priv, (*priv), | ||
1132 | hybrid_tuner_instance_list, i2c, client_address, "cx24117"); | ||
1133 | mutex_unlock(&cx24117_list_mutex); | ||
1134 | |||
1135 | return ret; | ||
1136 | } | ||
1137 | |||
1138 | static void cx24117_release_priv(struct cx24117_priv *priv) | ||
1139 | { | ||
1140 | mutex_lock(&cx24117_list_mutex); | ||
1141 | if (priv != NULL) | ||
1142 | hybrid_tuner_release_state(priv); | ||
1143 | mutex_unlock(&cx24117_list_mutex); | ||
1144 | } | ||
1145 | |||
1119 | static void cx24117_release(struct dvb_frontend *fe) | 1146 | static void cx24117_release(struct dvb_frontend *fe) |
1120 | { | 1147 | { |
1121 | struct cx24117_state *state = fe->demodulator_priv; | 1148 | struct cx24117_state *state = fe->demodulator_priv; |
1122 | dev_dbg(&state->priv->i2c->dev, "%s demod%d\n", | 1149 | dev_dbg(&state->priv->i2c->dev, "%s demod%d\n", |
1123 | __func__, state->demod); | 1150 | __func__, state->demod); |
1124 | if (!atomic_dec_and_test(&state->priv->fe_nr)) | 1151 | cx24117_release_priv(state->priv); |
1125 | kfree(state->priv); | ||
1126 | kfree(state); | 1152 | kfree(state); |
1127 | } | 1153 | } |
1128 | 1154 | ||
1129 | static struct dvb_frontend_ops cx24117_ops; | 1155 | static struct dvb_frontend_ops cx24117_ops; |
1130 | 1156 | ||
1131 | struct dvb_frontend *cx24117_attach(const struct cx24117_config *config, | 1157 | struct dvb_frontend *cx24117_attach(const struct cx24117_config *config, |
1132 | struct i2c_adapter *i2c, struct dvb_frontend *fe) | 1158 | struct i2c_adapter *i2c) |
1133 | { | 1159 | { |
1134 | struct cx24117_state *state = NULL; | 1160 | struct cx24117_state *state = NULL; |
1135 | struct cx24117_priv *priv = NULL; | 1161 | struct cx24117_priv *priv = NULL; |
1136 | int demod = 0; | 1162 | int demod = 0; |
1137 | 1163 | ||
1138 | /* first frontend attaching */ | 1164 | /* get the common data struct for both demods */ |
1139 | /* allocate shared priv struct */ | 1165 | demod = cx24117_get_priv(&priv, i2c, config->demod_address); |
1140 | if (fe == NULL) { | 1166 | |
1141 | priv = kzalloc(sizeof(struct cx24117_priv), GFP_KERNEL); | 1167 | switch (demod) { |
1142 | if (priv == NULL) | 1168 | case 0: |
1143 | goto error1; | 1169 | dev_err(&state->priv->i2c->dev, |
1170 | "%s: Error attaching frontend %d\n", | ||
1171 | KBUILD_MODNAME, demod); | ||
1172 | goto error1; | ||
1173 | break; | ||
1174 | case 1: | ||
1175 | /* new priv instance */ | ||
1144 | priv->i2c = i2c; | 1176 | priv->i2c = i2c; |
1145 | priv->demod_address = config->demod_address; | 1177 | priv->demod_address = config->demod_address; |
1146 | mutex_init(&priv->fe_lock); | 1178 | mutex_init(&priv->fe_lock); |
1147 | } else { | 1179 | break; |
1148 | demod = 1; | 1180 | default: |
1149 | priv = ((struct cx24117_state *) fe->demodulator_priv)->priv; | 1181 | /* existing priv instance */ |
1182 | break; | ||
1150 | } | 1183 | } |
1151 | 1184 | ||
1152 | /* allocate memory for the internal state */ | 1185 | /* allocate memory for the internal state */ |
@@ -1154,7 +1187,7 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config, | |||
1154 | if (state == NULL) | 1187 | if (state == NULL) |
1155 | goto error2; | 1188 | goto error2; |
1156 | 1189 | ||
1157 | state->demod = demod; | 1190 | state->demod = demod - 1; |
1158 | state->priv = priv; | 1191 | state->priv = priv; |
1159 | 1192 | ||
1160 | /* test i2c bus for ack */ | 1193 | /* test i2c bus for ack */ |
@@ -1163,12 +1196,9 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config, | |||
1163 | goto error3; | 1196 | goto error3; |
1164 | } | 1197 | } |
1165 | 1198 | ||
1166 | /* nr of frontends using the module */ | ||
1167 | atomic_inc(&priv->fe_nr); | ||
1168 | |||
1169 | dev_info(&state->priv->i2c->dev, | 1199 | dev_info(&state->priv->i2c->dev, |
1170 | "%s: Attaching frontend %d\n", | 1200 | "%s: Attaching frontend %d\n", |
1171 | KBUILD_MODNAME, demod); | 1201 | KBUILD_MODNAME, state->demod); |
1172 | 1202 | ||
1173 | /* create dvb_frontend */ | 1203 | /* create dvb_frontend */ |
1174 | memcpy(&state->frontend.ops, &cx24117_ops, | 1204 | memcpy(&state->frontend.ops, &cx24117_ops, |
@@ -1179,7 +1209,7 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config, | |||
1179 | error3: | 1209 | error3: |
1180 | kfree(state); | 1210 | kfree(state); |
1181 | error2: | 1211 | error2: |
1182 | kfree(priv); | 1212 | cx24117_release_priv(priv); |
1183 | error1: | 1213 | error1: |
1184 | return NULL; | 1214 | return NULL; |
1185 | } | 1215 | } |
diff --git a/drivers/media/dvb-frontends/cx24117.h b/drivers/media/dvb-frontends/cx24117.h index 5bc8f1119275..4e59e9574fa7 100644 --- a/drivers/media/dvb-frontends/cx24117.h +++ b/drivers/media/dvb-frontends/cx24117.h | |||
@@ -33,11 +33,11 @@ struct cx24117_config { | |||
33 | #if IS_ENABLED(CONFIG_DVB_CX24117) | 33 | #if IS_ENABLED(CONFIG_DVB_CX24117) |
34 | extern struct dvb_frontend *cx24117_attach( | 34 | extern struct dvb_frontend *cx24117_attach( |
35 | const struct cx24117_config *config, | 35 | const struct cx24117_config *config, |
36 | struct i2c_adapter *i2c, struct dvb_frontend *fe); | 36 | struct i2c_adapter *i2c); |
37 | #else | 37 | #else |
38 | static inline struct dvb_frontend *cx24117_attach( | 38 | static inline struct dvb_frontend *cx24117_attach( |
39 | const struct cx24117_config *config, | 39 | const struct cx24117_config *config, |
40 | struct i2c_adapter *i2c, struct dvb_frontend *fe) | 40 | struct i2c_adapter *i2c) |
41 | { | 41 | { |
42 | dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); | 42 | dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); |
43 | return NULL; | 43 | return NULL; |