blob: 1d6b8dfa0808b4a3715f3e1294e01aab23a7f545 [file] [log] [blame]
Uri Shkolnike5275792009-04-27 09:09:47 -03001/****************************************************************
2
3Siano Mobile Silicon, Inc.
4MDTV receiver kernel modules.
5Copyright (C) 2006-2008, Uri Shkolnik
6
7This program is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the 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,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20****************************************************************/
Steven Toth8d4f9d02008-05-22 18:05:26 -030021
Michael Krufky2e5c1ec82008-05-19 18:56:13 -030022#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Michael Krufky2e5c1ec82008-05-19 18:56:13 -030024#include <linux/init.h>
25
Uri Shkolnikc9679e32009-05-14 16:28:17 -030026#include "dmxdev.h"
27#include "dvbdev.h"
28#include "dvb_demux.h"
29#include "dvb_frontend.h"
30
Michael Krufky2e5c1ec82008-05-19 18:56:13 -030031#include "smscoreapi.h"
Michael Krufky1c11d542008-06-18 22:09:55 -030032#include "sms-cards.h"
Michael Krufky2e5c1ec82008-05-19 18:56:13 -030033
Michael Krufky9c59f9682008-05-19 18:57:12 -030034DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
35
Michael Krufky62c7167d2008-08-31 17:15:47 -030036struct smsdvb_client_t {
37 struct list_head entry;
38
39 struct smscore_device_t *coredev;
40 struct smscore_client_t *smsclient;
41
42 struct dvb_adapter adapter;
43 struct dvb_demux demux;
44 struct dmxdev dmxdev;
45 struct dvb_frontend frontend;
46
47 fe_status_t fe_status;
Michael Krufky62c7167d2008-08-31 17:15:47 -030048
Uri Shkolnik793786d2009-05-12 12:28:46 -030049 struct completion tune_done;
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -030050 struct completion stats_done;
Michael Krufky62c7167d2008-08-31 17:15:47 -030051
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -030052 struct SMSHOSTLIB_STATISTICS_DVB_EX_S sms_stat_dvb;
Uri Shkolnik793786d2009-05-12 12:28:46 -030053 int event_fe_state;
54 int event_unc_state;
Michael Krufky62c7167d2008-08-31 17:15:47 -030055};
56
Adrian Bunkc5e0bd12008-07-21 23:17:36 -030057static struct list_head g_smsdvb_clients;
58static struct mutex g_smsdvb_clientslock;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -030059
Michael Krufky0d02efe2009-02-27 02:42:16 -030060static int sms_dbg;
61module_param_named(debug, sms_dbg, int, 0644);
62MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
63
Uri Shkolnik793786d2009-05-12 12:28:46 -030064/* Events that may come from DVB v3 adapter */
65static void sms_board_dvb3_event(struct smsdvb_client_t *client,
66 enum SMS_DVB3_EVENTS event) {
Uri Shkolnik4db989f2009-05-19 12:28:02 -030067
68 struct smscore_device_t *coredev = client->coredev;
69 switch (event) {
70 case DVB3_EVENT_INIT:
71 sms_debug("DVB3_EVENT_INIT");
72 sms_board_event(coredev, BOARD_EVENT_BIND);
73 break;
74 case DVB3_EVENT_SLEEP:
75 sms_debug("DVB3_EVENT_SLEEP");
76 sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
77 break;
78 case DVB3_EVENT_HOTPLUG:
79 sms_debug("DVB3_EVENT_HOTPLUG");
80 sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
81 break;
82 case DVB3_EVENT_FE_LOCK:
83 if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
84 client->event_fe_state = DVB3_EVENT_FE_LOCK;
85 sms_debug("DVB3_EVENT_FE_LOCK");
86 sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
87 }
88 break;
89 case DVB3_EVENT_FE_UNLOCK:
90 if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
91 client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
92 sms_debug("DVB3_EVENT_FE_UNLOCK");
93 sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
94 }
95 break;
96 case DVB3_EVENT_UNC_OK:
97 if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
98 client->event_unc_state = DVB3_EVENT_UNC_OK;
99 sms_debug("DVB3_EVENT_UNC_OK");
100 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
101 }
102 break;
103 case DVB3_EVENT_UNC_ERR:
104 if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
105 client->event_unc_state = DVB3_EVENT_UNC_ERR;
106 sms_debug("DVB3_EVENT_UNC_ERR");
107 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
108 }
109 break;
110
111 default:
112 sms_err("Unknown dvb3 api event");
113 break;
114 }
Uri Shkolnik793786d2009-05-12 12:28:46 -0300115}
116
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300117static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300118 struct SMSHOSTLIB_STATISTICS_ST *p)
119{
120 if (sms_dbg & 2) {
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300121 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
122 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
123 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
124 printk(KERN_DEBUG "SNR = %d", p->SNR);
125 printk(KERN_DEBUG "BER = %d", p->BER);
126 printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
127 printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
128 printk(KERN_DEBUG "MFER = %d", p->MFER);
129 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
130 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
131 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300132 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300133 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
134 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
135 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
136 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
137 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
138 printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
139 printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
140 printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
141 printk(KERN_DEBUG "Constellation = %d", p->Constellation);
142 printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
143 printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
144 printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
145 printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
146 printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
147 printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
148 printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
149 printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
150 printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
151 printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
152 printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
153 printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
154 printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
155 printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
156 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
157 printk(KERN_DEBUG "PreBER = %d", p->PreBER);
158 printk(KERN_DEBUG "CellId = %d", p->CellId);
159 printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
160 printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
161 printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300162 }
163
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300164 /* update reception data */
165 pReceptionData->IsRfLocked = p->IsRfLocked;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300166 pReceptionData->IsDemodLocked = p->IsDemodLocked;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300167 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
168 pReceptionData->ModemState = p->ModemState;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300169 pReceptionData->SNR = p->SNR;
170 pReceptionData->BER = p->BER;
171 pReceptionData->BERErrorCount = p->BERErrorCount;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300172 pReceptionData->BERBitCount = p->BERBitCount;
173 pReceptionData->RSSI = p->RSSI;
174 CORRECT_STAT_RSSI(*pReceptionData);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300175 pReceptionData->InBandPwr = p->InBandPwr;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300176 pReceptionData->CarrierOffset = p->CarrierOffset;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300177 pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300178 pReceptionData->TotalTSPackets = p->TotalTSPackets;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300179};
180
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300181static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300182 struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
183{
184 int i;
185
186 if (sms_dbg & 2) {
187 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
188 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
189 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
190 printk(KERN_DEBUG "SNR = %d", p->SNR);
191 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
192 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
193 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
194 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
195 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
196 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
197 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
198 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
199 printk(KERN_DEBUG "SystemType = %d", p->SystemType);
200 printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
201 printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
202 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
203
204 for (i = 0; i < 3; i++) {
205 printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
206 printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
207 printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
208 printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
209 printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
210 printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
211 printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
212 printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
213 printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
214 printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
215 printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
216 printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
217 }
218 }
219
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300220 /* update reception data */
221 pReceptionData->IsRfLocked = p->IsRfLocked;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300222 pReceptionData->IsDemodLocked = p->IsDemodLocked;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300223 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
224 pReceptionData->ModemState = p->ModemState;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300225 pReceptionData->SNR = p->SNR;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300226 pReceptionData->BER = p->LayerInfo[0].BER;
227 pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
228 pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
229 pReceptionData->RSSI = p->RSSI;
230 CORRECT_STAT_RSSI(*pReceptionData);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300231 pReceptionData->InBandPwr = p->InBandPwr;
232
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300233 pReceptionData->CarrierOffset = p->CarrierOffset;
234 pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
235 pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
236 pReceptionData->MFER = 0;
237
238 /* TS PER */
239 if ((p->LayerInfo[0].TotalTSPackets +
240 p->LayerInfo[0].ErrorTSPackets) > 0) {
241 pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets
242 * 100) / (p->LayerInfo[0].TotalTSPackets
243 + p->LayerInfo[0].ErrorTSPackets);
244 } else {
245 pReceptionData->TS_PER = 0;
246 }
247}
248
249static void smsdvb_update_isdbt_stats_ex(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
250 struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST *p)
251{
252 int i;
253
254 if (sms_dbg & 2) {
255 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
256 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
257 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
258 printk(KERN_DEBUG "SNR = %d", p->SNR);
259 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
260 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
261 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
262 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
263 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
264 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
265 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
266 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
267 printk(KERN_DEBUG "SystemType = %d", p->SystemType);
268 printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
269 printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
270 printk(KERN_DEBUG "SegmentNumber = %d", p->SegmentNumber);
271 printk(KERN_DEBUG "TuneBW = %d", p->TuneBW);
272 for (i = 0; i < 3; i++) {
273 printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
274 printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
275 printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
276 printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
277 printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
278 printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
279 printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
280 printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
281 printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
282 printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
283 printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
284 printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
285 }
286 }
287
288 /* update reception data */
289 pReceptionData->IsRfLocked = p->IsRfLocked;
290 pReceptionData->IsDemodLocked = p->IsDemodLocked;
291 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
292 pReceptionData->ModemState = p->ModemState;
293 pReceptionData->SNR = p->SNR;
294 pReceptionData->BER = p->LayerInfo[0].BER;
295 pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
296 pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
297 pReceptionData->RSSI = p->RSSI;
298 CORRECT_STAT_RSSI(*pReceptionData);
299 pReceptionData->InBandPwr = p->InBandPwr;
300
301 pReceptionData->CarrierOffset = p->CarrierOffset;
302 pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
303 pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
304 pReceptionData->MFER = 0;
305
306 /* TS PER */
307 if ((p->LayerInfo[0].TotalTSPackets +
308 p->LayerInfo[0].ErrorTSPackets) > 0) {
309 pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets
310 * 100) / (p->LayerInfo[0].TotalTSPackets
311 + p->LayerInfo[0].ErrorTSPackets);
312 } else {
313 pReceptionData->TS_PER = 0;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300314 }
315}
316
Michael Krufky0c071f32008-06-21 02:44:02 -0300317static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300318{
Michael Krufky18245e12008-06-15 17:52:24 -0300319 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300320 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
321 + cb->offset);
322 u32 *pMsgData = (u32 *) phdr + 1;
323 /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
324 bool is_status_update = false;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300325
Michael Krufkyfa830e82008-06-15 15:52:43 -0300326 switch (phdr->msgType) {
Michael Krufky82237412008-06-15 15:14:13 -0300327 case MSG_SMS_DVBT_BDA_DATA:
328 dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
Michael Krufky18245e12008-06-15 17:52:24 -0300329 cb->size - sizeof(struct SmsMsgHdr_ST));
Michael Krufky82237412008-06-15 15:14:13 -0300330 break;
331
332 case MSG_SMS_RF_TUNE_RES:
Michael Krufky6b26fce2009-12-22 21:08:49 -0300333 case MSG_SMS_ISDBT_TUNE_RES:
Michael Krufky82237412008-06-15 15:14:13 -0300334 complete(&client->tune_done);
335 break;
336
Uri Shkolnik793786d2009-05-12 12:28:46 -0300337 case MSG_SMS_SIGNAL_DETECTED_IND:
Uri Shkolnik793786d2009-05-12 12:28:46 -0300338 client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
339 is_status_update = true;
340 break;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300341
Uri Shkolnik793786d2009-05-12 12:28:46 -0300342 case MSG_SMS_NO_SIGNAL_IND:
Uri Shkolnik793786d2009-05-12 12:28:46 -0300343 client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
344 is_status_update = true;
345 break;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300346
Uri Shkolnik793786d2009-05-12 12:28:46 -0300347 case MSG_SMS_TRANSMISSION_IND: {
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300348
Uri Shkolnik793786d2009-05-12 12:28:46 -0300349 pMsgData++;
350 memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
351 sizeof(struct TRANSMISSION_STATISTICS_S));
352
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300353#if 1
354 /*
355 * FIXME: newer driver doesn't have those fixes
356 * Are those firmware-specific stuff?
357 */
358
Uri Shkolnik793786d2009-05-12 12:28:46 -0300359 /* Mo need to correct guard interval
360 * (as opposed to old statistics message).
361 */
362 CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
363 CORRECT_STAT_TRANSMISSON_MODE(
364 client->sms_stat_dvb.TransmissionData);
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300365#endif
Uri Shkolnik793786d2009-05-12 12:28:46 -0300366 is_status_update = true;
367 break;
368 }
369 case MSG_SMS_HO_PER_SLICES_IND: {
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300370 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
Uri Shkolnik793786d2009-05-12 12:28:46 -0300371 &client->sms_stat_dvb.ReceptionData;
372 struct SRVM_SIGNAL_STATUS_S SignalStatusData;
373
Uri Shkolnik793786d2009-05-12 12:28:46 -0300374 pMsgData++;
375 SignalStatusData.result = pMsgData[0];
376 SignalStatusData.snr = pMsgData[1];
377 SignalStatusData.inBandPower = (s32) pMsgData[2];
378 SignalStatusData.tsPackets = pMsgData[3];
379 SignalStatusData.etsPackets = pMsgData[4];
380 SignalStatusData.constellation = pMsgData[5];
381 SignalStatusData.hpCode = pMsgData[6];
382 SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
383 SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
384 SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
385 SignalStatusData.reason = pMsgData[10];
386 SignalStatusData.requestId = pMsgData[11];
387 pReceptionData->IsRfLocked = pMsgData[16];
388 pReceptionData->IsDemodLocked = pMsgData[17];
389 pReceptionData->ModemState = pMsgData[12];
390 pReceptionData->SNR = pMsgData[1];
391 pReceptionData->BER = pMsgData[13];
392 pReceptionData->RSSI = pMsgData[14];
393 CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
394
395 pReceptionData->InBandPwr = (s32) pMsgData[2];
396 pReceptionData->CarrierOffset = (s32) pMsgData[15];
397 pReceptionData->TotalTSPackets = pMsgData[3];
398 pReceptionData->ErrorTSPackets = pMsgData[4];
399
400 /* TS PER */
401 if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
402 > 0) {
403 pReceptionData->TS_PER = (SignalStatusData.etsPackets
404 * 100) / (SignalStatusData.tsPackets
405 + SignalStatusData.etsPackets);
Michael Krufky82237412008-06-15 15:14:13 -0300406 } else {
Uri Shkolnik793786d2009-05-12 12:28:46 -0300407 pReceptionData->TS_PER = 0;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300408 }
Michael Krufky82237412008-06-15 15:14:13 -0300409
Uri Shkolnik793786d2009-05-12 12:28:46 -0300410 pReceptionData->BERBitCount = pMsgData[18];
411 pReceptionData->BERErrorCount = pMsgData[19];
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300412
Uri Shkolnik793786d2009-05-12 12:28:46 -0300413 pReceptionData->MRC_SNR = pMsgData[20];
414 pReceptionData->MRC_InBandPwr = pMsgData[21];
415 pReceptionData->MRC_RSSI = pMsgData[22];
416
417 is_status_update = true;
418 break;
419 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300420 case MSG_SMS_GET_STATISTICS_RES: {
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300421 union {
422 struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
423 struct SmsMsgStatisticsInfo_ST dvb;
424 } *p = (void *) (phdr + 1);
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300425 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300426 &client->sms_stat_dvb.ReceptionData;
427
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300428 is_status_update = true;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300429
430 switch (smscore_get_device_mode(client->coredev)) {
431 case DEVICE_MODE_ISDBT:
432 case DEVICE_MODE_ISDBT_BDA:
433 smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
434 break;
435 default:
436 smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
437 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300438 if (!pReceptionData->IsDemodLocked) {
439 pReceptionData->SNR = 0;
440 pReceptionData->BER = 0;
441 pReceptionData->BERErrorCount = 0;
442 pReceptionData->InBandPwr = 0;
443 pReceptionData->ErrorTSPackets = 0;
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300444 }
445
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300446 break;
447 }
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300448 case MSG_SMS_GET_STATISTICS_EX_RES: {
449 union {
450 struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST isdbt;
451 struct SMSHOSTLIB_STATISTICS_ST dvb;
452 } *p = (void *) (phdr + 1);
453 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
454 &client->sms_stat_dvb.ReceptionData;
455
456 is_status_update = true;
457
458 switch (smscore_get_device_mode(client->coredev)) {
459 case DEVICE_MODE_ISDBT:
460 case DEVICE_MODE_ISDBT_BDA:
461 smsdvb_update_isdbt_stats_ex(pReceptionData, &p->isdbt);
462 break;
463 default:
464 smsdvb_update_dvb_stats(pReceptionData, &p->dvb);
465 }
466 if (!pReceptionData->IsDemodLocked) {
467 pReceptionData->SNR = 0;
468 pReceptionData->BER = 0;
469 pReceptionData->BERErrorCount = 0;
470 pReceptionData->InBandPwr = 0;
471 pReceptionData->ErrorTSPackets = 0;
472 }
473
474 break;
475 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300476 default:
Mauro Carvalho Chehab4c3bdb52013-03-09 09:27:39 -0300477 sms_info("message not handled");
Uri Shkolnik793786d2009-05-12 12:28:46 -0300478 }
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300479 smscore_putbuffer(client->coredev, cb);
480
Uri Shkolnik793786d2009-05-12 12:28:46 -0300481 if (is_status_update) {
482 if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
483 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
484 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
485 sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
486 if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
487 == 0)
488 sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
489 else
490 sms_board_dvb3_event(client,
491 DVB3_EVENT_UNC_ERR);
492
493 } else {
Mauro Carvalho Chehabb4622c12009-12-25 18:04:17 -0300494 if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
495 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
496 else
497 client->fe_status = 0;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300498 sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
499 }
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -0300500 complete(&client->stats_done);
Uri Shkolnik793786d2009-05-12 12:28:46 -0300501 }
502
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300503 return 0;
504}
505
Michael Krufky0c071f32008-06-21 02:44:02 -0300506static void smsdvb_unregister_client(struct smsdvb_client_t *client)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300507{
Michael Krufkyfa830e82008-06-15 15:52:43 -0300508 /* must be called under clientslock */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300509
510 list_del(&client->entry);
511
512 smscore_unregister_client(client->smsclient);
513 dvb_unregister_frontend(&client->frontend);
514 dvb_dmxdev_release(&client->dmxdev);
515 dvb_dmx_release(&client->demux);
516 dvb_unregister_adapter(&client->adapter);
517 kfree(client);
518}
519
Michael Krufky0c071f32008-06-21 02:44:02 -0300520static void smsdvb_onremove(void *context)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300521{
522 kmutex_lock(&g_smsdvb_clientslock);
523
Michael Krufky18245e12008-06-15 17:52:24 -0300524 smsdvb_unregister_client((struct smsdvb_client_t *) context);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300525
526 kmutex_unlock(&g_smsdvb_clientslock);
527}
528
529static int smsdvb_start_feed(struct dvb_demux_feed *feed)
530{
Michael Krufky18245e12008-06-15 17:52:24 -0300531 struct smsdvb_client_t *client =
532 container_of(feed->demux, struct smsdvb_client_t, demux);
533 struct SmsMsgData_ST PidMsg;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300534
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300535 sms_debug("add pid %d(%x)",
Michael Krufky068d6c02008-06-19 01:15:46 -0300536 feed->pid, feed->pid);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300537
538 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
539 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
540 PidMsg.xMsgHeader.msgFlags = 0;
541 PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ;
542 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
543 PidMsg.msgData[0] = feed->pid;
544
Michael Krufky82237412008-06-15 15:14:13 -0300545 return smsclient_sendrequest(client->smsclient,
546 &PidMsg, sizeof(PidMsg));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300547}
548
549static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
550{
Michael Krufky18245e12008-06-15 17:52:24 -0300551 struct smsdvb_client_t *client =
552 container_of(feed->demux, struct smsdvb_client_t, demux);
553 struct SmsMsgData_ST PidMsg;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300554
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300555 sms_debug("remove pid %d(%x)",
Michael Krufky068d6c02008-06-19 01:15:46 -0300556 feed->pid, feed->pid);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300557
558 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
559 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
560 PidMsg.xMsgHeader.msgFlags = 0;
561 PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ;
562 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
563 PidMsg.msgData[0] = feed->pid;
564
Michael Krufky82237412008-06-15 15:14:13 -0300565 return smsclient_sendrequest(client->smsclient,
566 &PidMsg, sizeof(PidMsg));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300567}
568
Michael Krufky18245e12008-06-15 17:52:24 -0300569static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
Michael Krufkya83ccdd2008-05-06 03:11:51 -0300570 void *buffer, size_t size,
571 struct completion *completion)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300572{
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300573 int rc;
574
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300575 rc = smsclient_sendrequest(client->smsclient, buffer, size);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300576 if (rc < 0)
577 return rc;
578
Michael Krufky82237412008-06-15 15:14:13 -0300579 return wait_for_completion_timeout(completion,
580 msecs_to_jiffies(2000)) ?
581 0 : -ETIME;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300582}
583
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300584static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
585{
586 int rc;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300587 struct SmsMsgHdr_ST Msg;
588
589
590 Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
591 Msg.msgDstId = HIF_TASK;
592 Msg.msgFlags = 0;
593 Msg.msgLength = sizeof(Msg);
594
595 /*
596 * Check for firmware version, to avoid breaking for old cards
597 */
598 if (client->coredev->fw_version >= 0x800)
599 Msg.msgType = MSG_SMS_GET_STATISTICS_EX_REQ;
600 else
601 Msg.msgType = MSG_SMS_GET_STATISTICS_REQ;
602
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300603 rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -0300604 &client->stats_done);
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300605
606 return rc;
607}
608
Michael Krufky3746b612009-07-12 23:30:14 -0300609static inline int led_feedback(struct smsdvb_client_t *client)
610{
611 if (client->fe_status & FE_HAS_LOCK)
612 return sms_board_led_feedback(client->coredev,
613 (client->sms_stat_dvb.ReceptionData.BER
614 == 0) ? SMS_LED_HI : SMS_LED_LO);
615 else
616 return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
617}
618
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300619static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
620{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300621 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300622 struct smsdvb_client_t *client;
623 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300624
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300625 rc = smsdvb_send_statistics_request(client);
626
Uri Shkolnik793786d2009-05-12 12:28:46 -0300627 *stat = client->fe_status;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300628
Michael Krufky3746b612009-07-12 23:30:14 -0300629 led_feedback(client);
630
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300631 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300632}
633
634static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
635{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300636 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300637 struct smsdvb_client_t *client;
638 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300639
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300640 rc = smsdvb_send_statistics_request(client);
641
Uri Shkolnik793786d2009-05-12 12:28:46 -0300642 *ber = client->sms_stat_dvb.ReceptionData.BER;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300643
Michael Krufky3746b612009-07-12 23:30:14 -0300644 led_feedback(client);
645
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300646 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300647}
648
649static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
650{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300651 int rc;
652
Uri Shkolnik793786d2009-05-12 12:28:46 -0300653 struct smsdvb_client_t *client;
654 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300655
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300656 rc = smsdvb_send_statistics_request(client);
657
Uri Shkolnik793786d2009-05-12 12:28:46 -0300658 if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
659 *strength = 0;
660 else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
661 *strength = 100;
662 else
663 *strength =
664 (client->sms_stat_dvb.ReceptionData.InBandPwr
665 + 95) * 3 / 2;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300666
Michael Krufky3746b612009-07-12 23:30:14 -0300667 led_feedback(client);
668
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300669 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300670}
671
672static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
673{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300674 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300675 struct smsdvb_client_t *client;
676 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300677
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300678 rc = smsdvb_send_statistics_request(client);
679
Uri Shkolnik793786d2009-05-12 12:28:46 -0300680 *snr = client->sms_stat_dvb.ReceptionData.SNR;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300681
Michael Krufky3746b612009-07-12 23:30:14 -0300682 led_feedback(client);
683
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300684 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300685}
686
Michael Krufky851a9092008-11-22 14:56:37 -0300687static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
688{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300689 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300690 struct smsdvb_client_t *client;
691 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky851a9092008-11-22 14:56:37 -0300692
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300693 rc = smsdvb_send_statistics_request(client);
694
Uri Shkolnik793786d2009-05-12 12:28:46 -0300695 *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
Michael Krufky851a9092008-11-22 14:56:37 -0300696
Michael Krufky3746b612009-07-12 23:30:14 -0300697 led_feedback(client);
698
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300699 return rc;
Michael Krufky851a9092008-11-22 14:56:37 -0300700}
701
Michael Krufky82237412008-06-15 15:14:13 -0300702static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
703 struct dvb_frontend_tune_settings *tune)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300704{
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300705 sms_debug("");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300706
707 tune->min_delay_ms = 400;
708 tune->step_size = 250000;
709 tune->max_drift = 0;
710 return 0;
711}
712
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300713static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300714{
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300715 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Michael Krufky18245e12008-06-15 17:52:24 -0300716 struct smsdvb_client_t *client =
717 container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300718
Michael Krufky18245e12008-06-15 17:52:24 -0300719 struct {
720 struct SmsMsgHdr_ST Msg;
Michael Krufky82237412008-06-15 15:14:13 -0300721 u32 Data[3];
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300722 } Msg;
723
Michael Krufky3746b612009-07-12 23:30:14 -0300724 int ret;
725
Uri Shkolnik793786d2009-05-12 12:28:46 -0300726 client->fe_status = FE_HAS_SIGNAL;
727 client->event_fe_state = -1;
728 client->event_unc_state = -1;
Mauro Carvalho Chehabe85c97a2009-12-25 07:17:03 -0300729 fe->dtv_property_cache.delivery_system = SYS_DVBT;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300730
731 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
732 Msg.Msg.msgDstId = HIF_TASK;
733 Msg.Msg.msgFlags = 0;
734 Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300735 Msg.Msg.msgLength = sizeof(Msg);
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300736 Msg.Data[0] = c->frequency;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300737 Msg.Data[2] = 12000000;
738
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300739 sms_info("%s: freq %d band %d", __func__, c->frequency,
740 c->bandwidth_hz);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300741
Mauro Carvalho Chehab643e15a2009-12-25 07:29:06 -0300742 switch (c->bandwidth_hz / 1000000) {
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300743 case 8:
744 Msg.Data[1] = BW_8_MHZ;
745 break;
746 case 7:
747 Msg.Data[1] = BW_7_MHZ;
748 break;
749 case 6:
750 Msg.Data[1] = BW_6_MHZ;
751 break;
752 case 0:
753 return -EOPNOTSUPP;
754 default:
755 return -EINVAL;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300756 }
Michael Krufky3746b612009-07-12 23:30:14 -0300757 /* Disable LNA, if any. An error is returned if no LNA is present */
758 ret = sms_board_lna_control(client->coredev, 0);
759 if (ret == 0) {
760 fe_status_t status;
761
762 /* tune with LNA off at first */
763 ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
764 &client->tune_done);
765
766 smsdvb_read_status(fe, &status);
767
768 if (status & FE_HAS_LOCK)
769 return ret;
770
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300771 /* previous tune didn't lock - enable LNA and tune again */
Michael Krufky3746b612009-07-12 23:30:14 -0300772 sms_board_lna_control(client->coredev, 1);
773 }
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300774
Michael Krufky82237412008-06-15 15:14:13 -0300775 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
776 &client->tune_done);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300777}
778
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300779static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
Michael Krufky6b26fce2009-12-22 21:08:49 -0300780{
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300781 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300782 struct smsdvb_client_t *client =
783 container_of(fe, struct smsdvb_client_t, frontend);
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300784 int board_id = smscore_get_board_id(client->coredev);
785 struct sms_board *board = sms_get_board(board_id);
786 enum sms_device_type_st type = board->type;
Mauro Carvalho Chehab0c189fa2013-03-07 16:34:53 -0300787 int ret;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300788 struct {
789 struct SmsMsgHdr_ST Msg;
790 u32 Data[4];
791 } Msg;
792
Mauro Carvalho Chehabe85c97a2009-12-25 07:17:03 -0300793 fe->dtv_property_cache.delivery_system = SYS_ISDBT;
794
Michael Krufky6b26fce2009-12-22 21:08:49 -0300795 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
796 Msg.Msg.msgDstId = HIF_TASK;
797 Msg.Msg.msgFlags = 0;
798 Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ;
799 Msg.Msg.msgLength = sizeof(Msg);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300800
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300801 if (c->isdbt_sb_segment_idx == -1)
802 c->isdbt_sb_segment_idx = 0;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300803
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300804 if (!c->isdbt_layer_enabled)
805 c->isdbt_layer_enabled = 7;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300806
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300807 Msg.Data[0] = c->frequency;
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300808 Msg.Data[1] = BW_ISDBT_1SEG;
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300809 Msg.Data[2] = 12000000;
810 Msg.Data[3] = c->isdbt_sb_segment_idx;
811
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300812 if (c->isdbt_partial_reception) {
813 if ((type == SMS_PELE || type == SMS_RIO) &&
814 c->isdbt_sb_segment_count > 3)
815 Msg.Data[1] = BW_ISDBT_13SEG;
816 else if (c->isdbt_sb_segment_count > 1)
817 Msg.Data[1] = BW_ISDBT_3SEG;
818 } else if (type == SMS_PELE || type == SMS_RIO)
819 Msg.Data[1] = BW_ISDBT_13SEG;
820
821 c->bandwidth_hz = 6000000;
822
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300823 sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
824 c->frequency, c->isdbt_sb_segment_count,
825 c->isdbt_sb_segment_idx);
826
Mauro Carvalho Chehab0c189fa2013-03-07 16:34:53 -0300827 /* Disable LNA, if any. An error is returned if no LNA is present */
828 ret = sms_board_lna_control(client->coredev, 0);
829 if (ret == 0) {
830 fe_status_t status;
831
832 /* tune with LNA off at first */
833 ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
834 &client->tune_done);
835
836 smsdvb_read_status(fe, &status);
837
838 if (status & FE_HAS_LOCK)
839 return ret;
840
841 /* previous tune didn't lock - enable LNA and tune again */
842 sms_board_lna_control(client->coredev, 1);
843 }
Michael Krufky6b26fce2009-12-22 21:08:49 -0300844 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
845 &client->tune_done);
846}
847
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300848static int smsdvb_set_frontend(struct dvb_frontend *fe)
Michael Krufky6b26fce2009-12-22 21:08:49 -0300849{
850 struct smsdvb_client_t *client =
851 container_of(fe, struct smsdvb_client_t, frontend);
852 struct smscore_device_t *coredev = client->coredev;
853
854 switch (smscore_get_device_mode(coredev)) {
855 case DEVICE_MODE_DVBT:
856 case DEVICE_MODE_DVBT_BDA:
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300857 return smsdvb_dvbt_set_frontend(fe);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300858 case DEVICE_MODE_ISDBT:
859 case DEVICE_MODE_ISDBT_BDA:
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300860 return smsdvb_isdbt_set_frontend(fe);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300861 default:
862 return -EINVAL;
863 }
864}
865
Mauro Carvalho Chehabeab0fa02013-03-09 12:05:58 -0300866static int smsdvb_get_frontend_dvb(struct dvb_frontend *fe)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300867{
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -0300868 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
Michael Krufky18245e12008-06-15 17:52:24 -0300869 struct smsdvb_client_t *client =
870 container_of(fe, struct smsdvb_client_t, frontend);
Gianluca Gennarid1382102012-02-20 07:50:33 -0300871 struct TRANSMISSION_STATISTICS_S *td =
872 &client->sms_stat_dvb.TransmissionData;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300873
Mauro Carvalho Chehabeab0fa02013-03-09 12:05:58 -0300874 fep->frequency = td->Frequency;
875
876 switch (td->Bandwidth) {
877 case 6:
878 fep->bandwidth_hz = 6000000;
879 break;
880 case 7:
881 fep->bandwidth_hz = 7000000;
882 break;
883 case 8:
884 fep->bandwidth_hz = 8000000;
885 break;
886 }
887
888 switch (td->TransmissionMode) {
889 case 2:
890 fep->transmission_mode = TRANSMISSION_MODE_2K;
891 break;
892 case 8:
893 fep->transmission_mode = TRANSMISSION_MODE_8K;
894 }
895
896 switch (td->GuardInterval) {
897 case 0:
898 fep->guard_interval = GUARD_INTERVAL_1_32;
899 break;
900 case 1:
901 fep->guard_interval = GUARD_INTERVAL_1_16;
902 break;
903 case 2:
904 fep->guard_interval = GUARD_INTERVAL_1_8;
905 break;
906 case 3:
907 fep->guard_interval = GUARD_INTERVAL_1_4;
908 break;
909 }
910
911 switch (td->CodeRate) {
912 case 0:
913 fep->code_rate_HP = FEC_1_2;
914 break;
915 case 1:
916 fep->code_rate_HP = FEC_2_3;
917 break;
918 case 2:
919 fep->code_rate_HP = FEC_3_4;
920 break;
921 case 3:
922 fep->code_rate_HP = FEC_5_6;
923 break;
924 case 4:
925 fep->code_rate_HP = FEC_7_8;
926 break;
927 }
928
929 switch (td->LPCodeRate) {
930 case 0:
931 fep->code_rate_LP = FEC_1_2;
932 break;
933 case 1:
934 fep->code_rate_LP = FEC_2_3;
935 break;
936 case 2:
937 fep->code_rate_LP = FEC_3_4;
938 break;
939 case 3:
940 fep->code_rate_LP = FEC_5_6;
941 break;
942 case 4:
943 fep->code_rate_LP = FEC_7_8;
944 break;
945 }
946
947 switch (td->Constellation) {
948 case 0:
949 fep->modulation = QPSK;
950 break;
951 case 1:
952 fep->modulation = QAM_16;
953 break;
954 case 2:
955 fep->modulation = QAM_64;
956 break;
957 }
958
959 switch (td->Hierarchy) {
960 case 0:
961 fep->hierarchy = HIERARCHY_NONE;
962 break;
963 case 1:
964 fep->hierarchy = HIERARCHY_1;
965 break;
966 case 2:
967 fep->hierarchy = HIERARCHY_2;
968 break;
969 case 3:
970 fep->hierarchy = HIERARCHY_4;
971 break;
972 }
973
974 fep->inversion = INVERSION_AUTO;
975
976 return 0;
977}
978
979static int smsdvb_get_frontend_isdb(struct dvb_frontend *fe)
980{
981 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
982 struct smsdvb_client_t *client =
983 container_of(fe, struct smsdvb_client_t, frontend);
984 struct TRANSMISSION_STATISTICS_S *td =
985 &client->sms_stat_dvb.TransmissionData;
986
987 fep->frequency = td->Frequency;
988 fep->bandwidth_hz = 6000000;
989 /* todo: retrive the other parameters */
990
991 return 0;
992}
993
994static int smsdvb_get_frontend(struct dvb_frontend *fe)
995{
996 struct smsdvb_client_t *client =
997 container_of(fe, struct smsdvb_client_t, frontend);
998 struct smscore_device_t *coredev = client->coredev;
999
Gianluca Gennarid1382102012-02-20 07:50:33 -03001000 switch (smscore_get_device_mode(coredev)) {
1001 case DEVICE_MODE_DVBT:
1002 case DEVICE_MODE_DVBT_BDA:
Mauro Carvalho Chehabeab0fa02013-03-09 12:05:58 -03001003 return smsdvb_get_frontend_dvb(fe);
Gianluca Gennarid1382102012-02-20 07:50:33 -03001004 case DEVICE_MODE_ISDBT:
1005 case DEVICE_MODE_ISDBT_BDA:
Mauro Carvalho Chehabeab0fa02013-03-09 12:05:58 -03001006 return smsdvb_get_frontend_isdb(fe);
Gianluca Gennarid1382102012-02-20 07:50:33 -03001007 default:
1008 return -EINVAL;
1009 }
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001010}
1011
1012static int smsdvb_init(struct dvb_frontend *fe)
1013{
1014 struct smsdvb_client_t *client =
1015 container_of(fe, struct smsdvb_client_t, frontend);
1016
Michael Krufky3746b612009-07-12 23:30:14 -03001017 sms_board_power(client->coredev, 1);
1018
Uri Shkolnik793786d2009-05-12 12:28:46 -03001019 sms_board_dvb3_event(client, DVB3_EVENT_INIT);
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001020 return 0;
1021}
1022
1023static int smsdvb_sleep(struct dvb_frontend *fe)
1024{
1025 struct smsdvb_client_t *client =
1026 container_of(fe, struct smsdvb_client_t, frontend);
1027
Michael Krufky3746b612009-07-12 23:30:14 -03001028 sms_board_led_feedback(client->coredev, SMS_LED_OFF);
1029 sms_board_power(client->coredev, 0);
1030
Uri Shkolnik793786d2009-05-12 12:28:46 -03001031 sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001032
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001033 return 0;
1034}
1035
1036static void smsdvb_release(struct dvb_frontend *fe)
1037{
Michael Krufkyfa830e82008-06-15 15:52:43 -03001038 /* do nothing */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001039}
1040
1041static struct dvb_frontend_ops smsdvb_fe_ops = {
1042 .info = {
Uri Shkolnike0f14c22008-08-31 00:44:04 -03001043 .name = "Siano Mobile Digital MDTV Receiver",
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001044 .frequency_min = 44250000,
1045 .frequency_max = 867250000,
1046 .frequency_stepsize = 250000,
1047 .caps = FE_CAN_INVERSION_AUTO |
Michael Krufky82237412008-06-15 15:14:13 -03001048 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,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001055 },
1056
1057 .release = smsdvb_release,
1058
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001059 .set_frontend = smsdvb_set_frontend,
1060 .get_frontend = smsdvb_get_frontend,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001061 .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,
Michael Krufky851a9092008-11-22 14:56:37 -03001067 .read_ucblocks = smsdvb_read_ucblocks,
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001068
1069 .init = smsdvb_init,
1070 .sleep = smsdvb_sleep,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001071};
1072
Michael Krufky0c071f32008-06-21 02:44:02 -03001073static int smsdvb_hotplug(struct smscore_device_t *coredev,
1074 struct device *device, int arrival)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001075{
Michael Krufky18245e12008-06-15 17:52:24 -03001076 struct smsclient_params_t params;
1077 struct smsdvb_client_t *client;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001078 int rc;
1079
Michael Krufkyfa830e82008-06-15 15:52:43 -03001080 /* device removal handled by onremove callback */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001081 if (!arrival)
1082 return 0;
Michael Krufky18245e12008-06-15 17:52:24 -03001083 client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
Michael Krufky82237412008-06-15 15:14:13 -03001084 if (!client) {
Michael Krufkyeb250942008-06-19 22:07:23 -03001085 sms_err("kmalloc() failed");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001086 return -ENOMEM;
1087 }
1088
Michael Krufkyfa830e82008-06-15 15:52:43 -03001089 /* register dvb adapter */
Michael Krufky1c11d542008-06-18 22:09:55 -03001090 rc = dvb_register_adapter(&client->adapter,
1091 sms_get_board(
1092 smscore_get_board_id(coredev))->name,
Michael Krufky82237412008-06-15 15:14:13 -03001093 THIS_MODULE, device, adapter_nr);
1094 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001095 sms_err("dvb_register_adapter() failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001096 goto adapter_error;
1097 }
1098
Michael Krufkyfa830e82008-06-15 15:52:43 -03001099 /* init dvb demux */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001100 client->demux.dmx.capabilities = DMX_TS_FILTERING;
Michael Krufkyfa830e82008-06-15 15:52:43 -03001101 client->demux.filternum = 32; /* todo: nova ??? */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001102 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);
Michael Krufky82237412008-06-15 15:14:13 -03001107 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001108 sms_err("dvb_dmx_init failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001109 goto dvbdmx_error;
1110 }
1111
Michael Krufkyfa830e82008-06-15 15:52:43 -03001112 /* init dmxdev */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001113 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);
Michael Krufky82237412008-06-15 15:14:13 -03001118 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001119 sms_err("dvb_dmxdev_init failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001120 goto dmxdev_error;
1121 }
1122
Michael Krufkyfa830e82008-06-15 15:52:43 -03001123 /* init and register frontend */
Michael Krufky82237412008-06-15 15:14:13 -03001124 memcpy(&client->frontend.ops, &smsdvb_fe_ops,
1125 sizeof(struct dvb_frontend_ops));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001126
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001127 switch (smscore_get_device_mode(coredev)) {
1128 case DEVICE_MODE_DVBT:
1129 case DEVICE_MODE_DVBT_BDA:
Mauro Carvalho Chehab9bd58e72012-03-01 07:25:39 -03001130 client->frontend.ops.delsys[0] = SYS_DVBT;
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001131 break;
1132 case DEVICE_MODE_ISDBT:
1133 case DEVICE_MODE_ISDBT_BDA:
Mauro Carvalho Chehab9bd58e72012-03-01 07:25:39 -03001134 client->frontend.ops.delsys[0] = SYS_ISDBT;
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001135 break;
1136 }
1137
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001138 rc = dvb_register_frontend(&client->adapter, &client->frontend);
Michael Krufky82237412008-06-15 15:14:13 -03001139 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001140 sms_err("frontend registration failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001141 goto frontend_error;
1142 }
1143
Michael Krufkyf17407a2008-06-14 00:43:26 -03001144 params.initial_id = 1;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001145 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);
Michael Krufky82237412008-06-15 15:14:13 -03001151 if (rc < 0) {
Michael Krufkyeb250942008-06-19 22:07:23 -03001152 sms_err("smscore_register_client() failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001153 goto client_error;
1154 }
1155
1156 client->coredev = coredev;
1157
1158 init_completion(&client->tune_done);
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -03001159 init_completion(&client->stats_done);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001160
1161 kmutex_lock(&g_smsdvb_clientslock);
1162
1163 list_add(&client->entry, &g_smsdvb_clients);
1164
1165 kmutex_unlock(&g_smsdvb_clientslock);
1166
Uri Shkolnik793786d2009-05-12 12:28:46 -03001167 client->event_fe_state = -1;
1168 client->event_unc_state = -1;
1169 sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001170
Uri Shkolnik793786d2009-05-12 12:28:46 -03001171 sms_info("success");
Michael Krufky250fa672008-11-16 22:45:42 -03001172 sms_board_setup(coredev);
1173
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001174 return 0;
1175
1176client_error:
1177 dvb_unregister_frontend(&client->frontend);
1178
1179frontend_error:
1180 dvb_dmxdev_release(&client->dmxdev);
1181
1182dmxdev_error:
1183 dvb_dmx_release(&client->demux);
1184
1185dvbdmx_error:
1186 dvb_unregister_adapter(&client->adapter);
1187
1188adapter_error:
1189 kfree(client);
1190 return rc;
1191}
1192
Márton Németh2184dda2009-12-11 20:05:10 -03001193static int __init smsdvb_module_init(void)
Steven Totheae55662008-05-22 18:04:36 -03001194{
1195 int rc;
1196
1197 INIT_LIST_HEAD(&g_smsdvb_clients);
1198 kmutex_init(&g_smsdvb_clientslock);
1199
1200 rc = smscore_register_hotplug(smsdvb_hotplug);
1201
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001202 sms_debug("");
Steven Totheae55662008-05-22 18:04:36 -03001203
1204 return rc;
1205}
1206
Márton Németh2184dda2009-12-11 20:05:10 -03001207static void __exit smsdvb_module_exit(void)
Steven Totheae55662008-05-22 18:04:36 -03001208{
1209 smscore_unregister_hotplug(smsdvb_hotplug);
1210
1211 kmutex_lock(&g_smsdvb_clientslock);
1212
1213 while (!list_empty(&g_smsdvb_clients))
Michael Krufky82237412008-06-15 15:14:13 -03001214 smsdvb_unregister_client(
Michael Krufky18245e12008-06-15 17:52:24 -03001215 (struct smsdvb_client_t *) g_smsdvb_clients.next);
Steven Totheae55662008-05-22 18:04:36 -03001216
1217 kmutex_unlock(&g_smsdvb_clientslock);
Steven Totheae55662008-05-22 18:04:36 -03001218}
Uri Shkolnike0f14c22008-08-31 00:44:04 -03001219
1220module_init(smsdvb_module_init);
1221module_exit(smsdvb_module_exit);
1222
1223MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
Uri Shkolnik843d0602009-05-12 13:13:13 -03001224MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
Uri Shkolnike0f14c22008-08-31 00:44:04 -03001225MODULE_LICENSE("GPL");