msm: camera: isp: Buffer alignment support for TFE WM

This change is added to support buffer alignment for TFE
WM in x and y axis. This change is required in SHDR usecase to
align short exposure frame with long exposure frame.

CRs-Fixed: 3538642
Change-Id: I9a3d35d0884bfbd6f62034b207e5784fdf2f7430
Signed-off-by: Ayush Kumar <quic_ayushkr@quicinc.com>
This commit is contained in:
Ayush Kumar
2023-06-08 18:07:46 +05:30
committed by Alok Chauhan
parent fe4bd2e6a1
commit bfbfc5d3d4
6 changed files with 184 additions and 10 deletions

View File

@@ -2008,12 +2008,15 @@ static int __cam_isp_ctx_handle_buf_done_for_request(
}
if (!req_isp->bubble_detected) {
handle_type = __cam_isp_resource_handle_id_to_type(
ctx_isp->isp_device_type,
req_isp->fence_map_out[j].resource_handle);
CAM_DBG(CAM_ISP,
"Sync with success: req %lld res 0x%x fd 0x%x, ctx %u link: 0x%x",
"Sync with success: req %lld res 0x%x fd 0x%x, ctx %u link: 0x%x port %s",
req->request_id,
req_isp->fence_map_out[j].resource_handle,
req_isp->fence_map_out[j].sync_id,
ctx->ctx_id, ctx->link_hdl);
ctx->ctx_id, ctx->link_hdl, handle_type);
cam_smmu_buffer_tracker_buffer_putref(
req_isp->fence_map_out[j].buffer_tracker);

View File

@@ -40,7 +40,6 @@
#define CAM_TFE_SAFE_ENABLE 1
#define SMMU_SE_TFE 0
static struct cam_tfe_hw_mgr g_tfe_hw_mgr;
static int cam_tfe_hw_mgr_event_handler(
@@ -4091,6 +4090,56 @@ static int cam_tfe_mgr_release_hw(void *hw_mgr_priv,
return rc;
}
static int cam_isp_tfe_blob_buffer_alignment_update(
uint32_t blob_type,
struct cam_isp_generic_blob_info *blob_info,
struct cam_isp_tfe_alignment_resource_info *alignment_info,
struct cam_hw_prepare_update_args *prepare)
{
struct cam_isp_tfe_alignment_offset_config *alignment_port_cfg;
struct cam_isp_resource_node *res;
struct cam_isp_hw_get_cmd_update cmd_update;
struct cam_tfe_hw_mgr_ctx *ctx = NULL;
struct cam_isp_hw_mgr_res *hw_mgr_res;
struct cam_hw_intf *hw_intf;
uint32_t res_id_out, i;
int rc = 0;
ctx = prepare->ctxt_to_hw_map;
for (i = 0; i < alignment_info->num_ports; i++) {
alignment_port_cfg = &alignment_info->port_alignment_cfg[i];
res_id_out = alignment_port_cfg->resource_type & 0xFF;
if (res_id_out >= CAM_TFE_HW_OUT_RES_MAX) {
CAM_ERR(CAM_ISP, "invalid out restype:%x ctx %d",
alignment_port_cfg->resource_type, ctx->ctx_index);
return -EINVAL;
}
hw_mgr_res = &ctx->res_list_tfe_out[res_id_out];
res = hw_mgr_res->hw_res[i];
hw_intf = res->hw_intf;
if (hw_intf && hw_intf->hw_ops.process_cmd) {
cmd_update.res = res;
cmd_update.data = alignment_port_cfg;
cmd_update.cmd_type = CAM_ISP_HW_CMD_BUFFER_ALIGNMENT_UPDATE;
rc = hw_intf->hw_ops.process_cmd(
hw_intf->hw_priv,
CAM_ISP_HW_CMD_BUFFER_ALIGNMENT_UPDATE,
&cmd_update,
sizeof(struct cam_isp_hw_get_cmd_update));
if (rc)
CAM_ERR(CAM_ISP, "Ctx %d Buffer alignment Update failed",
ctx->ctx_index);
} else {
CAM_ERR(CAM_ISP, "NULL hw_intf! ctx %d", ctx->ctx_index);
}
}
return rc;
}
static int cam_isp_tfe_blob_hfr_update(
uint32_t blob_type,
struct cam_isp_generic_blob_info *blob_info,
@@ -4774,6 +4823,50 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data,
prepare->packet->header.request_id, rc, tfe_mgr_ctx->ctx_index);
}
break;
case CAM_ISP_TFE_GENERIC_BLOB_TYPE_ALIGNMENT_OFFSET_INFO: {
struct cam_isp_tfe_alignment_resource_info *alignment_info =
(struct cam_isp_tfe_alignment_resource_info *)blob_data;
if (tfe_mgr_ctx->is_dual) {
CAM_ERR(CAM_ISP, "Alignment blob can't be use in dual mode ctx %d",
tfe_mgr_ctx->ctx_index);
return -EINVAL;
}
if (blob_size < sizeof(struct cam_isp_tfe_alignment_resource_info)) {
CAM_ERR(CAM_ISP,
"Invalid alignment blob size %u expected %u ctx %d",
blob_size, sizeof(struct cam_isp_tfe_alignment_resource_info),
tfe_mgr_ctx->ctx_index);
return -EINVAL;
}
if (alignment_info->num_ports > CAM_ISP_TFE_OUT_RES_MAX) {
CAM_ERR(CAM_ISP, "Invalid num_ports %u in alignment config",
alignment_info->num_ports);
return -EINVAL;
}
if ((alignment_info->num_ports != 0) && (blob_size <
(sizeof(struct cam_isp_tfe_alignment_resource_info) +
(alignment_info->num_ports - 1) *
sizeof(struct cam_isp_tfe_alignment_offset_config)))) {
CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
blob_size,
sizeof(struct cam_isp_tfe_alignment_resource_info) +
(alignment_info->num_ports - 1) *
sizeof(struct cam_isp_tfe_alignment_offset_config));
return -EINVAL;
}
rc = cam_isp_tfe_blob_buffer_alignment_update(blob_type, blob_info,
alignment_info, prepare);
if (rc)
CAM_ERR(CAM_ISP,
"Alignment buffer update failed for req %lld rc %d ctx %d",
prepare->packet->header.request_id, rc, tfe_mgr_ctx->ctx_index);
}
break;
default:
CAM_WARN(CAM_ISP, "Invalid blob type %d ctx %d", blob_type,
tfe_mgr_ctx->ctx_index);

View File

@@ -259,6 +259,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE,
CAM_ISP_HW_CMD_SET_SYNC_HW_IDX,
CAM_ISP_HW_CMD_BUS_WM_DISABLE,
CAM_ISP_HW_CMD_BUFFER_ALIGNMENT_UPDATE,
CAM_ISP_HW_CMD_MAX,
};

View File

@@ -111,6 +111,9 @@ struct cam_tfe_bus_wm_resource_data {
uint32_t acquired_width;
uint32_t acquired_height;
uint32_t acquired_stride;
uint32_t buffer_offset;
bool is_buffer_aligned;
bool limiter_blob_status;
};
@@ -2293,6 +2296,7 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args,
(wm_data->mode == CAM_ISP_TFE_WM_LINE_BASED_MODE)) ||
(wm_data->out_id == CAM_TFE_BUS_TFE_OUT_PDAF) ||
(wm_data->index >= 11 && wm_data->index <= 15)) {
CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
wm_data->hw_regs->image_cfg_2,
io_cfg->planes[i].plane_stride);
@@ -2304,6 +2308,9 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args,
frame_inc = io_cfg->planes[i].plane_stride *
io_cfg->planes[i].slice_height;
if (wm_data->is_buffer_aligned)
update_buf->wm_update->image_buf[i] += wm_data->buffer_offset;
CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
wm_data->hw_regs->image_addr,
update_buf->wm_update->image_buf[i]);
@@ -2351,6 +2358,38 @@ static int cam_tfe_bus_update_wm(void *priv, void *cmd_args,
return 0;
}
static int cam_tfe_buffer_alignment_update(void *priv, void *cmd_args,
uint32_t arg_size)
{
struct cam_tfe_bus_priv *bus_priv;
struct cam_isp_hw_get_cmd_update *alignment_cmd;
struct cam_tfe_bus_tfe_out_data *tfe_out_data = NULL;
struct cam_tfe_bus_wm_resource_data *wm_data = NULL;
struct cam_isp_tfe_alignment_offset_config *alignment_port_cfg = NULL;
uint32_t i, rc = 0;
bus_priv = (struct cam_tfe_bus_priv *) priv;
alignment_cmd = (struct cam_isp_hw_get_cmd_update *) cmd_args;
alignment_port_cfg = (struct cam_isp_tfe_alignment_offset_config *) alignment_cmd->data;
tfe_out_data = (struct cam_tfe_bus_tfe_out_data *) alignment_cmd->res->res_priv;
if (!tfe_out_data) {
CAM_ERR(CAM_ISP, "Failed! invalid data");
return -EINVAL;
}
for (i = 0; i < tfe_out_data->num_wm; i++) {
wm_data = tfe_out_data->wm_res[i]->res_priv;
wm_data->is_buffer_aligned = true;
wm_data->offset = alignment_port_cfg->x_offset;
wm_data->buffer_offset = alignment_port_cfg->y_offset;
CAM_DBG(CAM_ISP, "wm %d X-Offset %x Y-Offset %x", wm_data->index,
wm_data->offset, wm_data->buffer_offset);
}
return rc;
}
static int cam_tfe_bus_update_hfr(void *priv, void *cmd_args,
uint32_t arg_size)
@@ -2858,6 +2897,9 @@ static int cam_tfe_bus_process_cmd(void *priv,
case CAM_ISP_HW_NOTIFY_OVERFLOW:
rc = cam_tfe_bus_check_overflow(priv, cmd_args, arg_size);
break;
case CAM_ISP_HW_CMD_BUFFER_ALIGNMENT_UPDATE:
rc = cam_tfe_buffer_alignment_update(priv, cmd_args, arg_size);
break;
default:
CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d",
cmd_type);

View File

@@ -3441,6 +3441,7 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type,
case CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG:
case CAM_ISP_HW_CMD_GET_LAST_CONSUMED_ADDR:
case CAM_ISP_HW_CMD_BUS_WM_DISABLE:
case CAM_ISP_HW_CMD_BUFFER_ALIGNMENT_UPDATE:
rc = core_info->tfe_bus->hw_ops.process_cmd(
core_info->tfe_bus->bus_priv, cmd_type, cmd_args,
arg_size);

View File

@@ -73,8 +73,9 @@
#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_CONFIG_V2 2
#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 3
#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_INIT_CONFIG 4
#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_LIMITER_CFG 16
#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH 15
#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_LIMITER_CFG 16
#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_ALIGNMENT_OFFSET_INFO 17
/* DSP mode */
#define CAM_ISP_TFE_DSP_MODE_NONE 0
@@ -528,6 +529,39 @@ struct cam_isp_tfe_out_rsrc_bw_limiter_config {
struct cam_isp_tfe_wm_bw_limiter_config bw_limiter_config[1];
};
/**
* struct cam_isp_tfe_alignment_offset_config - ISP TFE buffer alignment config
*
* @resource_type: Resourse type
* @x_offset: Offset of the buffer from x-axies
* @y_offset: Offset of the buffer from y-axies
* @width: Width of out resource
* @height: Height of out resource
* @stride: Stride of out resource
*
*/
struct cam_isp_tfe_alignment_offset_config {
__u32 resource_type;
__u32 x_offset;
__u32 y_offset;
__u32 width;
__u32 height;
__u32 stride;
} __attribute__((packed));
/**
* struct cam_isp_tfe_alignment_resource_info - ISP TFE Resource Alignment
*
* @version: Alignment api version
* @num_ports: Number of ports
* @port_alignment_cfg: Buffer alignment for each IO port
*/
struct cam_isp_tfe_alignment_resource_info {
__u32 version;
__u32 num_ports;
struct cam_isp_tfe_alignment_offset_config port_alignment_cfg[1];
} __attribute__((packed));
#define CAM_TFE_ACQUIRE_COMMON_VER0 0x1000
#define CAM_TFE_ACQUIRE_COMMON_SIZE_VER0 0x0