aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/modules
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules')
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c62
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.h1
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c2
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_shared.h60
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_vmid.h46
-rw-r--r--drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c4
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/modules/vmid/vmid.c167
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);
+ }
+}