[media] siano: update message macros
[deliverable/linux.git] / drivers / media / common / siano / smsdvb.c
CommitLineData
e5275793
US
1/****************************************************************
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****************************************************************/
8d4f9d0e 21
2e5c1ec8 22#include <linux/module.h>
5a0e3ad6 23#include <linux/slab.h>
2e5c1ec8
MK
24#include <linux/init.h>
25
c9679e3b
US
26#include "dmxdev.h"
27#include "dvbdev.h"
28#include "dvb_demux.h"
29#include "dvb_frontend.h"
30
2e5c1ec8 31#include "smscoreapi.h"
ba79bb2c 32#include "smsendian.h"
1c11d546 33#include "sms-cards.h"
2e5c1ec8 34
9c59f968
MK
35DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
36
62c7167d
MK
37struct 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;
62c7167d 49
793786d1 50 struct completion tune_done;
62c7167d 51
793786d1
US
52 struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
53 int event_fe_state;
54 int event_unc_state;
62c7167d
MK
55};
56
c5e0bd1a
AB
57static struct list_head g_smsdvb_clients;
58static struct mutex g_smsdvb_clientslock;
2e5c1ec8 59
0d02efe4
MK
60static 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
793786d1
US
64/* Events that may come from DVB v3 adapter */
65static void sms_board_dvb3_event(struct smsdvb_client_t *client,
66 enum SMS_DVB3_EVENTS event) {
4db989f7
US
67
68 struct smscore_device_t *coredev = client->coredev;
69 switch (event) {
70 case DVB3_EVENT_INIT:
71 sms_debug("DVB3_EVENT_INIT");
72 sms_board_event(coredev, BOARD_EVENT_BIND);
73 break;
74 case DVB3_EVENT_SLEEP:
75 sms_debug("DVB3_EVENT_SLEEP");
76 sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
77 break;
78 case DVB3_EVENT_HOTPLUG:
79 sms_debug("DVB3_EVENT_HOTPLUG");
80 sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
81 break;
82 case DVB3_EVENT_FE_LOCK:
83 if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
84 client->event_fe_state = DVB3_EVENT_FE_LOCK;
85 sms_debug("DVB3_EVENT_FE_LOCK");
86 sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
87 }
88 break;
89 case DVB3_EVENT_FE_UNLOCK:
90 if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
91 client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
92 sms_debug("DVB3_EVENT_FE_UNLOCK");
93 sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
94 }
95 break;
96 case DVB3_EVENT_UNC_OK:
97 if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
98 client->event_unc_state = DVB3_EVENT_UNC_OK;
99 sms_debug("DVB3_EVENT_UNC_OK");
100 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
101 }
102 break;
103 case DVB3_EVENT_UNC_ERR:
104 if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
105 client->event_unc_state = DVB3_EVENT_UNC_ERR;
106 sms_debug("DVB3_EVENT_UNC_ERR");
107 sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
108 }
109 break;
110
111 default:
112 sms_err("Unknown dvb3 api event");
113 break;
114 }
793786d1
US
115}
116
5eb23975
MCC
117
118static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
119 struct SMSHOSTLIB_STATISTICS_ST *p)
120{
121 if (sms_dbg & 2) {
122 printk(KERN_DEBUG "Reserved = %d", p->Reserved);
123 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
124 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
125 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
126 printk(KERN_DEBUG "SNR = %d", p->SNR);
127 printk(KERN_DEBUG "BER = %d", p->BER);
128 printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
129 printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
130 printk(KERN_DEBUG "MFER = %d", p->MFER);
131 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
132 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
133 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
134 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
135 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
136 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
137 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
138 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
139 printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
140 printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
141 printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
142 printk(KERN_DEBUG "Constellation = %d", p->Constellation);
143 printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
144 printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
145 printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
146 printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
147 printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
148 printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
149 printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
150 printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
151 printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
152 printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
153 printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
154 printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
155 printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
156 printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
157 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
158 printk(KERN_DEBUG "PreBER = %d", p->PreBER);
159 printk(KERN_DEBUG "CellId = %d", p->CellId);
160 printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
161 printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
162 printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
5eb23975
MCC
163 }
164
165 pReceptionData->IsDemodLocked = p->IsDemodLocked;
166
167 pReceptionData->SNR = p->SNR;
168 pReceptionData->BER = p->BER;
169 pReceptionData->BERErrorCount = p->BERErrorCount;
170 pReceptionData->InBandPwr = p->InBandPwr;
171 pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
172};
173
174
175static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
176 struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
177{
178 int i;
179
180 if (sms_dbg & 2) {
181 printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
182 printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
183 printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
184 printk(KERN_DEBUG "SNR = %d", p->SNR);
185 printk(KERN_DEBUG "RSSI = %d", p->RSSI);
186 printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
187 printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
188 printk(KERN_DEBUG "Frequency = %d", p->Frequency);
189 printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
190 printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
191 printk(KERN_DEBUG "ModemState = %d", p->ModemState);
192 printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
193 printk(KERN_DEBUG "SystemType = %d", p->SystemType);
194 printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
195 printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
196 printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
197
198 for (i = 0; i < 3; i++) {
199 printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
200 printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
201 printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
202 printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
203 printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
204 printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
205 printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
206 printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
207 printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
208 printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
209 printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
210 printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
211 }
212 }
213
214 pReceptionData->IsDemodLocked = p->IsDemodLocked;
215
216 pReceptionData->SNR = p->SNR;
217 pReceptionData->InBandPwr = p->InBandPwr;
218
219 pReceptionData->ErrorTSPackets = 0;
220 pReceptionData->BER = 0;
221 pReceptionData->BERErrorCount = 0;
222 for (i = 0; i < 3; i++) {
223 pReceptionData->BER += p->LayerInfo[i].BER;
224 pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount;
225 pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets;
226 }
227}
228
0c071f37 229static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
2e5c1ec8 230{
18245e18 231 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
793786d1
US
232 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
233 + cb->offset);
234 u32 *pMsgData = (u32 *) phdr + 1;
235 /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
236 bool is_status_update = false;
2e5c1ec8 237
ba79bb2c
US
238 smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr);
239
fa830e8a 240 switch (phdr->msgType) {
82237416
MK
241 case MSG_SMS_DVBT_BDA_DATA:
242 dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
18245e18 243 cb->size - sizeof(struct SmsMsgHdr_ST));
82237416
MK
244 break;
245
246 case MSG_SMS_RF_TUNE_RES:
6b26fcea 247 case MSG_SMS_ISDBT_TUNE_RES:
82237416
MK
248 complete(&client->tune_done);
249 break;
2e5c1ec8 250
793786d1
US
251 case MSG_SMS_SIGNAL_DETECTED_IND:
252 sms_info("MSG_SMS_SIGNAL_DETECTED_IND");
253 client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
254 is_status_update = true;
255 break;
256
257 case MSG_SMS_NO_SIGNAL_IND:
258 sms_info("MSG_SMS_NO_SIGNAL_IND");
259 client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
260 is_status_update = true;
261 break;
262
263 case MSG_SMS_TRANSMISSION_IND: {
264 sms_info("MSG_SMS_TRANSMISSION_IND");
265
266 pMsgData++;
267 memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
268 sizeof(struct TRANSMISSION_STATISTICS_S));
269
270 /* Mo need to correct guard interval
271 * (as opposed to old statistics message).
272 */
273 CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
274 CORRECT_STAT_TRANSMISSON_MODE(
275 client->sms_stat_dvb.TransmissionData);
276 is_status_update = true;
277 break;
278 }
279 case MSG_SMS_HO_PER_SLICES_IND: {
280 struct RECEPTION_STATISTICS_S *pReceptionData =
281 &client->sms_stat_dvb.ReceptionData;
282 struct SRVM_SIGNAL_STATUS_S SignalStatusData;
283
284 /*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/
285 pMsgData++;
286 SignalStatusData.result = pMsgData[0];
287 SignalStatusData.snr = pMsgData[1];
288 SignalStatusData.inBandPower = (s32) pMsgData[2];
289 SignalStatusData.tsPackets = pMsgData[3];
290 SignalStatusData.etsPackets = pMsgData[4];
291 SignalStatusData.constellation = pMsgData[5];
292 SignalStatusData.hpCode = pMsgData[6];
293 SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
294 SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
295 SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
296 SignalStatusData.reason = pMsgData[10];
297 SignalStatusData.requestId = pMsgData[11];
298 pReceptionData->IsRfLocked = pMsgData[16];
299 pReceptionData->IsDemodLocked = pMsgData[17];
300 pReceptionData->ModemState = pMsgData[12];
301 pReceptionData->SNR = pMsgData[1];
302 pReceptionData->BER = pMsgData[13];
303 pReceptionData->RSSI = pMsgData[14];
304 CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
305
306 pReceptionData->InBandPwr = (s32) pMsgData[2];
307 pReceptionData->CarrierOffset = (s32) pMsgData[15];
308 pReceptionData->TotalTSPackets = pMsgData[3];
309 pReceptionData->ErrorTSPackets = pMsgData[4];
310
311 /* TS PER */
312 if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
313 > 0) {
314 pReceptionData->TS_PER = (SignalStatusData.etsPackets
315 * 100) / (SignalStatusData.tsPackets
316 + SignalStatusData.etsPackets);
82237416 317 } else {
793786d1 318 pReceptionData->TS_PER = 0;
2e5c1ec8 319 }
82237416 320
793786d1
US
321 pReceptionData->BERBitCount = pMsgData[18];
322 pReceptionData->BERErrorCount = pMsgData[19];
2e5c1ec8 323
793786d1
US
324 pReceptionData->MRC_SNR = pMsgData[20];
325 pReceptionData->MRC_InBandPwr = pMsgData[21];
326 pReceptionData->MRC_RSSI = pMsgData[22];
327
328 is_status_update = true;
329 break;
330 }
67ae1d26 331 case MSG_SMS_GET_STATISTICS_RES: {
5eb23975
MCC
332 union {
333 struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
334 struct SmsMsgStatisticsInfo_ST dvb;
335 } *p = (void *) (phdr + 1);
67ae1d26
MCC
336 struct RECEPTION_STATISTICS_S *pReceptionData =
337 &client->sms_stat_dvb.ReceptionData;
338
339 sms_info("MSG_SMS_GET_STATISTICS_RES");
340
341 is_status_update = true;
5eb23975
MCC
342
343 switch (smscore_get_device_mode(client->coredev)) {
344 case DEVICE_MODE_ISDBT:
345 case DEVICE_MODE_ISDBT_BDA:
346 smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
347 break;
348 default:
349 smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
350 }
67ae1d26
MCC
351 if (!pReceptionData->IsDemodLocked) {
352 pReceptionData->SNR = 0;
353 pReceptionData->BER = 0;
354 pReceptionData->BERErrorCount = 0;
355 pReceptionData->InBandPwr = 0;
356 pReceptionData->ErrorTSPackets = 0;
67ae1d26
MCC
357 }
358
67ae1d26
MCC
359 complete(&client->tune_done);
360 break;
361 }
362 default:
363 sms_info("Unhandled message %d", phdr->msgType);
364
793786d1 365 }
2e5c1ec8
MK
366 smscore_putbuffer(client->coredev, cb);
367
793786d1
US
368 if (is_status_update) {
369 if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
370 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
371 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
372 sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
373 if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
374 == 0)
375 sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
376 else
377 sms_board_dvb3_event(client,
378 DVB3_EVENT_UNC_ERR);
379
380 } else {
b4622c14
MCC
381 if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
382 client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
383 else
384 client->fe_status = 0;
793786d1
US
385 sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
386 }
387 }
388
2e5c1ec8
MK
389 return 0;
390}
391
0c071f37 392static void smsdvb_unregister_client(struct smsdvb_client_t *client)
2e5c1ec8 393{
fa830e8a 394 /* must be called under clientslock */
2e5c1ec8
MK
395
396 list_del(&client->entry);
397
398 smscore_unregister_client(client->smsclient);
399 dvb_unregister_frontend(&client->frontend);
400 dvb_dmxdev_release(&client->dmxdev);
401 dvb_dmx_release(&client->demux);
402 dvb_unregister_adapter(&client->adapter);
403 kfree(client);
404}
405
0c071f37 406static void smsdvb_onremove(void *context)
2e5c1ec8
MK
407{
408 kmutex_lock(&g_smsdvb_clientslock);
409
18245e18 410 smsdvb_unregister_client((struct smsdvb_client_t *) context);
2e5c1ec8
MK
411
412 kmutex_unlock(&g_smsdvb_clientslock);
413}
414
415static int smsdvb_start_feed(struct dvb_demux_feed *feed)
416{
18245e18
MK
417 struct smsdvb_client_t *client =
418 container_of(feed->demux, struct smsdvb_client_t, demux);
419 struct SmsMsgData_ST PidMsg;
2e5c1ec8 420
a0c0abcb 421 sms_debug("add pid %d(%x)",
068d6c0f 422 feed->pid, feed->pid);
2e5c1ec8
MK
423
424 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
425 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
426 PidMsg.xMsgHeader.msgFlags = 0;
427 PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ;
428 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
429 PidMsg.msgData[0] = feed->pid;
430
ba79bb2c 431 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
82237416
MK
432 return smsclient_sendrequest(client->smsclient,
433 &PidMsg, sizeof(PidMsg));
2e5c1ec8
MK
434}
435
436static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
437{
18245e18
MK
438 struct smsdvb_client_t *client =
439 container_of(feed->demux, struct smsdvb_client_t, demux);
440 struct SmsMsgData_ST PidMsg;
2e5c1ec8 441
a0c0abcb 442 sms_debug("remove pid %d(%x)",
068d6c0f 443 feed->pid, feed->pid);
2e5c1ec8
MK
444
445 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
446 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
447 PidMsg.xMsgHeader.msgFlags = 0;
448 PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ;
449 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
450 PidMsg.msgData[0] = feed->pid;
451
ba79bb2c 452 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
82237416
MK
453 return smsclient_sendrequest(client->smsclient,
454 &PidMsg, sizeof(PidMsg));
2e5c1ec8
MK
455}
456
18245e18 457static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
a83ccdd6
MK
458 void *buffer, size_t size,
459 struct completion *completion)
2e5c1ec8 460{
ba79bb2c
US
461 int rc;
462
463 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer);
464 rc = smsclient_sendrequest(client->smsclient, buffer, size);
2e5c1ec8
MK
465 if (rc < 0)
466 return rc;
467
82237416
MK
468 return wait_for_completion_timeout(completion,
469 msecs_to_jiffies(2000)) ?
470 0 : -ETIME;
2e5c1ec8
MK
471}
472
67ae1d26
MCC
473static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
474{
475 int rc;
476 struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
477 DVBT_BDA_CONTROL_MSG_ID,
478 HIF_TASK,
479 sizeof(struct SmsMsgHdr_ST), 0 };
480
481 rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
482 &client->tune_done);
483
484 return rc;
485}
486
3746b617
MK
487static inline int led_feedback(struct smsdvb_client_t *client)
488{
489 if (client->fe_status & FE_HAS_LOCK)
490 return sms_board_led_feedback(client->coredev,
491 (client->sms_stat_dvb.ReceptionData.BER
492 == 0) ? SMS_LED_HI : SMS_LED_LO);
493 else
494 return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
495}
496
2e5c1ec8
MK
497static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
498{
67ae1d26 499 int rc;
793786d1
US
500 struct smsdvb_client_t *client;
501 client = container_of(fe, struct smsdvb_client_t, frontend);
2e5c1ec8 502
67ae1d26
MCC
503 rc = smsdvb_send_statistics_request(client);
504
793786d1 505 *stat = client->fe_status;
2e5c1ec8 506
3746b617
MK
507 led_feedback(client);
508
67ae1d26 509 return rc;
2e5c1ec8
MK
510}
511
512static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
513{
67ae1d26 514 int rc;
793786d1
US
515 struct smsdvb_client_t *client;
516 client = container_of(fe, struct smsdvb_client_t, frontend);
2e5c1ec8 517
67ae1d26
MCC
518 rc = smsdvb_send_statistics_request(client);
519
793786d1 520 *ber = client->sms_stat_dvb.ReceptionData.BER;
2e5c1ec8 521
3746b617
MK
522 led_feedback(client);
523
67ae1d26 524 return rc;
2e5c1ec8
MK
525}
526
527static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
528{
67ae1d26
MCC
529 int rc;
530
793786d1
US
531 struct smsdvb_client_t *client;
532 client = container_of(fe, struct smsdvb_client_t, frontend);
2e5c1ec8 533
67ae1d26
MCC
534 rc = smsdvb_send_statistics_request(client);
535
793786d1
US
536 if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
537 *strength = 0;
538 else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
539 *strength = 100;
540 else
541 *strength =
542 (client->sms_stat_dvb.ReceptionData.InBandPwr
543 + 95) * 3 / 2;
2e5c1ec8 544
3746b617
MK
545 led_feedback(client);
546
67ae1d26 547 return rc;
2e5c1ec8
MK
548}
549
550static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
551{
67ae1d26 552 int rc;
793786d1
US
553 struct smsdvb_client_t *client;
554 client = container_of(fe, struct smsdvb_client_t, frontend);
2e5c1ec8 555
67ae1d26
MCC
556 rc = smsdvb_send_statistics_request(client);
557
793786d1 558 *snr = client->sms_stat_dvb.ReceptionData.SNR;
2e5c1ec8 559
3746b617
MK
560 led_feedback(client);
561
67ae1d26 562 return rc;
2e5c1ec8
MK
563}
564
851a9091
MK
565static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
566{
67ae1d26 567 int rc;
793786d1
US
568 struct smsdvb_client_t *client;
569 client = container_of(fe, struct smsdvb_client_t, frontend);
851a9091 570
67ae1d26
MCC
571 rc = smsdvb_send_statistics_request(client);
572
793786d1 573 *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
851a9091 574
3746b617
MK
575 led_feedback(client);
576
67ae1d26 577 return rc;
851a9091
MK
578}
579
82237416
MK
580static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
581 struct dvb_frontend_tune_settings *tune)
2e5c1ec8 582{
a0c0abcb 583 sms_debug("");
2e5c1ec8
MK
584
585 tune->min_delay_ms = 400;
586 tune->step_size = 250000;
587 tune->max_drift = 0;
588 return 0;
589}
590
15115c17 591static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
2e5c1ec8 592{
cf4fab72 593 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
18245e18
MK
594 struct smsdvb_client_t *client =
595 container_of(fe, struct smsdvb_client_t, frontend);
2e5c1ec8 596
18245e18
MK
597 struct {
598 struct SmsMsgHdr_ST Msg;
82237416 599 u32 Data[3];
2e5c1ec8
MK
600 } Msg;
601
3746b617
MK
602 int ret;
603
793786d1
US
604 client->fe_status = FE_HAS_SIGNAL;
605 client->event_fe_state = -1;
606 client->event_unc_state = -1;
e85c97a0 607 fe->dtv_property_cache.delivery_system = SYS_DVBT;
793786d1
US
608
609 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
610 Msg.Msg.msgDstId = HIF_TASK;
611 Msg.Msg.msgFlags = 0;
612 Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
2e5c1ec8 613 Msg.Msg.msgLength = sizeof(Msg);
cf4fab72 614 Msg.Data[0] = c->frequency;
2e5c1ec8
MK
615 Msg.Data[2] = 12000000;
616
cf4fab72
MCC
617 sms_info("%s: freq %d band %d", __func__, c->frequency,
618 c->bandwidth_hz);
2e5c1ec8 619
643e15a0 620 switch (c->bandwidth_hz / 1000000) {
cf4fab72
MCC
621 case 8:
622 Msg.Data[1] = BW_8_MHZ;
623 break;
624 case 7:
625 Msg.Data[1] = BW_7_MHZ;
626 break;
627 case 6:
628 Msg.Data[1] = BW_6_MHZ;
629 break;
630 case 0:
631 return -EOPNOTSUPP;
632 default:
633 return -EINVAL;
2e5c1ec8 634 }
3746b617
MK
635 /* Disable LNA, if any. An error is returned if no LNA is present */
636 ret = sms_board_lna_control(client->coredev, 0);
637 if (ret == 0) {
638 fe_status_t status;
639
640 /* tune with LNA off at first */
641 ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
642 &client->tune_done);
643
644 smsdvb_read_status(fe, &status);
645
646 if (status & FE_HAS_LOCK)
647 return ret;
648
25985edc 649 /* previous tune didn't lock - enable LNA and tune again */
3746b617
MK
650 sms_board_lna_control(client->coredev, 1);
651 }
2e5c1ec8 652
82237416
MK
653 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
654 &client->tune_done);
2e5c1ec8
MK
655}
656
15115c17 657static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
6b26fcea 658{
cf4fab72 659 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
6b26fcea
MK
660 struct smsdvb_client_t *client =
661 container_of(fe, struct smsdvb_client_t, frontend);
662
663 struct {
664 struct SmsMsgHdr_ST Msg;
665 u32 Data[4];
666 } Msg;
667
e85c97a0
MCC
668 fe->dtv_property_cache.delivery_system = SYS_ISDBT;
669
6b26fcea
MK
670 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
671 Msg.Msg.msgDstId = HIF_TASK;
672 Msg.Msg.msgFlags = 0;
673 Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ;
674 Msg.Msg.msgLength = sizeof(Msg);
6b26fcea 675
cf4fab72
MCC
676 if (c->isdbt_sb_segment_idx == -1)
677 c->isdbt_sb_segment_idx = 0;
6b26fcea 678
cf4fab72
MCC
679 switch (c->isdbt_sb_segment_count) {
680 case 3:
6b26fcea
MK
681 Msg.Data[1] = BW_ISDBT_3SEG;
682 break;
cf4fab72 683 case 1:
6b26fcea
MK
684 Msg.Data[1] = BW_ISDBT_1SEG;
685 break;
cf4fab72 686 case 0: /* AUTO */
643e15a0 687 switch (c->bandwidth_hz / 1000000) {
cf4fab72
MCC
688 case 8:
689 case 7:
690 c->isdbt_sb_segment_count = 3;
691 Msg.Data[1] = BW_ISDBT_3SEG;
692 break;
693 case 6:
694 c->isdbt_sb_segment_count = 1;
695 Msg.Data[1] = BW_ISDBT_1SEG;
696 break;
697 default: /* Assumes 6 MHZ bw */
698 c->isdbt_sb_segment_count = 1;
699 c->bandwidth_hz = 6000;
700 Msg.Data[1] = BW_ISDBT_1SEG;
701 break;
702 }
703 break;
6b26fcea 704 default:
cf4fab72 705 sms_info("Segment count %d not supported", c->isdbt_sb_segment_count);
6b26fcea
MK
706 return -EINVAL;
707 }
708
cf4fab72
MCC
709 Msg.Data[0] = c->frequency;
710 Msg.Data[2] = 12000000;
711 Msg.Data[3] = c->isdbt_sb_segment_idx;
712
713 sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
714 c->frequency, c->isdbt_sb_segment_count,
715 c->isdbt_sb_segment_idx);
716
6b26fcea
MK
717 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
718 &client->tune_done);
719}
720
15115c17 721static int smsdvb_set_frontend(struct dvb_frontend *fe)
6b26fcea
MK
722{
723 struct smsdvb_client_t *client =
724 container_of(fe, struct smsdvb_client_t, frontend);
725 struct smscore_device_t *coredev = client->coredev;
726
727 switch (smscore_get_device_mode(coredev)) {
728 case DEVICE_MODE_DVBT:
729 case DEVICE_MODE_DVBT_BDA:
15115c17 730 return smsdvb_dvbt_set_frontend(fe);
6b26fcea
MK
731 case DEVICE_MODE_ISDBT:
732 case DEVICE_MODE_ISDBT_BDA:
15115c17 733 return smsdvb_isdbt_set_frontend(fe);
6b26fcea
MK
734 default:
735 return -EINVAL;
736 }
737}
738
7c61d80a 739static int smsdvb_get_frontend(struct dvb_frontend *fe)
2e5c1ec8 740{
7c61d80a 741 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
18245e18
MK
742 struct smsdvb_client_t *client =
743 container_of(fe, struct smsdvb_client_t, frontend);
d138210f
GG
744 struct smscore_device_t *coredev = client->coredev;
745 struct TRANSMISSION_STATISTICS_S *td =
746 &client->sms_stat_dvb.TransmissionData;
2e5c1ec8 747
d138210f
GG
748 switch (smscore_get_device_mode(coredev)) {
749 case DEVICE_MODE_DVBT:
750 case DEVICE_MODE_DVBT_BDA:
751 fep->frequency = td->Frequency;
752
753 switch (td->Bandwidth) {
754 case 6:
755 fep->bandwidth_hz = 6000000;
756 break;
757 case 7:
758 fep->bandwidth_hz = 7000000;
759 break;
760 case 8:
761 fep->bandwidth_hz = 8000000;
762 break;
763 }
764
765 switch (td->TransmissionMode) {
766 case 2:
767 fep->transmission_mode = TRANSMISSION_MODE_2K;
768 break;
769 case 8:
770 fep->transmission_mode = TRANSMISSION_MODE_8K;
771 }
772
773 switch (td->GuardInterval) {
774 case 0:
775 fep->guard_interval = GUARD_INTERVAL_1_32;
776 break;
777 case 1:
778 fep->guard_interval = GUARD_INTERVAL_1_16;
779 break;
780 case 2:
781 fep->guard_interval = GUARD_INTERVAL_1_8;
782 break;
783 case 3:
784 fep->guard_interval = GUARD_INTERVAL_1_4;
785 break;
786 }
787
788 switch (td->CodeRate) {
789 case 0:
790 fep->code_rate_HP = FEC_1_2;
791 break;
792 case 1:
793 fep->code_rate_HP = FEC_2_3;
794 break;
795 case 2:
796 fep->code_rate_HP = FEC_3_4;
797 break;
798 case 3:
799 fep->code_rate_HP = FEC_5_6;
800 break;
801 case 4:
802 fep->code_rate_HP = FEC_7_8;
803 break;
804 }
805
806 switch (td->LPCodeRate) {
807 case 0:
808 fep->code_rate_LP = FEC_1_2;
809 break;
810 case 1:
811 fep->code_rate_LP = FEC_2_3;
812 break;
813 case 2:
814 fep->code_rate_LP = FEC_3_4;
815 break;
816 case 3:
817 fep->code_rate_LP = FEC_5_6;
818 break;
819 case 4:
820 fep->code_rate_LP = FEC_7_8;
821 break;
822 }
823
824 switch (td->Constellation) {
825 case 0:
826 fep->modulation = QPSK;
827 break;
828 case 1:
829 fep->modulation = QAM_16;
830 break;
831 case 2:
832 fep->modulation = QAM_64;
833 break;
834 }
835
836 switch (td->Hierarchy) {
837 case 0:
838 fep->hierarchy = HIERARCHY_NONE;
839 break;
840 case 1:
841 fep->hierarchy = HIERARCHY_1;
842 break;
843 case 2:
844 fep->hierarchy = HIERARCHY_2;
845 break;
846 case 3:
847 fep->hierarchy = HIERARCHY_4;
848 break;
849 }
2e5c1ec8 850
d138210f
GG
851 fep->inversion = INVERSION_AUTO;
852 break;
853 case DEVICE_MODE_ISDBT:
854 case DEVICE_MODE_ISDBT_BDA:
855 fep->frequency = td->Frequency;
856 fep->bandwidth_hz = 6000000;
857 /* todo: retrive the other parameters */
858 break;
859 default:
860 return -EINVAL;
861 }
7a6fbed6
MK
862
863 return 0;
864}
865
866static int smsdvb_init(struct dvb_frontend *fe)
867{
868 struct smsdvb_client_t *client =
869 container_of(fe, struct smsdvb_client_t, frontend);
870
3746b617
MK
871 sms_board_power(client->coredev, 1);
872
793786d1 873 sms_board_dvb3_event(client, DVB3_EVENT_INIT);
7a6fbed6
MK
874 return 0;
875}
876
877static int smsdvb_sleep(struct dvb_frontend *fe)
878{
879 struct smsdvb_client_t *client =
880 container_of(fe, struct smsdvb_client_t, frontend);
881
3746b617
MK
882 sms_board_led_feedback(client->coredev, SMS_LED_OFF);
883 sms_board_power(client->coredev, 0);
884
793786d1 885 sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
7a6fbed6 886
2e5c1ec8
MK
887 return 0;
888}
889
890static void smsdvb_release(struct dvb_frontend *fe)
891{
fa830e8a 892 /* do nothing */
2e5c1ec8
MK
893}
894
895static struct dvb_frontend_ops smsdvb_fe_ops = {
896 .info = {
e0f14c25 897 .name = "Siano Mobile Digital MDTV Receiver",
2e5c1ec8
MK
898 .frequency_min = 44250000,
899 .frequency_max = 867250000,
900 .frequency_stepsize = 250000,
901 .caps = FE_CAN_INVERSION_AUTO |
82237416
MK
902 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
903 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
904 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
905 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
906 FE_CAN_GUARD_INTERVAL_AUTO |
907 FE_CAN_RECOVER |
908 FE_CAN_HIERARCHY_AUTO,
2e5c1ec8
MK
909 },
910
911 .release = smsdvb_release,
912
15115c17
MCC
913 .set_frontend = smsdvb_set_frontend,
914 .get_frontend = smsdvb_get_frontend,
2e5c1ec8
MK
915 .get_tune_settings = smsdvb_get_tune_settings,
916
917 .read_status = smsdvb_read_status,
918 .read_ber = smsdvb_read_ber,
919 .read_signal_strength = smsdvb_read_signal_strength,
920 .read_snr = smsdvb_read_snr,
851a9091 921 .read_ucblocks = smsdvb_read_ucblocks,
7a6fbed6
MK
922
923 .init = smsdvb_init,
924 .sleep = smsdvb_sleep,
2e5c1ec8
MK
925};
926
0c071f37
MK
927static int smsdvb_hotplug(struct smscore_device_t *coredev,
928 struct device *device, int arrival)
2e5c1ec8 929{
18245e18
MK
930 struct smsclient_params_t params;
931 struct smsdvb_client_t *client;
2e5c1ec8
MK
932 int rc;
933
fa830e8a 934 /* device removal handled by onremove callback */
2e5c1ec8
MK
935 if (!arrival)
936 return 0;
18245e18 937 client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
82237416 938 if (!client) {
eb250942 939 sms_err("kmalloc() failed");
2e5c1ec8
MK
940 return -ENOMEM;
941 }
942
fa830e8a 943 /* register dvb adapter */
1c11d546
MK
944 rc = dvb_register_adapter(&client->adapter,
945 sms_get_board(
946 smscore_get_board_id(coredev))->name,
82237416
MK
947 THIS_MODULE, device, adapter_nr);
948 if (rc < 0) {
a0c0abcb 949 sms_err("dvb_register_adapter() failed %d", rc);
2e5c1ec8
MK
950 goto adapter_error;
951 }
952
fa830e8a 953 /* init dvb demux */
2e5c1ec8 954 client->demux.dmx.capabilities = DMX_TS_FILTERING;
fa830e8a 955 client->demux.filternum = 32; /* todo: nova ??? */
2e5c1ec8
MK
956 client->demux.feednum = 32;
957 client->demux.start_feed = smsdvb_start_feed;
958 client->demux.stop_feed = smsdvb_stop_feed;
959
960 rc = dvb_dmx_init(&client->demux);
82237416 961 if (rc < 0) {
a0c0abcb 962 sms_err("dvb_dmx_init failed %d", rc);
2e5c1ec8
MK
963 goto dvbdmx_error;
964 }
965
fa830e8a 966 /* init dmxdev */
2e5c1ec8
MK
967 client->dmxdev.filternum = 32;
968 client->dmxdev.demux = &client->demux.dmx;
969 client->dmxdev.capabilities = 0;
970
971 rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
82237416 972 if (rc < 0) {
a0c0abcb 973 sms_err("dvb_dmxdev_init failed %d", rc);
2e5c1ec8
MK
974 goto dmxdev_error;
975 }
976
fa830e8a 977 /* init and register frontend */
82237416
MK
978 memcpy(&client->frontend.ops, &smsdvb_fe_ops,
979 sizeof(struct dvb_frontend_ops));
2e5c1ec8 980
15115c17
MCC
981 switch (smscore_get_device_mode(coredev)) {
982 case DEVICE_MODE_DVBT:
983 case DEVICE_MODE_DVBT_BDA:
9bd58e77 984 client->frontend.ops.delsys[0] = SYS_DVBT;
15115c17
MCC
985 break;
986 case DEVICE_MODE_ISDBT:
987 case DEVICE_MODE_ISDBT_BDA:
9bd58e77 988 client->frontend.ops.delsys[0] = SYS_ISDBT;
15115c17
MCC
989 break;
990 }
991
2e5c1ec8 992 rc = dvb_register_frontend(&client->adapter, &client->frontend);
82237416 993 if (rc < 0) {
a0c0abcb 994 sms_err("frontend registration failed %d", rc);
2e5c1ec8
MK
995 goto frontend_error;
996 }
997
f17407a8 998 params.initial_id = 1;
2e5c1ec8
MK
999 params.data_type = MSG_SMS_DVBT_BDA_DATA;
1000 params.onresponse_handler = smsdvb_onresponse;
1001 params.onremove_handler = smsdvb_onremove;
1002 params.context = client;
1003
1004 rc = smscore_register_client(coredev, &params, &client->smsclient);
82237416 1005 if (rc < 0) {
eb250942 1006 sms_err("smscore_register_client() failed %d", rc);
2e5c1ec8
MK
1007 goto client_error;
1008 }
1009
1010 client->coredev = coredev;
1011
1012 init_completion(&client->tune_done);
2e5c1ec8
MK
1013
1014 kmutex_lock(&g_smsdvb_clientslock);
1015
1016 list_add(&client->entry, &g_smsdvb_clients);
1017
1018 kmutex_unlock(&g_smsdvb_clientslock);
1019
793786d1
US
1020 client->event_fe_state = -1;
1021 client->event_unc_state = -1;
1022 sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
2e5c1ec8 1023
793786d1 1024 sms_info("success");
250fa674
MK
1025 sms_board_setup(coredev);
1026
2e5c1ec8
MK
1027 return 0;
1028
1029client_error:
1030 dvb_unregister_frontend(&client->frontend);
1031
1032frontend_error:
1033 dvb_dmxdev_release(&client->dmxdev);
1034
1035dmxdev_error:
1036 dvb_dmx_release(&client->demux);
1037
1038dvbdmx_error:
1039 dvb_unregister_adapter(&client->adapter);
1040
1041adapter_error:
1042 kfree(client);
1043 return rc;
1044}
1045
2184dda0 1046static int __init smsdvb_module_init(void)
eae55660
ST
1047{
1048 int rc;
1049
1050 INIT_LIST_HEAD(&g_smsdvb_clients);
1051 kmutex_init(&g_smsdvb_clientslock);
1052
1053 rc = smscore_register_hotplug(smsdvb_hotplug);
1054
a0c0abcb 1055 sms_debug("");
eae55660
ST
1056
1057 return rc;
1058}
1059
2184dda0 1060static void __exit smsdvb_module_exit(void)
eae55660
ST
1061{
1062 smscore_unregister_hotplug(smsdvb_hotplug);
1063
1064 kmutex_lock(&g_smsdvb_clientslock);
1065
1066 while (!list_empty(&g_smsdvb_clients))
82237416 1067 smsdvb_unregister_client(
18245e18 1068 (struct smsdvb_client_t *) g_smsdvb_clients.next);
eae55660
ST
1069
1070 kmutex_unlock(&g_smsdvb_clientslock);
eae55660 1071}
e0f14c25
US
1072
1073module_init(smsdvb_module_init);
1074module_exit(smsdvb_module_exit);
1075
1076MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
843d0605 1077MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
e0f14c25 1078MODULE_LICENSE("GPL");
This page took 0.411268 seconds and 5 git commands to generate.