aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2014-08-12 17:50:19 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-08-21 16:25:29 -0400
commitb601d9a5d668119219d1db95cbe04fdc38eaf5a4 (patch)
treee9d325a042df220c202697cd8ed01b7c5eb344cf
parentd8eb070b6649c1663204300555fb740affc6cdc2 (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.c17
-rw-r--r--drivers/media/usb/as102/as102_drv.h15
-rw-r--r--drivers/media/usb/as102/as102_fe.c542
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:
252void as102_dvb_unregister(struct as102_dev_t *as102_dev) 262void 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 {
84int as102_dvb_register(struct as102_dev_t *dev); 77int as102_dvb_register(struct as102_dev_t *dev);
85void as102_dvb_unregister(struct as102_dev_t *dev); 78void as102_dvb_unregister(struct as102_dev_t *dev);
86 79
87int as102_dvb_register_fe(struct as102_dev_t *dev, struct dvb_frontend *fe); 80/* FIXME: move it to a separate header */
88int as102_dvb_unregister_fe(struct dvb_frontend *dev); 81struct 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
20static void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *dst, 20struct 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
23static void as102_fe_copy_tune_parameters(struct as10x_tune_args *dst, 25 uint8_t elna_cfg;
24 struct dtv_frontend_properties *src);
25 26
26static 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
53static 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
78static 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
87static 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
150out:
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 */
162static 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
175static 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
188static 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
202static 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
218static 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
245static 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
276int 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
287int 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
312static void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *fe_tps, 33static 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
284static 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
307static 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
328static 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
337static 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
396out:
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 */
408static 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
417static 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
426static 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
436static 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
448static 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
471static 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
502struct 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}
527EXPORT_SYMBOL_GPL(as102_attach);