blob: 654685c9303e58e8eff7edd15c50aae0c6daeaec [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 Krufky62c7167d2008-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 Krufky62c7167d2008-08-31 17:15:47 -030049
Uri Shkolnik793786d2009-05-12 12:28:46 -030050 struct completion tune_done;
Michael Krufky62c7167d2008-08-31 17:15:47 -030051
52 /* todo: save freq/band instead whole struct */
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -030053 struct dtv_frontend_properties fe_params;
Uri Shkolnik793786d2009-05-12 12:28:46 -030054
55 struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
56 int event_fe_state;
57 int event_unc_state;
Michael Krufky62c7167d2008-08-31 17:15:47 -030058};
59
Adrian Bunkc5e0bd12008-07-21 23:17:36 -030060static struct list_head g_smsdvb_clients;
61static struct mutex g_smsdvb_clientslock;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -030062
Michael Krufky0d02efe2009-02-27 02:42:16 -030063static int sms_dbg;
64module_param_named(debug, sms_dbg, int, 0644);
65MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
66
Uri Shkolnik793786d2009-05-12 12:28:46 -030067/* Events that may come from DVB v3 adapter */
68static void sms_board_dvb3_event(struct smsdvb_client_t *client,
69 enum SMS_DVB3_EVENTS event) {
Uri Shkolnik4db989f2009-05-19 12:28:02 -030070
71 struct smscore_device_t *coredev = client->coredev;
72 switch (event) {
73 case DVB3_EVENT_INIT:
74 sms_debug("DVB3_EVENT_INIT");
75 sms_board_event(coredev, BOARD_EVENT_BIND);
76 break;
77 case DVB3_EVENT_SLEEP:
78 sms_debug("DVB3_EVENT_SLEEP");
79 sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
80 break;
81 case DVB3_EVENT_HOTPLUG:
82 sms_debug("DVB3_EVENT_HOTPLUG");
83 sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
84 break;
85 case DVB3_EVENT_FE_LOCK:
86 if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
87 client->event_fe_state = DVB3_EVENT_FE_LOCK;
88 sms_debug("DVB3_EVENT_FE_LOCK");
89 sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
90 }
91 break;
92 case DVB3_EVENT_FE_UNLOCK:
93 if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
94 client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
95 sms_debug("DVB3_EVENT_FE_UNLOCK");
96 sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
97 }
98 break;
99 case DVB3_EVENT_UNC_OK:
100 if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
101 client->event_unc_state = DVB3_EVENT_UNC_OK;
102 sms_debug("DVB3_EVENT_UNC_OK");
103 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
104 }
105 break;
106 case DVB3_EVENT_UNC_ERR:
107 if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
108 client->event_unc_state = DVB3_EVENT_UNC_ERR;
109 sms_debug("DVB3_EVENT_UNC_ERR");
110 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
111 }
112 break;
113
114 default:
115 sms_err("Unknown dvb3 api event");
116 break;
117 }
Uri Shkolnik793786d2009-05-12 12:28:46 -0300118}
119
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300120
121static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
122 struct SMSHOSTLIB_STATISTICS_ST *p)
123{
124 if (sms_dbg & 2) {
125 printk(KERN_DEBUG "Reserved = %d", p->Reserved);
126 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
127 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
128 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
129 printk(KERN_DEBUG "SNR = %d", p->SNR);
130 printk(KERN_DEBUG "BER = %d", p->BER);
131 printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
132 printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
133 printk(KERN_DEBUG "MFER = %d", p->MFER);
134 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
135 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
136 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
137 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
138 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
139 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
140 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
141 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
142 printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
143 printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
144 printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
145 printk(KERN_DEBUG "Constellation = %d", p->Constellation);
146 printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
147 printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
148 printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
149 printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
150 printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
151 printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
152 printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
153 printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
154 printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
155 printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
156 printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
157 printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
158 printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
159 printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
160 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
161 printk(KERN_DEBUG "PreBER = %d", p->PreBER);
162 printk(KERN_DEBUG "CellId = %d", p->CellId);
163 printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
164 printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
165 printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300166 }
167
168 pReceptionData->IsDemodLocked = p->IsDemodLocked;
169
170 pReceptionData->SNR = p->SNR;
171 pReceptionData->BER = p->BER;
172 pReceptionData->BERErrorCount = p->BERErrorCount;
173 pReceptionData->InBandPwr = p->InBandPwr;
174 pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
175};
176
177
178static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
179 struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
180{
181 int i;
182
183 if (sms_dbg & 2) {
184 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
185 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
186 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
187 printk(KERN_DEBUG "SNR = %d", p->SNR);
188 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
189 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
190 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
191 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
192 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
193 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
194 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
195 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
196 printk(KERN_DEBUG "SystemType = %d", p->SystemType);
197 printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
198 printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
199 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
200
201 for (i = 0; i < 3; i++) {
202 printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
203 printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
204 printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
205 printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
206 printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
207 printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
208 printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
209 printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
210 printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
211 printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
212 printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
213 printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
214 }
215 }
216
217 pReceptionData->IsDemodLocked = p->IsDemodLocked;
218
219 pReceptionData->SNR = p->SNR;
220 pReceptionData->InBandPwr = p->InBandPwr;
221
222 pReceptionData->ErrorTSPackets = 0;
223 pReceptionData->BER = 0;
224 pReceptionData->BERErrorCount = 0;
225 for (i = 0; i < 3; i++) {
226 pReceptionData->BER += p->LayerInfo[i].BER;
227 pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount;
228 pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets;
229 }
230}
231
Michael Krufky0c071f32008-06-21 02:44:02 -0300232static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300233{
Michael Krufky18245e12008-06-15 17:52:24 -0300234 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300235 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
236 + cb->offset);
237 u32 *pMsgData = (u32 *) phdr + 1;
238 /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
239 bool is_status_update = false;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300240
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300241 smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr);
242
Michael Krufkyfa830e82008-06-15 15:52:43 -0300243 switch (phdr->msgType) {
Michael Krufky82237412008-06-15 15:14:13 -0300244 case MSG_SMS_DVBT_BDA_DATA:
245 dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
Michael Krufky18245e12008-06-15 17:52:24 -0300246 cb->size - sizeof(struct SmsMsgHdr_ST));
Michael Krufky82237412008-06-15 15:14:13 -0300247 break;
248
249 case MSG_SMS_RF_TUNE_RES:
Michael Krufky6b26fce2009-12-22 21:08:49 -0300250 case MSG_SMS_ISDBT_TUNE_RES:
Michael Krufky82237412008-06-15 15:14:13 -0300251 complete(&client->tune_done);
252 break;
253
Uri Shkolnik793786d2009-05-12 12:28:46 -0300254 case MSG_SMS_SIGNAL_DETECTED_IND:
255 sms_info("MSG_SMS_SIGNAL_DETECTED_IND");
256 client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
257 is_status_update = true;
258 break;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300259
Uri Shkolnik793786d2009-05-12 12:28:46 -0300260 case MSG_SMS_NO_SIGNAL_IND:
261 sms_info("MSG_SMS_NO_SIGNAL_IND");
262 client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
263 is_status_update = true;
264 break;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300265
Uri Shkolnik793786d2009-05-12 12:28:46 -0300266 case MSG_SMS_TRANSMISSION_IND: {
267 sms_info("MSG_SMS_TRANSMISSION_IND");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300268
Uri Shkolnik793786d2009-05-12 12:28:46 -0300269 pMsgData++;
270 memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
271 sizeof(struct TRANSMISSION_STATISTICS_S));
272
273 /* Mo need to correct guard interval
274 * (as opposed to old statistics message).
275 */
276 CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
277 CORRECT_STAT_TRANSMISSON_MODE(
278 client->sms_stat_dvb.TransmissionData);
279 is_status_update = true;
280 break;
281 }
282 case MSG_SMS_HO_PER_SLICES_IND: {
283 struct RECEPTION_STATISTICS_S *pReceptionData =
284 &client->sms_stat_dvb.ReceptionData;
285 struct SRVM_SIGNAL_STATUS_S SignalStatusData;
286
287 /*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/
288 pMsgData++;
289 SignalStatusData.result = pMsgData[0];
290 SignalStatusData.snr = pMsgData[1];
291 SignalStatusData.inBandPower = (s32) pMsgData[2];
292 SignalStatusData.tsPackets = pMsgData[3];
293 SignalStatusData.etsPackets = pMsgData[4];
294 SignalStatusData.constellation = pMsgData[5];
295 SignalStatusData.hpCode = pMsgData[6];
296 SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
297 SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
298 SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
299 SignalStatusData.reason = pMsgData[10];
300 SignalStatusData.requestId = pMsgData[11];
301 pReceptionData->IsRfLocked = pMsgData[16];
302 pReceptionData->IsDemodLocked = pMsgData[17];
303 pReceptionData->ModemState = pMsgData[12];
304 pReceptionData->SNR = pMsgData[1];
305 pReceptionData->BER = pMsgData[13];
306 pReceptionData->RSSI = pMsgData[14];
307 CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
308
309 pReceptionData->InBandPwr = (s32) pMsgData[2];
310 pReceptionData->CarrierOffset = (s32) pMsgData[15];
311 pReceptionData->TotalTSPackets = pMsgData[3];
312 pReceptionData->ErrorTSPackets = pMsgData[4];
313
314 /* TS PER */
315 if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
316 > 0) {
317 pReceptionData->TS_PER = (SignalStatusData.etsPackets
318 * 100) / (SignalStatusData.tsPackets
319 + SignalStatusData.etsPackets);
Michael Krufky82237412008-06-15 15:14:13 -0300320 } else {
Uri Shkolnik793786d2009-05-12 12:28:46 -0300321 pReceptionData->TS_PER = 0;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300322 }
Michael Krufky82237412008-06-15 15:14:13 -0300323
Uri Shkolnik793786d2009-05-12 12:28:46 -0300324 pReceptionData->BERBitCount = pMsgData[18];
325 pReceptionData->BERErrorCount = pMsgData[19];
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300326
Uri Shkolnik793786d2009-05-12 12:28:46 -0300327 pReceptionData->MRC_SNR = pMsgData[20];
328 pReceptionData->MRC_InBandPwr = pMsgData[21];
329 pReceptionData->MRC_RSSI = pMsgData[22];
330
331 is_status_update = true;
332 break;
333 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300334 case MSG_SMS_GET_STATISTICS_RES: {
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300335 union {
336 struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
337 struct SmsMsgStatisticsInfo_ST dvb;
338 } *p = (void *) (phdr + 1);
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300339 struct RECEPTION_STATISTICS_S *pReceptionData =
340 &client->sms_stat_dvb.ReceptionData;
341
342 sms_info("MSG_SMS_GET_STATISTICS_RES");
343
344 is_status_update = true;
Mauro Carvalho Chehab5eb23972009-12-25 11:29:42 -0300345
346 switch (smscore_get_device_mode(client->coredev)) {
347 case DEVICE_MODE_ISDBT:
348 case DEVICE_MODE_ISDBT_BDA:
349 smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
350 break;
351 default:
352 smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
353 }
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300354 if (!pReceptionData->IsDemodLocked) {
355 pReceptionData->SNR = 0;
356 pReceptionData->BER = 0;
357 pReceptionData->BERErrorCount = 0;
358 pReceptionData->InBandPwr = 0;
359 pReceptionData->ErrorTSPackets = 0;
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300360 }
361
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300362 complete(&client->tune_done);
363 break;
364 }
365 default:
366 sms_info("Unhandled message %d", phdr->msgType);
367
Uri Shkolnik793786d2009-05-12 12:28:46 -0300368 }
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300369 smscore_putbuffer(client->coredev, cb);
370
Uri Shkolnik793786d2009-05-12 12:28:46 -0300371 if (is_status_update) {
372 if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
373 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
374 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
375 sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
376 if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
377 == 0)
378 sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
379 else
380 sms_board_dvb3_event(client,
381 DVB3_EVENT_UNC_ERR);
382
383 } else {
Mauro Carvalho Chehabb4622c12009-12-25 18:04:17 -0300384 if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
385 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
386 else
387 client->fe_status = 0;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300388 sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
389 }
390 }
391
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300392 return 0;
393}
394
Michael Krufky0c071f32008-06-21 02:44:02 -0300395static void smsdvb_unregister_client(struct smsdvb_client_t *client)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300396{
Michael Krufkyfa830e82008-06-15 15:52:43 -0300397 /* must be called under clientslock */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300398
399 list_del(&client->entry);
400
401 smscore_unregister_client(client->smsclient);
402 dvb_unregister_frontend(&client->frontend);
403 dvb_dmxdev_release(&client->dmxdev);
404 dvb_dmx_release(&client->demux);
405 dvb_unregister_adapter(&client->adapter);
406 kfree(client);
407}
408
Michael Krufky0c071f32008-06-21 02:44:02 -0300409static void smsdvb_onremove(void *context)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300410{
411 kmutex_lock(&g_smsdvb_clientslock);
412
Michael Krufky18245e12008-06-15 17:52:24 -0300413 smsdvb_unregister_client((struct smsdvb_client_t *) context);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300414
415 kmutex_unlock(&g_smsdvb_clientslock);
416}
417
418static int smsdvb_start_feed(struct dvb_demux_feed *feed)
419{
Michael Krufky18245e12008-06-15 17:52:24 -0300420 struct smsdvb_client_t *client =
421 container_of(feed->demux, struct smsdvb_client_t, demux);
422 struct SmsMsgData_ST PidMsg;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300423
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300424 sms_debug("add pid %d(%x)",
Michael Krufky068d6c02008-06-19 01:15:46 -0300425 feed->pid, feed->pid);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300426
427 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
428 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
429 PidMsg.xMsgHeader.msgFlags = 0;
430 PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ;
431 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
432 PidMsg.msgData[0] = feed->pid;
433
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300434 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
Michael Krufky82237412008-06-15 15:14:13 -0300435 return smsclient_sendrequest(client->smsclient,
436 &PidMsg, sizeof(PidMsg));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300437}
438
439static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
440{
Michael Krufky18245e12008-06-15 17:52:24 -0300441 struct smsdvb_client_t *client =
442 container_of(feed->demux, struct smsdvb_client_t, demux);
443 struct SmsMsgData_ST PidMsg;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300444
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300445 sms_debug("remove pid %d(%x)",
Michael Krufky068d6c02008-06-19 01:15:46 -0300446 feed->pid, feed->pid);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300447
448 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
449 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
450 PidMsg.xMsgHeader.msgFlags = 0;
451 PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ;
452 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
453 PidMsg.msgData[0] = feed->pid;
454
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300455 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
Michael Krufky82237412008-06-15 15:14:13 -0300456 return smsclient_sendrequest(client->smsclient,
457 &PidMsg, sizeof(PidMsg));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300458}
459
Michael Krufky18245e12008-06-15 17:52:24 -0300460static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
Michael Krufkya83ccdd2008-05-06 03:11:51 -0300461 void *buffer, size_t size,
462 struct completion *completion)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300463{
Uri Shkolnikba79bb22009-05-12 11:37:09 -0300464 int rc;
465
466 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer);
467 rc = smsclient_sendrequest(client->smsclient, buffer, size);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300468 if (rc < 0)
469 return rc;
470
Michael Krufky82237412008-06-15 15:14:13 -0300471 return wait_for_completion_timeout(completion,
472 msecs_to_jiffies(2000)) ?
473 0 : -ETIME;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300474}
475
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300476static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
477{
478 int rc;
479 struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
480 DVBT_BDA_CONTROL_MSG_ID,
481 HIF_TASK,
482 sizeof(struct SmsMsgHdr_ST), 0 };
483
484 rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
485 &client->tune_done);
486
487 return rc;
488}
489
Michael Krufky3746b612009-07-12 23:30:14 -0300490static inline int led_feedback(struct smsdvb_client_t *client)
491{
492 if (client->fe_status & FE_HAS_LOCK)
493 return sms_board_led_feedback(client->coredev,
494 (client->sms_stat_dvb.ReceptionData.BER
495 == 0) ? SMS_LED_HI : SMS_LED_LO);
496 else
497 return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
498}
499
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300500static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
501{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300502 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300503 struct smsdvb_client_t *client;
504 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300505
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300506 rc = smsdvb_send_statistics_request(client);
507
Uri Shkolnik793786d2009-05-12 12:28:46 -0300508 *stat = client->fe_status;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300509
Michael Krufky3746b612009-07-12 23:30:14 -0300510 led_feedback(client);
511
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300512 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300513}
514
515static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
516{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300517 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300518 struct smsdvb_client_t *client;
519 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300520
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300521 rc = smsdvb_send_statistics_request(client);
522
Uri Shkolnik793786d2009-05-12 12:28:46 -0300523 *ber = client->sms_stat_dvb.ReceptionData.BER;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300524
Michael Krufky3746b612009-07-12 23:30:14 -0300525 led_feedback(client);
526
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300527 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300528}
529
530static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
531{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300532 int rc;
533
Uri Shkolnik793786d2009-05-12 12:28:46 -0300534 struct smsdvb_client_t *client;
535 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300536
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300537 rc = smsdvb_send_statistics_request(client);
538
Uri Shkolnik793786d2009-05-12 12:28:46 -0300539 if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
540 *strength = 0;
541 else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
542 *strength = 100;
543 else
544 *strength =
545 (client->sms_stat_dvb.ReceptionData.InBandPwr
546 + 95) * 3 / 2;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300547
Michael Krufky3746b612009-07-12 23:30:14 -0300548 led_feedback(client);
549
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300550 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300551}
552
553static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
554{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300555 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300556 struct smsdvb_client_t *client;
557 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300558
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300559 rc = smsdvb_send_statistics_request(client);
560
Uri Shkolnik793786d2009-05-12 12:28:46 -0300561 *snr = client->sms_stat_dvb.ReceptionData.SNR;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300562
Michael Krufky3746b612009-07-12 23:30:14 -0300563 led_feedback(client);
564
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300565 return rc;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300566}
567
Michael Krufky851a9092008-11-22 14:56:37 -0300568static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
569{
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300570 int rc;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300571 struct smsdvb_client_t *client;
572 client = container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky851a9092008-11-22 14:56:37 -0300573
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300574 rc = smsdvb_send_statistics_request(client);
575
Uri Shkolnik793786d2009-05-12 12:28:46 -0300576 *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
Michael Krufky851a9092008-11-22 14:56:37 -0300577
Michael Krufky3746b612009-07-12 23:30:14 -0300578 led_feedback(client);
579
Mauro Carvalho Chehab67ae1d22009-12-23 10:07:16 -0300580 return rc;
Michael Krufky851a9092008-11-22 14:56:37 -0300581}
582
Michael Krufky82237412008-06-15 15:14:13 -0300583static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
584 struct dvb_frontend_tune_settings *tune)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300585{
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300586 sms_debug("");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300587
588 tune->min_delay_ms = 400;
589 tune->step_size = 250000;
590 tune->max_drift = 0;
591 return 0;
592}
593
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300594static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300595{
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300596 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Michael Krufky18245e12008-06-15 17:52:24 -0300597 struct smsdvb_client_t *client =
598 container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300599
Michael Krufky18245e12008-06-15 17:52:24 -0300600 struct {
601 struct SmsMsgHdr_ST Msg;
Michael Krufky82237412008-06-15 15:14:13 -0300602 u32 Data[3];
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300603 } Msg;
604
Michael Krufky3746b612009-07-12 23:30:14 -0300605 int ret;
606
Uri Shkolnik793786d2009-05-12 12:28:46 -0300607 client->fe_status = FE_HAS_SIGNAL;
608 client->event_fe_state = -1;
609 client->event_unc_state = -1;
Mauro Carvalho Chehabe85c97a2009-12-25 07:17:03 -0300610 fe->dtv_property_cache.delivery_system = SYS_DVBT;
Uri Shkolnik793786d2009-05-12 12:28:46 -0300611
612 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
613 Msg.Msg.msgDstId = HIF_TASK;
614 Msg.Msg.msgFlags = 0;
615 Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300616 Msg.Msg.msgLength = sizeof(Msg);
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300617 Msg.Data[0] = c->frequency;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300618 Msg.Data[2] = 12000000;
619
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300620 sms_info("%s: freq %d band %d", __func__, c->frequency,
621 c->bandwidth_hz);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300622
Mauro Carvalho Chehab643e15a2009-12-25 07:29:06 -0300623 switch (c->bandwidth_hz / 1000000) {
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300624 case 8:
625 Msg.Data[1] = BW_8_MHZ;
626 break;
627 case 7:
628 Msg.Data[1] = BW_7_MHZ;
629 break;
630 case 6:
631 Msg.Data[1] = BW_6_MHZ;
632 break;
633 case 0:
634 return -EOPNOTSUPP;
635 default:
636 return -EINVAL;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300637 }
Michael Krufky3746b612009-07-12 23:30:14 -0300638 /* Disable LNA, if any. An error is returned if no LNA is present */
639 ret = sms_board_lna_control(client->coredev, 0);
640 if (ret == 0) {
641 fe_status_t status;
642
643 /* tune with LNA off at first */
644 ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
645 &client->tune_done);
646
647 smsdvb_read_status(fe, &status);
648
649 if (status & FE_HAS_LOCK)
650 return ret;
651
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300652 /* previous tune didn't lock - enable LNA and tune again */
Michael Krufky3746b612009-07-12 23:30:14 -0300653 sms_board_lna_control(client->coredev, 1);
654 }
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300655
Michael Krufky82237412008-06-15 15:14:13 -0300656 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
657 &client->tune_done);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300658}
659
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300660static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
Michael Krufky6b26fce2009-12-22 21:08:49 -0300661{
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300662 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300663 struct smsdvb_client_t *client =
664 container_of(fe, struct smsdvb_client_t, frontend);
665
666 struct {
667 struct SmsMsgHdr_ST Msg;
668 u32 Data[4];
669 } Msg;
670
Mauro Carvalho Chehabe85c97a2009-12-25 07:17:03 -0300671 fe->dtv_property_cache.delivery_system = SYS_ISDBT;
672
Michael Krufky6b26fce2009-12-22 21:08:49 -0300673 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
674 Msg.Msg.msgDstId = HIF_TASK;
675 Msg.Msg.msgFlags = 0;
676 Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ;
677 Msg.Msg.msgLength = sizeof(Msg);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300678
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300679 if (c->isdbt_sb_segment_idx == -1)
680 c->isdbt_sb_segment_idx = 0;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300681
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300682 switch (c->isdbt_sb_segment_count) {
683 case 3:
Michael Krufky6b26fce2009-12-22 21:08:49 -0300684 Msg.Data[1] = BW_ISDBT_3SEG;
685 break;
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300686 case 1:
Michael Krufky6b26fce2009-12-22 21:08:49 -0300687 Msg.Data[1] = BW_ISDBT_1SEG;
688 break;
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300689 case 0: /* AUTO */
Mauro Carvalho Chehab643e15a2009-12-25 07:29:06 -0300690 switch (c->bandwidth_hz / 1000000) {
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300691 case 8:
692 case 7:
693 c->isdbt_sb_segment_count = 3;
694 Msg.Data[1] = BW_ISDBT_3SEG;
695 break;
696 case 6:
697 c->isdbt_sb_segment_count = 1;
698 Msg.Data[1] = BW_ISDBT_1SEG;
699 break;
700 default: /* Assumes 6 MHZ bw */
701 c->isdbt_sb_segment_count = 1;
702 c->bandwidth_hz = 6000;
703 Msg.Data[1] = BW_ISDBT_1SEG;
704 break;
705 }
706 break;
Michael Krufky6b26fce2009-12-22 21:08:49 -0300707 default:
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300708 sms_info("Segment count %d not supported", c->isdbt_sb_segment_count);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300709 return -EINVAL;
710 }
711
Mauro Carvalho Chehabcf4fab72009-12-23 11:28:46 -0300712 Msg.Data[0] = c->frequency;
713 Msg.Data[2] = 12000000;
714 Msg.Data[3] = c->isdbt_sb_segment_idx;
715
716 sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
717 c->frequency, c->isdbt_sb_segment_count,
718 c->isdbt_sb_segment_idx);
719
Michael Krufky6b26fce2009-12-22 21:08:49 -0300720 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
721 &client->tune_done);
722}
723
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300724static int smsdvb_set_frontend(struct dvb_frontend *fe)
Michael Krufky6b26fce2009-12-22 21:08:49 -0300725{
726 struct smsdvb_client_t *client =
727 container_of(fe, struct smsdvb_client_t, frontend);
728 struct smscore_device_t *coredev = client->coredev;
729
730 switch (smscore_get_device_mode(coredev)) {
731 case DEVICE_MODE_DVBT:
732 case DEVICE_MODE_DVBT_BDA:
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300733 return smsdvb_dvbt_set_frontend(fe);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300734 case DEVICE_MODE_ISDBT:
735 case DEVICE_MODE_ISDBT_BDA:
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300736 return smsdvb_isdbt_set_frontend(fe);
Michael Krufky6b26fce2009-12-22 21:08:49 -0300737 default:
738 return -EINVAL;
739 }
740}
741
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -0300742static int smsdvb_get_frontend(struct dvb_frontend *fe)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300743{
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -0300744 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
Michael Krufky18245e12008-06-15 17:52:24 -0300745 struct smsdvb_client_t *client =
746 container_of(fe, struct smsdvb_client_t, frontend);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300747
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300748 sms_debug("");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300749
Michael Krufkyfa830e82008-06-15 15:52:43 -0300750 /* todo: */
Michael Krufky82237412008-06-15 15:14:13 -0300751 memcpy(fep, &client->fe_params,
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300752 sizeof(struct dtv_frontend_properties));
Michael Krufky7a6fbed2008-11-22 14:26:37 -0300753
754 return 0;
755}
756
757static int smsdvb_init(struct dvb_frontend *fe)
758{
759 struct smsdvb_client_t *client =
760 container_of(fe, struct smsdvb_client_t, frontend);
761
Michael Krufky3746b612009-07-12 23:30:14 -0300762 sms_board_power(client->coredev, 1);
763
Uri Shkolnik793786d2009-05-12 12:28:46 -0300764 sms_board_dvb3_event(client, DVB3_EVENT_INIT);
Michael Krufky7a6fbed2008-11-22 14:26:37 -0300765 return 0;
766}
767
768static int smsdvb_sleep(struct dvb_frontend *fe)
769{
770 struct smsdvb_client_t *client =
771 container_of(fe, struct smsdvb_client_t, frontend);
772
Michael Krufky3746b612009-07-12 23:30:14 -0300773 sms_board_led_feedback(client->coredev, SMS_LED_OFF);
774 sms_board_power(client->coredev, 0);
775
Uri Shkolnik793786d2009-05-12 12:28:46 -0300776 sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
Michael Krufky7a6fbed2008-11-22 14:26:37 -0300777
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300778 return 0;
779}
780
781static void smsdvb_release(struct dvb_frontend *fe)
782{
Michael Krufkyfa830e82008-06-15 15:52:43 -0300783 /* do nothing */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300784}
785
786static struct dvb_frontend_ops smsdvb_fe_ops = {
787 .info = {
Uri Shkolnike0f14c22008-08-31 00:44:04 -0300788 .name = "Siano Mobile Digital MDTV Receiver",
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300789 .frequency_min = 44250000,
790 .frequency_max = 867250000,
791 .frequency_stepsize = 250000,
792 .caps = FE_CAN_INVERSION_AUTO |
Michael Krufky82237412008-06-15 15:14:13 -0300793 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
794 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
795 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
796 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
797 FE_CAN_GUARD_INTERVAL_AUTO |
798 FE_CAN_RECOVER |
799 FE_CAN_HIERARCHY_AUTO,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300800 },
801
802 .release = smsdvb_release,
803
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300804 .set_frontend = smsdvb_set_frontend,
805 .get_frontend = smsdvb_get_frontend,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300806 .get_tune_settings = smsdvb_get_tune_settings,
807
808 .read_status = smsdvb_read_status,
809 .read_ber = smsdvb_read_ber,
810 .read_signal_strength = smsdvb_read_signal_strength,
811 .read_snr = smsdvb_read_snr,
Michael Krufky851a9092008-11-22 14:56:37 -0300812 .read_ucblocks = smsdvb_read_ucblocks,
Michael Krufky7a6fbed2008-11-22 14:26:37 -0300813
814 .init = smsdvb_init,
815 .sleep = smsdvb_sleep,
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300816};
817
Michael Krufky0c071f32008-06-21 02:44:02 -0300818static int smsdvb_hotplug(struct smscore_device_t *coredev,
819 struct device *device, int arrival)
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300820{
Michael Krufky18245e12008-06-15 17:52:24 -0300821 struct smsclient_params_t params;
822 struct smsdvb_client_t *client;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300823 int rc;
824
Michael Krufkyfa830e82008-06-15 15:52:43 -0300825 /* device removal handled by onremove callback */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300826 if (!arrival)
827 return 0;
Michael Krufky18245e12008-06-15 17:52:24 -0300828 client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
Michael Krufky82237412008-06-15 15:14:13 -0300829 if (!client) {
Michael Krufkyeb250942008-06-19 22:07:23 -0300830 sms_err("kmalloc() failed");
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300831 return -ENOMEM;
832 }
833
Michael Krufkyfa830e82008-06-15 15:52:43 -0300834 /* register dvb adapter */
Michael Krufky1c11d542008-06-18 22:09:55 -0300835 rc = dvb_register_adapter(&client->adapter,
836 sms_get_board(
837 smscore_get_board_id(coredev))->name,
Michael Krufky82237412008-06-15 15:14:13 -0300838 THIS_MODULE, device, adapter_nr);
839 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300840 sms_err("dvb_register_adapter() failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300841 goto adapter_error;
842 }
843
Michael Krufkyfa830e82008-06-15 15:52:43 -0300844 /* init dvb demux */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300845 client->demux.dmx.capabilities = DMX_TS_FILTERING;
Michael Krufkyfa830e82008-06-15 15:52:43 -0300846 client->demux.filternum = 32; /* todo: nova ??? */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300847 client->demux.feednum = 32;
848 client->demux.start_feed = smsdvb_start_feed;
849 client->demux.stop_feed = smsdvb_stop_feed;
850
851 rc = dvb_dmx_init(&client->demux);
Michael Krufky82237412008-06-15 15:14:13 -0300852 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300853 sms_err("dvb_dmx_init failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300854 goto dvbdmx_error;
855 }
856
Michael Krufkyfa830e82008-06-15 15:52:43 -0300857 /* init dmxdev */
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300858 client->dmxdev.filternum = 32;
859 client->dmxdev.demux = &client->demux.dmx;
860 client->dmxdev.capabilities = 0;
861
862 rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
Michael Krufky82237412008-06-15 15:14:13 -0300863 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300864 sms_err("dvb_dmxdev_init failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300865 goto dmxdev_error;
866 }
867
Michael Krufkyfa830e82008-06-15 15:52:43 -0300868 /* init and register frontend */
Michael Krufky82237412008-06-15 15:14:13 -0300869 memcpy(&client->frontend.ops, &smsdvb_fe_ops,
870 sizeof(struct dvb_frontend_ops));
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300871
Mauro Carvalho Chehab15115c12011-12-26 16:31:29 -0300872 switch (smscore_get_device_mode(coredev)) {
873 case DEVICE_MODE_DVBT:
874 case DEVICE_MODE_DVBT_BDA:
875 smsdvb_fe_ops.delsys[0] = SYS_DVBT;
876 break;
877 case DEVICE_MODE_ISDBT:
878 case DEVICE_MODE_ISDBT_BDA:
879 smsdvb_fe_ops.delsys[0] = SYS_ISDBT;
880 break;
881 }
882
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300883 rc = dvb_register_frontend(&client->adapter, &client->frontend);
Michael Krufky82237412008-06-15 15:14:13 -0300884 if (rc < 0) {
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300885 sms_err("frontend registration failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300886 goto frontend_error;
887 }
888
Michael Krufkyf17407a2008-06-14 00:43:26 -0300889 params.initial_id = 1;
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300890 params.data_type = MSG_SMS_DVBT_BDA_DATA;
891 params.onresponse_handler = smsdvb_onresponse;
892 params.onremove_handler = smsdvb_onremove;
893 params.context = client;
894
895 rc = smscore_register_client(coredev, &params, &client->smsclient);
Michael Krufky82237412008-06-15 15:14:13 -0300896 if (rc < 0) {
Michael Krufkyeb250942008-06-19 22:07:23 -0300897 sms_err("smscore_register_client() failed %d", rc);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300898 goto client_error;
899 }
900
901 client->coredev = coredev;
902
903 init_completion(&client->tune_done);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300904
905 kmutex_lock(&g_smsdvb_clientslock);
906
907 list_add(&client->entry, &g_smsdvb_clients);
908
909 kmutex_unlock(&g_smsdvb_clientslock);
910
Uri Shkolnik793786d2009-05-12 12:28:46 -0300911 client->event_fe_state = -1;
912 client->event_unc_state = -1;
913 sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300914
Uri Shkolnik793786d2009-05-12 12:28:46 -0300915 sms_info("success");
Michael Krufky250fa672008-11-16 22:45:42 -0300916 sms_board_setup(coredev);
917
Michael Krufky2e5c1ec82008-05-19 18:56:13 -0300918 return 0;
919
920client_error:
921 dvb_unregister_frontend(&client->frontend);
922
923frontend_error:
924 dvb_dmxdev_release(&client->dmxdev);
925
926dmxdev_error:
927 dvb_dmx_release(&client->demux);
928
929dvbdmx_error:
930 dvb_unregister_adapter(&client->adapter);
931
932adapter_error:
933 kfree(client);
934 return rc;
935}
936
Márton Németh2184dda2009-12-11 20:05:10 -0300937static int __init smsdvb_module_init(void)
Steven Totheae55662008-05-22 18:04:36 -0300938{
939 int rc;
940
941 INIT_LIST_HEAD(&g_smsdvb_clients);
942 kmutex_init(&g_smsdvb_clientslock);
943
944 rc = smscore_register_hotplug(smsdvb_hotplug);
945
Michael Krufkya0c0abc2008-06-19 20:35:21 -0300946 sms_debug("");
Steven Totheae55662008-05-22 18:04:36 -0300947
948 return rc;
949}
950
Márton Németh2184dda2009-12-11 20:05:10 -0300951static void __exit smsdvb_module_exit(void)
Steven Totheae55662008-05-22 18:04:36 -0300952{
953 smscore_unregister_hotplug(smsdvb_hotplug);
954
955 kmutex_lock(&g_smsdvb_clientslock);
956
957 while (!list_empty(&g_smsdvb_clients))
Michael Krufky82237412008-06-15 15:14:13 -0300958 smsdvb_unregister_client(
Michael Krufky18245e12008-06-15 17:52:24 -0300959 (struct smsdvb_client_t *) g_smsdvb_clients.next);
Steven Totheae55662008-05-22 18:04:36 -0300960
961 kmutex_unlock(&g_smsdvb_clientslock);
Steven Totheae55662008-05-22 18:04:36 -0300962}
Uri Shkolnike0f14c22008-08-31 00:44:04 -0300963
964module_init(smsdvb_module_init);
965module_exit(smsdvb_module_exit);
966
967MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
Uri Shkolnik843d0602009-05-12 13:13:13 -0300968MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
Uri Shkolnike0f14c22008-08-31 00:44:04 -0300969MODULE_LICENSE("GPL");