disp: msm: add cwb dither support
Add cwb dither support. Catalog: Read dtsi value of cwb dither in pp parse part. Wb: Install blob property for cwb dither. Wb hw: Adds a new wb ops function to program cwb dither hardware. CRTC: To ensure that userspace can check whether cwb dither is supported, added "has_cwb_dither" to sde kms info. PingPong: In order to reuse dither's map array, move dither_depth_map array to pp header file. Change-Id: I77e6a052a00b7c649452103145e5d7b4c8deb3a2 Signed-off-by: Yuchao Ma <yuchaom@codeaurora.org>
This commit is contained in:
@@ -193,6 +193,7 @@ enum msm_mdp_conn_property {
|
|||||||
CONNECTOR_PROP_HDR_INFO,
|
CONNECTOR_PROP_HDR_INFO,
|
||||||
CONNECTOR_PROP_EXT_HDR_INFO,
|
CONNECTOR_PROP_EXT_HDR_INFO,
|
||||||
CONNECTOR_PROP_PP_DITHER,
|
CONNECTOR_PROP_PP_DITHER,
|
||||||
|
CONNECTOR_PROP_PP_CWB_DITHER,
|
||||||
CONNECTOR_PROP_HDR_METADATA,
|
CONNECTOR_PROP_HDR_METADATA,
|
||||||
CONNECTOR_PROP_DEMURA_PANEL_ID,
|
CONNECTOR_PROP_DEMURA_PANEL_ID,
|
||||||
|
|
||||||
|
@@ -919,6 +919,10 @@ static void _sde_encoder_phys_wb_update_cwb_flush(
|
|||||||
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;
|
||||||
|
struct sde_connector *c_conn = NULL;
|
||||||
|
struct sde_connector_state *c_state = NULL;
|
||||||
|
void *dither_cfg = NULL;
|
||||||
|
size_t dither_sz = 0;
|
||||||
|
|
||||||
if (!phys_enc->in_clone_mode) {
|
if (!phys_enc->in_clone_mode) {
|
||||||
SDE_DEBUG("not in CWB mode. early return\n");
|
SDE_DEBUG("not in CWB mode. early return\n");
|
||||||
@@ -973,11 +977,30 @@ static void _sde_encoder_phys_wb_update_cwb_flush(
|
|||||||
|
|
||||||
if (test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features) ||
|
if (test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features) ||
|
||||||
test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features)) {
|
test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features)) {
|
||||||
|
if (test_bit(SDE_WB_CWB_DITHER_CTRL, &hw_wb->caps->features)) {
|
||||||
|
if (cwb_capture_mode) {
|
||||||
|
c_conn = to_sde_connector(phys_enc->connector);
|
||||||
|
c_state = to_sde_connector_state(phys_enc->connector->state);
|
||||||
|
dither_cfg = msm_property_get_blob(&c_conn->property_info,
|
||||||
|
&c_state->property_state, &dither_sz,
|
||||||
|
CONNECTOR_PROP_PP_CWB_DITHER);
|
||||||
|
SDE_DEBUG("Read cwb dither setting from blob %pK\n", dither_cfg);
|
||||||
|
} else {
|
||||||
|
/* disable case: tap is lm */
|
||||||
|
dither_cfg = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < crtc->num_mixers; i++) {
|
for (i = 0; i < crtc->num_mixers; i++) {
|
||||||
src_pp_idx = (enum sde_cwb) (src_pp_idx + i);
|
src_pp_idx = (enum sde_cwb) (src_pp_idx + i);
|
||||||
|
|
||||||
if (test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features)) {
|
if (test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features)) {
|
||||||
dcwb_idx = (enum sde_dcwb) ((hw_pp->idx % 2) + i);
|
dcwb_idx = (enum sde_dcwb) ((hw_pp->idx % 2) + i);
|
||||||
|
if (test_bit(SDE_WB_CWB_DITHER_CTRL, &hw_wb->caps->features)) {
|
||||||
|
if (hw_wb->ops.program_cwb_dither_ctrl)
|
||||||
|
hw_wb->ops.program_cwb_dither_ctrl(hw_wb,
|
||||||
|
dcwb_idx, dither_cfg, dither_sz, enable);
|
||||||
|
}
|
||||||
if (hw_wb->ops.program_dcwb_ctrl)
|
if (hw_wb->ops.program_dcwb_ctrl)
|
||||||
hw_wb->ops.program_dcwb_ctrl(hw_wb, dcwb_idx,
|
hw_wb->ops.program_dcwb_ctrl(hw_wb, dcwb_idx,
|
||||||
src_pp_idx, cwb_capture_mode,
|
src_pp_idx, cwb_capture_mode,
|
||||||
|
@@ -329,6 +329,7 @@ enum {
|
|||||||
DITHER_OFF,
|
DITHER_OFF,
|
||||||
DITHER_LEN,
|
DITHER_LEN,
|
||||||
DITHER_VER,
|
DITHER_VER,
|
||||||
|
CWB_DITHER,
|
||||||
PP_MERGE_3D_ID,
|
PP_MERGE_3D_ID,
|
||||||
PP_PROP_MAX,
|
PP_PROP_MAX,
|
||||||
};
|
};
|
||||||
@@ -850,6 +851,7 @@ static struct sde_prop_type pp_prop[] = {
|
|||||||
{DITHER_OFF, "qcom,sde-dither-off", false, PROP_TYPE_U32_ARRAY},
|
{DITHER_OFF, "qcom,sde-dither-off", false, PROP_TYPE_U32_ARRAY},
|
||||||
{DITHER_LEN, "qcom,sde-dither-size", false, PROP_TYPE_U32},
|
{DITHER_LEN, "qcom,sde-dither-size", false, PROP_TYPE_U32},
|
||||||
{DITHER_VER, "qcom,sde-dither-version", false, PROP_TYPE_U32},
|
{DITHER_VER, "qcom,sde-dither-version", false, PROP_TYPE_U32},
|
||||||
|
{CWB_DITHER, "qcom,sde-cwb-dither", false, PROP_TYPE_U32_ARRAY},
|
||||||
{PP_MERGE_3D_ID, "qcom,sde-pp-merge-3d-id", false, PROP_TYPE_U32_ARRAY},
|
{PP_MERGE_3D_ID, "qcom,sde-pp-merge-3d-id", false, PROP_TYPE_U32_ARRAY},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2564,6 +2566,10 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
|
|||||||
sde_cfg->cwb_blk_off = 0x83000;
|
sde_cfg->cwb_blk_off = 0x83000;
|
||||||
sde_cfg->cwb_blk_stride = 0x100;
|
sde_cfg->cwb_blk_stride = 0x100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sde_cfg->has_cwb_dither)
|
||||||
|
set_bit(SDE_WB_CWB_DITHER_CTRL, &wb->features);
|
||||||
|
|
||||||
} else if (sde_cfg->has_cwb_support) {
|
} 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))
|
||||||
@@ -3910,6 +3916,11 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
|
|||||||
sblk->dither.version = PROP_VALUE_ACCESS(prop_value, DITHER_VER,
|
sblk->dither.version = PROP_VALUE_ACCESS(prop_value, DITHER_VER,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
if (sde_cfg->has_cwb_dither &&
|
||||||
|
PROP_VALUE_ACCESS(prop_value, CWB_DITHER, i)) {
|
||||||
|
set_bit(SDE_PINGPONG_CWB_DITHER, &pp->features);
|
||||||
|
}
|
||||||
|
|
||||||
if (sde_cfg->dither_luma_mode_support)
|
if (sde_cfg->dither_luma_mode_support)
|
||||||
set_bit(SDE_PINGPONG_DITHER_LUMA, &pp->features);
|
set_bit(SDE_PINGPONG_DITHER_LUMA, &pp->features);
|
||||||
|
|
||||||
@@ -5094,6 +5105,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
|
|||||||
sde_cfg->syscache_supported = true;
|
sde_cfg->syscache_supported = true;
|
||||||
} else if (IS_WAIPIO_TARGET(hw_rev)) {
|
} else if (IS_WAIPIO_TARGET(hw_rev)) {
|
||||||
sde_cfg->has_dedicated_cwb_support = true;
|
sde_cfg->has_dedicated_cwb_support = true;
|
||||||
|
sde_cfg->has_cwb_dither = true;
|
||||||
sde_cfg->has_wb_ubwc = true;
|
sde_cfg->has_wb_ubwc = true;
|
||||||
sde_cfg->has_cwb_crop = true;
|
sde_cfg->has_cwb_crop = true;
|
||||||
sde_cfg->has_qsync = true;
|
sde_cfg->has_qsync = true;
|
||||||
|
@@ -421,6 +421,7 @@ enum {
|
|||||||
* @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_CWB, PP block supports CWB
|
||||||
|
* @SDE_PINGPONG_CWB_DITHER, PP block supports CWB dither
|
||||||
* @SDE_PINGPONG_MAX
|
* @SDE_PINGPONG_MAX
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
@@ -433,6 +434,7 @@ enum {
|
|||||||
SDE_PINGPONG_DITHER_LUMA,
|
SDE_PINGPONG_DITHER_LUMA,
|
||||||
SDE_PINGPONG_MERGE_3D,
|
SDE_PINGPONG_MERGE_3D,
|
||||||
SDE_PINGPONG_CWB,
|
SDE_PINGPONG_CWB,
|
||||||
|
SDE_PINGPONG_CWB_DITHER,
|
||||||
SDE_PINGPONG_MAX
|
SDE_PINGPONG_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -535,6 +537,7 @@ enum {
|
|||||||
* @SDE_WB_CROP CWB supports cropping
|
* @SDE_WB_CROP CWB supports cropping
|
||||||
* @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_DCWB_CTRL Separate DCWB control is available for configuring
|
||||||
|
* @SDE_WB_CWB_DITHER_CTRL CWB dither is available for configuring
|
||||||
* @SDE_WB_MAX maximum value
|
* @SDE_WB_MAX maximum value
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
@@ -559,6 +562,7 @@ enum {
|
|||||||
SDE_WB_CROP,
|
SDE_WB_CROP,
|
||||||
SDE_WB_CWB_CTRL,
|
SDE_WB_CWB_CTRL,
|
||||||
SDE_WB_DCWB_CTRL,
|
SDE_WB_DCWB_CTRL,
|
||||||
|
SDE_WB_CWB_DITHER_CTRL,
|
||||||
SDE_WB_MAX
|
SDE_WB_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1458,6 +1462,7 @@ struct sde_perf_cfg {
|
|||||||
* @has_cwb_crop CWB cropping is supported
|
* @has_cwb_crop CWB cropping is supported
|
||||||
* @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
|
* @has_dedicated_cwb_support indicates if device supports dedicated path for CWB capture
|
||||||
|
* @has_cwb_dither indicates if device supports cwb dither feature
|
||||||
* @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)
|
||||||
@@ -1543,6 +1548,7 @@ struct sde_mdss_cfg {
|
|||||||
bool has_cwb_crop;
|
bool has_cwb_crop;
|
||||||
bool has_cwb_support;
|
bool has_cwb_support;
|
||||||
bool has_dedicated_cwb_support;
|
bool has_dedicated_cwb_support;
|
||||||
|
bool has_cwb_dither;
|
||||||
u32 cwb_blk_off;
|
u32 cwb_blk_off;
|
||||||
u32 cwb_blk_stride;
|
u32 cwb_blk_stride;
|
||||||
u32 ubwc_version;
|
u32 ubwc_version;
|
||||||
|
@@ -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 <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
@@ -33,11 +33,6 @@
|
|||||||
#define PP_DCE_DATA_IN_SWAP 0x0ac
|
#define PP_DCE_DATA_IN_SWAP 0x0ac
|
||||||
#define PP_DCE_DATA_OUT_SWAP 0x0c8
|
#define PP_DCE_DATA_OUT_SWAP 0x0c8
|
||||||
|
|
||||||
#define DITHER_DEPTH_MAP_INDEX 9
|
|
||||||
static u32 dither_depth_map[DITHER_DEPTH_MAP_INDEX] = {
|
|
||||||
0, 0, 0, 0, 0, 1, 2, 3, 3
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DITHER_VER_MAJOR_1 1
|
#define DITHER_VER_MAJOR_1 1
|
||||||
/* supports LUMA Dither */
|
/* supports LUMA Dither */
|
||||||
#define DITHER_VER_MAJOR_2 2
|
#define DITHER_VER_MAJOR_2 2
|
||||||
|
@@ -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_PINGPONG_H
|
#ifndef _SDE_HW_PINGPONG_H
|
||||||
@@ -15,6 +15,11 @@
|
|||||||
struct sde_hw_pingpong;
|
struct sde_hw_pingpong;
|
||||||
struct sde_hw_merge_3d;
|
struct sde_hw_merge_3d;
|
||||||
|
|
||||||
|
#define DITHER_DEPTH_MAP_INDEX 9
|
||||||
|
static u32 dither_depth_map[DITHER_DEPTH_MAP_INDEX] = {
|
||||||
|
0, 0, 0, 0, 0, 1, 2, 3, 3
|
||||||
|
};
|
||||||
|
|
||||||
struct sde_hw_dsc_cfg {
|
struct sde_hw_dsc_cfg {
|
||||||
u8 enable;
|
u8 enable;
|
||||||
};
|
};
|
||||||
|
@@ -126,6 +126,38 @@ static void _sde_hw_dcwb_ctrl_init(struct sde_mdss_cfg *m,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _sde_hw_dcwb_pp_ctrl_init(struct sde_mdss_cfg *m,
|
||||||
|
void __iomem *addr, struct sde_hw_wb *hw_wb)
|
||||||
|
{
|
||||||
|
int i = 0, dcwb_pp_count = 0;
|
||||||
|
struct sde_pingpong_cfg *pp_blk = NULL;
|
||||||
|
|
||||||
|
if (!hw_wb) {
|
||||||
|
DRM_ERROR("hw_wb is null\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < m->pingpong_count; i++) {
|
||||||
|
pp_blk = &m->pingpong[i];
|
||||||
|
if (test_bit(SDE_PINGPONG_CWB_DITHER, &pp_blk->features)) {
|
||||||
|
if (dcwb_pp_count < DCWB_MAX - DCWB_0) {
|
||||||
|
hw_wb->dcwb_pp_hw[dcwb_pp_count].caps = pp_blk;
|
||||||
|
hw_wb->dcwb_pp_hw[dcwb_pp_count].idx = pp_blk->id;
|
||||||
|
hw_wb->dcwb_pp_hw[dcwb_pp_count].hw.base_off = addr;
|
||||||
|
hw_wb->dcwb_pp_hw[dcwb_pp_count].hw.blk_off = pp_blk->base;
|
||||||
|
hw_wb->dcwb_pp_hw[dcwb_pp_count].hw.length = pp_blk->len;
|
||||||
|
hw_wb->dcwb_pp_hw[dcwb_pp_count].hw.hwversion = m->hwversion;
|
||||||
|
hw_wb->dcwb_pp_hw[dcwb_pp_count].hw.log_mask = SDE_DBG_MASK_WB;
|
||||||
|
} else {
|
||||||
|
DRM_ERROR("Invalid dcwb pp count %d more than %d",
|
||||||
|
dcwb_pp_count, DCWB_MAX - DCWB_0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++dcwb_pp_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -374,6 +406,102 @@ static void sde_hw_wb_program_cwb_ctrl(struct sde_hw_wb *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sde_hw_wb_program_cwb_dither_ctrl(struct sde_hw_wb *ctx,
|
||||||
|
const enum sde_dcwb dcwb_idx, void *cfg, size_t len, bool enable)
|
||||||
|
{
|
||||||
|
struct sde_hw_pingpong *pp = NULL;
|
||||||
|
struct sde_hw_blk_reg_map *c = NULL;
|
||||||
|
struct drm_msm_dither *dither_data = NULL;
|
||||||
|
enum sde_pingpong pp_id = PINGPONG_MAX;
|
||||||
|
u32 dither_base = 0, offset = 0, data = 0, idx = 0;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
DRM_ERROR("Invalid pointer ctx is null\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* map to pp_id from dcwb id */
|
||||||
|
if (dcwb_idx == DCWB_0) {
|
||||||
|
pp_id = PINGPONG_CWB_0;
|
||||||
|
} else if (dcwb_idx == DCWB_1) {
|
||||||
|
pp_id = PINGPONG_CWB_1;
|
||||||
|
} else {
|
||||||
|
DRM_ERROR("Invalid dcwb_idx %d\n", dcwb_idx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find pp blk with pp_id */
|
||||||
|
for (idx = 0; idx < DCWB_MAX - DCWB_0; ++idx) {
|
||||||
|
pp = &ctx->dcwb_pp_hw[idx];
|
||||||
|
if (pp && pp->idx == pp_id) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
DRM_ERROR("Not found pp id %d\n", pp_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!test_bit(SDE_PINGPONG_CWB_DITHER, &pp->caps->features)) {
|
||||||
|
DRM_ERROR("Invalid ping-pong cwb config dcwb idx %d pp id %d\n",
|
||||||
|
dcwb_idx, pp_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = &pp->hw;
|
||||||
|
dither_base = pp->caps->sblk->dither.base;
|
||||||
|
dither_data = (struct drm_msm_dither *)cfg;
|
||||||
|
if (!dither_data || !enable) {
|
||||||
|
SDE_REG_WRITE(c, dither_base, 0);
|
||||||
|
SDE_DEBUG("cwb dither disabled, dcwb_idx %u pp_id %u\n", dcwb_idx, pp_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len != sizeof(struct drm_msm_dither)) {
|
||||||
|
SDE_ERROR("input len %zu, expected len %zu\n", len,
|
||||||
|
sizeof(struct drm_msm_dither));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dither_data->c0_bitdepth >= DITHER_DEPTH_MAP_INDEX ||
|
||||||
|
dither_data->c1_bitdepth >= DITHER_DEPTH_MAP_INDEX ||
|
||||||
|
dither_data->c2_bitdepth >= DITHER_DEPTH_MAP_INDEX ||
|
||||||
|
dither_data->c3_bitdepth >= DITHER_DEPTH_MAP_INDEX) {
|
||||||
|
SDE_ERROR("Invalid bitdepth [c0, c1, c2, c3] = [%u, %u, %u, %u]\n",
|
||||||
|
dither_data->c0_bitdepth, dither_data->c1_bitdepth,
|
||||||
|
dither_data->c2_bitdepth, dither_data->c3_bitdepth);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += 4;
|
||||||
|
data = dither_depth_map[dither_data->c0_bitdepth] & REG_MASK(2);
|
||||||
|
data |= (dither_depth_map[dither_data->c1_bitdepth] & REG_MASK(2)) << 2;
|
||||||
|
data |= (dither_depth_map[dither_data->c2_bitdepth] & REG_MASK(2)) << 4;
|
||||||
|
data |= (dither_depth_map[dither_data->c3_bitdepth] & REG_MASK(2)) << 6;
|
||||||
|
data |= (dither_data->temporal_en) ? (1 << 8) : 0;
|
||||||
|
SDE_REG_WRITE(c, dither_base + offset, data);
|
||||||
|
|
||||||
|
for (idx = 0; idx < DITHER_MATRIX_SZ - 3; idx += 4) {
|
||||||
|
offset += 4;
|
||||||
|
data = (dither_data->matrix[idx] & REG_MASK(4)) |
|
||||||
|
((dither_data->matrix[idx + 1] & REG_MASK(4)) << 4) |
|
||||||
|
((dither_data->matrix[idx + 2] & REG_MASK(4)) << 8) |
|
||||||
|
((dither_data->matrix[idx + 3] & REG_MASK(4)) << 12);
|
||||||
|
SDE_REG_WRITE(c, dither_base + offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable dither */
|
||||||
|
if (test_bit(SDE_PINGPONG_DITHER_LUMA, &pp->caps->features)
|
||||||
|
&& (dither_data->flags & DITHER_LUMA_MODE))
|
||||||
|
SDE_REG_WRITE(c, dither_base, 0x11);
|
||||||
|
else
|
||||||
|
SDE_REG_WRITE(c, dither_base, 1);
|
||||||
|
SDE_DEBUG("cwb dither enabled, dcwb_idx %u pp_id %u\n", dcwb_idx, pp_id);
|
||||||
|
}
|
||||||
|
|
||||||
static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
|
static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
|
||||||
unsigned long features)
|
unsigned long features)
|
||||||
{
|
{
|
||||||
@@ -402,6 +530,9 @@ static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
|
|||||||
ops->program_dcwb_ctrl = sde_hw_wb_program_dcwb_ctrl;
|
ops->program_dcwb_ctrl = sde_hw_wb_program_dcwb_ctrl;
|
||||||
ops->bind_dcwb_pp_blk = sde_hw_wb_bind_dcwb_pp_blk;
|
ops->bind_dcwb_pp_blk = sde_hw_wb_bind_dcwb_pp_blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (test_bit(SDE_WB_CWB_DITHER_CTRL, &features))
|
||||||
|
ops->program_cwb_dither_ctrl = sde_hw_wb_program_cwb_dither_ctrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sde_hw_blk_ops sde_hw_ops = {
|
static struct sde_hw_blk_ops sde_hw_ops = {
|
||||||
@@ -452,8 +583,10 @@ 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))
|
if (test_bit(SDE_WB_DCWB_CTRL, &cfg->features)) {
|
||||||
_sde_hw_dcwb_ctrl_init(m, addr, &c->dcwb_hw);
|
_sde_hw_dcwb_ctrl_init(m, addr, &c->dcwb_hw);
|
||||||
|
_sde_hw_dcwb_pp_ctrl_init(m, addr, c);
|
||||||
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include "sde_hw_mdss.h"
|
#include "sde_hw_mdss.h"
|
||||||
#include "sde_hw_top.h"
|
#include "sde_hw_top.h"
|
||||||
#include "sde_hw_util.h"
|
#include "sde_hw_util.h"
|
||||||
|
#include "sde_hw_pingpong.h"
|
||||||
|
|
||||||
struct sde_hw_wb;
|
struct sde_hw_wb;
|
||||||
|
|
||||||
@@ -149,6 +150,17 @@ struct sde_hw_wb_ops {
|
|||||||
*/
|
*/
|
||||||
void (*program_dcwb_ctrl)(struct sde_hw_wb *ctx, const enum sde_dcwb cwb,
|
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);
|
const enum sde_cwb data_src, int tap_location, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* program_cwb_dither_ctrl - program cwb dither block config
|
||||||
|
* @ctx: Pointer to wb context
|
||||||
|
* @dcwb_idx: Current Ping-Pong CWB block index to program
|
||||||
|
* @cfg: cwb dither data
|
||||||
|
* @len: the size of cwb dither data
|
||||||
|
* @enable: enable or disable the cwb dither
|
||||||
|
*/
|
||||||
|
void (*program_cwb_dither_ctrl)(struct sde_hw_wb *ctx,
|
||||||
|
const enum sde_dcwb dcwb_idx, void *cfg, size_t len, bool enable);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,6 +175,7 @@ struct sde_hw_wb_ops {
|
|||||||
* @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
|
* @dcwb_hw: DCWB control hwio details
|
||||||
|
* @dcwb_pp_hw: DCWB PingPong control hwio details
|
||||||
*/
|
*/
|
||||||
struct sde_hw_wb {
|
struct sde_hw_wb {
|
||||||
struct sde_hw_blk base;
|
struct sde_hw_blk base;
|
||||||
@@ -180,6 +193,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;
|
struct sde_hw_blk_reg_map dcwb_hw;
|
||||||
|
struct sde_hw_pingpong dcwb_pp_hw[DCWB_MAX - DCWB_0];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -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__
|
||||||
@@ -366,6 +366,8 @@ int sde_wb_connector_set_info_blob(struct drm_connector *connector,
|
|||||||
{
|
{
|
||||||
struct sde_wb_device *wb_dev = display;
|
struct sde_wb_device *wb_dev = display;
|
||||||
const struct sde_format_extended *format_list;
|
const struct sde_format_extended *format_list;
|
||||||
|
struct msm_drm_private *priv = NULL;
|
||||||
|
struct sde_kms *sde_kms = NULL;
|
||||||
|
|
||||||
if (!connector || !info || !display || !wb_dev->wb_cfg) {
|
if (!connector || !info || !display || !wb_dev->wb_cfg) {
|
||||||
SDE_ERROR("invalid params\n");
|
SDE_ERROR("invalid params\n");
|
||||||
@@ -405,9 +407,74 @@ int sde_wb_connector_set_info_blob(struct drm_connector *connector,
|
|||||||
sde_kms_info_append(info, "wb_ubwc");
|
sde_kms_info_append(info, "wb_ubwc");
|
||||||
sde_kms_info_stop(info);
|
sde_kms_info_stop(info);
|
||||||
|
|
||||||
|
if (wb_dev->drm_dev && wb_dev->drm_dev->dev_private) {
|
||||||
|
priv = wb_dev->drm_dev->dev_private;
|
||||||
|
if (!priv->kms) {
|
||||||
|
SDE_ERROR("invalid kms reference\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sde_kms = to_sde_kms(priv->kms);
|
||||||
|
sde_kms_info_add_keyint(info, "has_cwb_dither", sde_kms->catalog->has_cwb_dither);
|
||||||
|
} else {
|
||||||
|
SDE_ERROR("invalid params %pK\n", wb_dev->drm_dev);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sde_wb_connector_install_dither_property(struct sde_wb_device *wb_dev,
|
||||||
|
struct sde_connector *c_conn)
|
||||||
|
{
|
||||||
|
char prop_name[DRM_PROP_NAME_LEN];
|
||||||
|
struct sde_kms *sde_kms = NULL;
|
||||||
|
struct msm_drm_private *priv = NULL;
|
||||||
|
struct sde_mdss_cfg *catalog = NULL;
|
||||||
|
u32 version = 0;
|
||||||
|
|
||||||
|
if (!wb_dev || !c_conn) {
|
||||||
|
SDE_ERROR("invalid args (s), wb_dev %pK, c_conn %pK\n", wb_dev, c_conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wb_dev->drm_dev) {
|
||||||
|
SDE_ERROR("invalid drm_dev is null\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wb_dev->drm_dev->dev_private) {
|
||||||
|
SDE_ERROR("invalid dev_private is null\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv = wb_dev->drm_dev->dev_private;
|
||||||
|
if (!priv->kms) {
|
||||||
|
SDE_ERROR("invalid kms reference is null\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sde_kms = to_sde_kms(priv->kms);
|
||||||
|
catalog = sde_kms->catalog;
|
||||||
|
|
||||||
|
if (!catalog->has_cwb_dither)
|
||||||
|
return;
|
||||||
|
|
||||||
|
version = SDE_COLOR_PROCESS_MAJOR(
|
||||||
|
catalog->pingpong[0].sblk->dither.version);
|
||||||
|
snprintf(prop_name, ARRAY_SIZE(prop_name), "%s%d",
|
||||||
|
"SDE_PP_CWB_DITHER_V", version);
|
||||||
|
switch (version) {
|
||||||
|
case 2:
|
||||||
|
msm_property_install_blob(&c_conn->property_info, prop_name,
|
||||||
|
DRM_MODE_PROP_BLOB, CONNECTOR_PROP_PP_CWB_DITHER);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SDE_ERROR("unsupported cwb dither version %d\n", version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int sde_wb_connector_post_init(struct drm_connector *connector, void *display)
|
int sde_wb_connector_post_init(struct drm_connector *connector, void *display)
|
||||||
{
|
{
|
||||||
struct sde_connector *c_conn;
|
struct sde_connector *c_conn;
|
||||||
@@ -446,6 +513,8 @@ int sde_wb_connector_post_init(struct drm_connector *connector, void *display)
|
|||||||
ARRAY_SIZE(e_fb_translation_mode), 0,
|
ARRAY_SIZE(e_fb_translation_mode), 0,
|
||||||
CONNECTOR_PROP_FB_TRANSLATION_MODE);
|
CONNECTOR_PROP_FB_TRANSLATION_MODE);
|
||||||
|
|
||||||
|
sde_wb_connector_install_dither_property(wb_dev, c_conn);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user