drm/amd/display: Implement abm config table copy to dmcub
authorWyatt Wood <wyatt.wood@amd.com>
Sun, 5 Apr 2020 20:40:43 +0000 (16:40 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 9 Apr 2020 14:43:16 +0000 (10:43 -0400)
[Why]
Driver must pass abm config table to dmub fw. This provides various
parameters for abm functionality.

[How]
There is too much data to be passed in an inbox message, so we must pass
this data using an indirect buffer.  Copy the table to cw7 via x86,
driver copies to fw_state structure.

Signed-off-by: Wyatt Wood <wyatt.wood@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Acked-by: Tony Cheng <Tony.Cheng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
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/inc/hw/abm.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.c

index a4dae31400fa4957e9f23b9720300ef55fe3c238..e345df621a6af0e09dda3e068945c60b26d4d865 100644 (file)
@@ -447,7 +447,7 @@ static const struct abm_funcs dce_funcs = {
        .set_backlight_level_pwm = dce_abm_set_backlight_level_pwm,
        .get_current_backlight = dce_abm_get_current_backlight,
        .get_target_backlight = dce_abm_get_target_backlight,
-       .load_abm_config = NULL,
+       .init_abm_config = NULL,
        .set_abm_immediate_disable = dce_abm_immediate_disable
 };
 
index 81c967917c5bad1e324b031f73611ff985899b68..06435ecaf6a32cbda1ded40f64566759e008308f 100644 (file)
@@ -348,11 +348,30 @@ static bool dmub_abm_set_backlight_level_pwm(
        return true;
 }
 
-static bool dmub_abm_load_config(struct abm *abm,
-       unsigned int start_offset,
+static bool dmub_abm_init_config(struct abm *abm,
        const char *src,
        unsigned int bytes)
 {
+       union dmub_rb_cmd cmd;
+       struct dc_context *dc = abm->ctx;
+
+       // TODO: Optimize by only reading back final 4 bytes
+       dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb);
+
+       // Copy iramtable into cw7
+       memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)src, bytes);
+
+       // Fw will copy from cw7 to fw_state
+       cmd.abm_init_config.header.type = DMUB_CMD__ABM;
+       cmd.abm_init_config.header.sub_type = DMUB_CMD__ABM_INIT_CONFIG;
+       cmd.abm_init_config.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr;
+       cmd.abm_init_config.abm_init_config_data.bytes = bytes;
+       cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data);
+
+       dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd.abm_init_config.header);
+       dc_dmub_srv_cmd_execute(dc->dmub_srv);
+       dc_dmub_srv_wait_idle(dc->dmub_srv);
+
        return true;
 }
 
@@ -365,7 +384,7 @@ static const struct abm_funcs abm_funcs = {
        .get_current_backlight = dmub_abm_get_current_backlight,
        .get_target_backlight = dmub_abm_get_target_backlight,
        .set_abm_immediate_disable = dmub_abm_immediate_disable,
-       .load_abm_config = dmub_abm_load_config,
+       .init_abm_config = dmub_abm_init_config,
 };
 
 static void dmub_abm_construct(
index 9cca0ca30feee6aff4dcd3d23a64ac500ff3470a..0cae258a903e0323175f4614eb4c3651b6f87bb5 100644 (file)
@@ -60,8 +60,7 @@ struct abm_funcs {
 
        unsigned int (*get_current_backlight)(struct abm *abm);
        unsigned int (*get_target_backlight)(struct abm *abm);
-       bool (*load_abm_config)(struct abm *abm,
-                       unsigned int start_offset,
+       bool (*init_abm_config)(struct abm *abm,
                        const char *src,
                        unsigned int bytes);
 };
index c2671f2616c840dbbead13833126aa6d77f989d7..af678462f0e6547b6c452de796d8f6d0bf09035f 100644 (file)
@@ -565,6 +565,16 @@ dmub_srv_send_gpint_command(struct dmub_srv *dmub,
 enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub,
                                             uint32_t *response);
 
+/**
+ * dmub_flush_buffer_mem() - Read back entire frame buffer region.
+ * This ensures that the write from x86 has been flushed and will not
+ * hang the DMCUB.
+ * @fb: frame buffer to flush
+ *
+ * Can be called after software initialization.
+ */
+void dmub_flush_buffer_mem(const struct dmub_fb *fb);
+
 #if defined(__cplusplus)
 }
 #endif
index ce32cc7933c40777f185b08063b4b47cd5a892b1..0be8a54cc47547784b02cb251df2995b953beef0 100644 (file)
@@ -70,7 +70,7 @@ static inline uint32_t dmub_align(uint32_t val, uint32_t factor)
        return (val + factor - 1) / factor * factor;
 }
 
-static void dmub_flush_buffer_mem(const struct dmub_fb *fb)
+void dmub_flush_buffer_mem(const struct dmub_fb *fb)
 {
        const uint8_t *base = (const uint8_t *)fb->cpu_addr;
        uint8_t buf[64];
index 8bf1bdd0f457c88981fecf928d31b28978149545..c1a95da6706f179df15c1b127566ae075fa81174 100644 (file)
@@ -671,8 +671,8 @@ bool dmcu_load_iram(struct dmcu *dmcu,
        // ABM 2.4 and up are implemented on dmcub
        if (dmcu == NULL) {
                fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params);
-               result = abm->funcs->load_abm_config(
-                       abm, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2);
+               result = abm->funcs->init_abm_config(
+                       abm, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2);
        } else if (dmcu->dmcu_version.abm_version == 0x24) {
                fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params);
                        result = dmcu->funcs->load_iram(