Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d7b44e6 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "UPSTREAM: Merge remote-tracking branch 'quic/dev/msm-4.9-camx' into...

Merge "UPSTREAM: Merge remote-tracking branch 'quic/dev/msm-4.9-camx' into msm-4.9_UPSTREAM - 09/08/17"
parents c5d88ef8 9dc3c207
Loading
Loading
Loading
Loading
+90 −24
Original line number Diff line number Diff line
@@ -71,6 +71,16 @@ enum cam_vfe_bus_packer_format {
	PACKER_FMT_MAX                         = 0xF,
};

enum cam_vfe_bus_comp_grp_id {
	CAM_VFE_BUS_COMP_GROUP_NONE = -EINVAL,
	CAM_VFE_BUS_COMP_GROUP_ID_0 = 0x0,
	CAM_VFE_BUS_COMP_GROUP_ID_1 = 0x1,
	CAM_VFE_BUS_COMP_GROUP_ID_2 = 0x2,
	CAM_VFE_BUS_COMP_GROUP_ID_3 = 0x3,
	CAM_VFE_BUS_COMP_GROUP_ID_4 = 0x4,
	CAM_VFE_BUS_COMP_GROUP_ID_5 = 0x5,
};

struct cam_vfe_bus_ver2_common_data {
	uint32_t                                    core_index;
	void __iomem                               *mem_base;
@@ -136,6 +146,9 @@ struct cam_vfe_bus_ver2_comp_grp_data {
	uint32_t                         intra_client_mask;
	uint32_t                         composite_mask;

	uint32_t                         acquire_dev_cnt;
	uint32_t                         irq_trigger_cnt;

	void                            *ctx;
};

@@ -187,6 +200,28 @@ static int cam_vfe_bus_get_evt_payload(
	return 0;
}

static enum cam_vfe_bus_comp_grp_id
	cam_vfe_bus_comp_grp_id_convert(uint32_t comp_grp)
{
	switch (comp_grp) {
	case CAM_ISP_RES_COMP_GROUP_ID_0:
		return CAM_VFE_BUS_COMP_GROUP_ID_0;
	case CAM_ISP_RES_COMP_GROUP_ID_1:
		return CAM_VFE_BUS_COMP_GROUP_ID_1;
	case CAM_ISP_RES_COMP_GROUP_ID_2:
		return CAM_VFE_BUS_COMP_GROUP_ID_2;
	case CAM_ISP_RES_COMP_GROUP_ID_3:
		return CAM_VFE_BUS_COMP_GROUP_ID_3;
	case CAM_ISP_RES_COMP_GROUP_ID_4:
		return CAM_VFE_BUS_COMP_GROUP_ID_4;
	case CAM_ISP_RES_COMP_GROUP_ID_5:
		return CAM_VFE_BUS_COMP_GROUP_ID_5;
	case CAM_ISP_RES_COMP_GROUP_NONE:
	default:
		return CAM_VFE_BUS_COMP_GROUP_NONE;
	}
}

static int cam_vfe_bus_put_evt_payload(void     *core_info,
	struct cam_vfe_bus_irq_evt_payload     **evt_payload)
{
@@ -1188,12 +1223,18 @@ static int cam_vfe_bus_acquire_comp_grp(
	struct cam_isp_resource_node       **comp_grp)
{
	int rc = 0;
	uint32_t bus_comp_grp_id;
	struct cam_isp_resource_node           *comp_grp_local = NULL;
	struct cam_vfe_bus_ver2_comp_grp_data  *rsrc_data = NULL;

	bus_comp_grp_id = cam_vfe_bus_comp_grp_id_convert(
		out_port_info->comp_grp_id);
	/* Perform match only if there is valid comp grp request */
	if (out_port_info->comp_grp_id != CAM_ISP_RES_COMP_GROUP_NONE) {
		/* Check if matching comp_grp already acquired */
		cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
		out_port_info->comp_grp_id, unique_id);
			bus_comp_grp_id, unique_id);
	}

	if (!comp_grp_local) {
		/* First find a free group */
@@ -1228,7 +1269,7 @@ static int cam_vfe_bus_acquire_comp_grp(
		rsrc_data->is_master = is_master;
		rsrc_data->composite_mask = 0;
		rsrc_data->unique_id = unique_id;
		rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
		rsrc_data->comp_grp_local_idx = bus_comp_grp_id;

		list_add_tail(&comp_grp_local->list,
			&ver2_bus_priv->used_comp_grp);
@@ -1246,6 +1287,7 @@ static int cam_vfe_bus_acquire_comp_grp(
	}

	rsrc_data->ctx = ctx;
	rsrc_data->acquire_dev_cnt++;
	*comp_grp = comp_grp_local;

	return rc;
@@ -1260,15 +1302,21 @@ static int cam_vfe_bus_release_comp_grp(
	int match_found = 0;

	if (!in_comp_grp) {
		CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_rsrc_data);
		CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_comp_grp);
		return -EINVAL;
	}

	if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
		/* Already Released. Do Nothing */
		CAM_ERR(CAM_ISP, "Already released Comp Grp");
		return 0;
	}

	if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) {
		CAM_ERR(CAM_ISP, "Invalid State %d",
			in_comp_grp->res_state);
		return -EBUSY;
	}

	in_rsrc_data = in_comp_grp->res_priv;

	list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
@@ -1284,24 +1332,32 @@ static int cam_vfe_bus_release_comp_grp(
		return -ENODEV;
	}


	in_rsrc_data->acquire_dev_cnt--;
	if (in_rsrc_data->acquire_dev_cnt == 0) {
		list_del(&comp_grp->list);
	if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
		in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
		list_add_tail(&comp_grp->list,
			&ver2_bus_priv->free_dual_comp_grp);
	else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
		&& in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
		list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);

		in_rsrc_data->unique_id = 0;
	in_rsrc_data->comp_grp_local_idx = 0;
		in_rsrc_data->comp_grp_local_idx = CAM_VFE_BUS_COMP_GROUP_NONE;
		in_rsrc_data->composite_mask = 0;
		in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;

		comp_grp->tasklet_info = NULL;
		comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;

		if (in_rsrc_data->comp_grp_type >=
			CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
			in_rsrc_data->comp_grp_type <=
			CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
			list_add_tail(&comp_grp->list,
				&ver2_bus_priv->free_dual_comp_grp);
		else if (in_rsrc_data->comp_grp_type >=
			CAM_VFE_BUS_VER2_COMP_GRP_0 &&
			in_rsrc_data->comp_grp_type <=
			CAM_VFE_BUS_VER2_COMP_GRP_5)
			list_add_tail(&comp_grp->list,
				&ver2_bus_priv->free_comp_grp);
	}

	return 0;
}

@@ -1491,8 +1547,13 @@ static int cam_vfe_bus_handle_comp_done_bottom_half(

		/* Regular Composite SUCCESS */
		if (status_reg & BIT(comp_grp_id + 5)) {
			rsrc_data->irq_trigger_cnt++;
			if (rsrc_data->irq_trigger_cnt ==
				rsrc_data->acquire_dev_cnt) {
				cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
					~BIT(comp_grp_id + 5);
				rsrc_data->irq_trigger_cnt = 0;
			}
			rc = CAM_VFE_IRQ_STATUS_SUCCESS;
		}

@@ -1530,8 +1591,13 @@ static int cam_vfe_bus_handle_comp_done_bottom_half(

		/* DUAL Composite SUCCESS */
		if (status_reg & BIT(comp_grp_id)) {
			rsrc_data->irq_trigger_cnt++;
			if (rsrc_data->irq_trigger_cnt ==
				rsrc_data->acquire_dev_cnt) {
				cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
					~BIT(comp_grp_id + 5);
				rsrc_data->irq_trigger_cnt = 0;
			}
			rc = CAM_VFE_IRQ_STATUS_SUCCESS;
		}

+1 −0
Original line number Diff line number Diff line
@@ -6,3 +6,4 @@ obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois/
+9 −0
Original line number Diff line number Diff line
ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/

obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois_dev.o cam_ois_core.o cam_ois_soc.o
+594 −0
Original line number Diff line number Diff line
/* Copyright (c) 2017, 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 <linux/firmware.h>
#include <cam_sensor_cmn_header.h>
#include "cam_ois_core.h"
#include "cam_ois_soc.h"
#include "cam_sensor_util.h"
#include "cam_debug_util.h"

/**
 * cam_ois_get_dev_handle - get device handle
 * @o_ctrl:     ctrl structure
 * @arg:        Camera control command argument
 *
 * Returns success or failure
 */
static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl,
	void *arg)
{
	struct cam_sensor_acquire_dev    ois_acq_dev;
	struct cam_create_dev_hdl        bridge_params;
	struct cam_control              *cmd = (struct cam_control *)arg;

	if (o_ctrl->bridge_intf.device_hdl != -1) {
		CAM_ERR(CAM_OIS, "Device is already acquired");
		return -EFAULT;
	}
	if (copy_from_user(&ois_acq_dev, (void __user *) cmd->handle,
		sizeof(ois_acq_dev)))
		return -EFAULT;

	bridge_params.session_hdl = ois_acq_dev.session_handle;
	bridge_params.ops = &o_ctrl->bridge_intf.ops;
	bridge_params.v4l2_sub_dev_flag = 0;
	bridge_params.media_entity_flag = 0;
	bridge_params.priv = o_ctrl;

	ois_acq_dev.device_handle =
		cam_create_device_hdl(&bridge_params);
	o_ctrl->bridge_intf.device_hdl = ois_acq_dev.device_handle;
	o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle;

	CAM_DBG(CAM_OIS, "Device Handle: %d", ois_acq_dev.device_handle);
	if (copy_to_user((void __user *) cmd->handle, &ois_acq_dev,
		sizeof(struct cam_sensor_acquire_dev))) {
		CAM_ERR(CAM_OIS, "ACQUIRE_DEV: copy to user failed");
		return -EFAULT;
	}
	return 0;
}

static int cam_ois_vreg_control(struct cam_ois_ctrl_t *o_ctrl,
	int config)
{
	int rc = 0, cnt;
	struct cam_hw_soc_info  *soc_info;

	soc_info = &o_ctrl->soc_info;
	cnt = soc_info->num_rgltr;

	if (!cnt)
		return 0;

	if (cnt >= CAM_SOC_MAX_REGULATOR) {
		CAM_ERR(CAM_OIS, "Regulators more than supported %d", cnt);
		return -EINVAL;
	}

	if (config)
		rc = cam_soc_util_enable_platform_resource(soc_info, false, 0,
			false);
	else
		rc = cam_soc_util_disable_platform_resource(soc_info, false,
			false);

	return rc;
}

static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl)
{
	int rc = 0;
	struct cam_hw_soc_info  *soc_info =
		&o_ctrl->soc_info;
	struct msm_camera_gpio_num_info *gpio_num_info = NULL;

	rc = cam_ois_vreg_control(o_ctrl, 1);
	if (rc < 0) {
		CAM_ERR(CAM_OIS, "OIS Reg Failed %d", rc);
		return rc;
	}

	gpio_num_info = o_ctrl->gpio_num_info;

	if (soc_info->gpio_data &&
		gpio_num_info &&
		gpio_num_info->valid[SENSOR_VAF] == 1) {
		rc = cam_soc_util_request_platform_resource(&o_ctrl->soc_info,
			NULL, NULL);
		rc = cam_soc_util_enable_platform_resource(&o_ctrl->soc_info,
			false, 0, false);
		if (rc < 0) {
			CAM_ERR(CAM_OIS, "Failed in req gpio: %d", rc);
			return rc;
		}

		gpio_set_value_cansleep(
			gpio_num_info->gpio_num[SENSOR_VAF],
			1);
	}

	/* VREG needs some delay to power up */
	usleep_range(2000, 2050);

	return rc;
}

static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl)
{
	int32_t rc = 0;
	struct cam_hw_soc_info *soc_info =
		&o_ctrl->soc_info;
	struct msm_camera_gpio_num_info *gpio_num_info = NULL;

	rc = cam_ois_vreg_control(o_ctrl, 0);
	if (rc < 0) {
		CAM_ERR(CAM_OIS, "Failed %d");
		return rc;
	}

	gpio_num_info = o_ctrl->gpio_num_info;

	if (soc_info->gpio_data &&
		gpio_num_info &&
		gpio_num_info->valid[SENSOR_VAF] == 1) {

		gpio_set_value_cansleep(
			gpio_num_info->gpio_num[SENSOR_VAF],
			GPIOF_OUT_INIT_LOW);

		rc = cam_soc_util_release_platform_resource(&o_ctrl->soc_info);
		rc |= cam_soc_util_disable_platform_resource(&o_ctrl->soc_info,
					0, 0);
		if (rc < 0)
			CAM_ERR(CAM_OIS,
				"Failed to disable platform resources: %d", rc);
	}

	return rc;
}

static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl,
	struct i2c_settings_array *i2c_set)
{
	struct i2c_settings_list *i2c_list;
	int32_t rc = 0;
	uint32_t i, size;

	if (o_ctrl == NULL || i2c_set == NULL) {
		CAM_ERR(CAM_OIS, "Invalid Args");
		return -EINVAL;
	}

	if (i2c_set->is_settings_valid != 1) {
		CAM_ERR(CAM_OIS, " Invalid settings");
		return -EINVAL;
	}

	list_for_each_entry(i2c_list,
		&(i2c_set->list_head), list) {
		if (i2c_list->op_code ==  CAM_SENSOR_I2C_WRITE_RANDOM) {
			rc = camera_io_dev_write(&(o_ctrl->io_master_info),
				&(i2c_list->i2c_settings));
			if (rc < 0) {
				CAM_ERR(CAM_OIS,
					"Failed in Applying i2c wrt settings");
				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(
					&(o_ctrl->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_OIS,
						"i2c poll apply setting Fail");
					return rc;
				}
			}
		}
	}

	return rc;
}

static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
	uint32_t *cmd_buf)
{
	int32_t rc = 0;
	struct cam_cmd_ois_info *ois_info;

	if (!o_ctrl || !cmd_buf) {
		CAM_ERR(CAM_OIS, "Invalid Args");
		return -EINVAL;
	}

	ois_info = (struct cam_cmd_ois_info *)cmd_buf;
	if (o_ctrl->io_master_info.master_type == CCI_MASTER) {
		o_ctrl->io_master_info.cci_client->i2c_freq_mode =
			ois_info->i2c_freq_mode;
		o_ctrl->io_master_info.cci_client->sid =
			ois_info->slave_addr >> 1;
		o_ctrl->ois_fw_flag = ois_info->ois_fw_flag;
		o_ctrl->is_ois_calib = ois_info->is_ois_calib;
		memcpy(o_ctrl->ois_name, ois_info->ois_name, 32);
		o_ctrl->io_master_info.cci_client->retries = 3;
		o_ctrl->io_master_info.cci_client->id_map = 0;
		memcpy(&(o_ctrl->opcode), &(ois_info->opcode),
			sizeof(struct cam_ois_opcode));
		CAM_DBG(CAM_OIS, "Slave addr: 0x%x Freq Mode: %d",
			ois_info->slave_addr, ois_info->i2c_freq_mode);
	} else if (o_ctrl->io_master_info.master_type == I2C_MASTER) {
		o_ctrl->io_master_info.client->addr = ois_info->slave_addr;
		CAM_DBG(CAM_OIS, "Slave addr: 0x%x", ois_info->slave_addr);
	} else {
		CAM_ERR(CAM_OIS, "Invalid Master type : %d",
			o_ctrl->io_master_info.master_type);
		rc = -EINVAL;
	}

	return rc;
}

static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
{
	uint16_t                           total_bytes = 0;
	uint8_t                           *ptr = NULL;
	int32_t                            rc = 0, cnt;
	const struct firmware             *fw = NULL;
	const char                        *fw_name_prog = NULL;
	const char                        *fw_name_coeff = NULL;
	char                               name_prog[32] = {0};
	char                               name_coeff[32] = {0};
	struct device                     *dev = &(o_ctrl->pdev->dev);
	struct cam_sensor_i2c_reg_setting  i2c_reg_setting;

	if (!o_ctrl) {
		CAM_ERR(CAM_OIS, "Invalid Args");
		return -EINVAL;
	}

	snprintf(name_coeff, 32, "%s.coeff", o_ctrl->ois_name);

	snprintf(name_prog, 32, "%s.prog", o_ctrl->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) {
		CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_prog);
		return rc;
	}

	total_bytes = fw->size;
	i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
	i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
	i2c_reg_setting.size = total_bytes;
	i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *)
		kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes,
		GFP_KERNEL);
	if (!i2c_reg_setting.reg_setting) {
		CAM_ERR(CAM_OIS, "Failed in allocating i2c_array");
		release_firmware(fw);
		return -ENOMEM;
	}

	for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes;
		cnt++, ptr++) {
		i2c_reg_setting.reg_setting[cnt].reg_addr =
			o_ctrl->opcode.prog;
		i2c_reg_setting.reg_setting[cnt].reg_data = *ptr;
		i2c_reg_setting.reg_setting[cnt].delay = 0;
		i2c_reg_setting.reg_setting[cnt].data_mask = 0;
	}

	rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info),
		&i2c_reg_setting, 1);
	if (rc < 0) {
		CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);
		goto release_firmware;
	}
	kfree(i2c_reg_setting.reg_setting);
	release_firmware(fw);

	rc = request_firmware(&fw, fw_name_coeff, dev);
	if (rc) {
		CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_coeff);
		return rc;
	}

	total_bytes = fw->size;
	i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
	i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
	i2c_reg_setting.size = total_bytes;
	i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *)
		kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes,
		GFP_KERNEL);
	if (!i2c_reg_setting.reg_setting) {
		CAM_ERR(CAM_OIS, "Failed in allocating i2c_array");
		release_firmware(fw);
		return -ENOMEM;
	}

	for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes;
		cnt++, ptr++) {
		i2c_reg_setting.reg_setting[cnt].reg_addr =
			o_ctrl->opcode.coeff;
		i2c_reg_setting.reg_setting[cnt].reg_data = *ptr;
		i2c_reg_setting.reg_setting[cnt].delay = 0;
		i2c_reg_setting.reg_setting[cnt].data_mask = 0;
	}

	rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info),
		&i2c_reg_setting, 1);
	if (rc < 0)
		CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);

release_firmware:
	kfree(i2c_reg_setting.reg_setting);
	release_firmware(fw);

	return rc;
}

/**
 * cam_ois_pkt_parse - Parse csl packet
 * @o_ctrl:     ctrl structure
 * @arg:        Camera control command argument
 *
 * Returns success or failure
 */
static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
{
	int32_t                         rc = 0;
	uint64_t                        generic_ptr;
	struct cam_control             *ioctl_ctrl = NULL;
	struct cam_config_dev_cmd       dev_config;
	struct i2c_settings_array      *i2c_reg_settings = NULL;
	struct cam_cmd_buf_desc        *cmd_desc = NULL;
	uint64_t                        generic_pkt_addr;
	size_t                          pkt_len;
	struct cam_packet              *csl_packet = NULL;
	size_t                          len_of_buff = 0;
	uint32_t                       *offset = NULL, *cmd_buf;

	ioctl_ctrl = (struct cam_control *)arg;
	if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle,
		sizeof(dev_config)))
		return -EFAULT;
	rc = cam_mem_get_cpu_buf(dev_config.packet_handle,
		(uint64_t *)&generic_pkt_addr, &pkt_len);
	if (rc) {
		CAM_ERR(CAM_OIS,
			"error in converting command Handle Error: %d", rc);
		return rc;
	}

	if (dev_config.offset > pkt_len) {
		CAM_ERR(CAM_OIS,
			"offset is out of bound: off: %lld len: %zu",
			dev_config.offset, pkt_len);
		return -EINVAL;
	}

	csl_packet = (struct cam_packet *)
		(generic_pkt_addr + dev_config.offset);
	switch (csl_packet->header.op_code & 0xFFFFFF) {
	case CAM_OIS_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);

		if ((csl_packet->num_cmd_buf < 2) &&
			(csl_packet->num_cmd_buf > 3)) {
			CAM_ERR(CAM_OIS, "wrong cmd Buffer count: %d",
				csl_packet->num_cmd_buf);
			return -EINVAL;
		}

		rc = cam_mem_get_cpu_buf(cmd_desc[0].mem_handle,
			(uint64_t *)&generic_ptr, &len_of_buff);
		if (rc < 0) {
			CAM_ERR(CAM_OIS, "Failed to get cpu buf");
			return rc;
		}

		cmd_buf = (uint32_t *)generic_ptr;
		cmd_buf += cmd_desc->offset / sizeof(uint32_t);
		rc = cam_ois_slaveInfo_pkt_parser(o_ctrl, cmd_buf);
		if (rc < 0) {
			CAM_ERR(CAM_OIS, "Failed in parsing the pkt");
			return rc;
		}

		cmd_buf += (sizeof(struct cam_cmd_i2c_info)/sizeof(uint32_t));

		i2c_reg_settings = &(o_ctrl->i2c_init_data);
		i2c_reg_settings->is_settings_valid = 1;
		i2c_reg_settings->request_id = 0;
		rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings,
			&cmd_desc[1], 1);
		if (rc < 0) {
			CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d",
				rc);
			return rc;
		}

		if (o_ctrl->is_ois_calib) {
			i2c_reg_settings = &(o_ctrl->i2c_calib_data);
			i2c_reg_settings->is_settings_valid = 1;
			i2c_reg_settings->request_id = 0;
			rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings,
				&cmd_desc[2], 1);
			if (rc < 0) {
				CAM_ERR(CAM_OIS,
					"OIS pkt parsing failed: %d", rc);
				return rc;
			}
		}
		break;
	case CAM_OIS_PACKET_OPCODE_OIS_CONTROL:
		offset = (uint32_t *)&csl_packet->payload;
		offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
		i2c_reg_settings = &(o_ctrl->i2c_mode_data);
		i2c_reg_settings->is_settings_valid = 1;
		i2c_reg_settings->request_id = 0;
		rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings,
			cmd_desc, 1);
		if (rc < 0) {
			CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc);
			return rc;
		}

		rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings);
		if (rc < 0)
			CAM_ERR(CAM_OIS, "Cannot apply mode settings");
		break;
	default:
		break;
	}
	return rc;
}

/**
 * cam_ois_driver_cmd - Handle ois cmds
 * @e_ctrl:     ctrl structure
 * @arg:        Camera control command argument
 *
 * Returns success or failure
 */
int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg)
{
	int                            rc = 0;
	struct cam_ois_query_cap_t     ois_cap = {0};
	struct cam_control            *cmd = (struct cam_control *)arg;

	if (!o_ctrl) {
		CAM_ERR(CAM_OIS, "e_ctrl is NULL");
		return -EINVAL;
	}

	mutex_lock(&(o_ctrl->ois_mutex));
	switch (cmd->op_code) {
	case CAM_QUERY_CAP:
		ois_cap.slot_info = o_ctrl->subdev_id;

		if (copy_to_user((void __user *) cmd->handle,
			&ois_cap,
			sizeof(struct cam_ois_query_cap_t))) {
			CAM_ERR(CAM_OIS, "Failed Copy to User");
			return -EFAULT;
			goto release_mutex;
		}
		CAM_DBG(CAM_OIS, "ois_cap: ID: %d", ois_cap.slot_info);
		break;
	case CAM_ACQUIRE_DEV:
		rc = cam_ois_get_dev_handle(o_ctrl, arg);
		if (rc) {
			CAM_ERR(CAM_OIS, "Failed to acquire dev");
			goto release_mutex;
		}
		break;
	case CAM_START_DEV:
		rc = cam_ois_power_up(o_ctrl);
		if (rc) {
			CAM_ERR(CAM_OIS, " OIS Power up failed");
			goto release_mutex;
		}
		rc = camera_io_init(&o_ctrl->io_master_info);
		if (rc) {
			CAM_ERR(CAM_OIS, "cci_init failed");
			goto pwr_dwn;
		}

		if (o_ctrl->ois_fw_flag) {
			rc = cam_ois_fw_download(o_ctrl);
			if (rc) {
				CAM_ERR(CAM_OIS, "Failed OIS FW Download");
				goto pwr_dwn;
			}
		}

		rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_init_data);
		if (rc < 0) {
			CAM_ERR(CAM_OIS, "Cannot apply Init settings");
			goto pwr_dwn;
		}

		if (o_ctrl->is_ois_calib) {
			rc = cam_ois_apply_settings(o_ctrl,
				&o_ctrl->i2c_calib_data);
			if (rc) {
				CAM_ERR(CAM_OIS, "Cannot apply calib data");
				goto pwr_dwn;
			}
		}
		break;
	case CAM_CONFIG_DEV:
		rc = cam_ois_pkt_parse(o_ctrl, arg);
		if (rc) {
			CAM_ERR(CAM_OIS, "Failed in ois pkt Parsing");
			goto release_mutex;
		}
		break;
	case CAM_RELEASE_DEV:
		if (o_ctrl->bridge_intf.device_hdl == -1) {
			CAM_ERR(CAM_OIS, "link hdl: %d device hdl: %d",
				o_ctrl->bridge_intf.device_hdl,
				o_ctrl->bridge_intf.link_hdl);
			rc = -EINVAL;
			goto release_mutex;
		}
		rc = cam_destroy_device_hdl(o_ctrl->bridge_intf.device_hdl);
		if (rc < 0)
			CAM_ERR(CAM_OIS, "destroying the device hdl");
		o_ctrl->bridge_intf.device_hdl = -1;
		o_ctrl->bridge_intf.link_hdl = -1;
		o_ctrl->bridge_intf.session_hdl = -1;
		break;
	case CAM_STOP_DEV:
		rc = camera_io_release(&o_ctrl->io_master_info);
		if (rc < 0)
			CAM_ERR(CAM_OIS, "Failed in releasing CCI");
		rc = cam_ois_power_down(o_ctrl);
		if (rc < 0) {
			CAM_ERR(CAM_OIS, "OIS Power down failed");
			goto release_mutex;
		}
		break;
	default:
		CAM_ERR(CAM_OIS, "invalid opcode");
		goto release_mutex;
	}
pwr_dwn:
	cam_ois_power_down(o_ctrl);
release_mutex:
	mutex_unlock(&(o_ctrl->ois_mutex));

	return rc;
}
+20 −0
Original line number Diff line number Diff line
/* Copyright (c) 2017, 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 _CAM_OIS_CORE_H_
#define _CAM_OIS_CORE_H_

#include "cam_ois_dev.h"

int cam_ois_driver_cmd(struct cam_ois_ctrl_t *e_ctrl, void *arg);

#endif
/* _CAM_OIS_CORE_H_ */
Loading