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

Commit cd22865b authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: isp: Add support to update write master"

parents ad679d74 cafac95d
Loading
Loading
Loading
Loading
+153 −5
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@
	(CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1)

#define CAM_ISP_GENERIC_BLOB_TYPE_MAX               \
	(CAM_ISP_GENERIC_BLOB_TYPE_IFE_CORE_CONFIG + 1)
	(CAM_ISP_GENERIC_BLOB_TYPE_VFE_OUT_CONFIG + 1)

static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
	CAM_ISP_HW_CMD_GET_HFR_UPDATE,
@@ -46,6 +46,8 @@ static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
	CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
	CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG,
	CAM_ISP_HW_CMD_UBWC_UPDATE_V2,
	CAM_ISP_HW_CMD_CORE_CONFIG,
	CAM_ISP_HW_CMD_WM_CONFIG_UPDATE,
};

static struct cam_ife_hw_mgr g_ife_hw_mgr;
@@ -4171,6 +4173,100 @@ static int cam_isp_blob_clock_update(
	return rc;
}

static int cam_isp_blob_vfe_out_update(
	uint32_t                               blob_type,
	struct cam_isp_generic_blob_info      *blob_info,
	struct cam_isp_vfe_out_config         *vfe_out_config,
	struct cam_hw_prepare_update_args     *prepare)
{
	struct cam_isp_vfe_wm_config          *wm_config;
	struct cam_kmd_buf_info               *kmd_buf_info;
	struct cam_ife_hw_mgr_ctx             *ctx = NULL;
	struct cam_ife_hw_mgr_res             *ife_out_res;
	uint32_t                               res_id_out, i;
	uint32_t                               total_used_bytes = 0;
	uint32_t                               kmd_buf_remain_size;
	uint32_t                              *cmd_buf_addr;
	uint32_t                               bytes_used = 0;
	int                                    num_ent, rc = 0;

	ctx = prepare->ctxt_to_hw_map;

	if (prepare->num_hw_update_entries + 1 >=
			prepare->max_hw_update_entries) {
		CAM_ERR(CAM_ISP, "Insufficient HW entries :%d %d",
			prepare->num_hw_update_entries,
			prepare->max_hw_update_entries);
		return -EINVAL;
	}

	kmd_buf_info = blob_info->kmd_buf_info;
	for (i = 0; i < vfe_out_config->num_ports; i++) {
		wm_config = &vfe_out_config->wm_config[i];
		res_id_out = wm_config->port_type & 0xFF;

		CAM_DBG(CAM_ISP, "VFE out config idx: %d port: 0x%x",
			i, wm_config->port_type);

		if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) {
			CAM_ERR(CAM_ISP, "Invalid out port:0x%x",
				wm_config->port_type);
			return -EINVAL;
		}

		if ((kmd_buf_info->used_bytes
			+ total_used_bytes) < kmd_buf_info->size) {
			kmd_buf_remain_size = kmd_buf_info->size -
			(kmd_buf_info->used_bytes +
			total_used_bytes);
		} else {
			CAM_ERR(CAM_ISP,
			"No free kmd memory for base idx: %d",
			blob_info->base_info->idx);
			rc = -ENOMEM;
			return rc;
		}

		cmd_buf_addr = kmd_buf_info->cpu_addr +
			(kmd_buf_info->used_bytes / 4) +
			(total_used_bytes / 4);
		ife_out_res = &ctx->res_list_ife_out[res_id_out];

		rc = cam_isp_add_cmd_buf_update(
			ife_out_res, blob_type,
			blob_type_hw_cmd_map[blob_type],
			blob_info->base_info->idx,
			(void *)cmd_buf_addr,
			kmd_buf_remain_size,
			(void *)wm_config,
			&bytes_used);
		if (rc < 0) {
			CAM_ERR(CAM_ISP,
				"Failed to update VFE out base_idx: %d rc: %d",
				blob_info->base_info->idx, bytes_used);
			return rc;
		}

		total_used_bytes += bytes_used;
	}

	if (total_used_bytes) {
		num_ent = prepare->num_hw_update_entries;
		prepare->hw_update_entries[num_ent].handle =
			kmd_buf_info->handle;
		prepare->hw_update_entries[num_ent].len = total_used_bytes;
		prepare->hw_update_entries[num_ent].offset =
			kmd_buf_info->offset;
		num_ent++;

		kmd_buf_info->used_bytes += total_used_bytes;
		kmd_buf_info->offset     += total_used_bytes;
		prepare->num_hw_update_entries = num_ent;
	}

	return rc;
}

static int cam_isp_packet_generic_blob_handler(void *user_data,
	uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
{
@@ -4197,7 +4293,6 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
		return -EINVAL;
	}

	CAM_DBG(CAM_ISP, "FS2: BLOB Type: %d", blob_type);
	switch (blob_type) {
	case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: {
		struct cam_isp_resource_hfr_config    *hfr_config;
@@ -4402,8 +4497,15 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
	}
		break;
	case CAM_ISP_GENERIC_BLOB_TYPE_IFE_CORE_CONFIG: {
		struct cam_isp_core_config *core_config =
			(struct cam_isp_core_config *)blob_data;
		struct cam_isp_core_config *core_config;

		if (blob_size < sizeof(struct cam_isp_core_config)) {
			CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
				blob_size, sizeof(struct cam_isp_core_config));
			return -EINVAL;
		}

		core_config = (struct cam_isp_core_config *)blob_data;

		rc = cam_isp_blob_core_cfg_update(blob_type, blob_info,
			core_config, prepare);
@@ -4411,6 +4513,52 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
			CAM_ERR(CAM_ISP, "Core cfg update fail: %d", rc);
	}
		break;
	case CAM_ISP_GENERIC_BLOB_TYPE_VFE_OUT_CONFIG: {
		struct cam_isp_vfe_out_config *vfe_out_config;

		if (blob_size < sizeof(struct cam_isp_vfe_out_config)) {
			CAM_ERR(CAM_ISP, "Invalid blob size %u",
				blob_size,
				sizeof(struct cam_isp_vfe_out_config));
			return -EINVAL;
		}

		vfe_out_config = (struct cam_isp_vfe_out_config *)blob_data;

		if (vfe_out_config->num_ports >= CAM_IFE_HW_OUT_RES_MAX) {
			CAM_ERR(CAM_ISP, "num_ports %u exceeds max ports %u",
				vfe_out_config->num_ports,
				CAM_IFE_HW_OUT_RES_MAX);
			return -EINVAL;
		}

		/* Check for integer overflow */
		if (sizeof(struct cam_isp_vfe_wm_config) > ((UINT_MAX -
			sizeof(struct cam_isp_vfe_out_config)) /
			(vfe_out_config->num_ports - 1))) {
			CAM_ERR(CAM_ISP,
				"Size exceeds limit ports:%u size per port:%lu",
				vfe_out_config->num_ports - 1,
				sizeof(struct cam_isp_vfe_wm_config));
			return -EINVAL;
		}

		if (blob_size < (sizeof(struct cam_isp_vfe_out_config) +
			(vfe_out_config->num_ports - 1) *
			sizeof(struct cam_isp_vfe_wm_config))) {
			CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
				blob_size, sizeof(uint32_t) * 2 +
				vfe_out_config->num_ports *
				sizeof(struct cam_isp_vfe_wm_config));
			return -EINVAL;
		}

		rc = cam_isp_blob_vfe_out_update(blob_type, blob_info,
			vfe_out_config, prepare);
		if (rc)
			CAM_ERR(CAM_ISP, "VFE out update failed rc: %d", rc);
	}
		break;

	default:
		CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type);
+2 −0
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ enum cam_isp_hw_cmd_type {
	CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
	CAM_ISP_HW_CMD_UBWC_UPDATE_V2,
	CAM_ISP_HW_CMD_CORE_CONFIG,
	CAM_ISP_HW_CMD_WM_CONFIG_UPDATE,
	CAM_ISP_HW_CMD_MAX,
};

@@ -227,6 +228,7 @@ struct cam_isp_hw_get_cmd_update {
		struct cam_ubwc_plane_cfg_v1         *ubwc_update;
		struct cam_fe_config                 *fe_update;
		struct cam_vfe_generic_ubwc_config   *ubwc_config;
		struct cam_isp_vfe_wm_config         *wm_config;
	};
};

+1 −0
Original line number Diff line number Diff line
@@ -592,6 +592,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
	case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ:
	case CAM_ISP_HW_CMD_UBWC_UPDATE:
	case CAM_ISP_HW_CMD_UBWC_UPDATE_V2:
	case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE:
		rc = core_info->vfe_bus->hw_ops.process_cmd(
			core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
			arg_size);
+90 −29
Original line number Diff line number Diff line
@@ -1230,9 +1230,6 @@ static int cam_vfe_bus_ver3_acquire_wm(
		rsrc_data->en_cfg = 0x1;
	} else if (rsrc_data->index == 20) {
		/* WM 20 stats BAF */
		rsrc_data->width = 0;
		rsrc_data->height = 0;
		rsrc_data->stride = 1;
		rsrc_data->en_cfg = (0x1 << 16) | 0x1;
	} else if (rsrc_data->index > 11 && rsrc_data->index < 20) {
		/* WM 12-19 stats */
@@ -2725,16 +2722,6 @@ static int cam_vfe_bus_ver3_update_ubwc_regs(
	CAM_DBG(CAM_ISP, "WM:%d packer cfg 0x%x",
		wm_data->index, reg_val_pair[*j-1]);

	if (wm_data->is_dual) {
		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
			wm_data->hw_regs->image_cfg_1, wm_data->offset);
	} else {
		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
			wm_data->hw_regs->image_cfg_1, wm_data->h_init);
		CAM_DBG(CAM_ISP, "WM:%d h_init 0x%x",
			wm_data->index, reg_val_pair[*j-1]);
	}

	CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
		ubwc_regs->meta_cfg, wm_data->ubwc_meta_cfg);
	CAM_DBG(CAM_ISP, "WM:%d meta stride 0x%x",
@@ -2821,12 +2808,13 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,

		wm_data = vfe_out_data->wm_res[i]->res_priv;
		ubwc_client = wm_data->hw_regs->ubwc_regs;
		/* update width register */
		val = cam_io_r_mb(wm_data->common_data->mem_base +
			wm_data->hw_regs->image_cfg_0);
		/* mask previously written width but preserve height */
		val = val & 0xFFFF0000;
		val |= wm_data->width;

		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
			wm_data->hw_regs->cfg, wm_data->en_cfg);
		CAM_DBG(CAM_ISP, "WM:%d en_cfg 0x%x",
			wm_data->index, reg_val_pair[j-1]);

		val = (wm_data->height << 16) | wm_data->width;
		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
			wm_data->hw_regs->image_cfg_0, val);
		CAM_DBG(CAM_ISP, "WM:%d image height and width 0x%x",
@@ -2849,7 +2837,7 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,
				wm_data->hw_regs->image_cfg_2,
				io_cfg->planes[i].plane_stride);
			wm_data->stride = val;
			CAM_DBG(CAM_ISP, "WM %d image stride 0x%x",
			CAM_DBG(CAM_ISP, "WM:%d image stride 0x%x",
				wm_data->index, reg_val_pair[j-1]);
		}

@@ -2870,7 +2858,7 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,
				reg_val_pair, &j,
				wm_data->hw_regs->ubwc_regs,
				update_buf->wm_update->image_buf[i]);
			CAM_DBG(CAM_ISP, "WM %d ubwc meta addr 0x%llx",
			CAM_DBG(CAM_ISP, "WM:%d ubwc meta addr 0x%llx",
				wm_data->index,
				update_buf->wm_update->image_buf[i]);
		}
@@ -2880,7 +2868,7 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,
			    io_cfg->planes[i].slice_height, 4096);
			frame_inc += io_cfg->planes[i].meta_size;
			CAM_DBG(CAM_ISP,
				"WM %d frm %d: ht: %d stride %d meta: %d",
				"WM:%d frm %d: ht: %d stride %d meta: %d",
				wm_data->index, frame_inc,
				io_cfg->planes[i].slice_height,
				io_cfg->planes[i].plane_stride,
@@ -2890,6 +2878,13 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,
				io_cfg->planes[i].slice_height;
		}

		if (!(wm_data->en_cfg & (0x3 << 16))) {
			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
				wm_data->hw_regs->image_cfg_1, wm_data->h_init);
			CAM_DBG(CAM_ISP, "WM:%d h_init 0x%x",
				wm_data->index, reg_val_pair[j-1]);
		}

		if ((!bus_priv->common_data.is_lite && wm_data->index > 22) ||
			bus_priv->common_data.is_lite)
			loop_size = wm_data->irq_subsample_period + 1;
@@ -2904,18 +2899,24 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args,
					update_buf->wm_update->image_buf[i] +
					io_cfg->planes[i].meta_size +
					k * frame_inc);
			else if (wm_data->en_cfg & (0x3 << 16))
				CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
					wm_data->hw_regs->image_addr,
					(update_buf->wm_update->image_buf[i] +
					wm_data->offset + k * frame_inc));
			else
				CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
					wm_data->hw_regs->image_addr,
					update_buf->wm_update->image_buf[i] +
					wm_data->offset + k * frame_inc);
			CAM_DBG(CAM_ISP, "WM %d image address 0x%x",
					(update_buf->wm_update->image_buf[i] +
					k * frame_inc));

			CAM_DBG(CAM_ISP, "WM:%d image address 0x%x",
				wm_data->index, reg_val_pair[j-1]);
		}

		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
			wm_data->hw_regs->frame_incr, frame_inc);
		CAM_DBG(CAM_ISP, "WM %d frame_inc %d",
		CAM_DBG(CAM_ISP, "WM:%d frame_inc %d",
			wm_data->index, reg_val_pair[j-1]);


@@ -3219,10 +3220,67 @@ static int cam_vfe_bus_ver3_update_stripe_cfg(void *priv, void *cmd_args,
		stripe_config = (struct cam_isp_dual_stripe_config  *)
			&stripe_args->dual_cfg->stripes[ports_plane_idx + i];
		wm_data->width = stripe_config->width;

		/*
		 * UMD sends buffer offset address as offset for clients
		 * programmed to operate in frame/index based mode and h_init
		 * value as offset for clients programmed to operate in line
		 * based mode.
		 */

		if (wm_data->en_cfg & (0x3 << 16))
			wm_data->offset = stripe_config->offset;
		CAM_DBG(CAM_ISP, "id:%x WM:%d width:0x%x offset:%x",
		else
			wm_data->h_init = stripe_config->offset;

		CAM_DBG(CAM_ISP, "id:%x WM:%d width:%d offset:0x%x h_init:%d",
			stripe_args->res->res_id, wm_data->index,
			wm_data->width, wm_data->offset);
			wm_data->width, wm_data->offset, wm_data->h_init);
	}

	return 0;
}

static int cam_vfe_bus_ver3_update_wm_config(
	void                                        *cmd_args)
{
	int                                          i;
	struct cam_isp_hw_get_cmd_update            *wm_config_update;
	struct cam_vfe_bus_ver3_vfe_out_data        *vfe_out_data = NULL;
	struct cam_vfe_bus_ver3_wm_resource_data    *wm_data = NULL;
	struct cam_isp_vfe_wm_config                *wm_config = NULL;

	if (!cmd_args) {
		CAM_ERR(CAM_ISP, "Invalid args");
		return -EINVAL;
	}

	wm_config_update = cmd_args;
	vfe_out_data = wm_config_update->res->res_priv;
	wm_config = wm_config_update->wm_config;

	if (!vfe_out_data || !vfe_out_data->cdm_util_ops || !wm_config) {
		CAM_ERR(CAM_ISP, "Invalid data");
		return -EINVAL;
	}

	for (i = 0; i < vfe_out_data->num_wm; i++) {
		wm_data = vfe_out_data->wm_res[i]->res_priv;

		if (wm_config->wm_mode > 0x2) {
			CAM_ERR(CAM_ISP, "Invalid wm_mode: 0x%x",
				wm_config->wm_mode);
			return -EINVAL;
		}

		wm_data->en_cfg = (wm_config->wm_mode << 16) | 0x1;
		wm_data->height = wm_config->height;
		wm_data->width  = wm_config->width;

		CAM_DBG(CAM_ISP,
			"WM:%d en_cfg:0x%x height:%d width:%d",
			wm_data->index, wm_data->en_cfg, wm_data->height,
			wm_data->width);
	}

	return 0;
@@ -3379,6 +3437,9 @@ static int cam_vfe_bus_ver3_process_cmd(
	case CAM_ISP_HW_CMD_UBWC_UPDATE_V2:
		rc = cam_vfe_bus_ver3_update_ubwc_config_v2(cmd_args);
		break;
	case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE:
		rc = cam_vfe_bus_ver3_update_wm_config(cmd_args);
		break;
	default:
		CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d",
			cmd_type);
+50 −0
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@
#define CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG           5
#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG_V2      6
#define CAM_ISP_GENERIC_BLOB_TYPE_IFE_CORE_CONFIG     7
#define CAM_ISP_GENERIC_BLOB_TYPE_VFE_OUT_CONFIG      8

#define CAM_ISP_VC_DT_CFG    4

@@ -610,6 +611,55 @@ struct cam_isp_acquire_hw_info {
	uint64_t                data;
};

/**
 * struct cam_isp_vfe_wm_config  -  VFE write master config per port
 *
 * @port_type        : Unique ID of output port
 * @wm_mode          : Write master mode
 *                     0x0 - Line based mode
 *                     0x1 - Frame based mode
 *                     0x2 - Index based mode, valid for BAF only
 * @h_init           : Horizontal starting coordinate in pixels. Must be a
 *                     multiple of 3 for TP10 format
 * @height           : Height in pixels
 * @width            : Width in pixels
 * @virtual_frame_en : Enabling virtual frame will prevent actual request from
 *                     being sent to NOC
 * @stride           : Write master stride
 * @offset           : Write master offset
 * @reserved_1       : Reserved field for Write master config
 * @reserved_2       : Reserved field for Write master config
 * @reserved_3       : Reserved field for Write master config
 * @reserved_4       : Reserved field for Write master config
 */
struct cam_isp_vfe_wm_config {
	uint32_t                      port_type;
	uint32_t                      wm_mode;
	uint32_t                      h_init;
	uint32_t                      height;
	uint32_t                      width;
	uint32_t                      virtual_frame_en;
	uint32_t                      stride;
	uint32_t                      offset;
	uint32_t                      reserved_1;
	uint32_t                      reserved_2;
	uint32_t                      reserved_3;
	uint32_t                      reserved_4;
};

/**
 * struct cam_isp_vfe_out_config  -  VFE write master config
 *
 * @num_ports      : Number of ports
 * @reserved       : Reserved field
 * @wm_config      : VFE out config
 */
struct cam_isp_vfe_out_config {
	uint32_t                      num_ports;
	uint32_t                      reserved;
	struct cam_isp_vfe_wm_config  wm_config[1];
};

#define CAM_ISP_ACQUIRE_COMMON_VER0         0x1000

#define CAM_ISP_ACQUIRE_COMMON_SIZE_VER0    0x0