camsys_drv: v0.0x18.0 camsys_head: v0.0xa.0
authorzyc <zyc@rock-chips.com>
Mon, 10 Nov 2014 03:45:56 +0000 (11:45 +0800)
committerzyc <zyc@rock-chips.com>
Mon, 10 Nov 2014 03:45:56 +0000 (11:45 +0800)
18 files changed:
arch/arm/configs/rockchip_defconfig
drivers/media/video/rk_camsys/Kconfig
drivers/media/video/rk_camsys/Makefile
drivers/media/video/rk_camsys/camsys_drv.c
drivers/media/video/rk_camsys/camsys_gpio.h
drivers/media/video/rk_camsys/camsys_internal.h
drivers/media/video/rk_camsys/camsys_marvin.c
drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig [new file with mode: 0755]
drivers/media/video/rk_camsys/ext_flashled_drv/Makefile [new file with mode: 0755]
drivers/media/video/rk_camsys/ext_flashled_drv/flashlight.c [new file with mode: 0755]
drivers/media/video/rk_camsys/ext_flashled_drv/flashlight.h [new file with mode: 0755]
drivers/media/video/rk_camsys/ext_flashled_drv/leds-rt8547.c [new file with mode: 0755]
drivers/media/video/rk_camsys/ext_flashled_drv/leds-rt8547.h [new file with mode: 0755]
drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.c [new file with mode: 0755]
drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.h [new file with mode: 0755]
drivers/media/video/rk_camsys/ext_flashled_drv/rtfled.c [new file with mode: 0755]
drivers/media/video/rk_camsys/ext_flashled_drv/rtfled.h [new file with mode: 0755]
include/media/camsys_head.h

index 1a636b52c3efdfd9a0df021fdb6516cbfb08cee7..1591c45da8e1230ffb773bcc9b0f8028e55bf995 100644 (file)
@@ -387,6 +387,9 @@ CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_FLASHLIGHT=y
+CONFIG_LEDS_RT8547=y
+# CONFIG_RK30_CAMERA_ONEFRAME is not set
 CONFIG_MALI_MIDGARD=m
 CONFIG_MALI_MIDGARD_DVFS=y
 CONFIG_MALI_MIDGARD_RT_PM=y
index 8d22522235c7e350067882e8c3e7fe5f0834e25e..bd2b7e7bc970314bd035e1b2691aaeb1f85b562b 100755 (executable)
@@ -5,6 +5,8 @@ config CAMSYS_DRV
 menu "RockChip camera system driver"
        depends on CAMSYS_DRV
        
+source "drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig"
+       
 config CAMSYS_MRV
        tristate "camsys driver for marvin isp "
        default y
@@ -16,3 +18,4 @@ config CAMSYS_CIF
        ---help---
 
 endmenu          
+
index dfd880042164074a680a7c893dd0af45381d80f5..5704148ecc43a985edc0da943e4b7e1289043b9e 100755 (executable)
@@ -4,4 +4,5 @@
 obj-$(CONFIG_CAMSYS_DRV) += camsys_drv.o 
 obj-$(CONFIG_CAMSYS_MRV) += camsys_marvin.o camsys_mipicsi_phy.o camsys_soc_priv.o 
 obj-$(CONFIG_CAMSYS_CIF) += camsys_cif.o
+obj-y                                   += ext_flashled_drv/
 
index f0a088a69e1f71f7d82ace7196b6e7ed53cb2108..93bbab53a20011e989a12790983d6c61ec761b16 100755 (executable)
@@ -5,6 +5,7 @@
 #include "camsys_mipicsi_phy.h"
 #include "camsys_gpio.h"
 #include "camsys_soc_priv.h"
+#include "ext_flashled_drv/rk_ext_fshled_ctl.h"
 
 unsigned int camsys_debug=1;
 module_param(camsys_debug, int, S_IRUGO|S_IWUSR);
@@ -186,6 +187,18 @@ static int camsys_extdev_register(camsys_devio_name_t *devio, camsys_dev_t *cams
     
     extdev->dev_cfg = devio->dev_cfg;
     extdev->fl.fl.active = devio->fl.fl.active;
+    extdev->fl.ext_fsh_dev = NULL;
+    //should register external flash device ?
+    if(strlen(devio->fl.fl_drv_name) && (strcmp(devio->fl.fl_drv_name,"Internal") != 0)
+        && (strcmp(devio->fl.fl_drv_name,"NC") != 0)){
+        //register flash device
+        extdev->fl.ext_fsh_dev = camsys_register_ext_fsh_dev(&devio->fl);
+        if(extdev->fl.ext_fsh_dev == NULL){
+            camsys_err("register ext flash %s failed!",devio->fl.fl_drv_name);
+            err = -EINVAL;
+            goto fail;
+        }
+    }
     regulator_info = &devio->avdd;
     regulator = &extdev->avdd;
     for (i=(CamSys_Vdd_Start_Tag+1); i<CamSys_Vdd_End_Tag; i++) {
@@ -305,6 +318,9 @@ static int camsys_extdev_deregister(unsigned int dev_id, camsys_dev_t *camsys_de
             gpio++;
         }
 
+        if(extdev->fl.ext_fsh_dev != NULL){
+            camsys_deregister_ext_fsh_dev(extdev->fl.ext_fsh_dev);
+        }
         //spin_lock(&camsys_dev->lock);
         mutex_lock(&camsys_dev->extdevs.mut);
         list_del_init(&extdev->list);
@@ -340,6 +356,10 @@ static int camsys_extdev_deregister(unsigned int dev_id, camsys_dev_t *camsys_de
                     }
                     gpio++;
                 }
+
+                if(extdev->fl.ext_fsh_dev != NULL){
+                    camsys_deregister_ext_fsh_dev(extdev->fl.ext_fsh_dev);
+                }
                 camsys_trace(1,"Extdev(dev_id: 0x%x) is deregister success", extdev->dev_id);
                 list_del_init(&extdev->list);
                 list_del_init(&extdev->active);
@@ -387,7 +407,7 @@ static int camsys_sysctl(camsys_sysctrl_t *devctl, camsys_dev_t *camsys_dev)
             } 
             case CamSys_Flash_Trigger:
             {
-                camsys_dev->flash_trigger_cb(camsys_dev, devctl->on);
+                camsys_dev->flash_trigger_cb(camsys_dev,devctl->rev[0], devctl->on);
                 break;
             }
             case CamSys_IOMMU:
@@ -423,6 +443,8 @@ static int camsys_sysctl(camsys_sysctrl_t *devctl, camsys_dev_t *camsys_dev)
                             }
                         }
                     }
+                }else if(devctl->ops == CamSys_Flash_Trigger){
+                    err = camsys_ext_fsh_ctrl(extdev->fl.ext_fsh_dev,devctl->rev[0],devctl->on);
                 }
                 
             } else {
@@ -1184,7 +1206,7 @@ static int camsys_platform_probe(struct platform_device *pdev){
     list_add_tail(&camsys_dev->list, &camsys_devs.devs);
     spin_unlock(&camsys_devs.lock);
 
-    
+    camsys_init_ext_fsh_module();  
     camsys_trace(1, "Probe %s device success ", dev_name(&pdev->dev));
     return 0;
 request_mem_fail:
@@ -1259,6 +1281,8 @@ static int  camsys_platform_remove(struct platform_device *pdev)
         list_del_init(&camsys_dev->list);
         spin_unlock(&camsys_devs.lock);
 
+        camsys_deinit_ext_fsh_module();
+
         kfree(camsys_dev);
         camsys_dev=NULL;
     } else {
index 6d6e81e1fe4ece5d128ddc8f0ddeb0c6d8045b86..e75fac61b5263005557730c4e806671e8569bfd2 100755 (executable)
@@ -56,7 +56,11 @@ static inline unsigned int camsys_gpio_group(unsigned char *io_name)
         group = 5;      
     } else if (strstr(io_name,"PIN6")) {
         group = 6;      
-    } 
+    } else if (strstr(io_name,"PIN7")) {
+        group = 7;      
+    } else if (strstr(io_name,"PIN8")) {
+        group = 8;      
+    }  
 
     return group;
 }
index c0c413b804842d8dc966c25ec162730e670cc11c..58b372dfb41bd6ad9db0b592a45abe62ccacee92 100755 (executable)
                 1) enable or disable IOMMU just depending on CONFIG_ROCKCHIP_IOMMU. 
 *v0.0x17.0:
                 1) isp iommu status depend on vpu iommu status.
+*v0.0x18.0:
+         1) add flashlight RT8547 driver
+         2) support torch mode
 */
-#define CAMSYS_DRIVER_VERSION                   KERNEL_VERSION(0,0x17,0)
+#define CAMSYS_DRIVER_VERSION                   KERNEL_VERSION(0,0x18,0)
 
 
 #define CAMSYS_PLATFORM_DRV_NAME                "RockChip-CamSys"
@@ -197,6 +200,9 @@ typedef struct camsys_gpio_s {
 } camsys_gpio_t;
 typedef struct camsys_flash_s {
     camsys_gpio_t        fl;
+    camsys_gpio_t        fl_en;
+    void*   ext_fsh_dev;            
+    //flash call back
 } camsys_flash_t;
 typedef struct camsys_extdev_s {
     unsigned char            dev_name[CAMSYS_NAME_LEN];
@@ -264,7 +270,7 @@ typedef struct camsys_dev_s {
     int (*phy_cb) (camsys_extdev_t *extdev, camsys_sysctrl_t *devctl, void* ptr);
     int (*iomux)(camsys_extdev_t *extdev,void *ptr);
     int (*platform_remove)(struct platform_device *pdev);
-    int (*flash_trigger_cb)(void *ptr, unsigned int on);
+    int (*flash_trigger_cb)(void *ptr,int mode , unsigned int on);
     int (*iommu_cb)(void *ptr,camsys_sysctrl_t *devctl);
 } camsys_dev_t;
 
index c6a61d8b7317e048aa638fc52e55f08a34a4f932..a7544ca3080cf24b0c5d962d1bdef65d52694ffb 100755 (executable)
@@ -126,7 +126,7 @@ fail:
     return -1;
 }
 
-static int camsys_mrv_flash_trigger_cb(void *ptr,unsigned int on)
+static int camsys_mrv_flash_trigger_cb(void *ptr,int mode,unsigned int on)
 {
     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
     struct device *dev = &(camsys_dev->pdev->dev);
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig b/drivers/media/video/rk_camsys/ext_flashled_drv/Kconfig
new file mode 100755 (executable)
index 0000000..370ee54
--- /dev/null
@@ -0,0 +1,26 @@
+config FLASHLIGHT
+       bool "Flashlight Support"
+       default n
+       help
+         This option enables the led sysfs class in /sys/class/flashlight.
+
+config LEDS_RT8547
+       bool "LED Support for RT8547"
+       select RT_FLASH_LED
+       default n
+       help
+         This option enabled support for RT8547 LED drivers
+
+config LEDS_RT8547_DBG
+       bool "LED RT8547 Debug Info"
+       depends on LEDS_RT8547
+       default n
+       help
+         This option enabled RT8547 LED drivers debug option
+
+config RT_FLASH_LED
+       bool "Richtek flash LED driver support"
+       depends on FLASHLIGHT
+       default n
+       help
+         Say Y here to enable Richtek's flash LED driver HAL architecture
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/Makefile b/drivers/media/video/rk_camsys/ext_flashled_drv/Makefile
new file mode 100755 (executable)
index 0000000..c96b20e
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_FLASHLIGHT)               += flashlight.o rk_ext_fshled_ctl.o
+obj-$(CONFIG_RT_FLASH_LED)             += rtfled.o
+obj-$(CONFIG_LEDS_RT8547)              += leds-rt8547.o
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/flashlight.c b/drivers/media/video/rk_camsys/ext_flashled_drv/flashlight.c
new file mode 100755 (executable)
index 0000000..f63a65f
--- /dev/null
@@ -0,0 +1,544 @@
+/* drivers/leds/flashlight.c
+ * Flashlight Class Device Driver
+ *
+ * Copyright (C) 2013 Richtek Technology Corp.
+ * Author: Patrick Chang <patrick_chang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include "flashlight.h"
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+static const char const *flashlight_type_string[] = {
+       [FLASHLIGHT_TYPE_XENON] = "Xenon",
+       [FLASHLIGHT_TYPE_LED] = "LED",
+       [FLASHLIFHT_TYPE_BULB] = "Bulb",
+};
+
+static const char const *flashlight_mode_string[] = {
+       [FLASHLIGHT_MODE_OFF] = "Off",
+       [FLASHLIGHT_MODE_TORCH] = "Torch",
+       [FLASHLIGHT_MODE_FLASH] = "Flash",
+       [FLASHLIGHT_MODE_MIXED] = "Mixed",
+};
+
+static ssize_t flashlight_show_name(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%s\n",
+                      flashlight_dev->props.alias_name ?
+                      flashlight_dev->props.alias_name : "anonymous");
+}
+
+static ssize_t flashlight_show_type(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%s\n",
+                      flashlight_type_string[flashlight_dev->props.type]);
+}
+
+static ssize_t flashlight_show_mode(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%s\n",
+                      flashlight_mode_string[flashlight_dev->props.mode]);
+}
+
+static ssize_t flashlight_show_torch_max_brightness(struct device *dev,
+                                                   struct device_attribute
+                                                   *attr, char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%d\n", flashlight_dev->props.torch_max_brightness);
+}
+
+static ssize_t flashlight_show_strobe_max_brightness(struct device *dev,
+                                                    struct device_attribute
+                                                    *attr, char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%d\n",
+                      flashlight_dev->props.strobe_max_brightness);
+}
+
+static ssize_t flashlight_show_color_temperature(struct device *dev,
+                                                struct device_attribute *attr,
+                                                char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%d\n", flashlight_dev->props.color_temperature);
+}
+
+static ssize_t flashlight_show_strobe_delay(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%d\n", flashlight_dev->props.strobe_delay);
+}
+
+static ssize_t flashlight_store_strobe_timeout(struct device *dev,
+                                              struct device_attribute *attr,
+                                              const char *buf, size_t count)
+{
+       int rc;
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+       long timeout;
+
+       rc = kstrtol(buf, 0, &timeout);
+       if (rc)
+               return rc;
+       rc = flashlight_dev->ops->set_strobe_timeout(flashlight_dev, timeout);
+       if (rc == 0)
+               rc = count;
+       return rc;
+}
+
+static ssize_t flashlight_show_strobe_timeout(struct device *dev,
+                                             struct device_attribute *attr,
+                                             char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%d\n", flashlight_dev->props.strobe_timeout);
+}
+
+static ssize_t flashlight_store_torch_brightness(struct device *dev,
+                                                struct device_attribute *attr,
+                                                const char *buf, size_t count)
+{
+       int rc;
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+       long brightness;
+
+       rc = kstrtol(buf, 0, &brightness);
+       if (rc)
+               return rc;
+
+       rc = -ENXIO;
+
+       mutex_lock(&flashlight_dev->ops_lock);
+       if (flashlight_dev->ops && flashlight_dev->ops->set_torch_brightness) {
+               if (brightness > flashlight_dev->props.torch_max_brightness)
+                       rc = -EINVAL;
+               else {
+                       pr_debug("flashlight: set torch brightness to %ld\n",
+                                brightness);
+                       flashlight_dev->props.torch_brightness = brightness;
+                       flashlight_dev->ops->
+                           set_torch_brightness(flashlight_dev, brightness);
+                       rc = count;
+               }
+       }
+       mutex_unlock(&flashlight_dev->ops_lock);
+
+       return rc;
+}
+
+static ssize_t flashlight_show_torch_brightness(struct device *dev,
+                                               struct device_attribute *attr,
+                                               char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%d\n", flashlight_dev->props.torch_brightness);
+}
+
+static ssize_t flashlight_store_strobe_brightness(struct device *dev,
+                                                 struct device_attribute *attr,
+                                                 const char *buf, size_t count)
+{
+       int rc;
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+       long brightness;
+
+       rc = kstrtol(buf, 0, &brightness);
+       if (rc)
+               return rc;
+
+       rc = -ENXIO;
+
+       mutex_lock(&flashlight_dev->ops_lock);
+       if (flashlight_dev->ops && flashlight_dev->ops->set_strobe_brightness) {
+               if (brightness > flashlight_dev->props.strobe_max_brightness)
+                       rc = -EINVAL;
+               else {
+                       pr_debug("flashlight: set strobe brightness to %ld\n",
+                                brightness);
+                       flashlight_dev->props.strobe_brightness = brightness;
+                       flashlight_dev->ops->
+                           set_strobe_brightness(flashlight_dev, brightness);
+                       rc = count;
+               }
+       }
+       mutex_unlock(&flashlight_dev->ops_lock);
+       return rc;
+}
+
+static ssize_t flashlight_show_strobe_brightness(struct device *dev,
+                                                struct device_attribute *attr,
+                                                char *buf)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       return sprintf(buf, "%d\n", flashlight_dev->props.strobe_brightness);
+}
+
+static struct class *flashlight_class;
+
+static int flashlight_suspend(struct device *dev, pm_message_t state)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       if (flashlight_dev->ops)
+               flashlight_dev->ops->suspend(flashlight_dev, state);
+       return 0;
+}
+
+static int flashlight_resume(struct device *dev)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       if (flashlight_dev->ops)
+               flashlight_dev->ops->resume(flashlight_dev);
+       return 0;
+}
+
+static void flashlight_device_release(struct device *dev)
+{
+       struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
+
+       kfree(flashlight_dev);
+}
+
+static struct device_attribute flashlight_device_attributes[] = {
+       __ATTR(name, 0444, flashlight_show_name, NULL),
+       __ATTR(type, 0444, flashlight_show_type, NULL),
+       __ATTR(mode, 0444, flashlight_show_mode, NULL),
+       __ATTR(torch_max_brightness, 0444,
+              flashlight_show_torch_max_brightness, NULL),
+       __ATTR(strobe_max_brightness, 0444,
+              flashlight_show_strobe_max_brightness, NULL),
+       __ATTR(color_temperature, 0444,
+              flashlight_show_color_temperature, NULL),
+       __ATTR(strobe_delay, 0444,
+              flashlight_show_strobe_delay, NULL),
+       __ATTR(strobe_timeout, 0644,
+              flashlight_show_strobe_timeout,
+              flashlight_store_strobe_timeout),
+       __ATTR(torch_brightness, 0644,
+              flashlight_show_torch_brightness,
+              flashlight_store_torch_brightness),
+       __ATTR(strobe_brightness, 0644,
+              flashlight_show_strobe_brightness,
+              flashlight_store_strobe_brightness),
+       __ATTR_NULL,
+};
+
+/**
+ * flashlight_device_register - create and register a new object of
+ *   flashlight_device class.
+ * @name: the name of the new object(must be the same as the name of the
+ *   respective framebuffer device).
+ * @parent: a pointer to the parent device
+ * @devdata: an optional pointer to be stored for private driver use. The
+ *   methods may retrieve it by using bl_get_data(flashlight_dev).
+ * @ops: the flashlight operations structure.
+ *
+ * Creates and registers new flashlight device. Returns either an
+ * ERR_PTR() or a pointer to the newly allocated device.
+ */
+struct flashlight_device *flashlight_device_register(const char *name,
+                                                    struct device *parent,
+                                                    void *devdata,
+                                                    const struct flashlight_ops
+                                                    *ops,
+                                                    const struct
+                                                    flashlight_properties
+                                                    *props)
+{
+       struct flashlight_device *flashlight_dev;
+       int rc;
+
+       pr_debug("flashlight_device_register: name=%s\n", name);
+       flashlight_dev = kzalloc(sizeof(*flashlight_dev), GFP_KERNEL);
+       if (!flashlight_dev)
+               return ERR_PTR(-ENOMEM);
+
+       mutex_init(&flashlight_dev->ops_lock);
+       flashlight_dev->dev.class = flashlight_class;
+       flashlight_dev->dev.parent = parent;
+       flashlight_dev->dev.release = flashlight_device_release;
+       dev_set_name(&flashlight_dev->dev, name);
+       dev_set_drvdata(&flashlight_dev->dev, devdata);
+       /* Copy properties */
+       if (props) {
+               memcpy(&flashlight_dev->props, props,
+                      sizeof(struct flashlight_properties));
+       }
+       rc = device_register(&flashlight_dev->dev);
+       if (rc) {
+               kfree(flashlight_dev);
+               return ERR_PTR(rc);
+       }
+       flashlight_dev->ops = ops;
+       return flashlight_dev;
+}
+EXPORT_SYMBOL(flashlight_device_register);
+
+/**
+ * flashlight_device_unregister - unregisters a flashlight device object.
+ * @flashlight_dev: the flashlight device object to be unregistered and freed.
+ *
+ * Unregisters a previously registered via flashlight_device_register object.
+ */
+void flashlight_device_unregister(struct flashlight_device *flashlight_dev)
+{
+       if (!flashlight_dev)
+               return;
+
+       mutex_lock(&flashlight_dev->ops_lock);
+       flashlight_dev->ops = NULL;
+       mutex_unlock(&flashlight_dev->ops_lock);
+       device_unregister(&flashlight_dev->dev);
+}
+EXPORT_SYMBOL(flashlight_device_unregister);
+
+int flashlight_list_color_temperature(struct flashlight_device *flashlight_dev,
+                                     int selector)
+{
+       if (flashlight_dev->ops && flashlight_dev->ops->list_color_temperature)
+               return flashlight_dev->ops->
+                   list_color_temperature(flashlight_dev, selector);
+       return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_list_color_temperature);
+
+int flashlight_set_color_temperature(struct flashlight_device *flashlight_dev,
+                                    int minK, int maxK)
+{
+       int selector = 0;
+       int rc;
+
+       if ((flashlight_dev->ops == NULL) ||
+           (flashlight_dev->ops->set_color_temperature == NULL))
+               return -EINVAL;
+       for (selector = 0;; selector++) {
+               rc = flashlight_list_color_temperature(flashlight_dev,
+                                                      selector);
+               if (rc < 0)
+                       return rc;
+               if (rc >= minK && rc <= maxK) {
+                       mutex_lock(&flashlight_dev->ops_lock);
+                       rc = flashlight_dev->ops->
+                           set_color_temperature(flashlight_dev, rc);
+                       mutex_unlock(&flashlight_dev->ops_lock);
+                       if (rc == 0)
+                               flashlight_dev->props.color_temperature = rc;
+                       return rc;
+               }
+
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_set_color_temperature);
+
+int flashlight_set_torch_brightness(struct flashlight_device *flashlight_dev,
+                                   int brightness_level)
+{
+       int rc;
+
+       if ((flashlight_dev->ops == NULL) ||
+           (flashlight_dev->ops->set_torch_brightness == NULL))
+               return -EINVAL;
+       if (brightness_level > flashlight_dev->props.torch_max_brightness)
+               return -EINVAL;
+       mutex_lock(&flashlight_dev->ops_lock);
+       rc = flashlight_dev->ops->set_torch_brightness(flashlight_dev,
+                                                      brightness_level);
+       mutex_unlock(&flashlight_dev->ops_lock);
+       if (rc < 0)
+               return rc;
+       flashlight_dev->props.torch_brightness = brightness_level;
+       return rc;
+
+}
+EXPORT_SYMBOL(flashlight_set_torch_brightness);
+
+int flashlight_set_strobe_brightness(struct flashlight_device *flashlight_dev,
+                                    int brightness_level)
+{
+       int rc;
+
+       if ((flashlight_dev->ops == NULL) ||
+           (flashlight_dev->ops->set_strobe_brightness == NULL))
+               return -EINVAL;
+       if (brightness_level > flashlight_dev->props.strobe_max_brightness)
+               return -EINVAL;
+       mutex_lock(&flashlight_dev->ops_lock);
+       rc = flashlight_dev->ops->set_strobe_brightness(flashlight_dev,
+                                                       brightness_level);
+       mutex_unlock(&flashlight_dev->ops_lock);
+       if (rc < 0)
+               return rc;
+       flashlight_dev->props.strobe_brightness = brightness_level;
+       return rc;
+}
+EXPORT_SYMBOL(flashlight_set_strobe_brightness);
+
+int flashlight_list_strobe_timeout(struct flashlight_device *flashlight_dev,
+                                  int selector)
+{
+       if (flashlight_dev->ops && flashlight_dev->ops->list_strobe_timeout) {
+               return flashlight_dev->ops->list_strobe_timeout(flashlight_dev,
+                                                               selector);
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_list_strobe_timeout);
+
+int flashlight_set_strobe_timeout(struct flashlight_device *flashlight_dev,
+                                 int min_ms, int max_ms)
+{
+       int selector = 0;
+       int rc = -EINVAL;
+       int timeout;
+
+       if ((flashlight_dev->ops == NULL) ||
+           (flashlight_dev->ops->set_strobe_timeout == NULL))
+               return -EINVAL;
+       for (selector = 0;; selector++) {
+               timeout =
+                   flashlight_list_strobe_timeout(flashlight_dev, selector);
+               if (timeout < 0)
+                       return timeout;
+               if (timeout >= min_ms && timeout <= max_ms) {
+                       mutex_lock(&flashlight_dev->ops_lock);
+                       rc = flashlight_dev->ops->
+                           set_strobe_timeout(flashlight_dev, timeout);
+                       mutex_unlock(&flashlight_dev->ops_lock);
+                       if (rc == 0)
+                               flashlight_dev->props.strobe_timeout = timeout;
+                       return rc;
+               }
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_set_strobe_timeout);
+
+int flashlight_set_mode(struct flashlight_device *flashlight_dev, int mode)
+{
+       int rc;
+
+       if (mode >= FLASHLIGHT_MODE_MAX || mode < 0)
+               return -EINVAL;
+       if ((flashlight_dev->ops == NULL) ||
+           (flashlight_dev->ops->set_mode == NULL)) {
+               flashlight_dev->props.mode = mode;
+               return 0;
+       }
+       mutex_lock(&flashlight_dev->ops_lock);
+       rc = flashlight_dev->ops->set_mode(flashlight_dev, mode);
+       mutex_unlock(&flashlight_dev->ops_lock);
+       if (rc < 0)
+               return rc;
+       flashlight_dev->props.mode = mode;
+       return rc;
+}
+EXPORT_SYMBOL(flashlight_set_mode);
+
+int flashlight_strobe(struct flashlight_device *flashlight_dev)
+{
+       if (flashlight_dev->props.mode == FLASHLIGHT_MODE_FLASH
+           || flashlight_dev->props.mode == FLASHLIGHT_MODE_MIXED) {
+               if (flashlight_dev->ops == NULL ||
+                   flashlight_dev->ops->strobe == NULL)
+                       return -EINVAL;
+               return flashlight_dev->ops->strobe(flashlight_dev);
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_strobe);
+
+static int flashlight_match_device_by_name(struct device *dev, const void *data)
+{
+       const char *name = data;
+
+       return strcmp(dev_name(dev), name) == 0;
+}
+
+struct flashlight_device *find_flashlight_by_name(char *name)
+{
+       struct device *dev;
+
+       if (!name)
+               return (struct flashlight_device *)NULL;
+       dev = class_find_device(flashlight_class, NULL, (void*)name,
+                               flashlight_match_device_by_name);
+
+       return dev ? to_flashlight_device(dev) : NULL;
+
+}
+EXPORT_SYMBOL(find_flashlight_by_name);
+
+int flashlight_strobe_charge(struct flashlight_device *flashlight_dev,
+                            flashlight_charge_event_cb cb, void *data,
+                            int start)
+{
+
+       if (flashlight_dev->ops->strobe_charge)
+               return flashlight_dev->ops->strobe_charge(flashlight_dev,
+                                                         cb, data, start);
+       if (flashlight_dev->props.type == FLASHLIGHT_TYPE_LED) {
+               if (cb)
+                       cb(data, 0);
+               return 0;
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(flashlight_strobe_charge);
+
+static void __exit flashlight_class_exit(void)
+{
+       class_destroy(flashlight_class);
+}
+
+static int __init flashlight_class_init(void)
+{
+       flashlight_class = class_create(THIS_MODULE, "flashlight");
+       if (IS_ERR(flashlight_class)) {
+               pr_err(
+                      "Unable to create flashlight class; errno = %ld\n",
+                      PTR_ERR(flashlight_class));
+               return PTR_ERR(flashlight_class);
+       }
+       flashlight_class->dev_attrs = flashlight_device_attributes;
+       flashlight_class->suspend = flashlight_suspend;
+       flashlight_class->resume = flashlight_resume;
+       return 0;
+}
+subsys_initcall(flashlight_class_init);
+module_exit(flashlight_class_exit);
+
+MODULE_DESCRIPTION("Flashlight Class Device");
+MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com>");
+MODULE_VERSION("1.0.0_G");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/flashlight.h b/drivers/media/video/rk_camsys/ext_flashled_drv/flashlight.h
new file mode 100755 (executable)
index 0000000..48b1ea2
--- /dev/null
@@ -0,0 +1,138 @@
+/* include/linux/leds/flashlight.h
+ * Header of Flashlight Class Device Driver
+ *
+ * Copyright (C) 2013 Richtek Technology Corp.
+ * Patrick Chang <patrick_chang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef LINUX_LEDS_FLASHLIGHT_H
+#define LINUX_LEDS_FLASHLIGHT_H
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+typedef enum flashlight_type {
+       FLASHLIGHT_TYPE_XENON = 0,
+       FLASHLIGHT_TYPE_LED,
+       FLASHLIFHT_TYPE_BULB,
+       FLASHLIGHT_TYPE_MAX,
+} flashlight_type_t;
+typedef enum flashlight_mode {
+       FLASHLIGHT_MODE_OFF = 0,
+       FLASHLIGHT_MODE_TORCH,
+       FLASHLIGHT_MODE_FLASH,
+       /* MIXED mode means TORCH + FLASH */
+       FLASHLIGHT_MODE_MIXED,
+       FLASHLIGHT_MODE_MAX,
+} flashlight_mode_t;
+
+struct flashlight_device;
+
+typedef int (*flashlight_charge_event_cb) (void *data, int remains);
+
+struct flashlight_ops {
+       int (*set_torch_brightness)(struct flashlight_device *, int);
+       int (*set_strobe_brightness)(struct flashlight_device *, int);
+       int (*set_strobe_timeout)(struct flashlight_device *, int);
+       int (*list_strobe_timeout)(struct flashlight_device *, int);
+       int (*set_mode)(struct flashlight_device *, int);
+       int (*set_color_temperature)(struct flashlight_device *, int);
+       int (*list_color_temperature)(struct flashlight_device *, int);
+       int (*strobe_charge)(struct flashlight_device *,
+                             flashlight_charge_event_cb, void *, int);
+       int (*strobe)(struct flashlight_device *);
+       int (*suspend)(struct flashlight_device *, pm_message_t);
+       int (*resume)(struct flashlight_device *);
+};
+
+struct flashlight_properties {
+       /* Flashlight type */
+       enum flashlight_type type;
+       /* Xenon type flashlight doesn't support torch mode */
+       enum flashlight_mode mode;
+       /* Color temperature, unit: K, 0 means unknown */
+       int color_temperature;
+       int torch_brightness;
+       int torch_max_brightness;
+       int strobe_brightness;
+       int strobe_max_brightness;
+       int strobe_delay;
+       int strobe_timeout;
+       const char *alias_name;
+};
+
+struct flashlight_device {
+       /* Flashlight properties */
+       struct flashlight_properties props;
+       const struct flashlight_ops *ops;
+       struct mutex ops_lock;
+       struct device dev;
+};
+
+extern struct flashlight_device *flashlight_device_register(const char *name,
+                                                       struct device *parent,
+                                                       void *devdata,
+                                                       const struct
+                                                       flashlight_ops * ops,
+                                                       const struct
+                                                       flashlight_properties
+                                                       *props);
+extern void flashlight_device_unregister(struct flashlight_device
+                                        *flashlight_dev);
+extern struct flashlight_device *find_flashlight_by_name(char *name);
+extern int flashlight_list_color_temperature(struct flashlight_device
+                                            *flashlight_dev, int selector);
+extern int flashlight_set_color_temperature(struct flashlight_device
+                                           *flashlight_dev, int minK,
+                                           int maxK);
+extern int flashlight_set_torch_brightness(struct flashlight_device
+                                          *flashlight_dev,
+                                          int brightness_level);
+extern int flashlight_set_strobe_brightness(struct flashlight_device
+                                           *flashlight_dev,
+                                           int brightness_level);
+extern int flashlight_list_strobe_timeout(struct flashlight_device
+                                         *flashlight_dev, int selector);
+extern int flashlight_set_strobe_timeout(struct flashlight_device
+                                        *flashlight_dev, int min_ms,
+                                        int max_ms);
+extern int flashlight_set_mode(struct flashlight_device *flashlight_dev,
+                              int mode);
+
+extern int flashlight_strobe(struct flashlight_device *flashlight_dev);
+
+/* flashlight_charge_event_cb(void *data, int remains)
+ * description :
+ *   callback function of flashlight charging progress
+ * arguments :
+ *  @data : data pass by flashlight_strobe_charge()
+ *  @remains : remained time to full chargerd, unit : ms ; 0 means ready
+ * return : 0 means succeess, otherwise see definitions in errno.h
+ */
+
+/* flashlight_strobe_chargestruct flashlight_device *flashlight_dev,
+ *                      flashlight_charge_event_cb cb, void *data, int start)
+ * description :
+ * flashlight start / stop  charging
+ * @flashlight_dev : flashlight devices
+ * @flashlight_charge_event_cb : callback function to report progress
+ * @data : bypass to callback function
+ * @start : 1 means start; 0 means stop
+ */
+extern int flashlight_strobe_charge(struct flashlight_device *flashlight_dev,
+                                   flashlight_charge_event_cb cb, void *data,
+                                   int start);
+
+#define to_flashlight_device(obj) \
+       container_of(obj, struct flashlight_device, dev)
+
+static inline void *flashlight_get_data(struct flashlight_device
+                                       *flashlight_dev)
+{
+       return dev_get_drvdata(&flashlight_dev->dev);
+}
+#endif /*LINUX_LEDS_FLASHLIGHT_H */
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/leds-rt8547.c b/drivers/media/video/rk_camsys/ext_flashled_drv/leds-rt8547.c
new file mode 100755 (executable)
index 0000000..f4cdc7e
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+ *  drivers/leds/leds-rt8547.c
+ *  Driver for Richtek RT8547 LED Flash IC
+ *
+ *  Copyright (C) 2014 Richtek Technology Corp.
+ *  cy_huang <cy_huang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/of_gpio.h>
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif /* #ifdef CONFIG_OF */
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#endif /* #ifdef CONFIG_DEBUG_FS */
+
+#include "rtfled.h"
+#include "leds-rt8547.h"
+
+struct rt8547_chip {
+       rt_fled_info_t base;
+       struct device *dev;
+       struct rt8547_platform_data *pdata;
+       spinlock_t io_lock;
+       unsigned char suspend:1;
+       int in_use_mode;
+#ifdef CONFIG_DEBUG_FS
+       struct flashlight_device *fled_dev;
+       unsigned char reg_addr;
+       unsigned char reg_data;
+#endif                         /* #ifdef CONFIG_DEBUG_FS */
+};
+
+#ifdef CONFIG_DEBUG_FS
+struct rt_debug_st {
+       void *info;
+       int id;
+};
+
+enum {
+       RT8547_DBG_REG,
+       RT8547_DBG_DATA,
+       RT8547_DBG_REGS,
+       RT8547_DBG_FLED,
+       RT8547_DBG_MAX
+};
+
+static struct dentry *debugfs_rt_dent;
+static struct dentry *debugfs_file[RT8547_DBG_MAX];
+static struct rt_debug_st rtdbg_data[RT8547_DBG_MAX];
+#endif /* #ifdef CONFIG_DEBUG_FS */
+
+static unsigned char rt8547_reg_initval[] = {
+       0x06,                   /* REG 0x01 */
+       0x12,                   /* REG 0x02 */
+       0x02,                   /* REG 0x03 */
+       0x0F,                   /* REG 0x04 */
+};
+
+static inline int rt8547_send_bit(struct rt8547_platform_data *pdata,
+                                 unsigned char bit)
+{
+       if (bit) {
+               gpio_set_value(pdata->flset_gpio, (~(pdata->flset_active) & 0x1));
+               udelay(RT8547_SHORT_DELAY);
+               gpio_set_value(pdata->flset_gpio, ((pdata->flset_active) & 0x1));
+               udelay(RT8547_LONG_DELAY);
+       } else {
+               gpio_set_value(pdata->flset_gpio, (~(pdata->flset_active) & 0x1));
+               udelay(RT8547_LONG_DELAY);
+               gpio_set_value(pdata->flset_gpio, ((pdata->flset_active) & 0x1));
+               udelay(RT8547_SHORT_DELAY);
+       }
+       return 0;
+}
+
+static inline int rt8547_send_byte(struct rt8547_platform_data *pdata,
+                                  unsigned char byte)
+{
+       int i;
+
+       /*Send order is high bit to low bit */
+       for (i = 7; i >= 0; i--)
+               rt8547_send_bit(pdata, byte & (0x1 << i));
+       return 0;
+}
+
+static inline int rt8547_send_special_byte(struct rt8547_platform_data *pdata,
+                                          unsigned char byte)
+{
+       int i;
+
+       /*Only send three bit for register address */
+       for (i = 2; i >= 0; i--)
+               rt8547_send_bit(pdata, byte & (0x1 << i));
+       return 0;
+}
+
+static inline int rt8547_start_xfer(struct rt8547_platform_data *pdata)
+{
+       gpio_set_value(pdata->flset_gpio, ((pdata->flset_active) & 0x1));
+       udelay(RT8547_START_DELAY);
+       return 0;
+}
+
+static inline int rt8547_stop_xfer(struct rt8547_platform_data *pdata)
+{
+       /*Redundant one bit as the stop condition */
+       rt8547_send_bit(pdata, 1);
+       return 0;
+}
+
+static int rt8547_send_data(struct rt8547_chip *chip, unsigned char reg,
+                           unsigned char data)
+{
+       struct rt8547_platform_data *pdata = chip->pdata;
+       unsigned long flags;
+       unsigned char xfer_data[3];     /*0: adddr, 1: reg, 2: reg data*/
+
+       xfer_data[0] = RT8547_ONEWIRE_ADDR;
+       xfer_data[1] = reg;
+       xfer_data[2] = data;
+       RT_DBG("rt8547-> 0: 0x%02x, 1: 0x%02x, 2: 0x%02x\n", xfer_data[0],
+              xfer_data[1], xfer_data[2]);
+       spin_lock_irqsave(&chip->io_lock, flags);
+       rt8547_start_xfer(pdata);
+       rt8547_send_byte(pdata, xfer_data[0]);
+       rt8547_send_special_byte(pdata, xfer_data[1]);
+       rt8547_send_byte(pdata, xfer_data[2]);
+       rt8547_stop_xfer(pdata);
+       spin_unlock_irqrestore(&chip->io_lock, flags);
+       /*write back to reg array*/
+       rt8547_reg_initval[reg - 1] = data;
+       return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int reg_debug_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static int get_parameters(char *buf, long int *param1, int num_of_par)
+{
+       char *token;
+       int base, cnt;
+
+       token = strsep(&buf, " ");
+
+       for (cnt = 0; cnt < num_of_par; cnt++) {
+               if (token != NULL) {
+                       if ((token[1] == 'x') || (token[1] == 'X'))
+                               base = 16;
+                       else
+                               base = 10;
+
+                       if (kstrtoul(token, base, &param1[cnt]) != 0)
+                               return -EINVAL;
+
+                       token = strsep(&buf, " ");
+               } else
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+static ssize_t reg_debug_read(struct file *filp, char __user *ubuf,
+                             size_t count, loff_t *ppos)
+{
+       struct rt_debug_st *st = filp->private_data;
+       struct rt8547_chip *di = st->info;
+       char lbuf[1000];
+       int i = 0, j = 0;
+
+       lbuf[0] = '\0';
+       switch (st->id) {
+       case RT8547_DBG_REG:
+               snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_addr);
+               break;
+       case RT8547_DBG_DATA:
+               di->reg_data = rt8547_reg_initval[di->reg_addr - 1];
+               snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_data);
+               break;
+       case RT8547_DBG_REGS:
+               for (i = RT8547_FLED_REG0; i < RT8547_FLED_REGMAX; i++)
+                       j += snprintf(lbuf + j, 20, "0x%02x:%02x\n", i,
+                                     rt8547_reg_initval[i - 1]);
+               break;
+       case RT8547_DBG_FLED:
+               snprintf(lbuf, sizeof(lbuf), "%d\n", di->in_use_mode);
+               break;
+       default:
+               return -EINVAL;
+
+       }
+       return simple_read_from_buffer(ubuf, count, ppos, lbuf, strlen(lbuf));
+}
+
+static ssize_t reg_debug_write(struct file *filp,
+                              const char __user *ubuf, size_t cnt,
+                              loff_t *ppos)
+{
+       struct rt_debug_st *st = filp->private_data;
+       struct rt8547_chip *di = st->info;
+       char lbuf[32];
+       int rc;
+       long int param[5];
+
+       if (cnt > sizeof(lbuf) - 1)
+               return -EINVAL;
+
+       rc = copy_from_user(lbuf, ubuf, cnt);
+       if (rc)
+               return -EFAULT;
+
+       lbuf[cnt] = '\0';
+
+       switch (st->id) {
+       case RT8547_DBG_REG:
+               rc = get_parameters(lbuf, param, 1);
+               if ((param[0] < RT8547_FLED_REGMAX) && (rc == 0)) {
+                       if ((param[0] >= RT8547_FLED_REG0
+                            && param[0] <= RT8547_FLED_REG3))
+                               di->reg_addr = (unsigned char)param[0];
+                       else
+                               rc = -EINVAL;
+               } else
+                       rc = -EINVAL;
+               break;
+       case RT8547_DBG_DATA:
+               rc = get_parameters(lbuf, param, 1);
+               if ((param[0] <= 0xff) && (rc == 0)) {
+                       rt8547_send_data(di, di->reg_addr,
+                                        (unsigned char)param[0]);
+               } else
+                       rc = -EINVAL;
+               break;
+       case RT8547_DBG_FLED:
+               if (!di->fled_dev)
+                       di->fled_dev = find_flashlight_by_name("rt-flash-led");
+               rc = get_parameters(lbuf, param, 1);
+               if ((param[0] <= FLASHLIGHT_MODE_FLASH) && (rc == 0)
+                   && di->fled_dev) {
+                       switch (param[0]) {
+                       case FLASHLIGHT_MODE_TORCH:
+                               flashlight_set_torch_brightness(di->fled_dev,
+                                                               2);
+                               flashlight_set_mode(di->fled_dev,
+                                                   FLASHLIGHT_MODE_TORCH);
+                               break;
+                       case FLASHLIGHT_MODE_FLASH:
+                               flashlight_set_strobe_timeout(di->fled_dev,
+                                                             256, 256);
+                               flashlight_set_strobe_brightness(di->fled_dev,
+                                                                18);
+                               flashlight_set_mode(di->fled_dev,
+                                                   FLASHLIGHT_MODE_FLASH);
+                               flashlight_strobe(di->fled_dev);
+                               break;
+                       case FLASHLIGHT_MODE_OFF:
+                               flashlight_set_mode(di->fled_dev,
+                                                   FLASHLIGHT_MODE_OFF);
+                               break;
+                       }
+               } else
+                       rc = -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (rc == 0)
+               rc = cnt;
+       return rc;
+}
+
+static const struct file_operations reg_debug_ops = {
+       .open = reg_debug_open,
+       .write = reg_debug_write,
+       .read = reg_debug_read
+};
+
+static void rt8547_create_debugfs(struct rt8547_chip *chip)
+{
+       RT_DBG("add debugfs for RT8547\n");
+       debugfs_rt_dent = debugfs_create_dir("rt8547_dbg", 0);
+       if (!IS_ERR(debugfs_rt_dent)) {
+               rtdbg_data[0].info = chip;
+               rtdbg_data[0].id = RT8547_DBG_REG;
+               debugfs_file[0] = debugfs_create_file("reg",
+                                                     S_IFREG | S_IRUGO,
+                                                     debugfs_rt_dent,
+                                                     (void *)&rtdbg_data[0],
+                                                     &reg_debug_ops);
+
+               rtdbg_data[1].info = chip;
+               rtdbg_data[1].id = RT8547_DBG_DATA;
+               debugfs_file[1] = debugfs_create_file("data",
+                                                     S_IFREG | S_IRUGO,
+                                                     debugfs_rt_dent,
+                                                     (void *)&rtdbg_data[1],
+                                                     &reg_debug_ops);
+
+               rtdbg_data[2].info = chip;
+               rtdbg_data[2].id = RT8547_DBG_REGS;
+               debugfs_file[2] = debugfs_create_file("regs",
+                                                     S_IFREG | S_IRUGO,
+                                                     debugfs_rt_dent,
+                                                     (void *)&rtdbg_data[2],
+                                                     &reg_debug_ops);
+
+               rtdbg_data[3].info = chip;
+               rtdbg_data[3].id = RT8547_DBG_FLED;
+               debugfs_file[3] = debugfs_create_file("fled",
+                                                     S_IFREG | S_IRUGO,
+                                                     debugfs_rt_dent,
+                                                     (void *)&rtdbg_data[3],
+                                                     &reg_debug_ops);
+       } else {
+               dev_err(chip->dev, "create debugfs failed\n");
+       }
+}
+
+static void rt8547_remove_debugfs(void)
+{
+       if (!IS_ERR(debugfs_rt_dent))
+               debugfs_remove_recursive(debugfs_rt_dent);
+}
+#endif /* #ifdef CONFIG_DEBUG_FS */
+
+static inline void rt8547_fled_power_on(struct rt8547_platform_data *pdata)
+{
+    if (gpio_is_valid(pdata->flset_gpio))
+       gpio_set_value(pdata->flset_gpio, ((pdata->flset_active) & 0x1));
+}
+
+static inline void rt8547_fled_power_off(struct rt8547_platform_data *pdata)
+{
+    if (gpio_is_valid(pdata->flset_gpio))
+       gpio_set_value(pdata->flset_gpio, (~(pdata->flset_active) & 0x1));
+       udelay(RT8547_STOP_DELAY);
+}
+
+static inline void rt8547_fled_ctrl_en(struct rt8547_platform_data *pdata,
+                                      int en)
+{
+    if (gpio_is_valid(pdata->ctl_gpio)){
+       if (en)
+               gpio_set_value(pdata->ctl_gpio, ((pdata->ctl_active) & 0x1));
+       else
+               gpio_set_value(pdata->ctl_gpio, (~(pdata->ctl_active) & 0x1));
+       }
+       RT_DBG("en %d\n", en);
+}
+
+static inline void rt8547_fled_flash_en(struct rt8547_platform_data *pdata,
+                                       int en)
+{
+    if (gpio_is_valid(pdata->flen_gpio)){
+       if (en)
+               gpio_set_value(pdata->flen_gpio, ((pdata->flen_active) & 0x1));
+       else
+               gpio_set_value(pdata->flen_gpio, (~(pdata->flen_active) & 0x1));
+       }
+       RT_DBG("en %d\n", en);
+}
+
+static int rt8547_fled_init(struct rt_fled_info *info)
+{
+       RT_DBG("\n");
+       return 0;
+}
+
+static int rt8547_fled_resume(struct rt_fled_info *info)
+{
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+
+       RT_DBG("\n");
+       fi->suspend = 0;
+       return 0;
+}
+
+static int rt8547_fled_suspend(struct rt_fled_info *info, pm_message_t state)
+{
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+
+       RT_DBG("\n");
+       fi->suspend = 1;
+       return 0;
+}
+
+static int rt8547_fled_set_mode(struct rt_fled_info *info,
+                               flashlight_mode_t mode)
+{
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+       unsigned char tmp = 0;
+       int ret = 0;
+
+       RT_DBG("mode=%d\n", mode);
+       switch (mode) {
+       case FLASHLIGHT_MODE_TORCH:
+               if (fi->in_use_mode == FLASHLIGHT_MODE_OFF)
+                       rt8547_fled_power_on(fi->pdata);
+               tmp = rt8547_reg_initval[RT8547_FLED_REG2 - 1];
+               tmp |= RT8547_MODESEL_MASK;
+               rt8547_send_data(fi, RT8547_FLED_REG2, tmp);
+               rt8547_fled_ctrl_en(fi->pdata, 1);
+               rt8547_fled_flash_en(fi->pdata, 1);
+               fi->in_use_mode = mode;
+               break;
+       case FLASHLIGHT_MODE_FLASH:
+               if (fi->in_use_mode == FLASHLIGHT_MODE_OFF)
+                       rt8547_fled_power_on(fi->pdata);
+               tmp = rt8547_reg_initval[RT8547_FLED_REG2 - 1];
+               tmp &= ~RT8547_MODESEL_MASK;
+               rt8547_send_data(fi, RT8547_FLED_REG2, tmp);
+               fi->in_use_mode = mode;
+               break;
+       case FLASHLIGHT_MODE_OFF:
+               rt8547_fled_flash_en(fi->pdata, 0);
+               rt8547_fled_ctrl_en(fi->pdata, 0);
+               if (fi->in_use_mode != FLASHLIGHT_MODE_OFF)
+                       rt8547_fled_power_off(fi->pdata);
+               fi->in_use_mode = mode;
+               break;
+       case FLASHLIGHT_MODE_MIXED:
+       default:
+               ret = -EINVAL;
+       }
+       return 0;
+}
+
+static int rt8547_fled_get_mode(struct rt_fled_info *info)
+{
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+
+       RT_DBG("\n");
+       return fi->in_use_mode;
+}
+
+static int rt8547_fled_strobe(struct rt_fled_info *info)
+{
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+
+       RT_DBG("\n");
+       rt8547_fled_flash_en(fi->pdata, 0);
+       rt8547_fled_ctrl_en(fi->pdata, 0);
+       rt8547_fled_ctrl_en(fi->pdata, 1);
+       rt8547_fled_flash_en(fi->pdata, 1);
+       return 0;
+}
+
+static int rt8547_fled_torch_current_list(struct rt_fled_info *info,
+                                         int selector)
+{
+       RT_DBG("selector=%d\n", selector);
+       return 25000 + selector * 25000;        /* unit: uA */
+}
+
+static int rt8547_fled_strobe_current_list(struct rt_fled_info *info,
+                                          int selector)
+{
+       RT_DBG("selector=%d\n", selector);
+       return 100000 + selector * 50000;       /* unit: uA */
+}
+
+static int rt8547_fled_timeout_level_list(struct rt_fled_info *info,
+                                         int selector)
+{
+       RT_DBG("selector=%d\n", selector);
+       return 100000 + selector * 50000;       /* unit: uA */
+}
+
+static int rt8547_fled_lv_protection_list(struct rt_fled_info *info,
+                                         int selector)
+{
+       RT_DBG("selector=%d\n", selector);
+       return 3000 + selector * 100;   /* unit: mV */
+}
+
+static int rt8547_fled_strobe_timeout_list(struct rt_fled_info *info,
+                                          int selector)
+{
+       RT_DBG("selector=%d\n", selector);
+       return 64 + selector * 32;      /* unit: mS */
+}
+
+static int rt8547_fled_set_torch_current_sel(struct rt_fled_info *info,
+                                            int selector)
+{
+
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+       unsigned char tmp = 0;
+
+       RT_DBG("selector=%d\n", selector);
+       tmp = rt8547_reg_initval[RT8547_FLED_REG2 - 1];
+       tmp &= ~RT8547_TCLEVEL_MASK;
+       tmp |= selector;
+       rt8547_send_data(fi, RT8547_FLED_REG2, tmp);
+       return 0;
+}
+
+static int rt8547_fled_set_strobe_current_sel(struct rt_fled_info *info,
+                                             int selector)
+{
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+       unsigned char tmp = 0;
+
+       RT_DBG("selector=%d\n", selector);
+       tmp = rt8547_reg_initval[RT8547_FLED_REG1 - 1];
+       tmp &= ~RT8547_SCLEVEL_MASK;
+       tmp |= selector;
+       rt8547_send_data(fi, RT8547_FLED_REG1, tmp);
+       return 0;
+}
+
+static int rt8547_fled_set_timeout_level_sel(struct rt_fled_info *info,
+                                            int selector)
+{
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+       unsigned char tmp = 0;
+
+       RT_DBG("selector=%d\n", selector);
+       if (selector > RT8547_TOL_MAX)
+               return -EINVAL;
+       tmp = rt8547_reg_initval[RT8547_FLED_REG1 - 1];
+       tmp &= ~RT8547_TOCLEVEL_MASK;
+       tmp |= (selector << RT8547_TOCLEVEL_SHFT);
+       rt8547_send_data(fi, RT8547_FLED_REG1, tmp);
+       return 0;
+}
+
+static int rt8547_fled_set_lv_protection_sel(struct rt_fled_info *info,
+                                            int selector)
+{
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+       unsigned char tmp = 0;
+
+       RT_DBG("selector=%d\n", selector);
+       if (selector > RT8547_LVP_MAX)
+               return -EINVAL;
+       tmp = rt8547_reg_initval[RT8547_FLED_REG0 - 1];
+       tmp &= ~RT8547_LVP_MASK;
+       tmp |= selector;
+       rt8547_send_data(fi, RT8547_FLED_REG0, tmp);
+       return 0;
+}
+
+static int rt8547_fled_set_strobe_timeout_sel(struct rt_fled_info *info,
+                                             int selector)
+{
+       struct rt8547_chip *fi = (struct rt8547_chip *)info;
+       unsigned char tmp = 0;
+
+       RT_DBG("selector=%d\n", selector);
+       if (selector > RT8547_STO_MAX)
+               return -EINVAL;
+       tmp = rt8547_reg_initval[RT8547_FLED_REG3 - 1];
+       tmp &= ~RT8547_STO_MASK;
+       tmp |= selector;
+       rt8547_send_data(fi, RT8547_FLED_REG3, tmp);
+       return 0;
+}
+
+static int rt8547_fled_get_torch_current_sel(struct rt_fled_info *info)
+{
+       int selector =
+           rt8547_reg_initval[RT8547_FLED_REG2 - 1] & RT8547_TCLEVEL_MASK;
+
+       return selector;
+}
+
+static int rt8547_fled_get_strobe_current_sel(struct rt_fled_info *info)
+{
+       int selector =
+           rt8547_reg_initval[RT8547_FLED_REG1 - 1] & RT8547_SCLEVEL_MASK;
+
+       return selector;
+}
+
+static int rt8547_fled_get_timeout_level_sel(struct rt_fled_info *info)
+{
+       int selector =
+           rt8547_reg_initval[RT8547_FLED_REG1 - 1] & RT8547_TOCLEVEL_MASK;
+
+       selector >>= RT8547_TOCLEVEL_SHFT;
+       return selector;
+}
+
+static int rt8547_fled_get_lv_protection_sel(struct rt_fled_info *info)
+{
+       int selector =
+           rt8547_reg_initval[RT8547_FLED_REG0 - 1] & RT8547_LVP_MASK;
+
+       return selector;
+}
+
+static int rt8547_fled_get_strobe_timeout_sel(struct rt_fled_info *info)
+{
+       int selector =
+           rt8547_reg_initval[RT8547_FLED_REG3 - 1] & RT8547_STO_MASK;
+
+       return selector;
+}
+
+static struct rt_fled_hal rt8547_fled_hal = {
+       .fled_init = rt8547_fled_init,
+       .fled_suspend = rt8547_fled_suspend,
+       .fled_resume = rt8547_fled_resume,
+       .fled_set_mode = rt8547_fled_set_mode,
+       .fled_get_mode = rt8547_fled_get_mode,
+       .fled_strobe = rt8547_fled_strobe,
+       .fled_torch_current_list = rt8547_fled_torch_current_list,
+       .fled_strobe_current_list = rt8547_fled_strobe_current_list,
+       .fled_timeout_level_list = rt8547_fled_timeout_level_list,
+       .fled_lv_protection_list = rt8547_fled_lv_protection_list,
+       .fled_strobe_timeout_list = rt8547_fled_strobe_timeout_list,
+       /* method to set */
+       .fled_set_torch_current_sel = rt8547_fled_set_torch_current_sel,
+       .fled_set_strobe_current_sel = rt8547_fled_set_strobe_current_sel,
+       .fled_set_timeout_level_sel = rt8547_fled_set_timeout_level_sel,
+       .fled_set_lv_protection_sel = rt8547_fled_set_lv_protection_sel,
+       .fled_set_strobe_timeout_sel = rt8547_fled_set_strobe_timeout_sel,
+       /* method to get */
+       .fled_get_torch_current_sel = rt8547_fled_get_torch_current_sel,
+       .fled_get_strobe_current_sel = rt8547_fled_get_strobe_current_sel,
+       .fled_get_timeout_level_sel = rt8547_fled_get_timeout_level_sel,
+       .fled_get_lv_protection_sel = rt8547_fled_get_lv_protection_sel,
+       .fled_get_strobe_timeout_sel = rt8547_fled_get_strobe_timeout_sel,
+};
+
+static struct flashlight_properties rt8547_fled_props = {
+       .type = FLASHLIGHT_TYPE_LED,
+       .torch_brightness = 2,
+       .torch_max_brightness = 15,
+       .strobe_brightness = 18,
+       .strobe_max_brightness = 30,
+       .strobe_delay = 2,
+       .strobe_timeout = 544,
+       .alias_name = "rt8547-fled",
+};
+
+static void rt8547_parse_dt(struct rt8547_platform_data *pdata,
+                           struct device *dev)
+{
+#ifdef CONFIG_OF
+       struct device_node *np = dev->of_node;
+       u32 tmp;
+
+       if (of_property_read_u32(np, "rt,def_lvp", &tmp) < 0) {
+               dev_warn(dev, "use 3V as the default lvp\n");
+       } else {
+               if (tmp > RT8547_LVP_MAX)
+                       tmp = RT8547_LVP_MAX;
+               rt8547_reg_initval[RT8547_FLED_REG0 - 1] &= ~RT8547_LVP_MASK;
+               rt8547_reg_initval[RT8547_FLED_REG0 - 1] |= tmp;
+       }
+
+       if (of_property_read_u32(np, "rt,def_tol", &tmp) < 0) {
+               dev_warn(dev, "use 100mA as the default timeout level\n");
+       } else {
+               if (tmp > RT8547_TOL_MAX)
+                       tmp = RT8547_TOL_MAX;
+               tmp <<= RT8547_TOCLEVEL_SHFT;
+               rt8547_reg_initval[RT8547_FLED_REG1 - 1] &=
+                   ~RT8547_TOCLEVEL_MASK;
+               rt8547_reg_initval[RT8547_FLED_REG1 - 1] |= tmp;
+       }
+       pdata->flen_gpio = of_get_named_gpio(np, "rt,flen_gpio", 0);
+       pdata->ctl_gpio = of_get_named_gpio(np, "rt,ctl_gpio", 0);
+       pdata->flset_gpio = of_get_named_gpio(np, "rt,flset_gpio", 0);
+#endif /* #ifdef CONFIG_OF */
+}
+
+static void rt8547_parse_pdata(struct rt8547_platform_data *pdata,
+                              struct device *dev)
+{
+       u32 tmp;
+
+       tmp = pdata->def_lvp;
+       rt8547_reg_initval[RT8547_FLED_REG0 - 1] &= ~RT8547_LVP_MASK;
+       rt8547_reg_initval[RT8547_FLED_REG0 - 1] |= tmp;
+
+       tmp = pdata->def_tol;
+       tmp <<= RT8547_TOCLEVEL_SHFT;
+       rt8547_reg_initval[RT8547_FLED_REG1 - 1] &= ~RT8547_TOCLEVEL_MASK;
+       rt8547_reg_initval[RT8547_FLED_REG1 - 1] |= tmp;
+}
+
+static int rt8547_io_init(struct rt8547_platform_data *pdata,
+                         struct device *dev)
+{
+       int rc = 0;
+
+       if (gpio_is_valid(pdata->flen_gpio)) {
+               rc = gpio_request_one(pdata->flen_gpio, ((~(pdata->flen_active) & 0x1) ? GPIOF_OUT_INIT_HIGH:GPIOF_OUT_INIT_LOW),
+                                     "rt8547_flen");
+               if (rc < 0) {
+                       dev_err(dev, "request rt8547 flash en pin fail\n");
+                       goto gpio_request1;
+               }
+
+       }
+
+       if(gpio_is_valid(pdata->ctl_gpio)){
+               rc = gpio_request_one(pdata->ctl_gpio, ((~(pdata->ctl_active) & 0x1) ? GPIOF_OUT_INIT_HIGH:GPIOF_OUT_INIT_LOW),
+                                     "rt8547_ctl");
+               if (rc < 0) {
+                       dev_err(dev, "request rt8547 ctl pin fail\n");
+                       goto gpio_request2;
+               }
+       }
+
+       if(gpio_is_valid(pdata->flset_gpio)){
+               rc = gpio_request_one(pdata->flset_gpio, ((~(pdata->flset_active) & 0x1) ? GPIOF_OUT_INIT_HIGH:GPIOF_OUT_INIT_LOW),
+                                     "rt8547_flset");
+               if (rc < 0) {
+                       dev_err(dev, "request rt8547 flash set pin fail\n");
+                       goto gpio_request3;
+               }
+       }
+       return 0;
+gpio_request3:
+    if(gpio_is_valid(pdata->ctl_gpio))
+       gpio_free(pdata->ctl_gpio);
+gpio_request2:
+    if (gpio_is_valid(pdata->flen_gpio))
+       gpio_free(pdata->flen_gpio);
+gpio_request1:
+       return rc;
+
+}
+
+static int rt8547_io_deinit(struct rt8547_platform_data *pdata)
+{
+    if (gpio_is_valid(pdata->flen_gpio)){
+       gpio_direction_input(pdata->flen_gpio);
+       gpio_free(pdata->flen_gpio);
+       }
+    if(gpio_is_valid(pdata->ctl_gpio)){
+       gpio_direction_input(pdata->ctl_gpio);
+       gpio_free(pdata->ctl_gpio);
+       }
+       if(gpio_is_valid(pdata->flset_gpio)){
+       gpio_direction_input(pdata->flset_gpio);
+       gpio_free(pdata->flset_gpio);
+       }
+       return 0;
+}
+
+static void rt8547_reg_init(struct rt8547_chip *chip)
+{
+       RT_DBG("\n");
+       rt8547_send_data(chip, RT8547_FLED_REG0,
+                        rt8547_reg_initval[RT8547_FLED_REG0 - 1]);
+       rt8547_send_data(chip, RT8547_FLED_REG1,
+                        rt8547_reg_initval[RT8547_FLED_REG1 - 1]);
+       rt8547_send_data(chip, RT8547_FLED_REG2,
+                        rt8547_reg_initval[RT8547_FLED_REG2 - 1]);
+       rt8547_send_data(chip, RT8547_FLED_REG3,
+                        rt8547_reg_initval[RT8547_FLED_REG3 - 1]);
+}
+
+static struct platform_device rt_fled_pdev = {
+       .name = "rt-flash-led",
+       .id = -1,
+};
+
+static int rt8547_led_probe(struct platform_device *pdev)
+{
+       struct rt8547_platform_data *pdata = pdev->dev.platform_data;
+       struct rt8547_chip *chip;
+       bool use_dt = pdev->dev.of_node;
+       int ret = 0;
+
+       chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+       if (use_dt) {
+               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+               if (!pdata)
+                       goto err_probe;
+               rt8547_parse_dt(pdata, &pdev->dev);
+       } else {
+               if (!pdata)
+                       goto err_probe;
+               rt8547_parse_pdata(pdata, &pdev->dev);
+       }
+
+       ret = rt8547_io_init(pdata, &pdev->dev);
+       if (ret < 0)
+               goto err_io;
+
+       chip->dev = &pdev->dev;
+       chip->pdata = pdata;
+       spin_lock_init(&chip->io_lock);
+       chip->in_use_mode = FLASHLIGHT_MODE_OFF;
+       platform_set_drvdata(pdev, chip);
+
+       rt8547_fled_power_on(pdata);
+       rt8547_reg_init(chip);
+       rt8547_fled_power_off(pdata);
+
+       chip->base.hal = &rt8547_fled_hal;
+       chip->base.init_props = &rt8547_fled_props;
+       rt_fled_pdev.dev.parent = &pdev->dev;
+       ret = platform_device_register(&rt_fled_pdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "register rtfled fail\n");
+               goto err_io;
+       }
+#ifdef CONFIG_DEBUG_FS
+       rt8547_create_debugfs(chip);
+#endif /* #ifdef CONFIG_DEBUG_FS */
+       dev_info(&pdev->dev, "driver successfully registered\n");
+       return 0;
+err_io:
+       if (use_dt)
+               devm_kfree(&pdev->dev, pdata);
+err_probe:
+       devm_kfree(&pdev->dev, chip);
+       return ret;
+}
+
+static int rt8547_led_remove(struct platform_device *pdev)
+{
+       struct rt8547_chip *chip = platform_get_drvdata(pdev);
+
+#ifdef CONFIG_DEBUG_FS
+       rt8547_remove_debugfs();
+#endif /* #ifdef CONFIG_DEBUG_FS */
+       platform_device_unregister(&rt_fled_pdev);
+       rt8547_io_deinit(chip->pdata);
+       return 0;
+}
+
+static const struct of_device_id rt_match_table[] = {
+       {.compatible = "rt,rt8547",},
+       {},
+};
+
+static struct platform_driver rt8547_led_driver = {
+       .driver = {
+                  .name = "rt8547",
+                  .owner = THIS_MODULE,
+                  .of_match_table = rt_match_table,
+                  },
+       .probe = rt8547_led_probe,
+       .remove = rt8547_led_remove,
+};
+
+static int rt8547_led_init(void)
+{
+       return platform_driver_register(&rt8547_led_driver);
+}
+
+module_init(rt8547_led_init);
+
+static void rt8547_led_exit(void)
+{
+       platform_driver_unregister(&rt8547_led_driver);
+}
+
+module_exit(rt8547_led_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("LED Flash Driver for RT8547");
+MODULE_VERSION(RT8547_DRV_VER);
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/leds-rt8547.h b/drivers/media/video/rk_camsys/ext_flashled_drv/leds-rt8547.h
new file mode 100755 (executable)
index 0000000..a1a7a8e
--- /dev/null
@@ -0,0 +1,84 @@
+/* include/linux/leds-rt8547.h
+ * Include file of driver to Richtek RT8547 LED Flash IC
+ *
+ * Copyright (C) 2014 Richtek Technology Corporation
+ * Author: CY_Huang <cy_huang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_LEDS_RT8547_H
+#define __LINUX_LEDS_RT8547_H
+
+#define RT8547_DRV_VER "1.0.2_G"
+
+enum {
+       RT8547_FLED_REG0 = 0x01,
+       RT8547_FLED_REG1,
+       RT8547_FLED_REG2,
+       RT8547_FLED_REG3,
+       RT8547_FLED_REGMAX,
+};
+
+enum {
+       RT8547_LVP_3V,
+       RT8547_LVP_3P1V,
+       RT8547_LVP_3P2V,
+       RT8547_LVP_3P3V,
+       RT8547_LVP_3P4V,
+       RT8547_LVP_3P5V,
+       RT8547_LVP_3P6V,
+       RT8547_LVP_3P7V,
+       RT8547_LVP_3P8V,
+       RT8547_LVP_MAX = RT8547_LVP_3P8V,
+};
+
+enum {
+       RT8547_TOL_100mA,
+       RT8547_TOL_150mA,
+       RT8547_TOL_200mA,
+       RT8547_TOL_250mA,
+       RT8547_TOL_300mA,
+       RT8547_TOL_350mA,
+       RT8547_TOL_400mA,
+       RT8547_TOL_MAX = RT8547_TOL_400mA,
+};
+
+#define RT8547_STO_MAX 36
+
+#define RT8547_LVP_MASK 0x0F
+#define RT8547_TOCLEVEL_MASK 0xE0
+#define RT8547_TOCLEVEL_SHFT 5
+#define RT8547_SCLEVEL_MASK 0x1F
+#define RT8547_SWRST_MASK 0x20
+#define RT8547_MODESEL_MASK 0x10
+#define RT8547_TCLEVEL_MASK 0x0F
+#define RT8547_STO_MASK 0x3F
+
+struct rt8547_platform_data {
+       int flen_gpio;
+       int flen_active;
+       int ctl_gpio;
+       int ctl_active;
+       int flset_gpio;
+       int flset_active;
+       unsigned char def_lvp:4;
+       unsigned char def_tol:3;
+};
+
+/* one wire protocol parameter */
+#define RT8547_ONEWIRE_ADDR 0x99
+#define RT8547_LONG_DELAY 9
+#define RT8547_SHORT_DELAY 4
+#define RT8547_START_DELAY 10
+#define RT8547_STOP_DELAY 1500
+
+#ifdef CONFIG_LEDS_RT8547_DBG
+#define RT_DBG(fmt, args...) pr_info("%s: " fmt, __func__, ##args)
+#else
+#define RT_DBG(fmt, args...)
+#endif /* #ifdef CONFIG_LEDS_RT8547_DBG */
+
+#endif /* #ifndef __LINUX_LEDS_RT8547_H */
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.c b/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.c
new file mode 100755 (executable)
index 0000000..8d11019
--- /dev/null
@@ -0,0 +1,168 @@
+#include "rk_ext_fshled_ctl.h"
+#include "../camsys_gpio.h"
+#include "flashlight.h"
+#include "leds-rt8547.h"
+
+typedef struct ext_fsh_info_s{
+    struct      platform_device pdev;
+    char*       dev_model;    
+    struct      list_head         list;
+}ext_fsh_info_t;
+
+struct ext_fsh_dev_list_s{
+    struct list_head         dev_list;
+};
+
+static struct ext_fsh_dev_list_s g_ext_fsh_devs;
+
+int camsys_init_ext_fsh_module()
+{
+    camsys_trace(1,"init external flash module");
+    INIT_LIST_HEAD(&g_ext_fsh_devs.dev_list);
+    return 0;
+}
+
+int camsys_deinit_ext_fsh_module()
+{
+    ext_fsh_info_t* cur_fsh_info = NULL;
+    camsys_trace(1,"deinit external flash module");
+    if (!list_empty(&g_ext_fsh_devs.dev_list)) {
+        list_for_each_entry(cur_fsh_info, &g_ext_fsh_devs.dev_list, list) {
+            if (cur_fsh_info) {
+               platform_device_unregister(&cur_fsh_info->pdev);
+               list_del_init(&cur_fsh_info->list);
+               /* free after unregister device ?*/
+               kfree(cur_fsh_info->pdev.dev.platform_data);
+               kfree(cur_fsh_info);
+               cur_fsh_info = NULL;
+            }
+        }
+    }
+    
+    INIT_LIST_HEAD(&g_ext_fsh_devs.dev_list);
+    return 0;
+}
+void* camsys_register_ext_fsh_dev(camsys_flash_info_t *fsh_info)
+{
+    ext_fsh_info_t* new_dev = NULL;
+    if(strcmp(fsh_info->fl_drv_name,"rt8547") == 0){
+        struct rt8547_platform_data* new_rt_dev = NULL;
+        new_dev = kzalloc(sizeof(ext_fsh_info_t),GFP_KERNEL);
+        if(!new_dev){
+            camsys_err("register new ext flash dev erro !");
+            goto fail0;
+        }
+        
+        new_rt_dev = kzalloc(sizeof(ext_fsh_info_t),GFP_KERNEL);
+        if(!new_rt_dev){
+            camsys_err("register new ext flash dev erro !");
+            goto fail1;
+        }
+
+        new_dev->pdev.id = -1;
+        new_dev->pdev.name = fsh_info->fl_drv_name;
+        new_dev->pdev.dev.platform_data = (void*)new_rt_dev;
+        new_dev->dev_model = "rt-flash-led";
+
+        new_rt_dev->flen_gpio = camsys_gpio_get(fsh_info->fl_en.name);
+        new_rt_dev->flen_active = fsh_info->fl_en.active;
+        camsys_trace(1,"flen name :%s,gpio %d,active %d \n",fsh_info->fl_en.name,new_rt_dev->flen_gpio,new_rt_dev->flen_active);
+        new_rt_dev->flset_gpio = camsys_gpio_get(fsh_info->fl.name );
+        new_rt_dev->flset_active = fsh_info->fl.active;
+        camsys_trace(1,"flset name :%s, gpio %d, active %d \n",fsh_info->fl.name,new_rt_dev->flset_gpio,new_rt_dev->flset_active);
+        new_rt_dev->ctl_gpio   = -1;
+        new_rt_dev->def_lvp = RT8547_LVP_3V;
+           new_rt_dev->def_tol = RT8547_TOL_100mA;
+
+    //    new_rt_dev->def_lvp = RT8547_LVP_MAX;
+       //    new_rt_dev->def_tol = RT8547_TOL_MAX;
+
+       if(platform_device_register(&new_dev->pdev) < 0){
+               camsys_err("register rtfled fail\n");
+               kfree(new_rt_dev);
+               goto fail1;
+       }
+
+        list_add_tail(&new_dev->list, &g_ext_fsh_devs.dev_list);
+        camsys_trace(1,"register new rt led dev success !");
+    }
+    
+    return (void*)new_dev;
+fail1:
+    if(new_dev)
+        kfree(new_dev);
+fail0:
+    return NULL;
+}
+
+int camsys_deregister_ext_fsh_dev(void* dev)
+{
+    ext_fsh_info_t* cur_fsh_info = NULL;
+    if (!list_empty(&g_ext_fsh_devs.dev_list)) {
+        list_for_each_entry(cur_fsh_info, &g_ext_fsh_devs.dev_list, list) {
+            if (dev == cur_fsh_info) {
+                camsys_trace(1,"unregister  ext flsh dev !");
+               platform_device_unregister(&cur_fsh_info->pdev);
+               list_del_init(&cur_fsh_info->list);
+               /* free after unregister device ?*/
+               kfree(cur_fsh_info->pdev.dev.platform_data);
+               kfree(cur_fsh_info);
+            }
+        }
+    }
+    return 0;
+}
+
+/*******************************
+mode:
+    0:  CAM_ENGINE_FLASH_OFF = 0x00,
+    1:  CAM_ENGINE_FLASH_AUTO = 0x01,
+    2:  CAM_ENGINE_FLASH_ON = 0x02,
+    3:  CAM_ENGINE_FLASH_RED_EYE = 0x03,
+    5:  CAM_ENGINE_FLASH_TORCH = 0x05
+********************************/
+int camsys_ext_fsh_ctrl(void* dev,int mode,unsigned int on)
+{
+    ext_fsh_info_t* cur_fsh_info = NULL;
+    struct flashlight_device *fled_dev = NULL;
+    if (!list_empty(&g_ext_fsh_devs.dev_list)) {
+        list_for_each_entry(cur_fsh_info, &g_ext_fsh_devs.dev_list, list) {
+            if (dev == cur_fsh_info) {
+            break;
+            }
+        }
+    }
+    if(cur_fsh_info == NULL){
+               camsys_err("this flash dev have not been registered !");
+        return -1;
+    }
+
+    fled_dev = find_flashlight_by_name(cur_fsh_info->dev_model);
+    switch(mode){
+        case 0: /* off */
+           /* set flashlight mode to Off */
+            flashlight_set_mode(fled_dev, FLASHLIGHT_MODE_OFF);
+            break;
+        case 2: /* flash on */
+           /* set strobe timeout to 256ms */
+           //flashlight_set_strobe_timeout(fled_dev, 256, 256);
+           flashlight_set_strobe_timeout(fled_dev, 512, 512);
+           /* set strobe brightness to to index 18 (1A), refer to the datasheet for the others */
+           flashlight_set_strobe_brightness(fled_dev, 18);
+           /* set flashlight mode to Strobe */
+           flashlight_set_mode(fled_dev, FLASHLIGHT_MODE_FLASH);
+           flashlight_strobe(fled_dev);
+            break;
+        case 5: /* torch */
+            /* set the torch brightness index 2 (75mA), refer to the datasheet for index current value. */
+            flashlight_set_torch_brightness(fled_dev, 2);
+            /* set flashlight mode to Torch */
+            flashlight_set_mode(fled_dev, FLASHLIGHT_MODE_TORCH);
+            break;
+        default:
+               camsys_err("not support this mode %d !",mode);
+    }
+
+    return 0;
+}
+
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.h b/drivers/media/video/rk_camsys/ext_flashled_drv/rk_ext_fshled_ctl.h
new file mode 100755 (executable)
index 0000000..d66af0d
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __RK_EXT_FSHLED_H__
+#define __RK_EXT_FSHLED_H__
+#include "../camsys_internal.h"
+//register flash dev
+extern int camsys_init_ext_fsh_module(void);
+extern int camsys_deinit_ext_fsh_module(void);
+extern void* camsys_register_ext_fsh_dev(camsys_flash_info_t *fsh_info);
+extern int camsys_deregister_ext_fsh_dev(void* dev);
+extern int camsys_ext_fsh_ctrl(void* dev,int mode,unsigned int on);
+#endif
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/rtfled.c b/drivers/media/video/rk_camsys/ext_flashled_drv/rtfled.c
new file mode 100755 (executable)
index 0000000..8417431
--- /dev/null
@@ -0,0 +1,401 @@
+/* drivers/leds/rtfled.c
+ * Richtek Flash LED Universal Architecture
+ *
+ * Copyright (C) 2013 Richtek Technology Corp.
+ * Author: Patrick Chang <patrick_chang@richtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include "rtfled.h"
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define RTFLED_INFO(format, args...) \
+       pr_info("%s:%s() line-%d: " format, \
+         ALIAS_NAME, __func__, __LINE__, ## args)
+#define RTFLED_WARN(format, args...) \
+       pr_warn("%s:%s() line-%d: " format, \
+         ALIAS_NAME, __func__, __LINE__, ## args)
+#define RTFLED_ERR(format, args...) \
+       pr_err("%s:%s() line-%d: " format, \
+         ALIAS_NAME, __func__, __LINE__, ## args)
+
+#define RT_FLED_DEVICE  "rt-flash-led"
+#define ALIAS_NAME RT_FLED_DEVICE
+
+rt_fled_info_t *rt_fled_get_info_by_name(char *name)
+{
+       struct flashlight_device *flashlight_dev;
+
+       flashlight_dev = find_flashlight_by_name(name ? name : RT_FLED_DEVICE);
+       if (flashlight_dev == NULL)
+               return (rt_fled_info_t *) NULL;
+       return flashlight_get_data(flashlight_dev);
+}
+EXPORT_SYMBOL(rt_fled_get_info_by_name);
+
+static int rtfled_set_torch_brightness(struct flashlight_device *flashlight_dev,
+                                      int brightness_sel)
+{
+       rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+       return info->hal->fled_set_torch_current_sel(info, brightness_sel);
+}
+
+static int rtfled_set_strobe_brightness(struct flashlight_device
+                                       *flashlight_dev, int brightness_sel)
+{
+       rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+       return info->hal->fled_set_strobe_current_sel(info, brightness_sel);
+}
+
+static int rtfled_set_strobe_timeout(struct flashlight_device *flashlight_dev,
+                                    int timeout)
+{
+       rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+       int sel;
+
+       return info->hal->fled_set_strobe_timeout(info, timeout, timeout, &sel);
+}
+
+static int rtfled_list_strobe_timeout(struct flashlight_device *flashlight_dev,
+                                     int selector)
+{
+       rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+       return info->hal->fled_strobe_timeout_list(info, selector);
+}
+
+static int rtfled_set_mode(struct flashlight_device *flashlight_dev, int mode)
+{
+       rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+       return info->hal->fled_set_mode(info, mode);
+}
+
+static int rtfled_strobe(struct flashlight_device *flashlight_dev)
+{
+       rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+       return info->hal->fled_strobe(info);
+}
+
+static int rtfled_set_color_temperature(struct flashlight_device
+                                       *flashlight_dev, int color_temp)
+{
+       /* Doesn't support color temperature */
+       return -EINVAL;
+}
+
+static int rtfled_list_color_temperature(struct flashlight_device
+                                        *flashlight_dev, int selector)
+{
+       /* Doesn't support color temperature */
+       return -EINVAL;
+}
+
+static int rtfled_suspend(struct flashlight_device *flashlight_dev,
+                         pm_message_t state)
+{
+       rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+       if (info->hal->fled_suspend)
+               return info->hal->fled_suspend(info, state);
+       return 0;
+}
+
+static int rtfled_resume(struct flashlight_device *flashlight_dev)
+{
+       rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
+
+       if (info->hal->fled_resume)
+               return info->hal->fled_resume(info);
+       return 0;
+}
+
+static struct flashlight_ops rtfled_impl_ops = {
+       .set_torch_brightness = rtfled_set_torch_brightness,
+       .set_strobe_brightness = rtfled_set_strobe_brightness,
+       .set_strobe_timeout = rtfled_set_strobe_timeout,
+       .list_strobe_timeout = rtfled_list_strobe_timeout,
+       .set_mode = rtfled_set_mode,
+       .strobe = rtfled_strobe,
+       .set_color_temperature = rtfled_set_color_temperature,
+       .list_color_temperature = rtfled_list_color_temperature,
+       .suspend = rtfled_suspend,
+       .resume = rtfled_resume,
+};
+
+static void rfled_shutdown(struct platform_device *pdev)
+{
+       struct rt_fled_info *info = platform_get_drvdata(pdev);
+
+       if (info->hal->fled_shutdown)
+               info->hal->fled_shutdown(info);
+}
+
+static int rtled_impl_set_torch_current(struct rt_fled_info *info,
+                                       int min_uA, int max_uA, int *selector)
+{
+       int sel = 0;
+       int rc;
+
+       for (sel = 0;; sel++) {
+               rc = info->hal->fled_torch_current_list(info, sel);
+               if (rc < 0)
+                       return rc;
+               if (rc >= min_uA && rc <= max_uA) {
+                       *selector = sel;
+                       return info->hal->fled_set_torch_current_sel(info, sel);
+               }
+       }
+       return -EINVAL;
+}
+
+static int rtled_impl_set_strobe_current(struct rt_fled_info *info,
+                                        int min_uA, int max_uA, int *selector)
+{
+       int sel = 0;
+       int rc;
+
+       for (sel = 0;; sel++) {
+               rc = info->hal->fled_strobe_current_list(info, sel);
+               if (rc < 0)
+                       return rc;
+               if (rc >= min_uA && rc <= max_uA) {
+                       *selector = sel;
+                       return info->hal->fled_set_strobe_current_sel(info,
+                                                                     sel);
+               }
+       }
+       return -EINVAL;
+}
+
+static int rtled_impl_set_timeout_level(struct rt_fled_info *info,
+                                       int min_uA, int max_uA, int *selector)
+{
+       int sel = 0;
+       int rc;
+
+       for (sel = 0;; sel++) {
+               rc = info->hal->fled_timeout_level_list(info, sel);
+               if (rc < 0)
+                       return rc;
+               if (rc >= min_uA && rc <= max_uA) {
+                       *selector = sel;
+                       return info->hal->fled_set_timeout_level_sel(info, sel);
+               }
+       }
+       return -EINVAL;
+}
+
+static int rtled_impl_set_lv_protection(struct rt_fled_info *info,
+                                       int min_mV, int max_mV, int *selector)
+{
+       int sel = 0;
+       int rc;
+
+       for (sel = 0;; sel++) {
+               rc = info->hal->fled_lv_protection_list(info, sel);
+               if (rc < 0)
+                       return rc;
+               if (rc >= min_mV && rc <= max_mV) {
+                       *selector = sel;
+                       return info->hal->fled_set_lv_protection_sel(info, sel);
+               }
+       }
+       return -EINVAL;
+}
+
+static int rtled_impl_set_strobe_timeout(struct rt_fled_info *info,
+                                        int min_ms, int max_ms, int *selector)
+{
+       int sel = 0;
+       int rc;
+
+       for (sel = 0;; sel++) {
+               rc = info->hal->fled_strobe_timeout_list(info, sel);
+               if (rc < 0)
+                       return rc;
+               if (rc >= min_ms && rc <= max_ms) {
+                       *selector = sel;
+                       return info->hal->fled_set_strobe_timeout_sel(info,
+                                                                     sel);
+               }
+       }
+       return -EINVAL;
+}
+
+static int rtled_impl_get_torch_current(struct rt_fled_info *info)
+{
+       int sel = info->hal->fled_get_torch_current_sel(info);
+
+       if (sel < 0)
+               return sel;
+       return info->hal->fled_torch_current_list(info, sel);
+}
+
+static int rtled_impl_get_strobe_current(struct rt_fled_info *info)
+{
+       int sel = info->hal->fled_get_strobe_current_sel(info);
+
+       if (sel < 0)
+               return sel;
+       return info->hal->fled_strobe_current_list(info, sel);
+}
+
+static int rtled_impl_get_timeout_level(struct rt_fled_info *info)
+{
+       int sel = info->hal->fled_get_timeout_level_sel(info);
+
+       if (sel < 0)
+               return sel;
+       return info->hal->fled_timeout_level_list(info, sel);
+}
+
+static int rtled_impl_get_lv_protection(struct rt_fled_info *info)
+{
+       int sel = info->hal->fled_get_lv_protection_sel(info);
+
+       if (sel < 0)
+               return sel;
+       return info->hal->fled_lv_protection_list(info, sel);
+}
+
+static int rtled_impl_get_strobe_timeout(struct rt_fled_info *info)
+{
+       int sel = info->hal->fled_get_strobe_timeout_sel(info);
+
+       if (sel < 0)
+               return sel;
+       return info->hal->fled_strobe_timeout_list(info, sel);
+}
+
+#define HAL_NOT_IMPLEMENTED(x) (hal->x == NULL)
+#define CHECK_HAL_IMPLEMENTED(x)       \
+       do {                            \
+               if (hal->x == NULL)     \
+                       return -EINVAL; \
+       } while (0)
+
+static int rtfled_check_hal_implement(struct rt_fled_hal *hal)
+{
+       if (HAL_NOT_IMPLEMENTED(fled_set_torch_current))
+               hal->fled_set_torch_current = rtled_impl_set_torch_current;
+       if (HAL_NOT_IMPLEMENTED(fled_set_strobe_current))
+               hal->fled_set_strobe_current = rtled_impl_set_strobe_current;
+       if (HAL_NOT_IMPLEMENTED(fled_set_timeout_level))
+               hal->fled_set_timeout_level = rtled_impl_set_timeout_level;
+       if (HAL_NOT_IMPLEMENTED(fled_set_lv_protection))
+               hal->fled_set_lv_protection = rtled_impl_set_lv_protection;
+       if (HAL_NOT_IMPLEMENTED(fled_set_strobe_timeout))
+               hal->fled_set_strobe_timeout = rtled_impl_set_strobe_timeout;
+       if (HAL_NOT_IMPLEMENTED(fled_get_torch_current))
+               hal->fled_get_torch_current = rtled_impl_get_torch_current;
+       if (HAL_NOT_IMPLEMENTED(fled_get_strobe_current))
+               hal->fled_get_strobe_current = rtled_impl_get_strobe_current;
+       if (HAL_NOT_IMPLEMENTED(fled_get_timeout_level))
+               hal->fled_get_timeout_level = rtled_impl_get_timeout_level;
+       if (HAL_NOT_IMPLEMENTED(fled_get_lv_protection))
+               hal->fled_get_lv_protection = rtled_impl_get_lv_protection;
+       if (HAL_NOT_IMPLEMENTED(fled_get_strobe_timeout))
+               hal->fled_get_strobe_timeout = rtled_impl_get_strobe_timeout;
+       CHECK_HAL_IMPLEMENTED(fled_set_mode);
+       CHECK_HAL_IMPLEMENTED(fled_get_mode);
+       CHECK_HAL_IMPLEMENTED(fled_strobe);
+       CHECK_HAL_IMPLEMENTED(fled_torch_current_list);
+       CHECK_HAL_IMPLEMENTED(fled_strobe_current_list);
+       CHECK_HAL_IMPLEMENTED(fled_timeout_level_list);
+       CHECK_HAL_IMPLEMENTED(fled_lv_protection_list);
+       CHECK_HAL_IMPLEMENTED(fled_strobe_timeout_list);
+       CHECK_HAL_IMPLEMENTED(fled_set_torch_current_sel);
+       CHECK_HAL_IMPLEMENTED(fled_set_strobe_current_sel);
+       CHECK_HAL_IMPLEMENTED(fled_set_timeout_level_sel);
+       CHECK_HAL_IMPLEMENTED(fled_set_lv_protection_sel);
+       CHECK_HAL_IMPLEMENTED(fled_set_strobe_timeout_sel);
+       CHECK_HAL_IMPLEMENTED(fled_get_torch_current_sel);
+       CHECK_HAL_IMPLEMENTED(fled_get_strobe_current_sel);
+       CHECK_HAL_IMPLEMENTED(fled_get_timeout_level_sel);
+       CHECK_HAL_IMPLEMENTED(fled_get_lv_protection_sel);
+       CHECK_HAL_IMPLEMENTED(fled_get_strobe_timeout_sel);
+       return 0;
+}
+
+static int rtfled_probe(struct platform_device *pdev)
+{
+       rt_fled_info_t *info = dev_get_drvdata(pdev->dev.parent);
+       int rc;
+
+       BUG_ON(info == NULL);
+       BUG_ON(info->hal == NULL);
+
+       RTFLED_INFO("Richtek FlashLED Driver is probing\n");
+       rc = rtfled_check_hal_implement(info->hal);
+       if (rc < 0) {
+               RTFLED_ERR("HAL implemented uncompletedly\n");
+               goto err_check_hal;
+       }
+       platform_set_drvdata(pdev, info);
+       info->flashlight_dev =
+           flashlight_device_register(info->name ? info->name : RT_FLED_DEVICE,
+                                      &pdev->dev, info, &rtfled_impl_ops,
+                                      info->init_props);
+       if (info->hal->fled_init) {
+               rc = info->hal->fled_init(info);
+               if (rc < 0) {
+                       RTFLED_ERR("Initialization failed\n");
+                       goto err_init;
+               }
+       }
+       RTFLED_INFO("Richtek FlashLED Driver initialized successfully\n");
+       return 0;
+err_init:
+       flashlight_device_unregister(info->flashlight_dev);
+err_check_hal:
+       return rc;
+}
+
+static int rtfled_remove(struct platform_device *pdev)
+{
+       rt_fled_info_t *info = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+       flashlight_device_unregister(info->flashlight_dev);
+       return 0;
+}
+
+static struct platform_driver rt_flash_led_driver = {
+       .driver = {
+                  .name = RT_FLED_DEVICE,
+                  .owner = THIS_MODULE,
+                  },
+       .shutdown = rfled_shutdown,
+       .probe = rtfled_probe,
+       .remove = rtfled_remove,
+};
+
+static int rtfled_init(void)
+{
+       return platform_driver_register(&rt_flash_led_driver);
+}
+subsys_initcall(rtfled_init);
+
+static void rtfled_exit(void)
+{
+       platform_driver_unregister(&rt_flash_led_driver);
+}
+module_exit(rtfled_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com");
+MODULE_VERSION("1.0.0_G");
+MODULE_DESCRIPTION("Richtek Flash LED Driver");
diff --git a/drivers/media/video/rk_camsys/ext_flashled_drv/rtfled.h b/drivers/media/video/rk_camsys/ext_flashled_drv/rtfled.h
new file mode 100755 (executable)
index 0000000..0f8815e
--- /dev/null
@@ -0,0 +1,147 @@
+/*include/linux/leds/rtfled.h
+ *Header of Richtek Flash LED Driver
+ *
+ *Copyright (C) 2013 Richtek Technology Corp.
+ *Author: Patrick Chang <patrick_chang@richtek.com>
+ *
+ *This program is free software; you can redistribute it and/or modify
+ *it under the terms of the GNU General Public License version 2 as
+ *published by the Free Software Foundation; either version 2
+ *of the License, or (at your option) any later version.
+ */
+
+#ifndef LINUX_LEDS_RTFLED_H
+#define LINUX_LEDS_RTFLED_H
+#include "flashlight.h"
+
+struct rt_fled_info;
+typedef int (*rt_hal_fled_init) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_suspend) (struct rt_fled_info *info,
+                                   pm_message_t state);
+typedef int (*rt_hal_fled_resume) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_set_mode) (struct rt_fled_info *info,
+                                    flashlight_mode_t mode);
+typedef int (*rt_hal_fled_get_mode) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_strobe) (struct rt_fled_info *info);
+
+/*
+ *Return value : -EINVAL => selector parameter is out of range,
+ *otherwise current in uA
+ */
+typedef int (*rt_hal_fled_torch_current_list) (struct rt_fled_info *info,
+                                              int selector);
+typedef int (*rt_hal_fled_strobe_current_list) (struct rt_fled_info *info,
+                                               int selector);
+typedef int (*rt_hal_fled_timeout_level_list) (struct rt_fled_info *info,
+                                              int selector);
+/*
+ *Return value : -EINVAL => selector parameter is out of range,
+ *otherwise voltage in mV
+ */
+typedef int (*rt_hal_fled_lv_protection_list) (struct rt_fled_info *info,
+                                              int selector);
+/*
+ *Return value : -EINVAL => selector parameter is out of range,
+ *otherwise time in ms
+ */
+typedef int (*rt_hal_fled_strobe_timeout_list) (struct rt_fled_info *info,
+                                               int selector);
+typedef int (*rt_hal_fled_set_torch_current) (struct rt_fled_info *info,
+                                             int min_uA, int max_uA,
+                                             int *selector);
+typedef int (*rt_hal_fled_set_strobe_current) (struct rt_fled_info *info,
+                                              int min_uA, int max_uA,
+                                              int *selector);
+typedef int (*rt_hal_fled_set_timeout_level) (struct rt_fled_info *info,
+                                             int min_uA, int max_uA,
+                                             int *selector);
+typedef int (*rt_hal_fled_set_lv_protection) (struct rt_fled_info *info,
+                                             int min_mV, int max_mV,
+                                             int *selector);
+typedef int (*rt_hal_fled_set_strobe_timeout) (struct rt_fled_info *info,
+                                              int min_ms, int max_ms,
+                                              int *selector);
+typedef int (*rt_hal_fled_set_torch_current_sel) (struct rt_fled_info *info,
+                                                 int selector);
+typedef int (*rt_hal_fled_set_strobe_current_sel) (struct rt_fled_info *info,
+                                                  int selector);
+typedef int (*rt_hal_fled_set_timeout_level_sel) (struct rt_fled_info *info,
+                                                 int selector);
+typedef int (*rt_hal_fled_set_lv_protection_sel) (struct rt_fled_info *info,
+                                                 int selector);
+typedef int (*rt_hal_fled_set_strobe_timeout_sel) (struct rt_fled_info *info,
+                                                  int selector);
+typedef int (*rt_hal_fled_get_torch_current_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_strobe_current_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_timeout_level_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_lv_protection_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_strobe_timeout_sel) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_torch_current) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_strobe_current) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_timeout_level) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_lv_protection) (struct rt_fled_info *info);
+typedef int (*rt_hal_fled_get_strobe_timeout) (struct rt_fled_info *info);
+typedef void (*rt_hal_fled_shutdown) (struct rt_fled_info *info);
+
+struct rt_fled_hal {
+       rt_hal_fled_init fled_init;
+       rt_hal_fled_suspend fled_suspend;
+       rt_hal_fled_resume fled_resume;
+       rt_hal_fled_set_mode fled_set_mode;
+       rt_hal_fled_get_mode fled_get_mode;
+       rt_hal_fled_strobe fled_strobe;
+       rt_hal_fled_torch_current_list fled_torch_current_list;
+       rt_hal_fled_strobe_current_list fled_strobe_current_list;
+       rt_hal_fled_timeout_level_list fled_timeout_level_list;
+       rt_hal_fled_lv_protection_list fled_lv_protection_list;
+       rt_hal_fled_strobe_timeout_list fled_strobe_timeout_list;
+       /*method to set */
+       rt_hal_fled_set_torch_current_sel fled_set_torch_current_sel;
+       rt_hal_fled_set_strobe_current_sel fled_set_strobe_current_sel;
+       rt_hal_fled_set_timeout_level_sel fled_set_timeout_level_sel;
+       rt_hal_fled_set_lv_protection_sel fled_set_lv_protection_sel;
+       rt_hal_fled_set_strobe_timeout_sel fled_set_strobe_timeout_sel;
+       /*method to set, optional */
+       rt_hal_fled_set_torch_current fled_set_torch_current;
+       rt_hal_fled_set_strobe_current fled_set_strobe_current;
+       rt_hal_fled_set_timeout_level fled_set_timeout_level;
+       rt_hal_fled_set_lv_protection fled_set_lv_protection;
+       rt_hal_fled_set_strobe_timeout fled_set_strobe_timeout;
+       /*method to get */
+       rt_hal_fled_get_torch_current_sel fled_get_torch_current_sel;
+       rt_hal_fled_get_strobe_current_sel fled_get_strobe_current_sel;
+       rt_hal_fled_get_timeout_level_sel fled_get_timeout_level_sel;
+       rt_hal_fled_get_lv_protection_sel fled_get_lv_protection_sel;
+       rt_hal_fled_get_strobe_timeout_sel fled_get_strobe_timeout_sel;
+       /*method to get, optional */
+       rt_hal_fled_get_torch_current fled_get_torch_current;
+       rt_hal_fled_get_strobe_current fled_get_strobe_current;
+       rt_hal_fled_get_timeout_level fled_get_timeout_level;
+       rt_hal_fled_get_lv_protection fled_get_lv_protection;
+       rt_hal_fled_get_strobe_timeout fled_get_strobe_timeout;
+       /*PM shutdown, optional */
+       rt_hal_fled_shutdown fled_shutdown;
+};
+
+typedef struct rt_fled_info {
+       struct rt_fled_hal *hal;
+       struct flashlight_device *flashlight_dev;
+       const struct flashlight_properties *init_props;
+       char *name;
+       char *chip_name;
+} rt_fled_info_t;
+
+/*Public funtions
+ *argument
+ *  @name : Flash LED's name;pass NULL menas "rt-flash-led"
+ */
+
+rt_fled_info_t *rt_fled_get_info_by_name(char *name);
+
+/*Usage :
+ *fled_info = rt_fled_get_info_by_name("FlashLED1");
+ *fled_info->hal->fled_set_strobe_current(fled_info,
+ *                                       150, 200);
+ */
+
+#endif /*LINUX_LEDS_RTFLED_H */
index 28dcc5b01a13a6d19b20f0097048c08d2257375f..31a828f7bebf7300ed71076260b2648767e8662e 100755 (executable)
                 1) support isp iommu
 *v0.9.0:
          1) add dev_name in struct camsys_devio_name_s;
+*v0.a.0:
+         1) support external flash IC
 */
-#define CAMSYS_HEAD_VERSION           KERNEL_VERSION(0,9,0)
+#define CAMSYS_HEAD_VERSION           KERNEL_VERSION(0,0xa,0)
 
 #define CAMSYS_MARVIN_DEVNAME         "camsys_marvin"           
 #define CAMSYS_CIF0_DEVNAME           "camsys_cif0"
@@ -152,7 +154,9 @@ typedef struct camsys_sysctrl_s {
 } camsys_sysctrl_t;
 
 typedef struct camsys_flash_info_s {
-    camsys_gpio_info_t        fl;
+    unsigned char     fl_drv_name[CAMSYS_NAME_LEN];
+    camsys_gpio_info_t        fl; //fl_trig
+    camsys_gpio_info_t        fl_en;
 } camsys_flash_info_t;
 
 typedef struct camsys_mipiphy_s {