From 8210c9c2167bc38b4d22153b4595351a3a0b6f0f Mon Sep 17 00:00:00 2001 From: Suraj Dongre Date: Mon, 10 Feb 2020 20:01:39 -0800 Subject: [PATCH] msm: camera: jpeg: Add dma driver implementation Add code to fill register settings and irq handler code for JPEG DMA. CRs-Fixed: 2716356 Change-Id: Ib48c5b27e6b29bf935fff3b68a6c74b483ea572c Signed-off-by: Suraj Dongre --- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c | 193 +++++++++----- drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h | 2 + .../cam_jpeg_dma_hw_info_ver_4_2_0.h | 46 ++++ .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c | 241 +++++++++++++++++- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h | 42 ++- .../jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c | 18 +- .../jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c | 1 + .../jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c | 2 +- 8 files changed, 459 insertions(+), 86 deletions(-) create mode 100644 drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 3f7c179711af..b270ce955285 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -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) { @@ -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; @@ -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", @@ -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; @@ -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); + /* insert one of the cdm payloads */ + rc = cam_jpeg_process_next_hw_update(priv, ctx_data); if (rc) { - CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc); + CAM_ERR(CAM_JPEG, "next hw update 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); - if (rc) { - CAM_ERR(CAM_JPEG, "Failed to apply the configs %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); @@ -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); @@ -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); diff --git a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h index 3a00e424ebc9..9de5f2950d3a 100644 --- a/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h +++ b/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h @@ -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; @@ -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; }; /** diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h new file mode 100644 index 000000000000..d4c62f381851 --- /dev/null +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/cam_jpeg_dma_hw_info_ver_4_2_0.h @@ -0,0 +1,46 @@ +/* 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 */ diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c index 1304bbc71d38..87431897d4b1 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c @@ -1,6 +1,6 @@ // 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 @@ -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) { @@ -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) @@ -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) { @@ -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; -} diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h index 6b7c8344a292..94085814b472 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h @@ -1,6 +1,6 @@ /* 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 @@ -10,17 +10,48 @@ #include #include #include +#include #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, }; @@ -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); diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c index 0bbe7ddfba8f..214bde71bcb6 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c @@ -18,12 +18,9 @@ #include "cam_jpeg_hw_mgr_intf.h" #include "cam_cpas_api.h" #include "cam_debug_util.h" +#include "cam_jpeg_dma_hw_info_ver_4_2_0.h" #include "camera_main.h" -static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { - .reserved = 0, -}; - static int cam_jpeg_dma_register_cpas(struct cam_hw_soc_info *soc_info, struct cam_jpeg_dma_device_core_info *core_info, uint32_t hw_idx) @@ -90,6 +87,9 @@ static int cam_jpeg_dma_component_bind(struct device *dev, jpeg_dma_dev_intf->hw_priv = jpeg_dma_dev; jpeg_dma_dev_intf->hw_ops.init = cam_jpeg_dma_init_hw; jpeg_dma_dev_intf->hw_ops.deinit = cam_jpeg_dma_deinit_hw; + jpeg_dma_dev_intf->hw_ops.start = cam_jpeg_dma_start_hw; + jpeg_dma_dev_intf->hw_ops.stop = cam_jpeg_dma_stop_hw; + jpeg_dma_dev_intf->hw_ops.reset = cam_jpeg_dma_reset_hw; jpeg_dma_dev_intf->hw_ops.process_cmd = cam_jpeg_dma_process_cmd; jpeg_dma_dev_intf->hw_type = CAM_JPEG_DEV_DMA; @@ -134,14 +134,11 @@ static int cam_jpeg_dma_component_bind(struct device *dev, mutex_init(&jpeg_dma_dev->hw_mutex); spin_lock_init(&jpeg_dma_dev->hw_lock); init_completion(&jpeg_dma_dev->hw_complete); - - CAM_DBG(CAM_JPEG, "JPEG:%d component bound successfully", - jpeg_dma_dev_intf->hw_idx); - + CAM_DBG(CAM_JPEG, "JPEG-DMA component bound successfully"); return rc; error_reg_cpas: - rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); + cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); error_init_soc: mutex_destroy(&core_info->core_mutex); error_match_dev: @@ -150,6 +147,7 @@ error_alloc_core: kfree(jpeg_dma_dev); error_alloc_dev: kfree(jpeg_dma_dev_intf); + return rc; } @@ -198,8 +196,6 @@ deinit_soc: free_jpeg_hw_intf: kfree(jpeg_dma_dev_intf); - return; - } const static struct component_ops cam_jpeg_dma_component_ops = { diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c index c0cfbe7a76e4..62d0cb562aa5 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c @@ -356,6 +356,7 @@ int cam_jpeg_enc_start_hw(void *data, } spin_unlock_irqrestore(&jpeg_enc_dev->hw_lock, flags); + CAM_DBG(CAM_JPEG, "Starting JPEG ENC"); cam_io_w_mb(hw_info->reg_val.hw_cmd_start, mem_base + hw_info->reg_offset.hw_cmd); diff --git a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c index 130111e54119..e9c9ebd6e193 100644 --- a/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c +++ b/drivers/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c @@ -134,7 +134,7 @@ static int cam_jpeg_enc_component_bind(struct device *dev, mutex_init(&jpeg_enc_dev->hw_mutex); spin_lock_init(&jpeg_enc_dev->hw_lock); init_completion(&jpeg_enc_dev->hw_complete); - CAM_DBG(CAM_JPEG, "Encoder component bound successfully"); + CAM_DBG(CAM_JPEG, "JPEG-Encoder component bound successfully"); return rc;