diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules')
8 files changed, 324 insertions, 20 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 a1055413bade..88898935a5e6 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -23,6 +23,9 @@ * */ +#include <linux/mm.h> +#include <linux/slab.h> + #include "dc.h" #include "opp.h" #include "color_gamma.h" @@ -240,16 +243,27 @@ struct dividers { struct fixed31_32 divider3; }; -static void build_coefficients(struct gamma_coefficients *coefficients, bool is_2_4) +enum gamma_type_index { + gamma_type_index_2_4, + gamma_type_index_2_2, + gamma_type_index_2_2_flat +}; + +static void build_coefficients(struct gamma_coefficients *coefficients, enum gamma_type_index type) { - static const int32_t numerator01[] = { 31308, 180000}; - static const int32_t numerator02[] = { 12920, 4500}; - static const int32_t numerator03[] = { 55, 99}; - static const int32_t numerator04[] = { 55, 99}; - static const int32_t numerator05[] = { 2400, 2200}; + static const int32_t numerator01[] = { 31308, 180000, 0}; + static const int32_t numerator02[] = { 12920, 4500, 0}; + static const int32_t numerator03[] = { 55, 99, 0}; + static const int32_t numerator04[] = { 55, 99, 0}; + static const int32_t numerator05[] = { 2400, 2200, 2200}; uint32_t i = 0; - uint32_t index = is_2_4 == true ? 0:1; + uint32_t index = 0; + + if (type == gamma_type_index_2_2) + index = 1; + else if (type == gamma_type_index_2_2_flat) + index = 2; do { coefficients->a0[i] = dc_fixpt_from_fraction( @@ -697,7 +711,7 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq, static void build_regamma(struct pwl_float_data_ex *rgb_regamma, uint32_t hw_points_num, - const struct hw_x_point *coordinate_x, bool is_2_4) + const struct hw_x_point *coordinate_x, enum gamma_type_index type) { uint32_t i; @@ -705,7 +719,7 @@ static void build_regamma(struct pwl_float_data_ex *rgb_regamma, struct pwl_float_data_ex *rgb = rgb_regamma; const struct hw_x_point *coord_x = coordinate_x; - build_coefficients(&coeff, is_2_4); + build_coefficients(&coeff, type); i = 0; @@ -892,13 +906,13 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, static void build_degamma(struct pwl_float_data_ex *curve, uint32_t hw_points_num, - const struct hw_x_point *coordinate_x, bool is_2_4) + const struct hw_x_point *coordinate_x, enum gamma_type_index type) { uint32_t i; struct gamma_coefficients coeff; uint32_t begin_index, end_index; - build_coefficients(&coeff, is_2_4); + build_coefficients(&coeff, type); i = 0; /* X points is 2^-25 to 2^7 @@ -1558,7 +1572,8 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, output_tf->tf == TRANSFER_FUNCTION_SRGB) { if (ramp == NULL) return true; - if (ramp->is_identity || (!mapUserRamp && ramp->type == GAMMA_RGB_256)) + if ((ramp->is_logical_identity) || + (!mapUserRamp && ramp->type == GAMMA_RGB_256)) return true; } @@ -1614,7 +1629,7 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, coordinates_x, output_tf->sdr_ref_white_level); } else if (tf == TRANSFER_FUNCTION_GAMMA22 && - fs_params != NULL) { + fs_params != NULL && fs_params->skip_tm == 0) { build_freesync_hdr(rgb_regamma, MAX_HW_POINTS, coordinates_x, @@ -1627,7 +1642,9 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, build_regamma(rgb_regamma, MAX_HW_POINTS, - coordinates_x, tf == TRANSFER_FUNCTION_SRGB ? true:false); + coordinates_x, tf == TRANSFER_FUNCTION_SRGB ? gamma_type_index_2_4 : + tf == TRANSFER_FUNCTION_GAMMA22 ? + gamma_type_index_2_2_flat : gamma_type_index_2_2); } map_regamma_hw_to_x_user(ramp, coeff, rgb_user, coordinates_x, axis_x, rgb_regamma, @@ -1832,7 +1849,9 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, build_degamma(curve, MAX_HW_POINTS, coordinates_x, - tf == TRANSFER_FUNCTION_SRGB ? true : false); + tf == TRANSFER_FUNCTION_SRGB ? + gamma_type_index_2_4 : tf == TRANSFER_FUNCTION_GAMMA22 ? + gamma_type_index_2_2_flat : gamma_type_index_2_2); else if (tf == TRANSFER_FUNCTION_LINEAR) { // just copy coordinates_x into curve i = 0; @@ -1932,7 +1951,10 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, build_regamma(rgb_regamma, MAX_HW_POINTS, - coordinates_x, trans == TRANSFER_FUNCTION_SRGB ? true:false); + coordinates_x, + trans == TRANSFER_FUNCTION_SRGB ? + gamma_type_index_2_4 : trans == TRANSFER_FUNCTION_GAMMA22 ? + gamma_type_index_2_2_flat : gamma_type_index_2_2); for (i = 0; i <= MAX_HW_POINTS ; i++) { points->red[i] = rgb_regamma[i].r; points->green[i] = rgb_regamma[i].g; @@ -2002,7 +2024,8 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, kvfree(rgb_degamma); } else if (trans == TRANSFER_FUNCTION_SRGB || - trans == TRANSFER_FUNCTION_BT709) { + trans == TRANSFER_FUNCTION_BT709 || + trans == TRANSFER_FUNCTION_GAMMA22) { rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*rgb_degamma), GFP_KERNEL); @@ -2011,7 +2034,10 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, build_degamma(rgb_degamma, MAX_HW_POINTS, - coordinates_x, trans == TRANSFER_FUNCTION_SRGB ? true:false); + coordinates_x, + trans == TRANSFER_FUNCTION_SRGB ? + gamma_type_index_2_4 : trans == TRANSFER_FUNCTION_GAMMA22 ? + gamma_type_index_2_2_flat : gamma_type_index_2_2); for (i = 0; i <= MAX_HW_POINTS ; i++) { points->red[i] = rgb_degamma[i].r; points->green[i] = rgb_degamma[i].g; diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h index a6e164df090a..369953fafadf 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h @@ -79,6 +79,7 @@ struct freesync_hdr_tf_params { unsigned int max_content; // luminance in nits unsigned int min_display; // luminance in 1/10000 nits unsigned int max_display; // luminance in nits + unsigned int skip_tm; // skip tm }; void setup_x_points_distribution(void); diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 19b1eaebe484..7c20171a3b6d 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -23,6 +23,8 @@ * */ +#include <linux/slab.h> + #include "dm_services.h" #include "dc.h" #include "mod_freesync.h" diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_shared.h b/drivers/gpu/drm/amd/display/modules/inc/mod_shared.h index b711e7e6c204..b45f7d65e76a 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_shared.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_shared.h @@ -45,5 +45,65 @@ enum vrr_packet_type { PACKET_TYPE_VTEM }; +#if defined(CONFIG_DRM_AMD_DC_DCN2_0) +union lut3d_control_flags { + unsigned int raw; + struct { + unsigned int do_chroma_scale :1; + unsigned int spec_version :3; + unsigned int use_zero_display_black :1; + unsigned int use_zero_source_black :1; + unsigned int force_display_black :6; + unsigned int apply_display_gamma :1; + unsigned int exp_shaper_max :6; + unsigned int unity_3dlut :1; + unsigned int bypass_3dlut :1; + unsigned int use_3dlut :1; + unsigned int less_than_dcip3 :1; + unsigned int override_lum :1; + unsigned int use_gamut_map_lib :1; + unsigned int chromatic_adaptation_src :1; + unsigned int chromatic_adaptation_dst :1; + unsigned int do_blender_lut_degamma :1; + unsigned int reseved :4; + } bits; +}; + +enum tm_show_option_internal { + tm_show_option_internal_single_file = 0,/*flags2 not in use*/ + tm_show_option_internal_duplicate_file, /*use flags2*/ + tm_show_option_internal_duplicate_sidebyside/*use flags2*/ +}; + +enum lut3d_control_gamut_map { + lut3d_control_gamut_map_none = 0, + lut3d_control_gamut_map_tonemap, + lut3d_control_gamut_map_chto, + lut3d_control_gamut_map_chso, + lut3d_control_gamut_map_chci +}; + +enum lut3d_control_rotation_mode { + lut3d_control_rotation_mode_none = 0, + lut3d_control_rotation_mode_hue, + lut3d_control_rotation_mode_cc, + lut3d_control_rotation_mode_hue_cc +}; + +struct lut3d_settings { + unsigned char version; + union lut3d_control_flags flags; + union lut3d_control_flags flags2; + enum tm_show_option_internal option; + unsigned int min_lum;/*multiplied by 100*/ + unsigned int max_lum; + unsigned int min_lum2; + unsigned int max_lum2; + enum lut3d_control_gamut_map map; + enum lut3d_control_rotation_mode rotation; + enum lut3d_control_gamut_map map2; + enum lut3d_control_rotation_mode rotation2; +}; +#endif #endif /* MOD_SHARED_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_vmid.h b/drivers/gpu/drm/amd/display/modules/inc/mod_vmid.h new file mode 100644 index 000000000000..a3787fdf0c08 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_vmid.h @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef MOD_VMID_H_ +#define MOD_VMID_H_ + +#define MAX_VMID 16 + +#include "dc.h" + +struct mod_vmid { + int dummy; +}; + +uint8_t mod_vmid_get_for_ptb(struct mod_vmid *mod_vmid, uint64_t ptb); +void mod_vmid_reset(struct mod_vmid *mod_vmid); +struct mod_vmid *mod_vmid_create( + struct dc *dc, + unsigned int num_vmid, + struct dc_virtual_addr_space_config *va_config); + +void mod_vmid_destroy(struct mod_vmid *mod_vmid); + +#endif /* MOD_VMID_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index db06fab2ad5c..bc13c552797f 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -63,7 +63,9 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, if (stream->psr_version != 0) vscPacketRevision = 2; - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + /* Update to revision 5 for extended colorimetry support for DPCD 1.4+ */ + if (stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 && + stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) vscPacketRevision = 5; /* VSC packet not needed based on the features diff --git a/drivers/gpu/drm/amd/display/modules/power/Makefile b/drivers/gpu/drm/amd/display/modules/power/Makefile index 87851f892a52..9d1b22d35ece 100644 --- a/drivers/gpu/drm/amd/display/modules/power/Makefile +++ b/drivers/gpu/drm/amd/display/modules/power/Makefile @@ -28,4 +28,4 @@ MOD_POWER = power_helpers.o AMD_DAL_MOD_POWER = $(addprefix $(AMDDALPATH)/modules/power/,$(MOD_POWER)) #$(info ************ DAL POWER MODULE MAKEFILE ************) -AMD_DISPLAY_FILES += $(AMD_DAL_MOD_POWER)
\ No newline at end of file +AMD_DISPLAY_FILES += $(AMD_DAL_MOD_POWER) diff --git a/drivers/gpu/drm/amd/display/modules/vmid/vmid.c b/drivers/gpu/drm/amd/display/modules/vmid/vmid.c new file mode 100644 index 000000000000..f0a153704f6e --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/vmid/vmid.c @@ -0,0 +1,167 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "mod_vmid.h" + +struct core_vmid { + struct mod_vmid public; + struct dc *dc; + + unsigned int num_vmid; + unsigned int num_vmids_available; + uint64_t ptb_assigned_to_vmid[MAX_VMID]; + struct dc_virtual_addr_space_config base_config; +}; + +#define MOD_VMID_TO_CORE(mod_vmid)\ + container_of(mod_vmid, struct core_vmid, public) + +static void add_ptb_to_table(struct core_vmid *core_vmid, unsigned int vmid, uint64_t ptb) +{ + core_vmid->ptb_assigned_to_vmid[vmid] = ptb; + core_vmid->num_vmids_available--; +} + +static void clear_entry_from_vmid_table(struct core_vmid *core_vmid, unsigned int vmid) +{ + core_vmid->ptb_assigned_to_vmid[vmid] = 0; + core_vmid->num_vmids_available++; +} + +static void evict_vmids(struct core_vmid *core_vmid) +{ + int i; + uint16_t ord = dc_get_vmid_use_vector(core_vmid->dc); + + // At this point any positions with value 0 are unused vmids, evict them + for (i = 1; i < core_vmid->num_vmid; i++) { + if (ord & (1u << i)) + clear_entry_from_vmid_table(core_vmid, i); + } +} + +// Return value of -1 indicates vmid table unitialized or ptb dne in the table +static int get_existing_vmid_for_ptb(struct core_vmid *core_vmid, uint64_t ptb) +{ + int i; + + for (i = 0; i < core_vmid->num_vmid; i++) { + if (core_vmid->ptb_assigned_to_vmid[i] == ptb) + return i; + } + + return -1; +} + +// Expected to be called only when there's an available vmid +static int get_next_available_vmid(struct core_vmid *core_vmid) +{ + int i; + + for (i = 1; i < core_vmid->num_vmid; i++) { + if (core_vmid->ptb_assigned_to_vmid[i] == 0) + return i; + } + + return -1; +} + +uint8_t mod_vmid_get_for_ptb(struct mod_vmid *mod_vmid, uint64_t ptb) +{ + struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid); + unsigned int vmid = 0; + + // Physical address gets vmid 0 + if (ptb == 0) + return 0; + + vmid = get_existing_vmid_for_ptb(core_vmid, ptb); + + if (vmid == -1) { + struct dc_virtual_addr_space_config va_config = core_vmid->base_config; + + va_config.page_table_base_addr = ptb; + + if (core_vmid->num_vmids_available == 0) + evict_vmids(core_vmid); + + vmid = get_next_available_vmid(core_vmid); + add_ptb_to_table(core_vmid, vmid, ptb); + + dc_setup_vm_context(core_vmid->dc, &va_config, vmid); + } + + return vmid; +} + +void mod_vmid_reset(struct mod_vmid *mod_vmid) +{ + struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid); + + core_vmid->num_vmids_available = core_vmid->num_vmid - 1; + memset(core_vmid->ptb_assigned_to_vmid, 0, sizeof(core_vmid->ptb_assigned_to_vmid[0]) * MAX_VMID); +} + +struct mod_vmid *mod_vmid_create( + struct dc *dc, + unsigned int num_vmid, + struct dc_virtual_addr_space_config *va_config) +{ + struct core_vmid *core_vmid; + + if (num_vmid <= 1) + goto fail_no_vm_ctx; + + if (dc == NULL) + goto fail_dc_null; + + core_vmid = kzalloc(sizeof(struct core_vmid), GFP_KERNEL); + + if (core_vmid == NULL) + goto fail_alloc_context; + + core_vmid->dc = dc; + core_vmid->num_vmid = num_vmid; + core_vmid->num_vmids_available = num_vmid - 1; + core_vmid->base_config = *va_config; + + memset(core_vmid->ptb_assigned_to_vmid, 0, sizeof(core_vmid->ptb_assigned_to_vmid[0]) * MAX_VMID); + + return &core_vmid->public; + +fail_no_vm_ctx: +fail_alloc_context: +fail_dc_null: + return NULL; +} + +void mod_vmid_destroy(struct mod_vmid *mod_vmid) +{ + if (mod_vmid != NULL) { + struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid); + + kfree(core_vmid); + } +} |