drm/amd/display: Correctly restore user_level
authorCamille Cho <camille.cho@amd.com>
Thu, 16 Nov 2023 08:19:25 +0000 (16:19 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 3 Jan 2024 15:31:52 +0000 (10:31 -0500)
[Why]
BL1_PWM_USER_LEVEL is meant for the user brightness level setting from
OS. However, we update it along with other ABM levels to the real PWM
value which could be ABMed.

[How]
Driver to cache and restore the user brightness level setting so that
DMUB can retrieve the last user setting in ABM config initialization.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Anthony Koo <anthony.koo@amd.com>
Acked-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
Signed-off-by: Camille Cho <camille.cho@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
13 files changed:
drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.h
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h
drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c

index 874b132fe1d782f330353c628bf892da03f4618c..a6006776333d12f2da868c9699a1dd350ed803d5 100644 (file)
@@ -135,7 +135,7 @@ static void dmcu_set_backlight_level(
                        0, 1, 80000);
 }
 
-static void dce_abm_init(struct abm *abm, uint32_t backlight)
+static void dce_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level)
 {
        struct dce_abm *abm_dce = TO_DCE_ABM(abm);
 
@@ -162,7 +162,7 @@ static void dce_abm_init(struct abm *abm, uint32_t backlight)
                        BL1_PWM_TARGET_ABM_LEVEL, backlight);
 
        REG_UPDATE(BL1_PWM_USER_LEVEL,
-                       BL1_PWM_USER_LEVEL, backlight);
+                       BL1_PWM_USER_LEVEL, user_level);
 
        REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
                        ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
index 8c5e7f858be38a69f2ad5e4ea8e3937541e9d045..ccc154b0281c2c9274f7e28af06ab03288d592f9 100644 (file)
@@ -57,9 +57,9 @@ static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst
        return ret;
 }
 
-static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight)
+static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight, uint32_t user_level)
 {
-       dmub_abm_init(abm, backlight);
+       dmub_abm_init(abm, backlight, user_level);
 }
 
 static unsigned int dmub_abm_get_current_backlight_ex(struct abm *abm)
index 4cff36351f40a312e7f89e4b87a4dc3d6574f8d9..f9d6a181164aac70024480550a56e125cd96b167 100644 (file)
@@ -79,7 +79,7 @@ static void dmub_abm_enable_fractional_pwm(struct dc_context *dc)
        dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
 }
 
-void dmub_abm_init(struct abm *abm, uint32_t backlight)
+void dmub_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level)
 {
        struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
 
@@ -106,7 +106,7 @@ void dmub_abm_init(struct abm *abm, uint32_t backlight)
                        BL1_PWM_TARGET_ABM_LEVEL, backlight);
 
        REG_UPDATE(BL1_PWM_USER_LEVEL,
-                       BL1_PWM_USER_LEVEL, backlight);
+                       BL1_PWM_USER_LEVEL, user_level);
 
        REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
                        ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
index 07ea6c8d414f3baa5ec64d3eb57a162796db5004..761685e5b8c91eabb4d5a5ffb11c8d4299234ccc 100644 (file)
@@ -30,7 +30,7 @@
 
 struct abm_save_restore;
 
-void dmub_abm_init(struct abm *abm, uint32_t backlight);
+void dmub_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level);
 bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask);
 unsigned int dmub_abm_get_current_backlight(struct abm *abm);
 unsigned int dmub_abm_get_target_backlight(struct abm *abm);
index 6457099ed588203f58d47ad72b8ed648ceae2098..fb328cd06cea2c8a00f7450c8ade7408fb4716a9 100644 (file)
@@ -2593,6 +2593,7 @@ static void init_hw(struct dc *dc)
        struct dmcu *dmcu;
        struct dce_hwseq *hws = dc->hwseq;
        uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
 
        bp = dc->ctx->dc_bios;
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
@@ -2642,13 +2643,15 @@ static void init_hw(struct dc *dc)
        for (i = 0; i < dc->link_count; i++) {
                struct dc_link *link = dc->links[i];
 
-               if (link->panel_cntl)
+               if (link->panel_cntl) {
                        backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
+                       user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
+               }
        }
 
        abm = dc->res_pool->abm;
        if (abm != NULL)
-               abm->funcs->abm_init(abm, backlight);
+               abm->funcs->abm_init(abm, backlight, user_level);
 
        dmcu = dc->res_pool->dmcu;
        if (dmcu != NULL && abm != NULL)
index 1c5e3bb6f0ee418f48fab772f73180e046e59d9d..51dd2ae09b2a6235f822c7eb6c72335f38fafe24 100644 (file)
@@ -1490,6 +1490,7 @@ void dcn10_init_hw(struct dc *dc)
        struct dc_bios *dcb = dc->ctx->dc_bios;
        struct resource_pool *res_pool = dc->res_pool;
        uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
        bool   is_optimized_init_done = false;
 
        if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
@@ -1587,12 +1588,14 @@ void dcn10_init_hw(struct dc *dc)
                for (i = 0; i < dc->link_count; i++) {
                        struct dc_link *link = dc->links[i];
 
-                       if (link->panel_cntl)
+                       if (link->panel_cntl) {
                                backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
+                               user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
+                       }
                }
 
                if (abm != NULL)
-                       abm->funcs->abm_init(abm, backlight);
+                       abm->funcs->abm_init(abm, backlight, user_level);
 
                if (dmcu != NULL && !dmcu->auto_load_dmcu)
                        dmcu->funcs->dmcu_init(dmcu);
index 327c227a10ead72df9b383a5fbb14645249a3c36..c34c13e1e0a4ea918de9a9e36dbe305ce5224485 100644 (file)
@@ -476,6 +476,7 @@ void dcn30_init_hw(struct dc *dc)
        int i;
        int edp_num;
        uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
 
        if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
                dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
@@ -612,13 +613,15 @@ void dcn30_init_hw(struct dc *dc)
        for (i = 0; i < dc->link_count; i++) {
                struct dc_link *link = dc->links[i];
 
-               if (link->panel_cntl)
+               if (link->panel_cntl) {
                        backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
+                       user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
+               }
        }
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                if (abms[i] != NULL)
-                       abms[i]->funcs->abm_init(abms[i], backlight);
+                       abms[i]->funcs->abm_init(abms[i], backlight, user_level);
        }
 
        /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
index 260860c259f3a366533142b7faef1325317438dc..7423880fabb6e3b0d1a1003bab1fa8ff4898a936 100644 (file)
@@ -113,6 +113,7 @@ void dcn31_init_hw(struct dc *dc)
        struct dc_bios *dcb = dc->ctx->dc_bios;
        struct resource_pool *res_pool = dc->res_pool;
        uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
        int i;
 
        if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
@@ -224,13 +225,15 @@ void dcn31_init_hw(struct dc *dc)
        for (i = 0; i < dc->link_count; i++) {
                struct dc_link *link = dc->links[i];
 
-               if (link->panel_cntl)
+               if (link->panel_cntl) {
                        backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
+                       user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
+               }
        }
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                if (abms[i] != NULL)
-                       abms[i]->funcs->abm_init(abms[i], backlight);
+                       abms[i]->funcs->abm_init(abms[i], backlight, user_level);
        }
 
        /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
index 6f360f008f67a0c76d69ef4dc9e033e3e2d9e5d9..6c9299c7683df19b3c444b865d297182d91ae7b3 100644 (file)
@@ -753,6 +753,7 @@ void dcn32_init_hw(struct dc *dc)
        int i;
        int edp_num;
        uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
 
        if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
                dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
@@ -907,13 +908,15 @@ void dcn32_init_hw(struct dc *dc)
        for (i = 0; i < dc->link_count; i++) {
                struct dc_link *link = dc->links[i];
 
-               if (link->panel_cntl)
+               if (link->panel_cntl) {
                        backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
+                       user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
+               }
        }
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                if (abms[i] != NULL && abms[i]->funcs != NULL)
-                       abms[i]->funcs->abm_init(abms[i], backlight);
+                       abms[i]->funcs->abm_init(abms[i], backlight, user_level);
        }
 
        /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
index ad710b4036de0f47b92b941d7559ed47a3422996..c40f4a06abdbe8cefcc20fb79d57e0d8a405fff0 100644 (file)
@@ -134,6 +134,7 @@ void dcn35_init_hw(struct dc *dc)
        struct dc_bios *dcb = dc->ctx->dc_bios;
        struct resource_pool *res_pool = dc->res_pool;
        uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
        int i;
 
        if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
@@ -280,13 +281,15 @@ void dcn35_init_hw(struct dc *dc)
        for (i = 0; i < dc->link_count; i++) {
                struct dc_link *link = dc->links[i];
 
-               if (link->panel_cntl)
+               if (link->panel_cntl) {
                        backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
+                       user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
+               }
        }
        if (dc->ctx->dmub_srv) {
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                if (abms[i] != NULL && abms[i]->funcs != NULL)
-                       abms[i]->funcs->abm_init(abms[i], backlight);
+                       abms[i]->funcs->abm_init(abms[i], backlight, user_level);
                }
        }
 
index 9f521cf0fc5a2b4a629ccf69d1656be0d4da4add..3f0161d6467556720592b842059f0424237bf1dc 100644 (file)
@@ -36,7 +36,7 @@ struct abm {
 };
 
 struct abm_funcs {
-       void (*abm_init)(struct abm *abm, uint32_t back_light);
+       void (*abm_init)(struct abm *abm, uint32_t back_light, uint32_t user_level);
        bool (*set_abm_level)(struct abm *abm, unsigned int abm_level);
        bool (*set_abm_immediate_disable)(struct abm *abm, unsigned int panel_inst);
        bool (*set_pipe)(struct abm *abm, unsigned int controller_id, unsigned int panel_inst);
index 248adc1705e3578611ed92b944db2e99b017127f..5dcbaa2db964aee7de17c2e9306606cac1817b08 100644 (file)
@@ -40,6 +40,7 @@ struct panel_cntl_backlight_registers {
        unsigned int BL_PWM_PERIOD_CNTL;
        unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV;
        unsigned int PANEL_PWRSEQ_REF_DIV2;
+       unsigned int USER_LEVEL;
 };
 
 struct panel_cntl_funcs {
index bf53a86ea81718163a4746d8e6eadc1b60678889..e8de68e62403dc02e75af3c311acd366bdd3c3d1 100644 (file)
@@ -529,6 +529,9 @@ bool edp_set_backlight_level(const struct dc_link *link,
        if (dc_is_embedded_signal(link->connector_signal)) {
                struct pipe_ctx *pipe_ctx = get_pipe_from_link(link);
 
+               if (link->panel_cntl)
+                       link->panel_cntl->stored_backlight_registers.USER_LEVEL = backlight_pwm_u16_16;
+
                if (pipe_ctx) {
                        /* Disable brightness ramping when the display is blanked
                         * as it can hang the DMCU