Merge "msm: camera: Add a driver to control IR CUT device"
This commit is contained in:
commit
d099799530
14 changed files with 1446 additions and 2 deletions
26
Documentation/devicetree/bindings/media/video/msm-ir-cut.txt
Normal file
26
Documentation/devicetree/bindings/media/video/msm-ir-cut.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
* QTI MSM IR CUT
|
||||
|
||||
Required properties:
|
||||
- cell-index : ir cut filter hardware core index
|
||||
- compatible :
|
||||
- "qcom,ir-cut"
|
||||
|
||||
Optional properties:
|
||||
- gpios : should specify the gpios to be used for the ir cut filter.
|
||||
- qcom,gpio-req-tbl-num : should contain index to gpios specific to ir cut filter
|
||||
- qcom,gpio-req-tbl-flags : should contain direction of gpios present in
|
||||
qcom,gpio-req-tbl-num property (in the same order)
|
||||
- qcom,gpio-req-tbl-label : should contain name of gpios present in
|
||||
qcom,gpio-req-tbl-num property (in the same order)
|
||||
- label : should contain unique ir cut filter name
|
||||
Example:
|
||||
|
||||
qcom,ir-cut@60 {
|
||||
cell-index = <0>;
|
||||
compatible = "qcom,ir-cut";
|
||||
label = "led-ir-label";
|
||||
gpios = <&tlmm 60 0>;
|
||||
qcom,gpio-req-tbl-num = <0>;
|
||||
qcom,gpio-req-tbl-flags = <0>;
|
||||
qcom,gpio-req-tbl-label = "LED_IR_EN";
|
||||
};
|
26
Documentation/devicetree/bindings/media/video/msm-ir-led.txt
Normal file
26
Documentation/devicetree/bindings/media/video/msm-ir-led.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
* QTI MSM IR LED
|
||||
|
||||
Required properties:
|
||||
- cell-index : ir led hardware core index
|
||||
- compatible :
|
||||
- "qcom,ir-led"
|
||||
|
||||
Optional properties:
|
||||
- gpios : should specify the gpios to be used for the ir led.
|
||||
- qcom,gpio-req-tbl-num : should contain index to gpios specific to ir led
|
||||
- qcom,gpio-req-tbl-flags : should contain direction of gpios present in
|
||||
qcom,gpio-req-tbl-num property (in the same order)
|
||||
- qcom,gpio-req-tbl-label : should contain name of gpios present in
|
||||
qcom,gpio-req-tbl-num property (in the same order)
|
||||
- label : should contain unique ir led name
|
||||
Example:
|
||||
|
||||
qcom,ir-led {
|
||||
cell-index = <0>;
|
||||
compatible = "qcom,ir-led";
|
||||
label = "led-ir-label";
|
||||
gpios = <&tlmm 60 0>;
|
||||
qcom,gpio-req-tbl-num = <0>;
|
||||
qcom,gpio-req-tbl-flags = <0>;
|
||||
qcom,gpio-req-tbl-label = "LED_IR_EN";
|
||||
};
|
|
@ -4,5 +4,5 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v2/msm_vb2
|
|||
ccflags-y += -Idrivers/media/platform/msm/camera_v2/camera
|
||||
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
|
||||
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
|
||||
obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/ actuator/ eeprom/ ois/ flash/
|
||||
obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/ actuator/ eeprom/ ois/ flash/ ir_led/ ir_cut/
|
||||
obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor_init.o msm_sensor_driver.o msm_sensor.o
|
||||
|
|
|
@ -780,6 +780,54 @@ int msm_camera_init_gpio_pin_tbl(struct device_node *of_node,
|
|||
rc = -ENOMEM;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(of_node, "qcom,gpio-ir-p", &val);
|
||||
if (rc != -EINVAL) {
|
||||
if (rc < 0) {
|
||||
pr_err("%s:%d read qcom,gpio-ir-p failed rc %d\n",
|
||||
__func__, __LINE__, rc);
|
||||
goto ERROR;
|
||||
} else if (val >= gpio_array_size) {
|
||||
pr_err("%s:%d qcom,gpio-ir-p invalid %d\n",
|
||||
__func__, __LINE__, val);
|
||||
rc = -EINVAL;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
gconf->gpio_num_info->gpio_num[IR_CUT_FILTER_GPIO_P] =
|
||||
gpio_array[val];
|
||||
gconf->gpio_num_info->valid[IR_CUT_FILTER_GPIO_P] = 1;
|
||||
|
||||
CDBG("%s qcom,gpio-ir-p %d\n", __func__,
|
||||
gconf->gpio_num_info->gpio_num[IR_CUT_FILTER_GPIO_P]);
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(of_node, "qcom,gpio-ir-m", &val);
|
||||
if (rc != -EINVAL) {
|
||||
if (rc < 0) {
|
||||
pr_err("%s:%d read qcom,gpio-ir-m failed rc %d\n",
|
||||
__func__, __LINE__, rc);
|
||||
goto ERROR;
|
||||
} else if (val >= gpio_array_size) {
|
||||
pr_err("%s:%d qcom,gpio-ir-m invalid %d\n",
|
||||
__func__, __LINE__, val);
|
||||
rc = -EINVAL;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
gconf->gpio_num_info->gpio_num[IR_CUT_FILTER_GPIO_M] =
|
||||
gpio_array[val];
|
||||
|
||||
gconf->gpio_num_info->valid[IR_CUT_FILTER_GPIO_M] = 1;
|
||||
|
||||
CDBG("%s qcom,gpio-ir-m %d\n", __func__,
|
||||
gconf->gpio_num_info->gpio_num[IR_CUT_FILTER_GPIO_M]);
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(of_node, "qcom,gpio-vana", &val);
|
||||
if (rc != -EINVAL) {
|
||||
if (rc < 0) {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
ccflags-y += -Idrivers/media/platform/msm/camera_v2
|
||||
ccflags-y += -Idrivers/media/platform/msm/camera_v2/common
|
||||
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
|
||||
obj-$(CONFIG_MSMB_CAMERA) += msm_ir_cut.o
|
665
drivers/media/platform/msm/camera_v2/sensor/ir_cut/msm_ir_cut.c
Normal file
665
drivers/media/platform/msm/camera_v2/sensor/ir_cut/msm_ir_cut.c
Normal file
|
@ -0,0 +1,665 @@
|
|||
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include "msm_ir_cut.h"
|
||||
#include "msm_camera_dt_util.h"
|
||||
|
||||
#undef CDBG
|
||||
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
|
||||
|
||||
DEFINE_MSM_MUTEX(msm_ir_cut_mutex);
|
||||
|
||||
static struct v4l2_file_operations msm_ir_cut_v4l2_subdev_fops;
|
||||
|
||||
static const struct of_device_id msm_ir_cut_dt_match[] = {
|
||||
{.compatible = "qcom,ir-cut", .data = NULL},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct msm_ir_cut_table msm_gpio_ir_cut_table;
|
||||
|
||||
static struct msm_ir_cut_table *ir_cut_table[] = {
|
||||
&msm_gpio_ir_cut_table,
|
||||
};
|
||||
|
||||
static int32_t msm_ir_cut_get_subdev_id(
|
||||
struct msm_ir_cut_ctrl_t *ir_cut_ctrl, void *arg)
|
||||
{
|
||||
uint32_t *subdev_id = (uint32_t *)arg;
|
||||
|
||||
CDBG("Enter\n");
|
||||
if (!subdev_id) {
|
||||
pr_err("failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ir_cut_ctrl->ir_cut_device_type != MSM_CAMERA_PLATFORM_DEVICE) {
|
||||
pr_err("failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*subdev_id = ir_cut_ctrl->pdev->id;
|
||||
|
||||
CDBG("subdev_id %d\n", *subdev_id);
|
||||
CDBG("Exit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_cut_init(
|
||||
struct msm_ir_cut_ctrl_t *ir_cut_ctrl,
|
||||
struct msm_ir_cut_cfg_data_t *ir_cut_data)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
CDBG("Enter");
|
||||
|
||||
rc = ir_cut_ctrl->func_tbl->camera_ir_cut_on(ir_cut_ctrl, ir_cut_data);
|
||||
|
||||
CDBG("Exit");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_cut_release(
|
||||
struct msm_ir_cut_ctrl_t *ir_cut_ctrl)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
if (ir_cut_ctrl->ir_cut_state == MSM_CAMERA_IR_CUT_RELEASE) {
|
||||
pr_err("%s:%d Invalid ir_cut state = %d",
|
||||
__func__, __LINE__, ir_cut_ctrl->ir_cut_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ir_cut_ctrl->func_tbl->camera_ir_cut_on(ir_cut_ctrl, NULL);
|
||||
if (rc < 0) {
|
||||
pr_err("%s:%d camera_ir_cut_on failed rc = %d",
|
||||
__func__, __LINE__, rc);
|
||||
return rc;
|
||||
}
|
||||
ir_cut_ctrl->ir_cut_state = MSM_CAMERA_IR_CUT_RELEASE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_cut_off(struct msm_ir_cut_ctrl_t *ir_cut_ctrl,
|
||||
struct msm_ir_cut_cfg_data_t *ir_cut_data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CDBG("Enter cut off\n");
|
||||
|
||||
if (ir_cut_ctrl->gconf) {
|
||||
rc = msm_camera_request_gpio_table(
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl,
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl_size, 1);
|
||||
|
||||
if (rc < 0) {
|
||||
pr_err("ERR:%s:Failed in selecting state: %d\n",
|
||||
__func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
pr_err("%s: No IR CUT GPIOs\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ir_cut_ctrl->cam_pinctrl_status) {
|
||||
rc = pinctrl_select_state(
|
||||
ir_cut_ctrl->pinctrl_info.pinctrl,
|
||||
ir_cut_ctrl->pinctrl_info.gpio_state_active);
|
||||
|
||||
if (rc < 0)
|
||||
pr_err("ERR:%s:%d cannot set pin to active state: %d",
|
||||
__func__, __LINE__, rc);
|
||||
}
|
||||
|
||||
CDBG("ERR:%s:gpio_conf->gpio_num_info->gpio_num[0] = %d",
|
||||
__func__,
|
||||
ir_cut_ctrl->gconf->gpio_num_info->
|
||||
gpio_num[IR_CUT_FILTER_GPIO_P]);
|
||||
|
||||
CDBG("ERR:%s:gpio_conf->gpio_num_info->gpio_num[1] = %d",
|
||||
__func__,
|
||||
ir_cut_ctrl->gconf->gpio_num_info->
|
||||
gpio_num[IR_CUT_FILTER_GPIO_M]);
|
||||
|
||||
gpio_set_value_cansleep(
|
||||
ir_cut_ctrl->gconf->gpio_num_info->
|
||||
gpio_num[IR_CUT_FILTER_GPIO_P],
|
||||
0);
|
||||
|
||||
gpio_set_value_cansleep(
|
||||
ir_cut_ctrl->gconf->gpio_num_info->
|
||||
gpio_num[IR_CUT_FILTER_GPIO_M],
|
||||
1);
|
||||
|
||||
if (ir_cut_ctrl->gconf) {
|
||||
rc = msm_camera_request_gpio_table(
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl,
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl_size, 0);
|
||||
|
||||
if (rc < 0) {
|
||||
pr_err("ERR:%s:Failed in selecting state: %d\n",
|
||||
__func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
pr_err("%s: No IR CUT GPIOs\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CDBG("Exit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_cut_on(
|
||||
struct msm_ir_cut_ctrl_t *ir_cut_ctrl,
|
||||
struct msm_ir_cut_cfg_data_t *ir_cut_data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CDBG("Enter ir cut on\n");
|
||||
|
||||
if (ir_cut_ctrl->gconf) {
|
||||
rc = msm_camera_request_gpio_table(
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl,
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl_size, 1);
|
||||
|
||||
if (rc < 0) {
|
||||
pr_err("ERR:%s:Failed in selecting state: %d\n",
|
||||
__func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
pr_err("%s: No IR CUT GPIOs\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ir_cut_ctrl->cam_pinctrl_status) {
|
||||
rc = pinctrl_select_state(
|
||||
ir_cut_ctrl->pinctrl_info.pinctrl,
|
||||
ir_cut_ctrl->pinctrl_info.gpio_state_active);
|
||||
|
||||
if (rc < 0)
|
||||
pr_err("ERR:%s:%d cannot set pin to active state: %d",
|
||||
__func__, __LINE__, rc);
|
||||
}
|
||||
|
||||
CDBG("ERR:%s: gpio_conf->gpio_num_info->gpio_num[0] = %d",
|
||||
__func__,
|
||||
ir_cut_ctrl->gconf->gpio_num_info->
|
||||
gpio_num[IR_CUT_FILTER_GPIO_P]);
|
||||
|
||||
CDBG("ERR:%s: gpio_conf->gpio_num_info->gpio_num[1] = %d",
|
||||
__func__,
|
||||
ir_cut_ctrl->gconf->gpio_num_info->
|
||||
gpio_num[IR_CUT_FILTER_GPIO_M]);
|
||||
|
||||
gpio_set_value_cansleep(
|
||||
ir_cut_ctrl->gconf->gpio_num_info->
|
||||
gpio_num[IR_CUT_FILTER_GPIO_P],
|
||||
1);
|
||||
|
||||
gpio_set_value_cansleep(
|
||||
ir_cut_ctrl->gconf->
|
||||
gpio_num_info->gpio_num[IR_CUT_FILTER_GPIO_M],
|
||||
1);
|
||||
|
||||
if (ir_cut_ctrl->gconf) {
|
||||
rc = msm_camera_request_gpio_table(
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl,
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl_size, 0);
|
||||
|
||||
if (rc < 0) {
|
||||
pr_err("ERR:%s:Failed in selecting state: %d\n",
|
||||
__func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
pr_err("%s: No IR CUT GPIOs\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CDBG("Exit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_cut_handle_init(
|
||||
struct msm_ir_cut_ctrl_t *ir_cut_ctrl,
|
||||
struct msm_ir_cut_cfg_data_t *ir_cut_data)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
int32_t rc = -EFAULT;
|
||||
enum msm_ir_cut_driver_type ir_cut_driver_type =
|
||||
ir_cut_ctrl->ir_cut_driver_type;
|
||||
|
||||
CDBG("Enter");
|
||||
|
||||
if (ir_cut_ctrl->ir_cut_state == MSM_CAMERA_IR_CUT_INIT) {
|
||||
pr_err("%s:%d Invalid ir_cut state = %d",
|
||||
__func__, __LINE__, ir_cut_ctrl->ir_cut_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ir_cut_table); i++) {
|
||||
if (ir_cut_driver_type == ir_cut_table[i]->ir_cut_driver_type) {
|
||||
ir_cut_ctrl->func_tbl = &ir_cut_table[i]->func_tbl;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
pr_err("%s:%d failed invalid ir_cut_driver_type %d\n",
|
||||
__func__, __LINE__, ir_cut_driver_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = ir_cut_ctrl->func_tbl->camera_ir_cut_init(
|
||||
ir_cut_ctrl, ir_cut_data);
|
||||
if (rc < 0) {
|
||||
pr_err("%s:%d camera_ir_cut_init failed rc = %d",
|
||||
__func__, __LINE__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ir_cut_ctrl->ir_cut_state = MSM_CAMERA_IR_CUT_INIT;
|
||||
|
||||
CDBG("Exit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_cut_config(struct msm_ir_cut_ctrl_t *ir_cut_ctrl,
|
||||
void __user *argp)
|
||||
{
|
||||
int32_t rc = -EINVAL;
|
||||
struct msm_ir_cut_cfg_data_t *ir_cut_data =
|
||||
(struct msm_ir_cut_cfg_data_t *) argp;
|
||||
|
||||
mutex_lock(ir_cut_ctrl->ir_cut_mutex);
|
||||
|
||||
CDBG("Enter %s type %d\n", __func__, ir_cut_data->cfg_type);
|
||||
|
||||
switch (ir_cut_data->cfg_type) {
|
||||
case CFG_IR_CUT_INIT:
|
||||
rc = msm_ir_cut_handle_init(ir_cut_ctrl, ir_cut_data);
|
||||
break;
|
||||
case CFG_IR_CUT_RELEASE:
|
||||
if (ir_cut_ctrl->ir_cut_state == MSM_CAMERA_IR_CUT_INIT)
|
||||
rc = ir_cut_ctrl->func_tbl->camera_ir_cut_release(
|
||||
ir_cut_ctrl);
|
||||
break;
|
||||
case CFG_IR_CUT_OFF:
|
||||
if (ir_cut_ctrl->ir_cut_state == MSM_CAMERA_IR_CUT_INIT)
|
||||
rc = ir_cut_ctrl->func_tbl->camera_ir_cut_off(
|
||||
ir_cut_ctrl, ir_cut_data);
|
||||
break;
|
||||
case CFG_IR_CUT_ON:
|
||||
if (ir_cut_ctrl->ir_cut_state == MSM_CAMERA_IR_CUT_INIT)
|
||||
rc = ir_cut_ctrl->func_tbl->camera_ir_cut_on(
|
||||
ir_cut_ctrl, ir_cut_data);
|
||||
break;
|
||||
default:
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(ir_cut_ctrl->ir_cut_mutex);
|
||||
|
||||
CDBG("Exit %s type %d\n", __func__, ir_cut_data->cfg_type);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long msm_ir_cut_subdev_ioctl(struct v4l2_subdev *sd,
|
||||
unsigned int cmd, void *arg)
|
||||
{
|
||||
struct msm_ir_cut_ctrl_t *fctrl = NULL;
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
||||
CDBG("Enter\n");
|
||||
|
||||
if (!sd) {
|
||||
pr_err("sd NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
fctrl = v4l2_get_subdevdata(sd);
|
||||
if (!fctrl) {
|
||||
pr_err("fctrl NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (cmd) {
|
||||
case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
|
||||
return msm_ir_cut_get_subdev_id(fctrl, argp);
|
||||
case VIDIOC_MSM_IR_CUT_CFG:
|
||||
return msm_ir_cut_config(fctrl, argp);
|
||||
case MSM_SD_NOTIFY_FREEZE:
|
||||
return 0;
|
||||
case MSM_SD_SHUTDOWN:
|
||||
if (!fctrl->func_tbl) {
|
||||
pr_err("fctrl->func_tbl NULL\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return fctrl->func_tbl->camera_ir_cut_release(fctrl);
|
||||
}
|
||||
default:
|
||||
pr_err_ratelimited("invalid cmd %d\n", cmd);
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
CDBG("Exit\n");
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_core_ops msm_ir_cut_subdev_core_ops = {
|
||||
.ioctl = msm_ir_cut_subdev_ioctl,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops msm_ir_cut_subdev_ops = {
|
||||
.core = &msm_ir_cut_subdev_core_ops,
|
||||
};
|
||||
static int msm_ir_cut_close(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh) {
|
||||
|
||||
int rc = 0;
|
||||
struct msm_ir_cut_ctrl_t *ir_cut_ctrl = v4l2_get_subdevdata(sd);
|
||||
|
||||
CDBG("Enter\n");
|
||||
|
||||
if (!ir_cut_ctrl) {
|
||||
pr_err("%s: failed\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ir_cut_ctrl->ir_cut_state == MSM_CAMERA_IR_CUT_INIT)
|
||||
rc = ir_cut_ctrl->func_tbl->camera_ir_cut_release(
|
||||
ir_cut_ctrl);
|
||||
|
||||
CDBG("Exit\n");
|
||||
|
||||
return rc;
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_internal_ops msm_ir_cut_internal_ops = {
|
||||
.close = msm_ir_cut_close,
|
||||
};
|
||||
|
||||
static int32_t msm_ir_cut_get_gpio_dt_data(struct device_node *of_node,
|
||||
struct msm_ir_cut_ctrl_t *fctrl)
|
||||
{
|
||||
int32_t rc = 0, i = 0;
|
||||
uint16_t *gpio_array = NULL;
|
||||
int16_t gpio_array_size = 0;
|
||||
struct msm_camera_gpio_conf *gconf = NULL;
|
||||
|
||||
gpio_array_size = of_gpio_count(of_node);
|
||||
CDBG("%s gpio count %d\n", __func__, gpio_array_size);
|
||||
|
||||
if (gpio_array_size > 0) {
|
||||
fctrl->power_info.gpio_conf =
|
||||
kzalloc(sizeof(struct msm_camera_gpio_conf),
|
||||
GFP_KERNEL);
|
||||
if (!fctrl->power_info.gpio_conf) {
|
||||
pr_err("%s failed %d\n", __func__, __LINE__);
|
||||
rc = -ENOMEM;
|
||||
return rc;
|
||||
}
|
||||
gconf = fctrl->power_info.gpio_conf;
|
||||
|
||||
gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t),
|
||||
GFP_KERNEL);
|
||||
if (!gpio_array)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < gpio_array_size; i++) {
|
||||
gpio_array[i] = of_get_gpio(of_node, i);
|
||||
if (((int16_t)gpio_array[i]) < 0) {
|
||||
pr_err("%s failed %d\n", __func__, __LINE__);
|
||||
rc = -EINVAL;
|
||||
goto free_gpio_array;
|
||||
}
|
||||
CDBG("%s gpio_array[%d] = %d\n", __func__, i,
|
||||
gpio_array[i]);
|
||||
}
|
||||
|
||||
rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
|
||||
gpio_array, gpio_array_size);
|
||||
if (rc < 0) {
|
||||
pr_err("%s failed %d\n", __func__, __LINE__);
|
||||
goto free_gpio_array;
|
||||
}
|
||||
kfree(gpio_array);
|
||||
|
||||
if (fctrl->ir_cut_driver_type == IR_CUT_DRIVER_DEFAULT)
|
||||
fctrl->ir_cut_driver_type = IR_CUT_DRIVER_GPIO;
|
||||
CDBG("%s:%d fctrl->ir_cut_driver_type = %d", __func__, __LINE__,
|
||||
fctrl->ir_cut_driver_type);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
free_gpio_array:
|
||||
kfree(gpio_array);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_cut_get_dt_data(struct device_node *of_node,
|
||||
struct msm_ir_cut_ctrl_t *fctrl)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
CDBG("called\n");
|
||||
|
||||
if (!of_node) {
|
||||
pr_err("of_node NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Read the sub device */
|
||||
rc = of_property_read_u32(of_node, "cell-index", &fctrl->pdev->id);
|
||||
if (rc < 0) {
|
||||
pr_err("failed rc %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
fctrl->ir_cut_driver_type = IR_CUT_DRIVER_DEFAULT;
|
||||
|
||||
/* Read the gpio information from device tree */
|
||||
rc = msm_ir_cut_get_gpio_dt_data(of_node, fctrl);
|
||||
if (rc < 0) {
|
||||
pr_err("%s:%d msm_ir_cut_get_gpio_dt_data failed rc %d\n",
|
||||
__func__, __LINE__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long msm_ir_cut_subdev_do_ioctl(
|
||||
struct file *file, unsigned int cmd, void *arg)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
struct video_device *vdev = video_devdata(file);
|
||||
struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
|
||||
struct msm_ir_cut_cfg_data_t32 *u32 =
|
||||
(struct msm_ir_cut_cfg_data_t32 *)arg;
|
||||
struct msm_ir_cut_cfg_data_t ir_cut_data;
|
||||
|
||||
CDBG("Enter");
|
||||
ir_cut_data.cfg_type = u32->cfg_type;
|
||||
|
||||
switch (cmd) {
|
||||
case VIDIOC_MSM_IR_CUT_CFG32:
|
||||
cmd = VIDIOC_MSM_IR_CUT_CFG;
|
||||
break;
|
||||
default:
|
||||
return msm_ir_cut_subdev_ioctl(sd, cmd, arg);
|
||||
}
|
||||
|
||||
rc = msm_ir_cut_subdev_ioctl(sd, cmd, &ir_cut_data);
|
||||
|
||||
CDBG("Exit");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long msm_ir_cut_subdev_fops_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return video_usercopy(file, cmd, arg, msm_ir_cut_subdev_do_ioctl);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t msm_ir_cut_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
int32_t rc = 0, i = 0;
|
||||
struct msm_ir_cut_ctrl_t *ir_cut_ctrl = NULL;
|
||||
|
||||
CDBG("Enter");
|
||||
if (!pdev->dev.of_node) {
|
||||
pr_err("of_node NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ir_cut_ctrl = kzalloc(sizeof(struct msm_ir_cut_ctrl_t), GFP_KERNEL);
|
||||
if (!ir_cut_ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(ir_cut_ctrl, 0, sizeof(struct msm_ir_cut_ctrl_t));
|
||||
|
||||
ir_cut_ctrl->pdev = pdev;
|
||||
|
||||
rc = msm_ir_cut_get_dt_data(pdev->dev.of_node, ir_cut_ctrl);
|
||||
|
||||
if (rc < 0) {
|
||||
pr_err("%s:%d msm_ir_cut_get_dt_data failed\n",
|
||||
__func__, __LINE__);
|
||||
kfree(ir_cut_ctrl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = msm_sensor_driver_get_gpio_data(&(ir_cut_ctrl->gconf),
|
||||
(&pdev->dev)->of_node);
|
||||
|
||||
if ((rc < 0) || (ir_cut_ctrl->gconf == NULL)) {
|
||||
pr_err("%s: No IR CUT GPIOs\n", __func__);
|
||||
|
||||
kfree(ir_cut_ctrl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CDBG("%s: gpio_request_table_size = %d\n",
|
||||
__func__,
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl_size);
|
||||
|
||||
for (i = 0;
|
||||
i < ir_cut_ctrl->gconf->cam_gpio_req_tbl_size; i++) {
|
||||
CDBG("%s: gpio = %d\n", __func__,
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl[i].gpio);
|
||||
CDBG("%s: gpio-flags = %lu\n", __func__,
|
||||
ir_cut_ctrl->gconf->cam_gpio_req_tbl[i].flags);
|
||||
CDBG("%s: gconf->gpio_num_info->gpio_num[%d] = %d\n",
|
||||
__func__, i,
|
||||
ir_cut_ctrl->gconf->gpio_num_info->gpio_num[i]);
|
||||
}
|
||||
|
||||
ir_cut_ctrl->cam_pinctrl_status = 1;
|
||||
|
||||
rc = msm_camera_pinctrl_init(
|
||||
&(ir_cut_ctrl->pinctrl_info), &(pdev->dev));
|
||||
|
||||
if (rc < 0) {
|
||||
pr_err("ERR:%s: Error in reading IR CUT pinctrl\n",
|
||||
__func__);
|
||||
ir_cut_ctrl->cam_pinctrl_status = 0;
|
||||
}
|
||||
|
||||
ir_cut_ctrl->ir_cut_state = MSM_CAMERA_IR_CUT_RELEASE;
|
||||
ir_cut_ctrl->power_info.dev = &ir_cut_ctrl->pdev->dev;
|
||||
ir_cut_ctrl->ir_cut_device_type = MSM_CAMERA_PLATFORM_DEVICE;
|
||||
ir_cut_ctrl->ir_cut_mutex = &msm_ir_cut_mutex;
|
||||
|
||||
/* Initialize sub device */
|
||||
v4l2_subdev_init(&ir_cut_ctrl->msm_sd.sd, &msm_ir_cut_subdev_ops);
|
||||
v4l2_set_subdevdata(&ir_cut_ctrl->msm_sd.sd, ir_cut_ctrl);
|
||||
|
||||
ir_cut_ctrl->msm_sd.sd.internal_ops = &msm_ir_cut_internal_ops;
|
||||
ir_cut_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
snprintf(ir_cut_ctrl->msm_sd.sd.name,
|
||||
ARRAY_SIZE(ir_cut_ctrl->msm_sd.sd.name),
|
||||
"msm_camera_ir_cut");
|
||||
media_entity_init(&ir_cut_ctrl->msm_sd.sd.entity, 0, NULL, 0);
|
||||
ir_cut_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
|
||||
ir_cut_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_IR_CUT;
|
||||
ir_cut_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x1;
|
||||
msm_sd_register(&ir_cut_ctrl->msm_sd);
|
||||
|
||||
CDBG("%s:%d ir_cut sd name = %s", __func__, __LINE__,
|
||||
ir_cut_ctrl->msm_sd.sd.entity.name);
|
||||
msm_ir_cut_v4l2_subdev_fops = v4l2_subdev_fops;
|
||||
#ifdef CONFIG_COMPAT
|
||||
msm_ir_cut_v4l2_subdev_fops.compat_ioctl32 =
|
||||
msm_ir_cut_subdev_fops_ioctl;
|
||||
#endif
|
||||
ir_cut_ctrl->msm_sd.sd.devnode->fops = &msm_ir_cut_v4l2_subdev_fops;
|
||||
|
||||
CDBG("probe success\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(of, msm_ir_cut_dt_match);
|
||||
|
||||
static struct platform_driver msm_ir_cut_platform_driver = {
|
||||
.probe = msm_ir_cut_platform_probe,
|
||||
.driver = {
|
||||
.name = "qcom,ir-cut",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = msm_ir_cut_dt_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init msm_ir_cut_init_module(void)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
CDBG("Enter\n");
|
||||
rc = platform_driver_register(&msm_ir_cut_platform_driver);
|
||||
if (!rc)
|
||||
return rc;
|
||||
|
||||
pr_err("platform probe for ir_cut failed");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit msm_ir_cut_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&msm_ir_cut_platform_driver);
|
||||
}
|
||||
|
||||
static struct msm_ir_cut_table msm_gpio_ir_cut_table = {
|
||||
.ir_cut_driver_type = IR_CUT_DRIVER_GPIO,
|
||||
.func_tbl = {
|
||||
.camera_ir_cut_init = msm_ir_cut_init,
|
||||
.camera_ir_cut_release = msm_ir_cut_release,
|
||||
.camera_ir_cut_off = msm_ir_cut_off,
|
||||
.camera_ir_cut_on = msm_ir_cut_on,
|
||||
},
|
||||
};
|
||||
|
||||
module_init(msm_ir_cut_init_module);
|
||||
module_exit(msm_ir_cut_exit_module);
|
||||
MODULE_DESCRIPTION("MSM IR CUT");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,72 @@
|
|||
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSM_IR_CUT_H
|
||||
#define MSM_IR_CUT_H
|
||||
|
||||
#include <soc/qcom/camera2.h>
|
||||
#include "msm_camera_dt_util.h"
|
||||
#include "msm_camera_io_util.h"
|
||||
#include "msm_sd.h"
|
||||
|
||||
#define DEFINE_MSM_MUTEX(mutexname) \
|
||||
static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
|
||||
|
||||
enum msm_camera_ir_cut_state_t {
|
||||
MSM_CAMERA_IR_CUT_INIT,
|
||||
MSM_CAMERA_IR_CUT_RELEASE,
|
||||
};
|
||||
|
||||
enum msm_ir_cut_driver_type {
|
||||
IR_CUT_DRIVER_GPIO,
|
||||
IR_CUT_DRIVER_DEFAULT,
|
||||
};
|
||||
|
||||
struct msm_ir_cut_ctrl_t;
|
||||
|
||||
struct msm_ir_cut_func_t {
|
||||
int32_t (*camera_ir_cut_init)(struct msm_ir_cut_ctrl_t *,
|
||||
struct msm_ir_cut_cfg_data_t *);
|
||||
int32_t (*camera_ir_cut_release)(struct msm_ir_cut_ctrl_t *);
|
||||
int32_t (*camera_ir_cut_off)(struct msm_ir_cut_ctrl_t *,
|
||||
struct msm_ir_cut_cfg_data_t *);
|
||||
int32_t (*camera_ir_cut_on)(struct msm_ir_cut_ctrl_t *,
|
||||
struct msm_ir_cut_cfg_data_t *);
|
||||
};
|
||||
|
||||
struct msm_ir_cut_table {
|
||||
enum msm_ir_cut_driver_type ir_cut_driver_type;
|
||||
struct msm_ir_cut_func_t func_tbl;
|
||||
};
|
||||
|
||||
struct msm_ir_cut_ctrl_t {
|
||||
struct msm_sd_subdev msm_sd;
|
||||
struct platform_device *pdev;
|
||||
struct msm_ir_cut_func_t *func_tbl;
|
||||
struct msm_camera_power_ctrl_t power_info;
|
||||
|
||||
enum msm_camera_device_type_t ir_cut_device_type;
|
||||
struct mutex *ir_cut_mutex;
|
||||
|
||||
/* ir_cut driver type */
|
||||
enum msm_ir_cut_driver_type ir_cut_driver_type;
|
||||
|
||||
/* ir_cut state */
|
||||
enum msm_camera_ir_cut_state_t ir_cut_state;
|
||||
|
||||
struct msm_camera_gpio_conf *gconf;
|
||||
struct msm_pinctrl_info pinctrl_info;
|
||||
uint8_t cam_pinctrl_status;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
ccflags-y += -Idrivers/media/platform/msm/camera_v2
|
||||
ccflags-y += -Idrivers/media/platform/msm/camera_v2/common
|
||||
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
|
||||
obj-$(CONFIG_MSMB_CAMERA) += msm_ir_led.o
|
462
drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c
Normal file
462
drivers/media/platform/msm/camera_v2/sensor/ir_led/msm_ir_led.c
Normal file
|
@ -0,0 +1,462 @@
|
|||
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pwm.h>
|
||||
#include "msm_ir_led.h"
|
||||
#include "msm_camera_dt_util.h"
|
||||
|
||||
#undef CDBG
|
||||
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
|
||||
|
||||
DEFINE_MSM_MUTEX(msm_ir_led_mutex);
|
||||
|
||||
static struct v4l2_file_operations msm_ir_led_v4l2_subdev_fops;
|
||||
|
||||
static const struct of_device_id msm_ir_led_dt_match[] = {
|
||||
{.compatible = "qcom,ir-led", .data = NULL},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct msm_ir_led_table msm_default_ir_led_table;
|
||||
|
||||
static struct msm_ir_led_table *ir_led_table[] = {
|
||||
&msm_default_ir_led_table,
|
||||
};
|
||||
|
||||
static int32_t msm_ir_led_get_subdev_id(
|
||||
struct msm_ir_led_ctrl_t *ir_led_ctrl, void *arg)
|
||||
{
|
||||
uint32_t *subdev_id = (uint32_t *)arg;
|
||||
|
||||
CDBG("Enter\n");
|
||||
if (!subdev_id) {
|
||||
pr_err("subdevice ID is not valid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ir_led_ctrl->ir_led_device_type != MSM_CAMERA_PLATFORM_DEVICE) {
|
||||
pr_err("device type is not matching\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*subdev_id = ir_led_ctrl->pdev->id;
|
||||
|
||||
CDBG("subdev_id %d\n", *subdev_id);
|
||||
CDBG("Exit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_led_init(
|
||||
struct msm_ir_led_ctrl_t *ir_led_ctrl,
|
||||
struct msm_ir_led_cfg_data_t *ir_led_data)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
CDBG("Enter\n");
|
||||
|
||||
rc = ir_led_ctrl->func_tbl->camera_ir_led_off(ir_led_ctrl, ir_led_data);
|
||||
|
||||
CDBG("Exit\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_led_release(
|
||||
struct msm_ir_led_ctrl_t *ir_led_ctrl)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
if (ir_led_ctrl->ir_led_state == MSM_CAMERA_IR_LED_RELEASE) {
|
||||
pr_err("Invalid ir_led state = %d\n",
|
||||
ir_led_ctrl->ir_led_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ir_led_ctrl->func_tbl->camera_ir_led_off(ir_led_ctrl, NULL);
|
||||
if (rc < 0) {
|
||||
pr_err("camera_ir_led_off failed (%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
ir_led_ctrl->ir_led_state = MSM_CAMERA_IR_LED_RELEASE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_led_off(struct msm_ir_led_ctrl_t *ir_led_ctrl,
|
||||
struct msm_ir_led_cfg_data_t *ir_led_data)
|
||||
{
|
||||
CDBG("Enter\n");
|
||||
|
||||
if (ir_led_ctrl->pwm_dev)
|
||||
pwm_disable(ir_led_ctrl->pwm_dev);
|
||||
else
|
||||
pr_err("pwm device is null\n");
|
||||
|
||||
CDBG("Exit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_led_on(
|
||||
struct msm_ir_led_ctrl_t *ir_led_ctrl,
|
||||
struct msm_ir_led_cfg_data_t *ir_led_data)
|
||||
{
|
||||
int rc;
|
||||
|
||||
CDBG("pwm duty on(ns) %d, pwm period(ns) %d\n",
|
||||
ir_led_data->pwm_duty_on_ns, ir_led_data->pwm_period_ns);
|
||||
|
||||
if (ir_led_ctrl->pwm_dev) {
|
||||
rc = pwm_config(ir_led_ctrl->pwm_dev,
|
||||
ir_led_data->pwm_duty_on_ns,
|
||||
ir_led_data->pwm_period_ns);
|
||||
if (rc) {
|
||||
pr_err("PWM config failed (%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = pwm_enable(ir_led_ctrl->pwm_dev);
|
||||
if (rc) {
|
||||
pr_err("PWM enable failed(%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
} else
|
||||
pr_err("pwm device is null\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_led_handle_init(
|
||||
struct msm_ir_led_ctrl_t *ir_led_ctrl,
|
||||
struct msm_ir_led_cfg_data_t *ir_led_data)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
int32_t rc = -EFAULT;
|
||||
enum msm_ir_led_driver_type ir_led_driver_type =
|
||||
ir_led_ctrl->ir_led_driver_type;
|
||||
|
||||
CDBG("Enter\n");
|
||||
|
||||
if (ir_led_ctrl->ir_led_state == MSM_CAMERA_IR_LED_INIT) {
|
||||
pr_err("Invalid ir_led state = %d\n",
|
||||
ir_led_ctrl->ir_led_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ir_led_table); i++) {
|
||||
if (ir_led_driver_type == ir_led_table[i]->ir_led_driver_type) {
|
||||
ir_led_ctrl->func_tbl = &ir_led_table[i]->func_tbl;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
pr_err("failed invalid ir_led_driver_type %d\n",
|
||||
ir_led_driver_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = ir_led_ctrl->func_tbl->camera_ir_led_init(
|
||||
ir_led_ctrl, ir_led_data);
|
||||
if (rc < 0) {
|
||||
pr_err("camera_ir_led_init failed (%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ir_led_ctrl->ir_led_state = MSM_CAMERA_IR_LED_INIT;
|
||||
|
||||
CDBG("Exit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t msm_ir_led_config(struct msm_ir_led_ctrl_t *ir_led_ctrl,
|
||||
void __user *argp)
|
||||
{
|
||||
int32_t rc = -EINVAL;
|
||||
struct msm_ir_led_cfg_data_t *ir_led_data =
|
||||
(struct msm_ir_led_cfg_data_t *) argp;
|
||||
|
||||
mutex_lock(ir_led_ctrl->ir_led_mutex);
|
||||
|
||||
CDBG("type %d\n", ir_led_data->cfg_type);
|
||||
|
||||
switch (ir_led_data->cfg_type) {
|
||||
case CFG_IR_LED_INIT:
|
||||
rc = msm_ir_led_handle_init(ir_led_ctrl, ir_led_data);
|
||||
break;
|
||||
case CFG_IR_LED_RELEASE:
|
||||
if (ir_led_ctrl->ir_led_state == MSM_CAMERA_IR_LED_INIT)
|
||||
rc = ir_led_ctrl->func_tbl->camera_ir_led_release(
|
||||
ir_led_ctrl);
|
||||
break;
|
||||
case CFG_IR_LED_OFF:
|
||||
if (ir_led_ctrl->ir_led_state == MSM_CAMERA_IR_LED_INIT)
|
||||
rc = ir_led_ctrl->func_tbl->camera_ir_led_off(
|
||||
ir_led_ctrl, ir_led_data);
|
||||
break;
|
||||
case CFG_IR_LED_ON:
|
||||
if (ir_led_ctrl->ir_led_state == MSM_CAMERA_IR_LED_INIT)
|
||||
rc = ir_led_ctrl->func_tbl->camera_ir_led_on(
|
||||
ir_led_ctrl, ir_led_data);
|
||||
break;
|
||||
default:
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(ir_led_ctrl->ir_led_mutex);
|
||||
|
||||
CDBG("Exit: type %d\n", ir_led_data->cfg_type);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long msm_ir_led_subdev_ioctl(struct v4l2_subdev *sd,
|
||||
unsigned int cmd, void *arg)
|
||||
{
|
||||
struct msm_ir_led_ctrl_t *fctrl = NULL;
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
||||
CDBG("Enter\n");
|
||||
|
||||
if (!sd) {
|
||||
pr_err(" v4l2 ir led subdevice is NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
fctrl = v4l2_get_subdevdata(sd);
|
||||
if (!fctrl) {
|
||||
pr_err("fctrl NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (cmd) {
|
||||
case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
|
||||
return msm_ir_led_get_subdev_id(fctrl, argp);
|
||||
case VIDIOC_MSM_IR_LED_CFG:
|
||||
return msm_ir_led_config(fctrl, argp);
|
||||
case MSM_SD_NOTIFY_FREEZE:
|
||||
return 0;
|
||||
case MSM_SD_SHUTDOWN:
|
||||
if (!fctrl->func_tbl) {
|
||||
pr_err("No call back funcions\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return fctrl->func_tbl->camera_ir_led_release(fctrl);
|
||||
}
|
||||
default:
|
||||
pr_err_ratelimited("invalid cmd %d\n", cmd);
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
CDBG("Exit\n");
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_core_ops msm_ir_led_subdev_core_ops = {
|
||||
.ioctl = msm_ir_led_subdev_ioctl,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops msm_ir_led_subdev_ops = {
|
||||
.core = &msm_ir_led_subdev_core_ops,
|
||||
};
|
||||
|
||||
static int msm_ir_led_close(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh) {
|
||||
|
||||
int rc = 0;
|
||||
struct msm_ir_led_ctrl_t *ir_led_ctrl = v4l2_get_subdevdata(sd);
|
||||
|
||||
if (!ir_led_ctrl) {
|
||||
pr_err("v4l2 subdevice data read failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CDBG("Enter\n");
|
||||
|
||||
if (ir_led_ctrl->ir_led_state == MSM_CAMERA_IR_LED_INIT)
|
||||
rc = ir_led_ctrl->func_tbl->camera_ir_led_release(
|
||||
ir_led_ctrl);
|
||||
|
||||
CDBG("Exit (%d)\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_internal_ops msm_ir_led_internal_ops = {
|
||||
.close = msm_ir_led_close,
|
||||
};
|
||||
|
||||
static int32_t msm_ir_led_get_dt_data(struct device_node *of_node,
|
||||
struct msm_ir_led_ctrl_t *fctrl)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
CDBG("called\n");
|
||||
|
||||
/* Read the sub device */
|
||||
rc = of_property_read_u32(of_node, "cell-index", &fctrl->pdev->id);
|
||||
if (rc < 0) {
|
||||
pr_err("reading cell-index for ir-led node is failed(rc) %d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
fctrl->ir_led_driver_type = IR_LED_DRIVER_DEFAULT;
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long msm_ir_led_subdev_do_ioctl(
|
||||
struct file *file, unsigned int cmd, void *arg)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
struct video_device *vdev = video_devdata(file);
|
||||
struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
|
||||
struct msm_ir_led_cfg_data_t32 *u32 =
|
||||
(struct msm_ir_led_cfg_data_t32 *)arg;
|
||||
struct msm_ir_led_cfg_data_t ir_led_data;
|
||||
|
||||
CDBG("Enter\n");
|
||||
ir_led_data.cfg_type = u32->cfg_type;
|
||||
ir_led_data.pwm_duty_on_ns = u32->pwm_duty_on_ns;
|
||||
ir_led_data.pwm_period_ns = u32->pwm_period_ns;
|
||||
|
||||
switch (cmd) {
|
||||
case VIDIOC_MSM_IR_LED_CFG32:
|
||||
cmd = VIDIOC_MSM_IR_LED_CFG;
|
||||
break;
|
||||
default:
|
||||
return msm_ir_led_subdev_ioctl(sd, cmd, arg);
|
||||
}
|
||||
|
||||
rc = msm_ir_led_subdev_ioctl(sd, cmd, &ir_led_data);
|
||||
|
||||
CDBG("Exit\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long msm_ir_led_subdev_fops_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return video_usercopy(file, cmd, arg, msm_ir_led_subdev_do_ioctl);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t msm_ir_led_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
struct msm_ir_led_ctrl_t *ir_led_ctrl = NULL;
|
||||
|
||||
CDBG("Enter\n");
|
||||
if (!pdev->dev.of_node) {
|
||||
pr_err("IR LED device node is not present in device tree\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ir_led_ctrl = devm_kzalloc(&pdev->dev, sizeof(struct msm_ir_led_ctrl_t),
|
||||
GFP_KERNEL);
|
||||
if (!ir_led_ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
ir_led_ctrl->pdev = pdev;
|
||||
|
||||
/* Reading PWM device node */
|
||||
ir_led_ctrl->pwm_dev = of_pwm_get(pdev->dev.of_node, NULL);
|
||||
|
||||
if (IS_ERR(ir_led_ctrl->pwm_dev)) {
|
||||
rc = PTR_ERR(ir_led_ctrl->pwm_dev);
|
||||
pr_err("Cannot get PWM device (%d)\n", rc);
|
||||
ir_led_ctrl->pwm_dev = NULL;
|
||||
}
|
||||
|
||||
rc = msm_ir_led_get_dt_data(pdev->dev.of_node, ir_led_ctrl);
|
||||
if (rc < 0) {
|
||||
pr_err("msm_ir_led_get_dt_data failed\n");
|
||||
devm_kfree(&pdev->dev, ir_led_ctrl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ir_led_ctrl->ir_led_state = MSM_CAMERA_IR_LED_RELEASE;
|
||||
ir_led_ctrl->power_info.dev = &ir_led_ctrl->pdev->dev;
|
||||
ir_led_ctrl->ir_led_device_type = MSM_CAMERA_PLATFORM_DEVICE;
|
||||
ir_led_ctrl->ir_led_mutex = &msm_ir_led_mutex;
|
||||
|
||||
/* Initialize sub device */
|
||||
v4l2_subdev_init(&ir_led_ctrl->msm_sd.sd, &msm_ir_led_subdev_ops);
|
||||
v4l2_set_subdevdata(&ir_led_ctrl->msm_sd.sd, ir_led_ctrl);
|
||||
|
||||
ir_led_ctrl->msm_sd.sd.internal_ops = &msm_ir_led_internal_ops;
|
||||
ir_led_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
snprintf(ir_led_ctrl->msm_sd.sd.name,
|
||||
ARRAY_SIZE(ir_led_ctrl->msm_sd.sd.name),
|
||||
"msm_camera_ir_led");
|
||||
media_entity_init(&ir_led_ctrl->msm_sd.sd.entity, 0, NULL, 0);
|
||||
ir_led_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
|
||||
ir_led_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_IR_LED;
|
||||
ir_led_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x1;
|
||||
msm_sd_register(&ir_led_ctrl->msm_sd);
|
||||
|
||||
CDBG("ir_led sd name = %s\n",
|
||||
ir_led_ctrl->msm_sd.sd.entity.name);
|
||||
msm_ir_led_v4l2_subdev_fops = v4l2_subdev_fops;
|
||||
#ifdef CONFIG_COMPAT
|
||||
msm_ir_led_v4l2_subdev_fops.compat_ioctl32 =
|
||||
msm_ir_led_subdev_fops_ioctl;
|
||||
#endif
|
||||
ir_led_ctrl->msm_sd.sd.devnode->fops = &msm_ir_led_v4l2_subdev_fops;
|
||||
|
||||
CDBG("probe success\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(of, msm_ir_led_dt_match);
|
||||
|
||||
static struct platform_driver msm_ir_led_platform_driver = {
|
||||
.probe = msm_ir_led_platform_probe,
|
||||
.driver = {
|
||||
.name = "qcom,ir-led",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = msm_ir_led_dt_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init msm_ir_led_init_module(void)
|
||||
{
|
||||
int32_t rc = 0;
|
||||
|
||||
CDBG("Enter\n");
|
||||
rc = platform_driver_register(&msm_ir_led_platform_driver);
|
||||
if (!rc)
|
||||
return rc;
|
||||
|
||||
pr_err("ir-led driver register failed (%d)\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit msm_ir_led_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&msm_ir_led_platform_driver);
|
||||
}
|
||||
|
||||
static struct msm_ir_led_table msm_default_ir_led_table = {
|
||||
.ir_led_driver_type = IR_LED_DRIVER_DEFAULT,
|
||||
.func_tbl = {
|
||||
.camera_ir_led_init = msm_ir_led_init,
|
||||
.camera_ir_led_release = msm_ir_led_release,
|
||||
.camera_ir_led_off = msm_ir_led_off,
|
||||
.camera_ir_led_on = msm_ir_led_on,
|
||||
},
|
||||
};
|
||||
|
||||
module_init(msm_ir_led_init_module);
|
||||
module_exit(msm_ir_led_exit_module);
|
||||
MODULE_DESCRIPTION("MSM IR LED");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,71 @@
|
|||
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSM_IR_LED_H
|
||||
#define MSM_IR_LED_H
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/msm_cam_sensor.h>
|
||||
#include <soc/qcom/camera2.h>
|
||||
#include "msm_sd.h"
|
||||
|
||||
#define DEFINE_MSM_MUTEX(mutexname) \
|
||||
static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
|
||||
|
||||
enum msm_camera_ir_led_state_t {
|
||||
MSM_CAMERA_IR_LED_INIT,
|
||||
MSM_CAMERA_IR_LED_RELEASE,
|
||||
};
|
||||
|
||||
enum msm_ir_led_driver_type {
|
||||
IR_LED_DRIVER_GPIO,
|
||||
IR_LED_DRIVER_DEFAULT,
|
||||
};
|
||||
|
||||
struct msm_ir_led_ctrl_t;
|
||||
|
||||
struct msm_ir_led_func_t {
|
||||
int32_t (*camera_ir_led_init)(struct msm_ir_led_ctrl_t *,
|
||||
struct msm_ir_led_cfg_data_t *);
|
||||
int32_t (*camera_ir_led_release)(struct msm_ir_led_ctrl_t *);
|
||||
int32_t (*camera_ir_led_off)(struct msm_ir_led_ctrl_t *,
|
||||
struct msm_ir_led_cfg_data_t *);
|
||||
int32_t (*camera_ir_led_on)(struct msm_ir_led_ctrl_t *,
|
||||
struct msm_ir_led_cfg_data_t *);
|
||||
};
|
||||
|
||||
struct msm_ir_led_table {
|
||||
enum msm_ir_led_driver_type ir_led_driver_type;
|
||||
struct msm_ir_led_func_t func_tbl;
|
||||
};
|
||||
|
||||
struct msm_ir_led_ctrl_t {
|
||||
struct msm_sd_subdev msm_sd;
|
||||
struct platform_device *pdev;
|
||||
struct pwm_device *pwm_dev;
|
||||
struct msm_ir_led_func_t *func_tbl;
|
||||
struct msm_camera_power_ctrl_t power_info;
|
||||
|
||||
enum msm_camera_device_type_t ir_led_device_type;
|
||||
struct mutex *ir_led_mutex;
|
||||
|
||||
/* ir_led driver type */
|
||||
enum msm_ir_led_driver_type ir_led_driver_type;
|
||||
|
||||
/* ir_led state */
|
||||
enum msm_camera_ir_led_state_t ir_led_state;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -2,6 +2,7 @@
|
|||
#define __LINUX_MSM_CAM_SENSOR_H
|
||||
|
||||
#include <uapi/media/msm_cam_sensor.h>
|
||||
#include <uapi/media/msm_camsensor_sdk.h>
|
||||
|
||||
#include <linux/compat.h>
|
||||
|
||||
|
@ -72,6 +73,16 @@ struct csid_cfg_data32 {
|
|||
} cfg;
|
||||
};
|
||||
|
||||
struct msm_ir_led_cfg_data_t32 {
|
||||
enum msm_ir_led_cfg_type_t cfg_type;
|
||||
int32_t pwm_duty_on_ns;
|
||||
int32_t pwm_period_ns;
|
||||
};
|
||||
|
||||
struct msm_ir_cut_cfg_data_t32 {
|
||||
enum msm_ir_cut_cfg_type_t cfg_type;
|
||||
};
|
||||
|
||||
struct eeprom_read_t32 {
|
||||
compat_uptr_t dbuffer;
|
||||
uint32_t num_bytes;
|
||||
|
@ -258,6 +269,12 @@ struct msm_flash_cfg_data_t32 {
|
|||
|
||||
#define VIDIOC_MSM_FLASH_CFG32 \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct msm_flash_cfg_data_t32)
|
||||
|
||||
#define VIDIOC_MSM_IR_LED_CFG32 \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 14, struct msm_ir_led_cfg_data_t32)
|
||||
|
||||
#define VIDIOC_MSM_IR_CUT_CFG32 \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct msm_ir_cut_cfg_data_t32)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -291,6 +291,16 @@ struct msm_eeprom_info_t {
|
|||
struct msm_eeprom_memory_map_array *mem_map_array;
|
||||
};
|
||||
|
||||
struct msm_ir_led_cfg_data_t {
|
||||
enum msm_ir_led_cfg_type_t cfg_type;
|
||||
int32_t pwm_duty_on_ns;
|
||||
int32_t pwm_period_ns;
|
||||
};
|
||||
|
||||
struct msm_ir_cut_cfg_data_t {
|
||||
enum msm_ir_cut_cfg_type_t cfg_type;
|
||||
};
|
||||
|
||||
struct msm_eeprom_cfg_data {
|
||||
enum eeprom_cfg_type_t cfgtype;
|
||||
uint8_t is_supported;
|
||||
|
@ -600,5 +610,11 @@ struct sensor_init_cfg_data {
|
|||
#define VIDIOC_MSM_FLASH_QUERY_DATA \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct msm_flash_query_data_t)
|
||||
|
||||
#define VIDIOC_MSM_IR_LED_CFG \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct msm_ir_led_cfg_data_t)
|
||||
|
||||
#define VIDIOC_MSM_IR_CUT_CFG \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct msm_ir_cut_cfg_data_t)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -114,6 +114,15 @@ enum msm_sensor_power_seq_gpio_t {
|
|||
SENSOR_GPIO_MAX,
|
||||
};
|
||||
|
||||
enum msm_ir_cut_filter_gpio_t {
|
||||
IR_CUT_FILTER_GPIO_P = 0,
|
||||
IR_CUT_FILTER_GPIO_M,
|
||||
IR_CUT_FILTER_GPIO_MAX,
|
||||
};
|
||||
#define IR_CUT_FILTER_GPIO_P IR_CUT_FILTER_GPIO_P
|
||||
#define IR_CUT_FILTER_GPIO_M IR_CUT_FILTER_GPIO_M
|
||||
#define R_CUT_FILTER_GPIO_MAX IR_CUT_FILTER_GPIO_MAX
|
||||
|
||||
enum msm_camera_vreg_name_t {
|
||||
CAM_VDIG,
|
||||
CAM_VIO,
|
||||
|
@ -182,6 +191,28 @@ enum msm_flash_cfg_type_t {
|
|||
CFG_FLASH_HIGH,
|
||||
};
|
||||
|
||||
enum msm_ir_led_cfg_type_t {
|
||||
CFG_IR_LED_INIT = 0,
|
||||
CFG_IR_LED_RELEASE,
|
||||
CFG_IR_LED_OFF,
|
||||
CFG_IR_LED_ON,
|
||||
};
|
||||
#define CFG_IR_LED_INIT CFG_IR_LED_INIT
|
||||
#define CFG_IR_LED_RELEASE CFG_IR_LED_RELEASE
|
||||
#define CFG_IR_LED_OFF CFG_IR_LED_OFF
|
||||
#define CFG_IR_LED_ON CFG_IR_LED_ON
|
||||
|
||||
enum msm_ir_cut_cfg_type_t {
|
||||
CFG_IR_CUT_INIT = 0,
|
||||
CFG_IR_CUT_RELEASE,
|
||||
CFG_IR_CUT_OFF,
|
||||
CFG_IR_CUT_ON,
|
||||
};
|
||||
#define CFG_IR_CUT_INIT CFG_IR_CUT_INIT
|
||||
#define CFG_IR_CUT_RELEASE CFG_IR_CUT_RELEASE
|
||||
#define CFG_IR_CUT_OFF CFG_IR_CUT_OFF
|
||||
#define CFG_IR_CUT_ON CFG_IR_CUT_ON
|
||||
|
||||
enum msm_sensor_output_format_t {
|
||||
MSM_SENSOR_BAYER,
|
||||
MSM_SENSOR_YCBCR,
|
||||
|
|
|
@ -48,7 +48,9 @@
|
|||
#define MSM_CAMERA_SUBDEV_SENSOR_INIT 14
|
||||
#define MSM_CAMERA_SUBDEV_OIS 15
|
||||
#define MSM_CAMERA_SUBDEV_FLASH 16
|
||||
#define MSM_CAMERA_SUBDEV_EXT 17
|
||||
#define MSM_CAMERA_SUBDEV_IR_LED 17
|
||||
#define MSM_CAMERA_SUBDEV_IR_CUT 18
|
||||
#define MSM_CAMERA_SUBDEV_EXT 19
|
||||
|
||||
#define MSM_MAX_CAMERA_SENSORS 5
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue