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

Commit 626c08ec authored by Om Parkash's avatar Om Parkash
Browse files

JPEG: Add DMA driver implementation



Add code to fill register settings and IRQ handler code
for JPEG DMA.

Change-Id: I55b25b3bbeb0512ad8a6b42180807f0331bc8bb7
Signed-off-by: default avatarOm Parkash <oparkash@codeaurora.org>
parent 7e65e032
Loading
Loading
Loading
Loading
+130 −63
Original line number Diff line number Diff line
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved
/* Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -46,6 +46,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)
{
@@ -92,6 +198,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;
@@ -284,7 +405,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,
			(int)ch_base_len);
		return -EINVAL;
	}
	CAM_DBG(CAM_JPEG, "iova %pK len %zu offset %d",
@@ -323,8 +446,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;
@@ -426,66 +547,10 @@ 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;

	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;
		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);
	/* insert one of the cdm payloads */
	rc = cam_jpeg_process_next_hw_update(priv, ctx_data);
	if (rc) {
		CAM_ERR(CAM_JPEG, "Failed to start hw %d",
			rc);
		CAM_ERR(CAM_JPEG, "next hw update failed %d", rc);
		goto end_callcb;
	}

@@ -565,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);
@@ -784,6 +850,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);
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -76,12 +76,14 @@ struct cam_jpeg_hw_cdm_info_t {
 * @hw_cfg_args: Hw config args
 * @dev_type: Dev type for cfg request
 * @req_id: Request Id
 * @num_hw_entry_processed: Cdm payloads already processed
 */
struct cam_jpeg_hw_cfg_req {
	struct list_head list;
	struct cam_hw_config_args hw_cfg_args;
	uint32_t dev_type;
	uintptr_t req_id;
	uint32_t num_hw_entry_processed;
};

/**
+53 −0
Original line number Diff line number Diff line
/* Copyright (c) 2021 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#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 */
+233 −8
Original line number Diff line number Diff line
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,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)
{
@@ -131,7 +140,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)
@@ -142,6 +151,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)
{
@@ -186,11 +415,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;
}
+39 −2
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -21,14 +21,44 @@

#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,
};

@@ -39,12 +69,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