smsdvb-main.c 32 KB

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