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>
Tento commit je obsažen v:
Trishansh Bhardwaj
2019-12-23 16:12:03 +05:30
rodič 4fddce3d69
revize cb2e8943da
43 změnil soubory, kde provedl 18155 přidání a 30 odebrání

Zobrazit soubor

@@ -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

Zobrazit soubor

@@ -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];

Zobrazit soubor

@@ -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()

Zobrazit soubor

@@ -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;

Zobrazit soubor

@@ -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;
}

Rozdílový obsah nebyl zobrazen, protože je příliš veliký Načíst rozdílové porovnání

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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__ */

Zobrazit soubor

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

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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

Zobrazit soubor

@@ -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");

Zobrazit soubor

@@ -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_ */

Rozdílový obsah nebyl zobrazen, protože je příliš veliký Načíst rozdílové porovnání

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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;
}

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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;
}

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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

Zobrazit soubor

@@ -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");

Zobrazit soubor

@@ -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_ */

Rozdílový obsah nebyl zobrazen, protože je příliš veliký Načíst rozdílové porovnání

Zobrazit soubor

@@ -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_ */

Rozdílový obsah nebyl zobrazen, protože je příliš veliký Načíst rozdílové porovnání

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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;
}

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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;
}

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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

Zobrazit soubor

@@ -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;
}

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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;
}

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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;
}

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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");

Zobrazit soubor

@@ -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_ */

Zobrazit soubor

@@ -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),