blob: 04544f591df53911398c475737f7f2fdaf91716e [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
Mauro Carvalho Chehabff702eb2013-03-09 15:54:46 -030064static void smsdvb_print_dvb_stats(struct SMSHOSTLIB_STATISTICS_ST *p)
65{
66 if (!(sms_dbg & 2))
67 return;
68
69 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
70 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
71 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
72 printk(KERN_DEBUG "SNR = %d", p->SNR);
73 printk(KERN_DEBUG "BER = %d", p->BER);
74 printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
75 printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
76 printk(KERN_DEBUG "MFER = %d", p->MFER);
77 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
78 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
79 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
80 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
81 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
82 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
83 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
84 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
85 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
86 printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
87 printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
88 printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
89 printk(KERN_DEBUG "Constellation = %d", p->Constellation);
90 printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
91 printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
92 printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
93 printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
94 printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
95 printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
96 printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
97 printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
98 printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
99 printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
100 printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
101 printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
102 printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
103 printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
104 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
105 printk(KERN_DEBUG "PreBER = %d", p->PreBER);
106 printk(KERN_DEBUG "CellId = %d", p->CellId);
107 printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
108 printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
109 printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
110}
111
112static void smsdvb_print_isdb_stats(struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
113{
114 int i;
115
116 if (!(sms_dbg & 2))
117 return;
118
119 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
120 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
121 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
122 printk(KERN_DEBUG "SNR = %d", p->SNR);
123 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
124 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
125 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
126 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
127 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
128 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
129 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
130 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
131 printk(KERN_DEBUG "SystemType = %d", p->SystemType);
132 printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
133 printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
134 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
135
136 for (i = 0; i < 3; i++) {
137 printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
138 printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
139 printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
140 printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
141 printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
142 printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
143 printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
144 printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
145 printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
146 printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
147 printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
148 printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
149 }
150}
151
152static void
153smsdvb_print_isdb_stats_ex(struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST *p)
154{
155 int i;
156
157 if (!(sms_dbg & 2))
158 return;
159
160 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
161 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
162 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
163 printk(KERN_DEBUG "SNR = %d", p->SNR);
164 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
165 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
166 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
167 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
168 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
169 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
170 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
171 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
172 printk(KERN_DEBUG "SystemType = %d", p->SystemType);
173 printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
174 printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
175 printk(KERN_DEBUG "SegmentNumber = %d", p->SegmentNumber);
176 printk(KERN_DEBUG "TuneBW = %d", p->TuneBW);
177
178 for (i = 0; i < 3; i++) {
179 printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
180 printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
181 printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
182 printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
183 printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
184 printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
185 printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
186 printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
187 printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
188 printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
189 printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
190 printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
191 }
192}
193
Uri Shkolnik793786d2009-05-12 12:28:46 -0300194/* Events that may come from DVB v3 adapter */
195static void sms_board_dvb3_event(struct smsdvb_client_t *client,
196 enum SMS_DVB3_EVENTS event) {
Uri Shkolnik4db989f2009-05-19 12:28:02 -0300197
198 struct smscore_device_t *coredev = client->coredev;
199 switch (event) {
200 case DVB3_EVENT_INIT:
201 sms_debug("DVB3_EVENT_INIT");
202 sms_board_event(coredev, BOARD_EVENT_BIND);
203 break;
204 case DVB3_EVENT_SLEEP:
205 sms_debug("DVB3_EVENT_SLEEP");
206 sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
207 break;
208 case DVB3_EVENT_HOTPLUG:
209 sms_debug("DVB3_EVENT_HOTPLUG");
210 sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
211 break;
212 case DVB3_EVENT_FE_LOCK:
213 if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
214 client->event_fe_state = DVB3_EVENT_FE_LOCK;
215 sms_debug("DVB3_EVENT_FE_LOCK");
216 sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
217 }
218 break;
219 case DVB3_EVENT_FE_UNLOCK:
220 if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
221 client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
222 sms_debug("DVB3_EVENT_FE_UNLOCK");
223 sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
224 }
225 break;
226 case DVB3_EVENT_UNC_OK:
227 if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
228 client->event_unc_state = DVB3_EVENT_UNC_OK;
229 sms_debug("DVB3_EVENT_UNC_OK");
230 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
231 }
232 break;
233 case DVB3_EVENT_UNC_ERR:
234 if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
235 client->event_unc_state = DVB3_EVENT_UNC_ERR;
236 sms_debug("DVB3_EVENT_UNC_ERR");
237 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
238 }
239 break;
240
241 default:
242 sms_err("Unknown dvb3 api event");
243 break;
244 }
Uri Shkolnik793786d2009-05-12 12:28:46 -0300245}
246
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300247static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
Mauro Carvalho Chehabff702eb2013-03-09 15:54:46 -0300248 struct SMSHOSTLIB_STATISTICS_ST *p)
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300249{
Mauro Carvalho Chehabff702eb2013-03-09 15:54:46 -0300250 smsdvb_print_dvb_stats(p);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300251
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300252 /* update reception data */
253 pReceptionData->IsRfLocked = p->IsRfLocked;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300254 pReceptionData->IsDemodLocked = p->IsDemodLocked;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300255 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
256 pReceptionData->ModemState = p->ModemState;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300257 pReceptionData->SNR = p->SNR;
258 pReceptionData->BER = p->BER;
259 pReceptionData->BERErrorCount = p->BERErrorCount;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300260 pReceptionData->BERBitCount = p->BERBitCount;
261 pReceptionData->RSSI = p->RSSI;
262 CORRECT_STAT_RSSI(*pReceptionData);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300263 pReceptionData->InBandPwr = p->InBandPwr;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300264 pReceptionData->CarrierOffset = p->CarrierOffset;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300265 pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300266 pReceptionData->TotalTSPackets = p->TotalTSPackets;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300267};
268
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300269static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
Mauro Carvalho Chehabff702eb2013-03-09 15:54:46 -0300270 struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300271{
Mauro Carvalho Chehabff702eb2013-03-09 15:54:46 -0300272 smsdvb_print_isdb_stats(p);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300273
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300274 /* update reception data */
275 pReceptionData->IsRfLocked = p->IsRfLocked;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300276 pReceptionData->IsDemodLocked = p->IsDemodLocked;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300277 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
278 pReceptionData->ModemState = p->ModemState;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300279 pReceptionData->SNR = p->SNR;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300280 pReceptionData->BER = p->LayerInfo[0].BER;
281 pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
282 pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
283 pReceptionData->RSSI = p->RSSI;
284 CORRECT_STAT_RSSI(*pReceptionData);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300285 pReceptionData->InBandPwr = p->InBandPwr;
286
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300287 pReceptionData->CarrierOffset = p->CarrierOffset;
288 pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
289 pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
290 pReceptionData->MFER = 0;
291
292 /* TS PER */
293 if ((p->LayerInfo[0].TotalTSPackets +
294 p->LayerInfo[0].ErrorTSPackets) > 0) {
295 pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets
296 * 100) / (p->LayerInfo[0].TotalTSPackets
297 + p->LayerInfo[0].ErrorTSPackets);
298 } else {
299 pReceptionData->TS_PER = 0;
300 }
301}
302
303static void smsdvb_update_isdbt_stats_ex(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
304 struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST *p)
305{
Mauro Carvalho Chehabff702eb2013-03-09 15:54:46 -0300306 smsdvb_print_isdb_stats_ex(p);
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300307
308 /* update reception data */
309 pReceptionData->IsRfLocked = p->IsRfLocked;
310 pReceptionData->IsDemodLocked = p->IsDemodLocked;
311 pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
312 pReceptionData->ModemState = p->ModemState;
313 pReceptionData->SNR = p->SNR;
314 pReceptionData->BER = p->LayerInfo[0].BER;
315 pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
316 pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
317 pReceptionData->RSSI = p->RSSI;
318 CORRECT_STAT_RSSI(*pReceptionData);
319 pReceptionData->InBandPwr = p->InBandPwr;
320
321 pReceptionData->CarrierOffset = p->CarrierOffset;
322 pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
323 pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
324 pReceptionData->MFER = 0;
325
326 /* TS PER */
327 if ((p->LayerInfo[0].TotalTSPackets +
328 p->LayerInfo[0].ErrorTSPackets) > 0) {
329 pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets
330 * 100) / (p->LayerInfo[0].TotalTSPackets
331 + p->LayerInfo[0].ErrorTSPackets);
332 } else {
333 pReceptionData->TS_PER = 0;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300334 }
335}
336
Michael Krufky0c071f32008-06-21 02:44:02 -0300337static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300338{
Michael Krufky18245e12008-06-15 17:52:24 -0300339 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300340 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
341 + cb->offset);
342 u32 *pMsgData = (u32 *) phdr + 1;
343 /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
344 bool is_status_update = false;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300345
Michael Krufkyfa830e82008-06-15 15:52:43 -0300346 switch (phdr->msgType) {
Michael Krufky82237412008-06-15 15:14:13 -0300347 case MSG_SMS_DVBT_BDA_DATA:
348 dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
Michael Krufky18245e12008-06-15 17:52:24 -0300349 cb->size - sizeof(struct SmsMsgHdr_ST));
Michael Krufky82237412008-06-15 15:14:13 -0300350 break;
351
352 case MSG_SMS_RF_TUNE_RES:
Michael Krufky6b26fce2009-12-22 21:08:49 -0300353 case MSG_SMS_ISDBT_TUNE_RES:
Michael Krufky82237412008-06-15 15:14:13 -0300354 complete(&client->tune_done);
355 break;
356
Uri Shkolnik793786d2009-05-12 12:28:46 -0300357 case MSG_SMS_SIGNAL_DETECTED_IND:
Uri Shkolnik793786d2009-05-12 12:28:46 -0300358 client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
359 is_status_update = true;
360 break;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300361
Uri Shkolnik793786d2009-05-12 12:28:46 -0300362 case MSG_SMS_NO_SIGNAL_IND:
Uri Shkolnik793786d2009-05-12 12:28:46 -0300363 client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
364 is_status_update = true;
365 break;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300366
Uri Shkolnik793786d2009-05-12 12:28:46 -0300367 case MSG_SMS_TRANSMISSION_IND: {
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300368
Uri Shkolnik793786d2009-05-12 12:28:46 -0300369 pMsgData++;
370 memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
371 sizeof(struct TRANSMISSION_STATISTICS_S));
372
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300373#if 1
374 /*
375 * FIXME: newer driver doesn't have those fixes
376 * Are those firmware-specific stuff?
377 */
378
Uri Shkolnik793786d2009-05-12 12:28:46 -0300379 /* Mo need to correct guard interval
380 * (as opposed to old statistics message).
381 */
382 CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
383 CORRECT_STAT_TRANSMISSON_MODE(
384 client->sms_stat_dvb.TransmissionData);
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300385#endif
Uri Shkolnik793786d2009-05-12 12:28:46 -0300386 is_status_update = true;
387 break;
388 }
389 case MSG_SMS_HO_PER_SLICES_IND: {
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300390 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
Uri Shkolnik793786d2009-05-12 12:28:46 -0300391 &client->sms_stat_dvb.ReceptionData;
392 struct SRVM_SIGNAL_STATUS_S SignalStatusData;
393
Uri Shkolnik793786d2009-05-12 12:28:46 -0300394 pMsgData++;
395 SignalStatusData.result = pMsgData[0];
396 SignalStatusData.snr = pMsgData[1];
397 SignalStatusData.inBandPower = (s32) pMsgData[2];
398 SignalStatusData.tsPackets = pMsgData[3];
399 SignalStatusData.etsPackets = pMsgData[4];
400 SignalStatusData.constellation = pMsgData[5];
401 SignalStatusData.hpCode = pMsgData[6];
402 SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
403 SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
404 SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
405 SignalStatusData.reason = pMsgData[10];
406 SignalStatusData.requestId = pMsgData[11];
407 pReceptionData->IsRfLocked = pMsgData[16];
408 pReceptionData->IsDemodLocked = pMsgData[17];
409 pReceptionData->ModemState = pMsgData[12];
410 pReceptionData->SNR = pMsgData[1];
411 pReceptionData->BER = pMsgData[13];
412 pReceptionData->RSSI = pMsgData[14];
413 CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
414
415 pReceptionData->InBandPwr = (s32) pMsgData[2];
416 pReceptionData->CarrierOffset = (s32) pMsgData[15];
417 pReceptionData->TotalTSPackets = pMsgData[3];
418 pReceptionData->ErrorTSPackets = pMsgData[4];
419
420 /* TS PER */
421 if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
422 > 0) {
423 pReceptionData->TS_PER = (SignalStatusData.etsPackets
424 * 100) / (SignalStatusData.tsPackets
425 + SignalStatusData.etsPackets);
Michael Krufky82237412008-06-15 15:14:13 -0300426 } else {
Uri Shkolnik793786d2009-05-12 12:28:46 -0300427 pReceptionData->TS_PER = 0;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300428 }
Michael Krufky82237412008-06-15 15:14:13 -0300429
Uri Shkolnik793786d2009-05-12 12:28:46 -0300430 pReceptionData->BERBitCount = pMsgData[18];
431 pReceptionData->BERErrorCount = pMsgData[19];
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300432
Uri Shkolnik793786d2009-05-12 12:28:46 -0300433 pReceptionData->MRC_SNR = pMsgData[20];
434 pReceptionData->MRC_InBandPwr = pMsgData[21];
435 pReceptionData->MRC_RSSI = pMsgData[22];
436
437 is_status_update = true;
438 break;
439 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300440 case MSG_SMS_GET_STATISTICS_RES: {
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300441 union {
442 struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
443 struct SmsMsgStatisticsInfo_ST dvb;
444 } *p = (void *) (phdr + 1);
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300445 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300446 &client->sms_stat_dvb.ReceptionData;
447
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300448 is_status_update = true;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300449
450 switch (smscore_get_device_mode(client->coredev)) {
451 case DEVICE_MODE_ISDBT:
452 case DEVICE_MODE_ISDBT_BDA:
453 smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
454 break;
455 default:
456 smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
457 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300458 if (!pReceptionData->IsDemodLocked) {
459 pReceptionData->SNR = 0;
460 pReceptionData->BER = 0;
461 pReceptionData->BERErrorCount = 0;
462 pReceptionData->InBandPwr = 0;
463 pReceptionData->ErrorTSPackets = 0;
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300464 }
465
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300466 break;
467 }
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300468 case MSG_SMS_GET_STATISTICS_EX_RES: {
469 union {
470 struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST isdbt;
471 struct SMSHOSTLIB_STATISTICS_ST dvb;
472 } *p = (void *) (phdr + 1);
473 struct RECEPTION_STATISTICS_EX_S *pReceptionData =
474 &client->sms_stat_dvb.ReceptionData;
475
476 is_status_update = true;
477
478 switch (smscore_get_device_mode(client->coredev)) {
479 case DEVICE_MODE_ISDBT:
480 case DEVICE_MODE_ISDBT_BDA:
481 smsdvb_update_isdbt_stats_ex(pReceptionData, &p->isdbt);
482 break;
483 default:
484 smsdvb_update_dvb_stats(pReceptionData, &p->dvb);
485 }
486 if (!pReceptionData->IsDemodLocked) {
487 pReceptionData->SNR = 0;
488 pReceptionData->BER = 0;
489 pReceptionData->BERErrorCount = 0;
490 pReceptionData->InBandPwr = 0;
491 pReceptionData->ErrorTSPackets = 0;
492 }
493
494 break;
495 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300496 default:
Mauro Carvalho Chehab4c3bdb52013-03-09 09:27:39 -0300497 sms_info("message not handled");
Uri Shkolnik793786d2009-05-12 12:28:46 -0300498 }
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300499 smscore_putbuffer(client->coredev, cb);
500
Uri Shkolnik793786d2009-05-12 12:28:46 -0300501 if (is_status_update) {
502 if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
503 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
504 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
505 sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
506 if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
507 == 0)
508 sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
509 else
510 sms_board_dvb3_event(client,
511 DVB3_EVENT_UNC_ERR);
512
513 } else {
Mauro Carvalho Chehabb4622c12009-12-25 18:04:17 -0300514 if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
515 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
516 else
517 client->fe_status = 0;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300518 sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
519 }
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -0300520 complete(&client->stats_done);
Uri Shkolnik793786d2009-05-12 12:28:46 -0300521 }
522
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300523 return 0;
524}
525
Michael Krufky0c071f32008-06-21 02:44:02 -0300526static void smsdvb_unregister_client(struct smsdvb_client_t *client)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300527{
Michael Krufkyfa830e82008-06-15 15:52:43 -0300528 /* must be called under clientslock */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300529
530 list_del(&client->entry);
531
532 smscore_unregister_client(client->smsclient);
533 dvb_unregister_frontend(&client->frontend);
534 dvb_dmxdev_release(&client->dmxdev);
535 dvb_dmx_release(&client->demux);
536 dvb_unregister_adapter(&client->adapter);
537 kfree(client);
538}
539
Michael Krufky0c071f32008-06-21 02:44:02 -0300540static void smsdvb_onremove(void *context)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300541{
542 kmutex_lock(&g_smsdvb_clientslock);
543
Michael Krufky18245e12008-06-15 17:52:24 -0300544 smsdvb_unregister_client((struct smsdvb_client_t *) context);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300545
546 kmutex_unlock(&g_smsdvb_clientslock);
547}
548
549static int smsdvb_start_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("add 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_ADD_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
569static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
570{
Michael Krufky18245e12008-06-15 17:52:24 -0300571 struct smsdvb_client_t *client =
572 container_of(feed->demux, struct smsdvb_client_t, demux);
573 struct SmsMsgData_ST PidMsg;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300574
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300575 sms_debug("remove pid %d(%x)",
Michael Krufky068d6c02008-06-19 01:15:46 -0300576 feed->pid, feed->pid);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300577
578 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
579 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
580 PidMsg.xMsgHeader.msgFlags = 0;
581 PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ;
582 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
583 PidMsg.msgData[0] = feed->pid;
584
Michael Krufky82237412008-06-15 15:14:13 -0300585 return smsclient_sendrequest(client->smsclient,
586 &PidMsg, sizeof(PidMsg));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300587}
588
Michael Krufky18245e12008-06-15 17:52:24 -0300589static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
Michael Krufkya83ccdd2008-05-06 03:11:51 -0300590 void *buffer, size_t size,
591 struct completion *completion)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300592{
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300593 int rc;
594
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300595 rc = smsclient_sendrequest(client->smsclient, buffer, size);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300596 if (rc < 0)
597 return rc;
598
Michael Krufky82237412008-06-15 15:14:13 -0300599 return wait_for_completion_timeout(completion,
600 msecs_to_jiffies(2000)) ?
601 0 : -ETIME;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300602}
603
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300604static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
605{
606 int rc;
Mauro Carvalho Chehabb4059092013-03-07 21:58:47 -0300607 struct SmsMsgHdr_ST Msg;
608
609
610 Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
611 Msg.msgDstId = HIF_TASK;
612 Msg.msgFlags = 0;
613 Msg.msgLength = sizeof(Msg);
614
615 /*
616 * Check for firmware version, to avoid breaking for old cards
617 */
618 if (client->coredev->fw_version >= 0x800)
619 Msg.msgType = MSG_SMS_GET_STATISTICS_EX_REQ;
620 else
621 Msg.msgType = MSG_SMS_GET_STATISTICS_REQ;
622
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300623 rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -0300624 &client->stats_done);
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300625
626 return rc;
627}
628
Michael Krufky3746b612009-07-12 23:30:14 -0300629static inline int led_feedback(struct smsdvb_client_t *client)
630{
631 if (client->fe_status & FE_HAS_LOCK)
632 return sms_board_led_feedback(client->coredev,
633 (client->sms_stat_dvb.ReceptionData.BER
634 == 0) ? SMS_LED_HI : SMS_LED_LO);
635 else
636 return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
637}
638
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300639static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
640{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300641 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300642 struct smsdvb_client_t *client;
643 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300644
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300645 rc = smsdvb_send_statistics_request(client);
646
Uri Shkolnik793786d2009-05-12 12:28:46 -0300647 *stat = client->fe_status;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300648
Michael Krufky3746b612009-07-12 23:30:14 -0300649 led_feedback(client);
650
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300651 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300652}
653
654static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
655{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300656 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300657 struct smsdvb_client_t *client;
658 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300659
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300660 rc = smsdvb_send_statistics_request(client);
661
Uri Shkolnik793786d2009-05-12 12:28:46 -0300662 *ber = client->sms_stat_dvb.ReceptionData.BER;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300663
Michael Krufky3746b612009-07-12 23:30:14 -0300664 led_feedback(client);
665
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300666 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300667}
668
669static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
670{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300671 int rc;
672
Uri Shkolnik793786d2009-05-12 12:28:46 -0300673 struct smsdvb_client_t *client;
674 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300675
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300676 rc = smsdvb_send_statistics_request(client);
677
Uri Shkolnik793786d2009-05-12 12:28:46 -0300678 if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
679 *strength = 0;
680 else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
681 *strength = 100;
682 else
683 *strength =
684 (client->sms_stat_dvb.ReceptionData.InBandPwr
685 + 95) * 3 / 2;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300686
Michael Krufky3746b612009-07-12 23:30:14 -0300687 led_feedback(client);
688
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300689 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300690}
691
692static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
693{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300694 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300695 struct smsdvb_client_t *client;
696 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300697
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300698 rc = smsdvb_send_statistics_request(client);
699
Uri Shkolnik793786d2009-05-12 12:28:46 -0300700 *snr = client->sms_stat_dvb.ReceptionData.SNR;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300701
Michael Krufky3746b612009-07-12 23:30:14 -0300702 led_feedback(client);
703
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300704 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300705}
706
Michael Krufky851a9092008-11-22 14:56:37 -0300707static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
708{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300709 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300710 struct smsdvb_client_t *client;
711 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky851a9092008-11-22 14:56:37 -0300712
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300713 rc = smsdvb_send_statistics_request(client);
714
Uri Shkolnik793786d2009-05-12 12:28:46 -0300715 *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
Michael Krufky851a9092008-11-22 14:56:37 -0300716
Michael Krufky3746b612009-07-12 23:30:14 -0300717 led_feedback(client);
718
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300719 return rc;
Michael Krufky851a9092008-11-22 14:56:37 -0300720}
721
Michael Krufky82237412008-06-15 15:14:13 -0300722static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
723 struct dvb_frontend_tune_settings *tune)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300724{
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300725 sms_debug("");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300726
727 tune->min_delay_ms = 400;
728 tune->step_size = 250000;
729 tune->max_drift = 0;
730 return 0;
731}
732
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300733static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300734{
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300735 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Michael Krufky18245e12008-06-15 17:52:24 -0300736 struct smsdvb_client_t *client =
737 container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300738
Michael Krufky18245e12008-06-15 17:52:24 -0300739 struct {
740 struct SmsMsgHdr_ST Msg;
Michael Krufky82237412008-06-15 15:14:13 -0300741 u32 Data[3];
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300742 } Msg;
743
Michael Krufky3746b612009-07-12 23:30:14 -0300744 int ret;
745
Uri Shkolnik793786d2009-05-12 12:28:46 -0300746 client->fe_status = FE_HAS_SIGNAL;
747 client->event_fe_state = -1;
748 client->event_unc_state = -1;
Mauro Carvalho Chehabe85c97a2009-12-25 07:17:03 -0300749 fe->dtv_property_cache.delivery_system = SYS_DVBT;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300750
751 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
752 Msg.Msg.msgDstId = HIF_TASK;
753 Msg.Msg.msgFlags = 0;
754 Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300755 Msg.Msg.msgLength = sizeof(Msg);
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300756 Msg.Data[0] = c->frequency;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300757 Msg.Data[2] = 12000000;
758
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300759 sms_info("%s: freq %d band %d", __func__, c->frequency,
760 c->bandwidth_hz);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300761
Mauro Carvalho Chehab643e15a2009-12-25 07:29:06 -0300762 switch (c->bandwidth_hz / 1000000) {
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300763 case 8:
764 Msg.Data[1] = BW_8_MHZ;
765 break;
766 case 7:
767 Msg.Data[1] = BW_7_MHZ;
768 break;
769 case 6:
770 Msg.Data[1] = BW_6_MHZ;
771 break;
772 case 0:
773 return -EOPNOTSUPP;
774 default:
775 return -EINVAL;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300776 }
Michael Krufky3746b612009-07-12 23:30:14 -0300777 /* Disable LNA, if any. An error is returned if no LNA is present */
778 ret = sms_board_lna_control(client->coredev, 0);
779 if (ret == 0) {
780 fe_status_t status;
781
782 /* tune with LNA off at first */
783 ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
784 &client->tune_done);
785
786 smsdvb_read_status(fe, &status);
787
788 if (status & FE_HAS_LOCK)
789 return ret;
790
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300791 /* previous tune didn't lock - enable LNA and tune again */
Michael Krufky3746b612009-07-12 23:30:14 -0300792 sms_board_lna_control(client->coredev, 1);
793 }
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300794
Michael Krufky82237412008-06-15 15:14:13 -0300795 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
796 &client->tune_done);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300797}
798
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300799static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
Michael Krufky6b26fce2009-12-22 21:08:49 -0300800{
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300801 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300802 struct smsdvb_client_t *client =
803 container_of(fe, struct smsdvb_client_t, frontend);
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300804 int board_id = smscore_get_board_id(client->coredev);
805 struct sms_board *board = sms_get_board(board_id);
806 enum sms_device_type_st type = board->type;
Mauro Carvalho Chehab0c189fa2013-03-07 16:34:53 -0300807 int ret;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300808 struct {
809 struct SmsMsgHdr_ST Msg;
810 u32 Data[4];
811 } Msg;
812
Mauro Carvalho Chehabe85c97a2009-12-25 07:17:03 -0300813 fe->dtv_property_cache.delivery_system = SYS_ISDBT;
814
Michael Krufky6b26fce2009-12-22 21:08:49 -0300815 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
816 Msg.Msg.msgDstId = HIF_TASK;
817 Msg.Msg.msgFlags = 0;
818 Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ;
819 Msg.Msg.msgLength = sizeof(Msg);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300820
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300821 if (c->isdbt_sb_segment_idx == -1)
822 c->isdbt_sb_segment_idx = 0;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300823
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300824 if (!c->isdbt_layer_enabled)
825 c->isdbt_layer_enabled = 7;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300826
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300827 Msg.Data[0] = c->frequency;
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300828 Msg.Data[1] = BW_ISDBT_1SEG;
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300829 Msg.Data[2] = 12000000;
830 Msg.Data[3] = c->isdbt_sb_segment_idx;
831
Mauro Carvalho Chehaba51fea42013-03-07 16:34:06 -0300832 if (c->isdbt_partial_reception) {
833 if ((type == SMS_PELE || type == SMS_RIO) &&
834 c->isdbt_sb_segment_count > 3)
835 Msg.Data[1] = BW_ISDBT_13SEG;
836 else if (c->isdbt_sb_segment_count > 1)
837 Msg.Data[1] = BW_ISDBT_3SEG;
838 } else if (type == SMS_PELE || type == SMS_RIO)
839 Msg.Data[1] = BW_ISDBT_13SEG;
840
841 c->bandwidth_hz = 6000000;
842
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300843 sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
844 c->frequency, c->isdbt_sb_segment_count,
845 c->isdbt_sb_segment_idx);
846
Mauro Carvalho Chehab0c189fa2013-03-07 16:34:53 -0300847 /* Disable LNA, if any. An error is returned if no LNA is present */
848 ret = sms_board_lna_control(client->coredev, 0);
849 if (ret == 0) {
850 fe_status_t status;
851
852 /* tune with LNA off at first */
853 ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
854 &client->tune_done);
855
856 smsdvb_read_status(fe, &status);
857
858 if (status & FE_HAS_LOCK)
859 return ret;
860
861 /* previous tune didn't lock - enable LNA and tune again */
862 sms_board_lna_control(client->coredev, 1);
863 }
Michael Krufky6b26fce2009-12-22 21:08:49 -0300864 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
865 &client->tune_done);
866}
867
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300868static int smsdvb_set_frontend(struct dvb_frontend *fe)
Michael Krufky6b26fce2009-12-22 21:08:49 -0300869{
870 struct smsdvb_client_t *client =
871 container_of(fe, struct smsdvb_client_t, frontend);
872 struct smscore_device_t *coredev = client->coredev;
873
874 switch (smscore_get_device_mode(coredev)) {
875 case DEVICE_MODE_DVBT:
876 case DEVICE_MODE_DVBT_BDA:
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300877 return smsdvb_dvbt_set_frontend(fe);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300878 case DEVICE_MODE_ISDBT:
879 case DEVICE_MODE_ISDBT_BDA:
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300880 return smsdvb_isdbt_set_frontend(fe);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300881 default:
882 return -EINVAL;
883 }
884}
885
Mauro Carvalho Chehabeab0fa02013-03-09 12:05:58 -0300886static int smsdvb_get_frontend_dvb(struct dvb_frontend *fe)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300887{
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -0300888 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
Michael Krufky18245e12008-06-15 17:52:24 -0300889 struct smsdvb_client_t *client =
890 container_of(fe, struct smsdvb_client_t, frontend);
Gianluca Gennarid1382102012-02-20 07:50:33 -0300891 struct TRANSMISSION_STATISTICS_S *td =
892 &client->sms_stat_dvb.TransmissionData;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300893
Mauro Carvalho Chehabeab0fa02013-03-09 12:05:58 -0300894 fep->frequency = td->Frequency;
895
896 switch (td->Bandwidth) {
897 case 6:
898 fep->bandwidth_hz = 6000000;
899 break;
900 case 7:
901 fep->bandwidth_hz = 7000000;
902 break;
903 case 8:
904 fep->bandwidth_hz = 8000000;
905 break;
906 }
907
908 switch (td->TransmissionMode) {
909 case 2:
910 fep->transmission_mode = TRANSMISSION_MODE_2K;
911 break;
912 case 8:
913 fep->transmission_mode = TRANSMISSION_MODE_8K;
914 }
915
916 switch (td->GuardInterval) {
917 case 0:
918 fep->guard_interval = GUARD_INTERVAL_1_32;
919 break;
920 case 1:
921 fep->guard_interval = GUARD_INTERVAL_1_16;
922 break;
923 case 2:
924 fep->guard_interval = GUARD_INTERVAL_1_8;
925 break;
926 case 3:
927 fep->guard_interval = GUARD_INTERVAL_1_4;
928 break;
929 }
930
931 switch (td->CodeRate) {
932 case 0:
933 fep->code_rate_HP = FEC_1_2;
934 break;
935 case 1:
936 fep->code_rate_HP = FEC_2_3;
937 break;
938 case 2:
939 fep->code_rate_HP = FEC_3_4;
940 break;
941 case 3:
942 fep->code_rate_HP = FEC_5_6;
943 break;
944 case 4:
945 fep->code_rate_HP = FEC_7_8;
946 break;
947 }
948
949 switch (td->LPCodeRate) {
950 case 0:
951 fep->code_rate_LP = FEC_1_2;
952 break;
953 case 1:
954 fep->code_rate_LP = FEC_2_3;
955 break;
956 case 2:
957 fep->code_rate_LP = FEC_3_4;
958 break;
959 case 3:
960 fep->code_rate_LP = FEC_5_6;
961 break;
962 case 4:
963 fep->code_rate_LP = FEC_7_8;
964 break;
965 }
966
967 switch (td->Constellation) {
968 case 0:
969 fep->modulation = QPSK;
970 break;
971 case 1:
972 fep->modulation = QAM_16;
973 break;
974 case 2:
975 fep->modulation = QAM_64;
976 break;
977 }
978
979 switch (td->Hierarchy) {
980 case 0:
981 fep->hierarchy = HIERARCHY_NONE;
982 break;
983 case 1:
984 fep->hierarchy = HIERARCHY_1;
985 break;
986 case 2:
987 fep->hierarchy = HIERARCHY_2;
988 break;
989 case 3:
990 fep->hierarchy = HIERARCHY_4;
991 break;
992 }
993
994 fep->inversion = INVERSION_AUTO;
995
996 return 0;
997}
998
999static int smsdvb_get_frontend_isdb(struct dvb_frontend *fe)
1000{
1001 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
1002 struct smsdvb_client_t *client =
1003 container_of(fe, struct smsdvb_client_t, frontend);
1004 struct TRANSMISSION_STATISTICS_S *td =
1005 &client->sms_stat_dvb.TransmissionData;
1006
1007 fep->frequency = td->Frequency;
1008 fep->bandwidth_hz = 6000000;
1009 /* todo: retrive the other parameters */
1010
1011 return 0;
1012}
1013
1014static int smsdvb_get_frontend(struct dvb_frontend *fe)
1015{
1016 struct smsdvb_client_t *client =
1017 container_of(fe, struct smsdvb_client_t, frontend);
1018 struct smscore_device_t *coredev = client->coredev;
1019
Gianluca Gennarid1382102012-02-20 07:50:33 -03001020 switch (smscore_get_device_mode(coredev)) {
1021 case DEVICE_MODE_DVBT:
1022 case DEVICE_MODE_DVBT_BDA:
Mauro Carvalho Chehabeab0fa02013-03-09 12:05:58 -03001023 return smsdvb_get_frontend_dvb(fe);
Gianluca Gennarid1382102012-02-20 07:50:33 -03001024 case DEVICE_MODE_ISDBT:
1025 case DEVICE_MODE_ISDBT_BDA:
Mauro Carvalho Chehabeab0fa02013-03-09 12:05:58 -03001026 return smsdvb_get_frontend_isdb(fe);
Gianluca Gennarid1382102012-02-20 07:50:33 -03001027 default:
1028 return -EINVAL;
1029 }
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001030}
1031
1032static int smsdvb_init(struct dvb_frontend *fe)
1033{
1034 struct smsdvb_client_t *client =
1035 container_of(fe, struct smsdvb_client_t, frontend);
1036
Michael Krufky3746b612009-07-12 23:30:14 -03001037 sms_board_power(client->coredev, 1);
1038
Uri Shkolnik793786d2009-05-12 12:28:46 -03001039 sms_board_dvb3_event(client, DVB3_EVENT_INIT);
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001040 return 0;
1041}
1042
1043static int smsdvb_sleep(struct dvb_frontend *fe)
1044{
1045 struct smsdvb_client_t *client =
1046 container_of(fe, struct smsdvb_client_t, frontend);
1047
Michael Krufky3746b612009-07-12 23:30:14 -03001048 sms_board_led_feedback(client->coredev, SMS_LED_OFF);
1049 sms_board_power(client->coredev, 0);
1050
Uri Shkolnik793786d2009-05-12 12:28:46 -03001051 sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001052
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001053 return 0;
1054}
1055
1056static void smsdvb_release(struct dvb_frontend *fe)
1057{
Michael Krufkyfa830e82008-06-15 15:52:43 -03001058 /* do nothing */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001059}
1060
1061static struct dvb_frontend_ops smsdvb_fe_ops = {
1062 .info = {
Uri Shkolnike0f14c22008-08-31 00:44:04 -03001063 .name = "Siano Mobile Digital MDTV Receiver",
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001064 .frequency_min = 44250000,
1065 .frequency_max = 867250000,
1066 .frequency_stepsize = 250000,
1067 .caps = FE_CAN_INVERSION_AUTO |
Michael Krufky82237412008-06-15 15:14:13 -03001068 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1069 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1070 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
1071 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
1072 FE_CAN_GUARD_INTERVAL_AUTO |
1073 FE_CAN_RECOVER |
1074 FE_CAN_HIERARCHY_AUTO,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001075 },
1076
1077 .release = smsdvb_release,
1078
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001079 .set_frontend = smsdvb_set_frontend,
1080 .get_frontend = smsdvb_get_frontend,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001081 .get_tune_settings = smsdvb_get_tune_settings,
1082
1083 .read_status = smsdvb_read_status,
1084 .read_ber = smsdvb_read_ber,
1085 .read_signal_strength = smsdvb_read_signal_strength,
1086 .read_snr = smsdvb_read_snr,
Michael Krufky851a9092008-11-22 14:56:37 -03001087 .read_ucblocks = smsdvb_read_ucblocks,
Michael Krufky7a6fbed2008-11-22 14:26:37 -03001088
1089 .init = smsdvb_init,
1090 .sleep = smsdvb_sleep,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001091};
1092
Michael Krufky0c071f32008-06-21 02:44:02 -03001093static int smsdvb_hotplug(struct smscore_device_t *coredev,
1094 struct device *device, int arrival)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001095{
Michael Krufky18245e12008-06-15 17:52:24 -03001096 struct smsclient_params_t params;
1097 struct smsdvb_client_t *client;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001098 int rc;
1099
Michael Krufkyfa830e82008-06-15 15:52:43 -03001100 /* device removal handled by onremove callback */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001101 if (!arrival)
1102 return 0;
Michael Krufky18245e12008-06-15 17:52:24 -03001103 client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
Michael Krufky82237412008-06-15 15:14:13 -03001104 if (!client) {
Michael Krufkyeb250942008-06-19 22:07:23 -03001105 sms_err("kmalloc() failed");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001106 return -ENOMEM;
1107 }
1108
Michael Krufkyfa830e82008-06-15 15:52:43 -03001109 /* register dvb adapter */
Michael Krufky1c11d542008-06-18 22:09:55 -03001110 rc = dvb_register_adapter(&client->adapter,
1111 sms_get_board(
1112 smscore_get_board_id(coredev))->name,
Michael Krufky82237412008-06-15 15:14:13 -03001113 THIS_MODULE, device, adapter_nr);
1114 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001115 sms_err("dvb_register_adapter() failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001116 goto adapter_error;
1117 }
1118
Michael Krufkyfa830e82008-06-15 15:52:43 -03001119 /* init dvb demux */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001120 client->demux.dmx.capabilities = DMX_TS_FILTERING;
Michael Krufkyfa830e82008-06-15 15:52:43 -03001121 client->demux.filternum = 32; /* todo: nova ??? */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001122 client->demux.feednum = 32;
1123 client->demux.start_feed = smsdvb_start_feed;
1124 client->demux.stop_feed = smsdvb_stop_feed;
1125
1126 rc = dvb_dmx_init(&client->demux);
Michael Krufky82237412008-06-15 15:14:13 -03001127 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001128 sms_err("dvb_dmx_init failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001129 goto dvbdmx_error;
1130 }
1131
Michael Krufkyfa830e82008-06-15 15:52:43 -03001132 /* init dmxdev */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001133 client->dmxdev.filternum = 32;
1134 client->dmxdev.demux = &client->demux.dmx;
1135 client->dmxdev.capabilities = 0;
1136
1137 rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
Michael Krufky82237412008-06-15 15:14:13 -03001138 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001139 sms_err("dvb_dmxdev_init failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001140 goto dmxdev_error;
1141 }
1142
Michael Krufkyfa830e82008-06-15 15:52:43 -03001143 /* init and register frontend */
Michael Krufky82237412008-06-15 15:14:13 -03001144 memcpy(&client->frontend.ops, &smsdvb_fe_ops,
1145 sizeof(struct dvb_frontend_ops));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001146
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001147 switch (smscore_get_device_mode(coredev)) {
1148 case DEVICE_MODE_DVBT:
1149 case DEVICE_MODE_DVBT_BDA:
Mauro Carvalho Chehab9bd58e72012-03-01 07:25:39 -03001150 client->frontend.ops.delsys[0] = SYS_DVBT;
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001151 break;
1152 case DEVICE_MODE_ISDBT:
1153 case DEVICE_MODE_ISDBT_BDA:
Mauro Carvalho Chehab9bd58e72012-03-01 07:25:39 -03001154 client->frontend.ops.delsys[0] = SYS_ISDBT;
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -03001155 break;
1156 }
1157
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001158 rc = dvb_register_frontend(&client->adapter, &client->frontend);
Michael Krufky82237412008-06-15 15:14:13 -03001159 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001160 sms_err("frontend registration failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001161 goto frontend_error;
1162 }
1163
Michael Krufkyf17407a2008-06-14 00:43:26 -03001164 params.initial_id = 1;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001165 params.data_type = MSG_SMS_DVBT_BDA_DATA;
1166 params.onresponse_handler = smsdvb_onresponse;
1167 params.onremove_handler = smsdvb_onremove;
1168 params.context = client;
1169
1170 rc = smscore_register_client(coredev, &params, &client->smsclient);
Michael Krufky82237412008-06-15 15:14:13 -03001171 if (rc < 0) {
Michael Krufkyeb250942008-06-19 22:07:23 -03001172 sms_err("smscore_register_client() failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001173 goto client_error;
1174 }
1175
1176 client->coredev = coredev;
1177
1178 init_completion(&client->tune_done);
Mauro Carvalho Chehab76e41a62013-03-07 16:32:33 -03001179 init_completion(&client->stats_done);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001180
1181 kmutex_lock(&g_smsdvb_clientslock);
1182
1183 list_add(&client->entry, &g_smsdvb_clients);
1184
1185 kmutex_unlock(&g_smsdvb_clientslock);
1186
Uri Shkolnik793786d2009-05-12 12:28:46 -03001187 client->event_fe_state = -1;
1188 client->event_unc_state = -1;
1189 sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001190
Uri Shkolnik793786d2009-05-12 12:28:46 -03001191 sms_info("success");
Michael Krufky250fa672008-11-16 22:45:42 -03001192 sms_board_setup(coredev);
1193
Michael Krufky2e5c1ec82008-05-19 18:56:13 -03001194 return 0;
1195
1196client_error:
1197 dvb_unregister_frontend(&client->frontend);
1198
1199frontend_error:
1200 dvb_dmxdev_release(&client->dmxdev);
1201
1202dmxdev_error:
1203 dvb_dmx_release(&client->demux);
1204
1205dvbdmx_error:
1206 dvb_unregister_adapter(&client->adapter);
1207
1208adapter_error:
1209 kfree(client);
1210 return rc;
1211}
1212
Márton Németh2184dda2009-12-11 20:05:10 -03001213static int __init smsdvb_module_init(void)
Steven Totheae55662008-05-22 18:04:36 -03001214{
1215 int rc;
1216
1217 INIT_LIST_HEAD(&g_smsdvb_clients);
1218 kmutex_init(&g_smsdvb_clientslock);
1219
1220 rc = smscore_register_hotplug(smsdvb_hotplug);
1221
Michael Krufkya0c0abc2008-06-19 20:35:21 -03001222 sms_debug("");
Steven Totheae55662008-05-22 18:04:36 -03001223
1224 return rc;
1225}
1226
Márton Németh2184dda2009-12-11 20:05:10 -03001227static void __exit smsdvb_module_exit(void)
Steven Totheae55662008-05-22 18:04:36 -03001228{
1229 smscore_unregister_hotplug(smsdvb_hotplug);
1230
1231 kmutex_lock(&g_smsdvb_clientslock);
1232
1233 while (!list_empty(&g_smsdvb_clients))
Michael Krufky82237412008-06-15 15:14:13 -03001234 smsdvb_unregister_client(
Michael Krufky18245e12008-06-15 17:52:24 -03001235 (struct smsdvb_client_t *) g_smsdvb_clients.next);
Steven Totheae55662008-05-22 18:04:36 -03001236
1237 kmutex_unlock(&g_smsdvb_clientslock);
Steven Totheae55662008-05-22 18:04:36 -03001238}
Uri Shkolnike0f14c22008-08-31 00:44:04 -03001239
1240module_init(smsdvb_module_init);
1241module_exit(smsdvb_module_exit);
1242
1243MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
Uri Shkolnik843d0602009-05-12 13:13:13 -03001244MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
Uri Shkolnike0f14c22008-08-31 00:44:04 -03001245MODULE_LICENSE("GPL");