sde: wb: add changes to support Dedicated-CWB

Add new capture/tap point as CRTC property for
D-CWB feature. Update the hardware blocks and
corresponding APIs to configure D-CWB data path.
Add new hardware pingpong blocks that
are dedicated for CWB.

Change-Id: I22576df1768b50f9f47d8527f62913b01ff4d9a7
Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>
This commit is contained in:
Chandan Uddaraju
2020-10-08 14:29:34 -07:00
parent 359caa1be3
commit 4fe3d97078
9 changed files with 204 additions and 26 deletions

View File

@@ -5454,6 +5454,12 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
{CAPTURE_DSPP_OUT, "capture_pp_out"}, {CAPTURE_DSPP_OUT, "capture_pp_out"},
}; };
static const struct drm_prop_enum_list e_dcwb_data_points[] = {
{CAPTURE_MIXER_OUT, "capture_mixer_out"},
{CAPTURE_DSPP_OUT, "capture_pp_out"},
{CAPTURE_DEMURA_OUT, "capture_demura_out"},
};
static const struct drm_prop_enum_list e_idle_pc_state[] = { static const struct drm_prop_enum_list e_idle_pc_state[] = {
{IDLE_PC_NONE, "idle_pc_none"}, {IDLE_PC_NONE, "idle_pc_none"},
{IDLE_PC_ENABLE, "idle_pc_enable"}, {IDLE_PC_ENABLE, "idle_pc_enable"},
@@ -5524,7 +5530,12 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
ARRAY_SIZE(e_idle_pc_state), 0, ARRAY_SIZE(e_idle_pc_state), 0,
CRTC_PROP_IDLE_PC_STATE); CRTC_PROP_IDLE_PC_STATE);
if (catalog->has_cwb_support) if (catalog->has_dedicated_cwb_support)
msm_property_install_enum(&sde_crtc->property_info,
"capture_mode", 0, 0, e_dcwb_data_points,
ARRAY_SIZE(e_dcwb_data_points), 0,
CRTC_PROP_CAPTURE_OUTPUT);
else if (catalog->has_cwb_support)
msm_property_install_enum(&sde_crtc->property_info, msm_property_install_enum(&sde_crtc->property_info,
"capture_mode", 0, 0, e_cwb_data_points, "capture_mode", 0, 0, e_cwb_data_points,
ARRAY_SIZE(e_cwb_data_points), 0, ARRAY_SIZE(e_cwb_data_points), 0,

View File

@@ -56,10 +56,12 @@ enum sde_crtc_client_type {
* enum sde_crtc_output_capture_point * enum sde_crtc_output_capture_point
* @MIXER_OUT : capture mixer output * @MIXER_OUT : capture mixer output
* @DSPP_OUT : capture output of dspp * @DSPP_OUT : capture output of dspp
* @CAPTURE_DEMURA_OUT : capture output of demura
*/ */
enum sde_crtc_output_capture_point { enum sde_crtc_output_capture_point {
CAPTURE_MIXER_OUT, CAPTURE_MIXER_OUT,
CAPTURE_DSPP_OUT CAPTURE_DSPP_OUT,
CAPTURE_DEMURA_OUT
}; };
/** /**

View File

@@ -467,12 +467,14 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc,
hw_ctl = crtc->mixers[0].hw_ctl; hw_ctl = crtc->mixers[0].hw_ctl;
if (hw_ctl && hw_ctl->ops.setup_intf_cfg_v1 && if (hw_ctl && hw_ctl->ops.setup_intf_cfg_v1 &&
test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features)) { test_bit(SDE_WB_CWB_CTRL | SDE_WB_DCWB_CTRL,
&hw_wb->caps->features)) {
struct sde_hw_intf_cfg_v1 intf_cfg = { 0, }; struct sde_hw_intf_cfg_v1 intf_cfg = { 0, };
for (i = 0; i < crtc->num_mixers; i++) for (i = 0; i < crtc->num_mixers; i++)
intf_cfg.cwb[intf_cfg.cwb_count++] = intf_cfg.cwb[intf_cfg.cwb_count++] = (enum sde_cwb)
(enum sde_cwb)(hw_pp->idx + i); (test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features) ?
((hw_pp->idx % 2) + i) : (hw_pp->idx + i));
if (hw_pp->merge_3d && (intf_cfg.merge_3d_count < if (hw_pp->merge_3d && (intf_cfg.merge_3d_count <
MAX_MERGE_3D_PER_CTL_V1) && need_merge) MAX_MERGE_3D_PER_CTL_V1) && need_merge)
@@ -483,12 +485,17 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc,
hw_pp->ops.setup_3d_mode(hw_pp, (enable && need_merge) ? hw_pp->ops.setup_3d_mode(hw_pp, (enable && need_merge) ?
BLEND_3D_H_ROW_INT : 0); BLEND_3D_H_ROW_INT : 0);
if (hw_wb->ops.bind_pingpong_blk) if ((hw_wb->ops.bind_pingpong_blk) &&
test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features))
hw_wb->ops.bind_pingpong_blk(hw_wb, enable, hw_pp->idx); hw_wb->ops.bind_pingpong_blk(hw_wb, enable, hw_pp->idx);
if ((hw_wb->ops.bind_dcwb_pp_blk) &&
test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features))
hw_wb->ops.bind_dcwb_pp_blk(hw_wb, enable, hw_pp->idx);
if (hw_ctl->ops.update_intf_cfg) { if (hw_ctl->ops.update_intf_cfg) {
hw_ctl->ops.update_intf_cfg(hw_ctl, &intf_cfg, enable); hw_ctl->ops.update_intf_cfg(hw_ctl, &intf_cfg, enable);
SDE_DEBUG("in CWB mode on CTL_%d PP-%d merge3d:%d\n", SDE_DEBUG("in CWB/DCWB mode on CTL_%d PP-%d merge3d:%d\n",
hw_ctl->idx - CTL_0, hw_ctl->idx - CTL_0,
hw_pp->idx - PINGPONG_0, hw_pp->idx - PINGPONG_0,
hw_pp->merge_3d ? hw_pp->merge_3d ?
@@ -503,7 +510,7 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc,
if (hw_ctl && hw_ctl->ops.update_wb_cfg) { if (hw_ctl && hw_ctl->ops.update_wb_cfg) {
hw_ctl->ops.update_wb_cfg(hw_ctl, intf_cfg, enable); hw_ctl->ops.update_wb_cfg(hw_ctl, intf_cfg, enable);
SDE_DEBUG("in CWB mode adding WB for CTL_%d\n", SDE_DEBUG("in CWB/DCWB mode adding WB for CTL_%d\n",
hw_ctl->idx - CTL_0); hw_ctl->idx - CTL_0);
} }
} }
@@ -593,13 +600,14 @@ static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc,
u32 encoder_mask = 0; u32 encoder_mask = 0;
/* Check if WB has CWB support */ /* Check if WB has CWB support */
if (wb_cfg->features & BIT(SDE_WB_HAS_CWB)) { if ((wb_cfg->features & BIT(SDE_WB_HAS_CWB))
|| (wb_cfg->features & BIT(SDE_WB_HAS_DCWB))) {
encoder_mask = crtc_state->encoder_mask; encoder_mask = crtc_state->encoder_mask;
encoder_mask &= ~drm_encoder_mask(phys_enc->parent); encoder_mask &= ~drm_encoder_mask(phys_enc->parent);
} }
phys_enc->in_clone_mode = encoder_mask ? true : false; phys_enc->in_clone_mode = encoder_mask ? true : false;
SDE_DEBUG("detect CWB - status:%d\n", phys_enc->in_clone_mode); SDE_DEBUG("detect CWB(OR)DCWB - status:%d\n", phys_enc->in_clone_mode);
} }
static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc,
@@ -863,6 +871,7 @@ static void _sde_encoder_phys_wb_update_cwb_flush(
int i = 0; int i = 0;
int cwb_capture_mode = 0; int cwb_capture_mode = 0;
enum sde_cwb cwb_idx = 0; enum sde_cwb cwb_idx = 0;
enum sde_dcwb dcwb_idx = 0;
enum sde_cwb src_pp_idx = 0; enum sde_cwb src_pp_idx = 0;
bool dspp_out = false; bool dspp_out = false;
bool need_merge = false; bool need_merge = false;
@@ -895,9 +904,19 @@ static void _sde_encoder_phys_wb_update_cwb_flush(
dspp_out = (cwb_capture_mode == CAPTURE_DSPP_OUT); dspp_out = (cwb_capture_mode == CAPTURE_DSPP_OUT);
need_merge = (crtc->num_mixers > 1) ? true : false; need_merge = (crtc->num_mixers > 1) ? true : false;
if (src_pp_idx > CWB_0 || ((cwb_idx + crtc->num_mixers) > CWB_MAX)) { if (test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features)) {
SDE_ERROR("invalid hw config for CWB\n"); dcwb_idx = (enum sde_dcwb) ((hw_pp->idx % 2) + i);
return; if ((dcwb_idx + crtc->num_mixers) > DCWB_MAX) {
SDE_ERROR("invalid hw config for DCWB. dcwb_idx=%d, num_mixers=%d\n",
dcwb_idx, crtc->num_mixers);
return;
}
} else {
if (src_pp_idx > CWB_0 || ((cwb_idx + crtc->num_mixers) > CWB_MAX)) {
SDE_ERROR("invalid hw config for CWB. pp_idx-%d, cwb_idx=%d, num_mixers=%d\n",
src_pp_idx, dcwb_idx, crtc->num_mixers);
return;
}
} }
if (hw_ctl->ops.update_bitmask) if (hw_ctl->ops.update_bitmask)
@@ -908,18 +927,30 @@ static void _sde_encoder_phys_wb_update_cwb_flush(
hw_ctl->ops.update_bitmask(hw_ctl, SDE_HW_FLUSH_CDM, hw_ctl->ops.update_bitmask(hw_ctl, SDE_HW_FLUSH_CDM,
hw_cdm->idx, 1); hw_cdm->idx, 1);
if (test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features)) { if (test_bit(SDE_WB_CWB_CTRL | SDE_WB_DCWB_CTRL,
&hw_wb->caps->features)) {
for (i = 0; i < crtc->num_mixers; i++) { for (i = 0; i < crtc->num_mixers; i++) {
cwb_idx = (enum sde_cwb) (hw_pp->idx + i);
src_pp_idx = (enum sde_cwb) (src_pp_idx + i); src_pp_idx = (enum sde_cwb) (src_pp_idx + i);
if (hw_wb->ops.program_cwb_ctrl) if (test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features)) {
hw_wb->ops.program_cwb_ctrl(hw_wb, cwb_idx, dcwb_idx = (enum sde_dcwb) ((hw_pp->idx % 2) + i);
src_pp_idx, dspp_out, enable); if (hw_wb->ops.program_dcwb_ctrl)
hw_wb->ops.program_dcwb_ctrl(hw_wb, dcwb_idx,
src_pp_idx, cwb_capture_mode,
enable);
if (hw_ctl->ops.update_bitmask)
hw_ctl->ops.update_bitmask(hw_ctl,
SDE_HW_FLUSH_CWB, dcwb_idx, 1);
if (hw_ctl->ops.update_bitmask) } else if (test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features)) {
hw_ctl->ops.update_bitmask(hw_ctl, cwb_idx = (enum sde_cwb) (hw_pp->idx + i);
if (hw_wb->ops.program_cwb_ctrl)
hw_wb->ops.program_cwb_ctrl(hw_wb, cwb_idx,
src_pp_idx, dspp_out, enable);
if (hw_ctl->ops.update_bitmask)
hw_ctl->ops.update_bitmask(hw_ctl,
SDE_HW_FLUSH_CWB, cwb_idx, 1); SDE_HW_FLUSH_CWB, cwb_idx, 1);
}
} }
if (need_merge && hw_ctl->ops.update_bitmask if (need_merge && hw_ctl->ops.update_bitmask

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/ */
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -306,6 +306,7 @@ enum {
enum { enum {
PP_OFF, PP_OFF,
PP_LEN, PP_LEN,
PP_CWB,
TE_OFF, TE_OFF,
TE_LEN, TE_LEN,
TE2_OFF, TE2_OFF,
@@ -782,6 +783,7 @@ static struct sde_prop_type ds_prop[] = {
static struct sde_prop_type pp_prop[] = { static struct sde_prop_type pp_prop[] = {
{PP_OFF, "qcom,sde-pp-off", true, PROP_TYPE_U32_ARRAY}, {PP_OFF, "qcom,sde-pp-off", true, PROP_TYPE_U32_ARRAY},
{PP_LEN, "qcom,sde-pp-size", false, PROP_TYPE_U32}, {PP_LEN, "qcom,sde-pp-size", false, PROP_TYPE_U32},
{PP_CWB, "qcom,sde-pp-cwb", false, PROP_TYPE_U32_ARRAY},
{TE_OFF, "qcom,sde-te-off", false, PROP_TYPE_U32_ARRAY}, {TE_OFF, "qcom,sde-te-off", false, PROP_TYPE_U32_ARRAY},
{TE_LEN, "qcom,sde-te-size", false, PROP_TYPE_U32}, {TE_LEN, "qcom,sde-te-size", false, PROP_TYPE_U32},
{TE2_OFF, "qcom,sde-te2-off", false, PROP_TYPE_U32_ARRAY}, {TE2_OFF, "qcom,sde-te2-off", false, PROP_TYPE_U32_ARRAY},
@@ -2349,7 +2351,18 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev))
set_bit(SDE_WB_INPUT_CTRL, &wb->features); set_bit(SDE_WB_INPUT_CTRL, &wb->features);
if (sde_cfg->has_cwb_support) { if (sde_cfg->has_dedicated_cwb_support) {
set_bit(SDE_WB_HAS_DCWB, &wb->features);
if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev))
set_bit(SDE_WB_DCWB_CTRL, &wb->features);
if (major_version >= SDE_HW_MAJOR(SDE_HW_VER_810)) {
sde_cfg->cwb_blk_off = 0x66A00;
sde_cfg->cwb_blk_stride = 0x400;
} else {
sde_cfg->cwb_blk_off = 0x83000;
sde_cfg->cwb_blk_stride = 0x100;
}
} else if (sde_cfg->has_cwb_support) {
set_bit(SDE_WB_HAS_CWB, &wb->features); set_bit(SDE_WB_HAS_CWB, &wb->features);
if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev))
set_bit(SDE_WB_CWB_CTRL, &wb->features); set_bit(SDE_WB_CWB_CTRL, &wb->features);
@@ -3629,6 +3642,9 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
if (PROP_VALUE_ACCESS(prop_value, PP_SLAVE, i)) if (PROP_VALUE_ACCESS(prop_value, PP_SLAVE, i))
set_bit(SDE_PINGPONG_SLAVE, &pp->features); set_bit(SDE_PINGPONG_SLAVE, &pp->features);
if (PROP_VALUE_ACCESS(prop_value, PP_CWB, i))
set_bit(SDE_PINGPONG_CWB, &pp->features);
if (major_version < SDE_HW_MAJOR(SDE_HW_VER_700)) { if (major_version < SDE_HW_MAJOR(SDE_HW_VER_700)) {
sblk->dsc.base = PROP_VALUE_ACCESS(prop_value, sblk->dsc.base = PROP_VALUE_ACCESS(prop_value,
DSC_OFF, i); DSC_OFF, i);

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/ */
#ifndef _SDE_HW_CATALOG_H #ifndef _SDE_HW_CATALOG_H
@@ -401,6 +401,7 @@ enum {
* @SDE_PINGPONG_DITHER, Dither blocks * @SDE_PINGPONG_DITHER, Dither blocks
* @SDE_PINGPONG_DITHER_LUMA, Dither sub-blocks and features * @SDE_PINGPONG_DITHER_LUMA, Dither sub-blocks and features
* @SDE_PINGPONG_MERGE_3D, Separate MERGE_3D block exists * @SDE_PINGPONG_MERGE_3D, Separate MERGE_3D block exists
* @SDE_PINGPONG_CWB, PP block supports CWB
* @SDE_PINGPONG_MAX * @SDE_PINGPONG_MAX
*/ */
enum { enum {
@@ -412,6 +413,7 @@ enum {
SDE_PINGPONG_DITHER, SDE_PINGPONG_DITHER,
SDE_PINGPONG_DITHER_LUMA, SDE_PINGPONG_DITHER_LUMA,
SDE_PINGPONG_MERGE_3D, SDE_PINGPONG_MERGE_3D,
SDE_PINGPONG_CWB,
SDE_PINGPONG_MAX SDE_PINGPONG_MAX
}; };
@@ -508,7 +510,9 @@ enum {
* @SDE_WB_INPUT_CTRL Writeback supports from which pp block input pixel * @SDE_WB_INPUT_CTRL Writeback supports from which pp block input pixel
* data arrives. * data arrives.
* @SDE_WB_HAS_CWB Writeback block supports concurrent writeback * @SDE_WB_HAS_CWB Writeback block supports concurrent writeback
* @SDE_WB_HAS_DCWB Writeback block supports dedicated CWB
* @SDE_WB_CWB_CTRL Separate CWB control is available for configuring * @SDE_WB_CWB_CTRL Separate CWB control is available for configuring
* @SDE_WB_DCWB_CTRL Separate DCWB control is available for configuring
* @SDE_WB_MAX maximum value * @SDE_WB_MAX maximum value
*/ */
enum { enum {
@@ -529,7 +533,9 @@ enum {
SDE_WB_CDP, SDE_WB_CDP,
SDE_WB_INPUT_CTRL, SDE_WB_INPUT_CTRL,
SDE_WB_HAS_CWB, SDE_WB_HAS_CWB,
SDE_WB_HAS_DCWB,
SDE_WB_CWB_CTRL, SDE_WB_CWB_CTRL,
SDE_WB_DCWB_CTRL,
SDE_WB_MAX SDE_WB_MAX
}; };
@@ -1400,6 +1406,7 @@ struct sde_perf_cfg {
* @has_cdp Client driven prefetch feature status * @has_cdp Client driven prefetch feature status
* @has_wb_ubwc UBWC feature supported on WB * @has_wb_ubwc UBWC feature supported on WB
* @has_cwb_support indicates if device supports primary capture through CWB * @has_cwb_support indicates if device supports primary capture through CWB
* @has_dedicated_cwb_support indicates if device supports dedicated path for CWB capture
* @cwb_blk_off CWB offset address * @cwb_blk_off CWB offset address
* @cwb_blk_stride offset between each CWB blk * @cwb_blk_stride offset between each CWB blk
* @ubwc_version UBWC feature version (0x0 for not supported) * @ubwc_version UBWC feature version (0x0 for not supported)
@@ -1481,6 +1488,7 @@ struct sde_mdss_cfg {
bool has_dim_layer; bool has_dim_layer;
bool has_wb_ubwc; bool has_wb_ubwc;
bool has_cwb_support; bool has_cwb_support;
bool has_dedicated_cwb_support;
u32 cwb_blk_off; u32 cwb_blk_off;
u32 cwb_blk_stride; u32 cwb_blk_stride;
u32 ubwc_version; u32 ubwc_version;

View File

@@ -161,6 +161,11 @@ static const u32 cdm_flush_tbl[CDM_MAX] = {SDE_NONE, 0};
static const u32 cwb_flush_tbl[CWB_MAX] = {SDE_NONE, SDE_NONE, 1, 2, 3, static const u32 cwb_flush_tbl[CWB_MAX] = {SDE_NONE, SDE_NONE, 1, 2, 3,
4, 5}; 4, 5};
/**
* list of CWB bits in CTL_CWB_FLUSH for dedicated cwb
*/
static const u32 dcwb_flush_tbl[CWB_MAX] = {SDE_NONE, SDE_NONE, 0, 1};
/** /**
* list of DSPP sub-blk flush bits in CTL_DSPP_x_FLUSH * list of DSPP sub-blk flush bits in CTL_DSPP_x_FLUSH
*/ */

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/ */
#ifndef _SDE_HW_MDSS_H #ifndef _SDE_HW_MDSS_H
@@ -223,6 +223,8 @@ enum sde_pingpong {
PINGPONG_3, PINGPONG_3,
PINGPONG_4, PINGPONG_4,
PINGPONG_5, PINGPONG_5,
PINGPONG_CWB_0,
PINGPONG_CWB_1,
PINGPONG_S0, PINGPONG_S0,
PINGPONG_MAX PINGPONG_MAX
}; };
@@ -302,6 +304,12 @@ enum sde_cwb {
CWB_MAX CWB_MAX
}; };
enum sde_dcwb {
DCWB_0 = 0x1,
DCWB_1,
DCWB_MAX
};
enum sde_wd_timer { enum sde_wd_timer {
WD_TIMER_0 = 0x1, WD_TIMER_0 = 0x1,
WD_TIMER_1, WD_TIMER_1,
@@ -335,6 +343,7 @@ enum sde_merge_3d {
MERGE_3D_0 = 1, MERGE_3D_0 = 1,
MERGE_3D_1, MERGE_3D_1,
MERGE_3D_2, MERGE_3D_2,
MERGE_3D_CWB_0,
MERGE_3D_MAX MERGE_3D_MAX
}; };

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/ */
#include "sde_hw_mdss.h" #include "sde_hw_mdss.h"
@@ -99,6 +99,31 @@ static void _sde_hw_cwb_ctrl_init(struct sde_mdss_cfg *m,
} }
} }
static void _sde_hw_dcwb_ctrl_init(struct sde_mdss_cfg *m,
void __iomem *addr, struct sde_hw_blk_reg_map *b)
{
int i;
u32 blk_off;
char name[64] = {0};
if (!b)
return;
b->base_off = addr;
b->blk_off = m->cwb_blk_off;
b->length = 0x20;
b->hwversion = m->hwversion;
b->log_mask = SDE_DBG_MASK_WB;
for (i = 0; i < m->pingpong_count; i++) {
snprintf(name, sizeof(name), "dcwb%d", i);
blk_off = b->blk_off + (m->cwb_blk_stride * i);
sde_dbg_reg_register_dump_range(SDE_DBG_NAME, name,
blk_off, blk_off + b->length, 0xff);
}
}
static void sde_hw_wb_setup_outaddress(struct sde_hw_wb *ctx, static void sde_hw_wb_setup_outaddress(struct sde_hw_wb *ctx,
struct sde_hw_wb_cfg *data) struct sde_hw_wb_cfg *data)
{ {
@@ -270,6 +295,46 @@ static void sde_hw_wb_bind_pingpong_blk(
SDE_REG_WRITE(c, WB_MUX, mux_cfg); SDE_REG_WRITE(c, WB_MUX, mux_cfg);
} }
static void sde_hw_wb_bind_dcwb_pp_blk(
struct sde_hw_wb *ctx,
bool enable,
const enum sde_pingpong pp)
{
struct sde_hw_blk_reg_map *c;
int mux_cfg = 0xF;
if (!ctx)
return;
c = &ctx->hw;
if (enable)
mux_cfg = 0xd;
SDE_REG_WRITE(c, WB_MUX, mux_cfg);
}
static void sde_hw_wb_program_dcwb_ctrl(struct sde_hw_wb *ctx,
const enum sde_dcwb cur_idx, const enum sde_cwb data_src,
int tap_location, bool enable)
{
struct sde_hw_blk_reg_map *c;
u32 blk_base;
if (!ctx)
return;
c = &ctx->dcwb_hw;
blk_base = ctx->catalog->cwb_blk_stride * (cur_idx - DCWB_0);
if (enable) {
SDE_REG_WRITE(c, blk_base + CWB_CTRL_SRC_SEL, data_src - CWB_0);
SDE_REG_WRITE(c, blk_base + CWB_CTRL_MODE, tap_location);
} else {
SDE_REG_WRITE(c, blk_base + CWB_CTRL_SRC_SEL, 0xf);
SDE_REG_WRITE(c, blk_base + CWB_CTRL_MODE, 0x0);
}
}
static void sde_hw_wb_program_cwb_ctrl(struct sde_hw_wb *ctx, static void sde_hw_wb_program_cwb_ctrl(struct sde_hw_wb *ctx,
const enum sde_cwb cur_idx, const enum sde_cwb data_src, const enum sde_cwb cur_idx, const enum sde_cwb data_src,
bool dspp_out, bool enable) bool dspp_out, bool enable)
@@ -312,6 +377,11 @@ static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
if (test_bit(SDE_WB_CWB_CTRL, &features)) if (test_bit(SDE_WB_CWB_CTRL, &features))
ops->program_cwb_ctrl = sde_hw_wb_program_cwb_ctrl; ops->program_cwb_ctrl = sde_hw_wb_program_cwb_ctrl;
if (test_bit(SDE_WB_DCWB_CTRL, &features)) {
ops->program_dcwb_ctrl = sde_hw_wb_program_dcwb_ctrl;
ops->bind_dcwb_pp_blk = sde_hw_wb_bind_dcwb_pp_blk;
}
} }
static struct sde_hw_blk_ops sde_hw_ops = { static struct sde_hw_blk_ops sde_hw_ops = {
@@ -362,6 +432,9 @@ struct sde_hw_wb *sde_hw_wb_init(enum sde_wb idx,
if (test_bit(SDE_WB_CWB_CTRL, &cfg->features)) if (test_bit(SDE_WB_CWB_CTRL, &cfg->features))
_sde_hw_cwb_ctrl_init(m, addr, &c->cwb_hw); _sde_hw_cwb_ctrl_init(m, addr, &c->cwb_hw);
if (test_bit(SDE_WB_DCWB_CTRL, &cfg->features))
_sde_hw_dcwb_ctrl_init(m, addr, &c->dcwb_hw);
return c; return c;
blk_init_error: blk_init_error:

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/ */
#ifndef _SDE_HW_WB_H #ifndef _SDE_HW_WB_H
@@ -114,6 +114,16 @@ struct sde_hw_wb_ops {
bool enable, bool enable,
const enum sde_pingpong pp); const enum sde_pingpong pp);
/**
* bind_dcwb_pp_blk - enable/disable the connection with cwb pp
* @ctx: Pointer to wb context
* @enable: enable/disable connection
* @pp: pingpong blk id
*/
void (*bind_dcwb_pp_blk)(struct sde_hw_wb *ctx,
bool enable,
const enum sde_pingpong pp);
/** /**
* program_cwb_ctrl - program cwb block configp * program_cwb_ctrl - program cwb block configp
* @ctx: Pointer to wb context * @ctx: Pointer to wb context
@@ -124,6 +134,17 @@ struct sde_hw_wb_ops {
*/ */
void (*program_cwb_ctrl)(struct sde_hw_wb *ctx, const enum sde_cwb cwb, void (*program_cwb_ctrl)(struct sde_hw_wb *ctx, const enum sde_cwb cwb,
const enum sde_cwb data_src, bool dspp_out, bool enable); const enum sde_cwb data_src, bool dspp_out, bool enable);
/**
* program_dcwb_ctrl - program cwb block configp
* @ctx: Pointer to wb context
* @pp_idx: Current CWB block index to poram
* @data_src: Source CWB/PingPong block index
* @tap_location: Tap LM output, dspp output or Demura output
* @enable: enable or disable the CWB path to tap the output
*/
void (*program_dcwb_ctrl)(struct sde_hw_wb *ctx, const enum sde_dcwb cwb,
const enum sde_cwb data_src, int tap_location, bool enable);
}; };
/** /**
@@ -137,6 +158,7 @@ struct sde_hw_wb_ops {
* @ops: function pointers * @ops: function pointers
* @hw_mdp: MDP top level hardware block * @hw_mdp: MDP top level hardware block
* @cwb_hw: CWB control hwio details * @cwb_hw: CWB control hwio details
* @dcwb_hw: DCWB control hwio details
*/ */
struct sde_hw_wb { struct sde_hw_wb {
struct sde_hw_blk base; struct sde_hw_blk base;
@@ -153,6 +175,7 @@ struct sde_hw_wb {
struct sde_hw_mdp *hw_mdp; struct sde_hw_mdp *hw_mdp;
struct sde_hw_blk_reg_map cwb_hw; struct sde_hw_blk_reg_map cwb_hw;
struct sde_hw_blk_reg_map dcwb_hw;
}; };
/** /**