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:
Yuchao Ma
2021-01-11 22:30:47 +08:00
parent e252e85f29
commit 1b0bd83473
9 changed files with 267 additions and 9 deletions

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

@@ -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];
}; };
/** /**

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