1
0

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>
Este cometimento está contido em:
Yuchao Ma
2021-01-11 22:30:47 +08:00
ascendente e252e85f29
cometimento 1b0bd83473
9 ficheiros modificados com 267 adições e 9 eliminações

Ver ficheiro

@@ -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,
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,
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->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 = {
@@ -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))
_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_pp_ctrl_init(m, addr, c);
}
return c;