Loading drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +129 −64 Original line number Diff line number Diff line Loading @@ -38,6 +38,112 @@ static struct cam_jpeg_hw_mgr g_jpeg_hw_mgr; static int32_t cam_jpeg_hw_mgr_cb(uint32_t irq_status, int32_t result_size, void *data); static int cam_jpeg_mgr_process_cmd(void *priv, void *data); static int cam_jpeg_insert_cdm_change_base( struct cam_hw_config_args *config_args, struct cam_jpeg_hw_ctx_data *ctx_data, struct cam_jpeg_hw_mgr *hw_mgr); static int cam_jpeg_process_next_hw_update(void *priv, void *data) { int rc; int i = 0; struct cam_jpeg_hw_mgr *hw_mgr = priv; struct cam_hw_update_entry *cmd; struct cam_cdm_bl_request *cdm_cmd; struct cam_hw_config_args *config_args = NULL; struct cam_jpeg_hw_ctx_data *ctx_data = NULL; uint32_t dev_type; struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; uint32_t cdm_cfg_to_insert = 0; if (!data || !priv) { CAM_ERR(CAM_JPEG, "Invalid data"); return -EINVAL; } ctx_data = (struct cam_jpeg_hw_ctx_data *)data; dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0]; config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args; if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { CAM_ERR(CAM_JPEG, "op reset null "); rc = -EFAULT; goto end_error; } rc = hw_mgr->devices[dev_type][0]->hw_ops.reset( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); goto end_error; } cdm_cmd = ctx_data->cdm_cmd; cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; cdm_cmd->flag = false; cdm_cmd->userdata = NULL; cdm_cmd->cookie = 0; cdm_cmd->cmd_arrary_count = 0; /* insert cdm chage base cmd */ rc = cam_jpeg_insert_cdm_change_base(config_args, ctx_data, hw_mgr); if (rc) { CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); goto end_error; } /* insert next cdm payload at index */ /* for enc or dma 1st pass at index 1 */ /* for dma 2nd pass at index 2, for 3rd at 4 */ if (p_cfg_req->num_hw_entry_processed == 0) cdm_cfg_to_insert = CAM_JPEG_CFG; else cdm_cfg_to_insert = p_cfg_req->num_hw_entry_processed + 2; CAM_DBG(CAM_JPEG, "processed %d total %d using cfg entry %d for %pK", p_cfg_req->num_hw_entry_processed, config_args->num_hw_update_entries, cdm_cfg_to_insert, p_cfg_req); cmd = (config_args->hw_update_entries + cdm_cfg_to_insert); cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle = cmd->handle; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = cmd->offset; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = cmd->len; CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", i, cmd->handle, cmd->offset, cmd->len); cdm_cmd->cmd_arrary_count++; rc = cam_cdm_submit_bls( hw_mgr->cdm_info[dev_type][0].cdm_handle, cdm_cmd); if (rc) { CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); goto end_error; } if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { CAM_ERR(CAM_JPEG, "op start null "); rc = -EINVAL; goto end_error; } rc = hw_mgr->devices[dev_type][0]->hw_ops.start( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); goto end_error; } return 0; end_error: return rc; } static int cam_jpeg_mgr_process_irq(void *priv, void *data) { Loading Loading @@ -85,6 +191,21 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) return -EINVAL; } p_cfg_req->num_hw_entry_processed++; CAM_DBG(CAM_JPEG, "hw entry processed %d", p_cfg_req->num_hw_entry_processed); if ((task_data->result_size > 0) && (p_cfg_req->num_hw_entry_processed < p_cfg_req->hw_cfg_args.num_hw_update_entries - 2)) { /* start processing next entry before marking device free */ rc = cam_jpeg_process_next_hw_update(priv, ctx_data); if (!rc) { mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); return 0; } } irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb; irq_cb.data = NULL; irq_cb.b_set_cb = false; Loading Loading @@ -281,7 +402,9 @@ static int cam_jpeg_insert_cdm_change_base( if (config_args->hw_update_entries[CAM_JPEG_CHBASE].offset >= ch_base_len) { CAM_ERR(CAM_JPEG, "Not enough buf"); CAM_ERR(CAM_JPEG, "Not enough buf offset %d len %d", config_args->hw_update_entries[CAM_JPEG_CHBASE].offset, ch_base_len); return -EINVAL; } CAM_DBG(CAM_JPEG, "iova %pK len %zu offset %d", Loading Loading @@ -321,8 +444,6 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) int rc; int i = 0; struct cam_jpeg_hw_mgr *hw_mgr = priv; struct cam_hw_update_entry *cmd; struct cam_cdm_bl_request *cdm_cmd; struct cam_hw_config_args *config_args = NULL; struct cam_jpeg_hw_ctx_data *ctx_data = NULL; uintptr_t request_id = 0; Loading Loading @@ -424,71 +545,13 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) goto end_callcb; } if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { CAM_ERR(CAM_JPEG, "op reset null "); rc = -EFAULT; goto end_callcb; } rc = hw_mgr->devices[dev_type][0]->hw_ops.reset( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); goto end_callcb; } cdm_cmd = ctx_data->cdm_cmd; cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; cdm_cmd->flag = false; cdm_cmd->userdata = NULL; cdm_cmd->cookie = 0; cdm_cmd->cmd_arrary_count = 0; cdm_cmd->gen_irq_arb = false; rc = cam_jpeg_insert_cdm_change_base(config_args, ctx_data, hw_mgr); if (rc) { CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); goto end_callcb; } CAM_DBG(CAM_JPEG, "num hw up %d", config_args->num_hw_update_entries); for (i = CAM_JPEG_CFG; i < (config_args->num_hw_update_entries - 1); i++) { cmd = (config_args->hw_update_entries + i); cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle = cmd->handle; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = cmd->offset; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = cmd->len; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].arbitrate = false; CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", i, cmd->handle, cmd->offset, cmd->len); cdm_cmd->cmd_arrary_count++; } rc = cam_cdm_submit_bls( hw_mgr->cdm_info[dev_type][0].cdm_handle, cdm_cmd); /* insert one of the cdm payloads */ rc = cam_jpeg_process_next_hw_update(priv, ctx_data); if (rc) { CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); CAM_ERR(CAM_JPEG, "next hw update failed %d", rc); goto end_callcb; } if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { CAM_ERR(CAM_JPEG, "op start null "); rc = -EINVAL; goto end_callcb; } rc = hw_mgr->devices[dev_type][0]->hw_ops.start( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_JPEG, "Failed to start hw %d", rc); goto end_callcb; } p_cfg_req->submit_timestamp = ktime_get(); mutex_unlock(&hw_mgr->hw_mgr_mutex); Loading Loading @@ -567,6 +630,7 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) request_id = (uintptr_t)config_args->priv; p_cfg_req->req_id = request_id; p_cfg_req->num_hw_entry_processed = 0; hw_update_entries = config_args->hw_update_entries; CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %lld %zd", ctx_data, request_id, (uintptr_t)config_args->priv); Loading Loading @@ -781,6 +845,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence); } CAM_DBG(CAM_JPEG, "received num cmd buf %d", packet->num_cmd_buf); j = prepare_args->num_hw_update_entries; rc = cam_packet_util_get_kmd_buffer(packet, &kmd_buf); Loading drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +2 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ struct cam_jpeg_hw_cdm_info_t { * @dev_type: Dev type for cfg request * @req_id: Request Id * @submit_timestamp: Timestamp of submitting request * @num_hw_entry_processed: Cdm payloads already processed */ struct cam_jpeg_hw_cfg_req { struct list_head list; Loading @@ -83,6 +84,7 @@ struct cam_jpeg_hw_cfg_req { uint32_t dev_type; uintptr_t req_id; ktime_t submit_timestamp; uint32_t num_hw_entry_processed; }; /** Loading drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h 0 → 100644 +46 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H #define CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H #define CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE (1 << 0) #define CAM_JPEGDMA_HW_IRQ_STATUS_RD_BUF_DONE (1 << 1) #define CAM_JPEGDMA_HW_IRQ_STATUS_WR_BUF_DONE (1 << 5) #define CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT (1 << 9) #define CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE (1 << 10) #define CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE \ CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE #define CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK \ CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { .reg_offset = { .hw_version = 0x0, .int_clr = 0x14, .int_status = 0x10, .int_mask = 0x0C, .hw_cmd = 0x1C, .reset_cmd = 0x08, .encode_size = 0x180, }, .reg_val = { .int_clr_clearall = 0xFFFFFFFF, .int_mask_disable_all = 0x00000000, .int_mask_enable_all = 0xFFFFFFFF, .hw_cmd_start = 0x00000001, .reset_cmd = 0x32083, .hw_cmd_stop = 0x00000004, }, .int_status = { .framedone = CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE, .resetdone = CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK, .iserror = 0x0, .stopdone = CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT, } }; #endif /* CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H */ drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c +233 −8 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/of.h> Loading @@ -23,6 +23,15 @@ #include "cam_cpas_api.h" #include "cam_debug_util.h" #define CAM_JPEG_HW_IRQ_IS_FRAME_DONE(jpeg_irq_status, hi) \ ((jpeg_irq_status) & (hi)->int_status.framedone) #define CAM_JPEG_HW_IRQ_IS_RESET_ACK(jpeg_irq_status, hi) \ ((jpeg_irq_status) & (hi)->int_status.resetdone) #define CAM_JPEG_HW_IRQ_IS_STOP_DONE(jpeg_irq_status, hi) \ ((jpeg_irq_status) & (hi)->int_status.stopdone) #define CAM_JPEG_DMA_RESET_TIMEOUT msecs_to_jiffies(500) int cam_jpeg_dma_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size) { Loading Loading @@ -132,7 +141,7 @@ int cam_jpeg_dma_deinit_hw(void *device_priv, rc = cam_jpeg_dma_disable_soc_resources(soc_info); if (rc) CAM_ERR(CAM_JPEG, "soc enable failed %d", rc); CAM_ERR(CAM_JPEG, "soc disable failed %d", rc); rc = cam_cpas_stop(core_info->cpas_handle); if (rc) Loading @@ -143,6 +152,226 @@ int cam_jpeg_dma_deinit_hw(void *device_priv, return 0; } irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data) { struct cam_hw_info *jpeg_dma_dev = data; struct cam_jpeg_dma_device_core_info *core_info = NULL; uint32_t irq_status = 0; struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; void __iomem *mem_base; if (!jpeg_dma_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); return IRQ_HANDLED; } soc_info = &jpeg_dma_dev->soc_info; core_info = (struct cam_jpeg_dma_device_core_info *) jpeg_dma_dev->core_info; hw_info = core_info->jpeg_dma_hw_info; mem_base = soc_info->reg_map[0].mem_base; irq_status = cam_io_r_mb(mem_base + core_info->jpeg_dma_hw_info->reg_offset.int_status); cam_io_w_mb(irq_status, soc_info->reg_map[0].mem_base + core_info->jpeg_dma_hw_info->reg_offset.int_clr); CAM_DBG(CAM_JPEG, "irq_num %d irq_status = %x , core_state %d", irq_num, irq_status, core_info->core_state); if (CAM_JPEG_HW_IRQ_IS_FRAME_DONE(irq_status, hw_info)) { spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_READY) { core_info->result_size = 1; CAM_DBG(CAM_JPEG, "result_size %d", core_info->result_size); core_info->core_state = CAM_JPEG_DMA_CORE_RESETTING_ON_DONE; cam_io_w_mb(hw_info->reg_val.reset_cmd, mem_base + hw_info->reg_offset.reset_cmd); } else { CAM_WARN(CAM_JPEG, "unexpected frame done "); core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; } spin_unlock(&jpeg_dma_dev->hw_lock); } if (CAM_JPEG_HW_IRQ_IS_RESET_ACK(irq_status, hw_info)) { spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING) { core_info->core_state = CAM_JPEG_DMA_CORE_READY; core_info->result_size = -1; complete(&jpeg_dma_dev->hw_complete); } else if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING_ON_DONE) { if (core_info->irq_cb.jpeg_hw_mgr_cb) { core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, core_info->result_size, core_info->irq_cb.data); } else { CAM_WARN(CAM_JPEG, "unexpected frame done"); } core_info->result_size = -1; core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; } else { CAM_ERR(CAM_JPEG, "unexpected reset irq"); } spin_unlock(&jpeg_dma_dev->hw_lock); } if (CAM_JPEG_HW_IRQ_IS_STOP_DONE(irq_status, hw_info)) { spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_ABORTING) { core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; complete(&jpeg_dma_dev->hw_complete); if (core_info->irq_cb.jpeg_hw_mgr_cb) { core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, -1, core_info->irq_cb.data); } } else { CAM_ERR(CAM_JPEG, "unexpected abort irq"); } spin_unlock(&jpeg_dma_dev->hw_lock); } return IRQ_HANDLED; } int cam_jpeg_dma_reset_hw(void *data, void *start_args, uint32_t arg_size) { struct cam_hw_info *jpeg_dma_dev = data; struct cam_jpeg_dma_device_core_info *core_info = NULL; struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; void __iomem *mem_base; unsigned long rem_jiffies; if (!jpeg_dma_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); return -EINVAL; } /* maskdisable.clrirq.maskenable.resetcmd */ soc_info = &jpeg_dma_dev->soc_info; core_info = (struct cam_jpeg_dma_device_core_info *) jpeg_dma_dev->core_info; hw_info = core_info->jpeg_dma_hw_info; mem_base = soc_info->reg_map[0].mem_base; mutex_lock(&core_info->core_mutex); spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING) { CAM_ERR(CAM_JPEG, "dma alrady resetting"); spin_unlock(&jpeg_dma_dev->hw_lock); mutex_unlock(&core_info->core_mutex); return 0; } reinit_completion(&jpeg_dma_dev->hw_complete); core_info->core_state = CAM_JPEG_DMA_CORE_RESETTING; spin_unlock(&jpeg_dma_dev->hw_lock); cam_io_w_mb(hw_info->reg_val.int_mask_disable_all, mem_base + hw_info->reg_offset.int_mask); cam_io_w_mb(hw_info->reg_val.int_clr_clearall, mem_base + hw_info->reg_offset.int_clr); cam_io_w_mb(hw_info->reg_val.int_mask_enable_all, mem_base + hw_info->reg_offset.int_mask); cam_io_w_mb(hw_info->reg_val.reset_cmd, mem_base + hw_info->reg_offset.reset_cmd); rem_jiffies = wait_for_completion_timeout(&jpeg_dma_dev->hw_complete, CAM_JPEG_DMA_RESET_TIMEOUT); if (!rem_jiffies) { CAM_ERR(CAM_JPEG, "dma error Reset Timeout"); core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; } mutex_unlock(&core_info->core_mutex); return 0; } int cam_jpeg_dma_start_hw(void *data, void *start_args, uint32_t arg_size) { struct cam_hw_info *jpeg_dma_dev = data; struct cam_jpeg_dma_device_core_info *core_info = NULL; struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; void __iomem *mem_base; if (!jpeg_dma_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); return -EINVAL; } soc_info = &jpeg_dma_dev->soc_info; core_info = (struct cam_jpeg_dma_device_core_info *) jpeg_dma_dev->core_info; hw_info = core_info->jpeg_dma_hw_info; mem_base = soc_info->reg_map[0].mem_base; if (core_info->core_state != CAM_JPEG_DMA_CORE_READY) { CAM_ERR(CAM_JPEG, "Error not ready"); return -EINVAL; } CAM_DBG(CAM_JPEG, "Starting DMA"); cam_io_w_mb(0x00000601, mem_base + hw_info->reg_offset.int_mask); cam_io_w_mb(hw_info->reg_val.hw_cmd_start, mem_base + hw_info->reg_offset.hw_cmd); return 0; } int cam_jpeg_dma_stop_hw(void *data, void *stop_args, uint32_t arg_size) { struct cam_hw_info *jpeg_dma_dev = data; struct cam_jpeg_dma_device_core_info *core_info = NULL; struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; void __iomem *mem_base; unsigned long rem_jiffies; if (!jpeg_dma_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); return -EINVAL; } soc_info = &jpeg_dma_dev->soc_info; core_info = (struct cam_jpeg_dma_device_core_info *) jpeg_dma_dev->core_info; hw_info = core_info->jpeg_dma_hw_info; mem_base = soc_info->reg_map[0].mem_base; mutex_lock(&core_info->core_mutex); spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_ABORTING) { CAM_ERR(CAM_JPEG, "alrady stopping"); spin_unlock(&jpeg_dma_dev->hw_lock); mutex_unlock(&core_info->core_mutex); return 0; } reinit_completion(&jpeg_dma_dev->hw_complete); core_info->core_state = CAM_JPEG_DMA_CORE_ABORTING; spin_unlock(&jpeg_dma_dev->hw_lock); cam_io_w_mb(hw_info->reg_val.hw_cmd_stop, mem_base + hw_info->reg_offset.hw_cmd); rem_jiffies = wait_for_completion_timeout(&jpeg_dma_dev->hw_complete, CAM_JPEG_DMA_RESET_TIMEOUT); if (!rem_jiffies) { CAM_ERR(CAM_JPEG, "error Reset Timeout"); core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; } mutex_unlock(&core_info->core_mutex); return 0; } int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { Loading Loading @@ -187,11 +416,7 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, rc = -EINVAL; break; } if (rc) CAM_ERR(CAM_JPEG, "error cmdtype %d rc = %d", cmd_type, rc); return rc; } irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data) { return IRQ_HANDLED; } drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h +40 −2 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_DMA_CORE_H Loading @@ -10,17 +10,48 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/dma-buf.h> #include "cam_jpeg_hw_intf.h" struct cam_jpeg_dma_reg_offsets { uint32_t hw_version; uint32_t int_status; uint32_t int_clr; uint32_t int_mask; uint32_t hw_cmd; uint32_t reset_cmd; uint32_t encode_size; }; struct cam_jpeg_dma_regval { uint32_t int_clr_clearall; uint32_t int_mask_disable_all; uint32_t int_mask_enable_all; uint32_t hw_cmd_start; uint32_t reset_cmd; uint32_t hw_cmd_stop; }; struct cam_jpeg_dma_int_status { uint32_t framedone; uint32_t resetdone; uint32_t iserror; uint32_t stopdone; }; struct cam_jpeg_dma_device_hw_info { uint32_t reserved; struct cam_jpeg_dma_reg_offsets reg_offset; struct cam_jpeg_dma_regval reg_val; struct cam_jpeg_dma_int_status int_status; }; enum cam_jpeg_dma_core_state { CAM_JPEG_DMA_CORE_NOT_READY, CAM_JPEG_DMA_CORE_READY, CAM_JPEG_DMA_CORE_RESETTING, CAM_JPEG_DMA_CORE_ABORTING, CAM_JPEG_DMA_CORE_RESETTING_ON_DONE, CAM_JPEG_DMA_CORE_STATE_MAX, }; Loading @@ -31,12 +62,19 @@ struct cam_jpeg_dma_device_core_info { struct cam_jpeg_set_irq_cb irq_cb; int32_t ref_count; struct mutex core_mutex; int32_t result_size; }; int cam_jpeg_dma_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_jpeg_dma_deinit_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_jpeg_dma_start_hw(void *device_priv, void *start_hw_args, uint32_t arg_size); int cam_jpeg_dma_stop_hw(void *device_priv, void *stop_hw_args, uint32_t arg_size); int cam_jpeg_dma_reset_hw(void *device_priv, void *reset_hw_args, uint32_t arg_size); int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data); Loading Loading
drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +129 −64 Original line number Diff line number Diff line Loading @@ -38,6 +38,112 @@ static struct cam_jpeg_hw_mgr g_jpeg_hw_mgr; static int32_t cam_jpeg_hw_mgr_cb(uint32_t irq_status, int32_t result_size, void *data); static int cam_jpeg_mgr_process_cmd(void *priv, void *data); static int cam_jpeg_insert_cdm_change_base( struct cam_hw_config_args *config_args, struct cam_jpeg_hw_ctx_data *ctx_data, struct cam_jpeg_hw_mgr *hw_mgr); static int cam_jpeg_process_next_hw_update(void *priv, void *data) { int rc; int i = 0; struct cam_jpeg_hw_mgr *hw_mgr = priv; struct cam_hw_update_entry *cmd; struct cam_cdm_bl_request *cdm_cmd; struct cam_hw_config_args *config_args = NULL; struct cam_jpeg_hw_ctx_data *ctx_data = NULL; uint32_t dev_type; struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL; uint32_t cdm_cfg_to_insert = 0; if (!data || !priv) { CAM_ERR(CAM_JPEG, "Invalid data"); return -EINVAL; } ctx_data = (struct cam_jpeg_hw_ctx_data *)data; dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0]; config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args; if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { CAM_ERR(CAM_JPEG, "op reset null "); rc = -EFAULT; goto end_error; } rc = hw_mgr->devices[dev_type][0]->hw_ops.reset( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); goto end_error; } cdm_cmd = ctx_data->cdm_cmd; cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; cdm_cmd->flag = false; cdm_cmd->userdata = NULL; cdm_cmd->cookie = 0; cdm_cmd->cmd_arrary_count = 0; /* insert cdm chage base cmd */ rc = cam_jpeg_insert_cdm_change_base(config_args, ctx_data, hw_mgr); if (rc) { CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); goto end_error; } /* insert next cdm payload at index */ /* for enc or dma 1st pass at index 1 */ /* for dma 2nd pass at index 2, for 3rd at 4 */ if (p_cfg_req->num_hw_entry_processed == 0) cdm_cfg_to_insert = CAM_JPEG_CFG; else cdm_cfg_to_insert = p_cfg_req->num_hw_entry_processed + 2; CAM_DBG(CAM_JPEG, "processed %d total %d using cfg entry %d for %pK", p_cfg_req->num_hw_entry_processed, config_args->num_hw_update_entries, cdm_cfg_to_insert, p_cfg_req); cmd = (config_args->hw_update_entries + cdm_cfg_to_insert); cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle = cmd->handle; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = cmd->offset; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = cmd->len; CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", i, cmd->handle, cmd->offset, cmd->len); cdm_cmd->cmd_arrary_count++; rc = cam_cdm_submit_bls( hw_mgr->cdm_info[dev_type][0].cdm_handle, cdm_cmd); if (rc) { CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); goto end_error; } if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { CAM_ERR(CAM_JPEG, "op start null "); rc = -EINVAL; goto end_error; } rc = hw_mgr->devices[dev_type][0]->hw_ops.start( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); goto end_error; } return 0; end_error: return rc; } static int cam_jpeg_mgr_process_irq(void *priv, void *data) { Loading Loading @@ -85,6 +191,21 @@ static int cam_jpeg_mgr_process_irq(void *priv, void *data) return -EINVAL; } p_cfg_req->num_hw_entry_processed++; CAM_DBG(CAM_JPEG, "hw entry processed %d", p_cfg_req->num_hw_entry_processed); if ((task_data->result_size > 0) && (p_cfg_req->num_hw_entry_processed < p_cfg_req->hw_cfg_args.num_hw_update_entries - 2)) { /* start processing next entry before marking device free */ rc = cam_jpeg_process_next_hw_update(priv, ctx_data); if (!rc) { mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex); return 0; } } irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb; irq_cb.data = NULL; irq_cb.b_set_cb = false; Loading Loading @@ -281,7 +402,9 @@ static int cam_jpeg_insert_cdm_change_base( if (config_args->hw_update_entries[CAM_JPEG_CHBASE].offset >= ch_base_len) { CAM_ERR(CAM_JPEG, "Not enough buf"); CAM_ERR(CAM_JPEG, "Not enough buf offset %d len %d", config_args->hw_update_entries[CAM_JPEG_CHBASE].offset, ch_base_len); return -EINVAL; } CAM_DBG(CAM_JPEG, "iova %pK len %zu offset %d", Loading Loading @@ -321,8 +444,6 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) int rc; int i = 0; struct cam_jpeg_hw_mgr *hw_mgr = priv; struct cam_hw_update_entry *cmd; struct cam_cdm_bl_request *cdm_cmd; struct cam_hw_config_args *config_args = NULL; struct cam_jpeg_hw_ctx_data *ctx_data = NULL; uintptr_t request_id = 0; Loading Loading @@ -424,71 +545,13 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data) goto end_callcb; } if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) { CAM_ERR(CAM_JPEG, "op reset null "); rc = -EFAULT; goto end_callcb; } rc = hw_mgr->devices[dev_type][0]->hw_ops.reset( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); goto end_callcb; } cdm_cmd = ctx_data->cdm_cmd; cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE; cdm_cmd->flag = false; cdm_cmd->userdata = NULL; cdm_cmd->cookie = 0; cdm_cmd->cmd_arrary_count = 0; cdm_cmd->gen_irq_arb = false; rc = cam_jpeg_insert_cdm_change_base(config_args, ctx_data, hw_mgr); if (rc) { CAM_ERR(CAM_JPEG, "insert change base failed %d", rc); goto end_callcb; } CAM_DBG(CAM_JPEG, "num hw up %d", config_args->num_hw_update_entries); for (i = CAM_JPEG_CFG; i < (config_args->num_hw_update_entries - 1); i++) { cmd = (config_args->hw_update_entries + i); cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle = cmd->handle; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset = cmd->offset; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len = cmd->len; cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].arbitrate = false; CAM_DBG(CAM_JPEG, "i %d entry h %d o %d l %d", i, cmd->handle, cmd->offset, cmd->len); cdm_cmd->cmd_arrary_count++; } rc = cam_cdm_submit_bls( hw_mgr->cdm_info[dev_type][0].cdm_handle, cdm_cmd); /* insert one of the cdm payloads */ rc = cam_jpeg_process_next_hw_update(priv, ctx_data); if (rc) { CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc); CAM_ERR(CAM_JPEG, "next hw update failed %d", rc); goto end_callcb; } if (!hw_mgr->devices[dev_type][0]->hw_ops.start) { CAM_ERR(CAM_JPEG, "op start null "); rc = -EINVAL; goto end_callcb; } rc = hw_mgr->devices[dev_type][0]->hw_ops.start( hw_mgr->devices[dev_type][0]->hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_JPEG, "Failed to start hw %d", rc); goto end_callcb; } p_cfg_req->submit_timestamp = ktime_get(); mutex_unlock(&hw_mgr->hw_mgr_mutex); Loading Loading @@ -567,6 +630,7 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args) request_id = (uintptr_t)config_args->priv; p_cfg_req->req_id = request_id; p_cfg_req->num_hw_entry_processed = 0; hw_update_entries = config_args->hw_update_entries; CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %lld %zd", ctx_data, request_id, (uintptr_t)config_args->priv); Loading Loading @@ -781,6 +845,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence); } CAM_DBG(CAM_JPEG, "received num cmd buf %d", packet->num_cmd_buf); j = prepare_args->num_hw_update_entries; rc = cam_packet_util_get_kmd_buffer(packet, &kmd_buf); Loading
drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +2 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ struct cam_jpeg_hw_cdm_info_t { * @dev_type: Dev type for cfg request * @req_id: Request Id * @submit_timestamp: Timestamp of submitting request * @num_hw_entry_processed: Cdm payloads already processed */ struct cam_jpeg_hw_cfg_req { struct list_head list; Loading @@ -83,6 +84,7 @@ struct cam_jpeg_hw_cfg_req { uint32_t dev_type; uintptr_t req_id; ktime_t submit_timestamp; uint32_t num_hw_entry_processed; }; /** Loading
drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h 0 → 100644 +46 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H #define CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H #define CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE (1 << 0) #define CAM_JPEGDMA_HW_IRQ_STATUS_RD_BUF_DONE (1 << 1) #define CAM_JPEGDMA_HW_IRQ_STATUS_WR_BUF_DONE (1 << 5) #define CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT (1 << 9) #define CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE (1 << 10) #define CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE \ CAM_JPEGDMA_HW_IRQ_STATUS_SESSION_DONE #define CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK \ CAM_JPEGDMA_HW_IRQ_STATUS_RST_DONE static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { .reg_offset = { .hw_version = 0x0, .int_clr = 0x14, .int_status = 0x10, .int_mask = 0x0C, .hw_cmd = 0x1C, .reset_cmd = 0x08, .encode_size = 0x180, }, .reg_val = { .int_clr_clearall = 0xFFFFFFFF, .int_mask_disable_all = 0x00000000, .int_mask_enable_all = 0xFFFFFFFF, .hw_cmd_start = 0x00000001, .reset_cmd = 0x32083, .hw_cmd_stop = 0x00000004, }, .int_status = { .framedone = CAM_JPEGDMA_HW_MASK_COMP_FRAMEDONE, .resetdone = CAM_JPEGDMA_HW_MASK_COMP_RESET_ACK, .iserror = 0x0, .stopdone = CAM_JPEGDMA_HW_IRQ_STATUS_AXI_HALT, } }; #endif /* CAM_JPEG_DMA_HW_INFO_VER_4_2_0_H */
drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c +233 −8 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/of.h> Loading @@ -23,6 +23,15 @@ #include "cam_cpas_api.h" #include "cam_debug_util.h" #define CAM_JPEG_HW_IRQ_IS_FRAME_DONE(jpeg_irq_status, hi) \ ((jpeg_irq_status) & (hi)->int_status.framedone) #define CAM_JPEG_HW_IRQ_IS_RESET_ACK(jpeg_irq_status, hi) \ ((jpeg_irq_status) & (hi)->int_status.resetdone) #define CAM_JPEG_HW_IRQ_IS_STOP_DONE(jpeg_irq_status, hi) \ ((jpeg_irq_status) & (hi)->int_status.stopdone) #define CAM_JPEG_DMA_RESET_TIMEOUT msecs_to_jiffies(500) int cam_jpeg_dma_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size) { Loading Loading @@ -132,7 +141,7 @@ int cam_jpeg_dma_deinit_hw(void *device_priv, rc = cam_jpeg_dma_disable_soc_resources(soc_info); if (rc) CAM_ERR(CAM_JPEG, "soc enable failed %d", rc); CAM_ERR(CAM_JPEG, "soc disable failed %d", rc); rc = cam_cpas_stop(core_info->cpas_handle); if (rc) Loading @@ -143,6 +152,226 @@ int cam_jpeg_dma_deinit_hw(void *device_priv, return 0; } irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data) { struct cam_hw_info *jpeg_dma_dev = data; struct cam_jpeg_dma_device_core_info *core_info = NULL; uint32_t irq_status = 0; struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; void __iomem *mem_base; if (!jpeg_dma_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); return IRQ_HANDLED; } soc_info = &jpeg_dma_dev->soc_info; core_info = (struct cam_jpeg_dma_device_core_info *) jpeg_dma_dev->core_info; hw_info = core_info->jpeg_dma_hw_info; mem_base = soc_info->reg_map[0].mem_base; irq_status = cam_io_r_mb(mem_base + core_info->jpeg_dma_hw_info->reg_offset.int_status); cam_io_w_mb(irq_status, soc_info->reg_map[0].mem_base + core_info->jpeg_dma_hw_info->reg_offset.int_clr); CAM_DBG(CAM_JPEG, "irq_num %d irq_status = %x , core_state %d", irq_num, irq_status, core_info->core_state); if (CAM_JPEG_HW_IRQ_IS_FRAME_DONE(irq_status, hw_info)) { spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_READY) { core_info->result_size = 1; CAM_DBG(CAM_JPEG, "result_size %d", core_info->result_size); core_info->core_state = CAM_JPEG_DMA_CORE_RESETTING_ON_DONE; cam_io_w_mb(hw_info->reg_val.reset_cmd, mem_base + hw_info->reg_offset.reset_cmd); } else { CAM_WARN(CAM_JPEG, "unexpected frame done "); core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; } spin_unlock(&jpeg_dma_dev->hw_lock); } if (CAM_JPEG_HW_IRQ_IS_RESET_ACK(irq_status, hw_info)) { spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING) { core_info->core_state = CAM_JPEG_DMA_CORE_READY; core_info->result_size = -1; complete(&jpeg_dma_dev->hw_complete); } else if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING_ON_DONE) { if (core_info->irq_cb.jpeg_hw_mgr_cb) { core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, core_info->result_size, core_info->irq_cb.data); } else { CAM_WARN(CAM_JPEG, "unexpected frame done"); } core_info->result_size = -1; core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; } else { CAM_ERR(CAM_JPEG, "unexpected reset irq"); } spin_unlock(&jpeg_dma_dev->hw_lock); } if (CAM_JPEG_HW_IRQ_IS_STOP_DONE(irq_status, hw_info)) { spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_ABORTING) { core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; complete(&jpeg_dma_dev->hw_complete); if (core_info->irq_cb.jpeg_hw_mgr_cb) { core_info->irq_cb.jpeg_hw_mgr_cb(irq_status, -1, core_info->irq_cb.data); } } else { CAM_ERR(CAM_JPEG, "unexpected abort irq"); } spin_unlock(&jpeg_dma_dev->hw_lock); } return IRQ_HANDLED; } int cam_jpeg_dma_reset_hw(void *data, void *start_args, uint32_t arg_size) { struct cam_hw_info *jpeg_dma_dev = data; struct cam_jpeg_dma_device_core_info *core_info = NULL; struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; void __iomem *mem_base; unsigned long rem_jiffies; if (!jpeg_dma_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); return -EINVAL; } /* maskdisable.clrirq.maskenable.resetcmd */ soc_info = &jpeg_dma_dev->soc_info; core_info = (struct cam_jpeg_dma_device_core_info *) jpeg_dma_dev->core_info; hw_info = core_info->jpeg_dma_hw_info; mem_base = soc_info->reg_map[0].mem_base; mutex_lock(&core_info->core_mutex); spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_RESETTING) { CAM_ERR(CAM_JPEG, "dma alrady resetting"); spin_unlock(&jpeg_dma_dev->hw_lock); mutex_unlock(&core_info->core_mutex); return 0; } reinit_completion(&jpeg_dma_dev->hw_complete); core_info->core_state = CAM_JPEG_DMA_CORE_RESETTING; spin_unlock(&jpeg_dma_dev->hw_lock); cam_io_w_mb(hw_info->reg_val.int_mask_disable_all, mem_base + hw_info->reg_offset.int_mask); cam_io_w_mb(hw_info->reg_val.int_clr_clearall, mem_base + hw_info->reg_offset.int_clr); cam_io_w_mb(hw_info->reg_val.int_mask_enable_all, mem_base + hw_info->reg_offset.int_mask); cam_io_w_mb(hw_info->reg_val.reset_cmd, mem_base + hw_info->reg_offset.reset_cmd); rem_jiffies = wait_for_completion_timeout(&jpeg_dma_dev->hw_complete, CAM_JPEG_DMA_RESET_TIMEOUT); if (!rem_jiffies) { CAM_ERR(CAM_JPEG, "dma error Reset Timeout"); core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; } mutex_unlock(&core_info->core_mutex); return 0; } int cam_jpeg_dma_start_hw(void *data, void *start_args, uint32_t arg_size) { struct cam_hw_info *jpeg_dma_dev = data; struct cam_jpeg_dma_device_core_info *core_info = NULL; struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; void __iomem *mem_base; if (!jpeg_dma_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); return -EINVAL; } soc_info = &jpeg_dma_dev->soc_info; core_info = (struct cam_jpeg_dma_device_core_info *) jpeg_dma_dev->core_info; hw_info = core_info->jpeg_dma_hw_info; mem_base = soc_info->reg_map[0].mem_base; if (core_info->core_state != CAM_JPEG_DMA_CORE_READY) { CAM_ERR(CAM_JPEG, "Error not ready"); return -EINVAL; } CAM_DBG(CAM_JPEG, "Starting DMA"); cam_io_w_mb(0x00000601, mem_base + hw_info->reg_offset.int_mask); cam_io_w_mb(hw_info->reg_val.hw_cmd_start, mem_base + hw_info->reg_offset.hw_cmd); return 0; } int cam_jpeg_dma_stop_hw(void *data, void *stop_args, uint32_t arg_size) { struct cam_hw_info *jpeg_dma_dev = data; struct cam_jpeg_dma_device_core_info *core_info = NULL; struct cam_hw_soc_info *soc_info = NULL; struct cam_jpeg_dma_device_hw_info *hw_info = NULL; void __iomem *mem_base; unsigned long rem_jiffies; if (!jpeg_dma_dev) { CAM_ERR(CAM_JPEG, "Invalid args"); return -EINVAL; } soc_info = &jpeg_dma_dev->soc_info; core_info = (struct cam_jpeg_dma_device_core_info *) jpeg_dma_dev->core_info; hw_info = core_info->jpeg_dma_hw_info; mem_base = soc_info->reg_map[0].mem_base; mutex_lock(&core_info->core_mutex); spin_lock(&jpeg_dma_dev->hw_lock); if (core_info->core_state == CAM_JPEG_DMA_CORE_ABORTING) { CAM_ERR(CAM_JPEG, "alrady stopping"); spin_unlock(&jpeg_dma_dev->hw_lock); mutex_unlock(&core_info->core_mutex); return 0; } reinit_completion(&jpeg_dma_dev->hw_complete); core_info->core_state = CAM_JPEG_DMA_CORE_ABORTING; spin_unlock(&jpeg_dma_dev->hw_lock); cam_io_w_mb(hw_info->reg_val.hw_cmd_stop, mem_base + hw_info->reg_offset.hw_cmd); rem_jiffies = wait_for_completion_timeout(&jpeg_dma_dev->hw_complete, CAM_JPEG_DMA_RESET_TIMEOUT); if (!rem_jiffies) { CAM_ERR(CAM_JPEG, "error Reset Timeout"); core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; } mutex_unlock(&core_info->core_mutex); return 0; } int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { Loading Loading @@ -187,11 +416,7 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, rc = -EINVAL; break; } if (rc) CAM_ERR(CAM_JPEG, "error cmdtype %d rc = %d", cmd_type, rc); return rc; } irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data) { return IRQ_HANDLED; }
drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h +40 −2 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_JPEG_DMA_CORE_H Loading @@ -10,17 +10,48 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/dma-buf.h> #include "cam_jpeg_hw_intf.h" struct cam_jpeg_dma_reg_offsets { uint32_t hw_version; uint32_t int_status; uint32_t int_clr; uint32_t int_mask; uint32_t hw_cmd; uint32_t reset_cmd; uint32_t encode_size; }; struct cam_jpeg_dma_regval { uint32_t int_clr_clearall; uint32_t int_mask_disable_all; uint32_t int_mask_enable_all; uint32_t hw_cmd_start; uint32_t reset_cmd; uint32_t hw_cmd_stop; }; struct cam_jpeg_dma_int_status { uint32_t framedone; uint32_t resetdone; uint32_t iserror; uint32_t stopdone; }; struct cam_jpeg_dma_device_hw_info { uint32_t reserved; struct cam_jpeg_dma_reg_offsets reg_offset; struct cam_jpeg_dma_regval reg_val; struct cam_jpeg_dma_int_status int_status; }; enum cam_jpeg_dma_core_state { CAM_JPEG_DMA_CORE_NOT_READY, CAM_JPEG_DMA_CORE_READY, CAM_JPEG_DMA_CORE_RESETTING, CAM_JPEG_DMA_CORE_ABORTING, CAM_JPEG_DMA_CORE_RESETTING_ON_DONE, CAM_JPEG_DMA_CORE_STATE_MAX, }; Loading @@ -31,12 +62,19 @@ struct cam_jpeg_dma_device_core_info { struct cam_jpeg_set_irq_cb irq_cb; int32_t ref_count; struct mutex core_mutex; int32_t result_size; }; int cam_jpeg_dma_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_jpeg_dma_deinit_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_jpeg_dma_start_hw(void *device_priv, void *start_hw_args, uint32_t arg_size); int cam_jpeg_dma_stop_hw(void *device_priv, void *stop_hw_args, uint32_t arg_size); int cam_jpeg_dma_reset_hw(void *device_priv, void *reset_hw_args, uint32_t arg_size); int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data); Loading