aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-03-09 17:26:28 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-21 06:47:31 -0400
commitd42f1cb25334bbcddf213a00bb67083414027933 (patch)
tree698df33b58aa2d1a5486afb4c9f3d7050e51124e
parentff702eb8d9c8ca293e7f0343dd38b718d58815b0 (diff)
[media] siano: Convert it to report DVBv5 stats
While this frontend provides a nice set of statistics, the way it is currently reported to userspace is poor. Worse than that, instead of using quality indicators that range from 0 to 65535, as expected by userspace, most indicators range from 0 to 100. Improve it by using DVBv5 statistics API. The legacy indicators are still reported using the very same old way, but they're now using a proper range (0 to 65535 for quality indicadors; 0.1 dB for SNR). Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/common/siano/smsdvb.c826
1 files changed, 468 insertions, 358 deletions
diff --git a/drivers/media/common/siano/smsdvb.c b/drivers/media/common/siano/smsdvb.c
index 04544f591df5..a5f52721154c 100644
--- a/drivers/media/common/siano/smsdvb.c
+++ b/drivers/media/common/siano/smsdvb.c
@@ -49,7 +49,10 @@ struct smsdvb_client_t {
49 struct completion tune_done; 49 struct completion tune_done;
50 struct completion stats_done; 50 struct completion stats_done;
51 51
52 struct SMSHOSTLIB_STATISTICS_DVB_EX_S sms_stat_dvb; 52 int last_per;
53
54 int legacy_ber, legacy_per;
55
53 int event_fe_state; 56 int event_fe_state;
54 int event_unc_state; 57 int event_unc_state;
55}; 58};
@@ -61,6 +64,82 @@ static int sms_dbg;
61module_param_named(debug, sms_dbg, int, 0644); 64module_param_named(debug, sms_dbg, int, 0644);
62MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); 65MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
63 66
67/*
68 * This struct is a mix of RECEPTION_STATISTICS_EX_S and SRVM_SIGNAL_STATUS_S.
69 * It was obtained by comparing the way it was filled by the original code
70 */
71struct RECEPTION_STATISTICS_PER_SLICES_S {
72 u32 result;
73 u32 snr;
74 s32 inBandPower;
75 u32 tsPackets;
76 u32 etsPackets;
77 u32 constellation;
78 u32 hpCode;
79 u32 tpsSrvIndLP;
80 u32 tpsSrvIndHP;
81 u32 cellId;
82 u32 reason;
83 u32 requestId;
84 u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
85
86 u32 BER; /* Post Viterbi BER [1E-5] */
87 s32 RSSI; /* dBm */
88 s32 CarrierOffset; /* Carrier Offset in bin/1024 */
89
90 u32 IsRfLocked; /* 0 - not locked, 1 - locked */
91 u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
92
93 u32 BERBitCount; /* Total number of SYNC bits. */
94 u32 BERErrorCount; /* Number of erronous SYNC bits. */
95
96 s32 MRC_SNR; /* dB */
97 s32 MRC_InBandPwr; /* In band power in dBM */
98 s32 MRC_RSSI; /* dBm */
99};
100
101u32 sms_to_bw_table[] = {
102 [BW_8_MHZ] = 8000000,
103 [BW_7_MHZ] = 7000000,
104 [BW_6_MHZ] = 6000000,
105 [BW_5_MHZ] = 5000000,
106 [BW_2_MHZ] = 2000000,
107 [BW_1_5_MHZ] = 1500000,
108 [BW_ISDBT_1SEG] = 6000000,
109 [BW_ISDBT_3SEG] = 6000000,
110 [BW_ISDBT_13SEG] = 6000000,
111};
112
113u32 sms_to_guard_interval_table[] = {
114 [0] = GUARD_INTERVAL_1_32,
115 [1] = GUARD_INTERVAL_1_16,
116 [2] = GUARD_INTERVAL_1_8,
117 [3] = GUARD_INTERVAL_1_4,
118};
119
120u32 sms_to_code_rate_table[] = {
121 [0] = FEC_1_2,
122 [1] = FEC_2_3,
123 [2] = FEC_3_4,
124 [3] = FEC_5_6,
125 [4] = FEC_7_8,
126};
127
128
129u32 sms_to_hierarchy_table[] = {
130 [0] = HIERARCHY_NONE,
131 [1] = HIERARCHY_1,
132 [2] = HIERARCHY_2,
133 [3] = HIERARCHY_4,
134};
135
136u32 sms_to_modulation_table[] = {
137 [0] = QPSK,
138 [1] = QAM_16,
139 [2] = QAM_64,
140 [3] = DQPSK,
141};
142
64static void smsdvb_print_dvb_stats(struct SMSHOSTLIB_STATISTICS_ST *p) 143static void smsdvb_print_dvb_stats(struct SMSHOSTLIB_STATISTICS_ST *p)
65{ 144{
66 if (!(sms_dbg & 2)) 145 if (!(sms_dbg & 2))
@@ -244,93 +323,350 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client,
244 } 323 }
245} 324}
246 325
247static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData, 326static void smsdvb_stats_not_ready(struct dvb_frontend *fe)
327{
328 struct smsdvb_client_t *client =
329 container_of(fe, struct smsdvb_client_t, frontend);
330 struct smscore_device_t *coredev = client->coredev;
331 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
332 int i, n_layers;
333
334 switch (smscore_get_device_mode(coredev)) {
335 case DEVICE_MODE_ISDBT:
336 case DEVICE_MODE_ISDBT_BDA:
337 n_layers = 4;
338 default:
339 n_layers = 1;
340 }
341
342 /* Fill the length of each status counter */
343
344 /* Only global stats */
345 c->strength.len = 1;
346 c->cnr.len = 1;
347
348 /* Per-layer stats */
349 c->post_bit_error.len = n_layers;
350 c->post_bit_count.len = n_layers;
351 c->block_error.len = n_layers;
352 c->block_count.len = n_layers;
353
354 /* Signal is always available */
355 c->strength.stat[0].scale = FE_SCALE_RELATIVE;
356 c->strength.stat[0].uvalue = 0;
357
358 /* Put all of them at FE_SCALE_NOT_AVAILABLE */
359 for (i = 0; i < n_layers; i++) {
360 c->cnr.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
361 c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
362 c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
363 c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
364 c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
365 }
366}
367
368static inline int sms_to_mode(u32 mode)
369{
370 switch (mode) {
371 case 2:
372 return TRANSMISSION_MODE_2K;
373 case 4:
374 return TRANSMISSION_MODE_4K;
375 case 8:
376 return TRANSMISSION_MODE_8K;
377 }
378 return TRANSMISSION_MODE_AUTO;
379}
380
381static inline int sms_to_status(u32 is_demod_locked, u32 is_rf_locked)
382{
383 if (is_demod_locked)
384 return FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
385 FE_HAS_SYNC | FE_HAS_LOCK;
386
387 if (is_rf_locked)
388 return FE_HAS_SIGNAL | FE_HAS_CARRIER;
389
390 return 0;
391}
392
393
394#define convert_from_table(value, table, defval) ({ \
395 u32 __ret; \
396 if (value < ARRAY_SIZE(table)) \
397 __ret = table[value]; \
398 else \
399 __ret = defval; \
400 __ret; \
401})
402
403#define sms_to_bw(value) \
404 convert_from_table(value, sms_to_bw_table, 0);
405
406#define sms_to_guard_interval(value) \
407 convert_from_table(value, sms_to_guard_interval_table, \
408 GUARD_INTERVAL_AUTO);
409
410#define sms_to_code_rate(value) \
411 convert_from_table(value, sms_to_code_rate_table, \
412 FEC_NONE);
413
414#define sms_to_hierarchy(value) \
415 convert_from_table(value, sms_to_hierarchy_table, \
416 FEC_NONE);
417
418#define sms_to_modulation(value) \
419 convert_from_table(value, sms_to_modulation_table, \
420 FEC_NONE);
421
422static void smsdvb_update_tx_params(struct smsdvb_client_t *client,
423 struct TRANSMISSION_STATISTICS_S *p)
424{
425 struct dvb_frontend *fe = &client->frontend;
426 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
427
428 c->frequency = p->Frequency;
429 client->fe_status = sms_to_status(p->IsDemodLocked, 0);
430 c->bandwidth_hz = sms_to_bw(p->Bandwidth);
431 c->transmission_mode = sms_to_mode(p->TransmissionMode);
432 c->guard_interval = sms_to_guard_interval(p->GuardInterval);
433 c->code_rate_HP = sms_to_code_rate(p->CodeRate);
434 c->code_rate_LP = sms_to_code_rate(p->LPCodeRate);
435 c->hierarchy = sms_to_hierarchy(p->Hierarchy);
436 c->modulation = sms_to_modulation(p->Constellation);
437}
438
439static void smsdvb_update_per_slices(struct smsdvb_client_t *client,
440 struct RECEPTION_STATISTICS_PER_SLICES_S *p)
441{
442 struct dvb_frontend *fe = &client->frontend;
443 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
444
445 client->fe_status = sms_to_status(p->IsDemodLocked, p->IsRfLocked);
446 c->modulation = sms_to_modulation(p->constellation);
447
448 /* TS PER */
449 client->last_per = c->block_error.stat[0].uvalue;
450 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
451 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
452 c->block_error.stat[0].uvalue += p->etsPackets;
453 c->block_count.stat[0].uvalue += p->etsPackets + p->tsPackets;
454
455 /* BER */
456 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
457 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
458 c->post_bit_error.stat[0].uvalue += p->BERErrorCount;
459 c->post_bit_count.stat[0].uvalue += p->BERBitCount;
460
461 /* Legacy PER/BER */
462 client->legacy_per = (p->etsPackets * 65535) /
463 (p->tsPackets + p->etsPackets);
464
465 /* Signal Strength, in DBm */
466 c->strength.stat[0].uvalue = p->RSSI * 1000;
467
468 /* Carrier to Noise ratio, in DB */
469 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
470 c->cnr.stat[0].svalue = p->snr * 1000;
471}
472
473static void smsdvb_update_dvb_stats(struct smsdvb_client_t *client,
248 struct SMSHOSTLIB_STATISTICS_ST *p) 474 struct SMSHOSTLIB_STATISTICS_ST *p)
249{ 475{
476 struct dvb_frontend *fe = &client->frontend;
477 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
478
250 smsdvb_print_dvb_stats(p); 479 smsdvb_print_dvb_stats(p);
251 480
481 client->fe_status = sms_to_status(p->IsDemodLocked, p->IsRfLocked);
482
483 /* Update DVB modulation parameters */
484 c->frequency = p->Frequency;
485 client->fe_status = sms_to_status(p->IsDemodLocked, 0);
486 c->bandwidth_hz = sms_to_bw(p->Bandwidth);
487 c->transmission_mode = sms_to_mode(p->TransmissionMode);
488 c->guard_interval = sms_to_guard_interval(p->GuardInterval);
489 c->code_rate_HP = sms_to_code_rate(p->CodeRate);
490 c->code_rate_LP = sms_to_code_rate(p->LPCodeRate);
491 c->hierarchy = sms_to_hierarchy(p->Hierarchy);
492 c->modulation = sms_to_modulation(p->Constellation);
493
252 /* update reception data */ 494 /* update reception data */
253 pReceptionData->IsRfLocked = p->IsRfLocked; 495 c->lna = p->IsExternalLNAOn ? 1 : 0;
254 pReceptionData->IsDemodLocked = p->IsDemodLocked; 496
255 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn; 497 /* Carrier to Noise ratio, in DB */
256 pReceptionData->ModemState = p->ModemState; 498 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
257 pReceptionData->SNR = p->SNR; 499 c->cnr.stat[0].svalue = p->SNR * 1000;
258 pReceptionData->BER = p->BER; 500
259 pReceptionData->BERErrorCount = p->BERErrorCount; 501 /* Signal Strength, in DBm */
260 pReceptionData->BERBitCount = p->BERBitCount; 502 c->strength.stat[0].uvalue = p->RSSI * 1000;
261 pReceptionData->RSSI = p->RSSI; 503
262 CORRECT_STAT_RSSI(*pReceptionData); 504 /* TS PER */
263 pReceptionData->InBandPwr = p->InBandPwr; 505 client->last_per = c->block_error.stat[0].uvalue;
264 pReceptionData->CarrierOffset = p->CarrierOffset; 506 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
265 pReceptionData->ErrorTSPackets = p->ErrorTSPackets; 507 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
266 pReceptionData->TotalTSPackets = p->TotalTSPackets; 508 c->block_error.stat[0].uvalue += p->ErrorTSPackets;
509 c->block_count.stat[0].uvalue += p->TotalTSPackets;
510
511 /* BER */
512 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
513 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
514 c->post_bit_error.stat[0].uvalue += p->BERErrorCount;
515 c->post_bit_count.stat[0].uvalue += p->BERBitCount;
516
517 /* Legacy PER/BER */
518 client->legacy_ber = p->BER;
267}; 519};
268 520
269static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData, 521static void smsdvb_update_isdbt_stats(struct smsdvb_client_t *client,
270 struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p) 522 struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
271{ 523{
524 struct dvb_frontend *fe = &client->frontend;
525 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
526 struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST *lr;
527 int i, n_layers;
528
272 smsdvb_print_isdb_stats(p); 529 smsdvb_print_isdb_stats(p);
273 530
531 /* Update ISDB-T transmission parameters */
532 c->frequency = p->Frequency;
533 client->fe_status = sms_to_status(p->IsDemodLocked, 0);
534 c->bandwidth_hz = sms_to_bw(p->Bandwidth);
535 c->transmission_mode = sms_to_mode(p->TransmissionMode);
536 c->guard_interval = sms_to_guard_interval(p->GuardInterval);
537 c->isdbt_partial_reception = p->PartialReception ? 1 : 0;
538 n_layers = p->NumOfLayers;
539 if (n_layers < 1)
540 n_layers = 1;
541 if (n_layers > 3)
542 n_layers = 3;
543 c->isdbt_layer_enabled = 0;
544
274 /* update reception data */ 545 /* update reception data */
275 pReceptionData->IsRfLocked = p->IsRfLocked; 546 c->lna = p->IsExternalLNAOn ? 1 : 0;
276 pReceptionData->IsDemodLocked = p->IsDemodLocked;
277 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
278 pReceptionData->ModemState = p->ModemState;
279 pReceptionData->SNR = p->SNR;
280 pReceptionData->BER = p->LayerInfo[0].BER;
281 pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
282 pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
283 pReceptionData->RSSI = p->RSSI;
284 CORRECT_STAT_RSSI(*pReceptionData);
285 pReceptionData->InBandPwr = p->InBandPwr;
286
287 pReceptionData->CarrierOffset = p->CarrierOffset;
288 pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
289 pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
290 pReceptionData->MFER = 0;
291 547
292 /* TS PER */ 548 /* Carrier to Noise ratio, in DB */
293 if ((p->LayerInfo[0].TotalTSPackets + 549 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
294 p->LayerInfo[0].ErrorTSPackets) > 0) { 550 c->cnr.stat[0].svalue = p->SNR * 1000;
295 pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets 551
296 * 100) / (p->LayerInfo[0].TotalTSPackets 552 /* Signal Strength, in DBm */
297 + p->LayerInfo[0].ErrorTSPackets); 553 c->strength.stat[0].uvalue = p->RSSI * 1000;
298 } else { 554
299 pReceptionData->TS_PER = 0; 555 client->last_per = c->block_error.stat[0].uvalue;
556
557 /* Clears global counters, as the code below will sum it again */
558 c->block_error.stat[0].uvalue = 0;
559 c->block_count.stat[0].uvalue = 0;
560 c->post_bit_error.stat[0].uvalue = 0;
561 c->post_bit_count.stat[0].uvalue = 0;
562
563 for (i = 0; i < n_layers; i++) {
564 lr = &p->LayerInfo[i];
565
566 /* Update per-layer transmission parameters */
567 if (lr->NumberOfSegments > 0 && lr->NumberOfSegments < 13) {
568 c->isdbt_layer_enabled |= 1 << i;
569 c->layer[i].segment_count = lr->NumberOfSegments;
570 } else {
571 continue;
572 }
573 c->layer[i].modulation = sms_to_modulation(lr->Constellation);
574
575 /* TS PER */
576 c->block_error.stat[i].scale = FE_SCALE_COUNTER;
577 c->block_count.stat[i].scale = FE_SCALE_COUNTER;
578 c->block_error.stat[i].uvalue += lr->ErrorTSPackets;
579 c->block_count.stat[i].uvalue += lr->TotalTSPackets;
580
581 /* Update global PER counter */
582 c->block_error.stat[0].uvalue += lr->ErrorTSPackets;
583 c->block_count.stat[0].uvalue += lr->TotalTSPackets;
584
585 /* BER */
586 c->post_bit_error.stat[i].scale = FE_SCALE_COUNTER;
587 c->post_bit_count.stat[i].scale = FE_SCALE_COUNTER;
588 c->post_bit_error.stat[i].uvalue += lr->BERErrorCount;
589 c->post_bit_count.stat[i].uvalue += lr->BERBitCount;
590
591 /* Update global BER counter */
592 c->post_bit_error.stat[0].uvalue += lr->BERErrorCount;
593 c->post_bit_count.stat[0].uvalue += lr->BERBitCount;
300 } 594 }
301} 595}
302 596
303static void smsdvb_update_isdbt_stats_ex(struct RECEPTION_STATISTICS_EX_S *pReceptionData, 597static void smsdvb_update_isdbt_stats_ex(struct smsdvb_client_t *client,
304 struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST *p) 598 struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST *p)
305{ 599{
600 struct dvb_frontend *fe = &client->frontend;
601 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
602 struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST *lr;
603 int i, n_layers;
604
306 smsdvb_print_isdb_stats_ex(p); 605 smsdvb_print_isdb_stats_ex(p);
307 606
607 /* Update ISDB-T transmission parameters */
608 c->frequency = p->Frequency;
609 client->fe_status = sms_to_status(p->IsDemodLocked, 0);
610 c->bandwidth_hz = sms_to_bw(p->Bandwidth);
611 c->transmission_mode = sms_to_mode(p->TransmissionMode);
612 c->guard_interval = sms_to_guard_interval(p->GuardInterval);
613 c->isdbt_partial_reception = p->PartialReception ? 1 : 0;
614 n_layers = p->NumOfLayers;
615 if (n_layers < 1)
616 n_layers = 1;
617 if (n_layers > 3)
618 n_layers = 3;
619 c->isdbt_layer_enabled = 0;
620
308 /* update reception data */ 621 /* update reception data */
309 pReceptionData->IsRfLocked = p->IsRfLocked; 622 c->lna = p->IsExternalLNAOn ? 1 : 0;
310 pReceptionData->IsDemodLocked = p->IsDemodLocked;
311 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
312 pReceptionData->ModemState = p->ModemState;
313 pReceptionData->SNR = p->SNR;
314 pReceptionData->BER = p->LayerInfo[0].BER;
315 pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
316 pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
317 pReceptionData->RSSI = p->RSSI;
318 CORRECT_STAT_RSSI(*pReceptionData);
319 pReceptionData->InBandPwr = p->InBandPwr;
320
321 pReceptionData->CarrierOffset = p->CarrierOffset;
322 pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
323 pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
324 pReceptionData->MFER = 0;
325 623
326 /* TS PER */ 624 /* Carrier to Noise ratio, in DB */
327 if ((p->LayerInfo[0].TotalTSPackets + 625 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
328 p->LayerInfo[0].ErrorTSPackets) > 0) { 626 c->cnr.stat[0].svalue = p->SNR * 1000;
329 pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets 627
330 * 100) / (p->LayerInfo[0].TotalTSPackets 628 /* Signal Strength, in DBm */
331 + p->LayerInfo[0].ErrorTSPackets); 629 c->strength.stat[0].uvalue = p->RSSI * 1000;
332 } else { 630
333 pReceptionData->TS_PER = 0; 631 client->last_per = c->block_error.stat[0].uvalue;
632
633 /* Clears global counters, as the code below will sum it again */
634 c->block_error.stat[0].uvalue = 0;
635 c->block_count.stat[0].uvalue = 0;
636 c->post_bit_error.stat[0].uvalue = 0;
637 c->post_bit_count.stat[0].uvalue = 0;
638
639 for (i = 0; i < n_layers; i++) {
640 lr = &p->LayerInfo[i];
641
642 /* Update per-layer transmission parameters */
643 if (lr->NumberOfSegments > 0 && lr->NumberOfSegments < 13) {
644 c->isdbt_layer_enabled |= 1 << i;
645 c->layer[i].segment_count = lr->NumberOfSegments;
646 } else {
647 continue;
648 }
649 c->layer[i].modulation = sms_to_modulation(lr->Constellation);
650
651 /* TS PER */
652 c->block_error.stat[i].scale = FE_SCALE_COUNTER;
653 c->block_count.stat[i].scale = FE_SCALE_COUNTER;
654 c->block_error.stat[i].uvalue += lr->ErrorTSPackets;
655 c->block_count.stat[i].uvalue += lr->TotalTSPackets;
656
657 /* Update global PER counter */
658 c->block_error.stat[0].uvalue += lr->ErrorTSPackets;
659 c->block_count.stat[0].uvalue += lr->TotalTSPackets;
660
661 /* BER */
662 c->post_bit_error.stat[i].scale = FE_SCALE_COUNTER;
663 c->post_bit_count.stat[i].scale = FE_SCALE_COUNTER;
664 c->post_bit_error.stat[i].uvalue += lr->BERErrorCount;
665 c->post_bit_count.stat[i].uvalue += lr->BERBitCount;
666
667 /* Update global BER counter */
668 c->post_bit_error.stat[0].uvalue += lr->BERErrorCount;
669 c->post_bit_count.stat[0].uvalue += lr->BERBitCount;
334 } 670 }
335} 671}
336 672
@@ -339,13 +675,14 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
339 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; 675 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
340 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p) 676 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
341 + cb->offset); 677 + cb->offset);
342 u32 *pMsgData = (u32 *) phdr + 1; 678 void *p = phdr + 1;
343 /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/ 679 struct dvb_frontend *fe = &client->frontend;
680 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
344 bool is_status_update = false; 681 bool is_status_update = false;
345 682
346 switch (phdr->msgType) { 683 switch (phdr->msgType) {
347 case MSG_SMS_DVBT_BDA_DATA: 684 case MSG_SMS_DVBT_BDA_DATA:
348 dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1), 685 dvb_dmx_swfilter(&client->demux, p,
349 cb->size - sizeof(struct SmsMsgHdr_ST)); 686 cb->size - sizeof(struct SmsMsgHdr_ST));
350 break; 687 break;
351 688
@@ -355,166 +692,64 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
355 break; 692 break;
356 693
357 case MSG_SMS_SIGNAL_DETECTED_IND: 694 case MSG_SMS_SIGNAL_DETECTED_IND:
358 client->sms_stat_dvb.TransmissionData.IsDemodLocked = true; 695 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
696 FE_HAS_VITERBI | FE_HAS_SYNC |
697 FE_HAS_LOCK;
698
359 is_status_update = true; 699 is_status_update = true;
360 break; 700 break;
361 701
362 case MSG_SMS_NO_SIGNAL_IND: 702 case MSG_SMS_NO_SIGNAL_IND:
363 client->sms_stat_dvb.TransmissionData.IsDemodLocked = false; 703 client->fe_status = 0;
704
364 is_status_update = true; 705 is_status_update = true;
365 break; 706 break;
366 707
367 case MSG_SMS_TRANSMISSION_IND: { 708 case MSG_SMS_TRANSMISSION_IND:
368 709 smsdvb_update_tx_params(client, p);
369 pMsgData++;
370 memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
371 sizeof(struct TRANSMISSION_STATISTICS_S));
372 710
373#if 1
374 /*
375 * FIXME: newer driver doesn't have those fixes
376 * Are those firmware-specific stuff?
377 */
378
379 /* Mo need to correct guard interval
380 * (as opposed to old statistics message).
381 */
382 CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
383 CORRECT_STAT_TRANSMISSON_MODE(
384 client->sms_stat_dvb.TransmissionData);
385#endif
386 is_status_update = true; 711 is_status_update = true;
387 break; 712 break;
388 }
389 case MSG_SMS_HO_PER_SLICES_IND: {
390 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
391 &client->sms_stat_dvb.ReceptionData;
392 struct SRVM_SIGNAL_STATUS_S SignalStatusData;
393
394 pMsgData++;
395 SignalStatusData.result = pMsgData[0];
396 SignalStatusData.snr = pMsgData[1];
397 SignalStatusData.inBandPower = (s32) pMsgData[2];
398 SignalStatusData.tsPackets = pMsgData[3];
399 SignalStatusData.etsPackets = pMsgData[4];
400 SignalStatusData.constellation = pMsgData[5];
401 SignalStatusData.hpCode = pMsgData[6];
402 SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
403 SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
404 SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
405 SignalStatusData.reason = pMsgData[10];
406 SignalStatusData.requestId = pMsgData[11];
407 pReceptionData->IsRfLocked = pMsgData[16];
408 pReceptionData->IsDemodLocked = pMsgData[17];
409 pReceptionData->ModemState = pMsgData[12];
410 pReceptionData->SNR = pMsgData[1];
411 pReceptionData->BER = pMsgData[13];
412 pReceptionData->RSSI = pMsgData[14];
413 CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
414
415 pReceptionData->InBandPwr = (s32) pMsgData[2];
416 pReceptionData->CarrierOffset = (s32) pMsgData[15];
417 pReceptionData->TotalTSPackets = pMsgData[3];
418 pReceptionData->ErrorTSPackets = pMsgData[4];
419 713
420 /* TS PER */ 714 case MSG_SMS_HO_PER_SLICES_IND:
421 if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets) 715 smsdvb_update_per_slices(client, p);
422 > 0) {
423 pReceptionData->TS_PER = (SignalStatusData.etsPackets
424 * 100) / (SignalStatusData.tsPackets
425 + SignalStatusData.etsPackets);
426 } else {
427 pReceptionData->TS_PER = 0;
428 }
429
430 pReceptionData->BERBitCount = pMsgData[18];
431 pReceptionData->BERErrorCount = pMsgData[19];
432
433 pReceptionData->MRC_SNR = pMsgData[20];
434 pReceptionData->MRC_InBandPwr = pMsgData[21];
435 pReceptionData->MRC_RSSI = pMsgData[22];
436 716
437 is_status_update = true; 717 is_status_update = true;
438 break; 718 break;
439 }
440 case MSG_SMS_GET_STATISTICS_RES: {
441 union {
442 struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
443 struct SmsMsgStatisticsInfo_ST dvb;
444 } *p = (void *) (phdr + 1);
445 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
446 &client->sms_stat_dvb.ReceptionData;
447
448 is_status_update = true;
449 719
720 case MSG_SMS_GET_STATISTICS_RES:
450 switch (smscore_get_device_mode(client->coredev)) { 721 switch (smscore_get_device_mode(client->coredev)) {
451 case DEVICE_MODE_ISDBT: 722 case DEVICE_MODE_ISDBT:
452 case DEVICE_MODE_ISDBT_BDA: 723 case DEVICE_MODE_ISDBT_BDA:
453 smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt); 724 smsdvb_update_isdbt_stats(client, p);
454 break; 725 break;
455 default: 726 default:
456 smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat); 727 smsdvb_update_dvb_stats(client, p);
457 }
458 if (!pReceptionData->IsDemodLocked) {
459 pReceptionData->SNR = 0;
460 pReceptionData->BER = 0;
461 pReceptionData->BERErrorCount = 0;
462 pReceptionData->InBandPwr = 0;
463 pReceptionData->ErrorTSPackets = 0;
464 } 728 }
465 729
730 is_status_update = true;
466 break; 731 break;
467 }
468 case MSG_SMS_GET_STATISTICS_EX_RES: {
469 union {
470 struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST isdbt;
471 struct SMSHOSTLIB_STATISTICS_ST dvb;
472 } *p = (void *) (phdr + 1);
473 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
474 &client->sms_stat_dvb.ReceptionData;
475 732
733 /* Only for ISDB-T */
734 case MSG_SMS_GET_STATISTICS_EX_RES:
735 smsdvb_update_isdbt_stats_ex(client, p);
476 is_status_update = true; 736 is_status_update = true;
477
478 switch (smscore_get_device_mode(client->coredev)) {
479 case DEVICE_MODE_ISDBT:
480 case DEVICE_MODE_ISDBT_BDA:
481 smsdvb_update_isdbt_stats_ex(pReceptionData, &p->isdbt);
482 break;
483 default:
484 smsdvb_update_dvb_stats(pReceptionData, &p->dvb);
485 }
486 if (!pReceptionData->IsDemodLocked) {
487 pReceptionData->SNR = 0;
488 pReceptionData->BER = 0;
489 pReceptionData->BERErrorCount = 0;
490 pReceptionData->InBandPwr = 0;
491 pReceptionData->ErrorTSPackets = 0;
492 }
493
494 break; 737 break;
495 }
496 default: 738 default:
497 sms_info("message not handled"); 739 sms_info("message not handled");
498 } 740 }
499 smscore_putbuffer(client->coredev, cb); 741 smscore_putbuffer(client->coredev, cb);
500 742
501 if (is_status_update) { 743 if (is_status_update) {
502 if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) { 744 if (client->fe_status == FE_HAS_LOCK) {
503 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
504 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
505 sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); 745 sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
506 if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets 746 if (client->last_per == c->block_error.stat[0].uvalue)
507 == 0)
508 sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); 747 sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
509 else 748 else
510 sms_board_dvb3_event(client, 749 sms_board_dvb3_event(client, DVB3_EVENT_UNC_ERR);
511 DVB3_EVENT_UNC_ERR);
512
513 } else { 750 } else {
514 if (client->sms_stat_dvb.ReceptionData.IsRfLocked) 751 smsdvb_stats_not_ready(fe);
515 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER; 752
516 else
517 client->fe_status = 0;
518 sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); 753 sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
519 } 754 }
520 complete(&client->stats_done); 755 complete(&client->stats_done);
@@ -612,13 +847,20 @@ static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
612 Msg.msgFlags = 0; 847 Msg.msgFlags = 0;
613 Msg.msgLength = sizeof(Msg); 848 Msg.msgLength = sizeof(Msg);
614 849
615 /* 850 switch (smscore_get_device_mode(client->coredev)) {
616 * Check for firmware version, to avoid breaking for old cards 851 case DEVICE_MODE_ISDBT:
617 */ 852 case DEVICE_MODE_ISDBT_BDA:
618 if (client->coredev->fw_version >= 0x800) 853 /*
619 Msg.msgType = MSG_SMS_GET_STATISTICS_EX_REQ; 854 * Check for firmware version, to avoid breaking for old cards
620 else 855 */
856 if (client->coredev->fw_version >= 0x800)
857 Msg.msgType = MSG_SMS_GET_STATISTICS_EX_REQ;
858 else
859 Msg.msgType = MSG_SMS_GET_STATISTICS_REQ;
860 break;
861 default:
621 Msg.msgType = MSG_SMS_GET_STATISTICS_REQ; 862 Msg.msgType = MSG_SMS_GET_STATISTICS_REQ;
863 }
622 864
623 rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), 865 rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
624 &client->stats_done); 866 &client->stats_done);
@@ -628,12 +870,12 @@ static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
628 870
629static inline int led_feedback(struct smsdvb_client_t *client) 871static inline int led_feedback(struct smsdvb_client_t *client)
630{ 872{
631 if (client->fe_status & FE_HAS_LOCK) 873 if (!(client->fe_status & FE_HAS_LOCK))
632 return sms_board_led_feedback(client->coredev,
633 (client->sms_stat_dvb.ReceptionData.BER
634 == 0) ? SMS_LED_HI : SMS_LED_LO);
635 else
636 return sms_board_led_feedback(client->coredev, SMS_LED_OFF); 874 return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
875
876 return sms_board_led_feedback(client->coredev,
877 (client->legacy_ber == 0) ?
878 SMS_LED_HI : SMS_LED_LO);
637} 879}
638 880
639static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) 881static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
@@ -655,11 +897,12 @@ static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
655{ 897{
656 int rc; 898 int rc;
657 struct smsdvb_client_t *client; 899 struct smsdvb_client_t *client;
900
658 client = container_of(fe, struct smsdvb_client_t, frontend); 901 client = container_of(fe, struct smsdvb_client_t, frontend);
659 902
660 rc = smsdvb_send_statistics_request(client); 903 rc = smsdvb_send_statistics_request(client);
661 904
662 *ber = client->sms_stat_dvb.ReceptionData.BER; 905 *ber = client->legacy_ber;
663 906
664 led_feedback(client); 907 led_feedback(client);
665 908
@@ -668,21 +911,21 @@ static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
668 911
669static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 912static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
670{ 913{
914 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
671 int rc; 915 int rc;
672 916 s32 power = (s32) c->strength.stat[0].uvalue;
673 struct smsdvb_client_t *client; 917 struct smsdvb_client_t *client;
918
674 client = container_of(fe, struct smsdvb_client_t, frontend); 919 client = container_of(fe, struct smsdvb_client_t, frontend);
675 920
676 rc = smsdvb_send_statistics_request(client); 921 rc = smsdvb_send_statistics_request(client);
677 922
678 if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) 923 if (power < -95)
679 *strength = 0; 924 *strength = 0;
680 else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) 925 else if (power > -29)
681 *strength = 100; 926 *strength = 65535;
682 else 927 else
683 *strength = 928 *strength = (power + 95) * 65535 / 66;
684 (client->sms_stat_dvb.ReceptionData.InBandPwr
685 + 95) * 3 / 2;
686 929
687 led_feedback(client); 930 led_feedback(client);
688 931
@@ -691,13 +934,16 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
691 934
692static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) 935static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
693{ 936{
937 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
694 int rc; 938 int rc;
695 struct smsdvb_client_t *client; 939 struct smsdvb_client_t *client;
940
696 client = container_of(fe, struct smsdvb_client_t, frontend); 941 client = container_of(fe, struct smsdvb_client_t, frontend);
697 942
698 rc = smsdvb_send_statistics_request(client); 943 rc = smsdvb_send_statistics_request(client);
699 944
700 *snr = client->sms_stat_dvb.ReceptionData.SNR; 945 /* Preferred scale for SNR with legacy API: 0.1 dB */
946 *snr = c->cnr.stat[0].svalue / 100;
701 947
702 led_feedback(client); 948 led_feedback(client);
703 949
@@ -707,12 +953,14 @@ static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
707static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 953static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
708{ 954{
709 int rc; 955 int rc;
956 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
710 struct smsdvb_client_t *client; 957 struct smsdvb_client_t *client;
958
711 client = container_of(fe, struct smsdvb_client_t, frontend); 959 client = container_of(fe, struct smsdvb_client_t, frontend);
712 960
713 rc = smsdvb_send_statistics_request(client); 961 rc = smsdvb_send_statistics_request(client);
714 962
715 *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; 963 *ucblocks = c->block_error.stat[0].uvalue;
716 964
717 led_feedback(client); 965 led_feedback(client);
718 966
@@ -743,7 +991,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
743 991
744 int ret; 992 int ret;
745 993
746 client->fe_status = FE_HAS_SIGNAL; 994 client->fe_status = 0;
747 client->event_fe_state = -1; 995 client->event_fe_state = -1;
748 client->event_unc_state = -1; 996 client->event_unc_state = -1;
749 fe->dtv_property_cache.delivery_system = SYS_DVBT; 997 fe->dtv_property_cache.delivery_system = SYS_DVBT;
@@ -871,6 +1119,8 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe)
871 container_of(fe, struct smsdvb_client_t, frontend); 1119 container_of(fe, struct smsdvb_client_t, frontend);
872 struct smscore_device_t *coredev = client->coredev; 1120 struct smscore_device_t *coredev = client->coredev;
873 1121
1122 smsdvb_stats_not_ready(fe);
1123
874 switch (smscore_get_device_mode(coredev)) { 1124 switch (smscore_get_device_mode(coredev)) {
875 case DEVICE_MODE_DVBT: 1125 case DEVICE_MODE_DVBT:
876 case DEVICE_MODE_DVBT_BDA: 1126 case DEVICE_MODE_DVBT_BDA:
@@ -883,150 +1133,10 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe)
883 } 1133 }
884} 1134}
885 1135
886static int smsdvb_get_frontend_dvb(struct dvb_frontend *fe) 1136/* Nothing to do here, as stats are automatically updated */
887{
888 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
889 struct smsdvb_client_t *client =
890 container_of(fe, struct smsdvb_client_t, frontend);
891 struct TRANSMISSION_STATISTICS_S *td =
892 &client->sms_stat_dvb.TransmissionData;
893
894 fep->frequency = td->Frequency;
895
896 switch (td->Bandwidth) {
897 case 6:
898 fep->bandwidth_hz = 6000000;
899 break;
900 case 7:
901 fep->bandwidth_hz = 7000000;
902 break;
903 case 8:
904 fep->bandwidth_hz = 8000000;
905 break;
906 }
907
908 switch (td->TransmissionMode) {
909 case 2:
910 fep->transmission_mode = TRANSMISSION_MODE_2K;
911 break;
912 case 8:
913 fep->transmission_mode = TRANSMISSION_MODE_8K;
914 }
915
916 switch (td->GuardInterval) {
917 case 0:
918 fep->guard_interval = GUARD_INTERVAL_1_32;
919 break;
920 case 1:
921 fep->guard_interval = GUARD_INTERVAL_1_16;
922 break;
923 case 2:
924 fep->guard_interval = GUARD_INTERVAL_1_8;
925 break;
926 case 3:
927 fep->guard_interval = GUARD_INTERVAL_1_4;
928 break;
929 }
930
931 switch (td->CodeRate) {
932 case 0:
933 fep->code_rate_HP = FEC_1_2;
934 break;
935 case 1:
936 fep->code_rate_HP = FEC_2_3;
937 break;
938 case 2:
939 fep->code_rate_HP = FEC_3_4;
940 break;
941 case 3:
942 fep->code_rate_HP = FEC_5_6;
943 break;
944 case 4:
945 fep->code_rate_HP = FEC_7_8;
946 break;
947 }
948
949 switch (td->LPCodeRate) {
950 case 0:
951 fep->code_rate_LP = FEC_1_2;
952 break;
953 case 1:
954 fep->code_rate_LP = FEC_2_3;
955 break;
956 case 2:
957 fep->code_rate_LP = FEC_3_4;
958 break;
959 case 3:
960 fep->code_rate_LP = FEC_5_6;
961 break;
962 case 4:
963 fep->code_rate_LP = FEC_7_8;
964 break;
965 }
966
967 switch (td->Constellation) {
968 case 0:
969 fep->modulation = QPSK;
970 break;
971 case 1:
972 fep->modulation = QAM_16;
973 break;
974 case 2:
975 fep->modulation = QAM_64;
976 break;
977 }
978
979 switch (td->Hierarchy) {
980 case 0:
981 fep->hierarchy = HIERARCHY_NONE;
982 break;
983 case 1:
984 fep->hierarchy = HIERARCHY_1;
985 break;
986 case 2:
987 fep->hierarchy = HIERARCHY_2;
988 break;
989 case 3:
990 fep->hierarchy = HIERARCHY_4;
991 break;
992 }
993
994 fep->inversion = INVERSION_AUTO;
995
996 return 0;
997}
998
999static int smsdvb_get_frontend_isdb(struct dvb_frontend *fe)
1000{
1001 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
1002 struct smsdvb_client_t *client =
1003 container_of(fe, struct smsdvb_client_t, frontend);
1004 struct TRANSMISSION_STATISTICS_S *td =
1005 &client->sms_stat_dvb.TransmissionData;
1006
1007 fep->frequency = td->Frequency;
1008 fep->bandwidth_hz = 6000000;
1009 /* todo: retrive the other parameters */
1010
1011 return 0;
1012}
1013
1014static int smsdvb_get_frontend(struct dvb_frontend *fe) 1137static int smsdvb_get_frontend(struct dvb_frontend *fe)
1015{ 1138{
1016 struct smsdvb_client_t *client = 1139 return 0;
1017 container_of(fe, struct smsdvb_client_t, frontend);
1018 struct smscore_device_t *coredev = client->coredev;
1019
1020 switch (smscore_get_device_mode(coredev)) {
1021 case DEVICE_MODE_DVBT:
1022 case DEVICE_MODE_DVBT_BDA:
1023 return smsdvb_get_frontend_dvb(fe);
1024 case DEVICE_MODE_ISDBT:
1025 case DEVICE_MODE_ISDBT_BDA:
1026 return smsdvb_get_frontend_isdb(fe);
1027 default:
1028 return -EINVAL;
1029 }
1030} 1140}
1031 1141
1032static int smsdvb_init(struct dvb_frontend *fe) 1142static int smsdvb_init(struct dvb_frontend *fe)