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
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
---help---
endmenu
+
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/
#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);
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++) {
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);
}
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);
}
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:
}
}
}
+ }else if(devctl->ops == CamSys_Flash_Trigger){
+ err = camsys_ext_fsh_ctrl(extdev->fl.ext_fsh_dev,devctl->rev[0],devctl->on);
}
} else {
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:
list_del_init(&camsys_dev->list);
spin_unlock(&camsys_devs.lock);
+ camsys_deinit_ext_fsh_module();
+
kfree(camsys_dev);
camsys_dev=NULL;
} else {
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;
}
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"
} 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];
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;
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);
--- /dev/null
+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
--- /dev/null
+obj-$(CONFIG_FLASHLIGHT) += flashlight.o rk_ext_fshled_ctl.o
+obj-$(CONFIG_RT_FLASH_LED) += rtfled.o
+obj-$(CONFIG_LEDS_RT8547) += leds-rt8547.o
--- /dev/null
+/* 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");
--- /dev/null
+/* 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 */
--- /dev/null
+/*
+ * 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, ¶m1[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],
+ ®_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],
+ ®_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],
+ ®_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],
+ ®_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);
--- /dev/null
+/* 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 */
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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
--- /dev/null
+/* 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");
--- /dev/null
+/*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 */
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"
} 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 {