2017-09-13 04:58:20 +09:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2019-06-10 07:07:52 +09:00
|
|
|
#include <linux/slab.h>
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
#include "dm_services.h"
|
2017-10-21 05:40:45 +09:00
|
|
|
#include "atom.h"
|
2017-09-13 04:58:20 +09:00
|
|
|
#include "dm_helpers.h"
|
|
|
|
#include "dc.h"
|
|
|
|
#include "grph_object_id.h"
|
|
|
|
#include "gpio_service_interface.h"
|
|
|
|
#include "core_status.h"
|
|
|
|
#include "dc_link_dp.h"
|
|
|
|
#include "dc_link_ddc.h"
|
|
|
|
#include "link_hwss.h"
|
2018-06-10 08:33:14 +09:00
|
|
|
#include "opp.h"
|
2017-08-02 04:00:25 +09:00
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
#include "link_encoder.h"
|
|
|
|
#include "hw_sequencer.h"
|
|
|
|
#include "resource.h"
|
2017-01-25 05:19:42 +09:00
|
|
|
#include "abm.h"
|
2017-09-13 04:58:20 +09:00
|
|
|
#include "fixed31_32.h"
|
2016-12-20 04:10:53 +09:00
|
|
|
#include "dpcd_defs.h"
|
2017-02-18 01:56:03 +09:00
|
|
|
#include "dmcu.h"
|
2019-04-23 08:39:35 +09:00
|
|
|
#include "hw/clk_mgr.h"
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-03-16 02:01:46 +09:00
|
|
|
#define DC_LOGGER_INIT(logger)
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
#define LINK_INFO(...) \
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_HW_HOTPLUG( \
|
2017-09-13 04:58:20 +09:00
|
|
|
__VA_ARGS__)
|
|
|
|
|
2018-08-01 09:14:26 +09:00
|
|
|
#define RETIMER_REDRIVER_INFO(...) \
|
|
|
|
DC_LOG_RETIMER_REDRIVER( \
|
|
|
|
__VA_ARGS__)
|
2017-09-13 04:58:20 +09:00
|
|
|
/*******************************************************************************
|
|
|
|
* Private structures
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
enum {
|
2018-07-14 07:00:06 +09:00
|
|
|
PEAK_FACTOR_X1000 = 1006,
|
|
|
|
/*
|
|
|
|
* Some receivers fail to train on first try and are good
|
|
|
|
* on subsequent tries. 2 retries should be plenty. If we
|
|
|
|
* don't have a successful training then we don't expect to
|
|
|
|
* ever get one.
|
|
|
|
*/
|
|
|
|
LINK_TRAINING_MAX_VERIFY_RETRY = 2
|
2017-09-13 04:58:20 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Private functions
|
|
|
|
******************************************************************************/
|
2017-07-23 09:05:20 +09:00
|
|
|
static void destruct(struct dc_link *link)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2019-01-18 15:07:54 +09:00
|
|
|
if (link->hpd_gpio != NULL) {
|
|
|
|
dal_gpio_close(link->hpd_gpio);
|
|
|
|
dal_gpio_destroy_irq(&link->hpd_gpio);
|
|
|
|
link->hpd_gpio = NULL;
|
|
|
|
}
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
if (link->ddc)
|
|
|
|
dal_ddc_service_destroy(&link->ddc);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
if(link->link_enc)
|
|
|
|
link->link_enc->funcs->destroy(&link->link_enc);
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
if (link->local_sink)
|
|
|
|
dc_sink_release(link->local_sink);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
for (i = 0; i < link->sink_count; ++i)
|
|
|
|
dc_sink_release(link->remote_sinks[i]);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2017-09-26 07:03:14 +09:00
|
|
|
struct gpio *get_hpd_gpio(struct dc_bios *dcb,
|
|
|
|
struct graphics_object_id link_id,
|
|
|
|
struct gpio_service *gpio_service)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
enum bp_result bp_result;
|
|
|
|
struct graphics_object_hpd_info hpd_info;
|
|
|
|
struct gpio_pin_info pin_info;
|
|
|
|
|
2017-09-26 07:03:14 +09:00
|
|
|
if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK)
|
2017-09-13 04:58:20 +09:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
bp_result = dcb->funcs->get_gpio_pin_info(dcb,
|
|
|
|
hpd_info.hpd_int_gpio_uid, &pin_info);
|
|
|
|
|
|
|
|
if (bp_result != BP_RESULT_OK) {
|
|
|
|
ASSERT(bp_result == BP_RESULT_NORECORD);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dal_gpio_service_create_irq(
|
2017-09-26 07:03:14 +09:00
|
|
|
gpio_service,
|
2017-09-13 04:58:20 +09:00
|
|
|
pin_info.offset,
|
|
|
|
pin_info.mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Function: program_hpd_filter
|
|
|
|
*
|
|
|
|
* @brief
|
|
|
|
* Programs HPD filter on associated HPD line
|
|
|
|
*
|
|
|
|
* @param [in] delay_on_connect_in_ms: Connect filter timeout
|
|
|
|
* @param [in] delay_on_disconnect_in_ms: Disconnect filter timeout
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* true on success, false otherwise
|
|
|
|
*/
|
|
|
|
static bool program_hpd_filter(
|
2018-02-07 02:25:17 +09:00
|
|
|
const struct dc_link *link)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
struct gpio *hpd;
|
|
|
|
|
|
|
|
int delay_on_connect_in_ms = 0;
|
|
|
|
int delay_on_disconnect_in_ms = 0;
|
|
|
|
|
2018-01-27 07:39:19 +09:00
|
|
|
if (link->is_hpd_filter_disabled)
|
|
|
|
return false;
|
2017-09-13 04:58:20 +09:00
|
|
|
/* Verify feature is supported */
|
2017-07-23 09:05:20 +09:00
|
|
|
switch (link->connector_signal) {
|
2017-09-13 04:58:20 +09:00
|
|
|
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
|
|
|
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
|
|
|
case SIGNAL_TYPE_HDMI_TYPE_A:
|
|
|
|
/* Program hpd filter */
|
|
|
|
delay_on_connect_in_ms = 500;
|
2018-02-07 02:25:17 +09:00
|
|
|
delay_on_disconnect_in_ms = 100;
|
2017-09-13 04:58:20 +09:00
|
|
|
break;
|
|
|
|
case SIGNAL_TYPE_DISPLAY_PORT:
|
|
|
|
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
|
|
|
/* Program hpd filter to allow DP signal to settle */
|
|
|
|
/* 500: not able to detect MST <-> SST switch as HPD is low for
|
|
|
|
* only 100ms on DELL U2413
|
|
|
|
* 0: some passive dongle still show aux mode instead of i2c
|
|
|
|
* 20-50:not enough to hide bouncing HPD with passive dongle.
|
|
|
|
* also see intermittent i2c read issues.
|
|
|
|
*/
|
|
|
|
delay_on_connect_in_ms = 80;
|
|
|
|
delay_on_disconnect_in_ms = 0;
|
|
|
|
break;
|
|
|
|
case SIGNAL_TYPE_LVDS:
|
|
|
|
case SIGNAL_TYPE_EDP:
|
|
|
|
default:
|
|
|
|
/* Don't program hpd filter */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Obtain HPD handle */
|
2017-09-26 07:03:14 +09:00
|
|
|
hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
if (!hpd)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
/* Setup HPD filtering */
|
|
|
|
if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
|
|
|
|
struct gpio_hpd_config config;
|
|
|
|
|
|
|
|
config.delay_on_connect = delay_on_connect_in_ms;
|
|
|
|
config.delay_on_disconnect = delay_on_disconnect_in_ms;
|
|
|
|
|
|
|
|
dal_irq_setup_hpd_filter(hpd, &config);
|
|
|
|
|
|
|
|
dal_gpio_close(hpd);
|
|
|
|
|
|
|
|
result = true;
|
|
|
|
} else {
|
|
|
|
ASSERT_CRITICAL(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release HPD handle */
|
|
|
|
dal_gpio_destroy_irq(&hpd);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-10-09 22:45:28 +09:00
|
|
|
/**
|
|
|
|
* dc_link_detect_sink() - Determine if there is a sink connected
|
|
|
|
*
|
|
|
|
* @type: Returned connection type
|
|
|
|
* Does not detect downstream devices, such as MST sinks
|
|
|
|
* or display connected through active dongles
|
|
|
|
*/
|
2018-09-27 02:42:10 +09:00
|
|
|
bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
uint32_t is_hpd_high = 0;
|
|
|
|
struct gpio *hpd_pin;
|
|
|
|
|
2018-08-15 04:53:52 +09:00
|
|
|
if (link->connector_signal == SIGNAL_TYPE_LVDS) {
|
|
|
|
*type = dc_connection_single;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-05-23 10:17:38 +09:00
|
|
|
if (link->connector_signal == SIGNAL_TYPE_EDP) {
|
|
|
|
/*in case it is not on*/
|
|
|
|
link->dc->hwss.edp_power_control(link, true);
|
drm/amd/display: Wait edp HPD to high in detect_sink
[Why]
In 99% user case, edp will be post by vbios.
In 1% / current case: Lenovo don't light up edp panel in vbios
post stage, vbios won't be lit up. Thus in dal when we init DCN
10 hw, we power up edp, then we start detect_sink, but internal
time is too short, when we detect it, HPD is still low, so we don't
detect the edp, and edp shows black.
[How]
When we init hw, we wait edp HPD to high after power up edp.
Signed-off-by: Dale Zhao <dale.zhao@amd.com>
Reviewed-by: Eric Yang <eric.yang2@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-22 18:13:46 +09:00
|
|
|
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
|
2019-05-23 10:17:38 +09:00
|
|
|
}
|
drm/amd/display: Wait edp HPD to high in detect_sink
[Why]
In 99% user case, edp will be post by vbios.
In 1% / current case: Lenovo don't light up edp panel in vbios
post stage, vbios won't be lit up. Thus in dal when we init DCN
10 hw, we power up edp, then we start detect_sink, but internal
time is too short, when we detect it, HPD is still low, so we don't
detect the edp, and edp shows black.
[How]
When we init hw, we wait edp HPD to high after power up edp.
Signed-off-by: Dale Zhao <dale.zhao@amd.com>
Reviewed-by: Eric Yang <eric.yang2@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-22 18:13:46 +09:00
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
/* todo: may need to lock gpio access */
|
2017-09-26 07:03:14 +09:00
|
|
|
hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
|
2017-09-13 04:58:20 +09:00
|
|
|
if (hpd_pin == NULL)
|
|
|
|
goto hpd_gpio_failure;
|
|
|
|
|
|
|
|
dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT);
|
|
|
|
dal_gpio_get_value(hpd_pin, &is_hpd_high);
|
|
|
|
dal_gpio_close(hpd_pin);
|
|
|
|
dal_gpio_destroy_irq(&hpd_pin);
|
|
|
|
|
|
|
|
if (is_hpd_high) {
|
|
|
|
*type = dc_connection_single;
|
|
|
|
/* TODO: need to do the actual detection */
|
|
|
|
} else {
|
|
|
|
*type = dc_connection_none;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
hpd_gpio_failure:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-10-03 14:11:01 +09:00
|
|
|
static enum ddc_transaction_type get_ddc_transaction_type(
|
2017-09-13 04:58:20 +09:00
|
|
|
enum signal_type sink_signal)
|
|
|
|
{
|
|
|
|
enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE;
|
|
|
|
|
|
|
|
switch (sink_signal) {
|
|
|
|
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
|
|
|
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
|
|
|
case SIGNAL_TYPE_HDMI_TYPE_A:
|
|
|
|
case SIGNAL_TYPE_LVDS:
|
|
|
|
case SIGNAL_TYPE_RGB:
|
|
|
|
transaction_type = DDC_TRANSACTION_TYPE_I2C;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGNAL_TYPE_DISPLAY_PORT:
|
|
|
|
case SIGNAL_TYPE_EDP:
|
|
|
|
transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
|
|
|
/* MST does not use I2COverAux, but there is the
|
|
|
|
* SPECIAL use case for "immediate dwnstrm device
|
|
|
|
* access" (EPR#370830). */
|
|
|
|
transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return transaction_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum signal_type get_basic_signal_type(
|
|
|
|
struct graphics_object_id encoder,
|
|
|
|
struct graphics_object_id downstream)
|
|
|
|
{
|
|
|
|
if (downstream.type == OBJECT_TYPE_CONNECTOR) {
|
|
|
|
switch (downstream.id) {
|
|
|
|
case CONNECTOR_ID_SINGLE_LINK_DVII:
|
|
|
|
switch (encoder.id) {
|
|
|
|
case ENCODER_ID_INTERNAL_DAC1:
|
|
|
|
case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
|
|
|
|
case ENCODER_ID_INTERNAL_DAC2:
|
|
|
|
case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
|
|
|
|
return SIGNAL_TYPE_RGB;
|
|
|
|
default:
|
|
|
|
return SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CONNECTOR_ID_DUAL_LINK_DVII:
|
|
|
|
{
|
|
|
|
switch (encoder.id) {
|
|
|
|
case ENCODER_ID_INTERNAL_DAC1:
|
|
|
|
case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
|
|
|
|
case ENCODER_ID_INTERNAL_DAC2:
|
|
|
|
case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
|
|
|
|
return SIGNAL_TYPE_RGB;
|
|
|
|
default:
|
|
|
|
return SIGNAL_TYPE_DVI_DUAL_LINK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CONNECTOR_ID_SINGLE_LINK_DVID:
|
|
|
|
return SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
case CONNECTOR_ID_DUAL_LINK_DVID:
|
|
|
|
return SIGNAL_TYPE_DVI_DUAL_LINK;
|
|
|
|
case CONNECTOR_ID_VGA:
|
|
|
|
return SIGNAL_TYPE_RGB;
|
|
|
|
case CONNECTOR_ID_HDMI_TYPE_A:
|
|
|
|
return SIGNAL_TYPE_HDMI_TYPE_A;
|
|
|
|
case CONNECTOR_ID_LVDS:
|
|
|
|
return SIGNAL_TYPE_LVDS;
|
|
|
|
case CONNECTOR_ID_DISPLAY_PORT:
|
|
|
|
return SIGNAL_TYPE_DISPLAY_PORT;
|
|
|
|
case CONNECTOR_ID_EDP:
|
|
|
|
return SIGNAL_TYPE_EDP;
|
|
|
|
default:
|
|
|
|
return SIGNAL_TYPE_NONE;
|
|
|
|
}
|
|
|
|
} else if (downstream.type == OBJECT_TYPE_ENCODER) {
|
|
|
|
switch (downstream.id) {
|
|
|
|
case ENCODER_ID_EXTERNAL_NUTMEG:
|
|
|
|
case ENCODER_ID_EXTERNAL_TRAVIS:
|
|
|
|
return SIGNAL_TYPE_DISPLAY_PORT;
|
|
|
|
default:
|
|
|
|
return SIGNAL_TYPE_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGNAL_TYPE_NONE;
|
|
|
|
}
|
|
|
|
|
2018-10-09 22:45:28 +09:00
|
|
|
/**
|
|
|
|
* dc_link_is_dp_sink_present() - Check if there is a native DP
|
|
|
|
* or passive DP-HDMI dongle connected
|
2017-09-13 04:58:20 +09:00
|
|
|
*/
|
2018-05-30 02:11:55 +09:00
|
|
|
bool dc_link_is_dp_sink_present(struct dc_link *link)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
enum gpio_result gpio_result;
|
|
|
|
uint32_t clock_pin = 0;
|
2018-11-22 19:43:45 +09:00
|
|
|
uint8_t retry = 0;
|
2017-09-13 04:58:20 +09:00
|
|
|
struct ddc *ddc;
|
|
|
|
|
|
|
|
enum connector_id connector_id =
|
|
|
|
dal_graphics_object_id_get_connector_id(link->link_id);
|
|
|
|
|
|
|
|
bool present =
|
|
|
|
((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
|
|
|
|
(connector_id == CONNECTOR_ID_EDP));
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
ddc = dal_ddc_service_get_ddc_pin(link->ddc);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
if (!ddc) {
|
|
|
|
BREAK_TO_DEBUGGER();
|
|
|
|
return present;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Open GPIO and set it to I2C mode */
|
|
|
|
/* Note: this GpioMode_Input will be converted
|
|
|
|
* to GpioConfigType_I2cAuxDualMode in GPIO component,
|
|
|
|
* which indicates we need additional delay */
|
|
|
|
|
|
|
|
if (GPIO_RESULT_OK != dal_ddc_open(
|
|
|
|
ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
|
2019-11-08 07:18:20 +09:00
|
|
|
dal_ddc_close(ddc);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
return present;
|
|
|
|
}
|
|
|
|
|
2018-11-22 19:43:45 +09:00
|
|
|
/*
|
|
|
|
* Read GPIO: DP sink is present if both clock and data pins are zero
|
|
|
|
*
|
|
|
|
* [W/A] plug-unplug DP cable, sometimes customer board has
|
|
|
|
* one short pulse on clk_pin(1V, < 1ms). DP will be config to HDMI/DVI
|
|
|
|
* then monitor can't br light up. Add retry 3 times
|
|
|
|
* But in real passive dongle, it need additional 3ms to detect
|
|
|
|
*/
|
|
|
|
do {
|
|
|
|
gpio_result = dal_gpio_get_value(ddc->pin_clock, &clock_pin);
|
|
|
|
ASSERT(gpio_result == GPIO_RESULT_OK);
|
|
|
|
if (clock_pin)
|
|
|
|
udelay(1000);
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
} while (retry++ < 3);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2016-12-30 00:56:32 +09:00
|
|
|
present = (gpio_result == GPIO_RESULT_OK) && !clock_pin;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
dal_ddc_close(ddc);
|
|
|
|
|
|
|
|
return present;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @brief
|
|
|
|
* Detect output sink type
|
|
|
|
*/
|
2017-09-12 05:42:14 +09:00
|
|
|
static enum signal_type link_detect_sink(
|
|
|
|
struct dc_link *link,
|
|
|
|
enum dc_detect_reason reason)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
enum signal_type result = get_basic_signal_type(
|
|
|
|
link->link_enc->id, link->link_id);
|
|
|
|
|
|
|
|
/* Internal digital encoder will detect only dongles
|
|
|
|
* that require digital signal */
|
|
|
|
|
|
|
|
/* Detection mechanism is different
|
|
|
|
* for different native connectors.
|
|
|
|
* LVDS connector supports only LVDS signal;
|
|
|
|
* PCIE is a bus slot, the actual connector needs to be detected first;
|
|
|
|
* eDP connector supports only eDP signal;
|
|
|
|
* HDMI should check straps for audio */
|
|
|
|
|
|
|
|
/* PCIE detects the actual connector on add-on board */
|
|
|
|
|
|
|
|
if (link->link_id.id == CONNECTOR_ID_PCIE) {
|
|
|
|
/* ZAZTODO implement PCIE add-on card detection */
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (link->link_id.id) {
|
|
|
|
case CONNECTOR_ID_HDMI_TYPE_A: {
|
|
|
|
/* check audio support:
|
|
|
|
* if native HDMI is not supported, switch to DVI */
|
|
|
|
struct audio_support *aud_support = &link->dc->res_pool->audio_support;
|
|
|
|
|
|
|
|
if (!aud_support->hdmi_audio_native)
|
|
|
|
if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A)
|
|
|
|
result = SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CONNECTOR_ID_DISPLAY_PORT: {
|
2017-09-12 05:42:14 +09:00
|
|
|
/* DP HPD short pulse. Passive DP dongle will not
|
|
|
|
* have short pulse
|
|
|
|
*/
|
|
|
|
if (reason != DETECT_REASON_HPDRX) {
|
|
|
|
/* Check whether DP signal detected: if not -
|
|
|
|
* we assume signal is DVI; it could be corrected
|
|
|
|
* to HDMI after dongle detection
|
|
|
|
*/
|
2018-05-30 02:11:55 +09:00
|
|
|
if (!dm_helpers_is_dp_sink_present(link))
|
2017-09-12 05:42:14 +09:00
|
|
|
result = SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum signal_type decide_signal_from_strap_and_dongle_type(
|
|
|
|
enum display_dongle_type dongle_type,
|
|
|
|
struct audio_support *audio_support)
|
|
|
|
{
|
|
|
|
enum signal_type signal = SIGNAL_TYPE_NONE;
|
|
|
|
|
|
|
|
switch (dongle_type) {
|
|
|
|
case DISPLAY_DONGLE_DP_HDMI_DONGLE:
|
|
|
|
if (audio_support->hdmi_audio_on_dongle)
|
|
|
|
signal = SIGNAL_TYPE_HDMI_TYPE_A;
|
|
|
|
else
|
|
|
|
signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
break;
|
|
|
|
case DISPLAY_DONGLE_DP_DVI_DONGLE:
|
|
|
|
signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
break;
|
|
|
|
case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE:
|
|
|
|
if (audio_support->hdmi_audio_native)
|
|
|
|
signal = SIGNAL_TYPE_HDMI_TYPE_A;
|
|
|
|
else
|
|
|
|
signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
signal = SIGNAL_TYPE_NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return signal;
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum signal_type dp_passive_dongle_detection(
|
|
|
|
struct ddc_service *ddc,
|
|
|
|
struct display_sink_capability *sink_cap,
|
|
|
|
struct audio_support *audio_support)
|
|
|
|
{
|
|
|
|
dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
|
|
|
|
ddc, sink_cap);
|
|
|
|
return decide_signal_from_strap_and_dongle_type(
|
|
|
|
sink_cap->dongle_type,
|
|
|
|
audio_support);
|
|
|
|
}
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
static void link_disconnect_sink(struct dc_link *link)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2017-07-23 09:05:20 +09:00
|
|
|
if (link->local_sink) {
|
|
|
|
dc_sink_release(link->local_sink);
|
|
|
|
link->local_sink = NULL;
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
link->dpcd_sink_count = 0;
|
|
|
|
}
|
|
|
|
|
2018-04-14 07:38:56 +09:00
|
|
|
static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *link)
|
|
|
|
{
|
|
|
|
dc_sink_release(link->local_sink);
|
|
|
|
link->local_sink = prev_sink;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-04-05 03:42:44 +09:00
|
|
|
static void read_edp_current_link_settings_on_detect(struct dc_link *link)
|
|
|
|
{
|
|
|
|
union lane_count_set lane_count_set = { {0} };
|
|
|
|
uint8_t link_bw_set;
|
|
|
|
uint8_t link_rate_set;
|
2019-05-23 10:17:38 +09:00
|
|
|
uint32_t read_dpcd_retry_cnt = 10;
|
|
|
|
enum dc_status status = DC_ERROR_UNEXPECTED;
|
|
|
|
int i;
|
2019-06-18 15:55:57 +09:00
|
|
|
union max_down_spread max_down_spread = { {0} };
|
2019-04-05 03:42:44 +09:00
|
|
|
|
|
|
|
// Read DPCD 00101h to find out the number of lanes currently set
|
2019-05-23 10:17:38 +09:00
|
|
|
for (i = 0; i < read_dpcd_retry_cnt; i++) {
|
|
|
|
status = core_link_read_dpcd(
|
|
|
|
link,
|
|
|
|
DP_LANE_COUNT_SET,
|
|
|
|
&lane_count_set.raw,
|
|
|
|
sizeof(lane_count_set));
|
|
|
|
/* First DPCD read after VDD ON can fail if the particular board
|
|
|
|
* does not have HPD pin wired correctly. So if DPCD read fails,
|
|
|
|
* which it should never happen, retry a few times. Target worst
|
|
|
|
* case scenario of 80 ms.
|
|
|
|
*/
|
|
|
|
if (status == DC_OK) {
|
|
|
|
link->cur_link_settings.lane_count = lane_count_set.bits.LANE_COUNT_SET;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-06-25 22:54:21 +09:00
|
|
|
msleep(8);
|
2019-05-23 10:17:38 +09:00
|
|
|
}
|
|
|
|
|
2019-04-05 03:42:44 +09:00
|
|
|
// Read DPCD 00100h to find if standard link rates are set
|
|
|
|
core_link_read_dpcd(link, DP_LINK_BW_SET,
|
|
|
|
&link_bw_set, sizeof(link_bw_set));
|
|
|
|
|
|
|
|
if (link_bw_set == 0) {
|
|
|
|
/* If standard link rates are not being used,
|
|
|
|
* Read DPCD 00115h to find the link rate set used
|
|
|
|
*/
|
|
|
|
core_link_read_dpcd(link, DP_LINK_RATE_SET,
|
|
|
|
&link_rate_set, sizeof(link_rate_set));
|
|
|
|
|
|
|
|
if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
|
|
|
|
link->cur_link_settings.link_rate =
|
|
|
|
link->dpcd_caps.edp_supported_link_rates[link_rate_set];
|
|
|
|
link->cur_link_settings.link_rate_set = link_rate_set;
|
|
|
|
link->cur_link_settings.use_link_rate_set = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
link->cur_link_settings.link_rate = link_bw_set;
|
|
|
|
link->cur_link_settings.use_link_rate_set = false;
|
|
|
|
}
|
2019-06-18 15:55:57 +09:00
|
|
|
// Read DPCD 00003h to find the max down spread.
|
|
|
|
core_link_read_dpcd(link, DP_MAX_DOWNSPREAD,
|
|
|
|
&max_down_spread.raw, sizeof(max_down_spread));
|
|
|
|
link->cur_link_settings.link_spread =
|
|
|
|
max_down_spread.bits.MAX_DOWN_SPREAD ?
|
|
|
|
LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
|
2019-04-05 03:42:44 +09:00
|
|
|
}
|
|
|
|
|
2018-01-24 01:39:09 +09:00
|
|
|
static bool detect_dp(
|
2017-07-23 09:05:20 +09:00
|
|
|
struct dc_link *link,
|
2017-09-13 04:58:20 +09:00
|
|
|
struct display_sink_capability *sink_caps,
|
|
|
|
bool *converter_disable_audio,
|
|
|
|
struct audio_support *audio_support,
|
2017-09-12 05:42:14 +09:00
|
|
|
enum dc_detect_reason reason)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2017-09-12 05:42:14 +09:00
|
|
|
bool boot = false;
|
|
|
|
sink_caps->signal = link_detect_sink(link, reason);
|
2017-09-13 04:58:20 +09:00
|
|
|
sink_caps->transaction_type =
|
|
|
|
get_ddc_transaction_type(sink_caps->signal);
|
|
|
|
|
|
|
|
if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
|
|
|
|
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
|
2018-01-24 01:39:09 +09:00
|
|
|
if (!detect_dp_sink_caps(link))
|
|
|
|
return false;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
if (is_mst_supported(link)) {
|
|
|
|
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
|
2017-09-22 07:53:40 +09:00
|
|
|
link->type = dc_connection_mst_branch;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-06-13 07:37:12 +09:00
|
|
|
dal_ddc_service_set_transaction_type(
|
|
|
|
link->ddc,
|
|
|
|
sink_caps->transaction_type);
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
/*
|
|
|
|
* This call will initiate MST topology discovery. Which
|
|
|
|
* will detect MST ports and add new DRM connector DRM
|
|
|
|
* framework. Then read EDID via remote i2c over aux. In
|
|
|
|
* the end, will notify DRM detect result and save EDID
|
|
|
|
* into DRM framework.
|
|
|
|
*
|
|
|
|
* .detect is called by .fill_modes.
|
|
|
|
* .fill_modes is called by user mode ioctl
|
|
|
|
* DRM_IOCTL_MODE_GETCONNECTOR.
|
|
|
|
*
|
|
|
|
* .get_modes is called by .fill_modes.
|
|
|
|
*
|
|
|
|
* call .get_modes, AMDGPU DM implementation will create
|
|
|
|
* new dc_sink and add to dc_link. For long HPD plug
|
|
|
|
* in/out, MST has its own handle.
|
|
|
|
*
|
|
|
|
* Therefore, just after dc_create, link->sink is not
|
|
|
|
* created for MST until user mode app calls
|
|
|
|
* DRM_IOCTL_MODE_GETCONNECTOR.
|
|
|
|
*
|
|
|
|
* Need check ->sink usages in case ->sink = NULL
|
|
|
|
* TODO: s3 resume check
|
|
|
|
*/
|
2017-09-12 05:42:14 +09:00
|
|
|
if (reason == DETECT_REASON_BOOT)
|
|
|
|
boot = true;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-07-05 08:05:16 +09:00
|
|
|
dm_helpers_dp_update_branch_info(
|
|
|
|
link->ctx,
|
|
|
|
link);
|
|
|
|
|
2017-09-22 07:53:40 +09:00
|
|
|
if (!dm_helpers_dp_mst_start_top_mgr(
|
2017-09-13 04:58:20 +09:00
|
|
|
link->ctx,
|
2017-07-23 09:05:20 +09:00
|
|
|
link, boot)) {
|
2017-09-13 04:58:20 +09:00
|
|
|
/* MST not supported */
|
2017-09-22 07:53:40 +09:00
|
|
|
link->type = dc_connection_single;
|
2017-09-13 04:58:20 +09:00
|
|
|
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
|
|
|
|
}
|
|
|
|
}
|
2017-10-23 22:11:46 +09:00
|
|
|
|
|
|
|
if (link->type != dc_connection_mst_branch &&
|
|
|
|
is_dp_active_dongle(link)) {
|
|
|
|
/* DP active dongles */
|
|
|
|
link->type = dc_connection_active_dongle;
|
|
|
|
if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
|
|
|
|
/*
|
|
|
|
* active dongle unplug processing for short irq
|
|
|
|
*/
|
|
|
|
link_disconnect_sink(link);
|
2018-01-24 01:39:09 +09:00
|
|
|
return true;
|
2017-10-23 22:11:46 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER)
|
|
|
|
*converter_disable_audio = true;
|
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
} else {
|
|
|
|
/* DP passive dongles */
|
2017-07-23 09:05:20 +09:00
|
|
|
sink_caps->signal = dp_passive_dongle_detection(link->ddc,
|
2017-09-13 04:58:20 +09:00
|
|
|
sink_caps,
|
|
|
|
audio_support);
|
|
|
|
}
|
2018-01-24 01:39:09 +09:00
|
|
|
|
|
|
|
return true;
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2018-04-14 07:38:56 +09:00
|
|
|
static bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid)
|
|
|
|
{
|
|
|
|
if (old_edid->length != new_edid->length)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (new_edid->length == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (memcmp(old_edid->raw_edid, new_edid->raw_edid, new_edid->length) == 0);
|
|
|
|
}
|
|
|
|
|
2019-07-11 11:41:51 +09:00
|
|
|
bool wait_for_alt_mode(struct dc_link *link)
|
|
|
|
{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* something is terribly wrong if time out is > 200ms. (5Hz)
|
|
|
|
* 500 microseconds * 400 tries us 200 ms
|
|
|
|
**/
|
|
|
|
unsigned int sleep_time_in_microseconds = 500;
|
|
|
|
unsigned int tries_allowed = 400;
|
|
|
|
bool is_in_alt_mode;
|
|
|
|
unsigned long long enter_timestamp;
|
|
|
|
unsigned long long finish_timestamp;
|
|
|
|
unsigned long long time_taken_in_ns;
|
|
|
|
int tries_taken;
|
|
|
|
|
|
|
|
DC_LOGGER_INIT(link->ctx->logger);
|
|
|
|
|
|
|
|
if (link->link_enc->funcs->is_in_alt_mode == NULL)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
is_in_alt_mode = link->link_enc->funcs->is_in_alt_mode(link->link_enc);
|
|
|
|
DC_LOG_WARNING("DP Alt mode state on HPD: %d\n", is_in_alt_mode);
|
|
|
|
|
|
|
|
if (is_in_alt_mode)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
enter_timestamp = dm_get_timestamp(link->ctx);
|
|
|
|
|
|
|
|
for (tries_taken = 0; tries_taken < tries_allowed; tries_taken++) {
|
|
|
|
udelay(sleep_time_in_microseconds);
|
|
|
|
/* ask the link if alt mode is enabled, if so return ok */
|
|
|
|
if (link->link_enc->funcs->is_in_alt_mode(link->link_enc)) {
|
|
|
|
|
|
|
|
finish_timestamp = dm_get_timestamp(link->ctx);
|
|
|
|
time_taken_in_ns = dm_get_elapse_time_in_ns(
|
|
|
|
link->ctx, finish_timestamp, enter_timestamp);
|
|
|
|
DC_LOG_WARNING("Alt mode entered finished after %llu ms\n",
|
2019-08-21 08:57:13 +09:00
|
|
|
div_u64(time_taken_in_ns, 1000000));
|
2019-07-11 11:41:51 +09:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
finish_timestamp = dm_get_timestamp(link->ctx);
|
|
|
|
time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp,
|
|
|
|
enter_timestamp);
|
|
|
|
DC_LOG_WARNING("Alt mode has timed out after %llu ms\n",
|
2019-08-21 08:57:13 +09:00
|
|
|
div_u64(time_taken_in_ns, 1000000));
|
2019-07-11 11:41:51 +09:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-10-09 22:45:28 +09:00
|
|
|
/**
|
|
|
|
* dc_link_detect() - Detect if a sink is attached to a given link
|
|
|
|
*
|
|
|
|
* link->local_sink is created or destroyed as needed.
|
|
|
|
*
|
|
|
|
* This does not create remote sinks but will trigger DM
|
|
|
|
* to start MST detection if a branch is detected.
|
|
|
|
*/
|
2017-09-12 05:42:14 +09:00
|
|
|
bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
struct dc_sink_init_data sink_init_data = { 0 };
|
|
|
|
struct display_sink_capability sink_caps = { 0 };
|
|
|
|
uint8_t i;
|
|
|
|
bool converter_disable_audio = false;
|
|
|
|
struct audio_support *aud_support = &link->dc->res_pool->audio_support;
|
2018-04-14 07:38:56 +09:00
|
|
|
bool same_edid = false;
|
2017-09-13 04:58:20 +09:00
|
|
|
enum dc_edid_status edid_status;
|
|
|
|
struct dc_context *dc_ctx = link->ctx;
|
2017-08-09 10:01:20 +09:00
|
|
|
struct dc_sink *sink = NULL;
|
2018-04-14 07:38:56 +09:00
|
|
|
struct dc_sink *prev_sink = NULL;
|
|
|
|
struct dpcd_caps prev_dpcd_caps;
|
|
|
|
bool same_dpcd = true;
|
2017-09-13 04:58:20 +09:00
|
|
|
enum dc_connection_type new_connection_type = dc_connection_none;
|
2018-03-16 02:01:46 +09:00
|
|
|
DC_LOGGER_INIT(link->ctx->logger);
|
2019-03-01 04:45:13 +09:00
|
|
|
|
|
|
|
if (dc_is_virtual_signal(link->connector_signal))
|
2017-09-13 04:58:20 +09:00
|
|
|
return false;
|
|
|
|
|
2019-05-23 10:17:38 +09:00
|
|
|
if ((link->connector_signal == SIGNAL_TYPE_LVDS ||
|
|
|
|
link->connector_signal == SIGNAL_TYPE_EDP) &&
|
|
|
|
link->local_sink)
|
|
|
|
return true;
|
|
|
|
|
2018-09-27 02:42:10 +09:00
|
|
|
if (false == dc_link_detect_sink(link, &new_connection_type)) {
|
2017-09-13 04:58:20 +09:00
|
|
|
BREAK_TO_DEBUGGER();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-04-14 07:38:56 +09:00
|
|
|
prev_sink = link->local_sink;
|
|
|
|
if (prev_sink != NULL) {
|
|
|
|
dc_sink_retain(prev_sink);
|
|
|
|
memcpy(&prev_dpcd_caps, &link->dpcd_caps, sizeof(struct dpcd_caps));
|
|
|
|
}
|
2017-09-26 03:53:14 +09:00
|
|
|
link_disconnect_sink(link);
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
if (new_connection_type != dc_connection_none) {
|
2017-07-23 09:05:20 +09:00
|
|
|
link->type = new_connection_type;
|
2019-04-30 03:35:01 +09:00
|
|
|
link->link_state_valid = false;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
/* From Disconnected-to-Connected. */
|
2017-07-23 09:05:20 +09:00
|
|
|
switch (link->connector_signal) {
|
2017-09-13 04:58:20 +09:00
|
|
|
case SIGNAL_TYPE_HDMI_TYPE_A: {
|
|
|
|
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
|
|
|
|
if (aud_support->hdmi_audio_native)
|
|
|
|
sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
|
|
|
|
else
|
|
|
|
sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SIGNAL_TYPE_DVI_SINGLE_LINK: {
|
|
|
|
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
|
|
|
|
sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SIGNAL_TYPE_DVI_DUAL_LINK: {
|
|
|
|
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
|
|
|
|
sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-08-15 04:53:52 +09:00
|
|
|
case SIGNAL_TYPE_LVDS: {
|
|
|
|
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
|
|
|
|
sink_caps.signal = SIGNAL_TYPE_LVDS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
case SIGNAL_TYPE_EDP: {
|
2017-07-27 05:27:37 +09:00
|
|
|
detect_edp_sink_caps(link);
|
2020-01-10 00:20:27 +09:00
|
|
|
read_edp_current_link_settings_on_detect(link);
|
2017-09-13 04:58:20 +09:00
|
|
|
sink_caps.transaction_type =
|
|
|
|
DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
|
|
|
|
sink_caps.signal = SIGNAL_TYPE_EDP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SIGNAL_TYPE_DISPLAY_PORT: {
|
2019-07-11 11:41:51 +09:00
|
|
|
/* wa HPD high coming too early*/
|
|
|
|
if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
|
|
|
|
|
|
|
|
/* if alt mode times out, return false */
|
|
|
|
if (wait_for_alt_mode(link) == false) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-24 01:39:09 +09:00
|
|
|
if (!detect_dp(
|
2017-09-13 04:58:20 +09:00
|
|
|
link,
|
|
|
|
&sink_caps,
|
|
|
|
&converter_disable_audio,
|
2018-04-14 07:38:56 +09:00
|
|
|
aud_support, reason)) {
|
|
|
|
if (prev_sink != NULL)
|
|
|
|
dc_sink_release(prev_sink);
|
2018-01-24 01:39:09 +09:00
|
|
|
return false;
|
2018-04-14 07:38:56 +09:00
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-04-14 07:38:56 +09:00
|
|
|
// Check if dpcp block is the same
|
|
|
|
if (prev_sink != NULL) {
|
|
|
|
if (memcmp(&link->dpcd_caps, &prev_dpcd_caps, sizeof(struct dpcd_caps)))
|
|
|
|
same_dpcd = false;
|
|
|
|
}
|
2018-11-23 19:55:20 +09:00
|
|
|
/* Active dongle plug in without display or downstream unplug*/
|
2019-02-25 20:16:52 +09:00
|
|
|
if (link->type == dc_connection_active_dongle &&
|
|
|
|
link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) {
|
2018-11-23 19:55:20 +09:00
|
|
|
if (prev_sink != NULL) {
|
|
|
|
/* Downstream unplug */
|
2018-04-14 07:38:56 +09:00
|
|
|
dc_sink_release(prev_sink);
|
2018-11-23 19:55:20 +09:00
|
|
|
} else {
|
|
|
|
/* Empty dongle plug in */
|
2019-07-27 03:53:20 +09:00
|
|
|
dp_verify_link_cap_with_retries(link,
|
|
|
|
&link->reported_link_cap,
|
|
|
|
LINK_TRAINING_MAX_VERIFY_RETRY);
|
2018-11-23 19:55:20 +09:00
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
return true;
|
2018-04-14 07:38:56 +09:00
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
if (link->type == dc_connection_mst_branch) {
|
2017-09-13 04:58:20 +09:00
|
|
|
LINK_INFO("link=%d, mst branch is now Connected\n",
|
2017-07-23 09:05:20 +09:00
|
|
|
link->link_index);
|
2017-08-18 05:05:37 +09:00
|
|
|
/* Need to setup mst link_cap struct here
|
|
|
|
* otherwise dc_link_detect() will leave mst link_cap
|
|
|
|
* empty which leads to allocate_mst_payload() has "0"
|
2018-04-19 00:37:53 +09:00
|
|
|
* pbn_per_slot value leading to exception on dc_fixpt_div()
|
2017-08-18 05:05:37 +09:00
|
|
|
*/
|
|
|
|
link->verified_link_cap = link->reported_link_cap;
|
2018-04-14 07:38:56 +09:00
|
|
|
if (prev_sink != NULL)
|
|
|
|
dc_sink_release(prev_sink);
|
2017-09-13 04:58:20 +09:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
DC_ERROR("Invalid connector type! signal:%d\n",
|
2017-07-23 09:05:20 +09:00
|
|
|
link->connector_signal);
|
2018-04-14 07:38:56 +09:00
|
|
|
if (prev_sink != NULL)
|
|
|
|
dc_sink_release(prev_sink);
|
2017-09-13 04:58:20 +09:00
|
|
|
return false;
|
|
|
|
} /* switch() */
|
|
|
|
|
|
|
|
if (link->dpcd_caps.sink_count.bits.SINK_COUNT)
|
|
|
|
link->dpcd_sink_count = link->dpcd_caps.sink_count.
|
|
|
|
bits.SINK_COUNT;
|
2017-09-07 14:02:05 +09:00
|
|
|
else
|
|
|
|
link->dpcd_sink_count = 1;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
dal_ddc_service_set_transaction_type(
|
2017-07-23 09:05:20 +09:00
|
|
|
link->ddc,
|
2017-09-13 04:58:20 +09:00
|
|
|
sink_caps.transaction_type);
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
link->aux_mode = dal_ddc_service_is_in_aux_transaction_mode(
|
|
|
|
link->ddc);
|
2017-03-29 05:57:52 +09:00
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
sink_init_data.link = link;
|
2017-09-13 04:58:20 +09:00
|
|
|
sink_init_data.sink_signal = sink_caps.signal;
|
|
|
|
|
2017-09-08 20:25:35 +09:00
|
|
|
sink = dc_sink_create(&sink_init_data);
|
|
|
|
if (!sink) {
|
|
|
|
DC_ERROR("Failed to create sink!\n");
|
2018-04-14 07:38:56 +09:00
|
|
|
if (prev_sink != NULL)
|
|
|
|
dc_sink_release(prev_sink);
|
2017-09-08 20:25:35 +09:00
|
|
|
return false;
|
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
sink->link->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock;
|
2017-09-26 03:53:14 +09:00
|
|
|
sink->converter_disable_audio = converter_disable_audio;
|
2017-09-08 20:25:35 +09:00
|
|
|
|
2019-02-10 19:13:01 +09:00
|
|
|
/* dc_sink_create returns a new reference */
|
2017-09-26 03:53:14 +09:00
|
|
|
link->local_sink = sink;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2017-09-26 03:53:14 +09:00
|
|
|
edid_status = dm_helpers_read_local_edid(
|
2017-03-29 05:57:52 +09:00
|
|
|
link->ctx,
|
2017-07-23 09:05:20 +09:00
|
|
|
link,
|
2017-07-25 03:04:27 +09:00
|
|
|
sink);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
switch (edid_status) {
|
|
|
|
case EDID_BAD_CHECKSUM:
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_ERROR("EDID checksum invalid.\n");
|
2017-09-13 04:58:20 +09:00
|
|
|
break;
|
|
|
|
case EDID_NO_RESPONSE:
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_ERROR("No EDID read.\n");
|
2018-08-01 23:48:23 +09:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Abort detection for non-DP connectors if we have
|
|
|
|
* no EDID
|
|
|
|
*
|
|
|
|
* DP needs to report as connected if HDP is high
|
|
|
|
* even if we have no EDID in order to go to
|
|
|
|
* fail-safe mode
|
|
|
|
*/
|
2018-08-03 04:32:01 +09:00
|
|
|
if (dc_is_hdmi_signal(link->connector_signal) ||
|
2018-08-16 05:55:18 +09:00
|
|
|
dc_is_dvi_signal(link->connector_signal)) {
|
|
|
|
if (prev_sink != NULL)
|
|
|
|
dc_sink_release(prev_sink);
|
|
|
|
|
2018-08-01 23:48:23 +09:00
|
|
|
return false;
|
2018-08-16 05:55:18 +09:00
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-04-14 07:38:56 +09:00
|
|
|
// Check if edid is the same
|
|
|
|
if ((prev_sink != NULL) && ((edid_status == EDID_THE_SAME) || (edid_status == EDID_OK)))
|
|
|
|
same_edid = is_same_edid(&prev_sink->dc_edid, &sink->dc_edid);
|
|
|
|
|
2018-07-20 04:39:55 +09:00
|
|
|
if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
|
2020-01-22 06:12:45 +09:00
|
|
|
sink_caps.transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
|
2018-07-20 04:39:55 +09:00
|
|
|
/*
|
|
|
|
* TODO debug why Dell 2413 doesn't like
|
|
|
|
* two link trainings
|
|
|
|
*/
|
2017-08-18 05:05:37 +09:00
|
|
|
|
2018-07-20 04:39:55 +09:00
|
|
|
/* deal with non-mst cases */
|
2019-07-27 03:53:20 +09:00
|
|
|
dp_verify_link_cap_with_retries(link,
|
|
|
|
&link->reported_link_cap,
|
|
|
|
LINK_TRAINING_MAX_VERIFY_RETRY);
|
2018-07-20 04:39:55 +09:00
|
|
|
} else {
|
|
|
|
// If edid is the same, then discard new sink and revert back to original sink
|
|
|
|
if (same_edid) {
|
|
|
|
link_disconnect_remap(prev_sink, link);
|
|
|
|
sink = prev_sink;
|
|
|
|
prev_sink = NULL;
|
|
|
|
|
|
|
|
}
|
2018-04-14 07:38:56 +09:00
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-07-20 04:39:55 +09:00
|
|
|
/* HDMI-DVI Dongle */
|
|
|
|
if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A &&
|
|
|
|
!sink->edid_caps.edid_hdmi)
|
|
|
|
sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
/* Connectivity log: detection */
|
2019-05-03 06:32:14 +09:00
|
|
|
for (i = 0; i < sink->dc_edid.length / DC_EDID_BLOCK_SIZE; i++) {
|
2017-09-13 04:58:20 +09:00
|
|
|
CONN_DATA_DETECT(link,
|
2019-05-03 06:32:14 +09:00
|
|
|
&sink->dc_edid.raw_edid[i * DC_EDID_BLOCK_SIZE],
|
|
|
|
DC_EDID_BLOCK_SIZE,
|
2017-07-25 03:04:27 +09:00
|
|
|
"%s: [Block %d] ", sink->edid_caps.display_name, i);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_DETECTION_EDID_PARSER("%s: "
|
2017-09-13 04:58:20 +09:00
|
|
|
"manufacturer_id = %X, "
|
|
|
|
"product_id = %X, "
|
|
|
|
"serial_number = %X, "
|
|
|
|
"manufacture_week = %d, "
|
|
|
|
"manufacture_year = %d, "
|
|
|
|
"display_name = %s, "
|
|
|
|
"speaker_flag = %d, "
|
|
|
|
"audio_mode_count = %d\n",
|
|
|
|
__func__,
|
2017-07-25 03:04:27 +09:00
|
|
|
sink->edid_caps.manufacturer_id,
|
|
|
|
sink->edid_caps.product_id,
|
|
|
|
sink->edid_caps.serial_number,
|
|
|
|
sink->edid_caps.manufacture_week,
|
|
|
|
sink->edid_caps.manufacture_year,
|
|
|
|
sink->edid_caps.display_name,
|
|
|
|
sink->edid_caps.speaker_flags,
|
|
|
|
sink->edid_caps.audio_mode_count);
|
|
|
|
|
|
|
|
for (i = 0; i < sink->edid_caps.audio_mode_count; i++) {
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_DETECTION_EDID_PARSER("%s: mode number = %d, "
|
2017-09-13 04:58:20 +09:00
|
|
|
"format_code = %d, "
|
|
|
|
"channel_count = %d, "
|
|
|
|
"sample_rate = %d, "
|
|
|
|
"sample_size = %d\n",
|
|
|
|
__func__,
|
|
|
|
i,
|
2017-07-25 03:04:27 +09:00
|
|
|
sink->edid_caps.audio_modes[i].format_code,
|
|
|
|
sink->edid_caps.audio_modes[i].channel_count,
|
|
|
|
sink->edid_caps.audio_modes[i].sample_rate,
|
|
|
|
sink->edid_caps.audio_modes[i].sample_size);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/* From Connected-to-Disconnected. */
|
2017-07-23 09:05:20 +09:00
|
|
|
if (link->type == dc_connection_mst_branch) {
|
2017-09-13 04:58:20 +09:00
|
|
|
LINK_INFO("link=%d, mst branch is now Disconnected\n",
|
2017-07-23 09:05:20 +09:00
|
|
|
link->link_index);
|
2017-09-26 03:53:14 +09:00
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
link->mst_stream_alloc_table.stream_count = 0;
|
|
|
|
memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations));
|
|
|
|
}
|
|
|
|
|
2017-09-26 03:53:14 +09:00
|
|
|
link->type = dc_connection_none;
|
|
|
|
sink_caps.signal = SIGNAL_TYPE_NONE;
|
2019-05-29 03:44:40 +09:00
|
|
|
/* When we unplug a passive DP-HDMI dongle connection, dongle_max_pix_clk
|
|
|
|
* is not cleared. If we emulate a DP signal on this connection, it thinks
|
|
|
|
* the dongle is still there and limits the number of modes we can emulate.
|
|
|
|
* Clear dongle_max_pix_clk on disconnect to fix this
|
|
|
|
*/
|
|
|
|
link->dongle_max_pix_clk = 0;
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2018-04-14 07:38:56 +09:00
|
|
|
LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p dpcd same=%d edid same=%d\n",
|
2017-07-25 03:04:27 +09:00
|
|
|
link->link_index, sink,
|
2017-09-13 04:58:20 +09:00
|
|
|
(sink_caps.signal == SIGNAL_TYPE_NONE ?
|
2018-04-14 07:38:56 +09:00
|
|
|
"Disconnected":"Connected"), prev_sink,
|
|
|
|
same_dpcd, same_edid);
|
|
|
|
|
|
|
|
if (prev_sink != NULL)
|
|
|
|
dc_sink_release(prev_sink);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-09-05 21:34:57 +09:00
|
|
|
bool dc_link_get_hpd_state(struct dc_link *dc_link)
|
|
|
|
{
|
|
|
|
uint32_t state;
|
|
|
|
|
2019-01-18 15:07:54 +09:00
|
|
|
dal_gpio_lock_pin(dc_link->hpd_gpio);
|
|
|
|
dal_gpio_get_value(dc_link->hpd_gpio, &state);
|
|
|
|
dal_gpio_unlock_pin(dc_link->hpd_gpio);
|
2018-09-05 21:34:57 +09:00
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
static enum hpd_source_id get_hpd_line(
|
2017-07-23 09:05:20 +09:00
|
|
|
struct dc_link *link)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
struct gpio *hpd;
|
|
|
|
enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN;
|
|
|
|
|
2017-09-26 07:03:14 +09:00
|
|
|
hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
if (hpd) {
|
|
|
|
switch (dal_irq_get_source(hpd)) {
|
|
|
|
case DC_IRQ_SOURCE_HPD1:
|
|
|
|
hpd_id = HPD_SOURCEID1;
|
|
|
|
break;
|
|
|
|
case DC_IRQ_SOURCE_HPD2:
|
|
|
|
hpd_id = HPD_SOURCEID2;
|
|
|
|
break;
|
|
|
|
case DC_IRQ_SOURCE_HPD3:
|
|
|
|
hpd_id = HPD_SOURCEID3;
|
|
|
|
break;
|
|
|
|
case DC_IRQ_SOURCE_HPD4:
|
|
|
|
hpd_id = HPD_SOURCEID4;
|
|
|
|
break;
|
|
|
|
case DC_IRQ_SOURCE_HPD5:
|
|
|
|
hpd_id = HPD_SOURCEID5;
|
|
|
|
break;
|
|
|
|
case DC_IRQ_SOURCE_HPD6:
|
|
|
|
hpd_id = HPD_SOURCEID6;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BREAK_TO_DEBUGGER();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
dal_gpio_destroy_irq(&hpd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hpd_id;
|
|
|
|
}
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
static enum channel_id get_ddc_line(struct dc_link *link)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
struct ddc *ddc;
|
|
|
|
enum channel_id channel = CHANNEL_ID_UNKNOWN;
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
ddc = dal_ddc_service_get_ddc_pin(link->ddc);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
if (ddc) {
|
|
|
|
switch (dal_ddc_get_line(ddc)) {
|
|
|
|
case GPIO_DDC_LINE_DDC1:
|
|
|
|
channel = CHANNEL_ID_DDC1;
|
|
|
|
break;
|
|
|
|
case GPIO_DDC_LINE_DDC2:
|
|
|
|
channel = CHANNEL_ID_DDC2;
|
|
|
|
break;
|
|
|
|
case GPIO_DDC_LINE_DDC3:
|
|
|
|
channel = CHANNEL_ID_DDC3;
|
|
|
|
break;
|
|
|
|
case GPIO_DDC_LINE_DDC4:
|
|
|
|
channel = CHANNEL_ID_DDC4;
|
|
|
|
break;
|
|
|
|
case GPIO_DDC_LINE_DDC5:
|
|
|
|
channel = CHANNEL_ID_DDC5;
|
|
|
|
break;
|
|
|
|
case GPIO_DDC_LINE_DDC6:
|
|
|
|
channel = CHANNEL_ID_DDC6;
|
|
|
|
break;
|
|
|
|
case GPIO_DDC_LINE_DDC_VGA:
|
|
|
|
channel = CHANNEL_ID_DDC_VGA;
|
|
|
|
break;
|
|
|
|
case GPIO_DDC_LINE_I2C_PAD:
|
|
|
|
channel = CHANNEL_ID_I2C_PAD;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BREAK_TO_DEBUGGER();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return channel;
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum transmitter translate_encoder_to_transmitter(
|
|
|
|
struct graphics_object_id encoder)
|
|
|
|
{
|
|
|
|
switch (encoder.id) {
|
|
|
|
case ENCODER_ID_INTERNAL_UNIPHY:
|
|
|
|
switch (encoder.enum_id) {
|
|
|
|
case ENUM_ID_1:
|
|
|
|
return TRANSMITTER_UNIPHY_A;
|
|
|
|
case ENUM_ID_2:
|
|
|
|
return TRANSMITTER_UNIPHY_B;
|
|
|
|
default:
|
|
|
|
return TRANSMITTER_UNKNOWN;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ENCODER_ID_INTERNAL_UNIPHY1:
|
|
|
|
switch (encoder.enum_id) {
|
|
|
|
case ENUM_ID_1:
|
|
|
|
return TRANSMITTER_UNIPHY_C;
|
|
|
|
case ENUM_ID_2:
|
|
|
|
return TRANSMITTER_UNIPHY_D;
|
|
|
|
default:
|
|
|
|
return TRANSMITTER_UNKNOWN;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ENCODER_ID_INTERNAL_UNIPHY2:
|
|
|
|
switch (encoder.enum_id) {
|
|
|
|
case ENUM_ID_1:
|
|
|
|
return TRANSMITTER_UNIPHY_E;
|
|
|
|
case ENUM_ID_2:
|
|
|
|
return TRANSMITTER_UNIPHY_F;
|
|
|
|
default:
|
|
|
|
return TRANSMITTER_UNKNOWN;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ENCODER_ID_INTERNAL_UNIPHY3:
|
|
|
|
switch (encoder.enum_id) {
|
|
|
|
case ENUM_ID_1:
|
|
|
|
return TRANSMITTER_UNIPHY_G;
|
|
|
|
default:
|
|
|
|
return TRANSMITTER_UNKNOWN;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ENCODER_ID_EXTERNAL_NUTMEG:
|
|
|
|
switch (encoder.enum_id) {
|
|
|
|
case ENUM_ID_1:
|
|
|
|
return TRANSMITTER_NUTMEG_CRT;
|
|
|
|
default:
|
|
|
|
return TRANSMITTER_UNKNOWN;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ENCODER_ID_EXTERNAL_TRAVIS:
|
|
|
|
switch (encoder.enum_id) {
|
|
|
|
case ENUM_ID_1:
|
|
|
|
return TRANSMITTER_TRAVIS_CRT;
|
|
|
|
case ENUM_ID_2:
|
|
|
|
return TRANSMITTER_TRAVIS_LCD;
|
|
|
|
default:
|
|
|
|
return TRANSMITTER_UNKNOWN;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return TRANSMITTER_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool construct(
|
2017-07-23 09:05:20 +09:00
|
|
|
struct dc_link *link,
|
2017-09-13 04:58:20 +09:00
|
|
|
const struct link_init_data *init_params)
|
|
|
|
{
|
|
|
|
uint8_t i;
|
2017-02-25 06:25:51 +09:00
|
|
|
struct ddc_service_init_data ddc_service_init_data = { { 0 } };
|
2017-09-13 04:58:20 +09:00
|
|
|
struct dc_context *dc_ctx = init_params->ctx;
|
|
|
|
struct encoder_init_data enc_init_data = { 0 };
|
|
|
|
struct integrated_info info = {{{ 0 }}};
|
|
|
|
struct dc_bios *bios = init_params->dc->ctx->dc_bios;
|
|
|
|
const struct dc_vbios_funcs *bp_funcs = bios->funcs;
|
2018-03-16 02:01:46 +09:00
|
|
|
DC_LOGGER_INIT(dc_ctx->logger);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
|
|
|
|
link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
link->link_status.dpcd_caps = &link->dpcd_caps;
|
|
|
|
|
|
|
|
link->dc = init_params->dc;
|
|
|
|
link->ctx = dc_ctx;
|
2017-07-23 09:05:20 +09:00
|
|
|
link->link_index = init_params->link_index;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2019-05-31 00:56:39 +09:00
|
|
|
memset(&link->preferred_training_settings, 0, sizeof(struct dc_link_training_overrides));
|
|
|
|
memset(&link->preferred_link_setting, 0, sizeof(struct dc_link_settings));
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index);
|
2018-07-31 01:27:23 +09:00
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
|
2019-05-28 01:07:19 +09:00
|
|
|
dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n",
|
2017-11-24 23:11:23 +09:00
|
|
|
__func__, init_params->connector_index,
|
|
|
|
link->link_id.type, OBJECT_TYPE_CONNECTOR);
|
2017-09-13 04:58:20 +09:00
|
|
|
goto create_fail;
|
|
|
|
}
|
|
|
|
|
2018-08-08 03:43:20 +09:00
|
|
|
if (link->dc->res_pool->funcs->link_init)
|
|
|
|
link->dc->res_pool->funcs->link_init(link);
|
|
|
|
|
2019-01-18 15:07:54 +09:00
|
|
|
link->hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
|
2019-02-08 05:12:35 +09:00
|
|
|
if (link->hpd_gpio != NULL) {
|
|
|
|
dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);
|
|
|
|
dal_gpio_unlock_pin(link->hpd_gpio);
|
2019-01-18 15:07:54 +09:00
|
|
|
link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
|
2019-02-08 05:12:35 +09:00
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
switch (link->link_id.id) {
|
|
|
|
case CONNECTOR_ID_HDMI_TYPE_A:
|
2017-07-23 09:05:20 +09:00
|
|
|
link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
break;
|
|
|
|
case CONNECTOR_ID_SINGLE_LINK_DVID:
|
|
|
|
case CONNECTOR_ID_SINGLE_LINK_DVII:
|
2017-07-23 09:05:20 +09:00
|
|
|
link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
|
2017-09-13 04:58:20 +09:00
|
|
|
break;
|
|
|
|
case CONNECTOR_ID_DUAL_LINK_DVID:
|
|
|
|
case CONNECTOR_ID_DUAL_LINK_DVII:
|
2017-07-23 09:05:20 +09:00
|
|
|
link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
|
2017-09-13 04:58:20 +09:00
|
|
|
break;
|
|
|
|
case CONNECTOR_ID_DISPLAY_PORT:
|
2017-07-23 09:05:20 +09:00
|
|
|
link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2019-01-18 15:07:54 +09:00
|
|
|
if (link->hpd_gpio != NULL)
|
2017-07-23 09:05:20 +09:00
|
|
|
link->irq_source_hpd_rx =
|
2019-01-18 15:07:54 +09:00
|
|
|
dal_irq_get_rx_source(link->hpd_gpio);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
break;
|
|
|
|
case CONNECTOR_ID_EDP:
|
2017-07-23 09:05:20 +09:00
|
|
|
link->connector_signal = SIGNAL_TYPE_EDP;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2019-01-18 15:07:54 +09:00
|
|
|
if (link->hpd_gpio != NULL) {
|
2017-07-23 09:05:20 +09:00
|
|
|
link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
|
|
|
|
link->irq_source_hpd_rx =
|
2019-01-18 15:07:54 +09:00
|
|
|
dal_irq_get_rx_source(link->hpd_gpio);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
break;
|
2018-08-15 04:53:52 +09:00
|
|
|
case CONNECTOR_ID_LVDS:
|
|
|
|
link->connector_signal = SIGNAL_TYPE_LVDS;
|
|
|
|
break;
|
2017-09-13 04:58:20 +09:00
|
|
|
default:
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_WARNING("Unsupported Connector type:%d!\n", link->link_id.id);
|
2017-09-13 04:58:20 +09:00
|
|
|
goto create_fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: #DAL3 Implement id to str function.*/
|
|
|
|
LINK_INFO("Connector[%d] description:"
|
|
|
|
"signal %d\n",
|
|
|
|
init_params->connector_index,
|
2017-07-23 09:05:20 +09:00
|
|
|
link->connector_signal);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
ddc_service_init_data.ctx = link->ctx;
|
|
|
|
ddc_service_init_data.id = link->link_id;
|
|
|
|
ddc_service_init_data.link = link;
|
2017-07-23 09:05:20 +09:00
|
|
|
link->ddc = dal_ddc_service_create(&ddc_service_init_data);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
if (link->ddc == NULL) {
|
2017-09-13 04:58:20 +09:00
|
|
|
DC_ERROR("Failed to create ddc_service!\n");
|
|
|
|
goto ddc_create_fail;
|
|
|
|
}
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
link->ddc_hw_inst =
|
2017-09-13 04:58:20 +09:00
|
|
|
dal_ddc_get_line(
|
2017-07-23 09:05:20 +09:00
|
|
|
dal_ddc_service_get_ddc_pin(link->ddc));
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
enc_init_data.ctx = dc_ctx;
|
|
|
|
bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, &enc_init_data.encoder);
|
|
|
|
enc_init_data.connector = link->link_id;
|
|
|
|
enc_init_data.channel = get_ddc_line(link);
|
|
|
|
enc_init_data.hpd_source = get_hpd_line(link);
|
2017-06-14 00:54:10 +09:00
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
link->hpd_src = enc_init_data.hpd_source;
|
2017-06-14 00:54:10 +09:00
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
enc_init_data.transmitter =
|
|
|
|
translate_encoder_to_transmitter(enc_init_data.encoder);
|
|
|
|
link->link_enc = link->dc->res_pool->funcs->link_enc_create(
|
|
|
|
&enc_init_data);
|
|
|
|
|
2019-02-23 01:11:07 +09:00
|
|
|
if (link->link_enc == NULL) {
|
2017-09-13 04:58:20 +09:00
|
|
|
DC_ERROR("Failed to create link encoder!\n");
|
|
|
|
goto link_enc_create_fail;
|
|
|
|
}
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
link->link_enc_hw_inst = link->link_enc->transmitter;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
if (BP_RESULT_OK !=
|
|
|
|
bp_funcs->get_device_tag(dc_ctx->dc_bios, link->link_id, i, &link->device_tag)) {
|
|
|
|
DC_ERROR("Failed to find device tag!\n");
|
|
|
|
goto device_tag_fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Look for device tag that matches connector signal,
|
|
|
|
* CRT for rgb, LCD for other supported signal tyes
|
|
|
|
*/
|
|
|
|
if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios, link->device_tag.dev_id))
|
|
|
|
continue;
|
|
|
|
if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT
|
2017-07-23 09:05:20 +09:00
|
|
|
&& link->connector_signal != SIGNAL_TYPE_RGB)
|
2017-09-13 04:58:20 +09:00
|
|
|
continue;
|
|
|
|
if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD
|
2017-07-23 09:05:20 +09:00
|
|
|
&& link->connector_signal == SIGNAL_TYPE_RGB)
|
2017-09-13 04:58:20 +09:00
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bios->integrated_info)
|
|
|
|
info = *bios->integrated_info;
|
|
|
|
|
|
|
|
/* Look for channel mapping corresponding to connector and device tag */
|
|
|
|
for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
|
|
|
|
struct external_display_path *path =
|
|
|
|
&info.ext_disp_conn_info.path[i];
|
|
|
|
if (path->device_connector_id.enum_id == link->link_id.enum_id
|
|
|
|
&& path->device_connector_id.id == link->link_id.id
|
2017-08-15 07:43:11 +09:00
|
|
|
&& path->device_connector_id.type == link->link_id.type) {
|
|
|
|
|
|
|
|
if (link->device_tag.acpi_device != 0
|
|
|
|
&& path->device_acpi_enum == link->device_tag.acpi_device) {
|
|
|
|
link->ddi_channel_mapping = path->channel_mapping;
|
|
|
|
link->chip_caps = path->caps;
|
|
|
|
} else if (path->device_tag ==
|
|
|
|
link->device_tag.dev_id.raw_device_tag) {
|
|
|
|
link->ddi_channel_mapping = path->channel_mapping;
|
|
|
|
link->chip_caps = path->caps;
|
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO check if GPIO programmed correctly
|
|
|
|
*
|
|
|
|
* If GPIO isn't programmed correctly HPD might not rise or drain
|
|
|
|
* fast enough, leading to bounces.
|
|
|
|
*/
|
2018-02-07 02:25:17 +09:00
|
|
|
program_hpd_filter(link);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
return true;
|
|
|
|
device_tag_fail:
|
|
|
|
link->link_enc->funcs->destroy(&link->link_enc);
|
|
|
|
link_enc_create_fail:
|
2017-07-23 09:05:20 +09:00
|
|
|
dal_ddc_service_destroy(&link->ddc);
|
2017-09-13 04:58:20 +09:00
|
|
|
ddc_create_fail:
|
|
|
|
create_fail:
|
|
|
|
|
2019-01-18 15:07:54 +09:00
|
|
|
if (link->hpd_gpio != NULL) {
|
|
|
|
dal_gpio_destroy_irq(&link->hpd_gpio);
|
|
|
|
link->hpd_gpio = NULL;
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Public functions
|
|
|
|
******************************************************************************/
|
2017-07-23 09:05:20 +09:00
|
|
|
struct dc_link *link_create(const struct link_init_data *init_params)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2017-07-23 09:05:20 +09:00
|
|
|
struct dc_link *link =
|
2017-09-27 23:53:50 +09:00
|
|
|
kzalloc(sizeof(*link), GFP_KERNEL);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
if (NULL == link)
|
|
|
|
goto alloc_fail;
|
|
|
|
|
|
|
|
if (false == construct(link, init_params))
|
|
|
|
goto construct_fail;
|
|
|
|
|
|
|
|
return link;
|
|
|
|
|
|
|
|
construct_fail:
|
2017-09-27 23:53:50 +09:00
|
|
|
kfree(link);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
alloc_fail:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
void link_destroy(struct dc_link **link)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
destruct(*link);
|
2017-09-27 23:53:50 +09:00
|
|
|
kfree(*link);
|
2017-09-13 04:58:20 +09:00
|
|
|
*link = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void enable_stream_features(struct pipe_ctx *pipe_ctx)
|
|
|
|
{
|
2017-07-27 22:33:33 +09:00
|
|
|
struct dc_stream_state *stream = pipe_ctx->stream;
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
struct dc_link *link = stream->link;
|
2018-03-16 03:54:30 +09:00
|
|
|
union down_spread_ctrl old_downspread;
|
|
|
|
union down_spread_ctrl new_downspread;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2016-12-13 15:41:11 +09:00
|
|
|
core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL,
|
2018-03-16 03:54:30 +09:00
|
|
|
&old_downspread.raw, sizeof(old_downspread));
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-03-16 03:54:30 +09:00
|
|
|
new_downspread.raw = old_downspread.raw;
|
|
|
|
|
|
|
|
new_downspread.bits.IGNORE_MSA_TIMING_PARAM =
|
2017-07-26 09:51:26 +09:00
|
|
|
(stream->ignore_msa_timing_param) ? 1 : 0;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-03-16 03:54:30 +09:00
|
|
|
if (new_downspread.raw != old_downspread.raw) {
|
|
|
|
core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
|
|
|
|
&new_downspread.raw, sizeof(new_downspread));
|
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2017-08-29 03:25:01 +09:00
|
|
|
static enum dc_status enable_link_dp(
|
|
|
|
struct dc_state *state,
|
|
|
|
struct pipe_ctx *pipe_ctx)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2017-07-27 22:33:33 +09:00
|
|
|
struct dc_stream_state *stream = pipe_ctx->stream;
|
2017-09-13 04:58:20 +09:00
|
|
|
enum dc_status status;
|
|
|
|
bool skip_video_pattern;
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
struct dc_link *link = stream->link;
|
2017-09-13 04:58:20 +09:00
|
|
|
struct dc_link_settings link_settings = {0};
|
|
|
|
enum dp_panel_mode panel_mode;
|
2019-05-31 00:56:39 +09:00
|
|
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
|
|
|
bool fec_enable;
|
|
|
|
#endif
|
2019-07-18 05:08:19 +09:00
|
|
|
int i;
|
|
|
|
bool apply_seamless_boot_optimization = false;
|
|
|
|
|
|
|
|
// check for seamless boot
|
|
|
|
for (i = 0; i < state->stream_count; i++) {
|
|
|
|
if (state->streams[i]->apply_seamless_boot_optimization) {
|
|
|
|
apply_seamless_boot_optimization = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
/* get link settings for video mode timing */
|
|
|
|
decide_link_settings(stream, &link_settings);
|
|
|
|
|
2019-04-05 03:42:44 +09:00
|
|
|
if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) {
|
|
|
|
/* If link settings are different than current and link already enabled
|
|
|
|
* then need to disable before programming to new rate.
|
|
|
|
*/
|
|
|
|
if (link->link_status.link_active &&
|
|
|
|
(link->cur_link_settings.lane_count != link_settings.lane_count ||
|
|
|
|
link->cur_link_settings.link_rate != link_settings.link_rate)) {
|
|
|
|
dp_disable_link_phy(link, pipe_ctx->stream->signal);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*in case it is not on*/
|
|
|
|
link->dc->hwss.edp_power_control(link, true);
|
|
|
|
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
|
2019-03-26 03:30:12 +09:00
|
|
|
}
|
|
|
|
|
2018-09-14 06:42:14 +09:00
|
|
|
pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =
|
|
|
|
link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
|
2019-07-18 05:08:19 +09:00
|
|
|
if (!apply_seamless_boot_optimization)
|
|
|
|
state->clk_mgr->funcs->update_clocks(state->clk_mgr, state, false);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
dp_enable_link_phy(
|
|
|
|
link,
|
|
|
|
pipe_ctx->stream->signal,
|
|
|
|
pipe_ctx->clock_source->id,
|
|
|
|
&link_settings);
|
|
|
|
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
if (stream->sink_patches.dppowerup_delay > 0) {
|
|
|
|
int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
|
2018-02-01 21:03:17 +09:00
|
|
|
|
|
|
|
msleep(delay_dp_power_up_in_ms);
|
|
|
|
}
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
panel_mode = dp_get_panel_mode(link);
|
2019-06-24 23:34:13 +09:00
|
|
|
dp_set_panel_mode(link, panel_mode);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
skip_video_pattern = true;
|
|
|
|
|
|
|
|
if (link_settings.link_rate == LINK_RATE_LOW)
|
|
|
|
skip_video_pattern = false;
|
|
|
|
|
2019-05-31 00:56:39 +09:00
|
|
|
if (link->aux_access_disabled) {
|
|
|
|
dc_link_dp_perform_link_training_skip_aux(link, &link_settings);
|
|
|
|
|
|
|
|
link->cur_link_settings = link_settings;
|
|
|
|
status = DC_OK;
|
|
|
|
} else if (perform_link_training_with_retries(
|
2017-09-13 04:58:20 +09:00
|
|
|
link,
|
|
|
|
&link_settings,
|
|
|
|
skip_video_pattern,
|
|
|
|
LINK_TRAINING_ATTEMPTS)) {
|
2017-07-23 09:05:20 +09:00
|
|
|
link->cur_link_settings = link_settings;
|
2017-09-13 04:58:20 +09:00
|
|
|
status = DC_OK;
|
|
|
|
}
|
|
|
|
else
|
2017-05-05 02:34:55 +09:00
|
|
|
status = DC_FAIL_DP_LINK_TRAINING;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2019-02-26 03:26:34 +09:00
|
|
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
2019-06-25 04:44:42 +09:00
|
|
|
if (link->preferred_training_settings.fec_enable != NULL)
|
|
|
|
fec_enable = *link->preferred_training_settings.fec_enable;
|
|
|
|
else
|
|
|
|
fec_enable = true;
|
|
|
|
|
2019-05-31 00:56:39 +09:00
|
|
|
dp_set_fec_enable(link, fec_enable);
|
2019-02-26 03:26:34 +09:00
|
|
|
#endif
|
2017-09-13 04:58:20 +09:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2017-11-25 06:31:03 +09:00
|
|
|
static enum dc_status enable_link_edp(
|
|
|
|
struct dc_state *state,
|
|
|
|
struct pipe_ctx *pipe_ctx)
|
|
|
|
{
|
|
|
|
enum dc_status status;
|
|
|
|
|
|
|
|
status = enable_link_dp(state, pipe_ctx);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2017-08-29 03:25:01 +09:00
|
|
|
static enum dc_status enable_link_dp_mst(
|
|
|
|
struct dc_state *state,
|
|
|
|
struct pipe_ctx *pipe_ctx)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
struct dc_link *link = pipe_ctx->stream->link;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
/* sink signal type after MST branch is MST. Multiple MST sinks
|
|
|
|
* share one link. Link DP PHY is enable or training only once.
|
|
|
|
*/
|
2017-07-23 09:05:20 +09:00
|
|
|
if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
|
2017-09-13 04:58:20 +09:00
|
|
|
return DC_OK;
|
|
|
|
|
2019-02-11 16:26:21 +09:00
|
|
|
/* clear payload table */
|
|
|
|
dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
|
|
|
|
|
2019-01-10 14:05:15 +09:00
|
|
|
/* to make sure the pending down rep can be processed
|
2019-02-11 16:26:21 +09:00
|
|
|
* before enabling the link
|
2019-01-10 14:05:15 +09:00
|
|
|
*/
|
|
|
|
dm_helpers_dp_mst_poll_pending_down_reply(link->ctx, link);
|
|
|
|
|
2017-04-11 03:02:23 +09:00
|
|
|
/* set the sink to MST mode before enabling the link */
|
|
|
|
dp_enable_mst_on_sink(link, true);
|
|
|
|
|
2017-08-29 03:25:01 +09:00
|
|
|
return enable_link_dp(state, pipe_ctx);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2017-08-15 07:43:11 +09:00
|
|
|
static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,
|
|
|
|
enum engine_id eng_id,
|
|
|
|
struct ext_hdmi_settings *settings)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
int i = 0;
|
|
|
|
struct integrated_info *integrated_info =
|
|
|
|
pipe_ctx->stream->ctx->dc_bios->integrated_info;
|
|
|
|
|
|
|
|
if (integrated_info == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get retimer settings from sbios for passing SI eye test for DCE11
|
|
|
|
* The setting values are varied based on board revision and port id
|
|
|
|
* Therefore the setting values of each ports is passed by sbios.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Check if current bios contains ext Hdmi settings
|
|
|
|
if (integrated_info->gpu_cap_info & 0x20) {
|
|
|
|
switch (eng_id) {
|
|
|
|
case ENGINE_ID_DIGA:
|
|
|
|
settings->slv_addr = integrated_info->dp0_ext_hdmi_slv_addr;
|
|
|
|
settings->reg_num = integrated_info->dp0_ext_hdmi_6g_reg_num;
|
|
|
|
settings->reg_num_6g = integrated_info->dp0_ext_hdmi_6g_reg_num;
|
|
|
|
memmove(settings->reg_settings,
|
|
|
|
integrated_info->dp0_ext_hdmi_reg_settings,
|
|
|
|
sizeof(integrated_info->dp0_ext_hdmi_reg_settings));
|
|
|
|
memmove(settings->reg_settings_6g,
|
|
|
|
integrated_info->dp0_ext_hdmi_6g_reg_settings,
|
|
|
|
sizeof(integrated_info->dp0_ext_hdmi_6g_reg_settings));
|
|
|
|
result = true;
|
|
|
|
break;
|
|
|
|
case ENGINE_ID_DIGB:
|
|
|
|
settings->slv_addr = integrated_info->dp1_ext_hdmi_slv_addr;
|
|
|
|
settings->reg_num = integrated_info->dp1_ext_hdmi_6g_reg_num;
|
|
|
|
settings->reg_num_6g = integrated_info->dp1_ext_hdmi_6g_reg_num;
|
|
|
|
memmove(settings->reg_settings,
|
|
|
|
integrated_info->dp1_ext_hdmi_reg_settings,
|
|
|
|
sizeof(integrated_info->dp1_ext_hdmi_reg_settings));
|
|
|
|
memmove(settings->reg_settings_6g,
|
|
|
|
integrated_info->dp1_ext_hdmi_6g_reg_settings,
|
|
|
|
sizeof(integrated_info->dp1_ext_hdmi_6g_reg_settings));
|
|
|
|
result = true;
|
|
|
|
break;
|
|
|
|
case ENGINE_ID_DIGC:
|
|
|
|
settings->slv_addr = integrated_info->dp2_ext_hdmi_slv_addr;
|
|
|
|
settings->reg_num = integrated_info->dp2_ext_hdmi_6g_reg_num;
|
|
|
|
settings->reg_num_6g = integrated_info->dp2_ext_hdmi_6g_reg_num;
|
|
|
|
memmove(settings->reg_settings,
|
|
|
|
integrated_info->dp2_ext_hdmi_reg_settings,
|
|
|
|
sizeof(integrated_info->dp2_ext_hdmi_reg_settings));
|
|
|
|
memmove(settings->reg_settings_6g,
|
|
|
|
integrated_info->dp2_ext_hdmi_6g_reg_settings,
|
|
|
|
sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings));
|
|
|
|
result = true;
|
|
|
|
break;
|
2017-10-12 04:12:58 +09:00
|
|
|
case ENGINE_ID_DIGD:
|
|
|
|
settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr;
|
|
|
|
settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num;
|
|
|
|
settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num;
|
|
|
|
memmove(settings->reg_settings,
|
|
|
|
integrated_info->dp3_ext_hdmi_reg_settings,
|
|
|
|
sizeof(integrated_info->dp3_ext_hdmi_reg_settings));
|
|
|
|
memmove(settings->reg_settings_6g,
|
|
|
|
integrated_info->dp3_ext_hdmi_6g_reg_settings,
|
|
|
|
sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings));
|
|
|
|
result = true;
|
|
|
|
break;
|
2017-08-15 07:43:11 +09:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result == true) {
|
|
|
|
// Validate settings from bios integrated info table
|
|
|
|
if (settings->slv_addr == 0)
|
|
|
|
return false;
|
|
|
|
if (settings->reg_num > 9)
|
|
|
|
return false;
|
|
|
|
if (settings->reg_num_6g > 3)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (i = 0; i < settings->reg_num; i++) {
|
|
|
|
if (settings->reg_settings[i].i2c_reg_index > 0x20)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < settings->reg_num_6g; i++) {
|
|
|
|
if (settings->reg_settings_6g[i].i2c_reg_index > 0x20)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool i2c_write(struct pipe_ctx *pipe_ctx,
|
|
|
|
uint8_t address, uint8_t *buffer, uint32_t length)
|
|
|
|
{
|
|
|
|
struct i2c_command cmd = {0};
|
|
|
|
struct i2c_payload payload = {0};
|
|
|
|
|
|
|
|
memset(&payload, 0, sizeof(payload));
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
|
|
|
|
cmd.number_of_payloads = 1;
|
|
|
|
cmd.engine = I2C_COMMAND_ENGINE_DEFAULT;
|
|
|
|
cmd.speed = pipe_ctx->stream->ctx->dc->caps.i2c_speed_in_khz;
|
|
|
|
|
|
|
|
payload.address = address;
|
|
|
|
payload.data = buffer;
|
|
|
|
payload.length = length;
|
|
|
|
payload.write = true;
|
|
|
|
cmd.payloads = &payload;
|
|
|
|
|
2018-07-24 03:12:10 +09:00
|
|
|
if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx,
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
pipe_ctx->stream->link, &cmd))
|
2017-08-15 07:43:11 +09:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_i2c_retimer_setting(
|
|
|
|
struct pipe_ctx *pipe_ctx,
|
|
|
|
bool is_vga_mode,
|
|
|
|
bool is_over_340mhz,
|
|
|
|
struct ext_hdmi_settings *settings)
|
|
|
|
{
|
|
|
|
uint8_t slave_address = (settings->slv_addr >> 1);
|
|
|
|
uint8_t buffer[2];
|
|
|
|
const uint8_t apply_rx_tx_change = 0x4;
|
|
|
|
uint8_t offset = 0xA;
|
|
|
|
uint8_t value = 0;
|
|
|
|
int i = 0;
|
|
|
|
bool i2c_success = false;
|
2018-08-01 09:14:26 +09:00
|
|
|
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
memset(&buffer, 0, sizeof(buffer));
|
|
|
|
|
|
|
|
/* Start Ext-Hdmi programming*/
|
|
|
|
|
|
|
|
for (i = 0; i < settings->reg_num; i++) {
|
|
|
|
/* Apply 3G settings */
|
|
|
|
if (settings->reg_settings[i].i2c_reg_index <= 0x20) {
|
|
|
|
|
|
|
|
buffer[0] = settings->reg_settings[i].i2c_reg_index;
|
|
|
|
buffer[1] = settings->reg_settings[i].i2c_reg_val;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
|
|
|
|
* needs to be set to 1 on every 0xA-0xC write.
|
|
|
|
*/
|
|
|
|
if (settings->reg_settings[i].i2c_reg_index == 0xA ||
|
|
|
|
settings->reg_settings[i].i2c_reg_index == 0xB ||
|
|
|
|
settings->reg_settings[i].i2c_reg_index == 0xC) {
|
|
|
|
|
|
|
|
/* Query current value from offset 0xA */
|
|
|
|
if (settings->reg_settings[i].i2c_reg_index == 0xA)
|
|
|
|
value = settings->reg_settings[i].i2c_reg_val;
|
|
|
|
else {
|
|
|
|
i2c_success =
|
|
|
|
dal_ddc_service_query_ddc_data(
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
pipe_ctx->stream->link->ddc,
|
2017-08-15 07:43:11 +09:00
|
|
|
slave_address, &offset, 1, &value, 1);
|
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
buffer[0] = offset;
|
|
|
|
/* Set APPLY_RX_TX_CHANGE bit to 1 */
|
|
|
|
buffer[1] = value | apply_rx_tx_change;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Apply 3G settings */
|
|
|
|
if (is_over_340mhz) {
|
|
|
|
for (i = 0; i < settings->reg_num_6g; i++) {
|
|
|
|
/* Apply 3G settings */
|
|
|
|
if (settings->reg_settings[i].i2c_reg_index <= 0x20) {
|
|
|
|
|
|
|
|
buffer[0] = settings->reg_settings_6g[i].i2c_reg_index;
|
|
|
|
buffer[1] = settings->reg_settings_6g[i].i2c_reg_val;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("above 340Mhz: retimer write to slave_address = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
|
|
|
|
* needs to be set to 1 on every 0xA-0xC write.
|
|
|
|
*/
|
|
|
|
if (settings->reg_settings_6g[i].i2c_reg_index == 0xA ||
|
|
|
|
settings->reg_settings_6g[i].i2c_reg_index == 0xB ||
|
|
|
|
settings->reg_settings_6g[i].i2c_reg_index == 0xC) {
|
|
|
|
|
|
|
|
/* Query current value from offset 0xA */
|
|
|
|
if (settings->reg_settings_6g[i].i2c_reg_index == 0xA)
|
|
|
|
value = settings->reg_settings_6g[i].i2c_reg_val;
|
|
|
|
else {
|
|
|
|
i2c_success =
|
|
|
|
dal_ddc_service_query_ddc_data(
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
pipe_ctx->stream->link->ddc,
|
2017-08-15 07:43:11 +09:00
|
|
|
slave_address, &offset, 1, &value, 1);
|
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
buffer[0] = offset;
|
|
|
|
/* Set APPLY_RX_TX_CHANGE bit to 1 */
|
|
|
|
buffer[1] = value | apply_rx_tx_change;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_vga_mode) {
|
|
|
|
/* Program additional settings if using 640x480 resolution */
|
|
|
|
|
|
|
|
/* Write offset 0xFF to 0x01 */
|
|
|
|
buffer[0] = 0xff;
|
|
|
|
buffer[1] = 0x01;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Write offset 0x00 to 0x23 */
|
|
|
|
buffer[0] = 0x00;
|
|
|
|
buffer[1] = 0x23;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
|
2018-11-05 19:33:35 +09:00
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
2018-08-01 09:14:26 +09:00
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Write offset 0xff to 0x00 */
|
|
|
|
buffer[0] = 0xff;
|
|
|
|
buffer[1] = 0x00;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
|
2018-11-05 19:33:35 +09:00
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
2018-08-01 09:14:26 +09:00
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
}
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
i2c_write_fail:
|
|
|
|
DC_LOG_DEBUG("Set retimer failed");
|
2017-08-15 07:43:11 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
static void write_i2c_default_retimer_setting(
|
|
|
|
struct pipe_ctx *pipe_ctx,
|
|
|
|
bool is_vga_mode,
|
|
|
|
bool is_over_340mhz)
|
|
|
|
{
|
|
|
|
uint8_t slave_address = (0xBA >> 1);
|
|
|
|
uint8_t buffer[2];
|
|
|
|
bool i2c_success = false;
|
2018-08-01 09:14:26 +09:00
|
|
|
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
memset(&buffer, 0, sizeof(buffer));
|
|
|
|
|
|
|
|
/* Program Slave Address for tuning single integrity */
|
|
|
|
/* Write offset 0x0A to 0x13 */
|
|
|
|
buffer[0] = 0x0A;
|
|
|
|
buffer[1] = 0x13;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer writes default setting to slave_address = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Write offset 0x0A to 0x17 */
|
|
|
|
buffer[0] = 0x0A;
|
|
|
|
buffer[1] = 0x17;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Write offset 0x0B to 0xDA or 0xD8 */
|
|
|
|
buffer[0] = 0x0B;
|
|
|
|
buffer[1] = is_over_340mhz ? 0xDA : 0xD8;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Write offset 0x0A to 0x17 */
|
|
|
|
buffer[0] = 0x0A;
|
|
|
|
buffer[1] = 0x17;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Write offset 0x0C to 0x1D or 0x91 */
|
|
|
|
buffer[0] = 0x0C;
|
|
|
|
buffer[1] = is_over_340mhz ? 0x1D : 0x91;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Write offset 0x0A to 0x17 */
|
|
|
|
buffer[0] = 0x0A;
|
|
|
|
buffer[1] = 0x17;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
|
|
|
|
if (is_vga_mode) {
|
|
|
|
/* Program additional settings if using 640x480 resolution */
|
|
|
|
|
|
|
|
/* Write offset 0xFF to 0x01 */
|
|
|
|
buffer[0] = 0xff;
|
|
|
|
buffer[1] = 0x01;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Write offset 0x00 to 0x23 */
|
|
|
|
buffer[0] = 0x00;
|
|
|
|
buffer[1] = 0x23;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
/* Write offset 0xff to 0x00 */
|
|
|
|
buffer[0] = 0xff;
|
|
|
|
buffer[1] = 0x00;
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("retimer write default setting to slave_addr = 0x%x,\
|
|
|
|
offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n",
|
|
|
|
slave_address, buffer[0], buffer[1], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
goto i2c_write_fail;
|
2017-08-15 07:43:11 +09:00
|
|
|
}
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
i2c_write_fail:
|
|
|
|
DC_LOG_DEBUG("Set default retimer failed");
|
2017-08-15 07:43:11 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
static void write_i2c_redriver_setting(
|
|
|
|
struct pipe_ctx *pipe_ctx,
|
|
|
|
bool is_over_340mhz)
|
|
|
|
{
|
|
|
|
uint8_t slave_address = (0xF0 >> 1);
|
|
|
|
uint8_t buffer[16];
|
|
|
|
bool i2c_success = false;
|
2018-08-01 09:14:26 +09:00
|
|
|
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
memset(&buffer, 0, sizeof(buffer));
|
|
|
|
|
|
|
|
// Program Slave Address for tuning single integrity
|
|
|
|
buffer[3] = 0x4E;
|
|
|
|
buffer[4] = 0x4E;
|
|
|
|
buffer[5] = 0x4E;
|
|
|
|
buffer[6] = is_over_340mhz ? 0x4E : 0x4A;
|
|
|
|
|
|
|
|
i2c_success = i2c_write(pipe_ctx, slave_address,
|
|
|
|
buffer, sizeof(buffer));
|
2018-08-01 09:14:26 +09:00
|
|
|
RETIMER_REDRIVER_INFO("redriver write 0 to all 16 reg offset expect following:\n\
|
|
|
|
\t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x,\
|
|
|
|
offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x,\
|
|
|
|
i2c_success = %d\n",
|
|
|
|
slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success?1:0);
|
2017-08-15 07:43:11 +09:00
|
|
|
|
|
|
|
if (!i2c_success)
|
drm/amd/display: Stop if retimer is not available
[ Upstream commit a0e40018dcc3f59a10ca21d58f8ea8ceb1b035ac ]
Raven provides retimer feature support that requires i2c interaction in
order to make it work well, all settings required for this configuration
are loaded from the Atom bios which include the i2c address. If the
retimer feature is not available, we should abort the attempt to set
this feature, otherwise, it makes the following line return
I2C_CHANNEL_OPERATION_NO_RESPONSE:
i2c_success = i2c_write(pipe_ctx, slave_address, buffer, sizeof(buffer));
...
if (!i2c_success)
ASSERT(i2c_success);
This ends up causing problems with hotplugging HDMI displays on Raven,
and causes retimer settings to warn like so:
WARNING: CPU: 1 PID: 429 at
drivers/gpu/drm/amd/amdgpu/../dal/dc/core/dc_link.c:1998
write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu] Modules linked in:
edac_mce_amd ccp kvm irqbypass binfmt_misc crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_hda_codec_realtek snd_hda_codec_generic
ledtrig_audio snd_hda_codec_hdmi snd_hda_intel amdgpu(+) snd_hda_codec
snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event
snd_rawmidi aesni_intel snd_seq amd_iommu_v2 gpu_sched aes_x86_64
crypto_simd cryptd glue_helper snd_seq_device ttm drm_kms_helper
snd_timer eeepc_wmi wmi_bmof asus_wmi sparse_keymap drm mxm_wmi snd
k10temp fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore joydev
input_leds mac_hid sch_fq_codel parport_pc ppdev lp parport ip_tables
x_tables autofs4 igb i2c_algo_bit hid_generic usbhid i2c_piix4 dca ahci
hid libahci video wmi gpio_amdpt gpio_generic CPU: 1 PID: 429 Comm:
systemd-udevd Tainted: G W 5.2.0-rc1sept162019+ #1
Hardware name: System manufacturer System Product Name/ROG STRIX B450-F
GAMING, BIOS 2605 08/06/2019
RIP: 0010:write_i2c_retimer_setting+0xc2/0x3c0 [amdgpu]
Code: ff 0f b6 4d ce 44 0f b6 45 cf 44 0f b6 c8 45 89 cf 44 89 e2 48 c7
c6 f0 34 bc c0 bf 04 00 00 00 e8 63 b0 90 ff 45 84 ff 75 02 <0f> 0b 42
0f b6 04 73 8d 50 f6 80 fa 02 77 8c 3c 0a 0f 85 c8 00 00 RSP:
0018:ffffa99d02726fd0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffffa99d02727035 RCX: 0000000000000006
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff976acc857440
RBP: ffffa99d02727018 R08: 0000000000000002 R09: 000000000002a600
R10: ffffe90610193680 R11: 00000000000005e3 R12: 000000000000005d
R13: ffff976ac4b201b8 R14: 0000000000000001 R15: 0000000000000000
FS: 00007f14f99e1680(0000) GS:ffff976acc840000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdf212843b8 CR3: 0000000408906000 CR4: 00000000003406e0
Call Trace:
core_link_enable_stream+0x626/0x680 [amdgpu]
dce110_apply_ctx_to_hw+0x414/0x4e0 [amdgpu]
dc_commit_state+0x331/0x5e0 [amdgpu]
? drm_calc_timestamping_constants+0xf9/0x150 [drm]
amdgpu_dm_atomic_commit_tail+0x395/0x1e00 [amdgpu]
? dm_plane_helper_prepare_fb+0x20c/0x280 [amdgpu]
commit_tail+0x42/0x70 [drm_kms_helper]
drm_atomic_helper_commit+0x10c/0x120 [drm_kms_helper]
amdgpu_dm_atomic_commit+0x95/0xa0 [amdgpu]
drm_atomic_commit+0x4a/0x50 [drm]
restore_fbdev_mode_atomic+0x1c0/0x1e0 [drm_kms_helper]
restore_fbdev_mode+0x4c/0x160 [drm_kms_helper]
? _cond_resched+0x19/0x40
drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_helper]
drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper]
fbcon_init+0x471/0x630
visual_init+0xd5/0x130
do_bind_con_driver+0x20a/0x430
do_take_over_console+0x7d/0x1b0
do_fbcon_takeover+0x5c/0xb0
fbcon_event_notify+0x6cd/0x8a0
notifier_call_chain+0x4c/0x70
blocking_notifier_call_chain+0x43/0x60
fb_notifier_call_chain+0x1b/0x20
register_framebuffer+0x254/0x360
__drm_fb_helper_initial_config_and_unlock+0x2c5/0x510 [drm_kms_helper]
drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper]
amdgpu_fbdev_init+0xcd/0x100 [amdgpu]
amdgpu_device_init+0x1156/0x1930 [amdgpu]
amdgpu_driver_load_kms+0x8d/0x2e0 [amdgpu]
drm_dev_register+0x12b/0x1c0 [drm]
amdgpu_pci_probe+0xd3/0x160 [amdgpu]
local_pci_probe+0x47/0xa0
pci_device_probe+0x142/0x1b0
really_probe+0xf5/0x3d0
driver_probe_device+0x11b/0x130
device_driver_attach+0x58/0x60
__driver_attach+0xa3/0x140
? device_driver_attach+0x60/0x60
? device_driver_attach+0x60/0x60
bus_for_each_dev+0x74/0xb0
? kmem_cache_alloc_trace+0x1a3/0x1c0
driver_attach+0x1e/0x20
bus_add_driver+0x147/0x220
? 0xffffffffc0cb9000
driver_register+0x60/0x100
? 0xffffffffc0cb9000
__pci_register_driver+0x5a/0x60
amdgpu_init+0x74/0x83 [amdgpu]
do_one_initcall+0x4a/0x1fa
? _cond_resched+0x19/0x40
? kmem_cache_alloc_trace+0x3f/0x1c0
? __vunmap+0x1cc/0x200
do_init_module+0x5f/0x227
load_module+0x2330/0x2b40
__do_sys_finit_module+0xfc/0x120
? __do_sys_finit_module+0xfc/0x120
__x64_sys_finit_module+0x1a/0x20
do_syscall_64+0x5a/0x130
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7f14f9500839
Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89
f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
f0 ff ff 73 01 c3 48 8b 0d 1f f6 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007fff9bc4f5a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 000055afb5abce30 RCX: 00007f14f9500839
RDX: 0000000000000000 RSI: 000055afb5ace0f0 RDI: 0000000000000017
RBP: 000055afb5ace0f0 R08: 0000000000000000 R09: 000000000000000a
R10: 0000000000000017 R11: 0000000000000246 R12: 0000000000000000
R13: 000055afb5aad800 R14: 0000000000020000 R15: 0000000000000000
---[ end trace c286e96563966f08 ]---
This commit reworks the way that we handle i2c write for retimer in the
way that we abort this configuration if the feature is not available in
the device. For debug sake, we kept a simple log message in case the
retimer is not available.
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2020-02-25 00:13:37 +09:00
|
|
|
DC_LOG_DEBUG("Set redriver failed");
|
2017-08-15 07:43:11 +09:00
|
|
|
}
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
|
|
|
|
{
|
2017-07-27 22:33:33 +09:00
|
|
|
struct dc_stream_state *stream = pipe_ctx->stream;
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
struct dc_link *link = stream->link;
|
2017-02-02 10:35:53 +09:00
|
|
|
enum dc_color_depth display_color_depth;
|
2017-08-15 07:43:11 +09:00
|
|
|
enum engine_id eng_id;
|
|
|
|
struct ext_hdmi_settings settings = {0};
|
|
|
|
bool is_over_340mhz = false;
|
|
|
|
bool is_vga_mode = (stream->timing.h_addressable == 640)
|
|
|
|
&& (stream->timing.v_addressable == 480);
|
|
|
|
|
2018-07-31 06:59:20 +09:00
|
|
|
if (stream->phy_pix_clk == 0)
|
2018-11-07 04:24:12 +09:00
|
|
|
stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
|
2017-08-15 07:43:11 +09:00
|
|
|
if (stream->phy_pix_clk > 340000)
|
|
|
|
is_over_340mhz = true;
|
|
|
|
|
|
|
|
if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
unsigned short masked_chip_caps = pipe_ctx->stream->link->chip_caps &
|
2017-10-12 03:59:51 +09:00
|
|
|
EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
|
2017-10-21 05:40:45 +09:00
|
|
|
if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
|
2017-08-15 07:43:11 +09:00
|
|
|
/* DP159, Retimer settings */
|
|
|
|
eng_id = pipe_ctx->stream_res.stream_enc->id;
|
|
|
|
|
|
|
|
if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) {
|
|
|
|
write_i2c_retimer_setting(pipe_ctx,
|
|
|
|
is_vga_mode, is_over_340mhz, &settings);
|
|
|
|
} else {
|
|
|
|
write_i2c_default_retimer_setting(pipe_ctx,
|
|
|
|
is_vga_mode, is_over_340mhz);
|
|
|
|
}
|
2017-10-21 05:40:45 +09:00
|
|
|
} else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {
|
2017-08-15 07:43:11 +09:00
|
|
|
/* PI3EQX1204, Redriver settings */
|
|
|
|
write_i2c_redriver_setting(pipe_ctx, is_over_340mhz);
|
|
|
|
}
|
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
|
|
|
|
dal_ddc_service_write_scdc_data(
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
stream->link->ddc,
|
2017-09-13 04:58:20 +09:00
|
|
|
stream->phy_pix_clk,
|
2017-07-26 09:51:26 +09:00
|
|
|
stream->timing.flags.LTE_340MCSC_SCRAMBLE);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
memset(&stream->link->cur_link_settings, 0,
|
2017-09-13 04:58:20 +09:00
|
|
|
sizeof(struct dc_link_settings));
|
|
|
|
|
2017-07-26 09:51:26 +09:00
|
|
|
display_color_depth = stream->timing.display_color_depth;
|
|
|
|
if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
|
2017-02-02 10:35:53 +09:00
|
|
|
display_color_depth = COLOR_DEPTH_888;
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
link->link_enc->funcs->enable_tmds_output(
|
|
|
|
link->link_enc,
|
|
|
|
pipe_ctx->clock_source->id,
|
2017-02-02 10:35:53 +09:00
|
|
|
display_color_depth,
|
2017-12-19 01:57:28 +09:00
|
|
|
pipe_ctx->stream->signal,
|
2017-09-13 04:58:20 +09:00
|
|
|
stream->phy_pix_clk);
|
|
|
|
|
2019-02-23 01:11:07 +09:00
|
|
|
if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
|
2017-07-23 09:05:20 +09:00
|
|
|
dal_ddc_service_read_scdc_data(link->ddc);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2018-08-15 04:53:52 +09:00
|
|
|
static void enable_link_lvds(struct pipe_ctx *pipe_ctx)
|
|
|
|
{
|
|
|
|
struct dc_stream_state *stream = pipe_ctx->stream;
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
struct dc_link *link = stream->link;
|
2018-08-15 04:53:52 +09:00
|
|
|
|
|
|
|
if (stream->phy_pix_clk == 0)
|
2018-11-07 04:24:12 +09:00
|
|
|
stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
|
2018-08-15 04:53:52 +09:00
|
|
|
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
memset(&stream->link->cur_link_settings, 0,
|
2018-08-15 04:53:52 +09:00
|
|
|
sizeof(struct dc_link_settings));
|
|
|
|
|
|
|
|
link->link_enc->funcs->enable_lvds_output(
|
|
|
|
link->link_enc,
|
|
|
|
pipe_ctx->clock_source->id,
|
|
|
|
stream->phy_pix_clk);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
/****************************enable_link***********************************/
|
2017-08-29 03:25:01 +09:00
|
|
|
static enum dc_status enable_link(
|
|
|
|
struct dc_state *state,
|
|
|
|
struct pipe_ctx *pipe_ctx)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
enum dc_status status = DC_ERROR_UNEXPECTED;
|
|
|
|
switch (pipe_ctx->stream->signal) {
|
|
|
|
case SIGNAL_TYPE_DISPLAY_PORT:
|
2017-08-29 03:25:01 +09:00
|
|
|
status = enable_link_dp(state, pipe_ctx);
|
2017-09-13 04:58:20 +09:00
|
|
|
break;
|
2017-11-25 06:31:03 +09:00
|
|
|
case SIGNAL_TYPE_EDP:
|
|
|
|
status = enable_link_edp(state, pipe_ctx);
|
|
|
|
break;
|
2017-09-13 04:58:20 +09:00
|
|
|
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
2017-08-29 03:25:01 +09:00
|
|
|
status = enable_link_dp_mst(state, pipe_ctx);
|
2017-09-13 04:58:20 +09:00
|
|
|
msleep(200);
|
|
|
|
break;
|
|
|
|
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
|
|
|
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
|
|
|
case SIGNAL_TYPE_HDMI_TYPE_A:
|
|
|
|
enable_link_hdmi(pipe_ctx);
|
|
|
|
status = DC_OK;
|
|
|
|
break;
|
2018-08-15 04:53:52 +09:00
|
|
|
case SIGNAL_TYPE_LVDS:
|
|
|
|
enable_link_lvds(pipe_ctx);
|
|
|
|
status = DC_OK;
|
|
|
|
break;
|
2017-09-13 04:58:20 +09:00
|
|
|
case SIGNAL_TYPE_VIRTUAL:
|
|
|
|
status = DC_OK;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-02-08 10:38:34 +09:00
|
|
|
if (status == DC_OK)
|
|
|
|
pipe_ctx->stream->link->link_status.link_active = true;
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
static void disable_link(struct dc_link *link, enum signal_type signal)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* TODO: implement call for dp_set_hw_test_pattern
|
|
|
|
* it is needed for compliance testing
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* here we need to specify that encoder output settings
|
|
|
|
* need to be calculated as for the set mode,
|
|
|
|
* it will lead to querying dynamic link capabilities
|
|
|
|
* which should be done before enable output */
|
|
|
|
|
|
|
|
if (dc_is_dp_signal(signal)) {
|
|
|
|
/* SST DP, eDP */
|
|
|
|
if (dc_is_dp_sst_signal(signal))
|
|
|
|
dp_disable_link_phy(link, signal);
|
|
|
|
else
|
|
|
|
dp_disable_link_phy_mst(link, signal);
|
2019-02-26 03:26:34 +09:00
|
|
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
|
|
|
|
|
|
|
if (dc_is_dp_sst_signal(signal) ||
|
|
|
|
link->mst_stream_alloc_table.stream_count == 0) {
|
|
|
|
dp_set_fec_enable(link, false);
|
|
|
|
dp_set_fec_ready(link, false);
|
|
|
|
}
|
|
|
|
#endif
|
2019-08-22 11:02:13 +09:00
|
|
|
} else {
|
|
|
|
if (signal != SIGNAL_TYPE_VIRTUAL)
|
|
|
|
link->link_enc->funcs->disable_output(link->link_enc, signal);
|
|
|
|
}
|
2019-02-08 10:38:34 +09:00
|
|
|
|
|
|
|
if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
|
|
|
|
/* MST disable link only when no stream use the link */
|
|
|
|
if (link->mst_stream_alloc_table.stream_count <= 0)
|
|
|
|
link->link_status.link_active = false;
|
|
|
|
} else {
|
|
|
|
link->link_status.link_active = false;
|
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2019-02-14 07:06:31 +09:00
|
|
|
static uint32_t get_timing_pixel_clock_100hz(const struct dc_crtc_timing *timing)
|
|
|
|
{
|
|
|
|
|
|
|
|
uint32_t pxl_clk = timing->pix_clk_100hz;
|
|
|
|
|
|
|
|
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
|
|
|
|
pxl_clk /= 2;
|
|
|
|
else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
|
|
|
|
pxl_clk = pxl_clk * 2 / 3;
|
|
|
|
|
|
|
|
if (timing->display_color_depth == COLOR_DEPTH_101010)
|
|
|
|
pxl_clk = pxl_clk * 10 / 8;
|
|
|
|
else if (timing->display_color_depth == COLOR_DEPTH_121212)
|
|
|
|
pxl_clk = pxl_clk * 12 / 8;
|
|
|
|
|
|
|
|
return pxl_clk;
|
|
|
|
}
|
|
|
|
|
2017-11-11 00:44:24 +09:00
|
|
|
static bool dp_active_dongle_validate_timing(
|
2017-10-19 09:22:40 +09:00
|
|
|
const struct dc_crtc_timing *timing,
|
2018-03-20 04:22:51 +09:00
|
|
|
const struct dpcd_caps *dpcd_caps)
|
2017-10-19 09:22:40 +09:00
|
|
|
{
|
2018-03-20 04:22:51 +09:00
|
|
|
const struct dc_dongle_caps *dongle_caps = &dpcd_caps->dongle_caps;
|
|
|
|
|
|
|
|
switch (dpcd_caps->dongle_type) {
|
|
|
|
case DISPLAY_DONGLE_DP_VGA_CONVERTER:
|
|
|
|
case DISPLAY_DONGLE_DP_DVI_CONVERTER:
|
|
|
|
case DISPLAY_DONGLE_DP_DVI_DONGLE:
|
|
|
|
if (timing->pixel_encoding == PIXEL_ENCODING_RGB)
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2017-10-19 09:22:40 +09:00
|
|
|
|
2019-09-21 09:20:23 +09:00
|
|
|
if (dpcd_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER ||
|
2017-10-19 09:22:40 +09:00
|
|
|
dongle_caps->extendedCapValid == false)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* Check Pixel Encoding */
|
|
|
|
switch (timing->pixel_encoding) {
|
|
|
|
case PIXEL_ENCODING_RGB:
|
|
|
|
case PIXEL_ENCODING_YCBCR444:
|
|
|
|
break;
|
|
|
|
case PIXEL_ENCODING_YCBCR422:
|
|
|
|
if (!dongle_caps->is_dp_hdmi_ycbcr422_pass_through)
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case PIXEL_ENCODING_YCBCR420:
|
|
|
|
if (!dongle_caps->is_dp_hdmi_ycbcr420_pass_through)
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Invalid Pixel Encoding*/
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (timing->display_color_depth) {
|
|
|
|
case COLOR_DEPTH_666:
|
|
|
|
case COLOR_DEPTH_888:
|
|
|
|
/*888 and 666 should always be supported*/
|
|
|
|
break;
|
|
|
|
case COLOR_DEPTH_101010:
|
|
|
|
if (dongle_caps->dp_hdmi_max_bpc < 10)
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case COLOR_DEPTH_121212:
|
|
|
|
if (dongle_caps->dp_hdmi_max_bpc < 12)
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case COLOR_DEPTH_141414:
|
|
|
|
case COLOR_DEPTH_161616:
|
|
|
|
default:
|
|
|
|
/* These color depths are currently not supported */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-20 04:21:50 +09:00
|
|
|
if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
|
2017-10-19 09:22:40 +09:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
enum dc_status dc_link_validate_mode_timing(
|
2017-07-27 22:33:33 +09:00
|
|
|
const struct dc_stream_state *stream,
|
2017-07-23 09:05:20 +09:00
|
|
|
struct dc_link *link,
|
2017-09-13 04:58:20 +09:00
|
|
|
const struct dc_crtc_timing *timing)
|
|
|
|
{
|
2018-11-07 04:24:12 +09:00
|
|
|
uint32_t max_pix_clk = stream->link->dongle_max_pix_clk * 10;
|
2018-03-20 04:22:51 +09:00
|
|
|
struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
/* A hack to avoid failing any modes for EDID override feature on
|
|
|
|
* topology change such as lower quality cable for DP or different dongle
|
|
|
|
*/
|
2020-09-22 06:52:43 +09:00
|
|
|
if (link->remote_sinks[0] && link->remote_sinks[0]->sink_signal == SIGNAL_TYPE_VIRTUAL)
|
2017-09-13 04:58:20 +09:00
|
|
|
return DC_OK;
|
|
|
|
|
2017-10-19 09:22:40 +09:00
|
|
|
/* Passive Dongle */
|
2019-02-14 07:06:31 +09:00
|
|
|
if (max_pix_clk != 0 && get_timing_pixel_clock_100hz(timing) > max_pix_clk)
|
2017-10-19 09:22:40 +09:00
|
|
|
return DC_EXCEED_DONGLE_CAP;
|
|
|
|
|
|
|
|
/* Active Dongle*/
|
2018-03-20 04:22:51 +09:00
|
|
|
if (!dp_active_dongle_validate_timing(timing, dpcd_caps))
|
2017-10-19 09:22:40 +09:00
|
|
|
return DC_EXCEED_DONGLE_CAP;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
switch (stream->signal) {
|
|
|
|
case SIGNAL_TYPE_EDP:
|
|
|
|
case SIGNAL_TYPE_DISPLAY_PORT:
|
|
|
|
if (!dp_validate_mode_timing(
|
|
|
|
link,
|
|
|
|
timing))
|
|
|
|
return DC_NO_DP_LINK_BANDWIDTH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DC_OK;
|
|
|
|
}
|
|
|
|
|
2018-07-20 00:25:05 +09:00
|
|
|
int dc_link_get_backlight_level(const struct dc_link *link)
|
|
|
|
{
|
|
|
|
struct abm *abm = link->ctx->dc->res_pool->abm;
|
|
|
|
|
2018-10-13 10:34:32 +09:00
|
|
|
if (abm == NULL || abm->funcs->get_current_backlight == NULL)
|
2018-07-20 00:25:05 +09:00
|
|
|
return DC_ERROR_UNEXPECTED;
|
|
|
|
|
2018-10-13 10:34:32 +09:00
|
|
|
return (int) abm->funcs->get_current_backlight(abm);
|
2018-07-20 00:25:05 +09:00
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-10-13 10:34:32 +09:00
|
|
|
bool dc_link_set_backlight_level(const struct dc_link *link,
|
|
|
|
uint32_t backlight_pwm_u16_16,
|
2018-11-20 23:42:58 +09:00
|
|
|
uint32_t frame_ramp)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2017-08-02 04:00:25 +09:00
|
|
|
struct dc *core_dc = link->ctx->dc;
|
2017-01-25 05:19:42 +09:00
|
|
|
struct abm *abm = core_dc->res_pool->abm;
|
2017-11-25 05:43:05 +09:00
|
|
|
struct dmcu *dmcu = core_dc->res_pool->dmcu;
|
2017-09-13 04:58:20 +09:00
|
|
|
unsigned int controller_id = 0;
|
2017-11-25 05:43:05 +09:00
|
|
|
bool use_smooth_brightness = true;
|
2017-09-13 04:58:20 +09:00
|
|
|
int i;
|
2018-03-16 02:01:46 +09:00
|
|
|
DC_LOGGER_INIT(link->ctx->logger);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2017-11-25 05:43:05 +09:00
|
|
|
if ((dmcu == NULL) ||
|
|
|
|
(abm == NULL) ||
|
2018-10-13 10:34:32 +09:00
|
|
|
(abm->funcs->set_backlight_level_pwm == NULL))
|
2017-01-25 05:19:42 +09:00
|
|
|
return false;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2017-11-25 05:43:05 +09:00
|
|
|
use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
|
|
|
|
|
2018-10-13 10:34:32 +09:00
|
|
|
DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
|
|
|
|
backlight_pwm_u16_16, backlight_pwm_u16_16);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
if (dc_is_embedded_signal(link->connector_signal)) {
|
2018-10-26 04:47:43 +09:00
|
|
|
for (i = 0; i < MAX_PIPES; i++) {
|
|
|
|
if (core_dc->current_state->res_ctx.pipe_ctx[i].stream) {
|
2017-08-26 05:16:10 +09:00
|
|
|
if (core_dc->current_state->res_ctx.
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
pipe_ctx[i].stream->link
|
2019-06-20 23:55:26 +09:00
|
|
|
== link) {
|
2017-01-25 05:19:42 +09:00
|
|
|
/* DMCU -1 for all controller id values,
|
|
|
|
* therefore +1 here
|
|
|
|
*/
|
|
|
|
controller_id =
|
2017-08-26 05:16:10 +09:00
|
|
|
core_dc->current_state->
|
2017-07-31 02:59:26 +09:00
|
|
|
res_ctx.pipe_ctx[i].stream_res.tg->inst +
|
2017-01-25 05:19:42 +09:00
|
|
|
1;
|
2019-06-20 23:55:26 +09:00
|
|
|
|
|
|
|
/* Disable brightness ramping when the display is blanked
|
|
|
|
* as it can hang the DMCU
|
|
|
|
*/
|
|
|
|
if (core_dc->current_state->res_ctx.pipe_ctx[i].plane_state == NULL)
|
|
|
|
frame_ramp = 0;
|
|
|
|
}
|
2017-01-25 05:19:42 +09:00
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
2018-10-13 10:34:32 +09:00
|
|
|
abm->funcs->set_backlight_level_pwm(
|
2017-01-25 05:19:42 +09:00
|
|
|
abm,
|
2018-10-13 10:34:32 +09:00
|
|
|
backlight_pwm_u16_16,
|
2017-01-25 05:19:42 +09:00
|
|
|
frame_ramp,
|
2017-11-25 05:43:05 +09:00
|
|
|
controller_id,
|
|
|
|
use_smooth_brightness);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-29 23:56:17 +09:00
|
|
|
bool dc_link_set_abm_disable(const struct dc_link *link)
|
|
|
|
{
|
|
|
|
struct dc *core_dc = link->ctx->dc;
|
|
|
|
struct abm *abm = core_dc->res_pool->abm;
|
|
|
|
|
2018-10-13 10:34:32 +09:00
|
|
|
if ((abm == NULL) || (abm->funcs->set_backlight_level_pwm == NULL))
|
2018-03-29 23:56:17 +09:00
|
|
|
return false;
|
|
|
|
|
|
|
|
abm->funcs->set_abm_immediate_disable(abm);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-08-29 05:28:34 +09:00
|
|
|
bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2017-08-02 04:00:25 +09:00
|
|
|
struct dc *core_dc = link->ctx->dc;
|
2017-02-18 01:56:03 +09:00
|
|
|
struct dmcu *dmcu = core_dc->res_pool->dmcu;
|
|
|
|
|
2018-10-24 02:58:39 +09:00
|
|
|
if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_enabled)
|
2017-08-29 05:28:34 +09:00
|
|
|
dmcu->funcs->set_psr_enable(dmcu, enable, wait);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
const struct dc_link_status *dc_link_get_status(const struct dc_link *link)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
|
|
|
return &link->link_status;
|
|
|
|
}
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
void core_link_resume(struct dc_link *link)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2017-07-23 09:05:20 +09:00
|
|
|
if (link->connector_signal != SIGNAL_TYPE_VIRTUAL)
|
2018-02-07 02:25:17 +09:00
|
|
|
program_hpd_filter(link);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2017-07-27 22:33:33 +09:00
|
|
|
static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2019-03-20 08:47:32 +09:00
|
|
|
struct fixed31_32 mbytes_per_sec;
|
2019-05-11 02:34:30 +09:00
|
|
|
uint32_t link_rate_in_mbytes_per_sec = dc_link_bandwidth_kbps(stream->link,
|
|
|
|
&stream->link->cur_link_settings);
|
2019-03-20 08:47:32 +09:00
|
|
|
link_rate_in_mbytes_per_sec /= 8000; /* Kbits to MBytes */
|
|
|
|
|
|
|
|
mbytes_per_sec = dc_fixpt_from_int(link_rate_in_mbytes_per_sec);
|
|
|
|
|
|
|
|
return dc_fixpt_div_int(mbytes_per_sec, 54);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
static int get_color_depth(enum dc_color_depth color_depth)
|
|
|
|
{
|
|
|
|
switch (color_depth) {
|
|
|
|
case COLOR_DEPTH_666: return 6;
|
|
|
|
case COLOR_DEPTH_888: return 8;
|
|
|
|
case COLOR_DEPTH_101010: return 10;
|
|
|
|
case COLOR_DEPTH_121212: return 12;
|
|
|
|
case COLOR_DEPTH_141414: return 14;
|
|
|
|
case COLOR_DEPTH_161616: return 16;
|
|
|
|
default: return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
|
|
|
|
{
|
|
|
|
uint32_t bpc;
|
|
|
|
uint64_t kbps;
|
|
|
|
struct fixed31_32 peak_kbps;
|
|
|
|
uint32_t numerator;
|
|
|
|
uint32_t denominator;
|
|
|
|
|
2017-07-31 04:17:43 +09:00
|
|
|
bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth);
|
2019-03-22 02:05:36 +09:00
|
|
|
kbps = dc_bandwidth_in_kbps_from_timing(&pipe_ctx->stream->timing);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
/*
|
|
|
|
* margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
|
|
|
|
* The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
|
|
|
|
* common multiplier to render an integer PBN for all link rate/lane
|
|
|
|
* counts combinations
|
|
|
|
* calculate
|
|
|
|
* peak_kbps *= (1006/1000)
|
|
|
|
* peak_kbps *= (64/54)
|
|
|
|
* peak_kbps *= 8 convert to bytes
|
|
|
|
*/
|
|
|
|
|
|
|
|
numerator = 64 * PEAK_FACTOR_X1000;
|
|
|
|
denominator = 54 * 8 * 1000 * 1000;
|
|
|
|
kbps *= numerator;
|
2018-04-19 00:37:53 +09:00
|
|
|
peak_kbps = dc_fixpt_from_fraction(kbps, denominator);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
return peak_kbps;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void update_mst_stream_alloc_table(
|
2017-07-23 09:05:20 +09:00
|
|
|
struct dc_link *link,
|
2017-09-13 04:58:20 +09:00
|
|
|
struct stream_encoder *stream_enc,
|
|
|
|
const struct dp_mst_stream_allocation_table *proposed_table)
|
|
|
|
{
|
|
|
|
struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = {
|
|
|
|
{ 0 } };
|
|
|
|
struct link_mst_stream_allocation *dc_alloc;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
/* if DRM proposed_table has more than one new payload */
|
|
|
|
ASSERT(proposed_table->stream_count -
|
|
|
|
link->mst_stream_alloc_table.stream_count < 2);
|
|
|
|
|
2017-07-23 09:05:20 +09:00
|
|
|
/* copy proposed_table to link, add stream encoder */
|
2017-09-13 04:58:20 +09:00
|
|
|
for (i = 0; i < proposed_table->stream_count; i++) {
|
|
|
|
|
|
|
|
for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) {
|
|
|
|
dc_alloc =
|
|
|
|
&link->mst_stream_alloc_table.stream_allocations[j];
|
|
|
|
|
|
|
|
if (dc_alloc->vcp_id ==
|
|
|
|
proposed_table->stream_allocations[i].vcp_id) {
|
|
|
|
|
|
|
|
work_table[i] = *dc_alloc;
|
|
|
|
break; /* exit j loop */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* new vcp_id */
|
|
|
|
if (j == link->mst_stream_alloc_table.stream_count) {
|
|
|
|
work_table[i].vcp_id =
|
|
|
|
proposed_table->stream_allocations[i].vcp_id;
|
|
|
|
work_table[i].slot_count =
|
|
|
|
proposed_table->stream_allocations[i].slot_count;
|
|
|
|
work_table[i].stream_enc = stream_enc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update link->mst_stream_alloc_table with work_table */
|
|
|
|
link->mst_stream_alloc_table.stream_count =
|
|
|
|
proposed_table->stream_count;
|
|
|
|
for (i = 0; i < MAX_CONTROLLER_NUM; i++)
|
|
|
|
link->mst_stream_alloc_table.stream_allocations[i] =
|
|
|
|
work_table[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table
|
|
|
|
* because stream_encoder is not exposed to dm
|
|
|
|
*/
|
|
|
|
static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
|
|
|
{
|
2017-07-27 22:33:33 +09:00
|
|
|
struct dc_stream_state *stream = pipe_ctx->stream;
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
struct dc_link *link = stream->link;
|
2017-09-13 04:58:20 +09:00
|
|
|
struct link_encoder *link_encoder = link->link_enc;
|
2017-07-31 03:36:12 +09:00
|
|
|
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
|
2017-09-13 04:58:20 +09:00
|
|
|
struct dp_mst_stream_allocation_table proposed_table = {0};
|
|
|
|
struct fixed31_32 avg_time_slots_per_mtp;
|
|
|
|
struct fixed31_32 pbn;
|
|
|
|
struct fixed31_32 pbn_per_slot;
|
|
|
|
uint8_t i;
|
2018-03-16 02:01:46 +09:00
|
|
|
DC_LOGGER_INIT(link->ctx->logger);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
/* enable_link_dp_mst already check link->enabled_stream_count
|
|
|
|
* and stream is in link->stream[]. This is called during set mode,
|
|
|
|
* stream_enc is available.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* get calculate VC payload for stream: stream_alloc */
|
|
|
|
if (dm_helpers_dp_mst_write_payload_allocation_table(
|
|
|
|
stream->ctx,
|
2017-07-26 09:51:26 +09:00
|
|
|
stream,
|
2017-09-13 04:58:20 +09:00
|
|
|
&proposed_table,
|
|
|
|
true)) {
|
|
|
|
update_mst_stream_alloc_table(
|
2017-07-31 03:36:12 +09:00
|
|
|
link, pipe_ctx->stream_res.stream_enc, &proposed_table);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
else
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_WARNING("Failed to update"
|
2017-09-13 04:58:20 +09:00
|
|
|
"MST allocation table for"
|
|
|
|
"pipe idx:%d\n",
|
|
|
|
pipe_ctx->pipe_idx);
|
|
|
|
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_MST("%s "
|
2017-09-13 04:58:20 +09:00
|
|
|
"stream_count: %d: \n ",
|
|
|
|
__func__,
|
|
|
|
link->mst_stream_alloc_table.stream_count);
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
|
2018-03-15 00:19:15 +09:00
|
|
|
DC_LOG_MST("stream_enc[%d]: %p "
|
2017-09-13 04:58:20 +09:00
|
|
|
"stream[%d].vcp_id: %d "
|
|
|
|
"stream[%d].slot_count: %d\n",
|
|
|
|
i,
|
2018-03-15 00:19:15 +09:00
|
|
|
(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
|
2017-09-13 04:58:20 +09:00
|
|
|
i,
|
|
|
|
link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
|
|
|
|
i,
|
|
|
|
link->mst_stream_alloc_table.stream_allocations[i].slot_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(proposed_table.stream_count > 0);
|
|
|
|
|
|
|
|
/* program DP source TX for payload */
|
|
|
|
link_encoder->funcs->update_mst_stream_allocation_table(
|
|
|
|
link_encoder,
|
|
|
|
&link->mst_stream_alloc_table);
|
|
|
|
|
|
|
|
/* send down message */
|
|
|
|
dm_helpers_dp_mst_poll_for_allocation_change_trigger(
|
|
|
|
stream->ctx,
|
2017-07-26 09:51:26 +09:00
|
|
|
stream);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
dm_helpers_dp_mst_send_payload_allocation(
|
|
|
|
stream->ctx,
|
2017-07-26 09:51:26 +09:00
|
|
|
stream,
|
2017-09-13 04:58:20 +09:00
|
|
|
true);
|
|
|
|
|
|
|
|
/* slot X.Y for only current stream */
|
|
|
|
pbn_per_slot = get_pbn_per_slot(stream);
|
|
|
|
pbn = get_pbn_from_timing(pipe_ctx);
|
2018-04-19 00:37:53 +09:00
|
|
|
avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
stream_encoder->funcs->set_mst_bandwidth(
|
|
|
|
stream_encoder,
|
|
|
|
avg_time_slots_per_mtp);
|
|
|
|
|
|
|
|
return DC_OK;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
|
|
|
{
|
2017-07-27 22:33:33 +09:00
|
|
|
struct dc_stream_state *stream = pipe_ctx->stream;
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
struct dc_link *link = stream->link;
|
2017-09-13 04:58:20 +09:00
|
|
|
struct link_encoder *link_encoder = link->link_enc;
|
2017-07-31 03:36:12 +09:00
|
|
|
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
|
2017-09-13 04:58:20 +09:00
|
|
|
struct dp_mst_stream_allocation_table proposed_table = {0};
|
2018-04-19 00:37:53 +09:00
|
|
|
struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
|
2017-09-13 04:58:20 +09:00
|
|
|
uint8_t i;
|
2017-07-23 09:05:20 +09:00
|
|
|
bool mst_mode = (link->type == dc_connection_mst_branch);
|
2018-03-16 02:01:46 +09:00
|
|
|
DC_LOGGER_INIT(link->ctx->logger);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
/* deallocate_mst_payload is called before disable link. When mode or
|
|
|
|
* disable/enable monitor, new stream is created which is not in link
|
|
|
|
* stream[] yet. For this, payload is not allocated yet, so de-alloc
|
|
|
|
* should not done. For new mode set, map_resources will get engine
|
|
|
|
* for new stream, so stream_enc->id should be validated until here.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* slot X.Y */
|
|
|
|
stream_encoder->funcs->set_mst_bandwidth(
|
|
|
|
stream_encoder,
|
|
|
|
avg_time_slots_per_mtp);
|
|
|
|
|
|
|
|
/* TODO: which component is responsible for remove payload table? */
|
|
|
|
if (mst_mode) {
|
|
|
|
if (dm_helpers_dp_mst_write_payload_allocation_table(
|
|
|
|
stream->ctx,
|
2017-07-26 09:51:26 +09:00
|
|
|
stream,
|
2017-09-13 04:58:20 +09:00
|
|
|
&proposed_table,
|
|
|
|
false)) {
|
|
|
|
|
|
|
|
update_mst_stream_alloc_table(
|
2017-07-31 03:36:12 +09:00
|
|
|
link, pipe_ctx->stream_res.stream_enc, &proposed_table);
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
else {
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_WARNING("Failed to update"
|
2017-09-13 04:58:20 +09:00
|
|
|
"MST allocation table for"
|
|
|
|
"pipe idx:%d\n",
|
|
|
|
pipe_ctx->pipe_idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_MST("%s"
|
2017-09-13 04:58:20 +09:00
|
|
|
"stream_count: %d: ",
|
|
|
|
__func__,
|
|
|
|
link->mst_stream_alloc_table.stream_count);
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
|
2018-03-15 00:19:15 +09:00
|
|
|
DC_LOG_MST("stream_enc[%d]: %p "
|
2017-09-13 04:58:20 +09:00
|
|
|
"stream[%d].vcp_id: %d "
|
|
|
|
"stream[%d].slot_count: %d\n",
|
|
|
|
i,
|
2018-03-15 00:19:15 +09:00
|
|
|
(void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
|
2017-09-13 04:58:20 +09:00
|
|
|
i,
|
|
|
|
link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
|
|
|
|
i,
|
|
|
|
link->mst_stream_alloc_table.stream_allocations[i].slot_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
link_encoder->funcs->update_mst_stream_allocation_table(
|
|
|
|
link_encoder,
|
|
|
|
&link->mst_stream_alloc_table);
|
|
|
|
|
|
|
|
if (mst_mode) {
|
|
|
|
dm_helpers_dp_mst_poll_for_allocation_change_trigger(
|
|
|
|
stream->ctx,
|
2017-07-26 09:51:26 +09:00
|
|
|
stream);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
|
|
|
dm_helpers_dp_mst_send_payload_allocation(
|
|
|
|
stream->ctx,
|
2017-07-26 09:51:26 +09:00
|
|
|
stream,
|
2017-09-13 04:58:20 +09:00
|
|
|
false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DC_OK;
|
|
|
|
}
|
|
|
|
|
2017-08-29 03:25:01 +09:00
|
|
|
void core_link_enable_stream(
|
|
|
|
struct dc_state *state,
|
|
|
|
struct pipe_ctx *pipe_ctx)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2019-03-09 07:09:46 +09:00
|
|
|
struct dc *core_dc = pipe_ctx->stream->ctx->dc;
|
2018-05-01 23:39:26 +09:00
|
|
|
struct dc_stream_state *stream = pipe_ctx->stream;
|
2018-02-03 07:35:00 +09:00
|
|
|
enum dc_status status;
|
2018-03-16 02:01:46 +09:00
|
|
|
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
|
2018-02-03 07:35:00 +09:00
|
|
|
|
2019-03-01 04:45:13 +09:00
|
|
|
if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) {
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
stream->link->link_enc->funcs->setup(
|
|
|
|
stream->link->link_enc,
|
2018-05-01 23:39:26 +09:00
|
|
|
pipe_ctx->stream->signal);
|
|
|
|
pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync(
|
|
|
|
pipe_ctx->stream_res.stream_enc,
|
|
|
|
pipe_ctx->stream_res.tg->inst,
|
|
|
|
stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dc_is_dp_signal(pipe_ctx->stream->signal))
|
|
|
|
pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(
|
|
|
|
pipe_ctx->stream_res.stream_enc,
|
|
|
|
&stream->timing,
|
2019-03-13 09:11:37 +09:00
|
|
|
stream->output_color_space,
|
|
|
|
stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
|
2018-05-01 23:39:26 +09:00
|
|
|
|
2019-02-15 23:27:22 +09:00
|
|
|
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
|
2018-05-01 23:39:26 +09:00
|
|
|
pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute(
|
|
|
|
pipe_ctx->stream_res.stream_enc,
|
|
|
|
&stream->timing,
|
|
|
|
stream->phy_pix_clk,
|
|
|
|
pipe_ctx->stream_res.audio != NULL);
|
|
|
|
|
2019-04-30 03:35:01 +09:00
|
|
|
pipe_ctx->stream->link->link_state_valid = true;
|
|
|
|
|
2018-05-01 23:39:26 +09:00
|
|
|
if (dc_is_dvi_signal(pipe_ctx->stream->signal))
|
|
|
|
pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute(
|
|
|
|
pipe_ctx->stream_res.stream_enc,
|
|
|
|
&stream->timing,
|
|
|
|
(pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
|
|
|
|
true : false);
|
|
|
|
|
2018-08-15 04:53:52 +09:00
|
|
|
if (dc_is_lvds_signal(pipe_ctx->stream->signal))
|
|
|
|
pipe_ctx->stream_res.stream_enc->funcs->lvds_set_stream_attribute(
|
|
|
|
pipe_ctx->stream_res.stream_enc,
|
|
|
|
&stream->timing);
|
|
|
|
|
2018-08-17 03:27:11 +09:00
|
|
|
if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
|
2019-01-20 15:41:44 +09:00
|
|
|
bool apply_edp_fast_boot_optimization =
|
|
|
|
pipe_ctx->stream->apply_edp_fast_boot_optimization;
|
|
|
|
|
|
|
|
pipe_ctx->stream->apply_edp_fast_boot_optimization = false;
|
|
|
|
|
2018-08-17 03:27:11 +09:00
|
|
|
resource_build_info_frame(pipe_ctx);
|
|
|
|
core_dc->hwss.update_info_frame(pipe_ctx);
|
|
|
|
|
2019-01-20 15:41:44 +09:00
|
|
|
/* Do not touch link on seamless boot optimization. */
|
|
|
|
if (pipe_ctx->stream->apply_seamless_boot_optimization) {
|
|
|
|
pipe_ctx->stream->dpms_off = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-17 03:27:11 +09:00
|
|
|
/* eDP lit up by bios already, no need to enable again. */
|
|
|
|
if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&
|
2019-01-20 15:41:44 +09:00
|
|
|
apply_edp_fast_boot_optimization) {
|
2018-08-17 03:27:11 +09:00
|
|
|
pipe_ctx->stream->dpms_off = false;
|
|
|
|
return;
|
|
|
|
}
|
2018-02-03 07:35:00 +09:00
|
|
|
|
2018-08-17 03:27:11 +09:00
|
|
|
if (pipe_ctx->stream->dpms_off)
|
|
|
|
return;
|
2018-02-15 07:12:39 +09:00
|
|
|
|
2018-08-17 03:27:11 +09:00
|
|
|
status = enable_link(state, pipe_ctx);
|
2017-05-05 02:34:55 +09:00
|
|
|
|
2018-08-17 03:27:11 +09:00
|
|
|
if (status != DC_OK) {
|
2018-02-21 07:42:50 +09:00
|
|
|
DC_LOG_WARNING("enabling link %u failed: %d\n",
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
pipe_ctx->stream->link->link_index,
|
2017-05-05 02:34:55 +09:00
|
|
|
status);
|
|
|
|
|
|
|
|
/* Abort stream enable *unless* the failure was due to
|
|
|
|
* DP link training - some DP monitors will recover and
|
2017-11-02 04:43:47 +09:00
|
|
|
* show the stream anyway. But MST displays can't proceed
|
|
|
|
* without link training.
|
2017-05-05 02:34:55 +09:00
|
|
|
*/
|
2017-11-02 04:43:47 +09:00
|
|
|
if (status != DC_FAIL_DP_LINK_TRAINING ||
|
|
|
|
pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
|
2017-05-05 02:34:55 +09:00
|
|
|
BREAK_TO_DEBUGGER();
|
|
|
|
return;
|
|
|
|
}
|
2018-08-17 03:27:11 +09:00
|
|
|
}
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-08-17 03:27:11 +09:00
|
|
|
core_dc->hwss.enable_audio_stream(pipe_ctx);
|
2018-05-11 03:21:47 +09:00
|
|
|
|
2018-08-17 03:27:11 +09:00
|
|
|
/* turn off otg test pattern if enable */
|
|
|
|
if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
|
|
|
|
pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
|
|
|
|
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
|
|
|
|
COLOR_DEPTH_UNDEFINED);
|
2017-01-28 05:44:26 +09:00
|
|
|
|
2019-07-18 08:02:14 +09:00
|
|
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
|
|
|
if (pipe_ctx->stream->timing.flags.DSC) {
|
|
|
|
if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
|
|
|
|
dc_is_virtual_signal(pipe_ctx->stream->signal))
|
|
|
|
dp_set_dsc_enable(pipe_ctx, true);
|
|
|
|
}
|
|
|
|
#endif
|
2018-08-17 03:27:11 +09:00
|
|
|
core_dc->hwss.enable_stream(pipe_ctx);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2019-02-26 03:26:34 +09:00
|
|
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
2019-07-18 08:02:14 +09:00
|
|
|
/* Set DPS PPS SDP (AKA "info frames") */
|
2019-06-06 05:35:08 +09:00
|
|
|
if (pipe_ctx->stream->timing.flags.DSC) {
|
|
|
|
if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
|
|
|
|
dc_is_virtual_signal(pipe_ctx->stream->signal))
|
2019-07-18 08:02:14 +09:00
|
|
|
dp_set_dsc_pps_sdp(pipe_ctx, true);
|
2019-02-26 03:26:34 +09:00
|
|
|
}
|
|
|
|
#endif
|
2019-07-18 08:02:14 +09:00
|
|
|
|
|
|
|
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
|
|
|
|
allocate_mst_payload(pipe_ctx);
|
|
|
|
|
2018-08-17 03:27:11 +09:00
|
|
|
core_dc->hwss.unblank_stream(pipe_ctx,
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
&pipe_ctx->stream->link->cur_link_settings);
|
2018-08-17 03:27:11 +09:00
|
|
|
|
2018-10-31 04:34:33 +09:00
|
|
|
if (dc_is_dp_signal(pipe_ctx->stream->signal))
|
|
|
|
enable_stream_features(pipe_ctx);
|
2018-08-17 03:27:11 +09:00
|
|
|
}
|
2019-02-26 03:26:34 +09:00
|
|
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
|
|
|
else { // if (IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment))
|
|
|
|
if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
|
|
|
|
dc_is_virtual_signal(pipe_ctx->stream->signal))
|
|
|
|
dp_set_dsc_enable(pipe_ctx, true);
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2019-07-26 03:43:55 +09:00
|
|
|
void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
|
2017-09-13 04:58:20 +09:00
|
|
|
{
|
2017-08-02 04:00:25 +09:00
|
|
|
struct dc *core_dc = pipe_ctx->stream->ctx->dc;
|
2019-03-18 19:04:05 +09:00
|
|
|
struct dc_stream_state *stream = pipe_ctx->stream;
|
2019-04-24 10:59:54 +09:00
|
|
|
struct dc_link *link = stream->sink->link;
|
2017-09-13 04:58:20 +09:00
|
|
|
|
2018-12-18 00:32:22 +09:00
|
|
|
core_dc->hwss.blank_stream(pipe_ctx);
|
|
|
|
|
2017-09-13 04:58:20 +09:00
|
|
|
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
|
|
|
|
deallocate_mst_payload(pipe_ctx);
|
|
|
|
|
2019-04-24 10:59:54 +09:00
|
|
|
if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
|
|
|
|
struct ext_hdmi_settings settings = {0};
|
|
|
|
enum engine_id eng_id = pipe_ctx->stream_res.stream_enc->id;
|
2019-03-18 19:04:05 +09:00
|
|
|
|
2019-04-24 10:59:54 +09:00
|
|
|
unsigned short masked_chip_caps = link->chip_caps &
|
|
|
|
EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
|
|
|
|
//Need to inform that sink is going to use legacy HDMI mode.
|
|
|
|
dal_ddc_service_write_scdc_data(
|
|
|
|
link->ddc,
|
|
|
|
165000,//vbios only handles 165Mhz.
|
|
|
|
false);
|
|
|
|
if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
|
|
|
|
/* DP159, Retimer settings */
|
|
|
|
if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings))
|
|
|
|
write_i2c_retimer_setting(pipe_ctx,
|
|
|
|
false, false, &settings);
|
|
|
|
else
|
|
|
|
write_i2c_default_retimer_setting(pipe_ctx,
|
|
|
|
false, false);
|
|
|
|
} else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {
|
|
|
|
/* PI3EQX1204, Redriver settings */
|
|
|
|
write_i2c_redriver_setting(pipe_ctx, false);
|
|
|
|
}
|
|
|
|
}
|
2019-07-26 03:43:55 +09:00
|
|
|
core_dc->hwss.disable_stream(pipe_ctx);
|
2017-09-13 04:58:20 +09:00
|
|
|
|
drm/amd/display: remove sink reference in dc_stream_state
[why]
dc_stream_state containing a pointer to sink is poor design.
Sink describes the display, and the specifications or capabilities
it has. That information is irrelevant for dc_stream_state, which describes
hardware state, and is generally used for hardware programming. It
could further be argued that dc_sink itself is just a convenience dc
provides, and DC should be perfectly capable of programming hardware
without any dc_sinks (for example, emulated sinks).
[how]
Phase 1:
Deprecate use of dc_sink pointer in dc_stream. Most references are trivial
to remove, but some call sites are risky (such as is_timing_changed) with
no obvious logical replacement. These will be removed in follow up change.
Add dc_link pointer to dc_stream. This is the typical reason DC really needed
sink pointer, and most call sites are replaced with this.
DMs also need minor updates, as all 3 DMs leverage stream->sink for
some functionality. this is replaced instead by a pointer to private data
inside dc_stream_state, which is used by DMs as a quality of life improvment
for some key functionality. it allows DMs to set pointers have to their own objects
which associate OS objects to dc_stream_states (such as DisplayTarget
and amdgpu_dm_connector). Without the private pointer, DMs would be
forced to perform a lookup for callbacks.
Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: David Francis <David.Francis@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2018-11-09 23:21:21 +09:00
|
|
|
disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
|
2019-02-26 03:26:34 +09:00
|
|
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
2019-06-06 05:35:08 +09:00
|
|
|
if (pipe_ctx->stream->timing.flags.DSC) {
|
|
|
|
if (dc_is_dp_signal(pipe_ctx->stream->signal))
|
|
|
|
dp_set_dsc_enable(pipe_ctx, false);
|
2019-02-26 03:26:34 +09:00
|
|
|
}
|
|
|
|
#endif
|
2017-09-13 04:58:20 +09:00
|
|
|
}
|
|
|
|
|
2017-07-18 05:04:02 +09:00
|
|
|
void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
|
|
|
|
{
|
2017-08-02 04:00:25 +09:00
|
|
|
struct dc *core_dc = pipe_ctx->stream->ctx->dc;
|
2017-07-18 05:04:02 +09:00
|
|
|
|
2019-06-25 03:11:55 +09:00
|
|
|
if (!dc_is_hdmi_signal(pipe_ctx->stream->signal))
|
2017-07-18 05:04:02 +09:00
|
|
|
return;
|
|
|
|
|
|
|
|
core_dc->hwss.set_avmute(pipe_ctx, enable);
|
|
|
|
}
|
|
|
|
|
2018-05-05 05:53:03 +09:00
|
|
|
/**
|
|
|
|
*****************************************************************************
|
|
|
|
* Function: dc_link_enable_hpd_filter
|
|
|
|
*
|
|
|
|
* @brief
|
|
|
|
* If enable is true, programs HPD filter on associated HPD line using
|
|
|
|
* delay_on_disconnect/delay_on_connect values dependent on
|
|
|
|
* link->connector_signal
|
|
|
|
*
|
|
|
|
* If enable is false, programs HPD filter on associated HPD line with no
|
|
|
|
* delays on connect or disconnect
|
|
|
|
*
|
|
|
|
* @param [in] link: pointer to the dc link
|
|
|
|
* @param [in] enable: boolean specifying whether to enable hbd
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2018-02-10 07:48:18 +09:00
|
|
|
void dc_link_enable_hpd_filter(struct dc_link *link, bool enable)
|
2018-01-27 07:39:19 +09:00
|
|
|
{
|
|
|
|
struct gpio *hpd;
|
|
|
|
|
2018-02-10 07:48:18 +09:00
|
|
|
if (enable) {
|
|
|
|
link->is_hpd_filter_disabled = false;
|
|
|
|
program_hpd_filter(link);
|
|
|
|
} else {
|
2018-01-27 07:39:19 +09:00
|
|
|
link->is_hpd_filter_disabled = true;
|
|
|
|
/* Obtain HPD handle */
|
|
|
|
hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
|
|
|
|
|
|
|
|
if (!hpd)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Setup HPD filtering */
|
|
|
|
if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
|
|
|
|
struct gpio_hpd_config config;
|
|
|
|
|
|
|
|
config.delay_on_connect = 0;
|
|
|
|
config.delay_on_disconnect = 0;
|
|
|
|
|
|
|
|
dal_irq_setup_hpd_filter(hpd, &config);
|
|
|
|
|
|
|
|
dal_gpio_close(hpd);
|
|
|
|
} else {
|
|
|
|
ASSERT_CRITICAL(false);
|
|
|
|
}
|
|
|
|
/* Release HPD handle */
|
|
|
|
dal_gpio_destroy_irq(&hpd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-22 02:05:36 +09:00
|
|
|
uint32_t dc_bandwidth_in_kbps_from_timing(
|
|
|
|
const struct dc_crtc_timing *timing)
|
|
|
|
{
|
|
|
|
uint32_t bits_per_channel = 0;
|
|
|
|
uint32_t kbps;
|
|
|
|
|
2019-02-26 03:26:34 +09:00
|
|
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
|
|
|
if (timing->flags.DSC) {
|
|
|
|
kbps = (timing->pix_clk_100hz * timing->dsc_cfg.bits_per_pixel);
|
|
|
|
kbps = kbps / 160 + ((kbps % 160) ? 1 : 0);
|
|
|
|
return kbps;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-03-22 02:05:36 +09:00
|
|
|
switch (timing->display_color_depth) {
|
|
|
|
case COLOR_DEPTH_666:
|
|
|
|
bits_per_channel = 6;
|
|
|
|
break;
|
|
|
|
case COLOR_DEPTH_888:
|
|
|
|
bits_per_channel = 8;
|
|
|
|
break;
|
|
|
|
case COLOR_DEPTH_101010:
|
|
|
|
bits_per_channel = 10;
|
|
|
|
break;
|
|
|
|
case COLOR_DEPTH_121212:
|
|
|
|
bits_per_channel = 12;
|
|
|
|
break;
|
|
|
|
case COLOR_DEPTH_141414:
|
|
|
|
bits_per_channel = 14;
|
|
|
|
break;
|
|
|
|
case COLOR_DEPTH_161616:
|
|
|
|
bits_per_channel = 16;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(bits_per_channel != 0);
|
|
|
|
|
|
|
|
kbps = timing->pix_clk_100hz / 10;
|
|
|
|
kbps *= bits_per_channel;
|
|
|
|
|
|
|
|
if (timing->flags.Y_ONLY != 1) {
|
|
|
|
/*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
|
|
|
|
kbps *= 3;
|
|
|
|
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
|
|
|
|
kbps /= 2;
|
|
|
|
else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
|
|
|
|
kbps = kbps * 2 / 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
return kbps;
|
|
|
|
|
|
|
|
}
|
2019-05-11 02:34:30 +09:00
|
|
|
|
|
|
|
void dc_link_set_drive_settings(struct dc *dc,
|
|
|
|
struct link_training_settings *lt_settings,
|
|
|
|
const struct dc_link *link)
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < dc->link_count; i++) {
|
|
|
|
if (dc->links[i] == link)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i >= dc->link_count)
|
|
|
|
ASSERT_CRITICAL(false);
|
|
|
|
|
|
|
|
dc_link_dp_set_drive_settings(dc->links[i], lt_settings);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dc_link_perform_link_training(struct dc *dc,
|
|
|
|
struct dc_link_settings *link_setting,
|
|
|
|
bool skip_video_pattern)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < dc->link_count; i++)
|
|
|
|
dc_link_dp_perform_link_training(
|
|
|
|
dc->links[i],
|
|
|
|
link_setting,
|
|
|
|
skip_video_pattern);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dc_link_set_preferred_link_settings(struct dc *dc,
|
|
|
|
struct dc_link_settings *link_setting,
|
|
|
|
struct dc_link *link)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct pipe_ctx *pipe;
|
|
|
|
struct dc_stream_state *link_stream;
|
|
|
|
struct dc_link_settings store_settings = *link_setting;
|
|
|
|
|
|
|
|
link->preferred_link_setting = store_settings;
|
|
|
|
|
|
|
|
/* Retrain with preferred link settings only relevant for
|
|
|
|
* DP signal type
|
2019-06-05 04:52:59 +09:00
|
|
|
* Check for non-DP signal or if passive dongle present
|
2019-05-11 02:34:30 +09:00
|
|
|
*/
|
2019-06-05 04:52:59 +09:00
|
|
|
if (!dc_is_dp_signal(link->connector_signal) ||
|
|
|
|
link->dongle_max_pix_clk > 0)
|
2019-05-11 02:34:30 +09:00
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_PIPES; i++) {
|
|
|
|
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
|
|
|
if (pipe->stream && pipe->stream->link) {
|
2019-06-01 03:17:43 +09:00
|
|
|
if (pipe->stream->link == link) {
|
|
|
|
link_stream = pipe->stream;
|
2019-05-11 02:34:30 +09:00
|
|
|
break;
|
2019-06-01 03:17:43 +09:00
|
|
|
}
|
2019-05-11 02:34:30 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Stream not found */
|
|
|
|
if (i == MAX_PIPES)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Cannot retrain link if backend is off */
|
|
|
|
if (link_stream->dpms_off)
|
|
|
|
return;
|
|
|
|
|
2019-06-01 03:17:43 +09:00
|
|
|
decide_link_settings(link_stream, &store_settings);
|
2019-05-11 02:34:30 +09:00
|
|
|
|
|
|
|
if ((store_settings.lane_count != LANE_COUNT_UNKNOWN) &&
|
|
|
|
(store_settings.link_rate != LINK_RATE_UNKNOWN))
|
|
|
|
dp_retrain_link_dp_test(link, &store_settings, false);
|
|
|
|
}
|
|
|
|
|
2019-05-31 00:56:39 +09:00
|
|
|
void dc_link_set_preferred_training_settings(struct dc *dc,
|
|
|
|
struct dc_link_settings *link_setting,
|
|
|
|
struct dc_link_training_overrides *lt_overrides,
|
|
|
|
struct dc_link *link,
|
|
|
|
bool skip_immediate_retrain)
|
|
|
|
{
|
|
|
|
if (lt_overrides != NULL)
|
|
|
|
link->preferred_training_settings = *lt_overrides;
|
|
|
|
else
|
|
|
|
memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings));
|
|
|
|
|
|
|
|
if (link_setting != NULL) {
|
|
|
|
link->preferred_link_setting = *link_setting;
|
|
|
|
} else {
|
|
|
|
link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN;
|
|
|
|
link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Retrain now, or wait until next stream update to apply */
|
|
|
|
if (skip_immediate_retrain == false)
|
|
|
|
dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
|
|
|
|
}
|
|
|
|
|
2019-05-11 02:34:30 +09:00
|
|
|
void dc_link_enable_hpd(const struct dc_link *link)
|
|
|
|
{
|
|
|
|
dc_link_dp_enable_hpd(link);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dc_link_disable_hpd(const struct dc_link *link)
|
|
|
|
{
|
|
|
|
dc_link_dp_disable_hpd(link);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dc_link_set_test_pattern(struct dc_link *link,
|
|
|
|
enum dp_test_pattern test_pattern,
|
|
|
|
const struct link_training_settings *p_link_settings,
|
|
|
|
const unsigned char *p_custom_pattern,
|
|
|
|
unsigned int cust_pattern_size)
|
|
|
|
{
|
|
|
|
if (link != NULL)
|
|
|
|
dc_link_dp_set_test_pattern(
|
|
|
|
link,
|
|
|
|
test_pattern,
|
|
|
|
p_link_settings,
|
|
|
|
p_custom_pattern,
|
|
|
|
cust_pattern_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t dc_link_bandwidth_kbps(
|
|
|
|
const struct dc_link *link,
|
|
|
|
const struct dc_link_settings *link_setting)
|
|
|
|
{
|
|
|
|
uint32_t link_bw_kbps =
|
|
|
|
link_setting->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; /* bytes per sec */
|
|
|
|
|
|
|
|
link_bw_kbps *= 8; /* 8 bits per byte*/
|
|
|
|
link_bw_kbps *= link_setting->lane_count;
|
|
|
|
|
2019-05-11 02:34:30 +09:00
|
|
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
|
|
|
if (link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
|
|
|
|
/* Account for FEC overhead.
|
|
|
|
* We have to do it based on caps,
|
|
|
|
* and not based on FEC being set ready,
|
|
|
|
* because FEC is set ready too late in
|
|
|
|
* the process to correctly be picked up
|
|
|
|
* by mode enumeration.
|
|
|
|
*
|
|
|
|
* There's enough zeros at the end of 'kbps'
|
|
|
|
* that make the below operation 100% precise
|
|
|
|
* for our purposes.
|
|
|
|
* 'long long' makes it work even for HDMI 2.1
|
|
|
|
* max bandwidth (and much, much bigger bandwidths
|
|
|
|
* than that, actually).
|
|
|
|
*
|
|
|
|
* NOTE: Reducing link BW by 3% may not be precise
|
|
|
|
* because it may be a stream BT that increases by 3%, and so
|
|
|
|
* 1/1.03 = 0.970873 factor should have been used instead,
|
|
|
|
* but the difference is minimal and is in a safe direction,
|
|
|
|
* which all works well around potential ambiguity of DP 1.4a spec.
|
|
|
|
*/
|
2019-07-08 22:52:08 +09:00
|
|
|
link_bw_kbps = mul_u64_u32_shr(BIT_ULL(32) * 970LL / 1000,
|
|
|
|
link_bw_kbps, 32);
|
2019-05-11 02:34:30 +09:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-05-11 02:34:30 +09:00
|
|
|
return link_bw_kbps;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct dc_link_settings *dc_link_get_link_cap(
|
|
|
|
const struct dc_link *link)
|
|
|
|
{
|
|
|
|
if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN &&
|
|
|
|
link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
|
|
|
|
return &link->preferred_link_setting;
|
|
|
|
return &link->verified_link_cap;
|
|
|
|
}
|