msm: camera: isp: Add support for PHY TPG
This change adds support for PHY TPG version 102 hardware. CRs-Fixed: 2608550 Change-Id: I92387b08e8a91bb0c6a77b5301ebc30c7cb6f252 Signed-off-by: Vishalsingh Hajeri <vhajeri@codeaurora.org> Signed-off-by: Venkat Chinta <vchinta@codeaurora.org> Signed-off-by: Mukund Madhusudan Atre <matre@codeaurora.org>
This commit is contained in:
@@ -85,6 +85,11 @@ camera-$(CONFIG_SPECTRA_ISP) += \
|
||||
cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe.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_ver2.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.o \
|
||||
cam_isp/isp_hw_mgr/cam_isp_hw_mgr.o \
|
||||
cam_isp/isp_hw_mgr/cam_ife_hw_mgr.o \
|
||||
cam_isp/cam_isp_dev.o \
|
||||
@@ -197,7 +202,9 @@ camera-$(CONFIG_SPECTRA_CAMERA) += \
|
||||
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
|
||||
cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.o \
|
||||
cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.o
|
||||
|
||||
|
||||
camera-y += camera_main.o
|
||||
|
||||
|
@@ -424,6 +424,17 @@ static int cam_ife_hw_mgr_init_hw(
|
||||
struct cam_isp_hw_mgr_res *hw_mgr_res;
|
||||
int rc = 0, i;
|
||||
|
||||
if (ctx->is_tpg) {
|
||||
CAM_DBG(CAM_ISP, "INIT TPG ... in ctx id:%d",
|
||||
ctx->ctx_index);
|
||||
rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_tpg);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Can not INIT TFE TPG(id :%d)",
|
||||
ctx->res_list_tpg.hw_res[0]->hw_intf->hw_idx);
|
||||
goto deinit;
|
||||
}
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d",
|
||||
ctx->ctx_index);
|
||||
/* INIT IFE CID */
|
||||
@@ -840,6 +851,10 @@ static int cam_ife_hw_mgr_release_hw_for_ctx(
|
||||
cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &hw_mgr_res);
|
||||
}
|
||||
|
||||
/* ife phy tpg resource */
|
||||
if (ife_ctx->is_tpg)
|
||||
cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_tpg);
|
||||
|
||||
/* ife root node */
|
||||
if (ife_ctx->res_list_ife_in.res_type != CAM_ISP_RESOURCE_UNINT)
|
||||
cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_ife_in);
|
||||
@@ -1862,6 +1877,48 @@ end:
|
||||
|
||||
}
|
||||
|
||||
static int cam_ife_hw_mgr_acquire_tpg(
|
||||
struct cam_ife_hw_mgr_ctx *ife_ctx,
|
||||
struct cam_isp_in_port_generic_info *in_port,
|
||||
uint32_t num_inport)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
uint32_t i;
|
||||
struct cam_ife_hw_mgr *ife_hw_mgr;
|
||||
struct cam_hw_intf *hw_intf;
|
||||
struct cam_top_tpg_ver2_reserve_args tpg_reserve;
|
||||
|
||||
ife_hw_mgr = ife_ctx->hw_mgr;
|
||||
|
||||
for (i = 0; i < CAM_TOP_TPG_HW_NUM_MAX; i++) {
|
||||
if (!ife_hw_mgr->tpg_devices[i])
|
||||
continue;
|
||||
|
||||
hw_intf = ife_hw_mgr->tpg_devices[i];
|
||||
tpg_reserve.num_inport = num_inport;
|
||||
tpg_reserve.node_res = NULL;
|
||||
tpg_reserve.in_port = in_port;
|
||||
|
||||
rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
|
||||
&tpg_reserve, sizeof(tpg_reserve));
|
||||
if (!rc)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == CAM_TOP_TPG_HW_NUM_MAX || !tpg_reserve.node_res) {
|
||||
CAM_ERR(CAM_ISP, "Can not acquire IFE TPG");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ife_ctx->res_list_tpg.res_type = in_port->res_type;
|
||||
ife_ctx->res_list_tpg.hw_res[0] = tpg_reserve.node_res;
|
||||
ife_ctx->is_tpg = true;
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl(
|
||||
struct cam_ife_hw_mgr_ctx *ife_ctx,
|
||||
struct cam_isp_in_port_generic_info *in_port,
|
||||
@@ -2755,6 +2812,16 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
|
||||
ife_ctx->use_frame_header_ts = true;
|
||||
}
|
||||
|
||||
if ((in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) ||
|
||||
(in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1))
|
||||
rc = cam_ife_hw_mgr_acquire_tpg(ife_ctx, in_port,
|
||||
acquire_hw_info->num_inputs);
|
||||
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "can not acquire TPG resource");
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
|
||||
&num_pix_port_per_in, &num_rdi_port_per_in,
|
||||
&acquire_args->acquired_hw_id[i],
|
||||
@@ -3752,6 +3819,9 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
|
||||
if (cam_cdm_stream_off(ctx->cdm_handle))
|
||||
CAM_ERR(CAM_ISP, "CDM stream off failed %d", ctx->cdm_handle);
|
||||
|
||||
if (ctx->is_tpg)
|
||||
cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_tpg);
|
||||
|
||||
cam_ife_hw_mgr_deinit_hw(ctx);
|
||||
CAM_DBG(CAM_ISP,
|
||||
"Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc);
|
||||
@@ -4077,6 +4147,17 @@ start_only:
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->is_tpg) {
|
||||
CAM_DBG(CAM_ISP, "START TPG HW ... in ctx id:%d",
|
||||
ctx->ctx_index);
|
||||
rc = cam_ife_hw_mgr_start_hw_res(&ctx->res_list_tpg, ctx);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ISP, "Can not start IFE TPG (%d)",
|
||||
ctx->res_list_tpg.res_id);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start IFE root node: do nothing */
|
||||
CAM_DBG(CAM_ISP, "Start success for ctx id:%d", ctx->ctx_index);
|
||||
|
||||
@@ -7100,6 +7181,16 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* fill tpg hw intf information */
|
||||
for (i = 0, j = 0; i < CAM_TOP_TPG_HW_NUM_MAX; i++) {
|
||||
rc = cam_top_tpg_hw_init(&g_ife_hw_mgr.tpg_devices[i], i);
|
||||
if (!rc)
|
||||
j++;
|
||||
}
|
||||
if (!j)
|
||||
CAM_ERR(CAM_ISP, "no valid IFE TPG HW");
|
||||
|
||||
|
||||
cam_ife_hw_mgr_sort_dev_with_caps(&g_ife_hw_mgr);
|
||||
|
||||
/* setup ife context list */
|
||||
@@ -7146,6 +7237,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
|
||||
sizeof(g_ife_hw_mgr.ctx_pool[i]));
|
||||
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].list);
|
||||
|
||||
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_tpg.list);
|
||||
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_in.list);
|
||||
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_cid);
|
||||
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_csid);
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "cam_isp_hw_mgr.h"
|
||||
#include "cam_vfe_hw_intf.h"
|
||||
#include "cam_ife_csid_hw_intf.h"
|
||||
#include "cam_top_tpg_hw_intf.h"
|
||||
#include "cam_tasklet_util.h"
|
||||
|
||||
/* IFE resource constants */
|
||||
@@ -48,6 +49,7 @@ struct cam_ife_hw_mgr_debug {
|
||||
* @slave_hw_idx: hw index for slave core
|
||||
* @hw_mgr: IFE hw mgr which owns this context
|
||||
* @ctx_in_use: flag to tell whether context is active
|
||||
* @res_list_tpg: TPG resource list
|
||||
* @res_list_ife_in: Starting resource(TPG,PHY0, PHY1...) Can only be
|
||||
* one.
|
||||
* @res_list_csid: CSID resource list
|
||||
@@ -85,6 +87,7 @@ struct cam_ife_hw_mgr_debug {
|
||||
* @custom_enabled update the flag if context is connected to custom HW
|
||||
* @use_frame_header_ts obtain qtimer ts using frame header
|
||||
* @ts captured timestamp when the ctx is acquired
|
||||
* @is_tpg indicate whether context is using PHY TPG
|
||||
*/
|
||||
struct cam_ife_hw_mgr_ctx {
|
||||
struct list_head list;
|
||||
@@ -97,6 +100,7 @@ struct cam_ife_hw_mgr_ctx {
|
||||
uint32_t ctx_in_use;
|
||||
|
||||
struct cam_isp_hw_mgr_res res_list_ife_in;
|
||||
struct cam_isp_hw_mgr_res res_list_tpg;
|
||||
struct list_head res_list_ife_cid;
|
||||
struct list_head res_list_ife_csid;
|
||||
struct list_head res_list_ife_src;
|
||||
@@ -134,6 +138,7 @@ struct cam_ife_hw_mgr_ctx {
|
||||
bool custom_enabled;
|
||||
bool use_frame_header_ts;
|
||||
struct timespec64 ts;
|
||||
bool is_tpg;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -155,6 +160,7 @@ struct cam_ife_hw_mgr_ctx {
|
||||
*/
|
||||
struct cam_ife_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_IFE_CSID_HW_NUM_MAX];
|
||||
struct cam_hw_intf *ife_devices[CAM_IFE_HW_NUM_MAX];
|
||||
struct cam_soc_reg_map *cdm_reg_map[CAM_IFE_HW_NUM_MAX];
|
||||
|
@@ -1350,7 +1350,7 @@ static int cam_tfe_hw_mgr_acquire_tpg(
|
||||
uint32_t i, j = 0;
|
||||
struct cam_tfe_hw_mgr *tfe_hw_mgr;
|
||||
struct cam_hw_intf *hw_intf;
|
||||
struct cam_top_tpg_hw_reserve_resource_args tpg_reserve;
|
||||
struct cam_top_tpg_ver1_reserve_args tpg_reserve;
|
||||
|
||||
tfe_hw_mgr = tfe_ctx->hw_mgr;
|
||||
|
||||
|
@@ -25,6 +25,10 @@
|
||||
#define CAM_IFE_CSID_TPG_VC_VAL 0xA
|
||||
#define CAM_IFE_CSID_TPG_DT_VAL 0x2B
|
||||
|
||||
/* CSIPHY TPG VC/DT values */
|
||||
#define CAM_IFE_CSI_TPG_VC_VAL 0x0
|
||||
#define CAM_IFE_CSI_TPG_DT_VAL 0x2B
|
||||
|
||||
/* Timeout values in usec */
|
||||
#define CAM_IFE_CSID_TIMEOUT_SLEEP_US 1000
|
||||
#define CAM_IFE_CSID_TIMEOUT_ALL_US 100000
|
||||
@@ -957,6 +961,12 @@ int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
|
||||
csid_hw->tpg_cfg.height);
|
||||
|
||||
cid_data->tpg_set = 1;
|
||||
} else if (cid_reserv->in_port->res_type ==
|
||||
CAM_ISP_IFE_IN_RES_CPHY_TPG_0) {
|
||||
csid_hw->csi2_rx_cfg.phy_sel = 0;
|
||||
} else if (cid_reserv->in_port->res_type ==
|
||||
CAM_ISP_IFE_IN_RES_CPHY_TPG_1) {
|
||||
csid_hw->csi2_rx_cfg.phy_sel = 1;
|
||||
} else {
|
||||
csid_hw->csi2_rx_cfg.phy_sel =
|
||||
(cid_reserv->in_port->res_type & 0xFF) - 1;
|
||||
@@ -1129,9 +1139,10 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
|
||||
reserve->in_port->line_start, reserve->in_port->line_stop,
|
||||
path_data->crop_enable);
|
||||
|
||||
if (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) {
|
||||
path_data->dt = CAM_IFE_CSID_TPG_DT_VAL;
|
||||
path_data->vc = CAM_IFE_CSID_TPG_VC_VAL;
|
||||
if ((reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_0) ||
|
||||
(reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1)) {
|
||||
path_data->dt = CAM_IFE_CSI_TPG_DT_VAL;
|
||||
path_data->vc = CAM_IFE_CSI_TPG_VC_VAL;
|
||||
} else {
|
||||
path_data->dt = reserve->in_port->dt[0];
|
||||
path_data->vc = reserve->in_port->vc[0];
|
||||
@@ -4459,6 +4470,7 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
|
||||
num_paths = ife_csid_hw->csid_info->csid_reg->cmn_reg->num_pix +
|
||||
ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis +
|
||||
ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis;
|
||||
|
||||
/* Initialize the CID resource */
|
||||
for (i = 0; i < num_paths; i++) {
|
||||
ife_csid_hw->cid_res[i].res_type = CAM_ISP_RESOURCE_CID;
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "cam_isp_hw.h"
|
||||
#include "cam_hw_intf.h"
|
||||
#include "cam_ife_csid_hw_intf.h"
|
||||
|
||||
/* Max top tpg instance */
|
||||
#define CAM_TOP_TPG_HW_NUM_MAX 2
|
||||
@@ -37,7 +38,7 @@ struct cam_top_tpg_hw_caps {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_tfe_csid_hw_reserve_resource_args- hw reserve
|
||||
* struct cam_top_tpg_ver1_reserve_args- hw reserve
|
||||
* @num_inport: number of inport
|
||||
* TPG support 4 dt types, each different dt comes in different
|
||||
* in port.
|
||||
@@ -45,12 +46,26 @@ struct cam_top_tpg_hw_caps {
|
||||
* @node_res : Reserved resource structure pointer
|
||||
*
|
||||
*/
|
||||
struct cam_top_tpg_hw_reserve_resource_args {
|
||||
struct cam_top_tpg_ver1_reserve_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;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_top_tpg_ver2_reserve_args
|
||||
* @num_inport: number of inport
|
||||
* TPG supports 1 VC/DT
|
||||
* @in_port : Input port resource info structure pointer
|
||||
* @node_res : Reserved resource structure pointer
|
||||
*
|
||||
*/
|
||||
struct cam_top_tpg_ver2_reserve_args {
|
||||
uint32_t num_inport;
|
||||
struct cam_isp_in_port_generic_info *in_port;
|
||||
struct cam_isp_resource_node *node_res;
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_top_tpg_hw_init()
|
||||
*
|
||||
|
@@ -1,15 +0,0 @@
|
||||
# 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
|
48
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c
Normal file
48
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.c
Normal file
@@ -0,0 +1,48 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "cam_top_tpg101.h"
|
||||
#include "cam_top_tpg102.h"
|
||||
#include "cam_top_tpg_core.h"
|
||||
#include "cam_top_tpg_dev.h"
|
||||
#include "camera_main.h"
|
||||
|
||||
static const struct of_device_id cam_top_tpg_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,tpg101",
|
||||
.data = &cam_top_tpg101_hw_info,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,tpg102",
|
||||
.data = &cam_top_tpg102_hw_info,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, cam_top_tpg_dt_match);
|
||||
|
||||
struct platform_driver cam_top_tpg_driver = {
|
||||
.probe = cam_top_tpg_probe,
|
||||
.remove = cam_top_tpg_remove,
|
||||
.driver = {
|
||||
.name = "cam_top_tpg",
|
||||
.of_match_table = cam_top_tpg_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
};
|
||||
|
||||
int cam_top_tpg_init_module(void)
|
||||
{
|
||||
return platform_driver_register(&cam_top_tpg_driver);
|
||||
}
|
||||
|
||||
void cam_top_tpg_exit_module(void)
|
||||
{
|
||||
platform_driver_unregister(&cam_top_tpg_driver);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("CAM TOP TPG driver");
|
||||
MODULE_LICENSE("GPL v2");
|
12
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.h
Normal file
12
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_H_
|
||||
#define _CAM_TOP_TPG_H_
|
||||
|
||||
int cam_top_tpg_init_module(void);
|
||||
void cam_top_tpg_exit_module(void);
|
||||
|
||||
#endif /*_CAM_TOP_TPG_H_ */
|
@@ -3,12 +3,13 @@
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_V1_H_
|
||||
#define _CAM_TOP_TPG_V1_H_
|
||||
#ifndef _CAM_TOP_TPG101_H_
|
||||
#define _CAM_TOP_TPG101_H_
|
||||
|
||||
#include "cam_top_tpg_ver1.h"
|
||||
#include "cam_top_tpg_core.h"
|
||||
|
||||
static struct cam_top_tpg_reg_offset cam_top_tpg_v1_reg_offset = {
|
||||
static struct cam_top_tpg_ver1_reg_offset cam_top_tpg101_reg = {
|
||||
.tpg_hw_version = 0x0,
|
||||
.tpg_hw_status = 0x4,
|
||||
.tpg_ctrl = 0x60,
|
||||
@@ -50,7 +51,11 @@ static struct cam_top_tpg_reg_offset cam_top_tpg_v1_reg_offset = {
|
||||
.top_mux_reg_offset = 0x1C,
|
||||
};
|
||||
|
||||
int cam_top_tpg_v1_init_module(void);
|
||||
void cam_top_tpg_v1_exit_module(void);
|
||||
struct cam_top_tpg_hw_info cam_top_tpg101_hw_info = {
|
||||
.tpg_reg = &cam_top_tpg101_reg,
|
||||
.hw_dts_version = CAM_TOP_TPG_VERSION_1,
|
||||
.csid_max_clk = 426400000,
|
||||
.phy_max_clk = 384000000,
|
||||
};
|
||||
|
||||
#endif /*_CAM_TOP_TPG_V1_H_ */
|
||||
#endif /* _CAM_TOP_TPG101_H_ */
|
50
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h
Normal file
50
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg102.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG102_H_
|
||||
#define _CAM_TOP_TPG102_H_
|
||||
|
||||
#include "cam_top_tpg_ver2.h"
|
||||
#include "cam_top_tpg_core.h"
|
||||
|
||||
static struct cam_top_tpg_ver2_reg_offset cam_top_tpg102_reg = {
|
||||
.tpg_hw_version = 0x0,
|
||||
.tpg_hw_status = 0x4,
|
||||
.tpg_module_cfg = 0x60,
|
||||
.tpg_cfg_0 = 0x68,
|
||||
.tpg_cfg_1 = 0x6C,
|
||||
.tpg_cfg_2 = 0x70,
|
||||
.tpg_cfg_3 = 0x74,
|
||||
.tpg_spare = 0xFC,
|
||||
.top_mux_sel = 0x90,
|
||||
/* configurations */
|
||||
.major_version = 1,
|
||||
.minor_version = 0,
|
||||
.version_incr = 0,
|
||||
.tpg_module_en = 1,
|
||||
.tpg_mux_sel_en = 1,
|
||||
.tpg_mux_sel_tpg_0_shift = 0,
|
||||
.tpg_mux_sel_tpg_1_shift = 8,
|
||||
.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,
|
||||
};
|
||||
|
||||
struct cam_top_tpg_hw_info cam_top_tpg102_hw_info = {
|
||||
.tpg_reg = &cam_top_tpg102_reg,
|
||||
.hw_dts_version = CAM_TOP_TPG_VERSION_2,
|
||||
.csid_max_clk = 426400000,
|
||||
.phy_max_clk = 384000000,
|
||||
};
|
||||
|
||||
#endif /* _CAM_TOP_TPG102_H_ */
|
@@ -13,210 +13,8 @@
|
||||
#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;
|
||||
}
|
||||
#include "cam_top_tpg_ver1.h"
|
||||
#include "cam_top_tpg_ver2.h"
|
||||
|
||||
static int cam_top_tpg_release(void *hw_priv,
|
||||
void *release_args, uint32_t arg_size)
|
||||
@@ -266,9 +64,8 @@ static int cam_top_tpg_init_hw(void *hw_priv,
|
||||
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;
|
||||
uint32_t clk_lvl;
|
||||
|
||||
if (!hw_priv || !init_args ||
|
||||
(arg_size != sizeof(struct cam_isp_resource_node))) {
|
||||
@@ -279,7 +76,6 @@ static int cam_top_tpg_init_hw(void *hw_priv,
|
||||
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) {
|
||||
@@ -321,11 +117,6 @@ static int cam_top_tpg_init_hw(void *hw_priv,
|
||||
|
||||
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;
|
||||
|
||||
@@ -389,148 +180,6 @@ end:
|
||||
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);
|
||||
|
||||
/*
|
||||
* if hblank is notset configureHBlank count 500 and
|
||||
* V blank count is 600
|
||||
*/
|
||||
|
||||
if (tpg_data->h_blank_count)
|
||||
cam_io_w_mb(tpg_data->h_blank_count,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1);
|
||||
else
|
||||
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);
|
||||
|
||||
/* if VBI is notset configureVBI to 0xAFF */
|
||||
if (tpg_data->v_blank_count)
|
||||
cam_io_w_mb(tpg_data->v_blank_count,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg);
|
||||
else
|
||||
cam_io_w_mb(0xAFFF,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@@ -592,14 +241,14 @@ static int cam_top_tpg_process_cmd(void *hw_priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf,
|
||||
int cam_top_tpg_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;
|
||||
uint32_t hw_version = 0;
|
||||
|
||||
if (tpg_idx >= CAM_TOP_TPG_HW_NUM_MAX) {
|
||||
CAM_ERR(CAM_ISP, "Invalid tpg index:%d", tpg_idx);
|
||||
@@ -620,7 +269,6 @@ int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf,
|
||||
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,
|
||||
@@ -630,18 +278,20 @@ int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf,
|
||||
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;
|
||||
|
||||
hw_version = tpg_hw->tpg_info->hw_dts_version;
|
||||
if (hw_version == CAM_TOP_TPG_VERSION_1)
|
||||
cam_top_tpg_ver1_init(tpg_hw);
|
||||
else if (hw_version == CAM_TOP_TPG_VERSION_2)
|
||||
cam_top_tpg_ver2_init(tpg_hw);
|
||||
|
||||
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;
|
||||
@@ -655,18 +305,13 @@ int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf,
|
||||
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:
|
||||
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_top_tpg_hw_deinit(struct cam_top_tpg_hw *top_tpg_hw)
|
||||
int cam_top_tpg_deinit(struct cam_top_tpg_hw *top_tpg_hw)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
|
||||
|
@@ -3,13 +3,16 @@
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_HW_H_
|
||||
#define _CAM_TOP_TPG_HW_H_
|
||||
#ifndef _CAM_TOP_TPG_CORE_H_
|
||||
#define _CAM_TOP_TPG_CORE_H_
|
||||
|
||||
#include "cam_hw.h"
|
||||
#include "cam_top_tpg_hw_intf.h"
|
||||
#include "cam_top_tpg_soc.h"
|
||||
|
||||
#define CAM_TOP_TPG_VERSION_1 0x10000001
|
||||
#define CAM_TOP_TPG_VERSION_2 0x10000002
|
||||
|
||||
enum cam_top_tpg_encode_format {
|
||||
CAM_TOP_TPG_ENCODE_FORMAT_RAW6,
|
||||
CAM_TOP_TPG_ENCODE_FORMAT_RAW8,
|
||||
@@ -20,48 +23,6 @@ enum cam_top_tpg_encode_format {
|
||||
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
|
||||
*
|
||||
@@ -72,7 +33,7 @@ struct cam_top_tpg_reg_offset {
|
||||
*
|
||||
*/
|
||||
struct cam_top_tpg_hw_info {
|
||||
const struct cam_top_tpg_reg_offset *tpg_reg;
|
||||
void *tpg_reg;
|
||||
uint32_t hw_dts_version;
|
||||
uint32_t csid_max_clk;
|
||||
uint32_t phy_max_clk;
|
||||
@@ -86,15 +47,24 @@ struct cam_top_tpg_hw_info {
|
||||
* @data_type: data type(dt) value
|
||||
* @encode_format: encode format for this data type
|
||||
* @payload_mode payload data, such color bar, color box etc
|
||||
* @bayer_pattern: Bayer patter information
|
||||
* @rotate_period: period value for repeating color, 0 for no rotate
|
||||
* @split_en: enables split mode
|
||||
* @unicolor_en: enables unicolor value
|
||||
* @unicolor_sel: select color used in unicolor mode
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
uint32_t bayer_pattern;
|
||||
uint32_t rotate_period;
|
||||
uint32_t split_en;
|
||||
uint32_t unicolor_en;
|
||||
uint32_t unicolor_sel;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -107,6 +77,7 @@ struct cam_top_tpg_dt_cfg {
|
||||
* @h_blank_count: vertical blanking count value
|
||||
* @vbi_cnt: vbi count
|
||||
* @num_active_dts: number of active dts need to configure
|
||||
* @num_frames: number of output frames
|
||||
* @dt_cfg: dt configuration values
|
||||
*
|
||||
*/
|
||||
@@ -119,6 +90,7 @@ struct cam_top_tpg_cfg {
|
||||
uint32_t h_blank_count;
|
||||
uint32_t vbi_cnt;
|
||||
uint32_t num_active_dts;
|
||||
uint32_t num_frames;
|
||||
struct cam_top_tpg_dt_cfg dt_cfg[4];
|
||||
};
|
||||
|
||||
@@ -145,9 +117,9 @@ struct cam_top_tpg_hw {
|
||||
struct completion tpg_complete;
|
||||
};
|
||||
|
||||
int cam_top_tpg_hw_probe_init(struct cam_hw_intf *tpg_hw_intf,
|
||||
int cam_top_tpg_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);
|
||||
int cam_top_tpg_deinit(struct cam_top_tpg_hw *top_tpg_hw);
|
||||
|
||||
#endif /* _CAM_TOP_TPG_HW_H_ */
|
||||
#endif /* _CAM_TOP_TPG_CORE_H_ */
|
||||
|
@@ -21,10 +21,10 @@ static int cam_top_tpg_component_bind(struct device *dev,
|
||||
struct device *master_dev, void *data)
|
||||
{
|
||||
struct cam_hw_intf *tpg_hw_intf;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct cam_top_tpg_hw *tpg_dev = NULL;
|
||||
struct cam_hw_info *hw_info;
|
||||
struct cam_top_tpg_hw *tpg_hw = NULL;
|
||||
const struct of_device_id *match_dev = NULL;
|
||||
struct cam_top_tpg_hw_info *tpg_hw_data = NULL;
|
||||
struct cam_top_tpg_hw_info *tpg_hw_info = NULL;
|
||||
uint32_t tpg_dev_idx;
|
||||
int rc = 0;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
@@ -37,14 +37,14 @@ static int cam_top_tpg_component_bind(struct device *dev,
|
||||
goto err;
|
||||
}
|
||||
|
||||
tpg_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||
if (!tpg_hw_info) {
|
||||
hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||
if (!hw_info) {
|
||||
rc = -ENOMEM;
|
||||
goto free_hw_intf;
|
||||
}
|
||||
|
||||
tpg_dev = kzalloc(sizeof(struct cam_top_tpg_hw), GFP_KERNEL);
|
||||
if (!tpg_dev) {
|
||||
tpg_hw = kzalloc(sizeof(struct cam_top_tpg_hw), GFP_KERNEL);
|
||||
if (!tpg_hw) {
|
||||
rc = -ENOMEM;
|
||||
goto free_hw_info;
|
||||
}
|
||||
@@ -66,23 +66,23 @@ static int cam_top_tpg_component_bind(struct device *dev,
|
||||
|
||||
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_intf->hw_priv = 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;
|
||||
hw_info->core_info = tpg_hw;
|
||||
hw_info->soc_info.pdev = pdev;
|
||||
hw_info->soc_info.dev = &pdev->dev;
|
||||
hw_info->soc_info.dev_name = tpg_dev_name;
|
||||
hw_info->soc_info.index = tpg_dev_idx;
|
||||
|
||||
tpg_hw_data = (struct cam_top_tpg_hw_info *)match_dev->data;
|
||||
tpg_hw_info = (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;
|
||||
tpg_hw->tpg_info = tpg_hw_info;
|
||||
|
||||
rc = cam_top_tpg_hw_probe_init(tpg_hw_intf, tpg_dev_idx);
|
||||
rc = cam_top_tpg_probe_init(tpg_hw_intf, tpg_dev_idx);
|
||||
if (rc)
|
||||
goto free_dev;
|
||||
|
||||
platform_set_drvdata(pdev, tpg_dev);
|
||||
platform_set_drvdata(pdev, tpg_hw);
|
||||
CAM_DBG(CAM_ISP, "TPG: %d component binded successfully",
|
||||
tpg_hw_intf->hw_idx);
|
||||
|
||||
@@ -94,9 +94,9 @@ static int cam_top_tpg_component_bind(struct device *dev,
|
||||
return 0;
|
||||
|
||||
free_dev:
|
||||
kfree(tpg_dev);
|
||||
kfree(tpg_hw);
|
||||
free_hw_info:
|
||||
kfree(tpg_hw_info);
|
||||
kfree(hw_info);
|
||||
free_hw_intf:
|
||||
kfree(tpg_hw_intf);
|
||||
err:
|
||||
@@ -108,19 +108,19 @@ static void cam_top_tpg_component_unbind(struct device *dev,
|
||||
{
|
||||
struct cam_top_tpg_hw *tpg_dev = NULL;
|
||||
struct cam_hw_intf *tpg_hw_intf;
|
||||
struct cam_hw_info *tpg_hw_info;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct cam_hw_info *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;
|
||||
hw_info = tpg_dev->hw_info;
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG:%d component unbound", tpg_dev->hw_intf->hw_idx);
|
||||
cam_top_tpg_hw_deinit(tpg_dev);
|
||||
cam_top_tpg_deinit(tpg_dev);
|
||||
|
||||
/*release the tpg device memory */
|
||||
kfree(tpg_dev);
|
||||
kfree(tpg_hw_info);
|
||||
kfree(hw_info);
|
||||
kfree(tpg_hw_intf);
|
||||
}
|
||||
|
||||
|
@@ -1,54 +0,0 @@
|
||||
// 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"
|
||||
#include "camera_main.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);
|
||||
|
||||
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");
|
385
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c
Normal file
385
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c
Normal file
@@ -0,0 +1,385 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 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_top_tpg_ver1.h"
|
||||
|
||||
static uint32_t tpg_num_dt_map[CAM_TOP_TPG_MAX_SUPPORTED_DT] = {
|
||||
0,
|
||||
3,
|
||||
1,
|
||||
2
|
||||
};
|
||||
|
||||
static int cam_top_tpg_ver1_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_ver1_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;
|
||||
const struct cam_top_tpg_ver1_reg_offset *tpg_reg;
|
||||
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;
|
||||
tpg_reg = tpg_hw->tpg_info->tpg_reg;
|
||||
|
||||
hw_caps->major_version = tpg_reg->major_version;
|
||||
hw_caps->minor_version = tpg_reg->minor_version;
|
||||
hw_caps->version_incr = 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_ver1_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_ver1_reserve_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_ver1_reserve_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_ver1_reserve_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_ver1_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_ver1_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_ver1_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;
|
||||
struct cam_top_tpg_ver1_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);
|
||||
|
||||
/*
|
||||
* if hblank is notset configureHBlank count 500 and
|
||||
* V blank count is 600
|
||||
*/
|
||||
|
||||
if (tpg_data->h_blank_count)
|
||||
cam_io_w_mb(tpg_data->h_blank_count,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1);
|
||||
else
|
||||
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);
|
||||
|
||||
/* if VBI is notset configureVBI to 0xAFF */
|
||||
if (tpg_data->v_blank_count)
|
||||
cam_io_w_mb(tpg_data->v_blank_count,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg);
|
||||
else
|
||||
cam_io_w_mb(0xAFFF,
|
||||
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg);
|
||||
|
||||
/* 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;
|
||||
|
||||
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 started",
|
||||
tpg_hw->hw_intf->hw_idx, val);
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_ver1_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_ver1_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;
|
||||
}
|
||||
|
||||
int cam_top_tpg_ver1_init(
|
||||
struct cam_top_tpg_hw *tpg_hw)
|
||||
{
|
||||
tpg_hw->hw_intf->hw_ops.get_hw_caps = cam_top_tpg_ver1_get_hw_caps;
|
||||
tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_ver1_reserve;
|
||||
tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_ver1_start;
|
||||
tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_ver1_stop;
|
||||
|
||||
return 0;
|
||||
}
|
55
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h
Normal file
55
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_VER1_H_
|
||||
#define _CAM_TOP_TPG_VER1_H_
|
||||
|
||||
#include "cam_top_tpg_core.h"
|
||||
|
||||
struct cam_top_tpg_ver1_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;
|
||||
};
|
||||
|
||||
int cam_top_tpg_ver1_init(struct cam_top_tpg_hw *tpg_hw);
|
||||
|
||||
#endif /* _CAM_TOP_TPG_VER1_H_ */
|
242
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c
Normal file
242
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.c
Normal file
@@ -0,0 +1,242 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/slab.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_top_tpg_ver2.h"
|
||||
|
||||
#define CAM_TOP_TPG_VER2_MAX_SUPPORTED_DT 1
|
||||
|
||||
static int cam_top_tpg_ver2_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;
|
||||
const struct cam_top_tpg_ver2_reg_offset *tpg_reg;
|
||||
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;
|
||||
tpg_reg = tpg_hw->tpg_info->tpg_reg;
|
||||
|
||||
hw_caps->major_version = tpg_reg->major_version;
|
||||
hw_caps->minor_version = tpg_reg->minor_version;
|
||||
hw_caps->version_incr = 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_ver2_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_ver2_reserve_args *reserv;
|
||||
struct cam_top_tpg_cfg *tpg_data;
|
||||
|
||||
if (!hw_priv || !reserve_args || (arg_size !=
|
||||
sizeof(struct cam_top_tpg_ver2_reserve_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_ver2_reserve_args *)reserve_args;
|
||||
|
||||
if (reserv->num_inport <= 0 ||
|
||||
reserv->num_inport > CAM_TOP_TPG_VER2_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) {
|
||||
CAM_ERR(CAM_ISP, "TPG:%d resource not available state:%d",
|
||||
tpg_hw->hw_intf->hw_idx, tpg_hw->tpg_res.res_state);
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv;
|
||||
tpg_data->h_blank_count = reserv->in_port->hbi_cnt;
|
||||
tpg_data->v_blank_count = 600;
|
||||
tpg_data->dt_cfg[0].data_type = reserv->in_port->dt[0];
|
||||
tpg_data->dt_cfg[0].frame_height = reserv->in_port->height;
|
||||
if (reserv->in_port->usage_type)
|
||||
tpg_data->dt_cfg[0].frame_width =
|
||||
((reserv->in_port->right_stop -
|
||||
reserv->in_port->left_start) + 1);
|
||||
else
|
||||
tpg_data->dt_cfg[0].frame_width =
|
||||
reserv->in_port->left_width;
|
||||
tpg_data->num_active_dts = 1;
|
||||
|
||||
CAM_DBG(CAM_ISP, "TPG:%u dt:0x%x h:%d w:%d hbi:%d vbi:%d reserved",
|
||||
tpg_hw->hw_intf->hw_idx,
|
||||
tpg_data->dt_cfg[0].data_type,
|
||||
tpg_data->dt_cfg[0].frame_height,
|
||||
tpg_data->dt_cfg[0].frame_width,
|
||||
tpg_data->h_blank_count,
|
||||
tpg_data->v_blank_count);
|
||||
|
||||
reserv->node_res = &tpg_hw->tpg_res;
|
||||
tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
|
||||
|
||||
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_top_tpg_ver2_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;
|
||||
struct cam_top_tpg_ver2_reg_offset *tpg_reg;
|
||||
struct cam_top_tpg_cfg *tpg_data;
|
||||
uint32_t val;
|
||||
uint32_t mux_sel_shift = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (tpg_hw->hw_intf->hw_idx == CAM_TOP_TPG_ID_0)
|
||||
mux_sel_shift = tpg_reg->tpg_mux_sel_tpg_0_shift;
|
||||
else if (tpg_hw->hw_intf->hw_idx == CAM_TOP_TPG_ID_1)
|
||||
mux_sel_shift = tpg_reg->tpg_mux_sel_tpg_1_shift;
|
||||
|
||||
cam_io_w_mb((tpg_reg->tpg_mux_sel_en << mux_sel_shift),
|
||||
soc_info->reg_map[1].mem_base + tpg_reg->top_mux_sel);
|
||||
|
||||
val = (((tpg_data->dt_cfg[0].frame_width & 0x3FFF) << 16) |
|
||||
(tpg_data->dt_cfg[0].frame_height & 0x3FFF));
|
||||
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_0);
|
||||
|
||||
val = (tpg_data->h_blank_count & 0x7FF) << 20;
|
||||
val |= (tpg_data->v_blank_count & 0x3FFFF);
|
||||
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_1);
|
||||
|
||||
val = tpg_data->dt_cfg[0].data_type << 11;
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_2);
|
||||
|
||||
/* program number of frames */
|
||||
cam_io_w_mb(1, soc_info->reg_map[0].mem_base + tpg_reg->tpg_cfg_3);
|
||||
|
||||
cam_io_w_mb(tpg_reg->tpg_module_en, soc_info->reg_map[0].mem_base +
|
||||
tpg_reg->tpg_module_cfg);
|
||||
|
||||
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_ver2_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_ver2_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_module_cfg);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int cam_top_tpg_ver2_init(
|
||||
struct cam_top_tpg_hw *tpg_hw)
|
||||
{
|
||||
tpg_hw->hw_intf->hw_ops.get_hw_caps = cam_top_tpg_ver2_get_hw_caps;
|
||||
tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_ver2_reserve;
|
||||
tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_ver2_start;
|
||||
tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_ver2_stop;
|
||||
|
||||
return 0;
|
||||
}
|
44
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.h
Normal file
44
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver2.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_TOP_TPG_VER2_H_
|
||||
#define _CAM_TOP_TPG_VER2_H_
|
||||
|
||||
#include "cam_top_tpg_core.h"
|
||||
|
||||
struct cam_top_tpg_ver2_reg_offset {
|
||||
uint32_t tpg_hw_version;
|
||||
uint32_t tpg_hw_status;
|
||||
uint32_t tpg_module_cfg;
|
||||
uint32_t tpg_cfg_0;
|
||||
uint32_t tpg_cfg_1;
|
||||
uint32_t tpg_cfg_2;
|
||||
uint32_t tpg_cfg_3;
|
||||
uint32_t tpg_spare;
|
||||
uint32_t top_mux_sel;
|
||||
/* configurations */
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t version_incr;
|
||||
uint32_t tpg_module_en;
|
||||
uint32_t tpg_mux_sel_en;
|
||||
uint32_t tpg_mux_sel_tpg_0_shift;
|
||||
uint32_t tpg_mux_sel_tpg_1_shift;
|
||||
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;
|
||||
};
|
||||
|
||||
int cam_top_tpg_ver2_init(struct cam_top_tpg_hw *tpg_hw);
|
||||
|
||||
#endif /* _CAM_TOP_TPG_VER2_H_ */
|
@@ -50,7 +50,7 @@
|
||||
|
||||
#include "ope_dev_intf.h"
|
||||
|
||||
#include "cam_top_tpg_v1.h"
|
||||
#include "cam_top_tpg.h"
|
||||
#include "cam_tfe_dev.h"
|
||||
#include "cam_tfe_csid530.h"
|
||||
#include "camera_main.h"
|
||||
@@ -77,6 +77,7 @@ static const struct camera_submodule_component camera_base[] = {
|
||||
|
||||
static const struct camera_submodule_component camera_isp[] = {
|
||||
#ifdef CONFIG_SPECTRA_ISP
|
||||
{&cam_top_tpg_init_module, &cam_top_tpg_exit_module},
|
||||
{&cam_ife_csid17x_init_module, &cam_ife_csid17x_exit_module},
|
||||
{&cam_ife_csid_lite_init_module, &cam_ife_csid_lite_exit_module},
|
||||
{&cam_vfe_init_module, &cam_vfe_exit_module},
|
||||
@@ -86,7 +87,7 @@ static const struct camera_submodule_component camera_isp[] = {
|
||||
|
||||
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_top_tpg_init_module, &cam_top_tpg_exit_module},
|
||||
{&cam_tfe_init_module, &cam_tfe_exit_module},
|
||||
{&cam_tfe_csid530_init_module, &cam_tfe_csid530_exit_module},
|
||||
#endif
|
||||
@@ -218,13 +219,14 @@ static struct platform_driver *const cam_component_drivers[] = {
|
||||
&cam_cdm_intf_driver,
|
||||
&cam_hw_cdm_driver,
|
||||
#ifdef CONFIG_SPECTRA_ISP
|
||||
&cam_top_tpg_driver,
|
||||
&cam_ife_csid17x_driver,
|
||||
&cam_ife_csid_lite_driver,
|
||||
&cam_vfe_driver,
|
||||
&isp_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_SPECTRA_TFE
|
||||
&cam_top_tpg_v1_driver,
|
||||
&cam_top_tpg_driver,
|
||||
&cam_tfe_driver,
|
||||
&cam_tfe_csid530_driver,
|
||||
#endif
|
||||
|
@@ -15,13 +15,14 @@ extern struct platform_driver cam_cpas_driver;
|
||||
extern struct platform_driver cam_cdm_intf_driver;
|
||||
extern struct platform_driver cam_hw_cdm_driver;
|
||||
#ifdef CONFIG_SPECTRA_ISP
|
||||
extern struct platform_driver cam_top_tpg_driver;
|
||||
extern struct platform_driver cam_ife_csid17x_driver;
|
||||
extern struct platform_driver cam_ife_csid_lite_driver;
|
||||
extern struct platform_driver cam_vfe_driver;
|
||||
extern struct platform_driver isp_driver;
|
||||
#endif
|
||||
#ifdef CONFIG_SPECTRA_TFE
|
||||
extern struct platform_driver cam_top_tpg_v1_driver;
|
||||
extern struct platform_driver cam_top_tpg_driver;
|
||||
extern struct platform_driver cam_tfe_driver;
|
||||
extern struct platform_driver cam_tfe_csid530_driver;
|
||||
#endif
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __UAPI_CAM_ISP_IFE_H__
|
||||
@@ -49,6 +49,8 @@
|
||||
#define CAM_ISP_IFE_IN_RES_PHY_4 (CAM_ISP_IFE_IN_RES_BASE + 5)
|
||||
#define CAM_ISP_IFE_IN_RES_PHY_5 (CAM_ISP_IFE_IN_RES_BASE + 6)
|
||||
#define CAM_ISP_IFE_IN_RES_RD (CAM_ISP_IFE_IN_RES_BASE + 7)
|
||||
#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 8)
|
||||
#define CAM_ISP_IFE_IN_RES_CPHY_TPG_0 (CAM_ISP_IFE_IN_RES_BASE + 8)
|
||||
#define CAM_ISP_IFE_IN_RES_CPHY_TPG_1 (CAM_ISP_IFE_IN_RES_BASE + 9)
|
||||
#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 10)
|
||||
|
||||
#endif /* __UAPI_CAM_ISP_IFE_H__ */
|
||||
|
Reference in New Issue
Block a user