0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "smscoreapi.h"
0012
0013 #include <linux/module.h>
0014 #include <linux/slab.h>
0015 #include <linux/init.h>
0016 #include <asm/div64.h>
0017
0018 #include <media/dmxdev.h>
0019 #include <media/dvbdev.h>
0020 #include <media/dvb_demux.h>
0021 #include <media/dvb_frontend.h>
0022
0023 #include "sms-cards.h"
0024
0025 #include "smsdvb.h"
0026
0027 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0028
0029 static LIST_HEAD(g_smsdvb_clients);
0030 static DEFINE_MUTEX(g_smsdvb_clientslock);
0031
0032 static u32 sms_to_guard_interval_table[] = {
0033 [0] = GUARD_INTERVAL_1_32,
0034 [1] = GUARD_INTERVAL_1_16,
0035 [2] = GUARD_INTERVAL_1_8,
0036 [3] = GUARD_INTERVAL_1_4,
0037 };
0038
0039 static u32 sms_to_code_rate_table[] = {
0040 [0] = FEC_1_2,
0041 [1] = FEC_2_3,
0042 [2] = FEC_3_4,
0043 [3] = FEC_5_6,
0044 [4] = FEC_7_8,
0045 };
0046
0047
0048 static u32 sms_to_hierarchy_table[] = {
0049 [0] = HIERARCHY_NONE,
0050 [1] = HIERARCHY_1,
0051 [2] = HIERARCHY_2,
0052 [3] = HIERARCHY_4,
0053 };
0054
0055 static u32 sms_to_modulation_table[] = {
0056 [0] = QPSK,
0057 [1] = QAM_16,
0058 [2] = QAM_64,
0059 [3] = DQPSK,
0060 };
0061
0062
0063
0064 static void sms_board_dvb3_event(struct smsdvb_client_t *client,
0065 enum SMS_DVB3_EVENTS event) {
0066
0067 struct smscore_device_t *coredev = client->coredev;
0068 switch (event) {
0069 case DVB3_EVENT_INIT:
0070 pr_debug("DVB3_EVENT_INIT\n");
0071 sms_board_event(coredev, BOARD_EVENT_BIND);
0072 break;
0073 case DVB3_EVENT_SLEEP:
0074 pr_debug("DVB3_EVENT_SLEEP\n");
0075 sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
0076 break;
0077 case DVB3_EVENT_HOTPLUG:
0078 pr_debug("DVB3_EVENT_HOTPLUG\n");
0079 sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
0080 break;
0081 case DVB3_EVENT_FE_LOCK:
0082 if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
0083 client->event_fe_state = DVB3_EVENT_FE_LOCK;
0084 pr_debug("DVB3_EVENT_FE_LOCK\n");
0085 sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
0086 }
0087 break;
0088 case DVB3_EVENT_FE_UNLOCK:
0089 if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
0090 client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
0091 pr_debug("DVB3_EVENT_FE_UNLOCK\n");
0092 sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
0093 }
0094 break;
0095 case DVB3_EVENT_UNC_OK:
0096 if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
0097 client->event_unc_state = DVB3_EVENT_UNC_OK;
0098 pr_debug("DVB3_EVENT_UNC_OK\n");
0099 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
0100 }
0101 break;
0102 case DVB3_EVENT_UNC_ERR:
0103 if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
0104 client->event_unc_state = DVB3_EVENT_UNC_ERR;
0105 pr_debug("DVB3_EVENT_UNC_ERR\n");
0106 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
0107 }
0108 break;
0109
0110 default:
0111 pr_err("Unknown dvb3 api event\n");
0112 break;
0113 }
0114 }
0115
0116 static void smsdvb_stats_not_ready(struct dvb_frontend *fe)
0117 {
0118 struct smsdvb_client_t *client =
0119 container_of(fe, struct smsdvb_client_t, frontend);
0120 struct smscore_device_t *coredev = client->coredev;
0121 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0122 int i, n_layers;
0123
0124 switch (smscore_get_device_mode(coredev)) {
0125 case DEVICE_MODE_ISDBT:
0126 case DEVICE_MODE_ISDBT_BDA:
0127 n_layers = 4;
0128 break;
0129 default:
0130 n_layers = 1;
0131 }
0132
0133
0134 c->strength.len = 1;
0135 c->cnr.len = 1;
0136 c->strength.stat[0].scale = FE_SCALE_DECIBEL;
0137 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
0138
0139
0140 c->post_bit_error.len = n_layers;
0141 c->post_bit_count.len = n_layers;
0142 c->block_error.len = n_layers;
0143 c->block_count.len = n_layers;
0144
0145
0146
0147
0148
0149 for (i = 0; i < n_layers; i++) {
0150 c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
0151 c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
0152 c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
0153 c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
0154 }
0155 }
0156
0157 static inline int sms_to_mode(u32 mode)
0158 {
0159 switch (mode) {
0160 case 2:
0161 return TRANSMISSION_MODE_2K;
0162 case 4:
0163 return TRANSMISSION_MODE_4K;
0164 case 8:
0165 return TRANSMISSION_MODE_8K;
0166 }
0167 return TRANSMISSION_MODE_AUTO;
0168 }
0169
0170 static inline int sms_to_isdbt_mode(u32 mode)
0171 {
0172 switch (mode) {
0173 case 1:
0174 return TRANSMISSION_MODE_2K;
0175 case 2:
0176 return TRANSMISSION_MODE_4K;
0177 case 3:
0178 return TRANSMISSION_MODE_8K;
0179 }
0180 return TRANSMISSION_MODE_AUTO;
0181 }
0182
0183 static inline int sms_to_isdbt_guard_interval(u32 interval)
0184 {
0185 switch (interval) {
0186 case 4:
0187 return GUARD_INTERVAL_1_4;
0188 case 8:
0189 return GUARD_INTERVAL_1_8;
0190 case 16:
0191 return GUARD_INTERVAL_1_16;
0192 case 32:
0193 return GUARD_INTERVAL_1_32;
0194 }
0195 return GUARD_INTERVAL_AUTO;
0196 }
0197
0198 static inline int sms_to_status(u32 is_demod_locked, u32 is_rf_locked)
0199 {
0200 if (is_demod_locked)
0201 return FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
0202 FE_HAS_SYNC | FE_HAS_LOCK;
0203
0204 if (is_rf_locked)
0205 return FE_HAS_SIGNAL | FE_HAS_CARRIER;
0206
0207 return 0;
0208 }
0209
0210 static inline u32 sms_to_bw(u32 value)
0211 {
0212 return value * 1000000;
0213 }
0214
0215 #define convert_from_table(value, table, defval) ({ \
0216 u32 __ret; \
0217 if (value < ARRAY_SIZE(table)) \
0218 __ret = table[value]; \
0219 else \
0220 __ret = defval; \
0221 __ret; \
0222 })
0223
0224 #define sms_to_guard_interval(value) \
0225 convert_from_table(value, sms_to_guard_interval_table, \
0226 GUARD_INTERVAL_AUTO);
0227
0228 #define sms_to_code_rate(value) \
0229 convert_from_table(value, sms_to_code_rate_table, \
0230 FEC_NONE);
0231
0232 #define sms_to_hierarchy(value) \
0233 convert_from_table(value, sms_to_hierarchy_table, \
0234 FEC_NONE);
0235
0236 #define sms_to_modulation(value) \
0237 convert_from_table(value, sms_to_modulation_table, \
0238 FEC_NONE);
0239
0240 static void smsdvb_update_tx_params(struct smsdvb_client_t *client,
0241 struct sms_tx_stats *p)
0242 {
0243 struct dvb_frontend *fe = &client->frontend;
0244 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0245
0246 c->frequency = p->frequency;
0247 client->fe_status = sms_to_status(p->is_demod_locked, 0);
0248 c->bandwidth_hz = sms_to_bw(p->bandwidth);
0249 c->transmission_mode = sms_to_mode(p->transmission_mode);
0250 c->guard_interval = sms_to_guard_interval(p->guard_interval);
0251 c->code_rate_HP = sms_to_code_rate(p->code_rate);
0252 c->code_rate_LP = sms_to_code_rate(p->lp_code_rate);
0253 c->hierarchy = sms_to_hierarchy(p->hierarchy);
0254 c->modulation = sms_to_modulation(p->constellation);
0255 }
0256
0257 static void smsdvb_update_per_slices(struct smsdvb_client_t *client,
0258 struct RECEPTION_STATISTICS_PER_SLICES_S *p)
0259 {
0260 struct dvb_frontend *fe = &client->frontend;
0261 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0262 u64 tmp;
0263
0264 client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
0265 c->modulation = sms_to_modulation(p->constellation);
0266
0267
0268 c->strength.stat[0].uvalue = p->in_band_power * 1000;
0269
0270
0271 c->cnr.stat[0].svalue = p->snr * 1000;
0272
0273
0274 if (!p->is_demod_locked)
0275 return;
0276
0277
0278 client->last_per = c->block_error.stat[0].uvalue;
0279 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
0280 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
0281 c->block_error.stat[0].uvalue += p->ets_packets;
0282 c->block_count.stat[0].uvalue += p->ets_packets + p->ts_packets;
0283
0284
0285 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
0286 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
0287 c->post_bit_error.stat[0].uvalue += p->ber_error_count;
0288 c->post_bit_count.stat[0].uvalue += p->ber_bit_count;
0289
0290
0291 tmp = p->ets_packets * 65535ULL;
0292 if (p->ts_packets + p->ets_packets)
0293 do_div(tmp, p->ts_packets + p->ets_packets);
0294 client->legacy_per = tmp;
0295 }
0296
0297 static void smsdvb_update_dvb_stats(struct smsdvb_client_t *client,
0298 struct sms_stats *p)
0299 {
0300 struct dvb_frontend *fe = &client->frontend;
0301 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0302
0303 if (client->prt_dvb_stats)
0304 client->prt_dvb_stats(client->debug_data, p);
0305
0306 client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
0307
0308
0309 c->frequency = p->frequency;
0310 client->fe_status = sms_to_status(p->is_demod_locked, 0);
0311 c->bandwidth_hz = sms_to_bw(p->bandwidth);
0312 c->transmission_mode = sms_to_mode(p->transmission_mode);
0313 c->guard_interval = sms_to_guard_interval(p->guard_interval);
0314 c->code_rate_HP = sms_to_code_rate(p->code_rate);
0315 c->code_rate_LP = sms_to_code_rate(p->lp_code_rate);
0316 c->hierarchy = sms_to_hierarchy(p->hierarchy);
0317 c->modulation = sms_to_modulation(p->constellation);
0318
0319
0320 c->lna = p->is_external_lna_on ? 1 : 0;
0321
0322
0323 c->cnr.stat[0].svalue = p->SNR * 1000;
0324
0325
0326 c->strength.stat[0].uvalue = p->in_band_pwr * 1000;
0327
0328
0329 if (!p->is_demod_locked)
0330 return;
0331
0332
0333 client->last_per = c->block_error.stat[0].uvalue;
0334 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
0335 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
0336 c->block_error.stat[0].uvalue += p->error_ts_packets;
0337 c->block_count.stat[0].uvalue += p->total_ts_packets;
0338
0339
0340 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
0341 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
0342 c->post_bit_error.stat[0].uvalue += p->ber_error_count;
0343 c->post_bit_count.stat[0].uvalue += p->ber_bit_count;
0344
0345
0346 client->legacy_ber = p->ber;
0347 };
0348
0349 static void smsdvb_update_isdbt_stats(struct smsdvb_client_t *client,
0350 struct sms_isdbt_stats *p)
0351 {
0352 struct dvb_frontend *fe = &client->frontend;
0353 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0354 struct sms_isdbt_layer_stats *lr;
0355 int i, n_layers;
0356
0357 if (client->prt_isdb_stats)
0358 client->prt_isdb_stats(client->debug_data, p);
0359
0360 client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
0361
0362
0363
0364
0365
0366
0367 if (p->statistics_type == 0) {
0368 c->strength.stat[0].uvalue = ((s32)p->transmission_mode) * 1000;
0369 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
0370 return;
0371 }
0372
0373
0374 c->frequency = p->frequency;
0375 c->bandwidth_hz = sms_to_bw(p->bandwidth);
0376 c->transmission_mode = sms_to_isdbt_mode(p->transmission_mode);
0377 c->guard_interval = sms_to_isdbt_guard_interval(p->guard_interval);
0378 c->isdbt_partial_reception = p->partial_reception ? 1 : 0;
0379 n_layers = p->num_of_layers;
0380 if (n_layers < 1)
0381 n_layers = 1;
0382 if (n_layers > 3)
0383 n_layers = 3;
0384 c->isdbt_layer_enabled = 0;
0385
0386
0387 c->lna = p->is_external_lna_on ? 1 : 0;
0388
0389
0390 c->cnr.stat[0].svalue = p->SNR * 1000;
0391
0392
0393 c->strength.stat[0].uvalue = p->in_band_pwr * 1000;
0394
0395
0396 if (!p->is_demod_locked)
0397 return;
0398
0399 client->last_per = c->block_error.stat[0].uvalue;
0400
0401
0402 c->block_error.stat[0].uvalue = 0;
0403 c->block_count.stat[0].uvalue = 0;
0404 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
0405 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
0406 c->post_bit_error.stat[0].uvalue = 0;
0407 c->post_bit_count.stat[0].uvalue = 0;
0408 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
0409 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
0410
0411 for (i = 0; i < n_layers; i++) {
0412 lr = &p->layer_info[i];
0413
0414
0415 if (lr->number_of_segments > 0 && lr->number_of_segments < 13) {
0416 c->isdbt_layer_enabled |= 1 << i;
0417 c->layer[i].segment_count = lr->number_of_segments;
0418 } else {
0419 continue;
0420 }
0421 c->layer[i].modulation = sms_to_modulation(lr->constellation);
0422 c->layer[i].fec = sms_to_code_rate(lr->code_rate);
0423
0424
0425 c->layer[i].interleaving = (u8)lr->ti_ldepth_i;
0426
0427
0428 c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER;
0429 c->block_count.stat[i + 1].scale = FE_SCALE_COUNTER;
0430 c->block_error.stat[i + 1].uvalue += lr->error_ts_packets;
0431 c->block_count.stat[i + 1].uvalue += lr->total_ts_packets;
0432
0433
0434 c->block_error.stat[0].uvalue += lr->error_ts_packets;
0435 c->block_count.stat[0].uvalue += lr->total_ts_packets;
0436
0437
0438 c->post_bit_error.stat[i + 1].scale = FE_SCALE_COUNTER;
0439 c->post_bit_count.stat[i + 1].scale = FE_SCALE_COUNTER;
0440 c->post_bit_error.stat[i + 1].uvalue += lr->ber_error_count;
0441 c->post_bit_count.stat[i + 1].uvalue += lr->ber_bit_count;
0442
0443
0444 c->post_bit_error.stat[0].uvalue += lr->ber_error_count;
0445 c->post_bit_count.stat[0].uvalue += lr->ber_bit_count;
0446 }
0447 }
0448
0449 static void smsdvb_update_isdbt_stats_ex(struct smsdvb_client_t *client,
0450 struct sms_isdbt_stats_ex *p)
0451 {
0452 struct dvb_frontend *fe = &client->frontend;
0453 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0454 struct sms_isdbt_layer_stats *lr;
0455 int i, n_layers;
0456
0457 if (client->prt_isdb_stats_ex)
0458 client->prt_isdb_stats_ex(client->debug_data, p);
0459
0460
0461 c->frequency = p->frequency;
0462 client->fe_status = sms_to_status(p->is_demod_locked, 0);
0463 c->bandwidth_hz = sms_to_bw(p->bandwidth);
0464 c->transmission_mode = sms_to_isdbt_mode(p->transmission_mode);
0465 c->guard_interval = sms_to_isdbt_guard_interval(p->guard_interval);
0466 c->isdbt_partial_reception = p->partial_reception ? 1 : 0;
0467 n_layers = p->num_of_layers;
0468 if (n_layers < 1)
0469 n_layers = 1;
0470 if (n_layers > 3)
0471 n_layers = 3;
0472 c->isdbt_layer_enabled = 0;
0473
0474
0475 c->lna = p->is_external_lna_on ? 1 : 0;
0476
0477
0478 c->cnr.stat[0].svalue = p->SNR * 1000;
0479
0480
0481 c->strength.stat[0].uvalue = p->in_band_pwr * 1000;
0482
0483
0484 if (!p->is_demod_locked)
0485 return;
0486
0487 client->last_per = c->block_error.stat[0].uvalue;
0488
0489
0490 c->block_error.stat[0].uvalue = 0;
0491 c->block_count.stat[0].uvalue = 0;
0492 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
0493 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
0494 c->post_bit_error.stat[0].uvalue = 0;
0495 c->post_bit_count.stat[0].uvalue = 0;
0496 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
0497 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
0498
0499 c->post_bit_error.len = n_layers + 1;
0500 c->post_bit_count.len = n_layers + 1;
0501 c->block_error.len = n_layers + 1;
0502 c->block_count.len = n_layers + 1;
0503 for (i = 0; i < n_layers; i++) {
0504 lr = &p->layer_info[i];
0505
0506
0507 if (lr->number_of_segments > 0 && lr->number_of_segments < 13) {
0508 c->isdbt_layer_enabled |= 1 << i;
0509 c->layer[i].segment_count = lr->number_of_segments;
0510 } else {
0511 continue;
0512 }
0513 c->layer[i].modulation = sms_to_modulation(lr->constellation);
0514 c->layer[i].fec = sms_to_code_rate(lr->code_rate);
0515
0516
0517 c->layer[i].interleaving = (u8)lr->ti_ldepth_i;
0518
0519
0520 c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER;
0521 c->block_count.stat[i + 1].scale = FE_SCALE_COUNTER;
0522 c->block_error.stat[i + 1].uvalue += lr->error_ts_packets;
0523 c->block_count.stat[i + 1].uvalue += lr->total_ts_packets;
0524
0525
0526 c->block_error.stat[0].uvalue += lr->error_ts_packets;
0527 c->block_count.stat[0].uvalue += lr->total_ts_packets;
0528
0529
0530 c->post_bit_error.stat[i + 1].scale = FE_SCALE_COUNTER;
0531 c->post_bit_count.stat[i + 1].scale = FE_SCALE_COUNTER;
0532 c->post_bit_error.stat[i + 1].uvalue += lr->ber_error_count;
0533 c->post_bit_count.stat[i + 1].uvalue += lr->ber_bit_count;
0534
0535
0536 c->post_bit_error.stat[0].uvalue += lr->ber_error_count;
0537 c->post_bit_count.stat[0].uvalue += lr->ber_bit_count;
0538 }
0539 }
0540
0541 static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
0542 {
0543 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
0544 struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) (((u8 *) cb->p)
0545 + cb->offset);
0546 void *p = phdr + 1;
0547 struct dvb_frontend *fe = &client->frontend;
0548 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0549 bool is_status_update = false;
0550
0551 switch (phdr->msg_type) {
0552 case MSG_SMS_DVBT_BDA_DATA:
0553
0554
0555
0556
0557 if (client->feed_users && client->has_tuned)
0558 dvb_dmx_swfilter(&client->demux, p,
0559 cb->size - sizeof(struct sms_msg_hdr));
0560 break;
0561
0562 case MSG_SMS_RF_TUNE_RES:
0563 case MSG_SMS_ISDBT_TUNE_RES:
0564 complete(&client->tune_done);
0565 break;
0566
0567 case MSG_SMS_SIGNAL_DETECTED_IND:
0568 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
0569 FE_HAS_VITERBI | FE_HAS_SYNC |
0570 FE_HAS_LOCK;
0571
0572 is_status_update = true;
0573 break;
0574
0575 case MSG_SMS_NO_SIGNAL_IND:
0576 client->fe_status = 0;
0577
0578 is_status_update = true;
0579 break;
0580
0581 case MSG_SMS_TRANSMISSION_IND:
0582 smsdvb_update_tx_params(client, p);
0583
0584 is_status_update = true;
0585 break;
0586
0587 case MSG_SMS_HO_PER_SLICES_IND:
0588 smsdvb_update_per_slices(client, p);
0589
0590 is_status_update = true;
0591 break;
0592
0593 case MSG_SMS_GET_STATISTICS_RES:
0594 switch (smscore_get_device_mode(client->coredev)) {
0595 case DEVICE_MODE_ISDBT:
0596 case DEVICE_MODE_ISDBT_BDA:
0597 smsdvb_update_isdbt_stats(client, p);
0598 break;
0599 default:
0600
0601 smsdvb_update_dvb_stats(client, p + sizeof(u32));
0602 }
0603
0604 is_status_update = true;
0605 break;
0606
0607
0608 case MSG_SMS_GET_STATISTICS_EX_RES:
0609
0610 smsdvb_update_isdbt_stats_ex(client, p + sizeof(u32));
0611 is_status_update = true;
0612 break;
0613 default:
0614 pr_debug("message not handled\n");
0615 }
0616 smscore_putbuffer(client->coredev, cb);
0617
0618 if (is_status_update) {
0619 if (client->fe_status & FE_HAS_LOCK) {
0620 sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
0621 if (client->last_per == c->block_error.stat[0].uvalue)
0622 sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
0623 else
0624 sms_board_dvb3_event(client, DVB3_EVENT_UNC_ERR);
0625 client->has_tuned = true;
0626 } else {
0627 smsdvb_stats_not_ready(fe);
0628 client->has_tuned = false;
0629 sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
0630 }
0631 complete(&client->stats_done);
0632 }
0633
0634 return 0;
0635 }
0636
0637 static void smsdvb_media_device_unregister(struct smsdvb_client_t *client)
0638 {
0639 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
0640 struct smscore_device_t *coredev = client->coredev;
0641
0642 if (!coredev->media_dev)
0643 return;
0644 media_device_unregister(coredev->media_dev);
0645 media_device_cleanup(coredev->media_dev);
0646 kfree(coredev->media_dev);
0647 coredev->media_dev = NULL;
0648 #endif
0649 }
0650
0651 static void smsdvb_unregister_client(struct smsdvb_client_t *client)
0652 {
0653
0654
0655 list_del(&client->entry);
0656
0657 smsdvb_debugfs_release(client);
0658 smscore_unregister_client(client->smsclient);
0659 dvb_unregister_frontend(&client->frontend);
0660 dvb_dmxdev_release(&client->dmxdev);
0661 dvb_dmx_release(&client->demux);
0662 smsdvb_media_device_unregister(client);
0663 dvb_unregister_adapter(&client->adapter);
0664 kfree(client);
0665 }
0666
0667 static void smsdvb_onremove(void *context)
0668 {
0669 mutex_lock(&g_smsdvb_clientslock);
0670
0671 smsdvb_unregister_client((struct smsdvb_client_t *) context);
0672
0673 mutex_unlock(&g_smsdvb_clientslock);
0674 }
0675
0676 static int smsdvb_start_feed(struct dvb_demux_feed *feed)
0677 {
0678 struct smsdvb_client_t *client =
0679 container_of(feed->demux, struct smsdvb_client_t, demux);
0680 struct sms_msg_data pid_msg;
0681
0682 pr_debug("add pid %d(%x)\n",
0683 feed->pid, feed->pid);
0684
0685 client->feed_users++;
0686
0687 pid_msg.x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
0688 pid_msg.x_msg_header.msg_dst_id = HIF_TASK;
0689 pid_msg.x_msg_header.msg_flags = 0;
0690 pid_msg.x_msg_header.msg_type = MSG_SMS_ADD_PID_FILTER_REQ;
0691 pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
0692 pid_msg.msg_data[0] = feed->pid;
0693
0694 return smsclient_sendrequest(client->smsclient,
0695 &pid_msg, sizeof(pid_msg));
0696 }
0697
0698 static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
0699 {
0700 struct smsdvb_client_t *client =
0701 container_of(feed->demux, struct smsdvb_client_t, demux);
0702 struct sms_msg_data pid_msg;
0703
0704 pr_debug("remove pid %d(%x)\n",
0705 feed->pid, feed->pid);
0706
0707 client->feed_users--;
0708
0709 pid_msg.x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
0710 pid_msg.x_msg_header.msg_dst_id = HIF_TASK;
0711 pid_msg.x_msg_header.msg_flags = 0;
0712 pid_msg.x_msg_header.msg_type = MSG_SMS_REMOVE_PID_FILTER_REQ;
0713 pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
0714 pid_msg.msg_data[0] = feed->pid;
0715
0716 return smsclient_sendrequest(client->smsclient,
0717 &pid_msg, sizeof(pid_msg));
0718 }
0719
0720 static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
0721 void *buffer, size_t size,
0722 struct completion *completion)
0723 {
0724 int rc;
0725
0726 rc = smsclient_sendrequest(client->smsclient, buffer, size);
0727 if (rc < 0)
0728 return rc;
0729
0730 return wait_for_completion_timeout(completion,
0731 msecs_to_jiffies(2000)) ?
0732 0 : -ETIME;
0733 }
0734
0735 static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
0736 {
0737 int rc;
0738 struct sms_msg_hdr msg;
0739
0740
0741 if (client->get_stats_jiffies &&
0742 (!time_after(jiffies, client->get_stats_jiffies)))
0743 return 0;
0744 client->get_stats_jiffies = jiffies + msecs_to_jiffies(100);
0745
0746 msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
0747 msg.msg_dst_id = HIF_TASK;
0748 msg.msg_flags = 0;
0749 msg.msg_length = sizeof(msg);
0750
0751 switch (smscore_get_device_mode(client->coredev)) {
0752 case DEVICE_MODE_ISDBT:
0753 case DEVICE_MODE_ISDBT_BDA:
0754
0755
0756
0757 if (client->coredev->fw_version >= 0x800)
0758 msg.msg_type = MSG_SMS_GET_STATISTICS_EX_REQ;
0759 else
0760 msg.msg_type = MSG_SMS_GET_STATISTICS_REQ;
0761 break;
0762 default:
0763 msg.msg_type = MSG_SMS_GET_STATISTICS_REQ;
0764 }
0765
0766 rc = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
0767 &client->stats_done);
0768
0769 return rc;
0770 }
0771
0772 static inline int led_feedback(struct smsdvb_client_t *client)
0773 {
0774 if (!(client->fe_status & FE_HAS_LOCK))
0775 return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
0776
0777 return sms_board_led_feedback(client->coredev,
0778 (client->legacy_ber == 0) ?
0779 SMS_LED_HI : SMS_LED_LO);
0780 }
0781
0782 static int smsdvb_read_status(struct dvb_frontend *fe, enum fe_status *stat)
0783 {
0784 int rc;
0785 struct smsdvb_client_t *client;
0786 client = container_of(fe, struct smsdvb_client_t, frontend);
0787
0788 rc = smsdvb_send_statistics_request(client);
0789
0790 *stat = client->fe_status;
0791
0792 led_feedback(client);
0793
0794 return rc;
0795 }
0796
0797 static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
0798 {
0799 int rc;
0800 struct smsdvb_client_t *client;
0801
0802 client = container_of(fe, struct smsdvb_client_t, frontend);
0803
0804 rc = smsdvb_send_statistics_request(client);
0805
0806 *ber = client->legacy_ber;
0807
0808 led_feedback(client);
0809
0810 return rc;
0811 }
0812
0813 static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
0814 {
0815 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0816 int rc;
0817 s32 power = (s32) c->strength.stat[0].uvalue;
0818 struct smsdvb_client_t *client;
0819
0820 client = container_of(fe, struct smsdvb_client_t, frontend);
0821
0822 rc = smsdvb_send_statistics_request(client);
0823
0824 if (power < -95)
0825 *strength = 0;
0826 else if (power > -29)
0827 *strength = 65535;
0828 else
0829 *strength = (power + 95) * 65535 / 66;
0830
0831 led_feedback(client);
0832
0833 return rc;
0834 }
0835
0836 static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
0837 {
0838 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0839 int rc;
0840 struct smsdvb_client_t *client;
0841
0842 client = container_of(fe, struct smsdvb_client_t, frontend);
0843
0844 rc = smsdvb_send_statistics_request(client);
0845
0846
0847 *snr = ((u32)c->cnr.stat[0].svalue) / 100;
0848
0849 led_feedback(client);
0850
0851 return rc;
0852 }
0853
0854 static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
0855 {
0856 int rc;
0857 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0858 struct smsdvb_client_t *client;
0859
0860 client = container_of(fe, struct smsdvb_client_t, frontend);
0861
0862 rc = smsdvb_send_statistics_request(client);
0863
0864 *ucblocks = c->block_error.stat[0].uvalue;
0865
0866 led_feedback(client);
0867
0868 return rc;
0869 }
0870
0871 static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
0872 struct dvb_frontend_tune_settings *tune)
0873 {
0874 pr_debug("\n");
0875
0876 tune->min_delay_ms = 400;
0877 tune->step_size = 250000;
0878 tune->max_drift = 0;
0879 return 0;
0880 }
0881
0882 static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
0883 {
0884 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0885 struct smsdvb_client_t *client =
0886 container_of(fe, struct smsdvb_client_t, frontend);
0887
0888 struct {
0889 struct sms_msg_hdr msg;
0890 u32 Data[3];
0891 } msg;
0892
0893 int ret;
0894
0895 client->fe_status = 0;
0896 client->event_fe_state = -1;
0897 client->event_unc_state = -1;
0898 fe->dtv_property_cache.delivery_system = SYS_DVBT;
0899
0900 msg.msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
0901 msg.msg.msg_dst_id = HIF_TASK;
0902 msg.msg.msg_flags = 0;
0903 msg.msg.msg_type = MSG_SMS_RF_TUNE_REQ;
0904 msg.msg.msg_length = sizeof(msg);
0905 msg.Data[0] = c->frequency;
0906 msg.Data[2] = 12000000;
0907
0908 pr_debug("%s: freq %d band %d\n", __func__, c->frequency,
0909 c->bandwidth_hz);
0910
0911 switch (c->bandwidth_hz / 1000000) {
0912 case 8:
0913 msg.Data[1] = BW_8_MHZ;
0914 break;
0915 case 7:
0916 msg.Data[1] = BW_7_MHZ;
0917 break;
0918 case 6:
0919 msg.Data[1] = BW_6_MHZ;
0920 break;
0921 case 0:
0922 return -EOPNOTSUPP;
0923 default:
0924 return -EINVAL;
0925 }
0926
0927 ret = sms_board_lna_control(client->coredev, 0);
0928 if (ret == 0) {
0929 enum fe_status status;
0930
0931
0932 ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
0933 &client->tune_done);
0934
0935 smsdvb_read_status(fe, &status);
0936
0937 if (status & FE_HAS_LOCK)
0938 return ret;
0939
0940
0941 sms_board_lna_control(client->coredev, 1);
0942 }
0943
0944 return smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
0945 &client->tune_done);
0946 }
0947
0948 static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
0949 {
0950 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0951 struct smsdvb_client_t *client =
0952 container_of(fe, struct smsdvb_client_t, frontend);
0953 int board_id = smscore_get_board_id(client->coredev);
0954 struct sms_board *board = sms_get_board(board_id);
0955 enum sms_device_type_st type = board->type;
0956 int ret;
0957
0958 struct {
0959 struct sms_msg_hdr msg;
0960 u32 Data[4];
0961 } msg;
0962
0963 fe->dtv_property_cache.delivery_system = SYS_ISDBT;
0964
0965 msg.msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
0966 msg.msg.msg_dst_id = HIF_TASK;
0967 msg.msg.msg_flags = 0;
0968 msg.msg.msg_type = MSG_SMS_ISDBT_TUNE_REQ;
0969 msg.msg.msg_length = sizeof(msg);
0970
0971 if (c->isdbt_sb_segment_idx == -1)
0972 c->isdbt_sb_segment_idx = 0;
0973
0974 if (!c->isdbt_layer_enabled)
0975 c->isdbt_layer_enabled = 7;
0976
0977 msg.Data[0] = c->frequency;
0978 msg.Data[1] = BW_ISDBT_1SEG;
0979 msg.Data[2] = 12000000;
0980 msg.Data[3] = c->isdbt_sb_segment_idx;
0981
0982 if (c->isdbt_partial_reception) {
0983 if ((type == SMS_PELE || type == SMS_RIO) &&
0984 c->isdbt_sb_segment_count > 3)
0985 msg.Data[1] = BW_ISDBT_13SEG;
0986 else if (c->isdbt_sb_segment_count > 1)
0987 msg.Data[1] = BW_ISDBT_3SEG;
0988 } else if (type == SMS_PELE || type == SMS_RIO)
0989 msg.Data[1] = BW_ISDBT_13SEG;
0990
0991 c->bandwidth_hz = 6000000;
0992
0993 pr_debug("freq %d segwidth %d segindex %d\n",
0994 c->frequency, c->isdbt_sb_segment_count,
0995 c->isdbt_sb_segment_idx);
0996
0997
0998 ret = sms_board_lna_control(client->coredev, 0);
0999 if (ret == 0) {
1000 enum fe_status status;
1001
1002
1003 ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
1004 &client->tune_done);
1005
1006 smsdvb_read_status(fe, &status);
1007
1008 if (status & FE_HAS_LOCK)
1009 return ret;
1010
1011
1012 sms_board_lna_control(client->coredev, 1);
1013 }
1014 return smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
1015 &client->tune_done);
1016 }
1017
1018 static int smsdvb_set_frontend(struct dvb_frontend *fe)
1019 {
1020 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1021 struct smsdvb_client_t *client =
1022 container_of(fe, struct smsdvb_client_t, frontend);
1023 struct smscore_device_t *coredev = client->coredev;
1024
1025 smsdvb_stats_not_ready(fe);
1026 c->strength.stat[0].uvalue = 0;
1027 c->cnr.stat[0].uvalue = 0;
1028
1029 client->has_tuned = false;
1030
1031 switch (smscore_get_device_mode(coredev)) {
1032 case DEVICE_MODE_DVBT:
1033 case DEVICE_MODE_DVBT_BDA:
1034 return smsdvb_dvbt_set_frontend(fe);
1035 case DEVICE_MODE_ISDBT:
1036 case DEVICE_MODE_ISDBT_BDA:
1037 return smsdvb_isdbt_set_frontend(fe);
1038 default:
1039 return -EINVAL;
1040 }
1041 }
1042
1043 static int smsdvb_init(struct dvb_frontend *fe)
1044 {
1045 struct smsdvb_client_t *client =
1046 container_of(fe, struct smsdvb_client_t, frontend);
1047
1048 sms_board_power(client->coredev, 1);
1049
1050 sms_board_dvb3_event(client, DVB3_EVENT_INIT);
1051 return 0;
1052 }
1053
1054 static int smsdvb_sleep(struct dvb_frontend *fe)
1055 {
1056 struct smsdvb_client_t *client =
1057 container_of(fe, struct smsdvb_client_t, frontend);
1058
1059 sms_board_led_feedback(client->coredev, SMS_LED_OFF);
1060 sms_board_power(client->coredev, 0);
1061
1062 sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
1063
1064 return 0;
1065 }
1066
1067 static void smsdvb_release(struct dvb_frontend *fe)
1068 {
1069
1070 }
1071
1072 static const struct dvb_frontend_ops smsdvb_fe_ops = {
1073 .info = {
1074 .name = "Siano Mobile Digital MDTV Receiver",
1075 .frequency_min_hz = 44250 * kHz,
1076 .frequency_max_hz = 867250 * kHz,
1077 .frequency_stepsize_hz = 250 * kHz,
1078 .caps = FE_CAN_INVERSION_AUTO |
1079 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1080 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1081 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
1082 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
1083 FE_CAN_GUARD_INTERVAL_AUTO |
1084 FE_CAN_RECOVER |
1085 FE_CAN_HIERARCHY_AUTO,
1086 },
1087
1088 .release = smsdvb_release,
1089
1090 .set_frontend = smsdvb_set_frontend,
1091 .get_tune_settings = smsdvb_get_tune_settings,
1092
1093 .read_status = smsdvb_read_status,
1094 .read_ber = smsdvb_read_ber,
1095 .read_signal_strength = smsdvb_read_signal_strength,
1096 .read_snr = smsdvb_read_snr,
1097 .read_ucblocks = smsdvb_read_ucblocks,
1098
1099 .init = smsdvb_init,
1100 .sleep = smsdvb_sleep,
1101 };
1102
1103 static int smsdvb_hotplug(struct smscore_device_t *coredev,
1104 struct device *device, int arrival)
1105 {
1106 struct smsclient_params_t params;
1107 struct smsdvb_client_t *client;
1108 int rc;
1109
1110
1111 if (!arrival)
1112 return 0;
1113 client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
1114 if (!client)
1115 return -ENOMEM;
1116
1117
1118 rc = dvb_register_adapter(&client->adapter,
1119 sms_get_board(
1120 smscore_get_board_id(coredev))->name,
1121 THIS_MODULE, device, adapter_nr);
1122 if (rc < 0) {
1123 pr_err("dvb_register_adapter() failed %d\n", rc);
1124 goto adapter_error;
1125 }
1126 dvb_register_media_controller(&client->adapter, coredev->media_dev);
1127
1128
1129 client->demux.dmx.capabilities = DMX_TS_FILTERING;
1130 client->demux.filternum = 32;
1131 client->demux.feednum = 32;
1132 client->demux.start_feed = smsdvb_start_feed;
1133 client->demux.stop_feed = smsdvb_stop_feed;
1134
1135 rc = dvb_dmx_init(&client->demux);
1136 if (rc < 0) {
1137 pr_err("dvb_dmx_init failed %d\n", rc);
1138 goto dvbdmx_error;
1139 }
1140
1141
1142 client->dmxdev.filternum = 32;
1143 client->dmxdev.demux = &client->demux.dmx;
1144 client->dmxdev.capabilities = 0;
1145
1146 rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
1147 if (rc < 0) {
1148 pr_err("dvb_dmxdev_init failed %d\n", rc);
1149 goto dmxdev_error;
1150 }
1151
1152
1153 memcpy(&client->frontend.ops, &smsdvb_fe_ops,
1154 sizeof(struct dvb_frontend_ops));
1155
1156 switch (smscore_get_device_mode(coredev)) {
1157 case DEVICE_MODE_DVBT:
1158 case DEVICE_MODE_DVBT_BDA:
1159 client->frontend.ops.delsys[0] = SYS_DVBT;
1160 break;
1161 case DEVICE_MODE_ISDBT:
1162 case DEVICE_MODE_ISDBT_BDA:
1163 client->frontend.ops.delsys[0] = SYS_ISDBT;
1164 break;
1165 }
1166
1167 rc = dvb_register_frontend(&client->adapter, &client->frontend);
1168 if (rc < 0) {
1169 pr_err("frontend registration failed %d\n", rc);
1170 goto frontend_error;
1171 }
1172
1173 params.initial_id = 1;
1174 params.data_type = MSG_SMS_DVBT_BDA_DATA;
1175 params.onresponse_handler = smsdvb_onresponse;
1176 params.onremove_handler = smsdvb_onremove;
1177 params.context = client;
1178
1179 rc = smscore_register_client(coredev, ¶ms, &client->smsclient);
1180 if (rc < 0) {
1181 pr_err("smscore_register_client() failed %d\n", rc);
1182 goto client_error;
1183 }
1184
1185 client->coredev = coredev;
1186
1187 init_completion(&client->tune_done);
1188 init_completion(&client->stats_done);
1189
1190 mutex_lock(&g_smsdvb_clientslock);
1191
1192 list_add(&client->entry, &g_smsdvb_clients);
1193
1194 mutex_unlock(&g_smsdvb_clientslock);
1195
1196 client->event_fe_state = -1;
1197 client->event_unc_state = -1;
1198 sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
1199
1200 sms_board_setup(coredev);
1201
1202 if (smsdvb_debugfs_create(client) < 0)
1203 pr_info("failed to create debugfs node\n");
1204
1205 rc = dvb_create_media_graph(&client->adapter, true);
1206 if (rc < 0) {
1207 pr_err("dvb_create_media_graph failed %d\n", rc);
1208 goto media_graph_error;
1209 }
1210
1211 pr_info("DVB interface registered.\n");
1212 return 0;
1213
1214 media_graph_error:
1215 mutex_lock(&g_smsdvb_clientslock);
1216 list_del(&client->entry);
1217 mutex_unlock(&g_smsdvb_clientslock);
1218
1219 smsdvb_debugfs_release(client);
1220
1221 client_error:
1222 dvb_unregister_frontend(&client->frontend);
1223
1224 frontend_error:
1225 dvb_dmxdev_release(&client->dmxdev);
1226
1227 dmxdev_error:
1228 dvb_dmx_release(&client->demux);
1229
1230 dvbdmx_error:
1231 smsdvb_media_device_unregister(client);
1232 dvb_unregister_adapter(&client->adapter);
1233
1234 adapter_error:
1235 kfree(client);
1236 return rc;
1237 }
1238
1239 static int __init smsdvb_module_init(void)
1240 {
1241 int rc;
1242
1243 smsdvb_debugfs_register();
1244
1245 rc = smscore_register_hotplug(smsdvb_hotplug);
1246
1247 pr_debug("\n");
1248
1249 return rc;
1250 }
1251
1252 static void __exit smsdvb_module_exit(void)
1253 {
1254 smscore_unregister_hotplug(smsdvb_hotplug);
1255
1256 mutex_lock(&g_smsdvb_clientslock);
1257
1258 while (!list_empty(&g_smsdvb_clients))
1259 smsdvb_unregister_client((struct smsdvb_client_t *)g_smsdvb_clients.next);
1260
1261 smsdvb_debugfs_unregister();
1262
1263 mutex_unlock(&g_smsdvb_clientslock);
1264 }
1265
1266 module_init(smsdvb_module_init);
1267 module_exit(smsdvb_module_exit);
1268
1269 MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
1270 MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
1271 MODULE_LICENSE("GPL");