msm: camera: ope: Add support to OPE driver
OPE is camera offline engine, support is added to enable camera OPE hardware. CRs-Fixed: 2594541 Change-Id: I65c69f5763d05abf265b645b09c95c55fb290182 Signed-off-by: Suresh Vankadara <svankada@codeaurora.org> Signed-off-by: Ravikishore Pampana <rpampana@codeaurora.org> Signed-off-by: Trishansh Bhardwaj <tbhardwa@codeaurora.org>
This commit is contained in:

committed by
Karthik Jayakumar

parent
b7cfa8b7b0
commit
12d9311463
@@ -172,6 +172,17 @@ camera-$(CONFIG_SPECTRA_CUSTOM) += \
|
|||||||
cam_cust/cam_custom_dev.o \
|
cam_cust/cam_custom_dev.o \
|
||||||
cam_cust/cam_custom_context.o
|
cam_cust/cam_custom_context.o
|
||||||
|
|
||||||
|
camera-$(CONFIG_SPECTRA_OPE) += \
|
||||||
|
cam_ope/cam_ope_subdev.o \
|
||||||
|
cam_ope/cam_ope_context.o \
|
||||||
|
cam_ope/ope_hw_mgr/cam_ope_hw_mgr.o \
|
||||||
|
cam_ope/ope_hw_mgr/ope_hw/ope_dev.o \
|
||||||
|
cam_ope/ope_hw_mgr/ope_hw/ope_soc.o \
|
||||||
|
cam_ope/ope_hw_mgr/ope_hw/ope_core.o \
|
||||||
|
cam_ope/ope_hw_mgr/ope_hw/top/ope_top.o \
|
||||||
|
cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.o\
|
||||||
|
cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.o
|
||||||
|
|
||||||
camera-y += camera_main.o
|
camera-y += camera_main.o
|
||||||
|
|
||||||
obj-$(CONFIG_SPECTRA_CAMERA) += camera.o
|
obj-$(CONFIG_SPECTRA_CAMERA) += camera.o
|
||||||
|
273
drivers/cam_ope/cam_ope_context.c
Normal file
273
drivers/cam_ope/cam_ope_context.c
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <media/cam_sync.h>
|
||||||
|
#include <media/cam_defs.h>
|
||||||
|
#include <media/cam_ope.h>
|
||||||
|
#include "cam_sync_api.h"
|
||||||
|
#include "cam_node.h"
|
||||||
|
#include "cam_context.h"
|
||||||
|
#include "cam_context_utils.h"
|
||||||
|
#include "cam_ope_context.h"
|
||||||
|
#include "cam_req_mgr_util.h"
|
||||||
|
#include "cam_mem_mgr.h"
|
||||||
|
#include "cam_trace.h"
|
||||||
|
#include "cam_debug_util.h"
|
||||||
|
#include "cam_packet_util.h"
|
||||||
|
|
||||||
|
static const char ope_dev_name[] = "cam-ope";
|
||||||
|
|
||||||
|
static int cam_ope_context_dump_active_request(void *data, unsigned long iova,
|
||||||
|
uint32_t buf_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;
|
||||||
|
int rc = 0;
|
||||||
|
bool b_mem_found = false;
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ctx");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&ctx->ctx_mutex);
|
||||||
|
if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) {
|
||||||
|
CAM_ERR(CAM_ICP, "Invalid state icp ctx %d state %d",
|
||||||
|
ctx->ctx_id, ctx->state);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAM_INFO(CAM_OPE, "iommu fault for ope 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);
|
||||||
|
CAM_INFO(CAM_OPE, "req_id : %lld", req->request_id);
|
||||||
|
|
||||||
|
rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet,
|
||||||
|
iova, buf_info, &b_mem_found);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_OPE, "Failed to dump pf info");
|
||||||
|
|
||||||
|
if (b_mem_found)
|
||||||
|
CAM_ERR(CAM_OPE, "Found page fault in req %lld %d",
|
||||||
|
req->request_id, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
mutex_unlock(&ctx->ctx_mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cam_ope_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) {
|
||||||
|
ctx->state = CAM_CTX_ACQUIRED;
|
||||||
|
trace_cam_context_state("OPE", ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cam_ope_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_OPE, "Unable to release device");
|
||||||
|
|
||||||
|
ctx->state = CAM_CTX_AVAILABLE;
|
||||||
|
trace_cam_context_state("OPE", ctx);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cam_ope_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("OPE", ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cam_ope_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_OPE, "Failed to flush device");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cam_ope_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_OPE, "[%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_OPE, "Failed to prepare device");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cam_ope_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_OPE, "Failed to stop device");
|
||||||
|
|
||||||
|
ctx->state = CAM_CTX_ACQUIRED;
|
||||||
|
trace_cam_context_state("OPE", ctx);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cam_ope_release_dev_in_ready(struct cam_context *ctx,
|
||||||
|
struct cam_release_dev_cmd *cmd)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = __cam_ope_stop_dev_in_ready(ctx, NULL);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_OPE, "Failed to stop device");
|
||||||
|
|
||||||
|
rc = __cam_ope_release_dev_in_acquired(ctx, cmd);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_OPE, "Failed to release device");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cam_ope_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 struct cam_ctx_ops
|
||||||
|
cam_ope_ctx_state_machine[CAM_CTX_STATE_MAX] = {
|
||||||
|
/* Uninit */
|
||||||
|
{
|
||||||
|
.ioctl_ops = {},
|
||||||
|
.crm_ops = {},
|
||||||
|
.irq_ops = NULL,
|
||||||
|
},
|
||||||
|
/* Available */
|
||||||
|
{
|
||||||
|
.ioctl_ops = {
|
||||||
|
.acquire_dev = __cam_ope_acquire_dev_in_available,
|
||||||
|
},
|
||||||
|
.crm_ops = {},
|
||||||
|
.irq_ops = NULL,
|
||||||
|
},
|
||||||
|
/* Acquired */
|
||||||
|
{
|
||||||
|
.ioctl_ops = {
|
||||||
|
.release_dev = __cam_ope_release_dev_in_acquired,
|
||||||
|
.start_dev = __cam_ope_start_dev_in_acquired,
|
||||||
|
.config_dev = __cam_ope_config_dev_in_ready,
|
||||||
|
.flush_dev = __cam_ope_flush_dev_in_ready,
|
||||||
|
},
|
||||||
|
.crm_ops = {},
|
||||||
|
.irq_ops = __cam_ope_handle_buf_done_in_ready,
|
||||||
|
.pagefault_ops = cam_ope_context_dump_active_request,
|
||||||
|
},
|
||||||
|
/* Ready */
|
||||||
|
{
|
||||||
|
.ioctl_ops = {
|
||||||
|
.stop_dev = __cam_ope_stop_dev_in_ready,
|
||||||
|
.release_dev = __cam_ope_release_dev_in_ready,
|
||||||
|
.config_dev = __cam_ope_config_dev_in_ready,
|
||||||
|
.flush_dev = __cam_ope_flush_dev_in_ready,
|
||||||
|
},
|
||||||
|
.crm_ops = {},
|
||||||
|
.irq_ops = __cam_ope_handle_buf_done_in_ready,
|
||||||
|
.pagefault_ops = cam_ope_context_dump_active_request,
|
||||||
|
},
|
||||||
|
/* Activated */
|
||||||
|
{
|
||||||
|
.ioctl_ops = {},
|
||||||
|
.crm_ops = {},
|
||||||
|
.irq_ops = NULL,
|
||||||
|
.pagefault_ops = cam_ope_context_dump_active_request,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
int cam_ope_context_init(struct cam_ope_context *ctx,
|
||||||
|
struct cam_hw_mgr_intf *hw_intf, uint32_t ctx_id)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ((!ctx) || (!ctx->base) || (!hw_intf)) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid params: %pK %pK", ctx, hw_intf);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cam_context_init(ctx->base, ope_dev_name, CAM_OPE, ctx_id,
|
||||||
|
NULL, hw_intf, ctx->req_base, CAM_CTX_REQ_MAX);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_OPE, "Camera Context Base init failed");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->base->state_machine = cam_ope_ctx_state_machine;
|
||||||
|
ctx->base->ctx_priv = ctx;
|
||||||
|
ctx->ctxt_to_hw_map = NULL;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_context_deinit(struct cam_ope_context *ctx)
|
||||||
|
{
|
||||||
|
if ((!ctx) || (!ctx->base)) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid params: %pK", ctx);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cam_context_deinit(ctx->base);
|
||||||
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
44
drivers/cam_ope/cam_ope_context.h
Normal file
44
drivers/cam_ope/cam_ope_context.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CAM_OPE_CONTEXT_H_
|
||||||
|
#define _CAM_OPE_CONTEXT_H_
|
||||||
|
|
||||||
|
#include "cam_context.h"
|
||||||
|
|
||||||
|
#define OPE_CTX_MAX 32
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_context - ope context
|
||||||
|
* @base: ope context object
|
||||||
|
* @state_machine: state machine for OPE context
|
||||||
|
* @req_base: common request structure
|
||||||
|
* @state: ope context state
|
||||||
|
* @ctxt_to_hw_map: context to FW handle mapping
|
||||||
|
*/
|
||||||
|
struct cam_ope_context {
|
||||||
|
struct cam_context *base;
|
||||||
|
struct cam_ctx_ops *state_machine;
|
||||||
|
struct cam_ctx_request req_base[CAM_CTX_REQ_MAX];
|
||||||
|
uint32_t state;
|
||||||
|
void *ctxt_to_hw_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cam_ope_context_init() - OPE context init
|
||||||
|
* @ctx: Pointer to context
|
||||||
|
* @hw_intf: Pointer to OPE hardware interface
|
||||||
|
* @ctx_id: ID for this context
|
||||||
|
*/
|
||||||
|
int cam_ope_context_init(struct cam_ope_context *ctx,
|
||||||
|
struct cam_hw_mgr_intf *hw_intf, uint32_t ctx_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cam_ope_context_deinit() - OPE context deinit
|
||||||
|
* @ctx: Pointer to context
|
||||||
|
*/
|
||||||
|
int cam_ope_context_deinit(struct cam_ope_context *ctx);
|
||||||
|
|
||||||
|
#endif /* _CAM_OPE_CONTEXT_H_ */
|
277
drivers/cam_ope/cam_ope_subdev.c
Normal file
277
drivers/cam_ope/cam_ope_subdev.c
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, 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 <linux/iommu.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
#include <media/v4l2-fh.h>
|
||||||
|
#include <media/v4l2-device.h>
|
||||||
|
#include <media/v4l2-event.h>
|
||||||
|
#include <media/v4l2-ioctl.h>
|
||||||
|
#include <media/v4l2-subdev.h>
|
||||||
|
#include <media/cam_req_mgr.h>
|
||||||
|
#include <media/cam_defs.h>
|
||||||
|
#include <media/cam_ope.h>
|
||||||
|
#include "cam_req_mgr_dev.h"
|
||||||
|
#include "cam_subdev.h"
|
||||||
|
#include "cam_node.h"
|
||||||
|
#include "cam_context.h"
|
||||||
|
#include "cam_ope_context.h"
|
||||||
|
#include "cam_ope_hw_mgr_intf.h"
|
||||||
|
#include "cam_hw_mgr_intf.h"
|
||||||
|
#include "cam_debug_util.h"
|
||||||
|
#include "cam_smmu_api.h"
|
||||||
|
|
||||||
|
#define OPE_DEV_NAME "cam-ope"
|
||||||
|
|
||||||
|
struct cam_ope_subdev {
|
||||||
|
struct cam_subdev sd;
|
||||||
|
struct cam_node *node;
|
||||||
|
struct cam_context ctx[OPE_CTX_MAX];
|
||||||
|
struct cam_ope_context ctx_ope[OPE_CTX_MAX];
|
||||||
|
struct mutex ope_lock;
|
||||||
|
int32_t open_cnt;
|
||||||
|
int32_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cam_ope_subdev g_ope_dev;
|
||||||
|
|
||||||
|
static void cam_ope_dev_iommu_fault_handler(
|
||||||
|
struct iommu_domain *domain, struct device *dev, unsigned long iova,
|
||||||
|
int flags, void *token, uint32_t buf_info)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
struct cam_node *node = NULL;
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
CAM_ERR(CAM_OPE, "invalid token in page handler cb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = (struct cam_node *)token;
|
||||||
|
|
||||||
|
for (i = 0; i < node->ctx_size; i++)
|
||||||
|
cam_context_dump_pf_info(&(node->ctx_list[i]), iova,
|
||||||
|
buf_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_subdev_open(struct v4l2_subdev *sd,
|
||||||
|
struct v4l2_subdev_fh *fh)
|
||||||
|
{
|
||||||
|
struct cam_hw_mgr_intf *hw_mgr_intf = NULL;
|
||||||
|
struct cam_node *node = v4l2_get_subdevdata(sd);
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
mutex_lock(&g_ope_dev.ope_lock);
|
||||||
|
if (g_ope_dev.open_cnt >= 1) {
|
||||||
|
CAM_ERR(CAM_OPE, "OPE subdev is already opened");
|
||||||
|
rc = -EALREADY;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid args");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw_mgr_intf = &node->hw_mgr_intf;
|
||||||
|
rc = hw_mgr_intf->hw_open(hw_mgr_intf->hw_mgr_priv, NULL);
|
||||||
|
if (rc < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "OPE HW open failed: %d", rc);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
g_ope_dev.open_cnt++;
|
||||||
|
CAM_DBG(CAM_OPE, "OPE HW open success: %d", rc);
|
||||||
|
end:
|
||||||
|
mutex_unlock(&g_ope_dev.ope_lock);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_subdev_close(struct v4l2_subdev *sd,
|
||||||
|
struct v4l2_subdev_fh *fh)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct cam_hw_mgr_intf *hw_mgr_intf = NULL;
|
||||||
|
struct cam_node *node = v4l2_get_subdevdata(sd);
|
||||||
|
|
||||||
|
mutex_lock(&g_ope_dev.ope_lock);
|
||||||
|
if (g_ope_dev.open_cnt <= 0) {
|
||||||
|
CAM_DBG(CAM_OPE, "OPE subdev is already closed");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
g_ope_dev.open_cnt--;
|
||||||
|
if (!node) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid args");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw_mgr_intf = &node->hw_mgr_intf;
|
||||||
|
if (!hw_mgr_intf) {
|
||||||
|
CAM_ERR(CAM_OPE, "hw_mgr_intf is not initialized");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cam_node_shutdown(node);
|
||||||
|
if (rc < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "HW close failed");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
CAM_DBG(CAM_OPE, "OPE HW close success: %d", rc);
|
||||||
|
|
||||||
|
end:
|
||||||
|
mutex_unlock(&g_ope_dev.ope_lock);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct v4l2_subdev_internal_ops cam_ope_subdev_internal_ops = {
|
||||||
|
.open = cam_ope_subdev_open,
|
||||||
|
.close = cam_ope_subdev_close,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int cam_ope_subdev_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int rc = 0, i = 0;
|
||||||
|
struct cam_node *node;
|
||||||
|
struct cam_hw_mgr_intf *hw_mgr_intf;
|
||||||
|
int iommu_hdl = -1;
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "OPE subdev probe start");
|
||||||
|
if (!pdev) {
|
||||||
|
CAM_ERR(CAM_OPE, "pdev is NULL");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ope_dev.sd.pdev = pdev;
|
||||||
|
g_ope_dev.sd.internal_ops = &cam_ope_subdev_internal_ops;
|
||||||
|
rc = cam_subdev_probe(&g_ope_dev.sd, pdev, OPE_DEV_NAME,
|
||||||
|
CAM_OPE_DEVICE_TYPE);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_OPE, "OPE cam_subdev_probe failed:%d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = (struct cam_node *) g_ope_dev.sd.token;
|
||||||
|
|
||||||
|
hw_mgr_intf = kzalloc(sizeof(*hw_mgr_intf), GFP_KERNEL);
|
||||||
|
if (!hw_mgr_intf) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto hw_alloc_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cam_ope_hw_mgr_init(pdev->dev.of_node, (uint64_t *)hw_mgr_intf,
|
||||||
|
&iommu_hdl);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_OPE, "OPE HW manager init failed: %d", rc);
|
||||||
|
goto hw_init_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < OPE_CTX_MAX; i++) {
|
||||||
|
g_ope_dev.ctx_ope[i].base = &g_ope_dev.ctx[i];
|
||||||
|
rc = cam_ope_context_init(&g_ope_dev.ctx_ope[i],
|
||||||
|
hw_mgr_intf, i);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_OPE, "OPE context init failed");
|
||||||
|
goto ctx_fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cam_node_init(node, hw_mgr_intf, g_ope_dev.ctx,
|
||||||
|
OPE_CTX_MAX, OPE_DEV_NAME);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_OPE, "OPE node init failed");
|
||||||
|
goto ctx_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
cam_smmu_set_client_page_fault_handler(iommu_hdl,
|
||||||
|
cam_ope_dev_iommu_fault_handler, node);
|
||||||
|
|
||||||
|
g_ope_dev.open_cnt = 0;
|
||||||
|
mutex_init(&g_ope_dev.ope_lock);
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "OPE subdev probe complete");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
ctx_fail:
|
||||||
|
for (--i; i >= 0; i--)
|
||||||
|
cam_ope_context_deinit(&g_ope_dev.ctx_ope[i]);
|
||||||
|
hw_init_fail:
|
||||||
|
kfree(hw_mgr_intf);
|
||||||
|
hw_alloc_fail:
|
||||||
|
cam_subdev_remove(&g_ope_dev.sd);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_subdev_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct v4l2_subdev *sd;
|
||||||
|
struct cam_subdev *subdev;
|
||||||
|
|
||||||
|
if (!pdev) {
|
||||||
|
CAM_ERR(CAM_OPE, "pdev is NULL");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
sd = platform_get_drvdata(pdev);
|
||||||
|
if (!sd) {
|
||||||
|
CAM_ERR(CAM_OPE, "V4l2 subdev is NULL");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
subdev = v4l2_get_subdevdata(sd);
|
||||||
|
if (!subdev) {
|
||||||
|
CAM_ERR(CAM_OPE, "cam subdev is NULL");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < OPE_CTX_MAX; i++)
|
||||||
|
cam_ope_context_deinit(&g_ope_dev.ctx_ope[i]);
|
||||||
|
cam_node_deinit(g_ope_dev.node);
|
||||||
|
cam_subdev_remove(&g_ope_dev.sd);
|
||||||
|
mutex_destroy(&g_ope_dev.ope_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id cam_ope_dt_match[] = {
|
||||||
|
{.compatible = "qcom,cam-ope"},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct platform_driver cam_ope_driver = {
|
||||||
|
.probe = cam_ope_subdev_probe,
|
||||||
|
.remove = cam_ope_subdev_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "cam_ope",
|
||||||
|
.of_match_table = cam_ope_dt_match,
|
||||||
|
.suppress_bind_attrs = true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
int cam_ope_subdev_init_module(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&cam_ope_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cam_ope_subdev_exit_module(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&cam_ope_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("MSM OPE driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
2248
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c
Normal file
2248
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c
Normal file
File diff suppressed because it is too large
Load Diff
399
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h
Normal file
399
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAM_OPE_HW_MGR_H
|
||||||
|
#define CAM_OPE_HW_MGR_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
#include <media/cam_ope.h>
|
||||||
|
#include "ope_hw.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_smmu_api.h"
|
||||||
|
#include "cam_soc_util.h"
|
||||||
|
#include "cam_req_mgr_timer.h"
|
||||||
|
#include "cam_context.h"
|
||||||
|
#include "ope_hw.h"
|
||||||
|
#include "cam_cdm_intf_api.h"
|
||||||
|
#include "cam_req_mgr_timer.h"
|
||||||
|
|
||||||
|
#define OPE_CTX_MAX 32
|
||||||
|
#define CAM_FRAME_CMD_MAX 20
|
||||||
|
|
||||||
|
|
||||||
|
#define OPE_WORKQ_NUM_TASK 100
|
||||||
|
#define OPE_WORKQ_TASK_CMD_TYPE 1
|
||||||
|
#define OPE_WORKQ_TASK_MSG_TYPE 2
|
||||||
|
|
||||||
|
#define OPE_PACKET_SIZE 0
|
||||||
|
#define OPE_PACKET_TYPE 1
|
||||||
|
#define OPE_PACKET_OPCODE 2
|
||||||
|
|
||||||
|
#define OPE_PACKET_MAX_CMD_BUFS 4
|
||||||
|
|
||||||
|
#define OPE_MAX_OUTPUT_SUPPORTED 8
|
||||||
|
#define OPE_MAX_INPUT_SUPPORTED 3
|
||||||
|
|
||||||
|
#define OPE_FRAME_PROCESS_SUCCESS 0
|
||||||
|
#define OPE_FRAME_PROCESS_FAILURE 1
|
||||||
|
|
||||||
|
#define OPE_CTX_STATE_FREE 0
|
||||||
|
#define OPE_CTX_STATE_IN_USE 1
|
||||||
|
#define OPE_CTX_STATE_ACQUIRED 2
|
||||||
|
#define OPE_CTX_STATE_RELEASE 3
|
||||||
|
|
||||||
|
#define OPE_CMDS OPE_MAX_CMD_BUFS
|
||||||
|
#define CAM_MAX_IN_RES 8
|
||||||
|
|
||||||
|
#define OPE_MAX_CDM_BLS 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_cmd_work_data
|
||||||
|
*
|
||||||
|
* @type: Type of work data
|
||||||
|
* @data: Private data
|
||||||
|
* @req_id: Request Id
|
||||||
|
*/
|
||||||
|
struct ope_cmd_work_data {
|
||||||
|
uint32_t type;
|
||||||
|
void *data;
|
||||||
|
int64_t req_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_msg_work_data
|
||||||
|
*
|
||||||
|
* @type: Type of work data
|
||||||
|
* @data: Private data
|
||||||
|
* @irq_status: IRQ status
|
||||||
|
*/
|
||||||
|
struct ope_msg_work_data {
|
||||||
|
uint32_t type;
|
||||||
|
void *data;
|
||||||
|
uint32_t irq_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_clk_work_data
|
||||||
|
*
|
||||||
|
* @type: Type of work data
|
||||||
|
* @data: Private data
|
||||||
|
*/
|
||||||
|
struct ope_clk_work_data {
|
||||||
|
uint32_t type;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cdm_dmi_cmd
|
||||||
|
*
|
||||||
|
* @length: Number of bytes in LUT
|
||||||
|
* @reserved: reserved bits
|
||||||
|
* @cmd: Command ID (CDMCmd)
|
||||||
|
* @addr: Address of the LUT in memory
|
||||||
|
* @DMIAddr: Address of the target DMI config register
|
||||||
|
* @DMISel: DMI identifier
|
||||||
|
*/
|
||||||
|
struct cdm_dmi_cmd {
|
||||||
|
unsigned int length : 16;
|
||||||
|
unsigned int reserved : 8;
|
||||||
|
unsigned int cmd : 8;
|
||||||
|
unsigned int addr;
|
||||||
|
unsigned int DMIAddr : 24;
|
||||||
|
unsigned int DMISel : 8;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_debug_buffer
|
||||||
|
*
|
||||||
|
* @cpu_addr: CPU address
|
||||||
|
* @iova_addr: IOVA address
|
||||||
|
* @len: Buffer length
|
||||||
|
* @size: Buffer Size
|
||||||
|
*/
|
||||||
|
struct ope_debug_buffer {
|
||||||
|
uintptr_t cpu_addr;
|
||||||
|
dma_addr_t iova_addr;
|
||||||
|
size_t len;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_kmd_buffer
|
||||||
|
*
|
||||||
|
* @mem_handle: Memory handle
|
||||||
|
* @cpu_addr: CPU address
|
||||||
|
* @iova_addr: IOVA address
|
||||||
|
* @iova_cdm_addr: CDM IOVA address
|
||||||
|
* @len: Buffer length
|
||||||
|
* @size: Buffer Size
|
||||||
|
*/
|
||||||
|
struct ope_kmd_buffer {
|
||||||
|
uint32_t mem_handle;
|
||||||
|
uintptr_t cpu_addr;
|
||||||
|
dma_addr_t iova_addr;
|
||||||
|
dma_addr_t iova_cdm_addr;
|
||||||
|
size_t len;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ope_stripe_settings {
|
||||||
|
uintptr_t cpu_addr;
|
||||||
|
dma_addr_t iova_addr;
|
||||||
|
size_t len;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t buf_type;
|
||||||
|
uint32_t type_buffered;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_pass_settings
|
||||||
|
*
|
||||||
|
* @cpu_addr: CPU address
|
||||||
|
* @iova_addr: IOVA address
|
||||||
|
* @len: Buffer length
|
||||||
|
* @size: Buffer Size
|
||||||
|
* @idx: Pass Index
|
||||||
|
* @buf_type: Direct/Indirect type
|
||||||
|
* @type_buffered: SB/DB types
|
||||||
|
*/
|
||||||
|
struct ope_pass_settings {
|
||||||
|
uintptr_t cpu_addr;
|
||||||
|
dma_addr_t iova_addr;
|
||||||
|
size_t len;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t idx;
|
||||||
|
uint32_t buf_type;
|
||||||
|
uint32_t type_buffered;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_frame_settings
|
||||||
|
*
|
||||||
|
* @cpu_addr: CPU address
|
||||||
|
* @iova_addr: IOVA address
|
||||||
|
* @offset: offset
|
||||||
|
* @len: Buffer length
|
||||||
|
* @size: Buffer Size
|
||||||
|
* @buf_type: Direct/Indirect type
|
||||||
|
* @type_buffered: SB/DB types
|
||||||
|
* @prefecth_disable: Disable prefetch
|
||||||
|
*/
|
||||||
|
struct ope_frame_settings {
|
||||||
|
uintptr_t cpu_addr;
|
||||||
|
dma_addr_t iova_addr;
|
||||||
|
uint32_t offset;
|
||||||
|
size_t len;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t buf_type;
|
||||||
|
uint32_t type_buffered;
|
||||||
|
uint32_t prefecth_disable;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_stripe_io
|
||||||
|
*
|
||||||
|
* @format: Stripe format
|
||||||
|
* @s_location: Stripe location
|
||||||
|
* @cpu_addr: Stripe CPU address
|
||||||
|
* @iova_addr: Stripe IOVA address
|
||||||
|
* @width: Stripe width
|
||||||
|
* @height: Stripe height
|
||||||
|
* @stride: Stripe stride
|
||||||
|
* @unpack_format: Unpack format
|
||||||
|
* @pack_format: Packing format
|
||||||
|
* @alignment: Stripe alignment
|
||||||
|
* @offset: Stripe offset
|
||||||
|
* @x_init: X_init
|
||||||
|
* @subsample_period: Subsample period
|
||||||
|
* @subsample_pattern: Subsample pattern
|
||||||
|
* @len: Stripe buffer length
|
||||||
|
* @disable_bus: disable bus for the stripe
|
||||||
|
*/
|
||||||
|
struct ope_stripe_io {
|
||||||
|
uint32_t format;
|
||||||
|
uint32_t s_location;
|
||||||
|
uintptr_t cpu_addr;
|
||||||
|
dma_addr_t iova_addr;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
uint32_t stride;
|
||||||
|
uint32_t unpack_format;
|
||||||
|
uint32_t pack_format;
|
||||||
|
uint32_t alignment;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t x_init;
|
||||||
|
uint32_t subsample_period;
|
||||||
|
uint32_t subsample_pattern;
|
||||||
|
size_t len;
|
||||||
|
uint32_t disable_bus;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_io_buf
|
||||||
|
*
|
||||||
|
* @direction: Direction of a buffer
|
||||||
|
* @resource_type: Resource type of IO Buffer
|
||||||
|
* @format: Format
|
||||||
|
* @fence: Fence
|
||||||
|
* @num_planes: Number of planes
|
||||||
|
* @num_stripes: Number of stripes
|
||||||
|
* @s_io: Stripe info
|
||||||
|
*/
|
||||||
|
struct ope_io_buf {
|
||||||
|
uint32_t direction;
|
||||||
|
uint32_t resource_type;
|
||||||
|
uint32_t format;
|
||||||
|
uint32_t fence;
|
||||||
|
uint32_t num_planes;
|
||||||
|
uint32_t num_stripes[OPE_MAX_PLANES];
|
||||||
|
struct ope_stripe_io s_io[OPE_MAX_PLANES][OPE_MAX_STRIPES];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_request
|
||||||
|
*
|
||||||
|
* @request_id: Request Id
|
||||||
|
* @req_idx: Index in request list
|
||||||
|
* @state: Request state
|
||||||
|
* @num_batch: Number of batches
|
||||||
|
* @num_cmd_bufs: Number of command buffers
|
||||||
|
* @num_frame_bufs: Number of frame buffers
|
||||||
|
* @num_pass_bufs: Number of pass Buffers
|
||||||
|
* @num_stripes: Number of Stripes
|
||||||
|
* @num_io_bufs: Number of IO Buffers
|
||||||
|
* @in_resource: Input resource
|
||||||
|
* @num_stripe_cmd_bufs: Command buffers per stripe
|
||||||
|
* @ope_kmd_buf: KMD buffer for OPE programming
|
||||||
|
* @ope_debug_buf: Debug buffer
|
||||||
|
* @io_buf: IO config info of a request
|
||||||
|
* @cdm_cmd: CDM command for OPE CDM
|
||||||
|
*/
|
||||||
|
struct cam_ope_request {
|
||||||
|
uint64_t request_id;
|
||||||
|
uint32_t req_idx;
|
||||||
|
uint32_t state;
|
||||||
|
uint32_t num_batch;
|
||||||
|
uint32_t num_cmd_bufs;
|
||||||
|
uint32_t num_frame_bufs;
|
||||||
|
uint32_t num_pass_bufs;
|
||||||
|
uint32_t num_stripes[OPE_MAX_BATCH_SIZE];
|
||||||
|
uint32_t num_io_bufs[OPE_MAX_BATCH_SIZE];
|
||||||
|
uint32_t in_resource;
|
||||||
|
uint8_t num_stripe_cmd_bufs[OPE_MAX_BATCH_SIZE][OPE_MAX_STRIPES];
|
||||||
|
struct ope_kmd_buffer ope_kmd_buf;
|
||||||
|
struct ope_debug_buffer ope_debug_buf;
|
||||||
|
struct ope_io_buf io_buf[OPE_MAX_BATCH_SIZE][OPE_MAX_IO_BUFS];
|
||||||
|
struct cam_cdm_bl_request *cdm_cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_cdm
|
||||||
|
*
|
||||||
|
* @cdm_handle: OPE CDM Handle
|
||||||
|
* @cdm_ops: OPE CDM Operations
|
||||||
|
*/
|
||||||
|
struct cam_ope_cdm {
|
||||||
|
uint32_t cdm_handle;
|
||||||
|
struct cam_cdm_utils_ops *cdm_ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_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
|
||||||
|
* @ope_acquire: OPE acquire command
|
||||||
|
* @ctxt_event_cb: Callback of a context
|
||||||
|
* @req_list: Request List
|
||||||
|
* @ope_cdm: OPE CDM info
|
||||||
|
* @req_watch_dog: Watchdog for requests
|
||||||
|
*/
|
||||||
|
struct cam_ope_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 ope_acquire_dev_info ope_acquire;
|
||||||
|
cam_hw_event_cb_func ctxt_event_cb;
|
||||||
|
struct cam_ope_request *req_list[CAM_CTX_REQ_MAX];
|
||||||
|
struct cam_ope_cdm ope_cdm;
|
||||||
|
struct cam_req_mgr_timer *req_watch_dog;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_hw_mgr
|
||||||
|
*
|
||||||
|
* @open_cnt: OPE device open count
|
||||||
|
* @ope_ctx_cnt: Open context count
|
||||||
|
* @hw_mgr_mutex: Mutex for HW manager
|
||||||
|
* @hw_mgr_lock: Spinlock for HW manager
|
||||||
|
* @hfi_en: Flag for HFI
|
||||||
|
* @iommu_hdl: OPE Handle
|
||||||
|
* @iommu_sec_hdl: OPE Handle for secure
|
||||||
|
* @iommu_cdm_hdl: CDM Handle
|
||||||
|
* @iommu_sec_cdm_hdl: CDM Handle for secure
|
||||||
|
* @num_ope: Number of OPE
|
||||||
|
* @secure_mode: Mode of OPE operation
|
||||||
|
* @ctx_bitmap: Context bit map
|
||||||
|
* @ctx_bitmap_size: Context bit map size
|
||||||
|
* @ctx_bits: Context bit map bits
|
||||||
|
* @ctx: OPE context
|
||||||
|
* @devices: OPE devices
|
||||||
|
* @ope_caps: OPE 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
|
||||||
|
* @ope_dev_intf: OPE device interface
|
||||||
|
* @cdm_reg_map: OPE CDM register map
|
||||||
|
*/
|
||||||
|
struct cam_ope_hw_mgr {
|
||||||
|
int32_t open_cnt;
|
||||||
|
uint32_t ope_ctx_cnt;
|
||||||
|
struct mutex hw_mgr_mutex;
|
||||||
|
spinlock_t hw_mgr_lock;
|
||||||
|
bool hfi_en;
|
||||||
|
int32_t iommu_hdl;
|
||||||
|
int32_t iommu_sec_hdl;
|
||||||
|
int32_t iommu_cdm_hdl;
|
||||||
|
int32_t iommu_sec_cdm_hdl;
|
||||||
|
uint32_t num_ope;
|
||||||
|
bool secure_mode;
|
||||||
|
void *ctx_bitmap;
|
||||||
|
size_t ctx_bitmap_size;
|
||||||
|
size_t ctx_bits;
|
||||||
|
struct cam_ope_ctx ctx[OPE_CTX_MAX];
|
||||||
|
struct cam_hw_intf **devices[OPE_DEV_MAX];
|
||||||
|
struct ope_query_cap_cmd ope_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 ope_cmd_work_data *cmd_work_data;
|
||||||
|
struct ope_msg_work_data *msg_work_data;
|
||||||
|
struct ope_clk_work_data *timer_work_data;
|
||||||
|
struct cam_hw_intf *ope_dev_intf[OPE_DEV_MAX];
|
||||||
|
struct cam_soc_reg_map *cdm_reg_map[OPE_DEV_MAX][OPE_BASE_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CAM_OPE_HW_MGR_H */
|
16
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h
Normal file
16
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr_intf.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAM_OPE_HW_MGR_INTF_H
|
||||||
|
#define CAM_OPE_HW_MGR_INTF_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
#include <media/cam_ope.h>
|
||||||
|
|
||||||
|
int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||||
|
int *iommu_hdl);
|
||||||
|
|
||||||
|
#endif /* CAM_OPE_HW_MGR_INTF_H */
|
693
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c
Normal file
693
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.c
Normal file
@@ -0,0 +1,693 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, 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_ope.h>
|
||||||
|
#include "cam_io_util.h"
|
||||||
|
#include "cam_hw.h"
|
||||||
|
#include "cam_hw_intf.h"
|
||||||
|
#include "ope_core.h"
|
||||||
|
#include "ope_soc.h"
|
||||||
|
#include "cam_soc_util.h"
|
||||||
|
#include "cam_io_util.h"
|
||||||
|
#include "cam_cpas_api.h"
|
||||||
|
#include "cam_debug_util.h"
|
||||||
|
#include "cam_cdm_util.h"
|
||||||
|
#include "ope_hw.h"
|
||||||
|
#include "ope_dev_intf.h"
|
||||||
|
#include "ope_bus_rd.h"
|
||||||
|
|
||||||
|
static struct ope_bus_rd *bus_rd;
|
||||||
|
|
||||||
|
static int cam_ope_bus_rd_in_port_idx(uint32_t input_port_id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < OPE_IN_RES_MAX; i++)
|
||||||
|
if (bus_rd->in_port_to_rm[i].input_port_id ==
|
||||||
|
input_port_id)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_rd_combo_idx(uint32_t format)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case CAM_FORMAT_YUV422:
|
||||||
|
case CAM_FORMAT_NV21:
|
||||||
|
case CAM_FORMAT_NV12:
|
||||||
|
rc = BUS_RD_YUV;
|
||||||
|
break;
|
||||||
|
case CAM_FORMAT_MIPI_RAW_6:
|
||||||
|
case CAM_FORMAT_MIPI_RAW_8:
|
||||||
|
case CAM_FORMAT_MIPI_RAW_10:
|
||||||
|
case CAM_FORMAT_MIPI_RAW_12:
|
||||||
|
case CAM_FORMAT_MIPI_RAW_14:
|
||||||
|
case CAM_FORMAT_MIPI_RAW_16:
|
||||||
|
case CAM_FORMAT_MIPI_RAW_20:
|
||||||
|
case CAM_FORMAT_QTI_RAW_8:
|
||||||
|
case CAM_FORMAT_QTI_RAW_10:
|
||||||
|
case CAM_FORMAT_QTI_RAW_12:
|
||||||
|
case CAM_FORMAT_QTI_RAW_14:
|
||||||
|
case CAM_FORMAT_PLAIN8:
|
||||||
|
case CAM_FORMAT_PLAIN16_8:
|
||||||
|
case CAM_FORMAT_PLAIN16_10:
|
||||||
|
case CAM_FORMAT_PLAIN16_12:
|
||||||
|
case CAM_FORMAT_PLAIN16_14:
|
||||||
|
case CAM_FORMAT_PLAIN16_16:
|
||||||
|
case CAM_FORMAT_PLAIN32_20:
|
||||||
|
case CAM_FORMAT_PLAIN64:
|
||||||
|
case CAM_FORMAT_PLAIN128:
|
||||||
|
rc = BUS_RD_BAYER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "Input format = %u rc = %d",
|
||||||
|
format, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t *cam_ope_bus_rd_update(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, uint32_t *kmd_buf, int batch_idx,
|
||||||
|
int io_idx, struct cam_ope_dev_prepare_req *prepare)
|
||||||
|
{
|
||||||
|
int k, l, m;
|
||||||
|
uint32_t idx;
|
||||||
|
int32_t combo_idx;
|
||||||
|
uint32_t req_idx, count = 0, temp;
|
||||||
|
uint32_t temp_reg[128] = {0};
|
||||||
|
uint32_t rm_id, header_size;
|
||||||
|
uint32_t rsc_type;
|
||||||
|
struct cam_hw_prepare_update_args *prepare_args;
|
||||||
|
struct cam_ope_ctx *ctx_data;
|
||||||
|
struct cam_ope_request *ope_request;
|
||||||
|
struct ope_io_buf *io_buf;
|
||||||
|
struct ope_stripe_io *stripe_io;
|
||||||
|
struct ope_bus_rd_ctx *bus_rd_ctx;
|
||||||
|
struct cam_ope_bus_rd_reg *rd_reg;
|
||||||
|
struct cam_ope_bus_rd_client_reg *rd_reg_client;
|
||||||
|
struct cam_ope_bus_rd_reg_val *rd_reg_val;
|
||||||
|
struct cam_ope_bus_rd_client_reg_val *rd_res_val_client;
|
||||||
|
struct ope_bus_in_port_to_rm *in_port_to_rm;
|
||||||
|
struct ope_bus_rd_io_port_cdm_info *io_port_cdm;
|
||||||
|
struct cam_cdm_utils_ops *cdm_ops;
|
||||||
|
struct ope_bus_rd_io_port_info *io_port_info;
|
||||||
|
|
||||||
|
|
||||||
|
if (ctx_id < 0 || !prepare) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, prepare);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batch_idx >= OPE_MAX_BATCH_SIZE) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (io_idx >= OPE_MAX_IO_BUFS) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid IO idx: %d", io_idx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_args = prepare->prepare_args;
|
||||||
|
ctx_data = prepare->ctx_data;
|
||||||
|
req_idx = prepare->req_idx;
|
||||||
|
cdm_ops = ctx_data->ope_cdm.cdm_ops;
|
||||||
|
|
||||||
|
ope_request = ctx_data->req_list[req_idx];
|
||||||
|
CAM_DBG(CAM_OPE, "req_idx = %d req_id = %lld KMDbuf %x offset %d",
|
||||||
|
req_idx, ope_request->request_id,
|
||||||
|
kmd_buf, prepare->kmd_buf_offset);
|
||||||
|
bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id];
|
||||||
|
io_port_info = &bus_rd_ctx->io_port_info;
|
||||||
|
rd_reg = ope_hw_info->bus_rd_reg;
|
||||||
|
rd_reg_val = ope_hw_info->bus_rd_reg_val;
|
||||||
|
|
||||||
|
io_buf = &ope_request->io_buf[batch_idx][io_idx];
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "batch:%d iobuf:%d direction:%d",
|
||||||
|
batch_idx, io_idx, io_buf->direction);
|
||||||
|
io_port_cdm =
|
||||||
|
&bus_rd_ctx->io_port_cdm_batch.io_port_cdm[batch_idx];
|
||||||
|
in_port_to_rm =
|
||||||
|
&bus_rd->in_port_to_rm[io_buf->resource_type - 1];
|
||||||
|
combo_idx = cam_ope_bus_rd_combo_idx(io_buf->format);
|
||||||
|
if (combo_idx < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid combo_idx");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 0; k < io_buf->num_planes; k++) {
|
||||||
|
for (l = 0; l < io_buf->num_stripes[k]; l++) {
|
||||||
|
stripe_io = &io_buf->s_io[k][l];
|
||||||
|
rsc_type = io_buf->resource_type - 1;
|
||||||
|
/* frame level info */
|
||||||
|
/* stripe level info */
|
||||||
|
rm_id = in_port_to_rm->rm_port_id[combo_idx][k];
|
||||||
|
rd_reg_client = &rd_reg->rd_clients[rm_id];
|
||||||
|
rd_res_val_client = &rd_reg_val->rd_clients[rm_id];
|
||||||
|
|
||||||
|
/* security cfg */
|
||||||
|
temp_reg[count++] = rd_reg->offset +
|
||||||
|
rd_reg->security_cfg;
|
||||||
|
temp_reg[count++] =
|
||||||
|
ctx_data->ope_acquire.secure_mode;
|
||||||
|
|
||||||
|
/* enable client */
|
||||||
|
temp_reg[count++] = rd_reg->offset +
|
||||||
|
rd_reg_client->core_cfg;
|
||||||
|
temp_reg[count++] = 1;
|
||||||
|
|
||||||
|
/* ccif meta data */
|
||||||
|
temp_reg[count++] = rd_reg->offset +
|
||||||
|
rd_reg_client->ccif_meta_data;
|
||||||
|
temp = 0;
|
||||||
|
temp |= stripe_io->s_location &
|
||||||
|
rd_res_val_client->stripe_location_mask;
|
||||||
|
temp |= (io_port_info->pixel_pattern[rsc_type] &
|
||||||
|
rd_res_val_client->pix_pattern_mask) <<
|
||||||
|
rd_res_val_client->pix_pattern_shift;
|
||||||
|
temp_reg[count++] = temp;
|
||||||
|
|
||||||
|
/* Address of the Image */
|
||||||
|
temp_reg[count++] = rd_reg->offset +
|
||||||
|
rd_reg_client->img_addr;
|
||||||
|
temp_reg[count++] = stripe_io->iova_addr;
|
||||||
|
|
||||||
|
/* Buffer size */
|
||||||
|
temp_reg[count++] = rd_reg->offset +
|
||||||
|
rd_reg_client->img_cfg;
|
||||||
|
temp = 0;
|
||||||
|
temp = stripe_io->height;
|
||||||
|
temp |=
|
||||||
|
(stripe_io->width &
|
||||||
|
rd_res_val_client->img_width_mask) <<
|
||||||
|
rd_res_val_client->img_width_shift;
|
||||||
|
temp_reg[count++] = temp;
|
||||||
|
|
||||||
|
/* stride */
|
||||||
|
temp_reg[count++] = rd_reg->offset +
|
||||||
|
rd_reg_client->stride;
|
||||||
|
temp_reg[count++] = stripe_io->stride;
|
||||||
|
|
||||||
|
/* Unpack cfg : Mode and alignment */
|
||||||
|
temp_reg[count++] = rd_reg->offset +
|
||||||
|
rd_reg_client->unpack_cfg;
|
||||||
|
temp = 0;
|
||||||
|
temp |= (stripe_io->unpack_format &
|
||||||
|
rd_res_val_client->mode_mask) <<
|
||||||
|
rd_res_val_client->mode_shift;
|
||||||
|
temp |= (stripe_io->alignment &
|
||||||
|
rd_res_val_client->alignment_mask) <<
|
||||||
|
rd_res_val_client->alignment_shift;
|
||||||
|
temp_reg[count++] = temp;
|
||||||
|
|
||||||
|
/* latency buffer allocation */
|
||||||
|
temp_reg[count++] = rd_reg->offset +
|
||||||
|
rd_reg_client->latency_buf_allocation;
|
||||||
|
temp_reg[count++] = io_port_info->latency_buf_size;
|
||||||
|
|
||||||
|
header_size = cdm_ops->cdm_get_cmd_header_size(
|
||||||
|
CAM_CDM_CMD_REG_RANDOM);
|
||||||
|
idx = io_port_cdm->num_s_cmd_bufs[l];
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].len = sizeof(temp) *
|
||||||
|
(count + header_size);
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].offset =
|
||||||
|
prepare->kmd_buf_offset;
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf;
|
||||||
|
io_port_cdm->num_s_cmd_bufs[l]++;
|
||||||
|
|
||||||
|
kmd_buf = cdm_ops->cdm_write_regrandom(
|
||||||
|
kmd_buf, count/2, temp_reg);
|
||||||
|
prepare->kmd_buf_offset += ((count + header_size) *
|
||||||
|
sizeof(temp));
|
||||||
|
CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d",
|
||||||
|
batch_idx, io_idx, k, l);
|
||||||
|
for (m = 0; m < count; m++)
|
||||||
|
CAM_DBG(CAM_OPE, "%d:temp:%x",
|
||||||
|
m, temp_reg[m]);
|
||||||
|
CAM_DBG(CAM_OPE, "kmd_buf:%x offset:%d",
|
||||||
|
kmd_buf, prepare->kmd_buf_offset);
|
||||||
|
CAM_DBG(CAM_OPE, "%x count: %d size:%d",
|
||||||
|
temp_reg, count, header_size);
|
||||||
|
CAM_DBG(CAM_OPE, "RD cmdbufs:%d off:%d",
|
||||||
|
io_port_cdm->num_s_cmd_bufs[l],
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].offset);
|
||||||
|
CAM_DBG(CAM_OPE, "len:%d",
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].len);
|
||||||
|
CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d",
|
||||||
|
batch_idx, io_idx, k, l);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kmd_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_rd_prepare(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
int i, j;
|
||||||
|
int32_t combo_idx;
|
||||||
|
uint32_t req_idx, count = 0, temp;
|
||||||
|
uint32_t temp_reg[32] = {0};
|
||||||
|
uint32_t header_size;
|
||||||
|
uint32_t *kmd_buf;
|
||||||
|
struct cam_ope_dev_prepare_req *prepare;
|
||||||
|
struct cam_ope_ctx *ctx_data;
|
||||||
|
struct cam_ope_request *ope_request;
|
||||||
|
struct ope_io_buf *io_buf;
|
||||||
|
struct ope_bus_rd_ctx *bus_rd_ctx;
|
||||||
|
struct cam_ope_bus_rd_reg *rd_reg;
|
||||||
|
struct cam_ope_bus_rd_reg_val *rd_reg_val;
|
||||||
|
struct ope_bus_rd_io_port_cdm_batch *io_port_cdm_batch;
|
||||||
|
struct ope_bus_rd_io_port_cdm_info *io_port_cdm;
|
||||||
|
struct cam_cdm_utils_ops *cdm_ops;
|
||||||
|
|
||||||
|
if (ctx_id < 0 || !data) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
prepare = data;
|
||||||
|
|
||||||
|
ctx_data = prepare->ctx_data;
|
||||||
|
req_idx = prepare->req_idx;
|
||||||
|
cdm_ops = ctx_data->ope_cdm.cdm_ops;
|
||||||
|
|
||||||
|
ope_request = ctx_data->req_list[req_idx];
|
||||||
|
kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr +
|
||||||
|
prepare->kmd_buf_offset;
|
||||||
|
CAM_DBG(CAM_OPE, "req_idx = %d req_id = %lld",
|
||||||
|
req_idx, ope_request->request_id);
|
||||||
|
CAM_DBG(CAM_OPE, "KMD buf and offset = %x %d",
|
||||||
|
kmd_buf, prepare->kmd_buf_offset);
|
||||||
|
bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id];
|
||||||
|
io_port_cdm_batch =
|
||||||
|
&bus_rd_ctx->io_port_cdm_batch;
|
||||||
|
memset(io_port_cdm_batch, 0,
|
||||||
|
sizeof(struct ope_bus_rd_io_port_cdm_batch));
|
||||||
|
rd_reg = ope_hw_info->bus_rd_reg;
|
||||||
|
rd_reg_val = ope_hw_info->bus_rd_reg_val;
|
||||||
|
|
||||||
|
for (i = 0; i < ope_request->num_batch; i++) {
|
||||||
|
for (j = 0; j < ope_request->num_io_bufs[i]; j++) {
|
||||||
|
io_buf = &ope_request->io_buf[i][j];
|
||||||
|
if (io_buf->direction != CAM_BUF_INPUT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "batch:%d iobuf:%d direction:%d",
|
||||||
|
i, j, io_buf->direction);
|
||||||
|
io_port_cdm =
|
||||||
|
&bus_rd_ctx->io_port_cdm_batch.io_port_cdm[i];
|
||||||
|
|
||||||
|
combo_idx = cam_ope_bus_rd_combo_idx(io_buf->format);
|
||||||
|
if (combo_idx < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid combo_idx");
|
||||||
|
return combo_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
kmd_buf = cam_ope_bus_rd_update(ope_hw_info,
|
||||||
|
ctx_id, kmd_buf, i, j, prepare);
|
||||||
|
if (!kmd_buf) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!io_port_cdm) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go command */
|
||||||
|
count = 0;
|
||||||
|
temp_reg[count++] = rd_reg->offset +
|
||||||
|
rd_reg->input_if_cmd;
|
||||||
|
temp = 0;
|
||||||
|
temp |= rd_reg_val->go_cmd;
|
||||||
|
temp_reg[count++] = temp;
|
||||||
|
|
||||||
|
header_size =
|
||||||
|
cdm_ops->cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM);
|
||||||
|
io_port_cdm->go_cmd_addr = kmd_buf;
|
||||||
|
io_port_cdm->go_cmd_len =
|
||||||
|
sizeof(temp) * (count + header_size);
|
||||||
|
io_port_cdm->go_cmd_offset =
|
||||||
|
prepare->kmd_buf_offset;
|
||||||
|
kmd_buf = cdm_ops->cdm_write_regrandom(
|
||||||
|
kmd_buf, count/2, temp_reg);
|
||||||
|
prepare->kmd_buf_offset +=
|
||||||
|
((count + header_size) * sizeof(temp));
|
||||||
|
CAM_DBG(CAM_OPE, "kmd_buf:%x,offset:%d",
|
||||||
|
kmd_buf, prepare->kmd_buf_offset);
|
||||||
|
CAM_DBG(CAM_OPE, "t_reg:%xcount: %d size:%d",
|
||||||
|
temp_reg, count, header_size);
|
||||||
|
prepare->rd_cdm_batch = &bus_rd_ctx->io_port_cdm_batch;
|
||||||
|
|
||||||
|
end:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_rd_release(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0, i;
|
||||||
|
struct ope_acquire_dev_info *in_acquire;
|
||||||
|
struct ope_bus_rd_ctx *bus_rd_ctx;
|
||||||
|
|
||||||
|
if (ctx_id < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d", ctx_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_acquire = bus_rd->bus_rd_ctx[ctx_id].ope_acquire;
|
||||||
|
bus_rd->bus_rd_ctx[ctx_id].ope_acquire = NULL;
|
||||||
|
bus_rd_ctx = &bus_rd->bus_rd_ctx[ctx_id];
|
||||||
|
bus_rd_ctx->num_in_ports = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < bus_rd_ctx->num_in_ports; i++) {
|
||||||
|
bus_rd_ctx->io_port_info.input_port_id[i] = 0;
|
||||||
|
bus_rd_ctx->io_port_info.input_format_type[i - 1] = 0;
|
||||||
|
bus_rd_ctx->io_port_info.pixel_pattern[i - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_rd_acquire(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0, i;
|
||||||
|
struct ope_acquire_dev_info *in_acquire;
|
||||||
|
struct ope_bus_rd_ctx *bus_rd_ctx;
|
||||||
|
struct ope_bus_in_port_to_rm *in_port_to_rm;
|
||||||
|
struct cam_ope_bus_rd_reg_val *bus_rd_reg_val;
|
||||||
|
int combo_idx;
|
||||||
|
int in_port_idx;
|
||||||
|
|
||||||
|
|
||||||
|
if (ctx_id < 0 || !data || !ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d %x %x",
|
||||||
|
ctx_id, data, ope_hw_info);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bus_rd->bus_rd_ctx[ctx_id].ope_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 = ope_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_OPE, "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);
|
||||||
|
CAM_DBG(CAM_OPE, "pix_pattern:%u alignment:%u unpack_format:%u",
|
||||||
|
in_acquire->in_res[i].pixel_pattern,
|
||||||
|
in_acquire->in_res[i].alignment,
|
||||||
|
in_acquire->in_res[i].unpacker_format);
|
||||||
|
CAM_DBG(CAM_OPE, "max_stripe = %u fps = %u",
|
||||||
|
in_acquire->in_res[i].max_stripe_size,
|
||||||
|
in_acquire->in_res[i].fps);
|
||||||
|
|
||||||
|
in_port_idx = cam_ope_bus_rd_in_port_idx(i + 1);
|
||||||
|
if (in_port_idx < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid in_port_idx: %d", i + 1);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_port_to_rm = &bus_rd->in_port_to_rm[in_port_idx];
|
||||||
|
combo_idx = cam_ope_bus_rd_combo_idx(
|
||||||
|
in_acquire->in_res[i].format);
|
||||||
|
if (combo_idx < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid format: %d",
|
||||||
|
in_acquire->in_res[i].format);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_port_to_rm->num_rm[combo_idx]) {
|
||||||
|
CAM_ERR(CAM_OPE, "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;
|
||||||
|
if (in_acquire->in_res[i].pixel_pattern >
|
||||||
|
PIXEL_PATTERN_CRYCBY) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid pix pattern = %u",
|
||||||
|
in_acquire->in_res[i].pixel_pattern);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
bus_rd_ctx->io_port_info.pixel_pattern[i] =
|
||||||
|
in_acquire->in_res[i].pixel_pattern;
|
||||||
|
bus_rd_ctx->io_port_info.latency_buf_size =
|
||||||
|
bus_rd_reg_val->latency_buf_size;
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "i:%d port_id = %u format %u pix_pattern = %u",
|
||||||
|
i, bus_rd_ctx->io_port_info.input_port_id[i],
|
||||||
|
bus_rd_ctx->io_port_info.input_format_type[i],
|
||||||
|
bus_rd_ctx->io_port_info.pixel_pattern[i]);
|
||||||
|
CAM_DBG(CAM_OPE, "latency_buf_size = %u",
|
||||||
|
bus_rd_ctx->io_port_info.latency_buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_rd_init(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct cam_ope_bus_rd_reg_val *bus_rd_reg_val;
|
||||||
|
struct cam_ope_bus_rd_reg *bus_rd_reg;
|
||||||
|
struct cam_ope_dev_init *dev_init = data;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bus_rd_reg_val = ope_hw_info->bus_rd_reg_val;
|
||||||
|
bus_rd_reg = ope_hw_info->bus_rd_reg;
|
||||||
|
bus_rd_reg->base = dev_init->core_info->ope_hw_info->ope_bus_rd_base;
|
||||||
|
|
||||||
|
/* OPE SW RESET */
|
||||||
|
init_completion(&bus_rd->reset_complete);
|
||||||
|
|
||||||
|
/* enable interrupt mask */
|
||||||
|
cam_io_w_mb(bus_rd_reg_val->irq_mask,
|
||||||
|
ope_hw_info->bus_rd_reg->base + bus_rd_reg->irq_mask);
|
||||||
|
|
||||||
|
cam_io_w_mb(bus_rd_reg_val->sw_reset,
|
||||||
|
ope_hw_info->bus_rd_reg->base + bus_rd_reg->sw_reset);
|
||||||
|
|
||||||
|
rc = wait_for_completion_timeout(
|
||||||
|
&bus_rd->reset_complete, msecs_to_jiffies(30000));
|
||||||
|
|
||||||
|
if (!rc || rc < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "reset error result = %d", rc);
|
||||||
|
if (!rc)
|
||||||
|
rc = -ETIMEDOUT;
|
||||||
|
} else {
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cam_io_w_mb(bus_rd_reg_val->irq_mask,
|
||||||
|
ope_hw_info->bus_rd_reg->base + bus_rd_reg->irq_mask);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_rd_probe(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0, i, j, combo_idx, k;
|
||||||
|
struct cam_ope_bus_rd_reg_val *bus_rd_reg_val;
|
||||||
|
struct cam_ope_bus_rd_reg *bus_rd_reg;
|
||||||
|
struct ope_bus_in_port_to_rm *in_port_to_rm;
|
||||||
|
uint32_t input_port_idx;
|
||||||
|
uint32_t rm_idx;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
bus_rd = kzalloc(sizeof(struct ope_bus_rd), GFP_KERNEL);
|
||||||
|
if (!bus_rd) {
|
||||||
|
CAM_ERR(CAM_OPE, "Out of memory");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
bus_rd->ope_hw_info = ope_hw_info;
|
||||||
|
bus_rd_reg_val = ope_hw_info->bus_rd_reg_val;
|
||||||
|
bus_rd_reg = ope_hw_info->bus_rd_reg;
|
||||||
|
|
||||||
|
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];
|
||||||
|
if (bus_rd_reg_val->rd_clients[i].format_type &
|
||||||
|
BUS_RD_COMBO_BAYER_MASK) {
|
||||||
|
combo_idx = BUS_RD_BAYER;
|
||||||
|
rm_idx = in_port_to_rm->num_rm[combo_idx];
|
||||||
|
in_port_to_rm->input_port_id =
|
||||||
|
bus_rd_reg_val->rd_clients[i].input_port_id;
|
||||||
|
in_port_to_rm->rm_port_id[combo_idx][rm_idx] =
|
||||||
|
bus_rd_reg_val->rd_clients[i].rm_port_id;
|
||||||
|
if (!in_port_to_rm->num_rm[combo_idx])
|
||||||
|
in_port_to_rm->num_combos++;
|
||||||
|
in_port_to_rm->num_rm[combo_idx]++;
|
||||||
|
}
|
||||||
|
if (bus_rd_reg_val->rd_clients[i].format_type &
|
||||||
|
BUS_RD_COMBO_YUV_MASK) {
|
||||||
|
combo_idx = BUS_RD_YUV;
|
||||||
|
rm_idx = in_port_to_rm->num_rm[combo_idx];
|
||||||
|
in_port_to_rm->input_port_id =
|
||||||
|
bus_rd_reg_val->rd_clients[i].input_port_id;
|
||||||
|
in_port_to_rm->rm_port_id[combo_idx][rm_idx] =
|
||||||
|
bus_rd_reg_val->rd_clients[i].rm_port_id;
|
||||||
|
if (!in_port_to_rm->num_rm[combo_idx])
|
||||||
|
in_port_to_rm->num_combos++;
|
||||||
|
in_port_to_rm->num_rm[combo_idx]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < OPE_IN_RES_MAX; i++) {
|
||||||
|
in_port_to_rm = &bus_rd->in_port_to_rm[i];
|
||||||
|
CAM_DBG(CAM_OPE, "input port id = %d num_combos = %d",
|
||||||
|
in_port_to_rm->input_port_id,
|
||||||
|
in_port_to_rm->num_combos);
|
||||||
|
for (j = 0; j < in_port_to_rm->num_combos; j++) {
|
||||||
|
CAM_DBG(CAM_OPE, "combo idx = %d num_rms = %d",
|
||||||
|
j, in_port_to_rm->num_rm[j]);
|
||||||
|
for (k = 0; k < in_port_to_rm->num_rm[j]; k++) {
|
||||||
|
CAM_DBG(CAM_OPE, "rm port id = %d",
|
||||||
|
in_port_to_rm->rm_port_id[j][k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_rd_isr(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
uint32_t irq_status;
|
||||||
|
struct cam_ope_bus_rd_reg *bus_rd_reg;
|
||||||
|
struct cam_ope_bus_rd_reg_val *bus_rd_reg_val;
|
||||||
|
struct cam_ope_irq_data *irq_data = data;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bus_rd_reg = ope_hw_info->bus_rd_reg;
|
||||||
|
bus_rd_reg_val = ope_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_set_clear,
|
||||||
|
bus_rd_reg->base + bus_rd_reg->irq_cmd);
|
||||||
|
|
||||||
|
if (irq_status & bus_rd_reg_val->rst_done) {
|
||||||
|
complete(&bus_rd->reset_complete);
|
||||||
|
CAM_ERR(CAM_OPE, "ope bus rd reset done");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((irq_status & bus_rd_reg_val->violation) ==
|
||||||
|
bus_rd_reg_val->violation) {
|
||||||
|
irq_data->error = 1;
|
||||||
|
CAM_ERR(CAM_OPE, "ope bus rd CCIF vioalation");
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_bus_rd_process(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, uint32_t cmd_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
switch (cmd_id) {
|
||||||
|
case OPE_HW_PROBE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PROBE: E");
|
||||||
|
rc = cam_ope_bus_rd_probe(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PROBE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_INIT:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_INIT: E");
|
||||||
|
rc = cam_ope_bus_rd_init(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_INIT: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_ACQUIRE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: E");
|
||||||
|
rc = cam_ope_bus_rd_acquire(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_RELEASE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_RELEASE: E");
|
||||||
|
rc = cam_ope_bus_rd_release(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_RELEASE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_PREPARE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PREPARE: E");
|
||||||
|
rc = cam_ope_bus_rd_prepare(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PREPARE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_ISR:
|
||||||
|
rc = cam_ope_bus_rd_isr(ope_hw_info, 0, data);
|
||||||
|
break;
|
||||||
|
case OPE_HW_DEINIT:
|
||||||
|
case OPE_HW_START:
|
||||||
|
case OPE_HW_STOP:
|
||||||
|
case OPE_HW_FLUSH:
|
||||||
|
case OPE_HW_CLK_UPDATE:
|
||||||
|
case OPE_HW_BW_UPDATE:
|
||||||
|
case OPE_HW_RESET:
|
||||||
|
case OPE_HW_SET_IRQ_CB:
|
||||||
|
rc = 0;
|
||||||
|
CAM_DBG(CAM_OPE, "Unhandled cmds: %d", cmd_id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CAM_ERR(CAM_OPE, "Unsupported cmd: %d", cmd_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
139
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h
Normal file
139
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_rd/ope_bus_rd.h
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPE_BUS_RD_H
|
||||||
|
#define OPE_BUS_RD_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
#include <media/cam_ope.h>
|
||||||
|
#include "ope_hw.h"
|
||||||
|
#include "cam_hw_mgr_intf.h"
|
||||||
|
#include "cam_hw_intf.h"
|
||||||
|
#include "cam_soc_util.h"
|
||||||
|
#include "cam_context.h"
|
||||||
|
#include "cam_ope_context.h"
|
||||||
|
#include "cam_ope_hw_mgr.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_rd_cdm_info
|
||||||
|
*
|
||||||
|
* @offset: Offset
|
||||||
|
* @addr: Address
|
||||||
|
* @len: Length
|
||||||
|
*/
|
||||||
|
struct ope_bus_rd_cdm_info {
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t *addr;
|
||||||
|
uint32_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_rd_io_port_cdm_info
|
||||||
|
*
|
||||||
|
* @num_frames_cmds: Number of frame commands
|
||||||
|
* @f_cdm_info: Frame cdm info
|
||||||
|
* @num_stripes: Number of stripes
|
||||||
|
* @num_s_cmd_bufs: Number of stripe commands
|
||||||
|
* @s_cdm_info: Stripe cdm info
|
||||||
|
* @go_cmd_addr: GO command address
|
||||||
|
* @go_cmd_len: GO command length
|
||||||
|
*/
|
||||||
|
struct ope_bus_rd_io_port_cdm_info {
|
||||||
|
uint32_t num_frames_cmds;
|
||||||
|
struct ope_bus_rd_cdm_info f_cdm_info[MAX_RD_CLIENTS];
|
||||||
|
uint32_t num_stripes;
|
||||||
|
uint32_t num_s_cmd_bufs[OPE_MAX_STRIPES];
|
||||||
|
struct ope_bus_rd_cdm_info s_cdm_info[OPE_MAX_STRIPES][MAX_RD_CLIENTS];
|
||||||
|
uint32_t go_cmd_offset;
|
||||||
|
uint32_t *go_cmd_addr;
|
||||||
|
uint32_t go_cmd_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_rd_io_port_cdm_batch
|
||||||
|
*
|
||||||
|
* num_batch: Number of batches
|
||||||
|
* io_port_cdm: CDM IO Port Info
|
||||||
|
*/
|
||||||
|
struct ope_bus_rd_io_port_cdm_batch {
|
||||||
|
uint32_t num_batch;
|
||||||
|
struct ope_bus_rd_io_port_cdm_info io_port_cdm[OPE_MAX_BATCH_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_rd_rm
|
||||||
|
*
|
||||||
|
* @rm_port_id: RM port ID
|
||||||
|
* @format_type: Format type
|
||||||
|
*/
|
||||||
|
struct ope_bus_rd_rm {
|
||||||
|
uint32_t rm_port_id;
|
||||||
|
uint32_t format_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_in_port_to_rm
|
||||||
|
*
|
||||||
|
* @input_port_id: Intput port ID
|
||||||
|
* @num_combos: Number of combos
|
||||||
|
* @num_rm: Number of RMs
|
||||||
|
* @rm_port_id: RM port Id
|
||||||
|
*/
|
||||||
|
struct ope_bus_in_port_to_rm {
|
||||||
|
uint32_t input_port_id;
|
||||||
|
uint32_t num_combos;
|
||||||
|
uint32_t num_rm[BUS_RD_COMBO_MAX];
|
||||||
|
uint32_t rm_port_id[BUS_RD_COMBO_MAX][MAX_RD_CLIENTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_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 ope_bus_rd_io_port_info {
|
||||||
|
uint32_t pixel_pattern[OPE_IN_RES_MAX];
|
||||||
|
uint32_t input_port_id[OPE_IN_RES_MAX];
|
||||||
|
uint32_t input_format_type[OPE_IN_RES_MAX];
|
||||||
|
uint32_t latency_buf_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_rd_ctx
|
||||||
|
*
|
||||||
|
* @ope_acquire: OPE acquire structure
|
||||||
|
* @security_flag: security flag
|
||||||
|
* @num_in_ports: Number of in ports
|
||||||
|
* @io_port_info: IO port info
|
||||||
|
* @io_port_cdm_batch: IO port cdm info
|
||||||
|
*/
|
||||||
|
struct ope_bus_rd_ctx {
|
||||||
|
struct ope_acquire_dev_info *ope_acquire;
|
||||||
|
bool security_flag;
|
||||||
|
uint32_t num_in_ports;
|
||||||
|
struct ope_bus_rd_io_port_info io_port_info;
|
||||||
|
struct ope_bus_rd_io_port_cdm_batch io_port_cdm_batch;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_rd
|
||||||
|
*
|
||||||
|
* @ope_hw_info: OPE hardware info
|
||||||
|
* @in_port_to_rm: IO port to RM mapping
|
||||||
|
* @bus_rd_ctx: RM context
|
||||||
|
*/
|
||||||
|
struct ope_bus_rd {
|
||||||
|
struct ope_hw *ope_hw_info;
|
||||||
|
struct ope_bus_in_port_to_rm in_port_to_rm[OPE_IN_RES_MAX];
|
||||||
|
struct ope_bus_rd_ctx bus_rd_ctx[OPE_CTX_MAX];
|
||||||
|
struct completion reset_complete;
|
||||||
|
};
|
||||||
|
#endif /* OPE_BUS_RD_H */
|
||||||
|
|
785
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c
Normal file
785
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.c
Normal file
@@ -0,0 +1,785 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, 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_ope.h>
|
||||||
|
#include "cam_io_util.h"
|
||||||
|
#include "cam_hw.h"
|
||||||
|
#include "cam_hw_intf.h"
|
||||||
|
#include "ope_core.h"
|
||||||
|
#include "ope_soc.h"
|
||||||
|
#include "cam_soc_util.h"
|
||||||
|
#include "cam_io_util.h"
|
||||||
|
#include "cam_cpas_api.h"
|
||||||
|
#include "cam_debug_util.h"
|
||||||
|
#include "ope_hw.h"
|
||||||
|
#include "ope_dev_intf.h"
|
||||||
|
#include "ope_bus_wr.h"
|
||||||
|
#include "cam_cdm_util.h"
|
||||||
|
|
||||||
|
static struct ope_bus_wr *wr_info;
|
||||||
|
|
||||||
|
static int cam_ope_bus_en_port_idx(
|
||||||
|
struct cam_ope_request *ope_request,
|
||||||
|
uint32_t batch_idx,
|
||||||
|
uint32_t output_port_id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct ope_io_buf *io_buf;
|
||||||
|
|
||||||
|
if (batch_idx >= OPE_MAX_BATCH_SIZE) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ope_request->num_io_bufs[batch_idx]; i++) {
|
||||||
|
io_buf = &ope_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_ope_bus_wr_out_port_idx(uint32_t output_port_id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < OPE_OUT_RES_MAX; i++)
|
||||||
|
if (wr_info->out_port_to_wm[i].output_port_id == output_port_id)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cam_ope_bus_wr_subsample(
|
||||||
|
struct cam_ope_ctx *ctx_data,
|
||||||
|
struct ope_hw *ope_hw_info,
|
||||||
|
struct cam_ope_bus_wr_client_reg *wr_reg_client,
|
||||||
|
struct ope_io_buf *io_buf,
|
||||||
|
uint32_t *temp_reg, uint32_t count,
|
||||||
|
int plane_idx, int stripe_idx)
|
||||||
|
{
|
||||||
|
int k, l;
|
||||||
|
struct cam_ope_bus_wr_reg *wr_reg;
|
||||||
|
struct cam_ope_bus_wr_reg_val *wr_reg_val;
|
||||||
|
|
||||||
|
wr_reg = ope_hw_info->bus_wr_reg;
|
||||||
|
wr_reg_val = ope_hw_info->bus_wr_reg_val;
|
||||||
|
|
||||||
|
if (plane_idx >= OPE_MAX_PLANES) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid plane idx: %d", plane_idx);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
k = plane_idx;
|
||||||
|
l = stripe_idx;
|
||||||
|
|
||||||
|
/* subsample period and pattern */
|
||||||
|
if ((ctx_data->ope_acquire.dev_type ==
|
||||||
|
OPE_DEV_TYPE_OPE_RT) && l == 0) {
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->subsample_period;
|
||||||
|
temp_reg[count++] = io_buf->num_stripes[k];
|
||||||
|
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->subsample_pattern;
|
||||||
|
temp_reg[count++] = 1 <<
|
||||||
|
(io_buf->num_stripes[k] - 1);
|
||||||
|
} else if ((ctx_data->ope_acquire.dev_type ==
|
||||||
|
OPE_DEV_TYPE_OPE_NRT) &&
|
||||||
|
((l %
|
||||||
|
ctx_data->ope_acquire.nrt_stripes_for_arb) ==
|
||||||
|
0)) {
|
||||||
|
if (io_buf->num_stripes[k] >=
|
||||||
|
(l +
|
||||||
|
ctx_data->ope_acquire.nrt_stripes_for_arb)){
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->subsample_period;
|
||||||
|
temp_reg[count++] =
|
||||||
|
ctx_data->ope_acquire.nrt_stripes_for_arb;
|
||||||
|
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->subsample_pattern;
|
||||||
|
temp_reg[count++] = 1 <<
|
||||||
|
(ctx_data->ope_acquire.nrt_stripes_for_arb -
|
||||||
|
1);
|
||||||
|
} else {
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->subsample_period;
|
||||||
|
temp_reg[count++] = io_buf->num_stripes[k] - l;
|
||||||
|
|
||||||
|
/* subsample pattern */
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->subsample_pattern;
|
||||||
|
temp_reg[count++] = 1 << (io_buf->num_stripes[k] -
|
||||||
|
l - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_wr_release(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0, i;
|
||||||
|
struct ope_acquire_dev_info *in_acquire;
|
||||||
|
struct ope_bus_wr_ctx *bus_wr_ctx;
|
||||||
|
|
||||||
|
if (ctx_id < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d", ctx_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_acquire = wr_info->bus_wr_ctx[ctx_id].ope_acquire;
|
||||||
|
wr_info->bus_wr_ctx[ctx_id].ope_acquire = NULL;
|
||||||
|
bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id];
|
||||||
|
bus_wr_ctx->num_out_ports = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < bus_wr_ctx->num_out_ports; i++) {
|
||||||
|
bus_wr_ctx->io_port_info.output_port_id[i] = 0;
|
||||||
|
bus_wr_ctx->io_port_info.output_format_type[i - 1] = 0;
|
||||||
|
bus_wr_ctx->io_port_info.pixel_pattern[i - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t *cam_ope_bus_wr_update(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, struct cam_ope_dev_prepare_req *prepare,
|
||||||
|
int batch_idx, int io_idx,
|
||||||
|
uint32_t *kmd_buf, uint32_t *num_stripes)
|
||||||
|
{
|
||||||
|
int k, l, out_port_idx;
|
||||||
|
uint32_t idx;
|
||||||
|
uint32_t num_wm_ports;
|
||||||
|
uint32_t comb_idx;
|
||||||
|
uint32_t req_idx;
|
||||||
|
uint32_t temp_reg[128];
|
||||||
|
uint32_t count = 0;
|
||||||
|
uint32_t temp = 0;
|
||||||
|
uint32_t wm_port_id;
|
||||||
|
uint32_t header_size;
|
||||||
|
struct cam_hw_prepare_update_args *prepare_args;
|
||||||
|
struct cam_ope_ctx *ctx_data;
|
||||||
|
struct cam_ope_request *ope_request;
|
||||||
|
struct ope_io_buf *io_buf;
|
||||||
|
struct ope_stripe_io *stripe_io;
|
||||||
|
struct ope_bus_wr_ctx *bus_wr_ctx;
|
||||||
|
struct cam_ope_bus_wr_reg *wr_reg;
|
||||||
|
struct cam_ope_bus_wr_client_reg *wr_reg_client;
|
||||||
|
struct cam_ope_bus_wr_reg_val *wr_reg_val;
|
||||||
|
struct cam_ope_bus_wr_client_reg_val *wr_res_val_client;
|
||||||
|
struct ope_bus_out_port_to_wm *out_port_to_wm;
|
||||||
|
struct ope_bus_wr_io_port_cdm_batch *io_port_cdm_batch;
|
||||||
|
struct ope_bus_wr_io_port_cdm_info *io_port_cdm;
|
||||||
|
struct cam_cdm_utils_ops *cdm_ops;
|
||||||
|
|
||||||
|
|
||||||
|
if (ctx_id < 0 || !prepare) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, prepare);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batch_idx >= OPE_MAX_BATCH_SIZE) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (io_idx >= OPE_MAX_IO_BUFS) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid IO idx: %d", io_idx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_args = prepare->prepare_args;
|
||||||
|
ctx_data = prepare->ctx_data;
|
||||||
|
req_idx = prepare->req_idx;
|
||||||
|
cdm_ops = ctx_data->ope_cdm.cdm_ops;
|
||||||
|
|
||||||
|
ope_request = ctx_data->req_list[req_idx];
|
||||||
|
bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id];
|
||||||
|
io_port_cdm_batch = &bus_wr_ctx->io_port_cdm_batch;
|
||||||
|
wr_reg = ope_hw_info->bus_wr_reg;
|
||||||
|
wr_reg_val = ope_hw_info->bus_wr_reg_val;
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d req_id = %lld offset = %d",
|
||||||
|
kmd_buf, req_idx, ope_request->request_id,
|
||||||
|
prepare->kmd_buf_offset);
|
||||||
|
|
||||||
|
io_buf = &ope_request->io_buf[batch_idx][io_idx];
|
||||||
|
CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d",
|
||||||
|
batch_idx, io_idx, io_buf->direction);
|
||||||
|
|
||||||
|
io_port_cdm =
|
||||||
|
&bus_wr_ctx->io_port_cdm_batch.io_port_cdm[batch_idx];
|
||||||
|
out_port_idx =
|
||||||
|
cam_ope_bus_wr_out_port_idx(io_buf->resource_type);
|
||||||
|
if (out_port_idx < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "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];
|
||||||
|
comb_idx = BUS_WR_YUV;
|
||||||
|
num_wm_ports = out_port_to_wm->num_wm[comb_idx];
|
||||||
|
|
||||||
|
for (k = 0; k < io_buf->num_planes; k++) {
|
||||||
|
*num_stripes = io_buf->num_stripes[k];
|
||||||
|
for (l = 0; l < io_buf->num_stripes[k]; l++) {
|
||||||
|
stripe_io = &io_buf->s_io[k][l];
|
||||||
|
CAM_DBG(CAM_OPE, "comb_idx = %d p_idx = %d s_idx = %d",
|
||||||
|
comb_idx, k, l);
|
||||||
|
/* frame level info */
|
||||||
|
/* stripe level info */
|
||||||
|
wm_port_id = out_port_to_wm->wm_port_id[comb_idx][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_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->core_cfg;
|
||||||
|
temp = 0;
|
||||||
|
if (!stripe_io->disable_bus)
|
||||||
|
temp = wr_res_val_client->core_cfg_en;
|
||||||
|
temp |= ((wr_res_val_client->mode &
|
||||||
|
wr_res_val_client->mode_mask) <<
|
||||||
|
wr_res_val_client->mode_shift);
|
||||||
|
temp_reg[count++] = temp;
|
||||||
|
|
||||||
|
/* Address of the Image */
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->img_addr;
|
||||||
|
temp_reg[count++] = stripe_io->iova_addr;
|
||||||
|
|
||||||
|
/* Buffer size */
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->img_cfg;
|
||||||
|
temp = 0;
|
||||||
|
temp = stripe_io->width;
|
||||||
|
temp |= (stripe_io->height &
|
||||||
|
wr_res_val_client->height_mask) <<
|
||||||
|
wr_res_val_client->height_shift;
|
||||||
|
temp_reg[count++] = temp;
|
||||||
|
|
||||||
|
/* x_init */
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->x_init;
|
||||||
|
temp_reg[count++] = stripe_io->x_init;
|
||||||
|
|
||||||
|
/* stride */
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->stride;
|
||||||
|
temp_reg[count++] = stripe_io->stride;
|
||||||
|
|
||||||
|
/* pack cfg : Format and alignment */
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->pack_cfg;
|
||||||
|
temp = 0;
|
||||||
|
temp |= ((stripe_io->pack_format &
|
||||||
|
wr_res_val_client->format_mask) <<
|
||||||
|
wr_res_val_client->format_shift);
|
||||||
|
temp |= ((stripe_io->alignment &
|
||||||
|
wr_res_val_client->alignment_mask) <<
|
||||||
|
wr_res_val_client->alignment_shift);
|
||||||
|
temp_reg[count++] = temp;
|
||||||
|
|
||||||
|
/* subsample period and pattern */
|
||||||
|
count = cam_ope_bus_wr_subsample(
|
||||||
|
ctx_data, ope_hw_info,
|
||||||
|
wr_reg_client, io_buf,
|
||||||
|
temp_reg, count, k, l);
|
||||||
|
|
||||||
|
header_size = cdm_ops->cdm_get_cmd_header_size(
|
||||||
|
CAM_CDM_CMD_REG_RANDOM);
|
||||||
|
idx = io_port_cdm->num_s_cmd_bufs[l];
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].len =
|
||||||
|
sizeof(temp) * (count + header_size);
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].offset =
|
||||||
|
prepare->kmd_buf_offset;
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf;
|
||||||
|
io_port_cdm->num_s_cmd_bufs[l]++;
|
||||||
|
|
||||||
|
kmd_buf = cdm_ops->cdm_write_regrandom(
|
||||||
|
kmd_buf, count/2, temp_reg);
|
||||||
|
prepare->kmd_buf_offset += ((count + header_size) *
|
||||||
|
sizeof(temp));
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d",
|
||||||
|
batch_idx, io_idx, k, l);
|
||||||
|
CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d",
|
||||||
|
kmd_buf, prepare->kmd_buf_offset);
|
||||||
|
CAM_DBG(CAM_OPE, "count:%d temp_reg:%x",
|
||||||
|
count, temp_reg, header_size);
|
||||||
|
CAM_DBG(CAM_OPE, "header_size:%d", header_size);
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "WR cmd bufs = %d",
|
||||||
|
io_port_cdm->num_s_cmd_bufs[l]);
|
||||||
|
CAM_DBG(CAM_OPE, "off:%d len:%d",
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].offset,
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].len);
|
||||||
|
CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d",
|
||||||
|
batch_idx, io_idx, k, l);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kmd_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t *cam_ope_bus_wm_disable(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, struct cam_ope_dev_prepare_req *prepare,
|
||||||
|
int batch_idx, int io_idx,
|
||||||
|
uint32_t *kmd_buf, uint32_t num_stripes)
|
||||||
|
{
|
||||||
|
int k, l;
|
||||||
|
uint32_t idx;
|
||||||
|
uint32_t num_wm_ports;
|
||||||
|
uint32_t comb_idx;
|
||||||
|
uint32_t req_idx;
|
||||||
|
uint32_t temp_reg[128];
|
||||||
|
uint32_t count = 0;
|
||||||
|
uint32_t temp = 0;
|
||||||
|
uint32_t wm_port_id;
|
||||||
|
uint32_t header_size;
|
||||||
|
struct cam_ope_ctx *ctx_data;
|
||||||
|
struct ope_bus_wr_ctx *bus_wr_ctx;
|
||||||
|
struct cam_ope_bus_wr_reg *wr_reg;
|
||||||
|
struct cam_ope_bus_wr_client_reg *wr_reg_client;
|
||||||
|
struct ope_bus_out_port_to_wm *out_port_to_wm;
|
||||||
|
struct ope_bus_wr_io_port_cdm_batch *io_port_cdm_batch;
|
||||||
|
struct ope_bus_wr_io_port_cdm_info *io_port_cdm;
|
||||||
|
struct cam_cdm_utils_ops *cdm_ops;
|
||||||
|
|
||||||
|
|
||||||
|
if (ctx_id < 0 || !prepare) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, prepare);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batch_idx >= OPE_MAX_BATCH_SIZE) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid batch idx: %d", batch_idx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx_data = prepare->ctx_data;
|
||||||
|
req_idx = prepare->req_idx;
|
||||||
|
cdm_ops = ctx_data->ope_cdm.cdm_ops;
|
||||||
|
|
||||||
|
bus_wr_ctx = &wr_info->bus_wr_ctx[ctx_id];
|
||||||
|
io_port_cdm_batch = &bus_wr_ctx->io_port_cdm_batch;
|
||||||
|
wr_reg = ope_hw_info->bus_wr_reg;
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d offset = %d",
|
||||||
|
kmd_buf, req_idx, prepare->kmd_buf_offset);
|
||||||
|
|
||||||
|
io_port_cdm =
|
||||||
|
&bus_wr_ctx->io_port_cdm_batch.io_port_cdm[batch_idx];
|
||||||
|
out_port_to_wm = &wr_info->out_port_to_wm[io_idx];
|
||||||
|
comb_idx = BUS_WR_YUV;
|
||||||
|
num_wm_ports = out_port_to_wm->num_wm[comb_idx];
|
||||||
|
|
||||||
|
for (k = 0; k < num_wm_ports; k++) {
|
||||||
|
for (l = 0; l < num_stripes; l++) {
|
||||||
|
CAM_DBG(CAM_OPE, "comb_idx = %d p_idx = %d s_idx = %d",
|
||||||
|
comb_idx, k, l);
|
||||||
|
/* frame level info */
|
||||||
|
/* stripe level info */
|
||||||
|
wm_port_id = out_port_to_wm->wm_port_id[comb_idx][k];
|
||||||
|
wr_reg_client = &wr_reg->wr_clients[wm_port_id];
|
||||||
|
|
||||||
|
/* Core cfg: enable, Mode */
|
||||||
|
temp_reg[count++] = wr_reg->offset +
|
||||||
|
wr_reg_client->core_cfg;
|
||||||
|
temp_reg[count++] = 0;
|
||||||
|
|
||||||
|
header_size = cdm_ops->cdm_get_cmd_header_size(
|
||||||
|
CAM_CDM_CMD_REG_RANDOM);
|
||||||
|
idx = io_port_cdm->num_s_cmd_bufs[l];
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].len =
|
||||||
|
sizeof(temp) * (count + header_size);
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].offset =
|
||||||
|
prepare->kmd_buf_offset;
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].addr = kmd_buf;
|
||||||
|
io_port_cdm->num_s_cmd_bufs[l]++;
|
||||||
|
|
||||||
|
kmd_buf = cdm_ops->cdm_write_regrandom(
|
||||||
|
kmd_buf, count/2, temp_reg);
|
||||||
|
prepare->kmd_buf_offset += ((count + header_size) *
|
||||||
|
sizeof(temp));
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d",
|
||||||
|
batch_idx, io_idx, k, l);
|
||||||
|
CAM_DBG(CAM_OPE, "kmdbuf:%x, offset:%d",
|
||||||
|
kmd_buf, prepare->kmd_buf_offset);
|
||||||
|
CAM_DBG(CAM_OPE, "count:%d temp_reg:%x",
|
||||||
|
count, temp_reg, header_size);
|
||||||
|
CAM_DBG(CAM_OPE, "header_size:%d", header_size);
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "WR cmd bufs = %d",
|
||||||
|
io_port_cdm->num_s_cmd_bufs[l]);
|
||||||
|
CAM_DBG(CAM_OPE, "off:%d len:%d",
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].offset,
|
||||||
|
io_port_cdm->s_cdm_info[l][idx].len);
|
||||||
|
CAM_DBG(CAM_OPE, "b:%d io:%d p:%d s:%d",
|
||||||
|
batch_idx, io_idx, k, l);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare->wr_cdm_batch = &bus_wr_ctx->io_port_cdm_batch;
|
||||||
|
|
||||||
|
return kmd_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_wr_prepare(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
int i, j = 0;
|
||||||
|
uint32_t req_idx;
|
||||||
|
uint32_t *kmd_buf;
|
||||||
|
struct cam_ope_dev_prepare_req *prepare;
|
||||||
|
struct cam_ope_ctx *ctx_data;
|
||||||
|
struct cam_ope_request *ope_request;
|
||||||
|
struct ope_io_buf *io_buf;
|
||||||
|
uint32_t temp;
|
||||||
|
int io_buf_idx;
|
||||||
|
uint32_t num_stripes = 0;
|
||||||
|
struct ope_bus_wr_io_port_cdm_batch *io_port_cdm_batch;
|
||||||
|
struct ope_bus_wr_ctx *bus_wr_ctx;
|
||||||
|
|
||||||
|
if (ctx_id < 0 || !data) {
|
||||||
|
CAM_ERR(CAM_OPE, "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];
|
||||||
|
|
||||||
|
ope_request = ctx_data->req_list[req_idx];
|
||||||
|
kmd_buf = (uint32_t *)ope_request->ope_kmd_buf.cpu_addr +
|
||||||
|
(prepare->kmd_buf_offset / sizeof(temp));
|
||||||
|
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "kmd_buf = %x req_idx = %d req_id = %lld offset = %d",
|
||||||
|
kmd_buf, req_idx, ope_request->request_id,
|
||||||
|
prepare->kmd_buf_offset);
|
||||||
|
|
||||||
|
io_port_cdm_batch = &wr_info->bus_wr_ctx[ctx_id].io_port_cdm_batch;
|
||||||
|
memset(io_port_cdm_batch, 0,
|
||||||
|
sizeof(struct ope_bus_wr_io_port_cdm_batch));
|
||||||
|
|
||||||
|
for (i = 0; i < ope_request->num_batch; i++) {
|
||||||
|
for (j = 0; j < ope_request->num_io_bufs[i]; j++) {
|
||||||
|
io_buf = &ope_request->io_buf[i][j];
|
||||||
|
CAM_DBG(CAM_OPE, "batch = %d io buf num = %d dir = %d",
|
||||||
|
i, j, io_buf->direction);
|
||||||
|
if (io_buf->direction != CAM_BUF_OUTPUT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
kmd_buf = cam_ope_bus_wr_update(ope_hw_info,
|
||||||
|
ctx_id, prepare, i, j,
|
||||||
|
kmd_buf, &num_stripes);
|
||||||
|
if (!kmd_buf) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable WMs which are not enabled */
|
||||||
|
for (i = 0; i < ope_request->num_batch; i++) {
|
||||||
|
for (j = OPE_OUT_RES_VIDEO; j <= OPE_OUT_RES_MAX; j++) {
|
||||||
|
io_buf_idx = cam_ope_bus_en_port_idx(ope_request, i, j);
|
||||||
|
if (io_buf_idx >= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
io_buf_idx = cam_ope_bus_wr_out_port_idx(j);
|
||||||
|
if (io_buf_idx < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid idx for rsc type:%d",
|
||||||
|
j);
|
||||||
|
return io_buf_idx;
|
||||||
|
}
|
||||||
|
kmd_buf = cam_ope_bus_wm_disable(ope_hw_info,
|
||||||
|
ctx_id, prepare, i, io_buf_idx,
|
||||||
|
kmd_buf, num_stripes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prepare->wr_cdm_batch = &bus_wr_ctx->io_port_cdm_batch;
|
||||||
|
|
||||||
|
end:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_wr_acquire(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0, i;
|
||||||
|
struct ope_acquire_dev_info *in_acquire;
|
||||||
|
struct ope_bus_wr_ctx *bus_wr_ctx;
|
||||||
|
struct ope_bus_out_port_to_wm *out_port_to_wr;
|
||||||
|
int combo_idx;
|
||||||
|
int out_port_idx;
|
||||||
|
|
||||||
|
if (ctx_id < 0 || !data) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wr_info->bus_wr_ctx[ctx_id].ope_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_OPE, "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);
|
||||||
|
CAM_DBG(CAM_OPE, "pix_pattern:%u alignment:%u packer_format:%u",
|
||||||
|
in_acquire->out_res[i].pixel_pattern,
|
||||||
|
in_acquire->out_res[i].alignment,
|
||||||
|
in_acquire->out_res[i].packer_format);
|
||||||
|
CAM_DBG(CAM_OPE, "subsample_period = %u subsample_pattern = %u",
|
||||||
|
in_acquire->out_res[i].subsample_period,
|
||||||
|
in_acquire->out_res[i].subsample_pattern);
|
||||||
|
|
||||||
|
out_port_idx =
|
||||||
|
cam_ope_bus_wr_out_port_idx(in_acquire->out_res[i].res_id);
|
||||||
|
if (out_port_idx < 0) {
|
||||||
|
CAM_DBG(CAM_OPE, "Invalid in_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];
|
||||||
|
combo_idx = BUS_WR_YUV;
|
||||||
|
if (!out_port_to_wr->num_wm[combo_idx]) {
|
||||||
|
CAM_DBG(CAM_OPE, "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;
|
||||||
|
if (in_acquire->out_res[i].pixel_pattern >
|
||||||
|
PIXEL_PATTERN_CRYCBY) {
|
||||||
|
CAM_DBG(CAM_OPE, "Invalid pix pattern = %u",
|
||||||
|
in_acquire->out_res[i].pixel_pattern);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
bus_wr_ctx->io_port_info.pixel_pattern[i] =
|
||||||
|
in_acquire->out_res[i].pixel_pattern;
|
||||||
|
bus_wr_ctx->io_port_info.latency_buf_size = 4096;
|
||||||
|
CAM_DBG(CAM_OPE, "i:%d port_id = %u format %u pix_pattern = %u",
|
||||||
|
i, bus_wr_ctx->io_port_info.output_port_id[i],
|
||||||
|
bus_wr_ctx->io_port_info.output_format_type[i],
|
||||||
|
bus_wr_ctx->io_port_info.pixel_pattern[i]);
|
||||||
|
CAM_DBG(CAM_OPE, "latency_buf_size = %u",
|
||||||
|
bus_wr_ctx->io_port_info.latency_buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_wr_init(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct cam_ope_bus_wr_reg_val *bus_wr_reg_val;
|
||||||
|
struct cam_ope_bus_wr_reg *bus_wr_reg;
|
||||||
|
struct cam_ope_dev_init *dev_init = data;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wr_info->ope_hw_info = ope_hw_info;
|
||||||
|
bus_wr_reg_val = ope_hw_info->bus_wr_reg_val;
|
||||||
|
bus_wr_reg = ope_hw_info->bus_wr_reg;
|
||||||
|
bus_wr_reg->base = dev_init->core_info->ope_hw_info->ope_bus_wr_base;
|
||||||
|
|
||||||
|
cam_io_w_mb(bus_wr_reg_val->irq_mask_0,
|
||||||
|
ope_hw_info->bus_wr_reg->base + bus_wr_reg->irq_mask_0);
|
||||||
|
cam_io_w_mb(bus_wr_reg_val->irq_mask_1,
|
||||||
|
ope_hw_info->bus_wr_reg->base + bus_wr_reg->irq_mask_1);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_wr_probe(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0, i, j, combo_idx, k;
|
||||||
|
struct cam_ope_bus_wr_reg_val *bus_wr_reg_val;
|
||||||
|
struct ope_bus_out_port_to_wm *out_port_to_wm;
|
||||||
|
uint32_t output_port_idx;
|
||||||
|
uint32_t wm_idx;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
wr_info = kzalloc(sizeof(struct ope_bus_wr), GFP_KERNEL);
|
||||||
|
if (!wr_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Out of memory");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
wr_info->ope_hw_info = ope_hw_info;
|
||||||
|
bus_wr_reg_val = ope_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];
|
||||||
|
combo_idx = BUS_WR_YUV;
|
||||||
|
wm_idx = out_port_to_wm->num_wm[combo_idx];
|
||||||
|
out_port_to_wm->output_port_id =
|
||||||
|
bus_wr_reg_val->wr_clients[i].output_port_id;
|
||||||
|
out_port_to_wm->wm_port_id[combo_idx][wm_idx] =
|
||||||
|
bus_wr_reg_val->wr_clients[i].wm_port_id;
|
||||||
|
if (!out_port_to_wm->num_wm[combo_idx])
|
||||||
|
out_port_to_wm->num_combos++;
|
||||||
|
out_port_to_wm->num_wm[combo_idx]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < OPE_OUT_RES_MAX; i++) {
|
||||||
|
out_port_to_wm = &wr_info->out_port_to_wm[i];
|
||||||
|
CAM_DBG(CAM_OPE, "output port id = %d num_combos = %d",
|
||||||
|
out_port_to_wm->output_port_id,
|
||||||
|
out_port_to_wm->num_combos);
|
||||||
|
for (j = 0; j < out_port_to_wm->num_combos; j++) {
|
||||||
|
CAM_DBG(CAM_OPE, "combo idx = %d num_wms = %d",
|
||||||
|
j, out_port_to_wm->num_wm[j]);
|
||||||
|
for (k = 0; k < out_port_to_wm->num_wm[j]; k++) {
|
||||||
|
CAM_DBG(CAM_OPE, "wm port id = %d",
|
||||||
|
out_port_to_wm->wm_port_id[j][k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_bus_wr_isr(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
uint32_t irq_status_0, irq_status_1;
|
||||||
|
struct cam_ope_bus_wr_reg *bus_wr_reg;
|
||||||
|
struct cam_ope_bus_wr_reg_val *bus_wr_reg_val;
|
||||||
|
struct cam_ope_irq_data *irq_data = data;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bus_wr_reg = ope_hw_info->bus_wr_reg;
|
||||||
|
bus_wr_reg_val = ope_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_set_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_OPE, "ope bus wr cons_violation");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irq_status_0 & bus_wr_reg_val->violation) {
|
||||||
|
irq_data->error = 1;
|
||||||
|
CAM_ERR(CAM_OPE, "ope bus wr vioalation");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irq_status_0 & bus_wr_reg_val->img_size_violation) {
|
||||||
|
irq_data->error = 1;
|
||||||
|
CAM_ERR(CAM_OPE, "ope bus wr img_size_violation");
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_bus_wr_process(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, uint32_t cmd_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
switch (cmd_id) {
|
||||||
|
case OPE_HW_PROBE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PROBE: E");
|
||||||
|
rc = cam_ope_bus_wr_probe(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PROBE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_INIT:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_INIT: E");
|
||||||
|
rc = cam_ope_bus_wr_init(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_INIT: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_ACQUIRE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: E");
|
||||||
|
rc = cam_ope_bus_wr_acquire(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_RELEASE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_RELEASE: E");
|
||||||
|
rc = cam_ope_bus_wr_release(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_RELEASE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_PREPARE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PREPARE: E");
|
||||||
|
rc = cam_ope_bus_wr_prepare(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PREPARE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_DEINIT:
|
||||||
|
case OPE_HW_START:
|
||||||
|
case OPE_HW_STOP:
|
||||||
|
case OPE_HW_FLUSH:
|
||||||
|
case OPE_HW_CLK_UPDATE:
|
||||||
|
case OPE_HW_BW_UPDATE:
|
||||||
|
case OPE_HW_RESET:
|
||||||
|
case OPE_HW_SET_IRQ_CB:
|
||||||
|
rc = 0;
|
||||||
|
CAM_DBG(CAM_OPE, "Unhandled cmds: %d", cmd_id);
|
||||||
|
break;
|
||||||
|
case OPE_HW_ISR:
|
||||||
|
rc = cam_ope_bus_wr_isr(ope_hw_info, 0, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CAM_ERR(CAM_OPE, "Unsupported cmd: %d", cmd_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
137
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h
Normal file
137
drivers/cam_ope/ope_hw_mgr/ope_hw/bus_wr/ope_bus_wr.h
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPE_BUS_WR_H
|
||||||
|
#define OPE_BUS_WR_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
#include <media/cam_ope.h>
|
||||||
|
#include "ope_hw.h"
|
||||||
|
#include "cam_hw_mgr_intf.h"
|
||||||
|
#include "cam_hw_intf.h"
|
||||||
|
#include "cam_soc_util.h"
|
||||||
|
#include "cam_context.h"
|
||||||
|
#include "cam_ope_context.h"
|
||||||
|
#include "cam_ope_hw_mgr.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_wr_cdm_info
|
||||||
|
*
|
||||||
|
* @offset: Offset
|
||||||
|
* @addr: Address
|
||||||
|
* @len: Length
|
||||||
|
*/
|
||||||
|
struct ope_bus_wr_cdm_info {
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t *addr;
|
||||||
|
uint32_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_wr_io_port_cdm_info
|
||||||
|
*
|
||||||
|
* @num_frames_cmds: Number of frame commands
|
||||||
|
* @f_cdm_info: Frame cdm info
|
||||||
|
* @num_stripes: Number of stripes
|
||||||
|
* @num_s_cmd_bufs: Number of stripe commands
|
||||||
|
* @s_cdm_info: Stripe cdm info
|
||||||
|
* @go_cmd_addr: GO command address
|
||||||
|
* @go_cmd_len: GO command length
|
||||||
|
*/
|
||||||
|
struct ope_bus_wr_io_port_cdm_info {
|
||||||
|
uint32_t num_frames_cmds;
|
||||||
|
struct ope_bus_wr_cdm_info f_cdm_info[MAX_WR_CLIENTS];
|
||||||
|
uint32_t num_stripes;
|
||||||
|
uint32_t num_s_cmd_bufs[OPE_MAX_STRIPES];
|
||||||
|
struct ope_bus_wr_cdm_info s_cdm_info[OPE_MAX_STRIPES][MAX_WR_CLIENTS];
|
||||||
|
uint32_t *go_cmd_addr;
|
||||||
|
uint32_t go_cmd_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_wr_io_port_cdm_batch
|
||||||
|
*
|
||||||
|
* num_batch: Number of batches
|
||||||
|
* io_port_cdm: CDM IO Port Info
|
||||||
|
*/
|
||||||
|
struct ope_bus_wr_io_port_cdm_batch {
|
||||||
|
uint32_t num_batch;
|
||||||
|
struct ope_bus_wr_io_port_cdm_info io_port_cdm[OPE_MAX_BATCH_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_wr_wm
|
||||||
|
*
|
||||||
|
* @wm_port_id: WM port ID
|
||||||
|
* @format_type: Format type
|
||||||
|
*/
|
||||||
|
struct ope_bus_wr_wm {
|
||||||
|
uint32_t wm_port_id;
|
||||||
|
uint32_t format_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_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 ope_bus_out_port_to_wm {
|
||||||
|
uint32_t output_port_id;
|
||||||
|
uint32_t num_combos;
|
||||||
|
uint32_t num_wm[BUS_WR_COMBO_MAX];
|
||||||
|
uint32_t wm_port_id[BUS_WR_COMBO_MAX][MAX_WR_CLIENTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_wr_io_port_info
|
||||||
|
*
|
||||||
|
* @pixel_pattern: Pixel pattern
|
||||||
|
* @output_port_id: Port Id
|
||||||
|
* @output_format_type: Format type
|
||||||
|
* @latency_buf_size: Latency buffer size
|
||||||
|
*/
|
||||||
|
struct ope_bus_wr_io_port_info {
|
||||||
|
uint32_t pixel_pattern[OPE_OUT_RES_MAX];
|
||||||
|
uint32_t output_port_id[OPE_OUT_RES_MAX];
|
||||||
|
uint32_t output_format_type[OPE_OUT_RES_MAX];
|
||||||
|
uint32_t latency_buf_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_wr_ctx
|
||||||
|
*
|
||||||
|
* @ope_acquire: OPE acquire structure
|
||||||
|
* @security_flag: security flag
|
||||||
|
* @num_out_ports: Number of out ports
|
||||||
|
* @io_port_info: IO port info
|
||||||
|
* @io_port_cdm_batch: IO port cdm info
|
||||||
|
*/
|
||||||
|
struct ope_bus_wr_ctx {
|
||||||
|
struct ope_acquire_dev_info *ope_acquire;
|
||||||
|
bool security_flag;
|
||||||
|
uint32_t num_out_ports;
|
||||||
|
struct ope_bus_wr_io_port_info io_port_info;
|
||||||
|
struct ope_bus_wr_io_port_cdm_batch io_port_cdm_batch;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_bus_wr
|
||||||
|
*
|
||||||
|
* @ope_hw_info: OPE hardware info
|
||||||
|
* @out_port_to_wm: IO port to WM mapping
|
||||||
|
* @bus_wr_ctx: WM context
|
||||||
|
*/
|
||||||
|
struct ope_bus_wr {
|
||||||
|
struct ope_hw *ope_hw_info;
|
||||||
|
struct ope_bus_out_port_to_wm out_port_to_wm[OPE_OUT_RES_MAX];
|
||||||
|
struct ope_bus_wr_ctx bus_wr_ctx[OPE_CTX_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* OPE_BUS_WR_H */
|
||||||
|
|
1781
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c
Normal file
1781
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c
Normal file
File diff suppressed because it is too large
Load Diff
99
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h
Normal file
99
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.h
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAM_OPE_CORE_H
|
||||||
|
#define CAM_OPE_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_ope.h>
|
||||||
|
#include "cam_cpas_api.h"
|
||||||
|
#include "ope_hw.h"
|
||||||
|
#include "ope_dev_intf.h"
|
||||||
|
/**
|
||||||
|
* struct cam_ope_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_ope_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_ope_device_hw_info
|
||||||
|
*
|
||||||
|
* @ope_hw: OPE hardware
|
||||||
|
* @hw_idx: Hardware index
|
||||||
|
* @ope_cdm_base: Base address of CDM
|
||||||
|
* @ope_top_base: Base address of top
|
||||||
|
* @ope_qos_base: Base address of QOS
|
||||||
|
* @ope_pp_base: Base address of PP
|
||||||
|
* @ope_bus_rd_base: Base address of RD
|
||||||
|
* @ope_bus_wr_base: Base address of WM
|
||||||
|
* @hfi_en: HFI flag enable
|
||||||
|
* @reserved: Reserved
|
||||||
|
*/
|
||||||
|
struct cam_ope_device_hw_info {
|
||||||
|
struct ope_hw *ope_hw;
|
||||||
|
uint32_t hw_idx;
|
||||||
|
void *ope_cdm_base;
|
||||||
|
void *ope_top_base;
|
||||||
|
void *ope_qos_base;
|
||||||
|
void *ope_pp_base;
|
||||||
|
void *ope_bus_rd_base;
|
||||||
|
void *ope_bus_wr_base;
|
||||||
|
bool hfi_en;
|
||||||
|
uint32_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_device_core_info
|
||||||
|
*
|
||||||
|
* @ope_hw_info: OPE hardware info
|
||||||
|
* @hw_version: Hardware version
|
||||||
|
* @hw_idx: Hardware Index
|
||||||
|
* @hw_type: Hardware Type
|
||||||
|
* @cpas_handle: CPAS Handle
|
||||||
|
* @cpas_start: CPAS start flag
|
||||||
|
* @clk_enable: Clock enable flag
|
||||||
|
* @irq_cb: IRQ Callback
|
||||||
|
*/
|
||||||
|
struct cam_ope_device_core_info {
|
||||||
|
struct cam_ope_device_hw_info *ope_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_ope_set_irq_cb irq_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int cam_ope_init_hw(void *device_priv,
|
||||||
|
void *init_hw_args, uint32_t arg_size);
|
||||||
|
int cam_ope_deinit_hw(void *device_priv,
|
||||||
|
void *init_hw_args, uint32_t arg_size);
|
||||||
|
int cam_ope_start(void *device_priv,
|
||||||
|
void *start_args, uint32_t arg_size);
|
||||||
|
int cam_ope_stop(void *device_priv,
|
||||||
|
void *stop_args, uint32_t arg_size);
|
||||||
|
int cam_ope_flush(void *device_priv,
|
||||||
|
void *flush_args, uint32_t arg_size);
|
||||||
|
int cam_ope_get_hw_caps(void *device_priv,
|
||||||
|
void *get_hw_cap_args, uint32_t arg_size);
|
||||||
|
int cam_ope_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||||
|
void *cmd_args, uint32_t arg_size);
|
||||||
|
irqreturn_t cam_ope_irq(int irq_num, void *data);
|
||||||
|
|
||||||
|
#endif /* CAM_OPE_CORE_H */
|
253
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c
Normal file
253
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, 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 "ope_core.h"
|
||||||
|
#include "ope_soc.h"
|
||||||
|
#include "cam_hw.h"
|
||||||
|
#include "ope_hw.h"
|
||||||
|
#include "cam_hw_intf.h"
|
||||||
|
#include "cam_io_util.h"
|
||||||
|
#include "cam_ope_hw_mgr_intf.h"
|
||||||
|
#include "cam_cpas_api.h"
|
||||||
|
#include "cam_debug_util.h"
|
||||||
|
#include "ope_hw_100.h"
|
||||||
|
#include "ope_dev_intf.h"
|
||||||
|
|
||||||
|
static struct cam_ope_device_hw_info ope_hw_info;
|
||||||
|
static struct ope_dev_soc ope_soc_info;
|
||||||
|
EXPORT_SYMBOL(ope_soc_info);
|
||||||
|
|
||||||
|
static struct hw_version_reg ope_hw_version_reg = {
|
||||||
|
.hw_ver = 0x0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static char ope_dev_name[8];
|
||||||
|
|
||||||
|
static int cam_ope_init_hw_version(struct cam_hw_soc_info *soc_info,
|
||||||
|
struct cam_ope_device_core_info *core_info)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "soc_info = %x core_info = %x",
|
||||||
|
soc_info, core_info);
|
||||||
|
CAM_DBG(CAM_OPE, "CDM:%x TOP: %x QOS: %x PP: %x RD: %x WR: %x",
|
||||||
|
soc_info->reg_map[OPE_CDM_BASE].mem_base,
|
||||||
|
soc_info->reg_map[OPE_TOP_BASE].mem_base,
|
||||||
|
soc_info->reg_map[OPE_QOS_BASE].mem_base,
|
||||||
|
soc_info->reg_map[OPE_PP_BASE].mem_base,
|
||||||
|
soc_info->reg_map[OPE_BUS_RD].mem_base,
|
||||||
|
soc_info->reg_map[OPE_BUS_WR].mem_base);
|
||||||
|
CAM_DBG(CAM_OPE, "core: %x",
|
||||||
|
core_info->ope_hw_info->ope_cdm_base);
|
||||||
|
|
||||||
|
core_info->ope_hw_info->ope_cdm_base =
|
||||||
|
soc_info->reg_map[OPE_CDM_BASE].mem_base;
|
||||||
|
core_info->ope_hw_info->ope_top_base =
|
||||||
|
soc_info->reg_map[OPE_TOP_BASE].mem_base;
|
||||||
|
core_info->ope_hw_info->ope_qos_base =
|
||||||
|
soc_info->reg_map[OPE_QOS_BASE].mem_base;
|
||||||
|
core_info->ope_hw_info->ope_pp_base =
|
||||||
|
soc_info->reg_map[OPE_PP_BASE].mem_base;
|
||||||
|
core_info->ope_hw_info->ope_bus_rd_base =
|
||||||
|
soc_info->reg_map[OPE_BUS_RD].mem_base;
|
||||||
|
core_info->ope_hw_info->ope_bus_wr_base =
|
||||||
|
soc_info->reg_map[OPE_BUS_WR].mem_base;
|
||||||
|
|
||||||
|
core_info->hw_version = cam_io_r_mb(
|
||||||
|
core_info->ope_hw_info->ope_top_base +
|
||||||
|
ope_hw_version_reg.hw_ver);
|
||||||
|
|
||||||
|
switch (core_info->hw_version) {
|
||||||
|
case OPE_HW_VER_1_0_0:
|
||||||
|
core_info->ope_hw_info->ope_hw = &ope_hw_100;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CAM_ERR(CAM_OPE, "Unsupported version : %u",
|
||||||
|
core_info->hw_version);
|
||||||
|
rc = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ope_hw_100.top_reg->base = core_info->ope_hw_info->ope_top_base;
|
||||||
|
ope_hw_100.bus_rd_reg->base = core_info->ope_hw_info->ope_bus_rd_base;
|
||||||
|
ope_hw_100.bus_wr_reg->base = core_info->ope_hw_info->ope_bus_wr_base;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_register_cpas(struct cam_hw_soc_info *soc_info,
|
||||||
|
struct cam_ope_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, "ope", sizeof("ope"));
|
||||||
|
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_OPE, "failed: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
core_info->cpas_handle = cpas_register_params.client_handle;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct cam_hw_intf *ope_dev_intf = NULL;
|
||||||
|
struct cam_hw_info *ope_dev = NULL;
|
||||||
|
const struct of_device_id *match_dev = NULL;
|
||||||
|
struct cam_ope_device_core_info *core_info = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
uint32_t hw_idx;
|
||||||
|
struct cam_ope_dev_probe ope_probe;
|
||||||
|
|
||||||
|
of_property_read_u32(pdev->dev.of_node,
|
||||||
|
"cell-index", &hw_idx);
|
||||||
|
|
||||||
|
ope_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
|
||||||
|
if (!ope_dev_intf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ope_dev_intf->hw_idx = hw_idx;
|
||||||
|
ope_dev_intf->hw_type = OPE_DEV_OPE;
|
||||||
|
ope_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||||
|
if (!ope_dev) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto ope_dev_alloc_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(ope_dev_name, 0, sizeof(ope_dev_name));
|
||||||
|
snprintf(ope_dev_name, sizeof(ope_dev_name),
|
||||||
|
"ope%1u", ope_dev_intf->hw_idx);
|
||||||
|
|
||||||
|
ope_dev->soc_info.pdev = pdev;
|
||||||
|
ope_dev->soc_info.dev = &pdev->dev;
|
||||||
|
ope_dev->soc_info.dev_name = ope_dev_name;
|
||||||
|
ope_dev_intf->hw_priv = ope_dev;
|
||||||
|
ope_dev_intf->hw_ops.init = cam_ope_init_hw;
|
||||||
|
ope_dev_intf->hw_ops.deinit = cam_ope_deinit_hw;
|
||||||
|
ope_dev_intf->hw_ops.get_hw_caps = cam_ope_get_hw_caps;
|
||||||
|
ope_dev_intf->hw_ops.start = cam_ope_start;
|
||||||
|
ope_dev_intf->hw_ops.stop = cam_ope_stop;
|
||||||
|
ope_dev_intf->hw_ops.flush = cam_ope_flush;
|
||||||
|
ope_dev_intf->hw_ops.process_cmd = cam_ope_process_cmd;
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "type %d index %d",
|
||||||
|
ope_dev_intf->hw_type,
|
||||||
|
ope_dev_intf->hw_idx);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, ope_dev_intf);
|
||||||
|
|
||||||
|
ope_dev->core_info = kzalloc(sizeof(struct cam_ope_device_core_info),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!ope_dev->core_info) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto ope_core_alloc_failed;
|
||||||
|
}
|
||||||
|
core_info = (struct cam_ope_device_core_info *)ope_dev->core_info;
|
||||||
|
core_info->ope_hw_info = &ope_hw_info;
|
||||||
|
ope_dev->soc_info.soc_private = &ope_soc_info;
|
||||||
|
|
||||||
|
match_dev = of_match_device(pdev->dev.driver->of_match_table,
|
||||||
|
&pdev->dev);
|
||||||
|
if (!match_dev) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
CAM_DBG(CAM_OPE, "No ope hardware info");
|
||||||
|
goto ope_match_dev_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cam_ope_init_soc_resources(&ope_dev->soc_info, cam_ope_irq,
|
||||||
|
ope_dev);
|
||||||
|
if (rc < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "failed to init_soc");
|
||||||
|
goto init_soc_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cam_ope_enable_soc_resources(&ope_dev->soc_info);
|
||||||
|
if (rc < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "enable soc resorce failed: %d", rc);
|
||||||
|
goto enable_soc_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cam_ope_init_hw_version(&ope_dev->soc_info, ope_dev->core_info);
|
||||||
|
if (rc)
|
||||||
|
goto init_hw_failure;
|
||||||
|
|
||||||
|
core_info->hw_type = OPE_DEV_OPE;
|
||||||
|
core_info->hw_idx = hw_idx;
|
||||||
|
rc = cam_ope_register_cpas(&ope_dev->soc_info,
|
||||||
|
core_info, ope_dev_intf->hw_idx);
|
||||||
|
if (rc < 0)
|
||||||
|
goto register_cpas_failed;
|
||||||
|
|
||||||
|
cam_ope_disable_soc_resources(&ope_dev->soc_info, true);
|
||||||
|
ope_dev->hw_state = CAM_HW_STATE_POWER_DOWN;
|
||||||
|
|
||||||
|
ope_probe.hfi_en = ope_soc_info.hfi_en;
|
||||||
|
cam_ope_process_cmd(ope_dev, OPE_HW_PROBE,
|
||||||
|
&ope_probe, sizeof(ope_probe));
|
||||||
|
mutex_init(&ope_dev->hw_mutex);
|
||||||
|
spin_lock_init(&ope_dev->hw_lock);
|
||||||
|
init_completion(&ope_dev->hw_complete);
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "OPE%d probe successful",
|
||||||
|
ope_dev_intf->hw_idx);
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
init_hw_failure:
|
||||||
|
enable_soc_failed:
|
||||||
|
register_cpas_failed:
|
||||||
|
init_soc_failed:
|
||||||
|
ope_match_dev_failed:
|
||||||
|
kfree(ope_dev->core_info);
|
||||||
|
ope_core_alloc_failed:
|
||||||
|
kfree(ope_dev);
|
||||||
|
ope_dev_alloc_failed:
|
||||||
|
kfree(ope_dev_intf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id cam_ope_dt_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "qcom,ope",
|
||||||
|
.data = &ope_hw_version_reg,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, cam_ope_dt_match);
|
||||||
|
|
||||||
|
static struct platform_driver cam_ope_driver = {
|
||||||
|
.probe = cam_ope_probe,
|
||||||
|
.driver = {
|
||||||
|
.name = "ope",
|
||||||
|
.of_match_table = cam_ope_dt_match,
|
||||||
|
.suppress_bind_attrs = true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
int cam_ope_init_module(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&cam_ope_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cam_ope_exit_module(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&cam_ope_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("CAM OPE driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
174
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h
Normal file
174
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev_intf.h
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAM_OPE_DEV_INTF_H
|
||||||
|
#define CAM_OPE_DEV_INTF_H
|
||||||
|
|
||||||
|
#include <media/cam_ope.h>
|
||||||
|
#include "cam_ope_hw_mgr.h"
|
||||||
|
#include "cam_cdm_intf_api.h"
|
||||||
|
#include "cam_cpas_api.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define OPE_HW_INIT 0x1
|
||||||
|
#define OPE_HW_DEINIT 0x2
|
||||||
|
#define OPE_HW_ACQUIRE 0x3
|
||||||
|
#define OPE_HW_RELEASE 0x4
|
||||||
|
#define OPE_HW_START 0x5
|
||||||
|
#define OPE_HW_STOP 0x6
|
||||||
|
#define OPE_HW_FLUSH 0x7
|
||||||
|
#define OPE_HW_PREPARE 0x8
|
||||||
|
#define OPE_HW_ISR 0x9
|
||||||
|
#define OPE_HW_PROBE 0xA
|
||||||
|
#define OPE_HW_CLK_UPDATE 0xB
|
||||||
|
#define OPE_HW_BW_UPDATE 0xC
|
||||||
|
#define OPE_HW_RESET 0xD
|
||||||
|
#define OPE_HW_SET_IRQ_CB 0xE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_dev_probe
|
||||||
|
*
|
||||||
|
* @hfi_en: HFI enable flag
|
||||||
|
*/
|
||||||
|
struct cam_ope_dev_probe {
|
||||||
|
bool hfi_en;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_dev_init
|
||||||
|
*
|
||||||
|
* @hfi_en: HFI enable flag
|
||||||
|
* @core_info: OPE core info
|
||||||
|
*/
|
||||||
|
struct cam_ope_dev_init {
|
||||||
|
bool hfi_en;
|
||||||
|
struct cam_ope_device_core_info *core_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_dev_clk_update
|
||||||
|
*
|
||||||
|
* @clk_rate: Clock rate
|
||||||
|
*/
|
||||||
|
struct cam_ope_dev_clk_update {
|
||||||
|
uint32_t clk_rate;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_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_ope_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_ope_dev_caps
|
||||||
|
*
|
||||||
|
* @hw_idx: Hardware index
|
||||||
|
* @hw_ver: Hardware version info
|
||||||
|
*/
|
||||||
|
struct cam_ope_dev_caps {
|
||||||
|
uint32_t hw_idx;
|
||||||
|
struct ope_hw_ver hw_ver;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_dev_acquire
|
||||||
|
*
|
||||||
|
* @ctx_id: Context id
|
||||||
|
* @ope_acquire: OPE acquire info
|
||||||
|
* @bus_wr_ctx: Bus Write context
|
||||||
|
* @bus_rd_ctx: Bus Read context
|
||||||
|
*/
|
||||||
|
struct cam_ope_dev_acquire {
|
||||||
|
uint32_t ctx_id;
|
||||||
|
struct ope_acquire_dev_info *ope_acquire;
|
||||||
|
struct ope_bus_wr_ctx *bus_wr_ctx;
|
||||||
|
struct ope_bus_rd_ctx *bus_rd_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_dev_release
|
||||||
|
*
|
||||||
|
* @ctx_id: Context id
|
||||||
|
* @bus_wr_ctx: Bus Write context
|
||||||
|
* @bus_rd_ctx: Bus Read context
|
||||||
|
*/
|
||||||
|
struct cam_ope_dev_release {
|
||||||
|
uint32_t ctx_id;
|
||||||
|
struct ope_bus_wr_ctx *bus_wr_ctx;
|
||||||
|
struct ope_bus_rd_ctx *bus_rd_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_set_irq_cb
|
||||||
|
*
|
||||||
|
* @ope_hw_mgr_cb: Callback to hardware manager
|
||||||
|
* @data: Private data
|
||||||
|
*/
|
||||||
|
struct cam_ope_set_irq_cb {
|
||||||
|
int32_t (*ope_hw_mgr_cb)(uint32_t irq_status, void *data);
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_irq_data
|
||||||
|
*
|
||||||
|
* @error: IRQ error
|
||||||
|
*/
|
||||||
|
struct cam_ope_irq_data {
|
||||||
|
uint32_t error;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_ope_dev_prepare_req
|
||||||
|
*
|
||||||
|
* @hw_mgr: OPE hardware manager
|
||||||
|
* @packet: Packet
|
||||||
|
* @prepare_args: Prepare request args
|
||||||
|
* @ctx_data: Context data
|
||||||
|
* @wr_cdm_batch: WM request
|
||||||
|
* @rd_cdm_batch: RD master request
|
||||||
|
* @frame_process: Frame process command
|
||||||
|
* @req_idx: Request Index
|
||||||
|
* @kmd_buf_offset: KMD buffer offset
|
||||||
|
*/
|
||||||
|
struct cam_ope_dev_prepare_req {
|
||||||
|
struct cam_ope_hw_mgr *hw_mgr;
|
||||||
|
struct cam_packet *packet;
|
||||||
|
struct cam_hw_prepare_update_args *prepare_args;
|
||||||
|
struct cam_ope_ctx *ctx_data;
|
||||||
|
struct ope_bus_wr_io_port_cdm_batch *wr_cdm_batch;
|
||||||
|
struct ope_bus_rd_io_port_cdm_batch *rd_cdm_batch;
|
||||||
|
struct ope_frame_process *frame_process;
|
||||||
|
uint32_t req_idx;
|
||||||
|
uint32_t kmd_buf_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cam_ope_top_process(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, uint32_t cmd_id, void *data);
|
||||||
|
|
||||||
|
int cam_ope_bus_rd_process(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, uint32_t cmd_id, void *data);
|
||||||
|
|
||||||
|
int cam_ope_bus_wr_process(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, uint32_t cmd_id, void *data);
|
||||||
|
|
||||||
|
int cam_ope_init_module(void);
|
||||||
|
void cam_ope_exit_module(void);
|
||||||
|
|
||||||
|
int cam_ope_subdev_init_module(void);
|
||||||
|
void cam_ope_subdev_exit_module(void);
|
||||||
|
|
||||||
|
#endif /* CAM_OPE_DEV_INTF_H */
|
||||||
|
|
399
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h
Normal file
399
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAM_OPE_HW_H
|
||||||
|
#define CAM_OPE_HW_H
|
||||||
|
|
||||||
|
#define OPE_HW_VER_1_0_0 0x10000000
|
||||||
|
|
||||||
|
#define OPE_DEV_OPE 0
|
||||||
|
#define OPE_DEV_MAX 1
|
||||||
|
|
||||||
|
#define MAX_RD_CLIENTS 2
|
||||||
|
#define MAX_WR_CLIENTS 8
|
||||||
|
|
||||||
|
#define OPE_CDM_BASE 0x0
|
||||||
|
#define OPE_TOP_BASE 0x1
|
||||||
|
#define OPE_QOS_BASE 0x2
|
||||||
|
#define OPE_PP_BASE 0x3
|
||||||
|
#define OPE_BUS_RD 0x4
|
||||||
|
#define OPE_BUS_WR 0x5
|
||||||
|
#define OPE_BASE_MAX 0x6
|
||||||
|
|
||||||
|
|
||||||
|
#define BUS_RD_COMBO_BAYER_MASK 0x1
|
||||||
|
#define BUS_RD_COMBO_YUV_MASK 0x2
|
||||||
|
#define BUS_RD_COMBO_MAX 0x2
|
||||||
|
|
||||||
|
#define BUS_RD_BAYER 0x0
|
||||||
|
#define BUS_RD_YUV 0x1
|
||||||
|
|
||||||
|
#define BUS_WR_COMBO_YUV_MASK 0x1
|
||||||
|
#define BUS_WR_COMBO_MAX 0x1
|
||||||
|
|
||||||
|
#define BUS_WR_YUV 0x0
|
||||||
|
|
||||||
|
#define BUS_WR_VIDEO_Y 0x0
|
||||||
|
#define BUS_WR_VIDEO_C 0x1
|
||||||
|
#define BUS_WR_DISP_Y 0x2
|
||||||
|
#define BUS_WR_DISP_C 0x3
|
||||||
|
#define BUS_WR_ARGB 0x4
|
||||||
|
#define BUS_WR_STATS_RS 0x5
|
||||||
|
#define BUS_WR_STATS_IHIST 0x6
|
||||||
|
#define BUS_WR_STATS_LTM 0x7
|
||||||
|
|
||||||
|
#define OPE_WAIT_COMP_RUP 0x1
|
||||||
|
#define OPE_WAIT_COMP_WR_DONE 0x2
|
||||||
|
#define OPE_WAIT_COMP_IDLE 0x4
|
||||||
|
#define OPE_WAIT_COMP_GEN_IRQ 0x8
|
||||||
|
|
||||||
|
struct cam_ope_common {
|
||||||
|
uint32_t mode[CAM_FORMAT_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_top_reg {
|
||||||
|
void *base;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t hw_version;
|
||||||
|
uint32_t reset_cmd;
|
||||||
|
uint32_t core_clk_cfg_ctrl_0;
|
||||||
|
uint32_t ahb_clk_cgc_ctrl;
|
||||||
|
uint32_t core_cfg;
|
||||||
|
uint32_t irq_status;
|
||||||
|
uint32_t irq_mask;
|
||||||
|
uint32_t irq_clear;
|
||||||
|
uint32_t irq_set;
|
||||||
|
uint32_t irq_cmd;
|
||||||
|
uint32_t violation_status;
|
||||||
|
uint32_t throttle_cnt_cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_top_reg_val {
|
||||||
|
uint32_t hw_version;
|
||||||
|
uint32_t major_mask;
|
||||||
|
uint32_t major_shift;
|
||||||
|
uint32_t minor_mask;
|
||||||
|
uint32_t minor_shift;
|
||||||
|
uint32_t incr_mask;
|
||||||
|
uint32_t incr_shift;
|
||||||
|
uint32_t irq_mask;
|
||||||
|
uint32_t irq_set_clear;
|
||||||
|
uint32_t sw_reset_cmd;
|
||||||
|
uint32_t hw_reset_cmd;
|
||||||
|
uint32_t core_clk_cfg_ctrl_0;
|
||||||
|
uint32_t ahb_clk_cgc_ctrl;
|
||||||
|
uint32_t input_format;
|
||||||
|
uint32_t input_format_mask;
|
||||||
|
uint32_t color_correct_src_sel;
|
||||||
|
uint32_t color_correct_src_sel_mask;
|
||||||
|
uint32_t stats_ihist_src_sel;
|
||||||
|
uint32_t stats_ihist_src_sel_mask;
|
||||||
|
uint32_t chroma_up_src_sel;
|
||||||
|
uint32_t chroma_up_src_sel_mask;
|
||||||
|
uint32_t argb_alpha;
|
||||||
|
uint32_t argb_alpha_mask;
|
||||||
|
uint32_t rs_throttle_cnt;
|
||||||
|
uint32_t rs_throttle_cnt_mask;
|
||||||
|
uint32_t ihist_throttle_cnt;
|
||||||
|
uint32_t ihist_throttle_cnt_mask;
|
||||||
|
uint32_t rst_done;
|
||||||
|
uint32_t we_done;
|
||||||
|
uint32_t fe_done;
|
||||||
|
uint32_t ope_violation;
|
||||||
|
uint32_t idle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_qos_reg {
|
||||||
|
void *base;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t hw_version;
|
||||||
|
uint32_t hw_status;
|
||||||
|
uint32_t module_cfg;
|
||||||
|
uint32_t curve_cfg_0;
|
||||||
|
uint32_t curve_cfg_1;
|
||||||
|
uint32_t window_cfg;
|
||||||
|
uint32_t eos_status_0;
|
||||||
|
uint32_t eos_status_1;
|
||||||
|
uint32_t eos_status_2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_qos_reg_val {
|
||||||
|
uint32_t hw_version;
|
||||||
|
uint32_t proc_interval;
|
||||||
|
uint32_t proc_interval_mask;
|
||||||
|
uint32_t static_health;
|
||||||
|
uint32_t static_health_mask;
|
||||||
|
uint32_t module_cfg_en;
|
||||||
|
uint32_t module_cfg_en_mask;
|
||||||
|
uint32_t yexp_ymin_dec;
|
||||||
|
uint32_t yexp_ymin_dec_mask;
|
||||||
|
uint32_t ymin_inc;
|
||||||
|
uint32_t ymin_inc_mask;
|
||||||
|
uint32_t initial_delta;
|
||||||
|
uint32_t initial_delta_mask;
|
||||||
|
uint32_t window_cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_bus_rd_client_reg {
|
||||||
|
uint32_t core_cfg;
|
||||||
|
uint32_t ccif_meta_data;
|
||||||
|
uint32_t img_addr;
|
||||||
|
uint32_t img_cfg;
|
||||||
|
uint32_t stride;
|
||||||
|
uint32_t unpack_cfg;
|
||||||
|
uint32_t latency_buf_allocation;
|
||||||
|
uint32_t misr_cfg_0;
|
||||||
|
uint32_t misr_cfg_1;
|
||||||
|
uint32_t misr_rd_val;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_bus_rd_reg {
|
||||||
|
void *base;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t hw_version;
|
||||||
|
uint32_t sw_reset;
|
||||||
|
uint32_t cgc_override;
|
||||||
|
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 num_clients;
|
||||||
|
struct cam_ope_bus_rd_client_reg rd_clients[MAX_RD_CLIENTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_bus_rd_client_reg_val {
|
||||||
|
uint32_t core_cfg;
|
||||||
|
uint32_t stripe_location;
|
||||||
|
uint32_t stripe_location_mask;
|
||||||
|
uint32_t stripe_location_shift;
|
||||||
|
uint32_t pix_pattern;
|
||||||
|
uint32_t pix_pattern_mask;
|
||||||
|
uint32_t pix_pattern_shift;
|
||||||
|
uint32_t img_addr;
|
||||||
|
uint32_t img_width;
|
||||||
|
uint32_t img_width_mask;
|
||||||
|
uint32_t img_width_shift;
|
||||||
|
uint32_t img_height;
|
||||||
|
uint32_t img_height_mask;
|
||||||
|
uint32_t img_height_shift;
|
||||||
|
uint32_t stride;
|
||||||
|
uint32_t mode;
|
||||||
|
uint32_t mode_mask;
|
||||||
|
uint32_t mode_shift;
|
||||||
|
uint32_t alignment;
|
||||||
|
uint32_t alignment_mask;
|
||||||
|
uint32_t alignment_shift;
|
||||||
|
uint32_t latency_buf_allocation;
|
||||||
|
uint32_t misr_cfg_samp_mode;
|
||||||
|
uint32_t misr_cfg_samp_mode_mask;
|
||||||
|
uint32_t misr_cfg_en;
|
||||||
|
uint32_t misr_cfg_en_mask;
|
||||||
|
uint32_t misr_cfg_1;
|
||||||
|
uint32_t misr_rd_val;
|
||||||
|
uint32_t input_port_id;
|
||||||
|
uint32_t rm_port_id;
|
||||||
|
uint32_t format_type;
|
||||||
|
uint32_t num_combos_supported;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_bus_rd_reg_val {
|
||||||
|
uint32_t hw_version;
|
||||||
|
uint32_t sw_reset;
|
||||||
|
uint32_t cgc_override;
|
||||||
|
uint32_t irq_mask;
|
||||||
|
uint32_t go_cmd;
|
||||||
|
uint32_t go_cmd_mask;
|
||||||
|
uint32_t ica_en;
|
||||||
|
uint32_t ica_en_mask;
|
||||||
|
uint32_t static_prg;
|
||||||
|
uint32_t static_prg_mask;
|
||||||
|
uint32_t go_cmd_sel;
|
||||||
|
uint32_t go_cmd_sel_mask;
|
||||||
|
uint32_t fs_sync_en;
|
||||||
|
uint32_t fs_sync_en_mask;
|
||||||
|
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 irq_set_clear;
|
||||||
|
uint32_t rst_done;
|
||||||
|
uint32_t rup_done;
|
||||||
|
uint32_t rd_buf_done;
|
||||||
|
uint32_t violation;
|
||||||
|
uint32_t latency_buf_size;
|
||||||
|
|
||||||
|
uint32_t num_clients;
|
||||||
|
struct cam_ope_bus_rd_client_reg_val rd_clients[MAX_RD_CLIENTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_bus_wr_client_reg {
|
||||||
|
uint32_t core_cfg;
|
||||||
|
uint32_t img_addr;
|
||||||
|
uint32_t img_cfg;
|
||||||
|
uint32_t x_init;
|
||||||
|
uint32_t stride;
|
||||||
|
uint32_t pack_cfg;
|
||||||
|
uint32_t bw_limit;
|
||||||
|
uint32_t frame_header_addr;
|
||||||
|
uint32_t subsample_period;
|
||||||
|
uint32_t subsample_pattern;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_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 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_ope_bus_wr_client_reg wr_clients[MAX_WR_CLIENTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_bus_wr_client_reg_val {
|
||||||
|
uint32_t core_cfg_en;
|
||||||
|
uint32_t core_cfg_en_mask;
|
||||||
|
uint32_t core_cfg_en_shift;
|
||||||
|
uint32_t virtual_frame_en;
|
||||||
|
uint32_t virtual_frame_en_mask;
|
||||||
|
uint32_t virtual_frame_en_shift;
|
||||||
|
uint32_t frame_header_en;
|
||||||
|
uint32_t frame_header_en_mask;
|
||||||
|
uint32_t frame_header_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 stride;
|
||||||
|
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 subsample_period;
|
||||||
|
uint32_t subsample_pattern;
|
||||||
|
uint32_t output_port_id;
|
||||||
|
uint32_t wm_port_id;
|
||||||
|
uint32_t format_type;
|
||||||
|
uint32_t num_combos_supported;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cam_ope_bus_wr_reg_val {
|
||||||
|
uint32_t hw_version;
|
||||||
|
uint32_t cgc_override;
|
||||||
|
uint32_t irq_mask_0;
|
||||||
|
uint32_t irq_mask_1;
|
||||||
|
uint32_t irq_set_clear;
|
||||||
|
uint32_t comp_rup_done;
|
||||||
|
uint32_t comp_buf_done;
|
||||||
|
uint32_t cons_violation;
|
||||||
|
uint32_t violation;
|
||||||
|
uint32_t img_size_violation;
|
||||||
|
uint32_t frame_header_cfg_0;
|
||||||
|
uint32_t local_frame_header_cfg_0;
|
||||||
|
uint32_t iso_cfg;
|
||||||
|
uint32_t misr_0_en;
|
||||||
|
uint32_t misr_0_en_mask;
|
||||||
|
uint32_t misr_1_en;
|
||||||
|
uint32_t misr_1_en_mask;
|
||||||
|
uint32_t misr_2_en;
|
||||||
|
uint32_t misr_2_en_mask;
|
||||||
|
uint32_t misr_3_en;
|
||||||
|
uint32_t misr_3_en_mask;
|
||||||
|
uint32_t misr_0_samp_mode;
|
||||||
|
uint32_t misr_0_samp_mode_mask;
|
||||||
|
uint32_t misr_1_samp_mode;
|
||||||
|
uint32_t misr_1_samp_mode_mask;
|
||||||
|
uint32_t misr_2_samp_mode;
|
||||||
|
uint32_t misr_2_samp_mode_mask;
|
||||||
|
uint32_t misr_3_samp_mode;
|
||||||
|
uint32_t misr_3_samp_mode_mask;
|
||||||
|
uint32_t misr_0_id;
|
||||||
|
uint32_t misr_0_id_mask;
|
||||||
|
uint32_t misr_1_id;
|
||||||
|
uint32_t misr_1_id_mask;
|
||||||
|
uint32_t misr_2_id;
|
||||||
|
uint32_t misr_2_id_mask;
|
||||||
|
uint32_t misr_3_id;
|
||||||
|
uint32_t misr_3_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_ope_bus_wr_client_reg_val wr_clients[MAX_WR_CLIENTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ope_hw {
|
||||||
|
struct cam_ope_top_reg *top_reg;
|
||||||
|
struct cam_ope_top_reg_val *top_reg_val;
|
||||||
|
|
||||||
|
struct cam_ope_bus_rd_reg *bus_rd_reg;
|
||||||
|
struct cam_ope_bus_rd_reg_val *bus_rd_reg_val;
|
||||||
|
|
||||||
|
struct cam_ope_bus_wr_reg *bus_wr_reg;
|
||||||
|
struct cam_ope_bus_wr_reg_val *bus_wr_reg_val;
|
||||||
|
|
||||||
|
struct cam_ope_qos_reg *qos_reg;
|
||||||
|
struct cam_ope_qos_reg_val *qos_reg_val;
|
||||||
|
|
||||||
|
struct cam_ope_common *common;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hw_version_reg {
|
||||||
|
uint32_t hw_ver;
|
||||||
|
uint32_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CAM_OPE_HW_H */
|
532
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h
Normal file
532
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h
Normal file
@@ -0,0 +1,532 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAM_OPE_HW_100_H
|
||||||
|
#define CAM_OPE_HW_100_H
|
||||||
|
|
||||||
|
#define OPE_BUS_RD_TYPE_BAYER 0x0
|
||||||
|
#define OPE_BUS_RD_TYPE_YUV_Y 0x0
|
||||||
|
#define OPE_BUS_RD_TYPE_YUC_C 0x1
|
||||||
|
|
||||||
|
#define OPE_BUS_WR_TYPE_VID_Y 0x0
|
||||||
|
#define OPE_BUS_WR_TYPE_VID_C 0x1
|
||||||
|
#define OPE_BUS_WR_TYPE_DISP_Y 0x2
|
||||||
|
#define OPE_BUS_WR_TYPE_DISP_C 0x3
|
||||||
|
#define OPE_BUS_WR_TYPE_ARGB 0x4
|
||||||
|
#define OPE_BUS_WR_TYPE_RS 0x5
|
||||||
|
#define OPE_BUS_WR_TYPE_IHIST 0x6
|
||||||
|
#define OPE_BUS_WR_TYPE_LTM 0x7
|
||||||
|
|
||||||
|
enum cam_ope_bus_rd_unpacker_format {
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_128_BYPASS = 0x0,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_8 = 0x1,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_16_10BPP = 0x2,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_16_12BPP = 0x3,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_16_14BPP = 0x4,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_32_20BPP = 0x5,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_ARGB16_10 = 0x6,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_ARGB16_12 = 0x7,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_ARGB16_14 = 0x8,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_32 = 0x9,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_64 = 0xA,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_TP_10 = 0xB,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_MIPI_8 = 0xC,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_MIPI_10 = 0xD,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_MIPI_12 = 0xE,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_MIPI_14 = 0xF,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_16_16BPP = 0x10,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_BYPASS_SWAP = 0x11,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_PLAIN_8_SWAP = 0x12,
|
||||||
|
BUS_RD_VER1_PACKER_FMT_MAX = 0x13,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cam_ope_top_reg ope_top_reg = {
|
||||||
|
.offset = 0x400,
|
||||||
|
.hw_version = 0x0,
|
||||||
|
.reset_cmd = 0x4,
|
||||||
|
.core_clk_cfg_ctrl_0 = 0x8,
|
||||||
|
.ahb_clk_cgc_ctrl = 0xC,
|
||||||
|
.core_cfg = 0x10,
|
||||||
|
.irq_status = 0x14,
|
||||||
|
.irq_mask = 0x18,
|
||||||
|
.irq_clear = 0x1C,
|
||||||
|
.irq_set = 0x20,
|
||||||
|
.irq_cmd = 0x24,
|
||||||
|
.violation_status = 0x28,
|
||||||
|
.throttle_cnt_cfg = 0x2C,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cam_ope_top_reg_val ope_top_reg_val = {
|
||||||
|
.hw_version = 0x10000000,
|
||||||
|
.major_mask = 0xFFFF,
|
||||||
|
.major_shift = 0x0,
|
||||||
|
.minor_mask = 0x0FFF0000,
|
||||||
|
.minor_shift = 0xF,
|
||||||
|
.incr_mask = 0xF0000000,
|
||||||
|
.incr_shift = 0x1B,
|
||||||
|
.irq_mask = 0x0000000F,
|
||||||
|
.sw_reset_cmd = 0x2,
|
||||||
|
.hw_reset_cmd = 0x1,
|
||||||
|
.irq_set_clear = 0x1,
|
||||||
|
.rst_done = 0x1,
|
||||||
|
.we_done = 0x2,
|
||||||
|
.fe_done = 0x4,
|
||||||
|
.ope_violation = 0x8,
|
||||||
|
.idle = 0x10,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct cam_ope_bus_rd_reg_val ope_bus_rd_reg_val = {
|
||||||
|
.hw_version = 0x00050000,
|
||||||
|
.sw_reset = 0x1,
|
||||||
|
.cgc_override = 0x0,
|
||||||
|
.irq_mask = 0x30001,
|
||||||
|
.irq_set_clear = 0x1,
|
||||||
|
.rst_done = 0x1,
|
||||||
|
.rup_done = 0x2,
|
||||||
|
.rd_buf_done = 0xC,
|
||||||
|
.violation = 0x3000,
|
||||||
|
.go_cmd = 0x1,
|
||||||
|
.security_cfg = 0x0,
|
||||||
|
.latency_buf_size = 4096,
|
||||||
|
.num_clients = 0x2,
|
||||||
|
.rd_clients = {
|
||||||
|
{
|
||||||
|
.core_cfg = 0x1,
|
||||||
|
.stripe_location_mask = 0x3,
|
||||||
|
.stripe_location_shift = 0x0,
|
||||||
|
.pix_pattern_mask = 0x3F,
|
||||||
|
.pix_pattern_shift = 0x2,
|
||||||
|
.img_width_mask = 0xFFFF,
|
||||||
|
.img_width_shift = 0x10,
|
||||||
|
.img_height_mask = 0xFFFF,
|
||||||
|
.img_height_shift = 0x0,
|
||||||
|
.mode_mask = 0x1F,
|
||||||
|
.mode_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x5,
|
||||||
|
.latency_buf_allocation = 4096,
|
||||||
|
.input_port_id = OPE_IN_RES_FULL,
|
||||||
|
.rm_port_id = 0,
|
||||||
|
.format_type = BUS_RD_COMBO_BAYER_MASK |
|
||||||
|
BUS_RD_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg = 0x1,
|
||||||
|
.stripe_location_mask = 0x3,
|
||||||
|
.stripe_location_shift = 0x0,
|
||||||
|
.pix_pattern_mask = 0x3F,
|
||||||
|
.pix_pattern_shift = 0x2,
|
||||||
|
.img_width_mask = 0xFFFF,
|
||||||
|
.img_width_shift = 0x10,
|
||||||
|
.img_height_mask = 0xFFFF,
|
||||||
|
.img_height_shift = 0x0,
|
||||||
|
.mode_mask = 0x1F,
|
||||||
|
.mode_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x5,
|
||||||
|
.latency_buf_allocation = 4096,
|
||||||
|
.input_port_id = OPE_IN_RES_FULL,
|
||||||
|
.rm_port_id = 1,
|
||||||
|
.format_type = BUS_RD_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 1,
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cam_ope_bus_rd_reg ope_bus_rd_reg = {
|
||||||
|
.offset = 0x4C00,
|
||||||
|
.hw_version = 0x0,
|
||||||
|
.sw_reset = 0x4,
|
||||||
|
.cgc_override = 0x8,
|
||||||
|
.irq_mask = 0xC,
|
||||||
|
.irq_clear = 0x10,
|
||||||
|
.irq_cmd = 0x14,
|
||||||
|
.irq_status = 0x18,
|
||||||
|
.input_if_cmd = 0x1C,
|
||||||
|
.irq_set = 0x20,
|
||||||
|
.misr_reset = 0x24,
|
||||||
|
.security_cfg = 0x28,
|
||||||
|
.iso_cfg = 0x2C,
|
||||||
|
.iso_seed = 0x30,
|
||||||
|
.num_clients = 0x2,
|
||||||
|
.rd_clients = {
|
||||||
|
{
|
||||||
|
.core_cfg = 0x50,
|
||||||
|
.ccif_meta_data = 0x54,
|
||||||
|
.img_addr = 0x58,
|
||||||
|
.img_cfg = 0x5C,
|
||||||
|
.stride = 0x60,
|
||||||
|
.unpack_cfg = 0x64,
|
||||||
|
.latency_buf_allocation = 0x78,
|
||||||
|
.misr_cfg_0 = 0x80,
|
||||||
|
.misr_cfg_1 = 0x84,
|
||||||
|
.misr_rd_val = 0x88,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg = 0xF0,
|
||||||
|
.ccif_meta_data = 0xF4,
|
||||||
|
.img_addr = 0xF8,
|
||||||
|
.img_cfg = 0xFC,
|
||||||
|
.stride = 0x100,
|
||||||
|
.unpack_cfg = 0x104,
|
||||||
|
.latency_buf_allocation = 0x118,
|
||||||
|
.misr_cfg_0 = 0x120,
|
||||||
|
.misr_cfg_1 = 0x124,
|
||||||
|
.misr_rd_val = 0x128,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cam_ope_bus_wr_reg ope_bus_wr_reg = {
|
||||||
|
.offset = 0x4D90,
|
||||||
|
.hw_version = 0x0,
|
||||||
|
.cgc_override = 0x8,
|
||||||
|
.irq_mask_0 = 0x18,
|
||||||
|
.irq_mask_1 = 0x1C,
|
||||||
|
.irq_clear_0 = 0x20,
|
||||||
|
.irq_clear_1 = 0x24,
|
||||||
|
.irq_status_0 = 0x28,
|
||||||
|
.irq_status_1 = 0x2C,
|
||||||
|
.irq_cmd = 0x30,
|
||||||
|
.frame_header_cfg_0 = 0x34,
|
||||||
|
.local_frame_header_cfg_0 = 0x4C,
|
||||||
|
.irq_set_0 = 0x50,
|
||||||
|
.irq_set_1 = 0x54,
|
||||||
|
.iso_cfg = 0x5C,
|
||||||
|
.violation_status = 0x64,
|
||||||
|
.image_size_violation_status = 0x70,
|
||||||
|
.misr_cfg_0 = 0xB8,
|
||||||
|
.misr_cfg_1 = 0xBC,
|
||||||
|
.misr_rd_sel = 0xC8,
|
||||||
|
.misr_reset = 0xCC,
|
||||||
|
.misr_val = 0xD0,
|
||||||
|
.num_clients = 0x8,
|
||||||
|
.wr_clients = {
|
||||||
|
{
|
||||||
|
.core_cfg = 0x200,
|
||||||
|
.img_addr = 0x204,
|
||||||
|
.img_cfg = 0x20C,
|
||||||
|
.x_init = 0x210,
|
||||||
|
.stride = 0x214,
|
||||||
|
.pack_cfg = 0x218,
|
||||||
|
.bw_limit = 0x21C,
|
||||||
|
.frame_header_addr = 0x220,
|
||||||
|
.subsample_period = 0x230,
|
||||||
|
.subsample_pattern = 0x234,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg = 0x300,
|
||||||
|
.img_addr = 0x304,
|
||||||
|
.img_cfg = 0x30C,
|
||||||
|
.x_init = 0x310,
|
||||||
|
.stride = 0x314,
|
||||||
|
.pack_cfg = 0x318,
|
||||||
|
.bw_limit = 0x31C,
|
||||||
|
.frame_header_addr = 0x320,
|
||||||
|
.subsample_period = 0x330,
|
||||||
|
.subsample_pattern = 0x334,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg = 0x400,
|
||||||
|
.img_addr = 0x404,
|
||||||
|
.img_cfg = 0x40C,
|
||||||
|
.x_init = 0x410,
|
||||||
|
.stride = 0x414,
|
||||||
|
.pack_cfg = 0x418,
|
||||||
|
.bw_limit = 0x41C,
|
||||||
|
.frame_header_addr = 0x420,
|
||||||
|
.subsample_period = 0x430,
|
||||||
|
.subsample_pattern = 0x434,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg = 0x500,
|
||||||
|
.img_addr = 0x504,
|
||||||
|
.img_cfg = 0x50C,
|
||||||
|
.x_init = 0x510,
|
||||||
|
.stride = 0x514,
|
||||||
|
.pack_cfg = 0x518,
|
||||||
|
.bw_limit = 0x51C,
|
||||||
|
.frame_header_addr = 0x520,
|
||||||
|
.subsample_period = 0x530,
|
||||||
|
.subsample_pattern = 0x534,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg = 0x600,
|
||||||
|
.img_addr = 0x604,
|
||||||
|
.img_cfg = 0x60C,
|
||||||
|
.x_init = 0x610,
|
||||||
|
.stride = 0x614,
|
||||||
|
.pack_cfg = 0x618,
|
||||||
|
.bw_limit = 0x61C,
|
||||||
|
.frame_header_addr = 0x620,
|
||||||
|
.subsample_period = 0x630,
|
||||||
|
.subsample_pattern = 0x634,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg = 0x700,
|
||||||
|
.img_addr = 0x704,
|
||||||
|
.img_cfg = 0x70C,
|
||||||
|
.x_init = 0x710,
|
||||||
|
.stride = 0x714,
|
||||||
|
.pack_cfg = 0x718,
|
||||||
|
.bw_limit = 0x71C,
|
||||||
|
.frame_header_addr = 0x720,
|
||||||
|
.subsample_period = 0x730,
|
||||||
|
.subsample_pattern = 0x734,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg = 0x800,
|
||||||
|
.img_addr = 0x804,
|
||||||
|
.img_cfg = 0x80C,
|
||||||
|
.x_init = 0x810,
|
||||||
|
.stride = 0x814,
|
||||||
|
.pack_cfg = 0x818,
|
||||||
|
.bw_limit = 0x81C,
|
||||||
|
.frame_header_addr = 0x820,
|
||||||
|
.subsample_period = 0x830,
|
||||||
|
.subsample_pattern = 0x834,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg = 0x900,
|
||||||
|
.img_addr = 0x904,
|
||||||
|
.img_cfg = 0x90C,
|
||||||
|
.x_init = 0x910,
|
||||||
|
.stride = 0x914,
|
||||||
|
.pack_cfg = 0x918,
|
||||||
|
.bw_limit = 0x91C,
|
||||||
|
.frame_header_addr = 0x920,
|
||||||
|
.subsample_period = 0x930,
|
||||||
|
.subsample_pattern = 0x934,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cam_ope_bus_wr_reg_val ope_bus_wr_reg_val = {
|
||||||
|
.hw_version = 0x20010000,
|
||||||
|
.irq_mask_0 = 0xD0000000,
|
||||||
|
.irq_mask_1 = 0x0,
|
||||||
|
.irq_set_clear = 0x1,
|
||||||
|
.comp_rup_done = 0x1,
|
||||||
|
.comp_buf_done = 0x100,
|
||||||
|
.cons_violation = 0x10000000,
|
||||||
|
.violation = 0x40000000,
|
||||||
|
.img_size_violation = 0x80000000,
|
||||||
|
.num_clients = 0x8,
|
||||||
|
.wr_clients = {
|
||||||
|
{
|
||||||
|
.core_cfg_en = 0x1,
|
||||||
|
.core_cfg_en_mask = 0x1,
|
||||||
|
.core_cfg_en_shift = 0x0,
|
||||||
|
.virtual_frame_en_mask = 0x1,
|
||||||
|
.virtual_frame_en_shift = 0x1,
|
||||||
|
.frame_header_en_mask = 0x1,
|
||||||
|
.frame_header_en_shift = 0x2,
|
||||||
|
.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,
|
||||||
|
.format_mask = 0xF,
|
||||||
|
.format_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x4,
|
||||||
|
.output_port_id = OPE_OUT_RES_VIDEO,
|
||||||
|
.wm_port_id = BUS_WR_VIDEO_Y,
|
||||||
|
.format_type = BUS_WR_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg_en = 0x1,
|
||||||
|
.core_cfg_en_mask = 0x1,
|
||||||
|
.core_cfg_en_shift = 0x0,
|
||||||
|
.virtual_frame_en_mask = 0x1,
|
||||||
|
.virtual_frame_en_shift = 0x1,
|
||||||
|
.frame_header_en_mask = 0x1,
|
||||||
|
.frame_header_en_shift = 0x2,
|
||||||
|
.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,
|
||||||
|
.format_mask = 0xF,
|
||||||
|
.format_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x4,
|
||||||
|
.output_port_id = OPE_OUT_RES_VIDEO,
|
||||||
|
.wm_port_id = BUS_WR_VIDEO_C,
|
||||||
|
.format_type = BUS_WR_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg_en = 0x1,
|
||||||
|
.core_cfg_en_mask = 0x1,
|
||||||
|
.core_cfg_en_shift = 0x0,
|
||||||
|
.virtual_frame_en_mask = 0x1,
|
||||||
|
.virtual_frame_en_shift = 0x1,
|
||||||
|
.frame_header_en_mask = 0x1,
|
||||||
|
.frame_header_en_shift = 0x2,
|
||||||
|
.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,
|
||||||
|
.format_mask = 0xF,
|
||||||
|
.format_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x4,
|
||||||
|
.output_port_id = OPE_OUT_RES_DISP,
|
||||||
|
.wm_port_id = BUS_WR_DISP_Y,
|
||||||
|
.format_type = BUS_WR_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg_en = 0x1,
|
||||||
|
.core_cfg_en_mask = 0x1,
|
||||||
|
.core_cfg_en_shift = 0x0,
|
||||||
|
.virtual_frame_en_mask = 0x1,
|
||||||
|
.virtual_frame_en_shift = 0x1,
|
||||||
|
.frame_header_en_mask = 0x1,
|
||||||
|
.frame_header_en_shift = 0x2,
|
||||||
|
.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,
|
||||||
|
.format_mask = 0xF,
|
||||||
|
.format_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x4,
|
||||||
|
.output_port_id = OPE_OUT_RES_DISP,
|
||||||
|
.wm_port_id = BUS_WR_DISP_C,
|
||||||
|
.format_type = BUS_WR_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg_en = 0x1,
|
||||||
|
.core_cfg_en_mask = 0x1,
|
||||||
|
.core_cfg_en_shift = 0x0,
|
||||||
|
.virtual_frame_en_mask = 0x1,
|
||||||
|
.virtual_frame_en_shift = 0x1,
|
||||||
|
.frame_header_en_mask = 0x1,
|
||||||
|
.frame_header_en_shift = 0x2,
|
||||||
|
.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,
|
||||||
|
.format_mask = 0xF,
|
||||||
|
.format_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x4,
|
||||||
|
.output_port_id = OPE_OUT_RES_ARGB,
|
||||||
|
.wm_port_id = BUS_WR_ARGB,
|
||||||
|
.format_type = BUS_WR_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg_en = 0x1,
|
||||||
|
.core_cfg_en_mask = 0x1,
|
||||||
|
.core_cfg_en_shift = 0x0,
|
||||||
|
.virtual_frame_en_mask = 0x1,
|
||||||
|
.virtual_frame_en_shift = 0x1,
|
||||||
|
.frame_header_en_mask = 0x1,
|
||||||
|
.frame_header_en_shift = 0x2,
|
||||||
|
.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,
|
||||||
|
.format_mask = 0xF,
|
||||||
|
.format_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x4,
|
||||||
|
.output_port_id = OPE_OUT_RES_STATS_RS,
|
||||||
|
.wm_port_id = BUS_WR_STATS_RS,
|
||||||
|
.format_type = BUS_WR_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg_en = 0x1,
|
||||||
|
.core_cfg_en_mask = 0x1,
|
||||||
|
.core_cfg_en_shift = 0x0,
|
||||||
|
.virtual_frame_en_mask = 0x1,
|
||||||
|
.virtual_frame_en_shift = 0x1,
|
||||||
|
.frame_header_en_mask = 0x1,
|
||||||
|
.frame_header_en_shift = 0x2,
|
||||||
|
.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,
|
||||||
|
.format_mask = 0xF,
|
||||||
|
.format_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x4,
|
||||||
|
.output_port_id = OPE_OUT_RES_STATS_IHIST,
|
||||||
|
.wm_port_id = BUS_WR_STATS_IHIST,
|
||||||
|
.format_type = BUS_WR_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.core_cfg_en = 0x1,
|
||||||
|
.core_cfg_en_mask = 0x1,
|
||||||
|
.core_cfg_en_shift = 0x0,
|
||||||
|
.virtual_frame_en_mask = 0x1,
|
||||||
|
.virtual_frame_en_shift = 0x1,
|
||||||
|
.frame_header_en_mask = 0x1,
|
||||||
|
.frame_header_en_shift = 0x2,
|
||||||
|
.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,
|
||||||
|
.format_mask = 0xF,
|
||||||
|
.format_shift = 0x0,
|
||||||
|
.alignment_mask = 0x1,
|
||||||
|
.alignment_shift = 0x4,
|
||||||
|
.output_port_id = OPE_OUT_RES_STATS_LTM,
|
||||||
|
.wm_port_id = BUS_WR_STATS_LTM,
|
||||||
|
.format_type = BUS_WR_COMBO_YUV_MASK,
|
||||||
|
.num_combos_supported = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
static struct ope_hw ope_hw_100 = {
|
||||||
|
.top_reg = &ope_top_reg,
|
||||||
|
.top_reg_val = &ope_top_reg_val,
|
||||||
|
.bus_rd_reg = &ope_bus_rd_reg,
|
||||||
|
.bus_rd_reg_val = &ope_bus_rd_reg_val,
|
||||||
|
.bus_wr_reg = &ope_bus_wr_reg,
|
||||||
|
.bus_wr_reg_val = &ope_bus_wr_reg_val,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CAM_OPE_HW_100_H */
|
136
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c
Normal file
136
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.c
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/dma-buf.h>
|
||||||
|
#include <media/cam_defs.h>
|
||||||
|
#include <media/cam_icp.h>
|
||||||
|
#include "ope_soc.h"
|
||||||
|
#include "cam_soc_util.h"
|
||||||
|
#include "cam_debug_util.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int cam_ope_get_dt_properties(struct cam_hw_soc_info *soc_info)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct platform_device *pdev = NULL;
|
||||||
|
struct device_node *of_node = NULL;
|
||||||
|
struct ope_dev_soc *ope_soc_info;
|
||||||
|
|
||||||
|
if (!soc_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "soc_info is NULL");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdev = soc_info->pdev;
|
||||||
|
of_node = pdev->dev.of_node;
|
||||||
|
ope_soc_info = soc_info->soc_private;
|
||||||
|
|
||||||
|
rc = cam_soc_util_get_dt_properties(soc_info);
|
||||||
|
if (rc < 0)
|
||||||
|
CAM_ERR(CAM_OPE, "get ope dt prop is failed: %d", rc);
|
||||||
|
|
||||||
|
ope_soc_info->hfi_en = of_property_read_bool(of_node, "hfi_en");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_request_platform_resource(
|
||||||
|
struct cam_hw_soc_info *soc_info,
|
||||||
|
irq_handler_t ope_irq_handler, void *irq_data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
rc = cam_soc_util_request_platform_resource(soc_info, ope_irq_handler,
|
||||||
|
irq_data);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||||
|
irq_handler_t ope_irq_handler, void *irq_data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
rc = cam_ope_get_dt_properties(soc_info);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = cam_ope_request_platform_resource(soc_info, ope_irq_handler,
|
||||||
|
irq_data);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_enable_soc_resources(struct cam_hw_soc_info *soc_info)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
rc = cam_soc_util_enable_platform_resource(soc_info, true,
|
||||||
|
CAM_SVS_VOTE, true);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_OPE, "enable platform failed");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_disable_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||||
|
bool disable_clk)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
rc = cam_soc_util_disable_platform_resource(soc_info, disable_clk,
|
||||||
|
true);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_OPE, "enable platform failed");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_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_OPE, "Invalid soc info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
src_clk_idx = soc_info->src_clk_idx;
|
||||||
|
|
||||||
|
CAM_DBG(CAM_OPE, "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_OPE, "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_OPE, "clk_rate = %u src_clk_index = %d",
|
||||||
|
clk_rate, src_clk_idx);
|
||||||
|
return cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (clk_enable)
|
||||||
|
rc = cam_soc_util_clk_enable_default(soc_info, CAM_SVS_VOTE);
|
||||||
|
else
|
||||||
|
cam_soc_util_clk_disable_default(soc_info);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
33
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h
Normal file
33
drivers/cam_ope/ope_hw_mgr/ope_hw/ope_soc.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAM_OPE_SOC_H
|
||||||
|
#define CAM_OPE_SOC_H
|
||||||
|
|
||||||
|
#include "cam_soc_util.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_dev_soc
|
||||||
|
*
|
||||||
|
* @hfi_en: HFI enable flag
|
||||||
|
*/
|
||||||
|
struct ope_dev_soc {
|
||||||
|
uint32_t hfi_en;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cam_ope_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||||
|
irq_handler_t ope_irq_handler, void *irq_data);
|
||||||
|
|
||||||
|
|
||||||
|
int cam_ope_enable_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||||
|
|
||||||
|
int cam_ope_disable_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||||
|
bool disable_clk);
|
||||||
|
|
||||||
|
int cam_ope_update_clk_rate(struct cam_hw_soc_info *soc_info,
|
||||||
|
uint32_t clk_rate);
|
||||||
|
|
||||||
|
int cam_ope_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable);
|
||||||
|
#endif /* CAM_OPE_SOC_H */
|
246
drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c
Normal file
246
drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, 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_ope.h>
|
||||||
|
#include "cam_io_util.h"
|
||||||
|
#include "cam_hw.h"
|
||||||
|
#include "cam_hw_intf.h"
|
||||||
|
#include "ope_core.h"
|
||||||
|
#include "ope_soc.h"
|
||||||
|
#include "cam_soc_util.h"
|
||||||
|
#include "cam_io_util.h"
|
||||||
|
#include "cam_cpas_api.h"
|
||||||
|
#include "cam_debug_util.h"
|
||||||
|
#include "ope_hw.h"
|
||||||
|
#include "ope_dev_intf.h"
|
||||||
|
#include "ope_top.h"
|
||||||
|
|
||||||
|
static struct ope_top ope_top_info;
|
||||||
|
|
||||||
|
static int cam_ope_top_reset(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct cam_ope_top_reg *top_reg;
|
||||||
|
struct cam_ope_top_reg_val *top_reg_val;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
top_reg = ope_hw_info->top_reg;
|
||||||
|
top_reg_val = ope_hw_info->top_reg_val;
|
||||||
|
|
||||||
|
init_completion(&ope_top_info.reset_complete);
|
||||||
|
|
||||||
|
/* enable interrupt mask */
|
||||||
|
cam_io_w_mb(top_reg_val->irq_mask,
|
||||||
|
ope_hw_info->top_reg->base + top_reg->irq_mask);
|
||||||
|
|
||||||
|
/* OPE SW RESET */
|
||||||
|
cam_io_w_mb(top_reg_val->sw_reset_cmd,
|
||||||
|
ope_hw_info->top_reg->base + top_reg->reset_cmd);
|
||||||
|
|
||||||
|
rc = wait_for_completion_timeout(
|
||||||
|
&ope_top_info.reset_complete,
|
||||||
|
msecs_to_jiffies(30));
|
||||||
|
|
||||||
|
if (!rc || rc < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "reset error result = %d", rc);
|
||||||
|
if (!rc)
|
||||||
|
rc = -ETIMEDOUT;
|
||||||
|
} else {
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_top_release(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (ctx_id < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d", ctx_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ope_top_info.top_ctx[ctx_id].ope_acquire = NULL;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_top_acquire(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (ctx_id < 0 || !data) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid data: %d %x", ctx_id, data);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ope_top_info.top_ctx[ctx_id].ope_acquire = data;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_top_init(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct cam_ope_top_reg *top_reg;
|
||||||
|
struct cam_ope_top_reg_val *top_reg_val;
|
||||||
|
struct cam_ope_dev_init *dev_init = data;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
top_reg = ope_hw_info->top_reg;
|
||||||
|
top_reg_val = ope_hw_info->top_reg_val;
|
||||||
|
|
||||||
|
top_reg->base = dev_init->core_info->ope_hw_info->ope_top_base;
|
||||||
|
|
||||||
|
/* OPE SW RESET */
|
||||||
|
init_completion(&ope_top_info.reset_complete);
|
||||||
|
|
||||||
|
/* enable interrupt mask */
|
||||||
|
cam_io_w_mb(top_reg_val->irq_mask,
|
||||||
|
ope_hw_info->top_reg->base + top_reg->irq_mask);
|
||||||
|
|
||||||
|
cam_io_w_mb(top_reg_val->sw_reset_cmd,
|
||||||
|
ope_hw_info->top_reg->base + top_reg->reset_cmd);
|
||||||
|
|
||||||
|
rc = wait_for_completion_timeout(
|
||||||
|
&ope_top_info.reset_complete,
|
||||||
|
msecs_to_jiffies(30));
|
||||||
|
|
||||||
|
if (!rc || rc < 0) {
|
||||||
|
CAM_ERR(CAM_OPE, "reset error result = %d", rc);
|
||||||
|
if (!rc)
|
||||||
|
rc = -ETIMEDOUT;
|
||||||
|
} else {
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_top_probe(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ope_top_info.ope_hw_info = ope_hw_info;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ope_top_isr(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
uint32_t irq_status;
|
||||||
|
uint32_t violation_status;
|
||||||
|
struct cam_ope_top_reg *top_reg;
|
||||||
|
struct cam_ope_top_reg_val *top_reg_val;
|
||||||
|
struct cam_ope_irq_data *irq_data = data;
|
||||||
|
|
||||||
|
if (!ope_hw_info) {
|
||||||
|
CAM_ERR(CAM_OPE, "Invalid ope_hw_info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
top_reg = ope_hw_info->top_reg;
|
||||||
|
top_reg_val = ope_hw_info->top_reg_val;
|
||||||
|
|
||||||
|
/* 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_set_clear,
|
||||||
|
top_reg->base + top_reg->irq_cmd);
|
||||||
|
|
||||||
|
if (irq_status & top_reg_val->rst_done) {
|
||||||
|
CAM_DBG(CAM_OPE, "ope reset done");
|
||||||
|
complete(&ope_top_info.reset_complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irq_status & top_reg_val->ope_violation) {
|
||||||
|
violation_status = cam_io_r_mb(top_reg->base +
|
||||||
|
top_reg->violation_status);
|
||||||
|
irq_data->error = 1;
|
||||||
|
CAM_ERR(CAM_OPE, "ope violation: %x", violation_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cam_ope_top_process(struct ope_hw *ope_hw_info,
|
||||||
|
int32_t ctx_id, uint32_t cmd_id, void *data)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
switch (cmd_id) {
|
||||||
|
case OPE_HW_PROBE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PROBE: E");
|
||||||
|
rc = cam_ope_top_probe(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_PROBE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_INIT:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_INIT: E");
|
||||||
|
rc = cam_ope_top_init(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_INIT: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_DEINIT:
|
||||||
|
break;
|
||||||
|
case OPE_HW_ACQUIRE:
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: E");
|
||||||
|
rc = cam_ope_top_acquire(ope_hw_info, ctx_id, data);
|
||||||
|
CAM_DBG(CAM_OPE, "OPE_HW_ACQUIRE: X");
|
||||||
|
break;
|
||||||
|
case OPE_HW_PREPARE:
|
||||||
|
break;
|
||||||
|
case OPE_HW_RELEASE:
|
||||||
|
rc = cam_ope_top_release(ope_hw_info, ctx_id, data);
|
||||||
|
break;
|
||||||
|
case OPE_HW_START:
|
||||||
|
break;
|
||||||
|
case OPE_HW_STOP:
|
||||||
|
break;
|
||||||
|
case OPE_HW_FLUSH:
|
||||||
|
break;
|
||||||
|
case OPE_HW_ISR:
|
||||||
|
rc = cam_ope_top_isr(ope_hw_info, 0, data);
|
||||||
|
break;
|
||||||
|
case OPE_HW_RESET:
|
||||||
|
rc = cam_ope_top_reset(ope_hw_info, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
41
drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h
Normal file
41
drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPE_TOP_H
|
||||||
|
#define OPE_TOP_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
#include <media/cam_ope.h>
|
||||||
|
#include "ope_hw.h"
|
||||||
|
#include "cam_hw_mgr_intf.h"
|
||||||
|
#include "cam_hw_intf.h"
|
||||||
|
#include "cam_soc_util.h"
|
||||||
|
#include "cam_context.h"
|
||||||
|
#include "cam_ope_context.h"
|
||||||
|
#include "cam_ope_hw_mgr.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_top_ctx
|
||||||
|
*
|
||||||
|
* @ope_acquire: OPE acquire info
|
||||||
|
*/
|
||||||
|
struct ope_top_ctx {
|
||||||
|
struct ope_acquire_dev_info *ope_acquire;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ope_top
|
||||||
|
*
|
||||||
|
* @ope_hw_info: OPE hardware info
|
||||||
|
* @top_ctx: OPE top context
|
||||||
|
* @reset_complete: Reset complete flag
|
||||||
|
*/
|
||||||
|
struct ope_top {
|
||||||
|
struct ope_hw *ope_hw_info;
|
||||||
|
struct ope_top_ctx top_ctx[OPE_CTX_MAX];
|
||||||
|
struct completion reset_complete;
|
||||||
|
};
|
||||||
|
#endif /* OPE_TOP_H */
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2019, The Linux Foundataion. All rights reserved.
|
* Copyright (c) 2017-2020, The Linux Foundataion. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
@@ -93,6 +93,11 @@ const char *cam_get_module_name(unsigned int module_id)
|
|||||||
break;
|
break;
|
||||||
case CAM_CUSTOM:
|
case CAM_CUSTOM:
|
||||||
name = "CAM-CUSTOM";
|
name = "CAM-CUSTOM";
|
||||||
|
case CAM_OPE:
|
||||||
|
name = "CAM-OPE";
|
||||||
|
break;
|
||||||
|
case CAM_PRESIL:
|
||||||
|
name = "CAM-PRESIL";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
name = "CAM";
|
name = "CAM";
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CAM_DEBUG_UTIL_H_
|
#ifndef _CAM_DEBUG_UTIL_H_
|
||||||
@@ -39,6 +39,8 @@
|
|||||||
/* CAM_PERF: Used for performance (clock, BW etc) logs */
|
/* CAM_PERF: Used for performance (clock, BW etc) logs */
|
||||||
#define CAM_PERF (1 << 25)
|
#define CAM_PERF (1 << 25)
|
||||||
#define CAM_CUSTOM (1 << 26)
|
#define CAM_CUSTOM (1 << 26)
|
||||||
|
#define CAM_OPE (1 << 28)
|
||||||
|
#define CAM_PRESIL (1 << 27)
|
||||||
|
|
||||||
#define STR_BUFFER_MAX_LENGTH 1024
|
#define STR_BUFFER_MAX_LENGTH 1024
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/build_bug.h>
|
#include <linux/build_bug.h>
|
||||||
@@ -48,6 +48,8 @@
|
|||||||
|
|
||||||
#include "cam_debug_util.h"
|
#include "cam_debug_util.h"
|
||||||
|
|
||||||
|
#include "ope_dev_intf.h"
|
||||||
|
|
||||||
struct camera_submodule_component {
|
struct camera_submodule_component {
|
||||||
int (*init)(void);
|
int (*init)(void);
|
||||||
void (*exit)(void);
|
void (*exit)(void);
|
||||||
@@ -101,6 +103,13 @@ static const struct camera_submodule_component camera_icp[] = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct camera_submodule_component camera_ope[] = {
|
||||||
|
#ifdef CONFIG_SPECTRA_OPE
|
||||||
|
{&cam_ope_init_module, &cam_ope_exit_module},
|
||||||
|
{&cam_ope_subdev_init_module, &cam_ope_subdev_exit_module},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
static const struct camera_submodule_component camera_jpeg[] = {
|
static const struct camera_submodule_component camera_jpeg[] = {
|
||||||
#ifdef CONFIG_SPECTRA_JPEG
|
#ifdef CONFIG_SPECTRA_JPEG
|
||||||
{&cam_jpeg_enc_init_module, &cam_jpeg_enc_exit_module},
|
{&cam_jpeg_enc_init_module, &cam_jpeg_enc_exit_module},
|
||||||
@@ -152,6 +161,11 @@ static const struct camera_submodule submodule_table[] = {
|
|||||||
.num_component = ARRAY_SIZE(camera_icp),
|
.num_component = ARRAY_SIZE(camera_icp),
|
||||||
.component = camera_icp,
|
.component = camera_icp,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "Camera OPE",
|
||||||
|
.num_component = ARRAY_SIZE(camera_ope),
|
||||||
|
.component = camera_ope,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = "Camera JPEG",
|
.name = "Camera JPEG",
|
||||||
.num_component = ARRAY_SIZE(camera_jpeg),
|
.num_component = ARRAY_SIZE(camera_jpeg),
|
||||||
|
Reference in New Issue
Block a user