xref: /linux/drivers/media/common/siano/smsdvb-main.c (revision 148f9bb87745ed45f7a11b2cbd3bc0f017d5d257)
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 		break;
144 	default:
145 		n_layers = 1;
146 	}
147 
148 	/* Global stats */
149 	c->strength.len = 1;
150 	c->cnr.len = 1;
151 	c->strength.stat[0].scale = FE_SCALE_DECIBEL;
152 	c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
153 
154 	/* Per-layer stats */
155 	c->post_bit_error.len = n_layers;
156 	c->post_bit_count.len = n_layers;
157 	c->block_error.len = n_layers;
158 	c->block_count.len = n_layers;
159 
160 	/*
161 	 * Put all of them at FE_SCALE_NOT_AVAILABLE. They're dynamically
162 	 * changed when the stats become available.
163 	 */
164 	for (i = 0; i < n_layers; i++) {
165 		c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
166 		c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
167 		c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
168 		c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
169 	}
170 }
171 
172 static inline int sms_to_mode(u32 mode)
173 {
174 	switch (mode) {
175 	case 2:
176 		return TRANSMISSION_MODE_2K;
177 	case 4:
178 		return TRANSMISSION_MODE_4K;
179 	case 8:
180 		return TRANSMISSION_MODE_8K;
181 	}
182 	return TRANSMISSION_MODE_AUTO;
183 }
184 
185 static inline int sms_to_status(u32 is_demod_locked, u32 is_rf_locked)
186 {
187 	if (is_demod_locked)
188 		return FE_HAS_SIGNAL  | FE_HAS_CARRIER | FE_HAS_VITERBI |
189 		       FE_HAS_SYNC    | FE_HAS_LOCK;
190 
191 	if (is_rf_locked)
192 		return FE_HAS_SIGNAL | FE_HAS_CARRIER;
193 
194 	return 0;
195 }
196 
197 static inline u32 sms_to_bw(u32 value)
198 {
199 	return value * 1000000;
200 }
201 
202 #define convert_from_table(value, table, defval) ({			\
203 	u32 __ret;							\
204 	if (value < ARRAY_SIZE(table))					\
205 		__ret = table[value];					\
206 	else								\
207 		__ret = defval;						\
208 	__ret;								\
209 })
210 
211 #define sms_to_guard_interval(value)					\
212 	convert_from_table(value, sms_to_guard_interval_table,		\
213 			   GUARD_INTERVAL_AUTO);
214 
215 #define sms_to_code_rate(value)						\
216 	convert_from_table(value, sms_to_code_rate_table,		\
217 			   FEC_NONE);
218 
219 #define sms_to_hierarchy(value)						\
220 	convert_from_table(value, sms_to_hierarchy_table,		\
221 			   FEC_NONE);
222 
223 #define sms_to_modulation(value)					\
224 	convert_from_table(value, sms_to_modulation_table,		\
225 			   FEC_NONE);
226 
227 static void smsdvb_update_tx_params(struct smsdvb_client_t *client,
228 				    struct sms_tx_stats *p)
229 {
230 	struct dvb_frontend *fe = &client->frontend;
231 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
232 
233 	c->frequency = p->frequency;
234 	client->fe_status = sms_to_status(p->is_demod_locked, 0);
235 	c->bandwidth_hz = sms_to_bw(p->bandwidth);
236 	c->transmission_mode = sms_to_mode(p->transmission_mode);
237 	c->guard_interval = sms_to_guard_interval(p->guard_interval);
238 	c->code_rate_HP = sms_to_code_rate(p->code_rate);
239 	c->code_rate_LP = sms_to_code_rate(p->lp_code_rate);
240 	c->hierarchy = sms_to_hierarchy(p->hierarchy);
241 	c->modulation = sms_to_modulation(p->constellation);
242 }
243 
244 static void smsdvb_update_per_slices(struct smsdvb_client_t *client,
245 				     struct RECEPTION_STATISTICS_PER_SLICES_S *p)
246 {
247 	struct dvb_frontend *fe = &client->frontend;
248 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
249 	u64 tmp;
250 
251 	client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
252 	c->modulation = sms_to_modulation(p->constellation);
253 
254 	/* signal Strength, in DBm */
255 	c->strength.stat[0].uvalue = p->in_band_power * 1000;
256 
257 	/* Carrier to noise ratio, in DB */
258 	c->cnr.stat[0].svalue = p->snr * 1000;
259 
260 	/* PER/BER requires demod lock */
261 	if (!p->is_demod_locked)
262 		return;
263 
264 	/* TS PER */
265 	client->last_per = c->block_error.stat[0].uvalue;
266 	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
267 	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
268 	c->block_error.stat[0].uvalue += p->ets_packets;
269 	c->block_count.stat[0].uvalue += p->ets_packets + p->ts_packets;
270 
271 	/* ber */
272 	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
273 	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
274 	c->post_bit_error.stat[0].uvalue += p->ber_error_count;
275 	c->post_bit_count.stat[0].uvalue += p->ber_bit_count;
276 
277 	/* Legacy PER/BER */
278 	tmp = p->ets_packets * 65535;
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");
1232