diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display')
97 files changed, 3095 insertions, 2002 deletions
diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile index 8ba37dd9cf7f..c27c81cdeed3 100644 --- a/drivers/gpu/drm/amd/display/Makefile +++ b/drivers/gpu/drm/amd/display/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the DAL (Display Abstract Layer), which is a sub-component # of the AMDGPU drm driver. # It provides the HW control for display related functionalities. diff --git a/drivers/gpu/drm/amd/display/TODO b/drivers/gpu/drm/amd/display/TODO index 46464678f2b3..357d59648401 100644 --- a/drivers/gpu/drm/amd/display/TODO +++ b/drivers/gpu/drm/amd/display/TODO @@ -105,3 +105,6 @@ useless with filtering output. dynamic debug printing might be an option. 20. Use kernel i2c device to program HDMI retimer. Some boards have an HDMI retimer that we need to program to pass PHY compliance. Currently that's bypassing the i2c device and goes directly to HW. This should be changed. + +21. Remove vector.c from dc/basics. It's used in DDC code which can probably +be simplified enough to no longer need a vector implementation. diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile index 4699e47aa76b..2b72009844f8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'dm' sub-component of DAL. # It provides the control and status of dm blocks. diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ccbf10e3bbb6..1ce4c98385e3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -431,9 +431,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.dc = dc_create(&init_data); if (adev->dm.dc) { - DRM_INFO("Display Core initialized!\n"); + DRM_INFO("Display Core initialized with v%s!\n", DC_VER); } else { - DRM_INFO("Display Core failed to initialize!\n"); + DRM_INFO("Display Core failed to initialize with v%s!\n", DC_VER); goto error; } @@ -2351,7 +2351,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, const struct dm_connector_state *dm_state) { struct drm_display_mode *preferred_mode = NULL; - const struct drm_connector *drm_connector; + struct drm_connector *drm_connector; struct dc_stream_state *stream = NULL; struct drm_display_mode mode = *drm_mode; bool native_mode_found = false; @@ -2370,11 +2370,13 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (!aconnector->dc_sink) { /* - * Exclude MST from creating fake_sink - * TODO: need to enable MST into fake_sink feature + * Create dc_sink when necessary to MST + * Don't apply fake_sink to MST */ - if (aconnector->mst_port) - goto stream_create_fail; + if (aconnector->mst_port) { + dm_dp_mst_dc_sink_create(drm_connector); + goto mst_dc_sink_create_done; + } if (create_fake_sink(aconnector)) goto stream_create_fail; @@ -2425,6 +2427,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, stream_create_fail: dm_state_null: drm_connector_null: +mst_dc_sink_create_done: return stream; } @@ -2725,8 +2728,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) }; struct edid *edid; - if (!aconnector->base.edid_blob_ptr || - !aconnector->base.edid_blob_ptr->data) { + if (!aconnector->base.edid_blob_ptr) { DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n", aconnector->base.name); @@ -4514,18 +4516,15 @@ static int dm_update_crtcs_state(struct dc *dc, __func__, acrtc->base.base.id); break; } - } - if (enable && dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && - dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) { - - new_crtc_state->mode_changed = false; - - DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", - new_crtc_state->mode_changed); + if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && + dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) { + new_crtc_state->mode_changed = false; + DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", + new_crtc_state->mode_changed); + } } - if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) goto next_crtc; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 8a1e4f5dbd64..2faa77a7eeda 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -189,6 +189,8 @@ struct amdgpu_dm_connector { struct mutex hpd_lock; bool fake_enable; + + bool mst_connected; }; #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 707928b88448..f3d87f418d2e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -180,6 +180,42 @@ static int dm_connector_update_modes(struct drm_connector *connector, return drm_add_edid_modes(connector, edid); } +void dm_dp_mst_dc_sink_create(struct drm_connector *connector) +{ + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + struct edid *edid; + struct dc_sink *dc_sink; + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; + + edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); + + if (!edid) { + drm_mode_connector_update_edid_property( + &aconnector->base, + NULL); + return; + } + + aconnector->edid = edid; + + dc_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)aconnector->edid, + (aconnector->edid->extensions + 1) * EDID_LENGTH, + &init_params); + + dc_sink->priv = aconnector; + aconnector->dc_sink = dc_sink; + + amdgpu_dm_add_sink_to_freesync_module( + connector, aconnector->edid); + + drm_mode_connector_update_edid_property( + &aconnector->base, aconnector->edid); +} + static int dm_dp_mst_get_modes(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); @@ -306,6 +342,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_mode_connector_set_path_property(connector, pathprop); drm_connector_list_iter_end(&conn_iter); + aconnector->mst_connected = true; return &aconnector->base; } } @@ -358,6 +395,8 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, */ amdgpu_dm_connector_funcs_reset(connector); + aconnector->mst_connected = true; + DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n", aconnector, connector->base.id, aconnector->mst_port); @@ -389,6 +428,8 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_mode_connector_update_edid_property( &aconnector->base, NULL); + + aconnector->mst_connected = false; } static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) @@ -399,10 +440,18 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) drm_kms_helper_hotplug_event(dev); } +static void dm_dp_mst_link_status_reset(struct drm_connector *connector) +{ + mutex_lock(&connector->dev->mode_config.mutex); + drm_mode_connector_set_link_status_property(connector, DRM_MODE_LINK_STATUS_BAD); + mutex_unlock(&connector->dev->mode_config.mutex); +} + static void dm_dp_mst_register_connector(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); if (adev->mode_info.rfbdev) drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); @@ -411,6 +460,8 @@ static void dm_dp_mst_register_connector(struct drm_connector *connector) drm_connector_register(connector); + if (aconnector->mst_connected) + dm_dp_mst_link_status_reset(connector); } static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 2da851b40042..8cf51da26657 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -31,5 +31,6 @@ struct amdgpu_dm_connector; void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, struct amdgpu_dm_connector *aconnector); +void dm_dp_mst_dc_sink_create(struct drm_connector *connector); #endif diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 4f83e3011743..aed538a4d1ba 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for Display Core (dc) component. # diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile index 43c5ccdeeb72..bca33bd9a0d2 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/Makefile +++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile @@ -1,9 +1,30 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'utils' sub-component of DAL. # It provides the general basic services required by other DAL # subcomponents. -BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \ +BASICS = conversion.o fixpt31_32.o fixpt32_32.o \ logger.o log_helpers.o vector.o AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index 23c9a0ec0181..310964915a83 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -46,7 +46,7 @@ uint16_t fixed_point_to_int_frac( arg)); if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) - numerator = (uint16_t)dal_fixed31_32_floor( + numerator = (uint16_t)dal_fixed31_32_round( dal_fixed31_32_mul_int( arg, divisor)); diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 26936892c6f5..011a97f82fb6 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -554,6 +554,22 @@ static inline uint32_t ux_dy( return result | fractional_part; } +static inline uint32_t clamp_ux_dy( + int64_t value, + uint32_t integer_bits, + uint32_t fractional_bits, + uint32_t min_clamp) +{ + uint32_t truncated_val = ux_dy(value, integer_bits, fractional_bits); + + if (value >= (1LL << (integer_bits + FIXED31_32_BITS_PER_FRACTIONAL_PART))) + return (1 << (integer_bits + fractional_bits)) - 1; + else if (truncated_val > min_clamp) + return truncated_val; + else + return min_clamp; +} + uint32_t dal_fixed31_32_u2d19( struct fixed31_32 arg) { @@ -565,3 +581,15 @@ uint32_t dal_fixed31_32_u0d19( { return ux_dy(arg.value, 0, 19); } + +uint32_t dal_fixed31_32_clamp_u0d14( + struct fixed31_32 arg) +{ + return clamp_ux_dy(arg.value, 0, 14, 1); +} + +uint32_t dal_fixed31_32_clamp_u0d10( + struct fixed31_32 arg) +{ + return clamp_ux_dy(arg.value, 0, 10, 1); +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c deleted file mode 100644 index 147822545252..000000000000 --- a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2012-15 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 "dm_services.h" -#include "include/grph_object_id.h" - -static bool dal_graphics_object_id_is_valid(struct graphics_object_id id) -{ - bool rc = true; - - switch (id.type) { - case OBJECT_TYPE_UNKNOWN: - rc = false; - break; - case OBJECT_TYPE_GPU: - case OBJECT_TYPE_ENGINE: - /* do NOT check for id.id == 0 */ - if (id.enum_id == ENUM_ID_UNKNOWN) - rc = false; - break; - default: - if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) - rc = false; - break; - } - - return rc; -} - -bool dal_graphics_object_id_is_equal( - struct graphics_object_id id1, - struct graphics_object_id id2) -{ - if (false == dal_graphics_object_id_is_valid(id1)) { - dm_output_to_console( - "%s: Warning: comparing invalid object 'id1'!\n", __func__); - return false; - } - - if (false == dal_graphics_object_id_is_valid(id2)) { - dm_output_to_console( - "%s: Warning: comparing invalid object 'id2'!\n", __func__); - return false; - } - - if (id1.id == id2.id && id1.enum_id == id2.enum_id - && id1.type == id2.type) - return true; - - return false; -} - - diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index 6ec815dce9cc..239e86bbec5a 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'bios' sub-component of DAL. # It provides the parsing and executing controls for atom bios image. diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 86e6438c5cf3..c00e405b63e8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -190,6 +190,7 @@ static struct graphics_object_id bios_parser_get_connector_id( struct bios_parser *bp = BP_FROM_DCB(dcb); struct graphics_object_id object_id = dal_graphics_object_id_init( 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + uint16_t id; uint32_t connector_table_offset = bp->object_info_tbl_offset + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); @@ -197,12 +198,19 @@ static struct graphics_object_id bios_parser_get_connector_id( ATOM_OBJECT_TABLE *tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset); - if (tbl && tbl->ucNumberOfObjects > i) { - const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID); + if (!tbl) { + dm_error("Can't get connector table from atom bios.\n"); + return object_id; + } - object_id = object_id_from_bios_object_id(id); + if (tbl->ucNumberOfObjects <= i) { + dm_error("Can't find connector id %d in connector table of size %d.\n", + i, tbl->ucNumberOfObjects); + return object_id; } + id = le16_to_cpu(tbl->asObjects[i].usObjectID); + object_id = object_id_from_bios_object_id(id); return object_id; } @@ -2254,6 +2262,52 @@ static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, return BP_RESULT_OK; } +static bool dal_graphics_object_id_is_valid(struct graphics_object_id id) +{ + bool rc = true; + + switch (id.type) { + case OBJECT_TYPE_UNKNOWN: + rc = false; + break; + case OBJECT_TYPE_GPU: + case OBJECT_TYPE_ENGINE: + /* do NOT check for id.id == 0 */ + if (id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + default: + if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + } + + return rc; +} + +static bool dal_graphics_object_id_is_equal( + struct graphics_object_id id1, + struct graphics_object_id id2) +{ + if (false == dal_graphics_object_id_is_valid(id1)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id1'!\n", __func__); + return false; + } + + if (false == dal_graphics_object_id_is_valid(id2)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id2'!\n", __func__); + return false; + } + + if (id1.id == id2.id && id1.enum_id == id2.enum_id + && id1.type == id2.type) + return true; + + return false; +} + static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, struct graphics_object_id id) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 3f7b2dabc2b0..1aefed8cf98b 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -387,6 +387,7 @@ static void init_transmitter_control(struct bios_parser *bp) bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; break; default: + dm_error("Don't have transmitter_control for v%d\n", crev); bp->cmd_tbl.transmitter_control = NULL; break; } @@ -910,6 +911,8 @@ static void init_set_pixel_clock(struct bios_parser *bp) bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; break; default: + dm_error("Don't have set_pixel_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)); bp->cmd_tbl.set_pixel_clock = NULL; break; } @@ -1227,6 +1230,8 @@ static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp) enable_spread_spectrum_on_ppll_v3; break; default: + dm_error("Don't have enable_spread_spectrum_on_ppll for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)); bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL; break; } @@ -1422,6 +1427,8 @@ static void init_adjust_display_pll(struct bios_parser *bp) bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3; break; default: + dm_error("Don't have adjust_display_pll for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)); bp->cmd_tbl.adjust_display_pll = NULL; break; } @@ -1695,6 +1702,8 @@ static void init_set_crtc_timing(struct bios_parser *bp) set_crtc_using_dtd_timing_v3; break; default: + dm_error("Don't have set_crtc_timing for dtd v%d\n", + dtd_version); bp->cmd_tbl.set_crtc_timing = NULL; break; } @@ -1704,6 +1713,8 @@ static void init_set_crtc_timing(struct bios_parser *bp) bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1; break; default: + dm_error("Don't have set_crtc_timing for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)); bp->cmd_tbl.set_crtc_timing = NULL; break; } @@ -1890,6 +1901,8 @@ static void init_select_crtc_source(struct bios_parser *bp) bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; break; default: + dm_error("Don't select_crtc_source enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)); bp->cmd_tbl.select_crtc_source = NULL; break; } @@ -1997,6 +2010,8 @@ static void init_enable_crtc(struct bios_parser *bp) bp->cmd_tbl.enable_crtc = enable_crtc_v1; break; default: + dm_error("Don't have enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)); bp->cmd_tbl.enable_crtc = NULL; break; } @@ -2103,6 +2118,8 @@ static void init_program_clock(struct bios_parser *bp) bp->cmd_tbl.program_clock = program_clock_v6; break; default: + dm_error("Don't have program_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)); bp->cmd_tbl.program_clock = NULL; break; } @@ -2324,6 +2341,8 @@ static void init_enable_disp_power_gating( enable_disp_power_gating_v2_1; break; default: + dm_error("Don't enable_disp_power_gating enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)); bp->cmd_tbl.enable_disp_power_gating = NULL; break; } @@ -2371,6 +2390,8 @@ static void init_set_dce_clock(struct bios_parser *bp) bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; break; default: + dm_error("Don't have set_dce_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)); bp->cmd_tbl.set_dce_clock = NULL; break; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index ba68693758a7..946db12388d6 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -118,6 +118,7 @@ static void init_dig_encoder_control(struct bios_parser *bp) bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; break; default: + dm_error("Don't have dig_encoder_control for v%d\n", version); bp->cmd_tbl.dig_encoder_control = NULL; break; } @@ -205,6 +206,7 @@ static void init_transmitter_control(struct bios_parser *bp) bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; break; default: + dm_error("Don't have transmitter_control for v%d\n", crev); bp->cmd_tbl.transmitter_control = NULL; break; } @@ -268,6 +270,8 @@ static void init_set_pixel_clock(struct bios_parser *bp) bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; break; default: + dm_error("Don't have set_pixel_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)); bp->cmd_tbl.set_pixel_clock = NULL; break; } @@ -379,6 +383,7 @@ static void init_set_crtc_timing(struct bios_parser *bp) set_crtc_using_dtd_timing_v3; break; default: + dm_error("Don't have set_crtc_timing for v%d\n", dtd_version); bp->cmd_tbl.set_crtc_timing = NULL; break; } @@ -498,6 +503,8 @@ static void init_select_crtc_source(struct bios_parser *bp) bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; break; default: + dm_error("Don't select_crtc_source enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)); bp->cmd_tbl.select_crtc_source = NULL; break; } @@ -565,6 +572,8 @@ static void init_enable_crtc(struct bios_parser *bp) bp->cmd_tbl.enable_crtc = enable_crtc_v1; break; default: + dm_error("Don't have enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)); bp->cmd_tbl.enable_crtc = NULL; break; } @@ -661,6 +670,8 @@ static void init_enable_disp_power_gating( enable_disp_power_gating_v2_1; break; default: + dm_error("Don't enable_disp_power_gating enable_crtc for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)); bp->cmd_tbl.enable_disp_power_gating = NULL; break; } @@ -710,6 +721,8 @@ static void init_set_dce_clock(struct bios_parser *bp) bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; break; default: + dm_error("Don't have set_dce_clock for v%d\n", + BIOS_CMD_TABLE_PARA_REVISION(setdceclock)); bp->cmd_tbl.set_dce_clock = NULL; break; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 41ef35995b02..7959e382ed28 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'calcs' sub-component of DAL. # It calculates Bandwidth and Watermarks values for HW programming # diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 6347712db834..2e11fac2a63d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -29,6 +29,15 @@ #include "core_types.h" #include "dal_asic_id.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + /******************************************************************************* * Private Functions ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index 626f9cf8aad2..5e2ea12fbb73 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -27,6 +27,15 @@ #include "dcn_calc_auto.h" #include "dcn_calc_math.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + /*REVISION#250*/ void scaler_settings_calculation(struct dcn_bw_internal_vars *v) { @@ -773,11 +782,11 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->dst_y_after_scaler = 0.0; } v->time_calc = 24.0 / v->projected_dcfclk_deep_sleep; - v->v_update_offset[k] =dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->v_update_offset[k][j] = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); v->total_repeater_delay = v->max_inter_dcn_tile_repeaters * (2.0 / (v->required_dispclk[i][j] / (j + 1)) + 3.0 / v->required_dispclk[i][j]); - v->v_update_width[k] = (14.0 / v->projected_dcfclk_deep_sleep + 12.0 / (v->required_dispclk[i][j] / (j + 1)) + v->total_repeater_delay) * v->pixel_clock[k]; - v->v_ready_offset[k] =dcn_bw_max2(150.0 / (v->required_dispclk[i][j] / (j + 1)), v->total_repeater_delay + 20.0 / v->projected_dcfclk_deep_sleep + 10.0 / (v->required_dispclk[i][j] / (j + 1))) * v->pixel_clock[k]; - v->time_setup = (v->v_update_offset[k] + v->v_update_width[k] + v->v_ready_offset[k]) / v->pixel_clock[k]; + v->v_update_width[k][j] = (14.0 / v->projected_dcfclk_deep_sleep + 12.0 / (v->required_dispclk[i][j] / (j + 1)) + v->total_repeater_delay) * v->pixel_clock[k]; + v->v_ready_offset[k][j] = dcn_bw_max2(150.0 / (v->required_dispclk[i][j] / (j + 1)), v->total_repeater_delay + 20.0 / v->projected_dcfclk_deep_sleep + 10.0 / (v->required_dispclk[i][j] / (j + 1))) * v->pixel_clock[k]; + v->time_setup = (v->v_update_offset[k][j] + v->v_update_width[k][j] + v->v_ready_offset[k][j]) / v->pixel_clock[k]; v->extra_latency = v->urgent_round_trip_and_out_of_order_latency_per_state[i] + (v->total_number_of_active_dpp[i][j] * v->pixel_chunk_size_in_kbyte + v->total_number_of_dcc_active_dpp[i][j] * v->meta_chunk_size) * 1024.0 / v->return_bw_per_state[i]; if (v->pte_enable == dcn_bw_yes) { v->extra_latency = v->extra_latency + v->total_number_of_active_dpp[i][j] * v->pte_chunk_size * 1024.0 / v->return_bw_per_state[i]; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c index b6abe0f3bb15..7600a4a4abc7 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -25,37 +25,44 @@ #include "dcn_calc_math.h" +#define isNaN(number) ((number) != (number)) + +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + float dcn_bw_mod(const float arg1, const float arg2) { - if (arg1 != arg1) + if (isNaN(arg1)) return arg2; - if (arg2 != arg2) + if (isNaN(arg2)) return arg1; return arg1 - arg1 * ((int) (arg1 / arg2)); } float dcn_bw_min2(const float arg1, const float arg2) { - if (arg1 != arg1) + if (isNaN(arg1)) return arg2; - if (arg2 != arg2) + if (isNaN(arg2)) return arg1; return arg1 < arg2 ? arg1 : arg2; } unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) { - if (arg1 != arg1) - return arg2; - if (arg2 != arg2) - return arg1; return arg1 > arg2 ? arg1 : arg2; } float dcn_bw_max2(const float arg1, const float arg2) { - if (arg1 != arg1) + if (isNaN(arg1)) return arg2; - if (arg2 != arg2) + if (isNaN(arg2)) return arg1; return arg1 > arg2 ? arg1 : arg2; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index a4fbca34bcdf..331891c2c71a 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -33,6 +33,15 @@ #include "dcn10/dcn10_resource.h" #include "dcn_calc_math.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + /* Defaults from spreadsheet rev#247 */ const struct dcn_soc_bounding_box dcn10_soc_defaults = { /* latencies */ @@ -878,6 +887,17 @@ bool dcn_validate_bandwidth( + pipe->bottom_pipe->plane_res.scl_data.recout.width; } + if (pipe->plane_state->rotation % 2 == 0) { + ASSERT(pipe->plane_res.scl_data.ratios.horz.value != dal_fixed31_32_one.value + || v->scaler_rec_out_width[input_idx] == v->viewport_width[input_idx]); + ASSERT(pipe->plane_res.scl_data.ratios.vert.value != dal_fixed31_32_one.value + || v->scaler_recout_height[input_idx] == v->viewport_height[input_idx]); + } else { + ASSERT(pipe->plane_res.scl_data.ratios.horz.value != dal_fixed31_32_one.value + || v->scaler_recout_height[input_idx] == v->viewport_width[input_idx]); + ASSERT(pipe->plane_res.scl_data.ratios.vert.value != dal_fixed31_32_one.value + || v->scaler_rec_out_width[input_idx] == v->viewport_height[input_idx]); + } v->dcc_enable[input_idx] = pipe->plane_state->dcc.enable ? dcn_bw_yes : dcn_bw_no; v->source_pixel_format[input_idx] = tl_pixel_format_to_bw_defs( pipe->plane_state->format); @@ -888,6 +908,15 @@ bool dcn_validate_bandwidth( v->override_vta_ps[input_idx] = pipe->plane_res.scl_data.taps.v_taps; v->override_hta_pschroma[input_idx] = pipe->plane_res.scl_data.taps.h_taps_c; v->override_vta_pschroma[input_idx] = pipe->plane_res.scl_data.taps.v_taps_c; + /* + * Spreadsheet doesn't handle taps_c is one properly, + * need to force Chroma to always be scaled to pass + * bandwidth validation. + */ + if (v->override_hta_pschroma[input_idx] == 1) + v->override_hta_pschroma[input_idx] = 2; + if (v->override_vta_pschroma[input_idx] == 1) + v->override_vta_pschroma[input_idx] = 2; v->source_scan[input_idx] = (pipe->plane_state->rotation % 2) ? dcn_bw_vert : dcn_bw_hor; } if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) @@ -985,9 +1014,9 @@ bool dcn_validate_bandwidth( if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) continue; - pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; - pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; - pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; + pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; + pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; + pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total; @@ -1026,9 +1055,9 @@ bool dcn_validate_bandwidth( TIMING_3D_FORMAT_SIDE_BY_SIDE))) { if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { /* update previously split pipe */ - hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; - hsplit_pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; - hsplit_pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; + hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; + hsplit_pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; + hsplit_pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx][v->dpp_per_plane[input_idx] == 2 ? 1 : 0]; hsplit_pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; hsplit_pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total; @@ -1556,35 +1585,6 @@ void dcn_bw_sync_calcs_and_dml(struct dc *dc) dc->dcn_ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one, dc->dcn_ip->bug_forcing_luma_and_chroma_request_to_same_size_fixed, dc->dcn_ip->dcfclk_cstate_latency); - dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc->socclk; - dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc->socclk; - dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc->socclk; - dc->dml.soc.vmax.socclk_mhz = dc->dcn_soc->socclk; - - dc->dml.soc.vmin.dcfclk_mhz = dc->dcn_soc->dcfclkv_min0p65; - dc->dml.soc.vmid.dcfclk_mhz = dc->dcn_soc->dcfclkv_mid0p72; - dc->dml.soc.vnom.dcfclk_mhz = dc->dcn_soc->dcfclkv_nom0p8; - dc->dml.soc.vmax.dcfclk_mhz = dc->dcn_soc->dcfclkv_max0p9; - - dc->dml.soc.vmin.dispclk_mhz = dc->dcn_soc->max_dispclk_vmin0p65; - dc->dml.soc.vmid.dispclk_mhz = dc->dcn_soc->max_dispclk_vmid0p72; - dc->dml.soc.vnom.dispclk_mhz = dc->dcn_soc->max_dispclk_vnom0p8; - dc->dml.soc.vmax.dispclk_mhz = dc->dcn_soc->max_dispclk_vmax0p9; - - dc->dml.soc.vmin.dppclk_mhz = dc->dcn_soc->max_dppclk_vmin0p65; - dc->dml.soc.vmid.dppclk_mhz = dc->dcn_soc->max_dppclk_vmid0p72; - dc->dml.soc.vnom.dppclk_mhz = dc->dcn_soc->max_dppclk_vnom0p8; - dc->dml.soc.vmax.dppclk_mhz = dc->dcn_soc->max_dppclk_vmax0p9; - - dc->dml.soc.vmin.phyclk_mhz = dc->dcn_soc->phyclkv_min0p65; - dc->dml.soc.vmid.phyclk_mhz = dc->dcn_soc->phyclkv_mid0p72; - dc->dml.soc.vnom.phyclk_mhz = dc->dcn_soc->phyclkv_nom0p8; - dc->dml.soc.vmax.phyclk_mhz = dc->dcn_soc->phyclkv_max0p9; - - dc->dml.soc.vmin.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65; - dc->dml.soc.vmid.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72; - dc->dml.soc.vnom.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8; - dc->dml.soc.vmax.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9; dc->dml.soc.sr_exit_time_us = dc->dcn_soc->sr_exit_time; dc->dml.soc.sr_enter_plus_exit_time_us = dc->dcn_soc->sr_enter_plus_exit_time; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d1488d5ee028..35e84ed031de 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -283,19 +283,17 @@ static bool construct(struct dc *dc, const struct dc_init_data *init_params) { struct dal_logger *logger; - struct dc_context *dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL); - struct bw_calcs_dceip *dc_dceip = kzalloc(sizeof(*dc_dceip), - GFP_KERNEL); - struct bw_calcs_vbios *dc_vbios = kzalloc(sizeof(*dc_vbios), - GFP_KERNEL); + struct dc_context *dc_ctx; + struct bw_calcs_dceip *dc_dceip; + struct bw_calcs_vbios *dc_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct dcn_soc_bounding_box *dcn_soc = kzalloc(sizeof(*dcn_soc), - GFP_KERNEL); - struct dcn_ip_params *dcn_ip = kzalloc(sizeof(*dcn_ip), GFP_KERNEL); + struct dcn_soc_bounding_box *dcn_soc; + struct dcn_ip_params *dcn_ip; #endif enum dce_version dc_version = DCE_VERSION_UNKNOWN; + dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL); if (!dc_dceip) { dm_error("%s: failed to create dceip\n", __func__); goto fail; @@ -303,6 +301,7 @@ static bool construct(struct dc *dc, dc->bw_dceip = dc_dceip; + dc_vbios = kzalloc(sizeof(*dc_vbios), GFP_KERNEL); if (!dc_vbios) { dm_error("%s: failed to create vbios\n", __func__); goto fail; @@ -310,6 +309,7 @@ static bool construct(struct dc *dc, dc->bw_vbios = dc_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 + dcn_soc = kzalloc(sizeof(*dcn_soc), GFP_KERNEL); if (!dcn_soc) { dm_error("%s: failed to create dcn_soc\n", __func__); goto fail; @@ -317,6 +317,7 @@ static bool construct(struct dc *dc, dc->dcn_soc = dcn_soc; + dcn_ip = kzalloc(sizeof(*dcn_ip), GFP_KERNEL); if (!dcn_ip) { dm_error("%s: failed to create dcn_ip\n", __func__); goto fail; @@ -325,11 +326,18 @@ static bool construct(struct dc *dc, dc->dcn_ip = dcn_ip; #endif + dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL); if (!dc_ctx) { dm_error("%s: failed to create ctx\n", __func__); goto fail; } + dc_ctx->cgs_device = init_params->cgs_device; + dc_ctx->driver_context = init_params->driver; + dc_ctx->dc = dc; + dc_ctx->asic_id = init_params->asic_id; + dc->ctx = dc_ctx; + dc->current_state = dc_create_state(); if (!dc->current_state) { @@ -337,11 +345,6 @@ static bool construct(struct dc *dc, goto fail; } - dc_ctx->cgs_device = init_params->cgs_device; - dc_ctx->driver_context = init_params->driver; - dc_ctx->dc = dc; - dc_ctx->asic_id = init_params->asic_id; - /* Create logger */ logger = dal_logger_create(dc_ctx, init_params->log_mask); @@ -351,11 +354,10 @@ static bool construct(struct dc *dc, goto fail; } dc_ctx->logger = logger; - dc->ctx = dc_ctx; - dc->ctx->dce_environment = init_params->dce_environment; + dc_ctx->dce_environment = init_params->dce_environment; dc_version = resource_parse_asic_id(init_params->asic_id); - dc->ctx->dce_version = dc_version; + dc_ctx->dce_version = dc_version; #if defined(CONFIG_DRM_AMD_DC_FBC) dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr; @@ -578,7 +580,7 @@ static void program_timing_sync( for (j = 0; j < group_size; j++) { struct pipe_ctx *temp; - if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { + if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { if (j == 0) break; @@ -591,7 +593,7 @@ static void program_timing_sync( /* remove any other unblanked pipes as they have already been synced */ for (j = j + 1; j < group_size; j++) { - if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { + if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { group_size--; pipe_set[j] = pipe_set[group_size]; j--; @@ -786,6 +788,8 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]); } + dc->optimized_required = false; + /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) dc->hwss.set_bandwidth(dc, context, dc->ctx->dce_version < DCN_VERSION_1_0); @@ -981,6 +985,11 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) update_flags->bits.per_pixel_alpha_change = 1; + if (u->plane_info->dcc.enable != u->surface->dcc.enable + || u->plane_info->dcc.grph.independent_64b_blks != u->surface->dcc.grph.independent_64b_blks + || u->plane_info->dcc.grph.meta_pitch != u->surface->dcc.grph.meta_pitch) + update_flags->bits.dcc_change = 1; + if (pixel_format_to_bpp(u->plane_info->format) != pixel_format_to_bpp(u->surface->format)) /* different bytes per element will require full bandwidth @@ -1178,12 +1187,6 @@ static void commit_planes_for_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FULL) { dc->hwss.set_bandwidth(dc, context, false); context_clock_trace(dc, context); - - for (j = 0; j < dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx); - } } if (surface_count == 0) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 2e509382935f..1babac07bcc9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -1,4 +1,26 @@ /* + * Copyright 2017 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. + * + */ +/* * dc_debug.c * * Created on: Nov 3, 2016 diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 71993d5983bf..ebc96b720083 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -28,6 +28,8 @@ #include "timing_generator.h" #include "hw_sequencer.h" +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + /* used as index in array of black_color_format */ enum black_color_format { BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, @@ -38,6 +40,15 @@ enum black_color_format { BLACK_COLOR_FORMAT_DEBUG, }; +enum dc_color_space_type { + COLOR_SPACE_RGB_TYPE, + COLOR_SPACE_RGB_LIMITED_TYPE, + COLOR_SPACE_YCBCR601_TYPE, + COLOR_SPACE_YCBCR709_TYPE, + COLOR_SPACE_YCBCR601_LIMITED_TYPE, + COLOR_SPACE_YCBCR709_LIMITED_TYPE +}; + static const struct tg_color black_color_format[] = { /* BlackColorFormat_RGB_FullRange */ {0, 0, 0}, @@ -53,6 +64,140 @@ static const struct tg_color black_color_format[] = { {0xff, 0xff, 0}, }; +struct out_csc_color_matrix_type { + enum dc_color_space_type color_space_type; + uint16_t regval[12]; +}; + +static const struct out_csc_color_matrix_type output_csc_matrix[] = { + { COLOR_SPACE_RGB_TYPE, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + { COLOR_SPACE_RGB_LIMITED_TYPE, + { 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} }, + { COLOR_SPACE_YCBCR601_TYPE, + { 0xE04, 0xF444, 0xFDB9, 0x1004, 0x831, 0x1016, 0x320, 0x201, 0xFB45, + 0xF6B7, 0xE04, 0x1004} }, + { COLOR_SPACE_YCBCR709_TYPE, + { 0xE04, 0xF345, 0xFEB7, 0x1004, 0x5D3, 0x1399, 0x1FA, + 0x201, 0xFCCA, 0xF533, 0xE04, 0x1004} }, + + /* TODO: correct values below */ + { COLOR_SPACE_YCBCR601_LIMITED_TYPE, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, + { COLOR_SPACE_YCBCR709_LIMITED_TYPE, + { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +}; + +static bool is_rgb_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_SRGB || + color_space == COLOR_SPACE_XR_RGB || + color_space == COLOR_SPACE_MSREF_SCRGB || + color_space == COLOR_SPACE_2020_RGB_FULLRANGE || + color_space == COLOR_SPACE_ADOBERGB || + color_space == COLOR_SPACE_DCIP3 || + color_space == COLOR_SPACE_DOLBYVISION) + ret = true; + return ret; +} + +static bool is_rgb_limited_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_SRGB_LIMITED || + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) + ret = true; + return ret; +} + +static bool is_ycbcr601_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR601 || + color_space == COLOR_SPACE_XV_YCC_601) + ret = true; + return ret; +} + +static bool is_ycbcr601_limited_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR601_LIMITED) + ret = true; + return ret; +} + +static bool is_ycbcr709_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR709 || + color_space == COLOR_SPACE_XV_YCC_709) + ret = true; + return ret; +} + +static bool is_ycbcr709_limited_type( + enum dc_color_space color_space) +{ + bool ret = false; + + if (color_space == COLOR_SPACE_YCBCR709_LIMITED) + ret = true; + return ret; +} +enum dc_color_space_type get_color_space_type(enum dc_color_space color_space) +{ + enum dc_color_space_type type = COLOR_SPACE_RGB_TYPE; + + if (is_rgb_type(color_space)) + type = COLOR_SPACE_RGB_TYPE; + else if (is_rgb_limited_type(color_space)) + type = COLOR_SPACE_RGB_LIMITED_TYPE; + else if (is_ycbcr601_type(color_space)) + type = COLOR_SPACE_YCBCR601_TYPE; + else if (is_ycbcr709_type(color_space)) + type = COLOR_SPACE_YCBCR709_TYPE; + else if (is_ycbcr601_limited_type(color_space)) + type = COLOR_SPACE_YCBCR601_LIMITED_TYPE; + else if (is_ycbcr709_limited_type(color_space)) + type = COLOR_SPACE_YCBCR709_LIMITED_TYPE; + + return type; +} + +const uint16_t *find_color_matrix(enum dc_color_space color_space, + uint32_t *array_size) +{ + int i; + enum dc_color_space_type type; + const uint16_t *val = NULL; + int arr_size = NUM_ELEMENTS(output_csc_matrix); + + type = get_color_space_type(color_space); + for (i = 0; i < arr_size; i++) + if (output_csc_matrix[i].color_space_type == type) { + val = output_csc_matrix[i].regval; + *array_size = 12; + break; + } + + return val; +} + + void color_space_to_black_color( const struct dc *dc, enum dc_color_space colorspace, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 7b0e43c0685c..a37428271573 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -938,8 +938,9 @@ static bool construct( link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { - dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d!\n", - __func__, init_params->connector_index); + dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n", + __func__, init_params->connector_index, + link->link_id.type, OBJECT_TYPE_CONNECTOR); goto create_fail; } @@ -1271,6 +1272,24 @@ static enum dc_status enable_link_dp( return status; } +static enum dc_status enable_link_edp( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) +{ + enum dc_status status; + struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->sink->link; + + link->dc->hwss.edp_power_control(link, true); + link->dc->hwss.edp_wait_for_hpd_ready(link, true); + + status = enable_link_dp(state, pipe_ctx); + + link->dc->hwss.edp_backlight_control(link, true); + + return status; +} + static enum dc_status enable_link_dp_mst( struct dc_state *state, struct pipe_ctx *pipe_ctx) @@ -1746,9 +1765,11 @@ static enum dc_status enable_link( enum dc_status status = DC_ERROR_UNEXPECTED; switch (pipe_ctx->stream->signal) { case SIGNAL_TYPE_DISPLAY_PORT: - case SIGNAL_TYPE_EDP: status = enable_link_dp(state, pipe_ctx); break; + case SIGNAL_TYPE_EDP: + status = enable_link_edp(state, pipe_ctx); + break; case SIGNAL_TYPE_DISPLAY_PORT_MST: status = enable_link_dp_mst(state, pipe_ctx); msleep(200); @@ -1801,7 +1822,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) link->link_enc->funcs->disable_output(link->link_enc, signal); } -bool dp_active_dongle_validate_timing( +static bool dp_active_dongle_validate_timing( const struct dc_crtc_timing *timing, const struct dc_dongle_caps *dongle_caps) { @@ -1833,6 +1854,8 @@ bool dp_active_dongle_validate_timing( /* Check Color Depth and Pixel Clock */ if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) required_pix_clk /= 2; + else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + required_pix_clk = required_pix_clk * 2 / 3; switch (timing->display_color_depth) { case COLOR_DEPTH_666: @@ -1907,12 +1930,18 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, { struct dc *core_dc = link->ctx->dc; struct abm *abm = core_dc->res_pool->abm; + struct dmcu *dmcu = core_dc->res_pool->dmcu; unsigned int controller_id = 0; + bool use_smooth_brightness = true; int i; - if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) + if ((dmcu == NULL) || + (abm == NULL) || + (abm->funcs->set_backlight_level == NULL)) return false; + use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); + dm_logger_write(link->ctx->logger, LOG_BACKLIGHT, "New Backlight level: %d (0x%X)\n", level, level); @@ -1935,7 +1964,8 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, abm, level, frame_ramp, - controller_id); + controller_id, + use_smooth_brightness); } return true; @@ -1952,144 +1982,6 @@ bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait) return true; } -bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) -{ - struct dc *core_dc = link->ctx->dc; - struct dmcu *dmcu = core_dc->res_pool->dmcu; - - if (dmcu != NULL && link->psr_enabled) - dmcu->funcs->get_psr_state(dmcu, psr_state); - - return true; -} - -bool dc_link_setup_psr(struct dc_link *link, - const struct dc_stream_state *stream, struct psr_config *psr_config, - struct psr_context *psr_context) -{ - struct dc *core_dc = link->ctx->dc; - struct dmcu *dmcu = core_dc->res_pool->dmcu; - int i; - - psr_context->controllerId = CONTROLLER_ID_UNDEFINED; - - if (link != NULL && - dmcu != NULL) { - /* updateSinkPsrDpcdConfig*/ - union dpcd_psr_configuration psr_configuration; - - memset(&psr_configuration, 0, sizeof(psr_configuration)); - - psr_configuration.bits.ENABLE = 1; - psr_configuration.bits.CRC_VERIFICATION = 1; - psr_configuration.bits.FRAME_CAPTURE_INDICATION = - psr_config->psr_frame_capture_indication_req; - - /* Check for PSR v2*/ - if (psr_config->psr_version == 0x2) { - /* For PSR v2 selective update. - * Indicates whether sink should start capturing - * immediately following active scan line, - * or starting with the 2nd active scan line. - */ - psr_configuration.bits.LINE_CAPTURE_INDICATION = 0; - /*For PSR v2, determines whether Sink should generate - * IRQ_HPD when CRC mismatch is detected. - */ - psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; - } - - dm_helpers_dp_write_dpcd( - link->ctx, - link, - 368, - &psr_configuration.raw, - sizeof(psr_configuration.raw)); - - psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel; - psr_context->transmitterId = link->link_enc->transmitter; - psr_context->engineId = link->link_enc->preferred_engine; - - for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_state->res_ctx.pipe_ctx[i].stream - == stream) { - /* dmcu -1 for all controller id values, - * therefore +1 here - */ - psr_context->controllerId = - core_dc->current_state->res_ctx. - pipe_ctx[i].stream_res.tg->inst + 1; - break; - } - } - - /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/ - psr_context->phyType = PHY_TYPE_UNIPHY; - /*PhyId is associated with the transmitter id*/ - psr_context->smuPhyId = link->link_enc->transmitter; - - psr_context->crtcTimingVerticalTotal = stream->timing.v_total; - psr_context->vsyncRateHz = div64_u64(div64_u64((stream-> - timing.pix_clk_khz * 1000), - stream->timing.v_total), - stream->timing.h_total); - - psr_context->psrSupportedDisplayConfig = true; - psr_context->psrExitLinkTrainingRequired = - psr_config->psr_exit_link_training_required; - psr_context->sdpTransmitLineNumDeadline = - psr_config->psr_sdp_transmit_line_num_deadline; - psr_context->psrFrameCaptureIndicationReq = - psr_config->psr_frame_capture_indication_req; - - psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */ - - psr_context->numberOfControllers = - link->dc->res_pool->res_cap->num_timing_generator; - - psr_context->rfb_update_auto_en = true; - - /* 2 frames before enter PSR. */ - psr_context->timehyst_frames = 2; - /* half a frame - * (units in 100 lines, i.e. a value of 1 represents 100 lines) - */ - psr_context->hyst_lines = stream->timing.v_total / 2 / 100; - psr_context->aux_repeats = 10; - - psr_context->psr_level.u32all = 0; - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - /*skip power down the single pipe since it blocks the cstate*/ - if (ASIC_REV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) - psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; -#endif - - /* SMU will perform additional powerdown sequence. - * For unsupported ASICs, set psr_level flag to skip PSR - * static screen notification to SMU. - * (Always set for DAL2, did not check ASIC) - */ - psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION = 1; - - /* Complete PSR entry before aborting to prevent intermittent - * freezes on certain eDPs - */ - psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; - - /* Controls additional delay after remote frame capture before - * continuing power down, default = 0 - */ - psr_context->frame_delay = 0; - - link->psr_enabled = true; - dmcu->funcs->setup_psr(dmcu, link, psr_context); - return true; - } else - return false; - -} - const struct dc_link_status *dc_link_get_status(const struct dc_link *link) { return &link->link_status; @@ -2418,6 +2310,9 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); + if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) + core_dc->hwss.edp_backlight_control(pipe_ctx->stream->sink->link, false); + core_dc->hwss.disable_stream(pipe_ctx, option); disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 00528b214a9f..61e8c3e02d16 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1470,6 +1470,12 @@ void decide_link_settings(struct dc_stream_state *stream, return; } + /* EDP use the link cap setting */ + if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) { + *link_setting = link->verified_link_cap; + return; + } + /* search for the minimum link setting that: * 1. is supported according to the link training result * 2. could support the b/w requested by the timing diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index f2902569be2e..2096f2a179f2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -88,15 +88,7 @@ void dp_enable_link_phy( } if (dc_is_dp_sst_signal(signal)) { - if (signal == SIGNAL_TYPE_EDP) { - link->dc->hwss.edp_power_control(link, true); - link_enc->funcs->enable_dp_output( - link_enc, - link_settings, - clock_source); - link->dc->hwss.edp_backlight_control(link, true); - } else - link_enc->funcs->enable_dp_output( + link_enc->funcs->enable_dp_output( link_enc, link_settings, clock_source); @@ -138,7 +130,6 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dp_receiver_power_ctrl(link, false); if (signal == SIGNAL_TYPE_EDP) { - link->dc->hwss.edp_backlight_control(link, false); edp_receiver_ready_T9(link); link->link_enc->funcs->disable_output(link->link_enc, signal); link->dc->hwss.edp_power_control(link, false); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9c5e879f18b3..95b8dd0e53c6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1,5 +1,5 @@ /* -* Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-15 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"), @@ -498,26 +498,15 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; /* Handle hsplit */ - if (pri_split || sec_split) { - /* HMirror XOR Secondary_pipe XOR Rotation_180 */ - bool right_view = (sec_split != plane_state->horizontal_mirror) != - (plane_state->rotation == ROTATION_ANGLE_180); - - if (plane_state->rotation == ROTATION_ANGLE_90 - || plane_state->rotation == ROTATION_ANGLE_270) - /* Secondary_pipe XOR Rotation_270 */ - right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; - - if (right_view) { - data->viewport.x += data->viewport.width / 2; - data->viewport_c.x += data->viewport_c.width / 2; - /* Ceil offset pipe */ - data->viewport.width = (data->viewport.width + 1) / 2; - data->viewport_c.width = (data->viewport_c.width + 1) / 2; - } else { - data->viewport.width /= 2; - data->viewport_c.width /= 2; - } + if (sec_split) { + data->viewport.x += data->viewport.width / 2; + data->viewport_c.x += data->viewport_c.width / 2; + /* Ceil offset pipe */ + data->viewport.width = (data->viewport.width + 1) / 2; + data->viewport_c.width = (data->viewport_c.width + 1) / 2; + } else if (pri_split) { + data->viewport.width /= 2; + data->viewport_c.width /= 2; } if (plane_state->rotation == ROTATION_ANGLE_90 || @@ -534,6 +523,11 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip struct rect surf_src = plane_state->src_rect; struct rect surf_clip = plane_state->clip_rect; int recout_full_x, recout_full_y; + bool pri_split = pipe_ctx->bottom_pipe && + pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; + bool sec_split = pipe_ctx->top_pipe && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; + bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) @@ -568,33 +562,43 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip - pipe_ctx->plane_res.scl_data.recout.y; /* Handle h & vsplit */ - if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == - pipe_ctx->plane_state) { - if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { - pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height / 2; - /* Floor primary pipe, ceil 2ndary pipe */ - pipe_ctx->plane_res.scl_data.recout.height = (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; + if (sec_split && top_bottom_split) { + pipe_ctx->plane_res.scl_data.recout.y += + pipe_ctx->plane_res.scl_data.recout.height / 2; + /* Floor primary pipe, ceil 2ndary pipe */ + pipe_ctx->plane_res.scl_data.recout.height = + (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; + } else if (pri_split && top_bottom_split) + pipe_ctx->plane_res.scl_data.recout.height /= 2; + else if (pri_split || sec_split) { + /* HMirror XOR Secondary_pipe XOR Rotation_180 */ + bool right_view = (sec_split != plane_state->horizontal_mirror) != + (plane_state->rotation == ROTATION_ANGLE_180); + + if (plane_state->rotation == ROTATION_ANGLE_90 + || plane_state->rotation == ROTATION_ANGLE_270) + /* Secondary_pipe XOR Rotation_270 */ + right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; + + if (right_view) { + pipe_ctx->plane_res.scl_data.recout.x += + pipe_ctx->plane_res.scl_data.recout.width / 2; + /* Ceil offset pipe */ + pipe_ctx->plane_res.scl_data.recout.width = + (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; } else { - pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width / 2; - pipe_ctx->plane_res.scl_data.recout.width = (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; - } - } else if (pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) { - if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) - pipe_ctx->plane_res.scl_data.recout.height /= 2; - else pipe_ctx->plane_res.scl_data.recout.width /= 2; + } } - /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl * ratio) */ - recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) + recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) * stream->dst.width / stream->src.width - surf_src.x * plane_state->dst_rect.width / surf_src.width * stream->dst.width / stream->src.width; - recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) + recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) * stream->dst.height / stream->src.height - surf_src.y * plane_state->dst_rect.height / surf_src.height * stream->dst.height / stream->src.height; @@ -650,7 +654,20 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r struct rect src = pipe_ctx->plane_state->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; + bool flip_vert_scan_dir = false, flip_horz_scan_dir = false; + /* + * Need to calculate the scan direction for viewport to make adjustments + */ + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_180) { + flip_vert_scan_dir = true; + flip_horz_scan_dir = true; + } else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90) + flip_vert_scan_dir = true; + else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) + flip_horz_scan_dir = true; + if (pipe_ctx->plane_state->horizontal_mirror) + flip_horz_scan_dir = !flip_horz_scan_dir; if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { @@ -715,7 +732,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r } /* Adjust for non-0 viewport offset */ - if (data->viewport.x) { + if (data->viewport.x && !flip_horz_scan_dir) { int int_part; data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int( @@ -736,7 +753,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part); } - if (data->viewport_c.x) { + if (data->viewport_c.x && !flip_horz_scan_dir) { int int_part; data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int( @@ -757,7 +774,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part); } - if (data->viewport.y) { + if (data->viewport.y && !flip_vert_scan_dir) { int int_part; data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int( @@ -778,7 +795,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part); } - if (data->viewport_c.y) { + if (data->viewport_c.y && !flip_vert_scan_dir) { int int_part; data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 375fb457e223..261811e0c094 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -226,7 +226,7 @@ bool dc_stream_set_cursor_attributes( if (pipe_ctx->plane_res.dpp != NULL && pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( - pipe_ctx->plane_res.dpp, attributes); + pipe_ctx->plane_res.dpp, attributes->color_format); } stream->cursor_attributes = *attributes; @@ -301,6 +301,8 @@ bool dc_stream_set_cursor_position( } + stream->cursor_position = *position; + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c99ed85ba9a2..e2e3c9df79ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.20" +#define DC_VER "3.1.27" #define MAX_SURFACES 3 #define MAX_STREAMS 6 @@ -250,6 +250,8 @@ struct dc { */ struct dm_pp_display_configuration prev_display_config; + bool optimized_required; + /* FBC compressor */ #if defined(CONFIG_DRM_AMD_DC_FBC) struct compressor *fbc_compressor; @@ -340,7 +342,7 @@ struct dc_hdr_static_metadata { enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, - TF_TYPE_BYPASS + TF_TYPE_BYPASS, }; struct dc_transfer_func_distributed_points { @@ -359,6 +361,7 @@ enum dc_transfer_func_predefined { TRANSFER_FUNCTION_BT709, TRANSFER_FUNCTION_PQ, TRANSFER_FUNCTION_LINEAR, + TRANSFER_FUNCTION_UNITY, }; struct dc_transfer_func { @@ -385,6 +388,7 @@ union surface_update_flags { struct { /* Medium updates */ + uint32_t dcc_change:1; uint32_t color_space_change:1; uint32_t input_tf_change:1; uint32_t horizontal_mirror_change:1; @@ -436,6 +440,7 @@ struct dc_plane_state { enum dc_rotation_angle rotation; enum plane_stereo_format stereo_format; + bool is_tiling_rotated; bool per_pixel_alpha; bool visible; bool flip_immediate; diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index c584252669fd..48e1fcf53d43 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -1,4 +1,26 @@ /* + * Copyright 2017 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. + * + */ +/* * dc_helper.c * * Created on: Aug 30, 2016 diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 587c0bb3d4ac..03029f72dc3f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -579,8 +579,6 @@ enum dc_timing_standard { TIMING_STANDARD_MAX }; - - enum dc_color_depth { COLOR_DEPTH_UNDEFINED, COLOR_DEPTH_666, diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index fed0e5ea9625..01c60f11b2bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -86,6 +86,7 @@ struct dc_stream_state { struct dc_stream_status status; struct dc_cursor_attributes cursor_attributes; + struct dc_cursor_position cursor_position; /* from stream struct */ struct kref refcount; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 9291a60126ad..9faddfae241d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -218,6 +218,7 @@ struct dc_edid_caps { bool lte_340mcsc_scramble; bool edid_hdmi; + bool hdr_supported; }; struct view { diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index 8abec0bed379..11401fd8e535 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for common 'dce' logic # HW object file under this folder follow similar pattern for HW programming # - register offset and/or shift + mask stored in the dec_hw struct diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 3fe8e697483f..b48190f54907 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -385,21 +385,12 @@ static bool dce_abm_init_backlight(struct abm *abm) return true; } -static bool is_dmcu_initialized(struct abm *abm) -{ - struct dce_abm *abm_dce = TO_DCE_ABM(abm); - unsigned int dmcu_uc_reset; - - REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); - - return !dmcu_uc_reset; -} - static bool dce_abm_set_backlight_level( struct abm *abm, unsigned int backlight_level, unsigned int frame_ramp, - unsigned int controller_id) + unsigned int controller_id, + bool use_smooth_brightness) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); @@ -408,7 +399,7 @@ static bool dce_abm_set_backlight_level( backlight_level, backlight_level); /* If DMCU is in reset state, DMCU is uninitialized */ - if (is_dmcu_initialized(abm)) + if (use_smooth_brightness) dmcu_set_backlight_level(abm_dce, backlight_level, frame_ramp, @@ -425,8 +416,7 @@ static const struct abm_funcs dce_funcs = { .init_backlight = dce_abm_init_backlight, .set_backlight_level = dce_abm_set_backlight_level, .get_current_backlight_8_bit = dce_abm_get_current_backlight_8_bit, - .set_abm_immediate_disable = dce_abm_immediate_disable, - .is_dmcu_initialized = is_dmcu_initialized + .set_abm_immediate_disable = dce_abm_immediate_disable }; static void dce_abm_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index 59e909ec88f2..ff9436966041 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -37,8 +37,7 @@ SR(LVTMA_PWRSEQ_REF_DIV), \ SR(MASTER_COMM_CNTL_REG), \ SR(MASTER_COMM_CMD_REG), \ - SR(MASTER_COMM_DATA_REG1), \ - SR(DMCU_STATUS) + SR(MASTER_COMM_DATA_REG1) #define ABM_DCE110_COMMON_REG_LIST() \ ABM_COMMON_REG_LIST_DCE_BASE(), \ @@ -84,8 +83,7 @@ ABM_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE1, mask_sh), \ - ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh), \ - ABM_SF(DMCU_STATUS, UC_IN_RESET, mask_sh) + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh) #define ABM_MASK_SH_LIST_DCE110(mask_sh) \ ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ @@ -174,7 +172,6 @@ type MASTER_COMM_CMD_REG_BYTE2; \ type BL_PWM_REF_DIV; \ type BL_PWM_EN; \ - type UC_IN_RESET; \ type BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN; \ type BL_PWM_GRP1_REG_LOCK; \ type BL_PWM_GRP1_REG_UPDATE_PENDING @@ -206,7 +203,6 @@ struct dce_abm_registers { uint32_t MASTER_COMM_CMD_REG; uint32_t MASTER_COMM_DATA_REG1; uint32_t BIOS_SCRATCH_2; - uint32_t DMCU_STATUS; uint32_t BL_PWM_GRP1_REG_LOCK; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 9031d22285ea..9e98a5f39a6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -29,7 +29,6 @@ #include "fixed32_32.h" #include "bios_parser_interface.h" #include "dc.h" -#include "dce_abm.h" #include "dmcu.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dcn_calcs.h" @@ -384,7 +383,6 @@ static int dce112_set_clock( struct bp_set_dce_clock_parameters dce_clk_params; struct dc_bios *bp = clk->ctx->dc_bios; struct dc *core_dc = clk->ctx->dc; - struct abm *abm = core_dc->res_pool->abm; struct dmcu *dmcu = core_dc->res_pool->dmcu; int actual_clock = requested_clk_khz; /* Prepare to program display clock*/ @@ -417,7 +415,7 @@ static int dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); - if (abm->funcs->is_dmcu_initialized(abm) && clk_dce->dfs_bypass_disp_clk != actual_clock) + if (clk_dce->dfs_bypass_disp_clk != actual_clock) dmcu->funcs->set_psr_wait_loop(dmcu, actual_clock / 1000 / 7); clk_dce->dfs_bypass_disp_clk = actual_clock; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index a6de99db0444..f663adb33584 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -263,15 +263,35 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } +static bool dce_is_dmcu_initialized(struct dmcu *dmcu) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int dmcu_uc_reset; + + /* microcontroller is not running */ + REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); + + /* DMCU is not running */ + if (dmcu_uc_reset) + return false; + + return true; +} + static void dce_psr_wait_loop( struct dmcu *dmcu, unsigned int wait_loop_number) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + if (dmcu->cached_wait_loop_number == wait_loop_number) return; + /* DMCU is not running */ + if (!dce_is_dmcu_initialized(dmcu)) + return; + /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); @@ -691,6 +711,14 @@ static void dcn10_get_psr_wait_loop( return; } +static bool dcn10_is_dmcu_initialized(struct dmcu *dmcu) +{ + /* microcontroller is not running */ + if (dmcu->dmcu_state != DMCU_RUNNING) + return false; + return true; +} + #endif static const struct dmcu_funcs dce_funcs = { @@ -700,7 +728,8 @@ static const struct dmcu_funcs dce_funcs = { .setup_psr = dce_dmcu_setup_psr, .get_psr_state = dce_get_dmcu_psr_state, .set_psr_wait_loop = dce_psr_wait_loop, - .get_psr_wait_loop = dce_get_psr_wait_loop + .get_psr_wait_loop = dce_get_psr_wait_loop, + .is_dmcu_initialized = dce_is_dmcu_initialized }; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -711,7 +740,8 @@ static const struct dmcu_funcs dcn10_funcs = { .setup_psr = dcn10_dmcu_setup_psr, .get_psr_state = dcn10_get_dmcu_psr_state, .set_psr_wait_loop = dcn10_psr_wait_loop, - .get_psr_wait_loop = dcn10_get_psr_wait_loop + .get_psr_wait_loop = dcn10_get_psr_wait_loop, + .is_dmcu_initialized = dcn10_is_dmcu_initialized }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index 4c25e2dd28f8..1d4546f23135 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -62,6 +62,8 @@ DMCU_ENABLE, mask_sh), \ DMCU_SF(DMCU_STATUS, \ UC_IN_STOP_MODE, mask_sh), \ + DMCU_SF(DMCU_STATUS, \ + UC_IN_RESET, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ IRAM_HOST_ACCESS_EN, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ @@ -98,6 +100,7 @@ type IRAM_RD_ADDR_AUTO_INC; \ type DMCU_ENABLE; \ type UC_IN_STOP_MODE; \ + type UC_IN_RESET; \ type MASTER_COMM_CMD_REG_BYTE0; \ type MASTER_COMM_INTERRUPT; \ type DPHY_RX_FAST_TRAINING_CAPABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 3b0db253ac22..b73db9e78437 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -582,7 +582,8 @@ struct dce_hwseq_registers { type DOMAIN7_PGFSM_PWR_STATUS; \ type DCFCLK_GATE_DIS; \ type DCHUBBUB_GLOBAL_TIMER_REFDIV; \ - type DENTIST_DPPCLK_WDIVIDER; + type DENTIST_DPPCLK_WDIVIDER; \ + type DENTIST_DISPCLK_WDIVIDER; struct dce_hwseq_shift { HWSEQ_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index bad70c6b3aad..a266e3f5e75f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1072,21 +1072,6 @@ void dce110_link_encoder_disable_output( /* disable encoder */ if (dc_is_dp_signal(signal)) link_encoder_disable(enc110); - - /* - * TODO: Power control cause regression, we should implement - * it properly, for now just comment it. - */ -// if (enc110->base.connector.id == CONNECTOR_ID_EDP) { -// /* power down eDP panel */ -// link_encoder_edp_wait_for_hpd_ready( -// enc, -// enc->connector, -// false); -// -// link_encoder_edp_power_control( -// enc, false); -// } } void dce110_link_encoder_dp_set_lane_settings( diff --git a/drivers/gpu/drm/amd/display/dc/dce100/Makefile b/drivers/gpu/drm/amd/display/dc/dce100/Makefile index ea40870624b3..a822d4e2a169 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce100/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 90911258bdb3..3ea43e2a9450 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -1,5 +1,5 @@ /* -* Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-15 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"), diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index de8fdf438f9b..2f366d66635d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -1,4 +1,27 @@ /* + * Copyright 2017 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. + * + * + */ +/* * dce100_resource.h * * Created on: 2016-01-20 diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile index 98d956e2f218..d564c0eb8b04 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e650bdcd9423..86cdd7b4811f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -354,8 +354,8 @@ static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted, return false; } - if (!convert_to_custom_float_format(arr_points[2].slope, &fmt, - &arr_points[2].custom_float_slope)) { + if (!convert_to_custom_float_format(arr_points[1].slope, &fmt, + &arr_points[1].custom_float_slope)) { BREAK_TO_DEBUGGER(); return false; } @@ -870,8 +870,6 @@ void hwss_edp_power_control( "%s: Skipping Panel Power action: %s\n", __func__, (power_up ? "On":"Off")); } - - hwss_edp_wait_for_hpd_ready(link, true); } /*todo: cloned in stream enc, fix*/ @@ -972,11 +970,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) } /* blank at encoder level */ - if (dc_is_dp_signal(pipe_ctx->stream->signal)) { - if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) - hwss_edp_backlight_control(link, false); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); - } + link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, pipe_ctx->stream_res.stream_enc->id, @@ -988,15 +984,12 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings) { struct encoder_unblank_param params = { { 0 } }; - struct dc_link *link = pipe_ctx->stream->sink->link; /* only 3 items below are used by unblank */ params.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); - if (link->connector_signal == SIGNAL_TYPE_EDP) - hwss_edp_backlight_control(link, true); } @@ -1342,10 +1335,8 @@ static void power_down_encoders(struct dc *dc) if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(dc->links[i], false); - if (connector_id == CONNECTOR_ID_EDP) { + if (connector_id == CONNECTOR_ID_EDP) signal = SIGNAL_TYPE_EDP; - hwss_edp_backlight_control(dc->links[i], false); - } } dc->links[i]->link_enc->funcs->disable_output( @@ -1698,60 +1689,54 @@ static void apply_min_clocks( /* * Check if FBC can be enabled */ -static enum dc_status validate_fbc(struct dc *dc, - struct dc_state *context) +static bool should_enable_fbc(struct dc *dc, + struct dc_state *context) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[0]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; ASSERT(dc->fbc_compressor); /* FBC memory should be allocated */ if (!dc->ctx->fbc_gpu_addr) - return DC_ERROR_UNEXPECTED; + return false; /* Only supports single display */ if (context->stream_count != 1) - return DC_ERROR_UNEXPECTED; + return false; /* Only supports eDP */ if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) - return DC_ERROR_UNEXPECTED; + return false; /* PSR should not be enabled */ if (pipe_ctx->stream->sink->link->psr_enabled) - return DC_ERROR_UNEXPECTED; + return false; /* Nothing to compress */ if (!pipe_ctx->plane_state) - return DC_ERROR_UNEXPECTED; + return false; /* Only for non-linear tiling */ if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) - return DC_ERROR_UNEXPECTED; + return false; - return DC_OK; + return true; } /* * Enable FBC */ -static enum dc_status enable_fbc(struct dc *dc, - struct dc_state *context) +static void enable_fbc(struct dc *dc, + struct dc_state *context) { - enum dc_status status = validate_fbc(dc, context); - - if (status == DC_OK) { + if (should_enable_fbc(dc, context)) { /* Program GRPH COMPRESSED ADDRESS and PITCH */ struct compr_addr_and_pitch_params params = {0, 0, 0}; struct compressor *compr = dc->fbc_compressor; - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[0]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; - params.source_view_width = - pipe_ctx->stream->timing.h_addressable; - params.source_view_height = - pipe_ctx->stream->timing.v_addressable; + params.source_view_width = pipe_ctx->stream->timing.h_addressable; + params.source_view_height = pipe_ctx->stream->timing.v_addressable; compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; @@ -1760,7 +1745,6 @@ static enum dc_status enable_fbc(struct dc *dc, compr->funcs->enable_fbc(compr, ¶ms); } - return status; } #endif @@ -2026,8 +2010,7 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream == pipe_ctx_old->stream) continue; - if (pipe_ctx->stream && pipe_ctx_old->stream - && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) continue; if (pipe_ctx->top_pipe) @@ -2063,9 +2046,6 @@ enum dc_status dce110_apply_ctx_to_hw( context, dc); - if (dc->hwss.enable_plane) - dc->hwss.enable_plane(dc, pipe_ctx, context); - if (DC_OK != status) return status; } @@ -2095,16 +2075,8 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) struct default_adjustment default_adjust = { 0 }; default_adjust.force_hw_default = false; - if (pipe_ctx->plane_state == NULL) - default_adjust.in_color_space = COLOR_SPACE_SRGB; - else - default_adjust.in_color_space = - pipe_ctx->plane_state->color_space; - if (pipe_ctx->stream == NULL) - default_adjust.out_color_space = COLOR_SPACE_SRGB; - else - default_adjust.out_color_space = - pipe_ctx->stream->output_color_space; + default_adjust.in_color_space = pipe_ctx->plane_state->color_space; + default_adjust.out_color_space = pipe_ctx->stream->output_color_space; default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; @@ -2872,13 +2844,12 @@ static void dce110_apply_ctx_for_surface( continue; /* Need to allocate mem before program front end for Fiji */ - if (pipe_ctx->plane_res.mi != NULL) - pipe_ctx->plane_res.mi->funcs->allocate_mem_input( - pipe_ctx->plane_res.mi, - pipe_ctx->stream->timing.h_total, - pipe_ctx->stream->timing.v_total, - pipe_ctx->stream->timing.pix_clk_khz, - context->stream_count); + pipe_ctx->plane_res.mi->funcs->allocate_mem_input( + pipe_ctx->plane_res.mi, + pipe_ctx->stream->timing.h_total, + pipe_ctx->stream->timing.v_total, + pipe_ctx->stream->timing.pix_clk_khz, + context->stream_count); dce110_program_front_end_for_pipe(dc, pipe_ctx); @@ -2985,6 +2956,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .pplib_apply_display_requirements = pplib_apply_display_requirements, .edp_backlight_control = hwss_edp_backlight_control, .edp_power_control = hwss_edp_power_control, + .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, }; void dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 2dd6ac637572..fc637647f643 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -77,5 +77,9 @@ void hwss_edp_backlight_control( struct dc_link *link, bool enable); +void hwss_edp_wait_for_hpd_ready( + struct dc_link *link, + bool power_up); + #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 5228ee78f7e6..7c4779578fb7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1,5 +1,5 @@ /* -* Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-15 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"), diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 07d9303d5477..59b4cd329715 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -1,3 +1,26 @@ +/* + * Copyright 2017 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. + * + */ + #include "dm_services.h" /* include DCE11 register header files */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile index 265ac4310d85..8e090446d511 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile index 1779b963525c..37db1f8d45ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. @@ -8,4 +29,4 @@ dce120_hw_sequencer.o AMD_DAL_DCE120 = $(addprefix $(AMDDALPATH)/dc/dce120/,$(DCE120)) -AMD_DISPLAY_FILES += $(AMD_DAL_DCE120)
\ No newline at end of file +AMD_DISPLAY_FILES += $(AMD_DAL_DCE120) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index c1105895e5fa..bc388aa4b2f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index a6ca1f97f748..5469bdfe19f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -1,8 +1,29 @@ # +# Copyright 2017 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. +# +# # Makefile for DCN. DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ - dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ + dcn10_dpp.o dcn10_opp.o dcn10_optc.o \ dcn10_hubp.o dcn10_mpc.o \ dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o \ dcn10_hubbub.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index 7f579cb19f4b..53ba3600ee6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -22,11 +22,12 @@ * Authors: AMD * */ - +#include "dc.h" #include "reg_helper.h" #include "dcn10_dpp.h" #include "dcn10_cm_common.h" +#include "custom_float.h" #define REG(reg) reg @@ -121,3 +122,294 @@ void cm_helper_program_xfer_func( } } + + + +bool cm_helper_convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num, + bool fixpoint) +{ + struct custom_float_format fmt; + + struct pwl_result_data *rgb = rgb_resulted; + + uint32_t i = 0; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = false; + + if (!convert_to_custom_float_format(arr_points[0].x, &fmt, + &arr_points[0].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(arr_points[0].offset, &fmt, + &arr_points[0].custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(arr_points[0].slope, &fmt, + &arr_points[0].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 10; + fmt.sign = false; + + if (!convert_to_custom_float_format(arr_points[1].x, &fmt, + &arr_points[1].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (fixpoint == true) + arr_points[1].custom_float_y = dal_fixed31_32_clamp_u0d14(arr_points[1].y); + else if (!convert_to_custom_float_format(arr_points[1].y, &fmt, + &arr_points[1].custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(arr_points[1].slope, &fmt, + &arr_points[1].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true) + return true; + + fmt.mantissa_bits = 12; + fmt.sign = true; + + while (i != hw_points_num) { + if (!convert_to_custom_float_format(rgb->red, &fmt, + &rgb->red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->green, &fmt, + &rgb->green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->blue, &fmt, + &rgb->blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->delta_red, &fmt, + &rgb->delta_red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->delta_green, &fmt, + &rgb->delta_green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, + &rgb->delta_blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + ++rgb; + ++i; + } + + return true; +} + + +#define MAX_REGIONS_NUMBER 34 +#define MAX_LOW_POINT 25 +#define NUMBER_SEGMENTS 32 + +bool cm_helper_translate_curve_to_hw_format( + const struct dc_transfer_func *output_tf, + struct pwl_params *lut_params, bool fixpoint) +{ + struct curve_points *arr_points; + struct pwl_result_data *rgb_resulted; + struct pwl_result_data *rgb; + struct pwl_result_data *rgb_plus_1; + struct fixed31_32 y_r; + struct fixed31_32 y_g; + struct fixed31_32 y_b; + struct fixed31_32 y1_min; + struct fixed31_32 y3_max; + + int32_t segment_start, segment_end; + int32_t i; + uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; + + if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) + return false; + + PERF_TRACE(); + + arr_points = lut_params->arr_points; + rgb_resulted = lut_params->rgb_resulted; + hw_points = 0; + + memset(lut_params, 0, sizeof(struct pwl_params)); + memset(seg_distr, 0, sizeof(seg_distr)); + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* 32 segments + * segments are from 2^-25 to 2^7 + */ + for (i = 0; i < 32 ; i++) + seg_distr[i] = 3; + + segment_start = -25; + segment_end = 7; + } else { + /* 10 segments + * segment is from 2^-10 to 2^0 + * There are less than 256 points, for optimization + */ + seg_distr[0] = 3; + seg_distr[1] = 4; + seg_distr[2] = 4; + seg_distr[3] = 4; + seg_distr[4] = 4; + seg_distr[5] = 4; + seg_distr[6] = 4; + seg_distr[7] = 4; + seg_distr[8] = 5; + seg_distr[9] = 5; + + segment_start = -10; + segment_end = 0; + } + + for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++) + seg_distr[i] = -1; + + for (k = 0; k < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) + hw_points += (1 << seg_distr[k]); + } + + j = 0; + for (k = 0; k < (segment_end - segment_start); k++) { + increment = NUMBER_SEGMENTS / (1 << seg_distr[k]); + start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS; + for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) { + if (j == hw_points - 1) + break; + rgb_resulted[j].red = output_tf->tf_pts.red[i]; + rgb_resulted[j].green = output_tf->tf_pts.green[i]; + rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; + j++; + } + } + + /* last point */ + start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS; + rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; + + arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_start)); + arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + + y_r = rgb_resulted[0].red; + y_g = rgb_resulted[0].green; + y_b = rgb_resulted[0].blue; + + y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); + + arr_points[0].y = y1_min; + arr_points[0].slope = dal_fixed31_32_div(arr_points[0].y, arr_points[0].x); + y_r = rgb_resulted[hw_points - 1].red; + y_g = rgb_resulted[hw_points - 1].green; + y_b = rgb_resulted[hw_points - 1].blue; + + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ + y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[1].y = y3_max; + + arr_points[1].slope = dal_fixed31_32_zero; + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* for PQ, we want to have a straight line from last HW X point, + * and the slope to be such that we hit 1.0 at 10000 nits. + */ + const struct fixed31_32 end_value = + dal_fixed31_32_from_int(125); + + arr_points[1].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + } + + lut_params->hw_points_num = hw_points; + + i = 1; + for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) { + lut_params->arr_curve_points[k].segments_num = + seg_distr[k]; + lut_params->arr_curve_points[i].offset = + lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]); + } + i++; + } + + if (seg_distr[k] != -1) + lut_params->arr_curve_points[k].segments_num = seg_distr[k]; + + rgb = rgb_resulted; + rgb_plus_1 = rgb_resulted + 1; + + i = 1; + while (i != hw_points + 1) { + if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = rgb->red; + if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = rgb->green; + if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = rgb->blue; + + rgb->delta_red = dal_fixed31_32_sub(rgb_plus_1->red, rgb->red); + rgb->delta_green = dal_fixed31_32_sub(rgb_plus_1->green, rgb->green); + rgb->delta_blue = dal_fixed31_32_sub(rgb_plus_1->blue, rgb->blue); + + if (fixpoint == true) { + rgb->delta_red_reg = dal_fixed31_32_clamp_u0d10(rgb->delta_red); + rgb->delta_green_reg = dal_fixed31_32_clamp_u0d10(rgb->delta_green); + rgb->delta_blue_reg = dal_fixed31_32_clamp_u0d10(rgb->delta_blue); + rgb->red_reg = dal_fixed31_32_clamp_u0d14(rgb->red); + rgb->green_reg = dal_fixed31_32_clamp_u0d14(rgb->green); + rgb->blue_reg = dal_fixed31_32_clamp_u0d14(rgb->blue); + } + + ++rgb_plus_1; + ++rgb; + ++i; + } + cm_helper_convert_to_custom_float(rgb_resulted, + lut_params->arr_points, + hw_points, fixpoint); + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h index 64836dcf21f2..64e476b83bcb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h @@ -96,4 +96,14 @@ void cm_helper_program_xfer_func( const struct pwl_params *params, const struct xfer_func_reg *reg); +bool cm_helper_convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num, + bool fixpoint); + +bool cm_helper_translate_curve_to_hw_format( + const struct dc_transfer_func *output_tf, + struct pwl_params *lut_params, bool fixpoint); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 8df3945370cf..f2a08b156cf0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -159,11 +159,10 @@ bool dpp_get_optimal_number_of_taps( scl_data->taps.h_taps = 1; if (IDENTITY_RATIO(scl_data->ratios.vert)) scl_data->taps.v_taps = 1; - /* - * Spreadsheet doesn't handle taps_c is one properly, - * need to force Chroma to always be scaled to pass - * bandwidth validation. - */ + if (IDENTITY_RATIO(scl_data->ratios.horz_c)) + scl_data->taps.h_taps_c = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert_c)) + scl_data->taps.v_taps_c = 1; } return true; @@ -386,10 +385,9 @@ void dpp1_cnv_setup ( void dpp1_set_cursor_attributes( struct dpp *dpp_base, - const struct dc_cursor_attributes *attr) + enum dc_cursor_color_format color_format) { struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - enum dc_cursor_color_format color_format = attr->color_format; REG_UPDATE_2(CURSOR0_CONTROL, CUR0_MODE, color_format, @@ -402,13 +400,6 @@ void dpp1_set_cursor_attributes( REG_UPDATE(CURSOR0_COLOR1, CUR0_COLOR1, 0xFFFFFFFF); } - - /* TODO: Fixed vs float */ - - REG_UPDATE_3(FORMAT_CONTROL, - CNVC_BYPASS, 0, - FORMAT_CONTROL__ALPHA_EN, 1, - FORMAT_EXPANSION_MODE, 0); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index ad71fb50f8a5..f56ee4d08d89 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -730,8 +730,9 @@ type CM_BLNDGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_BLNDGAM_LUT_WRITE_EN_MASK; \ type CM_BLNDGAM_LUT_WRITE_SEL; \ + type CM_BLNDGAM_CONFIG_STATUS; \ type CM_BLNDGAM_LUT_INDEX; \ - type CM_BLNDGAM_LUT_DATA; \ + type BLNDGAM_MEM_PWR_FORCE; \ type CM_3DLUT_MODE; \ type CM_3DLUT_SIZE; \ type CM_3DLUT_INDEX; \ @@ -905,6 +906,7 @@ type CM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET; \ type CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_SHAPER_LUT_WRITE_EN_MASK; \ + type CM_SHAPER_CONFIG_STATUS; \ type CM_SHAPER_LUT_WRITE_SEL; \ type CM_SHAPER_LUT_INDEX; \ type CM_SHAPER_LUT_DATA; \ @@ -1005,258 +1007,255 @@ type CM_BYPASS; \ type FORMAT_CONTROL__ALPHA_EN; \ type CUR0_COLOR0; \ - type CUR0_COLOR1 - - + type CUR0_COLOR1; struct dcn_dpp_shift { - TF_REG_FIELD_LIST(uint8_t); + TF_REG_FIELD_LIST(uint8_t) }; struct dcn_dpp_mask { - TF_REG_FIELD_LIST(uint32_t); + TF_REG_FIELD_LIST(uint32_t) }; - - +#define DPP_COMMON_REG_VARIABLE_LIST \ + uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; \ + uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; \ + uint32_t OTG_H_BLANK; \ + uint32_t OTG_V_BLANK; \ + uint32_t SCL_MODE; \ + uint32_t LB_DATA_FORMAT; \ + uint32_t LB_MEMORY_CTRL; \ + uint32_t DSCL_AUTOCAL; \ + uint32_t SCL_BLACK_OFFSET; \ + uint32_t SCL_TAP_CONTROL; \ + uint32_t SCL_COEF_RAM_TAP_SELECT; \ + uint32_t SCL_COEF_RAM_TAP_DATA; \ + uint32_t DSCL_2TAP_CONTROL; \ + uint32_t MPC_SIZE; \ + uint32_t SCL_HORZ_FILTER_SCALE_RATIO; \ + uint32_t SCL_VERT_FILTER_SCALE_RATIO; \ + uint32_t SCL_HORZ_FILTER_SCALE_RATIO_C; \ + uint32_t SCL_VERT_FILTER_SCALE_RATIO_C; \ + uint32_t SCL_HORZ_FILTER_INIT; \ + uint32_t SCL_HORZ_FILTER_INIT_C; \ + uint32_t SCL_VERT_FILTER_INIT; \ + uint32_t SCL_VERT_FILTER_INIT_BOT; \ + uint32_t SCL_VERT_FILTER_INIT_C; \ + uint32_t SCL_VERT_FILTER_INIT_BOT_C; \ + uint32_t RECOUT_START; \ + uint32_t RECOUT_SIZE; \ + uint32_t CM_GAMUT_REMAP_CONTROL; \ + uint32_t CM_GAMUT_REMAP_C11_C12; \ + uint32_t CM_GAMUT_REMAP_C33_C34; \ + uint32_t CM_COMA_C11_C12; \ + uint32_t CM_COMA_C33_C34; \ + uint32_t CM_COMB_C11_C12; \ + uint32_t CM_COMB_C33_C34; \ + uint32_t CM_OCSC_CONTROL; \ + uint32_t CM_OCSC_C11_C12; \ + uint32_t CM_OCSC_C33_C34; \ + uint32_t CM_MEM_PWR_CTRL; \ + uint32_t CM_RGAM_LUT_DATA; \ + uint32_t CM_RGAM_LUT_WRITE_EN_MASK; \ + uint32_t CM_RGAM_LUT_INDEX; \ + uint32_t CM_RGAM_RAMB_START_CNTL_B; \ + uint32_t CM_RGAM_RAMB_START_CNTL_G; \ + uint32_t CM_RGAM_RAMB_START_CNTL_R; \ + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; \ + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; \ + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; \ + uint32_t CM_RGAM_RAMB_END_CNTL1_B; \ + uint32_t CM_RGAM_RAMB_END_CNTL2_B; \ + uint32_t CM_RGAM_RAMB_END_CNTL1_G; \ + uint32_t CM_RGAM_RAMB_END_CNTL2_G; \ + uint32_t CM_RGAM_RAMB_END_CNTL1_R; \ + uint32_t CM_RGAM_RAMB_END_CNTL2_R; \ + uint32_t CM_RGAM_RAMB_REGION_0_1; \ + uint32_t CM_RGAM_RAMB_REGION_32_33; \ + uint32_t CM_RGAM_RAMA_START_CNTL_B; \ + uint32_t CM_RGAM_RAMA_START_CNTL_G; \ + uint32_t CM_RGAM_RAMA_START_CNTL_R; \ + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; \ + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; \ + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; \ + uint32_t CM_RGAM_RAMA_END_CNTL1_B; \ + uint32_t CM_RGAM_RAMA_END_CNTL2_B; \ + uint32_t CM_RGAM_RAMA_END_CNTL1_G; \ + uint32_t CM_RGAM_RAMA_END_CNTL2_G; \ + uint32_t CM_RGAM_RAMA_END_CNTL1_R; \ + uint32_t CM_RGAM_RAMA_END_CNTL2_R; \ + uint32_t CM_RGAM_RAMA_REGION_0_1; \ + uint32_t CM_RGAM_RAMA_REGION_32_33; \ + uint32_t CM_RGAM_CONTROL; \ + uint32_t CM_CMOUT_CONTROL; \ + uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; \ + uint32_t CM_BLNDGAM_CONTROL; \ + uint32_t CM_BLNDGAM_RAMB_START_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMB_START_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMB_START_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_B; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_B; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_G; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_G; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_R; \ + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_R; \ + uint32_t CM_BLNDGAM_RAMB_REGION_0_1; \ + uint32_t CM_BLNDGAM_RAMB_REGION_2_3; \ + uint32_t CM_BLNDGAM_RAMB_REGION_4_5; \ + uint32_t CM_BLNDGAM_RAMB_REGION_6_7; \ + uint32_t CM_BLNDGAM_RAMB_REGION_8_9; \ + uint32_t CM_BLNDGAM_RAMB_REGION_10_11; \ + uint32_t CM_BLNDGAM_RAMB_REGION_12_13; \ + uint32_t CM_BLNDGAM_RAMB_REGION_14_15; \ + uint32_t CM_BLNDGAM_RAMB_REGION_16_17; \ + uint32_t CM_BLNDGAM_RAMB_REGION_18_19; \ + uint32_t CM_BLNDGAM_RAMB_REGION_20_21; \ + uint32_t CM_BLNDGAM_RAMB_REGION_22_23; \ + uint32_t CM_BLNDGAM_RAMB_REGION_24_25; \ + uint32_t CM_BLNDGAM_RAMB_REGION_26_27; \ + uint32_t CM_BLNDGAM_RAMB_REGION_28_29; \ + uint32_t CM_BLNDGAM_RAMB_REGION_30_31; \ + uint32_t CM_BLNDGAM_RAMB_REGION_32_33; \ + uint32_t CM_BLNDGAM_RAMA_START_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMA_START_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMA_START_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_B; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_B; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_G; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_G; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_R; \ + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_R; \ + uint32_t CM_BLNDGAM_RAMA_REGION_0_1; \ + uint32_t CM_BLNDGAM_RAMA_REGION_2_3; \ + uint32_t CM_BLNDGAM_RAMA_REGION_4_5; \ + uint32_t CM_BLNDGAM_RAMA_REGION_6_7; \ + uint32_t CM_BLNDGAM_RAMA_REGION_8_9; \ + uint32_t CM_BLNDGAM_RAMA_REGION_10_11; \ + uint32_t CM_BLNDGAM_RAMA_REGION_12_13; \ + uint32_t CM_BLNDGAM_RAMA_REGION_14_15; \ + uint32_t CM_BLNDGAM_RAMA_REGION_16_17; \ + uint32_t CM_BLNDGAM_RAMA_REGION_18_19; \ + uint32_t CM_BLNDGAM_RAMA_REGION_20_21; \ + uint32_t CM_BLNDGAM_RAMA_REGION_22_23; \ + uint32_t CM_BLNDGAM_RAMA_REGION_24_25; \ + uint32_t CM_BLNDGAM_RAMA_REGION_26_27; \ + uint32_t CM_BLNDGAM_RAMA_REGION_28_29; \ + uint32_t CM_BLNDGAM_RAMA_REGION_30_31; \ + uint32_t CM_BLNDGAM_RAMA_REGION_32_33; \ + uint32_t CM_BLNDGAM_LUT_INDEX; \ + uint32_t CM_3DLUT_MODE; \ + uint32_t CM_3DLUT_INDEX; \ + uint32_t CM_3DLUT_DATA; \ + uint32_t CM_3DLUT_DATA_30BIT; \ + uint32_t CM_3DLUT_READ_WRITE_CONTROL; \ + uint32_t CM_SHAPER_LUT_WRITE_EN_MASK; \ + uint32_t CM_SHAPER_CONTROL; \ + uint32_t CM_SHAPER_RAMB_START_CNTL_B; \ + uint32_t CM_SHAPER_RAMB_START_CNTL_G; \ + uint32_t CM_SHAPER_RAMB_START_CNTL_R; \ + uint32_t CM_SHAPER_RAMB_END_CNTL_B; \ + uint32_t CM_SHAPER_RAMB_END_CNTL_G; \ + uint32_t CM_SHAPER_RAMB_END_CNTL_R; \ + uint32_t CM_SHAPER_RAMB_REGION_0_1; \ + uint32_t CM_SHAPER_RAMB_REGION_2_3; \ + uint32_t CM_SHAPER_RAMB_REGION_4_5; \ + uint32_t CM_SHAPER_RAMB_REGION_6_7; \ + uint32_t CM_SHAPER_RAMB_REGION_8_9; \ + uint32_t CM_SHAPER_RAMB_REGION_10_11; \ + uint32_t CM_SHAPER_RAMB_REGION_12_13; \ + uint32_t CM_SHAPER_RAMB_REGION_14_15; \ + uint32_t CM_SHAPER_RAMB_REGION_16_17; \ + uint32_t CM_SHAPER_RAMB_REGION_18_19; \ + uint32_t CM_SHAPER_RAMB_REGION_20_21; \ + uint32_t CM_SHAPER_RAMB_REGION_22_23; \ + uint32_t CM_SHAPER_RAMB_REGION_24_25; \ + uint32_t CM_SHAPER_RAMB_REGION_26_27; \ + uint32_t CM_SHAPER_RAMB_REGION_28_29; \ + uint32_t CM_SHAPER_RAMB_REGION_30_31; \ + uint32_t CM_SHAPER_RAMB_REGION_32_33; \ + uint32_t CM_SHAPER_RAMA_START_CNTL_B; \ + uint32_t CM_SHAPER_RAMA_START_CNTL_G; \ + uint32_t CM_SHAPER_RAMA_START_CNTL_R; \ + uint32_t CM_SHAPER_RAMA_END_CNTL_B; \ + uint32_t CM_SHAPER_RAMA_END_CNTL_G; \ + uint32_t CM_SHAPER_RAMA_END_CNTL_R; \ + uint32_t CM_SHAPER_RAMA_REGION_0_1; \ + uint32_t CM_SHAPER_RAMA_REGION_2_3; \ + uint32_t CM_SHAPER_RAMA_REGION_4_5; \ + uint32_t CM_SHAPER_RAMA_REGION_6_7; \ + uint32_t CM_SHAPER_RAMA_REGION_8_9; \ + uint32_t CM_SHAPER_RAMA_REGION_10_11; \ + uint32_t CM_SHAPER_RAMA_REGION_12_13; \ + uint32_t CM_SHAPER_RAMA_REGION_14_15; \ + uint32_t CM_SHAPER_RAMA_REGION_16_17; \ + uint32_t CM_SHAPER_RAMA_REGION_18_19; \ + uint32_t CM_SHAPER_RAMA_REGION_20_21; \ + uint32_t CM_SHAPER_RAMA_REGION_22_23; \ + uint32_t CM_SHAPER_RAMA_REGION_24_25; \ + uint32_t CM_SHAPER_RAMA_REGION_26_27; \ + uint32_t CM_SHAPER_RAMA_REGION_28_29; \ + uint32_t CM_SHAPER_RAMA_REGION_30_31; \ + uint32_t CM_SHAPER_RAMA_REGION_32_33; \ + uint32_t CM_SHAPER_LUT_INDEX; \ + uint32_t CM_SHAPER_LUT_DATA; \ + uint32_t CM_ICSC_CONTROL; \ + uint32_t CM_ICSC_C11_C12; \ + uint32_t CM_ICSC_C33_C34; \ + uint32_t CM_BNS_VALUES_R; \ + uint32_t CM_BNS_VALUES_G; \ + uint32_t CM_BNS_VALUES_B; \ + uint32_t CM_DGAM_RAMB_START_CNTL_B; \ + uint32_t CM_DGAM_RAMB_START_CNTL_G; \ + uint32_t CM_DGAM_RAMB_START_CNTL_R; \ + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; \ + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; \ + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; \ + uint32_t CM_DGAM_RAMB_END_CNTL1_B; \ + uint32_t CM_DGAM_RAMB_END_CNTL2_B; \ + uint32_t CM_DGAM_RAMB_END_CNTL1_G; \ + uint32_t CM_DGAM_RAMB_END_CNTL2_G; \ + uint32_t CM_DGAM_RAMB_END_CNTL1_R; \ + uint32_t CM_DGAM_RAMB_END_CNTL2_R; \ + uint32_t CM_DGAM_RAMB_REGION_0_1; \ + uint32_t CM_DGAM_RAMB_REGION_14_15; \ + uint32_t CM_DGAM_RAMA_START_CNTL_B; \ + uint32_t CM_DGAM_RAMA_START_CNTL_G; \ + uint32_t CM_DGAM_RAMA_START_CNTL_R; \ + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; \ + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; \ + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; \ + uint32_t CM_DGAM_RAMA_END_CNTL1_B; \ + uint32_t CM_DGAM_RAMA_END_CNTL2_B; \ + uint32_t CM_DGAM_RAMA_END_CNTL1_G; \ + uint32_t CM_DGAM_RAMA_END_CNTL2_G; \ + uint32_t CM_DGAM_RAMA_END_CNTL1_R; \ + uint32_t CM_DGAM_RAMA_END_CNTL2_R; \ + uint32_t CM_DGAM_RAMA_REGION_0_1; \ + uint32_t CM_DGAM_RAMA_REGION_14_15; \ + uint32_t CM_DGAM_LUT_WRITE_EN_MASK; \ + uint32_t CM_DGAM_LUT_INDEX; \ + uint32_t CM_DGAM_LUT_DATA; \ + uint32_t CM_CONTROL; \ + uint32_t CM_DGAM_CONTROL; \ + uint32_t CM_IGAM_CONTROL; \ + uint32_t CM_IGAM_LUT_RW_CONTROL; \ + uint32_t CM_IGAM_LUT_RW_INDEX; \ + uint32_t CM_IGAM_LUT_SEQ_COLOR; \ + uint32_t FORMAT_CONTROL; \ + uint32_t CNVC_SURFACE_PIXEL_FORMAT; \ + uint32_t CURSOR_CONTROL; \ + uint32_t CURSOR0_CONTROL; \ + uint32_t CURSOR0_COLOR0; \ + uint32_t CURSOR0_COLOR1; struct dcn_dpp_registers { - uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; - uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; - uint32_t OTG_H_BLANK; - uint32_t OTG_V_BLANK; - uint32_t SCL_MODE; - uint32_t LB_DATA_FORMAT; - uint32_t LB_MEMORY_CTRL; - uint32_t DSCL_AUTOCAL; - uint32_t SCL_BLACK_OFFSET; - uint32_t SCL_TAP_CONTROL; - uint32_t SCL_COEF_RAM_TAP_SELECT; - uint32_t SCL_COEF_RAM_TAP_DATA; - uint32_t DSCL_2TAP_CONTROL; - uint32_t MPC_SIZE; - uint32_t SCL_HORZ_FILTER_SCALE_RATIO; - uint32_t SCL_VERT_FILTER_SCALE_RATIO; - uint32_t SCL_HORZ_FILTER_SCALE_RATIO_C; - uint32_t SCL_VERT_FILTER_SCALE_RATIO_C; - uint32_t SCL_HORZ_FILTER_INIT; - uint32_t SCL_HORZ_FILTER_INIT_C; - uint32_t SCL_VERT_FILTER_INIT; - uint32_t SCL_VERT_FILTER_INIT_BOT; - uint32_t SCL_VERT_FILTER_INIT_C; - uint32_t SCL_VERT_FILTER_INIT_BOT_C; - uint32_t RECOUT_START; - uint32_t RECOUT_SIZE; - uint32_t CM_GAMUT_REMAP_CONTROL; - uint32_t CM_GAMUT_REMAP_C11_C12; - uint32_t CM_GAMUT_REMAP_C33_C34; - uint32_t CM_COMA_C11_C12; - uint32_t CM_COMA_C33_C34; - uint32_t CM_COMB_C11_C12; - uint32_t CM_COMB_C33_C34; - uint32_t CM_OCSC_CONTROL; - uint32_t CM_OCSC_C11_C12; - uint32_t CM_OCSC_C33_C34; - uint32_t CM_MEM_PWR_CTRL; - uint32_t CM_RGAM_LUT_DATA; - uint32_t CM_RGAM_LUT_WRITE_EN_MASK; - uint32_t CM_RGAM_LUT_INDEX; - uint32_t CM_RGAM_RAMB_START_CNTL_B; - uint32_t CM_RGAM_RAMB_START_CNTL_G; - uint32_t CM_RGAM_RAMB_START_CNTL_R; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_RGAM_RAMB_END_CNTL1_B; - uint32_t CM_RGAM_RAMB_END_CNTL2_B; - uint32_t CM_RGAM_RAMB_END_CNTL1_G; - uint32_t CM_RGAM_RAMB_END_CNTL2_G; - uint32_t CM_RGAM_RAMB_END_CNTL1_R; - uint32_t CM_RGAM_RAMB_END_CNTL2_R; - uint32_t CM_RGAM_RAMB_REGION_0_1; - uint32_t CM_RGAM_RAMB_REGION_32_33; - uint32_t CM_RGAM_RAMA_START_CNTL_B; - uint32_t CM_RGAM_RAMA_START_CNTL_G; - uint32_t CM_RGAM_RAMA_START_CNTL_R; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_RGAM_RAMA_END_CNTL1_B; - uint32_t CM_RGAM_RAMA_END_CNTL2_B; - uint32_t CM_RGAM_RAMA_END_CNTL1_G; - uint32_t CM_RGAM_RAMA_END_CNTL2_G; - uint32_t CM_RGAM_RAMA_END_CNTL1_R; - uint32_t CM_RGAM_RAMA_END_CNTL2_R; - uint32_t CM_RGAM_RAMA_REGION_0_1; - uint32_t CM_RGAM_RAMA_REGION_32_33; - uint32_t CM_RGAM_CONTROL; - uint32_t CM_CMOUT_CONTROL; - uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; - uint32_t CM_BLNDGAM_CONTROL; - uint32_t CM_BLNDGAM_RAMB_START_CNTL_B; - uint32_t CM_BLNDGAM_RAMB_START_CNTL_G; - uint32_t CM_BLNDGAM_RAMB_START_CNTL_R; - uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_BLNDGAM_RAMB_END_CNTL1_B; - uint32_t CM_BLNDGAM_RAMB_END_CNTL2_B; - uint32_t CM_BLNDGAM_RAMB_END_CNTL1_G; - uint32_t CM_BLNDGAM_RAMB_END_CNTL2_G; - uint32_t CM_BLNDGAM_RAMB_END_CNTL1_R; - uint32_t CM_BLNDGAM_RAMB_END_CNTL2_R; - uint32_t CM_BLNDGAM_RAMB_REGION_0_1; - uint32_t CM_BLNDGAM_RAMB_REGION_2_3; - uint32_t CM_BLNDGAM_RAMB_REGION_4_5; - uint32_t CM_BLNDGAM_RAMB_REGION_6_7; - uint32_t CM_BLNDGAM_RAMB_REGION_8_9; - uint32_t CM_BLNDGAM_RAMB_REGION_10_11; - uint32_t CM_BLNDGAM_RAMB_REGION_12_13; - uint32_t CM_BLNDGAM_RAMB_REGION_14_15; - uint32_t CM_BLNDGAM_RAMB_REGION_16_17; - uint32_t CM_BLNDGAM_RAMB_REGION_18_19; - uint32_t CM_BLNDGAM_RAMB_REGION_20_21; - uint32_t CM_BLNDGAM_RAMB_REGION_22_23; - uint32_t CM_BLNDGAM_RAMB_REGION_24_25; - uint32_t CM_BLNDGAM_RAMB_REGION_26_27; - uint32_t CM_BLNDGAM_RAMB_REGION_28_29; - uint32_t CM_BLNDGAM_RAMB_REGION_30_31; - uint32_t CM_BLNDGAM_RAMB_REGION_32_33; - uint32_t CM_BLNDGAM_RAMA_START_CNTL_B; - uint32_t CM_BLNDGAM_RAMA_START_CNTL_G; - uint32_t CM_BLNDGAM_RAMA_START_CNTL_R; - uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_BLNDGAM_RAMA_END_CNTL1_B; - uint32_t CM_BLNDGAM_RAMA_END_CNTL2_B; - uint32_t CM_BLNDGAM_RAMA_END_CNTL1_G; - uint32_t CM_BLNDGAM_RAMA_END_CNTL2_G; - uint32_t CM_BLNDGAM_RAMA_END_CNTL1_R; - uint32_t CM_BLNDGAM_RAMA_END_CNTL2_R; - uint32_t CM_BLNDGAM_RAMA_REGION_0_1; - uint32_t CM_BLNDGAM_RAMA_REGION_2_3; - uint32_t CM_BLNDGAM_RAMA_REGION_4_5; - uint32_t CM_BLNDGAM_RAMA_REGION_6_7; - uint32_t CM_BLNDGAM_RAMA_REGION_8_9; - uint32_t CM_BLNDGAM_RAMA_REGION_10_11; - uint32_t CM_BLNDGAM_RAMA_REGION_12_13; - uint32_t CM_BLNDGAM_RAMA_REGION_14_15; - uint32_t CM_BLNDGAM_RAMA_REGION_16_17; - uint32_t CM_BLNDGAM_RAMA_REGION_18_19; - uint32_t CM_BLNDGAM_RAMA_REGION_20_21; - uint32_t CM_BLNDGAM_RAMA_REGION_22_23; - uint32_t CM_BLNDGAM_RAMA_REGION_24_25; - uint32_t CM_BLNDGAM_RAMA_REGION_26_27; - uint32_t CM_BLNDGAM_RAMA_REGION_28_29; - uint32_t CM_BLNDGAM_RAMA_REGION_30_31; - uint32_t CM_BLNDGAM_RAMA_REGION_32_33; - uint32_t CM_BLNDGAM_LUT_INDEX; - uint32_t CM_BLNDGAM_LUT_DATA; - uint32_t CM_3DLUT_MODE; - uint32_t CM_3DLUT_INDEX; - uint32_t CM_3DLUT_DATA; - uint32_t CM_3DLUT_DATA_30BIT; - uint32_t CM_3DLUT_READ_WRITE_CONTROL; - uint32_t CM_SHAPER_LUT_WRITE_EN_MASK; - uint32_t CM_SHAPER_CONTROL; - uint32_t CM_SHAPER_RAMB_START_CNTL_B; - uint32_t CM_SHAPER_RAMB_START_CNTL_G; - uint32_t CM_SHAPER_RAMB_START_CNTL_R; - uint32_t CM_SHAPER_RAMB_END_CNTL_B; - uint32_t CM_SHAPER_RAMB_END_CNTL_G; - uint32_t CM_SHAPER_RAMB_END_CNTL_R; - uint32_t CM_SHAPER_RAMB_REGION_0_1; - uint32_t CM_SHAPER_RAMB_REGION_2_3; - uint32_t CM_SHAPER_RAMB_REGION_4_5; - uint32_t CM_SHAPER_RAMB_REGION_6_7; - uint32_t CM_SHAPER_RAMB_REGION_8_9; - uint32_t CM_SHAPER_RAMB_REGION_10_11; - uint32_t CM_SHAPER_RAMB_REGION_12_13; - uint32_t CM_SHAPER_RAMB_REGION_14_15; - uint32_t CM_SHAPER_RAMB_REGION_16_17; - uint32_t CM_SHAPER_RAMB_REGION_18_19; - uint32_t CM_SHAPER_RAMB_REGION_20_21; - uint32_t CM_SHAPER_RAMB_REGION_22_23; - uint32_t CM_SHAPER_RAMB_REGION_24_25; - uint32_t CM_SHAPER_RAMB_REGION_26_27; - uint32_t CM_SHAPER_RAMB_REGION_28_29; - uint32_t CM_SHAPER_RAMB_REGION_30_31; - uint32_t CM_SHAPER_RAMB_REGION_32_33; - uint32_t CM_SHAPER_RAMA_START_CNTL_B; - uint32_t CM_SHAPER_RAMA_START_CNTL_G; - uint32_t CM_SHAPER_RAMA_START_CNTL_R; - uint32_t CM_SHAPER_RAMA_END_CNTL_B; - uint32_t CM_SHAPER_RAMA_END_CNTL_G; - uint32_t CM_SHAPER_RAMA_END_CNTL_R; - uint32_t CM_SHAPER_RAMA_REGION_0_1; - uint32_t CM_SHAPER_RAMA_REGION_2_3; - uint32_t CM_SHAPER_RAMA_REGION_4_5; - uint32_t CM_SHAPER_RAMA_REGION_6_7; - uint32_t CM_SHAPER_RAMA_REGION_8_9; - uint32_t CM_SHAPER_RAMA_REGION_10_11; - uint32_t CM_SHAPER_RAMA_REGION_12_13; - uint32_t CM_SHAPER_RAMA_REGION_14_15; - uint32_t CM_SHAPER_RAMA_REGION_16_17; - uint32_t CM_SHAPER_RAMA_REGION_18_19; - uint32_t CM_SHAPER_RAMA_REGION_20_21; - uint32_t CM_SHAPER_RAMA_REGION_22_23; - uint32_t CM_SHAPER_RAMA_REGION_24_25; - uint32_t CM_SHAPER_RAMA_REGION_26_27; - uint32_t CM_SHAPER_RAMA_REGION_28_29; - uint32_t CM_SHAPER_RAMA_REGION_30_31; - uint32_t CM_SHAPER_RAMA_REGION_32_33; - uint32_t CM_SHAPER_LUT_INDEX; - uint32_t CM_SHAPER_LUT_DATA; - uint32_t CM_ICSC_CONTROL; - uint32_t CM_ICSC_C11_C12; - uint32_t CM_ICSC_C33_C34; - uint32_t CM_BNS_VALUES_R; - uint32_t CM_BNS_VALUES_G; - uint32_t CM_BNS_VALUES_B; - uint32_t CM_DGAM_RAMB_START_CNTL_B; - uint32_t CM_DGAM_RAMB_START_CNTL_G; - uint32_t CM_DGAM_RAMB_START_CNTL_R; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_DGAM_RAMB_END_CNTL1_B; - uint32_t CM_DGAM_RAMB_END_CNTL2_B; - uint32_t CM_DGAM_RAMB_END_CNTL1_G; - uint32_t CM_DGAM_RAMB_END_CNTL2_G; - uint32_t CM_DGAM_RAMB_END_CNTL1_R; - uint32_t CM_DGAM_RAMB_END_CNTL2_R; - uint32_t CM_DGAM_RAMB_REGION_0_1; - uint32_t CM_DGAM_RAMB_REGION_14_15; - uint32_t CM_DGAM_RAMA_START_CNTL_B; - uint32_t CM_DGAM_RAMA_START_CNTL_G; - uint32_t CM_DGAM_RAMA_START_CNTL_R; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_DGAM_RAMA_END_CNTL1_B; - uint32_t CM_DGAM_RAMA_END_CNTL2_B; - uint32_t CM_DGAM_RAMA_END_CNTL1_G; - uint32_t CM_DGAM_RAMA_END_CNTL2_G; - uint32_t CM_DGAM_RAMA_END_CNTL1_R; - uint32_t CM_DGAM_RAMA_END_CNTL2_R; - uint32_t CM_DGAM_RAMA_REGION_0_1; - uint32_t CM_DGAM_RAMA_REGION_14_15; - uint32_t CM_DGAM_LUT_WRITE_EN_MASK; - uint32_t CM_DGAM_LUT_INDEX; - uint32_t CM_DGAM_LUT_DATA; - uint32_t CM_CONTROL; - uint32_t CM_DGAM_CONTROL; - uint32_t CM_IGAM_CONTROL; - uint32_t CM_IGAM_LUT_RW_CONTROL; - uint32_t CM_IGAM_LUT_RW_INDEX; - uint32_t CM_IGAM_LUT_SEQ_COLOR; - uint32_t FORMAT_CONTROL; - uint32_t CNVC_SURFACE_PIXEL_FORMAT; - uint32_t CURSOR_CONTROL; - uint32_t CURSOR0_CONTROL; - uint32_t CURSOR0_COLOR0; - uint32_t CURSOR0_COLOR1; + DPP_COMMON_REG_VARIABLE_LIST }; struct dcn10_dpp { @@ -1284,6 +1283,10 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; +void dpp1_set_cursor_attributes( + struct dpp *dpp_base, + enum dc_cursor_color_format color_format); + bool dpp1_dscl_is_lb_conf_valid( int ceil_vratio, int num_partitions, @@ -1371,7 +1374,7 @@ void dpp1_cm_program_regamma_lutb_settings( const struct pwl_params *params); void dpp1_cm_set_output_csc_adjustment( struct dpp *dpp_base, - const struct out_csc_color_matrix *tbl_entry); + const uint16_t *regval); void dpp1_cm_set_output_csc_default( struct dpp *dpp_base, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 4c90043e7b8c..a5b099023652 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -49,6 +49,8 @@ #define FN(reg_name, field_name) \ dpp->tf_shift->field_name, dpp->tf_mask->field_name +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + struct dcn10_input_csc_matrix { enum dc_color_space color_space; uint16_t regval[12]; @@ -223,18 +225,18 @@ void dpp1_cm_set_gamut_remap( static void dpp1_cm_program_color_matrix( struct dcn10_dpp *dpp, - const struct out_csc_color_matrix *tbl_entry) + const uint16_t *regval) { uint32_t mode; struct color_matrices_reg gam_regs; REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); - if (tbl_entry == NULL) { + if (regval == NULL) { BREAK_TO_DEBUGGER(); return; } - + mode = 4; gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_OCSC_C11; gam_regs.masks.csc_c11 = dpp->tf_mask->CM_OCSC_C11; gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_OCSC_C12; @@ -247,7 +249,7 @@ static void dpp1_cm_program_color_matrix( cm_helper_program_color_matrices( dpp->base.ctx, - tbl_entry->regval, + regval, &gam_regs); } else { @@ -257,7 +259,7 @@ static void dpp1_cm_program_color_matrix( cm_helper_program_color_matrices( dpp->base.ctx, - tbl_entry->regval, + regval, &gam_regs); } } @@ -266,24 +268,18 @@ void dpp1_cm_set_output_csc_default( struct dpp *dpp_base, enum dc_color_space colorspace) { - struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - struct out_csc_color_matrix tbl_entry; - int i, j; - int arr_size = sizeof(output_csc_matrix) / sizeof(struct output_csc_matrix); + const uint16_t *regval = NULL; + int arr_size; uint32_t ocsc_mode = 4; - tbl_entry.color_space = colorspace; - - for (i = 0; i < arr_size; i++) - if (output_csc_matrix[i].color_space == colorspace) { - for (j = 0; j < 12; j++) - tbl_entry.regval[j] = output_csc_matrix[i].regval[j]; - break; - } - + regval = find_color_matrix(colorspace, &arr_size); + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + dpp1_cm_program_color_matrix(dpp, regval); REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - dpp1_cm_program_color_matrix(dpp, &tbl_entry); } static void dpp1_cm_get_reg_field( @@ -315,41 +311,12 @@ static void dpp1_cm_get_reg_field( void dpp1_cm_set_output_csc_adjustment( struct dpp *dpp_base, - const struct out_csc_color_matrix *tbl_entry) + const uint16_t *regval) { struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; uint32_t ocsc_mode = 4; - - /** - *if (tbl_entry != NULL) { - * switch (tbl_entry->color_space) { - * case COLOR_SPACE_SRGB: - * case COLOR_SPACE_2020_RGB_FULLRANGE: - * ocsc_mode = 0; - * break; - * case COLOR_SPACE_SRGB_LIMITED: - * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - * ocsc_mode = 1; - * break; - * case COLOR_SPACE_YCBCR601: - * case COLOR_SPACE_YCBCR601_LIMITED: - * ocsc_mode = 2; - * break; - * case COLOR_SPACE_YCBCR709: - * case COLOR_SPACE_YCBCR709_LIMITED: - * case COLOR_SPACE_2020_YCBCR: - * ocsc_mode = 3; - * break; - * case COLOR_SPACE_UNKNOWN: - * default: - * break; - * } - *} - */ - + dpp1_cm_program_color_matrix(dpp, regval); REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - dpp1_cm_program_color_matrix(dpp, tbl_entry); } void dpp1_cm_power_on_regamma_lut(struct dpp *dpp_base, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index 584e82cc5df3..585b33384002 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -48,9 +48,20 @@ void hubp1_set_blank(struct hubp *hubp, bool blank) HUBP_TTU_DISABLE, blank_en); if (blank) { - REG_WAIT(DCHUBP_CNTL, - HUBP_NO_OUTSTANDING_REQ, 1, - 1, 200); + uint32_t reg_val = REG_READ(DCHUBP_CNTL); + + if (reg_val) { + /* init sequence workaround: in case HUBP is + * power gated, this wait would timeout. + * + * we just wrote reg_val to non-0, if it stay 0 + * it means HUBP is gated + */ + REG_WAIT(DCHUBP_CNTL, + HUBP_NO_OUTSTANDING_REQ, 1, + 1, 200); + } + hubp->mpcc_id = 0xf; hubp->opp_id = 0xf; } @@ -96,10 +107,12 @@ static void hubp1_vready_workaround(struct hubp *hubp, } void hubp1_program_tiling( - struct dcn10_hubp *hubp1, + struct hubp *hubp, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) { + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + REG_UPDATE_6(DCSURF_ADDR_CONFIG, NUM_PIPES, log_2(info->gfx9.num_pipes), NUM_BANKS, log_2(info->gfx9.num_banks), @@ -116,13 +129,14 @@ void hubp1_program_tiling( } void hubp1_program_size_and_rotation( - struct dcn10_hubp *hubp1, + struct hubp *hubp, enum dc_rotation_angle rotation, enum surface_pixel_format format, const union plane_size *plane_size, struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t pitch, meta_pitch, pitch_c, meta_pitch_c, mirror; /* Program data and meta surface pitch (calculation from addrlib) @@ -178,9 +192,10 @@ void hubp1_program_size_and_rotation( } void hubp1_program_pixel_format( - struct dcn10_hubp *hubp1, + struct hubp *hubp, enum surface_pixel_format format) { + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t red_bar = 3; uint32_t blue_bar = 2; @@ -424,13 +439,11 @@ void hubp1_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { - struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); - hubp1_program_tiling(hubp1, tiling_info, format); + hubp1_program_tiling(hubp, tiling_info, format); hubp1_program_size_and_rotation( - hubp1, rotation, format, plane_size, dcc, horizontal_mirror); - hubp1_program_pixel_format(hubp1, format); + hubp, rotation, format, plane_size, dcc, horizontal_mirror); + hubp1_program_pixel_format(hubp, format); } void hubp1_program_requestor( @@ -765,42 +778,7 @@ void hubp1_read_state(struct dcn10_hubp *hubp1, QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); } -enum cursor_pitch { - CURSOR_PITCH_64_PIXELS = 0, - CURSOR_PITCH_128_PIXELS, - CURSOR_PITCH_256_PIXELS -}; - -enum cursor_lines_per_chunk { - CURSOR_LINE_PER_CHUNK_2 = 1, - CURSOR_LINE_PER_CHUNK_4, - CURSOR_LINE_PER_CHUNK_8, - CURSOR_LINE_PER_CHUNK_16 -}; - -static bool ippn10_cursor_program_control( - struct dcn10_hubp *hubp1, - bool pixel_data_invert, - enum dc_cursor_color_format color_format) -{ - if (REG(CURSOR_SETTINS)) - REG_SET_2(CURSOR_SETTINS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - else - REG_SET_2(CURSOR_SETTINGS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - - return true; -} - -static enum cursor_pitch ippn10_get_cursor_pitch( - unsigned int pitch) +enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch) { enum cursor_pitch hw_pitch; @@ -823,7 +801,7 @@ static enum cursor_pitch ippn10_get_cursor_pitch( return hw_pitch; } -static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( +static enum cursor_lines_per_chunk hubp1_get_lines_per_chunk( unsigned int cur_width, enum dc_cursor_color_format format) { @@ -849,8 +827,8 @@ void hubp1_cursor_set_attributes( const struct dc_cursor_attributes *attr) { struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); - enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( + enum cursor_pitch hw_pitch = hubp1_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = hubp1_get_lines_per_chunk( attr->width, attr->color_format); hubp->curs_attr = *attr; @@ -863,13 +841,17 @@ void hubp1_cursor_set_attributes( REG_UPDATE_2(CURSOR_SIZE, CURSOR_WIDTH, attr->width, CURSOR_HEIGHT, attr->height); + REG_UPDATE_3(CURSOR_CONTROL, CURSOR_MODE, attr->color_format, CURSOR_PITCH, hw_pitch, CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(hubp1, - attr->attribute_flags.bits.INVERT_PIXEL_DATA, - attr->color_format); + + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); } void hubp1_cursor_set_position( @@ -909,7 +891,8 @@ void hubp1_cursor_set_position( cur_en = 0; /* not visible beyond left edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - hubp1_cursor_set_attributes(hubp, &hubp->curs_attr); + hubp->funcs->set_cursor_attributes(hubp, &hubp->curs_attr); + REG_UPDATE(CURSOR_CONTROL, CURSOR_ENABLE, cur_en); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h index a7834dd50716..33e91d9c010f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h @@ -127,113 +127,110 @@ SRI(CURSOR_HOT_SPOT, CURSOR, id), \ SRI(CURSOR_DST_OFFSET, CURSOR, id) - - -struct dcn_mi_registers { - uint32_t DCHUBP_CNTL; - uint32_t HUBPREQ_DEBUG_DB; - uint32_t DCSURF_ADDR_CONFIG; - uint32_t DCSURF_TILING_CONFIG; - uint32_t DCSURF_SURFACE_PITCH; - uint32_t DCSURF_SURFACE_PITCH_C; - uint32_t DCSURF_SURFACE_CONFIG; - uint32_t DCSURF_FLIP_CONTROL; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; - uint32_t DCSURF_PRI_VIEWPORT_START; - uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; - uint32_t DCSURF_SEC_VIEWPORT_START; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; - uint32_t DCSURF_PRI_VIEWPORT_START_C; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; - uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS; - uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH; - uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C; - uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; - uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; - uint32_t DCSURF_SURFACE_INUSE; - uint32_t DCSURF_SURFACE_INUSE_HIGH; - uint32_t DCSURF_SURFACE_INUSE_C; - uint32_t DCSURF_SURFACE_INUSE_HIGH_C; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE_C; - uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C; - uint32_t DCSURF_SURFACE_CONTROL; - uint32_t HUBPRET_CONTROL; - uint32_t DCN_EXPANSION_MODE; - uint32_t DCHUBP_REQ_SIZE_CONFIG; - uint32_t DCHUBP_REQ_SIZE_CONFIG_C; - uint32_t BLANK_OFFSET_0; - uint32_t BLANK_OFFSET_1; - uint32_t DST_DIMENSIONS; - uint32_t DST_AFTER_SCALER; - uint32_t PREFETCH_SETTINS; - uint32_t PREFETCH_SETTINGS; - uint32_t VBLANK_PARAMETERS_0; - uint32_t REF_FREQ_TO_PIX_FREQ; - uint32_t VBLANK_PARAMETERS_1; - uint32_t VBLANK_PARAMETERS_3; - uint32_t NOM_PARAMETERS_0; - uint32_t NOM_PARAMETERS_1; - uint32_t NOM_PARAMETERS_4; - uint32_t NOM_PARAMETERS_5; - uint32_t PER_LINE_DELIVERY_PRE; - uint32_t PER_LINE_DELIVERY; - uint32_t PREFETCH_SETTINS_C; - uint32_t PREFETCH_SETTINGS_C; - uint32_t VBLANK_PARAMETERS_2; - uint32_t VBLANK_PARAMETERS_4; - uint32_t NOM_PARAMETERS_2; - uint32_t NOM_PARAMETERS_3; - uint32_t NOM_PARAMETERS_6; - uint32_t NOM_PARAMETERS_7; - uint32_t DCN_TTU_QOS_WM; - uint32_t DCN_GLOBAL_TTU_CNTL; - uint32_t DCN_SURF0_TTU_CNTL0; - uint32_t DCN_SURF0_TTU_CNTL1; - uint32_t DCN_SURF1_TTU_CNTL0; - uint32_t DCN_SURF1_TTU_CNTL1; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB; - uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB; - uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB; - uint32_t DCN_VM_MX_L1_TLB_CNTL; - uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; - uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; - uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB; - uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; - uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; - uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; - uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; - uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; - uint32_t DCHUBBUB_SDPIF_FB_BASE; - uint32_t DCHUBBUB_SDPIF_FB_OFFSET; - uint32_t DCN_VM_FB_LOCATION_TOP; - uint32_t DCN_VM_FB_LOCATION_BASE; - uint32_t DCN_VM_FB_OFFSET; - uint32_t DCN_VM_AGP_BASE; - uint32_t DCN_VM_AGP_BOT; - uint32_t DCN_VM_AGP_TOP; - uint32_t CURSOR_SETTINS; - uint32_t CURSOR_SETTINGS; - uint32_t CURSOR_SURFACE_ADDRESS_HIGH; - uint32_t CURSOR_SURFACE_ADDRESS; - uint32_t CURSOR_SIZE; - uint32_t CURSOR_CONTROL; - uint32_t CURSOR_POSITION; - uint32_t CURSOR_HOT_SPOT; - uint32_t CURSOR_DST_OFFSET; -}; +#define HUBP_COMMON_REG_VARIABLE_LIST \ + uint32_t DCHUBP_CNTL; \ + uint32_t HUBPREQ_DEBUG_DB; \ + uint32_t DCSURF_ADDR_CONFIG; \ + uint32_t DCSURF_TILING_CONFIG; \ + uint32_t DCSURF_SURFACE_PITCH; \ + uint32_t DCSURF_SURFACE_PITCH_C; \ + uint32_t DCSURF_SURFACE_CONFIG; \ + uint32_t DCSURF_FLIP_CONTROL; \ + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; \ + uint32_t DCSURF_PRI_VIEWPORT_START; \ + uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; \ + uint32_t DCSURF_SEC_VIEWPORT_START; \ + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; \ + uint32_t DCSURF_PRI_VIEWPORT_START_C; \ + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; \ + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; \ + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; \ + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS; \ + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH; \ + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS; \ + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH; \ + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS; \ + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C; \ + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; \ + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; \ + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; \ + uint32_t DCSURF_SURFACE_INUSE; \ + uint32_t DCSURF_SURFACE_INUSE_HIGH; \ + uint32_t DCSURF_SURFACE_INUSE_C; \ + uint32_t DCSURF_SURFACE_INUSE_HIGH_C; \ + uint32_t DCSURF_SURFACE_EARLIEST_INUSE; \ + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH; \ + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_C; \ + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C; \ + uint32_t DCSURF_SURFACE_CONTROL; \ + uint32_t HUBPRET_CONTROL; \ + uint32_t DCN_EXPANSION_MODE; \ + uint32_t DCHUBP_REQ_SIZE_CONFIG; \ + uint32_t DCHUBP_REQ_SIZE_CONFIG_C; \ + uint32_t BLANK_OFFSET_0; \ + uint32_t BLANK_OFFSET_1; \ + uint32_t DST_DIMENSIONS; \ + uint32_t DST_AFTER_SCALER; \ + uint32_t PREFETCH_SETTINS; \ + uint32_t PREFETCH_SETTINGS; \ + uint32_t VBLANK_PARAMETERS_0; \ + uint32_t REF_FREQ_TO_PIX_FREQ; \ + uint32_t VBLANK_PARAMETERS_1; \ + uint32_t VBLANK_PARAMETERS_3; \ + uint32_t NOM_PARAMETERS_0; \ + uint32_t NOM_PARAMETERS_1; \ + uint32_t NOM_PARAMETERS_4; \ + uint32_t NOM_PARAMETERS_5; \ + uint32_t PER_LINE_DELIVERY_PRE; \ + uint32_t PER_LINE_DELIVERY; \ + uint32_t PREFETCH_SETTINS_C; \ + uint32_t PREFETCH_SETTINGS_C; \ + uint32_t VBLANK_PARAMETERS_2; \ + uint32_t VBLANK_PARAMETERS_4; \ + uint32_t NOM_PARAMETERS_2; \ + uint32_t NOM_PARAMETERS_3; \ + uint32_t NOM_PARAMETERS_6; \ + uint32_t NOM_PARAMETERS_7; \ + uint32_t DCN_TTU_QOS_WM; \ + uint32_t DCN_GLOBAL_TTU_CNTL; \ + uint32_t DCN_SURF0_TTU_CNTL0; \ + uint32_t DCN_SURF0_TTU_CNTL1; \ + uint32_t DCN_SURF1_TTU_CNTL0; \ + uint32_t DCN_SURF1_TTU_CNTL1; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB; \ + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB; \ + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB; \ + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB; \ + uint32_t DCN_VM_MX_L1_TLB_CNTL; \ + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; \ + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; \ + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; \ + uint32_t DCHUBBUB_SDPIF_FB_BASE; \ + uint32_t DCHUBBUB_SDPIF_FB_OFFSET; \ + uint32_t DCN_VM_FB_LOCATION_TOP; \ + uint32_t DCN_VM_FB_LOCATION_BASE; \ + uint32_t DCN_VM_FB_OFFSET; \ + uint32_t DCN_VM_AGP_BASE; \ + uint32_t DCN_VM_AGP_BOT; \ + uint32_t DCN_VM_AGP_TOP; \ + uint32_t CURSOR_SETTINS; \ + uint32_t CURSOR_SETTINGS; \ + uint32_t CURSOR_SURFACE_ADDRESS_HIGH; \ + uint32_t CURSOR_SURFACE_ADDRESS; \ + uint32_t CURSOR_SIZE; \ + uint32_t CURSOR_CONTROL; \ + uint32_t CURSOR_POSITION; \ + uint32_t CURSOR_HOT_SPOT; \ + uint32_t CURSOR_DST_OFFSET #define HUBP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -397,7 +394,6 @@ struct dcn_mi_registers { HUBP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ HUBP_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh) - #define DCN_HUBP_REG_FIELD_LIST(type) \ type HUBP_BLANK_EN;\ type HUBP_TTU_DISABLE;\ @@ -577,6 +573,10 @@ struct dcn_mi_registers { type CURSOR_DST_X_OFFSET; \ type OUTPUT_FP +struct dcn_mi_registers { + HUBP_COMMON_REG_VARIABLE_LIST; +}; + struct dcn_mi_shift { DCN_HUBP_REG_FIELD_LIST(uint8_t); }; @@ -611,11 +611,11 @@ void hubp1_program_requestor( struct _vcs_dpi_display_rq_regs_st *rq_regs); void hubp1_program_pixel_format( - struct dcn10_hubp *hubp, + struct hubp *hubp, enum surface_pixel_format format); void hubp1_program_size_and_rotation( - struct dcn10_hubp *hubp, + struct hubp *hubp, enum dc_rotation_angle rotation, enum surface_pixel_format format, const union plane_size *plane_size, @@ -623,7 +623,7 @@ void hubp1_program_size_and_rotation( bool horizontal_mirror); void hubp1_program_tiling( - struct dcn10_hubp *hubp, + struct hubp *hubp, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format); @@ -681,4 +681,6 @@ struct dcn_hubp_state { void hubp1_read_state(struct dcn10_hubp *hubp1, struct dcn_hubp_state *s); +enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 8e2ddbc2129c..82572863acab 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -32,7 +32,7 @@ #include "dce/dce_hwseq.h" #include "abm.h" #include "dmcu.h" -#include "dcn10/dcn10_timing_generator.h" +#include "dcn10_optc.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" #include "timing_generator.h" @@ -43,6 +43,7 @@ #include "custom_float.h" #include "dcn10_hubp.h" #include "dcn10_hubbub.h" +#include "dcn10_cm_common.h" #define CTX \ hws->ctx @@ -158,7 +159,7 @@ void dcn10_log_hw_state(struct dc *dc) struct timing_generator *tg = pool->timing_generators[i]; struct dcn_otg_state s = {0}; - tgn10_read_otg_state(DCN10TG_FROM_TG(tg), &s); + optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s); //only print if OTG master is enabled if ((s.otg_enabled & 1) == 0) @@ -425,6 +426,34 @@ static void bios_golden_init(struct dc *dc) } } +static void false_optc_underflow_wa( + struct dc *dc, + const struct dc_stream_state *stream, + struct timing_generator *tg) +{ + int i; + bool underflow; + + if (!dc->hwseq->wa.false_optc_underflow) + return; + + underflow = tg->funcs->is_optc_underflow_occurred(tg); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + + if (old_pipe_ctx->stream != stream) + continue; + + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx); + } + + tg->funcs->set_blank_data_double_buffer(tg, true); + + if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow) + tg->funcs->clear_optc_underflow(tg); +} + static enum dc_status dcn10_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, struct dc_state *context, @@ -433,9 +462,6 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( struct dc_stream_state *stream = pipe_ctx->stream; enum dc_color_space color_space; struct tg_color black_color = {0}; - bool enableStereo = stream->timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? - false:true; - bool rightEyePolarity = stream->timing.flags.RIGHT_EYE_3D_POLARITY; /* by upper caller loop, pipe0 is parent pipe and be called first. * back end is set up by for pipe0. Other children pipe share back end @@ -470,11 +496,6 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( &stream->timing, true); - pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity( - pipe_ctx->stream_res.opp, - enableStereo, - rightEyePolarity); - #if 0 /* move to after enable_crtc */ /* TODO: OPP FMT, ABM. etc. should be done here. */ /* or FPGA now. instance 0 only. TODO: move to opp.c */ @@ -489,12 +510,18 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( /* program otg blank color */ color_space = stream->output_color_space; color_space_to_black_color(dc, color_space, &black_color); - pipe_ctx->stream_res.tg->funcs->set_blank_color( - pipe_ctx->stream_res.tg, - &black_color); - pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); - hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg); + if (pipe_ctx->stream_res.tg->funcs->set_blank_color) + pipe_ctx->stream_res.tg->funcs->set_blank_color( + pipe_ctx->stream_res.tg, + &black_color); + + if (pipe_ctx->stream_res.tg->funcs->is_blanked && + !pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) { + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); + hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg); + false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg); + } /* VTG is within DCHUB command block. DCFCLK is always on */ if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) { @@ -573,41 +600,34 @@ static void plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) int fe_idx = pipe_ctx->pipe_idx; struct hubp *hubp = dc->res_pool->hubps[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; - int opp_id, z_idx; - int mpcc_id = -1; + int opp_id; + struct mpc_tree *mpc_tree_params; + struct mpcc *mpcc_to_remove = NULL; /* look at tree rather than mi here to know if we already reset */ for (opp_id = 0; opp_id < dc->res_pool->pipe_count; opp_id++) { struct output_pixel_processor *opp = dc->res_pool->opps[opp_id]; - for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) { - if (opp->mpc_tree.dpp[z_idx] == fe_idx) { - mpcc_id = opp->mpc_tree.mpcc[z_idx]; - break; - } - } - if (mpcc_id != -1) + mpc_tree_params = &(opp->mpc_tree_params); + mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, fe_idx); + if (mpcc_to_remove != NULL) break; } + /*Already reset*/ if (opp_id == dc->res_pool->pipe_count) return; - mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree), - dc->res_pool->opps[opp_id]->inst, fe_idx); + mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove); + dc->res_pool->opps[opp_id]->mpcc_disconnect_pending[fe_idx] = true; + + dc->optimized_required = true; if (hubp->funcs->hubp_disconnect) hubp->funcs->hubp_disconnect(hubp); if (dc->debug.sanity_checks) dcn10_verify_allow_pstate_change_high(dc); - - pipe_ctx->stream = NULL; - memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res)); - memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res)); - pipe_ctx->top_pipe = NULL; - pipe_ctx->bottom_pipe = NULL; - pipe_ctx->plane_state = NULL; } static void plane_atomic_power_down(struct dc *dc, int fe_idx) @@ -636,29 +656,30 @@ static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) int fe_idx = pipe_ctx->pipe_idx; struct dce_hwseq *hws = dc->hwseq; struct hubp *hubp = dc->res_pool->hubps[fe_idx]; - struct mpc *mpc = dc->res_pool->mpc; int opp_id = hubp->opp_id; - struct output_pixel_processor *opp; - if (opp_id != 0xf) { - mpc->funcs->wait_for_idle(mpc, hubp->mpcc_id); - opp = dc->res_pool->opps[hubp->opp_id]; - opp->mpcc_disconnect_pending[hubp->mpcc_id] = false; - hubp->funcs->set_blank(hubp, true); - } + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx); REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); - if (opp_id != 0xf && dc->res_pool->opps[opp_id]->mpc_tree.num_pipes == 0) + if (opp_id != 0xf && dc->res_pool->opps[opp_id]->mpc_tree_params.opp_list == NULL) REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 0); hubp->power_gated = true; + dc->optimized_required = false; /* We're powering off, no need to optimize */ plane_atomic_power_down(dc, fe_idx); + + pipe_ctx->stream = NULL; + memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res)); + memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res)); + pipe_ctx->top_pipe = NULL; + pipe_ctx->bottom_pipe = NULL; + pipe_ctx->plane_state = NULL; } static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) @@ -740,25 +761,27 @@ static void dcn10_init_hw(struct dc *dc) } } + /* Reset all MPCC muxes */ + dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc); + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct timing_generator *tg = dc->res_pool->timing_generators[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct output_pixel_processor *opp = dc->res_pool->opps[i]; - struct mpc_tree_cfg *mpc_tree = &opp->mpc_tree; struct hubp *hubp = dc->res_pool->hubps[i]; - mpc_tree->dpp[0] = i; - mpc_tree->mpcc[0] = i; - mpc_tree->num_pipes = 1; - pipe_ctx->stream_res.tg = tg; pipe_ctx->pipe_idx = i; pipe_ctx->plane_res.hubp = hubp; hubp->mpcc_id = i; - hubp->opp_id = dc->res_pool->mpc->funcs->get_opp_id(dc->res_pool->mpc, i); + hubp->opp_id = 0xf; hubp->power_gated = false; + dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst; + dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL; + dc->res_pool->opps[i]->mpcc_disconnect_pending[i] = true; + pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; + plane_atomic_disconnect(dc, pipe_ctx); } @@ -929,280 +952,10 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx, return result; } -/*modify the method to handle rgb for arr_points*/ -static bool convert_to_custom_float( - struct pwl_result_data *rgb_resulted, - struct curve_points *arr_points, - uint32_t hw_points_num) -{ - struct custom_float_format fmt; - - struct pwl_result_data *rgb = rgb_resulted; - - uint32_t i = 0; - - fmt.exponenta_bits = 6; - fmt.mantissa_bits = 12; - fmt.sign = false; - - if (!convert_to_custom_float_format(arr_points[0].x, &fmt, - &arr_points[0].custom_float_x)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format(arr_points[0].offset, &fmt, - &arr_points[0].custom_float_offset)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format(arr_points[0].slope, &fmt, - &arr_points[0].custom_float_slope)) { - BREAK_TO_DEBUGGER(); - return false; - } - - fmt.mantissa_bits = 10; - fmt.sign = false; - - if (!convert_to_custom_float_format(arr_points[1].x, &fmt, - &arr_points[1].custom_float_x)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format(arr_points[1].y, &fmt, - &arr_points[1].custom_float_y)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format(arr_points[1].slope, &fmt, - &arr_points[1].custom_float_slope)) { - BREAK_TO_DEBUGGER(); - return false; - } - fmt.mantissa_bits = 12; - fmt.sign = true; - while (i != hw_points_num) { - if (!convert_to_custom_float_format(rgb->red, &fmt, - &rgb->red_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format(rgb->green, &fmt, - &rgb->green_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - if (!convert_to_custom_float_format(rgb->blue, &fmt, - &rgb->blue_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - if (!convert_to_custom_float_format(rgb->delta_red, &fmt, - &rgb->delta_red_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format(rgb->delta_green, &fmt, - &rgb->delta_green_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, - &rgb->delta_blue_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - ++rgb; - ++i; - } - - return true; -} -#define MAX_REGIONS_NUMBER 34 -#define MAX_LOW_POINT 25 -#define NUMBER_SEGMENTS 32 - -static bool -dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, - struct pwl_params *regamma_params) -{ - struct curve_points *arr_points; - struct pwl_result_data *rgb_resulted; - struct pwl_result_data *rgb; - struct pwl_result_data *rgb_plus_1; - struct fixed31_32 y_r; - struct fixed31_32 y_g; - struct fixed31_32 y_b; - struct fixed31_32 y1_min; - struct fixed31_32 y3_max; - - int32_t segment_start, segment_end; - int32_t i; - uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; - - if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS) - return false; - - PERF_TRACE(); - - arr_points = regamma_params->arr_points; - rgb_resulted = regamma_params->rgb_resulted; - hw_points = 0; - - memset(regamma_params, 0, sizeof(struct pwl_params)); - memset(seg_distr, 0, sizeof(seg_distr)); - - if (output_tf->tf == TRANSFER_FUNCTION_PQ) { - /* 32 segments - * segments are from 2^-25 to 2^7 - */ - for (i = 0; i < 32 ; i++) - seg_distr[i] = 3; - - segment_start = -25; - segment_end = 7; - } else { - /* 10 segments - * segment is from 2^-10 to 2^0 - * There are less than 256 points, for optimization - */ - seg_distr[0] = 3; - seg_distr[1] = 4; - seg_distr[2] = 4; - seg_distr[3] = 4; - seg_distr[4] = 4; - seg_distr[5] = 4; - seg_distr[6] = 4; - seg_distr[7] = 4; - seg_distr[8] = 5; - seg_distr[9] = 5; - - segment_start = -10; - segment_end = 0; - } - - for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++) - seg_distr[i] = -1; - - for (k = 0; k < MAX_REGIONS_NUMBER; k++) { - if (seg_distr[k] != -1) - hw_points += (1 << seg_distr[k]); - } - - j = 0; - for (k = 0; k < (segment_end - segment_start); k++) { - increment = NUMBER_SEGMENTS / (1 << seg_distr[k]); - start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS; - for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) { - if (j == hw_points - 1) - break; - rgb_resulted[j].red = output_tf->tf_pts.red[i]; - rgb_resulted[j].green = output_tf->tf_pts.green[i]; - rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; - j++; - } - } - - /* last point */ - start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS; - rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; - rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; - rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; - - arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_start)); - arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), - dal_fixed31_32_from_int(segment_end)); - - y_r = rgb_resulted[0].red; - y_g = rgb_resulted[0].green; - y_b = rgb_resulted[0].blue; - - y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); - - arr_points[0].y = y1_min; - arr_points[0].slope = dal_fixed31_32_div(arr_points[0].y, arr_points[0].x); - y_r = rgb_resulted[hw_points - 1].red; - y_g = rgb_resulted[hw_points - 1].green; - y_b = rgb_resulted[hw_points - 1].blue; - - /* see comment above, m_arrPoints[1].y should be the Y value for the - * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) - */ - y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); - - arr_points[1].y = y3_max; - - arr_points[1].slope = dal_fixed31_32_zero; - - if (output_tf->tf == TRANSFER_FUNCTION_PQ) { - /* for PQ, we want to have a straight line from last HW X point, - * and the slope to be such that we hit 1.0 at 10000 nits. - */ - const struct fixed31_32 end_value = - dal_fixed31_32_from_int(125); - - arr_points[1].slope = dal_fixed31_32_div( - dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), - dal_fixed31_32_sub(end_value, arr_points[1].x)); - } - - regamma_params->hw_points_num = hw_points; - - i = 1; - for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) { - if (seg_distr[k] != -1) { - regamma_params->arr_curve_points[k].segments_num = - seg_distr[k]; - regamma_params->arr_curve_points[i].offset = - regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]); - } - i++; - } - - if (seg_distr[k] != -1) - regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; - - rgb = rgb_resulted; - rgb_plus_1 = rgb_resulted + 1; - - i = 1; - - while (i != hw_points + 1) { - if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) - rgb_plus_1->red = rgb->red; - if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) - rgb_plus_1->green = rgb->green; - if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) - rgb_plus_1->blue = rgb->blue; - - rgb->delta_red = dal_fixed31_32_sub(rgb_plus_1->red, rgb->red); - rgb->delta_green = dal_fixed31_32_sub(rgb_plus_1->green, rgb->green); - rgb->delta_blue = dal_fixed31_32_sub(rgb_plus_1->blue, rgb->blue); - - ++rgb_plus_1; - ++rgb; - ++i; - } - - convert_to_custom_float(rgb_resulted, arr_points, hw_points); - - PERF_TRACE(); - - return true; -} static bool dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx, @@ -1223,9 +976,9 @@ dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx, /* dcn10_translate_regamma_to_hw_format takes 750us, only do it when full * update. */ - else if (dcn10_translate_regamma_to_hw_format( + else if (cm_helper_translate_curve_to_hw_format( stream->out_transfer_func, - &dpp->regamma_params)) { + &dpp->regamma_params, false)) { dpp->funcs->dpp_program_regamma_pwl( dpp, &dpp->regamma_params, OPP_REGAMMA_USER); @@ -1579,7 +1332,6 @@ static void dcn10_enable_plane( /* make sure OPP_PIPE_CLOCK_EN = 1 */ REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->stream_res.tg->inst], OPP_PIPE_CLOCK_EN, 1); - /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ /* TODO: enable/disable in dm as per update type. if (plane_state) { @@ -1672,60 +1424,15 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace, uint16_t *matrix) { - int i; - struct out_csc_color_matrix tbl_entry; - if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { - enum dc_color_space color_space = - pipe_ctx->stream->output_color_space; - - //uint16_t matrix[12]; - for (i = 0; i < 12; i++) - tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - - tbl_entry.color_space = color_space; - //tbl_entry.regval = matrix; - if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) - pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, &tbl_entry); + pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix); } else { if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL) pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace); } } -static void set_mpc_output_csc(struct dc *dc, - struct pipe_ctx *pipe_ctx, - enum dc_color_space colorspace, - uint16_t *matrix, - int opp_id) -{ - struct mpc *mpc = dc->res_pool->mpc; - int i; - struct out_csc_color_matrix tbl_entry; - enum mpc_output_csc_mode ocsc_mode = MPC_OUTPUT_CSC_COEF_A; - - - if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { - //uint16_t matrix[12]; - for (i = 0; i < 12; i++) - tbl_entry.regval[i] = matrix[i]; - tbl_entry.color_space = colorspace; - - if (mpc->funcs->set_output_csc != NULL) - mpc->funcs->set_output_csc(mpc, - opp_id, - &tbl_entry, - ocsc_mode); - } else { - if (mpc->funcs->set_ocsc_default != NULL) - mpc->funcs->set_ocsc_default(mpc, - opp_id, - colorspace, - ocsc_mode); - } -} - static void program_output_csc(struct dc *dc, struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace, @@ -1736,13 +1443,6 @@ static void program_output_csc(struct dc *dc, program_csc_matrix(pipe_ctx, colorspace, matrix); - else - set_mpc_output_csc(dc, - pipe_ctx, - colorspace, - matrix, - opp_id); - } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) @@ -1914,35 +1614,73 @@ static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state) static void update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) { - struct mpcc_cfg mpcc_cfg = {0}; struct hubp *hubp = pipe_ctx->plane_res.hubp; - struct pipe_ctx *top_pipe; - bool per_pixel_alpha = - pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; + struct mpcc_blnd_cfg blnd_cfg; + bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; + int mpcc_id; + struct mpcc *new_mpcc; + struct mpc *mpc = dc->res_pool->mpc; + struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params); /* TODO: proper fix once fpga works */ - mpcc_cfg.dpp_id = hubp->inst; - mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst; - mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree); - for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) - mpcc_cfg.z_index++; if (dc->debug.surface_visual_confirm) dcn10_get_surface_visual_confirm_color( - pipe_ctx, &mpcc_cfg.black_color); + pipe_ctx, &blnd_cfg.black_color); else color_space_to_black_color( dc, pipe_ctx->stream->output_color_space, - &mpcc_cfg.black_color); - mpcc_cfg.per_pixel_alpha = per_pixel_alpha; + &blnd_cfg.black_color); + + if (per_pixel_alpha) + blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; + else + blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA; + + blnd_cfg.overlap_only = false; + blnd_cfg.global_alpha = 0xff; + blnd_cfg.global_gain = 0xff; + /* DCN1.0 has output CM before MPC which seems to screw with * pre-multiplied alpha. */ - mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( + blnd_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->output_color_space) && per_pixel_alpha; - hubp->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); - hubp->opp_id = mpcc_cfg.opp_id; + + /* + * TODO: remove hack + * Note: currently there is a bug in init_hw such that + * on resume from hibernate, BIOS sets up MPCC0, and + * we do mpcc_remove but the mpcc cannot go to idle + * after remove. This cause us to pick mpcc1 here, + * which causes a pstate hang for yet unknown reason. + */ + mpcc_id = hubp->inst; + + /* check if this MPCC is already being used */ + new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id); + /* remove MPCC if being used */ + if (new_mpcc != NULL) + mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc); + else + if (dc->debug.sanity_checks) + mpc->funcs->assert_mpcc_idle_before_connect( + dc->res_pool->mpc, mpcc_id); + + /* Call MPC to insert new plane */ + new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc, + mpc_tree_params, + &blnd_cfg, + NULL, + NULL, + hubp->inst, + mpcc_id); + + ASSERT(new_mpcc != NULL); + + hubp->opp_id = pipe_ctx->stream_res.opp->inst; + hubp->mpcc_id = mpcc_id; } static void update_scaler(struct pipe_ctx *pipe_ctx) @@ -1971,7 +1709,7 @@ static void update_dchubp_dpp( union plane_size size = plane_state->plane_size; /* depends on DML calculation, DPP clock value may change dynamically */ - if (pipe_ctx->plane_state->update_flags.raw != 0) { + if (plane_state->update_flags.bits.full_update) { enable_dppclk( dc->hwseq, pipe_ctx->pipe_idx, @@ -2015,7 +1753,8 @@ static void update_dchubp_dpp( } if (plane_state->update_flags.bits.full_update || - plane_state->update_flags.bits.scaling_change) { + plane_state->update_flags.bits.scaling_change || + plane_state->update_flags.bits.position_change) { hubp->funcs->mem_program_viewport( hubp, &pipe_ctx->plane_res.scl_data.viewport, @@ -2037,7 +1776,9 @@ static void update_dchubp_dpp( plane_state->update_flags.bits.horizontal_mirror_change || plane_state->update_flags.bits.rotation_change || plane_state->update_flags.bits.swizzle_change || - plane_state->update_flags.bits.bpp_change) { + plane_state->update_flags.bits.dcc_change || + plane_state->update_flags.bits.bpp_change || + plane_state->update_flags.bits.scaling_change) { hubp->funcs->hubp_program_surface_config( hubp, plane_state->format, @@ -2062,6 +1803,7 @@ static void program_all_pipe_in_tree( struct pipe_ctx *pipe_ctx, struct dc_state *context) { + if (pipe_ctx->top_pipe == NULL) { pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; @@ -2072,7 +1814,11 @@ static void program_all_pipe_in_tree( pipe_ctx->stream_res.tg->funcs->program_global_sync( pipe_ctx->stream_res.tg); - pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, !is_pipe_tree_visible(pipe_ctx)); + + if (pipe_ctx->stream_res.tg->funcs->set_blank) + pipe_ctx->stream_res.tg->funcs->set_blank( + pipe_ctx->stream_res.tg, + !is_pipe_tree_visible(pipe_ctx)); } if (pipe_ctx->plane_state != NULL) { @@ -2179,6 +1925,7 @@ static void dcn10_apply_ctx_for_surface( { int i; struct timing_generator *tg; + struct output_pixel_processor *opp; bool removed_pipe[4] = { false }; unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; bool program_water_mark = false; @@ -2189,6 +1936,8 @@ static void dcn10_apply_ctx_for_surface( if (!top_pipe_to_program) return; + opp = top_pipe_to_program->stream_res.opp; + tg = top_pipe_to_program->stream_res.tg; tg->funcs->lock(tg); @@ -2196,7 +1945,8 @@ static void dcn10_apply_ctx_for_surface( if (num_planes == 0) { /* OTG blank before remove all front end */ - tg->funcs->set_blank(tg, true); + if (tg->funcs->set_blank) + tg->funcs->set_blank(tg, true); } /* Disconnect unused mpcc */ @@ -2236,24 +1986,14 @@ static void dcn10_apply_ctx_for_surface( } } - if (num_planes > 0) { + if (num_planes > 0) program_all_pipe_in_tree(dc, top_pipe_to_program, context); - /* TODO: this is a hack w/a for switching from mpo to pipe split */ - if (stream->cursor_attributes.address.quad_part != 0) { - struct dc_cursor_position position = { 0 }; - - dc_stream_set_cursor_position( - (struct dc_stream_state *)stream, - &position); - dc_stream_set_cursor_attributes( - (struct dc_stream_state *)stream, - &stream->cursor_attributes); - } - } - tg->funcs->unlock(tg); + if (num_planes == 0) + false_optc_underflow_wa(dc, stream, tg); + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; @@ -2264,7 +2004,7 @@ static void dcn10_apply_ctx_for_surface( pipe_ctx->plane_state->update_flags.bits.full_update) program_water_mark = true; - if (removed_pipe[i] && num_planes == 0) + if (removed_pipe[i]) dcn10_disable_plane(dc, old_pipe_ctx); } @@ -2273,6 +2013,7 @@ static void dcn10_apply_ctx_for_surface( /* pstate stuck check after watermark update */ dcn10_verify_allow_pstate_change_high(dc); } + /* watermark is for all pipes */ hubbub1_program_watermarks(dc->res_pool->hubbub, &context->bw.dcn.watermarks, ref_clk_mhz); @@ -2502,10 +2243,10 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) dcn10_config_stereo_parameters(stream, &flags); - pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity( + pipe_ctx->stream_res.opp->funcs->opp_program_stereo( pipe_ctx->stream_res.opp, flags.PROGRAM_STEREO == 1 ? true:false, - stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); + &stream->timing); pipe_ctx->stream_res.tg->funcs->program_stereo( pipe_ctx->stream_res.tg, @@ -2619,7 +2360,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .pplib_apply_display_requirements = dcn10_pplib_apply_display_requirements, .edp_backlight_control = hwss_edp_backlight_control, - .edp_power_control = hwss_edp_power_control + .edp_power_control = hwss_edp_power_control, + .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index b016f4cbd45c..179890b1a8c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -25,8 +25,6 @@ #include "reg_helper.h" #include "dcn10_mpc.h" -#include "dc.h" -#include "mem_input.h" #define REG(reg)\ mpc10->mpc_regs->reg @@ -38,17 +36,13 @@ #define FN(reg_name, field_name) \ mpc10->mpc_shift->field_name, mpc10->mpc_mask->field_name -#define MODE_TOP_ONLY 1 -#define MODE_BLEND 3 -#define BLND_PP_ALPHA 0 -#define BLND_GLOBAL_ALPHA 2 - -static void mpc10_set_bg_color( - struct dcn10_mpc *mpc10, +void mpc1_set_bg_color(struct mpc *mpc, struct tg_color *bg_color, - int id) + int mpcc_id) { + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + /* mpc color is 12 bit. tg_color is 10 bit */ /* todo: might want to use 16 bit to represent color and have each * hw block translate to correct color depth. @@ -57,15 +51,47 @@ static void mpc10_set_bg_color( uint32_t bg_g_y = bg_color->color_g_y << 2; uint32_t bg_b_cb = bg_color->color_b_cb << 2; - REG_SET(MPCC_BG_R_CR[id], 0, + REG_SET(MPCC_BG_R_CR[mpcc_id], 0, MPCC_BG_R_CR, bg_r_cr); - REG_SET(MPCC_BG_G_Y[id], 0, + REG_SET(MPCC_BG_G_Y[mpcc_id], 0, MPCC_BG_G_Y, bg_g_y); - REG_SET(MPCC_BG_B_CB[id], 0, + REG_SET(MPCC_BG_B_CB[mpcc_id], 0, MPCC_BG_B_CB, bg_b_cb); } -void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) +static void mpc1_update_blending( + struct mpc *mpc, + struct mpcc_blnd_cfg *blnd_cfg, + int mpcc_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + + REG_UPDATE_5(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, blnd_cfg->alpha_mode, + MPCC_ALPHA_MULTIPLIED_MODE, blnd_cfg->pre_multiplied_alpha, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, blnd_cfg->overlap_only, + MPCC_GLOBAL_ALPHA, blnd_cfg->global_alpha, + MPCC_GLOBAL_GAIN, blnd_cfg->global_gain); + + mpc1_set_bg_color(mpc, &blnd_cfg->black_color, mpcc_id); +} + +void mpc1_update_stereo_mix( + struct mpc *mpc, + struct mpcc_sm_cfg *sm_cfg, + int mpcc_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + + REG_UPDATE_6(MPCC_SM_CONTROL[mpcc_id], + MPCC_SM_EN, sm_cfg->enable, + MPCC_SM_MODE, sm_cfg->sm_mode, + MPCC_SM_FRAME_ALT, sm_cfg->frame_alt, + MPCC_SM_FIELD_ALT, sm_cfg->field_alt, + MPCC_SM_FORCE_NEXT_FRAME_POL, sm_cfg->force_next_frame_porlarity, + MPCC_SM_FORCE_NEXT_TOP_POL, sm_cfg->force_next_field_polarity); +} +void mpc1_assert_idle_mpcc(struct mpc *mpc, int id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); @@ -75,39 +101,52 @@ void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) 1, 100000); } -static int mpc10_get_idle_mpcc_id(struct dcn10_mpc *mpc10) +struct mpcc *mpc1_get_mpcc(struct mpc *mpc, int mpcc_id) { - int i; - int last_free_mpcc_id = -1; + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - for (i = 0; i < mpc10->num_mpcc; i++) { - uint32_t is_idle = 0; + ASSERT(mpcc_id < mpc10->num_mpcc); + return &(mpc->mpcc_array[mpcc_id]); +} - if (mpc10->mpcc_in_use_mask & 1 << i) - continue; +struct mpcc *mpc1_get_mpcc_for_dpp(struct mpc_tree *tree, int dpp_id) +{ + struct mpcc *tmp_mpcc = tree->opp_list; - last_free_mpcc_id = i; - REG_GET(MPCC_STATUS[i], MPCC_IDLE, &is_idle); - if (is_idle) - return i; + while (tmp_mpcc != NULL) { + if (tmp_mpcc->dpp_id == dpp_id) + return tmp_mpcc; + tmp_mpcc = tmp_mpcc->mpcc_bot; } + return NULL; +} - /* This assert should never trigger, we have mpcc leak if it does */ - ASSERT(last_free_mpcc_id != -1); - - mpc10_assert_idle_mpcc(&mpc10->base, last_free_mpcc_id); - return last_free_mpcc_id; +bool mpc1_is_mpcc_idle(struct mpc *mpc, int mpcc_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + unsigned int top_sel; + unsigned int opp_id; + unsigned int idle; + + REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel); + REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); + REG_GET(MPCC_STATUS[mpcc_id], MPCC_IDLE, &idle); + if (top_sel == 0xf && opp_id == 0xf && idle) + return true; + else + return false; } -static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int id) +void mpc1_assert_mpcc_idle_before_connect(struct mpc *mpc, int mpcc_id) { + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); unsigned int top_sel, mpc_busy, mpc_idle; - REG_GET(MPCC_TOP_SEL[id], + REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel); if (top_sel == 0xf) { - REG_GET_2(MPCC_STATUS[id], + REG_GET_2(MPCC_STATUS[mpcc_id], MPCC_BUSY, &mpc_busy, MPCC_IDLE, &mpc_idle); @@ -116,241 +155,269 @@ static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int i } } -void mpc10_mpcc_remove( - struct mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - int opp_id, - int dpp_id) -{ - struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - int mpcc_id, z_idx; - - /* find z_idx for the dpp to be removed */ - for (z_idx = 0; z_idx < tree_cfg->num_pipes; z_idx++) - if (tree_cfg->dpp[z_idx] == dpp_id) - break; - - if (z_idx == tree_cfg->num_pipes) { - /* In case of resume from S3/S4, remove mpcc from bios left over */ - REG_SET(MPCC_OPP_ID[dpp_id], 0, - MPCC_OPP_ID, 0xf); - REG_SET(MPCC_TOP_SEL[dpp_id], 0, - MPCC_TOP_SEL, 0xf); - REG_SET(MPCC_BOT_SEL[dpp_id], 0, - MPCC_BOT_SEL, 0xf); - return; - } - - mpcc_id = tree_cfg->mpcc[z_idx]; - - REG_SET(MPCC_OPP_ID[mpcc_id], 0, - MPCC_OPP_ID, 0xf); - REG_SET(MPCC_TOP_SEL[mpcc_id], 0, - MPCC_TOP_SEL, 0xf); - REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, 0xf); - - if (z_idx > 0) { - int top_mpcc_id = tree_cfg->mpcc[z_idx - 1]; - - if (z_idx + 1 < tree_cfg->num_pipes) - /* mpcc to be removed is in the middle of the tree */ - REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, - MPCC_BOT_SEL, tree_cfg->mpcc[z_idx + 1]); - else { - /* mpcc to be removed is at the bottom of the tree */ - REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, - MPCC_BOT_SEL, 0xf); - REG_UPDATE(MPCC_CONTROL[top_mpcc_id], - MPCC_MODE, MODE_TOP_ONLY); - } - } else if (tree_cfg->num_pipes > 1) - /* mpcc to be removed is at the top of the tree */ - REG_SET(MUX[opp_id], 0, - MPC_OUT_MUX, tree_cfg->mpcc[z_idx + 1]); - else - /* mpcc to be removed is the only one in the tree */ - REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, 0xf); - - /* mark this mpcc as not in use */ - mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); - tree_cfg->num_pipes--; - for (; z_idx < tree_cfg->num_pipes; z_idx++) { - tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx + 1]; - tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx + 1]; - } - tree_cfg->dpp[tree_cfg->num_pipes] = 0xdeadbeef; - tree_cfg->mpcc[tree_cfg->num_pipes] = 0xdeadbeef; -} - -static void mpc10_add_to_tree_cfg( +/* + * Insert DPP into MPC tree based on specified blending position. + * Only used for planes that are part of blending chain for OPP output + * + * Parameters: + * [in/out] mpc - MPC context. + * [in/out] tree - MPC tree structure that plane will be added to. + * [in] blnd_cfg - MPCC blending configuration for the new blending layer. + * [in] sm_cfg - MPCC stereo mix configuration for the new blending layer. + * stereo mix must disable for the very bottom layer of the tree config. + * [in] insert_above_mpcc - Insert new plane above this MPCC. If NULL, insert as bottom plane. + * [in] dpp_id - DPP instance for the plane to be added. + * [in] mpcc_id - The MPCC physical instance to use for blending. + * + * Return: struct mpcc* - MPCC that was added. + */ +struct mpcc *mpc1_insert_plane( struct mpc *mpc, - struct mpcc_cfg *cfg, + struct mpc_tree *tree, + struct mpcc_blnd_cfg *blnd_cfg, + struct mpcc_sm_cfg *sm_cfg, + struct mpcc *insert_above_mpcc, + int dpp_id, int mpcc_id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - int mpcc_mode = MODE_TOP_ONLY; - int position = cfg->z_index; - struct mpc_tree_cfg *tree_cfg = cfg->tree_cfg; - int alpha_blnd_mode = cfg->per_pixel_alpha ? - BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; - int z_idx; + struct mpcc *new_mpcc = NULL; - REG_SET(MPCC_OPP_ID[mpcc_id], 0, - MPCC_OPP_ID, cfg->opp_id); + /* sanity check parameters */ + ASSERT(mpcc_id < mpc10->num_mpcc); + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); - REG_SET(MPCC_TOP_SEL[mpcc_id], 0, - MPCC_TOP_SEL, cfg->dpp_id); + if (insert_above_mpcc) { + /* check insert_above_mpcc exist in tree->opp_list */ + struct mpcc *temp_mpcc = tree->opp_list; - if (position == 0) { - /* idle dpp/mpcc is added to the top layer of tree */ + while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc) + temp_mpcc = temp_mpcc->mpcc_bot; + if (temp_mpcc == NULL) + return NULL; + } - if (tree_cfg->num_pipes > 0) { - /* get instance of previous top mpcc */ - int prev_top_mpcc_id = tree_cfg->mpcc[0]; + /* Get and update MPCC struct parameters */ + new_mpcc = mpc1_get_mpcc(mpc, mpcc_id); + new_mpcc->dpp_id = dpp_id; - REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, prev_top_mpcc_id); - mpcc_mode = MODE_BLEND; + /* program mux and MPCC_MODE */ + if (insert_above_mpcc) { + new_mpcc->mpcc_bot = insert_above_mpcc; + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, insert_above_mpcc->mpcc_id); + REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING); + } else { + new_mpcc->mpcc_bot = NULL; + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_UPDATE(MPCC_CONTROL[mpcc_id], MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH); + } + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, dpp_id); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, tree->opp_id); + + /* update mpc tree mux setting */ + if (tree->opp_list == insert_above_mpcc) { + /* insert the toppest mpcc */ + tree->opp_list = new_mpcc; + REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, mpcc_id); + } else { + /* find insert position */ + struct mpcc *temp_mpcc = tree->opp_list; + + while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc) + temp_mpcc = temp_mpcc->mpcc_bot; + if (temp_mpcc && temp_mpcc->mpcc_bot == insert_above_mpcc) { + REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, MPCC_BOT_SEL, mpcc_id); + temp_mpcc->mpcc_bot = new_mpcc; + if (!insert_above_mpcc) + REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id], + MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING); } + } - /* opp will get new output. from new added mpcc */ - REG_SET(MUX[cfg->opp_id], 0, MPC_OUT_MUX, mpcc_id); - - } else if (position == tree_cfg->num_pipes) { - /* idle dpp/mpcc is added to the bottom layer of tree */ - - /* get instance of previous bottom mpcc, set to middle layer */ - int prev_bot_mpcc_id = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; - - REG_SET(MPCC_BOT_SEL[prev_bot_mpcc_id], 0, - MPCC_BOT_SEL, mpcc_id); - REG_UPDATE(MPCC_CONTROL[prev_bot_mpcc_id], - MPCC_MODE, MODE_BLEND); - - /* mpcc_id become new bottom mpcc*/ - REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, 0xf); + /* update the blending configuration */ + new_mpcc->blnd_cfg = *blnd_cfg; + mpc->funcs->update_blending(mpc, &new_mpcc->blnd_cfg, mpcc_id); - } else { - /* idle dpp/mpcc is added to middle of tree */ - int above_mpcc_id = tree_cfg->mpcc[position - 1]; - int below_mpcc_id = tree_cfg->mpcc[position]; - - /* mpcc above new mpcc_id has new bottom mux*/ - REG_SET(MPCC_BOT_SEL[above_mpcc_id], 0, - MPCC_BOT_SEL, mpcc_id); - REG_UPDATE(MPCC_CONTROL[above_mpcc_id], - MPCC_MODE, MODE_BLEND); - - /* mpcc_id bottom mux is from below mpcc*/ - REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, below_mpcc_id); - mpcc_mode = MODE_BLEND; + /* update the stereo mix settings, if provided */ + if (sm_cfg != NULL) { + new_mpcc->sm_cfg = *sm_cfg; + mpc1_update_stereo_mix(mpc, sm_cfg, mpcc_id); } - REG_SET_4(MPCC_CONTROL[mpcc_id], 0xffffffff, - MPCC_MODE, mpcc_mode, - MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, - MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, false); + /* mark this mpcc as in use */ + mpc10->mpcc_in_use_mask |= 1 << mpcc_id; - /* update mpc_tree_cfg with new mpcc */ - for (z_idx = tree_cfg->num_pipes; z_idx > position; z_idx--) { - tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx - 1]; - tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx - 1]; - } - tree_cfg->dpp[position] = cfg->dpp_id; - tree_cfg->mpcc[position] = mpcc_id; - tree_cfg->num_pipes++; + return new_mpcc; } -int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +/* + * Remove a specified MPCC from the MPC tree. + * + * Parameters: + * [in/out] mpc - MPC context. + * [in/out] tree - MPC tree structure that plane will be removed from. + * [in/out] mpcc - MPCC to be removed from tree. + * + * Return: void + */ +void mpc1_remove_mpcc( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc *mpcc_to_remove) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - int mpcc_id, z_idx; - - ASSERT(cfg->z_index < mpc10->num_mpcc); - - /* check in dpp already exists in mpc tree */ - for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) - if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) - break; - if (z_idx == cfg->tree_cfg->num_pipes) { - ASSERT(cfg->z_index <= cfg->tree_cfg->num_pipes); - mpcc_id = mpc10_get_idle_mpcc_id(mpc10); - - /* - * TODO: remove hack - * Note: currently there is a bug in init_hw such that - * on resume from hibernate, BIOS sets up MPCC0, and - * we do mpcc_remove but the mpcc cannot go to idle - * after remove. This cause us to pick mpcc1 here, - * which causes a pstate hang for yet unknown reason. - */ - mpcc_id = cfg->dpp_id; - /* end hack*/ - - ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); - - if (mpc->ctx->dc->debug.sanity_checks) - mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); + bool found = false; + int mpcc_id = mpcc_to_remove->mpcc_id; + + if (tree->opp_list == mpcc_to_remove) { + found = true; + /* remove MPCC from top of tree */ + if (mpcc_to_remove->mpcc_bot) { + /* set the next MPCC in list to be the top MPCC */ + tree->opp_list = mpcc_to_remove->mpcc_bot; + REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, tree->opp_list->mpcc_id); + } else { + /* there are no other MPCC is list */ + tree->opp_list = NULL; + REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, 0xf); + } } else { - ASSERT(cfg->z_index < cfg->tree_cfg->num_pipes); - mpcc_id = cfg->tree_cfg->mpcc[z_idx]; - mpc10_mpcc_remove(mpc, cfg->tree_cfg, cfg->opp_id, cfg->dpp_id); + /* find mpcc to remove MPCC list */ + struct mpcc *temp_mpcc = tree->opp_list; + + while (temp_mpcc && temp_mpcc->mpcc_bot != mpcc_to_remove) + temp_mpcc = temp_mpcc->mpcc_bot; + + if (temp_mpcc && temp_mpcc->mpcc_bot == mpcc_to_remove) { + found = true; + temp_mpcc->mpcc_bot = mpcc_to_remove->mpcc_bot; + if (mpcc_to_remove->mpcc_bot) { + /* remove MPCC in middle of list */ + REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, + MPCC_BOT_SEL, mpcc_to_remove->mpcc_bot->mpcc_id); + } else { + /* remove MPCC from bottom of list */ + REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, + MPCC_BOT_SEL, 0xf); + REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id], + MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH); + } + } } - /* add dpp/mpcc pair to mpc_tree_cfg and update mpcc registers */ - mpc10_add_to_tree_cfg(mpc, cfg, mpcc_id); + if (found) { + /* turn off MPCC mux registers */ + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); - /* set background color */ - mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); - - /* mark this mpcc as in use */ - mpc10->mpcc_in_use_mask |= 1 << mpcc_id; + /* mark this mpcc as not in use */ + mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); + mpcc_to_remove->dpp_id = 0xf; + mpcc_to_remove->mpcc_bot = NULL; + } else { + /* In case of resume from S3/S4, remove mpcc from bios left over */ + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); + } +} - return mpcc_id; +static void mpc1_init_mpcc(struct mpcc *mpcc, int mpcc_inst) +{ + mpcc->mpcc_id = mpcc_inst; + mpcc->dpp_id = 0xf; + mpcc->mpcc_bot = NULL; + mpcc->blnd_cfg.overlap_only = false; + mpcc->blnd_cfg.global_alpha = 0xff; + mpcc->blnd_cfg.global_gain = 0xff; + mpcc->sm_cfg.enable = false; } -void mpc10_update_blend_mode( - struct mpc *mpc, - struct mpcc_cfg *cfg) +/* + * Reset the MPCC HW status by disconnecting all muxes. + * + * Parameters: + * [in/out] mpc - MPC context. + * + * Return: void + */ +void mpc1_mpc_init(struct mpc *mpc) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - int mpcc_id, z_idx; - int alpha_blnd_mode = cfg->per_pixel_alpha ? - BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; + int mpcc_id; + int opp_id; - /* find z_idx for the dpp that requires blending mode update*/ - for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) - if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) - break; + mpc10->mpcc_in_use_mask = 0; + for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) { + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); - ASSERT(z_idx < cfg->tree_cfg->num_pipes); - mpcc_id = cfg->tree_cfg->mpcc[z_idx]; + mpc1_init_mpcc(&(mpc->mpcc_array[mpcc_id]), mpcc_id); + } - REG_UPDATE_2(MPCC_CONTROL[mpcc_id], - MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, - MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha); + for (opp_id = 0; opp_id < MAX_OPP; opp_id++) { + if (REG(MUX[opp_id])) + REG_UPDATE(MUX[opp_id], MPC_OUT_MUX, 0xf); + } } -int mpc10_get_opp_id(struct mpc *mpc, int mpcc_id) +void mpc1_init_mpcc_list_from_hw( + struct mpc *mpc, + struct mpc_tree *tree) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - int opp_id = 0xF; - - REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); - - return opp_id; + unsigned int opp_id; + unsigned int top_sel; + unsigned int bot_sel; + unsigned int out_mux; + struct mpcc *mpcc; + int mpcc_id; + int bot_mpcc_id; + + REG_GET(MUX[tree->opp_id], MPC_OUT_MUX, &out_mux); + + if (out_mux != 0xf) { + for (mpcc_id = 0; mpcc_id < mpc10->num_mpcc; mpcc_id++) { + REG_GET(MPCC_OPP_ID[mpcc_id], MPCC_OPP_ID, &opp_id); + REG_GET(MPCC_TOP_SEL[mpcc_id], MPCC_TOP_SEL, &top_sel); + REG_GET(MPCC_BOT_SEL[mpcc_id], MPCC_BOT_SEL, &bot_sel); + + if (bot_sel == mpcc_id) + bot_sel = 0xf; + + if ((opp_id == tree->opp_id) && (top_sel != 0xf)) { + mpcc = mpc1_get_mpcc(mpc, mpcc_id); + mpcc->dpp_id = top_sel; + mpc10->mpcc_in_use_mask |= 1 << mpcc_id; + + if (out_mux == mpcc_id) + tree->opp_list = mpcc; + if (bot_sel != 0xf && bot_sel < mpc10->num_mpcc) { + bot_mpcc_id = bot_sel; + REG_GET(MPCC_OPP_ID[bot_mpcc_id], MPCC_OPP_ID, &opp_id); + REG_GET(MPCC_TOP_SEL[bot_mpcc_id], MPCC_TOP_SEL, &top_sel); + if ((opp_id == tree->opp_id) && (top_sel != 0xf)) { + struct mpcc *mpcc_bottom = mpc1_get_mpcc(mpc, bot_mpcc_id); + + mpcc->mpcc_bot = mpcc_bottom; + } + } + } + } + } } const struct mpc_funcs dcn10_mpc_funcs = { - .add = mpc10_mpcc_add, - .remove = mpc10_mpcc_remove, - .wait_for_idle = mpc10_assert_idle_mpcc, - .update_blend_mode = mpc10_update_blend_mode, - .get_opp_id = mpc10_get_opp_id, + .insert_plane = mpc1_insert_plane, + .remove_mpcc = mpc1_remove_mpcc, + .mpc_init = mpc1_mpc_init, + .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp, + .wait_for_idle = mpc1_assert_idle_mpcc, + .assert_mpcc_idle_before_connect = mpc1_assert_mpcc_idle_before_connect, + .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw, + .update_blending = mpc1_update_blending, }; void dcn10_mpc_construct(struct dcn10_mpc *mpc10, @@ -360,6 +427,8 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpc10, const struct dcn_mpc_mask *mpc_mask, int num_mpcc) { + int i; + mpc10->base.ctx = ctx; mpc10->base.funcs = &dcn10_mpc_funcs; @@ -370,5 +439,8 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpc10, mpc10->mpcc_in_use_mask = 0; mpc10->num_mpcc = num_mpcc; + + for (i = 0; i < MAX_MPCC; i++) + mpc1_init_mpcc(&mpc10->base.mpcc_array[i], i); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index e85e1f342266..267a2995ef6e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -30,9 +30,6 @@ #define TO_DCN10_MPC(mpc_base) \ container_of(mpc_base, struct dcn10_mpc, base) -#define MAX_MPCC 6 -#define MAX_OPP 6 - #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ SRII(MPCC_TOP_SEL, MPCC, inst),\ SRII(MPCC_BOT_SEL, MPCC, inst),\ @@ -42,7 +39,8 @@ SRII(MPCC_BG_G_Y, MPCC, inst),\ SRII(MPCC_BG_R_CR, MPCC, inst),\ SRII(MPCC_BG_B_CB, MPCC, inst),\ - SRII(MPCC_BG_B_CB, MPCC, inst) + SRII(MPCC_BG_B_CB, MPCC, inst),\ + SRII(MPCC_SM_CONTROL, MPCC, inst) #define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst) \ SRII(MUX, MPC_OUT, inst) @@ -56,6 +54,7 @@ uint32_t MPCC_BG_G_Y[MAX_MPCC]; \ uint32_t MPCC_BG_R_CR[MAX_MPCC]; \ uint32_t MPCC_BG_B_CB[MAX_MPCC]; \ + uint32_t MPCC_SM_CONTROL[MAX_MPCC]; \ uint32_t MUX[MAX_OPP]; #define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ @@ -65,12 +64,20 @@ SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_BLND_MODE, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_GLOBAL_ALPHA, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_GLOBAL_GAIN, mask_sh),\ SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\ SF(MPCC0_MPCC_STATUS, MPCC_BUSY, mask_sh),\ SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\ SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_EN, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_MODE, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FRAME_ALT, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FIELD_ALT, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_FRAME_POL, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_TOP_POL, mask_sh),\ SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh) #define MPC_REG_FIELD_LIST(type) \ @@ -80,12 +87,20 @@ type MPCC_ALPHA_BLND_MODE;\ type MPCC_ALPHA_MULTIPLIED_MODE;\ type MPCC_BLND_ACTIVE_OVERLAP_ONLY;\ + type MPCC_GLOBAL_ALPHA;\ + type MPCC_GLOBAL_GAIN;\ type MPCC_IDLE;\ type MPCC_BUSY;\ type MPCC_OPP_ID;\ type MPCC_BG_G_Y;\ type MPCC_BG_R_CR;\ type MPCC_BG_B_CB;\ + type MPCC_SM_EN;\ + type MPCC_SM_MODE;\ + type MPCC_SM_FRAME_ALT;\ + type MPCC_SM_FIELD_ALT;\ + type MPCC_SM_FORCE_NEXT_FRAME_POL;\ + type MPCC_SM_FORCE_NEXT_TOP_POL;\ type MPC_OUT_MUX; struct dcn_mpc_registers { @@ -117,23 +132,55 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpcc10, const struct dcn_mpc_mask *mpc_mask, int num_mpcc); -int mpc10_mpcc_add( - struct mpc *mpc, - struct mpcc_cfg *cfg); - -void mpc10_mpcc_remove( - struct mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - int opp_id, - int dpp_id); - -void mpc10_assert_idle_mpcc( - struct mpc *mpc, - int id); - -void mpc10_update_blend_mode( - struct mpc *mpc, - struct mpcc_cfg *cfg); -int mpc10_get_opp_id(struct mpc *mpc, int mpcc_id); +struct mpcc *mpc1_insert_plane( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc_blnd_cfg *blnd_cfg, + struct mpcc_sm_cfg *sm_cfg, + struct mpcc *insert_above_mpcc, + int dpp_id, + int mpcc_id); + +void mpc1_remove_mpcc( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc *mpcc); + +void mpc1_mpc_init( + struct mpc *mpc); + +void mpc1_assert_idle_mpcc( + struct mpc *mpc, + int id); + +void mpc1_set_bg_color( + struct mpc *mpc, + struct tg_color *bg_color, + int id); + +void mpc1_update_stereo_mix( + struct mpc *mpc, + struct mpcc_sm_cfg *sm_cfg, + int mpcc_id); + +bool mpc1_is_mpcc_idle( + struct mpc *mpc, + int mpcc_id); + +void mpc1_assert_mpcc_idle_before_connect( + struct mpc *mpc, + int mpcc_id); + +void mpc1_init_mpcc_list_from_hw( + struct mpc *mpc, + struct mpc_tree *tree); + +struct mpcc *mpc1_get_mpcc( + struct mpc *mpc, + int mpcc_id); + +struct mpcc *mpc1_get_mpcc_for_dpp( + struct mpc_tree *tree, + int dpp_id); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 6d6f67b7d30e..f6ba0eef4489 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -296,13 +296,75 @@ void opp1_program_fmt( return; } -void opp1_set_stereo_polarity( - struct output_pixel_processor *opp, - bool enable, bool rightEyePolarity) +void opp1_program_stereo( + struct output_pixel_processor *opp, + bool enable, + const struct dc_crtc_timing *timing) { struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, enable); + uint32_t active_width = timing->h_addressable - timing->h_border_right - timing->h_border_right; + uint32_t space1_size = timing->v_total - timing->v_addressable; + /* TODO: confirm computation of space2_size */ + uint32_t space2_size = timing->v_total - timing->v_addressable; + + if (!enable) { + active_width = 0; + space1_size = 0; + space2_size = 0; + } + + /* TODO: for which cases should FMT_STEREOSYNC_OVERRIDE be set? */ + REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, 0); + + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, active_width); + + /* Program OPPBUF_3D_VACT_SPACE1_SIZE and OPPBUF_VACT_SPACE2_SIZE registers + * In 3D progressive frames, Vactive space happens only in between the 2 frames, + * so only need to program OPPBUF_3D_VACT_SPACE1_SIZE + * In 3D alternative frames, left and right frames, top and bottom field. + */ + if (timing->timing_3d_format == TIMING_3D_FORMAT_FRAME_ALTERNATE) + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE2_SIZE, space2_size); + else + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); + + /* TODO: Is programming of OPPBUF_DUMMY_DATA_R/G/B needed? */ + /* + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, + OPPBUF_DUMMY_DATA_R, data_r); + REG_UPDATE(OPPBUF_3D_PARAMETERS_1, + OPPBUF_DUMMY_DATA_G, data_g); + REG_UPDATE(OPPBUF_3D_PARAMETERS_1, + OPPBUF_DUMMY_DATA_B, _data_b); + */ +} + +void opp1_program_oppbuf( + struct output_pixel_processor *opp, + struct oppbuf_params *oppbuf) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + /* Program the oppbuf active width to be the frame width from mpc */ + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, oppbuf->active_width); + + /* Specifies the number of segments in multi-segment mode (DP-MSO operation) + * description "In 1/2/4 segment mode, specifies the horizontal active width in pixels of the display panel. + * In 4 segment split left/right mode, specifies the horizontal 1/2 active width in pixels of the display panel. + * Used to determine segment boundaries in multi-segment mode. Used to determine the width of the vertical active space in 3D frame packed modes. + * OPPBUF_ACTIVE_WIDTH must be integer divisible by the total number of segments." + */ + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_DISPLAY_SEGMENTATION, oppbuf->mso_segmentation); + + /* description "Specifies the number of overlap pixels (1-8 overlapping pixels supported), used in multi-segment mode (DP-MSO operation)" */ + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_OVERLAP_PIXEL_NUM, oppbuf->mso_overlap_pixel_num); + + /* description "Specifies the number of times a pixel is replicated (0-15 pixel replications supported). + * A value of 0 disables replication. The total number of times a pixel is output is OPPBUF_PIXEL_REPETITION + 1." + */ + REG_UPDATE(OPPBUF_CONTROL, OPPBUF_PIXEL_REPETITION, oppbuf->pixel_repetition); + } /*****************************************/ @@ -319,7 +381,7 @@ static struct opp_funcs dcn10_opp_funcs = { .opp_set_dyn_expansion = opp1_set_dyn_expansion, .opp_program_fmt = opp1_program_fmt, .opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction, - .opp_set_stereo_polarity = opp1_set_stereo_polarity, + .opp_program_stereo = opp1_program_stereo, .opp_destroy = opp1_destroy }; @@ -330,6 +392,7 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask) { + oppn10->base.ctx = ctx; oppn10->base.inst = inst; oppn10->base.funcs = &dcn10_opp_funcs; @@ -338,4 +401,3 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, oppn10->opp_shift = opp_shift; oppn10->opp_mask = opp_mask; } - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index f3c298ec37fb..bc5058af6266 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -41,7 +41,10 @@ SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ SRI(FMT_CLAMP_CNTL, FMT, id), \ SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ - SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id) + SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id), \ + SRI(OPPBUF_CONTROL, OPPBUF, id),\ + SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, id), \ + SRI(OPPBUF_3D_PARAMETERS_1, OPPBUF, id) #define OPP_REG_LIST_DCN10(id) \ OPP_REG_LIST_DCN(id) @@ -54,7 +57,11 @@ uint32_t FMT_DITHER_RAND_B_SEED; \ uint32_t FMT_CLAMP_CNTL; \ uint32_t FMT_DYNAMIC_EXP_CNTL; \ - uint32_t FMT_MAP420_MEMORY_CONTROL; + uint32_t FMT_MAP420_MEMORY_CONTROL; \ + uint32_t OPPBUF_CONTROL; \ + uint32_t OPPBUF_CONTROL1; \ + uint32_t OPPBUF_3D_PARAMETERS_0; \ + uint32_t OPPBUF_3D_PARAMETERS_1 #define OPP_MASK_SH_LIST_DCN(mask_sh) \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ @@ -78,10 +85,16 @@ OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh), \ - OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh) + OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh), \ + OPP_SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ + OPP_SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_PIXEL_REPETITION, mask_sh),\ + OPP_SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh), \ + OPP_SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE2_SIZE, mask_sh) #define OPP_MASK_SH_LIST_DCN10(mask_sh) \ - OPP_MASK_SH_LIST_DCN(mask_sh) + OPP_MASK_SH_LIST_DCN(mask_sh), \ + OPP_SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_DISPLAY_SEGMENTATION, mask_sh),\ + OPP_SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_OVERLAP_PIXEL_NUM, mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ type FMT_TRUNCATE_EN; \ @@ -105,18 +118,25 @@ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_MAP420MEM_PWR_FORCE; \ - type FMT_STEREOSYNC_OVERRIDE; + type FMT_STEREOSYNC_OVERRIDE; \ + type OPPBUF_ACTIVE_WIDTH;\ + type OPPBUF_PIXEL_REPETITION;\ + type OPPBUF_DISPLAY_SEGMENTATION;\ + type OPPBUF_OVERLAP_PIXEL_NUM;\ + type OPPBUF_NUM_SEGMENT_PADDED_PIXELS; \ + type OPPBUF_3D_VACT_SPACE1_SIZE; \ + type OPPBUF_3D_VACT_SPACE2_SIZE struct dcn10_opp_registers { - OPP_COMMON_REG_VARIABLE_LIST + OPP_COMMON_REG_VARIABLE_LIST; }; struct dcn10_opp_shift { - OPP_DCN10_REG_FIELD_LIST(uint8_t) + OPP_DCN10_REG_FIELD_LIST(uint8_t); }; struct dcn10_opp_mask { - OPP_DCN10_REG_FIELD_LIST(uint32_t) + OPP_DCN10_REG_FIELD_LIST(uint32_t); }; struct dcn10_opp { @@ -151,9 +171,10 @@ void opp1_program_bit_depth_reduction( struct output_pixel_processor *opp, const struct bit_depth_reduction_params *params); -void opp1_set_stereo_polarity( - struct output_pixel_processor *opp, - bool enable, bool rightEyePolarity); +void opp1_program_stereo( + struct output_pixel_processor *opp, + bool enable, + const struct dc_crtc_timing *timing); void opp1_destroy(struct output_pixel_processor **opp); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index 73ff78f9cae1..4bf64d1b2c60 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -23,19 +23,20 @@ * */ + #include "reg_helper.h" -#include "dcn10_timing_generator.h" +#include "dcn10_optc.h" #include "dc.h" #define REG(reg)\ - tgn10->tg_regs->reg + optc1->tg_regs->reg #define CTX \ - tgn10->base.ctx + optc1->base.ctx #undef FN #define FN(reg_name, field_name) \ - tgn10->tg_shift->field_name, tgn10->tg_mask->field_name + optc1->tg_shift->field_name, optc1->tg_mask->field_name #define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100 @@ -45,8 +46,8 @@ * This is a workaround for a bug that has existed since R5xx and has not been * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. */ -static void tgn10_apply_front_porch_workaround( - struct timing_generator *tg, +static void optc1_apply_front_porch_workaround( + struct timing_generator *optc, struct dc_crtc_timing *timing) { if (timing->flags.INTERLACE == 1) { @@ -58,30 +59,30 @@ static void tgn10_apply_front_porch_workaround( } } -static void tgn10_program_global_sync( - struct timing_generator *tg) +void optc1_program_global_sync( + struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); - if (tg->dlg_otg_param.vstartup_start == 0) { + if (optc->dlg_otg_param.vstartup_start == 0) { BREAK_TO_DEBUGGER(); return; } REG_SET(OTG_VSTARTUP_PARAM, 0, - VSTARTUP_START, tg->dlg_otg_param.vstartup_start); + VSTARTUP_START, optc->dlg_otg_param.vstartup_start); REG_SET_2(OTG_VUPDATE_PARAM, 0, - VUPDATE_OFFSET, tg->dlg_otg_param.vupdate_offset, - VUPDATE_WIDTH, tg->dlg_otg_param.vupdate_width); + VUPDATE_OFFSET, optc->dlg_otg_param.vupdate_offset, + VUPDATE_WIDTH, optc->dlg_otg_param.vupdate_width); REG_SET(OTG_VREADY_PARAM, 0, - VREADY_OFFSET, tg->dlg_otg_param.vready_offset); + VREADY_OFFSET, optc->dlg_otg_param.vready_offset); } -static void tgn10_disable_stereo(struct timing_generator *tg) +static void optc1_disable_stereo(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_SET(OTG_STEREO_CONTROL, 0, OTG_STEREO_EN, 0); @@ -90,11 +91,6 @@ static void tgn10_disable_stereo(struct timing_generator *tg) OTG_3D_STRUCTURE_EN, 0, OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); - - REG_UPDATE(OPPBUF_CONTROL, - OPPBUF_ACTIVE_WIDTH, 0); - REG_UPDATE(OPPBUF_3D_PARAMETERS_0, - OPPBUF_3D_VACT_SPACE1_SIZE, 0); } /** @@ -102,8 +98,8 @@ static void tgn10_disable_stereo(struct timing_generator *tg) * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. * Including SYNC. Call BIOS command table to program Timings. */ -static void tgn10_program_timing( - struct timing_generator *tg, +void optc1_program_timing( + struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing, bool use_vbios) { @@ -121,10 +117,10 @@ static void tgn10_program_timing( uint32_t h_div_2; int32_t vertical_line_start; - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); patched_crtc_timing = *dc_crtc_timing; - tgn10_apply_front_porch_workaround(tg, &patched_crtc_timing); + optc1_apply_front_porch_workaround(optc, &patched_crtc_timing); /* Load horizontal timing */ @@ -217,7 +213,7 @@ static void tgn10_program_timing( /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, * program the reg for interrupt postition. */ - vertical_line_start = asic_blank_end - tg->dlg_otg_param.vstartup_start + 1; + vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; if (vertical_line_start < 0) { ASSERT(0); vertical_line_start = 0; @@ -233,26 +229,25 @@ static void tgn10_program_timing( OTG_V_SYNC_A_POL, v_sync_polarity); v_init = asic_blank_start; - if (tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || - tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || - tg->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { + if (optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || + optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + optc->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { start_point = 1; if (patched_crtc_timing.flags.INTERLACE == 1) field_num = 1; } v_fp2 = 0; - if (tg->dlg_otg_param.vstartup_start > asic_blank_end) - v_fp2 = tg->dlg_otg_param.vstartup_start > asic_blank_end; + if (optc->dlg_otg_param.vstartup_start > asic_blank_end) + v_fp2 = optc->dlg_otg_param.vstartup_start > asic_blank_end; /* Interlace */ if (patched_crtc_timing.flags.INTERLACE == 1) { REG_UPDATE(OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, 1); v_init = v_init / 2; - if ((tg->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) + if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) v_fp2 = v_fp2 / 2; - } - else + } else REG_UPDATE(OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, 0); @@ -270,13 +265,13 @@ static void tgn10_program_timing( OTG_START_POINT_CNTL, start_point, OTG_FIELD_NUMBER_CNTL, field_num); - tgn10_program_global_sync(tg); + optc1_program_global_sync(optc); /* TODO * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 * program_horz_count_by_2 * for DVI 30bpp mode, 0 otherwise - * program_horz_count_by_2(tg, &patched_crtc_timing); + * program_horz_count_by_2(optc, &patched_crtc_timing); */ /* Enable stereo - only when we need to pack 3D frame. Other types @@ -290,9 +285,9 @@ static void tgn10_program_timing( } -static void tgn10_set_blank_data_double_buffer(struct timing_generator *tg, bool enable) +static void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t blank_data_double_buffer_enable = enable ? 1 : 0; @@ -304,9 +299,9 @@ static void tgn10_set_blank_data_double_buffer(struct timing_generator *tg, bool * unblank_crtc * Call ASIC Control Object to UnBlank CRTC. */ -static void tgn10_unblank_crtc(struct timing_generator *tg) +static void optc1_unblank_crtc(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t vertical_interrupt_enable = 0; REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, @@ -316,7 +311,7 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) * this check will be removed. */ if (vertical_interrupt_enable) - tgn10_set_blank_data_double_buffer(tg, true); + optc1_set_blank_data_double_buffer(optc, true); REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, @@ -328,36 +323,29 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) * Call ASIC Control Object to Blank CRTC. */ -static void tgn10_blank_crtc(struct timing_generator *tg) +static void optc1_blank_crtc(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 1, OTG_BLANK_DE_MODE, 0); - /* todo: why are we waiting for BLANK_DATA_EN? shouldn't we be waiting - * for status? - */ - REG_WAIT(OTG_BLANK_CONTROL, - OTG_BLANK_DATA_EN, 1, - 1, 100000); - - tgn10_set_blank_data_double_buffer(tg, false); + optc1_set_blank_data_double_buffer(optc, false); } -static void tgn10_set_blank(struct timing_generator *tg, +void optc1_set_blank(struct timing_generator *optc, bool enable_blanking) { if (enable_blanking) - tgn10_blank_crtc(tg); + optc1_blank_crtc(optc); else - tgn10_unblank_crtc(tg); + optc1_unblank_crtc(optc); } -static bool tgn10_is_blanked(struct timing_generator *tg) +bool optc1_is_blanked(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t blank_en; uint32_t blank_state; @@ -368,9 +356,9 @@ static bool tgn10_is_blanked(struct timing_generator *tg) return blank_en && blank_state; } -static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) +void optc1_enable_optc_clock(struct timing_generator *optc, bool enable) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); if (enable) { REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, @@ -403,19 +391,19 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) * Enable CRTC * Enable CRTC - call ASIC Control Object to enable Timing generator. */ -static bool tgn10_enable_crtc(struct timing_generator *tg) +static bool optc1_enable_crtc(struct timing_generator *optc) { /* TODO FPGA wait for answer * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK */ - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); /* opp instance for OTG. For DCN1.0, ODM is remoed. * OPP and OPTC should 1:1 mapping */ REG_UPDATE(OPTC_DATA_SOURCE_SELECT, - OPTC_SRC_SEL, tg->inst); + OPTC_SRC_SEL, optc->inst); /* VTG enable first is for HW workaround */ REG_UPDATE(CONTROL, @@ -430,9 +418,9 @@ static bool tgn10_enable_crtc(struct timing_generator *tg) } /* disable_crtc - call ASIC Control Object to disable Timing generator. */ -static bool tgn10_disable_crtc(struct timing_generator *tg) +bool optc1_disable_crtc(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); /* disable otg request until end of the first line * in the vertical blank region @@ -453,11 +441,11 @@ static bool tgn10_disable_crtc(struct timing_generator *tg) } -static void tgn10_program_blank_color( - struct timing_generator *tg, +void optc1_program_blank_color( + struct timing_generator *optc, const struct tg_color *black_color) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_SET_3(OTG_BLACK_COLOR, 0, OTG_BLACK_COLOR_B_CB, black_color->color_b_cb, @@ -465,15 +453,15 @@ static void tgn10_program_blank_color( OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); } -static bool tgn10_validate_timing( - struct timing_generator *tg, +bool optc1_validate_timing( + struct timing_generator *optc, const struct dc_crtc_timing *timing) { uint32_t interlace_factor; uint32_t v_blank; uint32_t h_blank; uint32_t min_v_blank; - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); ASSERT(timing != NULL); @@ -503,19 +491,19 @@ static bool tgn10_validate_timing( * needs more than 8192 horizontal and * more than 8192 vertical total pixels) */ - if (timing->h_total > tgn10->max_h_total || - timing->v_total > tgn10->max_v_total) + if (timing->h_total > optc1->max_h_total || + timing->v_total > optc1->max_v_total) return false; - if (h_blank < tgn10->min_h_blank) + if (h_blank < optc1->min_h_blank) return false; - if (timing->h_sync_width < tgn10->min_h_sync_width || - timing->v_sync_width < tgn10->min_v_sync_width) + if (timing->h_sync_width < optc1->min_h_sync_width || + timing->v_sync_width < optc1->min_v_sync_width) return false; - min_v_blank = timing->flags.INTERLACE?tgn10->min_v_blank_interlace:tgn10->min_v_blank; + min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank; if (v_blank < min_v_blank) return false; @@ -532,15 +520,15 @@ static bool tgn10_validate_timing( * holds the counter of frames. * * @param - * struct timing_generator *tg - [in] timing generator which controls the + * struct timing_generator *optc - [in] timing generator which controls the * desired CRTC * * @return * Counter of frames, which should equal to number of vblanks. */ -static uint32_t tgn10_get_vblank_counter(struct timing_generator *tg) +uint32_t optc1_get_vblank_counter(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t frame_count; REG_GET(OTG_STATUS_FRAME_COUNT, @@ -549,34 +537,34 @@ static uint32_t tgn10_get_vblank_counter(struct timing_generator *tg) return frame_count; } -static void tgn10_lock(struct timing_generator *tg) +void optc1_lock(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_SET(OTG_GLOBAL_CONTROL0, 0, - OTG_MASTER_UPDATE_LOCK_SEL, tg->inst); + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 1); /* Should be fast, status does not update on maximus */ - if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1, 1, 10); } -static void tgn10_unlock(struct timing_generator *tg) +void optc1_unlock(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 0); } -static void tgn10_get_position(struct timing_generator *tg, +void optc1_get_position(struct timing_generator *optc, struct crtc_position *position) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_GET_2(OTG_STATUS_POSITION, OTG_HORZ_COUNT, &position->horizontal_count, @@ -586,12 +574,12 @@ static void tgn10_get_position(struct timing_generator *tg, OTG_VERT_COUNT_NOM, &position->nominal_vcount); } -static bool tgn10_is_counter_moving(struct timing_generator *tg) +bool optc1_is_counter_moving(struct timing_generator *optc) { struct crtc_position position1, position2; - tg->funcs->get_position(tg, &position1); - tg->funcs->get_position(tg, &position2); + optc->funcs->get_position(optc, &position1); + optc->funcs->get_position(optc, &position2); if (position1.horizontal_count == position2.horizontal_count && position1.vertical_count == position2.vertical_count) @@ -600,10 +588,10 @@ static bool tgn10_is_counter_moving(struct timing_generator *tg) return true; } -static bool tgn10_did_triggered_reset_occur( - struct timing_generator *tg) +bool optc1_did_triggered_reset_occur( + struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t occurred_force, occurred_vsync; REG_GET(OTG_FORCE_COUNT_NOW_CNTL, @@ -615,9 +603,9 @@ static bool tgn10_did_triggered_reset_occur( return occurred_vsync != 0 || occurred_force != 0; } -static void tgn10_disable_reset_trigger(struct timing_generator *tg) +void optc1_disable_reset_trigger(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_WRITE(OTG_TRIGA_CNTL, 0); @@ -628,9 +616,9 @@ static void tgn10_disable_reset_trigger(struct timing_generator *tg) OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1); } -static void tgn10_enable_reset_trigger(struct timing_generator *tg, int source_tg_inst) +void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t falling_edge; REG_GET(OTG_V_SYNC_A_CNTL, @@ -662,12 +650,12 @@ static void tgn10_enable_reset_trigger(struct timing_generator *tg, int source_t OTG_FORCE_COUNT_NOW_MODE, 2); } -void tgn10_enable_crtc_reset( - struct timing_generator *tg, +void optc1_enable_crtc_reset( + struct timing_generator *optc, int source_tg_inst, struct crtc_trigger_info *crtc_tp) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t falling_edge = 0; uint32_t rising_edge = 0; @@ -707,10 +695,10 @@ void tgn10_enable_crtc_reset( } } -static void tgn10_wait_for_state(struct timing_generator *tg, +void optc1_wait_for_state(struct timing_generator *optc, enum crtc_state state) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); switch (state) { case CRTC_STATE_VBLANK: @@ -730,8 +718,8 @@ static void tgn10_wait_for_state(struct timing_generator *tg, } } -static void tgn10_set_early_control( - struct timing_generator *tg, +void optc1_set_early_control( + struct timing_generator *optc, uint32_t early_cntl) { /* asic design change, do not need this control @@ -740,11 +728,11 @@ static void tgn10_set_early_control( } -static void tgn10_set_static_screen_control( - struct timing_generator *tg, +void optc1_set_static_screen_control( + struct timing_generator *optc, uint32_t value) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); /* Bit 8 is no longer applicable in RV for PSR case, * set bit 8 to 0 if given @@ -769,11 +757,11 @@ static void tgn10_set_static_screen_control( * ***************************************************************************** */ -static void tgn10_set_drr( - struct timing_generator *tg, +void optc1_set_drr( + struct timing_generator *optc, const struct drr_params *params) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); if (params != NULL && params->vertical_total_max > 0 && @@ -806,15 +794,15 @@ static void tgn10_set_drr( } } -static void tgn10_set_test_pattern( - struct timing_generator *tg, +static void optc1_set_test_pattern( + struct timing_generator *optc, /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' * because this is not DP-specific (which is probably somewhere in DP * encoder) */ enum controller_dp_test_pattern test_pattern, enum dc_color_depth color_depth) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); enum test_pattern_color_format bit_depth; enum test_pattern_dyn_range dyn_range; enum test_pattern_mode mode; @@ -1065,35 +1053,30 @@ static void tgn10_set_test_pattern( } } -static void tgn10_get_crtc_scanoutpos( - struct timing_generator *tg, +void optc1_get_crtc_scanoutpos( + struct timing_generator *optc, uint32_t *v_blank_start, uint32_t *v_blank_end, uint32_t *h_position, uint32_t *v_position) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); struct crtc_position position; REG_GET_2(OTG_V_BLANK_START_END, OTG_V_BLANK_START, v_blank_start, OTG_V_BLANK_END, v_blank_end); - tgn10_get_position(tg, &position); + optc1_get_position(optc, &position); *h_position = position.horizontal_count; *v_position = position.vertical_count; } - - -static void tgn10_enable_stereo(struct timing_generator *tg, +static void optc1_enable_stereo(struct timing_generator *optc, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - - uint32_t active_width = timing->h_addressable; - uint32_t space1_size = timing->v_total - timing->v_addressable; + struct optc *optc1 = DCN10TG_FROM_TG(optc); if (flags) { uint32_t stereo_en; @@ -1121,29 +1104,23 @@ static void tgn10_enable_stereo(struct timing_generator *tg, OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED); } - - REG_UPDATE(OPPBUF_CONTROL, - OPPBUF_ACTIVE_WIDTH, active_width); - - REG_UPDATE(OPPBUF_3D_PARAMETERS_0, - OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); } -static void tgn10_program_stereo(struct timing_generator *tg, +void optc1_program_stereo(struct timing_generator *optc, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) { if (flags->PROGRAM_STEREO) - tgn10_enable_stereo(tg, timing, flags); + optc1_enable_stereo(optc, timing, flags); else - tgn10_disable_stereo(tg); + optc1_disable_stereo(optc); } -static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) +bool optc1_is_stereo_left_eye(struct timing_generator *optc) { bool ret = false; uint32_t left_eye = 0; - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); REG_GET(OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, &left_eye); @@ -1155,7 +1132,7 @@ static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) return ret; } -void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, +void optc1_read_otg_state(struct optc *optc1, struct dcn_otg_state *s) { REG_GET(OTG_CONTROL, @@ -1199,17 +1176,22 @@ void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); } -static void tgn10_tg_init(struct timing_generator *tg) +static void optc1_clear_optc_underflow(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); - tgn10_set_blank_data_double_buffer(tg, true); REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1); } -static bool tgn10_is_tg_enabled(struct timing_generator *tg) +static void optc1_tg_init(struct timing_generator *optc) +{ + optc1_set_blank_data_double_buffer(optc, true); + optc1_clear_optc_underflow(optc); +} + +static bool optc1_is_tg_enabled(struct timing_generator *optc) { - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t otg_enabled = 0; REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled); @@ -1217,50 +1199,65 @@ static bool tgn10_is_tg_enabled(struct timing_generator *tg) return (otg_enabled != 0); } + +static bool optc1_is_optc_underflow_occurred(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t underflow_occurred = 0; + + REG_GET(OPTC_INPUT_GLOBAL_CONTROL, + OPTC_UNDERFLOW_OCCURRED_STATUS, + &underflow_occurred); + + return (underflow_occurred == 1); +} + static const struct timing_generator_funcs dcn10_tg_funcs = { - .validate_timing = tgn10_validate_timing, - .program_timing = tgn10_program_timing, - .program_global_sync = tgn10_program_global_sync, - .enable_crtc = tgn10_enable_crtc, - .disable_crtc = tgn10_disable_crtc, + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc1_enable_crtc, + .disable_crtc = optc1_disable_crtc, /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = tgn10_is_counter_moving, - .get_position = tgn10_get_position, - .get_frame_count = tgn10_get_vblank_counter, - .get_scanoutpos = tgn10_get_crtc_scanoutpos, - .set_early_control = tgn10_set_early_control, + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .set_early_control = optc1_set_early_control, /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = tgn10_wait_for_state, - .set_blank = tgn10_set_blank, - .is_blanked = tgn10_is_blanked, - .set_blank_color = tgn10_program_blank_color, - .did_triggered_reset_occur = tgn10_did_triggered_reset_occur, - .enable_reset_trigger = tgn10_enable_reset_trigger, - .enable_crtc_reset = tgn10_enable_crtc_reset, - .disable_reset_trigger = tgn10_disable_reset_trigger, - .lock = tgn10_lock, - .unlock = tgn10_unlock, - .enable_optc_clock = tgn10_enable_optc_clock, - .set_drr = tgn10_set_drr, - .set_static_screen_control = tgn10_set_static_screen_control, - .set_test_pattern = tgn10_set_test_pattern, - .program_stereo = tgn10_program_stereo, - .is_stereo_left_eye = tgn10_is_stereo_left_eye, - .set_blank_data_double_buffer = tgn10_set_blank_data_double_buffer, - .tg_init = tgn10_tg_init, - .is_tg_enabled = tgn10_is_tg_enabled, + .wait_for_state = optc1_wait_for_state, + .set_blank = optc1_set_blank, + .is_blanked = optc1_is_blanked, + .set_blank_color = optc1_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc1_lock, + .unlock = optc1_unlock, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc1_set_drr, + .set_static_screen_control = optc1_set_static_screen_control, + .set_test_pattern = optc1_set_test_pattern, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, + .tg_init = optc1_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, }; -void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) +void dcn10_timing_generator_init(struct optc *optc1) { - tgn10->base.funcs = &dcn10_tg_funcs; + optc1->base.funcs = &dcn10_tg_funcs; - tgn10->max_h_total = tgn10->tg_mask->OTG_H_TOTAL + 1; - tgn10->max_v_total = tgn10->tg_mask->OTG_V_TOTAL + 1; + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - tgn10->min_h_blank = 32; - tgn10->min_v_blank = 3; - tgn10->min_v_blank_interlace = 5; - tgn10->min_h_sync_width = 8; - tgn10->min_v_sync_width = 1; + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 8; + optc1->min_v_sync_width = 1; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index bb1cbfdc3554..a3c7c2012f05 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -29,7 +29,7 @@ #include "timing_generator.h" #define DCN10TG_FROM_TG(tg)\ - container_of(tg, struct dcn10_timing_generator, base) + container_of(tg, struct optc, base) #define TG_COMMON_REG_LIST_DCN(inst) \ SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ @@ -70,8 +70,6 @@ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ - SRI(OPPBUF_CONTROL, OPPBUF, inst),\ - SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ SRI(CONTROL, VTG, inst),\ SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ SRI(OTG_MASTER_UPDATE_MODE, OTG, inst),\ @@ -84,7 +82,7 @@ SRI(OTG_TEST_PATTERN_COLOR, OTG, inst) -struct dcn_tg_registers { +struct dcn_optc_registers { uint32_t OTG_VERT_SYNC_CONTROL; uint32_t OTG_MASTER_UPDATE_MODE; uint32_t OTG_GSL_CONTROL; @@ -129,9 +127,11 @@ struct dcn_tg_registers { uint32_t OPTC_INPUT_CLOCK_CONTROL; uint32_t OPTC_DATA_SOURCE_SELECT; uint32_t OPTC_INPUT_GLOBAL_CONTROL; - uint32_t OPPBUF_CONTROL; - uint32_t OPPBUF_3D_PARAMETERS_0; uint32_t CONTROL; + uint32_t OTG_GSL_WINDOW_X; + uint32_t OTG_GSL_WINDOW_Y; + uint32_t OTG_VUPDATE_KEEPOUT; + uint32_t OTG_DSC_START_POSITION; }; #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ @@ -211,8 +211,6 @@ struct dcn_tg_registers { SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ - SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ - SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ @@ -332,8 +330,6 @@ struct dcn_tg_registers { type OPTC_SEG0_SRC_SEL;\ type OPTC_UNDERFLOW_OCCURRED_STATUS;\ type OPTC_UNDERFLOW_CLEAR;\ - type OPPBUF_ACTIVE_WIDTH;\ - type OPPBUF_3D_VACT_SPACE1_SIZE;\ type VTG0_ENABLE;\ type VTG0_FP2;\ type VTG0_VCOUNT_INIT;\ @@ -346,22 +342,35 @@ struct dcn_tg_registers { type OTG_GSL2_EN;\ type OTG_GSL_MASTER_EN;\ type OTG_GSL_FORCE_DELAY;\ - type OTG_GSL_CHECK_ALL_FIELDS; + type OTG_GSL_CHECK_ALL_FIELDS;\ + type OTG_GSL_WINDOW_START_X;\ + type OTG_GSL_WINDOW_END_X;\ + type OTG_GSL_WINDOW_START_Y;\ + type OTG_GSL_WINDOW_END_Y;\ + type OTG_RANGE_TIMING_DBUF_UPDATE_MODE;\ + type OTG_GSL_MASTER_MODE;\ + type OTG_MASTER_UPDATE_LOCK_GSL_EN;\ + type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET;\ + type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET;\ + type OTG_DSC_START_POSITION_X;\ + type OTG_DSC_START_POSITION_LINE_NUM;\ + type OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN; -struct dcn_tg_shift { + +struct dcn_optc_shift { TG_REG_FIELD_LIST(uint8_t) }; -struct dcn_tg_mask { +struct dcn_optc_mask { TG_REG_FIELD_LIST(uint32_t) }; -struct dcn10_timing_generator { +struct optc { struct timing_generator base; - const struct dcn_tg_registers *tg_regs; - const struct dcn_tg_shift *tg_shift; - const struct dcn_tg_mask *tg_mask; + const struct dcn_optc_registers *tg_regs; + const struct dcn_optc_shift *tg_shift; + const struct dcn_optc_mask *tg_mask; enum controller_id controller_id; @@ -376,7 +385,7 @@ struct dcn10_timing_generator { uint32_t min_v_blank_interlace; }; -void dcn10_timing_generator_init(struct dcn10_timing_generator *tg); +void dcn10_timing_generator_init(struct optc *optc); struct dcn_otg_state { uint32_t v_blank_start; @@ -397,7 +406,77 @@ struct dcn_otg_state { uint32_t otg_enabled; }; -void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, +void optc1_read_otg_state(struct optc *optc1, struct dcn_otg_state *s); +bool optc1_validate_timing( + struct timing_generator *optc, + const struct dc_crtc_timing *timing); + +void optc1_program_timing( + struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing, + bool use_vbios); + +void optc1_program_global_sync( + struct timing_generator *optc); + +bool optc1_disable_crtc(struct timing_generator *optc); + +bool optc1_is_counter_moving(struct timing_generator *optc); + +void optc1_get_position(struct timing_generator *optc, + struct crtc_position *position); + +uint32_t optc1_get_vblank_counter(struct timing_generator *optc); + +void optc1_get_crtc_scanoutpos( + struct timing_generator *optc, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position); + +void optc1_set_early_control( + struct timing_generator *optc, + uint32_t early_cntl); + +void optc1_wait_for_state(struct timing_generator *optc, + enum crtc_state state); + +void optc1_set_blank(struct timing_generator *optc, + bool enable_blanking); + +bool optc1_is_blanked(struct timing_generator *optc); + +void optc1_program_blank_color( + struct timing_generator *optc, + const struct tg_color *black_color); + +bool optc1_did_triggered_reset_occur( + struct timing_generator *optc); + +void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst); + +void optc1_disable_reset_trigger(struct timing_generator *optc); + +void optc1_lock(struct timing_generator *optc); + +void optc1_unlock(struct timing_generator *optc); + +void optc1_enable_optc_clock(struct timing_generator *optc, bool enable); + +void optc1_set_drr( + struct timing_generator *optc, + const struct drr_params *params); + +void optc1_set_static_screen_control( + struct timing_generator *optc, + uint32_t value); + +void optc1_program_stereo(struct timing_generator *optc, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags); + +bool optc1_is_stereo_left_eye(struct timing_generator *optc); + #endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 10cce51d31d2..44825e2c9ebb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -34,7 +34,7 @@ #include "dcn10/dcn10_mpc.h" #include "irq/dcn10/irq_service_dcn10.h" #include "dcn10/dcn10_dpp.h" -#include "dcn10/dcn10_timing_generator.h" +#include "dcn10_optc.h" #include "dcn10/dcn10_hw_sequencer.h" #include "dce110/dce110_hw_sequencer.h" #include "dcn10/dcn10_opp.h" @@ -348,18 +348,18 @@ static const struct dcn_mpc_mask mpc_mask = { #define tg_regs(id)\ [id] = {TG_COMMON_REG_LIST_DCN1_0(id)} -static const struct dcn_tg_registers tg_regs[] = { +static const struct dcn_optc_registers tg_regs[] = { tg_regs(0), tg_regs(1), tg_regs(2), tg_regs(3), }; -static const struct dcn_tg_shift tg_shift = { +static const struct dcn_optc_shift tg_shift = { TG_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) }; -static const struct dcn_tg_mask tg_mask = { +static const struct dcn_optc_mask tg_mask = { TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK) }; @@ -553,8 +553,8 @@ static struct timing_generator *dcn10_timing_generator_create( struct dc_context *ctx, uint32_t instance) { - struct dcn10_timing_generator *tgn10 = - kzalloc(sizeof(struct dcn10_timing_generator), GFP_KERNEL); + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); if (!tgn10) return NULL; @@ -678,6 +678,7 @@ static struct dce_hwseq *dcn10_hwseq_create( hws->shifts = &hwseq_shift; hws->masks = &hwseq_mask; hws->wa.DEGVIDCN10_253 = true; + hws->wa.false_optc_underflow = true; } return hws; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 87bab8e8139f..3488af2b5786 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'utils' sub-component of DAL. # It provides the general basic services required by other DAL # subcomponents. diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index 4c31fa54af39..c109b2c34c8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -35,35 +35,6 @@ static void set_soc_bounding_box(struct _vcs_dpi_soc_bounding_box_st *soc, enum soc->writeback_latency_us = 12.0; soc->ideal_dram_bw_after_urgent_percent = 80.0; soc->max_request_size_bytes = 256; - - soc->vmin.dcfclk_mhz = 300.0; - soc->vmin.dispclk_mhz = 608.0; - soc->vmin.dppclk_mhz = 435.0; - soc->vmin.dram_bw_per_chan_gbps = 12.8; - soc->vmin.phyclk_mhz = 540.0; - soc->vmin.socclk_mhz = 208.0; - - soc->vmid.dcfclk_mhz = 600.0; - soc->vmid.dispclk_mhz = 661.0; - soc->vmid.dppclk_mhz = 661.0; - soc->vmid.dram_bw_per_chan_gbps = 12.8; - soc->vmid.phyclk_mhz = 540.0; - soc->vmid.socclk_mhz = 208.0; - - soc->vnom.dcfclk_mhz = 600.0; - soc->vnom.dispclk_mhz = 661.0; - soc->vnom.dppclk_mhz = 661.0; - soc->vnom.dram_bw_per_chan_gbps = 38.4; - soc->vnom.phyclk_mhz = 810; - soc->vnom.socclk_mhz = 208.0; - - soc->vmax.dcfclk_mhz = 600.0; - soc->vmax.dispclk_mhz = 1086.0; - soc->vmax.dppclk_mhz = 661.0; - soc->vmax.dram_bw_per_chan_gbps = 38.4; - soc->vmax.phyclk_mhz = 810.0; - soc->vmax.socclk_mhz = 208.0; - soc->downspread_percent = 0.5; soc->dram_page_open_time_ns = 50.0; soc->dram_rw_turnaround_time_ns = 17.5; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 2d9d6298f0d3..aeebd8bee628 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -79,10 +79,6 @@ struct _vcs_dpi_soc_bounding_box_st { double writeback_latency_us; double ideal_dram_bw_after_urgent_percent; unsigned int max_request_size_bytes; - struct _vcs_dpi_voltage_scaling_st vmin; - struct _vcs_dpi_voltage_scaling_st vmid; - struct _vcs_dpi_voltage_scaling_st vnom; - struct _vcs_dpi_voltage_scaling_st vmax; double downspread_percent; double dram_page_open_time_ns; double dram_rw_turnaround_time_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 1f337ecfeab0..260e113fcc02 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -28,6 +28,15 @@ #include "dml_inline_defs.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + #define BPP_INVALID 0 #define BPP_BLENDED_PIPE 0xffffffff static const unsigned int NumberOfStates = DC__VOLTAGE_STATES; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 8ba962df42e6..325dd2b757d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -27,6 +27,15 @@ #include "display_mode_vba.h" #include "display_rq_dlg_calc.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, double *refcyc_per_req_delivery_pre_cur, double *refcyc_per_req_delivery_cur, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index 1e4b1e383401..c2037daa8e66 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -28,6 +28,15 @@ #include "dml_inline_defs.h" +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index bc7d8c707221..324239c77958 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -27,6 +27,16 @@ #include "dc_features.h" #include "dml_inline_defs.h" + +/* + * NOTE: + * This file is gcc-parseable HW gospel, coming straight from HW engineers. + * + * It doesn't adhere to Linux kernel style and sometimes will do things in odd + * ways. Unless there is something clearly wrong with it the code should + * remain as-is as it provides us with a guarantee from HW that it is correct. + */ + void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box) { to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index 70d01a9e9676..562ee189d780 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'gpio' sub-component of DAL. # It provides the control and status of HW GPIO pins. diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile index 55603400acd9..352885cb4d07 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile +++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'i2c' sub-component of DAL. # It provides the control and status of HW i2c engine of the adapter. diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index d680b565af6f..d6971054ec07 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -212,7 +212,6 @@ struct pipe_ctx { struct _vcs_dpi_display_rq_regs_st rq_regs; struct _vcs_dpi_display_pipe_dest_params_st pipe_dlg_param; #endif - struct dwbc *dwbc; }; struct resource_context { @@ -241,6 +240,7 @@ struct dce_bw_output { struct dcn_bw_clocks { int dispclk_khz; + int dppclk_khz; bool dppclk_div; int dcfclk_khz; int dcfclk_deep_sleep_khz; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index 1e231f6de732..132d18d4b293 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -349,10 +349,10 @@ struct dcn_bw_internal_vars { float dst_x_after_scaler; float dst_y_after_scaler; float time_calc; - float v_update_offset[number_of_planes_minus_one + 1]; + float v_update_offset[number_of_planes_minus_one + 1][2]; float total_repeater_delay; - float v_update_width[number_of_planes_minus_one + 1]; - float v_ready_offset[number_of_planes_minus_one + 1]; + float v_update_width[number_of_planes_minus_one + 1][2]; + float v_ready_offset[number_of_planes_minus_one + 1][2]; float time_setup; float extra_latency; float maximum_vstartup; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index 48217ecfabd4..a83a48494613 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -50,9 +50,9 @@ struct abm_funcs { bool (*set_backlight_level)(struct abm *abm, unsigned int backlight_level, unsigned int frame_ramp, - unsigned int controller_id); + unsigned int controller_id, + bool use_smooth_brightness); unsigned int (*get_current_backlight_8_bit)(struct abm *abm); - bool (*is_dmcu_initialized)(struct abm *abm); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index b59712b41b81..ce206355461b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -63,6 +63,7 @@ struct dmcu_funcs { unsigned int wait_loop_number); void (*get_psr_wait_loop)(struct dmcu *dmcu, unsigned int *psr_wait_loop_number); + bool (*is_dmcu_initialized)(struct dmcu *dmcu); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index ccb4896975c2..25edbde6163e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -68,7 +68,7 @@ struct dpp_funcs { void (*dpp_set_csc_adjustment)( struct dpp *dpp, - const struct out_csc_color_matrix *tbl_entry); + const uint16_t *regval); void (*dpp_power_on_regamma_lut)( struct dpp *dpp, @@ -122,7 +122,7 @@ struct dpp_funcs { void (*set_cursor_attributes)( struct dpp *dpp_base, - const struct dc_cursor_attributes *attr); + enum dc_cursor_color_format color_format); void (*set_cursor_position)( struct dpp *dpp_base, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h index 49b12f602e79..b7c7e70022e4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -28,6 +28,20 @@ #include "mem_input.h" + +enum cursor_pitch { + CURSOR_PITCH_64_PIXELS = 0, + CURSOR_PITCH_128_PIXELS, + CURSOR_PITCH_256_PIXELS +}; + +enum cursor_lines_per_chunk { + CURSOR_LINE_PER_CHUNK_2 = 1, + CURSOR_LINE_PER_CHUNK_4, + CURSOR_LINE_PER_CHUNK_8, + CURSOR_LINE_PER_CHUNK_16 +}; + struct hubp { struct hubp_funcs *funcs; struct dc_context *ctx; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index ddc56700109b..e3f0b4056318 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -126,36 +126,12 @@ struct default_adjustment { bool force_hw_default; }; -struct out_csc_color_matrix { - enum dc_color_space color_space; - uint16_t regval[12]; -}; -struct output_csc_matrix { +struct out_csc_color_matrix { enum dc_color_space color_space; uint16_t regval[12]; }; -static const struct output_csc_matrix output_csc_matrix[] = { - { COLOR_SPACE_SRGB, - { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, - { COLOR_SPACE_SRGB_LIMITED, - { 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} }, - { COLOR_SPACE_YCBCR601, - { 0xE04, 0xF444, 0xFDB9, 0x1004, 0x831, 0x1016, 0x320, 0x201, 0xFB45, - 0xF6B7, 0xE04, 0x1004} }, - { COLOR_SPACE_YCBCR709, - { 0xE04, 0xF345, 0xFEB7, 0x1004, 0x5D3, 0x1399, 0x1FA, - 0x201, 0xFCCA, 0xF533, 0xE04, 0x1004} }, - - /* TODO: correct values below */ - { COLOR_SPACE_YCBCR601_LIMITED, - { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, - 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, - { COLOR_SPACE_YCBCR709_LIMITED, - { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, - 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, -}; enum opp_regamma { OPP_REGAMMA_BYPASS = 0, @@ -178,4 +154,41 @@ struct dc_bias_and_scale { uint16_t bias_blue; }; +enum test_pattern_dyn_range { + TEST_PATTERN_DYN_RANGE_VESA = 0, + TEST_PATTERN_DYN_RANGE_CEA +}; + +enum test_pattern_mode { + TEST_PATTERN_MODE_COLORSQUARES_RGB = 0, + TEST_PATTERN_MODE_COLORSQUARES_YCBCR601, + TEST_PATTERN_MODE_COLORSQUARES_YCBCR709, + TEST_PATTERN_MODE_VERTICALBARS, + TEST_PATTERN_MODE_HORIZONTALBARS, + TEST_PATTERN_MODE_SINGLERAMP_RGB, + TEST_PATTERN_MODE_DUALRAMP_RGB +}; + +enum test_pattern_color_format { + TEST_PATTERN_COLOR_FORMAT_BPC_6 = 0, + TEST_PATTERN_COLOR_FORMAT_BPC_8, + TEST_PATTERN_COLOR_FORMAT_BPC_10, + TEST_PATTERN_COLOR_FORMAT_BPC_12 +}; + +enum controller_dp_test_pattern { + CONTROLLER_DP_TEST_PATTERN_D102 = 0, + CONTROLLER_DP_TEST_PATTERN_SYMBOLERROR, + CONTROLLER_DP_TEST_PATTERN_PRBS7, + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES, + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS, + CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS, + CONTROLLER_DP_TEST_PATTERN_COLORRAMP, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + CONTROLLER_DP_TEST_PATTERN_RESERVED_8, + CONTROLLER_DP_TEST_PATTERN_RESERVED_9, + CONTROLLER_DP_TEST_PATTERN_RESERVED_A, + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA +}; + #endif /* __DAL_HW_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 8a08f0a97f94..0fd329deacd8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -1,4 +1,26 @@ /* + * Copyright 2017 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. + * + */ +/* * link_encoder.h * * Created on: Oct 6, 2015 diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 72ea33526a5c..23a8d5e53a89 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -26,7 +26,10 @@ #define __DC_MPCC_H__ #include "dc_hw_types.h" -#include "opp.h" +#include "hw_shared.h" + +#define MAX_MPCC 6 +#define MAX_OPP 6 enum mpc_output_csc_mode { MPC_OUTPUT_CSC_DISABLE = 0, @@ -34,45 +37,151 @@ enum mpc_output_csc_mode { MPC_OUTPUT_CSC_COEF_B }; -struct mpcc_cfg { - int dpp_id; - int opp_id; - struct mpc_tree_cfg *tree_cfg; - unsigned int z_index; - struct tg_color black_color; - bool per_pixel_alpha; - bool pre_multiplied_alpha; +enum mpcc_blend_mode { + MPCC_BLEND_MODE_BYPASS, + MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH, + MPCC_BLEND_MODE_TOP_LAYER_ONLY, + MPCC_BLEND_MODE_TOP_BOT_BLENDING +}; + +enum mpcc_alpha_blend_mode { + MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA, + MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN, + MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA +}; + +/* + * MPCC blending configuration + */ +struct mpcc_blnd_cfg { + struct tg_color black_color; /* background color */ + enum mpcc_alpha_blend_mode alpha_mode; /* alpha blend mode */ + bool pre_multiplied_alpha; /* alpha pre-multiplied mode flag */ + int global_gain; + int global_alpha; + bool overlap_only; + +}; + +struct mpcc_sm_cfg { + bool enable; + /* 0-single plane,2-row subsampling,4-column subsampling,6-checkboard subsampling */ + int sm_mode; + /* 0- disable frame alternate, 1- enable frame alternate */ + bool frame_alt; + /* 0- disable field alternate, 1- enable field alternate */ + bool field_alt; + /* 0-no force,2-force frame polarity from top,3-force frame polarity from bottom */ + int force_next_frame_porlarity; + /* 0-no force,2-force field polarity from top,3-force field polarity from bottom */ + int force_next_field_polarity; +}; + +/* + * MPCC connection and blending configuration for a single MPCC instance. + * This struct is used as a node in an MPC tree. + */ +struct mpcc { + int mpcc_id; /* MPCC physical instance */ + int dpp_id; /* DPP input to this MPCC */ + struct mpcc *mpcc_bot; /* pointer to bottom layer MPCC. NULL when not connected */ + struct mpcc_blnd_cfg blnd_cfg; /* The blending configuration for this MPCC */ + struct mpcc_sm_cfg sm_cfg; /* stereo mix setting for this MPCC */ +}; + +/* + * MPC tree represents all MPCC connections for a pipe. + */ +struct mpc_tree { + int opp_id; /* The OPP instance that owns this MPC tree */ + struct mpcc *opp_list; /* The top MPCC layer of the MPC tree that outputs to OPP endpoint */ }; struct mpc { const struct mpc_funcs *funcs; struct dc_context *ctx; + + struct mpcc mpcc_array[MAX_MPCC]; }; struct mpc_funcs { - int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + /* + * Insert DPP into MPC tree based on specified blending position. + * Only used for planes that are part of blending chain for OPP output + * + * Parameters: + * [in/out] mpc - MPC context. + * [in/out] tree - MPC tree structure that plane will be added to. + * [in] blnd_cfg - MPCC blending configuration for the new blending layer. + * [in] sm_cfg - MPCC stereo mix configuration for the new blending layer. + * stereo mix must disable for the very bottom layer of the tree config. + * [in] insert_above_mpcc - Insert new plane above this MPCC. If NULL, insert as bottom plane. + * [in] dpp_id - DPP instance for the plane to be added. + * [in] mpcc_id - The MPCC physical instance to use for blending. + * + * Return: struct mpcc* - MPCC that was added. + */ + struct mpcc* (*insert_plane)( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc_blnd_cfg *blnd_cfg, + struct mpcc_sm_cfg *sm_cfg, + struct mpcc *insert_above_mpcc, + int dpp_id, + int mpcc_id); - void (*remove)(struct mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - int opp_id, - int mpcc_inst); + /* + * Remove a specified MPCC from the MPC tree. + * + * Parameters: + * [in/out] mpc - MPC context. + * [in/out] tree - MPC tree structure that plane will be removed from. + * [in/out] mpcc - MPCC to be removed from tree. + * + * Return: void + */ + void (*remove_mpcc)( + struct mpc *mpc, + struct mpc_tree *tree, + struct mpcc *mpcc); - void (*wait_for_idle)(struct mpc *mpc, int id); + /* + * Reset the MPCC HW status by disconnecting all muxes. + * + * Parameters: + * [in/out] mpc - MPC context. + * + * Return: void + */ + void (*mpc_init)(struct mpc *mpc); - void (*update_blend_mode)(struct mpc *mpc, struct mpcc_cfg *cfg); + /* + * Update the blending configuration for a specified MPCC. + * + * Parameters: + * [in/out] mpc - MPC context. + * [in] blnd_cfg - MPCC blending configuration. + * [in] mpcc_id - The MPCC physical instance. + * + * Return: void + */ + void (*update_blending)( + struct mpc *mpc, + struct mpcc_blnd_cfg *blnd_cfg, + int mpcc_id); - int (*get_opp_id)(struct mpc *mpc, int mpcc_id); + struct mpcc* (*get_mpcc_for_dpp)( + struct mpc_tree *tree, + int dpp_id); + + void (*wait_for_idle)(struct mpc *mpc, int id); - void (*set_output_csc)(struct mpc *mpc, - int opp_id, - const struct out_csc_color_matrix *tbl_entry, - enum mpc_output_csc_mode ocsc_mode); + void (*assert_mpcc_idle_before_connect)(struct mpc *mpc, int mpcc_id); - void (*set_ocsc_default)(struct mpc *mpc, - int opp_id, - enum dc_color_space color_space, - enum mpc_output_csc_mode ocsc_mode); + void (*init_mpcc_list_from_hw)( + struct mpc *mpc, + struct mpc_tree *tree); }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 579d1059a3d4..ab8fb77f1ae5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -29,6 +29,7 @@ #include "hw_shared.h" #include "dc_hw_types.h" #include "transform.h" +#include "mpc.h" struct fixed31_32; @@ -204,7 +205,7 @@ struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; struct pwl_params regamma_params; - struct mpc_tree_cfg mpc_tree; + struct mpc_tree mpc_tree_params; bool mpcc_disconnect_pending[MAX_PIPES]; const struct opp_funcs *funcs; }; @@ -248,6 +249,21 @@ enum ovl_csc_adjust_item { OVERLAY_COLOR_TEMPERATURE }; +enum oppbuf_display_segmentation { + OPPBUF_DISPLAY_SEGMENTATION_1_SEGMENT = 0, + OPPBUF_DISPLAY_SEGMENTATION_2_SEGMENT = 1, + OPPBUF_DISPLAY_SEGMENTATION_4_SEGMENT = 2, + OPPBUF_DISPLAY_SEGMENTATION_4_SEGMENT_SPLIT_LEFT = 3, + OPPBUF_DISPLAY_SEGMENTATION_4_SEGMENT_SPLIT_RIGHT = 4 +}; + +struct oppbuf_params { + uint32_t active_width; + enum oppbuf_display_segmentation mso_segmentation; + uint32_t mso_overlap_pixel_num; + uint32_t pixel_repetition; +}; + struct opp_funcs { @@ -276,26 +292,11 @@ struct opp_funcs { void (*opp_destroy)(struct output_pixel_processor **opp); - void (*opp_set_stereo_polarity)( - struct output_pixel_processor *opp, - bool enable, - bool rightEyePolarity); - - void (*opp_set_test_pattern)( - struct output_pixel_processor *opp, - bool enable); - - void (*opp_dpg_blank_enable)( - struct output_pixel_processor *opp, - bool enable, - const struct tg_color *color, - int width, - int height); - - void (*opp_convert_pti)( + void (*opp_program_stereo)( struct output_pixel_processor *opp, bool enable, - bool polarity); + const struct dc_crtc_timing *timing); + }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 3050afe8e8a9..b5db1692393c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -1,4 +1,26 @@ /* + * Copyright 2017 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. + * + */ +/* * stream_encoder.h * */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 860259913d78..ec312f1a3e55 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -26,6 +26,8 @@ #ifndef __DAL_TIMING_GENERATOR_TYPES_H__ #define __DAL_TIMING_GENERATOR_TYPES_H__ +#include "hw_shared.h" + struct dc_bios; /* Contains CRTC vertical/horizontal pixel counters */ @@ -40,6 +42,19 @@ struct dcp_gsl_params { int gsl_master; }; +struct gsl_params { + int gsl0_en; + int gsl1_en; + int gsl2_en; + int gsl_master_en; + int gsl_master_mode; + int master_update_lock_gsl_en; + int gsl_window_start_x; + int gsl_window_end_x; + int gsl_window_start_y; + int gsl_window_end_y; +}; + /* define the structure of Dynamic Refresh Mode */ struct drr_params { uint32_t vertical_total_min; @@ -50,43 +65,6 @@ struct drr_params { #define LEFT_EYE_3D_PRIMARY_SURFACE 1 #define RIGHT_EYE_3D_PRIMARY_SURFACE 0 -enum test_pattern_dyn_range { - TEST_PATTERN_DYN_RANGE_VESA = 0, - TEST_PATTERN_DYN_RANGE_CEA -}; - -enum test_pattern_mode { - TEST_PATTERN_MODE_COLORSQUARES_RGB = 0, - TEST_PATTERN_MODE_COLORSQUARES_YCBCR601, - TEST_PATTERN_MODE_COLORSQUARES_YCBCR709, - TEST_PATTERN_MODE_VERTICALBARS, - TEST_PATTERN_MODE_HORIZONTALBARS, - TEST_PATTERN_MODE_SINGLERAMP_RGB, - TEST_PATTERN_MODE_DUALRAMP_RGB -}; - -enum test_pattern_color_format { - TEST_PATTERN_COLOR_FORMAT_BPC_6 = 0, - TEST_PATTERN_COLOR_FORMAT_BPC_8, - TEST_PATTERN_COLOR_FORMAT_BPC_10, - TEST_PATTERN_COLOR_FORMAT_BPC_12 -}; - -enum controller_dp_test_pattern { - CONTROLLER_DP_TEST_PATTERN_D102 = 0, - CONTROLLER_DP_TEST_PATTERN_SYMBOLERROR, - CONTROLLER_DP_TEST_PATTERN_PRBS7, - CONTROLLER_DP_TEST_PATTERN_COLORSQUARES, - CONTROLLER_DP_TEST_PATTERN_VERTICALBARS, - CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS, - CONTROLLER_DP_TEST_PATTERN_COLORRAMP, - CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, - CONTROLLER_DP_TEST_PATTERN_RESERVED_8, - CONTROLLER_DP_TEST_PATTERN_RESERVED_9, - CONTROLLER_DP_TEST_PATTERN_RESERVED_A, - CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA -}; - enum crtc_state { CRTC_STATE_VBLANK = 0, CRTC_STATE_VACTIVE @@ -100,6 +78,12 @@ struct _dlg_otg_param { enum signal_type signal; }; +struct vupdate_keepout_params { + int start_offset; + int end_offset; + int enable; +}; + struct crtc_stereo_flags { uint8_t PROGRAM_STEREO : 1; uint8_t PROGRAM_POLARITY : 1; @@ -187,6 +171,8 @@ struct timing_generator_funcs { void (*tg_init)(struct timing_generator *tg); bool (*is_tg_enabled)(struct timing_generator *tg); + bool (*is_optc_underflow_occurred)(struct timing_generator *tg); + void (*clear_optc_underflow)(struct timing_generator *tg); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 5dc4ecf618ff..4c0aa56f7bae 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -28,6 +28,7 @@ #include "dc_types.h" #include "clock_source.h" #include "inc/hw/timing_generator.h" +#include "inc/hw/opp.h" #include "inc/hw/link_encoder.h" #include "core_status.h" @@ -40,6 +41,7 @@ enum pipe_gating_control { struct dce_hwseq_wa { bool blnd_crtc_trigger; bool DEGVIDCN10_253; + bool false_optc_underflow; }; struct hwseq_wa_state { @@ -137,10 +139,6 @@ struct hw_sequencer_funcs { void (*disable_plane)(struct dc *dc, struct pipe_ctx *pipe_ctx); - void (*enable_plane)(struct dc *dc, - struct pipe_ctx *pipe, - struct dc_state *context); - void (*update_info_frame)(struct pipe_ctx *pipe_ctx); void (*enable_stream)(struct pipe_ctx *pipe_ctx); @@ -198,6 +196,7 @@ struct hw_sequencer_funcs { void (*edp_backlight_control)( struct dc_link *link, bool enable); + void (*edp_wait_for_hpd_ready)(struct dc_link *link, bool power_up); }; @@ -209,4 +208,8 @@ void color_space_to_black_color( bool hwss_wait_for_blank_complete( struct timing_generator *tg); +const uint16_t *find_color_matrix( + enum dc_color_space color_space, + uint32_t *array_size); + #endif /* __DC_HW_SEQUENCER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index c7e93f7223bd..498515aad4a5 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'audio' sub-component of DAL. # It provides the control and status of HW adapter resources, # that are global for the ASIC and sharable between pipes. diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index a87c0329541f..1fcbc99e63b5 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -26,8 +26,6 @@ #ifndef _OS_TYPES_H_ #define _OS_TYPES_H_ -#if defined __KERNEL__ - #include <asm/byteorder.h> #include <linux/types.h> #include <drm/drmP.h> @@ -46,14 +44,12 @@ #undef WRITE #undef FRAME_SIZE -#define dm_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__) +#define dm_output_to_console(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) #define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__) -#define dm_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) - -#define dm_vlog(fmt, args) vprintk(fmt, args) - +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include <asm/fpu/api.h> #endif /* @@ -89,8 +85,4 @@ BREAK_TO_DEBUGGER(); \ } while (0) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#include <asm/fpu/api.h> -#endif - #endif /* _OS_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/Makefile b/drivers/gpu/drm/amd/display/dc/virtual/Makefile index fc0b7318d9cc..07326d244d50 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/Makefile +++ b/drivers/gpu/drm/amd/display/dc/virtual/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the virtual sub-component of DAL. # It provides the control and status of HW CRTC block. diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index 3248f699daf2..4badaedbaadd 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -463,4 +463,11 @@ uint32_t dal_fixed31_32_u2d19( uint32_t dal_fixed31_32_u0d19( struct fixed31_32 arg); + +uint32_t dal_fixed31_32_clamp_u0d14( + struct fixed31_32 arg); + +uint32_t dal_fixed31_32_clamp_u0d10( + struct fixed31_32 arg); + #endif diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h index 03a7a9ca95ea..c4197432eb7c 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_id.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h @@ -233,10 +233,6 @@ static inline struct graphics_object_id dal_graphics_object_id_init( return result; } -bool dal_graphics_object_id_is_equal( - struct graphics_object_id id1, - struct graphics_object_id id2); - /* Based on internal data members memory layout */ static inline uint32_t dal_graphics_object_id_to_uint( struct graphics_object_id id) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/Makefile b/drivers/gpu/drm/amd/display/modules/freesync/Makefile index db8e0ff6d7a9..fb9a499780e8 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/Makefile +++ b/drivers/gpu/drm/amd/display/modules/freesync/Makefile @@ -1,4 +1,25 @@ # +# Copyright 2017 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. +# +# # Makefile for the 'freesync' sub-module of DAL. # |