msm: camera: tfe: Add support to TFE driver
TFE is thin front end hardware that capture and process the real time image. Support is added to enable the TFE hardware. CRs-Fixed: 2594541 Change-Id: I0ab2eff7924e9e01f6a0fcec772d3a7dda229b37 Signed-off-by: Ravikishore Pampana <rpampana@codeaurora.org> Signed-off-by: Trishansh Bhardwaj <tbhardwa@codeaurora.org>
This commit is contained in:
@@ -183,6 +183,22 @@ camera-$(CONFIG_SPECTRA_OPE) += \
|
||||
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-$(CONFIG_SPECTRA_CAMERA) += \
|
||||
cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.o
|
||||
|
||||
camera-y += camera_main.o
|
||||
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += camera.o
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
@@ -376,6 +376,38 @@ static const char *__cam_isp_resource_handle_id_to_type(
|
||||
}
|
||||
}
|
||||
|
||||
static const char *__cam_isp_tfe_resource_handle_id_to_type(
|
||||
uint32_t resource_handle)
|
||||
{
|
||||
|
||||
switch (resource_handle) {
|
||||
case CAM_ISP_TFE_OUT_RES_FULL:
|
||||
return "FULL";
|
||||
case CAM_ISP_TFE_OUT_RES_RAW_DUMP:
|
||||
return "RAW_DUMP";
|
||||
case CAM_ISP_TFE_OUT_RES_PDAF:
|
||||
return "PDAF";
|
||||
case CAM_ISP_TFE_OUT_RES_RDI_0:
|
||||
return "RDI_0";
|
||||
case CAM_ISP_TFE_OUT_RES_RDI_1:
|
||||
return "RDI_1";
|
||||
case CAM_ISP_TFE_OUT_RES_RDI_2:
|
||||
return "RDI_2";
|
||||
case CAM_ISP_TFE_OUT_RES_STATS_HDR_BE:
|
||||
return "STATS_HDR_BE";
|
||||
case CAM_ISP_TFE_OUT_RES_STATS_HDR_BHIST:
|
||||
return "STATS_HDR_BHIST";
|
||||
case CAM_ISP_TFE_OUT_RES_STATS_TL_BG:
|
||||
return "STATS_TL_BG";
|
||||
case CAM_ISP_TFE_OUT_RES_STATS_BF:
|
||||
return "STATS_BF";
|
||||
case CAM_ISP_TFE_OUT_RES_STATS_AWB_BG:
|
||||
return "STATS_AWB_BG";
|
||||
default:
|
||||
return "CAM_ISP_Invalid_Resource_Type";
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t __cam_isp_ctx_get_event_ts(uint32_t evt_id, void *evt_data)
|
||||
{
|
||||
uint64_t ts = 0;
|
||||
@@ -471,9 +503,11 @@ static void __cam_isp_ctx_send_sof_timestamp(
|
||||
}
|
||||
|
||||
static void __cam_isp_ctx_handle_buf_done_fail_log(
|
||||
uint64_t request_id, struct cam_isp_ctx_req *req_isp)
|
||||
uint64_t request_id, struct cam_isp_ctx_req *req_isp,
|
||||
uint32_t isp_device_type)
|
||||
{
|
||||
int i;
|
||||
const char *handle_type;
|
||||
|
||||
if (req_isp->num_fence_map_out >= CAM_ISP_CTX_RES_MAX) {
|
||||
CAM_ERR(CAM_ISP,
|
||||
@@ -490,10 +524,18 @@ static void __cam_isp_ctx_handle_buf_done_fail_log(
|
||||
"Resource Handles that fail to generate buf_done in prev frame");
|
||||
for (i = 0; i < req_isp->num_fence_map_out; i++) {
|
||||
if (req_isp->fence_map_out[i].sync_id != -1) {
|
||||
if (isp_device_type == CAM_IFE_DEVICE_TYPE)
|
||||
handle_type =
|
||||
__cam_isp_resource_handle_id_to_type(
|
||||
req_isp->fence_map_out[i].resource_handle);
|
||||
else
|
||||
handle_type =
|
||||
__cam_isp_tfe_resource_handle_id_to_type(
|
||||
req_isp->fence_map_out[i].resource_handle);
|
||||
|
||||
CAM_WARN(CAM_ISP,
|
||||
"Resource_Handle: [%s][0x%x] Sync_ID: [0x%x]",
|
||||
__cam_isp_resource_handle_id_to_type(
|
||||
req_isp->fence_map_out[i].resource_handle),
|
||||
handle_type,
|
||||
req_isp->fence_map_out[i].resource_handle,
|
||||
req_isp->fence_map_out[i].sync_id);
|
||||
}
|
||||
@@ -512,6 +554,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request(
|
||||
struct cam_isp_ctx_req *req_isp;
|
||||
struct cam_context *ctx = ctx_isp->base;
|
||||
uint64_t buf_done_req_id;
|
||||
const char *handle_type;
|
||||
|
||||
trace_cam_buf_done("ISP", ctx, req);
|
||||
|
||||
@@ -541,11 +584,18 @@ static int __cam_isp_ctx_handle_buf_done_for_request(
|
||||
}
|
||||
|
||||
if (req_isp->fence_map_out[j].sync_id == -1) {
|
||||
if (ctx_isp->isp_device_type == CAM_IFE_DEVICE_TYPE)
|
||||
handle_type =
|
||||
__cam_isp_resource_handle_id_to_type(
|
||||
req_isp->fence_map_out[i].resource_handle);
|
||||
else
|
||||
handle_type =
|
||||
__cam_isp_tfe_resource_handle_id_to_type(
|
||||
req_isp->fence_map_out[i].resource_handle);
|
||||
|
||||
CAM_WARN(CAM_ISP,
|
||||
"Duplicate BUF_DONE for req %lld : i=%d, j=%d, res=%s",
|
||||
req->request_id, i, j,
|
||||
__cam_isp_resource_handle_id_to_type(
|
||||
done->resource_handle[i]));
|
||||
req->request_id, i, j, handle_type);
|
||||
|
||||
if (done_next_req) {
|
||||
done_next_req->resource_handle
|
||||
@@ -1967,7 +2017,8 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
|
||||
active_req_isp =
|
||||
(struct cam_isp_ctx_req *) active_req->req_priv;
|
||||
__cam_isp_ctx_handle_buf_done_fail_log(
|
||||
active_req->request_id, active_req_isp);
|
||||
active_req->request_id, active_req_isp,
|
||||
ctx_isp->isp_device_type);
|
||||
}
|
||||
|
||||
rc = -EFAULT;
|
||||
@@ -4354,7 +4405,8 @@ int cam_isp_context_init(struct cam_isp_context *ctx,
|
||||
struct cam_context *ctx_base,
|
||||
struct cam_req_mgr_kmd_ops *crm_node_intf,
|
||||
struct cam_hw_mgr_intf *hw_intf,
|
||||
uint32_t ctx_id)
|
||||
uint32_t ctx_id,
|
||||
uint32_t isp_device_type)
|
||||
|
||||
{
|
||||
int rc = -1;
|
||||
@@ -4378,6 +4430,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx,
|
||||
ctx->substate_machine = cam_isp_ctx_activated_state_machine;
|
||||
ctx->substate_machine_irq = cam_isp_ctx_activated_state_machine_irq;
|
||||
ctx->init_timestamp = jiffies_to_msecs(jiffies);
|
||||
ctx->isp_device_type = isp_device_type;
|
||||
|
||||
for (i = 0; i < CAM_CTX_REQ_MAX; i++) {
|
||||
ctx->req_base[i].req_priv = &ctx->req_isp[i];
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_ISP_CONTEXT_H_
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <media/cam_isp.h>
|
||||
#include <media/cam_defs.h>
|
||||
#include <media/cam_tfe.h>
|
||||
|
||||
#include "cam_context.h"
|
||||
#include "cam_isp_hw_mgr_intf.h"
|
||||
@@ -177,6 +178,7 @@ struct cam_isp_context_state_monitor {
|
||||
* @init_received: Indicate whether init config packet is received
|
||||
* @split_acquire: Indicate whether a separate acquire is expected
|
||||
* @init_timestamp: Timestamp at which this context is initialized
|
||||
* @isp_device_type ISP device type
|
||||
*
|
||||
*/
|
||||
struct cam_isp_context {
|
||||
@@ -207,6 +209,7 @@ struct cam_isp_context {
|
||||
bool init_received;
|
||||
bool split_acquire;
|
||||
unsigned int init_timestamp;
|
||||
uint32_t isp_device_type;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -218,13 +221,15 @@ struct cam_isp_context {
|
||||
* @bridge_ops: Bridge call back funciton
|
||||
* @hw_intf: ISP hw manager interface
|
||||
* @ctx_id: ID for this context
|
||||
* @isp_device_type Isp device type
|
||||
*
|
||||
*/
|
||||
int cam_isp_context_init(struct cam_isp_context *ctx,
|
||||
struct cam_context *ctx_base,
|
||||
struct cam_req_mgr_kmd_ops *bridge_ops,
|
||||
struct cam_hw_mgr_intf *hw_intf,
|
||||
uint32_t ctx_id);
|
||||
uint32_t ctx_id,
|
||||
uint32_t isp_device_type);
|
||||
|
||||
/**
|
||||
* cam_isp_context_deinit()
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
@@ -117,12 +117,30 @@ static int cam_isp_dev_probe(struct platform_device *pdev)
|
||||
int i;
|
||||
struct cam_hw_mgr_intf hw_mgr_intf;
|
||||
struct cam_node *node;
|
||||
const char *compat_str = NULL;
|
||||
uint32_t isp_device_type;
|
||||
|
||||
int iommu_hdl = -1;
|
||||
|
||||
rc = of_property_read_string_index(pdev->dev.of_node, "arch-compat", 0,
|
||||
(const char **)&compat_str);
|
||||
|
||||
g_isp_dev.sd.internal_ops = &cam_isp_subdev_internal_ops;
|
||||
/* Initialize the v4l2 subdevice first. (create cam_node) */
|
||||
if (strnstr(compat_str, "ife", strlen(compat_str))) {
|
||||
rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME,
|
||||
CAM_IFE_DEVICE_TYPE);
|
||||
isp_device_type = CAM_IFE_DEVICE_TYPE;
|
||||
} else if (strnstr(compat_str, "tfe", strlen(compat_str))) {
|
||||
rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME,
|
||||
CAM_TFE_DEVICE_TYPE);
|
||||
isp_device_type = CAM_TFE_DEVICE_TYPE;
|
||||
} else {
|
||||
CAM_ERR(CAM_ISP, "Invalid ISP hw type %s", compat_str);
|
||||
rc = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "ISP cam_subdev_probe failed!");
|
||||
goto err;
|
||||
@@ -130,7 +148,7 @@ static int cam_isp_dev_probe(struct platform_device *pdev)
|
||||
node = (struct cam_node *) g_isp_dev.sd.token;
|
||||
|
||||
memset(&hw_mgr_intf, 0, sizeof(hw_mgr_intf));
|
||||
rc = cam_isp_hw_mgr_init(pdev->dev.of_node, &hw_mgr_intf, &iommu_hdl);
|
||||
rc = cam_isp_hw_mgr_init(compat_str, &hw_mgr_intf, &iommu_hdl);
|
||||
if (rc != 0) {
|
||||
CAM_ERR(CAM_ISP, "Can not initialized ISP HW manager!");
|
||||
goto unregister;
|
||||
@@ -141,7 +159,8 @@ static int cam_isp_dev_probe(struct platform_device *pdev)
|
||||
&g_isp_dev.ctx[i],
|
||||
&node->crm_node_intf,
|
||||
&node->hw_mgr_intf,
|
||||
i);
|
||||
i,
|
||||
isp_device_type);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "ISP context init failed!");
|
||||
goto unregister;
|
||||
|
@@ -1,26 +1,25 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "cam_isp_hw_mgr_intf.h"
|
||||
#include "cam_ife_hw_mgr.h"
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_tfe_hw_mgr.h"
|
||||
|
||||
|
||||
int cam_isp_hw_mgr_init(struct device_node *of_node,
|
||||
int cam_isp_hw_mgr_init(const char *device_name_str,
|
||||
struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl)
|
||||
{
|
||||
int rc = 0;
|
||||
const char *compat_str = NULL;
|
||||
|
||||
rc = of_property_read_string_index(of_node, "arch-compat", 0,
|
||||
(const char **)&compat_str);
|
||||
|
||||
if (strnstr(compat_str, "ife", strlen(compat_str)))
|
||||
if (strnstr(device_name_str, "ife", strlen(device_name_str)))
|
||||
rc = cam_ife_hw_mgr_init(hw_mgr, iommu_hdl);
|
||||
else if (strnstr(device_name_str, "tfe", strlen(device_name_str)))
|
||||
rc = cam_tfe_hw_mgr_init(hw_mgr, iommu_hdl);
|
||||
else {
|
||||
CAM_ERR(CAM_ISP, "Invalid ISP hw type");
|
||||
CAM_ERR(CAM_ISP, "Invalid ISP hw type :%s", device_name_str);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
|
5282
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c
Normal file
5282
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c
Normal file
File diff suppressed because it is too large
Load Diff
196
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h
Normal file
196
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_HW_MGR_H_
|
||||
#define _CAM_TFE_HW_MGR_H_
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <media/cam_isp_tfe.h>
|
||||
#include "cam_isp_hw_mgr.h"
|
||||
#include "cam_tfe_hw_intf.h"
|
||||
#include "cam_tfe_csid_hw_intf.h"
|
||||
#include "cam_top_tpg_hw_intf.h"
|
||||
#include "cam_tasklet_util.h"
|
||||
|
||||
|
||||
|
||||
/* TFE resource constants */
|
||||
#define CAM_TFE_HW_IN_RES_MAX (CAM_ISP_TFE_IN_RES_MAX & 0xFF)
|
||||
#define CAM_TFE_HW_OUT_RES_MAX (CAM_ISP_TFE_OUT_RES_MAX & 0xFF)
|
||||
#define CAM_TFE_HW_RES_POOL_MAX 64
|
||||
|
||||
/**
|
||||
* struct cam_tfe_hw_mgr_debug - contain the debug information
|
||||
*
|
||||
* @dentry: Debugfs entry
|
||||
* @csid_debug: csid debug information
|
||||
* @enable_recovery: enable recovery
|
||||
* @camif_debug: enable sensor diagnosis status
|
||||
* @enable_reg_dump: enable reg dump on error;
|
||||
* @per_req_reg_dump: Enable per request reg dump
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_hw_mgr_debug {
|
||||
struct dentry *dentry;
|
||||
uint64_t csid_debug;
|
||||
uint32_t enable_recovery;
|
||||
uint32_t camif_debug;
|
||||
bool enable_reg_dump;
|
||||
bool per_req_reg_dump;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_hw_mgr_ctx - TFE HW manager Context object
|
||||
*
|
||||
* @list: used by the ctx list.
|
||||
* @common: common acquired context data
|
||||
* @ctx_index: acquired context id.
|
||||
* @hw_mgr: tfe hw mgr which owns this context
|
||||
* @ctx_in_use: flag to tell whether context is active
|
||||
* @res_list_csid: csid resource list
|
||||
* @res_list_tfe_in: tfe input resource list
|
||||
* @res_list_tfe_out: tfe output resoruces array
|
||||
* @free_res_list: free resources list for the branch node
|
||||
* @res_pool: memory storage for the free resource list
|
||||
* @base device base index array contain the all TFE HW
|
||||
* instance associated with this context.
|
||||
* @num_base number of valid base data in the base array
|
||||
* @cdm_handle cdm hw acquire handle
|
||||
* @cdm_ops cdm util operation pointer for building
|
||||
* cdm commands
|
||||
* @cdm_cmd cdm base and length request pointer
|
||||
* @config_done_complete indicator for configuration complete
|
||||
* @sof_cnt sof count value per core, used for dual TFE
|
||||
* @epoch_cnt epoch count value per core, used for dual TFE
|
||||
* @eof_cnt eof count value per core, used for dual TFE
|
||||
* @overflow_pending flat to specify the overflow is pending for the
|
||||
* context
|
||||
* @cdm_done flag to indicate cdm has finished writing shadow
|
||||
* registers
|
||||
* @is_rdi_only_context flag to specify the context has only rdi resource
|
||||
* @reg_dump_buf_desc: cmd buffer descriptors for reg dump
|
||||
* @num_reg_dump_buf: count of descriptors in reg_dump_buf_desc
|
||||
* @applied_req_id: last request id to be applied
|
||||
* @last_dump_flush_req_id last req id for which reg dump on flush was called
|
||||
* @last_dump_err_req_id last req id for which reg dump on error was called
|
||||
* @init_done indicate whether init hw is done
|
||||
* @is_dual indicate whether context is in dual TFE mode
|
||||
* @is_tpg indicate whether context use tpg
|
||||
* @master_hw_idx master hardware index in dual tfe case
|
||||
* @dual_tfe_irq_mismatch_cnt irq mismatch count value per core, used for
|
||||
* dual TFE
|
||||
*/
|
||||
struct cam_tfe_hw_mgr_ctx {
|
||||
struct list_head list;
|
||||
struct cam_isp_hw_mgr_ctx common;
|
||||
|
||||
uint32_t ctx_index;
|
||||
struct cam_tfe_hw_mgr *hw_mgr;
|
||||
uint32_t ctx_in_use;
|
||||
|
||||
struct cam_isp_hw_mgr_res res_list_tpg;
|
||||
struct list_head res_list_tfe_csid;
|
||||
struct list_head res_list_tfe_in;
|
||||
struct cam_isp_hw_mgr_res
|
||||
res_list_tfe_out[CAM_TFE_HW_OUT_RES_MAX];
|
||||
|
||||
struct list_head free_res_list;
|
||||
struct cam_isp_hw_mgr_res res_pool[CAM_TFE_HW_RES_POOL_MAX];
|
||||
|
||||
struct cam_isp_ctx_base_info base[CAM_TFE_HW_NUM_MAX];
|
||||
uint32_t num_base;
|
||||
uint32_t cdm_handle;
|
||||
struct cam_cdm_utils_ops *cdm_ops;
|
||||
struct cam_cdm_bl_request *cdm_cmd;
|
||||
struct completion config_done_complete;
|
||||
|
||||
uint32_t sof_cnt[CAM_TFE_HW_NUM_MAX];
|
||||
uint32_t epoch_cnt[CAM_TFE_HW_NUM_MAX];
|
||||
uint32_t eof_cnt[CAM_TFE_HW_NUM_MAX];
|
||||
atomic_t overflow_pending;
|
||||
atomic_t cdm_done;
|
||||
uint32_t is_rdi_only_context;
|
||||
struct cam_cmd_buf_desc reg_dump_buf_desc[
|
||||
CAM_REG_DUMP_MAX_BUF_ENTRIES];
|
||||
uint32_t num_reg_dump_buf;
|
||||
uint64_t applied_req_id;
|
||||
uint64_t last_dump_flush_req_id;
|
||||
uint64_t last_dump_err_req_id;
|
||||
bool init_done;
|
||||
bool is_dual;
|
||||
bool is_tpg;
|
||||
uint32_t master_hw_idx;
|
||||
uint32_t dual_tfe_irq_mismatch_cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_hw_mgr - TFE HW Manager
|
||||
*
|
||||
* @mgr_common: common data for all HW managers
|
||||
* @tpg_devices: tpg devices instacnce array. This will be filled by
|
||||
* HW manager during the initialization.
|
||||
* @csid_devices: csid device instances array. This will be filled by
|
||||
* HW manager during the initialization.
|
||||
* @tfe_devices: TFE device instances array. This will be filled by
|
||||
* HW layer during initialization
|
||||
* @cdm_reg_map commands for register dump
|
||||
* @ctx_mutex: mutex for the hw context pool
|
||||
* @active_ctx_cnt active context count number
|
||||
* @free_ctx_list: free hw context list
|
||||
* @used_ctx_list: used hw context list
|
||||
* @ctx_pool: context storage
|
||||
* @tfe_csid_dev_caps csid device capability stored per core
|
||||
* @tfe_dev_caps tfe device capability per core
|
||||
* @work q work queue for TFE hw manager
|
||||
* @debug_cfg debug configuration
|
||||
*/
|
||||
struct cam_tfe_hw_mgr {
|
||||
struct cam_isp_hw_mgr mgr_common;
|
||||
struct cam_hw_intf *tpg_devices[CAM_TOP_TPG_HW_NUM_MAX];
|
||||
struct cam_hw_intf *csid_devices[CAM_TFE_CSID_HW_NUM_MAX];
|
||||
struct cam_hw_intf *tfe_devices[CAM_TFE_HW_NUM_MAX];
|
||||
struct cam_soc_reg_map *cdm_reg_map[CAM_TFE_HW_NUM_MAX];
|
||||
struct mutex ctx_mutex;
|
||||
atomic_t active_ctx_cnt;
|
||||
struct list_head free_ctx_list;
|
||||
struct list_head used_ctx_list;
|
||||
struct cam_tfe_hw_mgr_ctx ctx_pool[CAM_CTX_MAX];
|
||||
|
||||
struct cam_tfe_csid_hw_caps tfe_csid_dev_caps[
|
||||
CAM_TFE_CSID_HW_NUM_MAX];
|
||||
struct cam_tfe_hw_get_hw_cap tfe_dev_caps[CAM_TFE_HW_NUM_MAX];
|
||||
struct cam_req_mgr_core_workq *workq;
|
||||
struct cam_tfe_hw_mgr_debug debug_cfg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_hw_event_recovery_data - Payload for the recovery procedure
|
||||
*
|
||||
* @error_type: Error type that causes the recovery
|
||||
* @affected_core: Array of the hardware cores that are affected
|
||||
* @affected_ctx: Array of the hardware contexts that are affected
|
||||
* @no_of_context: Actual number of the affected context
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_hw_event_recovery_data {
|
||||
uint32_t error_type;
|
||||
uint32_t affected_core[CAM_TFE_HW_NUM_MAX];
|
||||
struct cam_tfe_hw_mgr_ctx *affected_ctx[CAM_CTX_MAX];
|
||||
uint32_t no_of_context;
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_tfe_hw_mgr_init()
|
||||
*
|
||||
* @brief: Initialize the TFE hardware manger. This is the
|
||||
* etnry functinon for the TFE HW manager.
|
||||
*
|
||||
* @hw_mgr_intf: TFE hardware manager object returned
|
||||
* @iommu_hdl: Iommu handle to be returned
|
||||
*
|
||||
*/
|
||||
int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl);
|
||||
|
||||
#endif /* _CAM_TFE_HW_MGR_H_ */
|
@@ -17,6 +17,8 @@
|
||||
#define CAM_IFE_RDI_NUM_MAX 4
|
||||
#define CAM_ISP_BW_CONFIG_V1 1
|
||||
#define CAM_ISP_BW_CONFIG_V2 2
|
||||
#define CAM_TFE_HW_NUM_MAX 3
|
||||
#define CAM_TFE_RDI_NUM_MAX 3
|
||||
|
||||
/* Appliacble vote paths for dual ife, based on no. of UAPI definitions */
|
||||
#define CAM_ISP_MAX_PER_PATH_VOTES 30
|
||||
@@ -252,12 +254,12 @@ struct cam_isp_hw_cmd_args {
|
||||
*
|
||||
* @brief: Initialization function for the ISP hardware manager
|
||||
*
|
||||
* @of_node: Device node input
|
||||
* @device_name_str: Device name string
|
||||
* @hw_mgr: Input/output structure for the ISP hardware manager
|
||||
* initialization
|
||||
* @iommu_hdl: Iommu handle to be returned
|
||||
*/
|
||||
int cam_isp_hw_mgr_init(struct device_node *of_node,
|
||||
int cam_isp_hw_mgr_init(const char *device_name_str,
|
||||
struct cam_hw_mgr_intf *hw_mgr, int *iommu_hdl);
|
||||
|
||||
#endif /* __CAM_ISP_HW_MGR_INTF_H__ */
|
||||
|
@@ -38,11 +38,14 @@ struct cam_isp_timestamp {
|
||||
void cam_isp_hw_get_timestamp(struct cam_isp_timestamp *time_stamp);
|
||||
|
||||
enum cam_isp_hw_type {
|
||||
CAM_ISP_HW_TYPE_CSID = 0,
|
||||
CAM_ISP_HW_TYPE_ISPIF = 1,
|
||||
CAM_ISP_HW_TYPE_VFE = 2,
|
||||
CAM_ISP_HW_TYPE_IFE_CSID = 3,
|
||||
CAM_ISP_HW_TYPE_MAX = 4,
|
||||
CAM_ISP_HW_TYPE_CSID,
|
||||
CAM_ISP_HW_TYPE_ISPIF,
|
||||
CAM_ISP_HW_TYPE_VFE,
|
||||
CAM_ISP_HW_TYPE_IFE_CSID,
|
||||
CAM_ISP_HW_TYPE_TFE,
|
||||
CAM_ISP_HW_TYPE_TFE_CSID,
|
||||
CAM_ISP_HW_TYPE_TPG,
|
||||
CAM_ISP_HW_TYPE_MAX,
|
||||
};
|
||||
|
||||
enum cam_isp_hw_split_id {
|
||||
@@ -74,6 +77,9 @@ enum cam_isp_resource_type {
|
||||
CAM_ISP_RESOURCE_VFE_IN,
|
||||
CAM_ISP_RESOURCE_VFE_OUT,
|
||||
CAM_ISP_RESOURCE_VFE_BUS_RD,
|
||||
CAM_ISP_RESOURCE_TPG,
|
||||
CAM_ISP_RESOURCE_TFE_IN,
|
||||
CAM_ISP_RESOURCE_TFE_OUT,
|
||||
CAM_ISP_RESOURCE_MAX,
|
||||
};
|
||||
|
||||
@@ -91,6 +97,7 @@ enum cam_isp_hw_cmd_type {
|
||||
CAM_ISP_HW_CMD_BW_UPDATE_V2,
|
||||
CAM_ISP_HW_CMD_BW_CONTROL,
|
||||
CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ,
|
||||
CAM_ISP_HW_CMD_GET_REG_DUMP,
|
||||
CAM_ISP_HW_CMD_UBWC_UPDATE,
|
||||
CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
|
||||
CAM_ISP_HW_CMD_SET_CAMIF_DEBUG,
|
||||
@@ -102,6 +109,8 @@ enum cam_isp_hw_cmd_type {
|
||||
CAM_ISP_HW_CMD_WM_CONFIG_UPDATE,
|
||||
CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED,
|
||||
CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA,
|
||||
CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE,
|
||||
CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
|
||||
CAM_ISP_HW_CMD_MAX,
|
||||
};
|
||||
|
||||
|
179
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h
Normal file
179
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_CSID_HW_INTF_H_
|
||||
#define _CAM_TFE_CSID_HW_INTF_H_
|
||||
|
||||
#include "cam_isp_hw.h"
|
||||
#include "cam_hw_intf.h"
|
||||
|
||||
/* MAX TFE CSID instance */
|
||||
#define CAM_TFE_CSID_HW_NUM_MAX 3
|
||||
#define CAM_TFE_CSID_RDI_MAX 3
|
||||
|
||||
/**
|
||||
* enum cam_tfe_pix_path_res_id - Specify the csid patch
|
||||
*/
|
||||
enum cam_tfe_csid_path_res_id {
|
||||
CAM_TFE_CSID_PATH_RES_RDI_0,
|
||||
CAM_TFE_CSID_PATH_RES_RDI_1,
|
||||
CAM_TFE_CSID_PATH_RES_RDI_2,
|
||||
CAM_TFE_CSID_PATH_RES_IPP,
|
||||
CAM_TFE_CSID_PATH_RES_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cam_tfe_csid_irq_reg
|
||||
*/
|
||||
enum cam_tfe_csid_irq_reg {
|
||||
TFE_CSID_IRQ_REG_RDI0,
|
||||
TFE_CSID_IRQ_REG_RDI1,
|
||||
TFE_CSID_IRQ_REG_RDI2,
|
||||
TFE_CSID_IRQ_REG_TOP,
|
||||
TFE_CSID_IRQ_REG_RX,
|
||||
TFE_CSID_IRQ_REG_IPP,
|
||||
TFE_CSID_IRQ_REG_MAX,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_hw_caps- get the CSID hw capability
|
||||
* @num_rdis: number of rdis supported by CSID HW device
|
||||
* @num_pix: number of pxl paths supported by CSID HW device
|
||||
* @major_version : major version
|
||||
* @minor_version: minor version
|
||||
* @version_incr: version increment
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_hw_caps {
|
||||
uint32_t num_rdis;
|
||||
uint32_t num_pix;
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t version_incr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_hw_reserve_resource_args- hw reserve
|
||||
* @res_type : Reource type ie PATH
|
||||
* @res_id : Resource id to be reserved
|
||||
* @in_port : Input port resource info
|
||||
* @out_port: Output port resource info, used for RDI path only
|
||||
* @sync_mode: Sync mode
|
||||
* Sync mode could be master, slave or none
|
||||
* @master_idx: Master device index to be configured in the slave path
|
||||
* for master path, this value is not required.
|
||||
* only slave need to configure the master index value
|
||||
* @phy_sel: Phy selection number if tpg is enabled from userspace
|
||||
* @event_cb_prv: Context data
|
||||
* @event_cb: Callback function to hw mgr in case of hw events
|
||||
* @node_res : Reserved resource structure pointer
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_hw_reserve_resource_args {
|
||||
enum cam_isp_resource_type res_type;
|
||||
uint32_t res_id;
|
||||
struct cam_isp_tfe_in_port_info *in_port;
|
||||
struct cam_isp_tfe_out_port_info *out_port;
|
||||
enum cam_isp_hw_sync_mode sync_mode;
|
||||
uint32_t master_idx;
|
||||
uint32_t phy_sel;
|
||||
void *event_cb_prv;
|
||||
cam_hw_mgr_event_cb_func event_cb;
|
||||
struct cam_isp_resource_node *node_res;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cam_tfe_csid_halt_cmd - Specify the halt command type
|
||||
*/
|
||||
enum cam_tfe_csid_halt_cmd {
|
||||
CAM_TFE_CSID_HALT_AT_FRAME_BOUNDARY,
|
||||
CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY,
|
||||
CAM_TFE_CSID_HALT_IMMEDIATELY,
|
||||
CAM_TFE_CSID_HALT_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_csid_hw_stop- stop all resources
|
||||
* @stop_cmd : Applicable only for PATH resources
|
||||
* if stop command set to Halt immediately,driver will stop
|
||||
* path immediately, manager need to reset the path after HI
|
||||
* if stop command set to halt at frame boundary, driver will set
|
||||
* halt at frame boundary and wait for frame boundary
|
||||
* @num_res : Number of resources to be stopped
|
||||
* @node_res : Reource pointer array( ie cid or CSID)
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_hw_stop_args {
|
||||
enum cam_tfe_csid_halt_cmd stop_cmd;
|
||||
uint32_t num_res;
|
||||
struct cam_isp_resource_node **node_res;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cam_tfe_csid_reset_type - Specify the reset type
|
||||
*/
|
||||
enum cam_tfe_csid_reset_type {
|
||||
CAM_TFE_CSID_RESET_GLOBAL,
|
||||
CAM_TFE_CSID_RESET_PATH,
|
||||
CAM_TFE_CSID_RESET_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_reset_cfg- Csid reset configuration
|
||||
* @ reset_type : Global reset or path reset
|
||||
* @res_node : Resource need to be reset
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_reset_cfg_args {
|
||||
enum cam_tfe_csid_reset_type reset_type;
|
||||
struct cam_isp_resource_node *node_res;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_csid_get_time_stamp_args- time stamp capture arguments
|
||||
* @res_node : Resource to get the time stamp
|
||||
* @time_stamp_val : Captured time stamp
|
||||
* @boot_timestamp : Boot time stamp
|
||||
*/
|
||||
struct cam_tfe_csid_get_time_stamp_args {
|
||||
struct cam_isp_resource_node *node_res;
|
||||
uint64_t time_stamp_val;
|
||||
uint64_t boot_timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cam_tfe_csid_cmd_type - Specify the csid command
|
||||
*/
|
||||
enum cam_tfe_csid_cmd_type {
|
||||
CAM_TFE_CSID_CMD_GET_TIME_STAMP,
|
||||
CAM_TFE_CSID_SET_CSID_DEBUG,
|
||||
CAM_TFE_CSID_SOF_IRQ_DEBUG,
|
||||
CAM_TFE_CSID_CMD_GET_REG_DUMP,
|
||||
CAM_TFE_CSID_CMD_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_tfe_csid_hw_init()
|
||||
*
|
||||
* @brief: Initialize function for the CSID hardware
|
||||
*
|
||||
* @tfe_csid_hw: CSID hardware instance returned
|
||||
* @hw_idex: CSID hardware instance id
|
||||
*/
|
||||
int cam_tfe_csid_hw_init(struct cam_hw_intf **tfe_csid_hw,
|
||||
uint32_t hw_idx);
|
||||
|
||||
/*
|
||||
* struct cam_tfe_csid_clock_update_args:
|
||||
*
|
||||
* @clk_rate: Clock rate requested
|
||||
*/
|
||||
struct cam_tfe_csid_clock_update_args {
|
||||
uint64_t clk_rate;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _CAM_TFE_CSID_HW_INTF_H_ */
|
253
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h
Normal file
253
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h
Normal file
@@ -0,0 +1,253 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_HW_INTF_H_
|
||||
#define _CAM_TFE_HW_INTF_H_
|
||||
|
||||
#include "cam_isp_hw.h"
|
||||
#include "cam_cpas_api.h"
|
||||
|
||||
#define CAM_TFE_HW_NUM_MAX 3
|
||||
#define TFE_CORE_BASE_IDX 0
|
||||
|
||||
|
||||
enum cam_isp_hw_tfe_in {
|
||||
CAM_ISP_HW_TFE_IN_CAMIF = 0,
|
||||
CAM_ISP_HW_TFE_IN_RDI0 = 1,
|
||||
CAM_ISP_HW_TFE_IN_RDI1 = 2,
|
||||
CAM_ISP_HW_TFE_IN_RDI2 = 3,
|
||||
CAM_ISP_HW_TFE_IN_MAX,
|
||||
};
|
||||
|
||||
enum cam_isp_hw_tfe_core {
|
||||
CAM_ISP_HW_TFE_CORE_0,
|
||||
CAM_ISP_HW_TFE_CORE_1,
|
||||
CAM_ISP_HW_TFE_CORE_2,
|
||||
CAM_ISP_HW_TFE_CORE_MAX,
|
||||
};
|
||||
|
||||
enum cam_tfe_hw_irq_status {
|
||||
CAM_TFE_IRQ_STATUS_SUCCESS,
|
||||
CAM_TFE_IRQ_STATUS_ERR,
|
||||
CAM_TFE_IRQ_STATUS_OVERFLOW,
|
||||
CAM_TFE_IRQ_STATUS_P2I_ERROR,
|
||||
CAM_TFE_IRQ_STATUS_VIOLATION,
|
||||
CAM_TFE_IRQ_STATUS_MAX,
|
||||
};
|
||||
|
||||
enum cam_tfe_hw_irq_regs {
|
||||
CAM_TFE_IRQ_CAMIF_REG_STATUS0 = 0,
|
||||
CAM_TFE_IRQ_CAMIF_REG_STATUS1 = 1,
|
||||
CAM_TFE_IRQ_CAMIF_REG_STATUS2 = 2,
|
||||
CAM_TFE_IRQ_REGISTERS_MAX,
|
||||
};
|
||||
|
||||
enum cam_tfe_bus_irq_regs {
|
||||
CAM_TFE_IRQ_BUS_REG_STATUS0 = 0,
|
||||
CAM_TFE_IRQ_BUS_REG_STATUS1 = 1,
|
||||
CAM_TFE_BUS_IRQ_REGISTERS_MAX,
|
||||
};
|
||||
|
||||
enum cam_tfe_reset_type {
|
||||
CAM_TFE_HW_RESET_HW_AND_REG,
|
||||
CAM_TFE_HW_RESET_HW,
|
||||
CAM_TFE_HW_RESET_MAX,
|
||||
};
|
||||
|
||||
enum cam_tfe_bw_control_action {
|
||||
CAM_TFE_BW_CONTROL_EXCLUDE = 0,
|
||||
CAM_TFE_BW_CONTROL_INCLUDE = 1
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_hw_get_hw_cap:
|
||||
*
|
||||
* @max_width: Max width supported by HW
|
||||
* @max_height: Max height supported by HW
|
||||
* @max_pixel_num: Max Pixel channels available
|
||||
* @max_rdi_num: Max Raw channels available
|
||||
*/
|
||||
struct cam_tfe_hw_get_hw_cap {
|
||||
uint32_t max_width;
|
||||
uint32_t max_height;
|
||||
uint32_t max_pixel_num;
|
||||
uint32_t max_rdi_num;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_hw_tfe_out_acquire_args:
|
||||
*
|
||||
* @rsrc_node: Pointer to Resource Node object, filled if acquire
|
||||
* is successful
|
||||
* @out_port_info: Output Port details to acquire
|
||||
* @unique_id: Unique Identity of Context to associate with this
|
||||
* resource. Used for composite grouping of multiple
|
||||
* resources in the same context
|
||||
* @is_dual: Dual TFE or not
|
||||
* @split_id: In case of Dual TFE, this is Left or Right.
|
||||
* (Default is Left if Single TFE)
|
||||
* @is_master: In case of Dual TFE, this is Master or Slave.
|
||||
* (Default is Master in case of Single TFE)
|
||||
* @cdm_ops: CDM operations
|
||||
* @ctx: Context data
|
||||
*/
|
||||
struct cam_tfe_hw_tfe_out_acquire_args {
|
||||
struct cam_isp_resource_node *rsrc_node;
|
||||
struct cam_isp_tfe_out_port_info *out_port_info;
|
||||
uint32_t unique_id;
|
||||
uint32_t is_dual;
|
||||
enum cam_isp_hw_split_id split_id;
|
||||
uint32_t is_master;
|
||||
struct cam_cdm_utils_ops *cdm_ops;
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_hw_tfe_in_acquire_args:
|
||||
*
|
||||
* @rsrc_node: Pointer to Resource Node object, filled if acquire
|
||||
* is successful
|
||||
* @res_id: Resource ID of resource to acquire if specific,
|
||||
* else CAM_ISP_HW_TFE_IN_MAX
|
||||
* @cdm_ops: CDM operations
|
||||
* @sync_mode: In case of Dual TFE, this is Master or Slave.
|
||||
* (Default is Master in case of Single TFE)
|
||||
* @in_port: Input port details to acquire
|
||||
* @camif_pd_enable Camif pd enable or disable
|
||||
* @dual_tfe_sync_sel_idx Dual tfe master hardware index
|
||||
*/
|
||||
struct cam_tfe_hw_tfe_in_acquire_args {
|
||||
struct cam_isp_resource_node *rsrc_node;
|
||||
struct cam_isp_tfe_in_port_info *in_port;
|
||||
uint32_t res_id;
|
||||
void *cdm_ops;
|
||||
enum cam_isp_hw_sync_mode sync_mode;
|
||||
bool camif_pd_enable;
|
||||
uint32_t dual_tfe_sync_sel_idx;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_acquire_args:
|
||||
*
|
||||
* @rsrc_type: Type of Resource (OUT/IN) to acquire
|
||||
* @tasklet: Tasklet to associate with this resource. This is
|
||||
* used to schedule bottom of IRQ events associated
|
||||
* with this resource.
|
||||
* @priv: Context data
|
||||
* @event_cb: Callback function to hw mgr in case of hw events
|
||||
* @tfe_out: Acquire args for TFE_OUT
|
||||
* @tfe_in: Acquire args for TFE_IN
|
||||
*/
|
||||
struct cam_tfe_acquire_args {
|
||||
enum cam_isp_resource_type rsrc_type;
|
||||
void *tasklet;
|
||||
void *priv;
|
||||
cam_hw_mgr_event_cb_func event_cb;
|
||||
union {
|
||||
struct cam_tfe_hw_tfe_out_acquire_args tfe_out;
|
||||
struct cam_tfe_hw_tfe_in_acquire_args tfe_in;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_clock_update_args:
|
||||
*
|
||||
* @node_res: Resource to get the time stamp
|
||||
* @clk_rate: Clock rate requested
|
||||
*/
|
||||
struct cam_tfe_clock_update_args {
|
||||
struct cam_isp_resource_node *node_res;
|
||||
uint64_t clk_rate;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_bw_update_args:
|
||||
*
|
||||
* @node_res: Resource to get the BW
|
||||
* @isp_vote: Vote info according to usage data (left/right/rdi)
|
||||
*/
|
||||
struct cam_tfe_bw_update_args {
|
||||
struct cam_isp_resource_node *node_res;
|
||||
struct cam_axi_vote isp_vote;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_dual_update_args:
|
||||
*
|
||||
* @Brief: update the dual isp striping configuration.
|
||||
*
|
||||
* @ split_id: spilt id to inform left or rifht
|
||||
* @ res: resource node
|
||||
* @ stripe_config: stripe configuration for port
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_dual_update_args {
|
||||
enum cam_isp_hw_split_id split_id;
|
||||
struct cam_isp_resource_node *res;
|
||||
struct cam_isp_tfe_dual_stripe_config *stripe_config;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_bw_control_args:
|
||||
*
|
||||
* @node_res: Resource to get the time stamp
|
||||
* @action: Bandwidth control action
|
||||
*/
|
||||
struct cam_tfe_bw_control_args {
|
||||
struct cam_isp_resource_node *node_res;
|
||||
enum cam_tfe_bw_control_action action;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_irq_evt_payload:
|
||||
*
|
||||
* @Brief: This structure is used to save payload for IRQ
|
||||
* related to TFE_TOP resources
|
||||
*
|
||||
* @list: list_head node for the payload
|
||||
* @core_index: Index of TFE HW that generated this IRQ event
|
||||
* @core_info: Private data of handler in bottom half context
|
||||
* @evt_id: IRQ event
|
||||
* @irq_reg_val: IRQ and Error register values, read when IRQ was
|
||||
* handled
|
||||
* @bus_irq_val Bus irq register status
|
||||
* @debug_status_0: Value of debug status_0 register at time of IRQ
|
||||
* @ccif_violation_status ccif violation status
|
||||
* @overflow_status bus overflow status
|
||||
* @image_size_violation_status image size violations status
|
||||
|
||||
* @error_type: Identify different errors
|
||||
* @enable_reg_dump: enable register dump on error
|
||||
* @ts: Timestamp
|
||||
*/
|
||||
struct cam_tfe_irq_evt_payload {
|
||||
struct list_head list;
|
||||
uint32_t core_index;
|
||||
void *core_info;
|
||||
uint32_t evt_id;
|
||||
uint32_t irq_reg_val[CAM_TFE_IRQ_REGISTERS_MAX];
|
||||
uint32_t bus_irq_val[CAM_TFE_BUS_IRQ_REGISTERS_MAX];
|
||||
uint32_t ccif_violation_status;
|
||||
uint32_t overflow_status;
|
||||
uint32_t image_size_violation_status;
|
||||
uint32_t debug_status_0;
|
||||
|
||||
uint32_t error_type;
|
||||
bool enable_reg_dump;
|
||||
struct cam_isp_timestamp ts;
|
||||
};
|
||||
|
||||
/*
|
||||
* cam_tfe_hw_init()
|
||||
*
|
||||
* @Brief: Initialize TFE HW device
|
||||
*
|
||||
* @tfe_hw: tfe_hw interface to fill in and return on
|
||||
* successful initialization
|
||||
* @hw_idx: Index of TFE HW
|
||||
*/
|
||||
int cam_tfe_hw_init(struct cam_hw_intf **tfe_hw, uint32_t hw_idx);
|
||||
|
||||
#endif /* _CAM_TFE_HW_INTF_H_ */
|
@@ -0,0 +1,74 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_HW_INTF_H_
|
||||
#define _CAM_TOP_TPG_HW_INTF_H_
|
||||
|
||||
#include "cam_isp_hw.h"
|
||||
#include "cam_hw_intf.h"
|
||||
|
||||
/* Max top tpg instance */
|
||||
#define CAM_TOP_TPG_HW_NUM_MAX 2
|
||||
/* Max supported number of DT for TPG */
|
||||
#define CAM_TOP_TPG_MAX_SUPPORTED_DT 4
|
||||
|
||||
/**
|
||||
* enum cam_top_tpg_id - top tpg hw instance id
|
||||
*/
|
||||
enum cam_top_tpg_id {
|
||||
CAM_TOP_TPG_ID_0,
|
||||
CAM_TOP_TPG_ID_1,
|
||||
CAM_TFE_TPG_ID_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_top_tpg_hw_caps- Get the top tpg hw capability
|
||||
* @major_version : Major version
|
||||
* @minor_version: Minor version
|
||||
* @version_incr: Version increment
|
||||
*
|
||||
*/
|
||||
struct cam_top_tpg_hw_caps {
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t version_incr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_hw_reserve_resource_args- hw reserve
|
||||
* @num_inport: number of inport
|
||||
* TPG support 4 dt types, each different dt comes in different
|
||||
* in port.
|
||||
* @in_port : Input port resource info structure pointer
|
||||
* @node_res : Reserved resource structure pointer
|
||||
*
|
||||
*/
|
||||
struct cam_top_tpg_hw_reserve_resource_args {
|
||||
uint32_t num_inport;
|
||||
struct cam_isp_tfe_in_port_info *in_port[CAM_TOP_TPG_MAX_SUPPORTED_DT];
|
||||
struct cam_isp_resource_node *node_res;
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_top_tpg_hw_init()
|
||||
*
|
||||
* @brief: Initialize function for the tpg hardware
|
||||
*
|
||||
* @top_tpg_hw: TPG hardware instance returned
|
||||
* @hw_idex: TPG hardware instance id
|
||||
*/
|
||||
int cam_top_tpg_hw_init(struct cam_hw_intf **top_tpg_hw,
|
||||
uint32_t hw_idx);
|
||||
|
||||
/*
|
||||
* struct cam_top_tpg_clock_update_args:
|
||||
*
|
||||
* @clk_rate: phy rate requested
|
||||
*/
|
||||
struct cam_top_tpg_clock_update_args {
|
||||
uint64_t clk_rate;
|
||||
};
|
||||
|
||||
#endif /* _CAM_TOP_TPG_HW_INTF_H_ */
|
15
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile
Normal file
15
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/
|
||||
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += cam_tfe_csid_dev.o cam_tfe_csid_soc.o cam_tfe_csid_core.o
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += cam_tfe_csid530.o
|
@@ -0,0 +1,51 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "cam_tfe_csid_core.h"
|
||||
#include "cam_tfe_csid530.h"
|
||||
#include "cam_tfe_csid_dev.h"
|
||||
|
||||
#define CAM_TFE_CSID_DRV_NAME "csid_530"
|
||||
#define CAM_TFE_CSID_VERSION_V530 0x50030000
|
||||
|
||||
static struct cam_tfe_csid_hw_info cam_tfe_csid530_hw_info = {
|
||||
.csid_reg = &cam_tfe_csid_530_reg_offset,
|
||||
.hw_dts_version = CAM_TFE_CSID_VERSION_V530,
|
||||
};
|
||||
|
||||
static const struct of_device_id cam_tfe_csid530_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,csid530",
|
||||
.data = &cam_tfe_csid530_hw_info,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, cam_tfe_csid530_dt_match);
|
||||
|
||||
static struct platform_driver cam_tfe_csid530_driver = {
|
||||
.probe = cam_tfe_csid_probe,
|
||||
.remove = cam_tfe_csid_remove,
|
||||
.driver = {
|
||||
.name = CAM_TFE_CSID_DRV_NAME,
|
||||
.of_match_table = cam_tfe_csid530_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
int cam_tfe_csid530_init_module(void)
|
||||
{
|
||||
return platform_driver_register(&cam_tfe_csid530_driver);
|
||||
}
|
||||
|
||||
void cam_tfe_csid530_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&cam_tfe_csid530_driver);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("CAM TFE_CSID530 driver");
|
||||
MODULE_LICENSE("GPL v2");
|
225
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h
Normal file
225
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h
Normal file
@@ -0,0 +1,225 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_CSID_530_H_
|
||||
#define _CAM_TFE_CSID_530_H_
|
||||
|
||||
#include "cam_tfe_csid_core.h"
|
||||
|
||||
static struct cam_tfe_csid_pxl_reg_offset cam_tfe_csid_530_ipp_reg_offset = {
|
||||
.csid_pxl_irq_status_addr = 0x30,
|
||||
.csid_pxl_irq_mask_addr = 0x34,
|
||||
.csid_pxl_irq_clear_addr = 0x38,
|
||||
.csid_pxl_irq_set_addr = 0x3c,
|
||||
|
||||
.csid_pxl_cfg0_addr = 0x200,
|
||||
.csid_pxl_cfg1_addr = 0x204,
|
||||
.csid_pxl_ctrl_addr = 0x208,
|
||||
.csid_pxl_hcrop_addr = 0x21c,
|
||||
.csid_pxl_vcrop_addr = 0x220,
|
||||
.csid_pxl_rst_strobes_addr = 0x240,
|
||||
.csid_pxl_status_addr = 0x254,
|
||||
.csid_pxl_misr_val_addr = 0x258,
|
||||
.csid_pxl_timestamp_curr0_sof_addr = 0x290,
|
||||
.csid_pxl_timestamp_curr1_sof_addr = 0x294,
|
||||
.csid_pxl_timestamp_perv0_sof_addr = 0x298,
|
||||
.csid_pxl_timestamp_perv1_sof_addr = 0x29c,
|
||||
.csid_pxl_timestamp_curr0_eof_addr = 0x2a0,
|
||||
.csid_pxl_timestamp_curr1_eof_addr = 0x2a4,
|
||||
.csid_pxl_timestamp_perv0_eof_addr = 0x2a8,
|
||||
.csid_pxl_timestamp_perv1_eof_addr = 0x2ac,
|
||||
.csid_pxl_err_recovery_cfg0_addr = 0x2d0,
|
||||
.csid_pxl_err_recovery_cfg1_addr = 0x2d4,
|
||||
.csid_pxl_err_recovery_cfg2_addr = 0x2d8,
|
||||
/* configurations */
|
||||
.pix_store_en_shift_val = 7,
|
||||
.early_eof_en_shift_val = 29,
|
||||
.halt_master_sel_shift = 4,
|
||||
.halt_mode_shift = 2,
|
||||
.halt_master_sel_master_val = 3,
|
||||
.halt_master_sel_slave_val = 0,
|
||||
};
|
||||
|
||||
static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_rdi_0_reg_offset = {
|
||||
.csid_rdi_irq_status_addr = 0x40,
|
||||
.csid_rdi_irq_mask_addr = 0x44,
|
||||
.csid_rdi_irq_clear_addr = 0x48,
|
||||
.csid_rdi_irq_set_addr = 0x4c,
|
||||
|
||||
.csid_rdi_cfg0_addr = 0x300,
|
||||
.csid_rdi_cfg1_addr = 0x304,
|
||||
.csid_rdi_ctrl_addr = 0x308,
|
||||
.csid_rdi_rst_strobes_addr = 0x340,
|
||||
.csid_rdi_status_addr = 0x350,
|
||||
.csid_rdi_misr_val0_addr = 0x354,
|
||||
.csid_rdi_misr_val1_addr = 0x358,
|
||||
.csid_rdi_timestamp_curr0_sof_addr = 0x390,
|
||||
.csid_rdi_timestamp_curr1_sof_addr = 0x394,
|
||||
.csid_rdi_timestamp_prev0_sof_addr = 0x398,
|
||||
.csid_rdi_timestamp_prev1_sof_addr = 0x39c,
|
||||
.csid_rdi_timestamp_curr0_eof_addr = 0x3a0,
|
||||
.csid_rdi_timestamp_curr1_eof_addr = 0x3a4,
|
||||
.csid_rdi_timestamp_prev0_eof_addr = 0x3a8,
|
||||
.csid_rdi_timestamp_prev1_eof_addr = 0x3ac,
|
||||
.csid_rdi_err_recovery_cfg0_addr = 0x3b0,
|
||||
.csid_rdi_err_recovery_cfg1_addr = 0x3b4,
|
||||
.csid_rdi_err_recovery_cfg2_addr = 0x3b8,
|
||||
.csid_rdi_byte_cntr_ping_addr = 0x3e0,
|
||||
.csid_rdi_byte_cntr_pong_addr = 0x3e4,
|
||||
};
|
||||
|
||||
static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_rdi_1_reg_offset = {
|
||||
.csid_rdi_irq_status_addr = 0x50,
|
||||
.csid_rdi_irq_mask_addr = 0x54,
|
||||
.csid_rdi_irq_clear_addr = 0x58,
|
||||
.csid_rdi_irq_set_addr = 0x5c,
|
||||
|
||||
.csid_rdi_cfg0_addr = 0x400,
|
||||
.csid_rdi_cfg1_addr = 0x404,
|
||||
.csid_rdi_ctrl_addr = 0x408,
|
||||
.csid_rdi_rst_strobes_addr = 0x440,
|
||||
.csid_rdi_status_addr = 0x450,
|
||||
.csid_rdi_misr_val0_addr = 0x454,
|
||||
.csid_rdi_misr_val1_addr = 0x458,
|
||||
.csid_rdi_timestamp_curr0_sof_addr = 0x490,
|
||||
.csid_rdi_timestamp_curr1_sof_addr = 0x494,
|
||||
.csid_rdi_timestamp_prev0_sof_addr = 0x498,
|
||||
.csid_rdi_timestamp_prev1_sof_addr = 0x49c,
|
||||
.csid_rdi_timestamp_curr0_eof_addr = 0x4a0,
|
||||
.csid_rdi_timestamp_curr1_eof_addr = 0x4a4,
|
||||
.csid_rdi_timestamp_prev0_eof_addr = 0x4a8,
|
||||
.csid_rdi_timestamp_prev1_eof_addr = 0x4ac,
|
||||
.csid_rdi_err_recovery_cfg0_addr = 0x4b0,
|
||||
.csid_rdi_err_recovery_cfg1_addr = 0x4b4,
|
||||
.csid_rdi_err_recovery_cfg2_addr = 0x4b8,
|
||||
.csid_rdi_byte_cntr_ping_addr = 0x4e0,
|
||||
.csid_rdi_byte_cntr_pong_addr = 0x4e4,
|
||||
};
|
||||
|
||||
static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_rdi_2_reg_offset = {
|
||||
.csid_rdi_irq_status_addr = 0x60,
|
||||
.csid_rdi_irq_mask_addr = 0x64,
|
||||
.csid_rdi_irq_clear_addr = 0x68,
|
||||
.csid_rdi_irq_set_addr = 0x6c,
|
||||
|
||||
.csid_rdi_cfg0_addr = 0x500,
|
||||
.csid_rdi_cfg1_addr = 0x504,
|
||||
.csid_rdi_ctrl_addr = 0x508,
|
||||
.csid_rdi_rst_strobes_addr = 0x540,
|
||||
.csid_rdi_status_addr = 0x550,
|
||||
.csid_rdi_misr_val0_addr = 0x554,
|
||||
.csid_rdi_misr_val1_addr = 0x558,
|
||||
.csid_rdi_timestamp_curr0_sof_addr = 0x590,
|
||||
.csid_rdi_timestamp_curr1_sof_addr = 0x594,
|
||||
.csid_rdi_timestamp_prev0_sof_addr = 0x598,
|
||||
.csid_rdi_timestamp_prev1_sof_addr = 0x59c,
|
||||
.csid_rdi_timestamp_curr0_eof_addr = 0x5a0,
|
||||
.csid_rdi_timestamp_curr1_eof_addr = 0x5a4,
|
||||
.csid_rdi_timestamp_prev0_eof_addr = 0x5a8,
|
||||
.csid_rdi_timestamp_prev1_eof_addr = 0x5ac,
|
||||
.csid_rdi_err_recovery_cfg0_addr = 0x5b0,
|
||||
.csid_rdi_err_recovery_cfg1_addr = 0x5b4,
|
||||
.csid_rdi_err_recovery_cfg2_addr = 0x5b8,
|
||||
.csid_rdi_byte_cntr_ping_addr = 0x5e0,
|
||||
.csid_rdi_byte_cntr_pong_addr = 0x5e4,
|
||||
};
|
||||
|
||||
static struct cam_tfe_csid_csi2_rx_reg_offset
|
||||
cam_tfe_csid_530_csi2_reg_offset = {
|
||||
.csid_csi2_rx_irq_status_addr = 0x20,
|
||||
.csid_csi2_rx_irq_mask_addr = 0x24,
|
||||
.csid_csi2_rx_irq_clear_addr = 0x28,
|
||||
.csid_csi2_rx_irq_set_addr = 0x2c,
|
||||
|
||||
/*CSI2 rx control */
|
||||
.csid_csi2_rx_cfg0_addr = 0x100,
|
||||
.csid_csi2_rx_cfg1_addr = 0x104,
|
||||
.csid_csi2_rx_capture_ctrl_addr = 0x108,
|
||||
.csid_csi2_rx_rst_strobes_addr = 0x110,
|
||||
.csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr = 0x120,
|
||||
.csid_csi2_rx_cap_unmap_long_pkt_hdr_1_addr = 0x124,
|
||||
.csid_csi2_rx_captured_short_pkt_0_addr = 0x128,
|
||||
.csid_csi2_rx_captured_short_pkt_1_addr = 0x12c,
|
||||
.csid_csi2_rx_captured_long_pkt_0_addr = 0x130,
|
||||
.csid_csi2_rx_captured_long_pkt_1_addr = 0x134,
|
||||
.csid_csi2_rx_captured_long_pkt_ftr_addr = 0x138,
|
||||
.csid_csi2_rx_captured_cphy_pkt_hdr_addr = 0x13c,
|
||||
.csid_csi2_rx_total_pkts_rcvd_addr = 0x160,
|
||||
.csid_csi2_rx_stats_ecc_addr = 0x164,
|
||||
.csid_csi2_rx_total_crc_err_addr = 0x168,
|
||||
|
||||
.csi2_rst_srb_all = 0x3FFF,
|
||||
.csi2_rst_done_shift_val = 27,
|
||||
.csi2_irq_mask_all = 0xFFFFFFF,
|
||||
.csi2_misr_enable_shift_val = 6,
|
||||
.csi2_capture_long_pkt_en_shift = 0,
|
||||
.csi2_capture_short_pkt_en_shift = 1,
|
||||
.csi2_capture_cphy_pkt_en_shift = 2,
|
||||
.csi2_capture_long_pkt_dt_shift = 4,
|
||||
.csi2_capture_long_pkt_vc_shift = 10,
|
||||
.csi2_capture_short_pkt_vc_shift = 12,
|
||||
.csi2_capture_cphy_pkt_dt_shift = 14,
|
||||
.csi2_capture_cphy_pkt_vc_shift = 20,
|
||||
.csi2_rx_phy_num_mask = 0x3,
|
||||
.csi2_rx_long_pkt_hdr_rst_stb_shift = 0x1,
|
||||
.csi2_rx_short_pkt_hdr_rst_stb_shift = 0x2,
|
||||
};
|
||||
|
||||
static struct cam_tfe_csid_common_reg_offset
|
||||
cam_tfe_csid_530_cmn_reg_offset = {
|
||||
.csid_hw_version_addr = 0x0,
|
||||
.csid_cfg0_addr = 0x4,
|
||||
.csid_ctrl_addr = 0x8,
|
||||
.csid_rst_strobes_addr = 0x10,
|
||||
|
||||
.csid_test_bus_ctrl_addr = 0x14,
|
||||
.csid_top_irq_status_addr = 0x70,
|
||||
.csid_top_irq_mask_addr = 0x74,
|
||||
.csid_top_irq_clear_addr = 0x78,
|
||||
.csid_top_irq_set_addr = 0x7c,
|
||||
.csid_irq_cmd_addr = 0x80,
|
||||
|
||||
/*configurations */
|
||||
.major_version = 5,
|
||||
.minor_version = 3,
|
||||
.version_incr = 0,
|
||||
.num_rdis = 3,
|
||||
.num_pix = 1,
|
||||
.csid_reg_rst_stb = 1,
|
||||
.csid_rst_stb = 0x1e,
|
||||
.csid_rst_stb_sw_all = 0x1f,
|
||||
.ipp_path_rst_stb_all = 0x17,
|
||||
.rdi_path_rst_stb_all = 0x97,
|
||||
.path_rst_done_shift_val = 1,
|
||||
.path_en_shift_val = 31,
|
||||
.dt_id_shift_val = 27,
|
||||
.vc_shift_val = 22,
|
||||
.dt_shift_val = 16,
|
||||
.fmt_shift_val = 12,
|
||||
.plain_fmt_shit_val = 10,
|
||||
.crop_v_en_shift_val = 6,
|
||||
.crop_h_en_shift_val = 5,
|
||||
.crop_shift = 16,
|
||||
.ipp_irq_mask_all = 0x3FFFF,
|
||||
.rdi_irq_mask_all = 0x3FFFF,
|
||||
.top_tfe2_pix_pipe_fuse_reg = 0xFE4,
|
||||
.top_tfe2_fuse_reg = 0xFE8,
|
||||
};
|
||||
|
||||
static struct cam_tfe_csid_reg_offset cam_tfe_csid_530_reg_offset = {
|
||||
.cmn_reg = &cam_tfe_csid_530_cmn_reg_offset,
|
||||
.csi2_reg = &cam_tfe_csid_530_csi2_reg_offset,
|
||||
.ipp_reg = &cam_tfe_csid_530_ipp_reg_offset,
|
||||
.rdi_reg = {
|
||||
&cam_tfe_csid_530_rdi_0_reg_offset,
|
||||
&cam_tfe_csid_530_rdi_1_reg_offset,
|
||||
&cam_tfe_csid_530_rdi_2_reg_offset,
|
||||
},
|
||||
};
|
||||
|
||||
int cam_tfe_csid530_init_module(void);
|
||||
void cam_tfe_csid530_exit_module(void);
|
||||
|
||||
#endif /*_CAM_TFE_CSID_530_H_ */
|
2824
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c
Normal file
2824
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,412 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_CSID_HW_H_
|
||||
#define _CAM_TFE_CSID_HW_H_
|
||||
|
||||
#include "cam_hw.h"
|
||||
#include "cam_tfe_csid_hw_intf.h"
|
||||
#include "cam_tfe_csid_soc.h"
|
||||
|
||||
#define CAM_TFE_CSID_CID_MAX 4
|
||||
|
||||
#define TFE_CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED BIT(0)
|
||||
#define TFE_CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED BIT(1)
|
||||
#define TFE_CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED BIT(2)
|
||||
#define TFE_CSID_CSI2_RX_INFO_PHY_DL3_EOT_CAPTURED BIT(3)
|
||||
#define TFE_CSID_CSI2_RX_INFO_PHY_DL0_SOT_CAPTURED BIT(4)
|
||||
#define TFE_CSID_CSI2_RX_INFO_PHY_DL1_SOT_CAPTURED BIT(5)
|
||||
#define TFE_CSID_CSI2_RX_INFO_PHY_DL2_SOT_CAPTURED BIT(6)
|
||||
#define TFE_CSID_CSI2_RX_INFO_PHY_DL3_SOT_CAPTURED BIT(7)
|
||||
#define TFE_CSID_CSI2_RX_INFO_LONG_PKT_CAPTURED BIT(8)
|
||||
#define TFE_CSID_CSI2_RX_INFO_SHORT_PKT_CAPTURED BIT(9)
|
||||
#define TFE_CSID_CSI2_RX_INFO_CPHY_PKT_HDR_CAPTURED BIT(10)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION BIT(11)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION BIT(12)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_CPHY_PH_CRC BIT(13)
|
||||
#define TFE_CSID_CSI2_RX_WARNING_ECC BIT(14)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW BIT(15)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW BIT(16)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW BIT(17)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW BIT(18)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_CRC BIT(19)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_ECC BIT(20)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_MMAPPED_VC_DT BIT(21)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_UNMAPPED_VC_DT BIT(22)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW BIT(23)
|
||||
#define TFE_CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME BIT(24)
|
||||
#define TFE_CSID_CSI2_RX_INFO_RST_DONE BIT(27)
|
||||
|
||||
#define TFE_CSID_PATH_INFO_RST_DONE BIT(1)
|
||||
#define TFE_CSID_PATH_ERROR_FIFO_OVERFLOW BIT(2)
|
||||
#define TFE_CSID_PATH_INFO_INPUT_EOF BIT(9)
|
||||
#define TFE_CSID_PATH_INFO_INPUT_EOL BIT(10)
|
||||
#define TFE_CSID_PATH_INFO_INPUT_SOL BIT(11)
|
||||
#define TFE_CSID_PATH_INFO_INPUT_SOF BIT(12)
|
||||
#define TFE_CSID_PATH_IPP_ERROR_CCIF_VIOLATION BIT(15)
|
||||
#define TFE_CSID_PATH_IPP_OVERFLOW_IRQ BIT(16)
|
||||
#define TFE_CSID_PATH_IPP_FRAME_DROP BIT(17)
|
||||
#define TFE_CSID_PATH_RDI_FRAME_DROP BIT(16)
|
||||
#define TFE_CSID_PATH_RDI_OVERFLOW_IRQ BIT(17)
|
||||
#define TFE_CSID_PATH_RDI_ERROR_CCIF_VIOLATION BIT(18)
|
||||
|
||||
/*
|
||||
* Debug values enable the corresponding interrupts and debug logs provide
|
||||
* necessary information
|
||||
*/
|
||||
#define TFE_CSID_DEBUG_ENABLE_SOF_IRQ BIT(0)
|
||||
#define TFE_CSID_DEBUG_ENABLE_EOF_IRQ BIT(1)
|
||||
#define TFE_CSID_DEBUG_ENABLE_SOT_IRQ BIT(2)
|
||||
#define TFE_CSID_DEBUG_ENABLE_EOT_IRQ BIT(3)
|
||||
#define TFE_CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE BIT(4)
|
||||
#define TFE_CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE BIT(5)
|
||||
#define TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE BIT(6)
|
||||
#define TFE_CSID_DEBUG_ENABLE_HBI_VBI_INFO BIT(7)
|
||||
#define TFE_CSID_DEBUG_DISABLE_EARLY_EOF BIT(8)
|
||||
|
||||
/* enum cam_csid_path_halt_mode select the path halt mode control */
|
||||
enum cam_tfe_csid_path_halt_mode {
|
||||
TFE_CSID_HALT_MODE_INTERNAL,
|
||||
TFE_CSID_HALT_MODE_GLOBAL,
|
||||
TFE_CSID_HALT_MODE_MASTER,
|
||||
TFE_CSID_HALT_MODE_SLAVE,
|
||||
};
|
||||
|
||||
/**
|
||||
*enum cam_csid_path_timestamp_stb_sel - select the sof/eof strobes used to
|
||||
* capture the timestamp
|
||||
*/
|
||||
enum cam_tfe_csid_path_timestamp_stb_sel {
|
||||
TFE_CSID_TIMESTAMP_STB_PRE_HALT,
|
||||
TFE_CSID_TIMESTAMP_STB_POST_HALT,
|
||||
TFE_CSID_TIMESTAMP_STB_POST_IRQ,
|
||||
TFE_CSID_TIMESTAMP_STB_MAX,
|
||||
};
|
||||
|
||||
struct cam_tfe_csid_pxl_reg_offset {
|
||||
/* Pxl path register offsets*/
|
||||
uint32_t csid_pxl_irq_status_addr;
|
||||
uint32_t csid_pxl_irq_mask_addr;
|
||||
uint32_t csid_pxl_irq_clear_addr;
|
||||
uint32_t csid_pxl_irq_set_addr;
|
||||
|
||||
uint32_t csid_pxl_cfg0_addr;
|
||||
uint32_t csid_pxl_cfg1_addr;
|
||||
uint32_t csid_pxl_ctrl_addr;
|
||||
uint32_t csid_pxl_hcrop_addr;
|
||||
uint32_t csid_pxl_vcrop_addr;
|
||||
uint32_t csid_pxl_rst_strobes_addr;
|
||||
uint32_t csid_pxl_status_addr;
|
||||
uint32_t csid_pxl_misr_val_addr;
|
||||
uint32_t csid_pxl_timestamp_curr0_sof_addr;
|
||||
uint32_t csid_pxl_timestamp_curr1_sof_addr;
|
||||
uint32_t csid_pxl_timestamp_perv0_sof_addr;
|
||||
uint32_t csid_pxl_timestamp_perv1_sof_addr;
|
||||
uint32_t csid_pxl_timestamp_curr0_eof_addr;
|
||||
uint32_t csid_pxl_timestamp_curr1_eof_addr;
|
||||
uint32_t csid_pxl_timestamp_perv0_eof_addr;
|
||||
uint32_t csid_pxl_timestamp_perv1_eof_addr;
|
||||
uint32_t csid_pxl_err_recovery_cfg0_addr;
|
||||
uint32_t csid_pxl_err_recovery_cfg1_addr;
|
||||
uint32_t csid_pxl_err_recovery_cfg2_addr;
|
||||
|
||||
/* configuration */
|
||||
uint32_t pix_store_en_shift_val;
|
||||
uint32_t early_eof_en_shift_val;
|
||||
uint32_t halt_master_sel_shift;
|
||||
uint32_t halt_mode_shift;
|
||||
uint32_t halt_master_sel_master_val;
|
||||
uint32_t halt_master_sel_slave_val;
|
||||
};
|
||||
|
||||
struct cam_tfe_csid_rdi_reg_offset {
|
||||
uint32_t csid_rdi_irq_status_addr;
|
||||
uint32_t csid_rdi_irq_mask_addr;
|
||||
uint32_t csid_rdi_irq_clear_addr;
|
||||
uint32_t csid_rdi_irq_set_addr;
|
||||
|
||||
/*RDI N register address */
|
||||
uint32_t csid_rdi_cfg0_addr;
|
||||
uint32_t csid_rdi_cfg1_addr;
|
||||
uint32_t csid_rdi_ctrl_addr;
|
||||
uint32_t csid_rdi_rst_strobes_addr;
|
||||
uint32_t csid_rdi_status_addr;
|
||||
uint32_t csid_rdi_misr_val0_addr;
|
||||
uint32_t csid_rdi_misr_val1_addr;
|
||||
uint32_t csid_rdi_timestamp_curr0_sof_addr;
|
||||
uint32_t csid_rdi_timestamp_curr1_sof_addr;
|
||||
uint32_t csid_rdi_timestamp_prev0_sof_addr;
|
||||
uint32_t csid_rdi_timestamp_prev1_sof_addr;
|
||||
uint32_t csid_rdi_timestamp_curr0_eof_addr;
|
||||
uint32_t csid_rdi_timestamp_curr1_eof_addr;
|
||||
uint32_t csid_rdi_timestamp_prev0_eof_addr;
|
||||
uint32_t csid_rdi_timestamp_prev1_eof_addr;
|
||||
uint32_t csid_rdi_err_recovery_cfg0_addr;
|
||||
uint32_t csid_rdi_err_recovery_cfg1_addr;
|
||||
uint32_t csid_rdi_err_recovery_cfg2_addr;
|
||||
uint32_t csid_rdi_byte_cntr_ping_addr;
|
||||
uint32_t csid_rdi_byte_cntr_pong_addr;
|
||||
|
||||
/* configuration */
|
||||
uint32_t packing_format;
|
||||
};
|
||||
|
||||
struct cam_tfe_csid_csi2_rx_reg_offset {
|
||||
uint32_t csid_csi2_rx_irq_status_addr;
|
||||
uint32_t csid_csi2_rx_irq_mask_addr;
|
||||
uint32_t csid_csi2_rx_irq_clear_addr;
|
||||
uint32_t csid_csi2_rx_irq_set_addr;
|
||||
uint32_t csid_csi2_rx_cfg0_addr;
|
||||
uint32_t csid_csi2_rx_cfg1_addr;
|
||||
uint32_t csid_csi2_rx_capture_ctrl_addr;
|
||||
uint32_t csid_csi2_rx_rst_strobes_addr;
|
||||
uint32_t csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr;
|
||||
uint32_t csid_csi2_rx_cap_unmap_long_pkt_hdr_1_addr;
|
||||
uint32_t csid_csi2_rx_captured_short_pkt_0_addr;
|
||||
uint32_t csid_csi2_rx_captured_short_pkt_1_addr;
|
||||
uint32_t csid_csi2_rx_captured_long_pkt_0_addr;
|
||||
uint32_t csid_csi2_rx_captured_long_pkt_1_addr;
|
||||
uint32_t csid_csi2_rx_captured_long_pkt_ftr_addr;
|
||||
uint32_t csid_csi2_rx_captured_cphy_pkt_hdr_addr;
|
||||
uint32_t csid_csi2_rx_total_pkts_rcvd_addr;
|
||||
uint32_t csid_csi2_rx_stats_ecc_addr; //no
|
||||
uint32_t csid_csi2_rx_total_crc_err_addr;
|
||||
|
||||
/*configurations */
|
||||
uint32_t csi2_rst_srb_all;
|
||||
uint32_t csi2_rst_done_shift_val;
|
||||
uint32_t csi2_irq_mask_all;
|
||||
uint32_t csi2_misr_enable_shift_val;
|
||||
uint32_t csi2_vc_mode_shift_val;
|
||||
uint32_t csi2_capture_long_pkt_en_shift;
|
||||
uint32_t csi2_capture_short_pkt_en_shift;
|
||||
uint32_t csi2_capture_cphy_pkt_en_shift;
|
||||
uint32_t csi2_capture_long_pkt_dt_shift;
|
||||
uint32_t csi2_capture_long_pkt_vc_shift;
|
||||
uint32_t csi2_capture_short_pkt_vc_shift;
|
||||
uint32_t csi2_capture_cphy_pkt_dt_shift;
|
||||
uint32_t csi2_capture_cphy_pkt_vc_shift;
|
||||
uint32_t csi2_rx_phy_num_mask;
|
||||
uint32_t csi2_rx_long_pkt_hdr_rst_stb_shift;
|
||||
uint32_t csi2_rx_short_pkt_hdr_rst_stb_shift;
|
||||
};
|
||||
|
||||
struct cam_tfe_csid_common_reg_offset {
|
||||
/* MIPI CSID registers */
|
||||
uint32_t csid_hw_version_addr;
|
||||
uint32_t csid_cfg0_addr;
|
||||
uint32_t csid_ctrl_addr;
|
||||
uint32_t csid_rst_strobes_addr;
|
||||
|
||||
uint32_t csid_test_bus_ctrl_addr;
|
||||
uint32_t csid_top_irq_status_addr;
|
||||
uint32_t csid_top_irq_mask_addr;
|
||||
uint32_t csid_top_irq_clear_addr;
|
||||
uint32_t csid_top_irq_set_addr;
|
||||
uint32_t csid_irq_cmd_addr;
|
||||
|
||||
/*configurations */
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t version_incr;
|
||||
uint32_t num_rdis;
|
||||
uint32_t num_pix;
|
||||
uint32_t csid_reg_rst_stb;
|
||||
uint32_t csid_rst_stb;
|
||||
uint32_t csid_rst_stb_sw_all;
|
||||
uint32_t ipp_path_rst_stb_all;
|
||||
uint32_t rdi_path_rst_stb_all;
|
||||
uint32_t path_rst_done_shift_val;
|
||||
uint32_t path_en_shift_val;
|
||||
uint32_t dt_id_shift_val;
|
||||
uint32_t vc_shift_val;
|
||||
uint32_t dt_shift_val;
|
||||
uint32_t fmt_shift_val;
|
||||
uint32_t plain_fmt_shit_val;
|
||||
uint32_t crop_v_en_shift_val;
|
||||
uint32_t crop_h_en_shift_val;
|
||||
uint32_t crop_shift;
|
||||
uint32_t ipp_irq_mask_all;
|
||||
uint32_t rdi_irq_mask_all;
|
||||
uint32_t top_tfe2_pix_pipe_fuse_reg;
|
||||
uint32_t top_tfe2_fuse_reg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_reg_offset- CSID instance register info
|
||||
*
|
||||
* @cmn_reg: csid common registers info
|
||||
* @ipp_reg: ipp register offset information
|
||||
* @ppp_reg: ppp register offset information
|
||||
* @rdi_reg: rdi register offset information
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_reg_offset {
|
||||
const struct cam_tfe_csid_common_reg_offset *cmn_reg;
|
||||
const struct cam_tfe_csid_csi2_rx_reg_offset *csi2_reg;
|
||||
const struct cam_tfe_csid_pxl_reg_offset *ipp_reg;
|
||||
const struct cam_tfe_csid_rdi_reg_offset *rdi_reg[CAM_TFE_CSID_RDI_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_hw_info- CSID HW info
|
||||
*
|
||||
* @csid_reg: csid register offsets
|
||||
* @hw_dts_version: HW DTS version
|
||||
* @csid_max_clk: maximim csid clock
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_hw_info {
|
||||
const struct cam_tfe_csid_reg_offset *csid_reg;
|
||||
uint32_t hw_dts_version;
|
||||
uint32_t csid_max_clk;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_csi2_rx_cfg- csid csi2 rx configuration data
|
||||
* @phy_sel: input resource type for sensor only
|
||||
* @lane_type: lane type: c-phy or d-phy
|
||||
* @lane_num : active lane number
|
||||
* @lane_cfg: lane configurations: 4 bits per lane
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_csi2_rx_cfg {
|
||||
uint32_t phy_sel;
|
||||
uint32_t lane_type;
|
||||
uint32_t lane_num;
|
||||
uint32_t lane_cfg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_cid_data- cid configuration private data
|
||||
*
|
||||
* @vc: Virtual channel
|
||||
* @dt: Data type
|
||||
* @cnt: Cid resource reference count.
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_cid_data {
|
||||
uint32_t vc;
|
||||
uint32_t dt;
|
||||
uint32_t cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_path_cfg- csid path configuration details. It is stored
|
||||
* as private data for IPP/ RDI paths
|
||||
* @vc : Virtual channel number
|
||||
* @dt : Data type number
|
||||
* @cid cid number, it is same as DT_ID number in HW
|
||||
* @in_format: input decode format
|
||||
* @out_format: output format
|
||||
* @crop_enable: crop is enable or disabled, if enabled
|
||||
* then remaining parameters are valid.
|
||||
* @start_pixel: start pixel
|
||||
* @end_pixel: end_pixel
|
||||
* @width: width
|
||||
* @start_line: start line
|
||||
* @end_line: end_line
|
||||
* @height: heigth
|
||||
* @sync_mode: Applicable for IPP/RDI path reservation
|
||||
* Reserving the path for master IPP or slave IPP
|
||||
* master (set value 1), Slave ( set value 2)
|
||||
* for RDI, set mode to none
|
||||
* @master_idx: For Slave reservation, Give master TFE instance Index.
|
||||
* Slave will synchronize with master Start and stop operations
|
||||
* @clk_rate Clock rate
|
||||
* @sensor_width Sensor width in pixel
|
||||
* @sensor_height Sensor height in pixel
|
||||
* @sensor_fps Sensor fps
|
||||
* @sensor_hbi Sensor horizontal blanking interval
|
||||
* @sensor_vbi Sensor vertical blanking interval
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_path_cfg {
|
||||
uint32_t vc;
|
||||
uint32_t dt;
|
||||
uint32_t cid;
|
||||
uint32_t in_format;
|
||||
uint32_t out_format;
|
||||
bool crop_enable;
|
||||
uint32_t start_pixel;
|
||||
uint32_t end_pixel;
|
||||
uint32_t width;
|
||||
uint32_t start_line;
|
||||
uint32_t end_line;
|
||||
uint32_t height;
|
||||
enum cam_isp_hw_sync_mode sync_mode;
|
||||
uint32_t master_idx;
|
||||
uint64_t clk_rate;
|
||||
uint32_t sensor_width;
|
||||
uint32_t sensor_height;
|
||||
uint32_t sensor_fps;
|
||||
uint32_t sensor_hbi;
|
||||
uint32_t sensor_vbi;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_hw- csid hw device resources data
|
||||
*
|
||||
* @hw_intf: contain the csid hw interface information
|
||||
* @hw_info: csid hw device information
|
||||
* @csid_info: csid hw specific information
|
||||
* @in_res_id: csid in resource type
|
||||
* @csi2_rx_cfg: csi2 rx decoder configuration for csid
|
||||
* @csi2_rx_reserve_cnt: csi2 reservations count value
|
||||
* @ipp_res: image pixel path resource
|
||||
* @rdi_res: raw dump image path resources
|
||||
* @cid_res: cid resources values
|
||||
* @csid_top_reset_complete: csid top reset completion
|
||||
* @csid_csi2_reset_complete: csi2 reset completion
|
||||
* @csid_ipp_reset_complete: ipp reset completion
|
||||
* @csid_ppp_complete: ppp reset completion
|
||||
* @csid_rdin_reset_complete: rdi n completion
|
||||
* @csid_debug: csid debug information to enable the SOT, EOT,
|
||||
* SOF, EOF, measure etc in the csid hw
|
||||
* @clk_rate Clock rate
|
||||
* @sof_irq_triggered: Flag is set on receiving event to enable sof irq
|
||||
* incase of SOF freeze.
|
||||
* @irq_debug_cnt: Counter to track sof irq's when above flag is set.
|
||||
* @error_irq_count Error IRQ count, if continuous error irq comes
|
||||
* need to stop the CSID and mask interrupts.
|
||||
* @device_enabled Device enabled will set once CSID powered on and
|
||||
* initial configuration are done.
|
||||
* @lock_state csid spin lock
|
||||
* @event_cb: Callback function to hw mgr in case of hw events
|
||||
* @event_cb_priv: Context data
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_hw {
|
||||
struct cam_hw_intf *hw_intf;
|
||||
struct cam_hw_info *hw_info;
|
||||
struct cam_tfe_csid_hw_info *csid_info;
|
||||
uint32_t in_res_id;
|
||||
struct cam_tfe_csid_csi2_rx_cfg csi2_rx_cfg;
|
||||
uint32_t csi2_reserve_cnt;
|
||||
uint32_t pxl_pipe_enable;
|
||||
struct cam_isp_resource_node ipp_res;
|
||||
struct cam_isp_resource_node rdi_res[CAM_TFE_CSID_RDI_MAX];
|
||||
struct cam_tfe_csid_cid_data cid_res[CAM_TFE_CSID_CID_MAX];
|
||||
struct completion csid_top_complete;
|
||||
struct completion csid_csi2_complete;
|
||||
struct completion csid_ipp_complete;
|
||||
struct completion csid_rdin_complete[CAM_TFE_CSID_RDI_MAX];
|
||||
uint64_t csid_debug;
|
||||
uint64_t clk_rate;
|
||||
bool sof_irq_triggered;
|
||||
uint32_t irq_debug_cnt;
|
||||
uint32_t error_irq_count;
|
||||
uint32_t device_enabled;
|
||||
spinlock_t spin_lock;
|
||||
cam_hw_mgr_event_cb_func event_cb;
|
||||
void *event_cb_priv;
|
||||
};
|
||||
|
||||
int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
|
||||
uint32_t csid_idx);
|
||||
|
||||
int cam_tfe_csid_hw_deinit(struct cam_tfe_csid_hw *tfe_csid_hw);
|
||||
|
||||
#endif /* _CAM_TFE_CSID_HW_H_ */
|
139
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c
Normal file
139
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.c
Normal file
@@ -0,0 +1,139 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_device.h>
|
||||
#include "cam_tfe_csid_core.h"
|
||||
#include "cam_tfe_csid_dev.h"
|
||||
#include "cam_tfe_csid_hw_intf.h"
|
||||
#include "cam_debug_util.h"
|
||||
|
||||
static struct cam_hw_intf *cam_tfe_csid_hw_list[CAM_TFE_CSID_HW_NUM_MAX] = {
|
||||
0, 0, 0};
|
||||
|
||||
static char csid_dev_name[8];
|
||||
|
||||
int cam_tfe_csid_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
struct cam_hw_intf *csid_hw_intf;
|
||||
struct cam_hw_info *csid_hw_info;
|
||||
struct cam_tfe_csid_hw *csid_dev = NULL;
|
||||
const struct of_device_id *match_dev = NULL;
|
||||
struct cam_tfe_csid_hw_info *csid_hw_data = NULL;
|
||||
uint32_t csid_dev_idx;
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_ISP, "probe called");
|
||||
|
||||
csid_hw_intf = kzalloc(sizeof(*csid_hw_intf), GFP_KERNEL);
|
||||
if (!csid_hw_intf) {
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
csid_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||
if (!csid_hw_info) {
|
||||
rc = -ENOMEM;
|
||||
goto free_hw_intf;
|
||||
}
|
||||
|
||||
csid_dev = kzalloc(sizeof(struct cam_tfe_csid_hw), GFP_KERNEL);
|
||||
if (!csid_dev) {
|
||||
rc = -ENOMEM;
|
||||
goto free_hw_info;
|
||||
}
|
||||
|
||||
/* get tfe csid hw index */
|
||||
of_property_read_u32(pdev->dev.of_node, "cell-index", &csid_dev_idx);
|
||||
/* get tfe csid hw information */
|
||||
match_dev = of_match_device(pdev->dev.driver->of_match_table,
|
||||
&pdev->dev);
|
||||
if (!match_dev) {
|
||||
CAM_ERR(CAM_ISP, "No matching table for the tfe csid hw");
|
||||
rc = -EINVAL;
|
||||
goto free_dev;
|
||||
}
|
||||
|
||||
memset(csid_dev_name, 0, sizeof(csid_dev_name));
|
||||
snprintf(csid_dev_name, sizeof(csid_dev_name),
|
||||
"csid%1u", csid_dev_idx);
|
||||
|
||||
csid_hw_intf->hw_idx = csid_dev_idx;
|
||||
csid_hw_intf->hw_type = CAM_ISP_HW_TYPE_TFE_CSID;
|
||||
csid_hw_intf->hw_priv = csid_hw_info;
|
||||
|
||||
csid_hw_info->core_info = csid_dev;
|
||||
csid_hw_info->soc_info.pdev = pdev;
|
||||
csid_hw_info->soc_info.dev = &pdev->dev;
|
||||
csid_hw_info->soc_info.dev_name = csid_dev_name;
|
||||
csid_hw_info->soc_info.index = csid_dev_idx;
|
||||
|
||||
csid_hw_data = (struct cam_tfe_csid_hw_info *)match_dev->data;
|
||||
/* need to setup the pdev before call the tfe hw probe init */
|
||||
csid_dev->csid_info = csid_hw_data;
|
||||
|
||||
rc = cam_tfe_csid_hw_probe_init(csid_hw_intf, csid_dev_idx);
|
||||
if (rc)
|
||||
goto free_dev;
|
||||
|
||||
platform_set_drvdata(pdev, csid_dev);
|
||||
CAM_DBG(CAM_ISP, "CSID:%d probe successful",
|
||||
csid_hw_intf->hw_idx);
|
||||
|
||||
if (csid_hw_intf->hw_idx < CAM_TFE_CSID_HW_NUM_MAX)
|
||||
cam_tfe_csid_hw_list[csid_hw_intf->hw_idx] = csid_hw_intf;
|
||||
else
|
||||
goto free_dev;
|
||||
|
||||
return 0;
|
||||
|
||||
free_dev:
|
||||
kfree(csid_dev);
|
||||
free_hw_info:
|
||||
kfree(csid_hw_info);
|
||||
free_hw_intf:
|
||||
kfree(csid_hw_intf);
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_csid_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cam_tfe_csid_hw *csid_dev = NULL;
|
||||
struct cam_hw_intf *csid_hw_intf;
|
||||
struct cam_hw_info *csid_hw_info;
|
||||
|
||||
csid_dev = (struct cam_tfe_csid_hw *)platform_get_drvdata(pdev);
|
||||
csid_hw_intf = csid_dev->hw_intf;
|
||||
csid_hw_info = csid_dev->hw_info;
|
||||
|
||||
CAM_DBG(CAM_ISP, "CSID:%d remove",
|
||||
csid_dev->hw_intf->hw_idx);
|
||||
|
||||
cam_tfe_csid_hw_deinit(csid_dev);
|
||||
|
||||
/*release the csid device memory */
|
||||
kfree(csid_dev);
|
||||
kfree(csid_hw_info);
|
||||
kfree(csid_hw_intf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_tfe_csid_hw_init(struct cam_hw_intf **tfe_csid_hw,
|
||||
uint32_t hw_idx)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (cam_tfe_csid_hw_list[hw_idx]) {
|
||||
*tfe_csid_hw = cam_tfe_csid_hw_list[hw_idx];
|
||||
} else {
|
||||
*tfe_csid_hw = NULL;
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_CSID_DEV_H_
|
||||
#define _CAM_TFE_CSID_DEV_H_
|
||||
|
||||
#include "cam_isp_hw.h"
|
||||
|
||||
irqreturn_t cam_tfe_csid_irq(int irq_num, void *data);
|
||||
|
||||
int cam_tfe_csid_probe(struct platform_device *pdev);
|
||||
int cam_tfe_csid_remove(struct platform_device *pdev);
|
||||
|
||||
#endif /*_CAM_TFE_CSID_DEV_H_ */
|
209
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.c
Normal file
209
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.c
Normal file
@@ -0,0 +1,209 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#include <linux/slab.h>
|
||||
#include "cam_tfe_csid_soc.h"
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cam_debug_util.h"
|
||||
|
||||
|
||||
int cam_tfe_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
irq_handler_t csid_irq_handler, void *irq_data)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_cpas_register_params cpas_register_param;
|
||||
struct cam_tfe_csid_soc_private *soc_private;
|
||||
|
||||
soc_private = kzalloc(sizeof(struct cam_tfe_csid_soc_private),
|
||||
GFP_KERNEL);
|
||||
if (!soc_private)
|
||||
return -ENOMEM;
|
||||
|
||||
soc_info->soc_private = soc_private;
|
||||
|
||||
|
||||
rc = cam_soc_util_get_dt_properties(soc_info);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Need to see if we want post process the clock list */
|
||||
rc = cam_soc_util_request_platform_resource(soc_info, csid_irq_handler,
|
||||
irq_data);
|
||||
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_ISP,
|
||||
"Error Request platform resources failed rc=%d", rc);
|
||||
goto free_soc_private;
|
||||
}
|
||||
|
||||
memset(&cpas_register_param, 0, sizeof(cpas_register_param));
|
||||
strlcpy(cpas_register_param.identifier, "csid",
|
||||
CAM_HW_IDENTIFIER_LENGTH);
|
||||
cpas_register_param.cell_index = soc_info->index;
|
||||
cpas_register_param.dev = soc_info->dev;
|
||||
rc = cam_cpas_register_client(&cpas_register_param);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
|
||||
goto release_soc;
|
||||
} else {
|
||||
soc_private->cpas_handle = cpas_register_param.client_handle;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
release_soc:
|
||||
cam_soc_util_release_platform_resource(soc_info);
|
||||
free_soc_private:
|
||||
kfree(soc_private);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_csid_deinit_soc_resources(
|
||||
struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_csid_soc_private *soc_private;
|
||||
|
||||
soc_private = soc_info->soc_private;
|
||||
if (!soc_private) {
|
||||
CAM_ERR(CAM_ISP, "Error soc_private NULL");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = cam_cpas_unregister_client(soc_private->cpas_handle);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc);
|
||||
|
||||
rc = cam_soc_util_release_platform_resource(soc_info);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_csid_enable_soc_resources(
|
||||
struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_csid_soc_private *soc_private;
|
||||
struct cam_ahb_vote ahb_vote;
|
||||
struct cam_axi_vote axi_vote = {0};
|
||||
|
||||
soc_private = soc_info->soc_private;
|
||||
|
||||
ahb_vote.type = CAM_VOTE_ABSOLUTE;
|
||||
ahb_vote.vote.level = CAM_SVS_VOTE;
|
||||
axi_vote.num_paths = 1;
|
||||
axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL;
|
||||
axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE;
|
||||
|
||||
axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW;
|
||||
axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW;
|
||||
axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW;
|
||||
|
||||
CAM_DBG(CAM_ISP, "csid camnoc_bw:%lld mnoc_ab_bw:%lld mnoc_ib_bw:%lld ",
|
||||
axi_vote.axi_path[0].camnoc_bw,
|
||||
axi_vote.axi_path[0].mnoc_ab_bw,
|
||||
axi_vote.axi_path[0].mnoc_ib_bw);
|
||||
|
||||
rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Error CPAS start failed");
|
||||
rc = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_enable_platform_resource(soc_info, true,
|
||||
clk_level, true);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "enable platform failed");
|
||||
goto stop_cpas;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
stop_cpas:
|
||||
cam_cpas_stop(soc_private->cpas_handle);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_csid_disable_soc_resources(struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_csid_soc_private *soc_private;
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_ISP, "Error Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
soc_private = soc_info->soc_private;
|
||||
|
||||
rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "Disable platform failed");
|
||||
|
||||
rc = cam_cpas_stop(soc_private->cpas_handle);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Error CPAS stop failed rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_csid_enable_tfe_force_clock_on(struct cam_hw_soc_info *soc_info,
|
||||
uint32_t cpas_tfe_base_offset)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_csid_soc_private *soc_private;
|
||||
uint32_t cpass_tfe_force_clk_offset;
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_ISP, "Error Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_private = soc_info->soc_private;
|
||||
cpass_tfe_force_clk_offset =
|
||||
cpas_tfe_base_offset + (0x4 * soc_info->index);
|
||||
rc = cam_cpas_reg_write(soc_private->cpas_handle, CAM_CPAS_REG_CPASTOP,
|
||||
cpass_tfe_force_clk_offset, 1, 1);
|
||||
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "CPASS set TFE:%d Force clock On failed",
|
||||
soc_info->index);
|
||||
else
|
||||
CAM_DBG(CAM_ISP, "CPASS set TFE:%d Force clock On",
|
||||
soc_info->index);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_csid_disable_tfe_force_clock_on(struct cam_hw_soc_info *soc_info,
|
||||
uint32_t cpas_tfe_base_offset)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_csid_soc_private *soc_private;
|
||||
uint32_t cpass_tfe_force_clk_offset;
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_ISP, "Error Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_private = soc_info->soc_private;
|
||||
cpass_tfe_force_clk_offset =
|
||||
cpas_tfe_base_offset + (0x4 * soc_info->index);
|
||||
rc = cam_cpas_reg_write(soc_private->cpas_handle, CAM_CPAS_REG_CPASTOP,
|
||||
cpass_tfe_force_clk_offset, 1, 0);
|
||||
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "CPASS set TFE:%d Force clock Off failed",
|
||||
soc_info->index);
|
||||
else
|
||||
CAM_DBG(CAM_ISP, "CPASS set TFE:%d Force clock off",
|
||||
soc_info->index);
|
||||
|
||||
return rc;
|
||||
}
|
119
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.h
Normal file
119
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_CSID_SOC_H_
|
||||
#define _CAM_TFE_CSID_SOC_H_
|
||||
|
||||
#include "cam_isp_hw.h"
|
||||
|
||||
/*
|
||||
* struct cam_csid_soc_private:
|
||||
*
|
||||
* @Brief: Private SOC data specific to CSID HW Driver
|
||||
*
|
||||
* @cpas_handle: Handle returned on registering with CPAS driver.
|
||||
* This handle is used for all further interface
|
||||
* with CPAS.
|
||||
*/
|
||||
struct cam_tfe_csid_soc_private {
|
||||
uint32_t cpas_handle;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct csid_device_soc_info - CSID SOC info object
|
||||
*
|
||||
* @csi_vdd_voltage: Csi vdd voltage value
|
||||
*
|
||||
*/
|
||||
struct cam_tfe_csid_device_soc_info {
|
||||
int csi_vdd_voltage;
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_tfe_csid_init_soc_resources()
|
||||
*
|
||||
* @brief: Csid initialization function for the soc info
|
||||
*
|
||||
* @soc_info: Soc info structure pointer
|
||||
* @csid_irq_handler: Irq handler function to be registered
|
||||
* @irq_data: Irq data for the callback function
|
||||
*
|
||||
*/
|
||||
int cam_tfe_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
irq_handler_t csid_irq_handler, void *irq_data);
|
||||
|
||||
|
||||
/**
|
||||
* cam_tfe_csid_deinit_soc_resources()
|
||||
*
|
||||
* @brief: Csid de initialization function for the soc info
|
||||
*
|
||||
* @soc_info: Soc info structure pointer
|
||||
*
|
||||
*/
|
||||
int cam_tfe_csid_deinit_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
/**
|
||||
* cam_tfe_csid_enable_soc_resources()
|
||||
*
|
||||
* @brief: Csid soc resource enable function
|
||||
*
|
||||
* @soc_info: Soc info structure pointer
|
||||
* @clk_lvl: Vote level to start with
|
||||
*
|
||||
*/
|
||||
int cam_tfe_csid_enable_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
uint32_t clk_lvl);
|
||||
|
||||
/**
|
||||
* cam_tfe_csid_disable_soc_resources()
|
||||
*
|
||||
* @brief: Csid soc resource disable function
|
||||
*
|
||||
* @soc_info: Soc info structure pointer
|
||||
*
|
||||
*/
|
||||
int cam_tfe_csid_disable_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
/**
|
||||
* cam_tfe_csid_enable_tfe_force_clock()
|
||||
*
|
||||
* @brief: If csid testgen used for dual isp case, before
|
||||
* starting csid test gen, enable tfe force clock on
|
||||
* through cpas
|
||||
*
|
||||
* @soc_info: Soc info structure pointer
|
||||
* @cpas_tfe_base_offset: Cpas tfe force clock base reg offset value
|
||||
*
|
||||
*/
|
||||
int cam_tfe_csid_enable_tfe_force_clock_on(struct cam_hw_soc_info *soc_info,
|
||||
uint32_t cpas_tfe_base_offset);
|
||||
|
||||
/**
|
||||
* cam_tfe_csid_disable_tfe_force_clock_on()
|
||||
*
|
||||
* @brief: Disable the TFE force clock on after dual ISP
|
||||
* CSID test gen stop
|
||||
*
|
||||
* @soc_info: Soc info structure pointer
|
||||
* @cpas_tfe_base_offset: Cpas tfe force clock base reg offset value
|
||||
*
|
||||
*/
|
||||
int cam_tfe_csid_disable_tfe_force_clock_on(struct cam_hw_soc_info *soc_info,
|
||||
uint32_t cpas_tfe_base_offset);
|
||||
|
||||
/**
|
||||
* cam_tfe_csid_get_vote_level()
|
||||
*
|
||||
* @brief: Get the vote level from clock rate
|
||||
*
|
||||
* @soc_info: Soc info structure pointer
|
||||
* @clock_rate Clock rate
|
||||
*
|
||||
*/
|
||||
uint32_t cam_tfe_csid_get_vote_level(struct cam_hw_soc_info *soc_info,
|
||||
uint64_t clock_rate);
|
||||
|
||||
#endif /* _CAM_TFE_CSID_SOC_H_ */
|
13
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile
Normal file
13
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller
|
||||
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += cam_tfe_soc.o cam_tfe_dev.o cam_tfe_core.o cam_tfe_bus.o cam_tfe.o
|
42
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c
Normal file
42
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe.c
Normal file
@@ -0,0 +1,42 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "cam_tfe530.h"
|
||||
#include "cam_tfe_hw_intf.h"
|
||||
#include "cam_tfe_core.h"
|
||||
#include "cam_tfe_dev.h"
|
||||
|
||||
static const struct of_device_id cam_tfe_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,tfe530",
|
||||
.data = &cam_tfe530,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cam_tfe_dt_match);
|
||||
|
||||
static struct platform_driver cam_tfe_driver = {
|
||||
.probe = cam_tfe_probe,
|
||||
.remove = cam_tfe_remove,
|
||||
.driver = {
|
||||
.name = "cam_tfe",
|
||||
.of_match_table = cam_tfe_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
int cam_tfe_init_module(void)
|
||||
{
|
||||
return platform_driver_register(&cam_tfe_driver);
|
||||
}
|
||||
|
||||
void cam_tfe_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&cam_tfe_driver);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("CAM TFE driver");
|
||||
MODULE_LICENSE("GPL v2");
|
813
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h
Normal file
813
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h
Normal file
@@ -0,0 +1,813 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CAM_TFE530_H_
|
||||
#define _CAM_TFE530_H_
|
||||
#include "cam_tfe_core.h"
|
||||
#include "cam_tfe_bus.h"
|
||||
|
||||
|
||||
static struct cam_tfe_top_reg_offset_common tfe530_top_commong_reg = {
|
||||
.hw_version = 0x00001000,
|
||||
.hw_capability = 0x00001004,
|
||||
.lens_feature = 0x00001008,
|
||||
.stats_feature = 0x0000100C,
|
||||
.zoom_feature = 0x00001010,
|
||||
.global_reset_cmd = 0x00001014,
|
||||
.core_cgc_ctrl = 0x00001018,
|
||||
.ahb_cgc_ctrl = 0x0000101C,
|
||||
.core_cfg_0 = 0x00001024,
|
||||
.core_cfg_1 = 0x00001028,
|
||||
.reg_update_cmd = 0x0000102C,
|
||||
.diag_config = 0x00001060,
|
||||
.diag_sensor_status_0 = 0x00001064,
|
||||
.diag_sensor_status_1 = 0x00001068,
|
||||
.diag_sensor_frame_cnt_status = 0x0000106C,
|
||||
.violation_status = 0x00001070,
|
||||
.stats_throttle_cnt_cfg_0 = 0x00001074,
|
||||
.stats_throttle_cnt_cfg_1 = 0x00001078,
|
||||
.debug_0 = 0x000010A0,
|
||||
.debug_1 = 0x000010A4,
|
||||
.debug_2 = 0x000010A8,
|
||||
.debug_3 = 0x000010AC,
|
||||
.debug_cfg = 0x000010DC,
|
||||
.perf_cnt_cfg = 0x000010E0,
|
||||
.perf_pixel_count = 0x000010E4,
|
||||
.perf_line_count = 0x000010E8,
|
||||
.perf_stall_count = 0x000010EC,
|
||||
.perf_always_count = 0x000010F0,
|
||||
.perf_count_status = 0x000010F4,
|
||||
};
|
||||
|
||||
static struct cam_tfe_camif_reg tfe530_camif_reg = {
|
||||
.hw_version = 0x00001200,
|
||||
.hw_status = 0x00001204,
|
||||
.module_cfg = 0x00001260,
|
||||
.pdaf_raw_crop_width_cfg = 0x00001268,
|
||||
.pdaf_raw_crop_height_cfg = 0x0000126C,
|
||||
.line_skip_pattern = 0x00001270,
|
||||
.pixel_skip_pattern = 0x00001274,
|
||||
.period_cfg = 0x00001278,
|
||||
.irq_subsample_pattern = 0x0000127C,
|
||||
.epoch_irq_cfg = 0x00001280,
|
||||
.debug_1 = 0x000013F0,
|
||||
.debug_0 = 0x000013F4,
|
||||
.test_bus_ctrl = 0x000013F8,
|
||||
.spare = 0x000013F8,
|
||||
.reg_update_cmd = 0x0000102C,
|
||||
};
|
||||
|
||||
static struct cam_tfe_camif_reg_data tfe530_camif_reg_data = {
|
||||
.extern_reg_update_mask = 0x00000001,
|
||||
.dual_tfe_pix_en_shift = 0x00000001,
|
||||
.extern_reg_update_shift = 0x0,
|
||||
.camif_pd_rdi2_src_sel_shift = 0x2,
|
||||
.dual_tfe_sync_sel_shift = 18,
|
||||
.pixel_pattern_shift = 24,
|
||||
.pixel_pattern_mask = 0x7000000,
|
||||
.module_enable_shift = 0,
|
||||
.pix_out_enable_shift = 8,
|
||||
.pdaf_output_enable_shift = 9,
|
||||
.dsp_mode_shift = 0,
|
||||
.dsp_mode_mask = 0,
|
||||
.dsp_en_shift = 0,
|
||||
.dsp_en_mask = 0,
|
||||
.reg_update_cmd_data = 0x1,
|
||||
.epoch_line_cfg = 0x00140014,
|
||||
.sof_irq_mask = 0x00000001,
|
||||
.epoch0_irq_mask = 0x00000004,
|
||||
.epoch1_irq_mask = 0x00000008,
|
||||
.eof_irq_mask = 0x00000002,
|
||||
.reg_update_irq_mask = 0x00000001,
|
||||
.error_irq_mask0 = 0x00010100,
|
||||
.error_irq_mask2 = 0x00000023,
|
||||
.subscribe_irq_mask = {
|
||||
0x00000000,
|
||||
0x00000007,
|
||||
0x00000000,
|
||||
},
|
||||
.enable_diagnostic_hw = 0x1,
|
||||
.perf_cnt_start_cmd_shift = 0,
|
||||
.perf_cnt_continuous_shift = 2,
|
||||
.perf_client_sel_shift = 8,
|
||||
.perf_window_start_shift = 16,
|
||||
.perf_window_end_shift = 20,
|
||||
};
|
||||
|
||||
static struct cam_tfe_rdi_reg tfe530_rdi0_reg = {
|
||||
.rdi_hw_version = 0x00001400,
|
||||
.rdi_hw_status = 0x00001404,
|
||||
.rdi_module_config = 0x00001460,
|
||||
.rdi_skip_period = 0x00001468,
|
||||
.rdi_irq_subsample_pattern = 0x0000146C,
|
||||
.rdi_epoch_irq = 0x00001470,
|
||||
.rdi_debug_1 = 0x000015F0,
|
||||
.rdi_debug_0 = 0x000015F4,
|
||||
.rdi_test_bus_ctrl = 0x000015F8,
|
||||
.rdi_spare = 0x000015FC,
|
||||
.reg_update_cmd = 0x0000102C,
|
||||
};
|
||||
|
||||
static struct cam_tfe_rdi_reg_data tfe530_rdi0_reg_data = {
|
||||
.reg_update_cmd_data = 0x2,
|
||||
.epoch_line_cfg = 0x00140014,
|
||||
.pixel_pattern_shift = 24,
|
||||
.pixel_pattern_mask = 0x07000000,
|
||||
.rdi_out_enable_shift = 0,
|
||||
|
||||
.sof_irq_mask = 0x00000010,
|
||||
.epoch0_irq_mask = 0x00000040,
|
||||
.epoch1_irq_mask = 0x00000080,
|
||||
.eof_irq_mask = 0x00000020,
|
||||
.error_irq_mask0 = 0x00020200,
|
||||
.error_irq_mask2 = 0x00000004,
|
||||
.subscribe_irq_mask = {
|
||||
0x00000000,
|
||||
0x00000030,
|
||||
0x00000000,
|
||||
},
|
||||
.enable_diagnostic_hw = 0x1,
|
||||
};
|
||||
|
||||
static struct cam_tfe_rdi_reg tfe530_rdi1_reg = {
|
||||
.rdi_hw_version = 0x00001600,
|
||||
.rdi_hw_status = 0x00001604,
|
||||
.rdi_module_config = 0x00001660,
|
||||
.rdi_skip_period = 0x00001668,
|
||||
.rdi_irq_subsample_pattern = 0x0000166C,
|
||||
.rdi_epoch_irq = 0x00001670,
|
||||
.rdi_debug_1 = 0x000017F0,
|
||||
.rdi_debug_0 = 0x000017F4,
|
||||
.rdi_test_bus_ctrl = 0x000017F8,
|
||||
.rdi_spare = 0x000017FC,
|
||||
.reg_update_cmd = 0x0000102C,
|
||||
};
|
||||
|
||||
static struct cam_tfe_rdi_reg_data tfe530_rdi1_reg_data = {
|
||||
.reg_update_cmd_data = 0x4,
|
||||
.epoch_line_cfg = 0x00140014,
|
||||
.pixel_pattern_shift = 24,
|
||||
.pixel_pattern_mask = 0x07000000,
|
||||
.rdi_out_enable_shift = 0,
|
||||
|
||||
.sof_irq_mask = 0x00000100,
|
||||
.epoch0_irq_mask = 0x00000400,
|
||||
.epoch1_irq_mask = 0x00000800,
|
||||
.eof_irq_mask = 0x00000200,
|
||||
.error_irq_mask0 = 0x00040400,
|
||||
.error_irq_mask2 = 0x00000008,
|
||||
.subscribe_irq_mask = {
|
||||
0x00000000,
|
||||
0x00000300,
|
||||
0x00000000,
|
||||
},
|
||||
.enable_diagnostic_hw = 0x1,
|
||||
};
|
||||
|
||||
static struct cam_tfe_rdi_reg tfe530_rdi2_reg = {
|
||||
.rdi_hw_version = 0x00001800,
|
||||
.rdi_hw_status = 0x00001804,
|
||||
.rdi_module_config = 0x00001860,
|
||||
.rdi_skip_period = 0x00001868,
|
||||
.rdi_irq_subsample_pattern = 0x0000186C,
|
||||
.rdi_epoch_irq = 0x00001870,
|
||||
.rdi_debug_1 = 0x000019F0,
|
||||
.rdi_debug_0 = 0x000019F4,
|
||||
.rdi_test_bus_ctrl = 0x000019F8,
|
||||
.rdi_spare = 0x000019FC,
|
||||
.reg_update_cmd = 0x0000102C,
|
||||
};
|
||||
|
||||
static struct cam_tfe_rdi_reg_data tfe530_rdi2_reg_data = {
|
||||
.reg_update_cmd_data = 0x8,
|
||||
.epoch_line_cfg = 0x00140014,
|
||||
.pixel_pattern_shift = 24,
|
||||
.pixel_pattern_mask = 0x07000000,
|
||||
.rdi_out_enable_shift = 0,
|
||||
|
||||
.sof_irq_mask = 0x00001000,
|
||||
.epoch0_irq_mask = 0x00004000,
|
||||
.epoch1_irq_mask = 0x00008000,
|
||||
.eof_irq_mask = 0x00002000,
|
||||
.error_irq_mask0 = 0x00080800,
|
||||
.error_irq_mask2 = 0x00000004,
|
||||
.subscribe_irq_mask = {
|
||||
0x00000000,
|
||||
0x00003000,
|
||||
0x00000000,
|
||||
},
|
||||
.enable_diagnostic_hw = 0x1,
|
||||
};
|
||||
|
||||
static struct cam_tfe_top_hw_info tfe530_top_hw_info = {
|
||||
.common_reg = &tfe530_top_commong_reg,
|
||||
.camif_hw_info = {
|
||||
.camif_reg = &tfe530_camif_reg,
|
||||
.reg_data = &tfe530_camif_reg_data,
|
||||
},
|
||||
.rdi_hw_info = {
|
||||
{
|
||||
.rdi_reg = &tfe530_rdi0_reg,
|
||||
.reg_data = &tfe530_rdi0_reg_data,
|
||||
},
|
||||
{
|
||||
.rdi_reg = &tfe530_rdi1_reg,
|
||||
.reg_data = &tfe530_rdi1_reg_data,
|
||||
},
|
||||
{
|
||||
.rdi_reg = &tfe530_rdi2_reg,
|
||||
.reg_data = &tfe530_rdi2_reg_data,
|
||||
},
|
||||
},
|
||||
.in_port = {
|
||||
CAM_TFE_CAMIF_VER_1_0,
|
||||
CAM_TFE_RDI_VER_1_0,
|
||||
CAM_TFE_RDI_VER_1_0,
|
||||
CAM_TFE_RDI_VER_1_0
|
||||
},
|
||||
.reg_dump_data = {
|
||||
.num_reg_dump_entries = 19,
|
||||
.num_lut_dump_entries = 0,
|
||||
.bus_start_addr = 0x2000,
|
||||
.bus_write_top_end_addr = 0x2120,
|
||||
.bus_client_start_addr = 0x2200,
|
||||
.bus_client_offset = 0x100,
|
||||
.num_bus_clients = 10,
|
||||
.reg_entry = {
|
||||
{
|
||||
.start_offset = 0x1000,
|
||||
.end_offset = 0x10F4,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x1260,
|
||||
.end_offset = 0x1280,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x13F0,
|
||||
.end_offset = 0x13FC,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x1460,
|
||||
.end_offset = 0x1470,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x15F0,
|
||||
.end_offset = 0x15FC,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x1660,
|
||||
.end_offset = 0x1670,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x17F0,
|
||||
.end_offset = 0x17FC,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x1860,
|
||||
.end_offset = 0x1870,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x19F0,
|
||||
.end_offset = 0x19FC,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x2660,
|
||||
.end_offset = 0x2694,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x2860,
|
||||
.end_offset = 0x2884,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x2A60,
|
||||
.end_offset = 0X2B34,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x2C60,
|
||||
.end_offset = 0X2C80,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x2E60,
|
||||
.end_offset = 0X2E7C,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x3060,
|
||||
.end_offset = 0X3110,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x3260,
|
||||
.end_offset = 0X3278,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x3460,
|
||||
.end_offset = 0X3478,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x3660,
|
||||
.end_offset = 0X3684,
|
||||
},
|
||||
{
|
||||
.start_offset = 0x3860,
|
||||
.end_offset = 0X3884,
|
||||
},
|
||||
},
|
||||
.lut_entry = {
|
||||
{
|
||||
.lut_word_size = 1,
|
||||
.lut_bank_sel = 0x40,
|
||||
.lut_addr_size = 180,
|
||||
.dmi_reg_offset = 0x2800,
|
||||
},
|
||||
{
|
||||
.lut_word_size = 1,
|
||||
.lut_bank_sel = 0x41,
|
||||
.lut_addr_size = 180,
|
||||
.dmi_reg_offset = 0x3000,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = {
|
||||
.common_reg = {
|
||||
.hw_version = 0x00001A00,
|
||||
.cgc_ovd = 0x00001A08,
|
||||
.comp_cfg_0 = 0x00001A0C,
|
||||
.comp_cfg_1 = 0x00001A10,
|
||||
.frameheader_cfg = {
|
||||
0x00001A34,
|
||||
0x00001A38,
|
||||
0x00001A3C,
|
||||
0x00001A40,
|
||||
},
|
||||
.pwr_iso_cfg = 0x00001A5C,
|
||||
.overflow_status_clear = 0x00001A60,
|
||||
.ccif_violation_status = 0x00001A64,
|
||||
.overflow_status = 0x00001A68,
|
||||
.image_size_violation_status = 0x00001A70,
|
||||
.perf_count_cfg = {
|
||||
0x00001A74,
|
||||
0x00001A78,
|
||||
0x00001A7C,
|
||||
0x00001A80,
|
||||
0x00001A84,
|
||||
0x00001A88,
|
||||
0x00001A8C,
|
||||
0x00001A90,
|
||||
},
|
||||
.perf_count_val = {
|
||||
0x00001A94,
|
||||
0x00001A98,
|
||||
0x00001A9C,
|
||||
0x00001AA0,
|
||||
0x00001AA4,
|
||||
0x00001AA8,
|
||||
0x00001AAC,
|
||||
0x00001AB0,
|
||||
},
|
||||
.perf_count_status = 0x00001AB4,
|
||||
.debug_status_top_cfg = 0x00001AD4,
|
||||
.debug_status_top = 0x00001AD8,
|
||||
.test_bus_ctrl = 0x00001ADC,
|
||||
.irq_mask = {
|
||||
0x00001A18,
|
||||
0x00001A1C,
|
||||
},
|
||||
.irq_clear = {
|
||||
0x00001A20,
|
||||
0x00001A24,
|
||||
},
|
||||
.irq_status = {
|
||||
0x00001A28,
|
||||
0x00001A2C,
|
||||
},
|
||||
.irq_cmd = 0x00001A30,
|
||||
},
|
||||
.num_client = CAM_TFE_BUS_MAX_CLIENTS,
|
||||
.bus_client_reg = {
|
||||
/* BUS Client 0 BAYER */
|
||||
{
|
||||
.cfg = 0x00001C00,
|
||||
.image_addr = 0x00001C04,
|
||||
.frame_incr = 0x00001C08,
|
||||
.image_cfg_0 = 0x00001C0C,
|
||||
.image_cfg_1 = 0x00001C10,
|
||||
.image_cfg_2 = 0x00001C14,
|
||||
.packer_cfg = 0x00001C18,
|
||||
.bw_limit = 0x00001C1C,
|
||||
.frame_header_addr = 0x00001C20,
|
||||
.frame_header_incr = 0x00001C24,
|
||||
.frame_header_cfg = 0x00001C28,
|
||||
.line_done_cfg = 0x00000000,
|
||||
.irq_subsample_period = 0x00001C30,
|
||||
.irq_subsample_pattern = 0x00001C34,
|
||||
.framedrop_period = 0x00001C38,
|
||||
.framedrop_pattern = 0x00001C3C,
|
||||
.addr_status_0 = 0x00001C68,
|
||||
.addr_status_1 = 0x00001C6C,
|
||||
.addr_status_2 = 0x00001C70,
|
||||
.addr_status_3 = 0x00001C74,
|
||||
.debug_status_cfg = 0x00001C78,
|
||||
.debug_status_0 = 0x00001C7C,
|
||||
.debug_status_1 = 0x00001C80,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_0,
|
||||
},
|
||||
/* BUS Client 1 IDEAL RAW*/
|
||||
{
|
||||
.cfg = 0x00001D00,
|
||||
.image_addr = 0x00001D04,
|
||||
.frame_incr = 0x00001D08,
|
||||
.image_cfg_0 = 0x00001D0C,
|
||||
.image_cfg_1 = 0x00001D10,
|
||||
.image_cfg_2 = 0x00001D14,
|
||||
.packer_cfg = 0x00001D18,
|
||||
.bw_limit = 0x00001D1C,
|
||||
.frame_header_addr = 0x00001D20,
|
||||
.frame_header_incr = 0x00001D24,
|
||||
.frame_header_cfg = 0x00001D28,
|
||||
.line_done_cfg = 0x00000000,
|
||||
.irq_subsample_period = 0x00001D30,
|
||||
.irq_subsample_pattern = 0x00001D34,
|
||||
.framedrop_period = 0x00001D38,
|
||||
.framedrop_pattern = 0x00001D3C,
|
||||
.addr_status_0 = 0x00001D68,
|
||||
.addr_status_1 = 0x00001D6C,
|
||||
.addr_status_2 = 0x00001D70,
|
||||
.addr_status_3 = 0x00001D74,
|
||||
.debug_status_cfg = 0x00001D78,
|
||||
.debug_status_0 = 0x00001D7C,
|
||||
.debug_status_1 = 0x00001D80,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_1,
|
||||
},
|
||||
/* BUS Client 2 Stats BE Tintless */
|
||||
{
|
||||
.cfg = 0x00001E00,
|
||||
.image_addr = 0x00001E04,
|
||||
.frame_incr = 0x00001E08,
|
||||
.image_cfg_0 = 0x00001E0C,
|
||||
.image_cfg_1 = 0x00001E10,
|
||||
.image_cfg_2 = 0x00001E14,
|
||||
.packer_cfg = 0x00001E18,
|
||||
.bw_limit = 0x00001E1C,
|
||||
.frame_header_addr = 0x00001E20,
|
||||
.frame_header_incr = 0x00001E24,
|
||||
.frame_header_cfg = 0x00001E28,
|
||||
.line_done_cfg = 0x00001E00,
|
||||
.irq_subsample_period = 0x00001E30,
|
||||
.irq_subsample_pattern = 0x00000E34,
|
||||
.framedrop_period = 0x00001E38,
|
||||
.framedrop_pattern = 0x00001E3C,
|
||||
.addr_status_0 = 0x00001E68,
|
||||
.addr_status_1 = 0x00001E6C,
|
||||
.addr_status_2 = 0x00001E70,
|
||||
.addr_status_3 = 0x00001E74,
|
||||
.debug_status_cfg = 0x00001E78,
|
||||
.debug_status_0 = 0x00001E7C,
|
||||
.debug_status_1 = 0x00001E80,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_2,
|
||||
},
|
||||
/* BUS Client 3 Stats Bhist */
|
||||
{
|
||||
.cfg = 0x00001F00,
|
||||
.image_addr = 0x00001F04,
|
||||
.frame_incr = 0x00001F08,
|
||||
.image_cfg_0 = 0x00001F0C,
|
||||
.image_cfg_1 = 0x00001F10,
|
||||
.image_cfg_2 = 0x00001F14,
|
||||
.packer_cfg = 0x00001F18,
|
||||
.bw_limit = 0x00001F1C,
|
||||
.frame_header_addr = 0x00001F20,
|
||||
.frame_header_incr = 0x00001F24,
|
||||
.frame_header_cfg = 0x00001F28,
|
||||
.line_done_cfg = 0x00000000,
|
||||
.irq_subsample_period = 0x00001F30,
|
||||
.irq_subsample_pattern = 0x00001F34,
|
||||
.framedrop_period = 0x00001F38,
|
||||
.framedrop_pattern = 0x00001F3C,
|
||||
.addr_status_0 = 0x00001F68,
|
||||
.addr_status_1 = 0x00001F6C,
|
||||
.addr_status_2 = 0x00001F70,
|
||||
.addr_status_3 = 0x00001F74,
|
||||
.debug_status_cfg = 0x00001F78,
|
||||
.debug_status_0 = 0x00001F7C,
|
||||
.debug_status_1 = 0x00001F80,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_2,
|
||||
},
|
||||
/* BUS Client 4 Stats AWB BG */
|
||||
{
|
||||
.cfg = 0x00002000,
|
||||
.image_addr = 0x00002004,
|
||||
.frame_incr = 0x00002008,
|
||||
.image_cfg_0 = 0x0000200C,
|
||||
.image_cfg_1 = 0x00002010,
|
||||
.image_cfg_2 = 0x00002014,
|
||||
.packer_cfg = 0x00002018,
|
||||
.bw_limit = 0x0000201C,
|
||||
.frame_header_addr = 0x00002020,
|
||||
.frame_header_incr = 0x00002024,
|
||||
.frame_header_cfg = 0x00002028,
|
||||
.line_done_cfg = 0x00000000,
|
||||
.irq_subsample_period = 0x00002030,
|
||||
.irq_subsample_pattern = 0x00002034,
|
||||
.framedrop_period = 0x00002038,
|
||||
.framedrop_pattern = 0x0000203C,
|
||||
.addr_status_0 = 0x00002068,
|
||||
.addr_status_1 = 0x0000206C,
|
||||
.addr_status_2 = 0x00002070,
|
||||
.addr_status_3 = 0x00002074,
|
||||
.debug_status_cfg = 0x00002078,
|
||||
.debug_status_0 = 0x0000207C,
|
||||
.debug_status_1 = 0x00002080,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_3,
|
||||
},
|
||||
/* BUS Client 5 Stats AEC BG */
|
||||
{
|
||||
.cfg = 0x00002100,
|
||||
.image_addr = 0x00002104,
|
||||
.frame_incr = 0x00002108,
|
||||
.image_cfg_0 = 0x0000210C,
|
||||
.image_cfg_1 = 0x00002110,
|
||||
.image_cfg_2 = 0x00002114,
|
||||
.packer_cfg = 0x00002118,
|
||||
.bw_limit = 0x0000211C,
|
||||
.frame_header_addr = 0x00002120,
|
||||
.frame_header_incr = 0x00002124,
|
||||
.frame_header_cfg = 0x00002128,
|
||||
.line_done_cfg = 0x00000000,
|
||||
.irq_subsample_period = 0x00002130,
|
||||
.irq_subsample_pattern = 0x00002134,
|
||||
.framedrop_period = 0x00002138,
|
||||
.framedrop_pattern = 0x0000213C,
|
||||
.addr_status_0 = 0x00002168,
|
||||
.addr_status_1 = 0x0000216C,
|
||||
.addr_status_2 = 0x00002170,
|
||||
.addr_status_3 = 0x00002174,
|
||||
.debug_status_cfg = 0x00002178,
|
||||
.debug_status_0 = 0x0000217C,
|
||||
.debug_status_1 = 0x00002180,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_3,
|
||||
},
|
||||
/* BUS Client 6 Stats BAF */
|
||||
{
|
||||
.cfg = 0x00002200,
|
||||
.image_addr = 0x00002204,
|
||||
.frame_incr = 0x00002208,
|
||||
.image_cfg_0 = 0x0000220C,
|
||||
.image_cfg_1 = 0x00002210,
|
||||
.image_cfg_2 = 0x00002214,
|
||||
.packer_cfg = 0x00002218,
|
||||
.bw_limit = 0x0000221C,
|
||||
.frame_header_addr = 0x00002220,
|
||||
.frame_header_incr = 0x00002224,
|
||||
.frame_header_cfg = 0x00002228,
|
||||
.line_done_cfg = 0x00000000,
|
||||
.irq_subsample_period = 0x00002230,
|
||||
.irq_subsample_pattern = 0x00002234,
|
||||
.framedrop_period = 0x00002238,
|
||||
.framedrop_pattern = 0x0000223C,
|
||||
.addr_status_0 = 0x00002268,
|
||||
.addr_status_1 = 0x0000226C,
|
||||
.addr_status_2 = 0x00002270,
|
||||
.addr_status_3 = 0x00002274,
|
||||
.debug_status_cfg = 0x00002278,
|
||||
.debug_status_0 = 0x0000227C,
|
||||
.debug_status_1 = 0x00002280,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_4,
|
||||
},
|
||||
/* BUS Client 7 RDI0 */
|
||||
{
|
||||
.cfg = 0x00002300,
|
||||
.image_addr = 0x00002304,
|
||||
.frame_incr = 0x00002308,
|
||||
.image_cfg_0 = 0x0000230C,
|
||||
.image_cfg_1 = 0x00002310,
|
||||
.image_cfg_2 = 0x00002314,
|
||||
.packer_cfg = 0x00002318,
|
||||
.bw_limit = 0x0000231C,
|
||||
.frame_header_addr = 0x00002320,
|
||||
.frame_header_incr = 0x00002324,
|
||||
.frame_header_cfg = 0x00002328,
|
||||
.line_done_cfg = 0x00000000,
|
||||
.irq_subsample_period = 0x00002330,
|
||||
.irq_subsample_pattern = 0x00002334,
|
||||
.framedrop_period = 0x00002338,
|
||||
.framedrop_pattern = 0x0000233C,
|
||||
.addr_status_0 = 0x00002368,
|
||||
.addr_status_1 = 0x0000236C,
|
||||
.addr_status_2 = 0x00002370,
|
||||
.addr_status_3 = 0x00002374,
|
||||
.debug_status_cfg = 0x00002378,
|
||||
.debug_status_0 = 0x0000237C,
|
||||
.debug_status_1 = 0x00002380,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_5,
|
||||
},
|
||||
/* BUS Client 8 RDI1 */
|
||||
{
|
||||
.cfg = 0x00002400,
|
||||
.image_addr = 0x00002404,
|
||||
.frame_incr = 0x00002408,
|
||||
.image_cfg_0 = 0x0000240C,
|
||||
.image_cfg_1 = 0x00002410,
|
||||
.image_cfg_2 = 0x00002414,
|
||||
.packer_cfg = 0x00002418,
|
||||
.bw_limit = 0x0000241C,
|
||||
.frame_header_addr = 0x00002420,
|
||||
.frame_header_incr = 0x00002424,
|
||||
.frame_header_cfg = 0x00002428,
|
||||
.line_done_cfg = 0x00000000,
|
||||
.irq_subsample_period = 0x00002430,
|
||||
.irq_subsample_pattern = 0x00002434,
|
||||
.framedrop_period = 0x00002438,
|
||||
.framedrop_pattern = 0x0000243C,
|
||||
.addr_status_0 = 0x00002468,
|
||||
.addr_status_1 = 0x0000246C,
|
||||
.addr_status_2 = 0x00002470,
|
||||
.addr_status_3 = 0x00002474,
|
||||
.debug_status_cfg = 0x00002478,
|
||||
.debug_status_0 = 0x0000247C,
|
||||
.debug_status_1 = 0x00002480,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_6,
|
||||
},
|
||||
/* BUS Client 9 PDAF/RDI2*/
|
||||
{
|
||||
.cfg = 0x00002500,
|
||||
.image_addr = 0x00002504,
|
||||
.frame_incr = 0x00002508,
|
||||
.image_cfg_0 = 0x0000250C,
|
||||
.image_cfg_1 = 0x00002510,
|
||||
.image_cfg_2 = 0x00002514,
|
||||
.packer_cfg = 0x00002518,
|
||||
.bw_limit = 0x0000251C,
|
||||
.frame_header_addr = 0x00002520,
|
||||
.frame_header_incr = 0x00002524,
|
||||
.frame_header_cfg = 0x00002528,
|
||||
.line_done_cfg = 0x00000000,
|
||||
.irq_subsample_period = 0x00002530,
|
||||
.irq_subsample_pattern = 0x00002534,
|
||||
.framedrop_period = 0x00002538,
|
||||
.framedrop_pattern = 0x0000253C,
|
||||
.addr_status_0 = 0x00002568,
|
||||
.addr_status_1 = 0x0000256C,
|
||||
.addr_status_2 = 0x00002570,
|
||||
.addr_status_3 = 0x00002574,
|
||||
.debug_status_cfg = 0x00002578,
|
||||
.debug_status_0 = 0x0000257C,
|
||||
.debug_status_1 = 0x00002580,
|
||||
.comp_group = CAM_TFE_BUS_COMP_GRP_7,
|
||||
},
|
||||
},
|
||||
.num_out = CAM_TFE_BUS_TFE_OUT_MAX,
|
||||
.tfe_out_hw_info = {
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_RDI0,
|
||||
.max_width = -1,
|
||||
.max_height = -1,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_5,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_1,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_RDI1,
|
||||
.max_width = -1,
|
||||
.max_height = -1,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_6,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_2,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_RDI2,
|
||||
.max_width = -1,
|
||||
.max_height = -1,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_7,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_3,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_FULL,
|
||||
.max_width = 4096,
|
||||
.max_height = 4096,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_0,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_0,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_RAW_DUMP,
|
||||
.max_width = 4096,
|
||||
.max_height = 4096,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_1,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_0,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_PDAF,
|
||||
.max_width = 4096,
|
||||
.max_height = 4096,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_7,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_3,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_HDR_BE,
|
||||
.max_width = -1,
|
||||
.max_height = -1,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_3,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_0,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_HDR_BHIST,
|
||||
.max_width = -1,
|
||||
.max_height = -1,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_2,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_0,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_TL_BG,
|
||||
.max_width = -1,
|
||||
.max_height = -1,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_2,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_0,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_AWB_BG,
|
||||
.max_width = -1,
|
||||
.max_height = -1,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_3,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_0,
|
||||
},
|
||||
{
|
||||
.tfe_out_id = CAM_TFE_BUS_TFE_OUT_STATS_BF,
|
||||
.max_width = -1,
|
||||
.max_height = -1,
|
||||
.composite_group = CAM_TFE_BUS_COMP_GRP_4,
|
||||
.rup_group_id = CAM_TFE_BUS_RUP_GRP_0,
|
||||
},
|
||||
},
|
||||
.comp_done_shift = 8,
|
||||
.top_bus_wr_irq_shift = 1,
|
||||
.comp_buf_done_mask = 0xFF00,
|
||||
.comp_rup_done_mask = 0xF,
|
||||
.bus_irq_error_mask = {
|
||||
0xD0000000,
|
||||
0x00000000,
|
||||
},
|
||||
};
|
||||
|
||||
struct cam_tfe_hw_info cam_tfe530 = {
|
||||
.top_irq_mask = {
|
||||
0x00001034,
|
||||
0x00001038,
|
||||
0x0000103C,
|
||||
},
|
||||
.top_irq_clear = {
|
||||
0x00001040,
|
||||
0x00001044,
|
||||
0x00001048,
|
||||
},
|
||||
.top_irq_status = {
|
||||
0x0000104C,
|
||||
0x00001050,
|
||||
0x00001054,
|
||||
},
|
||||
.top_irq_cmd = 0x00001030,
|
||||
.global_clear_bitmask = 0x00000001,
|
||||
|
||||
.bus_irq_mask = {
|
||||
0x00001A18,
|
||||
0x00001A1C,
|
||||
},
|
||||
.bus_irq_clear = {
|
||||
0x00001A20,
|
||||
0x00001A24,
|
||||
},
|
||||
.bus_irq_status = {
|
||||
0x00001A28,
|
||||
0x00001A2C,
|
||||
},
|
||||
.bus_irq_cmd = 0x00001A30,
|
||||
.bus_violation_reg = 0x00001A64,
|
||||
.bus_overflow_reg = 0x00001A68,
|
||||
.bus_image_size_vilation_reg = 0x1A70,
|
||||
.bus_overflow_clear_cmd = 0x1A60,
|
||||
.debug_status_top = 0x1AD8,
|
||||
|
||||
.reset_irq_mask = {
|
||||
0x00000001,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
},
|
||||
.error_irq_mask = {
|
||||
0x000F0F00,
|
||||
0x00000000,
|
||||
0x0000003F,
|
||||
},
|
||||
.bus_reg_irq_mask = {
|
||||
0x00000002,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
},
|
||||
|
||||
.bus_version = CAM_TFE_BUS_1_0,
|
||||
.bus_hw_info = &tfe530_bus_hw_info,
|
||||
|
||||
.top_version = CAM_TFE_TOP_1_0,
|
||||
.top_hw_info = &tfe530_top_hw_info,
|
||||
};
|
||||
|
||||
#endif /* _CAM_TFE530_H_ */
|
2149
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c
Normal file
2149
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c
Normal file
File diff suppressed because it is too large
Load Diff
240
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h
Normal file
240
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h
Normal file
@@ -0,0 +1,240 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CAM_TFE_BUS_H_
|
||||
#define _CAM_TFE_BUS_H_
|
||||
|
||||
#include "cam_soc_util.h"
|
||||
#include "cam_isp_hw.h"
|
||||
#include "cam_tfe_hw_intf.h"
|
||||
|
||||
#define CAM_TFE_BUS_MAX_CLIENTS 10
|
||||
#define CAM_TFE_BUS_MAX_SUB_GRPS 4
|
||||
#define CAM_TFE_BUS_MAX_PERF_CNT_REG 8
|
||||
#define CAM_TFE_BUS_MAX_IRQ_REGISTERS 2
|
||||
|
||||
#define CAM_TFE_BUS_1_0 0x1000
|
||||
|
||||
|
||||
#define CAM_TFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \
|
||||
do { \
|
||||
buf_array[(index)++] = offset; \
|
||||
buf_array[(index)++] = val; \
|
||||
} while (0)
|
||||
|
||||
#define ALIGNUP(value, alignment) \
|
||||
((value + alignment - 1) / alignment * alignment)
|
||||
|
||||
typedef int (*CAM_BUS_HANDLER_BOTTOM_HALF)(void *bus_priv,
|
||||
bool rup_process, struct cam_tfe_irq_evt_payload *evt_payload);
|
||||
|
||||
enum cam_tfe_bus_plane_type {
|
||||
PLANE_Y,
|
||||
PLANE_C,
|
||||
PLANE_MAX,
|
||||
};
|
||||
|
||||
|
||||
enum cam_tfe_bus_tfe_core_id {
|
||||
CAM_TFE_BUS_TFE_CORE_0,
|
||||
CAM_TFE_BUS_TFE_CORE_1,
|
||||
CAM_TFE_BUS_TFE_CORE_2,
|
||||
CAM_TFE_BUS_TFE_CORE_MAX,
|
||||
};
|
||||
|
||||
enum cam_tfe_bus_comp_grp_id {
|
||||
CAM_TFE_BUS_COMP_GRP_0,
|
||||
CAM_TFE_BUS_COMP_GRP_1,
|
||||
CAM_TFE_BUS_COMP_GRP_2,
|
||||
CAM_TFE_BUS_COMP_GRP_3,
|
||||
CAM_TFE_BUS_COMP_GRP_4,
|
||||
CAM_TFE_BUS_COMP_GRP_5,
|
||||
CAM_TFE_BUS_COMP_GRP_6,
|
||||
CAM_TFE_BUS_COMP_GRP_7,
|
||||
CAM_TFE_BUS_COMP_GRP_MAX,
|
||||
};
|
||||
|
||||
enum cam_tfe_bus_rup_grp_id {
|
||||
CAM_TFE_BUS_RUP_GRP_0,
|
||||
CAM_TFE_BUS_RUP_GRP_1,
|
||||
CAM_TFE_BUS_RUP_GRP_2,
|
||||
CAM_TFE_BUS_RUP_GRP_3,
|
||||
CAM_TFE_BUS_RUP_GRP_MAX,
|
||||
};
|
||||
|
||||
enum cam_tfe_bus_tfe_out_id {
|
||||
CAM_TFE_BUS_TFE_OUT_RDI0,
|
||||
CAM_TFE_BUS_TFE_OUT_RDI1,
|
||||
CAM_TFE_BUS_TFE_OUT_RDI2,
|
||||
CAM_TFE_BUS_TFE_OUT_FULL,
|
||||
CAM_TFE_BUS_TFE_OUT_RAW_DUMP,
|
||||
CAM_TFE_BUS_TFE_OUT_PDAF,
|
||||
CAM_TFE_BUS_TFE_OUT_STATS_HDR_BE,
|
||||
CAM_TFE_BUS_TFE_OUT_STATS_HDR_BHIST,
|
||||
CAM_TFE_BUS_TFE_OUT_STATS_TL_BG,
|
||||
CAM_TFE_BUS_TFE_OUT_STATS_AWB_BG,
|
||||
CAM_TFE_BUS_TFE_OUT_STATS_BF,
|
||||
CAM_TFE_BUS_TFE_OUT_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_bus_reg_offset_common:
|
||||
*
|
||||
* @Brief: Common registers across all BUS Clients
|
||||
*/
|
||||
struct cam_tfe_bus_reg_offset_common {
|
||||
uint32_t hw_version;
|
||||
uint32_t cgc_ovd;
|
||||
uint32_t comp_cfg_0;
|
||||
uint32_t comp_cfg_1;
|
||||
uint32_t frameheader_cfg[4];
|
||||
uint32_t pwr_iso_cfg;
|
||||
uint32_t overflow_status_clear;
|
||||
uint32_t ccif_violation_status;
|
||||
uint32_t overflow_status;
|
||||
uint32_t image_size_violation_status;
|
||||
uint32_t perf_count_cfg[CAM_TFE_BUS_MAX_PERF_CNT_REG];
|
||||
uint32_t perf_count_val[CAM_TFE_BUS_MAX_PERF_CNT_REG];
|
||||
uint32_t perf_count_status;
|
||||
uint32_t debug_status_top_cfg;
|
||||
uint32_t debug_status_top;
|
||||
uint32_t test_bus_ctrl;
|
||||
uint32_t irq_mask[CAM_TFE_BUS_IRQ_REGISTERS_MAX];
|
||||
uint32_t irq_clear[CAM_TFE_BUS_IRQ_REGISTERS_MAX];
|
||||
uint32_t irq_status[CAM_TFE_BUS_IRQ_REGISTERS_MAX];
|
||||
uint32_t irq_cmd;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_bus_reg_offset_bus_client:
|
||||
*
|
||||
* @Brief: Register offsets for BUS Clients
|
||||
*/
|
||||
struct cam_tfe_bus_reg_offset_bus_client {
|
||||
uint32_t cfg;
|
||||
uint32_t image_addr;
|
||||
uint32_t frame_incr;
|
||||
uint32_t image_cfg_0;
|
||||
uint32_t image_cfg_1;
|
||||
uint32_t image_cfg_2;
|
||||
uint32_t packer_cfg;
|
||||
uint32_t bw_limit;
|
||||
uint32_t frame_header_addr;
|
||||
uint32_t frame_header_incr;
|
||||
uint32_t frame_header_cfg;
|
||||
uint32_t line_done_cfg;
|
||||
uint32_t irq_subsample_period;
|
||||
uint32_t irq_subsample_pattern;
|
||||
uint32_t framedrop_period;
|
||||
uint32_t framedrop_pattern;
|
||||
uint32_t addr_status_0;
|
||||
uint32_t addr_status_1;
|
||||
uint32_t addr_status_2;
|
||||
uint32_t addr_status_3;
|
||||
uint32_t debug_status_cfg;
|
||||
uint32_t debug_status_0;
|
||||
uint32_t debug_status_1;
|
||||
uint32_t comp_group;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_bus_tfe_out_hw_info:
|
||||
*
|
||||
* @Brief: HW capability of TFE Bus Client
|
||||
* tfe_out_id Tfe out port id
|
||||
* max_width Max width supported by the outport
|
||||
* max_height Max height supported by outport
|
||||
* composite_group Out port composite group id
|
||||
* rup_group_id Reg update group of outport id
|
||||
*/
|
||||
struct cam_tfe_bus_tfe_out_hw_info {
|
||||
enum cam_tfe_bus_tfe_out_id tfe_out_id;
|
||||
uint32_t max_width;
|
||||
uint32_t max_height;
|
||||
uint32_t composite_group;
|
||||
uint32_t rup_group_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_bus_hw_info:
|
||||
*
|
||||
* @Brief: HW register info for entire Bus
|
||||
*
|
||||
* @common_reg: Common register details
|
||||
* @num_client: Total number of write clients
|
||||
* @bus_client_reg: Bus client register info
|
||||
* @tfe_out_hw_info: TFE output capability
|
||||
* @comp_done_shift: Mask shift for comp done mask
|
||||
* @top_bus_wr_irq_shift: Mask shift for top level BUS WR irq
|
||||
* @comp_buf_done_mask: Composite buf done bits mask
|
||||
* @comp_rup_done_mask: Reg update done mask
|
||||
* @bus_irq_error_mask: Bus irq error mask bits
|
||||
*/
|
||||
struct cam_tfe_bus_hw_info {
|
||||
struct cam_tfe_bus_reg_offset_common common_reg;
|
||||
uint32_t num_client;
|
||||
struct cam_tfe_bus_reg_offset_bus_client
|
||||
bus_client_reg[CAM_TFE_BUS_MAX_CLIENTS];
|
||||
uint32_t num_out;
|
||||
struct cam_tfe_bus_tfe_out_hw_info
|
||||
tfe_out_hw_info[CAM_TFE_BUS_TFE_OUT_MAX];
|
||||
uint32_t comp_done_shift;
|
||||
uint32_t top_bus_wr_irq_shift;
|
||||
uint32_t comp_buf_done_mask;
|
||||
uint32_t comp_rup_done_mask;
|
||||
uint32_t bus_irq_error_mask[CAM_TFE_BUS_IRQ_REGISTERS_MAX];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_bus:
|
||||
*
|
||||
* @Brief: Bus interface structure
|
||||
*
|
||||
* @bus_priv: Private data of bus
|
||||
* @hw_ops: Hardware interface functions
|
||||
* @bottom_half_handler: Bottom Half handler function
|
||||
*/
|
||||
struct cam_tfe_bus {
|
||||
void *bus_priv;
|
||||
struct cam_hw_ops hw_ops;
|
||||
CAM_BUS_HANDLER_BOTTOM_HALF bottom_half_handler;
|
||||
};
|
||||
|
||||
/*
|
||||
* cam_tfe_bus_init()
|
||||
*
|
||||
* @Brief: Initialize Bus layer
|
||||
*
|
||||
* @soc_info: Soc Information for the associated HW
|
||||
* @hw_intf: HW Interface of HW to which this resource belongs
|
||||
* @bus_hw_info: BUS HW info that contains details of BUS registers
|
||||
* @core_data: Core data pointer used for top irq config
|
||||
* @tfe_bus: Pointer to tfe_bus structure which will be filled
|
||||
* and returned on successful initialize
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_bus_init(
|
||||
struct cam_hw_soc_info *soc_info,
|
||||
struct cam_hw_intf *hw_intf,
|
||||
void *bus_hw_info,
|
||||
void *core_data,
|
||||
struct cam_tfe_bus **tfe_bus);
|
||||
|
||||
/*
|
||||
* cam_tfe_bus_deinit()
|
||||
*
|
||||
* @Brief: Deinitialize Bus layer
|
||||
*
|
||||
* @tfe_bus: Pointer to tfe_bus structure to deinitialize
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_bus_deinit(struct cam_tfe_bus **tfe_bus);
|
||||
|
||||
#endif /* _CAM_TFE_BUS_H_ */
|
2529
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c
Normal file
2529
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c
Normal file
File diff suppressed because it is too large
Load Diff
272
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h
Normal file
272
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h
Normal file
@@ -0,0 +1,272 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CAM_TFE_CORE_H_
|
||||
#define _CAM_TFE_CORE_H_
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include "cam_hw_intf.h"
|
||||
#include "cam_tfe_bus.h"
|
||||
#include "cam_tfe_hw_intf.h"
|
||||
#include "cam_tfe_irq.h"
|
||||
|
||||
#define CAM_TFE_CAMIF_VER_1_0 0x10
|
||||
#define CAM_TFE_RDI_VER_1_0 0x1000
|
||||
#define CAM_TFE_TOP_1_0 0x1000
|
||||
#define CAM_TFE_TOP_IN_PORT_MAX 4
|
||||
#define CAM_TFE_RDI_MAX 4
|
||||
|
||||
#define CAMIF_DEBUG_ENABLE_SENSOR_DIAG_STATUS BIT(0)
|
||||
#define CAM_TFE_EVT_MAX 256
|
||||
|
||||
#define CAM_TFE_MAX_REG_DUMP_ENTRIES 20
|
||||
#define CAM_TFE_MAX_LUT_DUMP_ENTRIES 10
|
||||
|
||||
enum cam_tfe_lut_word_size {
|
||||
CAM_TFE_LUT_WORD_SIZE_32,
|
||||
CAM_TFE_LUT_WORD_SIZE_64,
|
||||
CAM_TFE_LUT_WORD_SIZE_MAX,
|
||||
};
|
||||
|
||||
struct cam_tfe_reg_dump_entry {
|
||||
uint32_t start_offset;
|
||||
uint32_t end_offset;
|
||||
};
|
||||
|
||||
struct cam_tfe_lut_dump_entry {
|
||||
enum cam_tfe_lut_word_size lut_word_size;
|
||||
uint32_t lut_bank_sel;
|
||||
uint32_t lut_addr_size;
|
||||
uint32_t dmi_reg_offset;
|
||||
};
|
||||
struct cam_tfe_reg_dump_data {
|
||||
uint32_t num_reg_dump_entries;
|
||||
uint32_t num_lut_dump_entries;
|
||||
uint32_t bus_start_addr;
|
||||
uint32_t bus_write_top_end_addr;
|
||||
uint32_t bus_client_start_addr;
|
||||
uint32_t bus_client_offset;
|
||||
uint32_t num_bus_clients;
|
||||
struct cam_tfe_reg_dump_entry
|
||||
reg_entry[CAM_TFE_MAX_REG_DUMP_ENTRIES];
|
||||
struct cam_tfe_lut_dump_entry
|
||||
lut_entry[CAM_TFE_MAX_LUT_DUMP_ENTRIES];
|
||||
};
|
||||
|
||||
struct cam_tfe_top_reg_offset_common {
|
||||
uint32_t hw_version;
|
||||
uint32_t hw_capability;
|
||||
uint32_t lens_feature;
|
||||
uint32_t stats_feature;
|
||||
uint32_t zoom_feature;
|
||||
uint32_t global_reset_cmd;
|
||||
uint32_t core_cgc_ctrl;
|
||||
uint32_t ahb_cgc_ctrl;
|
||||
uint32_t core_cfg_0;
|
||||
uint32_t core_cfg_1;
|
||||
uint32_t reg_update_cmd;
|
||||
uint32_t diag_config;
|
||||
uint32_t diag_sensor_status_0;
|
||||
uint32_t diag_sensor_status_1;
|
||||
uint32_t diag_sensor_frame_cnt_status;
|
||||
uint32_t violation_status;
|
||||
uint32_t stats_throttle_cnt_cfg_0;
|
||||
uint32_t stats_throttle_cnt_cfg_1;
|
||||
uint32_t debug_0;
|
||||
uint32_t debug_1;
|
||||
uint32_t debug_2;
|
||||
uint32_t debug_3;
|
||||
uint32_t debug_cfg;
|
||||
uint32_t perf_cnt_cfg;
|
||||
uint32_t perf_pixel_count;
|
||||
uint32_t perf_line_count;
|
||||
uint32_t perf_stall_count;
|
||||
uint32_t perf_always_count;
|
||||
uint32_t perf_count_status;
|
||||
};
|
||||
|
||||
struct cam_tfe_camif_reg {
|
||||
uint32_t hw_version;
|
||||
uint32_t hw_status;
|
||||
uint32_t module_cfg;
|
||||
uint32_t pdaf_raw_crop_width_cfg;
|
||||
uint32_t pdaf_raw_crop_height_cfg;
|
||||
uint32_t line_skip_pattern;
|
||||
uint32_t pixel_skip_pattern;
|
||||
uint32_t period_cfg;
|
||||
uint32_t irq_subsample_pattern;
|
||||
uint32_t epoch_irq_cfg;
|
||||
uint32_t debug_1;
|
||||
uint32_t debug_0;
|
||||
uint32_t test_bus_ctrl;
|
||||
uint32_t spare;
|
||||
uint32_t reg_update_cmd;
|
||||
};
|
||||
|
||||
struct cam_tfe_camif_reg_data {
|
||||
uint32_t extern_reg_update_mask;
|
||||
uint32_t dual_tfe_pix_en_shift;
|
||||
uint32_t extern_reg_update_shift;
|
||||
uint32_t camif_pd_rdi2_src_sel_shift;
|
||||
uint32_t dual_tfe_sync_sel_shift;
|
||||
|
||||
uint32_t pixel_pattern_shift;
|
||||
uint32_t pixel_pattern_mask;
|
||||
uint32_t module_enable_shift;
|
||||
uint32_t pix_out_enable_shift;
|
||||
uint32_t pdaf_output_enable_shift;
|
||||
|
||||
uint32_t dsp_mode_shift;
|
||||
uint32_t dsp_mode_mask;
|
||||
uint32_t dsp_en_shift;
|
||||
uint32_t dsp_en_mask;
|
||||
|
||||
uint32_t reg_update_cmd_data;
|
||||
uint32_t epoch_line_cfg;
|
||||
uint32_t sof_irq_mask;
|
||||
uint32_t epoch0_irq_mask;
|
||||
uint32_t epoch1_irq_mask;
|
||||
uint32_t eof_irq_mask;
|
||||
uint32_t reg_update_irq_mask;
|
||||
uint32_t error_irq_mask0;
|
||||
uint32_t error_irq_mask2;
|
||||
uint32_t subscribe_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM];
|
||||
|
||||
uint32_t enable_diagnostic_hw;
|
||||
uint32_t perf_cnt_start_cmd_shift;
|
||||
uint32_t perf_cnt_continuous_shift;
|
||||
uint32_t perf_client_sel_shift;
|
||||
uint32_t perf_window_start_shift;
|
||||
uint32_t perf_window_end_shift;
|
||||
};
|
||||
|
||||
struct cam_tfe_camif_hw_info {
|
||||
struct cam_tfe_camif_reg *camif_reg;
|
||||
struct cam_tfe_camif_reg_data *reg_data;
|
||||
};
|
||||
|
||||
struct cam_tfe_rdi_reg {
|
||||
uint32_t rdi_hw_version;
|
||||
uint32_t rdi_hw_status;
|
||||
uint32_t rdi_module_config;
|
||||
uint32_t rdi_skip_period;
|
||||
uint32_t rdi_irq_subsample_pattern;
|
||||
uint32_t rdi_epoch_irq;
|
||||
uint32_t rdi_debug_1;
|
||||
uint32_t rdi_debug_0;
|
||||
uint32_t rdi_test_bus_ctrl;
|
||||
uint32_t rdi_spare;
|
||||
uint32_t reg_update_cmd;
|
||||
};
|
||||
|
||||
struct cam_tfe_rdi_reg_data {
|
||||
uint32_t reg_update_cmd_data;
|
||||
uint32_t epoch_line_cfg;
|
||||
|
||||
uint32_t pixel_pattern_shift;
|
||||
uint32_t pixel_pattern_mask;
|
||||
uint32_t rdi_out_enable_shift;
|
||||
|
||||
uint32_t sof_irq_mask;
|
||||
uint32_t epoch0_irq_mask;
|
||||
uint32_t epoch1_irq_mask;
|
||||
uint32_t eof_irq_mask;
|
||||
uint32_t error_irq_mask0;
|
||||
uint32_t error_irq_mask2;
|
||||
uint32_t subscribe_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM];
|
||||
uint32_t enable_diagnostic_hw;
|
||||
};
|
||||
|
||||
struct cam_tfe_rdi_hw_info {
|
||||
struct cam_tfe_rdi_reg *rdi_reg;
|
||||
struct cam_tfe_rdi_reg_data *reg_data;
|
||||
};
|
||||
|
||||
struct cam_tfe_top_hw_info {
|
||||
struct cam_tfe_top_reg_offset_common *common_reg;
|
||||
struct cam_tfe_camif_hw_info camif_hw_info;
|
||||
struct cam_tfe_rdi_hw_info rdi_hw_info[CAM_TFE_RDI_MAX];
|
||||
uint32_t in_port[CAM_TFE_TOP_IN_PORT_MAX];
|
||||
struct cam_tfe_reg_dump_data reg_dump_data;
|
||||
};
|
||||
|
||||
struct cam_tfe_hw_info {
|
||||
uint32_t top_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM];
|
||||
uint32_t top_irq_clear[CAM_TFE_TOP_IRQ_REG_NUM];
|
||||
uint32_t top_irq_status[CAM_TFE_TOP_IRQ_REG_NUM];
|
||||
uint32_t top_irq_cmd;
|
||||
uint32_t global_clear_bitmask;
|
||||
|
||||
uint32_t bus_irq_mask[CAM_TFE_BUS_MAX_IRQ_REGISTERS];
|
||||
uint32_t bus_irq_clear[CAM_TFE_BUS_MAX_IRQ_REGISTERS];
|
||||
uint32_t bus_irq_status[CAM_TFE_BUS_MAX_IRQ_REGISTERS];
|
||||
uint32_t bus_irq_cmd;
|
||||
|
||||
uint32_t bus_violation_reg;
|
||||
uint32_t bus_overflow_reg;
|
||||
uint32_t bus_image_size_vilation_reg;
|
||||
uint32_t bus_overflow_clear_cmd;
|
||||
uint32_t debug_status_top;
|
||||
|
||||
uint32_t reset_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM];
|
||||
uint32_t error_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM];
|
||||
uint32_t bus_reg_irq_mask[CAM_TFE_TOP_IRQ_REG_NUM];
|
||||
|
||||
uint32_t top_version;
|
||||
void *top_hw_info;
|
||||
|
||||
uint32_t bus_version;
|
||||
void *bus_hw_info;
|
||||
};
|
||||
|
||||
struct cam_tfe_hw_core_info {
|
||||
uint32_t core_index;
|
||||
struct cam_tfe_hw_info *tfe_hw_info;
|
||||
void *top_priv;
|
||||
struct cam_tfe_bus *tfe_bus;
|
||||
void *tasklet_info;
|
||||
struct cam_tfe_irq_evt_payload evt_payload[CAM_TFE_EVT_MAX];
|
||||
struct list_head free_payload_list;
|
||||
bool irq_err_config;
|
||||
uint32_t irq_err_config_cnt;
|
||||
spinlock_t spin_lock;
|
||||
struct completion reset_complete;
|
||||
};
|
||||
|
||||
int cam_tfe_get_hw_caps(void *device_priv,
|
||||
void *get_hw_cap_args, uint32_t arg_size);
|
||||
int cam_tfe_init_hw(void *device_priv,
|
||||
void *init_hw_args, uint32_t arg_size);
|
||||
int cam_tfe_deinit_hw(void *hw_priv,
|
||||
void *deinit_hw_args, uint32_t arg_size);
|
||||
int cam_tfe_reset(void *device_priv,
|
||||
void *reset_core_args, uint32_t arg_size);
|
||||
int cam_tfe_reserve(void *device_priv,
|
||||
void *reserve_args, uint32_t arg_size);
|
||||
int cam_tfe_release(void *device_priv,
|
||||
void *reserve_args, uint32_t arg_size);
|
||||
int cam_tfe_start(void *device_priv,
|
||||
void *start_args, uint32_t arg_size);
|
||||
int cam_tfe_stop(void *device_priv,
|
||||
void *stop_args, uint32_t arg_size);
|
||||
int cam_tfe_read(void *device_priv,
|
||||
void *read_args, uint32_t arg_size);
|
||||
int cam_tfe_write(void *device_priv,
|
||||
void *write_args, uint32_t arg_size);
|
||||
int cam_tfe_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
void *cmd_args, uint32_t arg_size);
|
||||
|
||||
irqreturn_t cam_tfe_irq(int irq_num, void *data);
|
||||
|
||||
int cam_tfe_core_init(struct cam_tfe_hw_core_info *core_info,
|
||||
struct cam_hw_soc_info *soc_info,
|
||||
struct cam_hw_intf *hw_intf,
|
||||
struct cam_tfe_hw_info *tfe_hw_info);
|
||||
|
||||
int cam_tfe_core_deinit(struct cam_tfe_hw_core_info *core_info,
|
||||
struct cam_tfe_hw_info *tfe_hw_info);
|
||||
|
||||
#endif /* _CAM_TFE_CORE_H_ */
|
197
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c
Normal file
197
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.c
Normal file
@@ -0,0 +1,197 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_device.h>
|
||||
#include "cam_tfe_dev.h"
|
||||
#include "cam_tfe_core.h"
|
||||
#include "cam_tfe_soc.h"
|
||||
#include "cam_debug_util.h"
|
||||
|
||||
static struct cam_hw_intf *cam_tfe_hw_list[CAM_TFE_HW_NUM_MAX] = {0, 0, 0};
|
||||
|
||||
static char tfe_dev_name[8];
|
||||
|
||||
int cam_tfe_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cam_hw_info *tfe_hw = NULL;
|
||||
struct cam_hw_intf *tfe_hw_intf = NULL;
|
||||
const struct of_device_id *match_dev = NULL;
|
||||
struct cam_tfe_hw_core_info *core_info = NULL;
|
||||
struct cam_tfe_hw_info *hw_info = NULL;
|
||||
int rc = 0;
|
||||
|
||||
tfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
|
||||
if (!tfe_hw_intf) {
|
||||
rc = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
|
||||
of_property_read_u32(pdev->dev.of_node,
|
||||
"cell-index", &tfe_hw_intf->hw_idx);
|
||||
|
||||
tfe_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||
if (!tfe_hw) {
|
||||
rc = -ENOMEM;
|
||||
goto free_tfe_hw_intf;
|
||||
}
|
||||
|
||||
memset(tfe_dev_name, 0, sizeof(tfe_dev_name));
|
||||
snprintf(tfe_dev_name, sizeof(tfe_dev_name),
|
||||
"tfe%1u", tfe_hw_intf->hw_idx);
|
||||
|
||||
tfe_hw->soc_info.pdev = pdev;
|
||||
tfe_hw->soc_info.dev = &pdev->dev;
|
||||
tfe_hw->soc_info.dev_name = tfe_dev_name;
|
||||
tfe_hw_intf->hw_priv = tfe_hw;
|
||||
tfe_hw_intf->hw_ops.get_hw_caps = cam_tfe_get_hw_caps;
|
||||
tfe_hw_intf->hw_ops.init = cam_tfe_init_hw;
|
||||
tfe_hw_intf->hw_ops.deinit = cam_tfe_deinit_hw;
|
||||
tfe_hw_intf->hw_ops.reset = cam_tfe_reset;
|
||||
tfe_hw_intf->hw_ops.reserve = cam_tfe_reserve;
|
||||
tfe_hw_intf->hw_ops.release = cam_tfe_release;
|
||||
tfe_hw_intf->hw_ops.start = cam_tfe_start;
|
||||
tfe_hw_intf->hw_ops.stop = cam_tfe_stop;
|
||||
tfe_hw_intf->hw_ops.read = cam_tfe_read;
|
||||
tfe_hw_intf->hw_ops.write = cam_tfe_write;
|
||||
tfe_hw_intf->hw_ops.process_cmd = cam_tfe_process_cmd;
|
||||
tfe_hw_intf->hw_type = CAM_ISP_HW_TYPE_TFE;
|
||||
|
||||
CAM_DBG(CAM_ISP, "type %d index %d",
|
||||
tfe_hw_intf->hw_type, tfe_hw_intf->hw_idx);
|
||||
|
||||
platform_set_drvdata(pdev, tfe_hw_intf);
|
||||
|
||||
tfe_hw->core_info = kzalloc(sizeof(struct cam_tfe_hw_core_info),
|
||||
GFP_KERNEL);
|
||||
if (!tfe_hw->core_info) {
|
||||
CAM_DBG(CAM_ISP, "Failed to alloc for core");
|
||||
rc = -ENOMEM;
|
||||
goto free_tfe_hw;
|
||||
}
|
||||
core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info;
|
||||
|
||||
match_dev = of_match_device(pdev->dev.driver->of_match_table,
|
||||
&pdev->dev);
|
||||
if (!match_dev) {
|
||||
CAM_ERR(CAM_ISP, "Of_match Failed");
|
||||
rc = -EINVAL;
|
||||
goto free_core_info;
|
||||
}
|
||||
hw_info = (struct cam_tfe_hw_info *)match_dev->data;
|
||||
core_info->tfe_hw_info = hw_info;
|
||||
core_info->core_index = tfe_hw_intf->hw_idx;
|
||||
|
||||
rc = cam_tfe_init_soc_resources(&tfe_hw->soc_info, cam_tfe_irq,
|
||||
tfe_hw);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_ISP, "Failed to init soc rc=%d", rc);
|
||||
goto free_core_info;
|
||||
}
|
||||
|
||||
rc = cam_tfe_core_init(core_info, &tfe_hw->soc_info,
|
||||
tfe_hw_intf, hw_info);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_ISP, "Failed to init core rc=%d", rc);
|
||||
goto deinit_soc;
|
||||
}
|
||||
|
||||
tfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
|
||||
mutex_init(&tfe_hw->hw_mutex);
|
||||
spin_lock_init(&tfe_hw->hw_lock);
|
||||
init_completion(&tfe_hw->hw_complete);
|
||||
|
||||
if (tfe_hw_intf->hw_idx < CAM_TFE_HW_NUM_MAX)
|
||||
cam_tfe_hw_list[tfe_hw_intf->hw_idx] = tfe_hw_intf;
|
||||
|
||||
cam_tfe_init_hw(tfe_hw, NULL, 0);
|
||||
cam_tfe_deinit_hw(tfe_hw, NULL, 0);
|
||||
|
||||
CAM_DBG(CAM_ISP, "TFE%d probe successful", tfe_hw_intf->hw_idx);
|
||||
|
||||
return rc;
|
||||
|
||||
deinit_soc:
|
||||
if (cam_tfe_deinit_soc_resources(&tfe_hw->soc_info))
|
||||
CAM_ERR(CAM_ISP, "Failed to deinit soc");
|
||||
free_core_info:
|
||||
kfree(tfe_hw->core_info);
|
||||
free_tfe_hw:
|
||||
kfree(tfe_hw);
|
||||
free_tfe_hw_intf:
|
||||
kfree(tfe_hw_intf);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cam_hw_info *tfe_hw = NULL;
|
||||
struct cam_hw_intf *tfe_hw_intf = NULL;
|
||||
struct cam_tfe_hw_core_info *core_info = NULL;
|
||||
int rc = 0;
|
||||
|
||||
tfe_hw_intf = platform_get_drvdata(pdev);
|
||||
if (!tfe_hw_intf) {
|
||||
CAM_ERR(CAM_ISP, "Error! No data in pdev");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_ISP, "type %d index %d",
|
||||
tfe_hw_intf->hw_type, tfe_hw_intf->hw_idx);
|
||||
|
||||
if (tfe_hw_intf->hw_idx < CAM_TFE_HW_NUM_MAX)
|
||||
cam_tfe_hw_list[tfe_hw_intf->hw_idx] = NULL;
|
||||
|
||||
tfe_hw = tfe_hw_intf->hw_priv;
|
||||
if (!tfe_hw) {
|
||||
CAM_ERR(CAM_ISP, "Error! HW data is NULL");
|
||||
rc = -ENODEV;
|
||||
goto free_tfe_hw_intf;
|
||||
}
|
||||
|
||||
core_info = (struct cam_tfe_hw_core_info *)tfe_hw->core_info;
|
||||
if (!core_info) {
|
||||
CAM_ERR(CAM_ISP, "Error! core data NULL");
|
||||
rc = -EINVAL;
|
||||
goto deinit_soc;
|
||||
}
|
||||
|
||||
rc = cam_tfe_core_deinit(core_info, core_info->tfe_hw_info);
|
||||
if (rc < 0)
|
||||
CAM_ERR(CAM_ISP, "Failed to deinit core rc=%d", rc);
|
||||
|
||||
kfree(tfe_hw->core_info);
|
||||
|
||||
deinit_soc:
|
||||
rc = cam_tfe_deinit_soc_resources(&tfe_hw->soc_info);
|
||||
if (rc < 0)
|
||||
CAM_ERR(CAM_ISP, "Failed to deinit soc rc=%d", rc);
|
||||
|
||||
mutex_destroy(&tfe_hw->hw_mutex);
|
||||
kfree(tfe_hw);
|
||||
|
||||
CAM_DBG(CAM_ISP, "TFE%d remove successful", tfe_hw_intf->hw_idx);
|
||||
|
||||
free_tfe_hw_intf:
|
||||
kfree(tfe_hw_intf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_hw_init(struct cam_hw_intf **tfe_hw, uint32_t hw_idx)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (cam_tfe_hw_list[hw_idx]) {
|
||||
*tfe_hw = cam_tfe_hw_list[hw_idx];
|
||||
rc = 0;
|
||||
} else {
|
||||
*tfe_hw = NULL;
|
||||
rc = -ENODEV;
|
||||
}
|
||||
return rc;
|
||||
}
|
38
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.h
Normal file
38
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_dev.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_DEV_H_
|
||||
#define _CAM_TFE_DEV_H_
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/*
|
||||
* cam_tfe_probe()
|
||||
*
|
||||
* @brief: Driver probe function called on Boot
|
||||
*
|
||||
* @pdev: Platform Device pointer
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_probe(struct platform_device *pdev);
|
||||
|
||||
/*
|
||||
* cam_tfe_remove()
|
||||
*
|
||||
* @brief: Driver remove function
|
||||
*
|
||||
* @pdev: Platform Device pointer
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_remove(struct platform_device *pdev);
|
||||
|
||||
int cam_tfe_init_module(void);
|
||||
void cam_tfe_exit_module(void);
|
||||
|
||||
#endif /* _CAM_TFE_DEV_H_ */
|
31
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_irq.h
Normal file
31
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_irq.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_IRQ_H_
|
||||
#define _CAM_TFE_IRQ_H_
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define CAM_TFE_TOP_IRQ_REG_NUM 3
|
||||
|
||||
/*
|
||||
* cam_tfe_irq_config()
|
||||
*
|
||||
* @brief: Tfe hw irq configuration
|
||||
*
|
||||
* @tfe_core_data: tfe core pointer
|
||||
* @irq_mask: Irq mask for enable interrupts or disable
|
||||
* @num_reg: Number irq mask registers
|
||||
* @enable: enable = 1, enable the given irq mask interrupts
|
||||
* enable = 0 disable the given irq mask interrupts
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_irq_config(void *tfe_core_data,
|
||||
uint32_t *irq_mask, uint32_t num_reg, bool enable);
|
||||
|
||||
|
||||
#endif /* _CAM_TFE_IRQ_H_ */
|
240
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c
Normal file
240
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c
Normal file
@@ -0,0 +1,240 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cam_tfe_soc.h"
|
||||
#include "cam_debug_util.h"
|
||||
|
||||
static bool cam_tfe_cpas_cb(uint32_t client_handle, void *userdata,
|
||||
struct cam_cpas_irq_data *irq_data)
|
||||
{
|
||||
bool error_handled = false;
|
||||
|
||||
if (!irq_data)
|
||||
return error_handled;
|
||||
|
||||
CAM_DBG(CAM_ISP, "CPSS error type=%d ",
|
||||
irq_data->irq_type);
|
||||
|
||||
return error_handled;
|
||||
}
|
||||
|
||||
int cam_tfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
irq_handler_t tfe_irq_handler, void *irq_data)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_soc_private *soc_private;
|
||||
struct cam_cpas_register_params cpas_register_param;
|
||||
|
||||
soc_private = kzalloc(sizeof(struct cam_tfe_soc_private),
|
||||
GFP_KERNEL);
|
||||
if (!soc_private) {
|
||||
CAM_DBG(CAM_ISP, "Error! soc_private Alloc Failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
soc_info->soc_private = soc_private;
|
||||
|
||||
rc = cam_soc_util_get_dt_properties(soc_info);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Error! get DT properties failed rc=%d", rc);
|
||||
goto free_soc_private;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_get_option_clk_by_name(soc_info,
|
||||
CAM_TFE_DSP_CLK_NAME, &soc_private->dsp_clk,
|
||||
&soc_private->dsp_clk_index, &soc_private->dsp_clk_rate);
|
||||
if (rc)
|
||||
CAM_WARN(CAM_ISP, "Option clk get failed with rc %d", rc);
|
||||
|
||||
rc = cam_soc_util_request_platform_resource(soc_info, tfe_irq_handler,
|
||||
irq_data);
|
||||
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_ISP,
|
||||
"Error! Request platform resources failed rc=%d", rc);
|
||||
goto free_soc_private;
|
||||
}
|
||||
|
||||
memset(&cpas_register_param, 0, sizeof(cpas_register_param));
|
||||
strlcpy(cpas_register_param.identifier, "tfe",
|
||||
CAM_HW_IDENTIFIER_LENGTH);
|
||||
cpas_register_param.cell_index = soc_info->index;
|
||||
cpas_register_param.dev = soc_info->dev;
|
||||
cpas_register_param.cam_cpas_client_cb = cam_tfe_cpas_cb;
|
||||
cpas_register_param.userdata = soc_info;
|
||||
rc = cam_cpas_register_client(&cpas_register_param);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
|
||||
goto release_soc;
|
||||
}
|
||||
|
||||
soc_private->cpas_handle = cpas_register_param.client_handle;
|
||||
|
||||
return rc;
|
||||
|
||||
release_soc:
|
||||
cam_soc_util_release_platform_resource(soc_info);
|
||||
free_soc_private:
|
||||
kfree(soc_private);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_soc_private *soc_private;
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_ISP, "Error! soc_info NULL");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
soc_private = soc_info->soc_private;
|
||||
if (!soc_private) {
|
||||
CAM_ERR(CAM_ISP, "Error! soc_private NULL");
|
||||
return -ENODEV;
|
||||
}
|
||||
rc = cam_cpas_unregister_client(soc_private->cpas_handle);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "CPAS0 unregistration failed rc=%d", rc);
|
||||
|
||||
rc = cam_soc_util_release_platform_resource(soc_info);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP,
|
||||
"Error! Release platform resource failed rc=%d", rc);
|
||||
|
||||
|
||||
rc = cam_soc_util_clk_put(&soc_private->dsp_clk);
|
||||
if (rc < 0)
|
||||
CAM_ERR(CAM_ISP,
|
||||
"Error Put dsp clk failed rc=%d", rc);
|
||||
|
||||
kfree(soc_private);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_soc_private *soc_private;
|
||||
struct cam_ahb_vote ahb_vote;
|
||||
struct cam_axi_vote axi_vote = {0};
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_ISP, "Error! Invalid params");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
soc_private = soc_info->soc_private;
|
||||
|
||||
ahb_vote.type = CAM_VOTE_ABSOLUTE;
|
||||
ahb_vote.vote.level = CAM_SVS_VOTE;
|
||||
axi_vote.num_paths = 1;
|
||||
axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_IFE_VID;
|
||||
axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE;
|
||||
axi_vote.axi_path[0].camnoc_bw = 10640000000L;
|
||||
axi_vote.axi_path[0].mnoc_ab_bw = 10640000000L;
|
||||
axi_vote.axi_path[0].mnoc_ib_bw = 10640000000L;
|
||||
|
||||
rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Error! CPAS0 start failed rc=%d", rc);
|
||||
rc = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_enable_platform_resource(soc_info, true,
|
||||
CAM_TURBO_VOTE, true);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Error! enable platform failed rc=%d", rc);
|
||||
goto stop_cpas;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
stop_cpas:
|
||||
cam_cpas_stop(soc_private->cpas_handle);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_soc_enable_clk(struct cam_hw_soc_info *soc_info,
|
||||
const char *clk_name)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_soc_private *soc_private;
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_ISP, "Error Invalid params");
|
||||
rc = -EINVAL;
|
||||
return rc;
|
||||
}
|
||||
soc_private = soc_info->soc_private;
|
||||
|
||||
if (strcmp(clk_name, CAM_TFE_DSP_CLK_NAME) == 0) {
|
||||
rc = cam_soc_util_clk_enable(soc_private->dsp_clk,
|
||||
CAM_TFE_DSP_CLK_NAME, soc_private->dsp_clk_rate);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP,
|
||||
"Error enable dsp clk failed rc=%d", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_tfe_soc_disable_clk(struct cam_hw_soc_info *soc_info,
|
||||
const char *clk_name)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_soc_private *soc_private;
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_ISP, "Error Invalid params");
|
||||
rc = -EINVAL;
|
||||
return rc;
|
||||
}
|
||||
soc_private = soc_info->soc_private;
|
||||
|
||||
if (strcmp(clk_name, CAM_TFE_DSP_CLK_NAME) == 0) {
|
||||
rc = cam_soc_util_clk_disable(soc_private->dsp_clk,
|
||||
CAM_TFE_DSP_CLK_NAME);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP,
|
||||
"Error enable dsp clk failed rc=%d", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int cam_tfe_disable_soc_resources(struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_tfe_soc_private *soc_private;
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_ISP, "Error! Invalid params");
|
||||
rc = -EINVAL;
|
||||
return rc;
|
||||
}
|
||||
soc_private = soc_info->soc_private;
|
||||
|
||||
rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Disable platform failed rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cam_cpas_stop(soc_private->cpas_handle);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
117
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h
Normal file
117
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TFE_SOC_H_
|
||||
#define _CAM_TFE_SOC_H_
|
||||
|
||||
#include "cam_soc_util.h"
|
||||
#include "cam_isp_hw.h"
|
||||
|
||||
#define CAM_TFE_DSP_CLK_NAME "tfe_dsp_clk"
|
||||
|
||||
enum cam_cpas_handle_id {
|
||||
CAM_CPAS_HANDLE_CAMIF,
|
||||
CAM_CPAS_HANDLE_RAW,
|
||||
CAM_CPAS_HANDLE_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_tfe_soc_private:
|
||||
*
|
||||
* @Brief: Private SOC data specific to TFE HW Driver
|
||||
*
|
||||
* @cpas_handle: Handle returned on registering with CPAS driver.
|
||||
* This handle is used for all further interface
|
||||
* with CPAS.
|
||||
* @cpas_version: Has cpas version read from Hardware
|
||||
*/
|
||||
struct cam_tfe_soc_private {
|
||||
uint32_t cpas_handle;
|
||||
uint32_t cpas_version;
|
||||
struct clk *dsp_clk;
|
||||
int32_t dsp_clk_index;
|
||||
int32_t dsp_clk_rate;
|
||||
};
|
||||
|
||||
/*
|
||||
* cam_tfe_init_soc_resources()
|
||||
*
|
||||
* @Brief: Initialize SOC resources including private data
|
||||
*
|
||||
* @soc_info: Device soc information
|
||||
* @handler: Irq handler function pointer
|
||||
* @irq_data: Irq handler function Callback data
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
irq_handler_t tfe_irq_handler, void *irq_data);
|
||||
|
||||
/*
|
||||
* cam_tfe_deinit_soc_resources()
|
||||
*
|
||||
* @Brief: Deinitialize SOC resources including private data
|
||||
*
|
||||
* @soc_info: Device soc information
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
/*
|
||||
* cam_tfe_enable_soc_resources()
|
||||
*
|
||||
* @brief: Enable regulator, irq resources, start CPAS
|
||||
*
|
||||
* @soc_info: Device soc information
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_enable_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
/*
|
||||
* cam_tfe_disable_soc_resources()
|
||||
*
|
||||
* @brief: Disable regulator, irq resources, stop CPAS
|
||||
*
|
||||
* @soc_info: Device soc information
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_disable_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
/*
|
||||
* cam_tfe_soc_enable_clk()
|
||||
*
|
||||
* @brief: Enable clock with given name
|
||||
*
|
||||
* @soc_info: Device soc information
|
||||
* @clk_name: Name of clock to enable
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_soc_enable_clk(struct cam_hw_soc_info *soc_info,
|
||||
const char *clk_name);
|
||||
|
||||
/*
|
||||
* cam_tfe_soc_disable_dsp_clk()
|
||||
*
|
||||
* @brief: Disable clock with given name
|
||||
*
|
||||
* @soc_info: Device soc information
|
||||
* @clk_name: Name of clock to enable
|
||||
*
|
||||
* @Return: 0: Success
|
||||
* Non-zero: Failure
|
||||
*/
|
||||
int cam_tfe_soc_disable_clk(struct cam_hw_soc_info *soc_info,
|
||||
const char *clk_name);
|
||||
|
||||
#endif /* _CAM_TFE_SOC_H_ */
|
15
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile
Normal file
15
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/
|
||||
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/
|
||||
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += cam_top_tpg_dev.o cam_top_tpg_soc.o cam_top_tpg_core.o
|
||||
obj-$(CONFIG_SPECTRA_CAMERA) += cam_top_tpg_v1.o
|
671
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c
Normal file
671
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c
Normal file
@@ -0,0 +1,671 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <media/cam_tfe.h>
|
||||
#include <media/cam_defs.h>
|
||||
|
||||
#include "cam_top_tpg_core.h"
|
||||
#include "cam_soc_util.h"
|
||||
#include "cam_io_util.h"
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_cpas_api.h"
|
||||
|
||||
|
||||
static uint32_t tpg_num_dt_map[CAM_TOP_TPG_MAX_SUPPORTED_DT] = {
|
||||
0,
|
||||
3,
|
||||
1,
|
||||
2
|
||||
};
|
||||
|
||||
static int cam_top_tpg_get_format(uint32_t in_format,
|
||||
uint32_t *tpg_encode_format)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (in_format) {
|
||||
case CAM_FORMAT_MIPI_RAW_6:
|
||||
*tpg_encode_format = 0;
|
||||
break;
|
||||
case CAM_FORMAT_MIPI_RAW_8:
|
||||
*tpg_encode_format = 1;
|
||||
break;
|
||||
case CAM_FORMAT_MIPI_RAW_10:
|
||||
*tpg_encode_format = 2;
|
||||
break;
|
||||
case CAM_FORMAT_MIPI_RAW_12:
|
||||
*tpg_encode_format = 3;
|
||||
break;
|
||||
case CAM_FORMAT_MIPI_RAW_14:
|
||||
*tpg_encode_format = 4;
|
||||
break;
|
||||
case CAM_FORMAT_MIPI_RAW_16:
|
||||
*tpg_encode_format = 4;
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "Unsupported input encode format %d",
|
||||
in_format);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_get_hw_caps(void *hw_priv,
|
||||
void *get_hw_cap_args, uint32_t arg_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_hw_caps *hw_caps;
|
||||
struct cam_top_tpg_hw *tpg_hw;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
|
||||
if (!hw_priv || !get_hw_cap_args) {
|
||||
CAM_ERR(CAM_ISP, "TPG: Invalid args");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_hw_info = (struct cam_hw_info *)hw_priv;
|
||||
tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
|
||||
hw_caps = (struct cam_top_tpg_hw_caps *) get_hw_cap_args;
|
||||
|
||||
hw_caps->major_version = tpg_hw->tpg_info->tpg_reg->major_version;
|
||||
hw_caps->minor_version = tpg_hw->tpg_info->tpg_reg->minor_version;
|
||||
hw_caps->version_incr = tpg_hw->tpg_info->tpg_reg->version_incr;
|
||||
|
||||
CAM_DBG(CAM_ISP,
|
||||
"TPG:%d major:%d minor:%d ver :%d",
|
||||
tpg_hw->hw_intf->hw_idx, hw_caps->major_version,
|
||||
hw_caps->minor_version, hw_caps->version_incr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_reserve(void *hw_priv,
|
||||
void *reserve_args, uint32_t arg_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_hw *tpg_hw;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct cam_top_tpg_hw_reserve_resource_args *reserv;
|
||||
struct cam_top_tpg_cfg *tpg_data;
|
||||
uint32_t encode_format = 0;
|
||||
uint32_t i;
|
||||
|
||||
if (!hw_priv || !reserve_args || (arg_size !=
|
||||
sizeof(struct cam_top_tpg_hw_reserve_resource_args))) {
|
||||
CAM_ERR(CAM_ISP, "TPG: Invalid args");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_hw_info = (struct cam_hw_info *)hw_priv;
|
||||
tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
|
||||
reserv = (struct cam_top_tpg_hw_reserve_resource_args *)reserve_args;
|
||||
|
||||
if (reserv->num_inport <= 0 ||
|
||||
reserv->num_inport > CAM_TOP_TPG_MAX_SUPPORTED_DT) {
|
||||
CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG: %u invalid input num port:%d",
|
||||
tpg_hw->hw_intf->hw_idx, reserv->num_inport);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&tpg_hw->hw_info->hw_mutex);
|
||||
if (tpg_hw->tpg_res.res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((reserv->in_port[0]->vc > 0xF) ||
|
||||
(reserv->in_port[0]->lane_num <= 0 ||
|
||||
reserv->in_port[0]->lane_num > 4) ||
|
||||
(reserv->in_port[0]->pix_pattern > 4) ||
|
||||
(reserv->in_port[0]->lane_type >= 2)) {
|
||||
CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG:%u invalid input %d %d %d %d",
|
||||
tpg_hw->hw_intf->hw_idx, reserv->in_port[0]->vc,
|
||||
reserv->in_port[0]->lane_num,
|
||||
reserv->in_port[0]->pix_pattern,
|
||||
reserv->in_port[0]->lane_type);
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
rc = cam_top_tpg_get_format(reserv->in_port[0]->format,
|
||||
&encode_format);
|
||||
if (rc)
|
||||
goto error;
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG: %u enter", tpg_hw->hw_intf->hw_idx);
|
||||
|
||||
tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv;
|
||||
tpg_data->vc_num = reserv->in_port[0]->vc;
|
||||
tpg_data->phy_sel = reserv->in_port[0]->lane_type;
|
||||
tpg_data->num_active_lanes = reserv->in_port[0]->lane_num;
|
||||
tpg_data->h_blank_count = reserv->in_port[0]->sensor_hbi;
|
||||
tpg_data->v_blank_count = reserv->in_port[0]->sensor_vbi;
|
||||
tpg_data->pix_pattern = reserv->in_port[0]->pix_pattern;
|
||||
tpg_data->dt_cfg[0].data_type = reserv->in_port[0]->dt;
|
||||
tpg_data->dt_cfg[0].frame_height = reserv->in_port[0]->height;
|
||||
if (reserv->in_port[0]->usage_type)
|
||||
tpg_data->dt_cfg[0].frame_width =
|
||||
((reserv->in_port[0]->right_end -
|
||||
reserv->in_port[0]->left_start) + 1);
|
||||
else
|
||||
tpg_data->dt_cfg[0].frame_width =
|
||||
reserv->in_port[0]->left_width;
|
||||
tpg_data->dt_cfg[0].encode_format = encode_format;
|
||||
tpg_data->num_active_dts = 1;
|
||||
|
||||
CAM_DBG(CAM_ISP,
|
||||
"TPG:%u vc_num:%d dt:%d phy:%d lines:%d pattern:%d format:%d",
|
||||
tpg_hw->hw_intf->hw_idx,
|
||||
tpg_data->vc_num, tpg_data->dt_cfg[0].data_type,
|
||||
tpg_data->phy_sel, tpg_data->num_active_lanes,
|
||||
tpg_data->pix_pattern,
|
||||
tpg_data->dt_cfg[0].encode_format);
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG:%u height:%d width:%d h blank:%d v blank:%d",
|
||||
tpg_hw->hw_intf->hw_idx,
|
||||
tpg_data->dt_cfg[0].frame_height,
|
||||
tpg_data->dt_cfg[0].frame_width,
|
||||
tpg_data->h_blank_count,
|
||||
tpg_data->v_blank_count);
|
||||
|
||||
if (reserv->num_inport == 1)
|
||||
goto end;
|
||||
|
||||
for (i = 1; i < reserv->num_inport; i++) {
|
||||
if ((tpg_data->vc_num != reserv->in_port[i]->vc) ||
|
||||
(tpg_data->phy_sel != reserv->in_port[i]->lane_type) ||
|
||||
(tpg_data->num_active_lanes !=
|
||||
reserv->in_port[i]->lane_num) ||
|
||||
(tpg_data->pix_pattern !=
|
||||
reserv->in_port[i]->pix_pattern)) {
|
||||
CAM_ERR_RATE_LIMIT(CAM_ISP,
|
||||
"TPG: %u invalid DT config for tpg",
|
||||
tpg_hw->hw_intf->hw_idx);
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
rc = cam_top_tpg_get_format(reserv->in_port[0]->format,
|
||||
&encode_format);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
tpg_data->dt_cfg[i].data_type = reserv->in_port[i]->dt;
|
||||
tpg_data->dt_cfg[i].frame_height =
|
||||
reserv->in_port[i]->height;
|
||||
tpg_data->dt_cfg[i].frame_width =
|
||||
reserv->in_port[i]->left_width;
|
||||
tpg_data->dt_cfg[i].encode_format = encode_format;
|
||||
tpg_data->num_active_dts++;
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG:%u height:%d width:%d dt:%d format:%d",
|
||||
tpg_hw->hw_intf->hw_idx,
|
||||
tpg_data->dt_cfg[i].frame_height,
|
||||
tpg_data->dt_cfg[i].frame_width,
|
||||
tpg_data->dt_cfg[i].data_type,
|
||||
tpg_data->dt_cfg[i].encode_format);
|
||||
|
||||
}
|
||||
end:
|
||||
reserv->node_res = &tpg_hw->tpg_res;
|
||||
tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
|
||||
error:
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
CAM_DBG(CAM_ISP, "exit rc %u", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_release(void *hw_priv,
|
||||
void *release_args, uint32_t arg_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_hw *tpg_hw;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct cam_top_tpg_cfg *tpg_data;
|
||||
struct cam_isp_resource_node *tpg_res;
|
||||
|
||||
if (!hw_priv || !release_args ||
|
||||
(arg_size != sizeof(struct cam_isp_resource_node))) {
|
||||
CAM_ERR(CAM_ISP, "TPG: Invalid args");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_hw_info = (struct cam_hw_info *)hw_priv;
|
||||
tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
|
||||
tpg_res = (struct cam_isp_resource_node *)release_args;
|
||||
|
||||
mutex_lock(&tpg_hw->hw_info->hw_mutex);
|
||||
if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) ||
|
||||
(tpg_res->res_state <= CAM_ISP_RESOURCE_STATE_AVAILABLE)) {
|
||||
CAM_ERR(CAM_ISP, "TPG:%d Invalid res type:%d res_state:%d",
|
||||
tpg_hw->hw_intf->hw_idx, tpg_res->res_type,
|
||||
tpg_res->res_state);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG:%d res type :%d",
|
||||
tpg_hw->hw_intf->hw_idx, tpg_res->res_type);
|
||||
|
||||
tpg_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
|
||||
tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_priv;
|
||||
memset(tpg_data, 0, sizeof(struct cam_top_tpg_cfg));
|
||||
|
||||
end:
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_init_hw(void *hw_priv,
|
||||
void *init_args, uint32_t arg_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_hw *tpg_hw;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct cam_isp_resource_node *tpg_res;
|
||||
const struct cam_top_tpg_reg_offset *tpg_reg;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
uint32_t val, clk_lvl;
|
||||
|
||||
if (!hw_priv || !init_args ||
|
||||
(arg_size != sizeof(struct cam_isp_resource_node))) {
|
||||
CAM_ERR(CAM_ISP, "TPG: Invalid args");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_hw_info = (struct cam_hw_info *)hw_priv;
|
||||
tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
|
||||
tpg_res = (struct cam_isp_resource_node *)init_args;
|
||||
tpg_reg = tpg_hw->tpg_info->tpg_reg;
|
||||
soc_info = &tpg_hw->hw_info->soc_info;
|
||||
|
||||
if (tpg_res->res_type != CAM_ISP_RESOURCE_TPG) {
|
||||
CAM_ERR(CAM_ISP, "TPG:%d Invalid res type state %d",
|
||||
tpg_hw->hw_intf->hw_idx,
|
||||
tpg_res->res_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG:%d init HW res type :%d",
|
||||
tpg_hw->hw_intf->hw_idx, tpg_res->res_type);
|
||||
mutex_lock(&tpg_hw->hw_info->hw_mutex);
|
||||
/* overflow check before increment */
|
||||
if (tpg_hw->hw_info->open_count == UINT_MAX) {
|
||||
CAM_ERR(CAM_ISP, "TPG:%d Open count reached max",
|
||||
tpg_hw->hw_intf->hw_idx);
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Increment ref Count */
|
||||
tpg_hw->hw_info->open_count++;
|
||||
if (tpg_hw->hw_info->open_count > 1) {
|
||||
CAM_DBG(CAM_ISP, "TPG hw has already been enabled");
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_get_clk_level(soc_info, tpg_hw->clk_rate,
|
||||
soc_info->src_clk_idx, &clk_lvl);
|
||||
CAM_DBG(CAM_ISP, "TPG phy clock level %u", clk_lvl);
|
||||
|
||||
rc = cam_top_tpg_enable_soc_resources(soc_info, clk_lvl);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "TPG:%d Enable SOC failed",
|
||||
tpg_hw->hw_intf->hw_idx);
|
||||
goto err;
|
||||
}
|
||||
|
||||
tpg_hw->hw_info->hw_state = CAM_HW_STATE_POWER_UP;
|
||||
|
||||
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_hw_version);
|
||||
CAM_DBG(CAM_ISP, "TPG:%d TPG HW version: 0x%x",
|
||||
tpg_hw->hw_intf->hw_idx, val);
|
||||
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
return rc;
|
||||
|
||||
err:
|
||||
tpg_hw->hw_info->open_count--;
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_deinit_hw(void *hw_priv,
|
||||
void *deinit_args, uint32_t arg_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_hw *tpg_hw;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct cam_isp_resource_node *tpg_res;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
|
||||
if (!hw_priv || !deinit_args ||
|
||||
(arg_size != sizeof(struct cam_isp_resource_node))) {
|
||||
CAM_ERR(CAM_ISP, "TPG:Invalid arguments");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_res = (struct cam_isp_resource_node *)deinit_args;
|
||||
tpg_hw_info = (struct cam_hw_info *)hw_priv;
|
||||
tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
|
||||
|
||||
if (tpg_res->res_type != CAM_ISP_RESOURCE_TPG) {
|
||||
CAM_ERR(CAM_ISP, "TPG:%d Invalid Res type %d",
|
||||
tpg_hw->hw_intf->hw_idx,
|
||||
tpg_res->res_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&tpg_hw->hw_info->hw_mutex);
|
||||
/* Check for refcount */
|
||||
if (!tpg_hw->hw_info->open_count) {
|
||||
CAM_WARN(CAM_ISP, "Unbalanced disable_hw");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Decrement ref Count */
|
||||
tpg_hw->hw_info->open_count--;
|
||||
if (tpg_hw->hw_info->open_count) {
|
||||
rc = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
soc_info = &tpg_hw->hw_info->soc_info;
|
||||
rc = cam_top_tpg_disable_soc_resources(soc_info);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "TPG:%d Disable SOC failed",
|
||||
tpg_hw->hw_intf->hw_idx);
|
||||
|
||||
tpg_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
|
||||
CAM_DBG(CAM_ISP, "TPG:%d deint completed", tpg_hw->hw_intf->hw_idx);
|
||||
|
||||
end:
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_start(void *hw_priv, void *start_args,
|
||||
uint32_t arg_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_hw *tpg_hw;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
struct cam_isp_resource_node *tpg_res;
|
||||
const struct cam_top_tpg_reg_offset *tpg_reg;
|
||||
struct cam_top_tpg_cfg *tpg_data;
|
||||
uint32_t i, val;
|
||||
|
||||
if (!hw_priv || !start_args ||
|
||||
(arg_size != sizeof(struct cam_isp_resource_node))) {
|
||||
CAM_ERR(CAM_ISP, "TPG: Invalid args");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_hw_info = (struct cam_hw_info *)hw_priv;
|
||||
tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
|
||||
tpg_reg = tpg_hw->tpg_info->tpg_reg;
|
||||
tpg_res = (struct cam_isp_resource_node *)start_args;
|
||||
tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_priv;
|
||||
soc_info = &tpg_hw->hw_info->soc_info;
|
||||
|
||||
if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) ||
|
||||
(tpg_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) {
|
||||
CAM_ERR(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d",
|
||||
tpg_hw->hw_intf->hw_idx,
|
||||
tpg_res->res_type, tpg_res->res_state);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
cam_io_w_mb(0x12345678, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_lfsr_seed);
|
||||
|
||||
for (i = 0; i < tpg_data->num_active_dts; i++) {
|
||||
val = (((tpg_data->dt_cfg[i].frame_width & 0xFFFF) << 16) |
|
||||
(tpg_data->dt_cfg[i].frame_height & 0x3FFF));
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_dt_0_cfg_0 + 0x10 * i);
|
||||
cam_io_w_mb(tpg_data->dt_cfg[i].data_type,
|
||||
soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_dt_0_cfg_1 + 0x10 * i);
|
||||
val = ((tpg_data->dt_cfg[i].encode_format & 0xF) <<
|
||||
tpg_reg->tpg_dt_encode_format_shift) |
|
||||
tpg_reg->tpg_payload_mode_color;
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_dt_0_cfg_2 + 0x10 * i);
|
||||
}
|
||||
|
||||
val = (tpg_num_dt_map[tpg_data->num_active_dts-1] <<
|
||||
tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num;
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg0);
|
||||
|
||||
/* HBlank count 500 and V blank count is 600 */
|
||||
cam_io_w_mb(0x2581F4,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1);
|
||||
|
||||
val = (1 << tpg_reg->tpg_split_en_shift);
|
||||
cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_common_gen_cfg);
|
||||
cam_io_w_mb(0xAFFF,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg);
|
||||
CAM_DBG(CAM_ISP, "TPG:%d set TPG VBI to 0xAFFF",
|
||||
tpg_hw->hw_intf->hw_idx);
|
||||
|
||||
/* Set the TOP tpg mux sel*/
|
||||
cam_io_w_mb((1 << tpg_hw->hw_intf->hw_idx),
|
||||
soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset);
|
||||
|
||||
val = ((tpg_data->num_active_lanes - 1) <<
|
||||
tpg_reg->tpg_num_active_lines_shift) |
|
||||
(1 << tpg_reg->tpg_fe_pkt_en_shift) |
|
||||
(1 << tpg_reg->tpg_fs_pkt_en_shift) |
|
||||
(tpg_data->phy_sel << tpg_reg->tpg_phy_sel_shift_val) |
|
||||
(1 << tpg_reg->tpg_en_shift_val);
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl);
|
||||
|
||||
tpg_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG:%d started", tpg_hw->hw_intf->hw_idx);
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_stop(void *hw_priv,
|
||||
void *stop_args, uint32_t arg_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_hw *tpg_hw;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
struct cam_isp_resource_node *tpg_res;
|
||||
const struct cam_top_tpg_reg_offset *tpg_reg;
|
||||
struct cam_top_tpg_cfg *tpg_data;
|
||||
|
||||
if (!hw_priv || !stop_args ||
|
||||
(arg_size != sizeof(struct cam_isp_resource_node))) {
|
||||
CAM_ERR(CAM_ISP, "TPG: Invalid args");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_hw_info = (struct cam_hw_info *)hw_priv;
|
||||
tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
|
||||
tpg_reg = tpg_hw->tpg_info->tpg_reg;
|
||||
tpg_res = (struct cam_isp_resource_node *) stop_args;
|
||||
tpg_data = (struct cam_top_tpg_cfg *)tpg_res->res_state;
|
||||
soc_info = &tpg_hw->hw_info->soc_info;
|
||||
|
||||
if ((tpg_res->res_type != CAM_ISP_RESOURCE_TPG) ||
|
||||
(tpg_res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING)) {
|
||||
CAM_DBG(CAM_ISP, "TPG:%d Invalid Res type:%d res_state:%d",
|
||||
tpg_hw->hw_intf->hw_idx,
|
||||
tpg_res->res_type, tpg_res->res_state);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_ctrl);
|
||||
|
||||
tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_read(void *hw_priv,
|
||||
void *read_args, uint32_t arg_size)
|
||||
{
|
||||
CAM_ERR(CAM_ISP, "TPG: un supported");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_write(void *hw_priv,
|
||||
void *write_args, uint32_t arg_size)
|
||||
{
|
||||
CAM_ERR(CAM_ISP, "TPG: un supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_set_phy_clock(
|
||||
struct cam_top_tpg_hw *csid_hw, void *cmd_args)
|
||||
{
|
||||
struct cam_top_tpg_clock_update_args *clk_update = NULL;
|
||||
|
||||
if (!csid_hw)
|
||||
return -EINVAL;
|
||||
|
||||
clk_update =
|
||||
(struct cam_top_tpg_clock_update_args *)cmd_args;
|
||||
|
||||
csid_hw->clk_rate = clk_update->clk_rate;
|
||||
CAM_DBG(CAM_ISP, "CSI PHY clock rate %llu", csid_hw->clk_rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_process_cmd(void *hw_priv,
|
||||
uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_hw *tpg_hw;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
|
||||
if (!hw_priv || !cmd_args) {
|
||||
CAM_ERR(CAM_ISP, "CSID: Invalid arguments");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_hw_info = (struct cam_hw_info *)hw_priv;
|
||||
tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
|
||||
|
||||
switch (cmd_type) {
|
||||
case CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE:
|
||||
rc = cam_top_tpg_set_phy_clock(tpg_hw, cmd_args);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "TPG:%d unsupported cmd:%d",
|
||||
tpg_hw->hw_intf->hw_idx, cmd_type);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf,
|
||||
uint32_t tpg_idx)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
struct cam_top_tpg_cfg *tpg_data;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct cam_top_tpg_hw *tpg_hw = NULL;
|
||||
uint32_t val = 0;
|
||||
|
||||
if (tpg_idx >= CAM_TOP_TPG_HW_NUM_MAX) {
|
||||
CAM_ERR(CAM_ISP, "Invalid tpg index:%d", tpg_idx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
tpg_hw_info = (struct cam_hw_info *)tpg_hw_intf->hw_priv;
|
||||
tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
|
||||
|
||||
tpg_hw->hw_intf = tpg_hw_intf;
|
||||
tpg_hw->hw_info = tpg_hw_info;
|
||||
|
||||
CAM_DBG(CAM_ISP, "type %d index %d",
|
||||
tpg_hw->hw_intf->hw_type, tpg_idx);
|
||||
|
||||
tpg_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
|
||||
mutex_init(&tpg_hw->hw_info->hw_mutex);
|
||||
spin_lock_init(&tpg_hw->hw_info->hw_lock);
|
||||
spin_lock_init(&tpg_hw->lock_state);
|
||||
init_completion(&tpg_hw->hw_info->hw_complete);
|
||||
|
||||
init_completion(&tpg_hw->tpg_complete);
|
||||
|
||||
rc = cam_top_tpg_init_soc_resources(&tpg_hw->hw_info->soc_info,
|
||||
tpg_hw);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_ISP, "TPG:%d Failed to init_soc", tpg_idx);
|
||||
goto err;
|
||||
}
|
||||
|
||||
tpg_hw->hw_intf->hw_ops.get_hw_caps = cam_top_tpg_get_hw_caps;
|
||||
tpg_hw->hw_intf->hw_ops.init = cam_top_tpg_init_hw;
|
||||
tpg_hw->hw_intf->hw_ops.deinit = cam_top_tpg_deinit_hw;
|
||||
tpg_hw->hw_intf->hw_ops.reset = NULL;
|
||||
tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_reserve;
|
||||
tpg_hw->hw_intf->hw_ops.release = cam_top_tpg_release;
|
||||
tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_start;
|
||||
tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_stop;
|
||||
tpg_hw->hw_intf->hw_ops.read = cam_top_tpg_read;
|
||||
tpg_hw->hw_intf->hw_ops.write = cam_top_tpg_write;
|
||||
tpg_hw->hw_intf->hw_ops.process_cmd = cam_top_tpg_process_cmd;
|
||||
|
||||
tpg_hw->tpg_res.res_type = CAM_ISP_RESOURCE_TPG;
|
||||
tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
|
||||
tpg_hw->tpg_res.hw_intf = tpg_hw->hw_intf;
|
||||
tpg_data = kzalloc(sizeof(*tpg_data), GFP_KERNEL);
|
||||
if (!tpg_data) {
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
tpg_hw->tpg_res.res_priv = tpg_data;
|
||||
|
||||
cam_top_tpg_enable_soc_resources(&tpg_hw->hw_info->soc_info,
|
||||
CAM_SVS_VOTE);
|
||||
|
||||
val = cam_io_r_mb(tpg_hw->hw_info->soc_info.reg_map[0].mem_base +
|
||||
tpg_hw->tpg_info->tpg_reg->tpg_hw_version);
|
||||
CAM_DBG(CAM_ISP, "TPG:%d TPG HW version: 0x%x",
|
||||
tpg_hw->hw_intf->hw_idx, val);
|
||||
|
||||
cam_top_tpg_disable_soc_resources(&tpg_hw->hw_info->soc_info);
|
||||
err:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_top_tpg_hw_deinit(struct cam_top_tpg_hw *top_tpg_hw)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
|
||||
if (!top_tpg_hw) {
|
||||
CAM_ERR(CAM_ISP, "Invalid param");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* release the privdate data memory from resources */
|
||||
kfree(top_tpg_hw->tpg_res.res_priv);
|
||||
cam_top_tpg_deinit_soc_resources(&top_tpg_hw->hw_info->soc_info);
|
||||
|
||||
return 0;
|
||||
}
|
153
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h
Normal file
153
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_HW_H_
|
||||
#define _CAM_TOP_TPG_HW_H_
|
||||
|
||||
#include "cam_hw.h"
|
||||
#include "cam_top_tpg_hw_intf.h"
|
||||
#include "cam_top_tpg_soc.h"
|
||||
|
||||
enum cam_top_tpg_encode_format {
|
||||
CAM_TOP_TPG_ENCODE_FORMAT_RAW6,
|
||||
CAM_TOP_TPG_ENCODE_FORMAT_RAW8,
|
||||
CAM_TOP_TPG_ENCODE_FORMAT_RAW10,
|
||||
CAM_TOP_TPG_ENCODE_FORMAT_RAW12,
|
||||
CAM_TOP_TPG_ENCODE_FORMAT_RAW14,
|
||||
CAM_TOP_TPG_ENCODE_FORMAT_RAW16,
|
||||
CAM_TOP_TPG_ENCODE_FORMAT_MAX,
|
||||
};
|
||||
|
||||
struct cam_top_tpg_reg_offset {
|
||||
uint32_t tpg_hw_version;
|
||||
uint32_t tpg_hw_status;
|
||||
uint32_t tpg_ctrl;
|
||||
uint32_t tpg_vc_cfg0;
|
||||
uint32_t tpg_vc_cfg1;
|
||||
uint32_t tpg_lfsr_seed;
|
||||
uint32_t tpg_dt_0_cfg_0;
|
||||
uint32_t tpg_dt_1_cfg_0;
|
||||
uint32_t tpg_dt_2_cfg_0;
|
||||
uint32_t tpg_dt_3_cfg_0;
|
||||
uint32_t tpg_dt_0_cfg_1;
|
||||
uint32_t tpg_dt_1_cfg_1;
|
||||
uint32_t tpg_dt_2_cfg_1;
|
||||
uint32_t tpg_dt_3_cfg_1;
|
||||
uint32_t tpg_dt_0_cfg_2;
|
||||
uint32_t tpg_dt_1_cfg_2;
|
||||
uint32_t tpg_dt_2_cfg_2;
|
||||
uint32_t tpg_dt_3_cfg_2;
|
||||
uint32_t tpg_color_bar_cfg;
|
||||
uint32_t tpg_common_gen_cfg;
|
||||
uint32_t tpg_vbi_cfg;
|
||||
uint32_t tpg_test_bus_crtl;
|
||||
uint32_t tpg_spare;
|
||||
/* configurations */
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t version_incr;
|
||||
uint32_t tpg_en_shift_val;
|
||||
uint32_t tpg_phy_sel_shift_val;
|
||||
uint32_t tpg_num_active_lines_shift;
|
||||
uint32_t tpg_fe_pkt_en_shift;
|
||||
uint32_t tpg_fs_pkt_en_shift;
|
||||
uint32_t tpg_line_interleaving_mode_shift;
|
||||
uint32_t tpg_num_dts_shift_val;
|
||||
uint32_t tpg_v_blank_cnt_shift;
|
||||
uint32_t tpg_dt_encode_format_shift;
|
||||
uint32_t tpg_payload_mode_color;
|
||||
uint32_t tpg_split_en_shift;
|
||||
uint32_t top_mux_reg_offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_top_tpg_hw_info- tpg hardware info
|
||||
*
|
||||
* @tpg_reg: tpg register offsets
|
||||
* @hw_dts_version: HW DTS version
|
||||
* @csid_max_clk: maximum csid clock
|
||||
* @phy_max_clk maximum phy clock
|
||||
*
|
||||
*/
|
||||
struct cam_top_tpg_hw_info {
|
||||
const struct cam_top_tpg_reg_offset *tpg_reg;
|
||||
uint32_t hw_dts_version;
|
||||
uint32_t csid_max_clk;
|
||||
uint32_t phy_max_clk;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_top_tpg_dt_cfg- tpg data type(dt) configuration
|
||||
*
|
||||
* @frame_width: frame width in pixel
|
||||
* @frame_height: frame height in pixel
|
||||
* @data_type: data type(dt) value
|
||||
* @encode_format: encode format for this data type
|
||||
* @payload_mode payload data, such color bar, color box etc
|
||||
*
|
||||
*/
|
||||
|
||||
struct cam_top_tpg_dt_cfg {
|
||||
uint32_t frame_width;
|
||||
uint32_t frame_height;
|
||||
uint32_t data_type;
|
||||
uint32_t encode_format;
|
||||
uint32_t payload_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_top_tpg_cfg- tpg congiguration
|
||||
* @pix_pattern : pixel pattern output of the tpg
|
||||
* @phy_sel : phy selection 0:dphy or 1:cphy
|
||||
* @num_active_lanes Number of active lines
|
||||
* @vc_num: Virtual channel number
|
||||
* @h_blank_count: horizontal blanking count value
|
||||
* @h_blank_count: vertical blanking count value
|
||||
* @vbi_cnt: vbi count
|
||||
* @num_active_dts: number of active dts need to configure
|
||||
* @dt_cfg: dt configuration values
|
||||
*
|
||||
*/
|
||||
struct cam_top_tpg_cfg {
|
||||
uint32_t pix_pattern;
|
||||
uint32_t phy_sel;
|
||||
uint32_t num_active_lanes;
|
||||
uint32_t vc_num;
|
||||
uint32_t v_blank_count;
|
||||
uint32_t h_blank_count;
|
||||
uint32_t vbi_cnt;
|
||||
uint32_t num_active_dts;
|
||||
struct cam_top_tpg_dt_cfg dt_cfg[4];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_top_tpg_hw- tpg hw device resources data
|
||||
*
|
||||
* @hw_intf: contain the tpg hw interface information
|
||||
* @hw_info: tpg hw device information
|
||||
* @tpg_info: tpg hw specific information
|
||||
* @tpg_res: tpg resource
|
||||
* @tpg_cfg: tpg configuration
|
||||
* @clk_rate clock rate
|
||||
* @lock_state lock state
|
||||
* @tpg_complete tpg completion
|
||||
*
|
||||
*/
|
||||
struct cam_top_tpg_hw {
|
||||
struct cam_hw_intf *hw_intf;
|
||||
struct cam_hw_info *hw_info;
|
||||
struct cam_top_tpg_hw_info *tpg_info;
|
||||
struct cam_isp_resource_node tpg_res;
|
||||
uint64_t clk_rate;
|
||||
spinlock_t lock_state;
|
||||
struct completion tpg_complete;
|
||||
};
|
||||
|
||||
int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf,
|
||||
uint32_t tpg_idx);
|
||||
|
||||
int cam_top_tpg_hw_deinit(struct cam_top_tpg_hw *top_tpg_hw);
|
||||
|
||||
#endif /* _CAM_TOP_TPG_HW_H_ */
|
140
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c
Normal file
140
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.c
Normal file
@@ -0,0 +1,140 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/of_device.h>
|
||||
#include "cam_top_tpg_core.h"
|
||||
#include "cam_top_tpg_dev.h"
|
||||
#include "cam_top_tpg_hw_intf.h"
|
||||
#include "cam_debug_util.h"
|
||||
|
||||
static struct cam_hw_intf *cam_top_tpg_hw_list[CAM_TOP_TPG_HW_NUM_MAX] = {
|
||||
0, 0};
|
||||
|
||||
static char tpg_dev_name[8];
|
||||
|
||||
int cam_top_tpg_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
struct cam_hw_intf *tpg_hw_intf;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct cam_top_tpg_hw *tpg_dev = NULL;
|
||||
const struct of_device_id *match_dev = NULL;
|
||||
struct cam_top_tpg_hw_info *tpg_hw_data = NULL;
|
||||
uint32_t tpg_dev_idx;
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_ISP, "probe called");
|
||||
|
||||
tpg_hw_intf = kzalloc(sizeof(*tpg_hw_intf), GFP_KERNEL);
|
||||
if (!tpg_hw_intf) {
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
tpg_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||
if (!tpg_hw_info) {
|
||||
rc = -ENOMEM;
|
||||
goto free_hw_intf;
|
||||
}
|
||||
|
||||
tpg_dev = kzalloc(sizeof(struct cam_top_tpg_hw), GFP_KERNEL);
|
||||
if (!tpg_dev) {
|
||||
rc = -ENOMEM;
|
||||
goto free_hw_info;
|
||||
}
|
||||
|
||||
/* get top tpg hw index */
|
||||
of_property_read_u32(pdev->dev.of_node, "cell-index", &tpg_dev_idx);
|
||||
/* get top tpg hw information */
|
||||
match_dev = of_match_device(pdev->dev.driver->of_match_table,
|
||||
&pdev->dev);
|
||||
if (!match_dev) {
|
||||
CAM_ERR(CAM_ISP, "No matching table for the top tpg hw");
|
||||
rc = -EINVAL;
|
||||
goto free_dev;
|
||||
}
|
||||
|
||||
memset(tpg_dev_name, 0, sizeof(tpg_dev_name));
|
||||
snprintf(tpg_dev_name, sizeof(tpg_dev_name),
|
||||
"tpg%1u", tpg_dev_idx);
|
||||
|
||||
tpg_hw_intf->hw_idx = tpg_dev_idx;
|
||||
tpg_hw_intf->hw_type = CAM_ISP_HW_TYPE_TPG;
|
||||
tpg_hw_intf->hw_priv = tpg_hw_info;
|
||||
|
||||
tpg_hw_info->core_info = tpg_dev;
|
||||
tpg_hw_info->soc_info.pdev = pdev;
|
||||
tpg_hw_info->soc_info.dev = &pdev->dev;
|
||||
tpg_hw_info->soc_info.dev_name = tpg_dev_name;
|
||||
tpg_hw_info->soc_info.index = tpg_dev_idx;
|
||||
|
||||
tpg_hw_data = (struct cam_top_tpg_hw_info *)match_dev->data;
|
||||
/* need to setup the pdev before call the tfe hw probe init */
|
||||
tpg_dev->tpg_info = tpg_hw_data;
|
||||
|
||||
rc = cam_top_tpg_hw_probe_init(tpg_hw_intf, tpg_dev_idx);
|
||||
if (rc)
|
||||
goto free_dev;
|
||||
|
||||
platform_set_drvdata(pdev, tpg_dev);
|
||||
CAM_DBG(CAM_ISP, "TPG:%d probe successful",
|
||||
tpg_hw_intf->hw_idx);
|
||||
|
||||
|
||||
if (tpg_hw_intf->hw_idx < CAM_TOP_TPG_HW_NUM_MAX)
|
||||
cam_top_tpg_hw_list[tpg_hw_intf->hw_idx] = tpg_hw_intf;
|
||||
else
|
||||
goto free_dev;
|
||||
|
||||
return 0;
|
||||
|
||||
free_dev:
|
||||
kfree(tpg_dev);
|
||||
free_hw_info:
|
||||
kfree(tpg_hw_info);
|
||||
free_hw_intf:
|
||||
kfree(tpg_hw_intf);
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_top_tpg_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cam_top_tpg_hw *tpg_dev = NULL;
|
||||
struct cam_hw_intf *tpg_hw_intf;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
|
||||
tpg_dev = (struct cam_top_tpg_hw *)platform_get_drvdata(pdev);
|
||||
tpg_hw_intf = tpg_dev->hw_intf;
|
||||
tpg_hw_info = tpg_dev->hw_info;
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG:%d remove",
|
||||
tpg_dev->hw_intf->hw_idx);
|
||||
|
||||
cam_top_tpg_hw_deinit(tpg_dev);
|
||||
|
||||
/*release the tpg device memory */
|
||||
kfree(tpg_dev);
|
||||
kfree(tpg_hw_info);
|
||||
kfree(tpg_hw_intf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_top_tpg_hw_init(struct cam_hw_intf **top_tpg_hw,
|
||||
uint32_t hw_idx)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (cam_top_tpg_hw_list[hw_idx]) {
|
||||
*top_tpg_hw = cam_top_tpg_hw_list[hw_idx];
|
||||
} else {
|
||||
*top_tpg_hw = NULL;
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
12
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.h
Normal file
12
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_dev.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_DEV_H_
|
||||
#define _CAM_TOP_TPG_DEV_H_
|
||||
|
||||
int cam_top_tpg_probe(struct platform_device *pdev);
|
||||
int cam_top_tpg_remove(struct platform_device *pdev);
|
||||
|
||||
#endif /*_CAM_TOP_TPG_DEV_H_ */
|
152
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c
Normal file
152
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.c
Normal file
@@ -0,0 +1,152 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#include <linux/slab.h>
|
||||
#include "cam_top_tpg_soc.h"
|
||||
#include "cam_cpas_api.h"
|
||||
#include "cam_debug_util.h"
|
||||
|
||||
int cam_top_tpg_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
void *irq_data)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_cpas_register_params cpas_register_param;
|
||||
struct cam_top_tpg_soc_private *soc_private;
|
||||
|
||||
soc_private = kzalloc(sizeof(struct cam_top_tpg_soc_private),
|
||||
GFP_KERNEL);
|
||||
if (!soc_private)
|
||||
return -ENOMEM;
|
||||
|
||||
soc_info->soc_private = soc_private;
|
||||
|
||||
rc = cam_soc_util_get_dt_properties(soc_info);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Need to see if we want post process the clock list */
|
||||
rc = cam_soc_util_request_platform_resource(soc_info, NULL,
|
||||
irq_data);
|
||||
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_ISP,
|
||||
"Error Request platform resources failed rc=%d", rc);
|
||||
goto free_soc_private;
|
||||
}
|
||||
|
||||
memset(&cpas_register_param, 0, sizeof(cpas_register_param));
|
||||
strlcpy(cpas_register_param.identifier, "tpg",
|
||||
CAM_HW_IDENTIFIER_LENGTH);
|
||||
cpas_register_param.cell_index = soc_info->index;
|
||||
cpas_register_param.dev = soc_info->dev;
|
||||
rc = cam_cpas_register_client(&cpas_register_param);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
|
||||
goto release_soc;
|
||||
} else {
|
||||
soc_private->cpas_handle = cpas_register_param.client_handle;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
release_soc:
|
||||
cam_soc_util_release_platform_resource(soc_info);
|
||||
free_soc_private:
|
||||
kfree(soc_private);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_top_tpg_deinit_soc_resources(
|
||||
struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_soc_private *soc_private;
|
||||
|
||||
soc_private = soc_info->soc_private;
|
||||
if (!soc_private) {
|
||||
CAM_ERR(CAM_ISP, "Error soc_private NULL");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = cam_cpas_unregister_client(soc_private->cpas_handle);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc);
|
||||
|
||||
rc = cam_soc_util_release_platform_resource(soc_info);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_top_tpg_enable_soc_resources(
|
||||
struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_soc_private *soc_private;
|
||||
struct cam_ahb_vote ahb_vote;
|
||||
struct cam_axi_vote axi_vote = {0};
|
||||
|
||||
soc_private = soc_info->soc_private;
|
||||
|
||||
ahb_vote.type = CAM_VOTE_ABSOLUTE;
|
||||
ahb_vote.vote.level = CAM_SVS_VOTE;
|
||||
axi_vote.num_paths = 1;
|
||||
axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL;
|
||||
axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE;
|
||||
|
||||
axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW;
|
||||
axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW;
|
||||
axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW;
|
||||
|
||||
CAM_DBG(CAM_ISP, "csid camnoc_bw:%lld mnoc_ab_bw:%lld mnoc_ib_bw:%lld ",
|
||||
axi_vote.axi_path[0].camnoc_bw,
|
||||
axi_vote.axi_path[0].mnoc_ab_bw,
|
||||
axi_vote.axi_path[0].mnoc_ib_bw);
|
||||
|
||||
rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Error CPAS start failed");
|
||||
rc = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_enable_platform_resource(soc_info, true,
|
||||
clk_level, false);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "enable platform failed");
|
||||
goto stop_cpas;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
stop_cpas:
|
||||
cam_cpas_stop(soc_private->cpas_handle);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_top_tpg_disable_soc_resources(struct cam_hw_soc_info *soc_info)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_top_tpg_soc_private *soc_private;
|
||||
|
||||
if (!soc_info) {
|
||||
CAM_ERR(CAM_ISP, "Error Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
soc_private = soc_info->soc_private;
|
||||
|
||||
rc = cam_soc_util_disable_platform_resource(soc_info, true, false);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "Disable platform failed");
|
||||
|
||||
rc = cam_cpas_stop(soc_private->cpas_handle);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Error CPAS stop failed rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
78
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h
Normal file
78
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_soc.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_SOC_H_
|
||||
#define _CAM_TOP_TPG_SOC_H_
|
||||
|
||||
#include "cam_isp_hw.h"
|
||||
|
||||
/*
|
||||
* struct cam_top_tpg_soc_private:
|
||||
*
|
||||
* @Brief: Private SOC data specific to TPG HW Driver
|
||||
*
|
||||
* @cpas_handle: Handle returned on registering with CPAS driver.
|
||||
* This handle is used for all further interface
|
||||
* with CPAS.
|
||||
*/
|
||||
struct cam_top_tpg_soc_private {
|
||||
uint32_t cpas_handle;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_top_tpg_device_soc_info - tpg soc SOC info object
|
||||
*
|
||||
* @csi_vdd_voltage: csi vdd voltage value
|
||||
*
|
||||
*/
|
||||
struct cam_top_tpg_device_soc_info {
|
||||
int csi_vdd_voltage;
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_top_tpg_init_soc_resources()
|
||||
*
|
||||
* @brief: csid initialization function for the soc info
|
||||
*
|
||||
* @soc_info: soc info structure pointer
|
||||
* @irq_data: irq data for the callback function
|
||||
*
|
||||
*/
|
||||
int cam_top_tpg_init_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
void *irq_data);
|
||||
|
||||
/**
|
||||
* cam_top_tpg_deinit_soc_resources()
|
||||
*
|
||||
* @brief: tpg de initialization function for the soc info
|
||||
*
|
||||
* @soc_info: soc info structure pointer
|
||||
*
|
||||
*/
|
||||
int cam_top_tpg_deinit_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
/**
|
||||
* cam_top_tpg_enable_soc_resources()
|
||||
*
|
||||
* @brief: tpg soc resource enable function
|
||||
*
|
||||
* @soc_info: soc info structure pointer
|
||||
* @clk_lvl: vote level to start with
|
||||
*
|
||||
*/
|
||||
int cam_top_tpg_enable_soc_resources(struct cam_hw_soc_info *soc_info,
|
||||
uint32_t clk_lvl);
|
||||
|
||||
/**
|
||||
* cam_top_tpg_disable_soc_resources()
|
||||
*
|
||||
* @brief: csid soc resource disable function
|
||||
*
|
||||
* @soc_info: soc info structure pointer
|
||||
*
|
||||
*/
|
||||
int cam_top_tpg_disable_soc_resources(struct cam_hw_soc_info *soc_info);
|
||||
|
||||
#endif /* _CAM_TOP_TPG_SOC_H_ */
|
53
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c
Normal file
53
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.c
Normal file
@@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "cam_top_tpg_core.h"
|
||||
#include "cam_top_tpg_v1.h"
|
||||
#include "cam_top_tpg_dev.h"
|
||||
|
||||
#define CAM_TOP_TPG_DRV_NAME "tpg_v1"
|
||||
#define CAM_TOP_TPG_VERSION_V1 0x10000000
|
||||
|
||||
static struct cam_top_tpg_hw_info cam_top_tpg_v1_hw_info = {
|
||||
.tpg_reg = &cam_top_tpg_v1_reg_offset,
|
||||
.hw_dts_version = CAM_TOP_TPG_VERSION_V1,
|
||||
.csid_max_clk = 426400000,
|
||||
.phy_max_clk = 384000000,
|
||||
};
|
||||
|
||||
static const struct of_device_id cam_top_tpg_v1_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,tpgv1",
|
||||
.data = &cam_top_tpg_v1_hw_info,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, cam_top_tpg_v1_dt_match);
|
||||
|
||||
static struct platform_driver cam_top_tpg_v1_driver = {
|
||||
.probe = cam_top_tpg_probe,
|
||||
.remove = cam_top_tpg_remove,
|
||||
.driver = {
|
||||
.name = CAM_TOP_TPG_DRV_NAME,
|
||||
.of_match_table = cam_top_tpg_v1_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
int cam_top_tpg_v1_init_module(void)
|
||||
{
|
||||
return platform_driver_register(&cam_top_tpg_v1_driver);
|
||||
}
|
||||
|
||||
void cam_top_tpg_v1_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&cam_top_tpg_v1_driver);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("CAM TOP TPG driver");
|
||||
MODULE_LICENSE("GPL v2");
|
56
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h
Normal file
56
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_V1_H_
|
||||
#define _CAM_TOP_TPG_V1_H_
|
||||
|
||||
#include "cam_top_tpg_core.h"
|
||||
|
||||
static struct cam_top_tpg_reg_offset cam_top_tpg_v1_reg_offset = {
|
||||
.tpg_hw_version = 0x0,
|
||||
.tpg_hw_status = 0x4,
|
||||
.tpg_ctrl = 0x60,
|
||||
.tpg_vc_cfg0 = 0x64,
|
||||
.tpg_vc_cfg1 = 0x68,
|
||||
.tpg_lfsr_seed = 0x6c,
|
||||
.tpg_dt_0_cfg_0 = 0x70,
|
||||
.tpg_dt_1_cfg_0 = 0x74,
|
||||
.tpg_dt_2_cfg_0 = 0x78,
|
||||
.tpg_dt_3_cfg_0 = 0x7C,
|
||||
.tpg_dt_0_cfg_1 = 0x80,
|
||||
.tpg_dt_1_cfg_1 = 0x84,
|
||||
.tpg_dt_2_cfg_1 = 0x88,
|
||||
.tpg_dt_3_cfg_1 = 0x8C,
|
||||
.tpg_dt_0_cfg_2 = 0x90,
|
||||
.tpg_dt_1_cfg_2 = 0x94,
|
||||
.tpg_dt_2_cfg_2 = 0x98,
|
||||
.tpg_dt_3_cfg_2 = 0x9C,
|
||||
.tpg_color_bar_cfg = 0xA0,
|
||||
.tpg_common_gen_cfg = 0xA4,
|
||||
.tpg_vbi_cfg = 0xA8,
|
||||
.tpg_test_bus_crtl = 0xF8,
|
||||
.tpg_spare = 0xFC,
|
||||
/* configurations */
|
||||
.major_version = 1,
|
||||
.minor_version = 0,
|
||||
.version_incr = 0,
|
||||
.tpg_en_shift_val = 0,
|
||||
.tpg_phy_sel_shift_val = 3,
|
||||
.tpg_num_active_lines_shift = 4,
|
||||
.tpg_fe_pkt_en_shift = 2,
|
||||
.tpg_fs_pkt_en_shift = 1,
|
||||
.tpg_line_interleaving_mode_shift = 10,
|
||||
.tpg_num_dts_shift_val = 8,
|
||||
.tpg_v_blank_cnt_shift = 12,
|
||||
.tpg_dt_encode_format_shift = 16,
|
||||
.tpg_payload_mode_color = 0x8,
|
||||
.tpg_split_en_shift = 5,
|
||||
.top_mux_reg_offset = 0x1C,
|
||||
};
|
||||
|
||||
int cam_top_tpg_v1_init_module(void);
|
||||
void cam_top_tpg_v1_exit_module(void);
|
||||
|
||||
#endif /*_CAM_TOP_TPG_V1_H_ */
|
@@ -50,6 +50,10 @@
|
||||
|
||||
#include "ope_dev_intf.h"
|
||||
|
||||
#include "cam_top_tpg_v1.h"
|
||||
#include "cam_tfe_dev.h"
|
||||
#include "cam_tfe_csid530.h"
|
||||
|
||||
struct camera_submodule_component {
|
||||
int (*init)(void);
|
||||
void (*exit)(void);
|
||||
@@ -79,6 +83,14 @@ static const struct camera_submodule_component camera_isp[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct camera_submodule_component camera_tfe[] = {
|
||||
#if IS_ENABLED(CONFIG_SPECTRA_TFE)
|
||||
{&cam_top_tpg_v1_init_module, &cam_top_tpg_v1_exit_module},
|
||||
{&cam_tfe_init_module, &cam_tfe_exit_module},
|
||||
{&cam_tfe_csid530_init_module, &cam_tfe_csid530_exit_module},
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct camera_submodule_component camera_sensor[] = {
|
||||
#ifdef CONFIG_SPECTRA_SENSOR
|
||||
{&cam_res_mgr_init, &cam_res_mgr_exit},
|
||||
@@ -151,6 +163,11 @@ static const struct camera_submodule submodule_table[] = {
|
||||
.num_component = ARRAY_SIZE(camera_isp),
|
||||
.component = camera_isp,
|
||||
},
|
||||
{
|
||||
.name = "Camera TFE",
|
||||
.num_component = ARRAY_SIZE(camera_tfe),
|
||||
.component = camera_tfe,
|
||||
},
|
||||
{
|
||||
.name = "Camera SENSOR",
|
||||
.num_component = ARRAY_SIZE(camera_sensor),
|
||||
|
Reference in New Issue
Block a user