summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSureshnaidu Laveti <lsuresh@codeaurora.org>2016-04-27 17:25:11 -0700
committerKyle Yan <kyan@codeaurora.org>2016-06-14 14:45:00 -0700
commitf0c5be8a96d56845c9ad2ef04f348195d4611827 (patch)
tree616aeff02d1146ea66500a67696d01e07c603c0a
parent4e9f522a76cf1a109dd1cbfa02eef13d4a27d46e (diff)
msm: sensor: Add support for downloading OIS coefficient and framework
Add OIS framework and coefficient download in OIS driver. Change-Id: Iff8e1c0367d13bb0d89946d81fb79427b6ef070e Signed-off-by: Sureshnaidu Laveti <lsuresh@codeaurora.org>
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c181
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h7
-rw-r--r--include/uapi/media/msm_cam_sensor.h25
3 files changed, 204 insertions, 9 deletions
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
index 82c9e5c5befa..5a891592b44f 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
@@ -13,6 +13,7 @@
#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
#include <linux/module.h>
+#include <linux/firmware.h>
#include "msm_sd.h"
#include "msm_ois.h"
#include "msm_cci.h"
@@ -32,6 +33,124 @@ static int32_t msm_ois_power_down(struct msm_ois_ctrl_t *o_ctrl);
static struct i2c_driver msm_ois_i2c_driver;
+static int32_t msm_ois_download(struct msm_ois_ctrl_t *o_ctrl)
+{
+ uint16_t bytes_in_tx = 0;
+ uint16_t total_bytes = 0;
+ uint8_t *ptr = NULL;
+ int32_t rc = 0;
+ const struct firmware *fw = NULL;
+ const char *fw_name_prog = NULL;
+ const char *fw_name_coeff = NULL;
+ char name_prog[MAX_SENSOR_NAME] = {0};
+ char name_coeff[MAX_SENSOR_NAME] = {0};
+ struct device *dev = &(o_ctrl->pdev->dev);
+ enum msm_camera_i2c_reg_addr_type save_addr_type;
+
+ CDBG("Enter\n");
+ save_addr_type = o_ctrl->i2c_client.addr_type;
+ o_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+
+ snprintf(name_coeff, MAX_SENSOR_NAME, "%s.coeff",
+ o_ctrl->oboard_info->ois_name);
+
+ snprintf(name_prog, MAX_SENSOR_NAME, "%s.prog",
+ o_ctrl->oboard_info->ois_name);
+
+ /* cast pointer as const pointer*/
+ fw_name_prog = name_prog;
+ fw_name_coeff = name_coeff;
+
+ /* Load FW */
+ rc = request_firmware(&fw, fw_name_prog, dev);
+ if (rc) {
+ dev_err(dev, "Failed to locate %s\n", fw_name_prog);
+ o_ctrl->i2c_client.addr_type = save_addr_type;
+ return rc;
+ }
+
+ total_bytes = fw->size;
+ for (ptr = (uint8_t *)fw->data; total_bytes;
+ total_bytes -= bytes_in_tx, ptr += bytes_in_tx) {
+ bytes_in_tx = (total_bytes > 10) ? 10 : total_bytes;
+ rc = o_ctrl->i2c_client.i2c_func_tbl->i2c_write_seq(
+ &o_ctrl->i2c_client, o_ctrl->oboard_info->opcode.prog,
+ ptr, bytes_in_tx);
+ if (rc < 0) {
+ pr_err("Failed:remaining bytes to be downloaded:%d\n",
+ bytes_in_tx);
+ /* abort download fw and return error*/
+ goto release_firmware;
+ }
+ }
+ release_firmware(fw);
+
+ rc = request_firmware(&fw, fw_name_coeff, dev);
+ if (rc) {
+ dev_err(dev, "Failed to locate %s\n", fw_name_coeff);
+ o_ctrl->i2c_client.addr_type = save_addr_type;
+ return rc;
+ }
+ total_bytes = fw->size;
+ for (ptr = (uint8_t *)fw->data; total_bytes;
+ total_bytes -= bytes_in_tx, ptr += bytes_in_tx) {
+ bytes_in_tx = (total_bytes > 10) ? 10 : total_bytes;
+ rc = o_ctrl->i2c_client.i2c_func_tbl->i2c_write_seq(
+ &o_ctrl->i2c_client, o_ctrl->oboard_info->opcode.coeff,
+ ptr, bytes_in_tx);
+ if (rc < 0) {
+ pr_err("Failed:remaining bytes to be downloaded:%d\n",
+ total_bytes);
+ /* abort download fw*/
+ break;
+ }
+ }
+release_firmware:
+ release_firmware(fw);
+ o_ctrl->i2c_client.addr_type = save_addr_type;
+
+ return rc;
+}
+
+static int32_t msm_ois_data_config(struct msm_ois_ctrl_t *o_ctrl,
+ struct msm_ois_slave_info *slave_info)
+{
+ int rc = 0;
+ struct msm_camera_cci_client *cci_client = NULL;
+
+ CDBG("Enter\n");
+ if (!slave_info) {
+ pr_err("failed : invalid slave_info\n");
+ return -EINVAL;
+ }
+ /* fill ois slave info*/
+ if (strlcpy(o_ctrl->oboard_info->ois_name, slave_info->ois_name,
+ sizeof(o_ctrl->oboard_info->ois_name)) < 0) {
+ pr_err("failed: copy_from_user\n");
+ return -EFAULT;
+ }
+ memcpy(&(o_ctrl->oboard_info->opcode), &(slave_info->opcode),
+ sizeof(struct msm_ois_opcode));
+ o_ctrl->oboard_info->i2c_slaveaddr = slave_info->i2c_addr;
+
+ /* config cci_client*/
+ if (o_ctrl->ois_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ cci_client = o_ctrl->i2c_client.cci_client;
+ cci_client->sid =
+ o_ctrl->oboard_info->i2c_slaveaddr >> 1;
+ cci_client->retries = 3;
+ cci_client->id_map = 0;
+ cci_client->cci_i2c_master = o_ctrl->cci_master;
+ } else {
+ o_ctrl->i2c_client.client->addr =
+ o_ctrl->oboard_info->i2c_slaveaddr;
+ }
+ o_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR;
+
+ CDBG("Exit\n");
+ return rc;
+}
+
static int32_t msm_ois_write_settings(struct msm_ois_ctrl_t *o_ctrl,
uint16_t size, struct reg_settings_ois_t *settings)
{
@@ -370,6 +489,40 @@ static int32_t msm_ois_config(struct msm_ois_ctrl_t *o_ctrl,
return rc;
}
+static int32_t msm_ois_config_download(struct msm_ois_ctrl_t *o_ctrl,
+ void __user *argp)
+{
+ struct msm_ois_cfg_download_data *cdata =
+ (struct msm_ois_cfg_download_data *)argp;
+ int32_t rc = 0;
+
+ if (!o_ctrl || !cdata) {
+ pr_err("failed: Invalid data\n");
+ return -EINVAL;
+ }
+ mutex_lock(o_ctrl->ois_mutex);
+ CDBG("Enter\n");
+ CDBG("%s type %d\n", __func__, cdata->cfgtype);
+ switch (cdata->cfgtype) {
+ case CFG_OIS_DATA_CONFIG:
+ rc = msm_ois_data_config(o_ctrl, &cdata->slave_info);
+ if (rc < 0)
+ pr_err("Failed ois data config %d\n", rc);
+ break;
+ case CFG_OIS_DOWNLOAD:
+ rc = msm_ois_download(o_ctrl);
+ if (rc < 0)
+ pr_err("Failed ois download %d\n", rc);
+ break;
+ default:
+ break;
+ }
+ mutex_unlock(o_ctrl->ois_mutex);
+ CDBG("Exit\n");
+ return rc;
+}
+
+
static int32_t msm_ois_get_subdev_id(struct msm_ois_ctrl_t *o_ctrl,
void *arg)
{
@@ -454,6 +607,8 @@ static long msm_ois_subdev_ioctl(struct v4l2_subdev *sd,
return msm_ois_get_subdev_id(o_ctrl, argp);
case VIDIOC_MSM_OIS_CFG:
return msm_ois_config(o_ctrl, argp);
+ case VIDIOC_MSM_OIS_CFG_DOWNLOAD:
+ return msm_ois_config_download(o_ctrl, argp);
case MSM_SD_SHUTDOWN:
if (!o_ctrl->i2c_client.i2c_func_tbl) {
pr_err("o_ctrl->i2c_client.i2c_func_tbl NULL\n");
@@ -696,22 +851,28 @@ static int32_t msm_ois_platform_probe(struct platform_device *pdev)
pr_err("%s:%d failed no memory\n", __func__, __LINE__);
return -ENOMEM;
}
+
+ msm_ois_t->oboard_info = kzalloc(sizeof(
+ struct msm_ois_board_info), GFP_KERNEL);
+ if (!msm_ois_t->oboard_info) {
+ kfree(msm_ois_t);
+ return -ENOMEM;
+ }
+
rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
&pdev->id);
CDBG("cell-index %d, rc %d\n", pdev->id, rc);
if (rc < 0) {
- kfree(msm_ois_t);
pr_err("failed rc %d\n", rc);
- return rc;
+ goto release_memory;
}
rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
&msm_ois_t->cci_master);
CDBG("qcom,cci-master %d, rc %d\n", msm_ois_t->cci_master, rc);
if (rc < 0 || msm_ois_t->cci_master >= MASTER_MAX) {
- kfree(msm_ois_t);
pr_err("failed rc %d\n", rc);
- return rc;
+ goto release_memory;
}
if (of_find_property((&pdev->dev)->of_node,
@@ -720,9 +881,8 @@ static int32_t msm_ois_platform_probe(struct platform_device *pdev)
rc = msm_camera_get_dt_vreg_data((&pdev->dev)->of_node,
&vreg_cfg->cam_vreg, &vreg_cfg->num_vreg);
if (rc < 0) {
- kfree(msm_ois_t);
pr_err("failed rc %d\n", rc);
- return rc;
+ goto release_memory;
}
}
@@ -753,9 +913,8 @@ static int32_t msm_ois_platform_probe(struct platform_device *pdev)
struct msm_camera_cci_client), GFP_KERNEL);
if (!msm_ois_t->i2c_client.cci_client) {
kfree(msm_ois_t->vreg_cfg.cam_vreg);
- kfree(msm_ois_t);
- pr_err("failed no memory\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto release_memory;
}
cci_client = msm_ois_t->i2c_client.cci_client;
@@ -784,6 +943,10 @@ static int32_t msm_ois_platform_probe(struct platform_device *pdev)
CDBG("Exit\n");
return rc;
+release_memory:
+ kfree(msm_ois_t->oboard_info);
+ kfree(msm_ois_t);
+ return rc;
}
static const struct of_device_id msm_ois_i2c_dt_match[] = {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h
index b9f8d4a0c3c8..614cc6c8cd5d 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h
@@ -41,6 +41,12 @@ struct msm_ois_vreg {
int num_vreg;
};
+struct msm_ois_board_info {
+ char ois_name[MAX_OIS_NAME_SIZE];
+ uint32_t i2c_slaveaddr;
+ struct msm_ois_opcode opcode;
+};
+
struct msm_ois_ctrl_t {
struct i2c_driver *i2c_driver;
struct platform_driver *pdriver;
@@ -61,6 +67,7 @@ struct msm_ois_ctrl_t {
struct msm_camera_gpio_conf *gconf;
struct msm_pinctrl_info pinctrl_info;
uint8_t cam_pinctrl_status;
+ struct msm_ois_board_info *oboard_info;
};
#endif
diff --git a/include/uapi/media/msm_cam_sensor.h b/include/uapi/media/msm_cam_sensor.h
index d83e00876fd5..5d340b9a2523 100644
--- a/include/uapi/media/msm_cam_sensor.h
+++ b/include/uapi/media/msm_cam_sensor.h
@@ -342,6 +342,13 @@ enum msm_actuator_cfg_type_t {
CFG_ACTUATOR_INIT,
};
+struct msm_ois_opcode {
+ uint32_t prog;
+ uint32_t coeff;
+ uint32_t pheripheral;
+ uint32_t memory;
+};
+
enum msm_ois_cfg_type_t {
CFG_OIS_INIT,
CFG_OIS_POWERDOWN,
@@ -350,6 +357,11 @@ enum msm_ois_cfg_type_t {
CFG_OIS_I2C_WRITE_SEQ_TABLE,
};
+enum msm_ois_cfg_download_type_t {
+ CFG_OIS_DOWNLOAD,
+ CFG_OIS_DATA_CONFIG,
+};
+
enum msm_ois_i2c_operation {
MSM_OIS_WRITE = 0,
MSM_OIS_POLL,
@@ -448,6 +460,11 @@ enum af_camera_name {
ACTUATOR_WEB_CAM_2,
};
+struct msm_ois_slave_info {
+ char ois_name[MAX_OIS_NAME_SIZE];
+ uint32_t i2c_addr;
+ struct msm_ois_opcode opcode;
+};
struct msm_ois_cfg_data {
int cfgtype;
union {
@@ -456,6 +473,11 @@ struct msm_ois_cfg_data {
} cfg;
};
+struct msm_ois_cfg_download_data {
+ int cfgtype;
+ struct msm_ois_slave_info slave_info;
+};
+
struct msm_actuator_set_position_t {
uint16_t number_of_steps;
uint32_t hw_params;
@@ -560,5 +582,8 @@ struct sensor_init_cfg_data {
#define VIDIOC_MSM_FLASH_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct msm_flash_cfg_data_t)
+#define VIDIOC_MSM_OIS_CFG_DOWNLOAD \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 14, struct msm_ois_cfg_download_data)
+
#endif