1 /**************************************************************** 2 3 Siano Mobile Silicon, Inc. 4 MDTV receiver kernel modules. 5 Copyright (C) 2006-2008, Uri Shkolnik 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20 ****************************************************************/ 21 22 #include "smscoreapi.h" 23 24 #include <linux/module.h> 25 #include <linux/slab.h> 26 #include <linux/init.h> 27 #include <asm/div64.h> 28 29 #include "dmxdev.h" 30 #include "dvbdev.h" 31 #include "dvb_demux.h" 32 #include "dvb_frontend.h" 33 34 #include "sms-cards.h" 35 36 #include "smsdvb.h" 37 38 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 39 40 static struct list_head g_smsdvb_clients; 41 static struct mutex g_smsdvb_clientslock; 42 43 static u32 sms_to_guard_interval_table[] = { 44 [0] = GUARD_INTERVAL_1_32, 45 [1] = GUARD_INTERVAL_1_16, 46 [2] = GUARD_INTERVAL_1_8, 47 [3] = GUARD_INTERVAL_1_4, 48 }; 49 50 static u32 sms_to_code_rate_table[] = { 51 [0] = FEC_1_2, 52 [1] = FEC_2_3, 53 [2] = FEC_3_4, 54 [3] = FEC_5_6, 55 [4] = FEC_7_8, 56 }; 57 58 59 static u32 sms_to_hierarchy_table[] = { 60 [0] = HIERARCHY_NONE, 61 [1] = HIERARCHY_1, 62 [2] = HIERARCHY_2, 63 [3] = HIERARCHY_4, 64 }; 65 66 static u32 sms_to_modulation_table[] = { 67 [0] = QPSK, 68 [1] = QAM_16, 69 [2] = QAM_64, 70 [3] = DQPSK, 71 }; 72 73 74 /* Events that may come from DVB v3 adapter */ 75 static void sms_board_dvb3_event(struct smsdvb_client_t *client, 76 enum SMS_DVB3_EVENTS event) { 77 78 struct smscore_device_t *coredev = client->coredev; 79 switch (event) { 80 case DVB3_EVENT_INIT: 81 pr_debug("DVB3_EVENT_INIT\n"); 82 sms_board_event(coredev, BOARD_EVENT_BIND); 83 break; 84 case DVB3_EVENT_SLEEP: 85 pr_debug("DVB3_EVENT_SLEEP\n"); 86 sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND); 87 break; 88 case DVB3_EVENT_HOTPLUG: 89 pr_debug("DVB3_EVENT_HOTPLUG\n"); 90 sms_board_event(coredev, BOARD_EVENT_POWER_INIT); 91 break; 92 case DVB3_EVENT_FE_LOCK: 93 if (client->event_fe_state != DVB3_EVENT_FE_LOCK) { 94 client->event_fe_state = DVB3_EVENT_FE_LOCK; 95 pr_debug("DVB3_EVENT_FE_LOCK\n"); 96 sms_board_event(coredev, BOARD_EVENT_FE_LOCK); 97 } 98 break; 99 case DVB3_EVENT_FE_UNLOCK: 100 if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) { 101 client->event_fe_state = DVB3_EVENT_FE_UNLOCK; 102 pr_debug("DVB3_EVENT_FE_UNLOCK\n"); 103 sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK); 104 } 105 break; 106 case DVB3_EVENT_UNC_OK: 107 if (client->event_unc_state != DVB3_EVENT_UNC_OK) { 108 client->event_unc_state = DVB3_EVENT_UNC_OK; 109 pr_debug("DVB3_EVENT_UNC_OK\n"); 110 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK); 111 } 112 break; 113 case DVB3_EVENT_UNC_ERR: 114 if (client->event_unc_state != DVB3_EVENT_UNC_ERR) { 115 client->event_unc_state = DVB3_EVENT_UNC_ERR; 116 pr_debug("DVB3_EVENT_UNC_ERR\n"); 117 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS); 118 } 119 break; 120 121 default: 122 pr_err("Unknown dvb3 api event\n"); 123 break; 124 } 125 } 126 127 static void smsdvb_stats_not_ready(struct dvb_frontend *fe) 128 { 129 struct smsdvb_client_t *client = 130 container_of(fe, struct smsdvb_client_t, frontend); 131 struct smscore_device_t *coredev = client->coredev; 132 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 133 int i, n_layers; 134 135 switch (smscore_get_device_mode(coredev)) { 136 case DEVICE_MODE_ISDBT: 137 case DEVICE_MODE_ISDBT_BDA: 138 n_layers = 4; 139 break; 140 default: 141 n_layers = 1; 142 } 143 144 /* Global stats */ 145 c->strength.len = 1; 146 c->cnr.len = 1; 147 c->strength.stat[0].scale = FE_SCALE_DECIBEL; 148 c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 149 150 /* Per-layer stats */ 151 c->post_bit_error.len = n_layers; 152 c->post_bit_count.len = n_layers; 153 c->block_error.len = n_layers; 154 c->block_count.len = n_layers; 155 156 /* 157 * Put all of them at FE_SCALE_NOT_AVAILABLE. They're dynamically 158 * changed when the stats become available. 159 */ 160 for (i = 0; i < n_layers; i++) { 161 c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; 162 c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; 163 c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; 164 c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; 165 } 166 } 167 168 static inline int sms_to_mode(u32 mode) 169 { 170 switch (mode) { 171 case 2: 172 return TRANSMISSION_MODE_2K; 173 case 4: 174 return TRANSMISSION_MODE_4K; 175 case 8: 176 return TRANSMISSION_MODE_8K; 177 } 178 return TRANSMISSION_MODE_AUTO; 179 } 180 181 static inline int sms_to_status(u32 is_demod_locked, u32 is_rf_locked) 182 { 183 if (is_demod_locked) 184 return FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | 185 FE_HAS_SYNC | FE_HAS_LOCK; 186 187 if (is_rf_locked) 188 return FE_HAS_SIGNAL | FE_HAS_CARRIER; 189 190 return 0; 191 } 192 193 static inline u32 sms_to_bw(u32 value) 194 { 195 return value * 1000000; 196 } 197 198 #define convert_from_table(value, table, defval) ({ \ 199 u32 __ret; \ 200 if (value < ARRAY_SIZE(table)) \ 201 __ret = table[value]; \ 202 else \ 203 __ret = defval; \ 204 __ret; \ 205 }) 206 207 #define sms_to_guard_interval(value) \ 208 convert_from_table(value, sms_to_guard_interval_table, \ 209 GUARD_INTERVAL_AUTO); 210 211 #define sms_to_code_rate(value) \ 212 convert_from_table(value, sms_to_code_rate_table, \ 213 FEC_NONE); 214 215 #define sms_to_hierarchy(value) \ 216 convert_from_table(value, sms_to_hierarchy_table, \ 217 FEC_NONE); 218 219 #define sms_to_modulation(value) \ 220 convert_from_table(value, sms_to_modulation_table, \ 221 FEC_NONE); 222 223 static void smsdvb_update_tx_params(struct smsdvb_client_t *client, 224 struct sms_tx_stats *p) 225 { 226 struct dvb_frontend *fe = &client->frontend; 227 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 228 229 c->frequency = p->frequency; 230 client->fe_status = sms_to_status(p->is_demod_locked, 0); 231 c->bandwidth_hz = sms_to_bw(p->bandwidth); 232 c->transmission_mode = sms_to_mode(p->transmission_mode); 233 c->guard_interval = sms_to_guard_interval(p->guard_interval); 234 c->code_rate_HP = sms_to_code_rate(p->code_rate); 235 c->code_rate_LP = sms_to_code_rate(p->lp_code_rate); 236 c->hierarchy = sms_to_hierarchy(p->hierarchy); 237 c->modulation = sms_to_modulation(p->constellation); 238 } 239 240 static void smsdvb_update_per_slices(struct smsdvb_client_t *client, 241 struct RECEPTION_STATISTICS_PER_SLICES_S *p) 242 { 243 struct dvb_frontend *fe = &client->frontend; 244 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 245 u64 tmp; 246 247 client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked); 248 c->modulation = sms_to_modulation(p->constellation); 249 250 /* signal Strength, in DBm */ 251 c->strength.stat[0].uvalue = p->in_band_power * 1000; 252 253 /* Carrier to noise ratio, in DB */ 254 c->cnr.stat[0].svalue = p->snr * 1000; 255 256 /* PER/BER requires demod lock */ 257 if (!p->is_demod_locked) 258 return; 259 260 /* TS PER */ 261 client->last_per = c->block_error.stat[0].uvalue; 262 c->block_error.stat[0].scale = FE_SCALE_COUNTER; 263 c->block_count.stat[0].scale = FE_SCALE_COUNTER; 264 c->block_error.stat[0].uvalue += p->ets_packets; 265 c->block_count.stat[0].uvalue += p->ets_packets + p->ts_packets; 266 267 /* ber */ 268 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 269 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 270 c->post_bit_error.stat[0].uvalue += p->ber_error_count; 271 c->post_bit_count.stat[0].uvalue += p->ber_bit_count; 272 273 /* Legacy PER/BER */ 274 tmp = p->ets_packets * 65535; 275 if (p->ts_packets + p->ets_packets) 276 do_div(tmp, p->ts_packets + p->ets_packets); 277 client->legacy_per = tmp; 278 } 279 280 static void smsdvb_update_dvb_stats(struct smsdvb_client_t *client, 281 struct sms_stats *p) 282 { 283 struct dvb_frontend *fe = &client->frontend; 284 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 285 286 if (client->prt_dvb_stats) 287 client->prt_dvb_stats(client->debug_data, p); 288 289 client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked); 290 291 /* Update DVB modulation parameters */ 292 c->frequency = p->frequency; 293 client->fe_status = sms_to_status(p->is_demod_locked, 0); 294 c->bandwidth_hz = sms_to_bw(p->bandwidth); 295 c->transmission_mode = sms_to_mode(p->transmission_mode); 296 c->guard_interval = sms_to_guard_interval(p->guard_interval); 297 c->code_rate_HP = sms_to_code_rate(p->code_rate); 298 c->code_rate_LP = sms_to_code_rate(p->lp_code_rate); 299 c->hierarchy = sms_to_hierarchy(p->hierarchy); 300 c->modulation = sms_to_modulation(p->constellation); 301 302 /* update reception data */ 303 c->lna = p->is_external_lna_on ? 1 : 0; 304 305 /* Carrier to noise ratio, in DB */ 306 c->cnr.stat[0].svalue = p->SNR * 1000; 307 308 /* signal Strength, in DBm */ 309 c->strength.stat[0].uvalue = p->in_band_pwr * 1000; 310 311 /* PER/BER requires demod lock */ 312 if (!p->is_demod_locked) 313 return; 314 315 /* TS PER */ 316 client->last_per = c->block_error.stat[0].uvalue; 317 c->block_error.stat[0].scale = FE_SCALE_COUNTER; 318 c->block_count.stat[0].scale = FE_SCALE_COUNTER; 319 c->block_error.stat[0].uvalue += p->error_ts_packets; 320 c->block_count.stat[0].uvalue += p->total_ts_packets; 321 322 /* ber */ 323 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 324 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 325 c->post_bit_error.stat[0].uvalue += p->ber_error_count; 326 c->post_bit_count.stat[0].uvalue += p->ber_bit_count; 327 328 /* Legacy PER/BER */ 329 client->legacy_ber = p->ber; 330 }; 331 332 static void smsdvb_update_isdbt_stats(struct smsdvb_client_t *client, 333 struct sms_isdbt_stats *p) 334 { 335 struct dvb_frontend *fe = &client->frontend; 336 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 337 struct sms_isdbt_layer_stats *lr; 338 int i, n_layers; 339 340 if (client->prt_isdb_stats) 341 client->prt_isdb_stats(client->debug_data, p); 342 343 client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked); 344 345 /* 346 * Firmware 2.1 seems to report only lock status and 347 * signal strength. The signal strength indicator is at the 348 * wrong field. 349 */ 350 if (p->statistics_type == 0) { 351 c->strength.stat[0].uvalue = ((s32)p->transmission_mode) * 1000; 352 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 353 return; 354 } 355 356 /* Update ISDB-T transmission parameters */ 357 c->frequency = p->frequency; 358 c->bandwidth_hz = sms_to_bw(p->bandwidth); 359 c->transmission_mode = sms_to_mode(p->transmission_mode); 360 c->guard_interval = sms_to_guard_interval(p->guard_interval); 361 c->isdbt_partial_reception = p->partial_reception ? 1 : 0; 362 n_layers = p->num_of_layers; 363 if (n_layers < 1) 364 n_layers = 1; 365 if (n_layers > 3) 366 n_layers = 3; 367 c->isdbt_layer_enabled = 0; 368 369 /* update reception data */ 370 c->lna = p->is_external_lna_on ? 1 : 0; 371 372 /* Carrier to noise ratio, in DB */ 373 c->cnr.stat[0].svalue = p->SNR * 1000; 374 375 /* signal Strength, in DBm */ 376 c->strength.stat[0].uvalue = p->in_band_pwr * 1000; 377 378 /* PER/BER and per-layer stats require demod lock */ 379 if (!p->is_demod_locked) 380 return; 381 382 client->last_per = c->block_error.stat[0].uvalue; 383 384 /* Clears global counters, as the code below will sum it again */ 385 c->block_error.stat[0].uvalue = 0; 386 c->block_count.stat[0].uvalue = 0; 387 c->block_error.stat[0].scale = FE_SCALE_COUNTER; 388 c->block_count.stat[0].scale = FE_SCALE_COUNTER; 389 c->post_bit_error.stat[0].uvalue = 0; 390 c->post_bit_count.stat[0].uvalue = 0; 391 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 392 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 393 394 for (i = 0; i < n_layers; i++) { 395 lr = &p->layer_info[i]; 396 397 /* Update per-layer transmission parameters */ 398 if (lr->number_of_segments > 0 && lr->number_of_segments < 13) { 399 c->isdbt_layer_enabled |= 1 << i; 400 c->layer[i].segment_count = lr->number_of_segments; 401 } else { 402 continue; 403 } 404 c->layer[i].modulation = sms_to_modulation(lr->constellation); 405 406 /* TS PER */ 407 c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER; 408 c->block_count.stat[i + 1].scale = FE_SCALE_COUNTER; 409 c->block_error.stat[i + 1].uvalue += lr->error_ts_packets; 410 c->block_count.stat[i + 1].uvalue += lr->total_ts_packets; 411 412 /* Update global PER counter */ 413 c->block_error.stat[0].uvalue += lr->error_ts_packets; 414 c->block_count.stat[0].uvalue += lr->total_ts_packets; 415 416 /* BER */ 417 c->post_bit_error.stat[i + 1].scale = FE_SCALE_COUNTER; 418 c->post_bit_count.stat[i + 1].scale = FE_SCALE_COUNTER; 419 c->post_bit_error.stat[i + 1].uvalue += lr->ber_error_count; 420 c->post_bit_count.stat[i + 1].uvalue += lr->ber_bit_count; 421 422 /* Update global BER counter */ 423 c->post_bit_error.stat[0].uvalue += lr->ber_error_count; 424 c->post_bit_count.stat[0].uvalue += lr->ber_bit_count; 425 } 426 } 427 428 static void smsdvb_update_isdbt_stats_ex(struct smsdvb_client_t *client, 429 struct sms_isdbt_stats_ex *p) 430 { 431 struct dvb_frontend *fe = &client->frontend; 432 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 433 struct sms_isdbt_layer_stats *lr; 434 int i, n_layers; 435 436 if (client->prt_isdb_stats_ex) 437 client->prt_isdb_stats_ex(client->debug_data, p); 438 439 /* Update ISDB-T transmission parameters */ 440 c->frequency = p->frequency; 441 client->fe_status = sms_to_status(p->is_demod_locked, 0); 442 c->bandwidth_hz = sms_to_bw(p->bandwidth); 443 c->transmission_mode = sms_to_mode(p->transmission_mode); 444 c->guard_interval = sms_to_guard_interval(p->guard_interval); 445 c->isdbt_partial_reception = p->partial_reception ? 1 : 0; 446 n_layers = p->num_of_layers; 447 if (n_layers < 1) 448 n_layers = 1; 449 if (n_layers > 3) 450 n_layers = 3; 451 c->isdbt_layer_enabled = 0; 452 453 /* update reception data */ 454 c->lna = p->is_external_lna_on ? 1 : 0; 455 456 /* Carrier to noise ratio, in DB */ 457 c->cnr.stat[0].svalue = p->SNR * 1000; 458 459 /* signal Strength, in DBm */ 460 c->strength.stat[0].uvalue = p->in_band_pwr * 1000; 461 462 /* PER/BER and per-layer stats require demod lock */ 463 if (!p->is_demod_locked) 464 return; 465 466 client->last_per = c->block_error.stat[0].uvalue; 467 468 /* Clears global counters, as the code below will sum it again */ 469 c->block_error.stat[0].uvalue = 0; 470 c->block_count.stat[0].uvalue = 0; 471 c->block_error.stat[0].scale = FE_SCALE_COUNTER; 472 c->block_count.stat[0].scale = FE_SCALE_COUNTER; 473 c->post_bit_error.stat[0].uvalue = 0; 474 c->post_bit_count.stat[0].uvalue = 0; 475 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 476 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 477 478 c->post_bit_error.len = n_layers + 1; 479 c->post_bit_count.len = n_layers + 1; 480 c->block_error.len = n_layers + 1; 481 c->block_count.len = n_layers + 1; 482 for (i = 0; i < n_layers; i++) { 483 lr = &p->layer_info[i]; 484 485 /* Update per-layer transmission parameters */ 486 if (lr->number_of_segments > 0 && lr->number_of_segments < 13) { 487 c->isdbt_layer_enabled |= 1 << i; 488 c->layer[i].segment_count = lr->number_of_segments; 489 } else { 490 continue; 491 } 492 c->layer[i].modulation = sms_to_modulation(lr->constellation); 493 494 /* TS PER */ 495 c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER; 496 c->block_count.stat[i + 1].scale = FE_SCALE_COUNTER; 497 c->block_error.stat[i + 1].uvalue += lr->error_ts_packets; 498 c->block_count.stat[i + 1].uvalue += lr->total_ts_packets; 499 500 /* Update global PER counter */ 501 c->block_error.stat[0].uvalue += lr->error_ts_packets; 502 c->block_count.stat[0].uvalue += lr->total_ts_packets; 503 504 /* ber */ 505 c->post_bit_error.stat[i + 1].scale = FE_SCALE_COUNTER; 506 c->post_bit_count.stat[i + 1].scale = FE_SCALE_COUNTER; 507 c->post_bit_error.stat[i + 1].uvalue += lr->ber_error_count; 508 c->post_bit_count.stat[i + 1].uvalue += lr->ber_bit_count; 509 510 /* Update global ber counter */ 511 c->post_bit_error.stat[0].uvalue += lr->ber_error_count; 512 c->post_bit_count.stat[0].uvalue += lr->ber_bit_count; 513 } 514 } 515 516 static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) 517 { 518 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; 519 struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) (((u8 *) cb->p) 520 + cb->offset); 521 void *p = phdr + 1; 522 struct dvb_frontend *fe = &client->frontend; 523 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 524 bool is_status_update = false; 525 526 switch (phdr->msg_type) { 527 case MSG_SMS_DVBT_BDA_DATA: 528 /* 529 * Only feed data to dvb demux if are there any feed listening 530 * to it and if the device has tuned 531 */ 532 if (client->feed_users && client->has_tuned) 533 dvb_dmx_swfilter(&client->demux, p, 534 cb->size - sizeof(struct sms_msg_hdr)); 535 break; 536 537 case MSG_SMS_RF_TUNE_RES: 538 case MSG_SMS_ISDBT_TUNE_RES: 539 complete(&client->tune_done); 540 break; 541 542 case MSG_SMS_SIGNAL_DETECTED_IND: 543 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 544 FE_HAS_VITERBI | FE_HAS_SYNC | 545 FE_HAS_LOCK; 546 547 is_status_update = true; 548 break; 549 550 case MSG_SMS_NO_SIGNAL_IND: 551 client->fe_status = 0; 552 553 is_status_update = true; 554 break; 555 556 case MSG_SMS_TRANSMISSION_IND: 557 smsdvb_update_tx_params(client, p); 558 559 is_status_update = true; 560 break; 561 562 case MSG_SMS_HO_PER_SLICES_IND: 563 smsdvb_update_per_slices(client, p); 564 565 is_status_update = true; 566 break; 567 568 case MSG_SMS_GET_STATISTICS_RES: 569 switch (smscore_get_device_mode(client->coredev)) { 570 case DEVICE_MODE_ISDBT: 571 case DEVICE_MODE_ISDBT_BDA: 572 smsdvb_update_isdbt_stats(client, p); 573 break; 574 default: 575 /* Skip sms_msg_statistics_info:request_result field */ 576 smsdvb_update_dvb_stats(client, p + sizeof(u32)); 577 } 578 579 is_status_update = true; 580 break; 581 582 /* Only for ISDB-T */ 583 case MSG_SMS_GET_STATISTICS_EX_RES: 584 /* Skip sms_msg_statistics_info:request_result field? */ 585 smsdvb_update_isdbt_stats_ex(client, p + sizeof(u32)); 586 is_status_update = true; 587 break; 588 default: 589 pr_debug("message not handled\n"); 590 } 591 smscore_putbuffer(client->coredev, cb); 592 593 if (is_status_update) { 594 if (client->fe_status & FE_HAS_LOCK) { 595 sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); 596 if (client->last_per == c->block_error.stat[0].uvalue) 597 sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); 598 else 599 sms_board_dvb3_event(client, DVB3_EVENT_UNC_ERR); 600 client->has_tuned = true; 601 } else { 602 smsdvb_stats_not_ready(fe); 603 client->has_tuned = false; 604 sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); 605 } 606 complete(&client->stats_done); 607 } 608 609 return 0; 610 } 611 612 static void smsdvb_media_device_unregister(struct smsdvb_client_t *client) 613 { 614 #ifdef CONFIG_MEDIA_CONTROLLER_DVB 615 struct smscore_device_t *coredev = client->coredev; 616 617 if (!coredev->media_dev) 618 return; 619 media_device_unregister(coredev->media_dev); 620 media_device_cleanup(coredev->media_dev); 621 kfree(coredev->media_dev); 622 coredev->media_dev = NULL; 623 #endif 624 } 625 626 static void smsdvb_unregister_client(struct smsdvb_client_t *client) 627 { 628 /* must be called under clientslock */ 629 630 list_del(&client->entry); 631 632 smsdvb_debugfs_release(client); 633 smscore_unregister_client(client->smsclient); 634 dvb_unregister_frontend(&client->frontend); 635 dvb_dmxdev_release(&client->dmxdev); 636 dvb_dmx_release(&client->demux); 637 smsdvb_media_device_unregister(client); 638 dvb_unregister_adapter(&client->adapter); 639 kfree(client); 640 } 641 642 static void smsdvb_onremove(void *context) 643 { 644 kmutex_lock(&g_smsdvb_clientslock); 645 646 smsdvb_unregister_client((struct smsdvb_client_t *) context); 647 648 kmutex_unlock(&g_smsdvb_clientslock); 649 } 650 651 static int smsdvb_start_feed(struct dvb_demux_feed *feed) 652 { 653 struct smsdvb_client_t *client = 654 container_of(feed->demux, struct smsdvb_client_t, demux); 655 struct sms_msg_data pid_msg; 656 657 pr_debug("add pid %d(%x)\n", 658 feed->pid, feed->pid); 659 660 client->feed_users++; 661 662 pid_msg.x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID; 663 pid_msg.x_msg_header.msg_dst_id = HIF_TASK; 664 pid_msg.x_msg_header.msg_flags = 0; 665 pid_msg.x_msg_header.msg_type = MSG_SMS_ADD_PID_FILTER_REQ; 666 pid_msg.x_msg_header.msg_length = sizeof(pid_msg); 667 pid_msg.msg_data[0] = feed->pid; 668 669 return smsclient_sendrequest(client->smsclient, 670 &pid_msg, sizeof(pid_msg)); 671 } 672 673 static int smsdvb_stop_feed(struct dvb_demux_feed *feed) 674 { 675 struct smsdvb_client_t *client = 676 container_of(feed->demux, struct smsdvb_client_t, demux); 677 struct sms_msg_data pid_msg; 678 679 pr_debug("remove pid %d(%x)\n", 680 feed->pid, feed->pid); 681 682 client->feed_users--; 683 684 pid_msg.x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID; 685 pid_msg.x_msg_header.msg_dst_id = HIF_TASK; 686 pid_msg.x_msg_header.msg_flags = 0; 687 pid_msg.x_msg_header.msg_type = MSG_SMS_REMOVE_PID_FILTER_REQ; 688 pid_msg.x_msg_header.msg_length = sizeof(pid_msg); 689 pid_msg.msg_data[0] = feed->pid; 690 691 return smsclient_sendrequest(client->smsclient, 692 &pid_msg, sizeof(pid_msg)); 693 } 694 695 static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, 696 void *buffer, size_t size, 697 struct completion *completion) 698 { 699 int rc; 700 701 rc = smsclient_sendrequest(client->smsclient, buffer, size); 702 if (rc < 0) 703 return rc; 704 705 return wait_for_completion_timeout(completion, 706 msecs_to_jiffies(2000)) ? 707 0 : -ETIME; 708 } 709 710 static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) 711 { 712 int rc; 713 struct sms_msg_hdr msg; 714 715 /* Don't request stats too fast */ 716 if (client->get_stats_jiffies && 717 (!time_after(jiffies, client->get_stats_jiffies))) 718 return 0; 719 client->get_stats_jiffies = jiffies + msecs_to_jiffies(100); 720 721 msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID; 722 msg.msg_dst_id = HIF_TASK; 723 msg.msg_flags = 0; 724 msg.msg_length = sizeof(msg); 725 726 switch (smscore_get_device_mode(client->coredev)) { 727 case DEVICE_MODE_ISDBT: 728 case DEVICE_MODE_ISDBT_BDA: 729 /* 730 * Check for firmware version, to avoid breaking for old cards 731 */ 732 if (client->coredev->fw_version >= 0x800) 733 msg.msg_type = MSG_SMS_GET_STATISTICS_EX_REQ; 734 else 735 msg.msg_type = MSG_SMS_GET_STATISTICS_REQ; 736 break; 737 default: 738 msg.msg_type = MSG_SMS_GET_STATISTICS_REQ; 739 } 740 741 rc = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg), 742 &client->stats_done); 743 744 return rc; 745 } 746 747 static inline int led_feedback(struct smsdvb_client_t *client) 748 { 749 if (!(client->fe_status & FE_HAS_LOCK)) 750 return sms_board_led_feedback(client->coredev, SMS_LED_OFF); 751 752 return sms_board_led_feedback(client->coredev, 753 (client->legacy_ber == 0) ? 754 SMS_LED_HI : SMS_LED_LO); 755 } 756 757 static int smsdvb_read_status(struct dvb_frontend *fe, enum fe_status *stat) 758 { 759 int rc; 760 struct smsdvb_client_t *client; 761 client = container_of(fe, struct smsdvb_client_t, frontend); 762 763 rc = smsdvb_send_statistics_request(client); 764 765 *stat = client->fe_status; 766 767 led_feedback(client); 768 769 return rc; 770 } 771 772 static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) 773 { 774 int rc; 775 struct smsdvb_client_t *client; 776 777 client = container_of(fe, struct smsdvb_client_t, frontend); 778 779 rc = smsdvb_send_statistics_request(client); 780 781 *ber = client->legacy_ber; 782 783 led_feedback(client); 784 785 return rc; 786 } 787 788 static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 789 { 790 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 791 int rc; 792 s32 power = (s32) c->strength.stat[0].uvalue; 793 struct smsdvb_client_t *client; 794 795 client = container_of(fe, struct smsdvb_client_t, frontend); 796 797 rc = smsdvb_send_statistics_request(client); 798 799 if (power < -95) 800 *strength = 0; 801 else if (power > -29) 802 *strength = 65535; 803 else 804 *strength = (power + 95) * 65535 / 66; 805 806 led_feedback(client); 807 808 return rc; 809 } 810 811 static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) 812 { 813 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 814 int rc; 815 struct smsdvb_client_t *client; 816 817 client = container_of(fe, struct smsdvb_client_t, frontend); 818 819 rc = smsdvb_send_statistics_request(client); 820 821 /* Preferred scale for SNR with legacy API: 0.1 dB */ 822 *snr = ((u32)c->cnr.stat[0].svalue) / 100; 823 824 led_feedback(client); 825 826 return rc; 827 } 828 829 static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 830 { 831 int rc; 832 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 833 struct smsdvb_client_t *client; 834 835 client = container_of(fe, struct smsdvb_client_t, frontend); 836 837 rc = smsdvb_send_statistics_request(client); 838 839 *ucblocks = c->block_error.stat[0].uvalue; 840 841 led_feedback(client); 842 843 return rc; 844 } 845 846 static int smsdvb_get_tune_settings(struct dvb_frontend *fe, 847 struct dvb_frontend_tune_settings *tune) 848 { 849 pr_debug("\n"); 850 851 tune->min_delay_ms = 400; 852 tune->step_size = 250000; 853 tune->max_drift = 0; 854 return 0; 855 } 856 857 static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe) 858 { 859 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 860 struct smsdvb_client_t *client = 861 container_of(fe, struct smsdvb_client_t, frontend); 862 863 struct { 864 struct sms_msg_hdr msg; 865 u32 Data[3]; 866 } msg; 867 868 int ret; 869 870 client->fe_status = 0; 871 client->event_fe_state = -1; 872 client->event_unc_state = -1; 873 fe->dtv_property_cache.delivery_system = SYS_DVBT; 874 875 msg.msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID; 876 msg.msg.msg_dst_id = HIF_TASK; 877 msg.msg.msg_flags = 0; 878 msg.msg.msg_type = MSG_SMS_RF_TUNE_REQ; 879 msg.msg.msg_length = sizeof(msg); 880 msg.Data[0] = c->frequency; 881 msg.Data[2] = 12000000; 882 883 pr_debug("%s: freq %d band %d\n", __func__, c->frequency, 884 c->bandwidth_hz); 885 886 switch (c->bandwidth_hz / 1000000) { 887 case 8: 888 msg.Data[1] = BW_8_MHZ; 889 break; 890 case 7: 891 msg.Data[1] = BW_7_MHZ; 892 break; 893 case 6: 894 msg.Data[1] = BW_6_MHZ; 895 break; 896 case 0: 897 return -EOPNOTSUPP; 898 default: 899 return -EINVAL; 900 } 901 /* Disable LNA, if any. An error is returned if no LNA is present */ 902 ret = sms_board_lna_control(client->coredev, 0); 903 if (ret == 0) { 904 enum fe_status status; 905 906 /* tune with LNA off at first */ 907 ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg), 908 &client->tune_done); 909 910 smsdvb_read_status(fe, &status); 911 912 if (status & FE_HAS_LOCK) 913 return ret; 914 915 /* previous tune didn't lock - enable LNA and tune again */ 916 sms_board_lna_control(client->coredev, 1); 917 } 918 919 return smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg), 920 &client->tune_done); 921 } 922 923 static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe) 924 { 925 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 926 struct smsdvb_client_t *client = 927 container_of(fe, struct smsdvb_client_t, frontend); 928 int board_id = smscore_get_board_id(client->coredev); 929 struct sms_board *board = sms_get_board(board_id); 930 enum sms_device_type_st type = board->type; 931 int ret; 932 933 struct { 934 struct sms_msg_hdr msg; 935 u32 Data[4]; 936 } msg; 937 938 fe->dtv_property_cache.delivery_system = SYS_ISDBT; 939 940 msg.msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID; 941 msg.msg.msg_dst_id = HIF_TASK; 942 msg.msg.msg_flags = 0; 943 msg.msg.msg_type = MSG_SMS_ISDBT_TUNE_REQ; 944 msg.msg.msg_length = sizeof(msg); 945 946 if (c->isdbt_sb_segment_idx == -1) 947 c->isdbt_sb_segment_idx = 0; 948 949 if (!c->isdbt_layer_enabled) 950 c->isdbt_layer_enabled = 7; 951 952 msg.Data[0] = c->frequency; 953 msg.Data[1] = BW_ISDBT_1SEG; 954 msg.Data[2] = 12000000; 955 msg.Data[3] = c->isdbt_sb_segment_idx; 956 957 if (c->isdbt_partial_reception) { 958 if ((type == SMS_PELE || type == SMS_RIO) && 959 c->isdbt_sb_segment_count > 3) 960 msg.Data[1] = BW_ISDBT_13SEG; 961 else if (c->isdbt_sb_segment_count > 1) 962 msg.Data[1] = BW_ISDBT_3SEG; 963 } else if (type == SMS_PELE || type == SMS_RIO) 964 msg.Data[1] = BW_ISDBT_13SEG; 965 966 c->bandwidth_hz = 6000000; 967 968 pr_debug("freq %d segwidth %d segindex %d\n", 969 c->frequency, c->isdbt_sb_segment_count, 970 c->isdbt_sb_segment_idx); 971 972 /* Disable LNA, if any. An error is returned if no LNA is present */ 973 ret = sms_board_lna_control(client->coredev, 0); 974 if (ret == 0) { 975 enum fe_status status; 976 977 /* tune with LNA off at first */ 978 ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg), 979 &client->tune_done); 980 981 smsdvb_read_status(fe, &status); 982 983 if (status & FE_HAS_LOCK) 984 return ret; 985 986 /* previous tune didn't lock - enable LNA and tune again */ 987 sms_board_lna_control(client->coredev, 1); 988 } 989 return smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg), 990 &client->tune_done); 991 } 992 993 static int smsdvb_set_frontend(struct dvb_frontend *fe) 994 { 995 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 996 struct smsdvb_client_t *client = 997 container_of(fe, struct smsdvb_client_t, frontend); 998 struct smscore_device_t *coredev = client->coredev; 999 1000 smsdvb_stats_not_ready(fe); 1001 c->strength.stat[0].uvalue = 0; 1002 c->cnr.stat[0].uvalue = 0; 1003 1004 client->has_tuned = false; 1005 1006 switch (smscore_get_device_mode(coredev)) { 1007 case DEVICE_MODE_DVBT: 1008 case DEVICE_MODE_DVBT_BDA: 1009 return smsdvb_dvbt_set_frontend(fe); 1010 case DEVICE_MODE_ISDBT: 1011 case DEVICE_MODE_ISDBT_BDA: 1012 return smsdvb_isdbt_set_frontend(fe); 1013 default: 1014 return -EINVAL; 1015 } 1016 } 1017 1018 static int smsdvb_init(struct dvb_frontend *fe) 1019 { 1020 struct smsdvb_client_t *client = 1021 container_of(fe, struct smsdvb_client_t, frontend); 1022 1023 sms_board_power(client->coredev, 1); 1024 1025 sms_board_dvb3_event(client, DVB3_EVENT_INIT); 1026 return 0; 1027 } 1028 1029 static int smsdvb_sleep(struct dvb_frontend *fe) 1030 { 1031 struct smsdvb_client_t *client = 1032 container_of(fe, struct smsdvb_client_t, frontend); 1033 1034 sms_board_led_feedback(client->coredev, SMS_LED_OFF); 1035 sms_board_power(client->coredev, 0); 1036 1037 sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); 1038 1039 return 0; 1040 } 1041 1042 static void smsdvb_release(struct dvb_frontend *fe) 1043 { 1044 /* do nothing */ 1045 } 1046 1047 static const struct dvb_frontend_ops smsdvb_fe_ops = { 1048 .info = { 1049 .name = "Siano Mobile Digital MDTV Receiver", 1050 .frequency_min = 44250000, 1051 .frequency_max = 867250000, 1052 .frequency_stepsize = 250000, 1053 .caps = FE_CAN_INVERSION_AUTO | 1054 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 1055 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 1056 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | 1057 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | 1058 FE_CAN_GUARD_INTERVAL_AUTO | 1059 FE_CAN_RECOVER | 1060 FE_CAN_HIERARCHY_AUTO, 1061 }, 1062 1063 .release = smsdvb_release, 1064 1065 .set_frontend = smsdvb_set_frontend, 1066 .get_tune_settings = smsdvb_get_tune_settings, 1067 1068 .read_status = smsdvb_read_status, 1069 .read_ber = smsdvb_read_ber, 1070 .read_signal_strength = smsdvb_read_signal_strength, 1071 .read_snr = smsdvb_read_snr, 1072 .read_ucblocks = smsdvb_read_ucblocks, 1073 1074 .init = smsdvb_init, 1075 .sleep = smsdvb_sleep, 1076 }; 1077 1078 static int smsdvb_hotplug(struct smscore_device_t *coredev, 1079 struct device *device, int arrival) 1080 { 1081 struct smsclient_params_t params; 1082 struct smsdvb_client_t *client; 1083 int rc; 1084 1085 /* device removal handled by onremove callback */ 1086 if (!arrival) 1087 return 0; 1088 client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); 1089 if (!client) 1090 return -ENOMEM; 1091 1092 /* register dvb adapter */ 1093 rc = dvb_register_adapter(&client->adapter, 1094 sms_get_board( 1095 smscore_get_board_id(coredev))->name, 1096 THIS_MODULE, device, adapter_nr); 1097 if (rc < 0) { 1098 pr_err("dvb_register_adapter() failed %d\n", rc); 1099 goto adapter_error; 1100 } 1101 dvb_register_media_controller(&client->adapter, coredev->media_dev); 1102 1103 /* init dvb demux */ 1104 client->demux.dmx.capabilities = DMX_TS_FILTERING; 1105 client->demux.filternum = 32; /* todo: nova ??? */ 1106 client->demux.feednum = 32; 1107 client->demux.start_feed = smsdvb_start_feed; 1108 client->demux.stop_feed = smsdvb_stop_feed; 1109 1110 rc = dvb_dmx_init(&client->demux); 1111 if (rc < 0) { 1112 pr_err("dvb_dmx_init failed %d\n", rc); 1113 goto dvbdmx_error; 1114 } 1115 1116 /* init dmxdev */ 1117 client->dmxdev.filternum = 32; 1118 client->dmxdev.demux = &client->demux.dmx; 1119 client->dmxdev.capabilities = 0; 1120 1121 rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); 1122 if (rc < 0) { 1123 pr_err("dvb_dmxdev_init failed %d\n", rc); 1124 goto dmxdev_error; 1125 } 1126 1127 /* init and register frontend */ 1128 memcpy(&client->frontend.ops, &smsdvb_fe_ops, 1129 sizeof(struct dvb_frontend_ops)); 1130 1131 switch (smscore_get_device_mode(coredev)) { 1132 case DEVICE_MODE_DVBT: 1133 case DEVICE_MODE_DVBT_BDA: 1134 client->frontend.ops.delsys[0] = SYS_DVBT; 1135 break; 1136 case DEVICE_MODE_ISDBT: 1137 case DEVICE_MODE_ISDBT_BDA: 1138 client->frontend.ops.delsys[0] = SYS_ISDBT; 1139 break; 1140 } 1141 1142 rc = dvb_register_frontend(&client->adapter, &client->frontend); 1143 if (rc < 0) { 1144 pr_err("frontend registration failed %d\n", rc); 1145 goto frontend_error; 1146 } 1147 1148 params.initial_id = 1; 1149 params.data_type = MSG_SMS_DVBT_BDA_DATA; 1150 params.onresponse_handler = smsdvb_onresponse; 1151 params.onremove_handler = smsdvb_onremove; 1152 params.context = client; 1153 1154 rc = smscore_register_client(coredev, ¶ms, &client->smsclient); 1155 if (rc < 0) { 1156 pr_err("smscore_register_client() failed %d\n", rc); 1157 goto client_error; 1158 } 1159 1160 client->coredev = coredev; 1161 1162 init_completion(&client->tune_done); 1163 init_completion(&client->stats_done); 1164 1165 kmutex_lock(&g_smsdvb_clientslock); 1166 1167 list_add(&client->entry, &g_smsdvb_clients); 1168 1169 kmutex_unlock(&g_smsdvb_clientslock); 1170 1171 client->event_fe_state = -1; 1172 client->event_unc_state = -1; 1173 sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); 1174 1175 sms_board_setup(coredev); 1176 1177 if (smsdvb_debugfs_create(client) < 0) 1178 pr_info("failed to create debugfs node\n"); 1179 1180 rc = dvb_create_media_graph(&client->adapter, true); 1181 if (rc < 0) { 1182 pr_err("dvb_create_media_graph failed %d\n", rc); 1183 goto client_error; 1184 } 1185 1186 pr_info("DVB interface registered.\n"); 1187 return 0; 1188 1189 client_error: 1190 dvb_unregister_frontend(&client->frontend); 1191 1192 frontend_error: 1193 dvb_dmxdev_release(&client->dmxdev); 1194 1195 dmxdev_error: 1196 dvb_dmx_release(&client->demux); 1197 1198 dvbdmx_error: 1199 smsdvb_media_device_unregister(client); 1200 dvb_unregister_adapter(&client->adapter); 1201 1202 adapter_error: 1203 kfree(client); 1204 return rc; 1205 } 1206 1207 static int __init smsdvb_module_init(void) 1208 { 1209 int rc; 1210 1211 INIT_LIST_HEAD(&g_smsdvb_clients); 1212 kmutex_init(&g_smsdvb_clientslock); 1213 1214 smsdvb_debugfs_register(); 1215 1216 rc = smscore_register_hotplug(smsdvb_hotplug); 1217 1218 pr_debug("\n"); 1219 1220 return rc; 1221 } 1222 1223 static void __exit smsdvb_module_exit(void) 1224 { 1225 smscore_unregister_hotplug(smsdvb_hotplug); 1226 1227 kmutex_lock(&g_smsdvb_clientslock); 1228 1229 while (!list_empty(&g_smsdvb_clients)) 1230 smsdvb_unregister_client((struct smsdvb_client_t *)g_smsdvb_clients.next); 1231 1232 smsdvb_debugfs_unregister(); 1233 1234 kmutex_unlock(&g_smsdvb_clientslock); 1235 } 1236 1237 module_init(smsdvb_module_init); 1238 module_exit(smsdvb_module_exit); 1239 1240 MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); 1241 MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); 1242 MODULE_LICENSE("GPL"); 1243