diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index 5b33a6ecb0e1..72bc959b6126 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -16,6 +16,7 @@ #include "cam_tasklet_util.h" #include "cam_vfe_bus.h" #include "cam_vfe_bus_ver2.h" +#include "cam_vfe_soc.h" #include "cam_vfe_core.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" @@ -80,6 +81,12 @@ enum cam_vfe_bus_comp_grp_id { CAM_VFE_BUS_COMP_GROUP_ID_5 = 0x5, }; +struct cam_vfe_bus_error_info { + uint32_t bitmask; + uint32_t vfe_output; + char *error_description; +}; + struct cam_vfe_bus_ver2_common_data { uint32_t core_index; void __iomem *mem_base; @@ -99,6 +106,7 @@ struct cam_vfe_bus_ver2_common_data { uint32_t num_sec_out; uint32_t addr_no_sync; cam_hw_mgr_event_cb_func event_cb; + bool is_lite; bool hw_init; bool support_consumed_addr; bool disable_ubwc_comp; @@ -193,6 +201,7 @@ struct cam_vfe_bus_ver2_priv { struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS]; struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX]; struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; + uint32_t vfe_out_map_outtype[CAM_VFE_BUS_VER2_VFE_OUT_MAX]; struct list_head free_comp_grp; struct list_head free_dual_comp_grp; @@ -204,6 +213,138 @@ struct cam_vfe_bus_ver2_priv { uint32_t max_out_res; }; +static const struct cam_vfe_bus_error_info vfe_error_list[] = { + { + .bitmask = 0x80000000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP, + .error_description = "DISP C 1:1" + }, + { + .bitmask = 0x40000000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP, + .error_description = "DISP Y 1:1" + }, + { + .bitmask = 0x01000000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG, + .error_description = "STATS TINTLESS BG" + }, + { + .bitmask = 0x00800000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST, + .error_description = "STATS BHIST" + }, + { + .bitmask = 0x00400000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST, + .error_description = "STATS IHIST" + }, + { + .bitmask = 0x00200000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS, + .error_description = "STATS CS" + }, + { + .bitmask = 0x00100000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS, + .error_description = "STATS RS" + }, + { + .bitmask = 0x00080000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST, + .error_description = "STATS HDR BHIST" + }, + { + .bitmask = 0x00040000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF, + .error_description = "STATS BAF" + }, + { + .bitmask = 0x00020000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG, + .error_description = "STATS AWB BG" + }, + { + .bitmask = 0x00010000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE, + .error_description = "STATS HDR BE" + }, + { + .bitmask = 0x00004000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_2PD, + .error_description = "PD" + }, + { + .bitmask = 0x00002000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP, + .error_description = "PIXEL RAW DUMP" + }, + { + .bitmask = 0x00001000, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FULL, + .error_description = "VID C 1:1" + }, + { + .bitmask = 0x00000800, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FULL, + .error_description = "VID Y 1:1" + }, + { + .bitmask = 0x00000400, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FD, + .error_description = "FD C" + }, + { + .bitmask = 0x00000200, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_FD, + .error_description = "FD Y" + }, + { + .bitmask = 0x00000020, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI3, + .error_description = "Full RDI 3" + }, + { + .bitmask = 0x00000010, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI2, + .error_description = "Full RDI 2" + }, + { + .bitmask = 0x00000008, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI1, + .error_description = "Full RDI 1" + }, + { + .bitmask = 0x00000004, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI0, + .error_description = "Full RDI 0" + }, +}; + +static const struct cam_vfe_bus_error_info vfe_lite_error_list[] = { + { + .bitmask = 0x04, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI0, + .error_description = "Lite RDI 0" + }, + { + .bitmask = 0x08, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI1, + .error_description = "Lite RDI 1" + }, + { + .bitmask = 0x10, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI2, + .error_description = "Lite RDI 2" + }, + { + .bitmask = 0x20, + .vfe_output = CAM_VFE_BUS_VER2_VFE_OUT_RDI3, + .error_description = "Lite RDI 3" + } +}; + + static int cam_vfe_bus_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); @@ -481,6 +622,22 @@ static enum cam_vfe_bus_ver2_vfe_out_type } } +static enum cam_vfe_bus_ver2_vfe_out_type + cam_vfe_bus_ver2_get_out_res_id_and_index( + struct cam_vfe_bus_ver2_priv *bus_priv, + uint32_t res_type, uint32_t *index) +{ + uint32_t vfe_out_type; + + vfe_out_type = cam_vfe_bus_get_out_res_id(res_type); + if (vfe_out_type == CAM_VFE_BUS_VER2_VFE_OUT_MAX) + *index = CAM_VFE_BUS_VER2_VFE_OUT_MAX; + else + *index = bus_priv->vfe_out_map_outtype[vfe_out_type]; + + return vfe_out_type; +} + static int cam_vfe_bus_get_num_wm( enum cam_vfe_bus_ver2_vfe_out_type res_type, uint32_t format) @@ -1440,6 +1597,94 @@ static int cam_vfe_bus_handle_wm_done_bottom_half(void *handler_priv, return rc; } +static int cam_vfe_bus_ver2_print_dimensions( + uint32_t res_id, + struct cam_vfe_bus_ver2_priv *bus_priv) +{ + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL; + struct cam_vfe_bus_ver2_common_data *common_data = NULL; + int i; + uint32_t addr_status0, addr_status1; + enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id = + CAM_VFE_BUS_VER2_VFE_OUT_MAX; + uint32_t outmap_index = CAM_VFE_BUS_VER2_VFE_OUT_MAX; + + if (!bus_priv) { + CAM_ERR(CAM_ISP, "Invalid bus private data, res_id: %d", + res_id); + return -EINVAL; + } + + vfe_out_res_id = cam_vfe_bus_ver2_get_out_res_id_and_index(bus_priv, + res_id, &outmap_index); + + if ((vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX) || + (outmap_index >= bus_priv->num_out)) { + CAM_WARN_RATE_LIMIT(CAM_ISP, + "target does not support req res id :0x%x outtype:%d index:%d", + res_id, + vfe_out_res_id, outmap_index); + return -EINVAL; + } + + rsrc_node = &bus_priv->vfe_out[outmap_index]; + rsrc_data = rsrc_node->res_priv; + if (!rsrc_data) { + CAM_ERR(CAM_ISP, "VFE out data is null, res_id: %d", + vfe_out_res_id); + return -EINVAL; + } + + for (i = 0; i < rsrc_data->num_wm; i++) { + wm_data = rsrc_data->wm_res[i]->res_priv; + common_data = rsrc_data->common_data; + addr_status0 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->status0); + addr_status1 = cam_io_r_mb(common_data->mem_base + + wm_data->hw_regs->status1); + + CAM_INFO(CAM_ISP, + "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", + wm_data->common_data->core_index, wm_data->index, + wm_data->width, + wm_data->height, + wm_data->stride, wm_data->h_init, + wm_data->en_cfg, + wm_data->acquired_width, + wm_data->acquired_height); + CAM_INFO(CAM_ISP, + "hw:%d WM:%d last consumed address:0x%x last frame addr:0x%x", + common_data->hw_intf->hw_idx, + wm_data->index, + addr_status0, + addr_status1); + } + return 0; +} + +static void cam_vfe_print_violations( + char *error_type, + const struct cam_vfe_bus_error_info *error_list, + uint32_t num_errors, + uint32_t status, + struct cam_vfe_bus_ver2_priv *bus_priv) +{ + int i; + + for (i = 0; i < num_errors; i++) { + if (status & error_list[i].bitmask) { + CAM_INFO(CAM_ISP, "%s: %s violation", + error_list[i].error_description, + error_type); + if (bus_priv != NULL) + cam_vfe_bus_ver2_print_dimensions( + error_list[i].vfe_output, + bus_priv); + } + } +} static int cam_vfe_bus_err_bottom_half(void *handler_priv, void *evt_payload_priv) @@ -1448,7 +1693,10 @@ static int cam_vfe_bus_err_bottom_half(void *handler_priv, struct cam_vfe_bus_ver2_priv *bus_priv = handler_priv; struct cam_vfe_bus_ver2_common_data *common_data; struct cam_isp_hw_event_info evt_info; + const struct cam_vfe_bus_error_info *error_list = NULL; uint32_t val = 0; + uint32_t error_list_size = 0; + uint32_t status = 0; if (!handler_priv || !evt_payload_priv) return -EINVAL; @@ -1459,77 +1707,76 @@ static int cam_vfe_bus_err_bottom_half(void *handler_priv, val = evt_payload->debug_status_0; CAM_ERR(CAM_ISP, "Bus Violation: debug_status_0 = 0x%x", val); - if (val & 0x01) + error_list = common_data->is_lite ? + vfe_lite_error_list : vfe_error_list; + error_list_size = common_data->is_lite ? + ARRAY_SIZE(vfe_lite_error_list) : ARRAY_SIZE(vfe_error_list); + + if (val & 0x00000004) CAM_INFO(CAM_ISP, "RDI 0 violation"); - if (val & 0x02) + if (val & 0x00000008) CAM_INFO(CAM_ISP, "RDI 1 violation"); - if (val & 0x04) + if (val & 0x00000010) CAM_INFO(CAM_ISP, "RDI 2 violation"); - if (val & 0x08) - CAM_INFO(CAM_ISP, "VID Y 1:1 UBWC violation"); + if (val & 0x00000020) + CAM_INFO(CAM_ISP, "RDI 3 violation"); - if (val & 0x010) - CAM_INFO(CAM_ISP, "VID C 1:1 UBWC violation"); - - if (val & 0x020) - CAM_INFO(CAM_ISP, "VID YC 4:1 violation"); - - if (val & 0x040) - CAM_INFO(CAM_ISP, "VID YC 16:1 violation"); - - if (val & 0x080) + if (val & 0x00000200) CAM_INFO(CAM_ISP, "FD Y violation"); - if (val & 0x0100) + if (val & 0x00000400) CAM_INFO(CAM_ISP, "FD C violation"); - if (val & 0x0200) + if (val & 0x00001000) + CAM_INFO(CAM_ISP, "VID C 1:1 UBWC violation"); + + if (val & 0x00000800) + CAM_INFO(CAM_ISP, "VID Y 1:1 UBWC violation"); + + if (val & 0x00002000) CAM_INFO(CAM_ISP, "RAW DUMP violation"); - if (val & 0x0400) + if (val & 0x00004000) CAM_INFO(CAM_ISP, "PDAF violation"); - if (val & 0x0800) + if (val & 0x00010000) CAM_INFO(CAM_ISP, "STATs HDR BE violation"); - if (val & 0x01000) - CAM_INFO(CAM_ISP, "STATs HDR BHIST violation"); - - if (val & 0x02000) - CAM_INFO(CAM_ISP, "STATs TINTLESS BG violation"); - - if (val & 0x04000) - CAM_INFO(CAM_ISP, "STATs BF violation"); - - if (val & 0x08000) + if (val & 0x00020000) CAM_INFO(CAM_ISP, "STATs AWB BG UBWC violation"); - if (val & 0x010000) - CAM_INFO(CAM_ISP, "STATs BHIST violation"); + if (val & 0x00040000) + CAM_INFO(CAM_ISP, "STATs BF violation"); - if (val & 0x020000) + if (val & 0x00080000) + CAM_INFO(CAM_ISP, "STATs HDR BHIST violation"); + + if (val & 0x00100000) CAM_INFO(CAM_ISP, "STATs RS violation"); - if (val & 0x040000) + if (val & 0x00200000) CAM_INFO(CAM_ISP, "STATs CS violation"); - if (val & 0x080000) + if (val & 0x00400000) CAM_INFO(CAM_ISP, "STATs IHIST violation"); - if (val & 0x0100000) + if (val & 0x00800000) + CAM_INFO(CAM_ISP, "STATs BHIST violation"); + + if (val & 0x01000000) + CAM_INFO(CAM_ISP, "STATs TINTLESS BG violation"); + + if (val & 0x40000000) CAM_INFO(CAM_ISP, "DISP Y 1:1 UBWC violation"); - if (val & 0x0200000) + if (val & 0x80000000) CAM_INFO(CAM_ISP, "DISP C 1:1 UBWC violation"); - if (val & 0x0400000) - CAM_INFO(CAM_ISP, "DISP YC 4:1 violation"); - - if (val & 0x0800000) - CAM_INFO(CAM_ISP, "DISP YC 16:1 violation"); + cam_vfe_print_violations("Error", error_list, + error_list_size, status, bus_priv); cam_vfe_bus_put_evt_payload(common_data, &evt_payload); @@ -2550,7 +2797,8 @@ static int cam_vfe_bus_init_vfe_out_resource(uint32_t index, return -EINVAL; } - vfe_out = &ver2_bus_priv->vfe_out[vfe_out_type]; + ver2_bus_priv->vfe_out_map_outtype[vfe_out_type] = index; + vfe_out = &ver2_bus_priv->vfe_out[index]; if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE || vfe_out->res_priv) { CAM_ERR(CAM_ISP, @@ -3830,6 +4078,7 @@ int cam_vfe_bus_ver2_init( struct cam_vfe_bus_ver2_priv *bus_priv = NULL; struct cam_vfe_bus *vfe_bus_local; struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info; + struct cam_vfe_soc_private *soc_private = NULL; CAM_DBG(CAM_ISP, "Enter"); @@ -3842,6 +4091,13 @@ int cam_vfe_bus_ver2_init( goto end; } + soc_private = soc_info->soc_private; + if (!soc_private) { + CAM_ERR(CAM_ISP, "Invalid soc_private"); + rc = -ENODEV; + goto end; + } + vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL); if (!vfe_bus_local) { CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus"); @@ -3876,6 +4132,7 @@ int cam_vfe_bus_ver2_init( bus_priv->common_data.support_consumed_addr = ver2_hw_info->support_consumed_addr; bus_priv->common_data.disable_ubwc_comp = false; + bus_priv->common_data.is_lite = soc_private->is_ife_lite; mutex_init(&bus_priv->common_data.bus_mutex); @@ -3909,6 +4166,10 @@ int cam_vfe_bus_ver2_init( } } + for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) + bus_priv->vfe_out_map_outtype[i] = + CAM_VFE_BUS_VER2_VFE_OUT_MAX; + for (i = 0; i < bus_priv->num_out; i++) { rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info);