diff options
author | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-08-12 17:50:19 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-08-21 16:25:29 -0400 |
commit | b601d9a5d668119219d1db95cbe04fdc38eaf5a4 (patch) | |
tree | e9d325a042df220c202697cd8ed01b7c5eb344cf | |
parent | d8eb070b6649c1663204300555fb740affc6cdc2 (diff) |
[media] as102: Move ancillary routines to the beggining
Avoid having function prototypes by moving some
ancillary routines to the beginning of the file.
No functional changes.
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r-- | drivers/media/usb/as102/as102_drv.c | 17 | ||||
-rw-r--r-- | drivers/media/usb/as102/as102_drv.h | 15 | ||||
-rw-r--r-- | drivers/media/usb/as102/as102_fe.c | 542 |
3 files changed, 274 insertions, 300 deletions
diff --git a/drivers/media/usb/as102/as102_drv.c b/drivers/media/usb/as102/as102_drv.c index d90a6651f03e..ff5bd2e5657a 100644 --- a/drivers/media/usb/as102/as102_drv.c +++ b/drivers/media/usb/as102/as102_drv.c | |||
@@ -216,7 +216,17 @@ int as102_dvb_register(struct as102_dev_t *as102_dev) | |||
216 | goto edmxdinit; | 216 | goto edmxdinit; |
217 | } | 217 | } |
218 | 218 | ||
219 | ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe); | 219 | /* Attach the frontend */ |
220 | as102_dev->dvb_fe = dvb_attach(as102_attach, as102_dev->name, | ||
221 | &as102_dev->bus_adap, | ||
222 | as102_dev->elna_cfg); | ||
223 | if (!as102_dev->dvb_fe) { | ||
224 | dev_err(dev, "%s: as102_attach() failed: %d", | ||
225 | __func__, ret); | ||
226 | goto efereg; | ||
227 | } | ||
228 | |||
229 | ret = dvb_register_frontend(&as102_dev->dvb_adap, as102_dev->dvb_fe); | ||
220 | if (ret < 0) { | 230 | if (ret < 0) { |
221 | dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d", | 231 | dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d", |
222 | __func__, ret); | 232 | __func__, ret); |
@@ -252,7 +262,10 @@ edmxinit: | |||
252 | void as102_dvb_unregister(struct as102_dev_t *as102_dev) | 262 | void as102_dvb_unregister(struct as102_dev_t *as102_dev) |
253 | { | 263 | { |
254 | /* unregister as102 frontend */ | 264 | /* unregister as102 frontend */ |
255 | as102_dvb_unregister_fe(&as102_dev->dvb_fe); | 265 | dvb_unregister_frontend(as102_dev->dvb_fe); |
266 | |||
267 | /* detach frontend */ | ||
268 | dvb_frontend_detach(as102_dev->dvb_fe); | ||
256 | 269 | ||
257 | /* unregister demux device */ | 270 | /* unregister demux device */ |
258 | dvb_dmxdev_release(&as102_dev->dvb_dmxdev); | 271 | dvb_dmxdev_release(&as102_dev->dvb_dmxdev); |
diff --git a/drivers/media/usb/as102/as102_drv.h b/drivers/media/usb/as102/as102_drv.h index d6e08e23b366..1e2a76d3c517 100644 --- a/drivers/media/usb/as102/as102_drv.h +++ b/drivers/media/usb/as102/as102_drv.h | |||
@@ -60,17 +60,10 @@ struct as102_dev_t { | |||
60 | uint8_t elna_cfg; | 60 | uint8_t elna_cfg; |
61 | 61 | ||
62 | struct dvb_adapter dvb_adap; | 62 | struct dvb_adapter dvb_adap; |
63 | struct dvb_frontend dvb_fe; | 63 | struct dvb_frontend *dvb_fe; |
64 | struct dvb_demux dvb_dmx; | 64 | struct dvb_demux dvb_dmx; |
65 | struct dmxdev dvb_dmxdev; | 65 | struct dmxdev dvb_dmxdev; |
66 | 66 | ||
67 | /* demodulator stats */ | ||
68 | struct as10x_demod_stats demod_stats; | ||
69 | /* signal strength */ | ||
70 | uint16_t signal_strength; | ||
71 | /* bit error rate */ | ||
72 | uint32_t ber; | ||
73 | |||
74 | /* timer handle to trig ts stream download */ | 67 | /* timer handle to trig ts stream download */ |
75 | struct timer_list timer_handle; | 68 | struct timer_list timer_handle; |
76 | 69 | ||
@@ -84,5 +77,7 @@ struct as102_dev_t { | |||
84 | int as102_dvb_register(struct as102_dev_t *dev); | 77 | int as102_dvb_register(struct as102_dev_t *dev); |
85 | void as102_dvb_unregister(struct as102_dev_t *dev); | 78 | void as102_dvb_unregister(struct as102_dev_t *dev); |
86 | 79 | ||
87 | int as102_dvb_register_fe(struct as102_dev_t *dev, struct dvb_frontend *fe); | 80 | /* FIXME: move it to a separate header */ |
88 | int as102_dvb_unregister_fe(struct dvb_frontend *dev); | 81 | struct dvb_frontend *as102_attach(const char *name, |
82 | struct as10x_bus_adapter_t *bus_adap, | ||
83 | uint8_t elna_cfg); | ||
diff --git a/drivers/media/usb/as102/as102_fe.c b/drivers/media/usb/as102/as102_fe.c index 041bb80aa4ba..7ec1c67ba119 100644 --- a/drivers/media/usb/as102/as102_fe.c +++ b/drivers/media/usb/as102/as102_fe.c | |||
@@ -17,298 +17,19 @@ | |||
17 | #include "as10x_types.h" | 17 | #include "as10x_types.h" |
18 | #include "as10x_cmd.h" | 18 | #include "as10x_cmd.h" |
19 | 19 | ||
20 | static void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *dst, | 20 | struct as102_state { |
21 | struct as10x_tps *src); | 21 | struct dvb_frontend frontend; |
22 | struct as10x_demod_stats demod_stats; | ||
23 | struct as10x_bus_adapter_t *bus_adap; | ||
22 | 24 | ||
23 | static void as102_fe_copy_tune_parameters(struct as10x_tune_args *dst, | 25 | uint8_t elna_cfg; |
24 | struct dtv_frontend_properties *src); | ||
25 | 26 | ||
26 | static int as102_fe_set_frontend(struct dvb_frontend *fe) | 27 | /* signal strength */ |
27 | { | 28 | uint16_t signal_strength; |
28 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | 29 | /* bit error rate */ |
29 | int ret = 0; | 30 | uint32_t ber; |
30 | struct as102_dev_t *dev; | ||
31 | struct as10x_tune_args tune_args = { 0 }; | ||
32 | |||
33 | dev = (struct as102_dev_t *) fe->tuner_priv; | ||
34 | if (dev == NULL) | ||
35 | return -ENODEV; | ||
36 | |||
37 | if (mutex_lock_interruptible(&dev->bus_adap.lock)) | ||
38 | return -EBUSY; | ||
39 | |||
40 | as102_fe_copy_tune_parameters(&tune_args, p); | ||
41 | |||
42 | /* send abilis command: SET_TUNE */ | ||
43 | ret = as10x_cmd_set_tune(&dev->bus_adap, &tune_args); | ||
44 | if (ret != 0) | ||
45 | dev_dbg(&dev->bus_adap.usb_dev->dev, | ||
46 | "as10x_cmd_set_tune failed. (err = %d)\n", ret); | ||
47 | |||
48 | mutex_unlock(&dev->bus_adap.lock); | ||
49 | |||
50 | return (ret < 0) ? -EINVAL : 0; | ||
51 | } | ||
52 | |||
53 | static int as102_fe_get_frontend(struct dvb_frontend *fe) | ||
54 | { | ||
55 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||
56 | int ret = 0; | ||
57 | struct as102_dev_t *dev; | ||
58 | struct as10x_tps tps = { 0 }; | ||
59 | |||
60 | dev = (struct as102_dev_t *) fe->tuner_priv; | ||
61 | if (dev == NULL) | ||
62 | return -EINVAL; | ||
63 | |||
64 | if (mutex_lock_interruptible(&dev->bus_adap.lock)) | ||
65 | return -EBUSY; | ||
66 | |||
67 | /* send abilis command: GET_TPS */ | ||
68 | ret = as10x_cmd_get_tps(&dev->bus_adap, &tps); | ||
69 | |||
70 | if (ret == 0) | ||
71 | as10x_fe_copy_tps_parameters(p, &tps); | ||
72 | |||
73 | mutex_unlock(&dev->bus_adap.lock); | ||
74 | |||
75 | return (ret < 0) ? -EINVAL : 0; | ||
76 | } | ||
77 | |||
78 | static int as102_fe_get_tune_settings(struct dvb_frontend *fe, | ||
79 | struct dvb_frontend_tune_settings *settings) { | ||
80 | |||
81 | settings->min_delay_ms = 1000; | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | |||
87 | static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
88 | { | ||
89 | int ret = 0; | ||
90 | struct as102_dev_t *dev; | ||
91 | struct as10x_tune_status tstate = { 0 }; | ||
92 | |||
93 | dev = (struct as102_dev_t *) fe->tuner_priv; | ||
94 | if (dev == NULL) | ||
95 | return -ENODEV; | ||
96 | |||
97 | if (mutex_lock_interruptible(&dev->bus_adap.lock)) | ||
98 | return -EBUSY; | ||
99 | |||
100 | /* send abilis command: GET_TUNE_STATUS */ | ||
101 | ret = as10x_cmd_get_tune_status(&dev->bus_adap, &tstate); | ||
102 | if (ret < 0) { | ||
103 | dev_dbg(&dev->bus_adap.usb_dev->dev, | ||
104 | "as10x_cmd_get_tune_status failed (err = %d)\n", | ||
105 | ret); | ||
106 | goto out; | ||
107 | } | ||
108 | |||
109 | dev->signal_strength = tstate.signal_strength; | ||
110 | dev->ber = tstate.BER; | ||
111 | |||
112 | switch (tstate.tune_state) { | ||
113 | case TUNE_STATUS_SIGNAL_DVB_OK: | ||
114 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
115 | break; | ||
116 | case TUNE_STATUS_STREAM_DETECTED: | ||
117 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC; | ||
118 | break; | ||
119 | case TUNE_STATUS_STREAM_TUNED: | ||
120 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | | ||
121 | FE_HAS_LOCK; | ||
122 | break; | ||
123 | default: | ||
124 | *status = TUNE_STATUS_NOT_TUNED; | ||
125 | } | ||
126 | |||
127 | dev_dbg(&dev->bus_adap.usb_dev->dev, | ||
128 | "tuner status: 0x%02x, strength %d, per: %d, ber: %d\n", | ||
129 | tstate.tune_state, tstate.signal_strength, | ||
130 | tstate.PER, tstate.BER); | ||
131 | |||
132 | if (*status & FE_HAS_LOCK) { | ||
133 | if (as10x_cmd_get_demod_stats(&dev->bus_adap, | ||
134 | (struct as10x_demod_stats *) &dev->demod_stats) < 0) { | ||
135 | memset(&dev->demod_stats, 0, sizeof(dev->demod_stats)); | ||
136 | dev_dbg(&dev->bus_adap.usb_dev->dev, | ||
137 | "as10x_cmd_get_demod_stats failed (probably not tuned)\n"); | ||
138 | } else { | ||
139 | dev_dbg(&dev->bus_adap.usb_dev->dev, | ||
140 | "demod status: fc: 0x%08x, bad fc: 0x%08x, bytes corrected: 0x%08x , MER: 0x%04x\n", | ||
141 | dev->demod_stats.frame_count, | ||
142 | dev->demod_stats.bad_frame_count, | ||
143 | dev->demod_stats.bytes_fixed_by_rs, | ||
144 | dev->demod_stats.mer); | ||
145 | } | ||
146 | } else { | ||
147 | memset(&dev->demod_stats, 0, sizeof(dev->demod_stats)); | ||
148 | } | ||
149 | |||
150 | out: | ||
151 | mutex_unlock(&dev->bus_adap.lock); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Note: | ||
157 | * - in AS102 SNR=MER | ||
158 | * - the SNR will be returned in linear terms, i.e. not in dB | ||
159 | * - the accuracy equals ±2dB for a SNR range from 4dB to 30dB | ||
160 | * - the accuracy is >2dB for SNR values outside this range | ||
161 | */ | ||
162 | static int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
163 | { | ||
164 | struct as102_dev_t *dev; | ||
165 | |||
166 | dev = (struct as102_dev_t *) fe->tuner_priv; | ||
167 | if (dev == NULL) | ||
168 | return -ENODEV; | ||
169 | |||
170 | *snr = dev->demod_stats.mer; | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
176 | { | ||
177 | struct as102_dev_t *dev; | ||
178 | |||
179 | dev = (struct as102_dev_t *) fe->tuner_priv; | ||
180 | if (dev == NULL) | ||
181 | return -ENODEV; | ||
182 | |||
183 | *ber = dev->ber; | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int as102_fe_read_signal_strength(struct dvb_frontend *fe, | ||
189 | u16 *strength) | ||
190 | { | ||
191 | struct as102_dev_t *dev; | ||
192 | |||
193 | dev = (struct as102_dev_t *) fe->tuner_priv; | ||
194 | if (dev == NULL) | ||
195 | return -ENODEV; | ||
196 | |||
197 | *strength = (((0xffff * 400) * dev->signal_strength + 41000) * 2); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
203 | { | ||
204 | struct as102_dev_t *dev; | ||
205 | |||
206 | dev = (struct as102_dev_t *) fe->tuner_priv; | ||
207 | if (dev == NULL) | ||
208 | return -ENODEV; | ||
209 | |||
210 | if (dev->demod_stats.has_started) | ||
211 | *ucblocks = dev->demod_stats.bad_frame_count; | ||
212 | else | ||
213 | *ucblocks = 0; | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) | ||
219 | { | ||
220 | struct as102_dev_t *dev; | ||
221 | int ret; | ||
222 | |||
223 | dev = (struct as102_dev_t *) fe->tuner_priv; | ||
224 | if (dev == NULL) | ||
225 | return -ENODEV; | ||
226 | |||
227 | if (mutex_lock_interruptible(&dev->bus_adap.lock)) | ||
228 | return -EBUSY; | ||
229 | |||
230 | if (acquire) { | ||
231 | if (elna_enable) | ||
232 | as10x_cmd_set_context(&dev->bus_adap, | ||
233 | CONTEXT_LNA, dev->elna_cfg); | ||
234 | |||
235 | ret = as10x_cmd_turn_on(&dev->bus_adap); | ||
236 | } else { | ||
237 | ret = as10x_cmd_turn_off(&dev->bus_adap); | ||
238 | } | ||
239 | |||
240 | mutex_unlock(&dev->bus_adap.lock); | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static struct dvb_frontend_ops as102_fe_ops = { | ||
246 | .delsys = { SYS_DVBT }, | ||
247 | .info = { | ||
248 | .name = "Abilis AS102 DVB-T", | ||
249 | .frequency_min = 174000000, | ||
250 | .frequency_max = 862000000, | ||
251 | .frequency_stepsize = 166667, | ||
252 | .caps = FE_CAN_INVERSION_AUTO | ||
253 | | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ||
254 | | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ||
255 | | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK | ||
256 | | FE_CAN_QAM_AUTO | ||
257 | | FE_CAN_TRANSMISSION_MODE_AUTO | ||
258 | | FE_CAN_GUARD_INTERVAL_AUTO | ||
259 | | FE_CAN_HIERARCHY_AUTO | ||
260 | | FE_CAN_RECOVER | ||
261 | | FE_CAN_MUTE_TS | ||
262 | }, | ||
263 | |||
264 | .set_frontend = as102_fe_set_frontend, | ||
265 | .get_frontend = as102_fe_get_frontend, | ||
266 | .get_tune_settings = as102_fe_get_tune_settings, | ||
267 | |||
268 | .read_status = as102_fe_read_status, | ||
269 | .read_snr = as102_fe_read_snr, | ||
270 | .read_ber = as102_fe_read_ber, | ||
271 | .read_signal_strength = as102_fe_read_signal_strength, | ||
272 | .read_ucblocks = as102_fe_read_ucblocks, | ||
273 | .ts_bus_ctrl = as102_fe_ts_bus_ctrl, | ||
274 | }; | 31 | }; |
275 | 32 | ||
276 | int as102_dvb_unregister_fe(struct dvb_frontend *fe) | ||
277 | { | ||
278 | /* unregister frontend */ | ||
279 | dvb_unregister_frontend(fe); | ||
280 | |||
281 | /* detach frontend */ | ||
282 | dvb_frontend_detach(fe); | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | int as102_dvb_register_fe(struct as102_dev_t *as102_dev, | ||
288 | struct dvb_frontend *dvb_fe) | ||
289 | { | ||
290 | int errno; | ||
291 | struct dvb_adapter *dvb_adap; | ||
292 | |||
293 | if (as102_dev == NULL) | ||
294 | return -EINVAL; | ||
295 | |||
296 | /* extract dvb_adapter */ | ||
297 | dvb_adap = &as102_dev->dvb_adap; | ||
298 | |||
299 | /* init frontend callback ops */ | ||
300 | memcpy(&dvb_fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops)); | ||
301 | strncpy(dvb_fe->ops.info.name, as102_dev->name, | ||
302 | sizeof(dvb_fe->ops.info.name)); | ||
303 | |||
304 | /* register dvb frontend */ | ||
305 | errno = dvb_register_frontend(dvb_adap, dvb_fe); | ||
306 | if (errno == 0) | ||
307 | dvb_fe->tuner_priv = as102_dev; | ||
308 | |||
309 | return errno; | ||
310 | } | ||
311 | |||
312 | static void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *fe_tps, | 33 | static void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *fe_tps, |
313 | struct as10x_tps *as10x_tps) | 34 | struct as10x_tps *as10x_tps) |
314 | { | 35 | { |
@@ -559,3 +280,248 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args, | |||
559 | as102_fe_get_code_rate(params->code_rate_HP); | 280 | as102_fe_get_code_rate(params->code_rate_HP); |
560 | } | 281 | } |
561 | } | 282 | } |
283 | |||
284 | static int as102_fe_set_frontend(struct dvb_frontend *fe) | ||
285 | { | ||
286 | struct as102_state *state = fe->demodulator_priv; | ||
287 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||
288 | int ret = 0; | ||
289 | struct as10x_tune_args tune_args = { 0 }; | ||
290 | |||
291 | if (mutex_lock_interruptible(&state->bus_adap->lock)) | ||
292 | return -EBUSY; | ||
293 | |||
294 | as102_fe_copy_tune_parameters(&tune_args, p); | ||
295 | |||
296 | /* send abilis command: SET_TUNE */ | ||
297 | ret = as10x_cmd_set_tune(state->bus_adap, &tune_args); | ||
298 | if (ret != 0) | ||
299 | dev_dbg(&state->bus_adap->usb_dev->dev, | ||
300 | "as10x_cmd_set_tune failed. (err = %d)\n", ret); | ||
301 | |||
302 | mutex_unlock(&state->bus_adap->lock); | ||
303 | |||
304 | return (ret < 0) ? -EINVAL : 0; | ||
305 | } | ||
306 | |||
307 | static int as102_fe_get_frontend(struct dvb_frontend *fe) | ||
308 | { | ||
309 | struct as102_state *state = fe->demodulator_priv; | ||
310 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||
311 | int ret = 0; | ||
312 | struct as10x_tps tps = { 0 }; | ||
313 | |||
314 | if (mutex_lock_interruptible(&state->bus_adap->lock)) | ||
315 | return -EBUSY; | ||
316 | |||
317 | /* send abilis command: GET_TPS */ | ||
318 | ret = as10x_cmd_get_tps(state->bus_adap, &tps); | ||
319 | |||
320 | if (ret == 0) | ||
321 | as10x_fe_copy_tps_parameters(p, &tps); | ||
322 | |||
323 | mutex_unlock(&state->bus_adap->lock); | ||
324 | |||
325 | return (ret < 0) ? -EINVAL : 0; | ||
326 | } | ||
327 | |||
328 | static int as102_fe_get_tune_settings(struct dvb_frontend *fe, | ||
329 | struct dvb_frontend_tune_settings *settings) { | ||
330 | |||
331 | settings->min_delay_ms = 1000; | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | |||
337 | static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
338 | { | ||
339 | int ret = 0; | ||
340 | struct as102_state *state = fe->demodulator_priv; | ||
341 | struct as10x_tune_status tstate = { 0 }; | ||
342 | |||
343 | if (mutex_lock_interruptible(&state->bus_adap->lock)) | ||
344 | return -EBUSY; | ||
345 | |||
346 | /* send abilis command: GET_TUNE_STATUS */ | ||
347 | ret = as10x_cmd_get_tune_status(state->bus_adap, &tstate); | ||
348 | if (ret < 0) { | ||
349 | dev_dbg(&state->bus_adap->usb_dev->dev, | ||
350 | "as10x_cmd_get_tune_status failed (err = %d)\n", | ||
351 | ret); | ||
352 | goto out; | ||
353 | } | ||
354 | |||
355 | state->signal_strength = tstate.signal_strength; | ||
356 | state->ber = tstate.BER; | ||
357 | |||
358 | switch (tstate.tune_state) { | ||
359 | case TUNE_STATUS_SIGNAL_DVB_OK: | ||
360 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
361 | break; | ||
362 | case TUNE_STATUS_STREAM_DETECTED: | ||
363 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC; | ||
364 | break; | ||
365 | case TUNE_STATUS_STREAM_TUNED: | ||
366 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | | ||
367 | FE_HAS_LOCK; | ||
368 | break; | ||
369 | default: | ||
370 | *status = TUNE_STATUS_NOT_TUNED; | ||
371 | } | ||
372 | |||
373 | dev_dbg(&state->bus_adap->usb_dev->dev, | ||
374 | "tuner status: 0x%02x, strength %d, per: %d, ber: %d\n", | ||
375 | tstate.tune_state, tstate.signal_strength, | ||
376 | tstate.PER, tstate.BER); | ||
377 | |||
378 | if (*status & FE_HAS_LOCK) { | ||
379 | if (as10x_cmd_get_demod_stats(state->bus_adap, | ||
380 | (struct as10x_demod_stats *) &state->demod_stats) < 0) { | ||
381 | memset(&state->demod_stats, 0, sizeof(state->demod_stats)); | ||
382 | dev_dbg(&state->bus_adap->usb_dev->dev, | ||
383 | "as10x_cmd_get_demod_stats failed (probably not tuned)\n"); | ||
384 | } else { | ||
385 | dev_dbg(&state->bus_adap->usb_dev->dev, | ||
386 | "demod status: fc: 0x%08x, bad fc: 0x%08x, bytes corrected: 0x%08x , MER: 0x%04x\n", | ||
387 | state->demod_stats.frame_count, | ||
388 | state->demod_stats.bad_frame_count, | ||
389 | state->demod_stats.bytes_fixed_by_rs, | ||
390 | state->demod_stats.mer); | ||
391 | } | ||
392 | } else { | ||
393 | memset(&state->demod_stats, 0, sizeof(state->demod_stats)); | ||
394 | } | ||
395 | |||
396 | out: | ||
397 | mutex_unlock(&state->bus_adap->lock); | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * Note: | ||
403 | * - in AS102 SNR=MER | ||
404 | * - the SNR will be returned in linear terms, i.e. not in dB | ||
405 | * - the accuracy equals ±2dB for a SNR range from 4dB to 30dB | ||
406 | * - the accuracy is >2dB for SNR values outside this range | ||
407 | */ | ||
408 | static int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
409 | { | ||
410 | struct as102_state *state = fe->demodulator_priv; | ||
411 | |||
412 | *snr = state->demod_stats.mer; | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
418 | { | ||
419 | struct as102_state *state = fe->demodulator_priv; | ||
420 | |||
421 | *ber = state->ber; | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static int as102_fe_read_signal_strength(struct dvb_frontend *fe, | ||
427 | u16 *strength) | ||
428 | { | ||
429 | struct as102_state *state = fe->demodulator_priv; | ||
430 | |||
431 | *strength = (((0xffff * 400) * state->signal_strength + 41000) * 2); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
437 | { | ||
438 | struct as102_state *state = fe->demodulator_priv; | ||
439 | |||
440 | if (state->demod_stats.has_started) | ||
441 | *ucblocks = state->demod_stats.bad_frame_count; | ||
442 | else | ||
443 | *ucblocks = 0; | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) | ||
449 | { | ||
450 | struct as102_state *state = fe->demodulator_priv; | ||
451 | int ret; | ||
452 | |||
453 | if (mutex_lock_interruptible(&state->bus_adap->lock)) | ||
454 | return -EBUSY; | ||
455 | |||
456 | if (acquire) { | ||
457 | if (elna_enable) | ||
458 | as10x_cmd_set_context(state->bus_adap, | ||
459 | CONTEXT_LNA, state->elna_cfg); | ||
460 | |||
461 | ret = as10x_cmd_turn_on(state->bus_adap); | ||
462 | } else { | ||
463 | ret = as10x_cmd_turn_off(state->bus_adap); | ||
464 | } | ||
465 | |||
466 | mutex_unlock(&state->bus_adap->lock); | ||
467 | |||
468 | return ret; | ||
469 | } | ||
470 | |||
471 | static struct dvb_frontend_ops as102_fe_ops = { | ||
472 | .delsys = { SYS_DVBT }, | ||
473 | .info = { | ||
474 | .name = "Abilis AS102 DVB-T", | ||
475 | .frequency_min = 174000000, | ||
476 | .frequency_max = 862000000, | ||
477 | .frequency_stepsize = 166667, | ||
478 | .caps = FE_CAN_INVERSION_AUTO | ||
479 | | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ||
480 | | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ||
481 | | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK | ||
482 | | FE_CAN_QAM_AUTO | ||
483 | | FE_CAN_TRANSMISSION_MODE_AUTO | ||
484 | | FE_CAN_GUARD_INTERVAL_AUTO | ||
485 | | FE_CAN_HIERARCHY_AUTO | ||
486 | | FE_CAN_RECOVER | ||
487 | | FE_CAN_MUTE_TS | ||
488 | }, | ||
489 | |||
490 | .set_frontend = as102_fe_set_frontend, | ||
491 | .get_frontend = as102_fe_get_frontend, | ||
492 | .get_tune_settings = as102_fe_get_tune_settings, | ||
493 | |||
494 | .read_status = as102_fe_read_status, | ||
495 | .read_snr = as102_fe_read_snr, | ||
496 | .read_ber = as102_fe_read_ber, | ||
497 | .read_signal_strength = as102_fe_read_signal_strength, | ||
498 | .read_ucblocks = as102_fe_read_ucblocks, | ||
499 | .ts_bus_ctrl = as102_fe_ts_bus_ctrl, | ||
500 | }; | ||
501 | |||
502 | struct dvb_frontend *as102_attach(const char *name, | ||
503 | struct as10x_bus_adapter_t *bus_adap, | ||
504 | uint8_t elna_cfg) | ||
505 | { | ||
506 | struct as102_state *state; | ||
507 | struct dvb_frontend *fe; | ||
508 | |||
509 | state = kzalloc(sizeof(struct as102_state), GFP_KERNEL); | ||
510 | if (state == NULL) { | ||
511 | dev_err(&bus_adap->usb_dev->dev, | ||
512 | "%s: unable to allocate memory for state\n", __func__); | ||
513 | return NULL; | ||
514 | } | ||
515 | fe = &state->frontend; | ||
516 | fe->demodulator_priv = state; | ||
517 | state->bus_adap = bus_adap; | ||
518 | state->elna_cfg = elna_cfg; | ||
519 | |||
520 | /* init frontend callback ops */ | ||
521 | memcpy(&fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops)); | ||
522 | strncpy(fe->ops.info.name, name, sizeof(fe->ops.info.name)); | ||
523 | |||
524 | return fe; | ||
525 | |||
526 | } | ||
527 | EXPORT_SYMBOL_GPL(as102_attach); | ||