blob: ed0a26b70effc1c7c37f2402b146531fff45e32e [file] [log] [blame]
/* Copyright (c) 2017-2018, 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.
*/
#include <linux/module.h>
#include <cam_sensor_cmn_header.h>
#include "cam_actuator_core.h"
#include "cam_sensor_util.h"
#include "cam_trace.h"
#include "cam_res_mgr_api.h"
int32_t cam_actuator_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
{
int rc = 0;
power_info->power_setting_size = 1;
power_info->power_setting =
(struct cam_sensor_power_setting *)
kzalloc(sizeof(struct cam_sensor_power_setting),
GFP_KERNEL);
if (!power_info->power_setting)
return -ENOMEM;
power_info->power_setting[0].seq_type = SENSOR_VAF;
power_info->power_setting[0].seq_val = CAM_VAF;
power_info->power_setting[0].config_val = 1;
power_info->power_setting[0].delay = 2;
power_info->power_down_setting_size = 1;
power_info->power_down_setting =
(struct cam_sensor_power_setting *)
kzalloc(sizeof(struct cam_sensor_power_setting),
GFP_KERNEL);
if (!power_info->power_down_setting) {
rc = -ENOMEM;
goto free_power_settings;
}
power_info->power_down_setting[0].seq_type = SENSOR_VAF;
power_info->power_down_setting[0].seq_val = CAM_VAF;
power_info->power_down_setting[0].config_val = 0;
return rc;
free_power_settings:
kfree(power_info->power_setting);
power_info->power_setting = NULL;
power_info->power_setting_size = 0;
return rc;
}
static int32_t cam_actuator_power_up(struct cam_actuator_ctrl_t *a_ctrl)
{
int rc = 0;
struct cam_hw_soc_info *soc_info =
&a_ctrl->soc_info;
struct cam_actuator_soc_private *soc_private;
struct cam_sensor_power_ctrl_t *power_info;
soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
if ((power_info->power_setting == NULL) &&
(power_info->power_down_setting == NULL)) {
CAM_INFO(CAM_ACTUATOR,
"Using default power settings");
rc = cam_actuator_construct_default_power_setting(power_info);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Construct default actuator power setting failed.");
return rc;
}
}
/* Parse and fill vreg params for power up settings */
rc = msm_camera_fill_vreg_params(
&a_ctrl->soc_info,
power_info->power_setting,
power_info->power_setting_size);
if (rc) {
CAM_ERR(CAM_ACTUATOR,
"failed to fill vreg params for power up rc:%d", rc);
return rc;
}
/* Parse and fill vreg params for power down settings*/
rc = msm_camera_fill_vreg_params(
&a_ctrl->soc_info,
power_info->power_down_setting,
power_info->power_down_setting_size);
if (rc) {
CAM_ERR(CAM_ACTUATOR,
"failed to fill vreg params power down rc:%d", rc);
return rc;
}
power_info->dev = soc_info->dev;
rc = cam_sensor_core_power_up(power_info, soc_info);
if (rc) {
CAM_ERR(CAM_ACTUATOR,
"failed in actuator power up rc %d", rc);
return rc;
}
rc = camera_io_init(&a_ctrl->io_master_info);
if (rc < 0)
CAM_ERR(CAM_ACTUATOR, "cci init failed: rc: %d", rc);
return rc;
}
static int32_t cam_actuator_power_down(struct cam_actuator_ctrl_t *a_ctrl)
{
int32_t rc = 0;
struct cam_sensor_power_ctrl_t *power_info;
struct cam_hw_soc_info *soc_info = &a_ctrl->soc_info;
struct cam_actuator_soc_private *soc_private;
if (!a_ctrl) {
CAM_ERR(CAM_ACTUATOR, "failed: a_ctrl %pK", a_ctrl);
return -EINVAL;
}
soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
soc_info = &a_ctrl->soc_info;
if (!power_info) {
CAM_ERR(CAM_ACTUATOR, "failed: power_info %pK", power_info);
return -EINVAL;
}
rc = msm_camera_power_down(power_info, soc_info);
if (rc) {
CAM_ERR(CAM_ACTUATOR, "power down the core is failed:%d", rc);
return rc;
}
camera_io_release(&a_ctrl->io_master_info);
return rc;
}
static int32_t cam_actuator_i2c_modes_util(
struct camera_io_master *io_master_info,
struct i2c_settings_list *i2c_list)
{
int32_t rc = 0;
uint32_t i, size;
if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_RANDOM) {
rc = camera_io_dev_write(io_master_info,
&(i2c_list->i2c_settings));
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed to random write I2C settings: %d",
rc);
return rc;
}
} else if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) {
rc = camera_io_dev_write_continuous(
io_master_info,
&(i2c_list->i2c_settings),
0);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed to seq write I2C settings: %d",
rc);
return rc;
}
} else if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_BURST) {
rc = camera_io_dev_write_continuous(
io_master_info,
&(i2c_list->i2c_settings),
1);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed to burst write I2C settings: %d",
rc);
return rc;
}
} else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) {
size = i2c_list->i2c_settings.size;
for (i = 0; i < size; i++) {
rc = camera_io_dev_poll(
io_master_info,
i2c_list->i2c_settings.reg_setting[i].reg_addr,
i2c_list->i2c_settings.reg_setting[i].reg_data,
i2c_list->i2c_settings.reg_setting[i].data_mask,
i2c_list->i2c_settings.addr_type,
i2c_list->i2c_settings.data_type,
i2c_list->i2c_settings.reg_setting[i].delay);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"i2c poll apply setting Fail: %d", rc);
return rc;
}
}
}
return rc;
}
int32_t cam_actuator_slaveInfo_pkt_parser(struct cam_actuator_ctrl_t *a_ctrl,
uint32_t *cmd_buf)
{
int32_t rc = 0;
struct cam_cmd_i2c_info *i2c_info;
if (!a_ctrl || !cmd_buf) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
}
i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
if (a_ctrl->io_master_info.master_type == CCI_MASTER) {
a_ctrl->io_master_info.cci_client->cci_i2c_master =
a_ctrl->cci_i2c_master;
a_ctrl->io_master_info.cci_client->i2c_freq_mode =
i2c_info->i2c_freq_mode;
a_ctrl->io_master_info.cci_client->sid =
i2c_info->slave_addr >> 1;
CAM_DBG(CAM_ACTUATOR, "Slave addr: 0x%x Freq Mode: %d",
i2c_info->slave_addr, i2c_info->i2c_freq_mode);
} else if (a_ctrl->io_master_info.master_type == I2C_MASTER) {
a_ctrl->io_master_info.client->addr = i2c_info->slave_addr;
CAM_DBG(CAM_ACTUATOR, "Slave addr: 0x%x", i2c_info->slave_addr);
} else {
CAM_ERR(CAM_ACTUATOR, "Invalid Master type: %d",
a_ctrl->io_master_info.master_type);
rc = -EINVAL;
}
return rc;
}
int32_t cam_actuator_apply_settings(struct cam_actuator_ctrl_t *a_ctrl,
struct i2c_settings_array *i2c_set)
{
struct i2c_settings_list *i2c_list;
int32_t rc = 0;
if (a_ctrl == NULL || i2c_set == NULL) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
}
if (i2c_set->is_settings_valid != 1) {
CAM_ERR(CAM_ACTUATOR, " Invalid settings");
return -EINVAL;
}
list_for_each_entry(i2c_list,
&(i2c_set->list_head), list) {
rc = cam_actuator_i2c_modes_util(
&(a_ctrl->io_master_info),
i2c_list);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed to apply settings: %d",
rc);
} else {
CAM_DBG(CAM_ACTUATOR,
"Success:request ID: %d",
i2c_set->request_id);
}
}
return rc;
}
int32_t cam_actuator_apply_request(struct cam_req_mgr_apply_request *apply)
{
int32_t rc = 0, request_id, del_req_id;
struct cam_actuator_ctrl_t *a_ctrl = NULL;
if (!apply) {
CAM_ERR(CAM_ACTUATOR, "Invalid Input Args");
return -EINVAL;
}
a_ctrl = (struct cam_actuator_ctrl_t *)
cam_get_device_priv(apply->dev_hdl);
if (!a_ctrl) {
CAM_ERR(CAM_ACTUATOR, "Device data is NULL");
return -EINVAL;
}
request_id = apply->request_id % MAX_PER_FRAME_ARRAY;
trace_cam_apply_req("Actuator", apply->request_id);
CAM_DBG(CAM_ACTUATOR, "Request Id: %lld", apply->request_id);
if ((apply->request_id ==
a_ctrl->i2c_data.per_frame[request_id].request_id) &&
(a_ctrl->i2c_data.per_frame[request_id].is_settings_valid)
== 1) {
rc = cam_actuator_apply_settings(a_ctrl,
&a_ctrl->i2c_data.per_frame[request_id]);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed in applying the request: %lld\n",
apply->request_id);
return rc;
}
}
del_req_id = (request_id +
MAX_PER_FRAME_ARRAY - MAX_SYSTEM_PIPELINE_DELAY) %
MAX_PER_FRAME_ARRAY;
if (apply->request_id >
a_ctrl->i2c_data.per_frame[del_req_id].request_id) {
a_ctrl->i2c_data.per_frame[del_req_id].request_id = 0;
rc = delete_request(&a_ctrl->i2c_data.per_frame[del_req_id]);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Fail deleting the req: %d err: %d\n",
del_req_id, rc);
return rc;
}
} else {
CAM_DBG(CAM_ACTUATOR, "No Valid Req to clean Up");
}
return rc;
}
int32_t cam_actuator_establish_link(
struct cam_req_mgr_core_dev_link_setup *link)
{
struct cam_actuator_ctrl_t *a_ctrl = NULL;
if (!link) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
}
a_ctrl = (struct cam_actuator_ctrl_t *)
cam_get_device_priv(link->dev_hdl);
if (!a_ctrl) {
CAM_ERR(CAM_ACTUATOR, "Device data is NULL");
return -EINVAL;
}
if (link->link_enable) {
a_ctrl->bridge_intf.link_hdl = link->link_hdl;
a_ctrl->bridge_intf.crm_cb = link->crm_cb;
} else {
a_ctrl->bridge_intf.link_hdl = -1;
a_ctrl->bridge_intf.crm_cb = NULL;
}
return 0;
}
static void cam_actuator_update_req_mgr(
struct cam_actuator_ctrl_t *a_ctrl,
struct cam_packet *csl_packet)
{
struct cam_req_mgr_add_request add_req;
add_req.link_hdl = a_ctrl->bridge_intf.link_hdl;
add_req.req_id = csl_packet->header.request_id;
add_req.dev_hdl = a_ctrl->bridge_intf.device_hdl;
add_req.skip_before_applying = 0;
if (a_ctrl->bridge_intf.crm_cb &&
a_ctrl->bridge_intf.crm_cb->add_req) {
a_ctrl->bridge_intf.crm_cb->add_req(&add_req);
CAM_DBG(CAM_ACTUATOR, "Request Id: %lld added to CRM",
add_req.req_id);
} else {
CAM_ERR(CAM_ACTUATOR, "Can't add Request ID: %lld to CRM",
csl_packet->header.request_id);
}
}
int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info)
{
if (!info) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
}
info->dev_id = CAM_REQ_MGR_DEVICE_ACTUATOR;
strlcpy(info->name, CAM_ACTUATOR_NAME, sizeof(info->name));
info->p_delay = 1;
info->trigger = CAM_TRIGGER_POINT_SOF;
return 0;
}
int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
void *arg)
{
int32_t rc = 0;
int32_t i = 0;
uint32_t total_cmd_buf_in_bytes = 0;
size_t len_of_buff = 0;
uint32_t *offset = NULL;
uint32_t *cmd_buf = NULL;
uint64_t generic_ptr;
struct common_header *cmm_hdr = NULL;
struct cam_control *ioctl_ctrl = NULL;
struct cam_packet *csl_packet = NULL;
struct cam_config_dev_cmd config;
struct i2c_data_settings *i2c_data = NULL;
struct i2c_settings_array *i2c_reg_settings = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
struct cam_actuator_soc_private *soc_private = NULL;
struct cam_sensor_power_ctrl_t *power_info = NULL;
if (!a_ctrl || !arg) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
}
soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
ioctl_ctrl = (struct cam_control *)arg;
if (copy_from_user(&config, (void __user *) ioctl_ctrl->handle,
sizeof(config)))
return -EFAULT;
rc = cam_mem_get_cpu_buf(config.packet_handle,
(uint64_t *)&generic_ptr, &len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Error in converting command Handle %d",
rc);
return rc;
}
if (config.offset > len_of_buff) {
CAM_ERR(CAM_ACTUATOR,
"offset is out of bounds: offset: %lld len: %zu",
config.offset, len_of_buff);
return -EINVAL;
}
csl_packet = (struct cam_packet *)(generic_ptr + config.offset);
CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_ACTUATOR_PACKET_OPCODE_INIT:
offset = (uint32_t *)&csl_packet->payload;
offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
/* Loop through multiple command buffers */
for (i = 0; i < csl_packet->num_cmd_buf; i++) {
total_cmd_buf_in_bytes = cmd_desc[i].length;
if (!total_cmd_buf_in_bytes)
continue;
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
(uint64_t *)&generic_ptr, &len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Failed to get cpu buf");
return rc;
}
cmd_buf = (uint32_t *)generic_ptr;
if (!cmd_buf) {
CAM_ERR(CAM_ACTUATOR, "invalid cmd buf");
return -EINVAL;
}
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
cmm_hdr = (struct common_header *)cmd_buf;
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
CAM_DBG(CAM_ACTUATOR,
"Received slave info buffer");
rc = cam_actuator_slaveInfo_pkt_parser(
a_ctrl, cmd_buf);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed to parse slave info: %d", rc);
return rc;
}
break;
case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
CAM_DBG(CAM_ACTUATOR,
"Received power settings buffer");
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
power_info);
if (rc) {
CAM_ERR(CAM_ACTUATOR,
"Failed:parse power settings: %d",
rc);
return rc;
}
break;
default:
CAM_DBG(CAM_ACTUATOR,
"Received initSettings buffer");
i2c_data = &(a_ctrl->i2c_data);
i2c_reg_settings =
&i2c_data->init_settings;
i2c_reg_settings->request_id = 0;
i2c_reg_settings->is_settings_valid = 1;
rc = cam_sensor_i2c_command_parser(
&a_ctrl->io_master_info,
i2c_reg_settings,
&cmd_desc[i], 1);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed:parse init settings: %d",
rc);
return rc;
}
break;
}
}
if (a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE) {
rc = cam_actuator_power_up(a_ctrl);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
" Actuator Power up failed");
return rc;
}
a_ctrl->cam_act_state = CAM_ACTUATOR_CONFIG;
}
rc = cam_actuator_apply_settings(a_ctrl,
&a_ctrl->i2c_data.init_settings);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Cannot apply Init settings");
return rc;
}
/* Delete the request even if the apply is failed */
rc = delete_request(&a_ctrl->i2c_data.init_settings);
if (rc < 0) {
CAM_WARN(CAM_ACTUATOR,
"Fail in deleting the Init settings");
rc = 0;
}
break;
case CAM_ACTUATOR_PACKET_AUTO_MOVE_LENS:
if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) {
rc = -EINVAL;
CAM_WARN(CAM_ACTUATOR,
"Not in right state to move lens: %d",
a_ctrl->cam_act_state);
return rc;
}
a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_NOW;
i2c_data = &(a_ctrl->i2c_data);
i2c_reg_settings = &i2c_data->init_settings;
i2c_data->init_settings.request_id =
csl_packet->header.request_id;
i2c_reg_settings->is_settings_valid = 1;
offset = (uint32_t *)&csl_packet->payload;
offset += csl_packet->cmd_buf_offset / sizeof(uint32_t);
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_sensor_i2c_command_parser(
&a_ctrl->io_master_info,
i2c_reg_settings,
cmd_desc, 1);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Auto move lens parsing failed: %d", rc);
return rc;
}
cam_actuator_update_req_mgr(a_ctrl, csl_packet);
break;
case CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS:
if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) {
rc = -EINVAL;
CAM_WARN(CAM_ACTUATOR,
"Not in right state to move lens: %d",
a_ctrl->cam_act_state);
return rc;
}
a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_LATER;
i2c_data = &(a_ctrl->i2c_data);
i2c_reg_settings = &i2c_data->per_frame[
csl_packet->header.request_id % MAX_PER_FRAME_ARRAY];
i2c_reg_settings->request_id =
csl_packet->header.request_id;
i2c_reg_settings->is_settings_valid = 1;
offset = (uint32_t *)&csl_packet->payload;
offset += csl_packet->cmd_buf_offset / sizeof(uint32_t);
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_sensor_i2c_command_parser(
&a_ctrl->io_master_info,
i2c_reg_settings,
cmd_desc, 1);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Manual move lens parsing failed: %d", rc);
return rc;
}
cam_actuator_update_req_mgr(a_ctrl, csl_packet);
break;
case CAM_PKT_NOP_OPCODE:
if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) {
CAM_WARN(CAM_ACTUATOR,
"Received NOP packets in invalid state: %d",
a_ctrl->cam_act_state);
return -EINVAL;
}
cam_actuator_update_req_mgr(a_ctrl, csl_packet);
break;
}
return rc;
}
void cam_actuator_shutdown(struct cam_actuator_ctrl_t *a_ctrl)
{
int rc = 0;
struct cam_actuator_soc_private *soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
struct cam_sensor_power_ctrl_t *power_info =
&soc_private->power_info;
if (a_ctrl->cam_act_state == CAM_ACTUATOR_INIT)
return;
if (a_ctrl->cam_act_state >= CAM_ACTUATOR_CONFIG) {
rc = cam_actuator_power_down(a_ctrl);
if (rc < 0)
CAM_ERR(CAM_ACTUATOR, "Actuator Power down failed");
a_ctrl->cam_act_state = CAM_ACTUATOR_ACQUIRE;
}
if (a_ctrl->cam_act_state >= CAM_ACTUATOR_ACQUIRE) {
rc = cam_destroy_device_hdl(a_ctrl->bridge_intf.device_hdl);
if (rc < 0)
CAM_ERR(CAM_ACTUATOR, "destroying dhdl failed");
a_ctrl->bridge_intf.device_hdl = -1;
a_ctrl->bridge_intf.link_hdl = -1;
a_ctrl->bridge_intf.session_hdl = -1;
}
kfree(power_info->power_setting);
kfree(power_info->power_down_setting);
power_info->power_setting = NULL;
power_info->power_down_setting = NULL;
power_info->power_setting_size = 0;
power_info->power_down_setting_size = 0;
a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
}
int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl,
void *arg)
{
int rc = 0;
struct cam_control *cmd = (struct cam_control *)arg;
struct cam_actuator_soc_private *soc_private = NULL;
struct cam_sensor_power_ctrl_t *power_info = NULL;
if (!a_ctrl || !cmd) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
}
soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
CAM_ERR(CAM_ACTUATOR, "Invalid handle type: %d",
cmd->handle_type);
return -EINVAL;
}
CAM_DBG(CAM_ACTUATOR, "Opcode to Actuator: %d", cmd->op_code);
mutex_lock(&(a_ctrl->actuator_mutex));
switch (cmd->op_code) {
case CAM_ACQUIRE_DEV: {
struct cam_sensor_acquire_dev actuator_acq_dev;
struct cam_create_dev_hdl bridge_params;
if (a_ctrl->bridge_intf.device_hdl != -1) {
CAM_ERR(CAM_ACTUATOR, "Device is already acquired");
rc = -EINVAL;
goto release_mutex;
}
rc = copy_from_user(&actuator_acq_dev,
(void __user *) cmd->handle,
sizeof(actuator_acq_dev));
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Failed Copying from user\n");
goto release_mutex;
}
bridge_params.session_hdl = actuator_acq_dev.session_handle;
bridge_params.ops = &a_ctrl->bridge_intf.ops;
bridge_params.v4l2_sub_dev_flag = 0;
bridge_params.media_entity_flag = 0;
bridge_params.priv = a_ctrl;
actuator_acq_dev.device_handle =
cam_create_device_hdl(&bridge_params);
a_ctrl->bridge_intf.device_hdl = actuator_acq_dev.device_handle;
a_ctrl->bridge_intf.session_hdl =
actuator_acq_dev.session_handle;
CAM_DBG(CAM_ACTUATOR, "Device Handle: %d",
actuator_acq_dev.device_handle);
if (copy_to_user((void __user *) cmd->handle, &actuator_acq_dev,
sizeof(struct cam_sensor_acquire_dev))) {
CAM_ERR(CAM_ACTUATOR, "Failed Copy to User");
rc = -EFAULT;
goto release_mutex;
}
a_ctrl->cam_act_state = CAM_ACTUATOR_ACQUIRE;
}
break;
case CAM_RELEASE_DEV: {
if (a_ctrl->cam_act_state == CAM_ACTUATOR_START) {
rc = -EINVAL;
CAM_WARN(CAM_ACTUATOR,
"Cant release actuator: in start state");
goto release_mutex;
}
if (a_ctrl->cam_act_state == CAM_ACTUATOR_CONFIG) {
rc = cam_actuator_power_down(a_ctrl);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Actuator Power down failed");
goto release_mutex;
}
}
if (a_ctrl->bridge_intf.device_hdl == -1) {
CAM_ERR(CAM_ACTUATOR, "link hdl: %d device hdl: %d",
a_ctrl->bridge_intf.device_hdl,
a_ctrl->bridge_intf.link_hdl);
rc = -EINVAL;
goto release_mutex;
}
rc = cam_destroy_device_hdl(a_ctrl->bridge_intf.device_hdl);
if (rc < 0)
CAM_ERR(CAM_ACTUATOR, "destroying the device hdl");
a_ctrl->bridge_intf.device_hdl = -1;
a_ctrl->bridge_intf.link_hdl = -1;
a_ctrl->bridge_intf.session_hdl = -1;
a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
kfree(power_info->power_setting);
kfree(power_info->power_down_setting);
power_info->power_setting = NULL;
power_info->power_down_setting = NULL;
power_info->power_down_setting_size = 0;
power_info->power_setting_size = 0;
}
break;
case CAM_QUERY_CAP: {
struct cam_actuator_query_cap actuator_cap = {0};
actuator_cap.slot_info = a_ctrl->soc_info.index;
if (copy_to_user((void __user *) cmd->handle, &actuator_cap,
sizeof(struct cam_actuator_query_cap))) {
CAM_ERR(CAM_ACTUATOR, "Failed Copy to User");
rc = -EFAULT;
goto release_mutex;
}
}
break;
case CAM_START_DEV: {
if (a_ctrl->cam_act_state != CAM_ACTUATOR_CONFIG) {
rc = -EINVAL;
CAM_WARN(CAM_ACTUATOR,
"Not in right state to start : %d",
a_ctrl->cam_act_state);
goto release_mutex;
}
a_ctrl->cam_act_state = CAM_ACTUATOR_START;
}
break;
case CAM_STOP_DEV: {
struct i2c_settings_array *i2c_set = NULL;
int i;
if (a_ctrl->cam_act_state != CAM_ACTUATOR_START) {
rc = -EINVAL;
CAM_WARN(CAM_ACTUATOR,
"Not in right state to stop : %d",
a_ctrl->cam_act_state);
goto release_mutex;
}
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
i2c_set = &(a_ctrl->i2c_data.per_frame[i]);
if (i2c_set->is_settings_valid == 1) {
rc = delete_request(i2c_set);
if (rc < 0)
CAM_ERR(CAM_SENSOR,
"delete request: %lld rc: %d",
i2c_set->request_id, rc);
}
}
a_ctrl->cam_act_state = CAM_ACTUATOR_CONFIG;
}
break;
case CAM_CONFIG_DEV: {
a_ctrl->setting_apply_state =
ACT_APPLY_SETTINGS_LATER;
rc = cam_actuator_i2c_pkt_parse(a_ctrl, arg);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Failed in actuator Parsing");
goto release_mutex;
}
if (a_ctrl->setting_apply_state ==
ACT_APPLY_SETTINGS_NOW) {
rc = cam_actuator_apply_settings(a_ctrl,
&a_ctrl->i2c_data.init_settings);
if (rc < 0)
CAM_ERR(CAM_ACTUATOR,
"Cannot apply Update settings");
/* Delete the request even if the apply is failed */
rc = delete_request(&a_ctrl->i2c_data.init_settings);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed in Deleting the Init Pkt: %d",
rc);
goto release_mutex;
}
}
}
break;
default:
CAM_ERR(CAM_ACTUATOR, "Invalid Opcode %d", cmd->op_code);
}
release_mutex:
mutex_unlock(&(a_ctrl->actuator_mutex));
return rc;
}
int32_t cam_actuator_flush_request(struct cam_req_mgr_flush_request *flush_req)
{
int32_t rc = 0, i;
uint32_t cancel_req_id_found = 0;
struct cam_actuator_ctrl_t *a_ctrl = NULL;
struct i2c_settings_array *i2c_set = NULL;
if (!flush_req)
return -EINVAL;
a_ctrl = (struct cam_actuator_ctrl_t *)
cam_get_device_priv(flush_req->dev_hdl);
if (!a_ctrl) {
CAM_ERR(CAM_ACTUATOR, "Device data is NULL");
return -EINVAL;
}
if (a_ctrl->i2c_data.per_frame == NULL) {
CAM_ERR(CAM_ACTUATOR, "i2c frame data is NULL");
return -EINVAL;
}
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
i2c_set = &(a_ctrl->i2c_data.per_frame[i]);
if ((flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ)
&& (i2c_set->request_id != flush_req->req_id))
continue;
if (i2c_set->is_settings_valid == 1) {
rc = delete_request(i2c_set);
if (rc < 0)
CAM_ERR(CAM_ACTUATOR,
"delete request: %lld rc: %d",
i2c_set->request_id, rc);
if (flush_req->type ==
CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) {
cancel_req_id_found = 1;
break;
}
}
}
if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ &&
!cancel_req_id_found)
CAM_DBG(CAM_ACTUATOR,
"Flush request id:%lld not found in the pending list",
flush_req->req_id);
return rc;
}