Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
smscoreapi.c
Go to the documentation of this file.
1 /*
2  * Siano core API module
3  *
4  * This file contains implementation for the interface to sms core component
5  *
6  * author: Uri Shkolnik
7  *
8  * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation;
13  *
14  * Software distributed under the License is distributed on an "AS IS"
15  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
16  *
17  * See the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23 
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/delay.h>
30 #include <linux/io.h>
31 #include <linux/slab.h>
32 
33 #include <linux/firmware.h>
34 #include <linux/wait.h>
35 #include <asm/byteorder.h>
36 
37 #include "smscoreapi.h"
38 #include "sms-cards.h"
39 #include "smsir.h"
40 #include "smsendian.h"
41 
42 static int sms_dbg;
43 module_param_named(debug, sms_dbg, int, 0644);
44 MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
45 
47  struct list_head entry;
49 };
50 
52  struct list_head entry;
53  int id;
54  int data_type;
55 };
56 
58  struct list_head entry;
60  void *context;
61  struct list_head idlist;
64 };
65 
67 {
68  core->board_id = id;
69 }
70 
72 {
73  if (led >= 0)
74  core->led_state = led;
75  return core->led_state;
76 }
78 
80 {
81  return core->board_id;
82 }
84 
86  struct list_head entry;
87  char devpath[32];
88  int mode;
90 };
91 
92 static struct list_head g_smscore_notifyees;
93 static struct list_head g_smscore_devices;
94 static struct mutex g_smscore_deviceslock;
95 
96 static struct list_head g_smscore_registry;
97 static struct mutex g_smscore_registrylock;
98 
99 static int default_mode = 4;
100 
101 module_param(default_mode, int, 0644);
102 MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
103 
104 static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
105 {
107  struct list_head *next;
108 
109  kmutex_lock(&g_smscore_registrylock);
110  for (next = g_smscore_registry.next;
111  next != &g_smscore_registry;
112  next = next->next) {
113  entry = (struct smscore_registry_entry_t *) next;
114  if (!strcmp(entry->devpath, devpath)) {
115  kmutex_unlock(&g_smscore_registrylock);
116  return entry;
117  }
118  }
119  entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
120  if (entry) {
121  entry->mode = default_mode;
122  strcpy(entry->devpath, devpath);
123  list_add(&entry->entry, &g_smscore_registry);
124  } else
125  sms_err("failed to create smscore_registry.");
126  kmutex_unlock(&g_smscore_registrylock);
127  return entry;
128 }
129 
130 int smscore_registry_getmode(char *devpath)
131 {
133 
134  entry = smscore_find_registry(devpath);
135  if (entry)
136  return entry->mode;
137  else
138  sms_err("No registry found.");
139 
140  return default_mode;
141 }
143 
144 static enum sms_device_type_st smscore_registry_gettype(char *devpath)
145 {
147 
148  entry = smscore_find_registry(devpath);
149  if (entry)
150  return entry->type;
151  else
152  sms_err("No registry found.");
153 
154  return -1;
155 }
156 
157 void smscore_registry_setmode(char *devpath, int mode)
158 {
160 
161  entry = smscore_find_registry(devpath);
162  if (entry)
163  entry->mode = mode;
164  else
165  sms_err("No registry found.");
166 }
167 
168 static void smscore_registry_settype(char *devpath,
170 {
172 
173  entry = smscore_find_registry(devpath);
174  if (entry)
175  entry->type = type;
176  else
177  sms_err("No registry found.");
178 }
179 
180 
181 static void list_add_locked(struct list_head *new, struct list_head *head,
182  spinlock_t *lock)
183 {
184  unsigned long flags;
185 
186  spin_lock_irqsave(lock, flags);
187 
188  list_add(new, head);
189 
190  spin_unlock_irqrestore(lock, flags);
191 }
192 
202 {
203  struct smscore_device_notifyee_t *notifyee;
204  struct list_head *next, *first;
205  int rc = 0;
206 
207  kmutex_lock(&g_smscore_deviceslock);
208 
209  notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
210  GFP_KERNEL);
211  if (notifyee) {
212  /* now notify callback about existing devices */
213  first = &g_smscore_devices;
214  for (next = first->next;
215  next != first && !rc;
216  next = next->next) {
217  struct smscore_device_t *coredev =
218  (struct smscore_device_t *) next;
219  rc = hotplug(coredev, coredev->device, 1);
220  }
221 
222  if (rc >= 0) {
223  notifyee->hotplug = hotplug;
224  list_add(&notifyee->entry, &g_smscore_notifyees);
225  } else
226  kfree(notifyee);
227  } else
228  rc = -ENOMEM;
229 
230  kmutex_unlock(&g_smscore_deviceslock);
231 
232  return rc;
233 }
235 
243 {
244  struct list_head *next, *first;
245 
246  kmutex_lock(&g_smscore_deviceslock);
247 
248  first = &g_smscore_notifyees;
249 
250  for (next = first->next; next != first;) {
251  struct smscore_device_notifyee_t *notifyee =
252  (struct smscore_device_notifyee_t *) next;
253  next = next->next;
254 
255  if (notifyee->hotplug == hotplug) {
256  list_del(&notifyee->entry);
257  kfree(notifyee);
258  }
259  }
260 
261  kmutex_unlock(&g_smscore_deviceslock);
262 }
264 
265 static void smscore_notify_clients(struct smscore_device_t *coredev)
266 {
267  struct smscore_client_t *client;
268 
269  /* the client must call smscore_unregister_client from remove handler */
270  while (!list_empty(&coredev->clients)) {
271  client = (struct smscore_client_t *) coredev->clients.next;
272  client->onremove_handler(client->context);
273  }
274 }
275 
276 static int smscore_notify_callbacks(struct smscore_device_t *coredev,
277  struct device *device, int arrival)
278 {
280  int rc = 0;
281 
282  /* note: must be called under g_deviceslock */
283 
284  list_for_each_entry(elem, &g_smscore_notifyees, entry) {
285  rc = elem->hotplug(coredev, device, arrival);
286  if (rc < 0)
287  break;
288  }
289 
290  return rc;
291 }
292 
293 static struct
294 smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
295  dma_addr_t common_buffer_phys)
296 {
297  struct smscore_buffer_t *cb =
298  kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
299  if (!cb) {
300  sms_info("kmalloc(...) failed");
301  return NULL;
302  }
303 
304  cb->p = buffer;
305  cb->offset_in_common = buffer - (u8 *) common_buffer;
306  cb->phys = common_buffer_phys + cb->offset_in_common;
307 
308  return cb;
309 }
310 
322  struct smscore_device_t **coredev)
323 {
324  struct smscore_device_t *dev;
325  u8 *buffer;
326 
327  dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
328  if (!dev) {
329  sms_info("kzalloc(...) failed");
330  return -ENOMEM;
331  }
332 
333  /* init list entry so it could be safe in smscore_unregister_device */
334  INIT_LIST_HEAD(&dev->entry);
335 
336  /* init queues */
337  INIT_LIST_HEAD(&dev->clients);
338  INIT_LIST_HEAD(&dev->buffers);
339 
340  /* init locks */
343 
344  /* init completion events */
345  init_completion(&dev->version_ex_done);
346  init_completion(&dev->data_download_done);
347  init_completion(&dev->trigger_done);
348  init_completion(&dev->init_device_done);
349  init_completion(&dev->reload_start_done);
350  init_completion(&dev->resume_done);
351  init_completion(&dev->gpio_configuration_done);
352  init_completion(&dev->gpio_set_level_done);
353  init_completion(&dev->gpio_get_level_done);
354  init_completion(&dev->ir_init_done);
355 
356  /* Buffer management */
358 
359  /* alloc common buffer */
360  dev->common_buffer_size = params->buffer_size * params->num_buffers;
362  &dev->common_buffer_phys,
363  GFP_KERNEL | GFP_DMA);
364  if (!dev->common_buffer) {
366  return -ENOMEM;
367  }
368 
369  /* prepare dma buffers */
370  for (buffer = dev->common_buffer;
371  dev->num_buffers < params->num_buffers;
372  dev->num_buffers++, buffer += params->buffer_size) {
373  struct smscore_buffer_t *cb =
374  smscore_createbuffer(buffer, dev->common_buffer,
375  dev->common_buffer_phys);
376  if (!cb) {
378  return -ENOMEM;
379  }
380 
381  smscore_putbuffer(dev, cb);
382  }
383 
384  sms_info("allocated %d buffers", dev->num_buffers);
385 
386  dev->mode = DEVICE_MODE_NONE;
387  dev->context = params->context;
388  dev->device = params->device;
389  dev->setmode_handler = params->setmode_handler;
390  dev->detectmode_handler = params->detectmode_handler;
392  dev->preload_handler = params->preload_handler;
393  dev->postload_handler = params->postload_handler;
394 
395  dev->device_flags = params->flags;
396  strcpy(dev->devpath, params->devpath);
397 
398  smscore_registry_settype(dev->devpath, params->device_type);
399 
400  /* add device to devices list */
401  kmutex_lock(&g_smscore_deviceslock);
402  list_add(&dev->entry, &g_smscore_devices);
403  kmutex_unlock(&g_smscore_deviceslock);
404 
405  *coredev = dev;
406 
407  sms_info("device %p created", dev);
408 
409  return 0;
410 }
412 
413 
414 static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
415  void *buffer, size_t size, struct completion *completion) {
416  int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
417  if (rc < 0) {
418  sms_info("sendrequest returned error %d", rc);
419  return rc;
420  }
421 
422  return wait_for_completion_timeout(completion,
424  0 : -ETIME;
425 }
426 
432 static int smscore_init_ir(struct smscore_device_t *coredev)
433 {
434  int ir_io;
435  int rc;
436  void *buffer;
437 
438  coredev->ir.dev = NULL;
439  ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir;
440  if (ir_io) {/* only if IR port exist we use IR sub-module */
441  sms_info("IR loading");
442  rc = sms_ir_init(coredev);
443 
444  if (rc != 0)
445  sms_err("Error initialization DTV IR sub-module");
446  else {
447  buffer = kmalloc(sizeof(struct SmsMsgData_ST2) +
449  GFP_KERNEL | GFP_DMA);
450  if (buffer) {
451  struct SmsMsgData_ST2 *msg =
452  (struct SmsMsgData_ST2 *)
453  SMS_ALIGN_ADDRESS(buffer);
454 
455  SMS_INIT_MSG(&msg->xMsgHeader,
457  sizeof(struct SmsMsgData_ST2));
458  msg->msgData[0] = coredev->ir.controller;
459  msg->msgData[1] = coredev->ir.timeout;
460 
462  (struct SmsMsgHdr_ST2 *)msg);
463  rc = smscore_sendrequest_and_wait(coredev, msg,
464  msg->xMsgHeader. msgLength,
465  &coredev->ir_init_done);
466 
467  kfree(buffer);
468  } else
469  sms_err
470  ("Sending IR initialization message failed");
471  }
472  } else
473  sms_info("IR port has not been detected");
474 
475  return 0;
476 }
477 
487 {
488  int rc = smscore_set_device_mode(
489  coredev, smscore_registry_getmode(coredev->devpath));
490  if (rc < 0) {
491  sms_info("set device mode faile , rc %d", rc);
492  return rc;
493  }
494 
495  kmutex_lock(&g_smscore_deviceslock);
496 
497  rc = smscore_notify_callbacks(coredev, coredev->device, 1);
498  smscore_init_ir(coredev);
499 
500  sms_info("device %p started, rc %d", coredev, rc);
501 
502  kmutex_unlock(&g_smscore_deviceslock);
503 
504  return rc;
505 }
507 
508 
509 static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
510  void *buffer, size_t size)
511 {
512  struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
513  struct SmsMsgHdr_ST *msg;
514  u32 mem_address;
515  u8 *payload = firmware->Payload;
516  int rc = 0;
517  firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
518  firmware->Length = le32_to_cpu(firmware->Length);
519 
520  mem_address = firmware->StartAddress;
521 
522  sms_info("loading FW to addr 0x%x size %d",
523  mem_address, firmware->Length);
524  if (coredev->preload_handler) {
525  rc = coredev->preload_handler(coredev->context);
526  if (rc < 0)
527  return rc;
528  }
529 
530  /* PAGE_SIZE buffer shall be enough and dma aligned */
532  if (!msg)
533  return -ENOMEM;
534 
535  if (coredev->mode != DEVICE_MODE_NONE) {
536  sms_debug("sending reload command.");
538  sizeof(struct SmsMsgHdr_ST));
539  rc = smscore_sendrequest_and_wait(coredev, msg,
540  msg->msgLength,
541  &coredev->reload_start_done);
542  mem_address = *(u32 *) &payload[20];
543  }
544 
545  while (size && rc >= 0) {
546  struct SmsDataDownload_ST *DataMsg =
547  (struct SmsDataDownload_ST *) msg;
548  int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
549 
551  (u16)(sizeof(struct SmsMsgHdr_ST) +
552  sizeof(u32) + payload_size));
553 
554  DataMsg->MemAddr = mem_address;
555  memcpy(DataMsg->Payload, payload, payload_size);
556 
557  if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
558  (coredev->mode == DEVICE_MODE_NONE))
559  rc = coredev->sendrequest_handler(
560  coredev->context, DataMsg,
561  DataMsg->xMsgHeader.msgLength);
562  else
563  rc = smscore_sendrequest_and_wait(
564  coredev, DataMsg,
565  DataMsg->xMsgHeader.msgLength,
566  &coredev->data_download_done);
567 
568  payload += payload_size;
569  size -= payload_size;
570  mem_address += payload_size;
571  }
572 
573  if (rc >= 0) {
574  if (coredev->mode == DEVICE_MODE_NONE) {
575  struct SmsMsgData_ST *TriggerMsg =
576  (struct SmsMsgData_ST *) msg;
577 
579  sizeof(struct SmsMsgHdr_ST) +
580  sizeof(u32) * 5);
581 
582  TriggerMsg->msgData[0] = firmware->StartAddress;
583  /* Entry point */
584  TriggerMsg->msgData[1] = 5; /* Priority */
585  TriggerMsg->msgData[2] = 0x200; /* Stack size */
586  TriggerMsg->msgData[3] = 0; /* Parameter */
587  TriggerMsg->msgData[4] = 4; /* Task ID */
588 
589  if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
590  rc = coredev->sendrequest_handler(
591  coredev->context, TriggerMsg,
592  TriggerMsg->xMsgHeader.msgLength);
593  msleep(100);
594  } else
595  rc = smscore_sendrequest_and_wait(
596  coredev, TriggerMsg,
597  TriggerMsg->xMsgHeader.msgLength,
598  &coredev->trigger_done);
599  } else {
601  sizeof(struct SmsMsgHdr_ST));
602 
603  rc = coredev->sendrequest_handler(coredev->context,
604  msg, msg->msgLength);
605  }
606  msleep(500);
607  }
608 
609  sms_debug("rc=%d, postload=%p ", rc,
610  coredev->postload_handler);
611 
612  kfree(msg);
613 
614  return ((rc >= 0) && coredev->postload_handler) ?
615  coredev->postload_handler(coredev->context) :
616  rc;
617 }
618 
629 static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
630  char *filename,
631  loadfirmware_t loadfirmware_handler)
632 {
633  int rc = -ENOENT;
634  const struct firmware *fw;
635  u8 *fw_buffer;
636 
637  if (loadfirmware_handler == NULL && !(coredev->device_flags &
639  return -EINVAL;
640 
641  rc = request_firmware(&fw, filename, coredev->device);
642  if (rc < 0) {
643  sms_info("failed to open \"%s\"", filename);
644  return rc;
645  }
646  sms_info("read FW %s, size=%zd", filename, fw->size);
647  fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
648  GFP_KERNEL | GFP_DMA);
649  if (fw_buffer) {
650  memcpy(fw_buffer, fw->data, fw->size);
651 
652  rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
653  smscore_load_firmware_family2(coredev,
654  fw_buffer,
655  fw->size) :
656  loadfirmware_handler(coredev->context,
657  fw_buffer, fw->size);
658 
659  kfree(fw_buffer);
660  } else {
661  sms_info("failed to allocate firmware buffer");
662  rc = -ENOMEM;
663  }
664 
665  release_firmware(fw);
666 
667  return rc;
668 }
669 
680 {
681  struct smscore_buffer_t *cb;
682  int num_buffers = 0;
683  int retry = 0;
684 
685  kmutex_lock(&g_smscore_deviceslock);
686 
687  /* Release input device (IR) resources */
688  sms_ir_exit(coredev);
689 
690  smscore_notify_clients(coredev);
691  smscore_notify_callbacks(coredev, NULL, 0);
692 
693  /* at this point all buffers should be back
694  * onresponse must no longer be called */
695 
696  while (1) {
697  while (!list_empty(&coredev->buffers)) {
698  cb = (struct smscore_buffer_t *) coredev->buffers.next;
699  list_del(&cb->entry);
700  kfree(cb);
701  num_buffers++;
702  }
703  if (num_buffers == coredev->num_buffers)
704  break;
705  if (++retry > 10) {
706  sms_info("exiting although "
707  "not all buffers released.");
708  break;
709  }
710 
711  sms_info("waiting for %d buffer(s)",
712  coredev->num_buffers - num_buffers);
713  msleep(100);
714  }
715 
716  sms_info("freed %d buffers", num_buffers);
717 
718  if (coredev->common_buffer)
720  coredev->common_buffer, coredev->common_buffer_phys);
721 
722  if (coredev->fw_buf != NULL)
723  kfree(coredev->fw_buf);
724 
725  list_del(&coredev->entry);
726  kfree(coredev);
727 
728  kmutex_unlock(&g_smscore_deviceslock);
729 
730  sms_info("device %p destroyed", coredev);
731 }
733 
734 static int smscore_detect_mode(struct smscore_device_t *coredev)
735 {
736  void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
737  GFP_KERNEL | GFP_DMA);
738  struct SmsMsgHdr_ST *msg =
739  (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
740  int rc;
741 
742  if (!buffer)
743  return -ENOMEM;
744 
746  sizeof(struct SmsMsgHdr_ST));
747 
748  rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
749  &coredev->version_ex_done);
750  if (rc == -ETIME) {
751  sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
752 
754  msecs_to_jiffies(5000))) {
755  rc = smscore_sendrequest_and_wait(
756  coredev, msg, msg->msgLength,
757  &coredev->version_ex_done);
758  if (rc < 0)
759  sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
760  "second try, rc %d", rc);
761  } else
762  rc = -ETIME;
763  }
764 
765  kfree(buffer);
766 
767  return rc;
768 }
769 
770 static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
771  /*Stellar NOVA A0 Nova B0 VEGA*/
772  /*DVBT*/
773  {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
774  /*DVBH*/
775  {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
776  /*TDMB*/
777  {"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
778  /*DABIP*/
779  {"none", "none", "none", "none"},
780  /*BDA*/
781  {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
782  /*ISDBT*/
783  {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
784  /*ISDBTBDA*/
785  {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
786  /*CMMB*/
787  {"none", "none", "none", "cmmb_vega_12mhz.inp"}
788 };
789 
790 static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
791  int mode, enum sms_device_type_st type)
792 {
793  char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
794  return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
795 }
796 
807 int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
808 {
809  void *buffer;
810  int rc = 0;
812 
813  sms_debug("set device mode to %d", mode);
814  if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
815  if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) {
816  sms_err("invalid mode specified %d", mode);
817  return -EINVAL;
818  }
819 
820  smscore_registry_setmode(coredev->devpath, mode);
821 
822  if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
823  rc = smscore_detect_mode(coredev);
824  if (rc < 0) {
825  sms_err("mode detect failed %d", rc);
826  return rc;
827  }
828  }
829 
830  if (coredev->mode == mode) {
831  sms_info("device mode %d already set", mode);
832  return 0;
833  }
834 
835  if (!(coredev->modes_supported & (1 << mode))) {
836  char *fw_filename;
837 
838  type = smscore_registry_gettype(coredev->devpath);
839  fw_filename = sms_get_fw_name(coredev, mode, type);
840 
841  rc = smscore_load_firmware_from_file(coredev,
842  fw_filename, NULL);
843  if (rc < 0) {
844  sms_warn("error %d loading firmware: %s, "
845  "trying again with default firmware",
846  rc, fw_filename);
847 
848  /* try again with the default firmware */
849  fw_filename = smscore_fw_lkup[mode][type];
850  rc = smscore_load_firmware_from_file(coredev,
851  fw_filename, NULL);
852 
853  if (rc < 0) {
854  sms_warn("error %d loading "
855  "firmware: %s", rc,
856  fw_filename);
857  return rc;
858  }
859  }
860  sms_log("firmware download success: %s", fw_filename);
861  } else
862  sms_info("mode %d supported by running "
863  "firmware", mode);
864 
865  buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
867  if (buffer) {
868  struct SmsMsgData_ST *msg =
869  (struct SmsMsgData_ST *)
870  SMS_ALIGN_ADDRESS(buffer);
871 
873  sizeof(struct SmsMsgData_ST));
874  msg->msgData[0] = mode;
875 
876  rc = smscore_sendrequest_and_wait(
877  coredev, msg, msg->xMsgHeader.msgLength,
878  &coredev->init_device_done);
879 
880  kfree(buffer);
881  } else {
882  sms_err("Could not allocate buffer for "
883  "init device message.");
884  rc = -ENOMEM;
885  }
886  } else {
887  if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
888  sms_err("invalid mode specified %d", mode);
889  return -EINVAL;
890  }
891 
892  smscore_registry_setmode(coredev->devpath, mode);
893 
894  if (coredev->detectmode_handler)
895  coredev->detectmode_handler(coredev->context,
896  &coredev->mode);
897 
898  if (coredev->mode != mode && coredev->setmode_handler)
899  rc = coredev->setmode_handler(coredev->context, mode);
900  }
901 
902  if (rc >= 0) {
903  coredev->mode = mode;
904  coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
905  }
906 
907  if (rc < 0)
908  sms_err("return error code %d.", rc);
909  return rc;
910 }
911 
921 {
922  return coredev->mode;
923 }
925 
936 static struct
937 smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
938  int data_type, int id)
939 {
940  struct list_head *first;
941  struct smscore_client_t *client;
942  unsigned long flags;
943  struct list_head *firstid;
944  struct smscore_idlist_t *client_id;
945 
946  spin_lock_irqsave(&coredev->clientslock, flags);
947  first = &coredev->clients;
948  list_for_each_entry(client, first, entry) {
949  firstid = &client->idlist;
950  list_for_each_entry(client_id, firstid, entry) {
951  if ((client_id->id == id) &&
952  (client_id->data_type == data_type ||
953  (client_id->data_type == 0)))
954  goto found;
955  }
956  }
957  client = NULL;
958 found:
959  spin_unlock_irqrestore(&coredev->clientslock, flags);
960  return client;
961 }
962 
973  struct smscore_buffer_t *cb) {
974  struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p
975  + cb->offset);
976  struct smscore_client_t *client;
977  int rc = -EBUSY;
978  static unsigned long last_sample_time; /* = 0; */
979  static int data_total; /* = 0; */
980  unsigned long time_now = jiffies_to_msecs(jiffies);
981 
982  if (!last_sample_time)
983  last_sample_time = time_now;
984 
985  if (time_now - last_sample_time > 10000) {
986  sms_debug("\ndata rate %d bytes/secs",
987  (int)((data_total * 1000) /
988  (time_now - last_sample_time)));
989 
990  last_sample_time = time_now;
991  data_total = 0;
992  }
993 
994  data_total += cb->size;
995  /* Do we need to re-route? */
996  if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) ||
997  (phdr->msgType == MSG_SMS_TRANSMISSION_IND)) {
998  if (coredev->mode == DEVICE_MODE_DVBT_BDA)
1000  }
1001 
1002 
1003  client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
1004 
1005  /* If no client registered for type & id,
1006  * check for control client where type is not registered */
1007  if (client)
1008  rc = client->onresponse_handler(client->context, cb);
1009 
1010  if (rc < 0) {
1011  switch (phdr->msgType) {
1013  {
1014  struct SmsVersionRes_ST *ver =
1015  (struct SmsVersionRes_ST *) phdr;
1016  sms_debug("MSG_SMS_GET_VERSION_EX_RES "
1017  "id %d prots 0x%x ver %d.%d",
1018  ver->FirmwareId, ver->SupportedProtocols,
1019  ver->RomVersionMajor, ver->RomVersionMinor);
1020 
1021  coredev->mode = ver->FirmwareId == 255 ?
1023  coredev->modes_supported = ver->SupportedProtocols;
1024 
1025  complete(&coredev->version_ex_done);
1026  break;
1027  }
1029  sms_debug("MSG_SMS_INIT_DEVICE_RES");
1030  complete(&coredev->init_device_done);
1031  break;
1033  sms_debug("MSG_SW_RELOAD_START_RES");
1034  complete(&coredev->reload_start_done);
1035  break;
1037  complete(&coredev->data_download_done);
1038  break;
1040  sms_debug("MSG_SW_RELOAD_EXEC_RES");
1041  break;
1043  sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
1044  complete(&coredev->trigger_done);
1045  break;
1047  complete(&coredev->resume_done);
1048  break;
1050  sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
1051  complete(&coredev->gpio_configuration_done);
1052  break;
1054  sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
1055  complete(&coredev->gpio_set_level_done);
1056  break;
1058  {
1059  u32 *msgdata = (u32 *) phdr;
1060  coredev->gpio_get_res = msgdata[1];
1061  sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
1062  coredev->gpio_get_res);
1063  complete(&coredev->gpio_get_level_done);
1064  break;
1065  }
1066  case MSG_SMS_START_IR_RES:
1067  complete(&coredev->ir_init_done);
1068  break;
1070  sms_ir_event(coredev,
1071  (const char *)
1072  ((char *)phdr
1073  + sizeof(struct SmsMsgHdr_ST)),
1074  (int)phdr->msgLength
1075  - sizeof(struct SmsMsgHdr_ST));
1076  break;
1077 
1078  default:
1079  break;
1080  }
1081  smscore_putbuffer(coredev, cb);
1082  }
1083 }
1085 
1096 {
1097  struct smscore_buffer_t *cb = NULL;
1098  unsigned long flags;
1099 
1100  spin_lock_irqsave(&coredev->bufferslock, flags);
1101  if (!list_empty(&coredev->buffers)) {
1102  cb = (struct smscore_buffer_t *) coredev->buffers.next;
1103  list_del(&cb->entry);
1104  }
1105  spin_unlock_irqrestore(&coredev->bufferslock, flags);
1106  return cb;
1107 }
1108 
1110 {
1111  struct smscore_buffer_t *cb = NULL;
1112 
1113  wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev)));
1114 
1115  return cb;
1116 }
1118 
1128  struct smscore_buffer_t *cb) {
1130  list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
1131 }
1133 
1134 static int smscore_validate_client(struct smscore_device_t *coredev,
1135  struct smscore_client_t *client,
1136  int data_type, int id)
1137 {
1138  struct smscore_idlist_t *listentry;
1139  struct smscore_client_t *registered_client;
1140 
1141  if (!client) {
1142  sms_err("bad parameter.");
1143  return -EINVAL;
1144  }
1145  registered_client = smscore_find_client(coredev, data_type, id);
1146  if (registered_client == client)
1147  return 0;
1148 
1149  if (registered_client) {
1150  sms_err("The msg ID already registered to another client.");
1151  return -EEXIST;
1152  }
1153  listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
1154  if (!listentry) {
1155  sms_err("Can't allocate memory for client id.");
1156  return -ENOMEM;
1157  }
1158  listentry->id = id;
1159  listentry->data_type = data_type;
1160  list_add_locked(&listentry->entry, &client->idlist,
1161  &coredev->clientslock);
1162  return 0;
1163 }
1164 
1180  struct smsclient_params_t *params,
1181  struct smscore_client_t **client)
1182 {
1183  struct smscore_client_t *newclient;
1184  /* check that no other channel with same parameters exists */
1185  if (smscore_find_client(coredev, params->data_type,
1186  params->initial_id)) {
1187  sms_err("Client already exist.");
1188  return -EEXIST;
1189  }
1190 
1191  newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
1192  if (!newclient) {
1193  sms_err("Failed to allocate memory for client.");
1194  return -ENOMEM;
1195  }
1196 
1197  INIT_LIST_HEAD(&newclient->idlist);
1198  newclient->coredev = coredev;
1199  newclient->onresponse_handler = params->onresponse_handler;
1200  newclient->onremove_handler = params->onremove_handler;
1201  newclient->context = params->context;
1202  list_add_locked(&newclient->entry, &coredev->clients,
1203  &coredev->clientslock);
1204  smscore_validate_client(coredev, newclient, params->data_type,
1205  params->initial_id);
1206  *client = newclient;
1207  sms_debug("%p %d %d", params->context, params->data_type,
1208  params->initial_id);
1209 
1210  return 0;
1211 }
1213 
1222 {
1223  struct smscore_device_t *coredev = client->coredev;
1224  unsigned long flags;
1225 
1226  spin_lock_irqsave(&coredev->clientslock, flags);
1227 
1228 
1229  while (!list_empty(&client->idlist)) {
1230  struct smscore_idlist_t *identry =
1231  (struct smscore_idlist_t *) client->idlist.next;
1232  list_del(&identry->entry);
1233  kfree(identry);
1234  }
1235 
1236  sms_info("%p", client->context);
1237 
1238  list_del(&client->entry);
1239  kfree(client);
1240 
1241  spin_unlock_irqrestore(&coredev->clientslock, flags);
1242 }
1244 
1257  void *buffer, size_t size)
1258 {
1259  struct smscore_device_t *coredev;
1260  struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
1261  int rc;
1262 
1263  if (client == NULL) {
1264  sms_err("Got NULL client");
1265  return -EINVAL;
1266  }
1267 
1268  coredev = client->coredev;
1269 
1270  /* check that no other channel with same id exists */
1271  if (coredev == NULL) {
1272  sms_err("Got NULL coredev");
1273  return -EINVAL;
1274  }
1275 
1276  rc = smscore_validate_client(client->coredev, client, 0,
1277  phdr->msgSrcId);
1278  if (rc < 0)
1279  return rc;
1280 
1281  return coredev->sendrequest_handler(coredev->context, buffer, size);
1282 }
1284 
1285 
1286 /* old GPIO managements implementation */
1288  struct smscore_config_gpio *pinconfig)
1289 {
1290  struct {
1291  struct SmsMsgHdr_ST hdr;
1292  u32 data[6];
1293  } msg;
1294 
1295  if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
1297  msg.hdr.msgDstId = HIF_TASK;
1298  msg.hdr.msgFlags = 0;
1300  msg.hdr.msgLength = sizeof(msg);
1301 
1302  msg.data[0] = pin;
1303  msg.data[1] = pinconfig->pullupdown;
1304 
1305  /* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */
1306  msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0;
1307 
1308  switch (pinconfig->outputdriving) {
1310  msg.data[3] = 7; /* Nova - 16mA */
1311  break;
1313  msg.data[3] = 5; /* Nova - 11mA */
1314  break;
1316  msg.data[3] = 3; /* Nova - 7mA */
1317  break;
1319  default:
1320  msg.data[3] = 2; /* Nova - 4mA */
1321  break;
1322  }
1323 
1324  msg.data[4] = pinconfig->direction;
1325  msg.data[5] = 0;
1326  } else /* TODO: SMS_DEVICE_FAMILY1 */
1327  return -EINVAL;
1328 
1329  return coredev->sendrequest_handler(coredev->context,
1330  &msg, sizeof(msg));
1331 }
1332 
1333 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
1334 {
1335  struct {
1336  struct SmsMsgHdr_ST hdr;
1337  u32 data[3];
1338  } msg;
1339 
1340  if (pin > MAX_GPIO_PIN_NUMBER)
1341  return -EINVAL;
1342 
1344  msg.hdr.msgDstId = HIF_TASK;
1345  msg.hdr.msgFlags = 0;
1347  msg.hdr.msgLength = sizeof(msg);
1348 
1349  msg.data[0] = pin;
1350  msg.data[1] = level ? 1 : 0;
1351  msg.data[2] = 0;
1352 
1353  return coredev->sendrequest_handler(coredev->context,
1354  &msg, sizeof(msg));
1355 }
1356 
1357 /* new GPIO management implementation */
1358 static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
1359  u32 *pGroupNum, u32 *pGroupCfg) {
1360 
1361  *pGroupCfg = 1;
1362 
1363  if (PinNum <= 1) {
1364  *pTranslatedPinNum = 0;
1365  *pGroupNum = 9;
1366  *pGroupCfg = 2;
1367  } else if (PinNum >= 2 && PinNum <= 6) {
1368  *pTranslatedPinNum = 2;
1369  *pGroupNum = 0;
1370  *pGroupCfg = 2;
1371  } else if (PinNum >= 7 && PinNum <= 11) {
1372  *pTranslatedPinNum = 7;
1373  *pGroupNum = 1;
1374  } else if (PinNum >= 12 && PinNum <= 15) {
1375  *pTranslatedPinNum = 12;
1376  *pGroupNum = 2;
1377  *pGroupCfg = 3;
1378  } else if (PinNum == 16) {
1379  *pTranslatedPinNum = 16;
1380  *pGroupNum = 23;
1381  } else if (PinNum >= 17 && PinNum <= 24) {
1382  *pTranslatedPinNum = 17;
1383  *pGroupNum = 3;
1384  } else if (PinNum == 25) {
1385  *pTranslatedPinNum = 25;
1386  *pGroupNum = 6;
1387  } else if (PinNum >= 26 && PinNum <= 28) {
1388  *pTranslatedPinNum = 26;
1389  *pGroupNum = 4;
1390  } else if (PinNum == 29) {
1391  *pTranslatedPinNum = 29;
1392  *pGroupNum = 5;
1393  *pGroupCfg = 2;
1394  } else if (PinNum == 30) {
1395  *pTranslatedPinNum = 30;
1396  *pGroupNum = 8;
1397  } else if (PinNum == 31) {
1398  *pTranslatedPinNum = 31;
1399  *pGroupNum = 17;
1400  } else
1401  return -1;
1402 
1403  *pGroupCfg <<= 24;
1404 
1405  return 0;
1406 }
1407 
1408 int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
1409  struct smscore_gpio_config *pGpioConfig) {
1410 
1411  u32 totalLen;
1412  u32 TranslatedPinNum = 0;
1413  u32 GroupNum = 0;
1414  u32 ElectricChar;
1415  u32 groupCfg;
1416  void *buffer;
1417  int rc;
1418 
1419  struct SetGpioMsg {
1420  struct SmsMsgHdr_ST xMsgHeader;
1421  u32 msgData[6];
1422  } *pMsg;
1423 
1424 
1425  if (PinNum > MAX_GPIO_PIN_NUMBER)
1426  return -EINVAL;
1427 
1428  if (pGpioConfig == NULL)
1429  return -EINVAL;
1430 
1431  totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
1432 
1433  buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
1434  GFP_KERNEL | GFP_DMA);
1435  if (!buffer)
1436  return -ENOMEM;
1437 
1438  pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
1439 
1440  pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1441  pMsg->xMsgHeader.msgDstId = HIF_TASK;
1442  pMsg->xMsgHeader.msgFlags = 0;
1443  pMsg->xMsgHeader.msgLength = (u16) totalLen;
1444  pMsg->msgData[0] = PinNum;
1445 
1446  if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
1447  pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
1448  if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
1449  &groupCfg) != 0) {
1450  rc = -EINVAL;
1451  goto free;
1452  }
1453 
1454  pMsg->msgData[1] = TranslatedPinNum;
1455  pMsg->msgData[2] = GroupNum;
1456  ElectricChar = (pGpioConfig->PullUpDown)
1457  | (pGpioConfig->InputCharacteristics << 2)
1458  | (pGpioConfig->OutputSlewRate << 3)
1459  | (pGpioConfig->OutputDriving << 4);
1460  pMsg->msgData[3] = ElectricChar;
1461  pMsg->msgData[4] = pGpioConfig->Direction;
1462  pMsg->msgData[5] = groupCfg;
1463  } else {
1464  pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
1465  pMsg->msgData[1] = pGpioConfig->PullUpDown;
1466  pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
1467  pMsg->msgData[3] = pGpioConfig->OutputDriving;
1468  pMsg->msgData[4] = pGpioConfig->Direction;
1469  pMsg->msgData[5] = 0;
1470  }
1471 
1472  smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
1473  rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
1474  &coredev->gpio_configuration_done);
1475 
1476  if (rc != 0) {
1477  if (rc == -ETIME)
1478  sms_err("smscore_gpio_configure timeout");
1479  else
1480  sms_err("smscore_gpio_configure error");
1481  }
1482 free:
1483  kfree(buffer);
1484 
1485  return rc;
1486 }
1487 
1488 int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
1489  u8 NewLevel) {
1490 
1491  u32 totalLen;
1492  int rc;
1493  void *buffer;
1494 
1495  struct SetGpioMsg {
1496  struct SmsMsgHdr_ST xMsgHeader;
1497  u32 msgData[3]; /* keep it 3 ! */
1498  } *pMsg;
1499 
1500  if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER))
1501  return -EINVAL;
1502 
1503  totalLen = sizeof(struct SmsMsgHdr_ST) +
1504  (3 * sizeof(u32)); /* keep it 3 ! */
1505 
1506  buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
1507  GFP_KERNEL | GFP_DMA);
1508  if (!buffer)
1509  return -ENOMEM;
1510 
1511  pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
1512 
1513  pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1514  pMsg->xMsgHeader.msgDstId = HIF_TASK;
1515  pMsg->xMsgHeader.msgFlags = 0;
1516  pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
1517  pMsg->xMsgHeader.msgLength = (u16) totalLen;
1518  pMsg->msgData[0] = PinNum;
1519  pMsg->msgData[1] = NewLevel;
1520 
1521  /* Send message to SMS */
1522  smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
1523  rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
1524  &coredev->gpio_set_level_done);
1525 
1526  if (rc != 0) {
1527  if (rc == -ETIME)
1528  sms_err("smscore_gpio_set_level timeout");
1529  else
1530  sms_err("smscore_gpio_set_level error");
1531  }
1532  kfree(buffer);
1533 
1534  return rc;
1535 }
1536 
1537 int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
1538  u8 *level) {
1539 
1540  u32 totalLen;
1541  int rc;
1542  void *buffer;
1543 
1544  struct SetGpioMsg {
1545  struct SmsMsgHdr_ST xMsgHeader;
1546  u32 msgData[2];
1547  } *pMsg;
1548 
1549 
1550  if (PinNum > MAX_GPIO_PIN_NUMBER)
1551  return -EINVAL;
1552 
1553  totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
1554 
1555  buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
1556  GFP_KERNEL | GFP_DMA);
1557  if (!buffer)
1558  return -ENOMEM;
1559 
1560  pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
1561 
1562  pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1563  pMsg->xMsgHeader.msgDstId = HIF_TASK;
1564  pMsg->xMsgHeader.msgFlags = 0;
1565  pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
1566  pMsg->xMsgHeader.msgLength = (u16) totalLen;
1567  pMsg->msgData[0] = PinNum;
1568  pMsg->msgData[1] = 0;
1569 
1570  /* Send message to SMS */
1571  smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
1572  rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
1573  &coredev->gpio_get_level_done);
1574 
1575  if (rc != 0) {
1576  if (rc == -ETIME)
1577  sms_err("smscore_gpio_get_level timeout");
1578  else
1579  sms_err("smscore_gpio_get_level error");
1580  }
1581  kfree(buffer);
1582 
1583  /* Its a race between other gpio_get_level() and the copy of the single
1584  * global 'coredev->gpio_get_res' to the function's variable 'level'
1585  */
1586  *level = coredev->gpio_get_res;
1587 
1588  return rc;
1589 }
1590 
1591 static int __init smscore_module_init(void)
1592 {
1593  int rc = 0;
1594 
1595  INIT_LIST_HEAD(&g_smscore_notifyees);
1596  INIT_LIST_HEAD(&g_smscore_devices);
1597  kmutex_init(&g_smscore_deviceslock);
1598 
1599  INIT_LIST_HEAD(&g_smscore_registry);
1600  kmutex_init(&g_smscore_registrylock);
1601 
1602  return rc;
1603 }
1604 
1605 static void __exit smscore_module_exit(void)
1606 {
1607  kmutex_lock(&g_smscore_deviceslock);
1608  while (!list_empty(&g_smscore_notifyees)) {
1609  struct smscore_device_notifyee_t *notifyee =
1610  (struct smscore_device_notifyee_t *)
1611  g_smscore_notifyees.next;
1612 
1613  list_del(&notifyee->entry);
1614  kfree(notifyee);
1615  }
1616  kmutex_unlock(&g_smscore_deviceslock);
1617 
1618  kmutex_lock(&g_smscore_registrylock);
1619  while (!list_empty(&g_smscore_registry)) {
1620  struct smscore_registry_entry_t *entry =
1621  (struct smscore_registry_entry_t *)
1622  g_smscore_registry.next;
1623 
1624  list_del(&entry->entry);
1625  kfree(entry);
1626  }
1627  kmutex_unlock(&g_smscore_registrylock);
1628 
1629  sms_debug("");
1630 }
1631 
1632 module_init(smscore_module_init);
1633 module_exit(smscore_module_exit);
1634 
1635 MODULE_DESCRIPTION("Siano MDTV Core module");
1636 MODULE_AUTHOR("Siano Mobile Silicon, Inc. ([email protected])");
1637 MODULE_LICENSE("GPL");