diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules')
6 files changed, 140 insertions, 37 deletions
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index eced40a2fce4..5c67e12b2e55 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -30,6 +30,14 @@ #include "opp.h" #include "color_gamma.h" +/* When calculating LUT values the first region and at least one subsequent + * region are calculated with full precision. These defines are a demarcation + * of where the second region starts and ends. + * These are hardcoded values to avoid recalculating them in loops. + */ +#define PRECISE_LUT_REGION_START 224 +#define PRECISE_LUT_REGION_END 239 + static struct hw_x_point coordinates_x[MAX_HW_POINTS + 2]; // these are helpers for calculations to reduce stack usage @@ -346,7 +354,13 @@ static struct fixed31_32 translate_from_linear_space( dc_fixpt_recip(args->gamma)); } scratch_1 = dc_fixpt_add(one, args->a3); - if (cal_buffer->buffer_index < 16) + /* In the first region (first 16 points) and in the + * region delimited by START/END we calculate with + * full precision to avoid error accumulation. + */ + if ((cal_buffer->buffer_index >= PRECISE_LUT_REGION_START && + cal_buffer->buffer_index <= PRECISE_LUT_REGION_END) || + (cal_buffer->buffer_index < 16)) scratch_2 = dc_fixpt_pow(args->arg, dc_fixpt_recip(args->gamma)); else @@ -397,9 +411,7 @@ static struct fixed31_32 translate_from_linear_space_long( dc_fixpt_recip(args->gamma))), args->a2); else - return dc_fixpt_mul( - args->arg, - args->a1); + return dc_fixpt_mul(args->arg, args->a1); } static struct fixed31_32 calculate_gamma22(struct fixed31_32 arg, bool use_eetf, struct calculate_buffer *cal_buffer) @@ -717,7 +729,6 @@ static struct fixed31_32 calculate_mapped_value( BREAK_TO_DEBUGGER(); result = dc_fixpt_zero; } else { - BREAK_TO_DEBUGGER(); result = dc_fixpt_one; } @@ -976,6 +987,7 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, cal_buffer->buffer_index = 0; // see var definition for more info rgb += 32; // first 32 points have problems with fixed point, too small coord_x += 32; + for (i = 32; i <= hw_points_num; i++) { if (!is_clipped) { if (use_eetf) { diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 52c3cb6b439a..4762273b5bb9 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -569,6 +569,12 @@ static void build_vrr_infopacket_data_v1(const struct mod_vrr_params *vrr, static void build_vrr_infopacket_data_v3(const struct mod_vrr_params *vrr, struct dc_info_packet *infopacket) { + unsigned int min_refresh; + unsigned int max_refresh; + unsigned int fixed_refresh; + unsigned int min_programmed; + unsigned int max_programmed; + /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */ infopacket->sb[1] = 0x1A; @@ -598,23 +604,33 @@ static void build_vrr_infopacket_data_v3(const struct mod_vrr_params *vrr, vrr->state == VRR_STATE_ACTIVE_FIXED) infopacket->sb[6] |= 0x04; - if (vrr->state == VRR_STATE_ACTIVE_FIXED) { - /* PB7 = FreeSync Minimum refresh rate (Hz) */ - infopacket->sb[7] = (unsigned char)((vrr->fixed_refresh_in_uhz + 500000) / 1000000); - /* PB8 = FreeSync Maximum refresh rate (Hz) */ - infopacket->sb[8] = (unsigned char)((vrr->fixed_refresh_in_uhz + 500000) / 1000000); - } else if (vrr->state == VRR_STATE_ACTIVE_VARIABLE) { - /* PB7 = FreeSync Minimum refresh rate (Hz) */ - infopacket->sb[7] = (unsigned char)((vrr->min_refresh_in_uhz + 500000) / 1000000); - /* PB8 = FreeSync Maximum refresh rate (Hz) */ - infopacket->sb[8] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000); - } else { - // Non-fs case, program nominal range - /* PB7 = FreeSync Minimum refresh rate (Hz) */ - infopacket->sb[7] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000); - /* PB8 = FreeSync Maximum refresh rate (Hz) */ - infopacket->sb[8] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000); - } + min_refresh = (vrr->min_refresh_in_uhz + 500000) / 1000000; + max_refresh = (vrr->max_refresh_in_uhz + 500000) / 1000000; + fixed_refresh = (vrr->fixed_refresh_in_uhz + 500000) / 1000000; + + min_programmed = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? fixed_refresh : + (vrr->state == VRR_STATE_ACTIVE_VARIABLE) ? min_refresh : + (vrr->state == VRR_STATE_INACTIVE) ? min_refresh : + max_refresh; // Non-fs case, program nominal range + + max_programmed = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? fixed_refresh : + (vrr->state == VRR_STATE_ACTIVE_VARIABLE) ? max_refresh : + max_refresh;// Non-fs case, program nominal range + + /* PB7 = FreeSync Minimum refresh rate (Hz) */ + infopacket->sb[7] = min_programmed & 0xFF; + + /* PB8 = FreeSync Maximum refresh rate (Hz) */ + infopacket->sb[8] = max_programmed & 0xFF; + + /* PB11 : MSB FreeSync Minimum refresh rate [Hz] - bits 9:8 */ + infopacket->sb[11] = (min_programmed >> 8) & 0x03; + + /* PB12 : MSB FreeSync Maximum refresh rate [Hz] - bits 9:8 */ + infopacket->sb[12] = (max_programmed >> 8) & 0x03; + + /* PB16 : Reserved bits 7:1, FixedRate bit 0 */ + infopacket->sb[16] = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? 1 : 0; //FreeSync HDR infopacket->sb[9] = 0; @@ -733,6 +749,58 @@ static void build_vrr_infopacket_header_v2(enum signal_type signal, } } +static void build_vrr_infopacket_header_v3(enum signal_type signal, + struct dc_info_packet *infopacket, + unsigned int *payload_size) +{ + unsigned char version; + + version = 3; + if (dc_is_hdmi_signal(signal)) { + + /* HEADER */ + + /* HB0 = Packet Type = 0x83 (Source Product + * Descriptor InfoFrame) + */ + infopacket->hb0 = DC_HDMI_INFOFRAME_TYPE_SPD; + + /* HB1 = Version = 0x03 */ + infopacket->hb1 = version; + + /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length] */ + *payload_size = 0x10; + infopacket->hb2 = *payload_size - 1; //-1 for checksum + + } else if (dc_is_dp_signal(signal)) { + + /* HEADER */ + + /* HB0 = Secondary-data Packet ID = 0 - Only non-zero + * when used to associate audio related info packets + */ + infopacket->hb0 = 0x00; + + /* HB1 = Packet Type = 0x83 (Source Product + * Descriptor InfoFrame) + */ + infopacket->hb1 = DC_HDMI_INFOFRAME_TYPE_SPD; + + /* HB2 = [Bits 7:0 = Least significant eight bits - + * For INFOFRAME, the value must be 1Bh] + */ + infopacket->hb2 = 0x1B; + + /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x2] + * [Bits 1:0 = Most significant two bits = 0x00] + */ + + infopacket->hb3 = (version & 0x3F) << 2; + + *payload_size = 0x1B; + } +} + static void build_vrr_infopacket_checksum(unsigned int *payload_size, struct dc_info_packet *infopacket) { @@ -818,7 +886,7 @@ static void build_vrr_infopacket_v3(enum signal_type signal, { unsigned int payload_size = 0; - build_vrr_infopacket_header_v2(signal, infopacket, &payload_size); + build_vrr_infopacket_header_v3(signal, infopacket, &payload_size); build_vrr_infopacket_data_v3(vrr, infopacket); build_vrr_infopacket_fs2_data(app_tf, infopacket); diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c index f244b72e74e0..73ca49f05bd3 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c @@ -128,8 +128,12 @@ static inline uint8_t get_device_count(struct mod_hdcp *hdcp) static inline enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp) { - /* device count must be greater than or equal to tracked hdcp displays */ - return (get_device_count(hdcp) < get_active_display_count(hdcp)) ? + /* Some MST display may choose to report the internal panel as an HDCP RX. + * To update this condition with 1(because the immediate repeater's internal + * panel is possibly not included in DEVICE_COUNT) + get_device_count(hdcp). + * Device count must be greater than or equal to tracked hdcp displays. + */ + return ((1 + get_device_count(hdcp)) < get_active_display_count(hdcp)) ? MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE : MOD_HDCP_STATUS_SUCCESS; } diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c index 549c113abcf7..a0895a7efda2 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c @@ -207,8 +207,11 @@ static inline uint8_t get_device_count(struct mod_hdcp *hdcp) static enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp) { - /* device count must be greater than or equal to tracked hdcp displays */ - return (get_device_count(hdcp) < get_active_display_count(hdcp)) ? + /* Some MST display may choose to report the internal panel as an HDCP RX. */ + /* To update this condition with 1(because the immediate repeater's internal */ + /* panel is possibly not included in DEVICE_COUNT) + get_device_count(hdcp). */ + /* Device count must be greater than or equal to tracked hdcp displays. */ + return ((1 + get_device_count(hdcp)) < get_active_display_count(hdcp)) ? MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE : MOD_HDCP_STATUS_SUCCESS; } 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 cc983f662157..4fd8bce95d84 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -82,22 +82,24 @@ struct abm_parameters { unsigned char deviation_gain; unsigned char min_knee; unsigned char max_knee; + unsigned short blRampReduction; + unsigned short blRampStart; }; static const struct abm_parameters abm_settings_config0[abm_defines_max_level] = { -// min_red max_red bright_pos dark_pos brightness_gain contrast deviation min_knee max_knee - {0xff, 0xbf, 0x20, 0x00, 0xff, 0x99, 0xb3, 0x40, 0xe0}, - {0xde, 0x85, 0x20, 0x00, 0xff, 0x90, 0xa8, 0x40, 0xdf}, - {0xb0, 0x50, 0x20, 0x00, 0xc0, 0x88, 0x78, 0x70, 0xa0}, - {0x82, 0x40, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70}, +// min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blStart blRed + {0xff, 0xbf, 0x20, 0x00, 0xff, 0x99, 0xb3, 0x40, 0xe0, 0xCCCC, 0xCCCC}, + {0xde, 0x85, 0x20, 0x00, 0xff, 0x90, 0xa8, 0x40, 0xdf, 0xCCCC, 0xCCCC}, + {0xb0, 0x50, 0x20, 0x00, 0xc0, 0x88, 0x78, 0x70, 0xa0, 0xCCCC, 0xCCCC}, + {0x82, 0x40, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, }; static const struct abm_parameters abm_settings_config1[abm_defines_max_level] = { -// min_red max_red bright_pos dark_pos brightness_gain contrast deviation min_knee max_knee - {0xf0, 0xd9, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70}, - {0xcd, 0xa5, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70}, - {0x99, 0x65, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70}, - {0x82, 0x4d, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70}, +// min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blStart blRed + {0xf0, 0xd9, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, + {0xcd, 0xa5, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, + {0x99, 0x65, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, + {0x82, 0x4d, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xCCCC, 0xCCCC}, }; static const struct abm_parameters * const abm_settings[] = { @@ -662,6 +664,7 @@ bool dmub_init_abm_config(struct resource_pool *res_pool, { struct iram_table_v_2_2 ram_table; struct abm_config_table config; + unsigned int set = params.set; bool result = false; uint32_t i, j = 0; @@ -710,6 +713,18 @@ bool dmub_init_abm_config(struct resource_pool *res_pool, config.max_knee[i] = ram_table.max_knee[i]; } + if (params.backlight_ramping_override) { + for (i = 0; i < NUM_AGGR_LEVEL; i++) { + config.blRampReduction[i] = params.backlight_ramping_reduction; + config.blRampStart[i] = params.backlight_ramping_start; + } + } else { + for (i = 0; i < NUM_AGGR_LEVEL; i++) { + config.blRampReduction[i] = abm_settings[set][i].blRampReduction; + config.blRampStart[i] = abm_settings[set][i].blRampStart; + } + } + config.min_abm_backlight = ram_table.min_abm_backlight; #if defined(CONFIG_DRM_AMD_DC_DCN) diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h index fa4728d88092..6f2eecce6baa 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h @@ -39,6 +39,7 @@ enum abm_defines { struct dmcu_iram_parameters { unsigned int *backlight_lut_array; unsigned int backlight_lut_array_size; + bool backlight_ramping_override; unsigned int backlight_ramping_reduction; unsigned int backlight_ramping_start; unsigned int min_abm_backlight; |
