[media] siano: get rid of warning: no previous prototype
[deliverable/linux.git] / drivers / media / common / siano / smscoreapi.c
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
46 struct smscore_device_notifyee_t {
47 struct list_head entry;
48 hotplug_t hotplug;
49 };
50
51 struct smscore_idlist_t {
52 struct list_head entry;
53 int id;
54 int data_type;
55 };
56
57 struct smscore_client_t {
58 struct list_head entry;
59 struct smscore_device_t *coredev;
60 void *context;
61 struct list_head idlist;
62 onresponse_t onresponse_handler;
63 onremove_t onremove_handler;
64 };
65
66 void smscore_set_board_id(struct smscore_device_t *core, int id)
67 {
68 core->board_id = id;
69 }
70
71 int smscore_led_state(struct smscore_device_t *core, int led)
72 {
73 if (led >= 0)
74 core->led_state = led;
75 return core->led_state;
76 }
77 EXPORT_SYMBOL_GPL(smscore_set_board_id);
78
79 int smscore_get_board_id(struct smscore_device_t *core)
80 {
81 return core->board_id;
82 }
83 EXPORT_SYMBOL_GPL(smscore_get_board_id);
84
85 struct smscore_registry_entry_t {
86 struct list_head entry;
87 char devpath[32];
88 int mode;
89 enum sms_device_type_st type;
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 {
106 struct smscore_registry_entry_t *entry;
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 {
132 struct smscore_registry_entry_t *entry;
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 }
142 EXPORT_SYMBOL_GPL(smscore_registry_getmode);
143
144 static enum sms_device_type_st smscore_registry_gettype(char *devpath)
145 {
146 struct smscore_registry_entry_t *entry;
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 {
159 struct smscore_registry_entry_t *entry;
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,
169 enum sms_device_type_st type)
170 {
171 struct smscore_registry_entry_t *entry;
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
193 /**
194 * register a client callback that called when device plugged in/unplugged
195 * NOTE: if devices exist callback is called immediately for each device
196 *
197 * @param hotplug callback
198 *
199 * @return 0 on success, <0 on error.
200 */
201 int smscore_register_hotplug(hotplug_t hotplug)
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 }
234 EXPORT_SYMBOL_GPL(smscore_register_hotplug);
235
236 /**
237 * unregister a client callback that called when device plugged in/unplugged
238 *
239 * @param hotplug callback
240 *
241 */
242 void smscore_unregister_hotplug(hotplug_t hotplug)
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 }
263 EXPORT_SYMBOL_GPL(smscore_unregister_hotplug);
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 {
279 struct smscore_device_notifyee_t *elem;
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
311 /**
312 * creates coredev object for a device, prepares buffers,
313 * creates buffer mappings, notifies registered hotplugs about new device.
314 *
315 * @param params device pointer to struct with device specific parameters
316 * and handlers
317 * @param coredev pointer to a value that receives created coredev object
318 *
319 * @return 0 on success, <0 on error.
320 */
321 int smscore_register_device(struct smsdevice_params_t *params,
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 */
341 spin_lock_init(&dev->clientslock);
342 spin_lock_init(&dev->bufferslock);
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 */
357 init_waitqueue_head(&dev->buffer_mng_waitq);
358
359 /* alloc common buffer */
360 dev->common_buffer_size = params->buffer_size * params->num_buffers;
361 dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
362 &dev->common_buffer_phys,
363 GFP_KERNEL | GFP_DMA);
364 if (!dev->common_buffer) {
365 smscore_unregister_device(dev);
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) {
377 smscore_unregister_device(dev);
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;
391 dev->sendrequest_handler = params->sendrequest_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 }
411 EXPORT_SYMBOL_GPL(smscore_register_device);
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,
423 msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ?
424 0 : -ETIME;
425 }
426
427 /**
428 * Starts & enables IR operations
429 *
430 * @return 0 on success, < 0 on error.
431 */
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) +
448 SMS_DMA_ALIGNMENT,
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,
456 MSG_SMS_START_IR_REQ,
457 sizeof(struct SmsMsgData_ST2));
458 msg->msgData[0] = coredev->ir.controller;
459 msg->msgData[1] = coredev->ir.timeout;
460
461 smsendian_handle_tx_message(
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
478 /**
479 * sets initial device mode and notifies client hotplugs that device is ready
480 *
481 * @param coredev pointer to a coredev object returned by
482 * smscore_register_device
483 *
484 * @return 0 on success, <0 on error.
485 */
486 int smscore_start_device(struct smscore_device_t *coredev)
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 }
506 EXPORT_SYMBOL_GPL(smscore_start_device);
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 */
531 msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
532 if (!msg)
533 return -ENOMEM;
534
535 if (coredev->mode != DEVICE_MODE_NONE) {
536 sms_debug("sending reload command.");
537 SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
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
550 SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
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
578 SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
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 {
600 SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
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
619 /**
620 * loads specified firmware into a buffer and calls device loadfirmware_handler
621 *
622 * @param coredev pointer to a coredev object returned by
623 * smscore_register_device
624 * @param filename null-terminated string specifies firmware file name
625 * @param loadfirmware_handler device handler that loads firmware
626 *
627 * @return 0 on success, <0 on error.
628 */
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 &
638 SMS_DEVICE_FAMILY2))
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
670 /**
671 * notifies all clients registered with the device, notifies hotplugs,
672 * frees all buffers and coredev object
673 *
674 * @param coredev pointer to a coredev object returned by
675 * smscore_register_device
676 *
677 * @return 0 on success, <0 on error.
678 */
679 void smscore_unregister_device(struct smscore_device_t *coredev)
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)
719 dma_free_coherent(NULL, coredev->common_buffer_size,
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 }
732 EXPORT_SYMBOL_GPL(smscore_unregister_device);
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
745 SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
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
753 if (wait_for_completion_timeout(&coredev->resume_done,
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
797 /**
798 * calls device handler to change mode of operation
799 * NOTE: stellar/usb may disconnect when changing mode
800 *
801 * @param coredev pointer to a coredev object returned by
802 * smscore_register_device
803 * @param mode requested mode of operation
804 *
805 * @return 0 on success, <0 on error.
806 */
807 int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
808 {
809 void *buffer;
810 int rc = 0;
811 enum sms_device_type_st type;
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) +
866 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
867 if (buffer) {
868 struct SmsMsgData_ST *msg =
869 (struct SmsMsgData_ST *)
870 SMS_ALIGN_ADDRESS(buffer);
871
872 SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
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
912 /**
913 * calls device handler to get current mode of operation
914 *
915 * @param coredev pointer to a coredev object returned by
916 * smscore_register_device
917 *
918 * @return current mode
919 */
920 int smscore_get_device_mode(struct smscore_device_t *coredev)
921 {
922 return coredev->mode;
923 }
924 EXPORT_SYMBOL_GPL(smscore_get_device_mode);
925
926 /**
927 * find client by response id & type within the clients list.
928 * return client handle or NULL.
929 *
930 * @param coredev pointer to a coredev object returned by
931 * smscore_register_device
932 * @param data_type client data type (SMS_DONT_CARE for all types)
933 * @param id client id (SMS_DONT_CARE for all id)
934 *
935 */
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
963 /**
964 * find client by response id/type, call clients onresponse handler
965 * return buffer to pool on error
966 *
967 * @param coredev pointer to a coredev object returned by
968 * smscore_register_device
969 * @param cb pointer to response buffer descriptor
970 *
971 */
972 void smscore_onresponse(struct smscore_device_t *coredev,
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)
999 phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID;
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) {
1012 case MSG_SMS_GET_VERSION_EX_RES:
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 ?
1022 DEVICE_MODE_NONE : ver->FirmwareId;
1023 coredev->modes_supported = ver->SupportedProtocols;
1024
1025 complete(&coredev->version_ex_done);
1026 break;
1027 }
1028 case MSG_SMS_INIT_DEVICE_RES:
1029 sms_debug("MSG_SMS_INIT_DEVICE_RES");
1030 complete(&coredev->init_device_done);
1031 break;
1032 case MSG_SW_RELOAD_START_RES:
1033 sms_debug("MSG_SW_RELOAD_START_RES");
1034 complete(&coredev->reload_start_done);
1035 break;
1036 case MSG_SMS_DATA_DOWNLOAD_RES:
1037 complete(&coredev->data_download_done);
1038 break;
1039 case MSG_SW_RELOAD_EXEC_RES:
1040 sms_debug("MSG_SW_RELOAD_EXEC_RES");
1041 break;
1042 case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
1043 sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
1044 complete(&coredev->trigger_done);
1045 break;
1046 case MSG_SMS_SLEEP_RESUME_COMP_IND:
1047 complete(&coredev->resume_done);
1048 break;
1049 case MSG_SMS_GPIO_CONFIG_EX_RES:
1050 sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
1051 complete(&coredev->gpio_configuration_done);
1052 break;
1053 case MSG_SMS_GPIO_SET_LEVEL_RES:
1054 sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
1055 complete(&coredev->gpio_set_level_done);
1056 break;
1057 case MSG_SMS_GPIO_GET_LEVEL_RES:
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;
1069 case MSG_SMS_IR_SAMPLES_IND:
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 }
1084 EXPORT_SYMBOL_GPL(smscore_onresponse);
1085
1086 /**
1087 * return pointer to next free buffer descriptor from core pool
1088 *
1089 * @param coredev pointer to a coredev object returned by
1090 * smscore_register_device
1091 *
1092 * @return pointer to descriptor on success, NULL on error.
1093 */
1094
1095 static struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
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
1109 struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
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 }
1117 EXPORT_SYMBOL_GPL(smscore_getbuffer);
1118
1119 /**
1120 * return buffer descriptor to a pool
1121 *
1122 * @param coredev pointer to a coredev object returned by
1123 * smscore_register_device
1124 * @param cb pointer buffer descriptor
1125 *
1126 */
1127 void smscore_putbuffer(struct smscore_device_t *coredev,
1128 struct smscore_buffer_t *cb) {
1129 wake_up_interruptible(&coredev->buffer_mng_waitq);
1130 list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
1131 }
1132 EXPORT_SYMBOL_GPL(smscore_putbuffer);
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
1165 /**
1166 * creates smsclient object, check that id is taken by another client
1167 *
1168 * @param coredev pointer to a coredev object from clients hotplug
1169 * @param initial_id all messages with this id would be sent to this client
1170 * @param data_type all messages of this type would be sent to this client
1171 * @param onresponse_handler client handler that is called to
1172 * process incoming messages
1173 * @param onremove_handler client handler that is called when device is removed
1174 * @param context client-specific context
1175 * @param client pointer to a value that receives created smsclient object
1176 *
1177 * @return 0 on success, <0 on error.
1178 */
1179 int smscore_register_client(struct smscore_device_t *coredev,
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 }
1212 EXPORT_SYMBOL_GPL(smscore_register_client);
1213
1214 /**
1215 * frees smsclient object and all subclients associated with it
1216 *
1217 * @param client pointer to smsclient object returned by
1218 * smscore_register_client
1219 *
1220 */
1221 void smscore_unregister_client(struct smscore_client_t *client)
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 }
1243 EXPORT_SYMBOL_GPL(smscore_unregister_client);
1244
1245 /**
1246 * verifies that source id is not taken by another client,
1247 * calls device handler to send requests to the device
1248 *
1249 * @param client pointer to smsclient object returned by
1250 * smscore_register_client
1251 * @param buffer pointer to a request buffer
1252 * @param size size (in bytes) of request buffer
1253 *
1254 * @return 0 on success, <0 on error.
1255 */
1256 int smsclient_sendrequest(struct smscore_client_t *client,
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 }
1283 EXPORT_SYMBOL_GPL(smsclient_sendrequest);
1284
1285
1286 /* old GPIO managements implementation */
1287 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
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) {
1296 msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1297 msg.hdr.msgDstId = HIF_TASK;
1298 msg.hdr.msgFlags = 0;
1299 msg.hdr.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
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) {
1309 case SMS_GPIO_OUTPUTDRIVING_16mA:
1310 msg.data[3] = 7; /* Nova - 16mA */
1311 break;
1312 case SMS_GPIO_OUTPUTDRIVING_12mA:
1313 msg.data[3] = 5; /* Nova - 11mA */
1314 break;
1315 case SMS_GPIO_OUTPUTDRIVING_8mA:
1316 msg.data[3] = 3; /* Nova - 7mA */
1317 break;
1318 case SMS_GPIO_OUTPUTDRIVING_4mA:
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
1343 msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1344 msg.hdr.msgDstId = HIF_TASK;
1345 msg.hdr.msgFlags = 0;
1346 msg.hdr.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
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. (uris@siano-ms.com)");
1637 MODULE_LICENSE("GPL");
This page took 0.073394 seconds and 5 git commands to generate.