Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
smsdvb.c
Go to the documentation of this file.
1 /****************************************************************
2 
3 Siano Mobile Silicon, Inc.
4 MDTV receiver kernel modules.
5 Copyright (C) 2006-2008, Uri Shkolnik
6 
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the 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,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 
20 ****************************************************************/
21 
22 #include <linux/module.h>
23 #include <linux/slab.h>
24 #include <linux/init.h>
25 
26 #include "dmxdev.h"
27 #include "dvbdev.h"
28 #include "dvb_demux.h"
29 #include "dvb_frontend.h"
30 
31 #include "smscoreapi.h"
32 #include "smsendian.h"
33 #include "sms-cards.h"
34 
36 
38  struct list_head entry;
39 
42 
44  struct dvb_demux demux;
45  struct dmxdev dmxdev;
47 
49 
51 
55 };
56 
57 static struct list_head g_smsdvb_clients;
58 static struct mutex g_smsdvb_clientslock;
59 
60 static int sms_dbg;
61 module_param_named(debug, sms_dbg, int, 0644);
62 MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
63 
64 /* Events that may come from DVB v3 adapter */
65 static void sms_board_dvb3_event(struct smsdvb_client_t *client,
66  enum SMS_DVB3_EVENTS event) {
67 
68  struct smscore_device_t *coredev = client->coredev;
69  switch (event) {
70  case DVB3_EVENT_INIT:
71  sms_debug("DVB3_EVENT_INIT");
73  break;
74  case DVB3_EVENT_SLEEP:
75  sms_debug("DVB3_EVENT_SLEEP");
77  break;
78  case DVB3_EVENT_HOTPLUG:
79  sms_debug("DVB3_EVENT_HOTPLUG");
81  break;
82  case DVB3_EVENT_FE_LOCK:
83  if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
85  sms_debug("DVB3_EVENT_FE_LOCK");
87  }
88  break;
90  if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
92  sms_debug("DVB3_EVENT_FE_UNLOCK");
94  }
95  break;
96  case DVB3_EVENT_UNC_OK:
97  if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
99  sms_debug("DVB3_EVENT_UNC_OK");
101  }
102  break;
103  case DVB3_EVENT_UNC_ERR:
104  if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
106  sms_debug("DVB3_EVENT_UNC_ERR");
108  }
109  break;
110 
111  default:
112  sms_err("Unknown dvb3 api event");
113  break;
114  }
115 }
116 
117 
118 static 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);
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 
175 static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
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 
229 static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
230 {
231  struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
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;
237 
239 
240  switch (phdr->msgType) {
242  dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
243  cb->size - sizeof(struct SmsMsgHdr_ST));
244  break;
245 
246  case MSG_SMS_RF_TUNE_RES:
248  complete(&client->tune_done);
249  break;
250 
252  sms_info("MSG_SMS_SIGNAL_DETECTED_IND");
253  client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
254  is_status_update = true;
255  break;
256 
258  sms_info("MSG_SMS_NO_SIGNAL_IND");
259  client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
260  is_status_update = true;
261  break;
262 
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);
275  client->sms_stat_dvb.TransmissionData);
276  is_status_update = true;
277  break;
278  }
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);
317  } else {
318  pReceptionData->TS_PER = 0;
319  }
320 
321  pReceptionData->BERBitCount = pMsgData[18];
322  pReceptionData->BERErrorCount = pMsgData[19];
323 
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  }
332  union {
333  struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
334  struct SmsMsgStatisticsInfo_ST dvb;
335  } *p = (void *) (phdr + 1);
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;
342 
343  switch (smscore_get_device_mode(client->coredev)) {
344  case DEVICE_MODE_ISDBT:
346  smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
347  break;
348  default:
349  smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
350  }
351  if (!pReceptionData->IsDemodLocked) {
352  pReceptionData->SNR = 0;
353  pReceptionData->BER = 0;
354  pReceptionData->BERErrorCount = 0;
355  pReceptionData->InBandPwr = 0;
356  pReceptionData->ErrorTSPackets = 0;
357  }
358 
359  complete(&client->tune_done);
360  break;
361  }
362  default:
363  sms_info("Unhandled message %d", phdr->msgType);
364 
365  }
366  smscore_putbuffer(client->coredev, cb);
367 
368  if (is_status_update) {
369  if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
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,
379 
380  } else {
381  if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
383  else
384  client->fe_status = 0;
385  sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
386  }
387  }
388 
389  return 0;
390 }
391 
392 static void smsdvb_unregister_client(struct smsdvb_client_t *client)
393 {
394  /* must be called under clientslock */
395 
396  list_del(&client->entry);
397 
400  dvb_dmxdev_release(&client->dmxdev);
401  dvb_dmx_release(&client->demux);
403  kfree(client);
404 }
405 
406 static void smsdvb_onremove(void *context)
407 {
408  kmutex_lock(&g_smsdvb_clientslock);
409 
410  smsdvb_unregister_client((struct smsdvb_client_t *) context);
411 
412  kmutex_unlock(&g_smsdvb_clientslock);
413 }
414 
415 static int smsdvb_start_feed(struct dvb_demux_feed *feed)
416 {
417  struct smsdvb_client_t *client =
418  container_of(feed->demux, struct smsdvb_client_t, demux);
419  struct SmsMsgData_ST PidMsg;
420 
421  sms_debug("add pid %d(%x)",
422  feed->pid, feed->pid);
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 
431  smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
432  return smsclient_sendrequest(client->smsclient,
433  &PidMsg, sizeof(PidMsg));
434 }
435 
436 static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
437 {
438  struct smsdvb_client_t *client =
439  container_of(feed->demux, struct smsdvb_client_t, demux);
440  struct SmsMsgData_ST PidMsg;
441 
442  sms_debug("remove pid %d(%x)",
443  feed->pid, feed->pid);
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 
452  smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
453  return smsclient_sendrequest(client->smsclient,
454  &PidMsg, sizeof(PidMsg));
455 }
456 
457 static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
458  void *buffer, size_t size,
459  struct completion *completion)
460 {
461  int rc;
462 
463  smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer);
464  rc = smsclient_sendrequest(client->smsclient, buffer, size);
465  if (rc < 0)
466  return rc;
467 
468  return wait_for_completion_timeout(completion,
469  msecs_to_jiffies(2000)) ?
470  0 : -ETIME;
471 }
472 
473 static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
474 {
475  int rc;
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 
487 static 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 
497 static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
498 {
499  int rc;
500  struct smsdvb_client_t *client;
501  client = container_of(fe, struct smsdvb_client_t, frontend);
502 
503  rc = smsdvb_send_statistics_request(client);
504 
505  *stat = client->fe_status;
506 
507  led_feedback(client);
508 
509  return rc;
510 }
511 
512 static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
513 {
514  int rc;
515  struct smsdvb_client_t *client;
516  client = container_of(fe, struct smsdvb_client_t, frontend);
517 
518  rc = smsdvb_send_statistics_request(client);
519 
520  *ber = client->sms_stat_dvb.ReceptionData.BER;
521 
522  led_feedback(client);
523 
524  return rc;
525 }
526 
527 static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
528 {
529  int rc;
530 
531  struct smsdvb_client_t *client;
532  client = container_of(fe, struct smsdvb_client_t, frontend);
533 
534  rc = smsdvb_send_statistics_request(client);
535 
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;
544 
545  led_feedback(client);
546 
547  return rc;
548 }
549 
550 static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
551 {
552  int rc;
553  struct smsdvb_client_t *client;
554  client = container_of(fe, struct smsdvb_client_t, frontend);
555 
556  rc = smsdvb_send_statistics_request(client);
557 
558  *snr = client->sms_stat_dvb.ReceptionData.SNR;
559 
560  led_feedback(client);
561 
562  return rc;
563 }
564 
565 static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
566 {
567  int rc;
568  struct smsdvb_client_t *client;
569  client = container_of(fe, struct smsdvb_client_t, frontend);
570 
571  rc = smsdvb_send_statistics_request(client);
572 
573  *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
574 
575  led_feedback(client);
576 
577  return rc;
578 }
579 
580 static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
581  struct dvb_frontend_tune_settings *tune)
582 {
583  sms_debug("");
584 
585  tune->min_delay_ms = 400;
586  tune->step_size = 250000;
587  tune->max_drift = 0;
588  return 0;
589 }
590 
591 static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
592 {
594  struct smsdvb_client_t *client =
596 
597  struct {
598  struct SmsMsgHdr_ST Msg;
599  u32 Data[3];
600  } Msg;
601 
602  int ret;
603 
604  client->fe_status = FE_HAS_SIGNAL;
605  client->event_fe_state = -1;
606  client->event_unc_state = -1;
607  fe->dtv_property_cache.delivery_system = SYS_DVBT;
608 
610  Msg.Msg.msgDstId = HIF_TASK;
611  Msg.Msg.msgFlags = 0;
612  Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
613  Msg.Msg.msgLength = sizeof(Msg);
614  Msg.Data[0] = c->frequency;
615  Msg.Data[2] = 12000000;
616 
617  sms_info("%s: freq %d band %d", __func__, c->frequency,
618  c->bandwidth_hz);
619 
620  switch (c->bandwidth_hz / 1000000) {
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;
634  }
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) {
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 
649  /* previous tune didn't lock - enable LNA and tune again */
650  sms_board_lna_control(client->coredev, 1);
651  }
652 
653  return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
654  &client->tune_done);
655 }
656 
657 static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
658 {
660  struct smsdvb_client_t *client =
662 
663  struct {
664  struct SmsMsgHdr_ST Msg;
665  u32 Data[4];
666  } Msg;
667 
668  fe->dtv_property_cache.delivery_system = SYS_ISDBT;
669 
671  Msg.Msg.msgDstId = HIF_TASK;
672  Msg.Msg.msgFlags = 0;
674  Msg.Msg.msgLength = sizeof(Msg);
675 
676  if (c->isdbt_sb_segment_idx == -1)
677  c->isdbt_sb_segment_idx = 0;
678 
679  switch (c->isdbt_sb_segment_count) {
680  case 3:
681  Msg.Data[1] = BW_ISDBT_3SEG;
682  break;
683  case 1:
684  Msg.Data[1] = BW_ISDBT_1SEG;
685  break;
686  case 0: /* AUTO */
687  switch (c->bandwidth_hz / 1000000) {
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;
704  default:
705  sms_info("Segment count %d not supported", c->isdbt_sb_segment_count);
706  return -EINVAL;
707  }
708 
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__,
716 
717  return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
718  &client->tune_done);
719 }
720 
721 static int smsdvb_set_frontend(struct dvb_frontend *fe)
722 {
723  struct smsdvb_client_t *client =
725  struct smscore_device_t *coredev = client->coredev;
726 
727  switch (smscore_get_device_mode(coredev)) {
728  case DEVICE_MODE_DVBT:
730  return smsdvb_dvbt_set_frontend(fe);
731  case DEVICE_MODE_ISDBT:
733  return smsdvb_isdbt_set_frontend(fe);
734  default:
735  return -EINVAL;
736  }
737 }
738 
739 static int smsdvb_get_frontend(struct dvb_frontend *fe)
740 {
741  struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
742  struct smsdvb_client_t *client =
744  struct smscore_device_t *coredev = client->coredev;
745  struct TRANSMISSION_STATISTICS_S *td =
746  &client->sms_stat_dvb.TransmissionData;
747 
748  switch (smscore_get_device_mode(coredev)) {
749  case DEVICE_MODE_DVBT:
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:
768  break;
769  case 8:
771  }
772 
773  switch (td->GuardInterval) {
774  case 0:
776  break;
777  case 1:
779  break;
780  case 2:
782  break;
783  case 3:
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  }
850 
851  fep->inversion = INVERSION_AUTO;
852  break;
853  case DEVICE_MODE_ISDBT:
855  fep->frequency = td->Frequency;
856  fep->bandwidth_hz = 6000000;
857  /* todo: retrive the other parameters */
858  break;
859  default:
860  return -EINVAL;
861  }
862 
863  return 0;
864 }
865 
866 static int smsdvb_init(struct dvb_frontend *fe)
867 {
868  struct smsdvb_client_t *client =
870 
871  sms_board_power(client->coredev, 1);
872 
873  sms_board_dvb3_event(client, DVB3_EVENT_INIT);
874  return 0;
875 }
876 
877 static int smsdvb_sleep(struct dvb_frontend *fe)
878 {
879  struct smsdvb_client_t *client =
881 
883  sms_board_power(client->coredev, 0);
884 
885  sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
886 
887  return 0;
888 }
889 
890 static void smsdvb_release(struct dvb_frontend *fe)
891 {
892  /* do nothing */
893 }
894 
895 static struct dvb_frontend_ops smsdvb_fe_ops = {
896  .info = {
897  .name = "Siano Mobile Digital MDTV Receiver",
898  .frequency_min = 44250000,
899  .frequency_max = 867250000,
900  .frequency_stepsize = 250000,
901  .caps = FE_CAN_INVERSION_AUTO |
909  },
910 
911  .release = smsdvb_release,
912 
913  .set_frontend = smsdvb_set_frontend,
914  .get_frontend = smsdvb_get_frontend,
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,
921  .read_ucblocks = smsdvb_read_ucblocks,
922 
923  .init = smsdvb_init,
924  .sleep = smsdvb_sleep,
925 };
926 
927 static int smsdvb_hotplug(struct smscore_device_t *coredev,
928  struct device *device, int arrival)
929 {
930  struct smsclient_params_t params;
931  struct smsdvb_client_t *client;
932  int rc;
933 
934  /* device removal handled by onremove callback */
935  if (!arrival)
936  return 0;
937  client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
938  if (!client) {
939  sms_err("kmalloc() failed");
940  return -ENOMEM;
941  }
942 
943  /* register dvb adapter */
944  rc = dvb_register_adapter(&client->adapter,
946  smscore_get_board_id(coredev))->name,
947  THIS_MODULE, device, adapter_nr);
948  if (rc < 0) {
949  sms_err("dvb_register_adapter() failed %d", rc);
950  goto adapter_error;
951  }
952 
953  /* init dvb demux */
954  client->demux.dmx.capabilities = DMX_TS_FILTERING;
955  client->demux.filternum = 32; /* todo: nova ??? */
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);
961  if (rc < 0) {
962  sms_err("dvb_dmx_init failed %d", rc);
963  goto dvbdmx_error;
964  }
965 
966  /* init dmxdev */
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);
972  if (rc < 0) {
973  sms_err("dvb_dmxdev_init failed %d", rc);
974  goto dmxdev_error;
975  }
976 
977  /* init and register frontend */
978  memcpy(&client->frontend.ops, &smsdvb_fe_ops,
979  sizeof(struct dvb_frontend_ops));
980 
981  switch (smscore_get_device_mode(coredev)) {
982  case DEVICE_MODE_DVBT:
984  client->frontend.ops.delsys[0] = SYS_DVBT;
985  break;
986  case DEVICE_MODE_ISDBT:
988  client->frontend.ops.delsys[0] = SYS_ISDBT;
989  break;
990  }
991 
992  rc = dvb_register_frontend(&client->adapter, &client->frontend);
993  if (rc < 0) {
994  sms_err("frontend registration failed %d", rc);
995  goto frontend_error;
996  }
997 
998  params.initial_id = 1;
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);
1005  if (rc < 0) {
1006  sms_err("smscore_register_client() failed %d", rc);
1007  goto client_error;
1008  }
1009 
1010  client->coredev = coredev;
1011 
1012  init_completion(&client->tune_done);
1013 
1014  kmutex_lock(&g_smsdvb_clientslock);
1015 
1016  list_add(&client->entry, &g_smsdvb_clients);
1017 
1018  kmutex_unlock(&g_smsdvb_clientslock);
1019 
1020  client->event_fe_state = -1;
1021  client->event_unc_state = -1;
1022  sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
1023 
1024  sms_info("success");
1025  sms_board_setup(coredev);
1026 
1027  return 0;
1028 
1029 client_error:
1031 
1032 frontend_error:
1033  dvb_dmxdev_release(&client->dmxdev);
1034 
1035 dmxdev_error:
1036  dvb_dmx_release(&client->demux);
1037 
1038 dvbdmx_error:
1039  dvb_unregister_adapter(&client->adapter);
1040 
1041 adapter_error:
1042  kfree(client);
1043  return rc;
1044 }
1045 
1046 static int __init smsdvb_module_init(void)
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 
1055  sms_debug("");
1056 
1057  return rc;
1058 }
1059 
1060 static void __exit smsdvb_module_exit(void)
1061 {
1062  smscore_unregister_hotplug(smsdvb_hotplug);
1063 
1064  kmutex_lock(&g_smsdvb_clientslock);
1065 
1066  while (!list_empty(&g_smsdvb_clients))
1067  smsdvb_unregister_client(
1068  (struct smsdvb_client_t *) g_smsdvb_clients.next);
1069 
1070  kmutex_unlock(&g_smsdvb_clientslock);
1071 }
1072 
1073 module_init(smsdvb_module_init);
1074 module_exit(smsdvb_module_exit);
1075 
1076 MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
1077 MODULE_AUTHOR("Siano Mobile Silicon, Inc. ([email protected])");
1078 MODULE_LICENSE("GPL");