summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWyatt Wood <wyatt.wood@amd.com>2020-04-30 20:04:47 -0400
committerAlex Deucher <alexander.deucher@amd.com>2020-05-28 14:00:48 -0400
commit1db14695929f26a8f524f5c7af7d30265374b51d (patch)
treefbd311bb3a3f0fa113f15ef8682893754e3f2322
parent7b8a6362fa146b78398d2cb9380cc7f3cb2145d3 (diff)
downloadlinux-1db14695929f26a8f524f5c7af7d30265374b51d.tar.bz2
drm/amd/display: Fix ABM memory alignment issue
[Why] Due to packing of abm_config_table, memory addresses aren't aligned to 32 bit boundary dmcub prefers. Therefore when using pointers to this structure, it's possible that dmcub will automatically align the data read from that address, yielding incorrect values. [How] Instead of packing 1 byte boundary, explicitly pack values to 4 byte boundary. Since there is a dependency on the existing iram table structure on driver side, we must copy to a second structure, which is aligned correctly, before passing to fw. Signed-off-by: Wyatt Wood <wyatt.wood@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
index 60b92f099af5..dbfdeed0b6e6 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -27,6 +27,7 @@
#include "dc/inc/hw/abm.h"
#include "dc.h"
#include "core_types.h"
+#include "dmub_cmd_dal.h"
#define DIV_ROUNDUP(a, b) (((a)+((b)/2))/(b))
#define bswap16_based_on_endian(big_endian, value) \
@@ -658,17 +659,55 @@ void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame
bool dmub_init_abm_config(struct abm *abm,
struct dmcu_iram_parameters params)
{
- unsigned char ram_table[IRAM_SIZE];
+ struct iram_table_v_2_2 ram_table;
+ struct abm_config_table config;
bool result = false;
+ uint32_t i, j = 0;
if (abm == NULL)
return false;
memset(&ram_table, 0, sizeof(ram_table));
+ memset(&config, 0, sizeof(config));
+
+ fill_iram_v_2_3(&ram_table, params, false);
+
+ // We must copy to structure that is aligned to 32-bit
+ for (i = 0; i < NUM_POWER_FN_SEGS; i++) {
+ config.crgb_thresh[i] = ram_table.crgb_thresh[i];
+ config.crgb_offset[i] = ram_table.crgb_offset[i];
+ config.crgb_slope[i] = ram_table.crgb_slope[i];
+ }
+
+ for (i = 0; i < NUM_BL_CURVE_SEGS; i++) {
+ config.backlight_thresholds[i] = ram_table.backlight_thresholds[i];
+ config.backlight_offsets[i] = ram_table.backlight_offsets[i];
+ }
+
+ for (i = 0; i < NUM_AMBI_LEVEL; i++)
+ config.iir_curve[i] = ram_table.iir_curve[i];
+
+ for (i = 0; i < NUM_AMBI_LEVEL; i++) {
+ for (j = 0; j < NUM_AGGR_LEVEL; j++) {
+ config.min_reduction[i][j] = ram_table.min_reduction[i][j];
+ config.max_reduction[i][j] = ram_table.max_reduction[i][j];
+ config.bright_pos_gain[i][j] = ram_table.bright_pos_gain[i][j];
+ config.dark_pos_gain[i][j] = ram_table.dark_pos_gain[i][j];
+ }
+ }
+
+ for (i = 0; i < NUM_AGGR_LEVEL; i++) {
+ config.hybrid_factor[i] = ram_table.hybrid_factor[i];
+ config.contrast_factor[i] = ram_table.contrast_factor[i];
+ config.deviation_gain[i] = ram_table.deviation_gain[i];
+ config.min_knee[i] = ram_table.min_knee[i];
+ config.max_knee[i] = ram_table.max_knee[i];
+ }
+
+ config.min_abm_backlight = ram_table.min_abm_backlight;
- fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params, false);
result = abm->funcs->init_abm_config(
- abm, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2);
+ abm, (char *)(&config), sizeof(struct abm_config_table));
return result;
}