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