Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq
[pandora-kernel.git] / drivers / media / dvb / 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: Anatoly Greenblat
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
32 #include <linux/firmware.h>
33
34 #include "smscoreapi.h"
35 #include "sms-cards.h"
36
37 int sms_debug;
38 module_param_named(debug, sms_debug, int, 0644);
39 MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
40
41 struct smscore_device_notifyee_t {
42         struct list_head entry;
43         hotplug_t hotplug;
44 };
45
46 struct smscore_idlist_t {
47         struct list_head entry;
48         int             id;
49         int             data_type;
50 };
51
52 struct smscore_client_t {
53         struct list_head entry;
54         struct smscore_device_t *coredev;
55         void                    *context;
56         struct list_head        idlist;
57         onresponse_t    onresponse_handler;
58         onremove_t              onremove_handler;
59 };
60
61 struct smscore_device_t {
62         struct list_head entry;
63
64         struct list_head clients;
65         struct list_head subclients;
66         spinlock_t              clientslock;
67
68         struct list_head buffers;
69         spinlock_t              bufferslock;
70         int                             num_buffers;
71
72         void                    *common_buffer;
73         int                             common_buffer_size;
74         dma_addr_t              common_buffer_phys;
75
76         void                    *context;
77         struct device   *device;
78
79         char                    devpath[32];
80         unsigned long   device_flags;
81
82         setmode_t               setmode_handler;
83         detectmode_t    detectmode_handler;
84         sendrequest_t   sendrequest_handler;
85         preload_t               preload_handler;
86         postload_t              postload_handler;
87
88         int                             mode, modes_supported;
89
90         struct completion version_ex_done, data_download_done, trigger_done;
91         struct completion init_device_done, reload_start_done, resume_done;
92
93         int board_id;
94         int led_state;
95 };
96
97 void smscore_set_board_id(struct smscore_device_t *core, int id)
98 {
99         core->board_id = id;
100 }
101
102 int smscore_led_state(struct smscore_device_t *core, int led)
103 {
104         if (led >= 0)
105                 core->led_state = led;
106         return core->led_state;
107 }
108
109 int smscore_get_board_id(struct smscore_device_t *core)
110 {
111         return core->board_id;
112 }
113
114 struct smscore_registry_entry_t {
115         struct list_head entry;
116         char                    devpath[32];
117         int                             mode;
118         enum sms_device_type_st type;
119 };
120
121 static struct list_head g_smscore_notifyees;
122 static struct list_head g_smscore_devices;
123 static struct mutex g_smscore_deviceslock;
124
125 static struct list_head g_smscore_registry;
126 static struct mutex g_smscore_registrylock;
127
128 static int default_mode = 4;
129
130 module_param(default_mode, int, 0644);
131 MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
132
133 static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
134 {
135         struct smscore_registry_entry_t *entry;
136         struct list_head *next;
137
138         kmutex_lock(&g_smscore_registrylock);
139         for (next = g_smscore_registry.next;
140              next != &g_smscore_registry;
141              next = next->next) {
142                 entry = (struct smscore_registry_entry_t *) next;
143                 if (!strcmp(entry->devpath, devpath)) {
144                         kmutex_unlock(&g_smscore_registrylock);
145                         return entry;
146                 }
147         }
148         entry = (struct smscore_registry_entry_t *)
149                         kmalloc(sizeof(struct smscore_registry_entry_t),
150                                 GFP_KERNEL);
151         if (entry) {
152                 entry->mode = default_mode;
153                 strcpy(entry->devpath, devpath);
154                 list_add(&entry->entry, &g_smscore_registry);
155         } else
156                 sms_err("failed to create smscore_registry.");
157         kmutex_unlock(&g_smscore_registrylock);
158         return entry;
159 }
160
161 int smscore_registry_getmode(char *devpath)
162 {
163         struct smscore_registry_entry_t *entry;
164
165         entry = smscore_find_registry(devpath);
166         if (entry)
167                 return entry->mode;
168         else
169                 sms_err("No registry found.");
170
171         return default_mode;
172 }
173
174 static enum sms_device_type_st smscore_registry_gettype(char *devpath)
175 {
176         struct smscore_registry_entry_t *entry;
177
178         entry = smscore_find_registry(devpath);
179         if (entry)
180                 return entry->type;
181         else
182                 sms_err("No registry found.");
183
184         return -1;
185 }
186
187 void smscore_registry_setmode(char *devpath, int mode)
188 {
189         struct smscore_registry_entry_t *entry;
190
191         entry = smscore_find_registry(devpath);
192         if (entry)
193                 entry->mode = mode;
194         else
195                 sms_err("No registry found.");
196 }
197
198 static void smscore_registry_settype(char *devpath,
199                                      enum sms_device_type_st type)
200 {
201         struct smscore_registry_entry_t *entry;
202
203         entry = smscore_find_registry(devpath);
204         if (entry)
205                 entry->type = type;
206         else
207                 sms_err("No registry found.");
208 }
209
210
211 static void list_add_locked(struct list_head *new, struct list_head *head,
212                             spinlock_t *lock)
213 {
214         unsigned long flags;
215
216         spin_lock_irqsave(lock, flags);
217
218         list_add(new, head);
219
220         spin_unlock_irqrestore(lock, flags);
221 }
222
223 /**
224  * register a client callback that called when device plugged in/unplugged
225  * NOTE: if devices exist callback is called immediately for each device
226  *
227  * @param hotplug callback
228  *
229  * @return 0 on success, <0 on error.
230  */
231 int smscore_register_hotplug(hotplug_t hotplug)
232 {
233         struct smscore_device_notifyee_t *notifyee;
234         struct list_head *next, *first;
235         int rc = 0;
236
237         kmutex_lock(&g_smscore_deviceslock);
238
239         notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
240                            GFP_KERNEL);
241         if (notifyee) {
242                 /* now notify callback about existing devices */
243                 first = &g_smscore_devices;
244                 for (next = first->next;
245                      next != first && !rc;
246                      next = next->next) {
247                         struct smscore_device_t *coredev =
248                                 (struct smscore_device_t *) next;
249                         rc = hotplug(coredev, coredev->device, 1);
250                 }
251
252                 if (rc >= 0) {
253                         notifyee->hotplug = hotplug;
254                         list_add(&notifyee->entry, &g_smscore_notifyees);
255                 } else
256                         kfree(notifyee);
257         } else
258                 rc = -ENOMEM;
259
260         kmutex_unlock(&g_smscore_deviceslock);
261
262         return rc;
263 }
264
265 /**
266  * unregister a client callback that called when device plugged in/unplugged
267  *
268  * @param hotplug callback
269  *
270  */
271 void smscore_unregister_hotplug(hotplug_t hotplug)
272 {
273         struct list_head *next, *first;
274
275         kmutex_lock(&g_smscore_deviceslock);
276
277         first = &g_smscore_notifyees;
278
279         for (next = first->next; next != first;) {
280                 struct smscore_device_notifyee_t *notifyee =
281                         (struct smscore_device_notifyee_t *) next;
282                 next = next->next;
283
284                 if (notifyee->hotplug == hotplug) {
285                         list_del(&notifyee->entry);
286                         kfree(notifyee);
287                 }
288         }
289
290         kmutex_unlock(&g_smscore_deviceslock);
291 }
292
293 static void smscore_notify_clients(struct smscore_device_t *coredev)
294 {
295         struct smscore_client_t *client;
296
297         /* the client must call smscore_unregister_client from remove handler */
298         while (!list_empty(&coredev->clients)) {
299                 client = (struct smscore_client_t *) coredev->clients.next;
300                 client->onremove_handler(client->context);
301         }
302 }
303
304 static int smscore_notify_callbacks(struct smscore_device_t *coredev,
305                                     struct device *device, int arrival)
306 {
307         struct list_head *next, *first;
308         int rc = 0;
309
310         /* note: must be called under g_deviceslock */
311
312         first = &g_smscore_notifyees;
313
314         for (next = first->next; next != first; next = next->next) {
315                 rc = ((struct smscore_device_notifyee_t *) next)->
316                                 hotplug(coredev, device, arrival);
317                 if (rc < 0)
318                         break;
319         }
320
321         return rc;
322 }
323
324 static struct
325 smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
326                                        dma_addr_t common_buffer_phys)
327 {
328         struct smscore_buffer_t *cb =
329                 kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
330         if (!cb) {
331                 sms_info("kmalloc(...) failed");
332                 return NULL;
333         }
334
335         cb->p = buffer;
336         cb->offset_in_common = buffer - (u8 *) common_buffer;
337         cb->phys = common_buffer_phys + cb->offset_in_common;
338
339         return cb;
340 }
341
342 /**
343  * creates coredev object for a device, prepares buffers,
344  * creates buffer mappings, notifies registered hotplugs about new device.
345  *
346  * @param params device pointer to struct with device specific parameters
347  *               and handlers
348  * @param coredev pointer to a value that receives created coredev object
349  *
350  * @return 0 on success, <0 on error.
351  */
352 int smscore_register_device(struct smsdevice_params_t *params,
353                             struct smscore_device_t **coredev)
354 {
355         struct smscore_device_t *dev;
356         u8 *buffer;
357
358         dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
359         if (!dev) {
360                 sms_info("kzalloc(...) failed");
361                 return -ENOMEM;
362         }
363
364         /* init list entry so it could be safe in smscore_unregister_device */
365         INIT_LIST_HEAD(&dev->entry);
366
367         /* init queues */
368         INIT_LIST_HEAD(&dev->clients);
369         INIT_LIST_HEAD(&dev->buffers);
370
371         /* init locks */
372         spin_lock_init(&dev->clientslock);
373         spin_lock_init(&dev->bufferslock);
374
375         /* init completion events */
376         init_completion(&dev->version_ex_done);
377         init_completion(&dev->data_download_done);
378         init_completion(&dev->trigger_done);
379         init_completion(&dev->init_device_done);
380         init_completion(&dev->reload_start_done);
381         init_completion(&dev->resume_done);
382
383         /* alloc common buffer */
384         dev->common_buffer_size = params->buffer_size * params->num_buffers;
385         dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
386                                                 &dev->common_buffer_phys,
387                                                 GFP_KERNEL | GFP_DMA);
388         if (!dev->common_buffer) {
389                 smscore_unregister_device(dev);
390                 return -ENOMEM;
391         }
392
393         /* prepare dma buffers */
394         for (buffer = dev->common_buffer;
395              dev->num_buffers < params->num_buffers;
396              dev->num_buffers++, buffer += params->buffer_size) {
397                 struct smscore_buffer_t *cb =
398                         smscore_createbuffer(buffer, dev->common_buffer,
399                                              dev->common_buffer_phys);
400                 if (!cb) {
401                         smscore_unregister_device(dev);
402                         return -ENOMEM;
403                 }
404
405                 smscore_putbuffer(dev, cb);
406         }
407
408         sms_info("allocated %d buffers", dev->num_buffers);
409
410         dev->mode = DEVICE_MODE_NONE;
411         dev->context = params->context;
412         dev->device = params->device;
413         dev->setmode_handler = params->setmode_handler;
414         dev->detectmode_handler = params->detectmode_handler;
415         dev->sendrequest_handler = params->sendrequest_handler;
416         dev->preload_handler = params->preload_handler;
417         dev->postload_handler = params->postload_handler;
418
419         dev->device_flags = params->flags;
420         strcpy(dev->devpath, params->devpath);
421
422         smscore_registry_settype(dev->devpath, params->device_type);
423
424         /* add device to devices list */
425         kmutex_lock(&g_smscore_deviceslock);
426         list_add(&dev->entry, &g_smscore_devices);
427         kmutex_unlock(&g_smscore_deviceslock);
428
429         *coredev = dev;
430
431         sms_info("device %p created", dev);
432
433         return 0;
434 }
435
436 /**
437  * sets initial device mode and notifies client hotplugs that device is ready
438  *
439  * @param coredev pointer to a coredev object returned by
440  *                smscore_register_device
441  *
442  * @return 0 on success, <0 on error.
443  */
444 int smscore_start_device(struct smscore_device_t *coredev)
445 {
446         int rc = smscore_set_device_mode(
447                         coredev, smscore_registry_getmode(coredev->devpath));
448         if (rc < 0) {
449                 sms_info("set device mode faile , rc %d", rc);
450                 return rc;
451         }
452
453         kmutex_lock(&g_smscore_deviceslock);
454
455         rc = smscore_notify_callbacks(coredev, coredev->device, 1);
456
457         sms_info("device %p started, rc %d", coredev, rc);
458
459         kmutex_unlock(&g_smscore_deviceslock);
460
461         return rc;
462 }
463
464 static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
465                                         void *buffer, size_t size,
466                                         struct completion *completion)
467 {
468         int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
469         if (rc < 0) {
470                 sms_info("sendrequest returned error %d", rc);
471                 return rc;
472         }
473
474         return wait_for_completion_timeout(completion,
475                                            msecs_to_jiffies(10000)) ?
476                                                 0 : -ETIME;
477 }
478
479 static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
480                                          void *buffer, size_t size)
481 {
482         struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
483         struct SmsMsgHdr_ST *msg;
484         u32 mem_address = firmware->StartAddress;
485         u8 *payload = firmware->Payload;
486         int rc = 0;
487
488         sms_info("loading FW to addr 0x%x size %d",
489                  mem_address, firmware->Length);
490         if (coredev->preload_handler) {
491                 rc = coredev->preload_handler(coredev->context);
492                 if (rc < 0)
493                         return rc;
494         }
495
496         /* PAGE_SIZE buffer shall be enough and dma aligned */
497         msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
498         if (!msg)
499                 return -ENOMEM;
500
501         if (coredev->mode != DEVICE_MODE_NONE) {
502                 sms_debug("sending reload command.");
503                 SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
504                              sizeof(struct SmsMsgHdr_ST));
505                 rc = smscore_sendrequest_and_wait(coredev, msg,
506                                                   msg->msgLength,
507                                                   &coredev->reload_start_done);
508                 mem_address = *(u32 *) &payload[20];
509         }
510
511         while (size && rc >= 0) {
512                 struct SmsDataDownload_ST *DataMsg =
513                         (struct SmsDataDownload_ST *) msg;
514                 int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
515
516                 SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
517                              (u16)(sizeof(struct SmsMsgHdr_ST) +
518                                       sizeof(u32) + payload_size));
519
520                 DataMsg->MemAddr = mem_address;
521                 memcpy(DataMsg->Payload, payload, payload_size);
522
523                 if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
524                     (coredev->mode == DEVICE_MODE_NONE))
525                         rc = coredev->sendrequest_handler(
526                                 coredev->context, DataMsg,
527                                 DataMsg->xMsgHeader.msgLength);
528                 else
529                         rc = smscore_sendrequest_and_wait(
530                                 coredev, DataMsg,
531                                 DataMsg->xMsgHeader.msgLength,
532                                 &coredev->data_download_done);
533
534                 payload += payload_size;
535                 size -= payload_size;
536                 mem_address += payload_size;
537         }
538
539         if (rc >= 0) {
540                 if (coredev->mode == DEVICE_MODE_NONE) {
541                         struct SmsMsgData_ST *TriggerMsg =
542                                 (struct SmsMsgData_ST *) msg;
543
544                         SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
545                                      sizeof(struct SmsMsgHdr_ST) +
546                                      sizeof(u32) * 5);
547
548                         TriggerMsg->msgData[0] = firmware->StartAddress;
549                                                 /* Entry point */
550                         TriggerMsg->msgData[1] = 5; /* Priority */
551                         TriggerMsg->msgData[2] = 0x200; /* Stack size */
552                         TriggerMsg->msgData[3] = 0; /* Parameter */
553                         TriggerMsg->msgData[4] = 4; /* Task ID */
554
555                         if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
556                                 rc = coredev->sendrequest_handler(
557                                         coredev->context, TriggerMsg,
558                                         TriggerMsg->xMsgHeader.msgLength);
559                                 msleep(100);
560                         } else
561                                 rc = smscore_sendrequest_and_wait(
562                                         coredev, TriggerMsg,
563                                         TriggerMsg->xMsgHeader.msgLength,
564                                         &coredev->trigger_done);
565                 } else {
566                         SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
567                                      sizeof(struct SmsMsgHdr_ST));
568
569                         rc = coredev->sendrequest_handler(coredev->context,
570                                                           msg, msg->msgLength);
571                 }
572                 msleep(500);
573         }
574
575         sms_debug("rc=%d, postload=%p ", rc,
576                   coredev->postload_handler);
577
578         kfree(msg);
579
580         return ((rc >= 0) && coredev->postload_handler) ?
581                 coredev->postload_handler(coredev->context) :
582                 rc;
583 }
584
585 /**
586  * loads specified firmware into a buffer and calls device loadfirmware_handler
587  *
588  * @param coredev pointer to a coredev object returned by
589  *                smscore_register_device
590  * @param filename null-terminated string specifies firmware file name
591  * @param loadfirmware_handler device handler that loads firmware
592  *
593  * @return 0 on success, <0 on error.
594  */
595 static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
596                                            char *filename,
597                                            loadfirmware_t loadfirmware_handler)
598 {
599         int rc = -ENOENT;
600         const struct firmware *fw;
601         u8 *fw_buffer;
602
603         if (loadfirmware_handler == NULL && !(coredev->device_flags &
604                                               SMS_DEVICE_FAMILY2))
605                 return -EINVAL;
606
607         rc = request_firmware(&fw, filename, coredev->device);
608         if (rc < 0) {
609                 sms_info("failed to open \"%s\"", filename);
610                 return rc;
611         }
612         sms_info("read FW %s, size=%zd", filename, fw->size);
613         fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
614                             GFP_KERNEL | GFP_DMA);
615         if (fw_buffer) {
616                 memcpy(fw_buffer, fw->data, fw->size);
617
618                 rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
619                       smscore_load_firmware_family2(coredev,
620                                                     fw_buffer,
621                                                     fw->size) :
622                       loadfirmware_handler(coredev->context,
623                                            fw_buffer, fw->size);
624
625                 kfree(fw_buffer);
626         } else {
627                 sms_info("failed to allocate firmware buffer");
628                 rc = -ENOMEM;
629         }
630
631         release_firmware(fw);
632
633         return rc;
634 }
635
636 /**
637  * notifies all clients registered with the device, notifies hotplugs,
638  * frees all buffers and coredev object
639  *
640  * @param coredev pointer to a coredev object returned by
641  *                smscore_register_device
642  *
643  * @return 0 on success, <0 on error.
644  */
645 void smscore_unregister_device(struct smscore_device_t *coredev)
646 {
647         struct smscore_buffer_t *cb;
648         int num_buffers = 0;
649         int retry = 0;
650
651         kmutex_lock(&g_smscore_deviceslock);
652
653         smscore_notify_clients(coredev);
654         smscore_notify_callbacks(coredev, NULL, 0);
655
656         /* at this point all buffers should be back
657          * onresponse must no longer be called */
658
659         while (1) {
660                 while ((cb = smscore_getbuffer(coredev))) {
661                         kfree(cb);
662                         num_buffers++;
663                 }
664                 if (num_buffers == coredev->num_buffers)
665                         break;
666                 if (++retry > 10) {
667                         sms_info("exiting although "
668                                  "not all buffers released.");
669                         break;
670                 }
671
672                 sms_info("waiting for %d buffer(s)",
673                          coredev->num_buffers - num_buffers);
674                 msleep(100);
675         }
676
677         sms_info("freed %d buffers", num_buffers);
678
679         if (coredev->common_buffer)
680                 dma_free_coherent(NULL, coredev->common_buffer_size,
681                                   coredev->common_buffer,
682                                   coredev->common_buffer_phys);
683
684         list_del(&coredev->entry);
685         kfree(coredev);
686
687         kmutex_unlock(&g_smscore_deviceslock);
688
689         sms_info("device %p destroyed", coredev);
690 }
691
692 static int smscore_detect_mode(struct smscore_device_t *coredev)
693 {
694         void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
695                                GFP_KERNEL | GFP_DMA);
696         struct SmsMsgHdr_ST *msg =
697                 (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
698         int rc;
699
700         if (!buffer)
701                 return -ENOMEM;
702
703         SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
704                      sizeof(struct SmsMsgHdr_ST));
705
706         rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
707                                           &coredev->version_ex_done);
708         if (rc == -ETIME) {
709                 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
710
711                 if (wait_for_completion_timeout(&coredev->resume_done,
712                                                 msecs_to_jiffies(5000))) {
713                         rc = smscore_sendrequest_and_wait(
714                                 coredev, msg, msg->msgLength,
715                                 &coredev->version_ex_done);
716                         if (rc < 0)
717                                 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
718                                         "second try, rc %d", rc);
719                 } else
720                         rc = -ETIME;
721         }
722
723         kfree(buffer);
724
725         return rc;
726 }
727
728 static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
729         /*Stellar               NOVA A0         Nova B0         VEGA*/
730         /*DVBT*/
731         {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
732         /*DVBH*/
733         {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
734         /*TDMB*/
735         {"none", "tdmb_nova_12mhz.inp", "none", "none"},
736         /*DABIP*/
737         {"none", "none", "none", "none"},
738         /*BDA*/
739         {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
740         /*ISDBT*/
741         {"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"},
742         /*ISDBTBDA*/
743         {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
744         /*CMMB*/
745         {"none", "none", "none", "cmmb_vega_12mhz.inp"}
746 };
747
748 static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
749                                     int mode, enum sms_device_type_st type)
750 {
751         char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
752         return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
753 }
754
755 /**
756  * calls device handler to change mode of operation
757  * NOTE: stellar/usb may disconnect when changing mode
758  *
759  * @param coredev pointer to a coredev object returned by
760  *                smscore_register_device
761  * @param mode requested mode of operation
762  *
763  * @return 0 on success, <0 on error.
764  */
765 int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
766 {
767         void *buffer;
768         int rc = 0;
769         enum sms_device_type_st type;
770
771         sms_debug("set device mode to %d", mode);
772         if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
773                 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) {
774                         sms_err("invalid mode specified %d", mode);
775                         return -EINVAL;
776                 }
777
778                 smscore_registry_setmode(coredev->devpath, mode);
779
780                 if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
781                         rc = smscore_detect_mode(coredev);
782                         if (rc < 0) {
783                                 sms_err("mode detect failed %d", rc);
784                                 return rc;
785                         }
786                 }
787
788                 if (coredev->mode == mode) {
789                         sms_info("device mode %d already set", mode);
790                         return 0;
791                 }
792
793                 if (!(coredev->modes_supported & (1 << mode))) {
794                         char *fw_filename;
795
796                         type = smscore_registry_gettype(coredev->devpath);
797                         fw_filename = sms_get_fw_name(coredev, mode, type);
798
799                         rc = smscore_load_firmware_from_file(coredev,
800                                                              fw_filename, NULL);
801                         if (rc < 0) {
802                                 sms_warn("error %d loading firmware: %s, "
803                                          "trying again with default firmware",
804                                          rc, fw_filename);
805
806                                 /* try again with the default firmware */
807                                 fw_filename = smscore_fw_lkup[mode][type];
808                                 rc = smscore_load_firmware_from_file(coredev,
809                                                              fw_filename, NULL);
810
811                                 if (rc < 0) {
812                                         sms_warn("error %d loading "
813                                                  "firmware: %s", rc,
814                                                  fw_filename);
815                                         return rc;
816                                 }
817                         }
818                         sms_log("firmware download success: %s", fw_filename);
819                 } else
820                         sms_info("mode %d supported by running "
821                                  "firmware", mode);
822
823                 buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
824                                  SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
825                 if (buffer) {
826                         struct SmsMsgData_ST *msg =
827                                 (struct SmsMsgData_ST *)
828                                         SMS_ALIGN_ADDRESS(buffer);
829
830                         SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
831                                      sizeof(struct SmsMsgData_ST));
832                         msg->msgData[0] = mode;
833
834                         rc = smscore_sendrequest_and_wait(
835                                 coredev, msg, msg->xMsgHeader.msgLength,
836                                 &coredev->init_device_done);
837
838                         kfree(buffer);
839                 } else {
840                         sms_err("Could not allocate buffer for "
841                                 "init device message.");
842                         rc = -ENOMEM;
843                 }
844         } else {
845                 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
846                         sms_err("invalid mode specified %d", mode);
847                         return -EINVAL;
848                 }
849
850                 smscore_registry_setmode(coredev->devpath, mode);
851
852                 if (coredev->detectmode_handler)
853                         coredev->detectmode_handler(coredev->context,
854                                                     &coredev->mode);
855
856                 if (coredev->mode != mode && coredev->setmode_handler)
857                         rc = coredev->setmode_handler(coredev->context, mode);
858         }
859
860         if (rc >= 0) {
861                 coredev->mode = mode;
862                 coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
863         }
864
865         if (rc != 0)
866                 sms_err("return error code %d.", rc);
867         return rc;
868 }
869
870 /**
871  * calls device handler to get current mode of operation
872  *
873  * @param coredev pointer to a coredev object returned by
874  *                smscore_register_device
875  *
876  * @return current mode
877  */
878 int smscore_get_device_mode(struct smscore_device_t *coredev)
879 {
880         return coredev->mode;
881 }
882
883 /**
884  * find client by response id & type within the clients list.
885  * return client handle or NULL.
886  *
887  * @param coredev pointer to a coredev object returned by
888  *                smscore_register_device
889  * @param data_type client data type (SMS_DONT_CARE for all types)
890  * @param id client id (SMS_DONT_CARE for all id)
891  *
892  */
893 static struct
894 smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
895                                       int data_type, int id)
896 {
897         struct smscore_client_t *client = NULL;
898         struct list_head *next, *first;
899         unsigned long flags;
900         struct list_head *firstid, *nextid;
901
902
903         spin_lock_irqsave(&coredev->clientslock, flags);
904         first = &coredev->clients;
905         for (next = first->next;
906              (next != first) && !client;
907              next = next->next) {
908                 firstid = &((struct smscore_client_t *)next)->idlist;
909                 for (nextid = firstid->next;
910                      nextid != firstid;
911                      nextid = nextid->next) {
912                         if ((((struct smscore_idlist_t *)nextid)->id == id) &&
913                             (((struct smscore_idlist_t *)nextid)->data_type == data_type ||
914                             (((struct smscore_idlist_t *)nextid)->data_type == 0))) {
915                                 client = (struct smscore_client_t *) next;
916                                 break;
917                         }
918                 }
919         }
920         spin_unlock_irqrestore(&coredev->clientslock, flags);
921         return client;
922 }
923
924 /**
925  * find client by response id/type, call clients onresponse handler
926  * return buffer to pool on error
927  *
928  * @param coredev pointer to a coredev object returned by
929  *                smscore_register_device
930  * @param cb pointer to response buffer descriptor
931  *
932  */
933 void smscore_onresponse(struct smscore_device_t *coredev,
934                         struct smscore_buffer_t *cb)
935 {
936         struct SmsMsgHdr_ST *phdr =
937                 (struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset);
938         struct smscore_client_t *client =
939                 smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
940         int rc = -EBUSY;
941
942         static unsigned long last_sample_time; /* = 0; */
943         static int data_total; /* = 0; */
944         unsigned long time_now = jiffies_to_msecs(jiffies);
945
946         if (!last_sample_time)
947                 last_sample_time = time_now;
948
949         if (time_now - last_sample_time > 10000) {
950                 sms_debug("\ndata rate %d bytes/secs",
951                           (int)((data_total * 1000) /
952                                 (time_now - last_sample_time)));
953
954                 last_sample_time = time_now;
955                 data_total = 0;
956         }
957
958         data_total += cb->size;
959         /* If no client registered for type & id,
960          * check for control client where type is not registered */
961         if (client)
962                 rc = client->onresponse_handler(client->context, cb);
963
964         if (rc < 0) {
965                 switch (phdr->msgType) {
966                 case MSG_SMS_GET_VERSION_EX_RES:
967                 {
968                         struct SmsVersionRes_ST *ver =
969                                 (struct SmsVersionRes_ST *) phdr;
970                         sms_debug("MSG_SMS_GET_VERSION_EX_RES "
971                                   "id %d prots 0x%x ver %d.%d",
972                                   ver->FirmwareId, ver->SupportedProtocols,
973                                   ver->RomVersionMajor, ver->RomVersionMinor);
974
975                         coredev->mode = ver->FirmwareId == 255 ?
976                                 DEVICE_MODE_NONE : ver->FirmwareId;
977                         coredev->modes_supported = ver->SupportedProtocols;
978
979                         complete(&coredev->version_ex_done);
980                         break;
981                 }
982                 case MSG_SMS_INIT_DEVICE_RES:
983                         sms_debug("MSG_SMS_INIT_DEVICE_RES");
984                         complete(&coredev->init_device_done);
985                         break;
986                 case MSG_SW_RELOAD_START_RES:
987                         sms_debug("MSG_SW_RELOAD_START_RES");
988                         complete(&coredev->reload_start_done);
989                         break;
990                 case MSG_SMS_DATA_DOWNLOAD_RES:
991                         complete(&coredev->data_download_done);
992                         break;
993                 case MSG_SW_RELOAD_EXEC_RES:
994                         sms_debug("MSG_SW_RELOAD_EXEC_RES");
995                         break;
996                 case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
997                         sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
998                         complete(&coredev->trigger_done);
999                         break;
1000                 case MSG_SMS_SLEEP_RESUME_COMP_IND:
1001                         complete(&coredev->resume_done);
1002                         break;
1003                 default:
1004                         break;
1005                 }
1006                 smscore_putbuffer(coredev, cb);
1007         }
1008 }
1009
1010 /**
1011  * return pointer to next free buffer descriptor from core pool
1012  *
1013  * @param coredev pointer to a coredev object returned by
1014  *                smscore_register_device
1015  *
1016  * @return pointer to descriptor on success, NULL on error.
1017  */
1018 struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
1019 {
1020         struct smscore_buffer_t *cb = NULL;
1021         unsigned long flags;
1022
1023         spin_lock_irqsave(&coredev->bufferslock, flags);
1024
1025         if (!list_empty(&coredev->buffers)) {
1026                 cb = (struct smscore_buffer_t *) coredev->buffers.next;
1027                 list_del(&cb->entry);
1028         }
1029
1030         spin_unlock_irqrestore(&coredev->bufferslock, flags);
1031
1032         return cb;
1033 }
1034
1035 /**
1036  * return buffer descriptor to a pool
1037  *
1038  * @param coredev pointer to a coredev object returned by
1039  *                smscore_register_device
1040  * @param cb pointer buffer descriptor
1041  *
1042  */
1043 void smscore_putbuffer(struct smscore_device_t *coredev,
1044                        struct smscore_buffer_t *cb)
1045 {
1046         list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
1047 }
1048
1049 static int smscore_validate_client(struct smscore_device_t *coredev,
1050                                    struct smscore_client_t *client,
1051                                    int data_type, int id)
1052 {
1053         struct smscore_idlist_t *listentry;
1054         struct smscore_client_t *registered_client;
1055
1056         if (!client) {
1057                 sms_err("bad parameter.");
1058                 return -EFAULT;
1059         }
1060         registered_client = smscore_find_client(coredev, data_type, id);
1061         if (registered_client == client)
1062                 return 0;
1063
1064         if (registered_client) {
1065                 sms_err("The msg ID already registered to another client.");
1066                 return -EEXIST;
1067         }
1068         listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
1069         if (!listentry) {
1070                 sms_err("Can't allocate memory for client id.");
1071                 return -ENOMEM;
1072         }
1073         listentry->id = id;
1074         listentry->data_type = data_type;
1075         list_add_locked(&listentry->entry, &client->idlist,
1076                         &coredev->clientslock);
1077         return 0;
1078 }
1079
1080 /**
1081  * creates smsclient object, check that id is taken by another client
1082  *
1083  * @param coredev pointer to a coredev object from clients hotplug
1084  * @param initial_id all messages with this id would be sent to this client
1085  * @param data_type all messages of this type would be sent to this client
1086  * @param onresponse_handler client handler that is called to
1087  *                           process incoming messages
1088  * @param onremove_handler client handler that is called when device is removed
1089  * @param context client-specific context
1090  * @param client pointer to a value that receives created smsclient object
1091  *
1092  * @return 0 on success, <0 on error.
1093  */
1094 int smscore_register_client(struct smscore_device_t *coredev,
1095                             struct smsclient_params_t *params,
1096                             struct smscore_client_t **client)
1097 {
1098         struct smscore_client_t *newclient;
1099         /* check that no other channel with same parameters exists */
1100         if (smscore_find_client(coredev, params->data_type,
1101                                 params->initial_id)) {
1102                 sms_err("Client already exist.");
1103                 return -EEXIST;
1104         }
1105
1106         newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
1107         if (!newclient) {
1108                 sms_err("Failed to allocate memory for client.");
1109                 return -ENOMEM;
1110         }
1111
1112         INIT_LIST_HEAD(&newclient->idlist);
1113         newclient->coredev = coredev;
1114         newclient->onresponse_handler = params->onresponse_handler;
1115         newclient->onremove_handler = params->onremove_handler;
1116         newclient->context = params->context;
1117         list_add_locked(&newclient->entry, &coredev->clients,
1118                         &coredev->clientslock);
1119         smscore_validate_client(coredev, newclient, params->data_type,
1120                                 params->initial_id);
1121         *client = newclient;
1122         sms_debug("%p %d %d", params->context, params->data_type,
1123                   params->initial_id);
1124
1125         return 0;
1126 }
1127
1128 /**
1129  * frees smsclient object and all subclients associated with it
1130  *
1131  * @param client pointer to smsclient object returned by
1132  *               smscore_register_client
1133  *
1134  */
1135 void smscore_unregister_client(struct smscore_client_t *client)
1136 {
1137         struct smscore_device_t *coredev = client->coredev;
1138         unsigned long flags;
1139
1140         spin_lock_irqsave(&coredev->clientslock, flags);
1141
1142
1143         while (!list_empty(&client->idlist)) {
1144                 struct smscore_idlist_t *identry =
1145                         (struct smscore_idlist_t *) client->idlist.next;
1146                 list_del(&identry->entry);
1147                 kfree(identry);
1148         }
1149
1150         sms_info("%p", client->context);
1151
1152         list_del(&client->entry);
1153         kfree(client);
1154
1155         spin_unlock_irqrestore(&coredev->clientslock, flags);
1156 }
1157
1158 /**
1159  * verifies that source id is not taken by another client,
1160  * calls device handler to send requests to the device
1161  *
1162  * @param client pointer to smsclient object returned by
1163  *               smscore_register_client
1164  * @param buffer pointer to a request buffer
1165  * @param size size (in bytes) of request buffer
1166  *
1167  * @return 0 on success, <0 on error.
1168  */
1169 int smsclient_sendrequest(struct smscore_client_t *client,
1170                           void *buffer, size_t size)
1171 {
1172         struct smscore_device_t *coredev;
1173         struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
1174         int rc;
1175
1176         if (client == NULL) {
1177                 sms_err("Got NULL client");
1178                 return -EINVAL;
1179         }
1180
1181         coredev = client->coredev;
1182
1183         /* check that no other channel with same id exists */
1184         if (coredev == NULL) {
1185                 sms_err("Got NULL coredev");
1186                 return -EINVAL;
1187         }
1188
1189         rc = smscore_validate_client(client->coredev, client, 0,
1190                                      phdr->msgSrcId);
1191         if (rc < 0)
1192                 return rc;
1193
1194         return coredev->sendrequest_handler(coredev->context, buffer, size);
1195 }
1196
1197
1198 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
1199                            struct smscore_gpio_config *pinconfig)
1200 {
1201         struct {
1202                 struct SmsMsgHdr_ST hdr;
1203                 u32 data[6];
1204         } msg;
1205
1206         if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
1207                 msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1208                 msg.hdr.msgDstId = HIF_TASK;
1209                 msg.hdr.msgFlags = 0;
1210                 msg.hdr.msgType  = MSG_SMS_GPIO_CONFIG_EX_REQ;
1211                 msg.hdr.msgLength = sizeof(msg);
1212
1213                 msg.data[0] = pin;
1214                 msg.data[1] = pinconfig->pullupdown;
1215
1216                 /* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */
1217                 msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0;
1218
1219                 switch (pinconfig->outputdriving) {
1220                 case SMS_GPIO_OUTPUTDRIVING_16mA:
1221                         msg.data[3] = 7; /* Nova - 16mA */
1222                         break;
1223                 case SMS_GPIO_OUTPUTDRIVING_12mA:
1224                         msg.data[3] = 5; /* Nova - 11mA */
1225                         break;
1226                 case SMS_GPIO_OUTPUTDRIVING_8mA:
1227                         msg.data[3] = 3; /* Nova - 7mA */
1228                         break;
1229                 case SMS_GPIO_OUTPUTDRIVING_4mA:
1230                 default:
1231                         msg.data[3] = 2; /* Nova - 4mA */
1232                         break;
1233                 }
1234
1235                 msg.data[4] = pinconfig->direction;
1236                 msg.data[5] = 0;
1237         } else /* TODO: SMS_DEVICE_FAMILY1 */
1238                 return -EINVAL;
1239
1240         return coredev->sendrequest_handler(coredev->context,
1241                                             &msg, sizeof(msg));
1242 }
1243
1244 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
1245 {
1246         struct {
1247                 struct SmsMsgHdr_ST hdr;
1248                 u32 data[3];
1249         } msg;
1250
1251         if (pin > MAX_GPIO_PIN_NUMBER)
1252                 return -EINVAL;
1253
1254         msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1255         msg.hdr.msgDstId = HIF_TASK;
1256         msg.hdr.msgFlags = 0;
1257         msg.hdr.msgType  = MSG_SMS_GPIO_SET_LEVEL_REQ;
1258         msg.hdr.msgLength = sizeof(msg);
1259
1260         msg.data[0] = pin;
1261         msg.data[1] = level ? 1 : 0;
1262         msg.data[2] = 0;
1263
1264         return coredev->sendrequest_handler(coredev->context,
1265                                             &msg, sizeof(msg));
1266 }
1267
1268 static int __init smscore_module_init(void)
1269 {
1270         int rc = 0;
1271
1272         INIT_LIST_HEAD(&g_smscore_notifyees);
1273         INIT_LIST_HEAD(&g_smscore_devices);
1274         kmutex_init(&g_smscore_deviceslock);
1275
1276         INIT_LIST_HEAD(&g_smscore_registry);
1277         kmutex_init(&g_smscore_registrylock);
1278
1279         /* USB Register */
1280         rc = smsusb_register();
1281
1282         /* DVB Register */
1283         rc = smsdvb_register();
1284
1285         sms_debug("rc %d", rc);
1286
1287         return rc;
1288 }
1289
1290 static void __exit smscore_module_exit(void)
1291 {
1292
1293         kmutex_lock(&g_smscore_deviceslock);
1294         while (!list_empty(&g_smscore_notifyees)) {
1295                 struct smscore_device_notifyee_t *notifyee =
1296                         (struct smscore_device_notifyee_t *)
1297                                 g_smscore_notifyees.next;
1298
1299                 list_del(&notifyee->entry);
1300                 kfree(notifyee);
1301         }
1302         kmutex_unlock(&g_smscore_deviceslock);
1303
1304         kmutex_lock(&g_smscore_registrylock);
1305         while (!list_empty(&g_smscore_registry)) {
1306                 struct smscore_registry_entry_t *entry =
1307                         (struct smscore_registry_entry_t *)
1308                                 g_smscore_registry.next;
1309
1310                 list_del(&entry->entry);
1311                 kfree(entry);
1312         }
1313         kmutex_unlock(&g_smscore_registrylock);
1314
1315         /* DVB UnRegister */
1316         smsdvb_unregister();
1317
1318         /* Unregister USB */
1319         smsusb_unregister();
1320
1321         sms_debug("");
1322 }
1323
1324 module_init(smscore_module_init);
1325 module_exit(smscore_module_exit);
1326
1327 MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");
1328 MODULE_AUTHOR("Siano Mobile Silicon,,, (doronc@siano-ms.com)");
1329 MODULE_LICENSE("GPL");