root/drivers/media/common/siano/smsdvb-main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sms_board_dvb3_event
  2. smsdvb_stats_not_ready
  3. sms_to_mode
  4. sms_to_status
  5. sms_to_bw
  6. smsdvb_update_tx_params
  7. smsdvb_update_per_slices
  8. smsdvb_update_dvb_stats
  9. smsdvb_update_isdbt_stats
  10. smsdvb_update_isdbt_stats_ex
  11. smsdvb_onresponse
  12. smsdvb_media_device_unregister
  13. smsdvb_unregister_client
  14. smsdvb_onremove
  15. smsdvb_start_feed
  16. smsdvb_stop_feed
  17. smsdvb_sendrequest_and_wait
  18. smsdvb_send_statistics_request
  19. led_feedback
  20. smsdvb_read_status
  21. smsdvb_read_ber
  22. smsdvb_read_signal_strength
  23. smsdvb_read_snr
  24. smsdvb_read_ucblocks
  25. smsdvb_get_tune_settings
  26. smsdvb_dvbt_set_frontend
  27. smsdvb_isdbt_set_frontend
  28. smsdvb_set_frontend
  29. smsdvb_init
  30. smsdvb_sleep
  31. smsdvb_release
  32. smsdvb_hotplug
  33. smsdvb_module_init
  34. smsdvb_module_exit

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

/* [<][>][^][v][top][bottom][index][help] */