msm: drm: sde: Add support for UCSC via AHB programming

Add support for UCSC block parameters that includes unmult,
IGC/GC modes, CSC coefficients, and clamps.

Change-Id: I3ef4b729e9c973a98d53dc583233bf5e004035fa
Signed-off-by: Alisha Thapaliya <quic_athapali@quicinc.com>
Este commit está contenido en:
Alisha Thapaliya
2022-07-22 13:54:41 -07:00
cometido por Gerrit - the friendly Code Review server
padre 83cb3d44af
commit c2364bdd17
Se han modificado 10 ficheros con 703 adiciones y 2 borrados

Ver fichero

@@ -775,4 +775,11 @@ struct drm_msm_misr_sign {
__u64 misr_sign_value[MAX_DSI_DISPLAY];
};
#define UCSC_SUPPORTED
#define UCSC_CSC_CFG0_PARAM_LEN FP16_CSC_CFG0_PARAM_LEN
#define UCSC_CSC_CFG1_PARAM_LEN FP16_CSC_CFG1_PARAM_LEN
typedef struct drm_msm_fp16_csc drm_msm_ucsc_csc;
#endif /* _MSM_DRM_PP_H_ */

Ver fichero

@@ -124,6 +124,7 @@ enum msm_mdp_plane_property {
PLANE_PROP_FP16_GC,
PLANE_PROP_FP16_CSC,
PLANE_PROP_UBWC_STATS_ROI,
PLANE_PROP_UCSC_CSC,
/* # of blob properties */
PLANE_PROP_BLOBCOUNT,
@@ -147,12 +148,17 @@ enum msm_mdp_plane_property {
PLANE_PROP_INVERSE_PMA,
PLANE_PROP_FP16_IGC,
PLANE_PROP_FP16_UNMULT,
PLANE_PROP_UCSC_UNMULT,
PLANE_PROP_UCSC_ALPHA_DITHER,
/* enum/bitmask properties */
PLANE_PROP_BLEND_OP,
PLANE_PROP_SRC_CONFIG,
PLANE_PROP_FB_TRANSLATION_MODE,
PLANE_PROP_MULTIRECT_MODE,
PLANE_PROP_UCSC_IGC,
PLANE_PROP_UCSC_GC,
/* total # of properties */
PLANE_PROP_COUNT

Ver fichero

@@ -298,6 +298,11 @@ enum {
VIG_FP16_GC_PROP,
VIG_FP16_CSC_PROP,
VIG_FP16_UNMULT_PROP,
VIG_UCSC_IGC_PROP,
VIG_UCSC_GC_PROP,
VIG_UCSC_CSC_PROP,
VIG_UCSC_UNMULT_PROP,
VIG_UCSC_ALPHA_DITHER_PROP,
VIG_PROP_MAX,
};
@@ -312,6 +317,11 @@ enum {
DMA_FP16_GC_PROP,
DMA_FP16_CSC_PROP,
DMA_FP16_UNMULT_PROP,
DMA_UCSC_IGC_PROP,
DMA_UCSC_GC_PROP,
DMA_UCSC_CSC_PROP,
DMA_UCSC_UNMULT_PROP,
DMA_UCSC_ALPHA_DITHER_PROP,
DMA_PROP_MAX,
};
@@ -731,6 +741,16 @@ static struct sde_prop_type vig_prop[] = {
PROP_TYPE_U32_ARRAY},
[VIG_FP16_UNMULT_PROP] = {VIG_FP16_UNMULT_PROP, "qcom,sde-fp16-unmult",
false, PROP_TYPE_U32_ARRAY},
[VIG_UCSC_IGC_PROP] = {VIG_UCSC_IGC_PROP, "qcom,sde-ucsc-igc", false,
PROP_TYPE_U32_ARRAY},
[VIG_UCSC_GC_PROP] = {VIG_UCSC_GC_PROP, "qcom,sde-ucsc-gc", false,
PROP_TYPE_U32_ARRAY},
[VIG_UCSC_CSC_PROP] = {VIG_UCSC_CSC_PROP, "qcom,sde-ucsc-csc", false,
PROP_TYPE_U32_ARRAY},
[VIG_UCSC_UNMULT_PROP] = {VIG_UCSC_UNMULT_PROP, "qcom,sde-ucsc-unmult",
false, PROP_TYPE_U32_ARRAY},
[VIG_UCSC_ALPHA_DITHER_PROP] = {VIG_UCSC_ALPHA_DITHER_PROP, "qcom,sde-ucsc-alpha-dither",
false, PROP_TYPE_U32_ARRAY},
};
static struct sde_prop_type dma_prop[] = {
@@ -754,6 +774,16 @@ static struct sde_prop_type dma_prop[] = {
PROP_TYPE_U32_ARRAY},
[DMA_FP16_UNMULT_PROP] = {DMA_FP16_UNMULT_PROP, "qcom,sde-fp16-unmult",
false, PROP_TYPE_U32_ARRAY},
[DMA_UCSC_IGC_PROP] = {DMA_UCSC_IGC_PROP, "qcom,sde-ucsc-igc", false,
PROP_TYPE_U32_ARRAY},
[DMA_UCSC_GC_PROP] = {DMA_UCSC_GC_PROP, "qcom,sde-ucsc-gc", false,
PROP_TYPE_U32_ARRAY},
[DMA_UCSC_CSC_PROP] = {DMA_UCSC_CSC_PROP, "qcom,sde-ucsc-csc", false,
PROP_TYPE_U32_ARRAY},
[DMA_UCSC_UNMULT_PROP] = {DMA_UCSC_UNMULT_PROP, "qcom,sde-ucsc-unmult",
false, PROP_TYPE_U32_ARRAY},
[DMA_UCSC_ALPHA_DITHER_PROP] = {DMA_UCSC_ALPHA_DITHER_PROP, "qcom,sde-ucsc-alpha-dither",
false, PROP_TYPE_U32_ARRAY},
};
static struct sde_prop_type ctl_prop[] = {
@@ -1558,6 +1588,12 @@ static int _sde_sspp_setup_vigs(struct device_node *np,
sblk->num_fp16_csc_blk = 0;
sblk->num_fp16_unmult_blk = 0;
sblk->num_ucsc_igc_blk = 0;
sblk->num_ucsc_gc_blk = 0;
sblk->num_ucsc_csc_blk = 0;
sblk->num_ucsc_unmult_blk = 0;
sblk->num_ucsc_alpha_dither_blk = 0;
for (j = 0; j < SSPP_SUBBLK_COUNT_MAX; j++) {
if (!props[j])
continue;
@@ -1589,6 +1625,41 @@ static int _sde_sspp_setup_vigs(struct device_node *np,
SDE_SSPP_FP16_UNMULT,
VIG_FP16_UNMULT_PROP, true))
sblk->num_fp16_unmult_blk += 1;
if (_sde_sspp_setup_vcm(sspp, props[j],
"sspp_vig_ucsc_igc",
&sblk->ucsc_igc_blk[j],
SDE_SSPP_UCSC_IGC, VIG_UCSC_IGC_PROP,
true))
sblk->num_ucsc_igc_blk += 1;
if (_sde_sspp_setup_vcm(sspp, props[j],
"sspp_vig_ucsc_gc",
&sblk->ucsc_gc_blk[j],
SDE_SSPP_UCSC_GC, VIG_UCSC_GC_PROP,
true))
sblk->num_ucsc_gc_blk += 1;
if (_sde_sspp_setup_vcm(sspp, props[j],
"sspp_vig_ucsc_csc",
&sblk->ucsc_csc_blk[j],
SDE_SSPP_UCSC_CSC, VIG_UCSC_CSC_PROP,
true))
sblk->num_ucsc_csc_blk += 1;
if (_sde_sspp_setup_vcm(sspp, props[j],
"sspp_vig_ucsc_unmult",
&sblk->ucsc_unmult_blk[j],
SDE_SSPP_UCSC_UNMULT,
VIG_UCSC_UNMULT_PROP, true))
sblk->num_ucsc_unmult_blk += 1;
if (_sde_sspp_setup_vcm(sspp, props[j],
"sspp_vig_ucsc_alpha_dither",
&sblk->ucsc_alpha_dither_blk[j],
SDE_SSPP_UCSC_ALPHA_DITHER,
VIG_UCSC_ALPHA_DITHER_PROP, true))
sblk->num_ucsc_alpha_dither_blk += 1;
}
/* PP + scaling only supported on VIG rect 0 */
@@ -1804,6 +1875,41 @@ static int _sde_sspp_setup_dmas(struct device_node *np,
&sblk->fp16_unmult_blk[j],
SDE_SSPP_FP16_UNMULT,
DMA_FP16_UNMULT_PROP, true);
if (props[j]->exists[DMA_UCSC_IGC_PROP])
_sde_sspp_setup_dgm(sspp, props[j],
"sspp_dma_ucsc_igc",
&sblk->ucsc_igc_blk[j],
SDE_SSPP_UCSC_IGC,
DMA_UCSC_IGC_PROP, true);
if (props[j]->exists[DMA_UCSC_GC_PROP])
_sde_sspp_setup_dgm(sspp, props[j],
"sspp_dma_ucsc_gc",
&sblk->ucsc_gc_blk[j],
SDE_SSPP_UCSC_GC,
DMA_UCSC_GC_PROP, true);
if (props[j]->exists[DMA_UCSC_CSC_PROP])
_sde_sspp_setup_dgm(sspp, props[j],
"sspp_dma_ucsc_csc",
&sblk->ucsc_csc_blk[j],
SDE_SSPP_UCSC_CSC,
DMA_UCSC_CSC_PROP, true);
if (props[j]->exists[DMA_UCSC_UNMULT_PROP])
_sde_sspp_setup_dgm(sspp, props[j],
"sspp_dma_ucsc_unmult",
&sblk->ucsc_unmult_blk[j],
SDE_SSPP_UCSC_UNMULT,
DMA_UCSC_UNMULT_PROP, true);
if (props[j]->exists[DMA_UCSC_ALPHA_DITHER_PROP])
_sde_sspp_setup_dgm(sspp, props[j],
"sspp_dma_ucsc_alpha_dither",
&sblk->ucsc_alpha_dither_blk[j],
SDE_SSPP_UCSC_ALPHA_DITHER,
DMA_UCSC_ALPHA_DITHER_PROP, true);
}
}

Ver fichero

@@ -317,6 +317,11 @@ enum {
* @SDE_SSPP_UBWC_STATS: Support for ubwc stats
* @SDE_SSPP_SCALER_DE_LPF_BLEND: Support for detail enhancer
* @SDE_SSPP_LINE_INSERTION Line insertion support
* @SDE_SSPP_UCSC_IGC UCSC IGC color processing block support
* @SDE_SSPP_UCSC_GC UCSC GC color processing block support
* @SDE_SSPP_UCSC_CSC UCSC CSC color processing block support
* @SDE_SSPP_UCSC_UNMULT UCSC alpha unmult color processing block support
* @SDE_SSPP_UCSC_ALPHA_DITHER UCSC alpha dither color processing block support
* @SDE_SSPP_MAX maximum value
*/
enum {
@@ -354,6 +359,11 @@ enum {
SDE_SSPP_UBWC_STATS,
SDE_SSPP_SCALER_DE_LPF_BLEND,
SDE_SSPP_LINE_INSERTION,
SDE_SSPP_UCSC_IGC,
SDE_SSPP_UCSC_GC,
SDE_SSPP_UCSC_CSC,
SDE_SSPP_UCSC_UNMULT,
SDE_SSPP_UCSC_ALPHA_DITHER,
SDE_SSPP_MAX
};
@@ -742,6 +752,7 @@ enum {
* @SDE_FEATURE_SYS_CACHE_NSE Support for no-self-evict feature
* @SDE_FEATURE_HW_FENCE_IPCC HW fence supports ipcc signaling in dpu
* @SDE_FEATURE_EMULATED_ENV Emulated environment supported
* @SDE_FEATURE_UCSC_SUPPORTED UCSC pipe format supported
* @SDE_FEATURE_MAX: MAX features value
*/
enum sde_mdss_features {
@@ -786,6 +797,7 @@ enum sde_mdss_features {
SDE_FEATURE_SYS_CACHE_NSE,
SDE_FEATURE_HW_FENCE_IPCC,
SDE_FEATURE_EMULATED_ENV,
SDE_FEATURE_UCSC_SUPPORTED,
SDE_FEATURE_MAX
};
@@ -969,6 +981,16 @@ enum sde_danger_safe_lut_types {
* @fp16_csc_blk: FP16 CSC block array
* @num_fp16_unmult_blk: number of FP16 UNMULT blocks
* @fp16_unmult_blk: FP16 UNMULT block array
* @num_ucsc_igc_blk: number of UCSC IGC blocks
* @ucsc_igc_blk: UCSC IGC block array
* @num_ucsc_gc_blk: number of UCSC GC blocks
* @ucsc_gc_blk: UCSC GC block array
* @num_ucsc_csc_blk: number of UCSC CSC blocks
* @ucsc_csc_blk: UCSC CSC block array
* @num_ucsc_unmult_blk: number of ucsc UNMULT blocks
* @ucsc_unmult_blk: UCSC UNMULT block array
* @num_ucsc_alpha_dither_blk: number of ucsc ALPHA DITHER blocks
* @ucsc_alpha_dither_blk: UCSC ALPHA DITHER block array
* @unmult_offset: Unmult register offset
* @format_list: Pointer to list of supported formats
* @virt_format_list: Pointer to list of supported formats for virtual planes
@@ -1021,6 +1043,16 @@ struct sde_sspp_sub_blks {
struct sde_pp_blk fp16_csc_blk[SSPP_SUBBLK_COUNT_MAX];
u32 num_fp16_unmult_blk;
struct sde_pp_blk fp16_unmult_blk[SSPP_SUBBLK_COUNT_MAX];
u32 num_ucsc_igc_blk;
struct sde_pp_blk ucsc_igc_blk[SSPP_SUBBLK_COUNT_MAX];
u32 num_ucsc_gc_blk;
struct sde_pp_blk ucsc_gc_blk[SSPP_SUBBLK_COUNT_MAX];
u32 num_ucsc_csc_blk;
struct sde_pp_blk ucsc_csc_blk[SSPP_SUBBLK_COUNT_MAX];
u32 num_ucsc_unmult_blk;
struct sde_pp_blk ucsc_unmult_blk[SSPP_SUBBLK_COUNT_MAX];
u32 num_ucsc_alpha_dither_blk;
struct sde_pp_blk ucsc_alpha_dither_blk[SSPP_SUBBLK_COUNT_MAX];
u32 unmult_offset[SSPP_SUBBLK_COUNT_MAX];
const struct sde_format_extended *format_list;

Ver fichero

@@ -759,3 +759,286 @@ int sde_spr_read_opr_value(struct sde_hw_dspp *ctx, uint32_t *opr_value)
return 0;
}
void sde_setup_ucsc_cscv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data)
{
struct sde_hw_cp_cfg *hw_cfg = data;
drm_msm_ucsc_csc *ucsc_csc;
u32 csc_base, csc, i, offset = 0;
if (!ctx || !data || index == SDE_SSPP_RECT_MAX) {
DRM_ERROR("invalid parameter\tctx: %pK\tdata: %pK\tindex: %d\n",
ctx, data, index);
return;
}
if (index == SDE_SSPP_RECT_SOLO || index == SDE_SSPP_RECT_0)
csc_base = ctx->cap->sblk->ucsc_csc_blk[0].base;
else
csc_base = ctx->cap->sblk->ucsc_csc_blk[1].base;
if (!csc_base) {
DRM_ERROR("invalid offset for UCSC CSC CP block\tpipe: %d\tindex: %d\n",
ctx->idx, index);
return;
}
ucsc_csc = (drm_msm_ucsc_csc *)(hw_cfg->payload);
if (!ucsc_csc)
goto write_base;
if (hw_cfg->len != sizeof(drm_msm_ucsc_csc) ||
!hw_cfg->payload) {
DRM_ERROR("invalid hw_cfg payload\tpipe: %d\tindex: %d\tlen: %d\tpayload: %pK\n",
ctx->idx, index, hw_cfg->len, hw_cfg->payload);
return;
}
if (ucsc_csc->cfg_param_0_len != UCSC_CSC_CFG0_PARAM_LEN) {
DRM_ERROR("invalid param 0 length! Got: %d\tExpected: %d\tpipe: %d\tindex: %d\n",
ucsc_csc->cfg_param_0_len, UCSC_CSC_CFG0_PARAM_LEN,
ctx->idx, index);
return;
} else if (ucsc_csc->cfg_param_1_len != UCSC_CSC_CFG1_PARAM_LEN) {
DRM_ERROR("invalid param 1 length! Got: %d\tExpected: %d\tpipe: %d\tindex: %d\n",
ucsc_csc->cfg_param_1_len, UCSC_CSC_CFG1_PARAM_LEN,
ctx->idx, index);
return;
}
for (i = 0; i < (ucsc_csc->cfg_param_0_len / 2); i++) {
offset += 0x4;
csc = ucsc_csc->cfg_param_0[2 * i] & 0xFFFF;
csc |= (ucsc_csc->cfg_param_0[2 * i + 1] & 0xFFFF) << 16;
SDE_REG_WRITE(&ctx->hw, csc_base + offset, csc);
}
for (i = 0; i < (ucsc_csc->cfg_param_1_len / 2); i++) {
offset += 0x4;
csc = ucsc_csc->cfg_param_1[2 * i] & 0xFFFF;
csc |= (ucsc_csc->cfg_param_1[2 * i + 1] & 0xFFFF) << 16;
SDE_REG_WRITE(&ctx->hw, csc_base + offset, csc);
}
write_base:
csc = SDE_REG_READ(&ctx->hw, csc_base);
if (ucsc_csc)
csc |= BIT(2);
else
csc &= ~BIT(2);
SDE_REG_WRITE(&ctx->hw, csc_base, csc);
}
void sde_setup_ucsc_gcv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data)
{
struct sde_hw_cp_cfg *hw_cfg = data;
int *ucsc_gc;
u32 gc_base, gc;
if (!ctx || !data || index == SDE_SSPP_RECT_MAX) {
DRM_ERROR("invalid parameter\tctx: %pK\tdata: %pK\tindex: %d\n",
ctx, data, index);
return;
}
if (index == SDE_SSPP_RECT_SOLO || index == SDE_SSPP_RECT_0)
gc_base = ctx->cap->sblk->ucsc_gc_blk[0].base;
else
gc_base = ctx->cap->sblk->ucsc_gc_blk[1].base;
if (!gc_base) {
DRM_ERROR("invalid offset for UCSC GC CP block\tpipe: %d\tindex: %d\n",
ctx->idx, index);
return;
}
ucsc_gc = (int *)(hw_cfg->payload);
if (!ucsc_gc || (hw_cfg->len != sizeof(int))) {
DRM_ERROR("invalid hw_cfg payload\tpipe: %d\tindex: %d\tlen: %d\tpayload: %pK\n",
ctx->idx, index, hw_cfg->len, ucsc_gc);
return;
}
gc = SDE_REG_READ(&ctx->hw, gc_base);
gc &= 0x60707;
if (*ucsc_gc == UCSC_GC_MODE_DISABLE) {
DRM_INFO("UCSC GC is not enabled!\n");
goto reset_gc;
}
if (ucsc_gc && *ucsc_gc) {
gc |= BIT(4);
switch (*ucsc_gc)
{
case UCSC_GC_MODE_SRGB:
break;
case UCSC_GC_MODE_PQ:
gc |= BIT(5);
break;
case UCSC_GC_MODE_GAMMA2_2:
gc |= BIT(6);
break;
case UCSC_GC_MODE_HLG:
gc |= BIT(5)|BIT(6);
break;
default:
DRM_ERROR("Invalid UCSC GC mode \tmode: %d\n", *ucsc_gc);
return;
}
}
reset_gc:
SDE_REG_WRITE(&ctx->hw, gc_base, gc);
}
void sde_setup_ucsc_igcv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data)
{
struct sde_hw_cp_cfg *hw_cfg = data;
int *ucsc_igc;
u32 igc_base, igc;
if (!ctx || !data || index == SDE_SSPP_RECT_MAX) {
DRM_ERROR("invalid parameter\tctx: %pK\tdata: %pK\tindex: %d\n",
ctx, data, index);
return;
}
if (index == SDE_SSPP_RECT_SOLO || index == SDE_SSPP_RECT_0)
igc_base = ctx->cap->sblk->ucsc_igc_blk[0].base;
else
igc_base = ctx->cap->sblk->ucsc_igc_blk[1].base;
if (!igc_base) {
DRM_ERROR("invalid offset for UCSC GC CP block\tpipe: %d\tindex: %d\n",
ctx->idx, index);
return;
}
ucsc_igc = (int *)(hw_cfg->payload);
if (!ucsc_igc || (hw_cfg->len != sizeof(int))) {
DRM_ERROR("invalid hw_cfg payload\tpipe: %d\tindex: %d\tlen: %d\tpayload: %pK\n",
ctx->idx, index, hw_cfg->len, ucsc_igc);
return;
}
igc = SDE_REG_READ(&ctx->hw, igc_base);
igc &= 0x600FD;
if (*ucsc_igc == UCSC_IGC_MODE_DISABLE) {
DRM_INFO("UCSC IGC is not enabled!\n");
goto reset_igc;
}
if (ucsc_igc && *ucsc_igc) {
igc |= BIT(1);
switch (*ucsc_igc)
{
case UCSC_IGC_MODE_SRGB:
break;
case UCSC_IGC_MODE_REC709:
igc |= BIT(8);
break;
case UCSC_IGC_MODE_GAMMA2_2:
igc |= BIT(9);
break;
case UCSC_IGC_MODE_HLG:
igc |= BIT(8)|BIT(9);
break;
case UCSC_IGC_MODE_PQ:
igc |= BIT(10);
break;
default:
DRM_ERROR("Invalid UCSC IGC mode \tmode: %d\n", *ucsc_igc);
return;
}
}
reset_igc:
SDE_REG_WRITE(&ctx->hw, igc_base, igc);
}
void sde_setup_ucsc_unmultv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data)
{
struct sde_hw_cp_cfg *hw_cfg = data;
bool *ucsc_unmult;
u32 unmult_base, unmult;
if (!ctx || !data || index == SDE_SSPP_RECT_MAX) {
DRM_ERROR("invalid parameter\tctx: %pK\tdata: %pK\tindex: %d\n",
ctx, data, index);
return;
} else if (hw_cfg->len != sizeof(bool) || !hw_cfg->payload) {
DRM_ERROR("invalid hw_cfg payload\tpipe: %d\tindex: %d\tlen: %d\tpayload: %pK\n",
ctx->idx, index, hw_cfg->len, hw_cfg->payload);
return;
}
if (index == SDE_SSPP_RECT_SOLO || index == SDE_SSPP_RECT_0)
unmult_base = ctx->cap->sblk->ucsc_unmult_blk[0].base;
else
unmult_base = ctx->cap->sblk->ucsc_unmult_blk[1].base;
if (!unmult_base) {
DRM_ERROR("invalid offset for UCSC UNMULT CP block\tpipe: %d\tindex: %d\n",
ctx->idx, index);
return;
}
unmult = SDE_REG_READ(&ctx->hw, unmult_base);
ucsc_unmult = (bool *)(hw_cfg->payload);
if (ucsc_unmult && *ucsc_unmult)
unmult |= BIT(0)|BIT(18);
else
unmult &= ~(BIT(0)|BIT(18));
SDE_REG_WRITE(&ctx->hw, unmult_base, unmult);
}
void sde_setup_ucsc_alpha_ditherv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data)
{
struct sde_hw_cp_cfg *hw_cfg = data;
bool *ucsc_alpha_dither;
u32 alpha_dither_base, alpha_dither;
if (!ctx || index == SDE_SSPP_RECT_MAX) {
DRM_ERROR("invalid parameter\tctx: %pK\tindex: %d\n",
ctx, index);
return;
} else if (hw_cfg->len != sizeof(bool) || !hw_cfg->payload) {
DRM_ERROR("invalid hw_cfg payload\tpipe: %d\tindex: %d\tlen: %d\tpayload: %pK\n",
ctx->idx, index, hw_cfg->len, hw_cfg->payload);
return;
}
if (index == SDE_SSPP_RECT_SOLO || index == SDE_SSPP_RECT_0)
alpha_dither_base = ctx->cap->sblk->ucsc_alpha_dither_blk[0].base;
else
alpha_dither_base = ctx->cap->sblk->ucsc_alpha_dither_blk[1].base;
if (!alpha_dither_base) {
DRM_ERROR("invalid offset for UCSC ALPHA DITHER CP block\tpipe: %d\tindex: %d\n",
ctx->idx, index);
return;
}
alpha_dither = SDE_REG_READ(&ctx->hw, alpha_dither_base);
ucsc_alpha_dither = (bool *)(hw_cfg->payload);
if (ucsc_alpha_dither && *ucsc_alpha_dither)
alpha_dither |= BIT(17);
else
alpha_dither &= ~BIT(17);
SDE_REG_WRITE(&ctx->hw, alpha_dither_base, alpha_dither);
}

Ver fichero

@@ -161,4 +161,49 @@ void sde_demura_pu_cfg(struct sde_hw_dspp *ctx, void *cfg);
*/
int sde_spr_read_opr_value(struct sde_hw_dspp *ctx, uint32_t *opr_value);
/**
* sde_setup_ucsc_cscv1 - api to set UCSC CSC cp block
* @ctx: pointer to pipe object
* @index: pipe rectangle to operate on
* @data: pointer to sde_hw_cp_cfg object containing drm_msm_ucsc_csc data
*/
void sde_setup_ucsc_cscv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
/**
* sde_setup_ucsc_gcv1 - api to set UCSC GC cp block
* @ctx: pointer to pipe object
* @index: pipe rectangle to operate on
* @data: pointer to sde_hw_cp_cfg object containing gc mode data
*/
void sde_setup_ucsc_gcv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
/**
* sde_setup_ucsc_igcv1 - api to set UCSC IGC cp block
* @ctx: pointer to pipe object
* @index: pipe rectangle to operate on
* @data: pointer to sde_hw_cp_cfg object containing igc mode data
*/
void sde_setup_ucsc_igcv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
/**
* sde_setup_ucsc_unmultv1 - api to set UCSC UNMULT cp block
* @ctx: pointer to pipe object
* @index: pipe rectangle to operate on
* @data: pointer to sde_hw_cp_cfg object containing bool data
*/
void sde_setup_ucsc_unmultv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
/**
* sde_setup_ucsc_alpha_ditherv1 - api to set UCSC ALPHA DITHER cp block
* @ctx: pointer to pipe object
* @index: pipe rectangle to operate on
* @data: pointer to sde_hw_cp_cfg object containing bool data
*/
void sde_setup_ucsc_alpha_ditherv1(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
#endif /* _SDE_HW_COLOR_PROC_V4_H_ */

Ver fichero

@@ -59,6 +59,7 @@
#define SSPP_DGM_CSC_1 0x1800
#define SSPP_DGM_CSC_SIZE 0xFC
#define VIG_GAMUT_SIZE 0x1CC
#define SSPP_UCSC_SIZE 0x80
#define MDSS_MDP_OP_DEINTERLACE BIT(22)
#define MDSS_MDP_OP_DEINTERLACE_ODD BIT(23)
@@ -1340,6 +1341,26 @@ static void _setup_layer_ops_colorproc(struct sde_hw_pipe *c,
if (test_bit(SDE_SSPP_FP16_UNMULT, &features) &&
IS_SDE_CP_VER_1_0(c->cap->sblk->fp16_unmult_blk[0].version))
c->ops.setup_fp16_unmult = sde_setup_fp16_unmultv1;
if (test_bit(SDE_SSPP_UCSC_IGC, &features) &&
IS_SDE_CP_VER_1_0(c->cap->sblk->ucsc_igc_blk[0].version))
c->ops.setup_ucsc_igc = sde_setup_ucsc_igcv1;
if (test_bit(SDE_SSPP_UCSC_GC, &features) &&
IS_SDE_CP_VER_1_0(c->cap->sblk->ucsc_gc_blk[0].version))
c->ops.setup_ucsc_gc = sde_setup_ucsc_gcv1;
if (test_bit(SDE_SSPP_UCSC_CSC, &features) &&
IS_SDE_CP_VER_1_0(c->cap->sblk->ucsc_csc_blk[0].version))
c->ops.setup_ucsc_csc = sde_setup_ucsc_cscv1;
if (test_bit(SDE_SSPP_UCSC_UNMULT, &features) &&
IS_SDE_CP_VER_1_0(c->cap->sblk->ucsc_unmult_blk[0].version))
c->ops.setup_ucsc_unmult = sde_setup_ucsc_unmultv1;
if (test_bit(SDE_SSPP_UCSC_ALPHA_DITHER, &features) &&
IS_SDE_CP_VER_1_0(c->cap->sblk->ucsc_alpha_dither_blk[0].version))
c->ops.setup_ucsc_alpha_dither = sde_setup_ucsc_alpha_ditherv1;
}
static void sde_hw_sspp_setup_inverse_pma(struct sde_hw_pipe *ctx,
@@ -1672,6 +1693,17 @@ struct sde_hw_pipe *sde_hw_sspp_init(enum sde_sspp idx,
hw_pipe->hw.blk_off + cfg->sblk->gamut_blk.base + VIG_GAMUT_SIZE,
hw_pipe->hw.xin_id);
}
if (test_bit(SDE_SSPP_UCSC_CSC, &hw_pipe->cap->features)) {
sde_dbg_reg_register_dump_range(SDE_DBG_NAME, "UCSC_0",
hw_pipe->hw.blk_off + cfg->sblk->ucsc_csc_blk[0].base,
hw_pipe->hw.blk_off + cfg->sblk->ucsc_csc_blk[0].base +\
SSPP_UCSC_SIZE, hw_pipe->hw.xin_id);
sde_dbg_reg_register_dump_range(SDE_DBG_NAME, "UCSC_0",
hw_pipe->hw.blk_off + cfg->sblk->ucsc_csc_blk[1].base,
hw_pipe->hw.blk_off + cfg->sblk->ucsc_csc_blk[1].base +\
SSPP_UCSC_SIZE, hw_pipe->hw.xin_id);
}
}
if (cfg->sblk->scaler_blk.len && !is_virtual_pipe)

Ver fichero

@@ -97,6 +97,23 @@ enum sde_hw_filter_yuv {
SDE_SCALE_BIL
};
enum sde_sspp_ucsc_gc {
UCSC_GC_MODE_DISABLE = 0,
UCSC_GC_MODE_SRGB,
UCSC_GC_MODE_PQ,
UCSC_GC_MODE_GAMMA2_2,
UCSC_GC_MODE_HLG,
};
enum sde_sspp_ucsc_igc {
UCSC_IGC_MODE_DISABLE = 0,
UCSC_IGC_MODE_SRGB,
UCSC_IGC_MODE_REC709,
UCSC_IGC_MODE_GAMMA2_2,
UCSC_IGC_MODE_HLG,
UCSC_IGC_MODE_PQ,
};
struct sde_hw_sharp_cfg {
u32 strength;
u32 edge_thr;
@@ -713,6 +730,51 @@ struct sde_hw_sspp_ops {
void (*setup_line_insertion)(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index,
struct sde_hw_pipe_line_insertion_cfg *cfg);
/**
* setup_ucsc_csc - set UCSC CSC cp block
* @ctx: Pointer to pipe object
* @index: Pipe rectangle to operate on
* @data: Pointer to sde_hw_cp_cfg object holding drm_msm_ucsc_csc data
*/
void (*setup_ucsc_csc)(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
/**
* sde_setup_ucsc_gcv1 - set UCSC GC cp block
* @ctx: Pointer to pipe object
* @index: Pipe rectangle to operate on
* @mode: Pointer to sde_hw_cp_cfg object holding GC mode data
*/
void (*setup_ucsc_gc)(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
/**
* sde_setup_ucsc_igcv1 - set UCSC IGC cp block
* @ctx: Pointer to pipe object
* @index: Pipe rectangle to operate on
* @mode: Pointer to sde_hw_cp_cfg object containing IGC mode data
*/
void (*setup_ucsc_igc)(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
/**
* sde_setup_ucsc_unmultv1 - set UCSC UNMULT cp block
* @ctx: Pointer to pipe object
* @index: Pipe rectangle to operate on
* @data: Pointer to sde_hw_cp_cfg object containing bool data
*/
void (*setup_ucsc_unmult)(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
/**
* sde_setup_ucsc_alpha_ditherv1 - set UCSC ALPHA DITHER cp block
* @ctx: Pointer to pipe object
* @index: Pipe rectangle to operate on
* @data: Pointer to sde_hw_cp_cfg object containing bool data
*/
void (*setup_ucsc_alpha_dither)(struct sde_hw_pipe *ctx,
enum sde_sspp_multirect_index index, void *data);
};
/**

Ver fichero

@@ -1163,9 +1163,11 @@ static void sde_color_process_plane_setup(struct drm_plane *plane)
size_t memcol_sz = 0, size = 0;
struct sde_hw_cp_cfg hw_cfg = {};
struct sde_hw_ctl *ctl = _sde_plane_get_hw_ctl(plane);
bool fp16_igc, fp16_unmult;
bool fp16_igc, fp16_unmult, ucsc_unmult, ucsc_alpha_dither;
int ucsc_gc, ucsc_igc;
struct drm_msm_fp16_gc *fp16_gc = NULL;
struct drm_msm_fp16_csc *fp16_csc = NULL;
struct drm_msm_ucsc_csc *ucsc_csc = NULL;
psde = to_sde_plane(plane);
pstate = to_sde_plane_state(plane->state);
@@ -1317,6 +1319,68 @@ static void sde_color_process_plane_setup(struct drm_plane *plane)
psde->pipe_hw->ops.setup_fp16_unmult(psde->pipe_hw,
pstate->multirect_index, &hw_cfg);
}
if (pstate->dirty & SDE_PLANE_DIRTY_UCSC_IGC &&
psde->pipe_hw->ops.setup_ucsc_igc) {
ucsc_igc = sde_plane_get_property(pstate,
PLANE_PROP_UCSC_IGC);
hw_cfg.last_feature = 0;
hw_cfg.ctl = ctl;
hw_cfg.len = sizeof(int);
hw_cfg.payload = &ucsc_igc;
psde->pipe_hw->ops.setup_ucsc_igc(psde->pipe_hw,
pstate->multirect_index, &hw_cfg);
}
if (pstate->dirty & SDE_PLANE_DIRTY_UCSC_GC &&
psde->pipe_hw->ops.setup_ucsc_gc) {
ucsc_gc = sde_plane_get_property(pstate,
PLANE_PROP_UCSC_GC);
hw_cfg.last_feature = 0;
hw_cfg.ctl = ctl;
hw_cfg.len = sizeof(int);
hw_cfg.payload = &ucsc_gc;
psde->pipe_hw->ops.setup_ucsc_gc(psde->pipe_hw,
pstate->multirect_index, &hw_cfg);
}
if (pstate->dirty & SDE_PLANE_DIRTY_UCSC_CSC &&
psde->pipe_hw->ops.setup_ucsc_csc) {
ucsc_csc = msm_property_get_blob(&psde->property_info,
&pstate->property_state,
&size,
PLANE_PROP_UCSC_CSC);
hw_cfg.last_feature = 0;
hw_cfg.ctl = ctl;
hw_cfg.len = size;
hw_cfg.payload = ucsc_csc;
psde->pipe_hw->ops.setup_ucsc_csc(psde->pipe_hw,
pstate->multirect_index, &hw_cfg);
}
if (pstate->dirty & SDE_PLANE_DIRTY_UCSC_UNMULT &&
psde->pipe_hw->ops.setup_ucsc_unmult) {
ucsc_unmult = !!sde_plane_get_property(pstate,
PLANE_PROP_UCSC_UNMULT);
hw_cfg.last_feature = 0;
hw_cfg.ctl = ctl;
hw_cfg.len = sizeof(bool);
hw_cfg.payload = &ucsc_unmult;
psde->pipe_hw->ops.setup_ucsc_unmult(psde->pipe_hw,
pstate->multirect_index, &hw_cfg);
}
if (pstate->dirty & SDE_PLANE_DIRTY_UCSC_ALPHA_DITHER &&
psde->pipe_hw->ops.setup_ucsc_alpha_dither) {
ucsc_alpha_dither = !!sde_plane_get_property(pstate,
PLANE_PROP_UCSC_ALPHA_DITHER);
hw_cfg.last_feature = 0;
hw_cfg.ctl = ctl;
hw_cfg.len = sizeof(bool);
hw_cfg.payload = &ucsc_alpha_dither;
psde->pipe_hw->ops.setup_ucsc_alpha_dither(psde->pipe_hw,
pstate->multirect_index, &hw_cfg);
}
}
static void _sde_plane_setup_scaler(struct sde_plane *psde,
@@ -3669,6 +3733,23 @@ static void _sde_plane_install_colorproc_properties(struct sde_plane *psde,
char feature_name[256];
bool is_master = !psde->is_virtual;
static const struct drm_prop_enum_list ucsc_gc[] = {
{UCSC_GC_MODE_DISABLE, "disable"},
{UCSC_GC_MODE_SRGB, "srgb"},
{UCSC_GC_MODE_PQ, "pq"},
{UCSC_GC_MODE_GAMMA2_2, "gamma2_2"},
{UCSC_GC_MODE_HLG, "hlg"},
};
static const struct drm_prop_enum_list ucsc_igc[] = {
{UCSC_IGC_MODE_DISABLE, "disable"},
{UCSC_IGC_MODE_SRGB, "srgb"},
{UCSC_IGC_MODE_REC709, "rec709"},
{UCSC_IGC_MODE_GAMMA2_2, "gamma2_2"},
{UCSC_IGC_MODE_HLG, "hlg"},
{UCSC_IGC_MODE_PQ, "pq"},
};
if ((is_master &&
(psde->features & BIT(SDE_SSPP_INVERSE_PMA))) ||
(psde->features & BIT(SDE_SSPP_DGM_INVERSE_PMA))) {
@@ -3765,6 +3846,46 @@ static void _sde_plane_install_colorproc_properties(struct sde_plane *psde,
msm_property_install_range(&psde->property_info, feature_name,
0x0, 0, 1, 0, PLANE_PROP_FP16_UNMULT);
}
if (psde->features & BIT(SDE_SSPP_UCSC_IGC)) {
snprintf(feature_name, sizeof(feature_name), "%s%d",
"SDE_SSPP_UCSC_IGC_V",
psde->pipe_sblk->ucsc_igc_blk[0].version >> 16);
msm_property_install_enum(&psde->property_info, feature_name,
0x0, 0, ucsc_igc, ARRAY_SIZE(ucsc_igc), 0, PLANE_PROP_UCSC_IGC);
}
if (psde->features & BIT(SDE_SSPP_UCSC_GC)) {
snprintf(feature_name, sizeof(feature_name), "%s%d",
"SDE_SSPP_UCSC_GC_V",
psde->pipe_sblk->ucsc_gc_blk[0].version >> 16);
msm_property_install_enum(&psde->property_info, feature_name,
0x0, 0, ucsc_gc, ARRAY_SIZE(ucsc_gc), 0, PLANE_PROP_UCSC_GC);
}
if (psde->features & BIT(SDE_SSPP_UCSC_CSC)) {
snprintf(feature_name, sizeof(feature_name), "%s%d",
"SDE_SSPP_UCSC_CSC_V",
psde->pipe_sblk->ucsc_csc_blk[0].version >> 16);
msm_property_install_blob(&psde->property_info, feature_name, 0,
PLANE_PROP_UCSC_CSC);
}
if (psde->features & BIT(SDE_SSPP_UCSC_UNMULT)) {
snprintf(feature_name, sizeof(feature_name), "%s%d",
"SDE_SSPP_UCSC_UNMULT_V",
psde->pipe_sblk->ucsc_unmult_blk[0].version >> 16);
msm_property_install_range(&psde->property_info, feature_name,
0x0, 0, 1, 0, PLANE_PROP_UCSC_UNMULT);
}
if (psde->features & BIT(SDE_SSPP_UCSC_ALPHA_DITHER)) {
snprintf(feature_name, sizeof(feature_name), "%s%d",
"SDE_SSPP_UCSC_ALPHA_DITHER_V",
psde->pipe_sblk->ucsc_alpha_dither_blk[0].version >> 16);
msm_property_install_range(&psde->property_info, feature_name,
0x0, 0, 1, 0, PLANE_PROP_UCSC_ALPHA_DITHER);
}
}
static void _sde_plane_setup_capabilities_blob(struct sde_plane *psde,

Ver fichero

@@ -43,11 +43,18 @@
#define SDE_PLANE_DIRTY_FP16_GC 0x800
#define SDE_PLANE_DIRTY_FP16_CSC 0x1000
#define SDE_PLANE_DIRTY_FP16_UNMULT 0x2000
#define SDE_PLANE_DIRTY_UCSC_IGC 0x4000
#define SDE_PLANE_DIRTY_UCSC_GC 0x8000
#define SDE_PLANE_DIRTY_UCSC_CSC 0x10000
#define SDE_PLANE_DIRTY_UCSC_UNMULT 0x20000
#define SDE_PLANE_DIRTY_UCSC_ALPHA_DITHER 0x40000
#define SDE_PLANE_DIRTY_CP (SDE_PLANE_DIRTY_VIG_GAMUT |\
SDE_PLANE_DIRTY_VIG_IGC | SDE_PLANE_DIRTY_DMA_IGC |\
SDE_PLANE_DIRTY_DMA_GC | SDE_PLANE_DIRTY_FP16_IGC |\
SDE_PLANE_DIRTY_FP16_GC | SDE_PLANE_DIRTY_FP16_CSC |\
SDE_PLANE_DIRTY_FP16_UNMULT)
SDE_PLANE_DIRTY_FP16_UNMULT | SDE_PLANE_DIRTY_UCSC_IGC |\
SDE_PLANE_DIRTY_UCSC_GC | SDE_PLANE_DIRTY_UCSC_CSC |\
SDE_PLANE_DIRTY_UCSC_UNMULT | SDE_PLANE_DIRTY_UCSC_ALPHA_DITHER)
#define SDE_PLANE_DIRTY_ALL (0xFFFFFFFF & ~(SDE_PLANE_DIRTY_CP))
struct sde_plane {