blob: dbb807e3a212d8add80f284f80095488204093f1 [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"
Uri Shkolnikba79bb22009-05-12 11:37:09 -030032#include "smsendian.h"
Michael Krufky1c11d542008-06-18 22:09:55 -030033#include "sms-cards.h"
Michael Krufky2e5c1ec82008-05-19 18:56:13 -030034
Michael Krufky9c59f9682008-05-19 18:57:12 -030035DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
36
Michael Krufky62c71672008-08-31 17:15:47 -030037struct smsdvb_client_t {
38 struct list_head entry;
39
40 struct smscore_device_t *coredev;
41 struct smscore_client_t *smsclient;
42
43 struct dvb_adapter adapter;
44 struct dvb_demux demux;
45 struct dmxdev dmxdev;
46 struct dvb_frontend frontend;
47
48 fe_status_t fe_status;
Michael Krufky62c71672008-08-31 17:15:47 -030049
Uri Shkolnik793786d2009-05-12 12:28:46 -030050 struct completion tune_done;
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -030051 struct completion stats_done;
Michael Krufky62c71672008-08-31 17:15:47 -030052
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -030053 struct SMSHOSTLIB_STATISTICS_DVB_EX_S sms_stat_dvb;
Uri Shkolnik793786d2009-05-12 12:28:46 -030054 int event_fe_state;
55 int event_unc_state;
Michael Krufky62c71672008-08-31 17:15:47 -030056};
57
Adrian Bunkc5e0bd12008-07-21 23:17:36 -030058static struct list_head g_smsdvb_clients;
59static struct mutex g_smsdvb_clientslock;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -030060
Michael Krufky0d02efe2009-02-27 02:42:16 -030061static int sms_dbg;
62module_param_named(debug, sms_dbg, int, 0644);
63MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
64
Uri Shkolnik793786d2009-05-12 12:28:46 -030065/* Events that may come from DVB v3 adapter */
66static void sms_board_dvb3_event(struct smsdvb_client_t *client,
67 enum SMS_DVB3_EVENTS event) {
Uri Shkolnik4db989f2009-05-19 12:28:02 -030068
69 struct smscore_device_t *coredev = client->coredev;
70 switch (event) {
71 case DVB3_EVENT_INIT:
72 sms_debug("DVB3_EVENT_INIT");
73 sms_board_event(coredev, BOARD_EVENT_BIND);
74 break;
75 case DVB3_EVENT_SLEEP:
76 sms_debug("DVB3_EVENT_SLEEP");
77 sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
78 break;
79 case DVB3_EVENT_HOTPLUG:
80 sms_debug("DVB3_EVENT_HOTPLUG");
81 sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
82 break;
83 case DVB3_EVENT_FE_LOCK:
84 if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
85 client->event_fe_state = DVB3_EVENT_FE_LOCK;
86 sms_debug("DVB3_EVENT_FE_LOCK");
87 sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
88 }
89 break;
90 case DVB3_EVENT_FE_UNLOCK:
91 if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
92 client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
93 sms_debug("DVB3_EVENT_FE_UNLOCK");
94 sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
95 }
96 break;
97 case DVB3_EVENT_UNC_OK:
98 if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
99 client->event_unc_state = DVB3_EVENT_UNC_OK;
100 sms_debug("DVB3_EVENT_UNC_OK");
101 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
102 }
103 break;
104 case DVB3_EVENT_UNC_ERR:
105 if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
106 client->event_unc_state = DVB3_EVENT_UNC_ERR;
107 sms_debug("DVB3_EVENT_UNC_ERR");
108 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
109 }
110 break;
111
112 default:
113 sms_err("Unknown dvb3 api event");
114 break;
115 }
Uri Shkolnik793786d2009-05-12 12:28:46 -0300116}
117
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300118static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300119 struct SMSHOSTLIB_STATISTICS_ST *p)
120{
121 if (sms_dbg & 2) {
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300122 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
123 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
124 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
125 printk(KERN_DEBUG "SNR = %d", p->SNR);
126 printk(KERN_DEBUG "BER = %d", p->BER);
127 printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
128 printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
129 printk(KERN_DEBUG "MFER = %d", p->MFER);
130 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
131 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
132 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300133 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300134 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
135 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
136 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
137 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
138 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
139 printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
140 printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
141 printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
142 printk(KERN_DEBUG "Constellation = %d", p->Constellation);
143 printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
144 printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
145 printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
146 printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
147 printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
148 printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
149 printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
150 printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
151 printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
152 printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
153 printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
154 printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
155 printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
156 printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
157 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
158 printk(KERN_DEBUG "PreBER = %d", p->PreBER);
159 printk(KERN_DEBUG "CellId = %d", p->CellId);
160 printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
161 printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
162 printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300163 }
164
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300165 /* update reception data */
166 pReceptionData->IsRfLocked = p->IsRfLocked;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300167 pReceptionData->IsDemodLocked = p->IsDemodLocked;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300168 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
169 pReceptionData->ModemState = p->ModemState;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300170 pReceptionData->SNR = p->SNR;
171 pReceptionData->BER = p->BER;
172 pReceptionData->BERErrorCount = p->BERErrorCount;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300173 pReceptionData->BERBitCount = p->BERBitCount;
174 pReceptionData->RSSI = p->RSSI;
175 CORRECT_STAT_RSSI(*pReceptionData);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300176 pReceptionData->InBandPwr = p->InBandPwr;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300177 pReceptionData->CarrierOffset = p->CarrierOffset;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300178 pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300179 pReceptionData->TotalTSPackets = p->TotalTSPackets;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300180};
181
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300182static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300183 struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
184{
185 int i;
186
187 if (sms_dbg & 2) {
188 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
189 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
190 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
191 printk(KERN_DEBUG "SNR = %d", p->SNR);
192 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
193 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
194 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
195 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
196 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
197 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
198 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
199 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
200 printk(KERN_DEBUG "SystemType = %d", p->SystemType);
201 printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
202 printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
203 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
204
205 for (i = 0; i < 3; i++) {
206 printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
207 printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
208 printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
209 printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
210 printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
211 printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
212 printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
213 printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
214 printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
215 printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
216 printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
217 printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
218 }
219 }
220
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300221 /* update reception data */
222 pReceptionData->IsRfLocked = p->IsRfLocked;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300223 pReceptionData->IsDemodLocked = p->IsDemodLocked;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300224 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
225 pReceptionData->ModemState = p->ModemState;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300226 pReceptionData->SNR = p->SNR;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300227 pReceptionData->BER = p->LayerInfo[0].BER;
228 pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
229 pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
230 pReceptionData->RSSI = p->RSSI;
231 CORRECT_STAT_RSSI(*pReceptionData);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300232 pReceptionData->InBandPwr = p->InBandPwr;
233
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300234 pReceptionData->CarrierOffset = p->CarrierOffset;
235 pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
236 pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
237 pReceptionData->MFER = 0;
238
239 /* TS PER */
240 if ((p->LayerInfo[0].TotalTSPackets +
241 p->LayerInfo[0].ErrorTSPackets) > 0) {
242 pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets
243 * 100) / (p->LayerInfo[0].TotalTSPackets
244 + p->LayerInfo[0].ErrorTSPackets);
245 } else {
246 pReceptionData->TS_PER = 0;
247 }
248}
249
250static void smsdvb_update_isdbt_stats_ex(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
251 struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST *p)
252{
253 int i;
254
255 if (sms_dbg & 2) {
256 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
257 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
258 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
259 printk(KERN_DEBUG "SNR = %d", p->SNR);
260 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
261 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
262 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
263 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
264 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
265 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
266 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
267 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
268 printk(KERN_DEBUG "SystemType = %d", p->SystemType);
269 printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
270 printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
271 printk(KERN_DEBUG "SegmentNumber = %d", p->SegmentNumber);
272 printk(KERN_DEBUG "TuneBW = %d", p->TuneBW);
273 for (i = 0; i < 3; i++) {
274 printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
275 printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
276 printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
277 printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
278 printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
279 printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
280 printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
281 printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
282 printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
283 printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
284 printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
285 printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
286 }
287 }
288
289 /* update reception data */
290 pReceptionData->IsRfLocked = p->IsRfLocked;
291 pReceptionData->IsDemodLocked = p->IsDemodLocked;
292 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
293 pReceptionData->ModemState = p->ModemState;
294 pReceptionData->SNR = p->SNR;
295 pReceptionData->BER = p->LayerInfo[0].BER;
296 pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
297 pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
298 pReceptionData->RSSI = p->RSSI;
299 CORRECT_STAT_RSSI(*pReceptionData);
300 pReceptionData->InBandPwr = p->InBandPwr;
301
302 pReceptionData->CarrierOffset = p->CarrierOffset;
303 pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
304 pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
305 pReceptionData->MFER = 0;
306
307 /* TS PER */
308 if ((p->LayerInfo[0].TotalTSPackets +
309 p->LayerInfo[0].ErrorTSPackets) > 0) {
310 pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets
311 * 100) / (p->LayerInfo[0].TotalTSPackets
312 + p->LayerInfo[0].ErrorTSPackets);
313 } else {
314 pReceptionData->TS_PER = 0;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300315 }
316}
317
Michael Krufky0c071f32008-06-21 02:44:02 -0300318static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300319{
Michael Krufky18245e12008-06-15 17:52:24 -0300320 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300321 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
322 + cb->offset);
323 u32 *pMsgData = (u32 *) phdr + 1;
324 /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
325 bool is_status_update = false;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300326
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300327 smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr);
328
Michael Krufkyfa830e82008-06-15 15:52:43 -0300329 switch (phdr->msgType) {
Michael Krufky82237412008-06-15 15:14:13 -0300330 case MSG_SMS_DVBT_BDA_DATA:
331 dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
Michael Krufky18245e12008-06-15 17:52:24 -0300332 cb->size - sizeof(struct SmsMsgHdr_ST));
Michael Krufky82237412008-06-15 15:14:13 -0300333 break;
334
335 case MSG_SMS_RF_TUNE_RES:
Michael Krufky6b26fce2009-12-22 21:08:49 -0300336 case MSG_SMS_ISDBT_TUNE_RES:
Michael Krufky82237412008-06-15 15:14:13 -0300337 complete(&client->tune_done);
338 break;
339
Uri Shkolnik793786d2009-05-12 12:28:46 -0300340 case MSG_SMS_SIGNAL_DETECTED_IND:
Uri Shkolnik793786d2009-05-12 12:28:46 -0300341 client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
342 is_status_update = true;
343 break;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300344
Uri Shkolnik793786d2009-05-12 12:28:46 -0300345 case MSG_SMS_NO_SIGNAL_IND:
Uri Shkolnik793786d2009-05-12 12:28:46 -0300346 client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
347 is_status_update = true;
348 break;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300349
Uri Shkolnik793786d2009-05-12 12:28:46 -0300350 case MSG_SMS_TRANSMISSION_IND: {
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300351
Uri Shkolnik793786d2009-05-12 12:28:46 -0300352 pMsgData++;
353 memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
354 sizeof(struct TRANSMISSION_STATISTICS_S));
355
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300356#if 1
357 /*
358 * FIXME: newer driver doesn't have those fixes
359 * Are those firmware-specific stuff?
360 */
361
Uri Shkolnik793786d2009-05-12 12:28:46 -0300362 /* Mo need to correct guard interval
363 * (as opposed to old statistics message).
364 */
365 CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
366 CORRECT_STAT_TRANSMISSON_MODE(
367 client->sms_stat_dvb.TransmissionData);
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300368#endif
Uri Shkolnik793786d2009-05-12 12:28:46 -0300369 is_status_update = true;
370 break;
371 }
372 case MSG_SMS_HO_PER_SLICES_IND: {
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300373 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
Uri Shkolnik793786d2009-05-12 12:28:46 -0300374 &client->sms_stat_dvb.ReceptionData;
375 struct SRVM_SIGNAL_STATUS_S SignalStatusData;
376
Uri Shkolnik793786d2009-05-12 12:28:46 -0300377 pMsgData++;
378 SignalStatusData.result = pMsgData[0];
379 SignalStatusData.snr = pMsgData[1];
380 SignalStatusData.inBandPower = (s32) pMsgData[2];
381 SignalStatusData.tsPackets = pMsgData[3];
382 SignalStatusData.etsPackets = pMsgData[4];
383 SignalStatusData.constellation = pMsgData[5];
384 SignalStatusData.hpCode = pMsgData[6];
385 SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
386 SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
387 SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
388 SignalStatusData.reason = pMsgData[10];
389 SignalStatusData.requestId = pMsgData[11];
390 pReceptionData->IsRfLocked = pMsgData[16];
391 pReceptionData->IsDemodLocked = pMsgData[17];
392 pReceptionData->ModemState = pMsgData[12];
393 pReceptionData->SNR = pMsgData[1];
394 pReceptionData->BER = pMsgData[13];
395 pReceptionData->RSSI = pMsgData[14];
396 CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
397
398 pReceptionData->InBandPwr = (s32) pMsgData[2];
399 pReceptionData->CarrierOffset = (s32) pMsgData[15];
400 pReceptionData->TotalTSPackets = pMsgData[3];
401 pReceptionData->ErrorTSPackets = pMsgData[4];
402
403 /* TS PER */
404 if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
405 > 0) {
406 pReceptionData->TS_PER = (SignalStatusData.etsPackets
407 * 100) / (SignalStatusData.tsPackets
408 + SignalStatusData.etsPackets);
Michael Krufky82237412008-06-15 15:14:13 -0300409 } else {
Uri Shkolnik793786d2009-05-12 12:28:46 -0300410 pReceptionData->TS_PER = 0;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300411 }
Michael Krufky82237412008-06-15 15:14:13 -0300412
Uri Shkolnik793786d2009-05-12 12:28:46 -0300413 pReceptionData->BERBitCount = pMsgData[18];
414 pReceptionData->BERErrorCount = pMsgData[19];
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300415
Uri Shkolnik793786d2009-05-12 12:28:46 -0300416 pReceptionData->MRC_SNR = pMsgData[20];
417 pReceptionData->MRC_InBandPwr = pMsgData[21];
418 pReceptionData->MRC_RSSI = pMsgData[22];
419
420 is_status_update = true;
421 break;
422 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300423 case MSG_SMS_GET_STATISTICS_RES: {
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300424 union {
425 struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
426 struct SmsMsgStatisticsInfo_ST dvb;
427 } *p = (void *) (phdr + 1);
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300428 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300429 &client->sms_stat_dvb.ReceptionData;
430
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300431 is_status_update = true;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300432
433 switch (smscore_get_device_mode(client->coredev)) {
434 case DEVICE_MODE_ISDBT:
435 case DEVICE_MODE_ISDBT_BDA:
436 smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
437 break;
438 default:
439 smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
440 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300441 if (!pReceptionData->IsDemodLocked) {
442 pReceptionData->SNR = 0;
443 pReceptionData->BER = 0;
444 pReceptionData->BERErrorCount = 0;
445 pReceptionData->InBandPwr = 0;
446 pReceptionData->ErrorTSPackets = 0;
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300447 }
448
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300449 break;
450 }
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300451 case MSG_SMS_GET_STATISTICS_EX_RES: {
452 union {
453 struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST isdbt;
454 struct SMSHOSTLIB_STATISTICS_ST dvb;
455 } *p = (void *) (phdr + 1);
456 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
457 &client->sms_stat_dvb.ReceptionData;
458
459 is_status_update = true;
460
461 switch (smscore_get_device_mode(client->coredev)) {
462 case DEVICE_MODE_ISDBT:
463 case DEVICE_MODE_ISDBT_BDA:
464 smsdvb_update_isdbt_stats_ex(pReceptionData, &p->isdbt);
465 break;
466 default:
467 smsdvb_update_dvb_stats(pReceptionData, &p->dvb);
468 }
469 if (!pReceptionData->IsDemodLocked) {
470 pReceptionData->SNR = 0;
471 pReceptionData->BER = 0;
472 pReceptionData->BERErrorCount = 0;
473 pReceptionData->InBandPwr = 0;
474 pReceptionData->ErrorTSPackets = 0;
475 }
476
477 break;
478 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300479 default:
Mauro Carvalho Chehab4c3bdb52013-03-09 09:27:39 -0300480 sms_info("message not handled");
Uri Shkolnik793786d2009-05-12 12:28:46 -0300481 }
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300482 smscore_putbuffer(client->coredev, cb);
483
Uri Shkolnik793786d2009-05-12 12:28:46 -0300484 if (is_status_update) {
485 if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
486 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
487 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
488 sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
489 if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
490 == 0)
491 sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
492 else
493 sms_board_dvb3_event(client,
494 DVB3_EVENT_UNC_ERR);
495
496 } else {
Mauro Carvalho Chehabb4622c12009-12-25 18:04:17 -0300497 if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
498 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
499 else
500 client->fe_status = 0;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300501 sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
502 }
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -0300503 complete(&client->stats_done);
Uri Shkolnik793786d2009-05-12 12:28:46 -0300504 }
505
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300506 return 0;
507}
508
Michael Krufky0c071f32008-06-21 02:44:02 -0300509static void smsdvb_unregister_client(struct smsdvb_client_t *client)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300510{
Michael Krufkyfa830e82008-06-15 15:52:43 -0300511 /* must be called under clientslock */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300512
513 list_del(&client->entry);
514
515 smscore_unregister_client(client->smsclient);
516 dvb_unregister_frontend(&client->frontend);
517 dvb_dmxdev_release(&client->dmxdev);
518 dvb_dmx_release(&client->demux);
519 dvb_unregister_adapter(&client->adapter);
520 kfree(client);
521}
522
Michael Krufky0c071f32008-06-21 02:44:02 -0300523static void smsdvb_onremove(void *context)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300524{
525 kmutex_lock(&g_smsdvb_clientslock);
526
Michael Krufky18245e12008-06-15 17:52:24 -0300527 smsdvb_unregister_client((struct smsdvb_client_t *) context);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300528
529 kmutex_unlock(&g_smsdvb_clientslock);
530}
531
532static int smsdvb_start_feed(struct dvb_demux_feed *feed)
533{
Michael Krufky18245e12008-06-15 17:52:24 -0300534 struct smsdvb_client_t *client =
535 container_of(feed->demux, struct smsdvb_client_t, demux);
536 struct SmsMsgData_ST PidMsg;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300537
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300538 sms_debug("add pid %d(%x)",
Michael Krufky068d6c02008-06-19 01:15:46 -0300539 feed->pid, feed->pid);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300540
541 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
542 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
543 PidMsg.xMsgHeader.msgFlags = 0;
544 PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ;
545 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
546 PidMsg.msgData[0] = feed->pid;
547
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300548 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
Michael Krufky82237412008-06-15 15:14:13 -0300549 return smsclient_sendrequest(client->smsclient,
550 &PidMsg, sizeof(PidMsg));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300551}
552
553static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
554{
Michael Krufky18245e12008-06-15 17:52:24 -0300555 struct smsdvb_client_t *client =
556 container_of(feed->demux, struct smsdvb_client_t, demux);
557 struct SmsMsgData_ST PidMsg;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300558
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300559 sms_debug("remove pid %d(%x)",
Michael Krufky068d6c02008-06-19 01:15:46 -0300560 feed->pid, feed->pid);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300561
562 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
563 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
564 PidMsg.xMsgHeader.msgFlags = 0;
565 PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ;
566 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
567 PidMsg.msgData[0] = feed->pid;
568
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300569 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
Michael Krufky82237412008-06-15 15:14:13 -0300570 return smsclient_sendrequest(client->smsclient,
571 &PidMsg, sizeof(PidMsg));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300572}
573
Michael Krufky18245e12008-06-15 17:52:24 -0300574static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
Michael Krufkya83ccdd2008-05-06 03:11:51 -0300575 void *buffer, size_t size,
576 struct completion *completion)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300577{
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300578 int rc;
579
580 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer);
581 rc = smsclient_sendrequest(client->smsclient, buffer, size);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300582 if (rc < 0)
583 return rc;
584
Michael Krufky82237412008-06-15 15:14:13 -0300585 return wait_for_completion_timeout(completion,
586 msecs_to_jiffies(2000)) ?
587 0 : -ETIME;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300588}
589
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300590static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
591{
592 int rc;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300593 struct SmsMsgHdr_ST Msg;
594
595
596 Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
597 Msg.msgDstId = HIF_TASK;
598 Msg.msgFlags = 0;
599 Msg.msgLength = sizeof(Msg);
600
601 /*
602 * Check for firmware version, to avoid breaking for old cards
603 */
604 if (client->coredev->fw_version >= 0x800)
605 Msg.msgType = MSG_SMS_GET_STATISTICS_EX_REQ;
606 else
607 Msg.msgType = MSG_SMS_GET_STATISTICS_REQ;
608
609 smsendian_handle_tx_message((struct SmsMsgHdr_S *)&Msg);
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300610
611 rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -0300612 &client->stats_done);
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300613
614 return rc;
615}
616
Michael Krufky3746b612009-07-12 23:30:14 -0300617static inline int led_feedback(struct smsdvb_client_t *client)
618{
619 if (client->fe_status & FE_HAS_LOCK)
620 return sms_board_led_feedback(client->coredev,
621 (client->sms_stat_dvb.ReceptionData.BER
622 == 0) ? SMS_LED_HI : SMS_LED_LO);
623 else
624 return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
625}
626
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300627static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
628{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300629 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300630 struct smsdvb_client_t *client;
631 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300632
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300633 rc = smsdvb_send_statistics_request(client);
634
Uri Shkolnik793786d2009-05-12 12:28:46 -0300635 *stat = client->fe_status;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300636
Michael Krufky3746b612009-07-12 23:30:14 -0300637 led_feedback(client);
638
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300639 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300640}
641
642static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
643{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300644 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300645 struct smsdvb_client_t *client;
646 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300647
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300648 rc = smsdvb_send_statistics_request(client);
649
Uri Shkolnik793786d2009-05-12 12:28:46 -0300650 *ber = client->sms_stat_dvb.ReceptionData.BER;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300651
Michael Krufky3746b612009-07-12 23:30:14 -0300652 led_feedback(client);
653
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300654 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300655}
656
657static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
658{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300659 int rc;
660
Uri Shkolnik793786d2009-05-12 12:28:46 -0300661 struct smsdvb_client_t *client;
662 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300663
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300664 rc = smsdvb_send_statistics_request(client);
665
Uri Shkolnik793786d2009-05-12 12:28:46 -0300666 if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
667 *strength = 0;
668 else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
669 *strength = 100;
670 else
671 *strength =
672 (client->sms_stat_dvb.ReceptionData.InBandPwr
673 + 95) * 3 / 2;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300674
Michael Krufky3746b612009-07-12 23:30:14 -0300675 led_feedback(client);
676
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300677 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300678}
679
680static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
681{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300682 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300683 struct smsdvb_client_t *client;
684 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300685
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300686 rc = smsdvb_send_statistics_request(client);
687
Uri Shkolnik793786d2009-05-12 12:28:46 -0300688 *snr = client->sms_stat_dvb.ReceptionData.SNR;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300689
Michael Krufky3746b612009-07-12 23:30:14 -0300690 led_feedback(client);
691
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300692 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300693}
694
Michael Krufky851a9092008-11-22 14:56:37 -0300695static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
696{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300697 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300698 struct smsdvb_client_t *client;
699 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky851a9092008-11-22 14:56:37 -0300700
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300701 rc = smsdvb_send_statistics_request(client);
702
Uri Shkolnik793786d2009-05-12 12:28:46 -0300703 *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
Michael Krufky851a9092008-11-22 14:56:37 -0300704
Michael Krufky3746b612009-07-12 23:30:14 -0300705 led_feedback(client);
706
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300707 return rc;
Michael Krufky851a9092008-11-22 14:56:37 -0300708}
709
Michael Krufky82237412008-06-15 15:14:13 -0300710static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
711 struct dvb_frontend_tune_settings *tune)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300712{
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300713 sms_debug("");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300714
715 tune->min_delay_ms = 400;
716 tune->step_size = 250000;
717 tune->max_drift = 0;
718 return 0;
719}
720
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300721static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300722{
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300723 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Michael Krufky18245e12008-06-15 17:52:24 -0300724 struct smsdvb_client_t *client =
725 container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300726
Michael Krufky18245e12008-06-15 17:52:24 -0300727 struct {
728 struct SmsMsgHdr_ST Msg;
Michael Krufky82237412008-06-15 15:14:13 -0300729 u32 Data[3];
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300730 } Msg;
731
Michael Krufky3746b612009-07-12 23:30:14 -0300732 int ret;
733
Uri Shkolnik793786d2009-05-12 12:28:46 -0300734 client->fe_status = FE_HAS_SIGNAL;
735 client->event_fe_state = -1;
736 client->event_unc_state = -1;
Mauro Carvalho Chehabe85c97a2009-12-25 07:17:03 -0300737 fe->dtv_property_cache.delivery_system = SYS_DVBT;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300738
739 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
740 Msg.Msg.msgDstId = HIF_TASK;
741 Msg.Msg.msgFlags = 0;
742 Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300743 Msg.Msg.msgLength = sizeof(Msg);
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300744 Msg.Data[0] = c->frequency;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300745 Msg.Data[2] = 12000000;
746
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300747 sms_info("%s: freq %d band %d", __func__, c->frequency,
748 c->bandwidth_hz);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300749
Mauro Carvalho Chehab643e15a2009-12-25 07:29:06 -0300750 switch (c->bandwidth_hz / 1000000) {
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300751 case 8:
752 Msg.Data[1] = BW_8_MHZ;
753 break;
754 case 7:
755 Msg.Data[1] = BW_7_MHZ;
756 break;
757 case 6:
758 Msg.Data[1] = BW_6_MHZ;
759 break;
760 case 0:
761 return -EOPNOTSUPP;
762 default:
763 return -EINVAL;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300764 }
Michael Krufky3746b612009-07-12 23:30:14 -0300765 /* Disable LNA, if any. An error is returned if no LNA is present */
766 ret = sms_board_lna_control(client->coredev, 0);
767 if (ret == 0) {
768 fe_status_t status;
769
770 /* tune with LNA off at first */
771 ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
772 &client->tune_done);
773
774 smsdvb_read_status(fe, &status);
775
776 if (status & FE_HAS_LOCK)
777 return ret;
778
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300779 /* previous tune didn't lock - enable LNA and tune again */
Michael Krufky3746b612009-07-12 23:30:14 -0300780 sms_board_lna_control(client->coredev, 1);
781 }
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300782
Michael Krufky82237412008-06-15 15:14:13 -0300783 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
784 &client->tune_done);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300785}
786
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300787static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
Michael Krufky6b26fce2009-12-22 21:08:49 -0300788{
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300789 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300790 struct smsdvb_client_t *client =
791 container_of(fe, struct smsdvb_client_t, frontend);
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300792 int board_id = smscore_get_board_id(client->coredev);
793 struct sms_board *board = sms_get_board(board_id);
794 enum sms_device_type_st type = board->type;
Mauro Carvalho Chehab0c189fa2013-03-07 16:34:53 -0300795 int ret;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300796 struct {
797 struct SmsMsgHdr_ST Msg;
798 u32 Data[4];
799 } Msg;
800
Mauro Carvalho Chehabe85c97a2009-12-25 07:17:03 -0300801 fe->dtv_property_cache.delivery_system = SYS_ISDBT;
802
Michael Krufky6b26fce2009-12-22 21:08:49 -0300803 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
804 Msg.Msg.msgDstId = HIF_TASK;
805 Msg.Msg.msgFlags = 0;
806 Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ;
807 Msg.Msg.msgLength = sizeof(Msg);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300808
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300809 if (c->isdbt_sb_segment_idx == -1)
810 c->isdbt_sb_segment_idx = 0;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300811
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300812 if (!c->isdbt_layer_enabled)
813 c->isdbt_layer_enabled = 7;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300814
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300815 Msg.Data[0] = c->frequency;
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300816 Msg.Data[1] = BW_ISDBT_1SEG;
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300817 Msg.Data[2] = 12000000;
818 Msg.Data[3] = c->isdbt_sb_segment_idx;
819
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300820 if (c->isdbt_partial_reception) {
821 if ((type == SMS_PELE || type == SMS_RIO) &&
822 c->isdbt_sb_segment_count > 3)
823 Msg.Data[1] = BW_ISDBT_13SEG;
824 else if (c->isdbt_sb_segment_count > 1)
825 Msg.Data[1] = BW_ISDBT_3SEG;
826 } else if (type == SMS_PELE || type == SMS_RIO)
827 Msg.Data[1] = BW_ISDBT_13SEG;
828
829 c->bandwidth_hz = 6000000;
830
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300831 sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
832 c->frequency, c->isdbt_sb_segment_count,
833 c->isdbt_sb_segment_idx);
834
Mauro Carvalho Chehab0c189fa2013-03-07 16:34:53 -0300835 /* Disable LNA, if any. An error is returned if no LNA is present */
836 ret = sms_board_lna_control(client->coredev, 0);
837 if (ret == 0) {
838 fe_status_t status;
839
840 /* tune with LNA off at first */
841 ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
842 &client->tune_done);
843
844 smsdvb_read_status(fe, &status);
845
846 if (status & FE_HAS_LOCK)
847 return ret;
848
849 /* previous tune didn't lock - enable LNA and tune again */
850 sms_board_lna_control(client->coredev, 1);
851 }
Michael Krufky6b26fce2009-12-22 21:08:49 -0300852 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
853 &client->tune_done);
854}
855
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300856static int smsdvb_set_frontend(struct dvb_frontend *fe)
Michael Krufky6b26fce2009-12-22 21:08:49 -0300857{
858 struct smsdvb_client_t *client =
859 container_of(fe, struct smsdvb_client_t, frontend);
860 struct smscore_device_t *coredev = client->coredev;
861
862 switch (smscore_get_device_mode(coredev)) {
863 case DEVICE_MODE_DVBT:
864 case DEVICE_MODE_DVBT_BDA:
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300865 return smsdvb_dvbt_set_frontend(fe);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300866 case DEVICE_MODE_ISDBT:
867 case DEVICE_MODE_ISDBT_BDA:
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300868 return smsdvb_isdbt_set_frontend(fe);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300869 default:
870 return -EINVAL;
871 }
872}
873
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -0300874static int smsdvb_get_frontend(struct dvb_frontend *fe)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300875{
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -0300876 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
Michael Krufky18245e12008-06-15 17:52:24 -0300877 struct smsdvb_client_t *client =
878 container_of(fe, struct smsdvb_client_t, frontend);
Gianluca Gennarid1382102012-02-20 07:50:33 -0300879 struct smscore_device_t *coredev = client->coredev;
880 struct TRANSMISSION_STATISTICS_S *td =
881 &client->sms_stat_dvb.TransmissionData;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300882
Gianluca Gennarid1382102012-02-20 07:50:33 -0300883 switch (smscore_get_device_mode(coredev)) {
884 case DEVICE_MODE_DVBT:
885 case DEVICE_MODE_DVBT_BDA:
886 fep->frequency = td->Frequency;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300887
Gianluca Gennarid1382102012-02-20 07:50:33 -0300888 switch (td->Bandwidth) {
889 case 6:
890 fep->bandwidth_hz = 6000000;
891 break;
892 case 7:
893 fep->bandwidth_hz = 7000000;
894 break;
895 case 8:
896 fep->bandwidth_hz = 8000000;
897 break;
898 }
899
900 switch (td->TransmissionMode) {
901 case 2:
902 fep->transmission_mode = TRANSMISSION_MODE_2K;
903 break;
904 case 8:
905 fep->transmission_mode = TRANSMISSION_MODE_8K;
906 }
907
908 switch (td->GuardInterval) {
909 case 0:
910 fep->guard_interval = GUARD_INTERVAL_1_32;
911 break;
912 case 1:
913 fep->guard_interval = GUARD_INTERVAL_1_16;
914 break;
915 case 2:
916 fep->guard_interval = GUARD_INTERVAL_1_8;
917 break;
918 case 3:
919 fep->guard_interval = GUARD_INTERVAL_1_4;
920 break;
921 }
922
923 switch (td->CodeRate) {
924 case 0:
925 fep->code_rate_HP = FEC_1_2;
926 break;
927 case 1:
928 fep->code_rate_HP = FEC_2_3;
929 break;
930 case 2:
931 fep->code_rate_HP = FEC_3_4;
932 break;
933 case 3:
934 fep->code_rate_HP = FEC_5_6;
935 break;
936 case 4:
937 fep->code_rate_HP = FEC_7_8;
938 break;
939 }
940
941 switch (td->LPCodeRate) {
942 case 0:
943 fep->code_rate_LP = FEC_1_2;
944 break;
945 case 1:
946 fep->code_rate_LP = FEC_2_3;
947 break;
948 case 2:
949 fep->code_rate_LP = FEC_3_4;
950 break;
951 case 3:
952 fep->code_rate_LP = FEC_5_6;
953 break;
954 case 4:
955 fep->code_rate_LP = FEC_7_8;
956 break;
957 }
958
959 switch (td->Constellation) {
960 case 0:
961 fep->modulation = QPSK;
962 break;
963 case 1:
964 fep->modulation = QAM_16;
965 break;
966 case 2:
967 fep->modulation = QAM_64;
968 break;
969 }
970
971 switch (td->Hierarchy) {
972 case 0:
973 fep->hierarchy = HIERARCHY_NONE;
974 break;
975 case 1:
976 fep->hierarchy = HIERARCHY_1;
977 break;
978 case 2:
979 fep->hierarchy = HIERARCHY_2;
980 break;
981 case 3:
982 fep->hierarchy = HIERARCHY_4;
983 break;
984 }
985
986 fep->inversion = INVERSION_AUTO;
987 break;
988 case DEVICE_MODE_ISDBT:
989 case DEVICE_MODE_ISDBT_BDA:
990 fep->frequency = td->Frequency;
991 fep->bandwidth_hz = 6000000;
992 /* todo: retrive the other parameters */
993 break;
994 default:
995 return -EINVAL;
996 }
Michael Krufky7a6fbed2008-11-22 14:26:37 -0300997
998 return 0;
999}
1000
1001static int smsdvb_init(struct dvb_frontend *fe)
1002{
1003 struct smsdvb_client_t *client =
1004 container_of(fe, struct smsdvb_client_t, frontend);
1005
Michael Krufky3746b612009-07-12 23:30:14 -03001006 sms_board_power(client->coredev, 1);
1007
Uri Shkolnik793786d2009-05-12 12:28:46 -03001008 sms_board_dvb3_event(client, DVB3_EVENT_INIT);
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001009 return 0;
1010}
1011
1012static int smsdvb_sleep(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_led_feedback(client->coredev, SMS_LED_OFF);
1018 sms_board_power(client->coredev, 0);
1019
Uri Shkolnik793786d2009-05-12 12:28:46 -03001020 sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001021
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001022 return 0;
1023}
1024
1025static void smsdvb_release(struct dvb_frontend *fe)
1026{
Michael Krufkyfa830e82008-06-15 15:52:43 -03001027 /* do nothing */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001028}
1029
1030static struct dvb_frontend_ops smsdvb_fe_ops = {
1031 .info = {
Uri Shkolnike0f14c22008-08-31 00:44:04 -03001032 .name = "Siano Mobile Digital MDTV Receiver",
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001033 .frequency_min = 44250000,
1034 .frequency_max = 867250000,
1035 .frequency_stepsize = 250000,
1036 .caps = FE_CAN_INVERSION_AUTO |
Michael Krufky82237412008-06-15 15:14:13 -03001037 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1038 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1039 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
1040 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
1041 FE_CAN_GUARD_INTERVAL_AUTO |
1042 FE_CAN_RECOVER |
1043 FE_CAN_HIERARCHY_AUTO,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001044 },
1045
1046 .release = smsdvb_release,
1047
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001048 .set_frontend = smsdvb_set_frontend,
1049 .get_frontend = smsdvb_get_frontend,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001050 .get_tune_settings = smsdvb_get_tune_settings,
1051
1052 .read_status = smsdvb_read_status,
1053 .read_ber = smsdvb_read_ber,
1054 .read_signal_strength = smsdvb_read_signal_strength,
1055 .read_snr = smsdvb_read_snr,
Michael Krufky851a9092008-11-22 14:56:37 -03001056 .read_ucblocks = smsdvb_read_ucblocks,
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001057
1058 .init = smsdvb_init,
1059 .sleep = smsdvb_sleep,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001060};
1061
Michael Krufky0c071f32008-06-21 02:44:02 -03001062static int smsdvb_hotplug(struct smscore_device_t *coredev,
1063 struct device *device, int arrival)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001064{
Michael Krufky18245e12008-06-15 17:52:24 -03001065 struct smsclient_params_t params;
1066 struct smsdvb_client_t *client;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001067 int rc;
1068
Michael Krufkyfa830e82008-06-15 15:52:43 -03001069 /* device removal handled by onremove callback */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001070 if (!arrival)
1071 return 0;
Michael Krufky18245e12008-06-15 17:52:24 -03001072 client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
Michael Krufky82237412008-06-15 15:14:13 -03001073 if (!client) {
Michael Krufkyeb250942008-06-19 22:07:23 -03001074 sms_err("kmalloc() failed");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001075 return -ENOMEM;
1076 }
1077
Michael Krufkyfa830e82008-06-15 15:52:43 -03001078 /* register dvb adapter */
Michael Krufky1c11d542008-06-18 22:09:55 -03001079 rc = dvb_register_adapter(&client->adapter,
1080 sms_get_board(
1081 smscore_get_board_id(coredev))->name,
Michael Krufky82237412008-06-15 15:14:13 -03001082 THIS_MODULE, device, adapter_nr);
1083 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001084 sms_err("dvb_register_adapter() failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001085 goto adapter_error;
1086 }
1087
Michael Krufkyfa830e82008-06-15 15:52:43 -03001088 /* init dvb demux */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001089 client->demux.dmx.capabilities = DMX_TS_FILTERING;
Michael Krufkyfa830e82008-06-15 15:52:43 -03001090 client->demux.filternum = 32; /* todo: nova ??? */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001091 client->demux.feednum = 32;
1092 client->demux.start_feed = smsdvb_start_feed;
1093 client->demux.stop_feed = smsdvb_stop_feed;
1094
1095 rc = dvb_dmx_init(&client->demux);
Michael Krufky82237412008-06-15 15:14:13 -03001096 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001097 sms_err("dvb_dmx_init failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001098 goto dvbdmx_error;
1099 }
1100
Michael Krufkyfa830e82008-06-15 15:52:43 -03001101 /* init dmxdev */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001102 client->dmxdev.filternum = 32;
1103 client->dmxdev.demux = &client->demux.dmx;
1104 client->dmxdev.capabilities = 0;
1105
1106 rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
Michael Krufky82237412008-06-15 15:14:13 -03001107 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001108 sms_err("dvb_dmxdev_init failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001109 goto dmxdev_error;
1110 }
1111
Michael Krufkyfa830e82008-06-15 15:52:43 -03001112 /* init and register frontend */
Michael Krufky82237412008-06-15 15:14:13 -03001113 memcpy(&client->frontend.ops, &smsdvb_fe_ops,
1114 sizeof(struct dvb_frontend_ops));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001115
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001116 switch (smscore_get_device_mode(coredev)) {
1117 case DEVICE_MODE_DVBT:
1118 case DEVICE_MODE_DVBT_BDA:
Mauro Carvalho Chehab9bd58e72012-03-01 07:25:39 -03001119 client->frontend.ops.delsys[0] = SYS_DVBT;
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001120 break;
1121 case DEVICE_MODE_ISDBT:
1122 case DEVICE_MODE_ISDBT_BDA:
Mauro Carvalho Chehab9bd58e72012-03-01 07:25:39 -03001123 client->frontend.ops.delsys[0] = SYS_ISDBT;
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001124 break;
1125 }
1126
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001127 rc = dvb_register_frontend(&client->adapter, &client->frontend);
Michael Krufky82237412008-06-15 15:14:13 -03001128 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001129 sms_err("frontend registration failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001130 goto frontend_error;
1131 }
1132
Michael Krufkyf17407a2008-06-14 00:43:26 -03001133 params.initial_id = 1;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001134 params.data_type = MSG_SMS_DVBT_BDA_DATA;
1135 params.onresponse_handler = smsdvb_onresponse;
1136 params.onremove_handler = smsdvb_onremove;
1137 params.context = client;
1138
1139 rc = smscore_register_client(coredev, &params, &client->smsclient);
Michael Krufky82237412008-06-15 15:14:13 -03001140 if (rc < 0) {
Michael Krufkyeb250942008-06-19 22:07:23 -03001141 sms_err("smscore_register_client() failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001142 goto client_error;
1143 }
1144
1145 client->coredev = coredev;
1146
1147 init_completion(&client->tune_done);
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -03001148 init_completion(&client->stats_done);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001149
1150 kmutex_lock(&g_smsdvb_clientslock);
1151
1152 list_add(&client->entry, &g_smsdvb_clients);
1153
1154 kmutex_unlock(&g_smsdvb_clientslock);
1155
Uri Shkolnik793786d2009-05-12 12:28:46 -03001156 client->event_fe_state = -1;
1157 client->event_unc_state = -1;
1158 sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001159
Uri Shkolnik793786d2009-05-12 12:28:46 -03001160 sms_info("success");
Michael Krufky250fa672008-11-16 22:45:42 -03001161 sms_board_setup(coredev);
1162
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001163 return 0;
1164
1165client_error:
1166 dvb_unregister_frontend(&client->frontend);
1167
1168frontend_error:
1169 dvb_dmxdev_release(&client->dmxdev);
1170
1171dmxdev_error:
1172 dvb_dmx_release(&client->demux);
1173
1174dvbdmx_error:
1175 dvb_unregister_adapter(&client->adapter);
1176
1177adapter_error:
1178 kfree(client);
1179 return rc;
1180}
1181
Márton Németh2184dda2009-12-11 20:05:10 -03001182static int __init smsdvb_module_init(void)
Steven Totheae55662008-05-22 18:04:36 -03001183{
1184 int rc;
1185
1186 INIT_LIST_HEAD(&g_smsdvb_clients);
1187 kmutex_init(&g_smsdvb_clientslock);
1188
1189 rc = smscore_register_hotplug(smsdvb_hotplug);
1190
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001191 sms_debug("");
Steven Totheae55662008-05-22 18:04:36 -03001192
1193 return rc;
1194}
1195
Márton Németh2184dda2009-12-11 20:05:10 -03001196static void __exit smsdvb_module_exit(void)
Steven Totheae55662008-05-22 18:04:36 -03001197{
1198 smscore_unregister_hotplug(smsdvb_hotplug);
1199
1200 kmutex_lock(&g_smsdvb_clientslock);
1201
1202 while (!list_empty(&g_smsdvb_clients))
Michael Krufky82237412008-06-15 15:14:13 -03001203 smsdvb_unregister_client(
Michael Krufky18245e12008-06-15 17:52:24 -03001204 (struct smsdvb_client_t *) g_smsdvb_clients.next);
Steven Totheae55662008-05-22 18:04:36 -03001205
1206 kmutex_unlock(&g_smsdvb_clientslock);
Steven Totheae55662008-05-22 18:04:36 -03001207}
Uri Shkolnike0f14c22008-08-31 00:44:04 -03001208
1209module_init(smsdvb_module_init);
1210module_exit(smsdvb_module_exit);
1211
1212MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
Uri Shkolnik843d0602009-05-12 13:13:13 -03001213MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
Uri Shkolnike0f14c22008-08-31 00:44:04 -03001214MODULE_LICENSE("GPL");