rda5876 bt: update driver for android4.2
authorwdc <wdc@rock-chips.com>
Sat, 4 May 2013 02:12:08 +0000 (10:12 +0800)
committerwdc <wdc@rock-chips.com>
Sat, 4 May 2013 02:13:21 +0000 (10:13 +0800)
arch/arm/mach-rk2928/board-rk2928-phonepad-760.c
drivers/misc/tcc_bt_dev.c
include/linux/rfkill-rk.h

index 8a5a5dd1a27f817c769ff78d3040620c089e9663..b4bbc895789b599a382cf9ad5b6d065e1a74c956 100755 (executable)
@@ -847,7 +847,7 @@ int rk2928_sd_vcc_reset(){
  * SDMMC devices,  include the module of SD,MMC,and SDIO.noted by xbw at 2012-03-05
 **************************************************************************************************/
 
-#ifdef CONFIG_RFKILL_RK
+#if defined CONFIG_RFKILL_RK
 // bluetooth rfkill device, its driver in net/rfkill/rfkill-rk.c
 static struct rfkill_rk_platform_data rfkill_rk_platdata = {
     .type           = RFKILL_TYPE_BLUETOOTH,
@@ -904,6 +904,35 @@ static struct platform_device device_rfkill_rk = {
         },
 };
 #endif
+
+#if defined CONFIG_TCC_BT_DEV
+static struct tcc_bt_platform_data tcc_bt_platdata = {
+
+    .power_gpio   = { // ldoon
+        .io             =  RK2928_PIN3_PC0,
+        .enable         = GPIO_HIGH,
+        .iomux          = {
+            .name       = NULL,
+            },
+        },
+
+    .wake_host_gpio  = { // BT_HOST_WAKE, for bt wakeup host when it is in deep sleep
+        .io         = RK2928_PIN0_PC5, // set io to INVALID_GPIO for disable it
+        .enable     = IRQF_TRIGGER_RISING,// set IRQF_TRIGGER_FALLING for falling, set IRQF_TRIGGER_RISING for rising
+        .iomux      = {
+            .name       = NULL,
+        },
+    },
+};
+
+static struct platform_device device_tcc_bt = {
+    .name   = "tcc_bt_dev",
+    .id     = -1,
+    .dev    = {
+        .platform_data = &tcc_bt_platdata,
+        },
+};
+#endif
 #ifdef CONFIG_SDMMC_RK29
 #include "board-rk2928-phonepad-sdmmc.c"
 #endif
@@ -1364,6 +1393,9 @@ static struct platform_device *devices[] __initdata = {
        &device_rfkill_rk,
 #endif
 
+#ifdef CONFIG_TCC_BT_DEV
+       &device_tcc_bt,
+#endif
 };
 //i2c
 #ifdef CONFIG_I2C0_RK30
index 8e160a0e2bd9b2f73f3bdddcd21a6b2911e7d9c2..840b17d0158c8101452ff2bc57f647643b87dbd5 100755 (executable)
@@ -1,3 +1,4 @@
+\r
 /*\r
  *  Copyright (C) 2010-2011  RDA Micro <anli@rdamicro.com>\r
  *  This file belong to RDA micro\r
 #include <asm/uaccess.h>\r
 #include <linux/ioctl.h>\r
 #include <linux/device.h>\r
-\r
-//#include <mach/bsp.h>\r
 #include <asm/io.h>\r
 #include <linux/delay.h>\r
-\r
-//#include <linux/tcc_bt_dev.h>\r
-//#include <mach/tcc_pca953x.h>\r
-\r
 #include <linux/gpio.h>\r
 #include <mach/gpio.h>\r
 #include <asm/mach-types.h>\r
-\r
 #include <mach/iomux.h>\r
 #include <linux/interrupt.h>\r
 #include <asm/irq.h>\r
 #include <linux/wakelock.h>\r
+#include <linux/rfkill-rk.h>\r
+#include <linux/platform_device.h>\r
 \r
-#ifndef ON\r
-#define ON             1\r
-#endif\r
+#include <net/bluetooth/bluetooth.h>\r
+#include <net/bluetooth/hci_core.h>\r
 \r
-#ifndef OFF\r
-#define OFF    0\r
+\r
+#ifndef HOST_WAKE_DELAY\r
+#define HOST_WAKE_DELAY\r
 #endif\r
 \r
-#define LDO_ON_PIN            RK2928_PIN3_PC0\r
-#define RDA_BT_HOST_WAKE_PIN   RK2928_PIN0_PC5\r
+#define DEV_NAME "tcc_bt_dev"\r
 \r
-#define BT_DEV_ON                                      1\r
-#define BT_DEV_OFF                                     0\r
+#define BT_DEV_MAJOR_NUM                   234\r
+#define BT_DEV_MINOR_NUM                   0\r
 \r
-#define BT_DEV_MAJOR_NUM                       234\r
-#define BT_DEV_MINOR_NUM                       0\r
+#define IOCTL_BT_DEV_POWER         _IO(BT_DEV_MAJOR_NUM, 100)\r
+#define IOCTL_BT_SET_EINT        _IO(BT_DEV_MAJOR_NUM, 101)\r
 \r
-//#define IOCTL_BT_DEV_POWER                   _IO(BT_DEV_MAJOR_NUM, 100)\r
-//#define IOCTL_BT_DEV_SPECIFIC                _IO(BT_DEV_MAJOR_NUM, 101)\r
-//#define IOCTL_BT_DEV_IS_POWER                        _IO(BT_DEV_MAJOR_NUM, 102)\r
+static wait_queue_head_t        eint_wait;\r
+static struct work_struct       rda_bt_event_work;\r
+static struct workqueue_struct *rda_bt_workqueue;
 \r
+static int irq_num  = -1;
+static int eint_gen;\r
+static int eint_mask;\r
+static struct class *bt_dev_class;\r
+static struct mutex  sem;\r
+static struct tcc_bt_platform_data *tcc_bt_pdata = NULL;\r
 \r
-#define IOCTL_BT_DEV_POWER             _IO(BT_DEV_MAJOR_NUM, 100)\r
-#define IOCTL_BT_DEV_CTRL              _IO(BT_DEV_MAJOR_NUM, 101)\r
-#define IOCTL_BT_SET_EINT               _IO(BT_DEV_MAJOR_NUM, 102)\r
-#define IOCTL_BT_DEV_SPECIFIC          _IO(BT_DEV_MAJOR_NUM, 103)\r
 \r
+static void rda_bt_enable_irq(void)\r
+{\r
+    if(irq_num != -1) \r
+    {\r
+        enable_irq(irq_num);\r
+    }\r
+}\r
 \r
-static int bt_is_power = 0;\r
-static int rda_bt_irq = 0;\r
-static int irq_mask = 0;\r
-extern void export_bt_hci_wakeup_chip(void);\r
+static void rda_bt_disable_irq(void)\r
+{\r
+    if(irq_num != -1)\r
+    {  \r
+        disable_irq_nosync(irq_num);\r
+    }        \r
+}\r
 \r
-#define DEV_NAME "tcc_bt_dev"\r
-static struct class *bt_dev_class;\r
+static void rda_bt_work_fun(struct work_struct *work)\r
+{\r
+    struct hci_dev *hdev = NULL;\r
+\r
+    /* BlueZ stack, hci_uart driver */\r
+    hdev = hci_dev_get(0);\r
+    \r
+    if(hdev == NULL)\r
+    {\r
+        /* Avoid the early interrupt before hci0 registered */\r
+        //printk(KERN_ALERT "hdev is NULL\n ");\r
+    }\r
+    else\r
+    {\r
+        printk(KERN_ALERT "Send host wakeup command.\n");\r
+        hci_send_cmd(hdev, 0xC0FC, 0, NULL);\r
+    }\r
+    \r
+    rda_bt_enable_irq();\r
+}\r
 \r
-typedef struct {\r
-       int module;  // 0x12:CSR, 0x34:Broadcom\r
-       int TMP1;\r
-       int TMP2;\r
-} tcc_bt_info_t;\r
 \r
 static int tcc_bt_dev_open(struct inode *inode, struct file *file)\r
 {\r
-       printk("[## BT ##] tcc_bt_dev_open\n");\r
-       return 0;\r
+    printk("[## BT ##] tcc_bt_dev_open.\n");\r
+    eint_gen  = 0;\r
+    eint_mask = 0;\r
+    return 0;\r
 }\r
 \r
 static int tcc_bt_dev_release(struct inode *inode, struct file *file)\r
 {\r
-       printk("[## BT ##] tcc_bt_dev_release\n");\r
-       return 0;\r
+    printk("[## BT ##] tcc_bt_dev_release.\n");\r
+    eint_gen  = 0;\r
+    eint_mask = 0;\r
+    return 0;\r
 }\r
 \r
-static int tcc_bt_power_control(int on_off)\r
+/*****************************************************************************\r
+ *  tcc_bt_dev_poll\r
+*****************************************************************************/\r
+\r
+static unsigned int tcc_bt_dev_poll(struct file *file, poll_table *wait)\r
 {\r
-//     volatile PGPIO pGPIO = (volatile PGPIO)tcc_p2v(HwGPIO_BASE);\r
+    uint32_t mask = 0;\r
     \r
-       printk("[## BT ##] tcc_bt_power_control input[%d]\n", on_off);\r
-       \r
-       if(on_off == BT_DEV_ON)\r
-       {           \r
-               gpio_direction_output(LDO_ON_PIN, GPIO_HIGH);\r
-               bt_is_power = on_off;\r
-               msleep(500);\r
-       }\r
-       else if(on_off == BT_DEV_OFF)\r
-       {\r
-               gpio_direction_output(LDO_ON_PIN, GPIO_LOW);\r
-               bt_is_power = BT_DEV_OFF;\r
-               msleep(500);\r
-       }\r
-       else\r
-       {\r
-               printk("[## BT_ERR ##] input_error On[%d] Off[%d]\n", BT_DEV_ON, BT_DEV_OFF);\r
-       }\r
+    printk("[## BT ##] tcc_bt_poll eint_gen %d, eint_mask %d ++\n", eint_gen, eint_mask);\r
 \r
-       return 0;\r
+    wait_event_interruptible(eint_wait, (eint_gen == 1 || eint_mask == 1));\r
+    \r
+    printk("[## BT ##] tcc_bt_poll eint_gen %d, eint_mask %d --\n", eint_gen, eint_mask);\r
+    \r
+    if(eint_gen == 1)\r
+    {\r
+        mask = POLLIN|POLLRDNORM;\r
+        eint_gen = 0;\r
+    }\r
+    else if (eint_mask == 1)\r
+    {\r
+        mask = POLLERR;\r
+        eint_mask = 0;\r
+    }\r
+    \r
+    return mask;\r
 }\r
 \r
-\r
-static int tcc_bt_get_info(tcc_bt_info_t* arg)\r
-{\r
-       tcc_bt_info_t *info_t;\r
-       int module_t;\r
+static int tcc_bt_power_control(int on_off)\r
+{    \r
+    printk("[## BT ##] tcc_bt_power_control input[%d].\n", on_off);\r
        \r
-       info_t = (tcc_bt_info_t *)arg;\r
-       copy_from_user(info_t, (tcc_bt_info_t *)arg, sizeof(tcc_bt_info_t));\r
-\r
-       module_t = 0x56;        \r
-\r
-       printk("[## BT ##] module[0x%x]\n", module_t);\r
-\r
-       info_t->module = module_t;\r
-\r
-       copy_to_user((tcc_bt_info_t *)arg, info_t, sizeof(tcc_bt_info_t));\r
+    if(on_off)\r
+    {      \r
+        gpio_direction_output(tcc_bt_pdata->power_gpio.io, tcc_bt_pdata->power_gpio.enable);\r
+        msleep(500);
+        enable_irq(irq_num); \r
+    }\r
+    else\r
+    {\r
+       gpio_direction_output(tcc_bt_pdata->power_gpio.io, !tcc_bt_pdata->power_gpio.enable);\r
+       disable_irq(irq_num);
+       msleep(500);\r
+    }\r
 \r
-       return 0;\r
+    return 0;\r
 }\r
 \r
+\r
 static long  tcc_bt_dev_ioctl(struct file *file, unsigned int cmd,unsigned long arg)\r
 {\r
-       void __user *argp = (void __user *)arg;\r
-       char msg[14];\r
-       int ret = -1;\r
-       char rate;\r
-       //printk("[## BT ##] tcc_bt_dev_ioctl cmd[%d] arg[%d]\n", cmd, arg);\r
-       switch(cmd)\r
-       {\r
-               case IOCTL_BT_DEV_POWER:                        \r
-                       if (copy_from_user(&rate, argp, sizeof(rate)))\r
-                       return -EFAULT;\r
-                       printk("[## BT ##] IOCTL_BT_DEV_POWER cmd[%d] parm1[%d]\n", cmd, rate);\r
-                       tcc_bt_power_control(rate);\r
-                       // GPIO Control\r
-                       break;\r
-                       \r
-               case IOCTL_BT_DEV_SPECIFIC:\r
-                       printk("[## BT ##] IOCTL_BT_DEV_SPECIFIC cmd[%d]\n", cmd);\r
-                       tcc_bt_get_info((tcc_bt_info_t*)arg);\r
-                       break;\r
-\r
-               //case IOCTL_BT_DEV_IS_POWER:\r
-                       //if (copy_to_user(argp, &bt_is_power, sizeof(bt_is_power)))\r
-                       //return -EFAULT;\r
-                case IOCTL_BT_SET_EINT:\r
-                     printk("[## BT ##] IOCTL_BT_SET_EINT cmd[%d]\n", cmd);\r
-                     if (irq_mask)\r
-                     {\r
-                         irq_mask = 0;\r
-                         enable_irq(rda_bt_irq);\r
-                     }\r
-                     break;\r
-               default :\r
-                       printk("[## BT ##] tcc_bt_dev_ioctl cmd[%d]\n", cmd);\r
-                       break;\r
-       }\r
+    void __user *argp = (void __user *)arg;\r
+    int  ret   = -1;\r
+    int  rate  = 0;\r
+\r
+    switch(cmd)\r
+    {\r
+       case IOCTL_BT_DEV_POWER:\r
+       {\r
+                   printk("[## BT ##] IOCTL_BT_DEV_POWER cmd[%d] parm1[%d].\n", cmd, rate);\r
+            if (copy_from_user(&rate, argp, sizeof(rate)))\r
+               return -EFAULT;\r
+\r
+            mutex_lock(&sem);  \r
+            ret = tcc_bt_power_control(rate);\r
+            mutex_unlock(&sem);                        \r
+            break;\r
+       }               \r
+               \r
+        case IOCTL_BT_SET_EINT:\r
+        {\r
+               if (copy_from_user(&rate, argp, sizeof(rate)))\r
+                return -EFAULT;\r
+            printk("[## BT ##] IOCTL_BT_SET_EINT cmd[%d].\n", cmd);\r
+            mutex_lock(&sem); \r
+\r
+            if(rate)\r
+            {\r
+                rda_bt_enable_irq();\r
+            }\r
+            else\r
+            {\r
+                rda_bt_disable_irq();\r
+                eint_mask = 1;\r
+                wake_up_interruptible(&eint_wait);\r
+            }             \r
+            mutex_unlock(&sem); \r
+            ret = 0;\r
+            break;\r
+        }\r
+        \r
+        default :\r
+        {\r
+                printk("[## BT ##] tcc_bt_dev_ioctl cmd[%d].\n", cmd);\r
+                break;\r
+           }\r
+    }\r
 \r
-       return 0;\r
+    return ret;\r
 }\r
 \r
 \r
-struct file_operations tcc_bt_dev_ops = {\r
-    .owner      = THIS_MODULE,\r
-    .unlocked_ioctl      = tcc_bt_dev_ioctl,\r
-    .open       = tcc_bt_dev_open,\r
-    .release    = tcc_bt_dev_release,\r
+struct file_operations tcc_bt_dev_ops = \r
+{\r
+    .owner           = THIS_MODULE,\r
+    .unlocked_ioctl  = tcc_bt_dev_ioctl,\r
+    .open            = tcc_bt_dev_open,\r
+    .release         = tcc_bt_dev_release,\r
+    .poll            = tcc_bt_dev_poll,\r
 };\r
 \r
+#ifdef HOST_WAKE_DELAY\r
 struct wake_lock rda_bt_wakelock;\r
-static irqreturn_t rda_5876_host_wake_irq(int irq, void *dev)\r
+#endif\r
+\r
+static irqreturn_t rda_bt_host_wake_irq(int irq, void *dev)\r
 {\r
-       printk("rda_5876_host_wake_irq\n");\r
-       //export_bt_hci_wakeup_chip();\r
-        wake_lock_timeout(&rda_bt_wakelock, 3 * HZ); \r
-        disable_irq(rda_bt_irq);\r
-        irq_mask = 1;       \r
-       return IRQ_HANDLED;\r
+    printk("rda_bt_host_wake_irq.\n");\r
+       \r
+#ifdef HOST_WAKE_DELAY\r
+    wake_lock_timeout(&rda_bt_wakelock, 3 * HZ); \r
+#endif
+
+    if(irq_num != -1) \r
+    {  \r
+        disable_irq_nosync(irq_num);\r
+    }   \r
+\r
+#ifdef CONFIG_BT_HCIUART\r
+    if(rda_bt_workqueue)\r
+        queue_work(rda_bt_workqueue, &rda_bt_event_work);\r
+#else\r
+    /* Maybe handle the interrupt in user space? */\r
+    eint_gen = 1;\r
+    wake_up_interruptible(&eint_wait);\r
+    /* Send host wakeup command in user space, enable irq then */\r
+#endif\r
+   \r
+    return IRQ_HANDLED;\r
 }\r
 \r
-static int tcc_bt_init_module(void)\r
+static int tcc_bt_probe(struct platform_device *pdev)\r
 {\r
     int ret;\r
 \r
-        wake_lock_init(&rda_bt_wakelock, WAKE_LOCK_SUSPEND, "rda_bt_wake");\r
-       ret=gpio_request(LDO_ON_PIN, "ldoonpin");\r
-       if(ret < 0) {\r
-               printk("%s:fail to request gpio %d\n",__func__,LDO_ON_PIN);\r
-               return ret;\r
+    struct tcc_bt_platform_data *pdata = pdev->dev.platform_data;\r
+    \r
+    printk("tcc_bt_probe.\n");\r
+    if(pdata == NULL) {\r
+       printk("mt6622_probe failed.\n");\r
+       return -1;\r
+    }\r
+    tcc_bt_pdata = pdata;\r
+    \r
+    if(pdata->power_gpio.io != INVALID_GPIO) {\r
+       if (gpio_request(pdata->power_gpio.io, "ldoonpin")){\r
+           printk("tcc bt ldoonpin is busy!\n");\r
+           return -1;\r
        }\r
-       gpio_set_value(LDO_ON_PIN, GPIO_LOW);//GPIO_LOW\r
-       gpio_direction_output(LDO_ON_PIN, GPIO_LOW);//GPIO_LOW\r
-\r
-        if(rda_bt_irq == 0){\r
-               if(gpio_request(RDA_BT_HOST_WAKE_PIN, "bt_wake") != 0){\r
-                       printk("RDA_BT_HOST_WAKE_PIN request fail!\n");\r
-                       return -EIO;\r
-               }\r
-               gpio_direction_input(RDA_BT_HOST_WAKE_PIN);\r
-\r
-               rda_bt_irq = gpio_to_irq(RDA_BT_HOST_WAKE_PIN);\r
-               ret = request_irq(rda_bt_irq, rda_5876_host_wake_irq, IRQF_TRIGGER_RISING, "bt_host_wake",NULL);\r
-               if(ret){\r
-                       printk("bt_host_wake irq request fail\n");\r
-                       rda_bt_irq = 0;\r
-                       gpio_free(RDA_BT_HOST_WAKE_PIN);\r
-                       return -EIO;\r
-               }\r
-                enable_irq_wake(rda_bt_irq); //bt irq can wakeup host when host sleep\r
-                disable_irq(rda_bt_irq);\r
-                irq_mask = 1;\r
-            printk("request_irq bt_host_wake\n");\r
+    }\r
+    gpio_direction_output(pdata->power_gpio.io, !pdata->power_gpio.enable);//GPIO_LOW\r
+    \r
+#ifdef HOST_WAKE_DELAY\r
+    wake_lock_init(&rda_bt_wakelock, WAKE_LOCK_SUSPEND, "rda_bt_wake");\r
+#endif\r
+\r
+    if(pdata->wake_host_gpio.io != INVALID_GPIO) {\r
+       if (gpio_request(pdata->wake_host_gpio.io, "tcc_bt_wake")){\r
+           printk("tcc bt wakeis busy!\n");\r
+           gpio_free(pdata->wake_host_gpio.io);\r
+           return -1;\r
        }\r
+    }  \r
+\r
+    gpio_direction_input(pdata->wake_host_gpio.io);\r
+    irq_num = gpio_to_irq(pdata->wake_host_gpio.io);\r
+    ret = request_irq(irq_num, rda_bt_host_wake_irq, pdata->wake_host_gpio.enable, "tcc_bt_host_wake",NULL);      \r
+    if(ret < 0)\r
+    {\r
+        printk("bt_host_wake irq request fail.\n");\r
+         irq_num = -1;\r
+        goto error;\r
+    }\r
 \r
+\r
+    mutex_init(&sem);  \r
+    printk("[## BT ##] init_module\n");\r
        \r
-       printk("[## BT ##] init_module\n");\r
-       ret = register_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME, &tcc_bt_dev_ops);\r
-\r
-       bt_dev_class = class_create(THIS_MODULE, DEV_NAME);\r
-       device_create(bt_dev_class, NULL, MKDEV(BT_DEV_MAJOR_NUM, BT_DEV_MINOR_NUM), NULL, DEV_NAME);\r
-#if 0\r
-       if(machine_is_tcc8900()){\r
-           gpio_request(TCC_GPB(25), "bt_power");\r
-           gpio_request(TCC_GPEXT2(9), "bt_reset");\r
-               gpio_direction_output(TCC_GPB(25), 0); // output\r
-               gpio_direction_output(TCC_GPEXT2(9), 0);\r
-       }else if(machine_is_tcc9300() || machine_is_tcc8800()) {      // #elif defined (CONFIG_MACH_TCC9300)\r
-                       //gpio_set_value(TCC_GPEXT1(7), 0);   /* BT-ON Disable */\r
-               gpio_request(TCC_GPEXT3(2), "bt_wake");\r
-           gpio_request(TCC_GPEXT2(4), "bt_reset");\r
-               gpio_direction_output(TCC_GPEXT3(2), 0); // output\r
-               gpio_direction_output(TCC_GPEXT2(4), 0);\r
-       }\r
-       else if(machine_is_m801_88())\r
-       {\r
-               gpio_request(TCC_GPA(13), "bt_reset");\r
-               gpio_request(TCC_GPB(22), "BT WAKE");\r
-               gpio_direction_output(TCC_GPA(13), 0); // output\r
-               gpio_direction_output(TCC_GPB(22), 0); // output\r
-       }\r
-#endif \r
-    if(ret < 0){\r
-        printk("[## BT ##] [%d]fail to register the character device\n", ret);\r
-        return ret;\r
+    ret = register_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME, &tcc_bt_dev_ops);\r
+    if(ret < 0)\r
+    {\r
+        printk("[## BT ##] [%d]fail to register the character device.\n", ret);\r
+        goto error;\r
+    }\r
+    \r
+    bt_dev_class = class_create(THIS_MODULE, DEV_NAME);\r
+    if (IS_ERR(bt_dev_class)) \r
+    {\r
+        printk("BT RDA class_create failed\n");\r
+        goto error;\r
     }\r
+       \r
+    device_create(bt_dev_class, NULL, MKDEV(BT_DEV_MAJOR_NUM, BT_DEV_MINOR_NUM), NULL, DEV_NAME);\r
+
+    init_waitqueue_head(&eint_wait);\r
+    \r
+    INIT_WORK(&rda_bt_event_work, rda_bt_work_fun);\r
+    \r
+    rda_bt_workqueue = create_singlethread_workqueue("rda_bt");\r
+    \r
+    if (!rda_bt_workqueue)\r
+    {\r
+        printk("create_singlethread_workqueue failed.\n");\r
+        ret = -ESRCH;\r
+        goto error;\r
+    }  
 \r
     return 0;\r
+    \r
+error:\r
+    gpio_free(pdata->power_gpio.io); \r
+    gpio_free(pdata->wake_host_gpio.io);\r
+    return ret;    \r
 }\r
 \r
-static void tcc_bt_cleanup_module(void)\r
+static int tcc_bt_remove(struct platform_device *pdev)\r
 {\r
-       printk("[## BT ##] cleanup_module\n");\r
+    printk("[## BT ##] cleanup_module.\n");\r
     unregister_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME);\r
+    if(tcc_bt_pdata)\r
+        tcc_bt_pdata = NULL;
+
+    cancel_work_sync(&rda_bt_event_work);\r
+    destroy_workqueue(rda_bt_workqueue);    \r
+    \r
+#ifdef HOST_WAKE_DELAY    \r
     wake_lock_destroy(&rda_bt_wakelock);\r
+#endif    
+\r
+    return 0;\r
+}\r
+\r
+static struct platform_driver tcc_bt_driver = {\r
+        .probe = tcc_bt_probe,\r
+        .remove = tcc_bt_remove,\r
+        .driver = {\r
+                .name = "tcc_bt_dev",\r
+                .owner = THIS_MODULE,\r
+        },\r
+};\r
+\r
+static int __init tcc_bt_init_module(void)\r
+{\r
+    printk("Enter %s\n", __func__);\r
+    return platform_driver_register(&tcc_bt_driver);\r
 }\r
 \r
+static void __exit tcc_bt_cleanup_module(void)\r
+{\r
+    printk("Enter %s\n", __func__);\r
+    platform_driver_unregister(&tcc_bt_driver);\r
+}\r
 \r
-late_initcall(tcc_bt_init_module);\r
+module_init(tcc_bt_init_module);\r
 module_exit(tcc_bt_cleanup_module);\r
 \r
 \r
index 8c892b1ad201a15a9b142bb9c767dd37ecea6321..6ad5c884c09a86bf3e7e7306a5c018b2afacba5f 100755 (executable)
@@ -69,5 +69,10 @@ struct mt6622_platform_data {
     struct rfkill_rk_gpio   rts_gpio;
 };
 
+struct tcc_bt_platform_data {
+    struct rfkill_rk_gpio   power_gpio;
+    struct rfkill_rk_gpio   wake_host_gpio;
+};
+
 #endif /* __RFKILL_GPIO_H */