msm: camera: ife: Add support for csitpg 1.3

Add version_3 files to support next revision
of CPHY TPG. Extended capability for Multi-VC
mode of operation. Add support to handle IRQ.

CRs-Fixed: 2663712
Change-Id: I91864af6e9415e74104a6bce266dd78d5c021dc7
Signed-off-by: Vishalsingh Hajeri <vhajeri@codeaurora.org>
This commit is contained in:
Vishalsingh Hajeri
2020-03-26 17:35:01 -07:00
parent f480c039c7
commit 346084f00a
15 changed files with 707 additions and 51 deletions

View File

@@ -90,6 +90,7 @@ camera-$(CONFIG_SPECTRA_ISP) += \
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_ver1.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_ver3.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 \

View File

@@ -2946,7 +2946,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
}
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))
(in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) ||
(in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_2))
rc = cam_ife_hw_mgr_acquire_tpg(ife_ctx, in_port,
acquire_hw_info->num_inputs);

View File

@@ -1146,7 +1146,8 @@ int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
path_data->crop_enable);
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)) {
(reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_1) ||
(reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_CPHY_TPG_2)) {
path_data->dt = CAM_IFE_CPHY_TPG_DT_VAL;
path_data->vc = CAM_IFE_CPHY_TPG_VC_VAL;
} else if (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) {

View File

@@ -11,7 +11,7 @@
#include "cam_ife_csid_hw_intf.h"
/* Max top tpg instance */
#define CAM_TOP_TPG_HW_NUM_MAX 2
#define CAM_TOP_TPG_HW_NUM_MAX 3
/* Max supported number of DT for TPG */
#define CAM_TOP_TPG_MAX_SUPPORTED_DT 4
@@ -21,6 +21,7 @@
enum cam_top_tpg_id {
CAM_TOP_TPG_ID_0,
CAM_TOP_TPG_ID_1,
CAM_TOP_TPG_ID_2,
CAM_TFE_TPG_ID_MAX,
};
@@ -55,7 +56,7 @@ struct cam_top_tpg_ver1_reserve_args {
/**
* struct cam_top_tpg_ver2_reserve_args
* @num_inport: number of inport
* TPG supports 1 VC/DT
* TPG supports 1 VC/DT combo
* @in_port : Input port resource info structure pointer
* @node_res : Reserved resource structure pointer
*
@@ -66,6 +67,20 @@ struct cam_top_tpg_ver2_reserve_args {
struct cam_isp_resource_node *node_res;
};
/**
* struct cam_top_tpg_ver2_reserve_args
* @num_inport: number of inport
* TPG supports 4 VC's and 4 DT's per VC
* @in_port : Input port resource info structure pointer
* @node_res : Reserved resource structure pointer
*
*/
struct cam_top_tpg_ver3_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()
*

View File

@@ -6,6 +6,7 @@
#include <linux/module.h>
#include "cam_top_tpg101.h"
#include "cam_top_tpg102.h"
#include "cam_top_tpg103.h"
#include "cam_top_tpg_core.h"
#include "cam_top_tpg_dev.h"
#include "camera_main.h"
@@ -19,6 +20,10 @@ static const struct of_device_id cam_top_tpg_dt_match[] = {
.compatible = "qcom,tpg102",
.data = &cam_top_tpg102_hw_info,
},
{
.compatible = "qcom,tpg103",
.data = &cam_top_tpg103_hw_info,
},
{}
};

View File

@@ -43,8 +43,8 @@ static struct cam_top_tpg_ver2_reg_offset cam_top_tpg102_reg = {
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,
.csid_max_clk = 400000000,
.phy_max_clk = 400000000,
};
#endif /* _CAM_TOP_TPG102_H_ */

View File

@@ -0,0 +1,124 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_TOP_TPG103_H_
#define _CAM_TOP_TPG103_H_
#include "cam_top_tpg_ver3.h"
#include "cam_top_tpg_core.h"
static struct cam_top_tpg_ver3_reg_offset cam_top_tpg103_reg = {
.tpg_hw_version = 0x0,
.tpg_hw_status = 0x4,
.tpg_ctrl = 0x64,
.tpg_vc0_cfg0 = 0x68,
.tpg_vc0_lfsr_seed = 0x6C,
.tpg_vc0_hbi_cfg = 0x70,
.tpg_vc0_vbi_cfg = 0x74,
.tpg_vc0_color_bar_cfg = 0x78,
.tpg_vc0_dt_0_cfg_0 = 0x7C,
.tpg_vc0_dt_0_cfg_1 = 0x80,
.tpg_vc0_dt_0_cfg_2 = 0x84,
.tpg_vc0_dt_1_cfg_0 = 0x88,
.tpg_vc0_dt_1_cfg_1 = 0x8C,
.tpg_vc0_dt_1_cfg_2 = 0x90,
.tpg_vc0_dt_2_cfg_0 = 0x94,
.tpg_vc0_dt_2_cfg_1 = 0x98,
.tpg_vc0_dt_2_cfg_2 = 0x9C,
.tpg_vc0_dt_3_cfg_0 = 0xA0,
.tpg_vc0_dt_3_cfg_1 = 0xA4,
.tpg_vc0_dt_3_cfg_2 = 0xA8,
.tpg_vc1_cfg0 = 0xC8,
.tpg_vc1_lfsr_seed = 0xCC,
.tpg_vc1_hbi_cfg = 0xD0,
.tpg_vc1_vbi_cfg = 0xD4,
.tpg_vc1_color_bar_cfg = 0xD8,
.tpg_vc1_dt_0_cfg_0 = 0xDC,
.tpg_vc1_dt_0_cfg_1 = 0xE0,
.tpg_vc1_dt_0_cfg_2 = 0xE4,
.tpg_vc1_dt_1_cfg_0 = 0xE8,
.tpg_vc1_dt_1_cfg_1 = 0xEC,
.tpg_vc1_dt_1_cfg_2 = 0xF0,
.tpg_vc1_dt_2_cfg_0 = 0xF4,
.tpg_vc1_dt_2_cfg_1 = 0xF8,
.tpg_vc1_dt_2_cfg_2 = 0xFC,
.tpg_vc1_dt_3_cfg_0 = 0x100,
.tpg_vc1_dt_3_cfg_1 = 0x104,
.tpg_vc1_dt_3_cfg_2 = 0x108,
.tpg_vc2_cfg0 = 0x128,
.tpg_vc2_lfsr_seed = 0x12C,
.tpg_vc2_hbi_cfg = 0x130,
.tpg_vc2_vbi_cfg = 0x134,
.tpg_vc2_color_bar_cfg = 0x138,
.tpg_vc2_dt_0_cfg_0 = 0x13C,
.tpg_vc2_dt_0_cfg_1 = 0x140,
.tpg_vc2_dt_0_cfg_2 = 0x144,
.tpg_vc2_dt_1_cfg_0 = 0x148,
.tpg_vc2_dt_1_cfg_1 = 0x14C,
.tpg_vc2_dt_1_cfg_2 = 0x150,
.tpg_vc2_dt_2_cfg_0 = 0x154,
.tpg_vc2_dt_2_cfg_1 = 0x158,
.tpg_vc2_dt_2_cfg_2 = 0x15C,
.tpg_vc2_dt_3_cfg_0 = 0x160,
.tpg_vc2_dt_3_cfg_1 = 0x164,
.tpg_vc2_dt_3_cfg_2 = 0x168,
.tpg_vc3_cfg0 = 0x188,
.tpg_vc3_lfsr_seed = 0x18C,
.tpg_vc3_hbi_cfg = 0x190,
.tpg_vc3_vbi_cfg = 0x194,
.tpg_vc3_color_bar_cfg = 0x198,
.tpg_vc3_dt_0_cfg_0 = 0x19C,
.tpg_vc3_dt_0_cfg_1 = 0x1A0,
.tpg_vc3_dt_0_cfg_2 = 0x1A4,
.tpg_vc3_dt_1_cfg_0 = 0x1A8,
.tpg_vc3_dt_1_cfg_1 = 0x1AC,
.tpg_vc3_dt_1_cfg_2 = 0x1B0,
.tpg_vc3_dt_2_cfg_0 = 0x1B4,
.tpg_vc3_dt_2_cfg_1 = 0x1B8,
.tpg_vc3_dt_2_cfg_2 = 0x1BC,
.tpg_vc3_dt_3_cfg_0 = 0x1C0,
.tpg_vc3_dt_3_cfg_1 = 0x1C4,
.tpg_vc3_dt_3_cfg_2 = 0x1C8,
.tpg_throttle = 0x1CC,
.tpg_top_irq_status = 0x1E0,
.tpg_top_irq_mask = 0x1E4,
.tpg_top_irq_clear = 0x1E8,
.tpg_top_irq_set = 0x1EC,
.tpg_top_irq_cmd = 0x1F0,
.tpg_top_clear = 0x1F4,
.tpg_test_bus_crtl = 0x1F8,
.tpg_spare = 0x1FC,
/* configurations */
.major_version = 2,
.minor_version = 0,
.version_incr = 0,
.tpg_en_shift_val = 0,
.tpg_cphy_dphy_sel_shift_val = 3,
.tpg_num_active_lanes_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 = 20,
.tpg_payload_mode_color = 0x8,
.tpg_split_en_shift = 4,
.top_mux_reg_offset = 0x1C,
.tpg_vc_dt_pattern_id_shift = 6,
.tpg_num_active_vcs_shift = 30,
};
struct cam_top_tpg_hw_info cam_top_tpg103_hw_info = {
.tpg_reg = &cam_top_tpg103_reg,
.hw_dts_version = CAM_TOP_TPG_VERSION_3,
.csid_max_clk = 480000000,
.phy_max_clk = 480000000,
};
#endif /* _CAM_TOP_TPG103_H_ */

View File

@@ -15,6 +15,40 @@
#include "cam_cpas_api.h"
#include "cam_top_tpg_ver1.h"
#include "cam_top_tpg_ver2.h"
#include "cam_top_tpg_ver3.h"
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 = 5;
break;
default:
CAM_ERR(CAM_ISP, "Unsupported input encode format %d",
in_format);
rc = -EINVAL;
}
return rc;
}
static int cam_top_tpg_release(void *hw_priv,
void *release_args, uint32_t arg_size)
@@ -212,6 +246,42 @@ static int cam_top_tpg_set_phy_clock(
return 0;
}
irqreturn_t cam_top_tpg_irq(int irq_num, void *data)
{
struct cam_top_tpg_hw *tpg_hw;
struct cam_hw_soc_info *soc_info;
struct cam_top_tpg_ver3_reg_offset *tpg_reg;
uint32_t irq_status_top;
unsigned long flags;
if (!data) {
CAM_ERR(CAM_ISP, "TPG: Invalid arguments");
return IRQ_HANDLED;
}
tpg_hw = (struct cam_top_tpg_hw *) data;
CAM_DBG(CAM_ISP, "CPHY TPG %d IRQ Handling", tpg_hw->hw_intf->hw_idx);
soc_info = &tpg_hw->hw_info->soc_info;
tpg_reg = tpg_hw->tpg_info->tpg_reg;
irq_status_top = cam_io_r_mb(soc_info->reg_map[0].mem_base +
tpg_reg->tpg_top_irq_status);
spin_lock_irqsave(&tpg_hw->hw_info->hw_lock, flags);
/* clear */
cam_io_w_mb(irq_status_top, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_top_irq_clear);
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_top_irq_cmd);
spin_unlock_irqrestore(&tpg_hw->hw_info->hw_lock, flags);
CAM_DBG(CAM_ISP, "TPG: irq_status_top = 0x%x", irq_status_top);
return IRQ_HANDLED;
}
static int cam_top_tpg_process_cmd(void *hw_priv,
uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
{
@@ -272,7 +342,7 @@ int cam_top_tpg_probe_init(struct cam_hw_intf *tpg_hw_intf,
init_completion(&tpg_hw->tpg_complete);
rc = cam_top_tpg_init_soc_resources(&tpg_hw->hw_info->soc_info,
tpg_hw);
cam_top_tpg_irq, tpg_hw);
if (rc < 0) {
CAM_ERR(CAM_ISP, "TPG:%d Failed to init_soc", tpg_idx);
goto err;
@@ -291,6 +361,8 @@ int cam_top_tpg_probe_init(struct cam_hw_intf *tpg_hw_intf,
cam_top_tpg_ver1_init(tpg_hw);
else if (hw_version == CAM_TOP_TPG_VERSION_2)
cam_top_tpg_ver2_init(tpg_hw);
else if (hw_version == CAM_TOP_TPG_VERSION_3)
cam_top_tpg_ver3_init(tpg_hw);
tpg_hw->tpg_res.res_type = CAM_ISP_RESOURCE_TPG;
tpg_hw->tpg_res.res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;

View File

@@ -12,6 +12,8 @@
#define CAM_TOP_TPG_VERSION_1 0x10000001
#define CAM_TOP_TPG_VERSION_2 0x10000002
#define CAM_TOP_TPG_VERSION_3 0x20000000
enum cam_top_tpg_encode_format {
CAM_TOP_TPG_ENCODE_FORMAT_RAW6,
@@ -85,12 +87,13 @@ struct cam_top_tpg_cfg {
uint32_t pix_pattern;
uint32_t phy_sel;
uint32_t num_active_lanes;
uint32_t vc_num;
uint32_t vc_num[4];
uint32_t v_blank_count;
uint32_t h_blank_count;
uint32_t vbi_cnt;
uint32_t num_active_dts;
uint32_t num_frames;
uint32_t vc_dt_pattern_id;
struct cam_top_tpg_dt_cfg dt_cfg[4];
};
@@ -117,6 +120,8 @@ struct cam_top_tpg_hw {
struct completion tpg_complete;
};
int cam_top_tpg_get_format(uint32_t in_format, uint32_t *tpg_encode_format);
int cam_top_tpg_probe_init(struct cam_hw_intf *tpg_hw_intf,
uint32_t tpg_idx);

View File

@@ -8,7 +8,7 @@
#include "cam_debug_util.h"
int cam_top_tpg_init_soc_resources(struct cam_hw_soc_info *soc_info,
void *irq_data)
irq_handler_t tpg_irq_handler, void *irq_data)
{
int rc = 0;
struct cam_cpas_register_params cpas_register_param;
@@ -26,7 +26,7 @@ int cam_top_tpg_init_soc_resources(struct cam_hw_soc_info *soc_info,
return rc;
/* Need to see if we want post process the clock list */
rc = cam_soc_util_request_platform_resource(soc_info, NULL,
rc = cam_soc_util_request_platform_resource(soc_info, tpg_irq_handler,
irq_data);
if (rc < 0) {

View File

@@ -37,11 +37,12 @@ struct cam_top_tpg_device_soc_info {
* @brief: csid initialization function for the soc info
*
* @soc_info: soc info structure pointer
* @tpg_irq_handler: irq handler function to be registered
* @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);
irq_handler_t tpg_irq_handler, void *irq_data);
/**
* cam_top_tpg_deinit_soc_resources()

View File

@@ -21,39 +21,6 @@ static uint32_t tpg_num_dt_map[CAM_TOP_TPG_MAX_SUPPORTED_DT] = {
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,
@@ -136,7 +103,7 @@ static int cam_top_tpg_ver1_reserve(
mutex_unlock(&tpg_hw->hw_info->hw_mutex);
return -EINVAL;
}
rc = cam_top_tpg_ver1_get_format(reserv->in_port[0]->format,
rc = cam_top_tpg_get_format(reserv->in_port[0]->format,
&encode_format);
if (rc)
goto error;
@@ -144,7 +111,7 @@ static int cam_top_tpg_ver1_reserve(
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->vc_num[0] = 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;
@@ -165,7 +132,7 @@ static int cam_top_tpg_ver1_reserve(
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->vc_num[0], 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);
@@ -181,7 +148,7 @@ static int cam_top_tpg_ver1_reserve(
goto end;
for (i = 1; i < reserv->num_inport; i++) {
if ((tpg_data->vc_num != reserv->in_port[i]->vc) ||
if ((tpg_data->vc_num[0] != 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) ||
@@ -193,7 +160,7 @@ static int cam_top_tpg_ver1_reserve(
rc = -EINVAL;
goto error;
}
rc = cam_top_tpg_ver1_get_format(reserv->in_port[0]->format,
rc = cam_top_tpg_get_format(reserv->in_port[0]->format,
&encode_format);
if (rc)
return rc;
@@ -278,7 +245,7 @@ static int cam_top_tpg_ver1_start(
}
val = (tpg_num_dt_map[tpg_data->num_active_dts-1] <<
tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num;
tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num[0];
cam_io_w_mb(val, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg0);
/*

View File

@@ -0,0 +1,345 @@
// 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_ver3.h"
static int cam_top_tpg_ver3_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_ver3_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_ver3_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_ver3_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_ver3_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_ver3_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) {
rc = -EINVAL;
goto error;
}
if ((reserv->in_port->lane_num <= 0 ||
reserv->in_port->lane_num > 4) ||
(reserv->in_port->lane_type >= 2)) {
CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG:%u invalid input %d %d",
tpg_hw->hw_intf->hw_idx,
reserv->in_port->lane_num,
reserv->in_port->lane_type);
rc = -EINVAL;
goto error;
}
tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv;
for (i = 0; i < reserv->in_port->num_valid_vc_dt; i++) {
if (reserv->in_port->dt[i] > 0x3f ||
reserv->in_port->vc[i] > 0x1f) {
CAM_ERR(CAM_ISP, "TPG:%u Invalid vc:%d dt %d",
tpg_hw->hw_intf->hw_idx,
reserv->in_port->vc[i],
reserv->in_port->dt[i]);
rc = -EINVAL;
goto error;
}
tpg_data->vc_num[i] = reserv->in_port->vc[i];
tpg_data->dt_cfg[i].data_type = reserv->in_port->dt[i];
}
rc = cam_top_tpg_get_format(reserv->in_port->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->phy_sel = reserv->in_port->lane_type;
tpg_data->num_active_lanes = reserv->in_port->lane_num;
tpg_data->h_blank_count = reserv->in_port->hbi_cnt;
tpg_data->v_blank_count = 600;
tpg_data->num_active_dts = reserv->in_port->num_valid_vc_dt;
for (i = 0; i < reserv->in_port->num_valid_vc_dt; i++) {
tpg_data->dt_cfg[i].encode_format = encode_format;
tpg_data->dt_cfg[i].frame_height = reserv->in_port->height;
if (reserv->in_port->usage_type)
tpg_data->dt_cfg[i].frame_width =
((reserv->in_port->right_stop -
reserv->in_port->left_start) + 1);
else
tpg_data->dt_cfg[i].frame_width =
reserv->in_port->left_width;
}
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);
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_ver3_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_ver3_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(1, soc_info->reg_map[0].mem_base + tpg_reg->tpg_top_clear);
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 & 0xFFFF));
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_vc0_dt_0_cfg_0 + 0x60 * i);
cam_io_w_mb(tpg_data->dt_cfg[i].data_type,
soc_info->reg_map[0].mem_base +
tpg_reg->tpg_vc0_dt_0_cfg_1 + 0x60 * 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_vc0_dt_0_cfg_2 + 0x60 * i);
val = (1 << tpg_reg->tpg_split_en_shift);
val |= tpg_data->pix_pattern;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_vc0_color_bar_cfg + 0x60 * i);
/*
* 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_vc0_hbi_cfg + 0x60 * i);
else
cam_io_w_mb(0x1F4,
soc_info->reg_map[0].mem_base +
tpg_reg->tpg_vc0_hbi_cfg + 0x60 * i);
if (tpg_data->v_blank_count)
cam_io_w_mb(tpg_data->h_blank_count,
soc_info->reg_map[0].mem_base +
tpg_reg->tpg_vc0_vbi_cfg + 0x60 * i);
else
cam_io_w_mb(0x258,
soc_info->reg_map[0].mem_base +
tpg_reg->tpg_vc0_vbi_cfg + 0x60 * i);
cam_io_w_mb(0x12345678, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_vc0_lfsr_seed + 0x60 * i);
val = (((tpg_data->num_active_dts-1) <<
tpg_reg->tpg_num_dts_shift_val) | tpg_data->vc_num[i]);
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_vc0_cfg0 + 0x60 * i);
}
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_top_irq_mask);
val = ((tpg_data->num_active_dts - 1) <<
(tpg_reg->tpg_num_active_vcs_shift) |
(tpg_data->num_active_lanes - 1) <<
tpg_reg->tpg_num_active_lanes_shift) |
(tpg_data->vc_dt_pattern_id) <<
(tpg_reg->tpg_vc_dt_pattern_id_shift) |
(tpg_data->phy_sel << tpg_reg->tpg_cphy_dphy_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_ver3_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_ver3_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);
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_top_irq_mask);
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_top_irq_clear);
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_top_irq_cmd);
cam_io_w_mb(1, soc_info->reg_map[0].mem_base + tpg_reg->tpg_top_clear);
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_ver3_init(
struct cam_top_tpg_hw *tpg_hw)
{
tpg_hw->hw_intf->hw_ops.get_hw_caps = cam_top_tpg_ver3_get_hw_caps;
tpg_hw->hw_intf->hw_ops.reserve = cam_top_tpg_ver3_reserve;
tpg_hw->hw_intf->hw_ops.start = cam_top_tpg_ver3_start;
tpg_hw->hw_intf->hw_ops.stop = cam_top_tpg_ver3_stop;
return 0;
}

View File

@@ -0,0 +1,118 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_TOP_TPG_VER3_H_
#define _CAM_TOP_TPG_VER3_H_
#include "cam_top_tpg_core.h"
struct cam_top_tpg_ver3_reg_offset {
uint32_t tpg_hw_version;
uint32_t tpg_hw_status;
uint32_t tpg_ctrl;
uint32_t tpg_vc0_cfg0;
uint32_t tpg_vc0_lfsr_seed;
uint32_t tpg_vc0_hbi_cfg;
uint32_t tpg_vc0_vbi_cfg;
uint32_t tpg_vc0_color_bar_cfg;
uint32_t tpg_vc0_dt_0_cfg_0;
uint32_t tpg_vc0_dt_0_cfg_1;
uint32_t tpg_vc0_dt_0_cfg_2;
uint32_t tpg_vc0_dt_1_cfg_0;
uint32_t tpg_vc0_dt_1_cfg_1;
uint32_t tpg_vc0_dt_1_cfg_2;
uint32_t tpg_vc0_dt_2_cfg_0;
uint32_t tpg_vc0_dt_2_cfg_1;
uint32_t tpg_vc0_dt_2_cfg_2;
uint32_t tpg_vc0_dt_3_cfg_0;
uint32_t tpg_vc0_dt_3_cfg_1;
uint32_t tpg_vc0_dt_3_cfg_2;
uint32_t tpg_vc1_cfg0;
uint32_t tpg_vc1_lfsr_seed;
uint32_t tpg_vc1_hbi_cfg;
uint32_t tpg_vc1_vbi_cfg;
uint32_t tpg_vc1_color_bar_cfg;
uint32_t tpg_vc1_dt_0_cfg_0;
uint32_t tpg_vc1_dt_0_cfg_1;
uint32_t tpg_vc1_dt_0_cfg_2;
uint32_t tpg_vc1_dt_1_cfg_0;
uint32_t tpg_vc1_dt_1_cfg_1;
uint32_t tpg_vc1_dt_1_cfg_2;
uint32_t tpg_vc1_dt_2_cfg_0;
uint32_t tpg_vc1_dt_2_cfg_1;
uint32_t tpg_vc1_dt_2_cfg_2;
uint32_t tpg_vc1_dt_3_cfg_0;
uint32_t tpg_vc1_dt_3_cfg_1;
uint32_t tpg_vc1_dt_3_cfg_2;
uint32_t tpg_vc2_cfg0;
uint32_t tpg_vc2_lfsr_seed;
uint32_t tpg_vc2_hbi_cfg;
uint32_t tpg_vc2_vbi_cfg;
uint32_t tpg_vc2_color_bar_cfg;
uint32_t tpg_vc2_dt_0_cfg_0;
uint32_t tpg_vc2_dt_0_cfg_1;
uint32_t tpg_vc2_dt_0_cfg_2;
uint32_t tpg_vc2_dt_1_cfg_0;
uint32_t tpg_vc2_dt_1_cfg_1;
uint32_t tpg_vc2_dt_1_cfg_2;
uint32_t tpg_vc2_dt_2_cfg_0;
uint32_t tpg_vc2_dt_2_cfg_1;
uint32_t tpg_vc2_dt_2_cfg_2;
uint32_t tpg_vc2_dt_3_cfg_0;
uint32_t tpg_vc2_dt_3_cfg_1;
uint32_t tpg_vc2_dt_3_cfg_2;
uint32_t tpg_vc3_cfg0;
uint32_t tpg_vc3_lfsr_seed;
uint32_t tpg_vc3_hbi_cfg;
uint32_t tpg_vc3_vbi_cfg;
uint32_t tpg_vc3_color_bar_cfg;
uint32_t tpg_vc3_dt_0_cfg_0;
uint32_t tpg_vc3_dt_0_cfg_1;
uint32_t tpg_vc3_dt_0_cfg_2;
uint32_t tpg_vc3_dt_1_cfg_0;
uint32_t tpg_vc3_dt_1_cfg_1;
uint32_t tpg_vc3_dt_1_cfg_2;
uint32_t tpg_vc3_dt_2_cfg_0;
uint32_t tpg_vc3_dt_2_cfg_1;
uint32_t tpg_vc3_dt_2_cfg_2;
uint32_t tpg_vc3_dt_3_cfg_0;
uint32_t tpg_vc3_dt_3_cfg_1;
uint32_t tpg_vc3_dt_3_cfg_2;
uint32_t tpg_throttle;
uint32_t tpg_top_irq_status;
uint32_t tpg_top_irq_mask;
uint32_t tpg_top_irq_clear;
uint32_t tpg_top_irq_set;
uint32_t tpg_top_irq_cmd;
uint32_t tpg_top_clear;
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_cphy_dphy_sel_shift_val;
uint32_t tpg_num_active_lanes_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;
uint32_t tpg_vc_dt_pattern_id_shift;
uint32_t tpg_num_active_vcs_shift;
};
int cam_top_tpg_ver3_init(struct cam_top_tpg_hw *tpg_hw);
#endif /* _CAM_TOP_TPG_VER3_H_ */

View File

@@ -51,6 +51,7 @@
#define CAM_ISP_IFE_IN_RES_RD (CAM_ISP_IFE_IN_RES_BASE + 7)
#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)
#define CAM_ISP_IFE_IN_RES_CPHY_TPG_2 (CAM_ISP_IFE_IN_RES_BASE + 10)
#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 11)
#endif /* __UAPI_CAM_ISP_IFE_H__ */