msm: camera: cre: Updated FE/WE configuration

Changed from static to dynamic allocation for hw_mgr_intf.
Updated de-init handling during driver remove.
Updated Idle irq handling to not clear request data at idle irq.
Multiple request handling at buff done.
Offset fix.

CRs-Fixed: 2982472
Change-Id: I37fb690f9f4c1460ecf322a259e2e1001574339b
Signed-off-by: Vikram Sharma <vikramsa@codeaurora.org>
Цей коміт міститься в:
Vikram Sharma
2021-06-16 10:28:02 +05:30
зафіксовано Gerrit - the friendly Code Review server
джерело 16710c7458
коміт ffc9bf8758
17 змінених файлів з 860 додано та 638 видалено

Переглянути файл

@@ -238,36 +238,34 @@ static struct cam_ctx_ops
};
int cam_cre_context_init(struct cam_cre_context *ctx,
struct cam_context *ctx_base,
struct cam_hw_mgr_intf *hw_intf,
uint32_t ctx_id)
{
int rc;
int i;
if (!ctx || !ctx_base) {
if (!ctx || !ctx->base) {
CAM_ERR(CAM_CRE, "Invalid Context");
rc = -EFAULT;
goto err;
}
memset(ctx, 0, sizeof(*ctx));
ctx->base = ctx_base;
for (i = 0; i < CAM_CTX_REQ_MAX; i++)
ctx->req_base[i].req_priv = ctx;
rc = cam_context_init(ctx_base, cre_dev_name, CAM_CRE, ctx_id,
rc = cam_context_init(ctx->base, cre_dev_name, CAM_CRE, ctx_id,
NULL, hw_intf, ctx->req_base, CAM_CTX_REQ_MAX);
if (rc) {
CAM_ERR(CAM_CRE, "Camera Context Base init failed");
goto err;
}
ctx_base->state_machine = cam_cre_ctx_state_machine;
ctx_base->ctx_priv = ctx;
ctx->base->state_machine = cam_cre_ctx_state_machine;
ctx->base->ctx_priv = ctx;
ctx->base->max_hw_update_entries = CAM_CTX_CFG_MAX;
ctx->base->max_in_map_entries = CAM_CTX_CFG_MAX;
ctx->base->max_out_map_entries = CAM_CTX_CFG_MAX;
err:
return rc;
}

Переглянути файл

@@ -44,13 +44,11 @@ struct cam_cre_ctx_irq_ops {
* @brief: Initialization function for the CRE context
*
* @ctx: CRE context obj to be initialized
* @ctx_base: Context base from cam_context
* @hw_intf: CRE hw manager interface
* @ctx_id: ID for this context
*
*/
int cam_cre_context_init(struct cam_cre_context *ctx,
struct cam_context *ctx_base,
struct cam_hw_mgr_intf *hw_intf,
uint32_t ctx_id);

Переглянути файл

@@ -109,14 +109,14 @@ static const struct v4l2_subdev_internal_ops cam_cre_subdev_internal_ops = {
static int cam_cre_subdev_component_bind(struct device *dev,
struct device *master_dev, void *data)
{
int rc;
int i;
struct cam_hw_mgr_intf hw_mgr_intf;
int rc = 0;
struct cam_hw_mgr_intf *hw_mgr_intf;
struct cam_node *node;
int iommu_hdl = -1;
struct platform_device *pdev = to_platform_device(dev);
CAM_DBG(CAM_CRE, "CRE Subdev Component bind");
g_cre_dev.sd.pdev = pdev;
g_cre_dev.sd.internal_ops = &cam_cre_subdev_internal_ops;
rc = cam_subdev_probe(&g_cre_dev.sd, pdev, CAM_CRE_DEV_NAME,
CAM_CRE_DEVICE_TYPE);
@@ -126,18 +126,25 @@ static int cam_cre_subdev_component_bind(struct device *dev,
}
node = (struct cam_node *)g_cre_dev.sd.token;
rc = cam_cre_hw_mgr_init(pdev->dev.of_node,
(uint64_t *)&hw_mgr_intf, &iommu_hdl);
if (rc) {
CAM_ERR(CAM_CRE, "Can not initialize CRE HWmanager %d", rc);
goto unregister;
hw_mgr_intf = kzalloc(sizeof(*hw_mgr_intf), GFP_KERNEL);
if (!hw_mgr_intf) {
CAM_ERR(CAM_CRE, "Error allocating memory");
rc = -ENOMEM;
goto hw_alloc_fail;
}
rc = cam_cre_hw_mgr_init(pdev->dev.of_node, hw_mgr_intf,
&iommu_hdl);
if (rc) {
CAM_ERR(CAM_CRE, "Can not initialize CRE HWmanager %d", rc);
goto hw_init_fail;
}
memset(g_cre_dev.ctx_cre, 0, sizeof(g_cre_dev.ctx_cre));
for (i = 0; i < CAM_CRE_CTX_MAX; i++) {
g_cre_dev.ctx_cre[i].base = &g_cre_dev.ctx[i];
rc = cam_cre_context_init(&g_cre_dev.ctx_cre[i],
&g_cre_dev.ctx[i],
&node->hw_mgr_intf,
i);
hw_mgr_intf, i);
if (rc) {
CAM_ERR(CAM_CRE, "CRE context init failed %d %d",
i, rc);
@@ -145,8 +152,8 @@ static int cam_cre_subdev_component_bind(struct device *dev,
}
}
rc = cam_node_init(node, &hw_mgr_intf, g_cre_dev.ctx, CAM_CRE_CTX_MAX,
CAM_CRE_DEV_NAME);
rc = cam_node_init(node, hw_mgr_intf, g_cre_dev.ctx,
CAM_CRE_CTX_MAX, CAM_CRE_DEV_NAME);
if (rc) {
CAM_ERR(CAM_CRE, "CRE node init failed %d", rc);
goto ctx_init_fail;
@@ -156,6 +163,7 @@ static int cam_cre_subdev_component_bind(struct device *dev,
cam_smmu_set_client_page_fault_handler(iommu_hdl,
cam_cre_dev_iommu_fault_handler, node);
g_cre_dev.open_cnt = 0;
mutex_init(&g_cre_dev.cre_lock);
CAM_DBG(CAM_CRE, "Component bound successfully");
@@ -166,7 +174,9 @@ ctx_init_fail:
for (--i; i >= 0; i--)
if (cam_cre_context_deinit(&g_cre_dev.ctx_cre[i]))
CAM_ERR(CAM_CRE, "deinit fail %d %d", i, rc);
unregister:
hw_init_fail:
kfree(hw_mgr_intf);
hw_alloc_fail:
if (cam_subdev_remove(&g_cre_dev.sd))
CAM_ERR(CAM_CRE, "remove fail %d", rc);
err:
@@ -176,19 +186,14 @@ err:
static void cam_cre_subdev_component_unbind(struct device *dev,
struct device *master_dev, void *data)
{
int rc;
int i;
for (i = 0; i < CAM_CTX_MAX; i++) {
rc = cam_cre_context_deinit(&g_cre_dev.ctx_cre[i]);
if (rc)
CAM_ERR(CAM_CRE, "CRE context %d deinit failed %d",
i, rc);
}
for (i = 0; i < CRE_CTX_MAX; i++)
cam_cre_context_deinit(&g_cre_dev.ctx_cre[i]);
rc = cam_subdev_remove(&g_cre_dev.sd);
if (rc)
CAM_ERR(CAM_CRE, "Unregister failed %d", rc);
cam_node_deinit(g_cre_dev.node);
cam_subdev_remove(&g_cre_dev.sd);
mutex_destroy(&g_cre_dev.cre_lock);
}
const static struct component_ops cam_cre_subdev_component_ops = {

Переглянути файл

@@ -2,12 +2,6 @@
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
@@ -37,9 +31,6 @@
#include "cre_dev_intf.h"
#include "cam_compat.h"
#define CAM_CRE_FE_IRQ 0x4
#define CAM_CRE_WE_IRQ 0x2
static struct cam_cre_hw_mgr *cre_hw_mgr;
static struct cam_cre_io_buf_info *cam_cre_mgr_get_rsc(
@@ -131,6 +122,7 @@ static int cam_cre_mgr_process_cmd_io_buf_req(struct cam_cre_hw_mgr *hw_mgr,
cre_request = ctx_data->req_list[req_idx];
cre_request->num_batch = ctx_data->cre_acquire.batch_size;
CAM_DBG(CAM_CRE, "num_io_configs %d", packet->num_io_configs);
for (i = 0; i < cre_request->num_batch; i++) {
for (j = 0; j < packet->num_io_configs; j++) {
@@ -154,9 +146,15 @@ static int cam_cre_mgr_process_cmd_io_buf_req(struct cam_cre_hw_mgr *hw_mgr,
io_buf->num_planes = acq_io_buf->num_planes;
io_buf->resource_type = acq_io_buf->res_id;
io_buf->direction = acq_io_buf->direction;
io_buf->fence = acq_io_buf->fence;
io_buf->format = acq_io_buf->format;
alignment = acq_io_buf->alignment;
io_buf->fence = io_cfg_ptr[j].fence;
CAM_DBG(CAM_CRE,
"i %d j %d Number of planes %d res_type %d dir %d, fence %d format %d align %d",
i, j, io_buf->num_planes, io_buf->resource_type,
io_buf->direction, io_buf->fence, io_buf->format, alignment);
for (k = 0; k < io_buf->num_planes; k++) {
is_secure = cam_mem_is_secure_buf(
@@ -180,21 +178,27 @@ static int cam_cre_mgr_process_cmd_io_buf_req(struct cam_cre_hw_mgr *hw_mgr,
iova_addr += io_cfg_ptr[j].offsets[k];
plane_info = &io_buf->p_info[k];
plane_info->offset = io_cfg_ptr[j].offsets[k];
plane_info->format = io_buf->format;
/*
* TODO: Confirm if the calculation for batch frame offset
* is correct with some experiment in TFE.
*/
plane_info->offset = io_cfg_ptr[j].offsets[k];
plane_info->format = acq_io_buf->format;
plane_info->iova_addr = iova_addr +
((io_cfg_ptr[j].planes[k].plane_stride *
io_cfg_ptr[j].planes[k].slice_height) * i);
plane_info->width =
io_cfg_ptr[j].planes[k].width;
plane_info->height =
io_cfg_ptr[j].planes[k].height;
io_cfg_ptr[j].planes[k].slice_height) * k);
plane_info->stride =
io_cfg_ptr[j].planes[k].plane_stride;
/* Width for WE has to be updated in number of pixels */
if (acq_io_buf->direction == CAM_BUF_OUTPUT) {
/* PLAIN 128/8 = 16 Bytes per pixel */
plane_info->width =
io_cfg_ptr[j].planes[k].plane_stride/16;
} else {
/* FE width should be in bytes */
plane_info->width =
io_cfg_ptr[j].planes[k].plane_stride;
}
plane_info->height =
io_cfg_ptr[j].planes[k].height;
plane_info->len = len;
plane_info->alignment = alignment;
}
@@ -233,47 +237,27 @@ static int cam_cre_mgr_reset_hw(void)
}
static void cam_cre_ctx_wait_for_idle_irq(struct cam_cre_ctx *ctx,
struct cam_cre_request *cre_req, uint32_t cookie)
static void cam_cre_ctx_wait_for_idle_irq(struct cam_cre_ctx *ctx)
{
int rc;
if (ctx->ctx_state != CRE_CTX_STATE_ACQUIRED) {
CAM_ERR(CAM_CRE, "ctx %u is in %d state",
ctx->ctx_id, ctx->ctx_state);
mutex_unlock(&ctx->ctx_mutex);
return;
}
rc = wait_for_completion_timeout(
&ctx->cre_top->idle_done, msecs_to_jiffies(30000));
rc = cam_common_wait_for_completion_timeout(
&ctx->cre_top->idle_done,
msecs_to_jiffies(CAM_CRE_RESPONSE_TIME_THRESHOLD));
if (!rc) {
cam_cre_device_timer_reset(cre_hw_mgr);
} else {
CAM_INFO(CAM_CRE, "After reset of CRE, reapply req");
rc = cam_cre_mgr_reset_hw();
CAM_DBG(CAM_CRE, "IDLE done for req idx %d",
ctx->last_req_idx);
}
if (!test_bit(cookie, ctx->bitmap)) {
CAM_ERR(CAM_CRE, "Req not present reqIdx = %d for ctx_id = %d",
cookie, ctx->ctx_id);
goto end;
}
CAM_DBG(CAM_REQ, "req_id= %llu ctx_id= %d lcb=%llu",
cre_req->request_id, ctx->ctx_id);
ctx->req_cnt--;
cre_req->request_id = 0;
cam_cre_free_io_config(ctx->req_list[cookie]);
cam_free_clear((void *)ctx->req_list[cookie]);
ctx->req_list[cookie] = NULL;
clear_bit(cookie, ctx->bitmap);
end:
mutex_unlock(&ctx->ctx_mutex);
}
static int cam_cre_mgr_create_cre_reg_buf(struct cam_cre_hw_mgr *hw_mgr,
struct cam_packet *packet,
struct cam_hw_prepare_update_args *prepare_args,
@@ -570,16 +554,16 @@ static int cam_cre_mgr_handle_config_err(
struct cam_hw_config_args *config_args,
struct cam_cre_ctx *ctx_data)
{
struct cam_hw_done_event_data buf_data;
struct cam_hw_done_event_data err_data;
struct cam_cre_request *cre_req;
uint32_t req_idx;
cre_req = config_args->priv;
buf_data.request_id = cre_req->request_id;
buf_data.evt_param = CAM_SYNC_CRE_EVENT_CONFIG_ERR;
err_data.request_id = cre_req->request_id;
err_data.evt_param = CAM_SYNC_CRE_EVENT_CONFIG_ERR;
ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_ERROR,
&buf_data);
&err_data);
req_idx = cre_req->req_idx;
cre_req->request_id = 0;
@@ -684,7 +668,7 @@ static int32_t cam_cre_deinit_idle_clk(void *priv, void *data)
CAM_DBG(CAM_CRE, "Disable %d", clk_info->hw_type);
dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, NULL, 0);
dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id, NULL, 0);
done:
mutex_unlock(&hw_mgr->hw_mgr_mutex);
@@ -719,19 +703,14 @@ static void cam_cre_device_timer_cb(struct timer_list *timer_data)
static int cam_cre_device_timer_start(struct cam_cre_hw_mgr *hw_mgr)
{
int rc = 0;
int i;
for (i = 0; i < CLK_HW_MAX; i++) {
if (!hw_mgr->clk_info.watch_dog) {
rc = crm_timer_init(&hw_mgr->clk_info.watch_dog,
CRE_DEVICE_IDLE_TIMEOUT, &hw_mgr->clk_info,
&cam_cre_device_timer_cb);
if (rc)
CAM_ERR(CAM_CRE, "Failed to start timer %d", i);
hw_mgr->clk_info.watch_dog_reset_counter = 0;
}
if (!hw_mgr->clk_info.watch_dog) {
rc = crm_timer_init(&hw_mgr->clk_info.watch_dog,
CRE_DEVICE_IDLE_TIMEOUT, &hw_mgr->clk_info,
&cam_cre_device_timer_cb);
if (rc)
CAM_ERR(CAM_CRE, "Failed to start timer");
hw_mgr->clk_info.watch_dog_reset_counter = 0;
}
return rc;
@@ -753,7 +732,7 @@ static int cam_cre_mgr_process_cmd(void *priv, void *data)
struct cam_cre_ctx *ctx_data;
struct cam_cre_request *cre_req;
struct cam_cre_hw_mgr *hw_mgr = cre_hw_mgr;
uint32_t active_req_idx;
uint32_t num_batch;
if (!data || !priv) {
CAM_ERR(CAM_CRE, "Invalid params%pK %pK", data, priv);
@@ -772,12 +751,10 @@ static int cam_cre_mgr_process_cmd(void *priv, void *data)
return -EINVAL;
}
active_req_idx = task_data->req_idx;
if (active_req_idx >= CAM_CTX_REQ_MAX) {
if (task_data->req_idx >= CAM_CTX_REQ_MAX) {
mutex_unlock(&hw_mgr->hw_mgr_mutex);
CAM_ERR(CAM_CRE, "Invalid reqIdx = %llu",
active_req_idx);
task_data->req_idx);
return -EINVAL;
}
@@ -799,15 +776,34 @@ static int cam_cre_mgr_process_cmd(void *priv, void *data)
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return -EINVAL;
}
hw_mgr = task_data->data;
ctx_data->active_req = cre_req;
for (i = 0; i < cre_req->num_batch; i++) {
cam_cre_mgr_update_reg_set(hw_mgr, cre_req);
cam_cre_ctx_wait_for_idle_irq(ctx_data, cre_req,
active_req_idx);
}
num_batch = cre_req->num_batch;
CAM_DBG(CAM_CRE,
"Going to configure cre for req %d, req_idx %d num_batch %d",
cre_req->request_id, cre_req->req_idx, num_batch);
for (i = 0; i < num_batch; i++) {
if (i != 0) {
rc = cam_common_wait_for_completion_timeout(
&ctx_data->cre_top->bufdone,
msecs_to_jiffies(100));
if (!rc) {
cam_cre_device_timer_reset(cre_hw_mgr);
CAM_ERR(CAM_CRE,
"Timedout waiting for bufdone on last frame");
return -ETIMEDOUT;
} else {
reinit_completion(&ctx_data->cre_top->bufdone);
CAM_INFO(CAM_CRE,
"done for frame %d in batch of %d",
i-1, num_batch);
}
}
cam_cre_mgr_update_reg_set(hw_mgr, cre_req, i);
cam_cre_ctx_wait_for_idle_irq(ctx_data);
}
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return rc;
@@ -835,9 +831,11 @@ static int32_t cam_cre_mgr_process_msg(void *priv, void *data)
struct cam_hw_done_event_data buf_data;
struct cam_cre_hw_mgr *hw_mgr;
struct cam_cre_ctx *ctx;
struct cam_cre_request *active_req;
struct cam_cre_irq_data irq_data;
int32_t ctx_id;
uint32_t evt_id;
uint32_t active_req_idx;
int rc = 0;
if (!data || !priv) {
@@ -864,31 +862,325 @@ static int32_t cam_cre_mgr_process_msg(void *priv, void *data)
return -EINVAL;
}
active_req_idx = find_next_bit(ctx->bitmap, ctx->bits, ctx->last_done_req_idx);
CAM_DBG(CAM_CRE, "active_req_idx %d last_done_req_idx %d",
active_req_idx, ctx->last_done_req_idx);
active_req = ctx->req_list[active_req_idx];
if (!active_req)
CAM_ERR(CAM_CRE, "Active req cannot be null");
if (irq_data.error) {
evt_id = CAM_CTX_EVT_ID_ERROR;
buf_data.evt_param = CAM_SYNC_CRE_EVENT_HW_ERR;
buf_data.request_id = ctx->active_req->request_id;
buf_data.request_id = active_req->request_id;
ctx->ctxt_event_cb(ctx->context_priv, evt_id, &buf_data);
rc = cam_cre_mgr_reset_hw();
} else if ((irq_data.top_irq_status & CAM_CRE_WE_IRQ)
&& (irq_data.wr_buf_done)) {
clear_bit(active_req_idx, ctx->bitmap);
cam_cre_free_io_config(active_req);
cam_free_clear((void *)active_req);
ctx->req_cnt--;
ctx->req_list[active_req_idx] = NULL;
} else if (irq_data.wr_buf_done) {
/* Signal Buf done */
ctx->active_req->frames_done++;
if (ctx->active_req->frames_done == ctx->active_req->num_batch) {
active_req->frames_done++;
CAM_DBG(CAM_CRE, "Received frames_done %d num_batch %d req id %d",
active_req->frames_done, active_req->num_batch,
active_req->request_id);
complete(&ctx->cre_top->bufdone);
if (active_req->frames_done == active_req->num_batch) {
ctx->last_done_req_idx = active_req_idx;
CAM_DBG(CAM_CRE, "signaling buff done for req %d",
active_req->request_id);
evt_id = CAM_CTX_EVT_ID_SUCCESS;
buf_data.evt_param = CAM_SYNC_COMMON_EVENT_SUCCESS;
buf_data.request_id = ctx->active_req->request_id;
buf_data.request_id = active_req->request_id;
ctx->ctxt_event_cb(ctx->context_priv, evt_id, &buf_data);
clear_bit(active_req_idx, ctx->bitmap);
cam_cre_free_io_config(active_req);
cam_free_clear((void *)active_req);
ctx->req_cnt--;
ctx->req_list[active_req_idx] = NULL;
}
}
mutex_unlock(&ctx->ctx_mutex);
return rc;
}
static int cam_cre_get_actual_clk_rate_idx(
struct cam_cre_ctx *ctx_data, uint32_t base_clk)
{
int i;
for (i = 0; i < CAM_MAX_VOTE; i++)
if (ctx_data->clk_info.clk_rate[i] >= base_clk)
return i;
/*
* Caller has to ensure returned index is within array
* size bounds while accessing that index.
*/
return i;
}
static bool cam_cre_is_over_clk(struct cam_cre_hw_mgr *hw_mgr,
struct cam_cre_ctx *ctx_data,
struct cam_cre_clk_info *hw_mgr_clk_info)
{
int base_clk_idx;
int curr_clk_idx;
base_clk_idx = cam_cre_get_actual_clk_rate_idx(ctx_data,
hw_mgr_clk_info->base_clk);
curr_clk_idx = cam_cre_get_actual_clk_rate_idx(ctx_data,
hw_mgr_clk_info->curr_clk);
CAM_DBG(CAM_CRE, "bc_idx = %d cc_idx = %d %d %d",
base_clk_idx, curr_clk_idx, hw_mgr_clk_info->base_clk,
hw_mgr_clk_info->curr_clk);
if (curr_clk_idx > base_clk_idx)
return true;
return false;
}
static int cam_cre_get_lower_clk_rate(struct cam_cre_hw_mgr *hw_mgr,
struct cam_cre_ctx *ctx_data, uint32_t base_clk)
{
int i;
i = cam_cre_get_actual_clk_rate_idx(ctx_data, base_clk);
while (i > 0) {
if (ctx_data->clk_info.clk_rate[i - 1])
return ctx_data->clk_info.clk_rate[i - 1];
i--;
}
CAM_DBG(CAM_CRE, "Already clk at lower level");
return base_clk;
}
static int cam_cre_get_next_clk_rate(struct cam_cre_hw_mgr *hw_mgr,
struct cam_cre_ctx *ctx_data, uint32_t base_clk)
{
int i;
i = cam_cre_get_actual_clk_rate_idx(ctx_data, base_clk);
while (i < CAM_MAX_VOTE - 1) {
if (ctx_data->clk_info.clk_rate[i + 1])
return ctx_data->clk_info.clk_rate[i + 1];
i++;
}
CAM_DBG(CAM_CRE, "Already clk at higher level");
return base_clk;
}
static bool cam_cre_update_clk_overclk_free(struct cam_cre_hw_mgr *hw_mgr,
struct cam_cre_ctx *ctx_data,
struct cam_cre_clk_info *hw_mgr_clk_info,
struct cam_cre_clk_bw_request *clk_info,
uint32_t base_clk)
{
int rc = false;
/*
* In caseof no pending packets case
* 1. In caseof overclk cnt is less than threshold, increase
* overclk count and no update in the clock rate
* 2. In caseof overclk cnt is greater than or equal to threshold
* then lower clock rate by one level and update hw_mgr current
* clock value.
* a. In case of new clock rate greater than sum of clock
* rates, reset overclk count value to zero if it is
* overclock
* b. if it is less than sum of base clocks then go to next
* level of clock and make overclk count to zero
* c. if it is same as sum of base clock rates update overclock
* cnt to 0
*/
if (hw_mgr_clk_info->over_clked < hw_mgr_clk_info->threshold) {
hw_mgr_clk_info->over_clked++;
rc = false;
} else {
hw_mgr_clk_info->curr_clk =
cam_cre_get_lower_clk_rate(hw_mgr, ctx_data,
hw_mgr_clk_info->curr_clk);
if (hw_mgr_clk_info->curr_clk > hw_mgr_clk_info->base_clk) {
if (cam_cre_is_over_clk(hw_mgr, ctx_data,
hw_mgr_clk_info))
hw_mgr_clk_info->over_clked = 0;
} else if (hw_mgr_clk_info->curr_clk <
hw_mgr_clk_info->base_clk) {
hw_mgr_clk_info->curr_clk =
cam_cre_get_next_clk_rate(hw_mgr, ctx_data,
hw_mgr_clk_info->curr_clk);
hw_mgr_clk_info->over_clked = 0;
} else if (hw_mgr_clk_info->curr_clk ==
hw_mgr_clk_info->base_clk) {
hw_mgr_clk_info->over_clked = 0;
}
rc = true;
}
return rc;
}
static int cam_cre_calc_total_clk(struct cam_cre_hw_mgr *hw_mgr,
struct cam_cre_clk_info *hw_mgr_clk_info, uint32_t dev_type)
{
int i;
struct cam_cre_ctx *ctx_data;
hw_mgr_clk_info->base_clk = 0;
for (i = 0; i < CRE_CTX_MAX; i++) {
ctx_data = &hw_mgr->ctx[i];
if (ctx_data->ctx_state == CRE_CTX_STATE_ACQUIRED)
hw_mgr_clk_info->base_clk +=
ctx_data->clk_info.base_clk;
}
return 0;
}
static int cam_cre_get_actual_clk_rate(struct cam_cre_hw_mgr *hw_mgr,
struct cam_cre_ctx *ctx_data, uint32_t base_clk)
{
int i;
for (i = 0; i < CAM_MAX_VOTE; i++)
if (ctx_data->clk_info.clk_rate[i] >= base_clk)
return ctx_data->clk_info.clk_rate[i];
return base_clk;
}
static bool cam_cre_update_clk_busy(struct cam_cre_hw_mgr *hw_mgr,
struct cam_cre_ctx *ctx_data,
struct cam_cre_clk_info *hw_mgr_clk_info,
struct cam_cre_clk_bw_request *clk_info,
uint32_t base_clk)
{
uint32_t next_clk_level;
uint32_t actual_clk;
bool rc = false;
/* 1. if current request frame cycles(fc) are more than previous
* frame fc
* Calculate the new base clock.
* if sum of base clocks are more than next available clk level
* Update clock rate, change curr_clk_rate to sum of base clock
* rates and make over_clked to zero
* else
* Update clock rate to next level, update curr_clk_rate and make
* overclked cnt to zero
* 2. if current fc is less than or equal to previous frame fc
* Still Bump up the clock to next available level
* if it is available, then update clock, make overclk cnt to
* zero. If the clock is already at highest clock rate then
* no need to update the clock
*/
ctx_data->clk_info.base_clk = base_clk;
hw_mgr_clk_info->over_clked = 0;
if (clk_info->frame_cycles > ctx_data->clk_info.curr_fc) {
cam_cre_calc_total_clk(hw_mgr, hw_mgr_clk_info,
ctx_data->cre_acquire.dev_type);
actual_clk = cam_cre_get_actual_clk_rate(hw_mgr,
ctx_data, base_clk);
if (hw_mgr_clk_info->base_clk > actual_clk) {
hw_mgr_clk_info->curr_clk = hw_mgr_clk_info->base_clk;
} else {
next_clk_level = cam_cre_get_next_clk_rate(hw_mgr,
ctx_data, hw_mgr_clk_info->curr_clk);
hw_mgr_clk_info->curr_clk = next_clk_level;
}
rc = true;
} else {
next_clk_level =
cam_cre_get_next_clk_rate(hw_mgr, ctx_data,
hw_mgr_clk_info->curr_clk);
if (hw_mgr_clk_info->curr_clk < next_clk_level) {
hw_mgr_clk_info->curr_clk = next_clk_level;
rc = true;
}
}
ctx_data->clk_info.curr_fc = clk_info->frame_cycles;
return rc;
}
static bool cam_cre_update_clk_free(struct cam_cre_hw_mgr *hw_mgr,
struct cam_cre_ctx *ctx_data,
struct cam_cre_clk_info *hw_mgr_clk_info,
struct cam_cre_clk_bw_request *clk_info,
uint32_t base_clk)
{
int rc = false;
bool over_clocked = false;
ctx_data->clk_info.curr_fc = clk_info->frame_cycles;
ctx_data->clk_info.base_clk = base_clk;
cam_cre_calc_total_clk(hw_mgr, hw_mgr_clk_info,
ctx_data->cre_acquire.dev_type);
/*
* Current clock is not always sum of base clocks, due to
* clock scales update to next higher or lower levels, it
* equals to one of discrete clock values supported by hardware.
* So even current clock is higher than sum of base clocks, we
* can not consider it is over clocked. if it is greater than
* discrete clock level then only it is considered as over clock.
* 1. Handle over clock case
* 2. If current clock is less than sum of base clocks
* update current clock
* 3. If current clock is same as sum of base clocks no action
*/
over_clocked = cam_cre_is_over_clk(hw_mgr, ctx_data,
hw_mgr_clk_info);
if (hw_mgr_clk_info->curr_clk > hw_mgr_clk_info->base_clk &&
over_clocked) {
rc = cam_cre_update_clk_overclk_free(hw_mgr, ctx_data,
hw_mgr_clk_info, clk_info, base_clk);
} else if (hw_mgr_clk_info->curr_clk > hw_mgr_clk_info->base_clk) {
hw_mgr_clk_info->over_clked = 0;
rc = false;
} else if (hw_mgr_clk_info->curr_clk < hw_mgr_clk_info->base_clk) {
hw_mgr_clk_info->curr_clk = cam_cre_get_actual_clk_rate(hw_mgr,
ctx_data, hw_mgr_clk_info->base_clk);
rc = true;
}
return rc;
}
static uint32_t cam_cre_mgr_calc_base_clk(uint32_t frame_cycles,
uint64_t budget)
{
uint64_t mul = 1000000000;
uint64_t base_clk = frame_cycles * mul;
do_div(base_clk, budget);
CAM_DBG(CAM_CRE, "budget = %lld fc = %d ib = %lld base_clk = %lld",
budget, frame_cycles,
(long long)(frame_cycles * mul), base_clk);
return base_clk;
}
static bool cam_cre_check_clk_update(struct cam_cre_hw_mgr *hw_mgr,
struct cam_cre_ctx *ctx_data, int idx)
{
bool rc = false;
bool busy = false, rc = false;
uint64_t base_clk;
struct cam_cre_clk_bw_request *clk_info;
uint64_t req_id;
struct cam_cre_clk_info *hw_mgr_clk_info;
@@ -896,14 +1188,29 @@ static bool cam_cre_check_clk_update(struct cam_cre_hw_mgr *hw_mgr,
cam_cre_device_timer_reset(hw_mgr);
hw_mgr_clk_info = &hw_mgr->clk_info;
req_id = ctx_data->req_list[idx]->request_id;
if (ctx_data->req_cnt > 1)
busy = true;
CAM_DBG(CAM_CRE, "req_id = %lld", req_id);
CAM_DBG(CAM_CRE, "busy = %d req_id = %lld", busy, req_id);
clk_info = &ctx_data->req_list[idx]->clk_info;
/* Calculate base clk rate */
base_clk = cam_cre_mgr_calc_base_clk(
clk_info->frame_cycles, clk_info->budget_ns);
ctx_data->clk_info.rt_flag = clk_info->rt_flag;
if (busy)
rc = cam_cre_update_clk_busy(hw_mgr, ctx_data,
hw_mgr_clk_info, clk_info, base_clk);
else
rc = cam_cre_update_clk_free(hw_mgr, ctx_data,
hw_mgr_clk_info, clk_info, base_clk);
CAM_DBG(CAM_CRE, "bc = %d cc = %d busy = %d overclk = %d uc = %d",
hw_mgr_clk_info->base_clk, hw_mgr_clk_info->curr_clk,
busy, hw_mgr_clk_info->over_clked, rc);
return rc;
}
@@ -1020,7 +1327,8 @@ static int cam_cre_mgr_process_io_cfg(struct cam_cre_hw_mgr *hw_mgr,
prep_arg->num_out_map_entries = 0;
prep_arg->num_in_map_entries = 0;
CAM_DBG(CAM_CRE, "E: req_idx = %u %x", req_idx, packet);
CAM_DBG(CAM_CRE, "E: req_idx = %u %x num batch%d",
req_idx, packet, cre_request->num_batch);
for (i = 0; i < cre_request->num_batch; i++) {
for (l = 0; l < cre_request->num_io_bufs[i]; l++) {
@@ -1050,13 +1358,10 @@ static int cam_cre_mgr_process_io_cfg(struct cam_cre_hw_mgr *hw_mgr,
prep_arg->num_out_map_entries++;
}
}
CAM_DBG(CAM_REQ,
CAM_DBG(CAM_CRE,
"ctx_id: %u req_id: %llu dir[%d] %u, fence: %d",
ctx_data->ctx_id, packet->header.request_id, i,
io_buf->direction, io_buf->fence);
CAM_DBG(CAM_REQ, "rsc_type = %u fmt = %d",
io_buf->resource_type,
io_buf->format);
}
}
@@ -1080,16 +1385,16 @@ static int cam_cre_mgr_process_io_cfg(struct cam_cre_hw_mgr *hw_mgr,
prep_arg->in_map_entries[0].sync_id = merged_sync_in_obj;
prep_arg->num_in_map_entries = 1;
CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu Merged Sync obj: %d",
CAM_DBG(CAM_CRE, "ctx_id: %u req_id: %llu Merged Sync obj: %d",
ctx_data->ctx_id, packet->header.request_id,
merged_sync_in_obj);
} else if (prep_arg->num_in_map_entries == 1) {
prep_arg->in_map_entries[0].sync_id = sync_in_obj[0];
prep_arg->num_in_map_entries = 1;
cre_request->in_resource = 0;
CAM_DBG(CAM_CRE, "fence = %d", sync_in_obj[0]);
} else {
CAM_DBG(CAM_CRE, "Invalid count of input fences, count: %d",
CAM_ERR(CAM_CRE,
"Invalid count of input fences, count: %d",
prep_arg->num_in_map_entries);
prep_arg->num_in_map_entries = 0;
cre_request->in_resource = 0;
@@ -1203,48 +1508,42 @@ static int cam_cre_validate_acquire_res_info(
return -EINVAL;
}
if (cre_acquire->dev_type >= CRE_DEV_MAX) {
if (cre_acquire->dev_type >= CAM_CRE_DEV_TYPE_MAX) {
CAM_ERR(CAM_CRE, "Invalid device type: %d",
cre_acquire->dev_type);
return -EFAULT;
return -EINVAL;
}
/*
* TODO: Confirm this with CRE HW folks
* Reffering CRE HPG supported input formats are
* CAM_FORMAT_MIPI_RAW_10
* CAM_FORMAT_MIPI_RAW_12
* CAM_FORMAT_MIPI_RAW_14
* CAM_FORMAT_MIPI_RAW_16
* CAM_FORMAT_MIPI_RAW_20
*/
for (i = 0; i < cre_acquire->num_in_res; i++) {
if ((cre_acquire->in_res[i].format <
CAM_FORMAT_MIPI_RAW_10) ||
(cre_acquire->in_res[i].format >
CAM_FORMAT_MIPI_RAW_20)) {
CAM_ERR(CAM_CRE, "Invalid Input format");
return -EINVAL;
switch (cre_acquire->in_res[i].format) {
case CAM_FORMAT_MIPI_RAW_10:
case CAM_FORMAT_MIPI_RAW_12:
case CAM_FORMAT_MIPI_RAW_14:
case CAM_FORMAT_MIPI_RAW_20:
case CAM_FORMAT_PLAIN1128:
break;
default:
CAM_ERR(CAM_CRE, "Invalid input format %d",
cre_acquire->in_res[i].format);
return -EINVAL;
}
}
/*
* TODO: Confirm this with CRE HW folks
* Reffering CRE HPG supported output formats are
* CAM_FORMAT_PLAIN16_8
* CAM_FORMAT_PLAIN16_10
* CAM_FORMAT_PLAIN16_12
* CAM_FORMAT_PLAIN16_14
* CAM_FORMAT_PLAIN16_16
* CAM_FORMAT_PLAIN32_20
*/
for (i = 0; i < cre_acquire->num_out_res; i++) {
if ((cre_acquire->out_res[i].format <
CAM_FORMAT_PLAIN16_8) ||
(cre_acquire->out_res[i].format >
CAM_FORMAT_PLAIN32_20)) {
CAM_ERR(CAM_CRE, "Invalid output format");
return -EINVAL;
switch (cre_acquire->out_res[i].format) {
case CAM_FORMAT_PLAIN16_8:
case CAM_FORMAT_PLAIN16_10:
case CAM_FORMAT_PLAIN16_12:
case CAM_FORMAT_PLAIN16_14:
case CAM_FORMAT_PLAIN16_16:
case CAM_FORMAT_PLAIN32_20:
case CAM_FORMAT_PLAIN32:
case CAM_FORMAT_PLAIN1128:
break;
default:
CAM_ERR(CAM_CRE, "Invalid output format %d",
cre_acquire->out_res[i].format);
return -EINVAL;
}
}
@@ -1270,9 +1569,6 @@ static int cam_cre_get_acquire_info(struct cam_cre_hw_mgr *hw_mgr,
return -EFAULT;
}
if (cam_cre_validate_acquire_res_info(&ctx->cre_acquire))
return -EINVAL;
CAM_DBG(CAM_CRE, "top: %u %s %u %u %u",
ctx->cre_acquire.dev_type,
ctx->cre_acquire.dev_name,
@@ -1295,6 +1591,9 @@ static int cam_cre_get_acquire_info(struct cam_cre_hw_mgr *hw_mgr,
ctx->cre_acquire.out_res[i].format);
}
if (cam_cre_validate_acquire_res_info(&ctx->cre_acquire))
return -EINVAL;
return 0;
}
@@ -1626,6 +1925,8 @@ static int cam_cre_mgr_release_ctx(struct cam_cre_hw_mgr *hw_mgr, int ctx_id)
hw_mgr->ctx[ctx_id].req_cnt = 0;
hw_mgr->ctx[ctx_id].last_flush_req = 0;
hw_mgr->ctx[ctx_id].last_req_idx = 0;
hw_mgr->ctx[ctx_id].last_done_req_idx = 0;
cam_cre_put_free_ctx(hw_mgr, ctx_id);
rc = cam_cre_mgr_cre_clk_remove(hw_mgr, ctx_id);
@@ -1888,12 +2189,16 @@ static int cam_cre_mgr_prepare_hw_update(void *hw_priv,
return rc;
}
request_idx = find_first_zero_bit(ctx_data->bitmap, ctx_data->bits);
request_idx = find_next_zero_bit(ctx_data->bitmap,
ctx_data->bits, ctx_data->last_req_idx);
if (request_idx >= CAM_CTX_REQ_MAX || request_idx < 0) {
mutex_unlock(&ctx_data->ctx_mutex);
CAM_ERR(CAM_CRE, "Invalid ctx req slot = %d", request_idx);
return -EINVAL;
}
CAM_DBG(CAM_CRE, "req_idx %d last_req_idx %d bitmap size in bits %d",
request_idx, ctx_data->last_req_idx, ctx_data->bits);
ctx_data->last_req_idx = request_idx;
ctx_data->req_list[request_idx] =
kzalloc(sizeof(struct cam_cre_request), GFP_KERNEL);
@@ -1903,8 +2208,13 @@ static int cam_cre_mgr_prepare_hw_update(void *hw_priv,
rc = -ENOMEM;
goto req_mem_alloc_failed;
}
memset(ctx_data->req_list[request_idx], 0,
sizeof(struct cam_cre_request));
cre_req = ctx_data->req_list[request_idx];
cre_req->request_id = packet->header.request_id;
cre_req->frames_done = 0;
cre_req->req_idx = request_idx;
rc = cam_cre_mgr_process_io_cfg(hw_mgr, packet, ctx_data,
request_idx, prepare_args);
@@ -1987,8 +2297,13 @@ static int cam_cre_mgr_enqueue_config(struct cam_cre_hw_mgr *hw_mgr,
task_data->req_idx = cre_req->req_idx;
task_data->type = CRE_WORKQ_TASK_CMD_TYPE;
task->process_cb = cam_cre_mgr_process_cmd;
rc = cam_req_mgr_workq_enqueue_task(task, ctx_data,
CRM_TASK_PRIORITY_0);
if (ctx_data->cre_acquire.dev_type == CAM_CRE_DEV_TYPE_RT)
rc = cam_req_mgr_workq_enqueue_task(task, ctx_data,
CRM_TASK_PRIORITY_0);
else
rc = cam_req_mgr_workq_enqueue_task(task, ctx_data,
CRM_TASK_PRIORITY_1);
return rc;
}
@@ -2057,7 +2372,7 @@ static void cam_cre_mgr_print_io_bufs(struct cam_packet *packet,
int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info,
bool *mem_found)
{
dma_addr_t iova_addr;
dma_addr_t iova_addr;
size_t src_buf_size;
int i;
int j;
@@ -2158,6 +2473,8 @@ static int cam_cre_mgr_flush_req(struct cam_cre_ctx *ctx_data,
{
int idx;
int64_t request_id;
uint32_t evt_id;
struct cam_hw_done_event_data buf_data;
request_id = *(int64_t *)flush_args->flush_req_pending[0];
for (idx = 0; idx < CAM_CTX_REQ_MAX; idx++) {
@@ -2167,6 +2484,10 @@ static int cam_cre_mgr_flush_req(struct cam_cre_ctx *ctx_data,
if (ctx_data->req_list[idx]->request_id != request_id)
continue;
evt_id = CAM_CTX_EVT_ID_ERROR;
buf_data.evt_param = CAM_SYNC_CRE_EVENT_HW_ERR;
buf_data.request_id = ctx_data->req_list[idx]->request_id;
ctx_data->ctxt_event_cb(ctx_data->context_priv, evt_id, &buf_data);
ctx_data->req_list[idx]->request_id = 0;
cam_cre_free_io_config(ctx_data->req_list[idx]);
cam_free_clear(ctx_data->req_list[idx]);
@@ -2181,6 +2502,8 @@ static int cam_cre_mgr_flush_all(struct cam_cre_ctx *ctx_data,
struct cam_hw_flush_args *flush_args)
{
int i, rc;
uint32_t evt_id;
struct cam_hw_done_event_data buf_data;
mutex_lock(&ctx_data->ctx_mutex);
rc = cam_cre_mgr_reset_hw();
@@ -2189,6 +2512,10 @@ static int cam_cre_mgr_flush_all(struct cam_cre_ctx *ctx_data,
if (!ctx_data->req_list[i])
continue;
evt_id = CAM_CTX_EVT_ID_ERROR;
buf_data.evt_param = CAM_SYNC_CRE_EVENT_HW_ERR;
buf_data.request_id = ctx_data->req_list[i]->request_id;
ctx_data->ctxt_event_cb(ctx_data->context_priv, evt_id, &buf_data);
ctx_data->req_list[i]->request_id = 0;
cam_cre_free_io_config(ctx_data->req_list[i]);
cam_free_clear(ctx_data->req_list[i]);
@@ -2533,15 +2860,6 @@ static int cam_cre_create_debug_fs(void)
return -ENOMEM;
}
if (!debugfs_create_bool("frame_dump_enable",
0644,
cre_hw_mgr->dentry,
&cre_hw_mgr->frame_dump_enable)) {
CAM_ERR(CAM_CRE,
"failed to create dump_enable_debug");
goto err;
}
if (!debugfs_create_bool("dump_req_data_enable",
0644,
cre_hw_mgr->dentry,
@@ -2557,18 +2875,18 @@ err:
return -ENOMEM;
}
int cam_cre_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
int cam_cre_hw_mgr_init(struct device_node *of_node, void *hw_mgr,
int *iommu_hdl)
{
int i, rc = 0, j;
struct cam_hw_mgr_intf *hw_mgr_intf;
if (!of_node || !hw_mgr_hdl) {
if (!of_node || !hw_mgr) {
CAM_ERR(CAM_CRE, "Invalid args of_node %pK hw_mgr %pK",
of_node, hw_mgr_hdl);
of_node, hw_mgr);
return -EINVAL;
}
hw_mgr_intf = (struct cam_hw_mgr_intf *)hw_mgr_hdl;
hw_mgr_intf = (struct cam_hw_mgr_intf *)hw_mgr;
cre_hw_mgr = kzalloc(sizeof(struct cam_cre_hw_mgr), GFP_KERNEL);
if (!cre_hw_mgr) {

Переглянути файл

@@ -19,20 +19,12 @@
#include "cre_top.h"
#define CRE_CTX_MAX 32
#define CAM_FRAME_CMD_MAX 20
#define CRE_WORKQ_NUM_TASK 100
#define CRE_WORKQ_NUM_TASK 64
#define CRE_WORKQ_TASK_CMD_TYPE 1
#define CRE_WORKQ_TASK_MSG_TYPE 2
#define CRE_PACKET_SIZE 0
#define CRE_PACKET_TYPE 1
#define CRE_PACKET_OPCODE 2
#define CRE_PACKET_MAX_CMD_BUFS 4
#define CRE_FRAME_PROCESS_SUCCESS 0
#define CRE_FRAME_PROCESS_FAILURE 1
#define CRE_PACKET_MAX_CMD_BUFS 1
#define CRE_CTX_STATE_FREE 0
#define CRE_CTX_STATE_IN_USE 1
@@ -46,22 +38,18 @@
#define CAM_CRE_BW_CONFIG_UNKNOWN 0
#define CAM_CRE_BW_CONFIG_V2 2
#define CRE_DEV_MAX 1
#define CLK_HW_CRE 0x0
#define CLK_HW_MAX 0x1
#define CRE_DEVICE_IDLE_TIMEOUT 400
#define CRE_REQUEST_TIMEOUT 200
#define CAM_CRE_HW_CFG_Q_MAX 50
#define CAM_CRE_MAX_PER_PATH_VOTES 6
#define CAM_CRE_MAX_REG_SET 32
#define CAM_CRE_MAX_ACTIVE 8
/*
* Response time threshold in ms beyond which a request is not expected
* to be with CRE hw
*/
#define CAM_CRE_RESPONSE_TIME_THRESHOLD 100000
#define CAM_CRE_RESPONSE_TIME_THRESHOLD 300
/*
* struct cam_cre_irq_data
@@ -187,23 +175,6 @@ struct cre_clk_work_data {
void *data;
};
/**
* struct cre_debug_buffer
*
* @cpu_addr: CPU address
* @iova_addr: IOVA address
* @len: Buffer length
* @size: Buffer Size
* @offset: buffer offset
*/
struct cre_debug_buffer {
uintptr_t cpu_addr;
dma_addr_t iova_addr;
size_t len;
uint32_t size;
uint32_t offset;
};
struct plane_info {
uintptr_t cpu_addr;
dma_addr_t iova_addr;
@@ -213,7 +184,6 @@ struct plane_info {
uint32_t format;
uint32_t alignment;
uint32_t offset;
uint32_t x_init;
size_t len;
};
@@ -222,9 +192,10 @@ struct plane_info {
*
* @direction: Direction of a buffer
* @resource_type: Resource type of IO Buffer
* @format: Format
* @format: Format
* @fence: Fence
* @num_planes: Number of planes
* p_info: per plane info
*/
struct cre_io_buf {
uint32_t direction;
@@ -310,7 +281,6 @@ struct cam_cre_request {
uint32_t num_io_bufs[CRE_MAX_BATCH_SIZE];
uint32_t in_resource;
struct cre_reg_buffer cre_reg_buf[CRE_MAX_BATCH_SIZE];
struct cre_debug_buffer cre_debug_buf;
struct cre_io_buf *io_buf[CRE_MAX_BATCH_SIZE][CRE_MAX_IO_BUFS];
struct cam_cre_clk_bw_request clk_info;
struct cam_cre_clk_bw_req_internal_v2 clk_info_v2;
@@ -321,54 +291,54 @@ struct cam_cre_request {
/**
* struct cam_cre_ctx
*
* @context_priv: Private data of context
* @bitmap: Context bit map
* @bitmap_size: Context bit map size
* @bits: Context bit map bits
* @ctx_id: Context ID
* @ctx_state: State of a context
* @req_cnt: Requests count
* @ctx_mutex: Mutex for context
* @acquire_dev_cmd: Cam acquire command
* @cre_acquire: CRE acquire command
* @ctxt_event_cb: Callback of a context
* @req_list: Request List
* @last_req_time: Timestamp of last request
* @req_watch_dog: Watchdog for requests
* @req_watch_dog_reset_counter: Request reset counter
* @clk_info: CRE Ctx clock info
* @clk_watch_dog: Clock watchdog
* @clk_watch_dog_reset_counter: Reset counter
* @last_flush_req: last flush req for this ctx
* @ctx_id: Context ID
* @ctx_state: State of a context
* @req_cnt: Requests count
* @last_flush_req: last flush req for this ctx
* @last_req_time: Timestamp of last request
* @last_req_idx: Last submitted req index
* @last_done_req_idx: Last done req index
* @bitmap: Context bit map
* @bitmap_size: Context bit map size
* @bits: Context bit map bits
* @context_priv: Private data of context
* @iommu_hdl: smmu handle
* @ctx_mutex: Mutex for context
* @acquire_dev_cmd: Cam acquire command
* @cre_acquire: CRE acquire command
* @clk_info: CRE Ctx clock info
* @packet: Current packet to process
* @cre_top: Pointer to CRE top data structure
* @req_list: Request List
* @ctxt_event_cb: Callback of a context
*/
struct cam_cre_ctx {
void *context_priv;
size_t bitmap_size;
void *bitmap;
size_t bits;
uint32_t ctx_id;
uint32_t ctx_state;
uint32_t req_cnt;
struct mutex ctx_mutex;
struct cam_acquire_dev_cmd acquire_dev_cmd;
struct cam_cre_acquire_dev_info cre_acquire;
cam_hw_event_cb_func ctxt_event_cb;
struct cam_cre_request *req_list[CAM_CTX_REQ_MAX];
struct cam_cre_request *active_req;
uint64_t last_req_time;
struct cam_req_mgr_timer *req_watch_dog;
uint32_t req_watch_dog_reset_counter;
struct cam_cre_ctx_clk_info clk_info;
struct cam_req_mgr_timer *clk_watch_dog;
struct cre_top *cre_top;
uint32_t clk_watch_dog_reset_counter;
uint64_t last_flush_req;
uint64_t last_req_time;
uint64_t last_req_idx;
uint64_t last_done_req_idx;
void *bitmap;
size_t bitmap_size;
size_t bits;
void *context_priv;
int iommu_hdl;
struct mutex ctx_mutex;
struct cam_acquire_dev_cmd acquire_dev_cmd;
struct cam_cre_acquire_dev_info cre_acquire;
struct cam_cre_ctx_clk_info clk_info;
struct cre_top *cre_top;
struct cam_packet *packet;
struct cam_cre_request *req_list[CAM_CTX_REQ_MAX];
cam_hw_event_cb_func ctxt_event_cb;
};
/**
* struct cam_cre_hw_mgr
*
* @cren_cnt: CRE device cren count
* @cre_ctx_cnt: Open context count
* @hw_mgr_mutex: Mutex for HW manager
* @hw_mgr_lock: Spinlock for HW manager
@@ -391,11 +361,9 @@ struct cam_cre_ctx {
* @cre_dev_intf: CRE device interface
* @clk_info: CRE clock Info for HW manager
* @dentry: Pointer to CRE debugfs directory
* @frame_dump_enable: CRE frame setting dump enablement
* @dump_req_data_enable: CRE hang dump enablement
*/
struct cam_cre_hw_mgr {
int32_t cren_cnt;
uint32_t cre_ctx_cnt;
struct mutex hw_mgr_mutex;
spinlock_t hw_mgr_lock;
@@ -420,7 +388,6 @@ struct cam_cre_hw_mgr {
struct cam_soc_reg_map *reg_map[CRE_DEV_MAX][CRE_BASE_MAX];
struct cam_cre_clk_info clk_info;
struct dentry *dentry;
bool frame_dump_enable;
bool dump_req_data_enable;
};

Переглянути файл

@@ -2,30 +2,17 @@
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/of.h>
#include <linux/debugfs.h>
#include <linux/videodev2.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/iopoll.h>
#include <media/cam_cre.h>
#include "cam_io_util.h"
#include "cam_hw.h"
#include "cam_hw_intf.h"
#include "cre_core.h"
#include "cre_soc.h"
#include "cam_soc_util.h"
#include "cam_io_util.h"
#include "cam_cpas_api.h"
#include "cam_debug_util.h"
#include "cam_common_util.h"
#include "cre_core.h"
#include "cre_hw.h"
#include "cre_dev_intf.h"
#include "cre_bus_rd.h"
#include "cam_common_util.h"
#include <media/cam_cre.h>
static struct cre_bus_rd *bus_rd;
@@ -36,6 +23,55 @@ static struct cre_bus_rd *bus_rd;
cre_reg_buf->num_rd_reg_set++; \
} while (0)
static int cam_cre_bus_rd_in_port_idx(uint32_t input_port_id)
{
int i;
for (i = 0; i < CRE_MAX_IN_RES; i++)
if (bus_rd->in_port_to_rm[i].input_port_id ==
input_port_id)
return i;
return -EINVAL;
}
static void cam_cre_update_read_reg_val(struct plane_info p_info,
struct cam_cre_bus_rd_client_reg_val *rd_client_reg_val)
{
switch (p_info.format) {
case CAM_FORMAT_MIPI_RAW_10:
rd_client_reg_val->format = 0xd;
break;
case CAM_FORMAT_MIPI_RAW_12:
rd_client_reg_val->format = 0xe;
break;
case CAM_FORMAT_MIPI_RAW_14:
rd_client_reg_val->format = 0xf;
break;
case CAM_FORMAT_MIPI_RAW_20:
rd_client_reg_val->format = 0x13;
break;
case CAM_FORMAT_PLAIN128:
rd_client_reg_val->format = 0x0;
break;
default:
CAM_ERR(CAM_CRE, "Unsupported read format");
return;
}
CAM_DBG(CAM_CRE,
"format %d width(in bytes) %d height %d stride(in byte) %d",
p_info.format, p_info.width, p_info.height, p_info.stride);
CAM_DBG(CAM_CRE, "alignment 0x%x",
p_info.alignment);
/* Fetch engine width has to be updated in number of bytes */
rd_client_reg_val->img_width = p_info.stride;
rd_client_reg_val->stride = p_info.stride;
rd_client_reg_val->img_height = p_info.height;
rd_client_reg_val->alignment = p_info.alignment;
}
static int cam_cre_bus_rd_release(struct cam_cre_hw *cam_cre_hw_info,
int32_t ctx_id, void *data)
{
@@ -54,22 +90,17 @@ static int cam_cre_bus_rd_update(struct cam_cre_hw *cam_cre_hw_info,
int32_t ctx_id, struct cre_reg_buffer *cre_reg_buf, int batch_idx,
int io_idx, struct cam_cre_dev_prepare_req *prepare)
{
int k;
uint32_t req_idx, temp;
uint32_t rm_id;
uint32_t rsc_type;
int k, in_port_idx;
uint32_t req_idx, val;
uint32_t iova_base, iova_offset;
struct cam_hw_prepare_update_args *prepare_args;
struct cam_cre_ctx *ctx_data;
struct cam_cre_request *cre_request;
struct cre_io_buf *io_buf;
struct cre_bus_rd_ctx *bus_rd_ctx;
struct cam_cre_bus_rd_reg *rd_reg;
struct cam_cre_bus_rd_client_reg *rd_reg_client;
struct cam_cre_bus_rd_reg_val *rd_reg_val;
struct cam_cre_bus_rd_client_reg_val *rd_res_val_client;
struct cre_bus_in_port_to_rm *in_port_to_rm;
struct cre_bus_rd_io_port_info *io_port_info;
struct cam_cre_bus_rd_client_reg_val *rd_client_reg_val;
if (ctx_id < 0 || !prepare) {
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, prepare);
@@ -93,8 +124,6 @@ static int cam_cre_bus_rd_update(struct cam_cre_hw *cam_cre_hw_info,
cre_request = ctx_data->req_list[req_idx];
CAM_DBG(CAM_CRE, "req_idx = %d req_id = %lld",
req_idx, cre_request->request_id);
bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id];
io_port_info = &bus_rd_ctx->io_port_info;
rd_reg = cam_cre_hw_info->bus_rd_reg_offset;
rd_reg_val = cam_cre_hw_info->bus_rd_reg_val;
io_buf = cre_request->io_buf[batch_idx][io_idx];
@@ -106,15 +135,13 @@ static int cam_cre_bus_rd_update(struct cam_cre_hw *cam_cre_hw_info,
CAM_DBG(CAM_CRE, "batch:%d iobuf:%d direction:%d",
batch_idx, io_idx, io_buf->direction);
in_port_to_rm =
&bus_rd->in_port_to_rm[io_buf->resource_type - 1];
in_port_idx =
cam_cre_bus_rd_in_port_idx(io_buf->resource_type);
CAM_DBG(CAM_CRE, "in_port_idx %d", in_port_idx);
for (k = 0; k < io_buf->num_planes; k++) {
rsc_type = io_buf->resource_type - 1;
/* frame level info */
rm_id = in_port_to_rm->rm_port_id[k];
rd_reg_client = &rd_reg->rd_clients[rm_id];
rd_res_val_client = &rd_reg_val->rd_clients[rm_id];
rd_reg_client = &rd_reg->rd_clients[in_port_idx];
rd_client_reg_val = &rd_reg_val->rd_clients[in_port_idx];
/* security cfg */
update_cre_reg_set(cre_reg_buf,
@@ -127,11 +154,9 @@ static int cam_cre_bus_rd_update(struct cam_cre_hw *cam_cre_hw_info,
1);
/* ccif meta data */
temp = 0;
update_cre_reg_set(cre_reg_buf,
(rd_reg->offset + rd_reg_client->ccif_meta_data),
temp);
0);
/*
* As CRE have 36 Bit addressing support Image Address
* register will have 28 bit MSB of 36 bit iova.
@@ -148,40 +173,39 @@ static int cam_cre_bus_rd_update(struct cam_cre_hw *cam_cre_hw_info,
rd_reg->offset + rd_reg_client->addr_cfg,
iova_offset);
cam_cre_update_read_reg_val(io_buf->p_info[k],
rd_client_reg_val);
/* Buffer size */
update_cre_reg_set(cre_reg_buf,
rd_reg->offset + rd_reg_client->rd_width,
io_buf->p_info[k].width);
rd_client_reg_val->img_width);
update_cre_reg_set(cre_reg_buf,
rd_reg->offset + rd_reg_client->rd_height,
io_buf->p_info[k].height);
rd_client_reg_val->img_height);
/* stride */
update_cre_reg_set(cre_reg_buf,
rd_reg->offset + rd_reg_client->rd_stride,
io_buf->p_info[k].stride);
rd_client_reg_val->stride);
/* unpacker cfg : Mode and alignment */
temp = 0;
temp |= (io_buf->p_info[k].format &
rd_res_val_client->mode_mask) <<
rd_res_val_client->mode_shift;
temp |= (io_buf->p_info[k].alignment &
rd_res_val_client->alignment_mask) <<
rd_res_val_client->alignment_shift;
val = 0;
val |= (rd_client_reg_val->format &
rd_client_reg_val->format_mask) <<
rd_client_reg_val->format_shift;
val |= (rd_client_reg_val->alignment &
rd_client_reg_val->alignment_mask) <<
rd_client_reg_val->alignment_shift;
/* unpacker cfg : format and alignment */
update_cre_reg_set(cre_reg_buf,
rd_reg->offset + rd_reg_client->unpacker_cfg,
temp);
rd_reg->offset + rd_reg_client->unpacker_cfg,
val);
/* latency buffer allocation */
update_cre_reg_set(cre_reg_buf,
rd_reg->offset + rd_reg_client->latency_buf_allocation,
io_port_info->latency_buf_size);
/* Enable Debug cfg */
temp = 0xFFFF;
val = 0xFFFF;
update_cre_reg_set(cre_reg_buf,
rd_reg->offset + rd_reg_client->debug_status_cfg,
temp);
rd_reg->offset + rd_reg_client->debug_status_cfg,
val);
}
return 0;
@@ -197,12 +221,11 @@ static int cam_cre_bus_rd_prepare(struct cam_cre_hw *cam_cre_hw_info,
struct cam_cre_ctx *ctx_data;
struct cam_cre_request *cre_request;
struct cre_io_buf *io_buf;
struct cre_bus_rd_ctx *bus_rd_ctx;
struct cam_cre_bus_rd_reg *rd_reg;
struct cam_cre_bus_rd_reg_val *rd_reg_val;
struct cre_reg_buffer *cre_reg_buf;
int temp;
int val;
if (ctx_id < 0 || !data) {
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, data);
@@ -217,7 +240,6 @@ static int cam_cre_bus_rd_prepare(struct cam_cre_hw *cam_cre_hw_info,
CAM_DBG(CAM_CRE, "req_idx = %d req_id = %lld",
req_idx, cre_request->request_id);
bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id];
rd_reg = cam_cre_hw_info->bus_rd_reg_offset;
rd_reg_val = cam_cre_hw_info->bus_rd_reg_val;
@@ -238,29 +260,23 @@ static int cam_cre_bus_rd_prepare(struct cam_cre_hw *cam_cre_hw_info,
}
/* Go command */
temp = 0;
temp |= rd_reg_val->go_cmd;
temp |= rd_reg_val->static_prg & rd_reg_val->static_prg_mask;
val = 0;
val |= rd_reg_val->go_cmd;
val |= rd_reg_val->static_prg & rd_reg_val->static_prg_mask;
update_cre_reg_set(cre_reg_buf,
rd_reg->offset + rd_reg->input_if_cmd,
temp);
val);
}
for (i = 0; i < cre_reg_buf->num_rd_reg_set; i++) {
CAM_DBG(CAM_CRE, "CRE value 0x%x offset 0x%x",
cre_reg_buf->rd_reg_set[i].value,
cre_reg_buf->rd_reg_set[i].offset);
}
end:
return 0;
}
static int cam_cre_bus_rd_in_port_idx(uint32_t input_port_id)
{
int i;
for (i = 0; i < CRE_MAX_IN_RES; i++)
if (bus_rd->in_port_to_rm[i].input_port_id ==
input_port_id)
return i;
return -EINVAL;
}
static int cam_cre_bus_rd_acquire(struct cam_cre_hw *cam_cre_hw_info,
int32_t ctx_id, void *data)
{
@@ -271,7 +287,6 @@ static int cam_cre_bus_rd_acquire(struct cam_cre_hw *cam_cre_hw_info,
struct cam_cre_bus_rd_reg_val *bus_rd_reg_val;
int in_port_idx;
if (ctx_id < 0 || !data || !cam_cre_hw_info || ctx_id >= CRE_CTX_MAX) {
CAM_ERR(CAM_CRE, "Invalid data: %d %x %x",
ctx_id, data, cam_cre_hw_info);
@@ -295,12 +310,14 @@ static int cam_cre_bus_rd_acquire(struct cam_cre_hw *cam_cre_hw_info,
if (!in_acquire->in_res[i].width)
continue;
CAM_DBG(CAM_CRE, "i = %d format = %u width = %x height = %x",
CAM_DBG(CAM_CRE, "i = %d format = %u width = 0x%x height = 0x%x res id %d",
i, in_acquire->in_res[i].format,
in_acquire->in_res[i].width,
in_acquire->in_res[i].height);
in_acquire->in_res[i].height,
in_acquire->in_res[i].res_id);
in_port_idx = cam_cre_bus_rd_in_port_idx(i + 1);
in_port_idx =
cam_cre_bus_rd_in_port_idx(in_acquire->in_res[i].res_id);
if (in_port_idx < 0) {
CAM_ERR(CAM_CRE, "Invalid in_port_idx: %d", i + 1);
rc = -EINVAL;
@@ -308,21 +325,15 @@ static int cam_cre_bus_rd_acquire(struct cam_cre_hw *cam_cre_hw_info,
}
in_port_to_rm = &bus_rd->in_port_to_rm[in_port_idx];
if (!in_port_to_rm->num_rm) {
CAM_ERR(CAM_CRE, "Invalid format for Input port");
rc = -EINVAL;
goto end;
}
bus_rd_ctx->io_port_info.input_port_id[i] =
in_acquire->in_res[i].res_id;
bus_rd_ctx->io_port_info.input_format_type[i] =
in_acquire->in_res[i].format;
CAM_DBG(CAM_CRE, "i:%d port_id = %u format %u",
i, bus_rd_ctx->io_port_info.input_port_id[i],
bus_rd_ctx->io_port_info.input_format_type[i]);
i, in_acquire->in_res[i].res_id,
in_acquire->in_res[i].format);
}
end:
@@ -342,6 +353,9 @@ static int cam_cre_bus_rd_reg_set_update(struct cam_cre_hw *cam_cre_hw_info,
rd_reg_set = reg_set_upd_cmd->cre_reg_buf.rd_reg_set;
for (i = 0; i < num_reg_set; i++) {
CAM_DBG(CAM_CRE, "base 0x%x CRE value 0x%x offset 0x%x",
cam_cre_hw_info->bus_rd_reg_offset->base,
rd_reg_set[i].value, rd_reg_set[i].offset);
cam_io_w_mb(rd_reg_set[i].value,
cam_cre_hw_info->bus_rd_reg_offset->base + rd_reg_set[i].offset);
}
@@ -397,7 +411,7 @@ static int cam_cre_bus_rd_probe(struct cam_cre_hw *cam_cre_hw_info,
for (i = 0; i < bus_rd_reg_val->num_clients; i++) {
input_port_idx =
bus_rd_reg_val->rd_clients[i].input_port_id - 1;
bus_rd_reg_val->rd_clients[i].rm_port_id;
in_port_to_rm = &bus_rd->in_port_to_rm[input_port_idx];
rm_idx = in_port_to_rm->num_rm;
@@ -439,7 +453,6 @@ static int cam_cre_bus_rd_isr(struct cam_cre_hw *cam_cre_hw_info,
return -EINVAL;
}
CAM_DBG(CAM_CRE, "error 0x%x", irq_data->error);
bus_rd_reg = cam_cre_hw_info->bus_rd_reg_offset;
bus_rd_reg_val = cam_cre_hw_info->bus_rd_reg_val;

Переглянути файл

@@ -15,58 +15,17 @@
#include "cam_soc_util.h"
#include "cam_cre_hw_mgr.h"
/**
* struct cre_bus_rd_io_port_info
*
* @pixel_pattern: Pixel pattern
* @input_port_id: Port Id
* @input_format_type: Format type
* @latency_buf_size: Latency buffer size
*/
struct cre_bus_rd_io_port_info {
uint32_t pixel_pattern[CRE_MAX_IN_RES];
uint32_t input_port_id[CRE_MAX_IN_RES];
uint32_t input_format_type[CRE_MAX_IN_RES];
uint32_t latency_buf_size;
};
/**
* struct cre_bus_rd_io_port_batch
*
* num_batch: Number of batches
* io_port: CDM IO Port Info
*/
struct cre_bus_rd_io_port_batch {
uint32_t num_batch;
struct cre_bus_rd_io_port_info io_port[CRE_MAX_BATCH_SIZE];
};
/**
* struct cre_bus_rd_rm
*
* @rm_port_id: RM port ID
* @format_type: Format type
*/
struct cre_bus_rd_rm {
uint32_t rm_port_id;
uint32_t format_type;
};
/**
* struct cre_bus_rd_ctx
*
* @cre_acquire: CRE acquire structure
* @security_flag: security flag
* @num_in_ports: Number of in ports
* @io_port_info: IO port info
* @io_port_batch: IO port info
*/
struct cre_bus_rd_ctx {
struct cam_cre_acquire_dev_info *cre_acquire;
bool security_flag;
uint32_t num_in_ports;
struct cre_bus_rd_io_port_info io_port_info;
struct cre_bus_rd_io_port_batch io_port_batch;
};
/**

Переглянути файл

@@ -2,32 +2,19 @@
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/of.h>
#include <linux/debugfs.h>
#include <linux/videodev2.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/iopoll.h>
#include <media/cam_cre.h>
#include "cam_io_util.h"
#include "cam_hw.h"
#include "cam_hw_intf.h"
#include "cre_core.h"
#include "cre_soc.h"
#include "cam_soc_util.h"
#include "cam_io_util.h"
#include "cam_cpas_api.h"
#include "cam_debug_util.h"
#include "cam_common_util.h"
#include "cre_core.h"
#include "cre_hw.h"
#include "cre_dev_intf.h"
#include "cre_bus_wr.h"
#include "cam_common_util.h"
#include <media/cam_cre.h>
static struct cre_bus_wr *wr_info;
#define update_cre_reg_set(cre_reg_buf, off, val) \
do { \
cre_reg_buf->wr_reg_set[cre_reg_buf->num_wr_reg_set].offset = (off); \
@@ -35,6 +22,30 @@ static struct cre_bus_wr *wr_info;
cre_reg_buf->num_wr_reg_set++; \
} while (0)
static int cam_cre_translate_write_format(struct plane_info p_info,
struct cam_cre_bus_wr_client_reg_val *wr_client_reg_val)
{
CAM_DBG(CAM_CRE, "width 0x%x, height 0x%x stride 0x%x alignment 0x%x",
p_info.width, p_info.height, p_info.stride, p_info.alignment);
/* Number of output pixels */
wr_client_reg_val->width = p_info.width;
/* Number of output bytes */
wr_client_reg_val->stride = p_info.stride;
/* Number of output lines */
wr_client_reg_val->height = p_info.height;
wr_client_reg_val->alignment = p_info.alignment;
/*
* Update packer format to zero irrespective of output format
* This is as per the recomendation from CRE HW team for CRE 1.0
* This logic has to be updated for CRE 1.1
*/
wr_client_reg_val->format = 0;
return 0;
}
static int cam_cre_bus_wr_out_port_idx(uint32_t output_port_id)
{
int i;
@@ -59,6 +70,9 @@ static int cam_cre_bus_wr_reg_set_update(struct cam_cre_hw *cam_cre_hw_info,
wr_reg_set = reg_set_upd_cmd->cre_reg_buf.wr_reg_set;
for (i = 0; i < num_reg_set; i++) {
CAM_DBG(CAM_CRE, "base 0x%x CRE value 0x%x offset 0x%x",
cam_cre_hw_info->bus_wr_reg_offset->base,
wr_reg_set[i].value, wr_reg_set[i].offset);
cam_io_w_mb(wr_reg_set[i].value,
cam_cre_hw_info->bus_wr_reg_offset->base + wr_reg_set[i].offset);
}
@@ -84,23 +98,18 @@ static int cam_cre_bus_wr_update(struct cam_cre_hw *cam_cre_hw_info,
int batch_idx, int io_idx,
struct cre_reg_buffer *cre_reg_buf)
{
int k, out_port_idx;
uint32_t num_wm_ports;
uint32_t comb_idx = 0;
int rc, k, out_port_idx;
uint32_t req_idx;
uint32_t temp = 0;
uint32_t wm_port_id;
uint32_t val = 0;
uint32_t iova_base, iova_offset;
struct cam_hw_prepare_update_args *prepare_args;
struct cam_cre_ctx *ctx_data;
struct cam_cre_request *cre_request;
struct cre_io_buf *io_buf;
struct cre_bus_wr_ctx *bus_wr_ctx;
struct cam_cre_bus_wr_reg *wr_reg;
struct cam_cre_bus_wr_client_reg *wr_reg_client;
struct cam_cre_bus_wr_reg_val *wr_reg_val;
struct cam_cre_bus_wr_client_reg_val *wr_res_val_client;
struct cre_bus_out_port_to_wm *out_port_to_wm;
struct cam_cre_bus_wr_client_reg_val *wr_client_reg_val;
if (ctx_id < 0 || !prepare) {
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, prepare);
@@ -122,11 +131,10 @@ static int cam_cre_bus_wr_update(struct cam_cre_hw *cam_cre_hw_info,
req_idx = prepare->req_idx;
cre_request = ctx_data->req_list[req_idx];
bus_wr_ctx = wr_info->bus_wr_ctx[ctx_id];
wr_reg = cam_cre_hw_info->bus_wr_reg_offset;
wr_reg_val = cam_cre_hw_info->bus_wr_reg_val;
CAM_DBG(CAM_CRE, "req_idx = %d req_id = %lld offset = %d",
CAM_DBG(CAM_CRE, "req_idx = %d req_id = %lld",
req_idx, cre_request->request_id);
io_buf = cre_request->io_buf[batch_idx][io_idx];
@@ -140,25 +148,26 @@ static int cam_cre_bus_wr_update(struct cam_cre_hw *cam_cre_hw_info,
io_buf->resource_type);
return -EINVAL;
}
out_port_to_wm = &wr_info->out_port_to_wm[out_port_idx];
num_wm_ports = out_port_to_wm->num_wm;
CAM_DBG(CAM_CRE, "out_port_idx = %d", out_port_idx);
for (k = 0; k < io_buf->num_planes; k++) {
CAM_DBG(CAM_CRE, "comb_idx = %d p_idx = %d",
comb_idx, k);
/* frame level info */
wm_port_id = out_port_to_wm->wm_port_id[k];
wr_reg_client = &wr_reg->wr_clients[wm_port_id];
wr_res_val_client = &wr_reg_val->wr_clients[wm_port_id];
wr_reg_client = &wr_reg->wr_clients[out_port_idx];
wr_client_reg_val = &wr_reg_val->wr_clients[out_port_idx];
CAM_DBG(CAM_CRE, "wr_reg_client %x wr_client_reg_val %x",
wr_reg_client, wr_client_reg_val, wr_client_reg_val);
/* Core cfg: enable, Mode */
temp = 0;
temp |= ((wr_res_val_client->mode &
wr_res_val_client->mode_mask) <<
wr_res_val_client->mode_shift);
val = 0;
val |= ((wr_client_reg_val->mode &
wr_client_reg_val->mode_mask) <<
wr_client_reg_val->mode_shift);
val |= wr_client_reg_val->client_en;
update_cre_reg_set(cre_reg_buf,
wr_reg->offset + wr_reg_client->client_cfg,
temp);
val);
/*
* As CRE have 36 Bit addressing support Image Address
@@ -174,41 +183,43 @@ static int cam_cre_bus_wr_update(struct cam_cre_hw *cam_cre_hw_info,
wr_reg->offset + wr_reg_client->addr_cfg,
iova_offset);
rc = cam_cre_translate_write_format(io_buf->p_info[k],
wr_client_reg_val);
if (rc < 0)
return -EINVAL;
/* Buffer size */
temp = 0;
temp = io_buf->p_info[k].width;
temp |= (io_buf->p_info[k].height &
wr_res_val_client->height_mask) <<
wr_res_val_client->height_shift;
val = 0;
val = wr_client_reg_val->width;
val |= (wr_client_reg_val->height &
wr_client_reg_val->height_mask) <<
wr_client_reg_val->height_shift;
update_cre_reg_set(cre_reg_buf,
wr_reg->offset + wr_reg_client->img_cfg_0,
temp);
update_cre_reg_set(cre_reg_buf,
wr_reg->offset + wr_reg_client->img_cfg_1,
io_buf->p_info[k].x_init);
val);
/* stride */
update_cre_reg_set(cre_reg_buf,
wr_reg->offset + wr_reg_client->img_cfg_2,
io_buf->p_info[k].stride);
wr_client_reg_val->stride);
val = 0;
val |= ((wr_client_reg_val->format &
wr_client_reg_val->format_mask) <<
wr_client_reg_val->format_shift);
val |= ((wr_client_reg_val->alignment &
wr_client_reg_val->alignment_mask) <<
wr_client_reg_val->alignment_shift);
/* pack cfg : Format and alignment */
temp = 0;
temp |= ((io_buf->p_info[k].format &
wr_res_val_client->format_mask) <<
wr_res_val_client->format_shift);
temp |= ((io_buf->p_info[k].alignment &
wr_res_val_client->alignment_mask) <<
wr_res_val_client->alignment_shift);
update_cre_reg_set(cre_reg_buf,
wr_reg->offset + wr_reg_client->packer_cfg,
temp);
val);
/* Upadte debug status CFG*/
temp = 0xFFFF;
val = 0xFFFF;
update_cre_reg_set(cre_reg_buf,
wr_reg->offset + wr_reg_client->debug_status_cfg,
temp);
val);
}
return 0;
@@ -224,7 +235,6 @@ static int cam_cre_bus_wr_prepare(struct cam_cre_hw *cam_cre_hw_info,
struct cam_cre_ctx *ctx_data;
struct cam_cre_request *cre_request;
struct cre_io_buf *io_buf;
struct cre_bus_wr_ctx *bus_wr_ctx;
struct cre_reg_buffer *cre_reg_buf;
if (ctx_id < 0 || !data) {
@@ -234,7 +244,6 @@ static int cam_cre_bus_wr_prepare(struct cam_cre_hw *cam_cre_hw_info,
prepare = data;
ctx_data = prepare->ctx_data;
req_idx = prepare->req_idx;
bus_wr_ctx = wr_info->bus_wr_ctx[ctx_id];
cre_request = ctx_data->req_list[req_idx];
@@ -245,8 +254,8 @@ static int cam_cre_bus_wr_prepare(struct cam_cre_hw *cam_cre_hw_info,
cre_reg_buf = &cre_request->cre_reg_buf[i];
for (j = 0; j < cre_request->num_io_bufs[i]; j++) {
io_buf = cre_request->io_buf[i][j];
CAM_DBG(CAM_CRE, "batch = %d io buf num = %d dir = %d",
i, j, io_buf->direction);
CAM_DBG(CAM_CRE, "batch = %d io buf num = %d",
i, j);
if (io_buf->direction != CAM_BUF_OUTPUT)
continue;
@@ -292,10 +301,11 @@ static int cam_cre_bus_wr_acquire(struct cam_cre_hw *cam_cre_hw_info,
if (!in_acquire->out_res[i].width)
continue;
CAM_DBG(CAM_CRE, "i = %d format = %u width = %x height = %x",
CAM_DBG(CAM_CRE, "i = %d format = %u width = 0x%x height = 0x%x res_id %d",
i, in_acquire->out_res[i].format,
in_acquire->out_res[i].width,
in_acquire->out_res[i].height);
in_acquire->out_res[i].height,
in_acquire->in_res[i].res_id);
out_port_idx =
cam_cre_bus_wr_out_port_idx(in_acquire->out_res[i].res_id);
@@ -306,20 +316,12 @@ static int cam_cre_bus_wr_acquire(struct cam_cre_hw *cam_cre_hw_info,
goto end;
}
CAM_DBG(CAM_CRE, "out_port_idx %d", out_port_idx);
out_port_to_wr = &wr_info->out_port_to_wm[out_port_idx - 1];
out_port_to_wr = &wr_info->out_port_to_wm[out_port_idx];
if (!out_port_to_wr->num_wm) {
CAM_DBG(CAM_CRE, "Invalid format for Input port");
rc = -EINVAL;
goto end;
}
bus_wr_ctx->io_port_info.output_port_id[i] =
in_acquire->out_res[i].res_id;
bus_wr_ctx->io_port_info.output_format_type[i] =
in_acquire->out_res[i].format;
CAM_DBG(CAM_CRE, "i:%d port_id = %u",
i, bus_wr_ctx->io_port_info.output_port_id[i]);
}
end:
@@ -343,12 +345,12 @@ static int cam_cre_bus_wr_init(struct cam_cre_hw *cam_cre_hw_info,
bus_wr_reg = cam_cre_hw_info->bus_wr_reg_offset;
bus_wr_reg->base = dev_init->core_info->cre_hw_info->cre_bus_wr_base;
CAM_DBG(CAM_CRE, "bus_wr_reg->base 0x%x", bus_wr_reg->base);
cam_io_w_mb(bus_wr_reg_val->irq_mask_0,
cam_cre_hw_info->bus_wr_reg_offset->base +
bus_wr_reg->irq_mask_0);
bus_wr_reg->base + bus_wr_reg->irq_mask_0);
cam_io_w_mb(bus_wr_reg_val->irq_mask_1,
cam_cre_hw_info->bus_wr_reg_offset->base +
bus_wr_reg->irq_mask_1);
bus_wr_reg->base + bus_wr_reg->irq_mask_1);
return 0;
}
@@ -377,7 +379,7 @@ static int cam_cre_bus_wr_probe(struct cam_cre_hw *cam_cre_hw_info,
for (i = 0; i < bus_wr_reg_val->num_clients; i++) {
output_port_idx =
bus_wr_reg_val->wr_clients[i].output_port_id - 1;
bus_wr_reg_val->wr_clients[i].wm_port_id;
out_port_to_wm = &wr_info->out_port_to_wm[output_port_idx];
wm_idx = out_port_to_wm->num_wm;
out_port_to_wm->output_port_id =
@@ -391,12 +393,12 @@ static int cam_cre_bus_wr_probe(struct cam_cre_hw *cam_cre_hw_info,
out_port_to_wm = &wr_info->out_port_to_wm[i];
CAM_DBG(CAM_CRE, "output port id = %d",
out_port_to_wm->output_port_id);
CAM_DBG(CAM_CRE, "num_wms = %d",
out_port_to_wm->num_wm);
for (k = 0; k < out_port_to_wm->num_wm; k++) {
CAM_DBG(CAM_CRE, "wm port id = %d",
out_port_to_wm->wm_port_id[k]);
}
CAM_DBG(CAM_CRE, "num_wms = %d",
out_port_to_wm->num_wm);
for (k = 0; k < out_port_to_wm->num_wm; k++) {
CAM_DBG(CAM_CRE, "wm port id = %d",
out_port_to_wm->wm_port_id[k]);
}
}
return 0;
@@ -413,6 +415,7 @@ static int cam_cre_bus_wr_isr(struct cam_cre_hw *cam_cre_hw_info,
uint32_t debug_status_1;
uint32_t img_violation_status;
uint32_t violation_status;
int i;
if (!cam_cre_hw_info || !irq_data) {
CAM_ERR(CAM_CRE, "Invalid cam_cre_hw_info");
@@ -425,6 +428,10 @@ static int cam_cre_bus_wr_isr(struct cam_cre_hw *cam_cre_hw_info,
/* Read and Clear Top Interrupt status */
irq_status_0 = cam_io_r_mb(bus_wr_reg->base + bus_wr_reg->irq_status_0);
irq_status_1 = cam_io_r_mb(bus_wr_reg->base + bus_wr_reg->irq_status_1);
CAM_DBG(CAM_CRE, "BUS irq_status_0 0x%x irq_status_1 0x%x",
irq_status_0, irq_status_1);
cam_io_w_mb(irq_status_0,
bus_wr_reg->base + bus_wr_reg->irq_clear_0);
cam_io_w_mb(irq_status_1,
@@ -439,7 +446,8 @@ static int cam_cre_bus_wr_isr(struct cam_cre_hw *cam_cre_hw_info,
}
if ((irq_status_0 & bus_wr_reg_val->violation) ||
(irq_status_0 & bus_wr_reg_val->img_size_violation)) {
(irq_status_0 & bus_wr_reg_val->img_size_violation) ||
(irq_status_0 & bus_wr_reg_val->cons_violation)) {
irq_data->error = 1;
img_violation_status = cam_io_r_mb(bus_wr_reg->base +
bus_wr_reg->image_size_violation_status);
@@ -456,8 +464,14 @@ static int cam_cre_bus_wr_isr(struct cam_cre_hw *cam_cre_hw_info,
debug_status_0, debug_status_1);
}
if (irq_status_1 & bus_wr_reg_val->client_buf_done)
CAM_INFO(CAM_CRE, "Cleint 0 Buff done");
if (irq_status_0 & bus_wr_reg_val->comp_buf_done) {
for (i = 0; i < bus_wr_reg_val->num_clients; i++) {
if (irq_status_1 & bus_wr_reg_val->
wr_clients[i].client_buf_done)
CAM_INFO(CAM_CRE, "Cleint %d Buff done", i);
irq_data->wr_buf_done = 1 << i;
}
}
return 0;
}

Переглянути файл

@@ -15,43 +15,6 @@
#include "cam_soc_util.h"
#include "cam_cre_hw_mgr.h"
/**
* struct cre_bus_wr_io_port_info
*
* @num_frames_cmds: Number of frame commands
* @go_cmd_addr: GO command address
* @go_cmd_len: GO command length
*/
struct cre_bus_wr_io_port_info {
uint32_t num_frames_cmds;
uint32_t *go_cmd_addr;
uint32_t go_cmd_len;
uint32_t output_port_id[CRE_MAX_OUT_RES];
uint32_t output_format_type[CRE_MAX_OUT_RES];
};
/**
* struct cre_bus_wr_io_port_batch
*
* num_batch: Number of batches
* io_port: CDM IO Port Info
*/
struct cre_bus_wr_io_port_batch {
uint32_t num_batch;
struct cre_bus_wr_io_port_info io_port[CRE_MAX_BATCH_SIZE];
};
/**
* struct cre_bus_wr_wm
*
* @wm_port_id: WM port ID
* @format_type: Format type
*/
struct cre_bus_wr_wm {
uint32_t wm_port_id;
uint32_t format_type;
};
/**
* struct cre_bus_out_port_to_wm
*
@@ -72,14 +35,11 @@ struct cre_bus_out_port_to_wm {
* @cre_acquire: CRE acquire structure
* @security_flag: security flag
* @num_out_ports: Number of out ports
* @io_port_info: IO port info
*/
struct cre_bus_wr_ctx {
struct cam_cre_acquire_dev_info *cre_acquire;
bool security_flag;
uint32_t num_out_ports;
struct cre_bus_wr_io_port_info io_port_info;
struct cre_bus_wr_io_port_batch io_port_batch;
};
/**
@@ -94,5 +54,4 @@ struct cre_bus_wr {
struct cre_bus_out_port_to_wm out_port_to_wm[CRE_MAX_OUT_RES];
struct cre_bus_wr_ctx *bus_wr_ctx[CRE_CTX_MAX];
};
#endif /* CRE_BUS_WR_H */

Переглянути файл

@@ -4,9 +4,6 @@
*/
#include <linux/of.h>
#include <linux/debugfs.h>
#include <linux/videodev2.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/timer.h>
@@ -29,9 +26,6 @@
#define CAM_CRE_RESET_TIMEOUT msecs_to_jiffies(500)
#define CAM_CRE_FE_IRQ 0x4
#define CAM_CRE_WE_IRQ 0x2
struct cam_cre_irq_data irq_data;
static int cam_cre_caps_vote(struct cam_cre_device_core_info *core_info,
@@ -558,6 +552,7 @@ irqreturn_t cam_cre_irq(int irq_num, void *data)
cre_hw = core_info->cre_hw_info->cre_hw;
irq_data.error = 0;
irq_data.wr_buf_done = 0;
cam_cre_top_process(cre_hw, 0, CRE_HW_ISR, &irq_data);
@@ -567,10 +562,10 @@ irqreturn_t cam_cre_irq(int irq_num, void *data)
cam_cre_bus_rd_process(cre_hw, 0, CRE_HW_ISR, &irq_data);
spin_lock(&cre_dev->hw_lock);
CAM_DBG(CAM_CRE, "core_info->irq_cb.cre_hw_mgr_cb %x core_info->irq_cb.data %x",
core_info->irq_cb.cre_hw_mgr_cb, core_info->irq_cb.data);
if (core_info->irq_cb.cre_hw_mgr_cb && core_info->irq_cb.data)
if (irq_data.error ||
((irq_data.top_irq_status & CAM_CRE_WE_IRQ) &&
irq_data.wr_buf_done))
if (irq_data.error || irq_data.wr_buf_done)
core_info->irq_cb.cre_hw_mgr_cb(&irq_data,
sizeof(struct cam_hw_info),
core_info->irq_cb.data);

Переглянути файл

@@ -16,6 +16,11 @@
#include "cre_hw.h"
#include "cam_cre_hw_intf.h"
#define CAM_CRE_IDLE_IRQ 0x8
#define CAM_CRE_FE_IRQ 0x4
#define CAM_CRE_WE_IRQ 0x2
#define CAM_CRE_RESET_IRQ 0x1
/**
* struct cam_cre_cpas_vote
* @ahb_vote: AHB vote info

Переглянути файл

@@ -3,8 +3,6 @@
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mod_devicetable.h>
#include <linux/of_device.h>
#include <linux/timer.h>

Переглянути файл

@@ -14,11 +14,10 @@
#define MAX_CRE_RD_CLIENTS 1
#define MAX_CRE_WR_CLIENTS 1
#define CRE_TOP_BASE 0x1
#define CRE_QOS_BASE 0x2
#define CRE_BUS_RD 0x3
#define CRE_BUS_WR 0x4
#define CRE_BASE_MAX 0x5
#define CRE_TOP_BASE 0x0
#define CRE_BUS_RD 0x1
#define CRE_BUS_WR 0x2
#define CRE_BASE_MAX 0x3
#define CRE_WAIT_BUS_WR_RUP 0x1
#define CRE_WAIT_BUS_WR_DONE 0x2
@@ -133,9 +132,9 @@ struct cam_cre_bus_rd_client_reg_val {
uint32_t alignment;
uint32_t alignment_mask;
uint32_t alignment_shift;
uint32_t mode;
uint32_t mode_mask;
uint32_t mode_shift;
uint32_t format;
uint32_t format_mask;
uint32_t format_shift;
uint32_t latency_buf_size;
uint32_t latency_buf_size_mask;
uint32_t misr_cfg_en;
@@ -258,6 +257,7 @@ struct cam_cre_bus_wr_client_reg_val {
uint32_t x_init_mask;
uint32_t stride;
uint32_t stride_mask;
uint32_t client_buf_done;
uint32_t format;
uint32_t format_mask;
uint32_t format_shift;
@@ -291,7 +291,6 @@ struct cam_cre_bus_wr_reg_val {
uint32_t irq_status_1;
uint32_t irq_cmd_set;
uint32_t irq_cmd_clear;
uint32_t client_buf_done;
uint32_t frame_header_cfg_0;
uint32_t local_frame_header_cfg_0;
uint32_t iso_en;

Переглянути файл

@@ -12,22 +12,22 @@
#define CRE_BUS_WR_TYPE 0x2
static struct cam_cre_top_reg top_reg = {
.hw_version = 0xFA000,
.hw_cap = 0xFA004,
.debug_0 = 0xFA080,
.debug_1 = 0xFA084,
.debug_cfg = 0xFA0DC,
.testbus_ctrl = 0xFA1F4,
.scratch_0 = 0xFA1F8,
.irq_status = 0xFA00C,
.irq_mask = 0xFA010,
.irq_clear = 0xFA014,
.irq_set = 0xFA018,
.irq_cmd = 0xFA01C,
.reset_cmd = 0xFA008,
.core_clk_cfg_ctrl_0 = 0xFA020,
.core_clk_cfg_ctrl_1 = 0xFA024,
.top_spare = 0xFA1FC,
.hw_version = 0x000,
.hw_cap = 0x004,
.debug_0 = 0x080,
.debug_1 = 0x084,
.debug_cfg = 0x0DC,
.testbus_ctrl = 0x1F4,
.scratch_0 = 0x1F8,
.irq_status = 0x00C,
.irq_mask = 0x010,
.irq_clear = 0x014,
.irq_set = 0x018,
.irq_cmd = 0x01C,
.reset_cmd = 0x008,
.core_clk_cfg_ctrl_0 = 0x020,
.core_clk_cfg_ctrl_1 = 0x024,
.top_spare = 0x1FC,
};
struct cam_cre_top_reg_val top_reg_value = {
@@ -47,38 +47,38 @@ struct cam_cre_top_reg_val top_reg_value = {
};
struct cam_cre_bus_rd_reg bus_rd_reg = {
.hw_version = 0xFA400,
.irq_mask = 0xFA404,
.irq_clear = 0xFA408,
.irq_cmd = 0xFA40C,
.irq_status = 0xFA410,
.input_if_cmd = 0xFA414,
.irq_set = 0xFA418,
.misr_reset = 0xFA41C,
.security_cfg = 0xFA420,
.iso_cfg = 0xFA424,
.iso_seed = 0xFA428,
.test_bus_ctrl = 0xFA42C,
.hw_version = 0x00,
.irq_mask = 0x04,
.irq_clear = 0x08,
.irq_cmd = 0x0C,
.irq_status = 0x10,
.input_if_cmd = 0x14,
.irq_set = 0x18,
.misr_reset = 0x1C,
.security_cfg = 0x20,
.iso_cfg = 0x24,
.iso_seed = 0x28,
.test_bus_ctrl = 0x2C,
.num_clients = 1,
.rd_clients[0] = {
.core_cfg = 0xFA450,
.ccif_meta_data = 0xFA454,
.img_addr = 0xFA458,
.rd_width = 0xFA45C,
.rd_height = 0xFA460,
.rd_stride = 0xFA464,
.unpacker_cfg = 0xFA468,
.latency_buf_allocation = 0xFA47C,
.misr_cfg_0 = 0xFA484,
.misr_cfg_1 = 0xFA488,
.misr_rd_val = 0xFA48C,
.debug_status_cfg = 0xFA490,
.debug_status_0 = 0xFA494,
.debug_status_1 = 0xFA498,
.read_buff_cfg = 0xFA4A0,
.addr_cfg = 0xFA4A4,
.spare = 0xFA430,
.cons_violation = 0xFA434,
.core_cfg = 0x50,
.ccif_meta_data = 0x54,
.img_addr = 0x58,
.rd_width = 0x5C,
.rd_height = 0x60,
.rd_stride = 0x64,
.unpacker_cfg = 0x68,
.latency_buf_allocation = 0x7C,
.misr_cfg_0 = 0x84,
.misr_cfg_1 = 0x88,
.misr_rd_val = 0x8C,
.debug_status_cfg = 0x90,
.debug_status_0 = 0x94,
.debug_status_1 = 0x98,
.read_buff_cfg = 0xA0,
.addr_cfg = 0xA4,
.spare = 0x30,
.cons_violation = 0x34,
},
};
@@ -99,7 +99,6 @@ struct cam_cre_bus_wr_reg_val bus_wr_reg_value = {
.irq_status_1 = 0x1,
.irq_cmd_set = 0x10,
.irq_cmd_clear = 0x1,
.client_buf_done = 0x1,
.iso_en = 0x1,
.iso_en_mask = 0x1,
.misr_0_en = 0x1,
@@ -132,14 +131,15 @@ struct cam_cre_bus_wr_reg_val bus_wr_reg_value = {
.bw_limit_en = 0x1,
.bw_limit_en_mask = 0x1,
.bw_limit_counter_mask = 0x1fe,
.client_buf_done = 0x1,
.output_port_id = CAM_CRE_OUTPUT_IMAGE,
.wm_port_id = 1,
.wm_port_id = 0,
},
};
struct cam_cre_bus_rd_reg_val bus_rd_reg_value = {
.hw_version = 0x30000000,
.irq_mask = 0x7,
.irq_mask = 0x1, /* INFO_CONS_VIOLATION */
.rd_buf_done = 0x4,
.rup_done = 0x2,
.cons_violation = 0x1,
@@ -171,8 +171,8 @@ struct cam_cre_bus_rd_reg_val bus_rd_reg_value = {
.stripe_location_shift = 0x0,
.alignment_mask = 0x1,
.alignment_shift = 0x5,
.mode_mask = 0x1f,
.mode_shift = 0x0,
.format_mask = 0x1f,
.format_shift = 0x0,
.latency_buf_size_mask = 0xffff,
.misr_cfg_en_mask = 0x4,
.misr_cfg_samp_mode_mask = 0x3,
@@ -184,48 +184,48 @@ struct cam_cre_bus_rd_reg_val bus_rd_reg_value = {
};
struct cam_cre_bus_wr_reg bus_wr_reg = {
.hw_version = 0xFA700,
.cgc_override = 0xFA708,
.irq_mask_0 = 0xFA718,
.irq_mask_1 = 0xFA71C,
.irq_clear_0 = 0xFA720,
.irq_clear_1 = 0xFA724,
.irq_status_0 = 0xFA728,
.irq_status_1 = 0xFA72C,
.irq_cmd = 0xFA730,
.hw_version = 0x00,
.cgc_override = 0x08,
.irq_mask_0 = 0x18,
.irq_mask_1 = 0x1C,
.irq_clear_0 = 0x20,
.irq_clear_1 = 0x24,
.irq_status_0 = 0x28,
.irq_status_1 = 0x2C,
.irq_cmd = 0x30,
.frame_header_cfg_0 = 0x0,
.local_frame_header_cfg_0 = 0xFA74C,
.irq_set_0 = 0xFA750,
.irq_set_1 = 0xFA754,
.iso_cfg = 0xFA75C,
.violation_status = 0xFA764,
.image_size_violation_status = 0xFA770,
.perf_count_cfg_0 = 0xFA774,
.perf_count_cfg_1 = 0xFA778,
.perf_count_cfg_2 = 0xFA77C,
.perf_count_cfg_3 = 0xFA780,
.perf_count_val_0 = 0xFA794,
.perf_count_val_1 = 0xFA798,
.perf_count_val_2 = 0xFA79C,
.perf_count_val_3 = 0xFA7A0,
.perf_count_status = 0xFA7B4,
.misr_cfg_0 = 0xFA7B8,
.misr_cfg_1 = 0xFA7BC,
.misr_rd_sel = 0xFA7C8,
.misr_reset = 0xFA7CC,
.misr_val = 0xFA7D0,
.local_frame_header_cfg_0 = 0x4C,
.irq_set_0 = 0x50,
.irq_set_1 = 0x54,
.iso_cfg = 0x5C,
.violation_status = 0x64,
.image_size_violation_status = 0x70,
.perf_count_cfg_0 = 0x74,
.perf_count_cfg_1 = 0x78,
.perf_count_cfg_2 = 0x7C,
.perf_count_cfg_3 = 0x80,
.perf_count_val_0 = 0x94,
.perf_count_val_1 = 0x98,
.perf_count_val_2 = 0x9C,
.perf_count_val_3 = 0xA0,
.perf_count_status = 0xB4,
.misr_cfg_0 = 0xB8,
.misr_cfg_1 = 0xBC,
.misr_rd_sel = 0xC8,
.misr_reset = 0xCC,
.misr_val = 0xD0,
.wr_clients[0] = {
.client_cfg = 0xFA900,
.img_addr = 0xFA904,
.img_cfg_0 = 0xFA90C,
.img_cfg_1 = 0xFA910,
.img_cfg_2 = 0xFA914,
.bw_limit = 0xFA918,
.packer_cfg = 0xFA91C,
.addr_cfg = 0xFA970,
.debug_status_cfg = 0xFA984,
.debug_status_0 = 0xFA988,
.debug_status_1 = 0xFA98C,
.client_cfg = 0x200,
.img_addr = 0x204,
.img_cfg_0 = 0x20C,
.img_cfg_1 = 0x210,
.img_cfg_2 = 0x214,
.packer_cfg = 0x218,
.bw_limit = 0x21C,
.addr_cfg = 0x270,
.debug_status_cfg = 0x284,
.debug_status_0 = 0x288,
.debug_status_1 = 0x28C,
},
};

Переглянути файл

@@ -13,6 +13,6 @@
#define CAM_CRE_CTX_MAX 16
int cam_cre_hw_mgr_init(struct device_node *of_node,
uint64_t *hw_mgr_hdl, int *iommu_hdl);
void *hw_mgr, int *iommu_hdl);
#endif /* CAM_CRE_HW_MGR_INTF_H */

Переглянути файл

@@ -2,16 +2,9 @@
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/of.h>
#include <linux/debugfs.h>
#include <linux/videodev2.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/iopoll.h>
#include <linux/completion.h>
#include <media/cam_cre.h>
#include "cam_io_util.h"
@@ -21,7 +14,6 @@
#include "cre_soc.h"
#include "cam_soc_util.h"
#include "cam_io_util.h"
#include "cam_cpas_api.h"
#include "cam_debug_util.h"
#include "cre_hw.h"
#include "cre_dev_intf.h"
@@ -155,6 +147,7 @@ static int cam_cre_top_init(struct cam_cre_hw *cre_hw_info,
/* CRE SW RESET */
init_completion(&cre_top_info.reset_complete);
init_completion(&cre_top_info.idle_done);
init_completion(&cre_top_info.bufdone);
/* enable interrupt mask */
cam_io_w_mb(top_reg_val->irq_mask,

Переглянути файл

@@ -40,6 +40,7 @@ struct cre_top {
struct cre_top_ctx top_ctx[CAM_CRE_CTX_MAX];
struct completion reset_complete;
struct completion idle_done;
struct completion bufdone;
struct mutex cre_hw_mutex;
spinlock_t hw_lock;
};