[media] staging: as102: Fix CodingStyle errors in file as10x_cmd_stream.c
[deliverable/linux.git] / drivers / staging / media / as102 / as102_fe.c
CommitLineData
41b44e04
PH
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19#include <linux/version.h>
20
21#include "as102_drv.h"
22#include "as10x_types.h"
23#include "as10x_cmd.h"
24
25extern int elna_enable;
26
27#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
28static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
29 struct as10x_tps *src);
30
31static void as102_fe_copy_tune_parameters(struct as10x_tune_args *dst,
32 struct dvb_frontend_parameters *src);
33
34static void as102_fe_release(struct dvb_frontend *fe) {
35 struct as102_dev_t *dev;
36
37 ENTER();
38
39 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
40 return;
41
42#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
43 if (mutex_lock_interruptible(&dev->bus_adap.lock))
44 return;
45
46 /* send abilis command: TURN_OFF */
47 as10x_cmd_turn_off(&dev->bus_adap);
48
49 mutex_unlock(&dev->bus_adap.lock);
50#endif
51
52 /* release frontend callback ops */
53 memset(&fe->ops, 0, sizeof(struct dvb_frontend_ops));
54
55 /* flush statistics */
56 memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
57 dev->signal_strength = 0;
58 dev->ber = -1;
59
60 /* reset tuner private data */
61/* fe->tuner_priv = NULL; */
62
63 LEAVE();
64}
65
66#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
67static int as102_fe_init(struct dvb_frontend *fe) {
68 int ret = 0;
69 struct as102_dev_t *dev;
70
71 ENTER();
72
73 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
74 return -ENODEV;
75
76 if (mutex_lock_interruptible(&dev->bus_adap.lock))
77 return -EBUSY;
78
79 if (elna_enable)
80 ret = as10x_cmd_set_context(&dev->bus_adap, 1010, 0xC0);
81
82 /* send abilis command: TURN_ON */
83 ret = as10x_cmd_turn_on(&dev->bus_adap);
84
85 mutex_unlock(&dev->bus_adap.lock);
86
87 LEAVE();
88 return (ret < 0) ? -EINVAL : 0;
89}
90#endif
91
92static int as102_fe_set_frontend(struct dvb_frontend *fe,
93 struct dvb_frontend_parameters *params) {
94 int ret = 0;
95 struct as102_dev_t *dev;
96 struct as10x_tune_args tune_args = { 0 };
97
98 ENTER();
99
100 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
101 return -ENODEV;
102
103 if (mutex_lock_interruptible(&dev->bus_adap.lock))
104 return -EBUSY;
105
106 as102_fe_copy_tune_parameters(&tune_args, params);
107
108 /* send abilis command: SET_TUNE */
109 ret = as10x_cmd_set_tune(&dev->bus_adap, &tune_args);
110 if(ret != 0) {
111 dprintk(debug, "as10x_cmd_set_tune failed. (err = %d)\n", ret);
112 }
113
114 mutex_unlock(&dev->bus_adap.lock);
115
116 LEAVE();
117 return (ret < 0) ? -EINVAL : 0;
118}
119
120static int as102_fe_get_frontend(struct dvb_frontend* fe,
121 struct dvb_frontend_parameters *p) {
122 int ret = 0;
123 struct as102_dev_t *dev;
124 struct as10x_tps tps = { 0 };
125
126 ENTER();
127
128 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
129 return -EINVAL;
130
131 if (mutex_lock_interruptible(&dev->bus_adap.lock))
132 return -EBUSY;
133
134 /* send abilis command: GET_TPS */
135 ret = as10x_cmd_get_tps(&dev->bus_adap, &tps);
136
137 if (ret == 0)
138 as10x_fe_copy_tps_parameters(p, &tps);
139
140 mutex_unlock(&dev->bus_adap.lock);
141
142 LEAVE();
143 return (ret < 0) ? -EINVAL : 0;
144}
145
146static int as102_fe_get_tune_settings(struct dvb_frontend *fe,
147 struct dvb_frontend_tune_settings *settings) {
148 ENTER();
149
150#if 0
151 dprintk(debug, "step_size = %d\n", settings->step_size);
152 dprintk(debug, "max_drift = %d\n", settings->max_drift);
153 dprintk(debug, "min_delay_ms = %d -> %d\n", settings->min_delay_ms, 1000);
154#endif
155
156 settings->min_delay_ms = 1000;
157
158 LEAVE();
159 return 0;
160}
161
162
163static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) {
164 int ret = 0;
165 struct as102_dev_t *dev;
166 struct as10x_tune_status tstate = { 0 };
167
168 ENTER();
169
170 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
171 return -ENODEV;
172
173 if (mutex_lock_interruptible(&dev->bus_adap.lock))
174 return -EBUSY;
175
176 /* send abilis command: GET_TUNE_STATUS */
177 ret = as10x_cmd_get_tune_status(&dev->bus_adap, &tstate);
178 if (ret < 0) {
179 dprintk(debug, "as10x_cmd_get_tune_status failed (err = %d)\n", ret);
180 goto out;
181 }
182
183 dev->signal_strength = tstate.signal_strength;
184 dev->ber = tstate.BER;
185
186 switch(tstate.tune_state) {
187 case TUNE_STATUS_SIGNAL_DVB_OK:
188 *status = FE_HAS_SIGNAL |
189 FE_HAS_CARRIER;
190 break;
191 case TUNE_STATUS_STREAM_DETECTED:
192 *status = FE_HAS_SIGNAL |
193 FE_HAS_CARRIER |
194 FE_HAS_SYNC;
195 break;
196 case TUNE_STATUS_STREAM_TUNED:
197 *status = FE_HAS_SIGNAL |
198 FE_HAS_CARRIER |
199 FE_HAS_SYNC |
200 FE_HAS_LOCK;
201 break;
202 default:
203 *status = TUNE_STATUS_NOT_TUNED;
204 }
205
206 dprintk(debug, "tuner status: 0x%02x , strength %d , per: %d , ber: %d\n",
207 tstate.tune_state, tstate.signal_strength,
208 tstate.PER, tstate.BER);
209
210 if (*status & FE_HAS_LOCK) {
211 if (as10x_cmd_get_demod_stats(&dev->bus_adap,
212 (struct as10x_demod_stats *) &dev->demod_stats) < 0) {
213 memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
214 dprintk(debug, "as10x_cmd_get_demod_stats failed (probably not tuned)\n");
215 } else {
216 dprintk(debug, "demod status: fc: 0x%08x , bad fc: 0x%08x , bytes corrected: 0x%08x , MER: 0x%04x\n",
217 dev->demod_stats.frame_count,
218 dev->demod_stats.bad_frame_count,
219 dev->demod_stats.bytes_fixed_by_rs,
220 dev->demod_stats.mer);
221 }
222 } else {
223 memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
224 }
225
226out:
227 mutex_unlock(&dev->bus_adap.lock);
228 LEAVE();
229 return ret;
230}
231
232/*
233 * Note:
234 * - in AS102 SNR=MER
235 * - the SNR will be returned in linear terms, i.e. not in dB
236 * - the accuracy equals ±2dB for a SNR range from 4dB to 30dB
237 * - the accuracy is >2dB for SNR values outside this range
238 */
239static int as102_fe_read_snr(struct dvb_frontend* fe, u16* snr) {
240 struct as102_dev_t *dev;
241
242 ENTER();
243
244 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
245 return -ENODEV;
246
247 *snr = dev->demod_stats.mer;
248
249 LEAVE();
250 return 0;
251}
252
253static int as102_fe_read_ber(struct dvb_frontend* fe, u32* ber) {
254 struct as102_dev_t *dev;
255
256 ENTER();
257
258 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
259 return -ENODEV;
260
261 *ber = dev->ber;
262
263 LEAVE();
264 return 0;
265}
266
267static int as102_fe_read_signal_strength(struct dvb_frontend* fe, u16* strength) {
268 struct as102_dev_t *dev;
269
270 ENTER();
271
272 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
273 return -ENODEV;
274
275 *strength = (((0xffff * 400) * dev->signal_strength + 41000) * 2);
276
277 LEAVE();
278 return 0;
279}
280
281static int as102_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) {
282 struct as102_dev_t *dev;
283
284 ENTER();
285
286 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
287 return -ENODEV;
288
289 if (dev->demod_stats.has_started)
290 *ucblocks = dev->demod_stats.bad_frame_count;
291 else
292 *ucblocks = 0;
293
294 LEAVE();
295 return 0;
296}
297
298#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
299static int as102_fe_ts_bus_ctrl(struct dvb_frontend* fe, int acquire) {
300 struct as102_dev_t *dev;
301 int ret;
302
303 ENTER();
304
305 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
306 return -ENODEV;
307
308 if (mutex_lock_interruptible(&dev->bus_adap.lock))
309 return -EBUSY;
310
311 if (acquire) {
312 if (elna_enable)
313 as10x_cmd_set_context(&dev->bus_adap, 1010, 0xC0);
314
315 ret = as10x_cmd_turn_on(&dev->bus_adap);
316 } else {
317 ret = as10x_cmd_turn_off(&dev->bus_adap);
318 }
319
320 mutex_unlock(&dev->bus_adap.lock);
321
322 LEAVE();
323 return ret;
324}
325#endif
326
327static struct dvb_frontend_ops as102_fe_ops = {
328 .info = {
329 .name = DEVICE_FULL_NAME,
330 .type = FE_OFDM,
331 .frequency_min = 174000000,
332 .frequency_max = 862000000,
333 .frequency_stepsize = 166667,
334 .caps = FE_CAN_INVERSION_AUTO
335 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4
336 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO
337 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK
338 | FE_CAN_QAM_AUTO
339 | FE_CAN_TRANSMISSION_MODE_AUTO
340 | FE_CAN_GUARD_INTERVAL_AUTO
341 | FE_CAN_HIERARCHY_AUTO
342 | FE_CAN_RECOVER
343 | FE_CAN_MUTE_TS
344 },
345
346 .set_frontend = as102_fe_set_frontend,
347 .get_frontend = as102_fe_get_frontend,
348 .get_tune_settings = as102_fe_get_tune_settings,
349
350
351 .read_status = as102_fe_read_status,
352 .read_snr = as102_fe_read_snr,
353 .read_ber = as102_fe_read_ber,
354 .read_signal_strength = as102_fe_read_signal_strength,
355 .read_ucblocks = as102_fe_read_ucblocks,
356
357#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
358 .ts_bus_ctrl = as102_fe_ts_bus_ctrl,
359#else
360 .release = as102_fe_release,
361 .init = as102_fe_init,
362#endif
363};
364
365int as102_dvb_unregister_fe(struct dvb_frontend *fe) {
366
367 /* unregister frontend */
368 dvb_unregister_frontend(fe);
369
370#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
371 /* detach frontend */
372 dvb_frontend_detach(fe);
373#endif
374 return 0;
375}
376
377int as102_dvb_register_fe(struct as102_dev_t *as102_dev, struct dvb_frontend *dvb_fe) {
378 int errno;
379 struct dvb_adapter *dvb_adap;
380
381 if(as102_dev == NULL)
382 return -EINVAL;
383
384 /* extract dvb_adapter */
385 dvb_adap = &as102_dev->dvb_adap;
386
387 /* init frontend callback ops */
388 memcpy(&dvb_fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops));
389
390 /* register dbvb frontend */
391 errno = dvb_register_frontend(dvb_adap, dvb_fe);
392 if(errno == 0)
393 dvb_fe->tuner_priv = as102_dev;
394
395 return errno;
396}
397
398static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
399 struct as10x_tps *as10x_tps) {
400
401 struct dvb_ofdm_parameters *fe_tps = &dst->u.ofdm;
402
403 /* extract consteallation */
404 switch(as10x_tps->constellation) {
405 case CONST_QPSK:
406 fe_tps->constellation = QPSK;
407 break;
408 case CONST_QAM16:
409 fe_tps->constellation = QAM_16;
410 break;
411 case CONST_QAM64:
412 fe_tps->constellation = QAM_64;
413 break;
414 }
415
416 /* extract hierarchy */
417 switch(as10x_tps->hierarchy) {
418 case HIER_NONE:
419 fe_tps->hierarchy_information = HIERARCHY_NONE;
420 break;
421 case HIER_ALPHA_1:
422 fe_tps->hierarchy_information = HIERARCHY_1;
423 break;
424 case HIER_ALPHA_2:
425 fe_tps->hierarchy_information = HIERARCHY_2;
426 break;
427 case HIER_ALPHA_4:
428 fe_tps->hierarchy_information = HIERARCHY_4;
429 break;
430 }
431
432 /* extract code rate HP */
433 switch(as10x_tps->code_rate_HP) {
434 case CODE_RATE_1_2:
435 fe_tps->code_rate_HP = FEC_1_2;
436 break;
437 case CODE_RATE_2_3:
438 fe_tps->code_rate_HP = FEC_2_3;
439 break;
440 case CODE_RATE_3_4:
441 fe_tps->code_rate_HP = FEC_3_4;
442 break;
443 case CODE_RATE_5_6:
444 fe_tps->code_rate_HP = FEC_5_6;
445 break;
446 case CODE_RATE_7_8:
447 fe_tps->code_rate_HP = FEC_7_8;
448 break;
449 }
450
451 /* extract code rate LP */
452 switch(as10x_tps->code_rate_LP) {
453 case CODE_RATE_1_2:
454 fe_tps->code_rate_LP = FEC_1_2;
455 break;
456 case CODE_RATE_2_3:
457 fe_tps->code_rate_LP = FEC_2_3;
458 break;
459 case CODE_RATE_3_4:
460 fe_tps->code_rate_LP = FEC_3_4;
461 break;
462 case CODE_RATE_5_6:
463 fe_tps->code_rate_LP = FEC_5_6;
464 break;
465 case CODE_RATE_7_8:
466 fe_tps->code_rate_LP = FEC_7_8;
467 break;
468 }
469
470 /* extract guard interval */
471 switch(as10x_tps->guard_interval) {
472 case GUARD_INT_1_32:
473 fe_tps->guard_interval = GUARD_INTERVAL_1_32;
474 break;
475 case GUARD_INT_1_16:
476 fe_tps->guard_interval = GUARD_INTERVAL_1_16;
477 break;
478 case GUARD_INT_1_8:
479 fe_tps->guard_interval = GUARD_INTERVAL_1_8;
480 break;
481 case GUARD_INT_1_4:
482 fe_tps->guard_interval = GUARD_INTERVAL_1_4;
483 break;
484 }
485
486 /* extract transmission mode */
487 switch(as10x_tps->transmission_mode) {
488 case TRANS_MODE_2K:
489 fe_tps->transmission_mode = TRANSMISSION_MODE_2K;
490 break;
491 case TRANS_MODE_8K:
492 fe_tps->transmission_mode = TRANSMISSION_MODE_8K;
493 break;
494 }
495}
496
497static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg) {
498 uint8_t c;
499
500 switch(arg) {
501 case FEC_1_2:
502 c = CODE_RATE_1_2;
503 break;
504 case FEC_2_3:
505 c = CODE_RATE_2_3;
506 break;
507 case FEC_3_4:
508 c = CODE_RATE_3_4;
509 break;
510 case FEC_5_6:
511 c = CODE_RATE_5_6;
512 break;
513 case FEC_7_8:
514 c = CODE_RATE_7_8;
515 break;
516 default:
517 c = CODE_RATE_UNKNOWN;
518 break;
519 }
520
521 return c;
522}
523
524static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
525 struct dvb_frontend_parameters *params) {
526
527 /* set frequency */
528 tune_args->freq = params->frequency / 1000;
529
530 /* fix interleaving_mode */
531 tune_args->interleaving_mode = INTLV_NATIVE;
532
533 switch(params->u.ofdm.bandwidth) {
534 case BANDWIDTH_8_MHZ:
535 tune_args->bandwidth = BW_8_MHZ;
536 break;
537 case BANDWIDTH_7_MHZ:
538 tune_args->bandwidth = BW_7_MHZ;
539 break;
540 case BANDWIDTH_6_MHZ:
541 tune_args->bandwidth = BW_6_MHZ;
542 break;
543 default:
544 tune_args->bandwidth = BW_8_MHZ;
545 }
546
547 switch(params->u.ofdm.guard_interval) {
548 case GUARD_INTERVAL_1_32:
549 tune_args->guard_interval = GUARD_INT_1_32;
550 break;
551 case GUARD_INTERVAL_1_16:
552 tune_args->guard_interval = GUARD_INT_1_16;
553 break;
554 case GUARD_INTERVAL_1_8:
555 tune_args->guard_interval = GUARD_INT_1_8;
556 break;
557 case GUARD_INTERVAL_1_4:
558 tune_args->guard_interval = GUARD_INT_1_4;
559 break;
560 case GUARD_INTERVAL_AUTO:
561 default:
562 tune_args->guard_interval = GUARD_UNKNOWN;
563 break;
564 }
565
566 switch(params->u.ofdm.constellation) {
567 case QPSK:
568 tune_args->constellation = CONST_QPSK;
569 break;
570 case QAM_16:
571 tune_args->constellation = CONST_QAM16;
572 break;
573 case QAM_64:
574 tune_args->constellation = CONST_QAM64;
575 break;
576 default:
577 tune_args->constellation = CONST_UNKNOWN;
578 break;
579 }
580
581 switch(params->u.ofdm.transmission_mode) {
582 case TRANSMISSION_MODE_2K:
583 tune_args->transmission_mode = TRANS_MODE_2K;
584 break;
585 case TRANSMISSION_MODE_8K:
586 tune_args->transmission_mode = TRANS_MODE_8K;
587 break;
588 default:
589 tune_args->transmission_mode = TRANS_MODE_UNKNOWN;
590 }
591
592 switch(params->u.ofdm.hierarchy_information) {
593 case HIERARCHY_NONE:
594 tune_args->hierarchy = HIER_NONE;
595 break;
596 case HIERARCHY_1:
597 tune_args->hierarchy = HIER_ALPHA_1;
598 break;
599 case HIERARCHY_2:
600 tune_args->hierarchy = HIER_ALPHA_2;
601 break;
602 case HIERARCHY_4:
603 tune_args->hierarchy = HIER_ALPHA_4;
604 break;
605 case HIERARCHY_AUTO:
606 tune_args->hierarchy = HIER_UNKNOWN;
607 break;
608 }
609
610 dprintk(debug, "tuner parameters: freq: %d bw: 0x%02x gi: 0x%02x\n",
611 params->frequency,
612 tune_args->bandwidth,
613 tune_args->guard_interval);
614
615 /*
616 * Detect a hierarchy selection
617 * if HP/LP are both set to FEC_NONE, HP will be selected.
618 */
619 if ((tune_args->hierarchy != HIER_NONE) &&
620 ((params->u.ofdm.code_rate_LP == FEC_NONE) ||
621 (params->u.ofdm.code_rate_HP == FEC_NONE))) {
622
623 if (params->u.ofdm.code_rate_LP == FEC_NONE) {
624 tune_args->hier_select = HIER_HIGH_PRIORITY;
625 tune_args->code_rate =
626 as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
627 }
628
629 if (params->u.ofdm.code_rate_HP == FEC_NONE) {
630 tune_args->hier_select = HIER_LOW_PRIORITY;
631 tune_args->code_rate =
632 as102_fe_get_code_rate(params->u.ofdm.code_rate_LP);
633 }
634
635 dprintk(debug, "\thierarchy: 0x%02x "
636 "selected: %s code_rate_%s: 0x%02x\n",
637 tune_args->hierarchy,
638 tune_args->hier_select == HIER_HIGH_PRIORITY ? "HP" : "LP",
639 tune_args->hier_select == HIER_HIGH_PRIORITY ? "HP" : "LP",
640 tune_args->code_rate);
641 } else {
642 tune_args->code_rate = as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
643 }
644}
645#endif
646
647/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
This page took 0.046713 seconds and 5 git commands to generate.