diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 1b4b62d66a..e3d044a320 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -21,6 +21,9 @@ #include "sde_hw_color_proc_common_v4.h" #include "sde_vm.h" +#define DEMURA_BACKLIGHT_MAX 1024 +#define DEMURA_BACKLIGHT_MIN 64 + struct sde_cp_node { u32 property_id; u32 prop_flags; @@ -107,6 +110,8 @@ static void _sde_cp_crtc_update_ltm_roi(struct sde_crtc *sde_crtc, struct sde_hw_cp_cfg *hw_cfg); static int _sde_cp_flush_properties(struct drm_crtc *crtc); +static void _sde_cp_mark_bl_properties(struct sde_crtc *crtc); + static int _sde_cp_crtc_cache_property(struct drm_crtc *crtc, struct sde_crtc_state *cstate, struct sde_cp_node *prop_node, @@ -998,6 +1003,37 @@ static int _set_spr_udc_feature(struct sde_hw_dspp *hw_dspp, return ret; } +static int _set_demura_backlight(struct sde_hw_dspp *hw_dspp, + struct sde_hw_cp_cfg *hw_cfg, + struct sde_crtc *sde_crtc) +{ + int ret = 0; + u64 val = (DEMURA_BACKLIGHT_MAX << 16) | DEMURA_BACKLIGHT_MAX; + u32 brightness, inv; + + if (!hw_dspp || !hw_dspp->ops.setup_demura_backlight_cfg) { + ret = -EINVAL; + } else { + if (sde_crtc->back_light && sde_crtc->back_light_max) { + brightness = sde_crtc->back_light * ((1 << 10)); + do_div(brightness, sde_crtc->back_light_max); + /* Clip the brightness between 64 (min) and 1024 (max) */ + brightness = clamp_val(brightness, DEMURA_BACKLIGHT_MIN, + DEMURA_BACKLIGHT_MAX); + if (brightness) { + inv = (1 << 20); + do_div(inv, brightness); + inv = (inv < ((1 << 14) - 1)) ? inv : ((1 << 14) - 1); + val = (inv << 16) | brightness; + } + sde_crtc->back_light_pending = false; + } + hw_dspp->ops.setup_demura_backlight_cfg(hw_dspp, val, hw_cfg); + } + + return ret; +} + static int _set_demura_feature(struct sde_hw_dspp *hw_dspp, struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *sde_crtc) @@ -1011,6 +1047,7 @@ static int _set_demura_feature(struct sde_hw_dspp *hw_dspp, hw_dspp->ops.setup_demura_cfg(hw_dspp, hw_cfg); _update_pu_feature_enable(sde_crtc, SDE_CP_CRTC_DSPP_DEMURA_PU, hw_cfg->payload != NULL); + _set_demura_backlight(hw_dspp, hw_cfg, sde_crtc); } } @@ -1429,6 +1466,9 @@ void sde_cp_crtc_init(struct drm_crtc *crtc) INIT_LIST_HEAD(&sde_crtc->ltm_buf_free); INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy); sde_crtc->disable_pending_cp = false; + sde_crtc->back_light = 0; + sde_crtc->back_light_max = 0; + sde_crtc->back_light_pending = false; sde_cp_crtc_disable(crtc); } @@ -2320,6 +2360,7 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc) } _sde_cp_flush_properties(crtc); + _sde_cp_mark_bl_properties(sde_crtc); mutex_lock(&sde_crtc->crtc_cp_lock); _sde_clear_ltm_merge_mode(sde_crtc); @@ -5222,3 +5263,41 @@ void _sde_cp_mark_active_dirty_internal(struct sde_crtc *crtc) } mutex_unlock(&crtc->crtc_cp_lock); } + +void sde_cp_backlight_notification(struct drm_crtc *drm_crtc, u32 bl_val, u32 bl_max) +{ + struct sde_crtc *crtc; + + crtc = to_sde_crtc(drm_crtc); + mutex_lock(&crtc->crtc_cp_lock); + if (crtc->back_light != bl_val) { + crtc->back_light = bl_val; + crtc->back_light_max = bl_max; + crtc->back_light_pending = true; + } + mutex_unlock(&crtc->crtc_cp_lock); +} + +void _sde_cp_mark_bl_properties(struct sde_crtc *crtc) +{ + struct sde_cp_node *prop_node; + + mutex_lock(&crtc->crtc_cp_lock); + if (!crtc->back_light_pending) + goto skip_demura_bl; + + if (_sde_cp_feature_in_dirtylist(SDE_CP_CRTC_DSPP_DEMURA_INIT, + &crtc->cp_dirty_list)) + goto skip_demura_bl; + + prop_node = _sde_cp_feature_getnode_activelist(SDE_CP_CRTC_DSPP_DEMURA_INIT, + &crtc->cp_active_list); + + if (prop_node) { + _sde_cp_update_list(prop_node, crtc, true); + list_del_init(&prop_node->cp_active_list); + } +skip_demura_bl: + crtc->back_light_pending = false; + mutex_unlock(&crtc->crtc_cp_lock); +} diff --git a/msm/sde/sde_color_processing.h b/msm/sde/sde_color_processing.h index 93ba700981..77e17bc0ee 100644 --- a/msm/sde/sde_color_processing.h +++ b/msm/sde/sde_color_processing.h @@ -376,4 +376,12 @@ void sde_cp_set_skip_blend_plane_info(struct drm_crtc *crtc, */ int sde_dspp_spr_read_opr_value(struct sde_hw_dspp *hw_dspp, u32 *opr_value); +/** + * sde_cp_backlight_notification(): disable cp features + * @crtc: Pointer to drm_crtc. + * @bl_val: Backlight value. + * @bl_max: Max backlight value. + */ +void sde_cp_backlight_notification(struct drm_crtc *crtc, u32 bl_val, u32 bl_max); + #endif /*_SDE_COLOR_PROCESSING_H */ diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 27d0ce3085..1fd42946b9 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -182,8 +182,14 @@ static int sde_backlight_device_update_status(struct backlight_device *bd) } rc = c_conn->ops.set_backlight(&c_conn->base, c_conn->display, bl_lvl); - if (!rc) + + if (!rc) { sde_dimming_bl_notify(c_conn, &display->panel->bl_config); + if (c_conn->base.state && c_conn->base.state->crtc) { + sde_crtc_backlight_notify(c_conn->base.state->crtc, brightness, + display->panel->bl_config.brightness_max_level); + } + } c_conn->unset_bl_level = 0; } @@ -835,8 +841,16 @@ static int _sde_connector_update_bl_scale(struct sde_connector *c_conn) bl_config->bl_level); rc = c_conn->ops.set_backlight(&c_conn->base, dsi_display, bl_config->bl_level); - if (!rc) + + if (!rc) { sde_dimming_bl_notify(c_conn, bl_config); + if (c_conn->base.state && c_conn->base.state->crtc) { + sde_crtc_backlight_notify(c_conn->base.state->crtc, + dsi_display->panel->bl_config.brightness, + dsi_display->panel->bl_config.brightness_max_level); + } + } + c_conn->unset_bl_level = 0; return rc; diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index c9da5f34bf..7667e1c640 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -8744,3 +8744,9 @@ void sde_crtc_calc_vpadding_param(struct drm_crtc_state *state, u32 crtc_y, uint SDE_DEBUG("crtc:%d padding_y:%d padding_start:%d padding_height:%d\n", DRMID(cstate->base.crtc), *padding_y, *padding_start, *padding_height); } + +void sde_crtc_backlight_notify(struct drm_crtc *crtc, u32 bl_val, u32 bl_max) +{ + SDE_EVT32(bl_val, bl_max); + sde_cp_backlight_notification(crtc, bl_val, bl_max); +} diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index e613f28cb7..e40487deea 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -377,6 +377,9 @@ enum sde_crtc_hw_fence_flags { * used to slow-down creation of output hw-fences for debugging purposes. * @input_fence_status : input fence status, negative if the fence has been completed with error. * @hanle_fence_error_bw_update: bool to indicate if it is fence error and need to avoid bw vote. + * @back_light: backlight value + * @back_light_max: max backlight value + * @back_light_pending: flag to indicate if backlight update is pending */ struct sde_crtc { struct drm_crtc base; @@ -493,6 +496,10 @@ struct sde_crtc { u32 hwfence_out_fences_skip; int input_fence_status; bool handle_fence_error_bw_update; + + u32 back_light; + u32 back_light_max; + u32 back_light_pending; }; enum sde_crtc_dirty_flags { @@ -1201,4 +1208,12 @@ bool sde_crtc_is_line_insertion_supported(struct drm_crtc *crtc); void sde_crtc_calc_vpadding_param(struct drm_crtc_state *state, u32 crtc_y, u32 crtc_h, u32 *padding_y, u32 *padding_start, u32 *padding_height); +/** + * sde_crtc_backlight_notify - notify backlight + * @crtc: Pointer to drm_crtc. + * @bl_val: Backlight value. + * @bl_max: Max backlight value. + */ +void sde_crtc_backlight_notify(struct drm_crtc *crtc, u32 bl_val, u32 bl_max); + #endif /* _SDE_CRTC_H_ */ diff --git a/msm/sde/sde_hw_color_proc_v4.c b/msm/sde/sde_hw_color_proc_v4.c index 26fcead655..92f843a417 100644 --- a/msm/sde/sde_hw_color_proc_v4.c +++ b/msm/sde/sde_hw_color_proc_v4.c @@ -8,6 +8,9 @@ #include "sde_hw_color_proc_v4.h" #include "sde_dbg.h" +#define DEMURAV1_CFG0_PARAM4_MASK 5 +#define DEMURAV2_CFG0_PARAM4_MASK 7 + static int sde_write_3d_gamut(struct sde_hw_blk_reg_map *hw, struct drm_msm_3d_gamut *payload, u32 base, u32 *opcode, u32 pipe, u32 scale_tbl_a_len, @@ -478,20 +481,61 @@ void sde_ltm_clear_merge_mode(struct sde_hw_dspp *ctx) SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->ltm.base + 0x04, clear); } -void sde_demura_backlight_cfg(struct sde_hw_dspp *ctx, u64 val) +void sde_demura_backlight_cfg(struct sde_hw_dspp *ctx, u64 val, struct sde_hw_cp_cfg *hw_cfg) { u32 demura_base; - u32 backlight; + u32 backlight, gain[2]; + struct drm_msm_dem_cfg *dcfg = NULL; + uint32_t mask_bits = DEMURAV1_CFG0_PARAM4_MASK; if (!ctx) { DRM_ERROR("invalid parameter ctx %pK", ctx); return; } + if (!hw_cfg || !hw_cfg->payload) { + DRM_ERROR("invalid parameter hw_cfg"); + return; + } + + dcfg = (struct drm_msm_dem_cfg *)hw_cfg->payload; demura_base = ctx->cap->sblk->demura.base; - backlight = (val & REG_MASK_ULL(11)); - backlight |= ((val & REG_MASK_SHIFT_ULL(11, 32)) >> 16); + backlight = (val & REG_MASK(32)); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->demura.base + 0x8, backlight); + + backlight = backlight & REG_MASK(16); + if (backlight <= 41) { + /* Gain0.....Gain7 + * {0, 0, 0, 3, 2, 2, 1, 1} + */ + gain[0] = (0x0 & 0x3f) | ((0x0 & 0x3f) << 8) | + ((0x0 & 0x3f) << 16) | ((0x3 & 0x3f) << 24); + gain[1] = (0x2 & 0x3f) | ((0x2 & 0x3f) << 8) | + ((0x1 & 0x3f) << 16) | ((0x1 & 0x3f) << 24); + } else if (backlight <= 164) { + /* Gain0.....Gain7 + * {0, 0, 0, 2, 1, 1, 2, 3} + */ + gain[0] = (0x0 & 0x3f) | ((0x0 & 0x3f) << 8) | + ((0x0 & 0x3f) << 16) | ((0x2 & 0x3f) << 24); + gain[1] = (0x1 & 0x3f) | ((0x1 & 0x3f) << 8) | + ((0x2 & 0x3f) << 16) | ((0x3 & 0x3f) << 24); + } else { + /* check for demura v2 and assign mask bit accordingly */ + if (ctx->cap->sblk->demura.version == SDE_COLOR_PROCESS_VER(0x2, 0x0)) + mask_bits = DEMURAV2_CFG0_PARAM4_MASK; + + gain[0] = (dcfg->cfg0_param4[0] & REG_MASK(mask_bits)) | + ((dcfg->cfg0_param4[1] & REG_MASK(mask_bits)) << 8) | + ((dcfg->cfg0_param4[2] & REG_MASK(mask_bits)) << 16) | + ((dcfg->cfg0_param4[3] & REG_MASK(mask_bits)) << 24); + gain[1] = (dcfg->cfg0_param4[4] & REG_MASK(mask_bits)) | + ((dcfg->cfg0_param4[5] & REG_MASK(mask_bits)) << 8) | + ((dcfg->cfg0_param4[6] & REG_MASK(mask_bits)) << 16) | + ((dcfg->cfg0_param4[7] & REG_MASK(mask_bits)) << 24); + } + SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->demura.base + 0x4c, gain[0]); + SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->demura.base + 0x50, gain[1]); } void sde_setup_fp16_cscv1(struct sde_hw_pipe *ctx, diff --git a/msm/sde/sde_hw_color_proc_v4.h b/msm/sde/sde_hw_color_proc_v4.h index 18551a384c..1d047994fe 100644 --- a/msm/sde/sde_hw_color_proc_v4.h +++ b/msm/sde/sde_hw_color_proc_v4.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. */ #ifndef _SDE_HW_COLOR_PROC_V4_H_ @@ -101,8 +101,9 @@ void sde_ltm_clear_merge_modev1_2(struct sde_hw_dspp *dspp); * sde_demura_backlight_cfg - api to set backlight for demura * @ctx: pointer to dspp object * @val: value of backlight + * @cfg: pointer to sde_hw_cp_cfg */ -void sde_demura_backlight_cfg(struct sde_hw_dspp *ctx, u64 val); +void sde_demura_backlight_cfg(struct sde_hw_dspp *ctx, u64 val, struct sde_hw_cp_cfg *cfg); /** * sde_demura_read_plane_status - api to read demura plane fetch setup. diff --git a/msm/sde/sde_hw_dspp.h b/msm/sde/sde_hw_dspp.h index 32373224d6..e07a938ee0 100644 --- a/msm/sde/sde_hw_dspp.h +++ b/msm/sde/sde_hw_dspp.h @@ -304,9 +304,11 @@ struct sde_hw_dspp_ops { /** * setup_demura_backlight_cfg - function to program demura backlight * @ctx: Pointer to dspp context - * @status: Pointer to configuration. + * @val: value of backlight + * @hw_cfg: Pointer to configuration */ - void (*setup_demura_backlight_cfg)(struct sde_hw_dspp *ctx, u64 val); + void (*setup_demura_backlight_cfg)(struct sde_hw_dspp *ctx, u64 val, + struct sde_hw_cp_cfg *hw_cfg); /** * demura_read_plane_status - Query demura plane status diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/msm/sde/sde_hw_reg_dma_v1_color_proc.c index 80e649b892..a26465da16 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -126,9 +126,6 @@ #define REG_DMA_DSPP_GAMUT_OP_MASK 0xFFFFFFE0 -#define DEMURAV1_CFG0_PARAM4_MASK 5 -#define DEMURAV2_CFG0_PARAM4_MASK 7 - #define LOG_FEATURE_OFF SDE_EVT32(ctx->idx, 0) #define LOG_FEATURE_ON SDE_EVT32(ctx->idx, 1) @@ -6533,26 +6530,14 @@ static bool __reg_dmav1_valid_hfc_en_cfg(struct drm_msm_dem_cfg *dcfg, return false; } -static int __reg_dmav1_setup_demura_common_en(struct sde_hw_dspp *ctx, +static void __reg_dmav1_setup_demura_common_en(struct sde_hw_dspp *ctx, struct drm_msm_dem_cfg *dcfg, struct sde_reg_dma_setup_ops_cfg *dma_write_cfg, struct sde_hw_reg_dma_ops *dma_ops, struct sde_hw_cp_cfg *hw_cfg, u32 *en) { - u32 backl; - int rc; bool valid_hfc_cfg = false; - u32 demura_base = ctx->cap->sblk->demura.base + ctx->hw.blk_off; - - backl = (1024 << 16) | 1024; - REG_DMA_SETUP_OPS(*dma_write_cfg, demura_base + 0x8, - &backl, sizeof(backl), REG_SINGLE_WRITE, 0, 0, 0); - rc = dma_ops->setup_payload(dma_write_cfg); - if (rc) { - DRM_ERROR("0x8: REG_SINGLE_WRITE failed ret %d\n", rc); - return rc; - } *en = (dcfg->src_id == BIT(3)) ? 0 : BIT(31); *en |= (dcfg->cfg1_high_idx & REG_MASK(3)) << 24; @@ -6569,8 +6554,6 @@ static int __reg_dmav1_setup_demura_common_en(struct sde_hw_dspp *ctx, *en |= (dcfg->cfg0_en) ? BIT(2) : 0; *en |= (dcfg->cfg1_en) ? BIT(1) : 0; DRM_DEBUG_DRIVER("demura common en %x\n", *en); - - return rc; } static int __reg_dmav1_setup_demurav1_en(struct sde_hw_dspp *ctx, @@ -6583,11 +6566,7 @@ static int __reg_dmav1_setup_demurav1_en(struct sde_hw_dspp *ctx, int rc; u32 demura_base = ctx->cap->sblk->demura.base + ctx->hw.blk_off; - rc = __reg_dmav1_setup_demura_common_en(ctx, dcfg, dma_write_cfg, dma_ops, hw_cfg, &en); - if (rc) { - DRM_ERROR("failed reg_dmav1_setup_demura_common_en %d", rc); - return rc; - } + __reg_dmav1_setup_demura_common_en(ctx, dcfg, dma_write_cfg, dma_ops, hw_cfg, &en); DRM_DEBUG_DRIVER("demura v1 en 0x%x\n", en); SDE_EVT32(en); @@ -6610,11 +6589,7 @@ static int __reg_dmav1_setup_demurav2_en(struct sde_hw_dspp *ctx, int rc, val; u32 demura_base = ctx->cap->sblk->demura.base + ctx->hw.blk_off; - rc = __reg_dmav1_setup_demura_common_en(ctx, dcfg, dma_write_cfg, dma_ops, hw_cfg, &en); - if (rc) { - DRM_ERROR("failed reg_dmav1_setup_demura_common_en %d", rc); - return rc; - } + __reg_dmav1_setup_demura_common_en(ctx, dcfg, dma_write_cfg, dma_ops, hw_cfg, &en); /* These are Demura V2 config flags */ val = (dcfg->flags & DEMURA_FLAG_2) >> 2; @@ -6638,52 +6613,6 @@ static int __reg_dmav1_setup_demurav2_en(struct sde_hw_dspp *ctx, return rc; } -static int __reg_dmav1_setup_demura_cfg0_param4_common(struct sde_hw_dspp *ctx, - struct drm_msm_dem_cfg *dcfg, - struct sde_reg_dma_setup_ops_cfg *dma_write_cfg, - struct sde_hw_reg_dma_ops *dma_ops, - uint32_t mask_bits) -{ - int rc = 0; - u32 *temp = NULL, i; - u32 demura_base = ctx->cap->sblk->demura.base + ctx->hw.blk_off; - - if (!dcfg->cfg0_en) { - DRM_DEBUG_DRIVER("dcfg->cfg0_en is disabled\n"); - return 0; - } - - temp = kvzalloc(sizeof(struct drm_msm_dem_cfg), GFP_KERNEL); - if (!temp) - return -ENOMEM; - - memset(temp, 0, sizeof(u32) * 2); - for (i = 0; i < ARRAY_SIZE(dcfg->cfg0_param4); i++) - DRM_DEBUG_DRIVER("hfc gain is %d\n", dcfg->cfg0_param4[i]); - temp[0] = (dcfg->cfg0_param4[0] & REG_MASK(mask_bits)) | - ((dcfg->cfg0_param4[1] & REG_MASK(mask_bits)) << 8) | - ((dcfg->cfg0_param4[2] & REG_MASK(mask_bits)) << 16) | - ((dcfg->cfg0_param4[3] & REG_MASK(mask_bits)) << 24); - temp[1] = (dcfg->cfg0_param4[4] & REG_MASK(mask_bits)) | - ((dcfg->cfg0_param4[5] & REG_MASK(mask_bits)) << 8) | - ((dcfg->cfg0_param4[6] & REG_MASK(mask_bits)) << 16) | - ((dcfg->cfg0_param4[7] & REG_MASK(mask_bits)) << 24); - DRM_DEBUG_DRIVER("0x4c: value is temp[0] %x temp[1] %x\n", - temp[0], temp[1]); - REG_DMA_SETUP_OPS(*dma_write_cfg, demura_base + 0x4c, - temp, sizeof(u32) * 2, REG_BLK_WRITE_SINGLE, 0, 0, 0); - rc = dma_ops->setup_payload(dma_write_cfg); - if (rc) { - DRM_ERROR("0x4c: REG_BLK_WRITE_SINGLE %d len %zd buf idx %d\n", - rc, sizeof(u32) * 2, dma_write_cfg->dma_buf->index); - goto quit; - } - -quit: - kvfree(temp); - return rc; -} - static int __reg_dmav1_setup_demurav1_dual_pipe(struct sde_hw_dspp *ctx, struct sde_hw_cp_cfg *hw_cfg, struct sde_reg_dma_setup_ops_cfg *dma_write_cfg, @@ -6803,13 +6732,6 @@ void reg_dmav1_setup_demurav1(struct sde_hw_dspp *ctx, void *cfx) return; } - rc = __reg_dmav1_setup_demura_cfg0_param4_common(ctx, dcfg, &dma_write_cfg, - dma_ops, DEMURAV1_CFG0_PARAM4_MASK); - if (rc) { - DRM_ERROR("failed setup demura v1 cfg0_param4 rc %d", rc); - return; - } - rc = __reg_dmav1_setup_demurav1_en(ctx, dcfg, &dma_write_cfg, dma_ops, hw_cfg); if (rc) { DRM_ERROR("failed setup_demurav1_en rc %d", rc); @@ -6872,13 +6794,6 @@ void reg_dmav1_setup_demurav2(struct sde_hw_dspp *ctx, void *cfx) return; } - rc = __reg_dmav1_setup_demura_cfg0_param4_common(ctx, dcfg, &dma_write_cfg, - dma_ops, DEMURAV2_CFG0_PARAM4_MASK); - if (rc) { - DRM_ERROR("failed setup demura v2 cfg0_param4 rc %d", rc); - return; - } - rc = __reg_dmav1_setup_demurav2_en(ctx, dcfg, &dma_write_cfg, dma_ops, hw_cfg); if (rc) { DRM_ERROR("failed setup_demurav2_en rc %d", rc);