msm: camera: cre: Add CRE driver changes
Add new camera driver Camera Reformat Engine (CRE). CRs-Fixed: 2893978 Change-Id: Ia39b222493393bf7bb72525c86f0060ca0dc77c2 Signed-off-by: Vikram Sharma <vikramsa@codeaurora.org>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
4aa9286fd7
commit
23762a67ed
11
Kbuild
11
Kbuild
@@ -241,6 +241,17 @@ camera-$(CONFIG_SPECTRA_OPE) += \
|
||||
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.o\
|
||||
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.o
|
||||
|
||||
camera-$(CONFIG_SPECTRA_CRE) += \
|
||||
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_core.o \
|
||||
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_soc.o \
|
||||
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_dev.o \
|
||||
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/top/cre_top.o \
|
||||
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_rd/cre_bus_rd.o \
|
||||
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_wr/cre_bus_wr.o \
|
||||
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.o \
|
||||
drivers/cam_cre/cam_cre_dev.o \
|
||||
drivers/cam_cre/cam_cre_context.o
|
||||
|
||||
camera-$(CONFIG_SPECTRA_TFE) += \
|
||||
drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.o \
|
||||
drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.o \
|
||||
|
287
drivers/cam_cre/cam_cre_context.c
Normal file
287
drivers/cam_cre/cam_cre_context.c
Normal file
@@ -0,0 +1,287 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "cam_trace.h"
|
||||
#include "cam_mem_mgr.h"
|
||||
#include "cam_cre_context.h"
|
||||
#include "cam_context_utils.h"
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_packet_util.h"
|
||||
#include "cam_context.h"
|
||||
|
||||
static const char cre_dev_name[] = "cam-cre";
|
||||
|
||||
static int __cam_cre_start_dev_in_acquired(struct cam_context *ctx,
|
||||
struct cam_start_stop_dev_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cam_context_start_dev_to_hw(ctx, cmd);
|
||||
if (!rc) {
|
||||
ctx->state = CAM_CTX_READY;
|
||||
trace_cam_context_state("CRE", ctx);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int __cam_cre_ctx_flush_dev_in_ready(struct cam_context *ctx,
|
||||
struct cam_flush_dev_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cam_context_flush_dev_to_hw(ctx, cmd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Failed to flush device");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_cre_ctx_dump_dev_in_ready(struct cam_context *ctx,
|
||||
struct cam_dump_req_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cam_context_dump_dev_to_hw(ctx, cmd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Failed to dump device");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_cre_ctx_config_dev_in_ready(struct cam_context *ctx,
|
||||
struct cam_config_dev_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
size_t len;
|
||||
uintptr_t packet_addr;
|
||||
|
||||
rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle,
|
||||
&packet_addr, &len);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CRE, "[%s][%d] Can not get packet address",
|
||||
ctx->dev_name, ctx->ctx_id);
|
||||
rc = -EINVAL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cam_context_prepare_dev_to_hw(ctx, cmd);
|
||||
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Failed to prepare device");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_cre_ctx_stop_dev_in_ready(struct cam_context *ctx,
|
||||
struct cam_start_stop_dev_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cam_context_stop_dev_to_hw(ctx);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Failed to stop device");
|
||||
|
||||
ctx->state = CAM_CTX_ACQUIRED;
|
||||
trace_cam_context_state("CRE", ctx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_cre_ctx_release_dev_in_acquired(struct cam_context *ctx,
|
||||
struct cam_release_dev_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cam_context_release_dev_to_hw(ctx, cmd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Unable to release device %d", rc);
|
||||
|
||||
ctx->state = CAM_CTX_AVAILABLE;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_cre_ctx_release_dev_in_ready(struct cam_context *ctx,
|
||||
struct cam_release_dev_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = __cam_cre_ctx_stop_dev_in_ready(ctx, NULL);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Failed to stop device");
|
||||
|
||||
rc = __cam_cre_ctx_release_dev_in_acquired(ctx, cmd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Failed to release device");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_cre_ctx_handle_buf_done_in_ready(void *ctx,
|
||||
uint32_t evt_id, void *done)
|
||||
{
|
||||
return cam_context_buf_done_from_hw(ctx, done, evt_id);
|
||||
}
|
||||
|
||||
static int cam_cre_context_dump_active_request(void *data,
|
||||
struct cam_smmu_pf_info *pf_info)
|
||||
{
|
||||
|
||||
struct cam_context *ctx = (struct cam_context *)data;
|
||||
struct cam_ctx_request *req = NULL;
|
||||
struct cam_ctx_request *req_temp = NULL;
|
||||
struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL;
|
||||
uint32_t resource_type = 0;
|
||||
int rc = 0;
|
||||
int closest_port;
|
||||
bool b_mem_found = false, b_ctx_found = false;
|
||||
|
||||
|
||||
if (!ctx) {
|
||||
CAM_ERR(CAM_CRE, "Invalid ctx");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CAM_INFO(CAM_CRE, "iommu fault for cre ctx %d state %d",
|
||||
ctx->ctx_id, ctx->state);
|
||||
|
||||
list_for_each_entry_safe(req, req_temp,
|
||||
&ctx->active_req_list, list) {
|
||||
pf_dbg_entry = &(req->pf_data);
|
||||
closest_port = -1;
|
||||
CAM_INFO(CAM_CRE, "req_id : %lld ", req->request_id);
|
||||
|
||||
rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet,
|
||||
&b_mem_found, &b_ctx_found, &resource_type, pf_info);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Failed to dump pf info");
|
||||
|
||||
if (b_mem_found)
|
||||
CAM_ERR(CAM_CRE, "Found page fault in req %lld %d",
|
||||
req->request_id, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_cre_ctx_acquire_dev_in_available(struct cam_context *ctx,
|
||||
struct cam_acquire_dev_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cam_context_acquire_dev_to_hw(ctx, cmd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Unable to Acquire device %d", rc);
|
||||
else
|
||||
ctx->state = CAM_CTX_ACQUIRED;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* top state machine */
|
||||
static struct cam_ctx_ops
|
||||
cam_cre_ctx_state_machine[CAM_CTX_STATE_MAX] = {
|
||||
/* Uninit */
|
||||
{
|
||||
.ioctl_ops = { },
|
||||
.crm_ops = { },
|
||||
.irq_ops = NULL,
|
||||
},
|
||||
/* Available */
|
||||
{
|
||||
.ioctl_ops = {
|
||||
.acquire_dev = __cam_cre_ctx_acquire_dev_in_available,
|
||||
},
|
||||
.crm_ops = { },
|
||||
.irq_ops = NULL,
|
||||
},
|
||||
/* Acquired */
|
||||
{
|
||||
.ioctl_ops = {
|
||||
.release_dev = __cam_cre_ctx_release_dev_in_acquired,
|
||||
.start_dev = __cam_cre_start_dev_in_acquired,
|
||||
.config_dev = __cam_cre_ctx_config_dev_in_ready,
|
||||
.flush_dev = __cam_cre_ctx_flush_dev_in_ready,
|
||||
.dump_dev = __cam_cre_ctx_dump_dev_in_ready,
|
||||
},
|
||||
.crm_ops = { },
|
||||
.irq_ops = __cam_cre_ctx_handle_buf_done_in_ready,
|
||||
.pagefault_ops = cam_cre_context_dump_active_request,
|
||||
},
|
||||
/* Ready */
|
||||
{
|
||||
.ioctl_ops = {
|
||||
.stop_dev = __cam_cre_ctx_stop_dev_in_ready,
|
||||
.release_dev = __cam_cre_ctx_release_dev_in_ready,
|
||||
.config_dev = __cam_cre_ctx_config_dev_in_ready,
|
||||
.flush_dev = __cam_cre_ctx_flush_dev_in_ready,
|
||||
.dump_dev = __cam_cre_ctx_dump_dev_in_ready,
|
||||
},
|
||||
.crm_ops = {},
|
||||
.irq_ops = __cam_cre_ctx_handle_buf_done_in_ready,
|
||||
.pagefault_ops = cam_cre_context_dump_active_request,
|
||||
},
|
||||
/* Activated */
|
||||
{
|
||||
.ioctl_ops = {},
|
||||
.crm_ops = {},
|
||||
.irq_ops = NULL,
|
||||
.pagefault_ops = cam_cre_context_dump_active_request,
|
||||
},
|
||||
};
|
||||
|
||||
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) {
|
||||
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,
|
||||
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;
|
||||
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cre_context_deinit(struct cam_cre_context *ctx)
|
||||
{
|
||||
if (!ctx || !ctx->base) {
|
||||
CAM_ERR(CAM_CRE, "Invalid params: %pK", ctx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cam_context_deinit(ctx->base);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
return 0;
|
||||
}
|
67
drivers/cam_cre/cam_cre_context.h
Normal file
67
drivers/cam_cre/cam_cre_context.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CRE_CONTEXT_H_
|
||||
#define _CAM_CRE_CONTEXT_H_
|
||||
|
||||
#include <media/cam_cre.h>
|
||||
|
||||
#include "cam_context.h"
|
||||
#include "cam_cre_hw_mgr_intf.h"
|
||||
|
||||
#define CAM_CRE_HW_EVENT_MAX 20
|
||||
|
||||
/**
|
||||
* struct cam_cre_context - CRE context
|
||||
* @base: Base cre cam context object
|
||||
* @req_base: Common request structure
|
||||
*/
|
||||
struct cam_cre_context {
|
||||
struct cam_context *base;
|
||||
struct cam_ctx_request req_base[CAM_CTX_REQ_MAX];
|
||||
};
|
||||
|
||||
/* cam cre context irq handling function type */
|
||||
typedef int (*cam_cre_hw_event_cb_func)(
|
||||
struct cam_cre_context *ctx_cre,
|
||||
void *evt_data);
|
||||
|
||||
/**
|
||||
* struct cam_cre_ctx_irq_ops - Function table for handling IRQ callbacks
|
||||
*
|
||||
* @irq_ops: Array of handle function pointers.
|
||||
*
|
||||
*/
|
||||
struct cam_cre_ctx_irq_ops {
|
||||
cam_cre_hw_event_cb_func irq_ops[CAM_CRE_HW_EVENT_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_cre_context_init()
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* cam_cre_context_deinit()
|
||||
*
|
||||
* @brief: Deinitialize function for the CRE context
|
||||
*
|
||||
* @ctx: CRE context obj to be deinitialized
|
||||
*
|
||||
*/
|
||||
int cam_cre_context_deinit(struct cam_cre_context *ctx);
|
||||
|
||||
#endif /* __CAM_CRE_CONTEXT_H__ */
|
232
drivers/cam_cre/cam_cre_dev.c
Normal file
232
drivers/cam_cre/cam_cre_dev.c
Normal file
@@ -0,0 +1,232 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "cam_node.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_cre_hw_mgr.h"
|
||||
#include "cam_cre_dev.h"
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_smmu_api.h"
|
||||
#include "camera_main.h"
|
||||
|
||||
#define CAM_CRE_DEV_NAME "cam-cre"
|
||||
|
||||
struct cam_cre_subdev {
|
||||
struct cam_subdev sd;
|
||||
struct cam_node *node;
|
||||
struct cam_context ctx[CRE_CTX_MAX];
|
||||
struct cam_cre_context ctx_cre[CRE_CTX_MAX];
|
||||
struct mutex cre_lock;
|
||||
int32_t open_cnt;
|
||||
int32_t reserved;
|
||||
};
|
||||
static struct cam_cre_subdev g_cre_dev;
|
||||
|
||||
static void cam_cre_dev_iommu_fault_handler(
|
||||
struct cam_smmu_pf_info *pf_info)
|
||||
{
|
||||
int i = 0;
|
||||
struct cam_node *node = NULL;
|
||||
|
||||
if (!pf_info || !pf_info->token) {
|
||||
CAM_ERR(CAM_ISP, "invalid token in page handler cb");
|
||||
return;
|
||||
}
|
||||
|
||||
node = (struct cam_node *)pf_info->token;
|
||||
|
||||
for (i = 0; i < node->ctx_size; i++)
|
||||
cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info);
|
||||
}
|
||||
|
||||
static int cam_cre_subdev_open(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
|
||||
mutex_lock(&g_cre_dev.cre_lock);
|
||||
g_cre_dev.open_cnt++;
|
||||
mutex_unlock(&g_cre_dev.cre_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_subdev_close(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_node *node = v4l2_get_subdevdata(sd);
|
||||
|
||||
|
||||
mutex_lock(&g_cre_dev.cre_lock);
|
||||
if (g_cre_dev.open_cnt <= 0) {
|
||||
CAM_DBG(CAM_CRE, "CRE subdev is already closed");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
g_cre_dev.open_cnt--;
|
||||
|
||||
if (!node) {
|
||||
CAM_ERR(CAM_CRE, "Node ptr is NULL");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (g_cre_dev.open_cnt == 0)
|
||||
cam_node_shutdown(node);
|
||||
|
||||
end:
|
||||
mutex_unlock(&g_cre_dev.cre_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_internal_ops cam_cre_subdev_internal_ops = {
|
||||
.close = cam_cre_subdev_close,
|
||||
.open = cam_cre_subdev_open,
|
||||
};
|
||||
|
||||
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;
|
||||
struct cam_node *node;
|
||||
int iommu_hdl = -1;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
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);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CRE, "CRE cam_subdev_probe failed %d", rc);
|
||||
goto err;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
for (i = 0; i < CAM_CRE_CTX_MAX; i++) {
|
||||
rc = cam_cre_context_init(&g_cre_dev.ctx_cre[i],
|
||||
&g_cre_dev.ctx[i],
|
||||
&node->hw_mgr_intf,
|
||||
i);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CRE, "CRE context init failed %d %d",
|
||||
i, rc);
|
||||
goto ctx_init_fail;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
cam_smmu_set_client_page_fault_handler(iommu_hdl,
|
||||
cam_cre_dev_iommu_fault_handler, node);
|
||||
|
||||
mutex_init(&g_cre_dev.cre_lock);
|
||||
|
||||
CAM_DBG(CAM_CRE, "Component bound successfully");
|
||||
|
||||
return rc;
|
||||
|
||||
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:
|
||||
if (cam_subdev_remove(&g_cre_dev.sd))
|
||||
CAM_ERR(CAM_CRE, "remove fail %d", rc);
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
rc = cam_subdev_remove(&g_cre_dev.sd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Unregister failed %d", rc);
|
||||
}
|
||||
|
||||
const static struct component_ops cam_cre_subdev_component_ops = {
|
||||
.bind = cam_cre_subdev_component_bind,
|
||||
.unbind = cam_cre_subdev_component_unbind,
|
||||
};
|
||||
|
||||
static int cam_cre_subdev_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &cam_cre_subdev_component_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_subdev_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_CRE, "Adding CRE component");
|
||||
rc = component_add(&pdev->dev, &cam_cre_subdev_component_ops);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "failed to add component rc: %d", rc);
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
static const struct of_device_id cam_cre_subdev_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,cam-cre",
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cam_cre_subdev_dt_match);
|
||||
|
||||
struct platform_driver cam_cre_subdev_driver = {
|
||||
.probe = cam_cre_subdev_probe,
|
||||
.remove = cam_cre_subdev_remove,
|
||||
.driver = {
|
||||
.name = "cam_cre",
|
||||
.of_match_table = cam_cre_subdev_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
int cam_cre_subdev_init_module(void)
|
||||
{
|
||||
return platform_driver_register(&cam_cre_driver);
|
||||
}
|
||||
|
||||
void cam_cre_subdev_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&cam_cre_driver);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("MSM CRE driver");
|
||||
MODULE_LICENSE("GPL v2");
|
43
drivers/cam_cre/cam_cre_dev.h
Normal file
43
drivers/cam_cre/cam_cre_dev.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CRE_DEV_H_
|
||||
#define _CAM_CRE_DEV_H_
|
||||
|
||||
#include "cam_subdev.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_context.h"
|
||||
#include "cam_cre_context.h"
|
||||
|
||||
/**
|
||||
* struct cam_cre_dev - Camera CRE V4l2 device node
|
||||
*
|
||||
* @sd: Commone camera subdevice node
|
||||
* @node: Pointer to cre subdevice
|
||||
* @ctx: CRE base context storage
|
||||
* @ctx_cre: CRE private context storage
|
||||
* @cre_mutex: CRE dev mutex
|
||||
* @open_cnt: Open device count
|
||||
*/
|
||||
struct cam_cre_dev {
|
||||
struct cam_subdev sd;
|
||||
struct cam_node *node;
|
||||
struct cam_context ctx[CAM_CRE_CTX_MAX];
|
||||
struct cam_cre_context ctx_cre[CAM_CRE_CTX_MAX];
|
||||
struct mutex cre_mutex;
|
||||
int32_t open_cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief : API to register CRE dev to platform framework.
|
||||
* @return struct platform_device pointer on success, or ERR_PTR() on error.
|
||||
*/
|
||||
int cam_cre_dev_init_module(void);
|
||||
|
||||
/**
|
||||
* @brief : API to remove CRE dev from platform framework.
|
||||
*/
|
||||
void cam_cre_dev_exit_module(void);
|
||||
#endif /* __CAM_CRE_DEV_H__ */
|
2689
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.c
Normal file
2689
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.c
Normal file
File diff suppressed because it is too large
Load Diff
447
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.h
Normal file
447
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.h
Normal file
@@ -0,0 +1,447 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef CAM_CRE_HW_MGR_H
|
||||
#define CAM_CRE_HW_MGR_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/completion.h>
|
||||
#include <media/cam_cre.h>
|
||||
|
||||
#include "cam_cre_hw_intf.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_hw_intf.h"
|
||||
#include "cam_req_mgr_workq.h"
|
||||
#include "cam_mem_mgr.h"
|
||||
#include "cam_context.h"
|
||||
#include "cre_top.h"
|
||||
|
||||
#define CRE_CTX_MAX 32
|
||||
#define CAM_FRAME_CMD_MAX 20
|
||||
|
||||
#define CRE_WORKQ_NUM_TASK 100
|
||||
#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_CTX_STATE_FREE 0
|
||||
#define CRE_CTX_STATE_IN_USE 1
|
||||
#define CRE_CTX_STATE_ACQUIRED 2
|
||||
#define CRE_CTX_STATE_RELEASE 3
|
||||
|
||||
#define CRE_MAX_IN_RES 2
|
||||
#define CRE_MAX_OUT_RES 2
|
||||
#define CRE_MAX_IO_BUFS 3
|
||||
|
||||
#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
|
||||
/*
|
||||
* Response time threshold in ms beyond which a request is not expected
|
||||
* to be with CRE hw
|
||||
*/
|
||||
#define CAM_CRE_RESPONSE_TIME_THRESHOLD 100000
|
||||
|
||||
/*
|
||||
* struct cam_cre_irq_data
|
||||
*
|
||||
* @error: IRQ error
|
||||
* @top_irq_status: CRE top irq status
|
||||
* @wr_buf_done: write engine buf done
|
||||
*/
|
||||
struct cam_cre_irq_data {
|
||||
uint32_t error;
|
||||
uint32_t top_irq_status;
|
||||
uint32_t wr_buf_done;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct cam_cre_hw_intf_data - CRE hw intf data
|
||||
*
|
||||
* @Brief: cre hw intf pointer and pid list data
|
||||
*
|
||||
* @devices: cre hw intf pointer
|
||||
* @num_devices: Number of CRE devices
|
||||
* @num_hw_pid: Number of pids for this hw
|
||||
* @hw_pid: cre hw pid values
|
||||
*
|
||||
*/
|
||||
struct cam_cre_hw_intf_data {
|
||||
struct cam_hw_intf *hw_intf;
|
||||
uint32_t num_hw_pid;
|
||||
uint32_t hw_pid[CRE_DEV_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_ctx_clk_info
|
||||
* @curr_fc: Context latest request frame cycles
|
||||
* @rt_flag: Flag to indicate real time request
|
||||
* @base_clk: Base clock to process the request
|
||||
* @reserved: Reserved field
|
||||
* @clk_rate: Supported clock rates for the context
|
||||
* @num_paths: Number of valid AXI paths
|
||||
* @axi_path: ctx based per path bw vote
|
||||
*/
|
||||
struct cam_ctx_clk_info {
|
||||
uint32_t curr_fc;
|
||||
uint32_t rt_flag;
|
||||
uint32_t base_clk;
|
||||
uint32_t reserved;
|
||||
int32_t clk_rate[CAM_MAX_VOTE];
|
||||
uint32_t num_paths;
|
||||
struct cam_axi_per_path_bw_vote axi_path[CAM_CRE_MAX_PER_PATH_VOTES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_cmd_generic_blob
|
||||
* @ctx: Current context info
|
||||
* @req_info_idx: Index used for request
|
||||
* @io_buf_addr: pointer to io buffer address
|
||||
*/
|
||||
struct cre_cmd_generic_blob {
|
||||
struct cam_cre_ctx *ctx;
|
||||
uint32_t req_idx;
|
||||
uint64_t *io_buf_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_clk_info
|
||||
* @base_clk: Base clock to process request
|
||||
* @curr_clk: Current clock of hadrware
|
||||
* @threshold: Threshold for overclk count
|
||||
* @over_clked: Over clock count
|
||||
* @num_paths: Number of AXI vote paths
|
||||
* @axi_path: Current per path bw vote info
|
||||
* @hw_type: IPE/BPS device type
|
||||
* @watch_dog: watchdog timer handle
|
||||
* @watch_dog_reset_counter: Counter for watch dog reset
|
||||
*/
|
||||
struct cam_cre_clk_info {
|
||||
uint32_t base_clk;
|
||||
uint32_t curr_clk;
|
||||
uint32_t threshold;
|
||||
uint32_t over_clked;
|
||||
uint32_t num_paths;
|
||||
struct cam_axi_per_path_bw_vote axi_path[CAM_CRE_MAX_PER_PATH_VOTES];
|
||||
uint32_t hw_type;
|
||||
struct cam_req_mgr_timer *watch_dog;
|
||||
uint32_t watch_dog_reset_counter;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_cmd_work_data
|
||||
*
|
||||
* @type: Type of work data
|
||||
* @data: Private data
|
||||
* @req_id: Request Idx
|
||||
*/
|
||||
struct cre_cmd_work_data {
|
||||
uint32_t type;
|
||||
void *data;
|
||||
int64_t req_idx;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_msg_work_data
|
||||
*
|
||||
* @type: Type of work data
|
||||
* @data: Private data
|
||||
* @irq_status: IRQ status
|
||||
*/
|
||||
struct cre_msg_work_data {
|
||||
uint32_t type;
|
||||
void *data;
|
||||
struct cam_cre_irq_data irq_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_clk_work_data
|
||||
*
|
||||
* @type: Type of work data
|
||||
* @data: Private data
|
||||
*/
|
||||
struct cre_clk_work_data {
|
||||
uint32_t type;
|
||||
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;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t stride;
|
||||
uint32_t format;
|
||||
uint32_t alignment;
|
||||
uint32_t offset;
|
||||
uint32_t x_init;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_io_buf
|
||||
*
|
||||
* @direction: Direction of a buffer
|
||||
* @resource_type: Resource type of IO Buffer
|
||||
* @format: Format
|
||||
* @fence: Fence
|
||||
* @num_planes: Number of planes
|
||||
*/
|
||||
struct cre_io_buf {
|
||||
uint32_t direction;
|
||||
uint32_t resource_type;
|
||||
uint32_t format;
|
||||
uint32_t fence;
|
||||
uint32_t num_planes;
|
||||
struct plane_info p_info[CAM_CRE_MAX_PLANES];
|
||||
};
|
||||
|
||||
struct cre_reg_set {
|
||||
uint32_t offset;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
struct cre_reg_buffer {
|
||||
uint32_t num_rd_reg_set;
|
||||
uint32_t num_wr_reg_set;
|
||||
struct cre_reg_set rd_reg_set[CAM_CRE_MAX_REG_SET];
|
||||
struct cre_reg_set wr_reg_set[CAM_CRE_MAX_REG_SET];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_clk_bw_request
|
||||
* @budget_ns: Time required to process frame
|
||||
* @frame_cycles: Frame cycles needed to process the frame
|
||||
* @rt_flag: Flag to indicate real time stream
|
||||
* @uncompressed_bw: Bandwidth required to process frame
|
||||
* @compressed_bw: Compressed bandwidth to process frame
|
||||
*/
|
||||
struct cam_cre_clk_bw_request {
|
||||
uint64_t budget_ns;
|
||||
uint32_t frame_cycles;
|
||||
uint32_t rt_flag;
|
||||
uint64_t uncompressed_bw;
|
||||
uint64_t compressed_bw;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_clk_bw_req_internal_v2
|
||||
* @budget_ns: Time required to process frame
|
||||
* @frame_cycles: Frame cycles needed to process the frame
|
||||
* @rt_flag: Flag to indicate real time stream
|
||||
* @reserved: Reserved for future use
|
||||
* @num_paths: Number of paths for per path bw vote
|
||||
* @axi_path: Per path vote info for CRE
|
||||
*/
|
||||
struct cam_cre_clk_bw_req_internal_v2 {
|
||||
uint64_t budget_ns;
|
||||
uint32_t frame_cycles;
|
||||
uint32_t rt_flag;
|
||||
uint32_t reserved;
|
||||
uint32_t num_paths;
|
||||
struct cam_axi_per_path_bw_vote axi_path[CAM_CRE_MAX_PER_PATH_VOTES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_request
|
||||
*
|
||||
* @request_id: Request Id
|
||||
* @req_idx: Index in request list
|
||||
* @state: Request state
|
||||
* @num_batch: Number of batches
|
||||
* @num_frame_bufs: Number of frame buffers
|
||||
* @num_pass_bufs: Number of pass Buffers
|
||||
* @num_io_bufs: Number of IO Buffers
|
||||
* @in_resource: Input resource
|
||||
* @cre_debug_buf: Debug buffer
|
||||
* @io_buf: IO config info of a request
|
||||
* @clk_info: Clock Info V1
|
||||
* @clk_info_v2: Clock Info V2
|
||||
* @hang_data: Debug data for HW error
|
||||
* @submit_timestamp: Submit timestamp to hw
|
||||
*/
|
||||
struct cam_cre_request {
|
||||
uint64_t request_id;
|
||||
uint32_t req_idx;
|
||||
uint32_t state;
|
||||
uint32_t num_batch;
|
||||
uint32_t num_frame_bufs;
|
||||
uint32_t num_pass_bufs;
|
||||
uint32_t num_io_bufs[CRE_MAX_BATCH_SIZE];
|
||||
uint32_t in_resource;
|
||||
struct cre_reg_buffer cre_reg_buf;
|
||||
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;
|
||||
struct cam_hw_mgr_dump_pf_data hang_data;
|
||||
ktime_t submit_timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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_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;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @iommu_hdl: CRE Handle
|
||||
* @iommu_sec_hdl: CRE Handle for secure
|
||||
* @num_cre: Number of CRE
|
||||
* @secure_mode: Mode of CRE creration
|
||||
* @ctx_bitmap: Context bit map
|
||||
* @ctx_bitmap_size: Context bit map size
|
||||
* @ctx_bits: Context bit map bits
|
||||
* @ctx: CRE context
|
||||
* @devices: CRE devices
|
||||
* @cre_caps: CRE capabilities
|
||||
* @cmd_work: Command work
|
||||
* @msg_work: Message work
|
||||
* @timer_work: Timer work
|
||||
* @cmd_work_data: Command work data
|
||||
* @msg_work_data: Message work data
|
||||
* @timer_work_data: Timer work data
|
||||
* @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;
|
||||
int32_t iommu_hdl;
|
||||
int32_t iommu_sec_hdl;
|
||||
uint32_t num_cre;
|
||||
bool secure_mode;
|
||||
void *ctx_bitmap;
|
||||
size_t ctx_bitmap_size;
|
||||
size_t ctx_bits;
|
||||
struct cam_cre_ctx ctx[CRE_CTX_MAX];
|
||||
struct cam_hw_intf **devices[CRE_DEV_MAX];
|
||||
struct cam_cre_query_cap_cmd cre_caps;
|
||||
|
||||
struct cam_req_mgr_core_workq *cmd_work;
|
||||
struct cam_req_mgr_core_workq *msg_work;
|
||||
struct cam_req_mgr_core_workq *timer_work;
|
||||
struct cre_cmd_work_data *cmd_work_data;
|
||||
struct cre_msg_work_data *msg_work_data;
|
||||
struct cre_clk_work_data *timer_work_data;
|
||||
struct cam_hw_intf *cre_dev_intf[CRE_DEV_MAX];
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_hw_ctx_data
|
||||
*
|
||||
* @context_priv: Context private data, cam_context from
|
||||
* acquire.
|
||||
* @ctx_mutex: Mutex for context
|
||||
* @cre_dev_acquire_info: Acquire device info
|
||||
* @ctxt_event_cb: Context callback function
|
||||
* @in_use: Flag for context usage
|
||||
* @wait_complete: Completion info
|
||||
* @last_flush_req: req id which was flushed last.
|
||||
*/
|
||||
struct cam_cre_hw_ctx_data {
|
||||
void *context_priv;
|
||||
struct mutex ctx_mutex;
|
||||
struct cam_cre_acquire_dev_info cre_dev_acquire_info;
|
||||
cam_hw_event_cb_func ctxt_event_cb;
|
||||
bool in_use;
|
||||
struct completion wait_complete;
|
||||
uint64_t last_flush_req;
|
||||
};
|
||||
#endif /* CAM_CRE_HW_MGR_H */
|
619
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_rd/cre_bus_rd.c
Normal file
619
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_rd/cre_bus_rd.c
Normal file
@@ -0,0 +1,619 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* 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 "cre_hw.h"
|
||||
#include "cre_dev_intf.h"
|
||||
#include "cre_bus_rd.h"
|
||||
|
||||
static struct cre_bus_rd *bus_rd;
|
||||
|
||||
#define update_cre_reg_set(cre_reg_buf, off, val) \
|
||||
do { \
|
||||
cre_reg_buf->rd_reg_set[cre_reg_buf->num_rd_reg_set].offset = (off); \
|
||||
cre_reg_buf->rd_reg_set[cre_reg_buf->num_rd_reg_set].value = (val); \
|
||||
cre_reg_buf->num_rd_reg_set++; \
|
||||
} while (0)
|
||||
|
||||
static int cam_cre_bus_rd_release(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
if (ctx_id < 0 || ctx_id >= CRE_CTX_MAX) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d", ctx_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vfree(bus_rd->bus_rd_ctx[ctx_id]);
|
||||
bus_rd->bus_rd_ctx[ctx_id] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_is_rm_enabled(
|
||||
struct cam_cre_request *cre_request,
|
||||
uint32_t batch_idx,
|
||||
uint32_t rm_id)
|
||||
{
|
||||
int i, k;
|
||||
struct cre_io_buf *io_buf;
|
||||
struct cre_bus_in_port_to_rm *in_port_to_rm;
|
||||
|
||||
if (batch_idx >= CRE_MAX_BATCH_SIZE) {
|
||||
CAM_ERR(CAM_CRE, "Invalid batch idx: %d", batch_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < cre_request->num_io_bufs[batch_idx]; i++) {
|
||||
io_buf = cre_request->io_buf[batch_idx][i];
|
||||
if (io_buf->direction != CAM_BUF_INPUT)
|
||||
continue;
|
||||
in_port_to_rm =
|
||||
&bus_rd->in_port_to_rm[io_buf->resource_type - 1];
|
||||
for (k = 0; k < io_buf->num_planes; k++) {
|
||||
if (rm_id ==
|
||||
in_port_to_rm->rm_port_id[k])
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t *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;
|
||||
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;
|
||||
|
||||
|
||||
if (ctx_id < 0 || !prepare) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, prepare);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (batch_idx >= CRE_MAX_BATCH_SIZE) {
|
||||
CAM_ERR(CAM_CRE, "Invalid batch idx: %d", batch_idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (io_idx >= CRE_MAX_IO_BUFS) {
|
||||
CAM_ERR(CAM_CRE, "Invalid IO idx: %d", io_idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prepare_args = prepare->prepare_args;
|
||||
ctx_data = prepare->ctx_data;
|
||||
req_idx = prepare->req_idx;
|
||||
|
||||
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];
|
||||
|
||||
CAM_DBG(CAM_CRE,
|
||||
"req_idx = %d req_id = %lld rsc %d",
|
||||
req_idx, cre_request->request_id,
|
||||
io_buf->resource_type);
|
||||
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];
|
||||
|
||||
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];
|
||||
|
||||
/* security cfg */
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
rd_reg->offset + rd_reg->security_cfg,
|
||||
ctx_data->cre_acquire.secure_mode & 0x1);
|
||||
|
||||
/* enable client */
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
rd_reg->offset + rd_reg_client->core_cfg,
|
||||
1);
|
||||
|
||||
/* ccif meta data */
|
||||
temp = 0;
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
(rd_reg->offset + rd_reg_client->ccif_meta_data),
|
||||
temp);
|
||||
|
||||
/* Address of the Image */
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
rd_reg->offset + rd_reg_client->img_addr,
|
||||
io_buf->p_info[k].iova_addr);
|
||||
|
||||
/* Buffer size */
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
rd_reg->offset + rd_reg_client->rd_width,
|
||||
io_buf->p_info[k].width);
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
rd_reg->offset + rd_reg_client->rd_height,
|
||||
io_buf->p_info[k].height);
|
||||
|
||||
/* stride */
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
rd_reg->offset + rd_reg_client->rd_stride,
|
||||
io_buf->p_info[k].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;
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
rd_reg->offset + rd_reg_client->unpacker_cfg,
|
||||
temp);
|
||||
|
||||
/* 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;
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
rd_reg->offset + rd_reg_client->debug_status_cfg,
|
||||
temp);
|
||||
}
|
||||
|
||||
|
||||
return (uint32_t *)cre_reg_buf;
|
||||
}
|
||||
|
||||
static uint32_t *cam_cre_bus_rm_disable(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, struct cam_cre_dev_prepare_req *prepare,
|
||||
int batch_idx, int rm_idx,
|
||||
struct cre_reg_buffer *cre_reg_buf)
|
||||
{
|
||||
uint32_t req_idx;
|
||||
struct cam_cre_ctx *ctx_data;
|
||||
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;
|
||||
|
||||
|
||||
if (ctx_id < 0 || !prepare) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, prepare);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (batch_idx >= CRE_MAX_BATCH_SIZE) {
|
||||
CAM_ERR(CAM_CRE, "Invalid batch idx: %d", batch_idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (rm_idx >= CAM_CRE_INPUT_IMAGES_MAX) {
|
||||
CAM_ERR(CAM_CRE, "Invalid read client: %d", rm_idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx_data = prepare->ctx_data;
|
||||
req_idx = prepare->req_idx;
|
||||
|
||||
bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id];
|
||||
rd_reg = cam_cre_hw_info->bus_rd_reg_offset;
|
||||
|
||||
rd_reg_client = &rd_reg->rd_clients[rm_idx];
|
||||
|
||||
/* Core cfg: enable, Mode */
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
rd_reg->offset + rd_reg_client->core_cfg,
|
||||
0);
|
||||
|
||||
return (uint32_t *)cre_reg_buf;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_rd_prepare(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
int i, j;
|
||||
uint32_t req_idx;
|
||||
int is_rm_enabled;
|
||||
struct cam_cre_dev_prepare_req *prepare;
|
||||
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;
|
||||
uint32_t *ret;
|
||||
|
||||
int temp;
|
||||
|
||||
if (ctx_id < 0 || !data) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, data);
|
||||
return -EINVAL;
|
||||
}
|
||||
prepare = data;
|
||||
|
||||
ctx_data = prepare->ctx_data;
|
||||
req_idx = prepare->req_idx;
|
||||
|
||||
cre_request = ctx_data->req_list[req_idx];
|
||||
cre_reg_buf = &cre_request->cre_reg_buf;
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; i < cre_request->num_batch; i++) {
|
||||
for (j = 0; j < cre_request->num_io_bufs[i]; j++) {
|
||||
io_buf = cre_request->io_buf[i][j];
|
||||
if (io_buf->direction != CAM_BUF_INPUT)
|
||||
continue;
|
||||
|
||||
CAM_DBG(CAM_CRE, "batch:%d iobuf:%d direction:%d",
|
||||
i, j, io_buf->direction);
|
||||
|
||||
ret = cam_cre_bus_rd_update(cam_cre_hw_info,
|
||||
ctx_id, cre_reg_buf, i, j, prepare);
|
||||
if (!ret) {
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable RMs which are not enabled */
|
||||
for (i = 0; i < cre_request->num_batch; i++) {
|
||||
for (j = 0; j < rd_reg_val->num_clients; j++) {
|
||||
is_rm_enabled = cam_cre_bus_is_rm_enabled(
|
||||
cre_request, i, j);
|
||||
if (is_rm_enabled < 0) {
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
if (is_rm_enabled)
|
||||
continue;
|
||||
|
||||
ret = cam_cre_bus_rm_disable(cam_cre_hw_info,
|
||||
ctx_id, prepare, i, j,
|
||||
cre_reg_buf);
|
||||
if (!ret) {
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Go command */
|
||||
temp = 0;
|
||||
temp |= rd_reg_val->go_cmd;
|
||||
temp |= 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);
|
||||
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)
|
||||
{
|
||||
int rc = 0, i;
|
||||
struct cam_cre_acquire_dev_info *in_acquire;
|
||||
struct cre_bus_rd_ctx *bus_rd_ctx;
|
||||
struct cre_bus_in_port_to_rm *in_port_to_rm;
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_rd->bus_rd_ctx[ctx_id] = vzalloc(sizeof(struct cre_bus_rd_ctx));
|
||||
if (!bus_rd->bus_rd_ctx[ctx_id]) {
|
||||
CAM_ERR(CAM_CRE, "Out of memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bus_rd->bus_rd_ctx[ctx_id]->cre_acquire = data;
|
||||
in_acquire = data;
|
||||
bus_rd_ctx = bus_rd->bus_rd_ctx[ctx_id];
|
||||
bus_rd_ctx->num_in_ports = in_acquire->num_in_res;
|
||||
bus_rd_ctx->security_flag = in_acquire->secure_mode;
|
||||
bus_rd_reg_val = cam_cre_hw_info->bus_rd_reg_val;
|
||||
|
||||
for (i = 0; i < in_acquire->num_in_res; i++) {
|
||||
if (!in_acquire->in_res[i].width)
|
||||
continue;
|
||||
|
||||
CAM_DBG(CAM_CRE, "i = %d format = %u width = %x height = %x",
|
||||
i, in_acquire->in_res[i].format,
|
||||
in_acquire->in_res[i].width,
|
||||
in_acquire->in_res[i].height);
|
||||
|
||||
in_port_idx = cam_cre_bus_rd_in_port_idx(i + 1);
|
||||
if (in_port_idx < 0) {
|
||||
CAM_ERR(CAM_CRE, "Invalid in_port_idx: %d", i + 1);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_rd_reg_set_update(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int i;
|
||||
uint32_t num_reg_set;
|
||||
struct cre_reg_set *rd_reg_set;
|
||||
struct cam_cre_dev_reg_set_update *reg_set_upd_cmd =
|
||||
(struct cam_cre_dev_reg_set_update *)data;
|
||||
|
||||
num_reg_set = reg_set_upd_cmd->cre_reg_buf.num_rd_reg_set;
|
||||
rd_reg_set = reg_set_upd_cmd->cre_reg_buf.rd_reg_set;
|
||||
|
||||
for (i = 0; i < num_reg_set; i++) {
|
||||
cam_io_w_mb(rd_reg_set[i].value,
|
||||
cam_cre_hw_info->bus_rd_reg_offset->base + rd_reg_set[i].offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_rd_init(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
struct cam_cre_bus_rd_reg_val *bus_rd_reg_val;
|
||||
struct cam_cre_bus_rd_reg *bus_rd_reg;
|
||||
struct cam_cre_dev_init *dev_init = data;
|
||||
|
||||
if (!cam_cre_hw_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cam_cre_hw_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_rd_reg_val = cam_cre_hw_info->bus_rd_reg_val;
|
||||
bus_rd_reg = cam_cre_hw_info->bus_rd_reg_offset;
|
||||
bus_rd_reg->base =
|
||||
dev_init->core_info->cre_hw_info->cre_hw->bus_rd_reg_offset->base;
|
||||
|
||||
/* enable interrupt mask */
|
||||
cam_io_w_mb(bus_rd_reg_val->irq_mask,
|
||||
cam_cre_hw_info->bus_rd_reg_offset->base + bus_rd_reg->irq_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_rd_probe(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int i, k, rm_idx;
|
||||
struct cam_cre_bus_rd_reg_val *bus_rd_reg_val;
|
||||
struct cam_cre_bus_rd_reg *bus_rd_reg;
|
||||
struct cre_bus_in_port_to_rm *in_port_to_rm;
|
||||
uint32_t input_port_idx;
|
||||
|
||||
if (!cam_cre_hw_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cam_cre_hw_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_rd = kzalloc(sizeof(struct cre_bus_rd), GFP_KERNEL);
|
||||
if (!bus_rd) {
|
||||
CAM_ERR(CAM_CRE, "Out of memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
bus_rd->cre_hw_info = cam_cre_hw_info;
|
||||
bus_rd_reg_val = cam_cre_hw_info->bus_rd_reg_val;
|
||||
bus_rd_reg = cam_cre_hw_info->bus_rd_reg_offset;
|
||||
|
||||
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;
|
||||
in_port_to_rm = &bus_rd->in_port_to_rm[input_port_idx];
|
||||
|
||||
rm_idx = in_port_to_rm->num_rm;
|
||||
in_port_to_rm->input_port_id =
|
||||
bus_rd_reg_val->rd_clients[i].input_port_id;
|
||||
in_port_to_rm->rm_port_id[rm_idx] =
|
||||
bus_rd_reg_val->rd_clients[i].rm_port_id;
|
||||
in_port_to_rm->num_rm++;
|
||||
}
|
||||
|
||||
for (i = 0; i < CRE_MAX_IN_RES; i++) {
|
||||
in_port_to_rm = &bus_rd->in_port_to_rm[i];
|
||||
CAM_DBG(CAM_CRE, "input port id = %d",
|
||||
in_port_to_rm->input_port_id);
|
||||
CAM_DBG(CAM_CRE, "num_rms = %d",
|
||||
in_port_to_rm->num_rm);
|
||||
for (k = 0; k < in_port_to_rm->num_rm; k++) {
|
||||
CAM_DBG(CAM_CRE, "rm port id = %d",
|
||||
in_port_to_rm->rm_port_id[k]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_rd_isr(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
uint32_t irq_status;
|
||||
uint32_t violation_status;
|
||||
uint32_t debug_status_0;
|
||||
uint32_t debug_status_1;
|
||||
struct cam_cre_bus_rd_reg *bus_rd_reg;
|
||||
struct cam_cre_bus_rd_reg_val *bus_rd_reg_val;
|
||||
struct cam_cre_irq_data *irq_data = data;
|
||||
|
||||
if (!cam_cre_hw_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid 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;
|
||||
|
||||
/* Read and Clear Top Interrupt status */
|
||||
irq_status = cam_io_r_mb(bus_rd_reg->base + bus_rd_reg->irq_status);
|
||||
cam_io_w_mb(irq_status,
|
||||
bus_rd_reg->base + bus_rd_reg->irq_clear);
|
||||
|
||||
cam_io_w_mb(bus_rd_reg_val->irq_cmd_clear,
|
||||
bus_rd_reg->base + bus_rd_reg->irq_cmd);
|
||||
|
||||
if (irq_status & bus_rd_reg_val->rup_done)
|
||||
CAM_DBG(CAM_CRE, "CRE Read Bus RUP done");
|
||||
|
||||
if (irq_status & bus_rd_reg_val->rd_buf_done)
|
||||
CAM_DBG(CAM_CRE, "CRE Read Bus Buff done");
|
||||
|
||||
if (irq_status & bus_rd_reg_val->cons_violation) {
|
||||
irq_data->error = 1;
|
||||
violation_status = cam_io_r_mb(bus_rd_reg->base +
|
||||
bus_rd_reg->rd_clients[0].cons_violation_status);
|
||||
debug_status_0 = cam_io_r_mb(bus_rd_reg->base +
|
||||
bus_rd_reg->rd_clients[0].debug_status_0);
|
||||
debug_status_1 = cam_io_r_mb(bus_rd_reg->base +
|
||||
bus_rd_reg->rd_clients[0].debug_status_1);
|
||||
CAM_DBG(CAM_CRE, "CRE Read Bus Violation");
|
||||
CAM_DBG(CAM_CRE,
|
||||
"violation status 0x%x debug status 0/1 0x%x/0x%x",
|
||||
violation_status, debug_status_0, debug_status_1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_cre_bus_rd_process(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, uint32_t cmd_id, void *data)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
|
||||
switch (cmd_id) {
|
||||
case CRE_HW_PROBE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PROBE: E");
|
||||
rc = cam_cre_bus_rd_probe(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PROBE: X");
|
||||
break;
|
||||
case CRE_HW_INIT:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_INIT: E");
|
||||
rc = cam_cre_bus_rd_init(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_INIT: X");
|
||||
break;
|
||||
case CRE_HW_ACQUIRE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_ACQUIRE: E");
|
||||
rc = cam_cre_bus_rd_acquire(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_ACQUIRE: X");
|
||||
break;
|
||||
case CRE_HW_RELEASE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_RELEASE: E");
|
||||
rc = cam_cre_bus_rd_release(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_RELEASE: X");
|
||||
break;
|
||||
case CRE_HW_PREPARE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PREPARE: E");
|
||||
rc = cam_cre_bus_rd_prepare(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PREPARE: X");
|
||||
break;
|
||||
case CRE_HW_ISR:
|
||||
rc = cam_cre_bus_rd_isr(cam_cre_hw_info, 0, data);
|
||||
break;
|
||||
case CRE_HW_REG_SET_UPDATE:
|
||||
rc = cam_cre_bus_rd_reg_set_update(cam_cre_hw_info, 0, data);
|
||||
break;
|
||||
case CRE_HW_DEINIT:
|
||||
case CRE_HW_START:
|
||||
case CRE_HW_STOP:
|
||||
case CRE_HW_FLUSH:
|
||||
case CRE_HW_CLK_UPDATE:
|
||||
case CRE_HW_BW_UPDATE:
|
||||
case CRE_HW_RESET:
|
||||
case CRE_HW_SET_IRQ_CB:
|
||||
rc = 0;
|
||||
CAM_DBG(CAM_CRE, "Unhandled cmds: %d", cmd_id);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_CRE, "Unsupported cmd: %d", cmd_id);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
98
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_rd/cre_bus_rd.h
Normal file
98
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_rd/cre_bus_rd.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef CRE_BUS_RD_H
|
||||
#define CRE_BUS_RD_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/completion.h>
|
||||
#include <media/cam_cre.h>
|
||||
#include "cre_hw.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_hw_intf.h"
|
||||
#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;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_bus_in_port_to_rm
|
||||
*
|
||||
* @input_port_id: Intput port ID
|
||||
* @num_rm: Number of RMs
|
||||
* @rm_port_id: RM port Id
|
||||
*/
|
||||
struct cre_bus_in_port_to_rm {
|
||||
uint32_t input_port_id;
|
||||
uint32_t num_rm;
|
||||
uint32_t rm_port_id[CRE_MAX_IN_RES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_bus_rd
|
||||
*
|
||||
* @cre_hw_info: CRE hardware info
|
||||
* @in_port_to_rm: IO port to RM mapping
|
||||
* @bus_rd_ctx: RM context
|
||||
*/
|
||||
struct cre_bus_rd {
|
||||
struct cam_cre_hw *cre_hw_info;
|
||||
struct cre_bus_in_port_to_rm in_port_to_rm[CRE_MAX_IN_RES];
|
||||
struct cre_bus_rd_ctx *bus_rd_ctx[CRE_CTX_MAX];
|
||||
struct completion reset_complete;
|
||||
};
|
||||
#endif /* CRE_BUS_RD_H */
|
613
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_wr/cre_bus_wr.c
Normal file
613
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_wr/cre_bus_wr.c
Normal file
@@ -0,0 +1,613 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* 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 "cre_hw.h"
|
||||
#include "cre_dev_intf.h"
|
||||
#include "cre_bus_wr.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); \
|
||||
cre_reg_buf->wr_reg_set[cre_reg_buf->num_wr_reg_set].value = (val); \
|
||||
cre_reg_buf->num_wr_reg_set++; \
|
||||
} while (0)
|
||||
|
||||
static int cam_cre_bus_en_port_idx(
|
||||
struct cam_cre_request *cre_request,
|
||||
uint32_t batch_idx,
|
||||
uint32_t output_port_id)
|
||||
{
|
||||
int i;
|
||||
struct cre_io_buf *io_buf;
|
||||
|
||||
if (batch_idx >= CRE_MAX_BATCH_SIZE) {
|
||||
CAM_ERR(CAM_CRE, "Invalid batch idx: %d", batch_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < cre_request->num_io_bufs[batch_idx]; i++) {
|
||||
io_buf = cre_request->io_buf[batch_idx][i];
|
||||
if (io_buf->direction != CAM_BUF_OUTPUT)
|
||||
continue;
|
||||
if (io_buf->resource_type == output_port_id)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_wr_out_port_idx(uint32_t output_port_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CRE_MAX_OUT_RES; i++)
|
||||
if (wr_info->out_port_to_wm[i].output_port_id == output_port_id)
|
||||
return i;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_wr_reg_set_update(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int i;
|
||||
uint32_t num_reg_set;
|
||||
struct cre_reg_set *wr_reg_set;
|
||||
struct cam_cre_dev_reg_set_update *reg_set_upd_cmd =
|
||||
(struct cam_cre_dev_reg_set_update *)data;
|
||||
|
||||
num_reg_set = reg_set_upd_cmd->cre_reg_buf.num_wr_reg_set;
|
||||
wr_reg_set = reg_set_upd_cmd->cre_reg_buf.wr_reg_set;
|
||||
|
||||
for (i = 0; i < num_reg_set; i++) {
|
||||
cam_io_w_mb(wr_reg_set[i].value,
|
||||
cam_cre_hw_info->bus_wr_reg_offset->base + wr_reg_set[i].offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_wr_release(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
if (ctx_id < 0 || ctx_id >= CRE_CTX_MAX) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d", ctx_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vfree(wr_info->bus_wr_ctx[ctx_id]);
|
||||
wr_info->bus_wr_ctx[ctx_id] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t *cam_cre_bus_wr_update(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, struct cam_cre_dev_prepare_req *prepare,
|
||||
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;
|
||||
uint32_t req_idx;
|
||||
uint32_t temp = 0;
|
||||
uint32_t wm_port_id;
|
||||
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;
|
||||
|
||||
if (ctx_id < 0 || !prepare) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, prepare);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (batch_idx >= CRE_MAX_BATCH_SIZE) {
|
||||
CAM_ERR(CAM_CRE, "Invalid batch idx: %d", batch_idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (io_idx >= CRE_MAX_IO_BUFS) {
|
||||
CAM_ERR(CAM_CRE, "Invalid IO idx: %d", io_idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prepare_args = prepare->prepare_args;
|
||||
ctx_data = prepare->ctx_data;
|
||||
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",
|
||||
req_idx, cre_request->request_id);
|
||||
|
||||
io_buf = cre_request->io_buf[batch_idx][io_idx];
|
||||
CAM_DBG(CAM_CRE, "batch = %d io buf num = %d dir = %d rsc %d",
|
||||
batch_idx, io_idx, io_buf->direction, io_buf->resource_type);
|
||||
|
||||
out_port_idx =
|
||||
cam_cre_bus_wr_out_port_idx(io_buf->resource_type);
|
||||
if (out_port_idx < 0) {
|
||||
CAM_ERR(CAM_CRE, "Invalid idx for rsc type: %d",
|
||||
io_buf->resource_type);
|
||||
return NULL;
|
||||
}
|
||||
out_port_to_wm = &wr_info->out_port_to_wm[out_port_idx];
|
||||
num_wm_ports = out_port_to_wm->num_wm;
|
||||
|
||||
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];
|
||||
|
||||
/* Core cfg: enable, Mode */
|
||||
temp = 0;
|
||||
temp |= ((wr_res_val_client->mode &
|
||||
wr_res_val_client->mode_mask) <<
|
||||
wr_res_val_client->mode_shift);
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
wr_reg->offset + wr_reg_client->client_cfg,
|
||||
temp);
|
||||
|
||||
/* Address of the Image */
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
wr_reg->offset + wr_reg_client->img_addr,
|
||||
io_buf->p_info[k].iova_addr);
|
||||
|
||||
/* 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;
|
||||
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);
|
||||
|
||||
/* stride */
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
wr_reg->offset + wr_reg_client->img_cfg_2,
|
||||
io_buf->p_info[k].stride);
|
||||
|
||||
/* 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);
|
||||
/* Upadte debug status CFG*/
|
||||
temp = 0xFFFF;
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
wr_reg->offset + wr_reg_client->debug_status_cfg,
|
||||
temp);
|
||||
}
|
||||
|
||||
return (uint32_t *)cre_reg_buf;
|
||||
}
|
||||
|
||||
static uint32_t *cam_cre_bus_wm_disable(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, struct cam_cre_dev_prepare_req *prepare,
|
||||
int batch_idx, int io_idx,
|
||||
struct cre_reg_buffer *cre_reg_buf)
|
||||
{
|
||||
int k;
|
||||
uint32_t num_wm_ports;
|
||||
uint32_t req_idx;
|
||||
uint32_t wm_port_id;
|
||||
struct cam_cre_ctx *ctx_data;
|
||||
struct cre_bus_wr_ctx *bus_wr_ctx;
|
||||
struct cam_cre_bus_wr_reg *wr_reg;
|
||||
struct cre_bus_out_port_to_wm *out_port_to_wm;
|
||||
struct cam_cre_bus_wr_client_reg *wr_reg_client;
|
||||
|
||||
|
||||
if (ctx_id < 0 || !prepare) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, prepare);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (batch_idx >= CRE_MAX_BATCH_SIZE) {
|
||||
CAM_ERR(CAM_CRE, "Invalid batch idx: %d", batch_idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx_data = prepare->ctx_data;
|
||||
req_idx = prepare->req_idx;
|
||||
|
||||
bus_wr_ctx = wr_info->bus_wr_ctx[ctx_id];
|
||||
wr_reg = cam_cre_hw_info->bus_wr_reg_offset;
|
||||
|
||||
CAM_DBG(CAM_CRE,
|
||||
"req_idx = %d out_idx %d b %d",
|
||||
req_idx, io_idx, batch_idx);
|
||||
|
||||
out_port_to_wm = &wr_info->out_port_to_wm[io_idx];
|
||||
num_wm_ports = out_port_to_wm->num_wm;
|
||||
|
||||
for (k = 0; k < num_wm_ports; 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];
|
||||
|
||||
/* Core cfg: enable, Mode */
|
||||
update_cre_reg_set(cre_reg_buf,
|
||||
wr_reg->offset + wr_reg_client->client_cfg,
|
||||
0);
|
||||
}
|
||||
|
||||
return (uint32_t *)cre_reg_buf;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_wr_prepare(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
int i, j = 0;
|
||||
uint32_t req_idx;
|
||||
struct cam_cre_dev_prepare_req *prepare;
|
||||
struct cam_cre_ctx *ctx_data;
|
||||
struct cam_cre_request *cre_request;
|
||||
struct cre_io_buf *io_buf;
|
||||
int io_buf_idx;
|
||||
struct cre_bus_wr_ctx *bus_wr_ctx;
|
||||
struct cre_reg_buffer *cre_reg_buf;
|
||||
uint32_t *ret;
|
||||
|
||||
if (ctx_id < 0 || !data) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, data);
|
||||
return -EINVAL;
|
||||
}
|
||||
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];
|
||||
cre_reg_buf = &cre_request->cre_reg_buf;
|
||||
|
||||
CAM_DBG(CAM_CRE, "req_idx = %d req_id = %lld offset = %d",
|
||||
req_idx, cre_request->request_id);
|
||||
|
||||
|
||||
for (i = 0; i < cre_request->num_batch; 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);
|
||||
if (io_buf->direction != CAM_BUF_OUTPUT)
|
||||
continue;
|
||||
|
||||
ret = cam_cre_bus_wr_update(cam_cre_hw_info,
|
||||
ctx_id, prepare, i, j,
|
||||
cre_reg_buf);
|
||||
if (!ret) {
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable WMs which are not enabled */
|
||||
for (i = 0; i < cre_request->num_batch; i++) {
|
||||
for (j = CRE_MAX_IN_RES; j <= CRE_MAX_OUT_RES; j++) {
|
||||
io_buf_idx = cam_cre_bus_en_port_idx(cre_request, i, j);
|
||||
if (io_buf_idx >= 0)
|
||||
continue;
|
||||
|
||||
io_buf_idx = cam_cre_bus_wr_out_port_idx(j);
|
||||
if (io_buf_idx < 0) {
|
||||
CAM_ERR(CAM_CRE, "Invalid idx for rsc type:%d",
|
||||
j);
|
||||
return io_buf_idx;
|
||||
}
|
||||
ret = cam_cre_bus_wm_disable(cam_cre_hw_info,
|
||||
ctx_id, prepare, i, io_buf_idx,
|
||||
cre_reg_buf);
|
||||
if (!ret) {
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_wr_acquire(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int rc = 0, i;
|
||||
struct cam_cre_acquire_dev_info *in_acquire;
|
||||
struct cre_bus_wr_ctx *bus_wr_ctx;
|
||||
struct cre_bus_out_port_to_wm *out_port_to_wr;
|
||||
int out_port_idx;
|
||||
|
||||
if (ctx_id < 0 || !data || ctx_id >= CRE_CTX_MAX) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, data);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wr_info->bus_wr_ctx[ctx_id] = vzalloc(sizeof(struct cre_bus_wr_ctx));
|
||||
if (!wr_info->bus_wr_ctx[ctx_id]) {
|
||||
CAM_ERR(CAM_CRE, "Out of memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
wr_info->bus_wr_ctx[ctx_id]->cre_acquire = data;
|
||||
in_acquire = data;
|
||||
bus_wr_ctx = wr_info->bus_wr_ctx[ctx_id];
|
||||
bus_wr_ctx->num_out_ports = in_acquire->num_out_res;
|
||||
bus_wr_ctx->security_flag = in_acquire->secure_mode;
|
||||
|
||||
for (i = 0; i < in_acquire->num_out_res; i++) {
|
||||
if (!in_acquire->out_res[i].width)
|
||||
continue;
|
||||
|
||||
CAM_DBG(CAM_CRE, "i = %d format = %u width = %x height = %x",
|
||||
i, in_acquire->out_res[i].format,
|
||||
in_acquire->out_res[i].width,
|
||||
in_acquire->out_res[i].height);
|
||||
|
||||
out_port_idx =
|
||||
cam_cre_bus_wr_out_port_idx(in_acquire->out_res[i].res_id);
|
||||
if (out_port_idx < 0) {
|
||||
CAM_DBG(CAM_CRE, "Invalid out_port_idx: %d",
|
||||
in_acquire->out_res[i].res_id);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
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:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_wr_init(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
struct cam_cre_bus_wr_reg_val *bus_wr_reg_val;
|
||||
struct cam_cre_bus_wr_reg *bus_wr_reg;
|
||||
struct cam_cre_dev_init *dev_init = data;
|
||||
|
||||
if (!cam_cre_hw_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cam_cre_hw_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wr_info->cre_hw_info = cam_cre_hw_info;
|
||||
bus_wr_reg_val = cam_cre_hw_info->bus_wr_reg_val;
|
||||
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_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);
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_wr_probe(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int i, k;
|
||||
struct cam_cre_bus_wr_reg_val *bus_wr_reg_val;
|
||||
struct cre_bus_out_port_to_wm *out_port_to_wm;
|
||||
uint32_t output_port_idx;
|
||||
uint32_t wm_idx;
|
||||
|
||||
if (!cam_cre_hw_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cam_cre_hw_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
wr_info = kzalloc(sizeof(struct cre_bus_wr), GFP_KERNEL);
|
||||
if (!wr_info) {
|
||||
CAM_ERR(CAM_CRE, "Out of memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
wr_info->cre_hw_info = cam_cre_hw_info;
|
||||
bus_wr_reg_val = cam_cre_hw_info->bus_wr_reg_val;
|
||||
|
||||
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;
|
||||
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 =
|
||||
bus_wr_reg_val->wr_clients[i].output_port_id;
|
||||
out_port_to_wm->wm_port_id[wm_idx] =
|
||||
bus_wr_reg_val->wr_clients[i].wm_port_id;
|
||||
out_port_to_wm->num_wm++;
|
||||
}
|
||||
|
||||
for (i = 0; i < CRE_MAX_OUT_RES; i++) {
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_bus_wr_isr(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
uint32_t irq_status_0, irq_status_1;
|
||||
struct cam_cre_bus_wr_reg *bus_wr_reg;
|
||||
struct cam_cre_bus_wr_reg_val *bus_wr_reg_val;
|
||||
struct cam_cre_irq_data *irq_data = data;
|
||||
uint32_t debug_status_0;
|
||||
uint32_t debug_status_1;
|
||||
uint32_t img_violation_status;
|
||||
uint32_t violation_status;
|
||||
|
||||
if (!cam_cre_hw_info || !irq_data) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cam_cre_hw_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_wr_reg = cam_cre_hw_info->bus_wr_reg_offset;
|
||||
bus_wr_reg_val = cam_cre_hw_info->bus_wr_reg_val;
|
||||
|
||||
/* 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_io_w_mb(irq_status_0,
|
||||
bus_wr_reg->base + bus_wr_reg->irq_clear_0);
|
||||
cam_io_w_mb(irq_status_1,
|
||||
bus_wr_reg->base + bus_wr_reg->irq_clear_1);
|
||||
|
||||
cam_io_w_mb(bus_wr_reg_val->irq_cmd_clear,
|
||||
bus_wr_reg->base + bus_wr_reg->irq_cmd);
|
||||
|
||||
if (irq_status_0 & bus_wr_reg_val->cons_violation) {
|
||||
irq_data->error = 1;
|
||||
CAM_ERR(CAM_CRE, "cre bus wr cons_violation");
|
||||
}
|
||||
|
||||
if ((irq_status_0 & bus_wr_reg_val->violation) ||
|
||||
(irq_status_0 & bus_wr_reg_val->img_size_violation)) {
|
||||
irq_data->error = 1;
|
||||
img_violation_status = cam_io_r_mb(bus_wr_reg->base +
|
||||
bus_wr_reg->image_size_violation_status);
|
||||
violation_status = cam_io_r_mb(bus_wr_reg->base +
|
||||
bus_wr_reg->violation_status);
|
||||
|
||||
debug_status_0 = cam_io_r_mb(bus_wr_reg->base +
|
||||
bus_wr_reg->wr_clients[0].debug_status_0);
|
||||
debug_status_1 = cam_io_r_mb(bus_wr_reg->base +
|
||||
bus_wr_reg->wr_clients[0].debug_status_1);
|
||||
CAM_ERR(CAM_CRE,
|
||||
"violation status 0x%x 0x%x debug status 0/1 0x%x/0x%x",
|
||||
violation_status, img_violation_status,
|
||||
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");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_cre_bus_wr_process(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, uint32_t cmd_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (cmd_id) {
|
||||
case CRE_HW_PROBE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PROBE: E");
|
||||
rc = cam_cre_bus_wr_probe(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PROBE: X");
|
||||
break;
|
||||
case CRE_HW_INIT:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_INIT: E");
|
||||
rc = cam_cre_bus_wr_init(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_INIT: X");
|
||||
break;
|
||||
case CRE_HW_ACQUIRE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_ACQUIRE: E");
|
||||
rc = cam_cre_bus_wr_acquire(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_ACQUIRE: X");
|
||||
break;
|
||||
case CRE_HW_RELEASE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_RELEASE: E");
|
||||
rc = cam_cre_bus_wr_release(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_RELEASE: X");
|
||||
break;
|
||||
case CRE_HW_PREPARE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PREPARE: E");
|
||||
rc = cam_cre_bus_wr_prepare(cam_cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PREPARE: X");
|
||||
break;
|
||||
case CRE_HW_REG_SET_UPDATE:
|
||||
rc = cam_cre_bus_wr_reg_set_update(cam_cre_hw_info, 0, data);
|
||||
break;
|
||||
case CRE_HW_DEINIT:
|
||||
case CRE_HW_START:
|
||||
case CRE_HW_STOP:
|
||||
case CRE_HW_FLUSH:
|
||||
case CRE_HW_CLK_UPDATE:
|
||||
case CRE_HW_BW_UPDATE:
|
||||
case CRE_HW_RESET:
|
||||
case CRE_HW_SET_IRQ_CB:
|
||||
rc = 0;
|
||||
CAM_DBG(CAM_CRE, "Unhandled cmds: %d", cmd_id);
|
||||
break;
|
||||
case CRE_HW_ISR:
|
||||
rc = cam_cre_bus_wr_isr(cam_cre_hw_info, 0, data);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_CRE, "Unsupported cmd: %d", cmd_id);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
98
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_wr/cre_bus_wr.h
Normal file
98
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/bus_wr/cre_bus_wr.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef CRE_BUS_WR_H
|
||||
#define CRE_BUS_WR_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/completion.h>
|
||||
#include <media/cam_cre.h>
|
||||
#include "cre_hw.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_hw_intf.h"
|
||||
#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
|
||||
*
|
||||
* @output_port_id: Output port ID
|
||||
* @num_combos: Number of combos
|
||||
* @num_wm: Number of WMs
|
||||
* @wm_port_id: WM port Id
|
||||
*/
|
||||
struct cre_bus_out_port_to_wm {
|
||||
uint32_t output_port_id;
|
||||
uint32_t num_wm;
|
||||
uint32_t wm_port_id[CRE_MAX_OUT_RES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_bus_wr_ctx
|
||||
*
|
||||
* @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;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_bus_wr
|
||||
*
|
||||
* @cre_hw_info: CRE hardware info
|
||||
* @out_port_to_wm: IO port to WM mapping
|
||||
* @bus_wr_ctx: WM context
|
||||
*/
|
||||
struct cre_bus_wr {
|
||||
struct cam_cre_hw *cre_hw_info;
|
||||
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 */
|
580
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_core.c
Normal file
580
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_core.c
Normal file
@@ -0,0 +1,580 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* 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/delay.h>
|
||||
#include <linux/timer.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_cre_hw_intf.h"
|
||||
#include "cam_cre_hw_mgr_intf.h"
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cam_debug_util.h"
|
||||
#include "cre_dev_intf.h"
|
||||
#include "cam_compat.h"
|
||||
#include "cre_bus_wr.h"
|
||||
#include "cre_bus_rd.h"
|
||||
|
||||
#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,
|
||||
struct cam_cre_dev_bw_update *cpas_vote)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (cpas_vote->ahb_vote_valid)
|
||||
rc = cam_cpas_update_ahb_vote(core_info->cpas_handle,
|
||||
&cpas_vote->ahb_vote);
|
||||
if (cpas_vote->axi_vote_valid)
|
||||
rc = cam_cpas_update_axi_vote(core_info->cpas_handle,
|
||||
&cpas_vote->axi_vote);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "cpas vote is failed: %d", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cre_get_hw_caps(void *hw_priv, void *get_hw_cap_args,
|
||||
uint32_t arg_size)
|
||||
{
|
||||
struct cam_hw_info *cre_dev = hw_priv;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_cre_device_core_info *core_info = NULL;
|
||||
struct cam_cre_hw_ver *cre_hw_ver;
|
||||
struct cam_cre_top_reg_val *top_reg_val;
|
||||
|
||||
if (!hw_priv) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cam_dev_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_info = &cre_dev->soc_info;
|
||||
core_info = (struct cam_cre_device_core_info *)cre_dev->core_info;
|
||||
|
||||
if ((!soc_info) || (!core_info)) {
|
||||
CAM_ERR(CAM_CRE, "soc_info = %x core_info = %x",
|
||||
soc_info, core_info);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!get_hw_cap_args) {
|
||||
CAM_ERR(CAM_CRE, "Invalid caps");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
top_reg_val = core_info->cre_hw_info->cre_hw->top_reg_val;
|
||||
cre_hw_ver = get_hw_cap_args;
|
||||
cre_hw_ver->hw_ver.major =
|
||||
(core_info->hw_version & top_reg_val->major_mask) >>
|
||||
top_reg_val->major_shift;
|
||||
cre_hw_ver->hw_ver.minor =
|
||||
(core_info->hw_version & top_reg_val->minor_mask) >>
|
||||
top_reg_val->minor_shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_dev_process_init(struct cam_cre_hw *cre_hw,
|
||||
void *cmd_args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = cam_cre_top_process(cre_hw, 0, CRE_HW_INIT, cmd_args);
|
||||
if (rc)
|
||||
goto top_init_fail;
|
||||
|
||||
rc = cam_cre_bus_rd_process(cre_hw, 0, CRE_HW_INIT, cmd_args);
|
||||
if (rc)
|
||||
goto bus_rd_init_fail;
|
||||
|
||||
rc = cam_cre_bus_wr_process(cre_hw, 0, CRE_HW_INIT, cmd_args);
|
||||
if (rc)
|
||||
goto bus_wr_init_fail;
|
||||
|
||||
return rc;
|
||||
|
||||
bus_wr_init_fail:
|
||||
rc = cam_cre_bus_rd_process(cre_hw, 0,
|
||||
CRE_HW_DEINIT, NULL);
|
||||
bus_rd_init_fail:
|
||||
rc = cam_cre_top_process(cre_hw, 0,
|
||||
CRE_HW_DEINIT, NULL);
|
||||
top_init_fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_process_init(struct cam_cre_hw *cre_hw,
|
||||
void *cmd_args)
|
||||
{
|
||||
return cam_cre_dev_process_init(cre_hw, cmd_args);
|
||||
}
|
||||
|
||||
int cam_cre_init_hw(void *device_priv,
|
||||
void *init_hw_args, uint32_t arg_size)
|
||||
{
|
||||
struct cam_hw_info *cre_dev = device_priv;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_cre_device_core_info *core_info = NULL;
|
||||
struct cam_cre_cpas_vote *cpas_vote;
|
||||
int rc = 0;
|
||||
struct cam_cre_dev_init *init;
|
||||
struct cam_cre_hw *cre_hw;
|
||||
|
||||
if (!device_priv) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cam_dev_info");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
soc_info = &cre_dev->soc_info;
|
||||
core_info = (struct cam_cre_device_core_info *)cre_dev->core_info;
|
||||
if ((!soc_info) || (!core_info)) {
|
||||
CAM_ERR(CAM_CRE, "soc_info = %pK core_info = %pK",
|
||||
soc_info, core_info);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
cre_hw = core_info->cre_hw_info->cre_hw;
|
||||
|
||||
cpas_vote = kzalloc(sizeof(struct cam_cre_cpas_vote), GFP_KERNEL);
|
||||
if (!cpas_vote) {
|
||||
CAM_ERR(CAM_ISP, "Out of memory");
|
||||
rc = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
|
||||
cpas_vote->ahb_vote.type = CAM_VOTE_ABSOLUTE;
|
||||
cpas_vote->ahb_vote.vote.level = CAM_SVS_VOTE;
|
||||
cpas_vote->axi_vote.num_paths = 1;
|
||||
cpas_vote->axi_vote.axi_path[0].path_data_type =
|
||||
CAM_AXI_PATH_DATA_ALL;
|
||||
cpas_vote->axi_vote.axi_path[0].transac_type =
|
||||
CAM_AXI_TRANSACTION_WRITE;
|
||||
cpas_vote->axi_vote.axi_path[0].camnoc_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
cpas_vote->axi_vote.axi_path[0].mnoc_ab_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
cpas_vote->axi_vote.axi_path[0].mnoc_ib_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
cpas_vote->axi_vote.axi_path[0].ddr_ab_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
cpas_vote->axi_vote.axi_path[0].ddr_ib_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
|
||||
rc = cam_cpas_start(core_info->cpas_handle,
|
||||
&cpas_vote->ahb_vote, &cpas_vote->axi_vote);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CRE, "cpass start failed: %d", rc);
|
||||
goto free_cpas_vote;
|
||||
}
|
||||
core_info->cpas_start = true;
|
||||
|
||||
rc = cam_cre_enable_soc_resources(soc_info);
|
||||
if (rc)
|
||||
goto enable_soc_resource_failed;
|
||||
else
|
||||
core_info->clk_enable = true;
|
||||
|
||||
init = init_hw_args;
|
||||
|
||||
init->core_info = core_info;
|
||||
rc = cam_cre_process_init(cre_hw, init_hw_args);
|
||||
if (rc)
|
||||
goto process_init_failed;
|
||||
else
|
||||
goto free_cpas_vote;
|
||||
|
||||
process_init_failed:
|
||||
if (cam_cre_disable_soc_resources(soc_info))
|
||||
CAM_ERR(CAM_CRE, "disable soc resource failed");
|
||||
enable_soc_resource_failed:
|
||||
if (cam_cpas_stop(core_info->cpas_handle))
|
||||
CAM_ERR(CAM_CRE, "cpas stop is failed");
|
||||
else
|
||||
core_info->cpas_start = false;
|
||||
free_cpas_vote:
|
||||
cam_free_clear((void *)cpas_vote);
|
||||
cpas_vote = NULL;
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cre_deinit_hw(void *device_priv,
|
||||
void *init_hw_args, uint32_t arg_size)
|
||||
{
|
||||
struct cam_hw_info *cre_dev = device_priv;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_cre_device_core_info *core_info = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (!device_priv) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cam_dev_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_info = &cre_dev->soc_info;
|
||||
core_info = (struct cam_cre_device_core_info *)cre_dev->core_info;
|
||||
if ((!soc_info) || (!core_info)) {
|
||||
CAM_ERR(CAM_CRE, "soc_info = %pK core_info = %pK",
|
||||
soc_info, core_info);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = cam_cre_disable_soc_resources(soc_info);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "soc disable is failed : %d", rc);
|
||||
core_info->clk_enable = false;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_dev_process_dump_debug_reg(struct cam_cre_hw *cre_hw)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = cam_cre_top_process(cre_hw, -1,
|
||||
CRE_HW_DUMP_DEBUG, NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_dev_process_reset(struct cam_cre_hw *cre_hw, void *cmd_args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = cam_cre_top_process(cre_hw, -1,
|
||||
CRE_HW_RESET, NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_dev_process_release(struct cam_cre_hw *cre_hw, void *cmd_args)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_cre_dev_release *cre_dev_release;
|
||||
|
||||
cre_dev_release = cmd_args;
|
||||
rc = cam_cre_top_process(cre_hw, cre_dev_release->ctx_id,
|
||||
CRE_HW_RELEASE, NULL);
|
||||
|
||||
rc |= cam_cre_bus_rd_process(cre_hw, cre_dev_release->ctx_id,
|
||||
CRE_HW_RELEASE, NULL);
|
||||
|
||||
rc |= cam_cre_bus_wr_process(cre_hw, cre_dev_release->ctx_id,
|
||||
CRE_HW_RELEASE, NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_dev_process_acquire(struct cam_cre_hw *cre_hw, void *cmd_args)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_cre_dev_acquire *cre_dev_acquire;
|
||||
|
||||
if (!cmd_args || !cre_hw) {
|
||||
CAM_ERR(CAM_CRE, "Invalid arguments: %pK %pK",
|
||||
cmd_args, cre_hw);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cre_dev_acquire = cmd_args;
|
||||
rc = cam_cre_top_process(cre_hw, cre_dev_acquire->ctx_id,
|
||||
CRE_HW_ACQUIRE, cre_dev_acquire);
|
||||
if (rc)
|
||||
goto top_acquire_fail;
|
||||
|
||||
rc = cam_cre_bus_rd_process(cre_hw, cre_dev_acquire->ctx_id,
|
||||
CRE_HW_ACQUIRE, cre_dev_acquire->cre_acquire);
|
||||
if (rc)
|
||||
goto bus_rd_acquire_fail;
|
||||
|
||||
rc = cam_cre_bus_wr_process(cre_hw, cre_dev_acquire->ctx_id,
|
||||
CRE_HW_ACQUIRE, cre_dev_acquire->cre_acquire);
|
||||
if (rc)
|
||||
goto bus_wr_acquire_fail;
|
||||
|
||||
return 0;
|
||||
|
||||
bus_wr_acquire_fail:
|
||||
cam_cre_bus_rd_process(cre_hw, cre_dev_acquire->ctx_id,
|
||||
CRE_HW_RELEASE, cre_dev_acquire->cre_acquire);
|
||||
bus_rd_acquire_fail:
|
||||
cam_cre_top_process(cre_hw, cre_dev_acquire->ctx_id,
|
||||
CRE_HW_RELEASE, cre_dev_acquire->cre_acquire);
|
||||
top_acquire_fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_dev_process_reg_set_update(struct cam_cre_hw *cre_hw, void *cmd_args)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_cre_dev_reg_set_update *reg_set_update;
|
||||
|
||||
reg_set_update = cmd_args;
|
||||
|
||||
rc = cam_cre_top_process(cre_hw, 0,
|
||||
CRE_HW_REG_SET_UPDATE, reg_set_update);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
rc = cam_cre_bus_rd_process(cre_hw, 0,
|
||||
CRE_HW_REG_SET_UPDATE, reg_set_update);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
rc = cam_cre_bus_wr_process(cre_hw, 0,
|
||||
CRE_HW_REG_SET_UPDATE, reg_set_update);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_dev_process_prepare(struct cam_cre_hw *cre_hw, void *cmd_args)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_cre_dev_prepare_req *cre_dev_prepare_req;
|
||||
|
||||
cre_dev_prepare_req = cmd_args;
|
||||
|
||||
rc = cam_cre_top_process(cre_hw, cre_dev_prepare_req->ctx_data->ctx_id,
|
||||
CRE_HW_PREPARE, cre_dev_prepare_req);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
rc = cam_cre_bus_rd_process(cre_hw,
|
||||
cre_dev_prepare_req->ctx_data->ctx_id,
|
||||
CRE_HW_PREPARE, cre_dev_prepare_req);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
rc = cam_cre_bus_wr_process(cre_hw,
|
||||
cre_dev_prepare_req->ctx_data->ctx_id,
|
||||
CRE_HW_PREPARE, cre_dev_prepare_req);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_dev_process_probe(struct cam_cre_hw *cre_hw,
|
||||
void *cmd_args)
|
||||
{
|
||||
cam_cre_top_process(cre_hw, -1, CRE_HW_PROBE, NULL);
|
||||
cam_cre_bus_rd_process(cre_hw, -1, CRE_HW_PROBE, NULL);
|
||||
cam_cre_bus_wr_process(cre_hw, -1, CRE_HW_PROBE, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_cre_process_probe(struct cam_cre_hw *cre_hw,
|
||||
void *cmd_args)
|
||||
{
|
||||
return cam_cre_dev_process_probe(cre_hw, cmd_args);
|
||||
}
|
||||
|
||||
static int cam_cre_process_dump_debug_reg(struct cam_cre_hw *cre_hw)
|
||||
{
|
||||
return cam_cre_dev_process_dump_debug_reg(cre_hw);
|
||||
}
|
||||
|
||||
static int cam_cre_process_reset(struct cam_cre_hw *cre_hw,
|
||||
void *cmd_args)
|
||||
{
|
||||
return cam_cre_dev_process_reset(cre_hw, cmd_args);
|
||||
}
|
||||
|
||||
static int cam_cre_process_release(struct cam_cre_hw *cre_hw,
|
||||
void *cmd_args)
|
||||
{
|
||||
return cam_cre_dev_process_release(cre_hw, cmd_args);
|
||||
}
|
||||
|
||||
static int cam_cre_process_acquire(struct cam_cre_hw *cre_hw,
|
||||
void *cmd_args)
|
||||
{
|
||||
return cam_cre_dev_process_acquire(cre_hw, cmd_args);
|
||||
}
|
||||
|
||||
static int cam_cre_process_prepare(struct cam_cre_hw *cre_hw,
|
||||
void *cmd_args)
|
||||
{
|
||||
return cam_cre_dev_process_prepare(cre_hw, cmd_args);
|
||||
}
|
||||
|
||||
static int cam_cre_process_reg_set_update(struct cam_cre_hw *cre_hw,
|
||||
void *cmd_args)
|
||||
{
|
||||
return cam_cre_dev_process_reg_set_update(cre_hw, cmd_args);
|
||||
}
|
||||
|
||||
int cam_cre_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_hw_info *cre_dev = device_priv;
|
||||
struct cam_hw_soc_info *soc_info = NULL;
|
||||
struct cam_cre_device_core_info *core_info = NULL;
|
||||
struct cam_cre_hw *cre_hw;
|
||||
unsigned long flags;
|
||||
|
||||
if (!device_priv) {
|
||||
CAM_ERR(CAM_CRE, "Invalid args %x for cmd %u",
|
||||
device_priv, cmd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_info = &cre_dev->soc_info;
|
||||
core_info = (struct cam_cre_device_core_info *)cre_dev->core_info;
|
||||
if ((!soc_info) || (!core_info)) {
|
||||
CAM_ERR(CAM_CRE, "soc_info = %x core_info = %x",
|
||||
soc_info, core_info);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cre_hw = core_info->cre_hw_info->cre_hw;
|
||||
if (!cre_hw) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cre hw info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (cmd_type) {
|
||||
case CRE_HW_PROBE:
|
||||
rc = cam_cre_process_probe(cre_hw, cmd_args);
|
||||
break;
|
||||
case CRE_HW_ACQUIRE:
|
||||
rc = cam_cre_process_acquire(cre_hw, cmd_args);
|
||||
break;
|
||||
case CRE_HW_RELEASE:
|
||||
rc = cam_cre_process_release(cre_hw, cmd_args);
|
||||
break;
|
||||
case CRE_HW_PREPARE:
|
||||
rc = cam_cre_process_prepare(cre_hw, cmd_args);
|
||||
break;
|
||||
case CRE_HW_START:
|
||||
break;
|
||||
case CRE_HW_STOP:
|
||||
break;
|
||||
case CRE_HW_FLUSH:
|
||||
break;
|
||||
case CRE_HW_RESET:
|
||||
rc = cam_cre_process_reset(cre_hw, cmd_args);
|
||||
break;
|
||||
case CRE_HW_CLK_UPDATE: {
|
||||
struct cam_cre_dev_clk_update *clk_upd_cmd =
|
||||
(struct cam_cre_dev_clk_update *)cmd_args;
|
||||
|
||||
if (!core_info->clk_enable) {
|
||||
rc = cam_soc_util_clk_enable_default(soc_info,
|
||||
CAM_SVS_VOTE);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CRE, "Clock enable is failed");
|
||||
return rc;
|
||||
}
|
||||
core_info->clk_enable = true;
|
||||
}
|
||||
|
||||
rc = cam_cre_update_clk_rate(soc_info, clk_upd_cmd->clk_rate);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "Failed to update clk: %d", rc);
|
||||
}
|
||||
break;
|
||||
case CRE_HW_CLK_DISABLE: {
|
||||
if (core_info->clk_enable)
|
||||
cam_soc_util_clk_disable_default(soc_info);
|
||||
|
||||
core_info->clk_enable = false;
|
||||
}
|
||||
break;
|
||||
case CRE_HW_BW_UPDATE: {
|
||||
struct cam_cre_dev_bw_update *cpas_vote = cmd_args;
|
||||
|
||||
if (!cmd_args)
|
||||
return -EINVAL;
|
||||
|
||||
rc = cam_cre_caps_vote(core_info, cpas_vote);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "failed to update bw: %d", rc);
|
||||
}
|
||||
break;
|
||||
case CRE_HW_SET_IRQ_CB: {
|
||||
struct cam_cre_set_irq_cb *irq_cb = cmd_args;
|
||||
|
||||
if (!cmd_args) {
|
||||
CAM_ERR(CAM_CRE, "cmd args NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&cre_dev->hw_lock, flags);
|
||||
core_info->irq_cb.cre_hw_mgr_cb = irq_cb->cre_hw_mgr_cb;
|
||||
core_info->irq_cb.data = irq_cb->data;
|
||||
spin_unlock_irqrestore(&cre_dev->hw_lock, flags);
|
||||
}
|
||||
break;
|
||||
case CRE_HW_REG_SET_UPDATE:
|
||||
rc = cam_cre_process_reg_set_update(cre_hw, cmd_args);
|
||||
break;
|
||||
case CRE_HW_DUMP_DEBUG:
|
||||
rc = cam_cre_process_dump_debug_reg(cre_hw);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
irqreturn_t cam_cre_irq(int irq_num, void *data)
|
||||
{
|
||||
struct cam_hw_info *cre_dev = data;
|
||||
struct cam_cre_device_core_info *core_info = NULL;
|
||||
struct cam_cre_hw *cre_hw;
|
||||
|
||||
if (!data) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cam_dev_info or query_cap args");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
core_info = (struct cam_cre_device_core_info *)cre_dev->core_info;
|
||||
cre_hw = core_info->cre_hw_info->cre_hw;
|
||||
|
||||
irq_data.error = 0;
|
||||
|
||||
cam_cre_top_process(cre_hw, 0, CRE_HW_ISR, &irq_data);
|
||||
|
||||
if (irq_data.top_irq_status & CAM_CRE_FE_IRQ)
|
||||
cam_cre_bus_rd_process(cre_hw, 0, CRE_HW_ISR, &irq_data);
|
||||
if (irq_data.top_irq_status & CAM_CRE_WE_IRQ)
|
||||
cam_cre_bus_wr_process(cre_hw, 0, CRE_HW_ISR, &irq_data);
|
||||
|
||||
spin_lock(&cre_dev->hw_lock);
|
||||
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))
|
||||
core_info->irq_cb.cre_hw_mgr_cb(&irq_data,
|
||||
sizeof(struct cam_hw_info),
|
||||
core_info->irq_cb.data);
|
||||
spin_unlock(&cre_dev->hw_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
84
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_core.h
Normal file
84
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_core.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef CAM_CRE_CORE_H
|
||||
#define CAM_CRE_CORE_H
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <media/cam_cre.h>
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cre_hw.h"
|
||||
#include "cam_cre_hw_intf.h"
|
||||
|
||||
/**
|
||||
* struct cam_cre_cpas_vote
|
||||
* @ahb_vote: AHB vote info
|
||||
* @axi_vote: AXI vote info
|
||||
* @ahb_vote_valid: Flag for ahb vote data
|
||||
* @axi_vote_valid: flag for axi vote data
|
||||
*/
|
||||
struct cam_cre_cpas_vote {
|
||||
struct cam_ahb_vote ahb_vote;
|
||||
struct cam_axi_vote axi_vote;
|
||||
uint32_t ahb_vote_valid;
|
||||
uint32_t axi_vote_valid;
|
||||
};
|
||||
|
||||
|
||||
struct cam_cre_device_hw_info {
|
||||
struct cam_cre_hw *cre_hw;
|
||||
uint32_t hw_idx;
|
||||
void *cre_top_base;
|
||||
void *cre_qos_base;
|
||||
void *cre_pp_base;
|
||||
void *cre_bus_rd_base;
|
||||
void *cre_bus_wr_base;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
struct cam_cre_device_core_info {
|
||||
struct cam_cre_device_hw_info *cre_hw_info;
|
||||
uint32_t hw_version;
|
||||
uint32_t hw_idx;
|
||||
uint32_t hw_type;
|
||||
uint32_t cpas_handle;
|
||||
bool cpas_start;
|
||||
bool clk_enable;
|
||||
struct cam_cre_set_irq_cb irq_cb;
|
||||
};
|
||||
|
||||
int cam_cre_init_hw(void *device_priv,
|
||||
void *init_hw_args, uint32_t arg_size);
|
||||
int cam_cre_deinit_hw(void *device_priv,
|
||||
void *init_hw_args, uint32_t arg_size);
|
||||
int cam_cre_start_hw(void *device_priv,
|
||||
void *start_hw_args, uint32_t arg_size);
|
||||
int cam_cre_stop_hw(void *device_priv,
|
||||
void *stop_hw_args, uint32_t arg_size);
|
||||
int cam_cre_reset_hw(void *device_priv,
|
||||
void *reset_hw_args, uint32_t arg_size);
|
||||
int cam_cre_flush_hw(void *device_priv,
|
||||
void *flush_args, uint32_t arg_size);
|
||||
int cam_cre_get_hw_caps(void *device_priv,
|
||||
void *get_hw_cap_args, uint32_t arg_size);
|
||||
int cam_cre_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
void *cmd_args, uint32_t arg_size);
|
||||
irqreturn_t cam_cre_irq(int irq_num, void *data);
|
||||
|
||||
/**
|
||||
* @brief : API to register CRE hw to platform framework.
|
||||
* @return struct platform_device pointer on success, or ERR_PTR() on error.
|
||||
*/
|
||||
int cam_cre_init_module(void);
|
||||
|
||||
/**
|
||||
* @brief : API to remove CRE Hw from platform framework.
|
||||
*/
|
||||
void cam_cre_exit_module(void);
|
||||
#endif /* CAM_CRE_CORE_H */
|
321
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_dev.c
Normal file
321
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_dev.c
Normal file
@@ -0,0 +1,321 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#include "cam_node.h"
|
||||
#include "cre_core.h"
|
||||
#include "cre_soc.h"
|
||||
#include "cam_hw.h"
|
||||
#include "cre_hw.h"
|
||||
#include "cam_hw_intf.h"
|
||||
#include "cam_io_util.h"
|
||||
#include "cam_cre_hw_mgr_intf.h"
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cam_debug_util.h"
|
||||
#include "cre_hw_100.h"
|
||||
#include "cre_dev_intf.h"
|
||||
#include "cam_smmu_api.h"
|
||||
#include "camera_main.h"
|
||||
|
||||
static struct cam_cre_hw_intf_data cam_cre_dev_list[CRE_DEV_MAX];
|
||||
static struct cam_cre_device_hw_info cre_hw_info;
|
||||
static struct cam_cre_soc_private cre_soc_info;
|
||||
|
||||
static char cre_dev_name[8];
|
||||
|
||||
static struct cre_hw_version_reg cre_hw_version_reg = {
|
||||
.hw_ver = 0x0,
|
||||
};
|
||||
|
||||
static int cam_cre_init_hw_version(struct cam_hw_soc_info *soc_info,
|
||||
struct cam_cre_device_core_info *core_info)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_CRE, "soc_info = %x core_info = %x",
|
||||
soc_info, core_info);
|
||||
CAM_DBG(CAM_CRE, "TOP: %x RD: %x WR: %x",
|
||||
soc_info->reg_map[CRE_TOP_BASE].mem_base,
|
||||
soc_info->reg_map[CRE_BUS_RD].mem_base,
|
||||
soc_info->reg_map[CRE_BUS_WR].mem_base);
|
||||
|
||||
core_info->cre_hw_info->cre_top_base =
|
||||
soc_info->reg_map[CRE_TOP_BASE].mem_base;
|
||||
core_info->cre_hw_info->cre_bus_rd_base =
|
||||
soc_info->reg_map[CRE_BUS_RD].mem_base;
|
||||
core_info->cre_hw_info->cre_bus_wr_base =
|
||||
soc_info->reg_map[CRE_BUS_WR].mem_base;
|
||||
|
||||
core_info->hw_version = cam_io_r_mb(
|
||||
core_info->cre_hw_info->cre_top_base +
|
||||
cre_hw_version_reg.hw_ver);
|
||||
|
||||
switch (core_info->hw_version) {
|
||||
case CRE_HW_VER_1_0_0:
|
||||
core_info->cre_hw_info->cre_hw = &cre_hw_100;
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_CRE, "Unsupported version : %u",
|
||||
core_info->hw_version);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
cre_hw_100.top_reg_offset->base = core_info->cre_hw_info->cre_top_base;
|
||||
cre_hw_100.bus_rd_reg_offset->base = core_info->cre_hw_info->cre_bus_rd_base;
|
||||
cre_hw_100.bus_wr_reg_offset->base = core_info->cre_hw_info->cre_bus_wr_base;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cre_register_cpas(struct cam_hw_soc_info *soc_info,
|
||||
struct cam_cre_device_core_info *core_info,
|
||||
uint32_t hw_idx)
|
||||
{
|
||||
struct cam_cpas_register_params cpas_register_params;
|
||||
int rc;
|
||||
|
||||
cpas_register_params.dev = &soc_info->pdev->dev;
|
||||
memcpy(cpas_register_params.identifier, "cre", sizeof("cre"));
|
||||
cpas_register_params.cam_cpas_client_cb = NULL;
|
||||
cpas_register_params.cell_index = hw_idx;
|
||||
cpas_register_params.userdata = NULL;
|
||||
|
||||
rc = cam_cpas_register_client(&cpas_register_params);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CRE, "failed: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
core_info->cpas_handle = cpas_register_params.client_handle;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_component_bind(struct device *dev,
|
||||
struct device *master_dev, void *data)
|
||||
{
|
||||
struct cam_hw_intf *cre_dev_intf = NULL;
|
||||
struct cam_hw_info *cre_dev = NULL;
|
||||
const struct of_device_id *match_dev = NULL;
|
||||
struct cam_cre_device_core_info *core_info = NULL;
|
||||
struct cam_cre_dev_probe cre_probe;
|
||||
struct cam_cre_cpas_vote cpas_vote;
|
||||
struct cam_cre_soc_private *soc_private;
|
||||
int i;
|
||||
uint32_t hw_idx;
|
||||
int rc = 0;
|
||||
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
of_property_read_u32(pdev->dev.of_node,
|
||||
"cell-index", &hw_idx);
|
||||
|
||||
cre_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
|
||||
if (!cre_dev_intf)
|
||||
return -ENOMEM;
|
||||
|
||||
cre_dev_intf->hw_idx = hw_idx;
|
||||
cre_dev_intf->hw_type = CRE_DEV_CRE;
|
||||
cre_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||
if (!cre_dev) {
|
||||
rc = -ENOMEM;
|
||||
goto cre_dev_alloc_failed;
|
||||
}
|
||||
|
||||
memset(cre_dev_name, 0, sizeof(cre_dev_name));
|
||||
snprintf(cre_dev_name, sizeof(cre_dev_name),
|
||||
"cre%1u", cre_dev_intf->hw_idx);
|
||||
|
||||
cre_dev->soc_info.pdev = pdev;
|
||||
cre_dev->soc_info.dev = &pdev->dev;
|
||||
cre_dev->soc_info.dev_name = cre_dev_name;
|
||||
cre_dev_intf->hw_priv = cre_dev;
|
||||
cre_dev_intf->hw_ops.init = cam_cre_init_hw;
|
||||
cre_dev_intf->hw_ops.deinit = cam_cre_deinit_hw;
|
||||
cre_dev_intf->hw_ops.get_hw_caps = cam_cre_get_hw_caps;
|
||||
cre_dev_intf->hw_ops.process_cmd = cam_cre_process_cmd;
|
||||
|
||||
CAM_DBG(CAM_CRE, "type %d index %d",
|
||||
cre_dev_intf->hw_type,
|
||||
cre_dev_intf->hw_idx);
|
||||
|
||||
if (cre_dev_intf->hw_idx < CRE_DEV_MAX)
|
||||
cam_cre_dev_list[cre_dev_intf->hw_idx].hw_intf =
|
||||
cre_dev_intf;
|
||||
|
||||
platform_set_drvdata(pdev, cre_dev_intf);
|
||||
|
||||
|
||||
cre_dev->core_info = kzalloc(sizeof(struct cam_cre_device_core_info),
|
||||
GFP_KERNEL);
|
||||
if (!cre_dev->core_info) {
|
||||
rc = -ENOMEM;
|
||||
goto cre_core_alloc_failed;
|
||||
}
|
||||
core_info = (struct cam_cre_device_core_info *)cre_dev->core_info;
|
||||
core_info->cre_hw_info = &cre_hw_info;
|
||||
cre_dev->soc_info.soc_private = &cre_soc_info;
|
||||
|
||||
match_dev = of_match_device(pdev->dev.driver->of_match_table,
|
||||
&pdev->dev);
|
||||
if (!match_dev) {
|
||||
rc = -EINVAL;
|
||||
CAM_DBG(CAM_CRE, "No cre hardware info");
|
||||
goto cre_match_dev_failed;
|
||||
}
|
||||
|
||||
rc = cam_cre_init_soc_resources(&cre_dev->soc_info, cam_cre_irq,
|
||||
cre_dev);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CRE, "failed to init_soc");
|
||||
goto init_soc_failed;
|
||||
}
|
||||
core_info->hw_type = CRE_DEV_CRE;
|
||||
core_info->hw_idx = hw_idx;
|
||||
rc = cam_cre_register_cpas(&cre_dev->soc_info,
|
||||
core_info, cre_dev_intf->hw_idx);
|
||||
if (rc < 0)
|
||||
goto register_cpas_failed;
|
||||
|
||||
rc = cam_cre_enable_soc_resources(&cre_dev->soc_info);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CRE, "enable soc resorce failed: %d", rc);
|
||||
goto enable_soc_failed;
|
||||
}
|
||||
cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE;
|
||||
cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE;
|
||||
cpas_vote.axi_vote.num_paths = 1;
|
||||
cpas_vote.axi_vote.axi_path[0].path_data_type =
|
||||
CAM_AXI_PATH_DATA_CRE_WR_OUT;
|
||||
cpas_vote.axi_vote.axi_path[0].transac_type =
|
||||
CAM_AXI_TRANSACTION_WRITE;
|
||||
cpas_vote.axi_vote.axi_path[0].camnoc_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
cpas_vote.axi_vote.axi_path[0].mnoc_ab_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
cpas_vote.axi_vote.axi_path[0].mnoc_ib_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
cpas_vote.axi_vote.axi_path[0].ddr_ab_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
cpas_vote.axi_vote.axi_path[0].ddr_ib_bw =
|
||||
CAM_CPAS_DEFAULT_AXI_BW;
|
||||
|
||||
rc = cam_cpas_start(core_info->cpas_handle,
|
||||
&cpas_vote.ahb_vote, &cpas_vote.axi_vote);
|
||||
|
||||
rc = cam_cre_init_hw_version(&cre_dev->soc_info, cre_dev->core_info);
|
||||
if (rc)
|
||||
goto init_hw_failure;
|
||||
|
||||
cam_cre_disable_soc_resources(&cre_dev->soc_info);
|
||||
cam_cpas_stop(core_info->cpas_handle);
|
||||
cre_dev->hw_state = CAM_HW_STATE_POWER_DOWN;
|
||||
|
||||
cam_cre_process_cmd(cre_dev, CRE_HW_PROBE,
|
||||
&cre_probe, sizeof(cre_probe));
|
||||
mutex_init(&cre_dev->hw_mutex);
|
||||
spin_lock_init(&cre_dev->hw_lock);
|
||||
init_completion(&cre_dev->hw_complete);
|
||||
|
||||
CAM_DBG(CAM_CRE, "CRE:%d component bound successfully",
|
||||
cre_dev_intf->hw_idx);
|
||||
soc_private = cre_dev->soc_info.soc_private;
|
||||
cam_cre_dev_list[cre_dev_intf->hw_idx].num_hw_pid =
|
||||
soc_private->num_pid;
|
||||
|
||||
for (i = 0; i < soc_private->num_pid; i++)
|
||||
cam_cre_dev_list[cre_dev_intf->hw_idx].hw_pid[i] =
|
||||
soc_private->pid[i];
|
||||
|
||||
return rc;
|
||||
|
||||
init_hw_failure:
|
||||
enable_soc_failed:
|
||||
register_cpas_failed:
|
||||
init_soc_failed:
|
||||
cre_match_dev_failed:
|
||||
kfree(cre_dev->core_info);
|
||||
cre_core_alloc_failed:
|
||||
kfree(cre_dev);
|
||||
cre_dev_alloc_failed:
|
||||
kfree(cre_dev_intf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void cam_cre_component_unbind(struct device *dev,
|
||||
struct device *master_dev, void *data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
CAM_DBG(CAM_CRE, "Unbinding component: %s", pdev->name);
|
||||
}
|
||||
|
||||
int cam_cre_hw_init(struct cam_cre_hw_intf_data **cre_hw_intf_data,
|
||||
uint32_t hw_idx)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (cam_cre_dev_list[hw_idx].hw_intf) {
|
||||
*cre_hw_intf_data = &cam_cre_dev_list[hw_idx];
|
||||
rc = 0;
|
||||
} else {
|
||||
CAM_ERR(CAM_CRE, "inval param");
|
||||
*cre_hw_intf_data = NULL;
|
||||
rc = -ENODEV;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
const static struct component_ops cam_cre_component_ops = {
|
||||
.bind = cam_cre_component_bind,
|
||||
.unbind = cam_cre_component_unbind,
|
||||
};
|
||||
|
||||
int cam_cre_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_CRE, "Adding CRE component");
|
||||
rc = component_add(&pdev->dev, &cam_cre_component_ops);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "failed to add component rc: %d", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct of_device_id cam_cre_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,cre",
|
||||
.data = &cre_hw_version_reg,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cam_cre_dt_match);
|
||||
|
||||
struct platform_driver cam_cre_driver = {
|
||||
.probe = cam_cre_probe,
|
||||
.driver = {
|
||||
.name = "cre",
|
||||
.of_match_table = cam_cre_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
int cam_cre_init_module(void)
|
||||
{
|
||||
return platform_driver_register(&cam_cre_driver);
|
||||
}
|
||||
|
||||
void cam_cre_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&cam_cre_driver);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("CAM CRE driver");
|
||||
MODULE_LICENSE("GPL v2");
|
135
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_dev_intf.h
Normal file
135
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_dev_intf.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef CAM_CRE_DEV_INTF_H
|
||||
#define CAM_CRE_DEV_INTF_H
|
||||
|
||||
#include <media/cam_cre.h>
|
||||
#include "cam_cre_hw_mgr.h"
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cre_top.h"
|
||||
|
||||
|
||||
#define CRE_HW_INIT 0x1
|
||||
#define CRE_HW_DEINIT 0x2
|
||||
#define CRE_HW_ACQUIRE 0x3
|
||||
#define CRE_HW_RELEASE 0x4
|
||||
#define CRE_HW_START 0x5
|
||||
#define CRE_HW_STOP 0x6
|
||||
#define CRE_HW_FLUSH 0x7
|
||||
#define CRE_HW_PREPARE 0x8
|
||||
#define CRE_HW_ISR 0x9
|
||||
#define CRE_HW_PROBE 0xA
|
||||
#define CRE_HW_CLK_UPDATE 0xB
|
||||
#define CRE_HW_BW_UPDATE 0xC
|
||||
#define CRE_HW_RESET 0xD
|
||||
#define CRE_HW_SET_IRQ_CB 0xE
|
||||
#define CRE_HW_CLK_DISABLE 0xF
|
||||
#define CRE_HW_CLK_ENABLE 0x10
|
||||
#define CRE_HW_DUMP_DEBUG 0x11
|
||||
#define CRE_HW_REG_SET_UPDATE 0x12
|
||||
|
||||
/**
|
||||
* struct cam_cre_dev_probe
|
||||
*
|
||||
* @reserved: Reserved field for future use
|
||||
*/
|
||||
struct cam_cre_dev_probe {
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_dev_init
|
||||
*
|
||||
* @core_info: CRE core info
|
||||
*/
|
||||
struct cam_cre_dev_init {
|
||||
struct cam_cre_device_core_info *core_info;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_dev_clk_update
|
||||
*
|
||||
* @clk_rate: Clock rate
|
||||
*/
|
||||
struct cam_cre_dev_clk_update {
|
||||
uint32_t clk_rate;
|
||||
};
|
||||
|
||||
struct cam_cre_dev_reg_set_update {
|
||||
struct cre_reg_buffer cre_reg_buf;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_dev_bw_update
|
||||
*
|
||||
* @ahb_vote: AHB vote info
|
||||
* @axi_vote: AXI vote info
|
||||
* @ahb_vote_valid: Flag for ahb vote
|
||||
* @axi_vote_valid: Flag for axi vote
|
||||
*/
|
||||
struct cam_cre_dev_bw_update {
|
||||
struct cam_ahb_vote ahb_vote;
|
||||
struct cam_axi_vote axi_vote;
|
||||
uint32_t ahb_vote_valid;
|
||||
uint32_t axi_vote_valid;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_dev_acquire
|
||||
*
|
||||
* @ctx_id: Context id
|
||||
* @cre_acquire: CRE acquire info
|
||||
* @bus_wr_ctx: Bus Write context
|
||||
* @bus_rd_ctx: Bus Read context
|
||||
*/
|
||||
struct cam_cre_dev_acquire {
|
||||
uint32_t ctx_id;
|
||||
struct cre_top *cre_top;
|
||||
struct cam_cre_acquire_dev_info *cre_acquire;
|
||||
struct cre_bus_wr_ctx *bus_wr_ctx;
|
||||
struct cre_bus_rd_ctx *bus_rd_ctx;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_dev_release
|
||||
*
|
||||
* @ctx_id: Context id
|
||||
* @bus_wr_ctx: Bus Write context
|
||||
* @bus_rd_ctx: Bus Read context
|
||||
*/
|
||||
struct cam_cre_dev_release {
|
||||
uint32_t ctx_id;
|
||||
struct cre_bus_wr_ctx *bus_wr_ctx;
|
||||
struct cre_bus_rd_ctx *bus_rd_ctx;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_dev_prepare_req
|
||||
*
|
||||
* @hw_mgr: CRE hardware manager
|
||||
* @packet: Packet
|
||||
* @prepare_args: Prepare request args
|
||||
* @ctx_data: Context data
|
||||
* @frame_process: Frame process command
|
||||
* @req_idx: Request Index
|
||||
*/
|
||||
struct cam_cre_dev_prepare_req {
|
||||
struct cam_cre_hw_mgr *hw_mgr;
|
||||
struct cam_packet *packet;
|
||||
struct cam_hw_prepare_update_args *prepare_args;
|
||||
struct cam_cre_ctx *ctx_data;
|
||||
uint32_t req_idx;
|
||||
};
|
||||
|
||||
int cam_cre_top_process(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, uint32_t cmd_id, void *data);
|
||||
|
||||
int cam_cre_bus_rd_process(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, uint32_t cmd_id, void *data);
|
||||
|
||||
int cam_cre_bus_wr_process(struct cam_cre_hw *cam_cre_hw_info,
|
||||
int32_t ctx_id, uint32_t cmd_id, void *data);
|
||||
|
||||
#endif /* CAM_CRE_DEV_INTF_H */
|
340
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_hw.h
Normal file
340
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_hw.h
Normal file
@@ -0,0 +1,340 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef CAM_CRE_HW_H
|
||||
#define CAM_CRE_HW_H
|
||||
|
||||
#define CRE_HW_VER_1_0_0 0x10000000
|
||||
|
||||
#define CRE_DEV_CRE 0
|
||||
#define CRE_DEV_MAX 1
|
||||
|
||||
#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_WAIT_BUS_WR_RUP 0x1
|
||||
#define CRE_WAIT_BUS_WR_DONE 0x2
|
||||
#define CRE_WAIT_BUS_RD_DONE 0x3
|
||||
#define CRE_WAIT_IDLE_IRQ 0x4
|
||||
|
||||
struct cam_cre_top_reg {
|
||||
void *base;
|
||||
uint32_t offset;
|
||||
uint32_t hw_version;
|
||||
uint32_t hw_cap;
|
||||
uint32_t debug_0;
|
||||
uint32_t debug_1;
|
||||
uint32_t debug_cfg;
|
||||
uint32_t testbus_ctrl;
|
||||
uint32_t scratch_0;
|
||||
uint32_t irq_status;
|
||||
uint32_t irq_mask;
|
||||
uint32_t irq_clear;
|
||||
uint32_t irq_set;
|
||||
uint32_t irq_cmd;
|
||||
uint32_t reset_cmd;
|
||||
uint32_t core_clk_cfg_ctrl_0;
|
||||
uint32_t core_clk_cfg_ctrl_1;
|
||||
uint32_t top_spare;
|
||||
};
|
||||
|
||||
struct cam_cre_top_reg_val {
|
||||
uint32_t hw_version;
|
||||
uint32_t hw_cap;
|
||||
uint32_t major_mask;
|
||||
uint32_t major_shift;
|
||||
uint32_t minor_mask;
|
||||
uint32_t minor_shift;
|
||||
uint32_t irq_mask;
|
||||
uint32_t irq_set;
|
||||
uint32_t irq_clear;
|
||||
uint32_t irq_cmd_set;
|
||||
uint32_t irq_cmd_clear;
|
||||
uint32_t idle;
|
||||
uint32_t fe_done;
|
||||
uint32_t we_done;
|
||||
uint32_t rst_done;
|
||||
uint32_t sw_reset_cmd;
|
||||
uint32_t hw_reset_cmd;
|
||||
uint32_t core_clk_cfg_ctrl_0;
|
||||
uint32_t core_clk_cfg_ctrl_1;
|
||||
uint32_t top_override;
|
||||
uint32_t we_override;
|
||||
uint32_t fe_override;
|
||||
uint32_t ahb_override;
|
||||
};
|
||||
|
||||
struct cam_cre_bus_rd_client_reg {
|
||||
uint32_t bus_ctrl;
|
||||
uint32_t spare;
|
||||
uint32_t cons_violation;
|
||||
uint32_t cons_violation_status;
|
||||
uint32_t core_cfg;
|
||||
uint32_t ccif_meta_data;
|
||||
uint32_t img_addr;
|
||||
uint32_t rd_width;
|
||||
uint32_t rd_height;
|
||||
uint32_t rd_stride;
|
||||
uint32_t unpacker_cfg;
|
||||
uint32_t latency_buf_allocation;
|
||||
uint32_t misr_cfg_0;
|
||||
uint32_t misr_cfg_1;
|
||||
uint32_t misr_rd_val;
|
||||
uint32_t debug_status_cfg;
|
||||
uint32_t debug_status_0;
|
||||
uint32_t debug_status_1;
|
||||
uint32_t read_buff_cfg;
|
||||
uint32_t addr_cfg;
|
||||
};
|
||||
|
||||
struct cam_cre_bus_rd_reg {
|
||||
void *base;
|
||||
uint32_t offset;
|
||||
uint32_t hw_version;
|
||||
uint32_t irq_mask;
|
||||
uint32_t irq_clear;
|
||||
uint32_t irq_cmd;
|
||||
uint32_t irq_status;
|
||||
uint32_t input_if_cmd;
|
||||
uint32_t irq_set;
|
||||
uint32_t misr_reset;
|
||||
uint32_t security_cfg;
|
||||
uint32_t iso_cfg;
|
||||
uint32_t iso_seed;
|
||||
uint32_t test_bus_ctrl;
|
||||
|
||||
uint32_t num_clients;
|
||||
struct cam_cre_bus_rd_client_reg rd_clients[MAX_CRE_RD_CLIENTS];
|
||||
};
|
||||
|
||||
struct cam_cre_bus_rd_client_reg_val {
|
||||
uint32_t client_en;
|
||||
uint32_t ai_en;
|
||||
uint32_t ai_en_mask;
|
||||
uint32_t ai_en_shift;
|
||||
uint32_t pix_pattern;
|
||||
uint32_t pix_pattern_mask;
|
||||
uint32_t pix_pattern_shift;
|
||||
uint32_t stripe_location;
|
||||
uint32_t stripe_location_mask;
|
||||
uint32_t stripe_location_shift;
|
||||
uint32_t img_addr;
|
||||
uint32_t img_width;
|
||||
uint32_t img_height;
|
||||
uint32_t stride;
|
||||
uint32_t alignment;
|
||||
uint32_t alignment_mask;
|
||||
uint32_t alignment_shift;
|
||||
uint32_t mode;
|
||||
uint32_t mode_mask;
|
||||
uint32_t mode_shift;
|
||||
uint32_t latency_buf_size;
|
||||
uint32_t latency_buf_size_mask;
|
||||
uint32_t misr_cfg_en;
|
||||
uint32_t misr_cfg_en_mask;
|
||||
uint32_t misr_cfg_samp_mode;
|
||||
uint32_t misr_cfg_samp_mode_mask;
|
||||
uint32_t misr_cfg_1;
|
||||
uint32_t misr_rd_val;
|
||||
uint32_t x_int;
|
||||
uint32_t x_int_mask;
|
||||
uint32_t byte_offset;
|
||||
uint32_t byte_offset_mask;
|
||||
uint32_t input_port_id;
|
||||
uint32_t rm_port_id;
|
||||
};
|
||||
|
||||
struct cam_cre_bus_rd_reg_val {
|
||||
uint32_t hw_version;
|
||||
uint32_t cgc_override;
|
||||
uint32_t irq_mask;
|
||||
uint32_t irq_status;
|
||||
uint32_t irq_cmd_set;
|
||||
uint32_t irq_cmd_clear;
|
||||
uint32_t rup_done;
|
||||
uint32_t rd_buf_done;
|
||||
uint32_t cons_violation;
|
||||
uint32_t static_prg;
|
||||
uint32_t static_prg_mask;
|
||||
uint32_t ica_en;
|
||||
uint32_t ica_en_mask;
|
||||
uint32_t go_cmd;
|
||||
uint32_t go_cmd_mask;
|
||||
uint32_t irq_set;
|
||||
uint32_t irq_clear;
|
||||
uint32_t misr_reset;
|
||||
uint32_t security_cfg;
|
||||
uint32_t iso_bpp_select;
|
||||
uint32_t iso_bpp_select_mask;
|
||||
uint32_t iso_pattern_select;
|
||||
uint32_t iso_pattern_select_mask;
|
||||
uint32_t iso_en;
|
||||
uint32_t iso_en_mask;
|
||||
uint32_t iso_seed;
|
||||
uint32_t bus_ctrl;
|
||||
uint32_t spare;
|
||||
uint32_t num_clients;
|
||||
struct cam_cre_bus_rd_client_reg_val rd_clients[MAX_CRE_RD_CLIENTS];
|
||||
};
|
||||
|
||||
struct cam_cre_bus_wr_client_reg {
|
||||
uint32_t client_cfg;
|
||||
uint32_t img_addr;
|
||||
uint32_t img_cfg_0;
|
||||
uint32_t img_cfg_1;
|
||||
uint32_t img_cfg_2;
|
||||
uint32_t bw_limit;
|
||||
uint32_t packer_cfg;
|
||||
uint32_t addr_cfg;
|
||||
uint32_t debug_status_cfg;
|
||||
uint32_t debug_status_0;
|
||||
uint32_t debug_status_1;
|
||||
};
|
||||
|
||||
struct cam_cre_bus_wr_reg {
|
||||
void *base;
|
||||
uint32_t offset;
|
||||
uint32_t hw_version;
|
||||
uint32_t cgc_override;
|
||||
uint32_t irq_mask_0;
|
||||
uint32_t irq_mask_1;
|
||||
uint32_t irq_clear_0;
|
||||
uint32_t irq_clear_1;
|
||||
uint32_t irq_status_0;
|
||||
uint32_t irq_status_1;
|
||||
uint32_t irq_cmd;
|
||||
uint32_t frame_header_cfg_0;
|
||||
uint32_t local_frame_header_cfg_0;
|
||||
uint32_t irq_set_0;
|
||||
uint32_t irq_set_1;
|
||||
uint32_t iso_cfg;
|
||||
uint32_t violation_status;
|
||||
uint32_t image_size_violation_status;
|
||||
uint32_t perf_count_cfg_0;
|
||||
uint32_t perf_count_cfg_1;
|
||||
uint32_t perf_count_cfg_2;
|
||||
uint32_t perf_count_cfg_3;
|
||||
uint32_t perf_count_val_0;
|
||||
uint32_t perf_count_val_1;
|
||||
uint32_t perf_count_val_2;
|
||||
uint32_t perf_count_val_3;
|
||||
uint32_t perf_count_status;
|
||||
uint32_t misr_cfg_0;
|
||||
uint32_t misr_cfg_1;
|
||||
uint32_t misr_rd_sel;
|
||||
uint32_t misr_reset;
|
||||
uint32_t misr_val;
|
||||
|
||||
uint32_t num_clients;
|
||||
struct cam_cre_bus_wr_client_reg wr_clients[MAX_CRE_WR_CLIENTS];
|
||||
};
|
||||
|
||||
struct cam_cre_bus_wr_client_reg_val {
|
||||
uint32_t client_en;
|
||||
uint32_t client_en_mask;
|
||||
uint32_t client_en_shift;
|
||||
uint32_t auto_recovery_en;
|
||||
uint32_t auto_recovery_en_mask;
|
||||
uint32_t auto_recovery_en_shift;
|
||||
uint32_t mode;
|
||||
uint32_t mode_mask;
|
||||
uint32_t mode_shift;
|
||||
uint32_t img_addr;
|
||||
uint32_t width;
|
||||
uint32_t width_mask;
|
||||
uint32_t width_shift;
|
||||
uint32_t height;
|
||||
uint32_t height_mask;
|
||||
uint32_t height_shift;
|
||||
uint32_t x_init;
|
||||
uint32_t x_init_mask;
|
||||
uint32_t stride;
|
||||
uint32_t stride_mask;
|
||||
uint32_t format;
|
||||
uint32_t format_mask;
|
||||
uint32_t format_shift;
|
||||
uint32_t alignment;
|
||||
uint32_t alignment_mask;
|
||||
uint32_t alignment_shift;
|
||||
uint32_t bw_limit_en;
|
||||
uint32_t bw_limit_en_mask;
|
||||
uint32_t bw_limit_counter;
|
||||
uint32_t bw_limit_counter_mask;
|
||||
uint32_t frame_header_addr;
|
||||
uint32_t output_port_id;
|
||||
uint32_t wm_port_id;
|
||||
};
|
||||
|
||||
struct cam_cre_bus_wr_reg_val {
|
||||
uint32_t hw_version;
|
||||
uint32_t cgc_override;
|
||||
uint32_t irq_mask_0;
|
||||
uint32_t irq_set_0;
|
||||
uint32_t irq_clear_0;
|
||||
uint32_t irq_status_0;
|
||||
uint32_t img_size_violation;
|
||||
uint32_t violation;
|
||||
uint32_t cons_violation;
|
||||
uint32_t comp_buf_done;
|
||||
uint32_t comp_rup_done;
|
||||
uint32_t irq_mask_1;
|
||||
uint32_t irq_set_1;
|
||||
uint32_t irq_clear_1;
|
||||
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;
|
||||
uint32_t iso_en_mask;
|
||||
uint32_t violation_status;
|
||||
uint32_t img_size_violation_status;
|
||||
uint32_t misr_0_en;
|
||||
uint32_t misr_0_en_mask;
|
||||
uint32_t misr_0_samp_mode;
|
||||
uint32_t misr_0_samp_mode_mask;
|
||||
uint32_t misr_0_id;
|
||||
uint32_t misr_0_id_mask;
|
||||
uint32_t misr_rd_misr_sel;
|
||||
uint32_t misr_rd_misr_sel_mask;
|
||||
uint32_t misr_rd_word_sel;
|
||||
uint32_t misr_rd_word_sel_mask;
|
||||
uint32_t misr_reset;
|
||||
uint32_t misr_val;
|
||||
|
||||
uint32_t num_clients;
|
||||
struct cam_cre_bus_wr_client_reg_val wr_clients[MAX_CRE_WR_CLIENTS];
|
||||
};
|
||||
|
||||
struct cam_cre_debug_register {
|
||||
uint32_t offset;
|
||||
};
|
||||
|
||||
struct cam_cre_hw {
|
||||
struct cam_cre_top_reg *top_reg_offset;
|
||||
struct cam_cre_top_reg_val *top_reg_val;
|
||||
|
||||
struct cam_cre_bus_rd_reg *bus_rd_reg_offset;
|
||||
struct cam_cre_bus_rd_reg_val *bus_rd_reg_val;
|
||||
|
||||
struct cam_cre_bus_wr_reg *bus_wr_reg_offset;
|
||||
struct cam_cre_bus_wr_reg_val *bus_wr_reg_val;
|
||||
|
||||
struct cam_cre_common *common;
|
||||
};
|
||||
|
||||
struct cre_hw_version_reg {
|
||||
uint32_t hw_ver;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
#endif /* CAM_CRE_HW_H */
|
239
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_hw_100.h
Normal file
239
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_hw_100.h
Normal file
@@ -0,0 +1,239 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef CAM_CRE_HW_100_H
|
||||
#define CAM_CRE_HW_100_H
|
||||
|
||||
#include "cre_hw.h"
|
||||
|
||||
#define CRE_BUS_RD_TYPE 0x1
|
||||
#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,
|
||||
};
|
||||
|
||||
struct cam_cre_top_reg_val top_reg_value = {
|
||||
.hw_version = 0x10000000,
|
||||
.hw_cap = 0x4000,
|
||||
.irq_mask = 0xf,
|
||||
.irq_clear = 0xf,
|
||||
.irq_set = 0xf,
|
||||
.irq_cmd_set = 0xf,
|
||||
.irq_cmd_clear = 0xf,
|
||||
.idle = 0x8,
|
||||
.fe_done = 0x4,
|
||||
.we_done = 0x2,
|
||||
.rst_done = 0x1,
|
||||
.sw_reset_cmd = 0x2,
|
||||
.hw_reset_cmd = 0x1,
|
||||
};
|
||||
|
||||
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,
|
||||
.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,
|
||||
},
|
||||
};
|
||||
|
||||
struct cam_cre_bus_wr_reg_val bus_wr_reg_value = {
|
||||
.hw_version = 0x30000000,
|
||||
.cgc_override = 0x1,
|
||||
.irq_mask_0 = 0xd0000101,
|
||||
.irq_set_0 = 0xd0000101,
|
||||
.irq_clear_0 = 0xd0000101,
|
||||
.img_size_violation = 0x80000000,
|
||||
.violation = 0x40000000,
|
||||
.cons_violation = 0x10000000,
|
||||
.comp_buf_done = 0x100,
|
||||
.comp_rup_done = 0x1,
|
||||
.irq_mask_1 = 0x1,
|
||||
.irq_set_1 = 0x1,
|
||||
.irq_clear_1 = 0x1,
|
||||
.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,
|
||||
.misr_0_en_mask = 0x1,
|
||||
.misr_0_samp_mode = 0x1,
|
||||
.misr_0_samp_mode_mask = 0x10000,
|
||||
.misr_0_id_mask = 0xff,
|
||||
.misr_rd_misr_sel_mask = 0xf,
|
||||
.misr_rd_word_sel_mask = 0x70,
|
||||
.num_clients = 1,
|
||||
.wr_clients[0] = {
|
||||
.client_en = 0x1,
|
||||
.client_en_mask = 0x1,
|
||||
.client_en_shift = 0x0,
|
||||
.auto_recovery_en = 0x1,
|
||||
.auto_recovery_en_mask = 0x1,
|
||||
.auto_recovery_en_shift = 0x4,
|
||||
.mode_mask = 0x3,
|
||||
.mode_shift = 0x10,
|
||||
.width_mask = 0xffff,
|
||||
.width_shift = 0x0,
|
||||
.height_mask = 0xffff,
|
||||
.height_shift = 0x10,
|
||||
.x_init_mask = 0xff,
|
||||
.stride_mask = 0xffffff,
|
||||
.format_mask = 0xf,
|
||||
.format_shift = 0x0,
|
||||
.alignment_mask = 0x1,
|
||||
.alignment_shift = 0x5,
|
||||
.bw_limit_en = 0x1,
|
||||
.bw_limit_en_mask = 0x1,
|
||||
.bw_limit_counter_mask = 0x1fe,
|
||||
.output_port_id = 1,
|
||||
.wm_port_id = 1,
|
||||
},
|
||||
};
|
||||
|
||||
struct cam_cre_bus_rd_reg_val bus_rd_reg_value = {
|
||||
.hw_version = 0x30000000,
|
||||
.irq_mask = 0x7,
|
||||
.rd_buf_done = 0x4,
|
||||
.rup_done = 0x2,
|
||||
.cons_violation = 0x1,
|
||||
.irq_cmd_set = 0x10,
|
||||
.irq_cmd_clear = 0x1,
|
||||
.static_prg = 0x8,
|
||||
.static_prg_mask = 0x8,
|
||||
.ica_en = 0x1,
|
||||
.ica_en_mask = 0x2,
|
||||
.go_cmd = 0x1,
|
||||
.go_cmd_mask = 0x1,
|
||||
.irq_set = 0x7,
|
||||
.irq_clear = 0x7,
|
||||
.misr_reset = 0x1,
|
||||
.security_cfg = 0x1,
|
||||
.iso_bpp_select_mask = 0x60,
|
||||
.iso_pattern_select_mask = 0x6,
|
||||
.iso_en = 0x1,
|
||||
.iso_en_mask = 0x1,
|
||||
.num_clients = 1,
|
||||
.rd_clients[0] = {
|
||||
.client_en = 0x1,
|
||||
.ai_en = 0x1,
|
||||
.ai_en_mask = 0x1000,
|
||||
.ai_en_shift = 0xc,
|
||||
.pix_pattern_mask = 0xfc,
|
||||
.pix_pattern_shift = 0x2,
|
||||
.stripe_location_mask = 0x3,
|
||||
.stripe_location_shift = 0x0,
|
||||
.alignment_mask = 0x1,
|
||||
.alignment_shift = 0x5,
|
||||
.mode_mask = 0x1f,
|
||||
.mode_shift = 0x0,
|
||||
.latency_buf_size_mask = 0xffff,
|
||||
.misr_cfg_en_mask = 0x4,
|
||||
.misr_cfg_samp_mode_mask = 0x3,
|
||||
.x_int_mask = 0xffff,
|
||||
.byte_offset_mask = 0xff,
|
||||
.rm_port_id = 0x0,
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
.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,
|
||||
.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,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_cre_hw cre_hw_100 = {
|
||||
.top_reg_offset = &top_reg,
|
||||
.top_reg_val = &top_reg_value,
|
||||
.bus_wr_reg_offset = &bus_wr_reg,
|
||||
.bus_wr_reg_val = &bus_wr_reg_value,
|
||||
.bus_rd_reg_offset = &bus_rd_reg,
|
||||
.bus_rd_reg_val = &bus_rd_reg_value,
|
||||
};
|
||||
#endif // CAM_CRE_HW_100_H
|
83
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_soc.c
Normal file
83
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_soc.c
Normal file
@@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <media/cam_defs.h>
|
||||
#include <media/cam_cre.h>
|
||||
|
||||
#include "cre_soc.h"
|
||||
#include "cam_soc_util.h"
|
||||
#include "cam_debug_util.h"
|
||||
|
||||
int cam_cre_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
irq_handler_t cre_irq_handler, void *irq_data)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cam_soc_util_get_dt_properties(soc_info);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = cam_soc_util_request_platform_resource(soc_info,
|
||||
cre_irq_handler,
|
||||
irq_data);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "init soc failed %d", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cre_enable_soc_resources(struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cam_soc_util_enable_platform_resource(soc_info, true,
|
||||
CAM_SVS_VOTE, true);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "enable platform failed %d", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cre_disable_soc_resources(struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CRE, "disable platform failed %d", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cre_update_clk_rate(struct cam_hw_soc_info *soc_info,
|
||||
uint32_t clk_rate)
|
||||
{
|
||||
int32_t src_clk_idx;
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid soc info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
src_clk_idx = soc_info->src_clk_idx;
|
||||
|
||||
CAM_DBG(CAM_CRE, "clk_rate = %u src_clk_index = %d",
|
||||
clk_rate, src_clk_idx);
|
||||
if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) &&
|
||||
(soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) &&
|
||||
(clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) {
|
||||
CAM_DBG(CAM_CRE, "clk_rate %d greater than max, reset to %d",
|
||||
clk_rate,
|
||||
soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]);
|
||||
clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_CRE, "clk_rate = %u src_clk_index = %d",
|
||||
clk_rate, src_clk_idx);
|
||||
return cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
|
||||
}
|
33
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_soc.h
Normal file
33
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/cre_soc.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CRE_SOC_H_
|
||||
#define _CAM_CRE_SOC_H_
|
||||
|
||||
#include "cam_soc_util.h"
|
||||
|
||||
#define CAM_CRE_HW_MAX_NUM_PID 2
|
||||
|
||||
/**
|
||||
* struct cam_cre_soc_private
|
||||
*
|
||||
* @num_pid: CRE number of pids
|
||||
* @pid: CRE pid value list
|
||||
*/
|
||||
struct cam_cre_soc_private {
|
||||
uint32_t num_pid;
|
||||
uint32_t pid[CAM_CRE_HW_MAX_NUM_PID];
|
||||
};
|
||||
|
||||
int cam_cre_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
irq_handler_t cre_irq_handler, void *irq_data);
|
||||
|
||||
int cam_cre_enable_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
int cam_cre_disable_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
int cam_cre_update_clk_rate(struct cam_hw_soc_info *soc_info,
|
||||
uint32_t clk_rate);
|
||||
#endif /* _CAM_CRE_SOC_H_*/
|
@@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef CAM_CRE_HW_INTF_H
|
||||
#define CAM_CRE_HW_INTF_H
|
||||
|
||||
#include "cam_cpas_api.h"
|
||||
|
||||
#define CAM_CRE_DEV_PER_TYPE_MAX 1
|
||||
|
||||
#define CAM_CRE_CMD_BUF_MAX_SIZE 128
|
||||
#define CAM_CRE_MSG_BUF_MAX_SIZE CAM_CRE_CMD_BUF_MAX_SIZE
|
||||
|
||||
#define CRE_VOTE 640000000
|
||||
|
||||
#define CAM_CRE_HW_DUMP_TAG_MAX_LEN 32
|
||||
#define CAM_CRE_HW_DUMP_NUM_WORDS 5
|
||||
|
||||
struct cam_cre_set_irq_cb {
|
||||
int32_t (*cre_hw_mgr_cb)(void *irq_data,
|
||||
int32_t result_size, void *data);
|
||||
void *data;
|
||||
uint32_t b_set_cb;
|
||||
};
|
||||
|
||||
struct cam_cre_hw_dump_args {
|
||||
uint64_t request_id;
|
||||
uintptr_t cpu_addr;
|
||||
size_t offset;
|
||||
size_t buf_len;
|
||||
};
|
||||
|
||||
struct cam_cre_hw_dump_header {
|
||||
uint8_t tag[CAM_CRE_HW_DUMP_TAG_MAX_LEN];
|
||||
uint64_t size;
|
||||
uint32_t word_size;
|
||||
};
|
||||
|
||||
enum cam_cre_cmd_type {
|
||||
CAM_CRE_CMD_CFG,
|
||||
CAM_CRE_CMD_SET_IRQ_CB,
|
||||
CAM_CRE_CMD_HW_DUMP,
|
||||
CAM_CRE_CMD_RESET_HW,
|
||||
CAM_CRE_CMD_MAX,
|
||||
};
|
||||
|
||||
#endif
|
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef CAM_CRE_HW_MGR_INTF_H
|
||||
#define CAM_CRE_HW_MGR_INTF_H
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <media/cam_cre.h>
|
||||
#include <media/cam_defs.h>
|
||||
|
||||
#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);
|
||||
|
||||
#endif /* CAM_CRE_HW_MGR_INTF_H */
|
315
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/top/cre_top.c
Normal file
315
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/top/cre_top.c
Normal file
@@ -0,0 +1,315 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* 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"
|
||||
#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 "cre_hw.h"
|
||||
#include "cre_dev_intf.h"
|
||||
#include "cre_top.h"
|
||||
|
||||
static struct cre_top cre_top_info;
|
||||
|
||||
static int cam_cre_top_reset(struct cam_cre_hw *cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_cre_top_reg *top_reg;
|
||||
struct cam_cre_top_reg_val *top_reg_val;
|
||||
uint32_t irq_mask, irq_status;
|
||||
unsigned long flags;
|
||||
|
||||
if (!cre_hw_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cre_hw_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
top_reg = cre_hw_info->top_reg_offset;
|
||||
top_reg_val = cre_hw_info->top_reg_val;
|
||||
|
||||
mutex_lock(&cre_top_info.cre_hw_mutex);
|
||||
reinit_completion(&cre_top_info.reset_complete);
|
||||
reinit_completion(&cre_top_info.idle_done);
|
||||
|
||||
/* enable interrupt mask */
|
||||
cam_io_w_mb(top_reg_val->irq_mask,
|
||||
cre_hw_info->top_reg_offset->base + top_reg->irq_mask);
|
||||
|
||||
/* CRE SW RESET */
|
||||
cam_io_w_mb(top_reg_val->sw_reset_cmd,
|
||||
cre_hw_info->top_reg_offset->base + top_reg->reset_cmd);
|
||||
|
||||
rc = wait_for_completion_timeout(
|
||||
&cre_top_info.reset_complete,
|
||||
msecs_to_jiffies(60));
|
||||
|
||||
if (!rc || rc < 0) {
|
||||
spin_lock_irqsave(&cre_top_info.hw_lock, flags);
|
||||
if (!completion_done(&cre_top_info.reset_complete)) {
|
||||
CAM_DBG(CAM_CRE,
|
||||
"IRQ delayed, checking the status registers");
|
||||
irq_mask = cam_io_r_mb(cre_hw_info->top_reg_offset->base +
|
||||
top_reg->irq_mask);
|
||||
irq_status = cam_io_r_mb(cre_hw_info->top_reg_offset->base +
|
||||
top_reg->irq_status);
|
||||
if (irq_status & top_reg_val->rst_done) {
|
||||
CAM_DBG(CAM_CRE, "cre reset done");
|
||||
cam_io_w_mb(irq_status,
|
||||
top_reg->base + top_reg->irq_clear);
|
||||
cam_io_w_mb(top_reg_val->irq_cmd_clear,
|
||||
top_reg->base + top_reg->irq_cmd);
|
||||
} else {
|
||||
CAM_ERR(CAM_CRE,
|
||||
"irq mask 0x%x irq status 0x%x",
|
||||
irq_mask, irq_status);
|
||||
rc = -ETIMEDOUT;
|
||||
}
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&cre_top_info.hw_lock, flags);
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
/* enable interrupt mask */
|
||||
cam_io_w_mb(top_reg_val->irq_mask,
|
||||
cre_hw_info->top_reg_offset->base + top_reg->irq_mask);
|
||||
|
||||
mutex_unlock(&cre_top_info.cre_hw_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_top_release(struct cam_cre_hw *cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (ctx_id < 0) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d", ctx_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cre_top_info.top_ctx[ctx_id].cre_acquire = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_top_acquire(struct cam_cre_hw *cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_cre_dev_acquire *cre_dev_acquire = data;
|
||||
|
||||
if (ctx_id < 0 || !data) {
|
||||
CAM_ERR(CAM_CRE, "Invalid data: %d %x", ctx_id, data);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cre_top_info.top_ctx[ctx_id].cre_acquire = cre_dev_acquire->cre_acquire;
|
||||
cre_dev_acquire->cre_top = &cre_top_info;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_top_init(struct cam_cre_hw *cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_cre_top_reg *top_reg;
|
||||
struct cam_cre_top_reg_val *top_reg_val;
|
||||
struct cam_cre_dev_init *dev_init = data;
|
||||
uint32_t irq_mask, irq_status;
|
||||
unsigned long flags;
|
||||
|
||||
if (!cre_hw_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cre_hw_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
top_reg = cre_hw_info->top_reg_offset;
|
||||
top_reg_val = cre_hw_info->top_reg_val;
|
||||
|
||||
top_reg->base = dev_init->core_info->cre_hw_info->cre_top_base;
|
||||
|
||||
mutex_init(&cre_top_info.cre_hw_mutex);
|
||||
/* CRE SW RESET */
|
||||
init_completion(&cre_top_info.reset_complete);
|
||||
init_completion(&cre_top_info.idle_done);
|
||||
|
||||
/* enable interrupt mask */
|
||||
cam_io_w_mb(top_reg_val->irq_mask,
|
||||
cre_hw_info->top_reg_offset->base + top_reg->irq_mask);
|
||||
cam_io_w_mb(top_reg_val->sw_reset_cmd,
|
||||
cre_hw_info->top_reg_offset->base + top_reg->reset_cmd);
|
||||
|
||||
rc = wait_for_completion_timeout(
|
||||
&cre_top_info.reset_complete,
|
||||
msecs_to_jiffies(60));
|
||||
|
||||
if (!rc || rc < 0) {
|
||||
spin_lock_irqsave(&cre_top_info.hw_lock, flags);
|
||||
if (!completion_done(&cre_top_info.reset_complete)) {
|
||||
CAM_DBG(CAM_CRE,
|
||||
"IRQ delayed, checking the status registers");
|
||||
irq_mask = cam_io_r_mb(cre_hw_info->top_reg_offset->base +
|
||||
top_reg->irq_mask);
|
||||
irq_status = cam_io_r_mb(cre_hw_info->top_reg_offset->base +
|
||||
top_reg->irq_status);
|
||||
if (irq_status & top_reg_val->rst_done) {
|
||||
CAM_DBG(CAM_CRE, "cre reset done");
|
||||
cam_io_w_mb(irq_status,
|
||||
top_reg->base + top_reg->irq_clear);
|
||||
cam_io_w_mb(top_reg_val->irq_cmd_clear,
|
||||
top_reg->base + top_reg->irq_cmd);
|
||||
} else {
|
||||
CAM_ERR(CAM_CRE,
|
||||
"irq mask 0x%x irq status 0x%x",
|
||||
irq_mask, irq_status);
|
||||
rc = -ETIMEDOUT;
|
||||
}
|
||||
} else {
|
||||
CAM_DBG(CAM_CRE, "reset done");
|
||||
rc = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&cre_top_info.hw_lock, flags);
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
/* enable interrupt mask */
|
||||
cam_io_w_mb(top_reg_val->irq_mask,
|
||||
cre_hw_info->top_reg_offset->base + top_reg->irq_mask);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_top_probe(struct cam_cre_hw *cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!cre_hw_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cre_hw_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cre_top_info.cre_hw_info = cre_hw_info;
|
||||
spin_lock_init(&cre_top_info.hw_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_cre_top_isr(struct cam_cre_hw *cre_hw_info,
|
||||
int32_t ctx_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
uint32_t irq_status;
|
||||
struct cam_cre_top_reg *top_reg;
|
||||
struct cam_cre_top_reg_val *top_reg_val;
|
||||
struct cam_cre_irq_data *irq_data = data;
|
||||
|
||||
if (!cre_hw_info) {
|
||||
CAM_ERR(CAM_CRE, "Invalid cre_hw_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
top_reg = cre_hw_info->top_reg_offset;
|
||||
top_reg_val = cre_hw_info->top_reg_val;
|
||||
|
||||
spin_lock(&cre_top_info.hw_lock);
|
||||
/* Read and Clear Top Interrupt status */
|
||||
irq_status = cam_io_r_mb(top_reg->base + top_reg->irq_status);
|
||||
cam_io_w_mb(irq_status,
|
||||
top_reg->base + top_reg->irq_clear);
|
||||
|
||||
cam_io_w_mb(top_reg_val->irq_cmd_clear,
|
||||
top_reg->base + top_reg->irq_cmd);
|
||||
|
||||
if (irq_status & top_reg_val->rst_done) {
|
||||
CAM_DBG(CAM_CRE, "cre reset done");
|
||||
complete(&cre_top_info.reset_complete);
|
||||
}
|
||||
|
||||
if (irq_status & top_reg_val->idle) {
|
||||
CAM_DBG(CAM_CRE, "cre idle IRQ, can configure new settings");
|
||||
complete(&cre_top_info.idle_done);
|
||||
}
|
||||
|
||||
if (irq_status & top_reg_val->we_done)
|
||||
CAM_DBG(CAM_CRE, "Received Write Engine IRQ");
|
||||
|
||||
if (irq_status & top_reg_val->fe_done)
|
||||
CAM_DBG(CAM_CRE, "Received Fetch Engine IRQ");
|
||||
|
||||
irq_data->top_irq_status = irq_status;
|
||||
spin_unlock(&cre_top_info.hw_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cre_top_process(struct cam_cre_hw *cre_hw_info,
|
||||
int32_t ctx_id, uint32_t cmd_id, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (cmd_id) {
|
||||
case CRE_HW_PROBE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PROBE: E");
|
||||
rc = cam_cre_top_probe(cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_PROBE: X");
|
||||
break;
|
||||
case CRE_HW_INIT:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_INIT: E");
|
||||
rc = cam_cre_top_init(cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_INIT: X");
|
||||
break;
|
||||
case CRE_HW_DEINIT:
|
||||
break;
|
||||
case CRE_HW_ACQUIRE:
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_ACQUIRE: E");
|
||||
rc = cam_cre_top_acquire(cre_hw_info, ctx_id, data);
|
||||
CAM_DBG(CAM_CRE, "CRE_HW_ACQUIRE: X");
|
||||
break;
|
||||
case CRE_HW_PREPARE:
|
||||
break;
|
||||
case CRE_HW_RELEASE:
|
||||
rc = cam_cre_top_release(cre_hw_info, ctx_id, data);
|
||||
break;
|
||||
case CRE_HW_REG_SET_UPDATE:
|
||||
break;
|
||||
case CRE_HW_START:
|
||||
break;
|
||||
case CRE_HW_STOP:
|
||||
break;
|
||||
case CRE_HW_FLUSH:
|
||||
break;
|
||||
case CRE_HW_ISR:
|
||||
rc = cam_cre_top_isr(cre_hw_info, ctx_id, data);
|
||||
break;
|
||||
case CRE_HW_RESET:
|
||||
rc = cam_cre_top_reset(cre_hw_info, ctx_id, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
46
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/top/cre_top.h
Normal file
46
drivers/cam_cre/cam_cre_hw_mgr/cre_hw/top/cre_top.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef CRE_TOP_H
|
||||
#define CRE_TOP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/completion.h>
|
||||
#include <media/cam_cre.h>
|
||||
#include "cre_hw.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_hw_intf.h"
|
||||
#include "cam_soc_util.h"
|
||||
#include "cam_context.h"
|
||||
#include "cam_cre_context.h"
|
||||
#include "cam_cre_hw_mgr.h"
|
||||
|
||||
/**
|
||||
* struct cre_top_ctx
|
||||
*
|
||||
* @cre_acquire: CRE acquire info
|
||||
*/
|
||||
struct cre_top_ctx {
|
||||
struct cam_cre_acquire_dev_info *cre_acquire;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cre_top
|
||||
*
|
||||
* @cre_hw_info: CRE hardware info
|
||||
* @top_ctx: CRE top context
|
||||
* @reset_complete: Reset complete flag
|
||||
* @cre_mutex: CRE hardware mutex
|
||||
* @hw_lock: CRE hardware spinlock
|
||||
*/
|
||||
struct cre_top {
|
||||
struct cam_cre_hw *cre_hw_info;
|
||||
struct cre_top_ctx top_ctx[CAM_CRE_CTX_MAX];
|
||||
struct completion reset_complete;
|
||||
struct completion idle_done;
|
||||
struct mutex cre_hw_mutex;
|
||||
spinlock_t hw_lock;
|
||||
};
|
||||
#endif /* CRE_TOP_H */
|
@@ -40,6 +40,7 @@
|
||||
#define CAM_OPE (1 << 28)
|
||||
#define CAM_IO_ACCESS (1 << 29)
|
||||
#define CAM_SFE (1 << 30)
|
||||
#define CAM_CRE (1 << 31)
|
||||
|
||||
/* Log level types */
|
||||
#define CAM_TYPE_TRACE (1 << 0)
|
||||
|
@@ -39,6 +39,9 @@
|
||||
#include "jpeg_enc_core.h"
|
||||
#include "cam_jpeg_dev.h"
|
||||
|
||||
#include "cre_core.h"
|
||||
#include "cam_cre_dev.h"
|
||||
|
||||
#include "cam_fd_hw_intf.h"
|
||||
#include "cam_fd_dev.h"
|
||||
|
||||
@@ -131,6 +134,11 @@ static const struct camera_submodule_component camera_ope[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct camera_submodule_component camera_cre[] = {
|
||||
#ifdef CONFIG_SPECTRA_CRE
|
||||
{&cam_cre_init_module, &cam_cre_exit_module},
|
||||
#endif
|
||||
};
|
||||
static const struct camera_submodule_component camera_jpeg[] = {
|
||||
#ifdef CONFIG_SPECTRA_JPEG
|
||||
{&cam_jpeg_enc_init_module, &cam_jpeg_enc_exit_module},
|
||||
@@ -207,6 +215,11 @@ static const struct camera_submodule submodule_table[] = {
|
||||
.num_component = ARRAY_SIZE(camera_lrme),
|
||||
.component = camera_lrme,
|
||||
},
|
||||
{
|
||||
.name = "Camera CRE",
|
||||
.num_component = ARRAY_SIZE(camera_cre),
|
||||
.component = camera_cre,
|
||||
},
|
||||
{
|
||||
.name = "Camera CUSTOM",
|
||||
.num_component = ARRAY_SIZE(camera_custom),
|
||||
|
@@ -51,6 +51,9 @@ extern struct platform_driver cam_icp_driver;
|
||||
extern struct platform_driver cam_ope_driver;
|
||||
extern struct platform_driver cam_ope_subdev_driver;
|
||||
#endif
|
||||
#ifdef CONFIG_SPECTRA_CRE
|
||||
extern struct platform_driver cam_cre_driver;
|
||||
#endif
|
||||
#ifdef CONFIG_SPECTRA_JPEG
|
||||
extern struct platform_driver cam_jpeg_enc_driver;
|
||||
extern struct platform_driver cam_jpeg_dma_driver;
|
||||
@@ -123,6 +126,9 @@ static struct platform_driver *const cam_component_drivers[] = {
|
||||
&cam_jpeg_dma_driver,
|
||||
&jpeg_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_SPECTRA_CRE
|
||||
&cam_cre_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_SPECTRA_FD
|
||||
&cam_fd_hw_driver,
|
||||
&cam_fd_driver,
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
/* CRE HW TYPE */
|
||||
#define CAM_CRE_HW_TYPE_CRE 0x1
|
||||
#define CAM_CRE_HW_TYPE_MAX 0x2
|
||||
#define CAM_CRE_HW_TYPE_MAX 0x1
|
||||
|
||||
/* packet opcode types */
|
||||
#define CAM_CRE_OPCODE_CONFIG 0x1
|
||||
@@ -26,50 +26,17 @@
|
||||
#define CAM_CRE_OUTPUT_IMAGE 0x1
|
||||
#define CAM_CRE_OUTPUT_IMAGES_MAX (CAM_CRE_OUTPUT_IMAGE + 1)
|
||||
|
||||
#define CAM_CRE_MAX_PLANES 0x2
|
||||
#define CRE_MAX_BATCH_SIZE 0x10
|
||||
|
||||
/* definitions needed for cre aquire device */
|
||||
#define CAM_CRE_DEV_TYPE_NRT 0x1
|
||||
#define CAM_CRE_DEV_TYPE_RT 0x2
|
||||
#define CAM_CRE_DEV_TYPE_MAX 0x3
|
||||
|
||||
#define CAM_CRE_CMD_META_GENERIC_BLOB 0x1
|
||||
/* Clock blob */
|
||||
#define CAM_CRE_CMD_GENERIC_BLOB_CLK 0x1
|
||||
|
||||
#define CAM_CRE_MAX_PLANES 0x2
|
||||
#define CRE_MAX_BATCH_SIZE 0x10
|
||||
#define CAM_CRE_MAX_IO_BUFS 0x3
|
||||
|
||||
#define CAM_CRE_ACQUIRE_FLAG_SECURE 0x1
|
||||
|
||||
/**
|
||||
* struct cam_cre_io_buf_info - CRE IO buffers meta
|
||||
*
|
||||
* @direction: Direction of a buffer of a port(Input/Output)
|
||||
* @res_id: Resource ID
|
||||
* @num_planes: Number of planes
|
||||
* @width: Height of a plane buffer
|
||||
* @height: Height of a plane buffer
|
||||
* @stride: Plane stride
|
||||
* @packer_format: Format
|
||||
* @alignment: Alignment
|
||||
* @reserved: Reserved field 0
|
||||
* @reserved_1: Reserved field 1
|
||||
* @reserved_2: Reserved field 2
|
||||
*
|
||||
*/
|
||||
struct cam_cre_io_buf_info {
|
||||
__u32 direction;
|
||||
__u32 res_id;
|
||||
__u32 num_planes;
|
||||
__u32 width;
|
||||
__u32 height;
|
||||
__u32 stride;
|
||||
__u32 fence;
|
||||
__u32 packer_format;
|
||||
__u32 alignment;
|
||||
__u32 reserved;
|
||||
__u32 reserved_1;
|
||||
__u32 reserved_2;
|
||||
};
|
||||
#define CAM_CRE_CMD_GENERIC_BLOB_CLK_V2 0x1
|
||||
|
||||
/**
|
||||
* struct cam_cre_hw_ver - Device information for particular hw type
|
||||
@@ -77,13 +44,9 @@ struct cam_cre_io_buf_info {
|
||||
* This is used to get device version info of CRE
|
||||
* from hardware and use this info in CAM_QUERY_CAP IOCTL
|
||||
*
|
||||
* @hw_type: Hardware type
|
||||
* @reserved: Reserved field
|
||||
* @hw_ver: Major, minor and incr values of a device version
|
||||
*/
|
||||
struct cam_cre_hw_ver {
|
||||
__u32 hw_type;
|
||||
__u32 reserved;
|
||||
struct cam_hw_version hw_ver;
|
||||
};
|
||||
|
||||
@@ -103,29 +66,29 @@ struct cam_cre_query_cap_cmd {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_cre_clk_bw_request
|
||||
* struct cam_cre_io_buf_info - CRE IO buffers meta
|
||||
*
|
||||
* @budget_ns: Time required to process frame
|
||||
* @frame_cycles: Frame cycles needed to process the frame
|
||||
* @rt_flag: Flag to indicate real time stream
|
||||
* @uncompressed_bw: Bandwidth required to process frame
|
||||
* @compressed_bw: Compressed bandwidth to process frame
|
||||
* @direction: Direction of a buffer of a port(Input/Output)
|
||||
* @res_id: Resource ID
|
||||
* @num_planes: Number of planes
|
||||
* @width: Height of a plane buffer
|
||||
* @height: Height of a plane buffer
|
||||
* @stride: Plane stride
|
||||
* @format: unpacker format for FE, packer format for WE
|
||||
* @alignment: Alignment
|
||||
* @reserved: Reserved field 0
|
||||
* @reserved_1: Reserved field 1
|
||||
* @reserved_2: Reserved field 2
|
||||
* @num_path: Number of AXI Paths
|
||||
*/
|
||||
struct cam_cre_clk_bw_request {
|
||||
__u64 budget_ns;
|
||||
__u32 frame_cycles;
|
||||
__u32 rt_flag;
|
||||
__u64 uncompressed_bw;
|
||||
__u64 compressed_bw;
|
||||
__u32 num_paths;
|
||||
struct cam_cre_io_buf_info {
|
||||
__u32 direction;
|
||||
__u32 res_id;
|
||||
__u32 num_planes;
|
||||
__u32 width;
|
||||
__u32 height;
|
||||
__u32 stride;
|
||||
__u32 fence;
|
||||
__u32 format;
|
||||
__u32 alignment;
|
||||
__u32 reserved;
|
||||
__u32 reserved_1;
|
||||
__u32 reserved_2;
|
||||
struct cam_axi_per_path_bw_vote axi_path[1];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -133,28 +96,41 @@ struct cam_cre_clk_bw_request {
|
||||
*
|
||||
* @dev_type: NRT/RT Acquire
|
||||
* @dev_name: Device name (CRE)
|
||||
* @acquire_flag: Tells if CRE will process the secure buff or not.
|
||||
* @secure_mode: Tells if CRE will process the secure buff or not.
|
||||
* @batch_size: Batch size
|
||||
* @num_in_res: Number of In resources
|
||||
* @num_out_res: Number of Out resources
|
||||
* @reserved: Reserved field 0
|
||||
* @reserved_1: Reserved field 1
|
||||
* @reserved_2: Reserved field 2
|
||||
* @in_res: In resource info
|
||||
* @in_res: Out resource info
|
||||
*/
|
||||
struct cam_cre_acquire_dev_info {
|
||||
__u32 dev_type;
|
||||
char dev_name[CAM_CRE_DEV_NAME_SIZE];
|
||||
__u32 acquire_flag;
|
||||
__u32 dev_type;
|
||||
__u32 secure_mode;
|
||||
__u32 batch_size;
|
||||
__u32 num_in_res;
|
||||
__u32 num_out_res;
|
||||
__u32 reserved;
|
||||
__u32 reserved_1;
|
||||
__u32 reserved_2;
|
||||
struct cam_cre_io_buf_info in_res[CAM_CRE_INPUT_IMAGES_MAX];
|
||||
struct cam_cre_io_buf_info out_res[CAM_CRE_OUTPUT_IMAGES_MAX];
|
||||
}__attribute__((__packed__));
|
||||
|
||||
/**
|
||||
* struct cre_clk_bw_request_v2
|
||||
*
|
||||
* @budget_ns: Time required to process frame
|
||||
* @frame_cycles: Frame cycles needed to process the frame
|
||||
* @rt_flag: Flag to indicate real time stream
|
||||
* @reserved: Reserved field 0
|
||||
* @num_path: Number of AXI Paths
|
||||
*/
|
||||
struct cre_clk_bw_request_v2 {
|
||||
__u64 budget_ns;
|
||||
__u32 frame_cycles;
|
||||
__u32 rt_flag;
|
||||
__u32 reserved;
|
||||
__u32 num_paths;
|
||||
struct cam_axi_per_path_bw_vote axi_path[1];
|
||||
};
|
||||
#endif /* __UAPI_CAM_CRE_H__ */
|
||||
|
Reference in New Issue
Block a user