Merge tag 'drm-intel-next-2025-05-08' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next
Non-display related: - Fix undefined reference to `intel_pxp_gsccs_is_ready_for_sessions' Display related: - More work towards display separation (Jani) - Stop writing VRR_CTL_IGN_MAX_SHIFT for MTL onwards (Jouni) - DSC checks for 3 engines (Ankit) - Add link rate and lane count to i915_display_info (Khaled) - PSR fixes and workaround for underrun on idle (Jouni) - LOBF enablement and ALMP fixes (Animesh) - Clean up VGA plane handling (Ville) - Use an intel_connector pointer everywhere (Imre) - Fix warning for coffeelake on SunrisePoint PCH (Jiajia) - Rework/Correction on minimum hblank calculation (Arun) - Dmesg clean up (Jani) - Add a couple of simple display workarounds (Ankit, Vinod) - Refactor HDCP GSC (Jani) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://lore.kernel.org/r/aByyL3bEufPu79OM@intel.com
This commit is contained in:
@@ -4393,8 +4393,9 @@ EXPORT_SYMBOL(drm_panel_dp_aux_backlight);
|
||||
#endif
|
||||
|
||||
/* See DP Standard v2.1 2.6.4.4.1.1, 2.8.4.4, 2.8.7 */
|
||||
static int drm_dp_link_symbol_cycles(int lane_count, int pixels, int bpp_x16,
|
||||
int symbol_size, bool is_mst)
|
||||
static int drm_dp_link_data_symbol_cycles(int lane_count, int pixels,
|
||||
int bpp_x16, int symbol_size,
|
||||
bool is_mst)
|
||||
{
|
||||
int cycles = DIV_ROUND_UP(pixels * bpp_x16, 16 * symbol_size * lane_count);
|
||||
int align = is_mst ? 4 / lane_count : 1;
|
||||
@@ -4402,22 +4403,42 @@ static int drm_dp_link_symbol_cycles(int lane_count, int pixels, int bpp_x16,
|
||||
return ALIGN(cycles, align);
|
||||
}
|
||||
|
||||
static int drm_dp_link_dsc_symbol_cycles(int lane_count, int pixels, int slice_count,
|
||||
int bpp_x16, int symbol_size, bool is_mst)
|
||||
/**
|
||||
* drm_dp_link_symbol_cycles - calculate the link symbol count with/without dsc
|
||||
* @lane_count: DP link lane count
|
||||
* @pixels: number of pixels in a scanline
|
||||
* @dsc_slice_count: number of slices for DSC or '0' for non-DSC
|
||||
* @bpp_x16: bits per pixel in .4 binary fixed format
|
||||
* @symbol_size: DP symbol size
|
||||
* @is_mst: %true for MST and %false for SST
|
||||
*
|
||||
* Calculate the link symbol cycles for both DSC (@dsc_slice_count !=0) and
|
||||
* non-DSC case (@dsc_slice_count == 0) and return the count.
|
||||
*/
|
||||
int drm_dp_link_symbol_cycles(int lane_count, int pixels, int dsc_slice_count,
|
||||
int bpp_x16, int symbol_size, bool is_mst)
|
||||
{
|
||||
int slice_count = dsc_slice_count ? : 1;
|
||||
int slice_pixels = DIV_ROUND_UP(pixels, slice_count);
|
||||
int slice_data_cycles = drm_dp_link_symbol_cycles(lane_count, slice_pixels,
|
||||
bpp_x16, symbol_size, is_mst);
|
||||
int slice_eoc_cycles = is_mst ? 4 / lane_count : 1;
|
||||
int slice_data_cycles = drm_dp_link_data_symbol_cycles(lane_count,
|
||||
slice_pixels,
|
||||
bpp_x16,
|
||||
symbol_size,
|
||||
is_mst);
|
||||
int slice_eoc_cycles = 0;
|
||||
|
||||
if (dsc_slice_count)
|
||||
slice_eoc_cycles = is_mst ? 4 / lane_count : 1;
|
||||
|
||||
return slice_count * (slice_data_cycles + slice_eoc_cycles);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_link_symbol_cycles);
|
||||
|
||||
/**
|
||||
* drm_dp_bw_overhead - Calculate the BW overhead of a DP link stream
|
||||
* @lane_count: DP link lane count
|
||||
* @hactive: pixel count of the active period in one scanline of the stream
|
||||
* @dsc_slice_count: DSC slice count if @flags/DRM_DP_LINK_BW_OVERHEAD_DSC is set
|
||||
* @dsc_slice_count: number of slices for DSC or '0' for non-DSC
|
||||
* @bpp_x16: bits per pixel in .4 binary fixed point
|
||||
* @flags: DRM_DP_OVERHEAD_x flags
|
||||
*
|
||||
@@ -4431,7 +4452,7 @@ static int drm_dp_link_dsc_symbol_cycles(int lane_count, int pixels, int slice_c
|
||||
* as well as the stream's
|
||||
* - @hactive timing
|
||||
* - @bpp_x16 color depth
|
||||
* - compression mode (@flags / %DRM_DP_OVERHEAD_DSC).
|
||||
* - compression mode (@dsc_slice_count != 0)
|
||||
* Note that this overhead doesn't account for the 8b/10b, 128b/132b
|
||||
* channel coding efficiency, for that see
|
||||
* @drm_dp_link_bw_channel_coding_efficiency().
|
||||
@@ -4486,15 +4507,10 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
|
||||
WARN_ON((flags & DRM_DP_BW_OVERHEAD_UHBR) &&
|
||||
(flags & DRM_DP_BW_OVERHEAD_FEC));
|
||||
|
||||
if (flags & DRM_DP_BW_OVERHEAD_DSC)
|
||||
symbol_cycles = drm_dp_link_dsc_symbol_cycles(lane_count, hactive,
|
||||
dsc_slice_count,
|
||||
bpp_x16, symbol_size,
|
||||
is_mst);
|
||||
else
|
||||
symbol_cycles = drm_dp_link_symbol_cycles(lane_count, hactive,
|
||||
bpp_x16, symbol_size,
|
||||
is_mst);
|
||||
symbol_cycles = drm_dp_link_symbol_cycles(lane_count, hactive,
|
||||
dsc_slice_count,
|
||||
bpp_x16, symbol_size,
|
||||
is_mst);
|
||||
|
||||
return DIV_ROUND_UP_ULL(mul_u32_u32(symbol_cycles * symbol_size * lane_count,
|
||||
overhead * 16),
|
||||
|
||||
@@ -52,7 +52,6 @@ i915-y += \
|
||||
i915-y += \
|
||||
soc/intel_dram.o \
|
||||
soc/intel_gmch.o \
|
||||
soc/intel_pch.o \
|
||||
soc/intel_rom.o
|
||||
|
||||
# core library code
|
||||
@@ -282,6 +281,7 @@ i915-y += \
|
||||
display/intel_modeset_setup.o \
|
||||
display/intel_modeset_verify.o \
|
||||
display/intel_overlay.o \
|
||||
display/intel_pch.o \
|
||||
display/intel_pch_display.o \
|
||||
display/intel_pch_refclk.o \
|
||||
display/intel_plane_initial.o \
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "g4x_dp.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_backlight.h"
|
||||
#include "intel_connector.h"
|
||||
@@ -28,7 +30,6 @@
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_pch_display.h"
|
||||
#include "intel_pps.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
static const struct dpll g4x_dpll[] = {
|
||||
{ .dot = 162000, .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8, },
|
||||
@@ -60,14 +61,13 @@ static void g4x_dp_set_clock(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
const struct dpll *divisor = NULL;
|
||||
int i, count = 0;
|
||||
|
||||
if (display->platform.g4x) {
|
||||
divisor = g4x_dpll;
|
||||
count = ARRAY_SIZE(g4x_dpll);
|
||||
} else if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
} else if (HAS_PCH_SPLIT(display)) {
|
||||
divisor = pch_dpll;
|
||||
count = ARRAY_SIZE(pch_dpll);
|
||||
} else if (display->platform.cherryview) {
|
||||
@@ -93,7 +93,6 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
enum port port = encoder->port;
|
||||
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
|
||||
@@ -141,7 +140,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
|
||||
intel_dp->DP |= DP_ENHANCED_FRAMING;
|
||||
|
||||
intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);
|
||||
} else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
|
||||
} else if (HAS_PCH_CPT(display) && port != PORT_A) {
|
||||
intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
|
||||
|
||||
intel_de_rmw(display, TRANS_DP_CTL(crtc->pipe),
|
||||
@@ -183,7 +182,7 @@ static void assert_dp_port(struct intel_dp *intel_dp, bool state)
|
||||
|
||||
static void assert_edp_pll(struct intel_display *display, bool state)
|
||||
{
|
||||
bool cur_state = intel_de_read(display, DP_A) & DP_PLL_ENABLE;
|
||||
bool cur_state = intel_de_read(display, DP_A) & EDP_PLL_ENABLE;
|
||||
|
||||
INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
|
||||
"eDP PLL state assertion failure (expected %s, current %s)\n",
|
||||
@@ -205,12 +204,12 @@ static void ilk_edp_pll_on(struct intel_dp *intel_dp,
|
||||
drm_dbg_kms(display->drm, "enabling eDP PLL for clock %d\n",
|
||||
pipe_config->port_clock);
|
||||
|
||||
intel_dp->DP &= ~DP_PLL_FREQ_MASK;
|
||||
intel_dp->DP &= ~EDP_PLL_FREQ_MASK;
|
||||
|
||||
if (pipe_config->port_clock == 162000)
|
||||
intel_dp->DP |= DP_PLL_FREQ_162MHZ;
|
||||
intel_dp->DP |= EDP_PLL_FREQ_162MHZ;
|
||||
else
|
||||
intel_dp->DP |= DP_PLL_FREQ_270MHZ;
|
||||
intel_dp->DP |= EDP_PLL_FREQ_270MHZ;
|
||||
|
||||
intel_de_write(display, DP_A, intel_dp->DP);
|
||||
intel_de_posting_read(display, DP_A);
|
||||
@@ -225,7 +224,7 @@ static void ilk_edp_pll_on(struct intel_dp *intel_dp,
|
||||
if (display->platform.ironlake)
|
||||
intel_wait_for_vblank_if_active(display, !crtc->pipe);
|
||||
|
||||
intel_dp->DP |= DP_PLL_ENABLE;
|
||||
intel_dp->DP |= EDP_PLL_ENABLE;
|
||||
|
||||
intel_de_write(display, DP_A, intel_dp->DP);
|
||||
intel_de_posting_read(display, DP_A);
|
||||
@@ -243,7 +242,7 @@ static void ilk_edp_pll_off(struct intel_dp *intel_dp,
|
||||
|
||||
drm_dbg_kms(display->drm, "disabling eDP PLL\n");
|
||||
|
||||
intel_dp->DP &= ~DP_PLL_ENABLE;
|
||||
intel_dp->DP &= ~EDP_PLL_ENABLE;
|
||||
|
||||
intel_de_write(display, DP_A, intel_dp->DP);
|
||||
intel_de_posting_read(display, DP_A);
|
||||
@@ -277,7 +276,6 @@ bool g4x_dp_port_enabled(struct intel_display *display,
|
||||
i915_reg_t dp_reg, enum port port,
|
||||
enum pipe *pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
bool ret;
|
||||
u32 val;
|
||||
|
||||
@@ -287,13 +285,13 @@ bool g4x_dp_port_enabled(struct intel_display *display,
|
||||
|
||||
/* asserts want to know the pipe even if the port is disabled */
|
||||
if (display->platform.ivybridge && port == PORT_A)
|
||||
*pipe = (val & DP_PIPE_SEL_MASK_IVB) >> DP_PIPE_SEL_SHIFT_IVB;
|
||||
else if (HAS_PCH_CPT(dev_priv) && port != PORT_A)
|
||||
*pipe = REG_FIELD_GET(DP_PIPE_SEL_MASK_IVB, val);
|
||||
else if (HAS_PCH_CPT(display) && port != PORT_A)
|
||||
ret &= cpt_dp_port_selected(display, port, pipe);
|
||||
else if (display->platform.cherryview)
|
||||
*pipe = (val & DP_PIPE_SEL_MASK_CHV) >> DP_PIPE_SEL_SHIFT_CHV;
|
||||
*pipe = REG_FIELD_GET(DP_PIPE_SEL_MASK_CHV, val);
|
||||
else
|
||||
*pipe = (val & DP_PIPE_SEL_MASK) >> DP_PIPE_SEL_SHIFT;
|
||||
*pipe = REG_FIELD_GET(DP_PIPE_SEL_MASK, val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -338,7 +336,6 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
u32 tmp, flags = 0;
|
||||
enum port port = encoder->port;
|
||||
@@ -353,7 +350,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
|
||||
|
||||
pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A;
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
|
||||
if (HAS_PCH_CPT(display) && port != PORT_A) {
|
||||
u32 trans_dp = intel_de_read(display,
|
||||
TRANS_DP_CTL(crtc->pipe));
|
||||
|
||||
@@ -389,13 +386,12 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
|
||||
if (display->platform.g4x && tmp & DP_COLOR_RANGE_16_235)
|
||||
pipe_config->limited_color_range = true;
|
||||
|
||||
pipe_config->lane_count =
|
||||
((tmp & DP_PORT_WIDTH_MASK) >> DP_PORT_WIDTH_SHIFT) + 1;
|
||||
pipe_config->lane_count = REG_FIELD_GET(DP_PORT_WIDTH_MASK, tmp) + 1;
|
||||
|
||||
g4x_dp_get_m_n(pipe_config);
|
||||
|
||||
if (port == PORT_A) {
|
||||
if ((intel_de_read(display, DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_162MHZ)
|
||||
if ((intel_de_read(display, DP_A) & EDP_PLL_FREQ_MASK) == EDP_PLL_FREQ_162MHZ)
|
||||
pipe_config->port_clock = 162000;
|
||||
else
|
||||
pipe_config->port_clock = 270000;
|
||||
@@ -416,7 +412,6 @@ intel_dp_link_down(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *old_crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
|
||||
enum port port = encoder->port;
|
||||
@@ -429,7 +424,7 @@ intel_dp_link_down(struct intel_encoder *encoder,
|
||||
drm_dbg_kms(display->drm, "\n");
|
||||
|
||||
if ((display->platform.ivybridge && port == PORT_A) ||
|
||||
(HAS_PCH_CPT(dev_priv) && port != PORT_A)) {
|
||||
(HAS_PCH_CPT(display) && port != PORT_A)) {
|
||||
intel_dp->DP &= ~DP_LINK_TRAIN_MASK_CPT;
|
||||
intel_dp->DP |= DP_LINK_TRAIN_PAT_IDLE_CPT;
|
||||
} else {
|
||||
@@ -448,7 +443,7 @@ intel_dp_link_down(struct intel_encoder *encoder,
|
||||
* to transcoder A after disabling it to allow the
|
||||
* matching HDMI port to be enabled on transcoder A.
|
||||
*/
|
||||
if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B && port != PORT_A) {
|
||||
if (HAS_PCH_IBX(display) && crtc->pipe == PIPE_B && port != PORT_A) {
|
||||
/*
|
||||
* We get CPU/PCH FIFO underruns on the other pipe when
|
||||
* doing the workaround. Sweep them under the rug.
|
||||
@@ -581,16 +576,10 @@ static void chv_post_disable_dp(struct intel_atomic_state *state,
|
||||
const struct intel_crtc_state *old_crtc_state,
|
||||
const struct drm_connector_state *old_conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
|
||||
intel_dp_link_down(encoder, old_crtc_state);
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Assert data lane reset */
|
||||
chv_data_lane_soft_reset(encoder, old_crtc_state, true);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1223,10 +1212,10 @@ static int g4x_dp_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
int ret;
|
||||
|
||||
if (HAS_PCH_SPLIT(i915) && encoder->port != PORT_A)
|
||||
if (HAS_PCH_SPLIT(display) && encoder->port != PORT_A)
|
||||
crtc_state->has_pch_encoder = true;
|
||||
|
||||
ret = intel_dp_compute_config(encoder, crtc_state, conn_state);
|
||||
@@ -1279,7 +1268,6 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
|
||||
bool g4x_dp_init(struct intel_display *display,
|
||||
i915_reg_t output_reg, enum port port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
const struct intel_bios_encoder_data *devdata;
|
||||
struct intel_digital_port *dig_port;
|
||||
struct intel_encoder *intel_encoder;
|
||||
@@ -1353,7 +1341,7 @@ bool g4x_dp_init(struct intel_display *display,
|
||||
intel_encoder->audio_disable = g4x_dp_audio_disable;
|
||||
|
||||
if ((display->platform.ivybridge && port == PORT_A) ||
|
||||
(HAS_PCH_CPT(dev_priv) && port != PORT_A))
|
||||
(HAS_PCH_CPT(display) && port != PORT_A))
|
||||
dig_port->dp.set_link_train = cpt_set_link_train;
|
||||
else
|
||||
dig_port->dp.set_link_train = g4x_set_link_train;
|
||||
@@ -1370,7 +1358,7 @@ bool g4x_dp_init(struct intel_display *display,
|
||||
intel_encoder->set_signal_levels = g4x_set_signal_levels;
|
||||
|
||||
if (display->platform.valleyview || display->platform.cherryview ||
|
||||
(HAS_PCH_SPLIT(dev_priv) && port != PORT_A)) {
|
||||
(HAS_PCH_SPLIT(display) && port != PORT_A)) {
|
||||
dig_port->dp.preemph_max = intel_dp_preemph_max_3;
|
||||
dig_port->dp.voltage_max = intel_dp_voltage_max_3;
|
||||
} else {
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
* HDMI support for G4x,ILK,SNB,IVB,VLV,CHV (HSW+ handled by the DDI code).
|
||||
*/
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "g4x_hdmi.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
@@ -22,13 +23,11 @@
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_sdvo.h"
|
||||
#include "vlv_sideband.h"
|
||||
|
||||
static void intel_hdmi_prepare(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
@@ -37,7 +36,7 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder,
|
||||
intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
|
||||
|
||||
hdmi_val = SDVO_ENCODING_HDMI;
|
||||
if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range)
|
||||
if (!HAS_PCH_SPLIT(display) && crtc_state->limited_color_range)
|
||||
hdmi_val |= HDMI_COLOR_RANGE_16_235;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH;
|
||||
@@ -52,7 +51,7 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder,
|
||||
if (crtc_state->has_hdmi_sink)
|
||||
hdmi_val |= HDMI_MODE_SELECT_HDMI;
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_CPT(display))
|
||||
hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe);
|
||||
else if (display->platform.cherryview)
|
||||
hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe);
|
||||
@@ -134,9 +133,8 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
|
||||
if (HAS_PCH_SPLIT(i915)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
crtc_state->has_pch_encoder = true;
|
||||
if (!intel_fdi_compute_pipe_bpp(crtc_state))
|
||||
return -EINVAL;
|
||||
@@ -155,7 +153,6 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
u32 tmp, flags = 0;
|
||||
int dotclock;
|
||||
@@ -186,7 +183,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
|
||||
if (tmp & HDMI_AUDIO_ENABLE)
|
||||
pipe_config->has_audio = true;
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev_priv) &&
|
||||
if (!HAS_PCH_SPLIT(display) &&
|
||||
tmp & HDMI_COLOR_RANGE_16_235)
|
||||
pipe_config->limited_color_range = true;
|
||||
|
||||
@@ -383,7 +380,6 @@ static void intel_disable_hdmi(struct intel_atomic_state *state,
|
||||
const struct drm_connector_state *old_conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
struct intel_digital_port *dig_port =
|
||||
hdmi_to_dig_port(intel_hdmi);
|
||||
@@ -401,7 +397,7 @@ static void intel_disable_hdmi(struct intel_atomic_state *state,
|
||||
* to transcoder A after disabling it to allow the
|
||||
* matching DP port to be enabled on transcoder A.
|
||||
*/
|
||||
if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) {
|
||||
if (HAS_PCH_IBX(display) && crtc->pipe == PIPE_B) {
|
||||
/*
|
||||
* We get CPU/PCH FIFO underruns on the other pipe when
|
||||
* doing the workaround. Sweep them under the rug.
|
||||
@@ -539,15 +535,8 @@ static void chv_hdmi_post_disable(struct intel_atomic_state *state,
|
||||
const struct intel_crtc_state *old_crtc_state,
|
||||
const struct drm_connector_state *old_conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Assert data lane reset */
|
||||
chv_data_lane_soft_reset(encoder, old_crtc_state, true);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
static void chv_hdmi_pre_enable(struct intel_atomic_state *state,
|
||||
@@ -682,7 +671,6 @@ static bool assert_hdmi_port_valid(struct intel_display *display, enum port port
|
||||
bool g4x_hdmi_init(struct intel_display *display,
|
||||
i915_reg_t hdmi_reg, enum port port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
const struct intel_bios_encoder_data *devdata;
|
||||
struct intel_digital_port *dig_port;
|
||||
struct intel_encoder *intel_encoder;
|
||||
@@ -724,7 +712,7 @@ bool g4x_hdmi_init(struct intel_display *display,
|
||||
|
||||
intel_encoder->hotplug = intel_hdmi_hotplug;
|
||||
intel_encoder->compute_config = g4x_hdmi_compute_config;
|
||||
if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
intel_encoder->disable = pch_disable_hdmi;
|
||||
intel_encoder->post_disable = pch_post_disable_hdmi;
|
||||
} else {
|
||||
@@ -745,9 +733,9 @@ bool g4x_hdmi_init(struct intel_display *display,
|
||||
intel_encoder->post_disable = vlv_hdmi_post_disable;
|
||||
} else {
|
||||
intel_encoder->pre_enable = intel_hdmi_pre_enable;
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_CPT(display))
|
||||
intel_encoder->enable = cpt_enable_hdmi;
|
||||
else if (HAS_PCH_IBX(dev_priv))
|
||||
else if (HAS_PCH_IBX(display))
|
||||
intel_encoder->enable = ibx_enable_hdmi;
|
||||
else
|
||||
intel_encoder->enable = g4x_enable_hdmi;
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "i9xx_plane.h"
|
||||
#include "i9xx_plane_regs.h"
|
||||
#include "intel_atomic.h"
|
||||
@@ -631,92 +632,84 @@ static void
|
||||
bdw_primary_enable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
bdw_enable_pipe_irq(display, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
bdw_primary_disable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
bdw_disable_pipe_irq(display, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
ivb_primary_enable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
ilk_enable_display_irq(display, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
ivb_primary_disable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
ilk_disable_display_irq(display, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
ilk_primary_enable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
ilk_enable_display_irq(display, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
ilk_primary_disable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
ilk_disable_display_irq(display, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
vlv_primary_enable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
i915_enable_pipestat(display, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
vlv_primary_disable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
i915_disable_pipestat(display, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static bool i9xx_plane_can_async_flip(u64 modifier)
|
||||
|
||||
@@ -4143,10 +4143,8 @@ static const struct intel_wm_funcs nop_funcs = {
|
||||
|
||||
void i9xx_wm_init(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
/* For FIFO watermark updates */
|
||||
if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
ilk_setup_wm_latency(display);
|
||||
display->funcs.wm = &ilk_wm_funcs;
|
||||
} else if (display->platform.valleyview || display->platform.cherryview) {
|
||||
|
||||
@@ -5,12 +5,15 @@
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "intel_alpm.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dp_aux.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_psr_regs.h"
|
||||
|
||||
bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp)
|
||||
@@ -23,7 +26,7 @@ bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp)
|
||||
return intel_dp->alpm_dpcd & DP_ALPM_AUX_LESS_CAP;
|
||||
}
|
||||
|
||||
void intel_alpm_init_dpcd(struct intel_dp *intel_dp)
|
||||
void intel_alpm_init(struct intel_dp *intel_dp)
|
||||
{
|
||||
u8 dpcd;
|
||||
|
||||
@@ -31,6 +34,7 @@ void intel_alpm_init_dpcd(struct intel_dp *intel_dp)
|
||||
return;
|
||||
|
||||
intel_dp->alpm_dpcd = dpcd;
|
||||
mutex_init(&intel_dp->alpm_parameters.lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -276,6 +280,14 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
|
||||
int waketime_in_lines, first_sdp_position;
|
||||
int context_latency, guardband;
|
||||
|
||||
if (intel_dp->alpm_parameters.lobf_disable_debug) {
|
||||
drm_dbg_kms(display->drm, "LOBF is disabled by debug flag\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (intel_dp->alpm_parameters.sink_alpm_error)
|
||||
return;
|
||||
|
||||
if (!intel_dp_is_edp(intel_dp))
|
||||
return;
|
||||
|
||||
@@ -288,6 +300,10 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
|
||||
if (crtc_state->has_psr)
|
||||
return;
|
||||
|
||||
if (crtc_state->vrr.vmin != crtc_state->vrr.vmax ||
|
||||
crtc_state->vrr.vmin != crtc_state->vrr.flipline)
|
||||
return;
|
||||
|
||||
if (!(intel_alpm_aux_wake_supported(intel_dp) ||
|
||||
intel_alpm_aux_less_wake_supported(intel_dp)))
|
||||
return;
|
||||
@@ -316,15 +332,16 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
|
||||
enum port port = dp_to_dig_port(intel_dp)->base.port;
|
||||
u32 alpm_ctl;
|
||||
|
||||
if (DISPLAY_VER(display) < 20 ||
|
||||
(!intel_dp->psr.sel_update_enabled && !intel_dp_is_edp(intel_dp)))
|
||||
if (DISPLAY_VER(display) < 20 || (!intel_psr_needs_alpm(intel_dp, crtc_state) &&
|
||||
!crtc_state->has_lobf))
|
||||
return;
|
||||
|
||||
mutex_lock(&intel_dp->alpm_parameters.lock);
|
||||
/*
|
||||
* Panel Replay on eDP is always using ALPM aux less. I.e. no need to
|
||||
* check panel support at this point.
|
||||
*/
|
||||
if ((intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) ||
|
||||
if ((crtc_state->has_panel_replay && intel_dp_is_edp(intel_dp)) ||
|
||||
(crtc_state->has_lobf && intel_alpm_aux_less_wake_supported(intel_dp))) {
|
||||
alpm_ctl = ALPM_CTL_ALPM_ENABLE |
|
||||
ALPM_CTL_ALPM_AUX_LESS_ENABLE |
|
||||
@@ -353,18 +370,107 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
|
||||
ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines);
|
||||
}
|
||||
|
||||
if (crtc_state->has_lobf)
|
||||
if (crtc_state->has_lobf) {
|
||||
alpm_ctl |= ALPM_CTL_LOBF_ENABLE;
|
||||
drm_dbg_kms(display->drm, "Link off between frames (LOBF) enabled\n");
|
||||
}
|
||||
|
||||
alpm_ctl |= ALPM_CTL_ALPM_ENTRY_CHECK(intel_dp->alpm_parameters.check_entry_lines);
|
||||
|
||||
intel_de_write(display, ALPM_CTL(display, cpu_transcoder), alpm_ctl);
|
||||
mutex_unlock(&intel_dp->alpm_parameters.lock);
|
||||
}
|
||||
|
||||
void intel_alpm_configure(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
lnl_alpm_configure(intel_dp, crtc_state);
|
||||
intel_dp->alpm_parameters.transcoder = crtc_state->cpu_transcoder;
|
||||
}
|
||||
|
||||
void intel_alpm_pre_plane_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
const struct intel_crtc_state *crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
const struct intel_crtc_state *old_crtc_state =
|
||||
intel_atomic_get_old_crtc_state(state, crtc);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
if (DISPLAY_VER(display) < 20)
|
||||
return;
|
||||
|
||||
if (crtc_state->has_lobf || crtc_state->has_lobf == old_crtc_state->has_lobf)
|
||||
return;
|
||||
|
||||
for_each_intel_encoder_mask(display->drm, encoder,
|
||||
crtc_state->uapi.encoder_mask) {
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
if (!intel_encoder_is_dp(encoder))
|
||||
continue;
|
||||
|
||||
intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
if (!intel_dp_is_edp(intel_dp))
|
||||
continue;
|
||||
|
||||
if (old_crtc_state->has_lobf) {
|
||||
mutex_lock(&intel_dp->alpm_parameters.lock);
|
||||
intel_de_write(display, ALPM_CTL(display, cpu_transcoder), 0);
|
||||
drm_dbg_kms(display->drm, "Link off between frames (LOBF) disabled\n");
|
||||
mutex_unlock(&intel_dp->alpm_parameters.lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_alpm_enable_sink(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
if (!intel_psr_needs_alpm(intel_dp, crtc_state) && !crtc_state->has_lobf)
|
||||
return;
|
||||
|
||||
val = DP_ALPM_ENABLE | DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE;
|
||||
|
||||
if (crtc_state->has_panel_replay || (crtc_state->has_lobf &&
|
||||
intel_alpm_aux_less_wake_supported(intel_dp)))
|
||||
val |= DP_ALPM_MODE_AUX_LESS;
|
||||
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val);
|
||||
}
|
||||
|
||||
void intel_alpm_post_plane_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
const struct intel_crtc_state *crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
const struct intel_crtc_state *old_crtc_state =
|
||||
intel_atomic_get_old_crtc_state(state, crtc);
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
if ((!crtc_state->has_lobf ||
|
||||
crtc_state->has_lobf == old_crtc_state->has_lobf) && !crtc_state->has_psr)
|
||||
return;
|
||||
|
||||
for_each_intel_encoder_mask(display->drm, encoder,
|
||||
crtc_state->uapi.encoder_mask) {
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
if (!intel_encoder_is_dp(encoder))
|
||||
continue;
|
||||
|
||||
intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
if (intel_dp_is_edp(intel_dp)) {
|
||||
intel_alpm_enable_sink(intel_dp, crtc_state);
|
||||
intel_alpm_configure(intel_dp, crtc_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int i915_edp_lobf_info_show(struct seq_file *m, void *data)
|
||||
@@ -403,6 +509,32 @@ out:
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(i915_edp_lobf_info);
|
||||
|
||||
static int
|
||||
i915_edp_lobf_debug_get(void *data, u64 *val)
|
||||
{
|
||||
struct intel_connector *connector = data;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
|
||||
|
||||
*val = intel_dp->alpm_parameters.lobf_disable_debug;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_edp_lobf_debug_set(void *data, u64 val)
|
||||
{
|
||||
struct intel_connector *connector = data;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
|
||||
|
||||
intel_dp->alpm_parameters.lobf_disable_debug = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(i915_edp_lobf_debug_fops,
|
||||
i915_edp_lobf_debug_get, i915_edp_lobf_debug_set,
|
||||
"%llu\n");
|
||||
|
||||
void intel_alpm_lobf_debugfs_add(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
@@ -412,6 +544,55 @@ void intel_alpm_lobf_debugfs_add(struct intel_connector *connector)
|
||||
connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
|
||||
return;
|
||||
|
||||
debugfs_create_file("i915_edp_lobf_debug", 0644, root,
|
||||
connector, &i915_edp_lobf_debug_fops);
|
||||
|
||||
debugfs_create_file("i915_edp_lobf_info", 0444, root,
|
||||
connector, &i915_edp_lobf_info_fops);
|
||||
}
|
||||
|
||||
void intel_alpm_disable(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
enum transcoder cpu_transcoder = intel_dp->alpm_parameters.transcoder;
|
||||
|
||||
if (DISPLAY_VER(display) < 20 || !intel_dp->alpm_dpcd)
|
||||
return;
|
||||
|
||||
mutex_lock(&intel_dp->alpm_parameters.lock);
|
||||
|
||||
intel_de_rmw(display, ALPM_CTL(display, cpu_transcoder),
|
||||
ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE |
|
||||
ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
|
||||
|
||||
intel_de_rmw(display,
|
||||
PORT_ALPM_CTL(cpu_transcoder),
|
||||
PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
|
||||
|
||||
drm_dbg_kms(display->drm, "Disabling ALPM\n");
|
||||
mutex_unlock(&intel_dp->alpm_parameters.lock);
|
||||
}
|
||||
|
||||
bool intel_alpm_get_error(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
struct drm_dp_aux *aux = &intel_dp->aux;
|
||||
u8 val;
|
||||
int r;
|
||||
|
||||
r = drm_dp_dpcd_readb(aux, DP_RECEIVER_ALPM_STATUS, &val);
|
||||
if (r != 1) {
|
||||
drm_err(display->drm, "Error reading ALPM status\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (val & DP_ALPM_LOCK_TIMEOUT_ERROR) {
|
||||
drm_dbg_kms(display->drm, "ALPM lock timeout error\n");
|
||||
|
||||
/* Clearing error */
|
||||
drm_dp_dpcd_writeb(aux, DP_RECEIVER_ALPM_STATUS, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,10 @@ struct intel_dp;
|
||||
struct intel_crtc_state;
|
||||
struct drm_connector_state;
|
||||
struct intel_connector;
|
||||
struct intel_atomic_state;
|
||||
struct intel_crtc;
|
||||
|
||||
void intel_alpm_init_dpcd(struct intel_dp *intel_dp);
|
||||
void intel_alpm_init(struct intel_dp *intel_dp);
|
||||
bool intel_alpm_compute_params(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
|
||||
@@ -21,7 +23,13 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
|
||||
struct drm_connector_state *conn_state);
|
||||
void intel_alpm_configure(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_alpm_pre_plane_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void intel_alpm_post_plane_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void intel_alpm_lobf_debugfs_add(struct intel_connector *connector);
|
||||
bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp);
|
||||
bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp);
|
||||
void intel_alpm_disable(struct intel_dp *intel_dp);
|
||||
bool intel_alpm_get_error(struct intel_dp *intel_dp);
|
||||
#endif
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_eld.h>
|
||||
#include <drm/drm_fixed.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/intel/i915_component.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_audio_regs.h"
|
||||
@@ -587,19 +587,17 @@ static void ibx_audio_regs_init(struct intel_display *display,
|
||||
enum pipe pipe,
|
||||
struct ibx_audio_regs *regs)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (display->platform.valleyview || display->platform.cherryview) {
|
||||
regs->hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe);
|
||||
regs->aud_config = VLV_AUD_CFG(pipe);
|
||||
regs->aud_cntl_st = VLV_AUD_CNTL_ST(pipe);
|
||||
regs->aud_cntrl_st2 = VLV_AUD_CNTL_ST2;
|
||||
} else if (HAS_PCH_CPT(i915)) {
|
||||
} else if (HAS_PCH_CPT(display)) {
|
||||
regs->hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe);
|
||||
regs->aud_config = CPT_AUD_CFG(pipe);
|
||||
regs->aud_cntl_st = CPT_AUD_CNTL_ST(pipe);
|
||||
regs->aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
|
||||
} else if (HAS_PCH_IBX(i915)) {
|
||||
} else if (HAS_PCH_IBX(display)) {
|
||||
regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
|
||||
regs->aud_config = IBX_AUD_CFG(pipe);
|
||||
regs->aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
|
||||
@@ -889,12 +887,10 @@ static const struct intel_audio_funcs hsw_audio_funcs = {
|
||||
*/
|
||||
void intel_audio_hooks_init(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (display->platform.g4x)
|
||||
display->funcs.audio = &g4x_audio_funcs;
|
||||
else if (display->platform.valleyview || display->platform.cherryview ||
|
||||
HAS_PCH_CPT(i915) || HAS_PCH_IBX(i915))
|
||||
HAS_PCH_CPT(display) || HAS_PCH_IBX(display))
|
||||
display->funcs.audio = &ibx_audio_funcs;
|
||||
else if (display->platform.haswell || DISPLAY_VER(display) >= 8)
|
||||
display->funcs.audio = &hsw_audio_funcs;
|
||||
|
||||
@@ -10,8 +10,11 @@
|
||||
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_backlight.h"
|
||||
#include "intel_backlight_regs.h"
|
||||
#include "intel_connector.h"
|
||||
@@ -473,7 +476,6 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
|
||||
{
|
||||
struct intel_connector *connector = to_intel_connector(conn_state->connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 pch_ctl1, pch_ctl2;
|
||||
|
||||
@@ -486,7 +488,7 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
|
||||
intel_de_write(display, BLC_PWM_PCH_CTL1, pch_ctl1);
|
||||
}
|
||||
|
||||
if (HAS_PCH_LPT(i915))
|
||||
if (HAS_PCH_LPT(display))
|
||||
intel_de_rmw(display, SOUTH_CHICKEN2, LPT_PWM_GRANULARITY,
|
||||
panel->backlight.alternate_pwm_increment ?
|
||||
LPT_PWM_GRANULARITY : 0);
|
||||
@@ -503,7 +505,7 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
|
||||
pch_ctl1 |= BLM_PCH_POLARITY;
|
||||
|
||||
/* After LPT, override is the default. */
|
||||
if (HAS_PCH_LPT(i915))
|
||||
if (HAS_PCH_LPT(display))
|
||||
pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
|
||||
|
||||
intel_de_write(display, BLC_PWM_PCH_CTL1, pch_ctl1);
|
||||
@@ -1064,7 +1066,7 @@ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
|
||||
*/
|
||||
static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 mul, clock;
|
||||
|
||||
@@ -1073,7 +1075,7 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
|
||||
else
|
||||
mul = 128;
|
||||
|
||||
if (HAS_PCH_LPT_H(i915))
|
||||
if (HAS_PCH_LPT_H(display))
|
||||
clock = MHz(135); /* LPT:H */
|
||||
else
|
||||
clock = MHz(24); /* LPT:LP */
|
||||
@@ -1230,12 +1232,11 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector)
|
||||
static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
|
||||
bool alt, cpu_mode;
|
||||
|
||||
if (HAS_PCH_LPT(i915))
|
||||
if (HAS_PCH_LPT(display))
|
||||
alt = intel_de_read(display, SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY;
|
||||
else
|
||||
alt = intel_de_read(display, SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY;
|
||||
@@ -1259,7 +1260,7 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus
|
||||
|
||||
panel->backlight.pwm_enabled = pch_ctl1 & BLM_PCH_PWM_ENABLE;
|
||||
|
||||
cpu_mode = panel->backlight.pwm_enabled && HAS_PCH_LPT(i915) &&
|
||||
cpu_mode = panel->backlight.pwm_enabled && HAS_PCH_LPT(display) &&
|
||||
!(pch_ctl1 & BLM_PCH_OVERRIDE_ENABLE) &&
|
||||
(cpu_ctl2 & BLM_PWM_ENABLE);
|
||||
|
||||
@@ -1466,15 +1467,13 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused)
|
||||
|
||||
static int cnp_num_backlight_controllers(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_MTL)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_MTL)
|
||||
return 2;
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_DG1)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_DG1)
|
||||
return 1;
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
return 2;
|
||||
|
||||
return 1;
|
||||
@@ -1482,14 +1481,12 @@ static int cnp_num_backlight_controllers(struct intel_display *display)
|
||||
|
||||
static bool cnp_backlight_controller_is_valid(struct intel_display *display, int controller)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (controller < 0 || controller >= cnp_num_backlight_controllers(display))
|
||||
return false;
|
||||
|
||||
if (controller == 1 &&
|
||||
INTEL_PCH_TYPE(i915) >= PCH_ICP &&
|
||||
INTEL_PCH_TYPE(i915) <= PCH_ADP)
|
||||
INTEL_PCH_TYPE(display) >= PCH_ICP &&
|
||||
INTEL_PCH_TYPE(display) <= PCH_ADP)
|
||||
return intel_de_read(display, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT;
|
||||
|
||||
return true;
|
||||
@@ -1818,7 +1815,6 @@ void intel_backlight_init_funcs(struct intel_panel *panel)
|
||||
struct intel_connector *connector =
|
||||
container_of(panel, struct intel_connector, panel);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
|
||||
if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI &&
|
||||
intel_dsi_dcs_init_backlight_funcs(connector) == 0)
|
||||
@@ -1826,14 +1822,14 @@ void intel_backlight_init_funcs(struct intel_panel *panel)
|
||||
|
||||
if (display->platform.geminilake || display->platform.broxton) {
|
||||
panel->backlight.pwm_funcs = &bxt_pwm_funcs;
|
||||
} else if (INTEL_PCH_TYPE(i915) >= PCH_CNP) {
|
||||
} else if (INTEL_PCH_TYPE(display) >= PCH_CNP) {
|
||||
panel->backlight.pwm_funcs = &cnp_pwm_funcs;
|
||||
} else if (INTEL_PCH_TYPE(i915) >= PCH_LPT_H) {
|
||||
if (HAS_PCH_LPT(i915))
|
||||
} else if (INTEL_PCH_TYPE(display) >= PCH_LPT_H) {
|
||||
if (HAS_PCH_LPT(display))
|
||||
panel->backlight.pwm_funcs = &lpt_pwm_funcs;
|
||||
else
|
||||
panel->backlight.pwm_funcs = &spt_pwm_funcs;
|
||||
} else if (HAS_PCH_SPLIT(i915)) {
|
||||
} else if (HAS_PCH_SPLIT(display)) {
|
||||
panel->backlight.pwm_funcs = &pch_pwm_funcs;
|
||||
} else if (display->platform.valleyview || display->platform.cherryview) {
|
||||
if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) {
|
||||
|
||||
@@ -2245,28 +2245,27 @@ static const u8 adlp_ddc_pin_map[] = {
|
||||
|
||||
static u8 map_ddc_pin(struct intel_display *display, u8 vbt_pin)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
const u8 *ddc_pin_map;
|
||||
int i, n_entries;
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_MTL || display->platform.alderlake_p) {
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_MTL || display->platform.alderlake_p) {
|
||||
ddc_pin_map = adlp_ddc_pin_map;
|
||||
n_entries = ARRAY_SIZE(adlp_ddc_pin_map);
|
||||
} else if (display->platform.alderlake_s) {
|
||||
ddc_pin_map = adls_ddc_pin_map;
|
||||
n_entries = ARRAY_SIZE(adls_ddc_pin_map);
|
||||
} else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) {
|
||||
} else if (INTEL_PCH_TYPE(display) >= PCH_DG1) {
|
||||
return vbt_pin;
|
||||
} else if (display->platform.rocketlake && INTEL_PCH_TYPE(i915) == PCH_TGP) {
|
||||
} else if (display->platform.rocketlake && INTEL_PCH_TYPE(display) == PCH_TGP) {
|
||||
ddc_pin_map = rkl_pch_tgp_ddc_pin_map;
|
||||
n_entries = ARRAY_SIZE(rkl_pch_tgp_ddc_pin_map);
|
||||
} else if (HAS_PCH_TGP(i915) && DISPLAY_VER(display) == 9) {
|
||||
} else if (HAS_PCH_TGP(display) && DISPLAY_VER(display) == 9) {
|
||||
ddc_pin_map = gen9bc_tgp_ddc_pin_map;
|
||||
n_entries = ARRAY_SIZE(gen9bc_tgp_ddc_pin_map);
|
||||
} else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) {
|
||||
} else if (INTEL_PCH_TYPE(display) >= PCH_ICP) {
|
||||
ddc_pin_map = icp_ddc_pin_map;
|
||||
n_entries = ARRAY_SIZE(icp_ddc_pin_map);
|
||||
} else if (HAS_PCH_CNP(i915)) {
|
||||
} else if (HAS_PCH_CNP(display)) {
|
||||
ddc_pin_map = cnp_ddc_pin_map;
|
||||
n_entries = ARRAY_SIZE(cnp_ddc_pin_map);
|
||||
} else {
|
||||
@@ -2865,8 +2864,6 @@ parse_general_definitions(struct intel_display *display)
|
||||
static void
|
||||
init_vbt_defaults(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
display->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC;
|
||||
|
||||
/* general features */
|
||||
@@ -2883,7 +2880,7 @@ init_vbt_defaults(struct intel_display *display)
|
||||
* clock for LVDS.
|
||||
*/
|
||||
display->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(display,
|
||||
!HAS_PCH_SPLIT(i915));
|
||||
!HAS_PCH_SPLIT(display));
|
||||
drm_dbg_kms(display->drm, "Set default to SSC at %d kHz\n",
|
||||
display->vbt.lvds_ssc_freq);
|
||||
}
|
||||
@@ -3126,7 +3123,7 @@ static const struct vbt_header *intel_bios_get_vbt(struct intel_display *display
|
||||
* If the OpRegion does not have VBT, look in SPI flash
|
||||
* through MMIO or PCI mapping
|
||||
*/
|
||||
if (!vbt && IS_DGFX(i915))
|
||||
if (!vbt && display->platform.dgfx)
|
||||
with_intel_display_rpm(display)
|
||||
vbt = oprom_get_vbt(display, intel_rom_spi(i915), sizep, "SPI flash");
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/*
|
||||
* Please use intel_vbt_defs.h for VBT private data, to hide and abstract away
|
||||
* the VBT from the rest of the driver. Add the parsed, clean data to struct
|
||||
* intel_vbt_data within struct drm_i915_private.
|
||||
* intel_vbt_data within struct intel_display.
|
||||
*/
|
||||
|
||||
#ifndef _INTEL_BIOS_H_
|
||||
|
||||
@@ -3494,7 +3494,6 @@ static int dg1_rawclk(struct intel_display *display)
|
||||
|
||||
static int cnp_rawclk(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
int divider, fraction;
|
||||
u32 rawclk;
|
||||
|
||||
@@ -3514,7 +3513,7 @@ static int cnp_rawclk(struct intel_display *display)
|
||||
|
||||
rawclk |= CNP_RAWCLK_DEN(DIV_ROUND_CLOSEST(numerator * 1000,
|
||||
fraction) - 1);
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
rawclk |= ICP_RAWCLK_NUM(numerator);
|
||||
}
|
||||
|
||||
@@ -3553,21 +3552,20 @@ static int i9xx_hrawclk(struct intel_display *display)
|
||||
*/
|
||||
u32 intel_read_rawclk(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 freq;
|
||||
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTL)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_MTL)
|
||||
/*
|
||||
* MTL always uses a 38.4 MHz rawclk. The bspec tells us
|
||||
* "RAWCLK_FREQ defaults to the values for 38.4 and does
|
||||
* not need to be programmed."
|
||||
*/
|
||||
freq = 38400;
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_DG1)
|
||||
freq = dg1_rawclk(display);
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_CNP)
|
||||
freq = cnp_rawclk(display);
|
||||
else if (HAS_PCH_SPLIT(dev_priv))
|
||||
else if (HAS_PCH_SPLIT(display))
|
||||
freq = pch_rawclk(display);
|
||||
else if (display->platform.valleyview || display->platform.cherryview)
|
||||
freq = vlv_hrawclk(display);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_cmtg.h"
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_irq.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_connector.h"
|
||||
@@ -91,13 +91,12 @@ static struct intel_crt *intel_attached_crt(struct intel_connector *connector)
|
||||
bool intel_crt_port_enabled(struct intel_display *display,
|
||||
i915_reg_t adpa_reg, enum pipe *pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 val;
|
||||
|
||||
val = intel_de_read(display, adpa_reg);
|
||||
|
||||
/* asserts want to know the pipe even if the port is disabled */
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_CPT(display))
|
||||
*pipe = REG_FIELD_GET(ADPA_PIPE_SEL_MASK_CPT, val);
|
||||
else
|
||||
*pipe = REG_FIELD_GET(ADPA_PIPE_SEL_MASK, val);
|
||||
@@ -177,7 +176,6 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder,
|
||||
int mode)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crt *crt = intel_encoder_to_crt(encoder);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
@@ -194,14 +192,14 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder,
|
||||
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
|
||||
|
||||
/* For CPT allow 3 pipe config, for others just use A or B */
|
||||
if (HAS_PCH_LPT(dev_priv))
|
||||
if (HAS_PCH_LPT(display))
|
||||
; /* Those bits don't exist here */
|
||||
else if (HAS_PCH_CPT(dev_priv))
|
||||
else if (HAS_PCH_CPT(display))
|
||||
adpa |= ADPA_PIPE_SEL_CPT(crtc->pipe);
|
||||
else
|
||||
adpa |= ADPA_PIPE_SEL(crtc->pipe);
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev_priv))
|
||||
if (!HAS_PCH_SPLIT(display))
|
||||
intel_de_write(display, BCLRPAT(display, crtc->pipe), 0);
|
||||
|
||||
switch (mode) {
|
||||
@@ -356,7 +354,6 @@ intel_crt_mode_valid(struct drm_connector *connector,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
int max_dotclk = display->cdclk.max_dotclk_freq;
|
||||
enum drm_mode_status status;
|
||||
int max_clock;
|
||||
@@ -368,9 +365,9 @@ intel_crt_mode_valid(struct drm_connector *connector,
|
||||
if (mode->clock < 25000)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
if (HAS_PCH_LPT(dev_priv))
|
||||
if (HAS_PCH_LPT(display))
|
||||
max_clock = 180000;
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
else if (display->platform.valleyview)
|
||||
/*
|
||||
* 270 MHz due to current DPLL limits,
|
||||
* DAC limit supposedly 355 MHz.
|
||||
@@ -387,7 +384,7 @@ intel_crt_mode_valid(struct drm_connector *connector,
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
/* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */
|
||||
if (HAS_PCH_LPT(dev_priv) &&
|
||||
if (HAS_PCH_LPT(display) &&
|
||||
ilk_get_lanes_required(mode->clock, 270000, 24) > 2)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
@@ -438,7 +435,6 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
|
||||
@@ -457,7 +453,7 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
|
||||
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
|
||||
/* LPT FDI RX only supports 8bpc. */
|
||||
if (HAS_PCH_LPT(dev_priv)) {
|
||||
if (HAS_PCH_LPT(display)) {
|
||||
/* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
|
||||
if (crtc_state->bw_constrained && crtc_state->pipe_bpp < 24) {
|
||||
drm_dbg_kms(display->drm,
|
||||
@@ -482,13 +478,12 @@ static bool ilk_crt_detect_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
u32 adpa;
|
||||
bool ret;
|
||||
|
||||
/* The first time through, trigger an explicit detection cycle */
|
||||
if (crt->force_hotplug_required) {
|
||||
bool turn_off_dac = HAS_PCH_SPLIT(dev_priv);
|
||||
bool turn_off_dac = HAS_PCH_SPLIT(display);
|
||||
u32 save_adpa;
|
||||
|
||||
crt->force_hotplug_required = false;
|
||||
@@ -583,15 +578,14 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
|
||||
static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
u32 stat;
|
||||
bool ret = false;
|
||||
int i, tries = 0;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv))
|
||||
if (HAS_PCH_SPLIT(display))
|
||||
return ilk_crt_detect_hotplug(connector);
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv))
|
||||
if (display->platform.valleyview)
|
||||
return valleyview_crt_detect_hotplug(connector);
|
||||
|
||||
/*
|
||||
@@ -599,7 +593,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
||||
* to get a reliable result.
|
||||
*/
|
||||
|
||||
if (IS_G45(dev_priv))
|
||||
if (display->platform.g45)
|
||||
tries = 2;
|
||||
else
|
||||
tries = 1;
|
||||
@@ -940,7 +934,6 @@ out:
|
||||
static int intel_crt_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
|
||||
struct intel_encoder *encoder = &crt->base;
|
||||
intel_wakeref_t wakeref;
|
||||
@@ -953,7 +946,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
|
||||
wakeref = intel_display_power_get(display, encoder->power_domain);
|
||||
|
||||
ret = intel_crt_ddc_get_modes(connector, connector->ddc);
|
||||
if (ret || !IS_G4X(dev_priv))
|
||||
if (ret || !display->platform.g4x)
|
||||
goto out;
|
||||
|
||||
/* Try to probe digital port for output in DVI-I -> VGA mode. */
|
||||
@@ -1012,16 +1005,15 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
|
||||
|
||||
void intel_crt_init(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_connector *connector;
|
||||
struct intel_crt *crt;
|
||||
i915_reg_t adpa_reg;
|
||||
u8 ddc_pin;
|
||||
u32 adpa;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv))
|
||||
if (HAS_PCH_SPLIT(display))
|
||||
adpa_reg = PCH_ADPA;
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
else if (display->platform.valleyview)
|
||||
adpa_reg = VLV_ADPA;
|
||||
else
|
||||
adpa_reg = ADPA;
|
||||
@@ -1069,7 +1061,7 @@ void intel_crt_init(struct intel_display *display)
|
||||
|
||||
crt->base.type = INTEL_OUTPUT_ANALOG;
|
||||
crt->base.cloneable = BIT(INTEL_OUTPUT_DVO) | BIT(INTEL_OUTPUT_HDMI);
|
||||
if (IS_I830(dev_priv))
|
||||
if (display->platform.i830)
|
||||
crt->base.pipe_mask = BIT(PIPE_A);
|
||||
else
|
||||
crt->base.pipe_mask = ~0;
|
||||
@@ -1109,7 +1101,7 @@ void intel_crt_init(struct intel_display *display)
|
||||
|
||||
intel_ddi_buf_trans_init(&crt->base);
|
||||
} else {
|
||||
if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
crt->base.compute_config = pch_crt_compute_config;
|
||||
crt->base.disable = pch_disable_crt;
|
||||
crt->base.post_disable = pch_post_disable_crt;
|
||||
@@ -1131,7 +1123,7 @@ void intel_crt_init(struct intel_display *display)
|
||||
* polarity and link reversal bits or not, instead of relying on the
|
||||
* BIOS.
|
||||
*/
|
||||
if (HAS_PCH_LPT(dev_priv)) {
|
||||
if (HAS_PCH_LPT(display)) {
|
||||
u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT |
|
||||
FDI_RX_LINK_REVERSAL_OVERRIDE;
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
crtc->block_dc_for_vblank = intel_psr_needs_block_dc_vblank(crtc_state);
|
||||
crtc->vblank_psr_notify = intel_psr_needs_vblank_notification(crtc_state);
|
||||
|
||||
assert_vblank_disabled(&crtc->base);
|
||||
drm_crtc_set_max_vblank_count(&crtc->base,
|
||||
@@ -154,9 +154,9 @@ void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
|
||||
drm_crtc_vblank_off(&crtc->base);
|
||||
assert_vblank_disabled(&crtc->base);
|
||||
|
||||
crtc->block_dc_for_vblank = false;
|
||||
crtc->vblank_psr_notify = false;
|
||||
|
||||
flush_work(&display->irq.vblank_dc_work);
|
||||
flush_work(&display->irq.vblank_notify_work);
|
||||
}
|
||||
|
||||
struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
|
||||
@@ -305,7 +305,6 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = {
|
||||
|
||||
int intel_crtc_init(struct intel_display *display, enum pipe pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_plane *primary, *cursor;
|
||||
const struct drm_crtc_funcs *funcs;
|
||||
struct intel_crtc *crtc;
|
||||
@@ -333,7 +332,7 @@ int intel_crtc_init(struct intel_display *display, enum pipe pipe)
|
||||
for_each_sprite(display, pipe, sprite) {
|
||||
struct intel_plane *plane;
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 9)
|
||||
if (DISPLAY_VER(display) >= 9)
|
||||
plane = skl_universal_plane_create(display, pipe, PLANE_2 + sprite);
|
||||
else
|
||||
plane = intel_sprite_plane_create(display, pipe, sprite);
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_atomic_plane.h"
|
||||
#include "intel_cursor.h"
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
#include <linux/log2.h>
|
||||
#include <linux/math64.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_cx0_phy.h"
|
||||
#include "intel_cx0_phy_regs.h"
|
||||
#include "intel_ddi.h"
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
|
||||
#include <drm/display/drm_dp_helper.h>
|
||||
#include <drm/display/drm_scdc_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_privacy_screen_consumer.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "icl_dsi.h"
|
||||
#include "intel_alpm.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_audio_regs.h"
|
||||
#include "intel_backlight.h"
|
||||
@@ -3553,6 +3555,7 @@ static void intel_ddi_disable_dp(struct intel_atomic_state *state,
|
||||
intel_dp->link.active = false;
|
||||
|
||||
intel_psr_disable(intel_dp, old_crtc_state);
|
||||
intel_alpm_disable(intel_dp);
|
||||
intel_edp_backlight_off(old_conn_state);
|
||||
/* Disable the decompression in DP Sink */
|
||||
intel_dp_sink_disable_decompression(state,
|
||||
@@ -4902,9 +4905,7 @@ static enum hpd_pin tgl_hpd_pin(struct intel_display *display, enum port port)
|
||||
|
||||
static enum hpd_pin rkl_hpd_pin(struct intel_display *display, enum port port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (HAS_PCH_TGP(dev_priv))
|
||||
if (HAS_PCH_TGP(display))
|
||||
return tgl_hpd_pin(display, port);
|
||||
|
||||
if (port >= PORT_TC1)
|
||||
@@ -4923,12 +4924,10 @@ static enum hpd_pin icl_hpd_pin(struct intel_display *display, enum port port)
|
||||
|
||||
static enum hpd_pin ehl_hpd_pin(struct intel_display *display, enum port port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (port == PORT_D)
|
||||
return HPD_PORT_A;
|
||||
|
||||
if (HAS_PCH_TGP(dev_priv))
|
||||
if (HAS_PCH_TGP(display))
|
||||
return icl_hpd_pin(display, port);
|
||||
|
||||
return HPD_PORT_A + port - PORT_A;
|
||||
@@ -4936,9 +4935,7 @@ static enum hpd_pin ehl_hpd_pin(struct intel_display *display, enum port port)
|
||||
|
||||
static enum hpd_pin skl_hpd_pin(struct intel_display *display, enum port port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (HAS_PCH_TGP(dev_priv))
|
||||
if (HAS_PCH_TGP(display))
|
||||
return icl_hpd_pin(display, port);
|
||||
|
||||
return HPD_PORT_A + port - PORT_A;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#ifndef __INTEL_DE_H__
|
||||
#define __INTEL_DE_H__
|
||||
|
||||
#include "intel_display_conversion.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_dmc_wl.h"
|
||||
#include "intel_dsb.h"
|
||||
@@ -19,7 +18,7 @@ static inline struct intel_uncore *__to_uncore(struct intel_display *display)
|
||||
}
|
||||
|
||||
static inline u32
|
||||
__intel_de_read(struct intel_display *display, i915_reg_t reg)
|
||||
intel_de_read(struct intel_display *display, i915_reg_t reg)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -31,7 +30,6 @@ __intel_de_read(struct intel_display *display, i915_reg_t reg)
|
||||
|
||||
return val;
|
||||
}
|
||||
#define intel_de_read(p,...) __intel_de_read(__to_intel_display(p), __VA_ARGS__)
|
||||
|
||||
static inline u8
|
||||
intel_de_read8(struct intel_display *display, i915_reg_t reg)
|
||||
@@ -66,7 +64,7 @@ intel_de_read64_2x32(struct intel_display *display,
|
||||
}
|
||||
|
||||
static inline void
|
||||
__intel_de_posting_read(struct intel_display *display, i915_reg_t reg)
|
||||
intel_de_posting_read(struct intel_display *display, i915_reg_t reg)
|
||||
{
|
||||
intel_dmc_wl_get(display, reg);
|
||||
|
||||
@@ -74,10 +72,9 @@ __intel_de_posting_read(struct intel_display *display, i915_reg_t reg)
|
||||
|
||||
intel_dmc_wl_put(display, reg);
|
||||
}
|
||||
#define intel_de_posting_read(p,...) __intel_de_posting_read(__to_intel_display(p), __VA_ARGS__)
|
||||
|
||||
static inline void
|
||||
__intel_de_write(struct intel_display *display, i915_reg_t reg, u32 val)
|
||||
intel_de_write(struct intel_display *display, i915_reg_t reg, u32 val)
|
||||
{
|
||||
intel_dmc_wl_get(display, reg);
|
||||
|
||||
@@ -85,7 +82,6 @@ __intel_de_write(struct intel_display *display, i915_reg_t reg, u32 val)
|
||||
|
||||
intel_dmc_wl_put(display, reg);
|
||||
}
|
||||
#define intel_de_write(p,...) __intel_de_write(__to_intel_display(p), __VA_ARGS__)
|
||||
|
||||
static inline u32
|
||||
__intel_de_rmw_nowl(struct intel_display *display, i915_reg_t reg,
|
||||
@@ -95,8 +91,7 @@ __intel_de_rmw_nowl(struct intel_display *display, i915_reg_t reg,
|
||||
}
|
||||
|
||||
static inline u32
|
||||
__intel_de_rmw(struct intel_display *display, i915_reg_t reg, u32 clear,
|
||||
u32 set)
|
||||
intel_de_rmw(struct intel_display *display, i915_reg_t reg, u32 clear, u32 set)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -108,7 +103,6 @@ __intel_de_rmw(struct intel_display *display, i915_reg_t reg, u32 clear,
|
||||
|
||||
return val;
|
||||
}
|
||||
#define intel_de_rmw(p,...) __intel_de_rmw(__to_intel_display(p), __VA_ARGS__)
|
||||
|
||||
static inline int
|
||||
__intel_de_wait_for_register_nowl(struct intel_display *display,
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "i9xx_plane.h"
|
||||
#include "i9xx_plane_regs.h"
|
||||
#include "i9xx_wm.h"
|
||||
#include "intel_alpm.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_atomic_plane.h"
|
||||
#include "intel_audio.h"
|
||||
@@ -1043,14 +1044,13 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
const struct intel_crtc_state *old_crtc_state =
|
||||
intel_atomic_get_old_crtc_state(state, crtc);
|
||||
const struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
intel_frontbuffer_flip(dev_priv, new_crtc_state->fb_bits);
|
||||
intel_frontbuffer_flip(display, new_crtc_state->fb_bits);
|
||||
|
||||
if (new_crtc_state->update_wm_post && new_crtc_state->hw.active)
|
||||
intel_update_watermarks(display);
|
||||
@@ -1079,6 +1079,8 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
|
||||
if (audio_enabling(old_crtc_state, new_crtc_state))
|
||||
intel_encoders_audio_enable(state, crtc);
|
||||
|
||||
intel_alpm_post_plane_update(state, crtc);
|
||||
|
||||
intel_psr_post_plane_update(state, crtc);
|
||||
}
|
||||
|
||||
@@ -1174,6 +1176,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
intel_alpm_pre_plane_update(state, crtc);
|
||||
intel_psr_pre_plane_update(state, crtc);
|
||||
|
||||
if (intel_crtc_vrr_disabling(state, crtc)) {
|
||||
@@ -1281,7 +1284,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
|
||||
static void intel_crtc_disable_planes(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
const struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
unsigned int update_mask = new_crtc_state->update_planes;
|
||||
@@ -1303,7 +1306,7 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state,
|
||||
fb_bits |= plane->frontbuffer_bit;
|
||||
}
|
||||
|
||||
intel_frontbuffer_flip(dev_priv, fb_bits);
|
||||
intel_frontbuffer_flip(display, fb_bits);
|
||||
}
|
||||
|
||||
static void intel_encoders_update_prepare(struct intel_atomic_state *state)
|
||||
@@ -1510,7 +1513,6 @@ static void ilk_crtc_enable(struct intel_atomic_state *state,
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
const struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
if (drm_WARN_ON(display->drm, crtc->active))
|
||||
@@ -1562,7 +1564,7 @@ static void ilk_crtc_enable(struct intel_atomic_state *state,
|
||||
|
||||
intel_encoders_enable(state, crtc);
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_CPT(display))
|
||||
intel_wait_for_pipe_scanline_moving(crtc);
|
||||
|
||||
/*
|
||||
@@ -2404,14 +2406,6 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool intel_crtc_needs_wa_14015401596(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
|
||||
return intel_vrr_possible(crtc_state) && crtc_state->has_psr &&
|
||||
IS_DISPLAY_VER(display, 13, 14);
|
||||
}
|
||||
|
||||
static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
@@ -2420,9 +2414,7 @@ static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state)
|
||||
if (!HAS_DSB(display))
|
||||
return 0;
|
||||
|
||||
/* Wa_14015401596 */
|
||||
if (intel_crtc_needs_wa_14015401596(crtc_state))
|
||||
vblank_delay = max(vblank_delay, 1);
|
||||
vblank_delay = max(vblank_delay, intel_psr_min_vblank_delay(crtc_state));
|
||||
|
||||
return vblank_delay;
|
||||
}
|
||||
@@ -2534,15 +2526,13 @@ intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes,
|
||||
|
||||
void intel_panel_sanitize_ssc(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
/*
|
||||
* There may be no VBT; and if the BIOS enabled SSC we can
|
||||
* just keep using it to avoid unnecessary flicker. Whereas if the
|
||||
* BIOS isn't using it, don't assume it will work even if the VBT
|
||||
* indicates as much.
|
||||
*/
|
||||
if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
|
||||
if (HAS_PCH_IBX(display) || HAS_PCH_CPT(display)) {
|
||||
bool bios_lvds_use_ssc = intel_de_read(display,
|
||||
PCH_DREF_CONTROL) &
|
||||
DREF_SSC1_ENABLE;
|
||||
@@ -2724,6 +2714,19 @@ static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_sta
|
||||
intel_de_write(display, TRANS_VTOTAL(display, pipe),
|
||||
VACTIVE(crtc_vdisplay - 1) |
|
||||
VTOTAL(crtc_vtotal - 1));
|
||||
|
||||
if (DISPLAY_VER(display) >= 30) {
|
||||
/*
|
||||
* Address issues for resolutions with high refresh rate that
|
||||
* have small Hblank, specifically where Hblank is smaller than
|
||||
* one MTP. Simulations indicate this will address the
|
||||
* jitter issues that currently causes BS to be immediately
|
||||
* followed by BE which DPRX devices are unable to handle.
|
||||
* https://groups.vesa.org/wg/DP/document/20494
|
||||
*/
|
||||
intel_de_write(display, DP_MIN_HBLANK_CTL(cpu_transcoder),
|
||||
crtc_state->min_hblank);
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_set_transcoder_timings_lrr(const struct intel_crtc_state *crtc_state)
|
||||
@@ -2867,6 +2870,10 @@ static void intel_get_transcoder_timings(struct intel_crtc *crtc,
|
||||
adjusted_mode->crtc_vdisplay +
|
||||
intel_de_read(display,
|
||||
TRANS_SET_CONTEXT_LATENCY(display, cpu_transcoder));
|
||||
|
||||
if (DISPLAY_VER(display) >= 30)
|
||||
pipe_config->min_hblank = intel_de_read(display,
|
||||
DP_MIN_HBLANK_CTL(cpu_transcoder));
|
||||
}
|
||||
|
||||
static void intel_joiner_adjust_pipe_src(struct intel_crtc_state *crtc_state)
|
||||
@@ -5217,6 +5224,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
|
||||
PIPE_CONF_CHECK_I(lane_count);
|
||||
PIPE_CONF_CHECK_X(lane_lat_optim_mask);
|
||||
|
||||
PIPE_CONF_CHECK_I(min_hblank);
|
||||
|
||||
if (HAS_DOUBLE_BUFFERED_M_N(display)) {
|
||||
if (!fastset || !pipe_config->update_m_n)
|
||||
PIPE_CONF_CHECK_M_N(dp_m_n);
|
||||
@@ -6547,7 +6556,6 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
|
||||
{
|
||||
struct intel_display *display = to_intel_display(new_crtc_state);
|
||||
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
|
||||
/*
|
||||
* Update pipe size and adjust fitter if needed: the reason for this is
|
||||
@@ -6563,7 +6571,7 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
|
||||
if (DISPLAY_VER(display) >= 9) {
|
||||
if (new_crtc_state->pch_pfit.enabled)
|
||||
skl_pfit_enable(new_crtc_state);
|
||||
} else if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
} else if (HAS_PCH_SPLIT(display)) {
|
||||
if (new_crtc_state->pch_pfit.enabled)
|
||||
ilk_pfit_enable(new_crtc_state);
|
||||
else if (old_crtc_state->pch_pfit.enabled)
|
||||
@@ -6664,6 +6672,8 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
|
||||
intel_crtc_update_active_timings(pipe_crtc_state, false);
|
||||
}
|
||||
|
||||
intel_psr_notify_pipe_change(state, crtc, true);
|
||||
|
||||
display->funcs.display->crtc_enable(state, crtc);
|
||||
|
||||
/* vblanks work again, re-enable pipe CRC. */
|
||||
@@ -6783,6 +6793,8 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
|
||||
intel_crtc_joined_pipe_mask(old_crtc_state))
|
||||
intel_crtc_disable_pipe_crc(pipe_crtc);
|
||||
|
||||
intel_psr_notify_pipe_change(state, crtc, false);
|
||||
|
||||
display->funcs.display->crtc_disable(state, crtc);
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc,
|
||||
@@ -7639,15 +7651,13 @@ static bool ilk_has_edp_a(struct intel_display *display)
|
||||
|
||||
static bool intel_ddi_crt_present(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (DISPLAY_VER(display) >= 9)
|
||||
return false;
|
||||
|
||||
if (display->platform.haswell_ult || display->platform.broadwell_ult)
|
||||
return false;
|
||||
|
||||
if (HAS_PCH_LPT_H(dev_priv) &&
|
||||
if (HAS_PCH_LPT_H(display) &&
|
||||
intel_de_read(display, SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED)
|
||||
return false;
|
||||
|
||||
@@ -7669,7 +7679,6 @@ bool assert_port_valid(struct intel_display *display, enum port port)
|
||||
|
||||
void intel_setup_outputs(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_encoder *encoder;
|
||||
bool dpd_is_edp = false;
|
||||
|
||||
@@ -7686,7 +7695,7 @@ void intel_setup_outputs(struct intel_display *display)
|
||||
|
||||
if (display->platform.geminilake || display->platform.broxton)
|
||||
vlv_dsi_init(display);
|
||||
} else if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
} else if (HAS_PCH_SPLIT(display)) {
|
||||
int found;
|
||||
|
||||
/*
|
||||
@@ -8054,13 +8063,11 @@ static const struct intel_display_funcs i9xx_display_funcs = {
|
||||
*/
|
||||
void intel_init_display_hooks(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (DISPLAY_VER(display) >= 9) {
|
||||
display->funcs.display = &skl_display_funcs;
|
||||
} else if (HAS_DDI(display)) {
|
||||
display->funcs.display = &ddi_display_funcs;
|
||||
} else if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
} else if (HAS_PCH_SPLIT(display)) {
|
||||
display->funcs.display = &pch_split_display_funcs;
|
||||
} else if (display->platform.cherryview ||
|
||||
display->platform.valleyview) {
|
||||
|
||||
@@ -21,17 +21,15 @@
|
||||
#include "intel_display_limits.h"
|
||||
#include "intel_display_params.h"
|
||||
#include "intel_display_power.h"
|
||||
#include "intel_dmc_wl.h"
|
||||
#include "intel_dpll_mgr.h"
|
||||
#include "intel_fbc.h"
|
||||
#include "intel_global_state.h"
|
||||
#include "intel_gmbus.h"
|
||||
#include "intel_opregion.h"
|
||||
#include "intel_dmc_wl.h"
|
||||
#include "intel_pch.h"
|
||||
#include "intel_wm_types.h"
|
||||
|
||||
struct task_struct;
|
||||
|
||||
struct drm_i915_private;
|
||||
struct drm_property;
|
||||
struct drm_property_blob;
|
||||
struct i915_audio_component;
|
||||
@@ -52,6 +50,7 @@ struct intel_hotplug_funcs;
|
||||
struct intel_initial_plane_config;
|
||||
struct intel_opregion;
|
||||
struct intel_overlay;
|
||||
struct task_struct;
|
||||
|
||||
/* Amount of SAGV/QGV points, BSpec precisely defines this */
|
||||
#define I915_NUM_QGV_POINTS 8
|
||||
@@ -180,7 +179,7 @@ struct intel_hotplug {
|
||||
|
||||
/*
|
||||
* Queuing of hotplug_work, reenable_work and poll_init_work is
|
||||
* enabled. Protected by drm_i915_private::irq_lock.
|
||||
* enabled. Protected by intel_display::irq::lock.
|
||||
*/
|
||||
bool detection_work_enabled;
|
||||
|
||||
@@ -289,6 +288,9 @@ struct intel_display {
|
||||
/* Platform (and subplatform, if any) identification */
|
||||
struct intel_display_platforms platform;
|
||||
|
||||
/* Intel PCH: where the south display engine lives */
|
||||
enum intel_pch pch_type;
|
||||
|
||||
/* Display functions */
|
||||
struct {
|
||||
/* Top level crtc-ish functions */
|
||||
@@ -426,7 +428,7 @@ struct intel_display {
|
||||
* reused when sending message to gsc cs.
|
||||
* this is only populated post Meteorlake
|
||||
*/
|
||||
struct intel_hdcp_gsc_message *hdcp_message;
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
/* Mutex to protect the above hdcp related values. */
|
||||
struct mutex hdcp_mutex;
|
||||
} hdcp;
|
||||
@@ -454,6 +456,9 @@ struct intel_display {
|
||||
} ips;
|
||||
|
||||
struct {
|
||||
/* protects the irq masks */
|
||||
spinlock_t lock;
|
||||
|
||||
/*
|
||||
* Most platforms treat the display irq block as an always-on
|
||||
* power domain. vlv/chv can disable it at runtime and need
|
||||
@@ -466,9 +471,9 @@ struct intel_display {
|
||||
/* For i915gm/i945gm vblank irq workaround */
|
||||
u8 vblank_enabled;
|
||||
|
||||
int vblank_wa_num_pipes;
|
||||
int vblank_enable_count;
|
||||
|
||||
struct work_struct vblank_dc_work;
|
||||
struct work_struct vblank_notify_work;
|
||||
|
||||
u32 de_irq_mask[I915_MAX_PIPES];
|
||||
u32 pipestat_irq_mask[I915_MAX_PIPES];
|
||||
@@ -575,6 +580,8 @@ struct intel_display {
|
||||
struct intel_vbt_data vbt;
|
||||
struct intel_dmc_wl wl;
|
||||
struct intel_wm wm;
|
||||
|
||||
struct work_struct psr_dc5_dc6_wa_work;
|
||||
};
|
||||
|
||||
#endif /* __INTEL_DISPLAY_CORE_H__ */
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
#include "hsw_ips.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_irq.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i9xx_wm_regs.h"
|
||||
@@ -53,10 +54,9 @@ static struct intel_display *node_to_intel_display(struct drm_info_node *node)
|
||||
static int intel_display_caps(struct seq_file *m, void *data)
|
||||
{
|
||||
struct intel_display *display = node_to_intel_display(m->private);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
drm_printf(&p, "PCH type: %d\n", INTEL_PCH_TYPE(i915));
|
||||
drm_printf(&p, "PCH type: %d\n", INTEL_PCH_TYPE(display));
|
||||
|
||||
intel_display_device_info_print(DISPLAY_INFO(display),
|
||||
DISPLAY_RUNTIME_INFO(display), &p);
|
||||
@@ -85,7 +85,6 @@ static int i915_frontbuffer_tracking(struct seq_file *m, void *unused)
|
||||
static int i915_sr_status(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct intel_display *display = node_to_intel_display(m->private);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
intel_wakeref_t wakeref;
|
||||
bool sr_enabled = false;
|
||||
|
||||
@@ -93,7 +92,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
|
||||
|
||||
if (DISPLAY_VER(display) >= 9)
|
||||
/* no global SR status; inspect per-plane WM */;
|
||||
else if (HAS_PCH_SPLIT(dev_priv))
|
||||
else if (HAS_PCH_SPLIT(display))
|
||||
sr_enabled = intel_de_read(display, WM1_LP_ILK) & WM_LP_ENABLE;
|
||||
else if (display->platform.i965gm || display->platform.g4x ||
|
||||
display->platform.i945g || display->platform.i945gm)
|
||||
@@ -558,6 +557,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
|
||||
seq_printf(m, "\tpipe src=" DRM_RECT_FMT ", dither=%s, bpp=%d\n",
|
||||
DRM_RECT_ARG(&crtc_state->pipe_src),
|
||||
str_yes_no(crtc_state->dither), crtc_state->pipe_bpp);
|
||||
seq_printf(m, "\tport_clock=%d, lane_count=%d\n",
|
||||
crtc_state->port_clock, crtc_state->lane_count);
|
||||
|
||||
intel_scaler_info(m, crtc);
|
||||
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <drm/intel/pciids.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/intel/pciids.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "intel_cx0_phy_regs.h"
|
||||
#include "intel_de.h"
|
||||
@@ -1711,7 +1713,6 @@ void intel_display_device_remove(struct intel_display *display)
|
||||
|
||||
static void __intel_display_device_info_runtime_init(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(display);
|
||||
enum pipe pipe;
|
||||
|
||||
@@ -1775,7 +1776,7 @@ static void __intel_display_device_info_runtime_init(struct intel_display *displ
|
||||
goto display_fused_off;
|
||||
}
|
||||
|
||||
if (IS_DISPLAY_VER(display, 7, 8) && HAS_PCH_SPLIT(i915)) {
|
||||
if (IS_DISPLAY_VER(display, 7, 8) && HAS_PCH_SPLIT(display)) {
|
||||
u32 fuse_strap = intel_de_read(display, FUSE_STRAP);
|
||||
u32 sfuse_strap = intel_de_read(display, SFUSE_STRAP);
|
||||
|
||||
@@ -1790,7 +1791,7 @@ static void __intel_display_device_info_runtime_init(struct intel_display *displ
|
||||
*/
|
||||
if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
|
||||
sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
|
||||
(HAS_PCH_CPT(i915) &&
|
||||
(HAS_PCH_CPT(display) &&
|
||||
!(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
|
||||
drm_info(display->drm,
|
||||
"Display fused off, disabling\n");
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "intel_plane_initial.h"
|
||||
#include "intel_pmdemand.h"
|
||||
#include "intel_pps.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_quirks.h"
|
||||
#include "intel_vga.h"
|
||||
#include "intel_wm.h"
|
||||
@@ -180,6 +181,9 @@ static void intel_plane_possible_crtcs_init(struct intel_display *display)
|
||||
|
||||
void intel_display_driver_early_probe(struct intel_display *display)
|
||||
{
|
||||
/* This must be called before any calls to HAS_PCH_* */
|
||||
intel_pch_detect(display);
|
||||
|
||||
if (!HAS_DISPLAY(display))
|
||||
return;
|
||||
|
||||
@@ -223,6 +227,8 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
|
||||
if (ret)
|
||||
goto cleanup_bios;
|
||||
|
||||
intel_psr_dc5_dc6_wa_init(display);
|
||||
|
||||
/* FIXME: completely on the wrong abstraction layer */
|
||||
ret = intel_power_domains_init(display);
|
||||
if (ret < 0)
|
||||
@@ -415,7 +421,6 @@ bool intel_display_driver_check_access(struct intel_display *display)
|
||||
/* part #2: call after irq install, but before gem init */
|
||||
int intel_display_driver_probe_nogem(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
enum pipe pipe;
|
||||
int ret;
|
||||
|
||||
@@ -453,8 +458,6 @@ int intel_display_driver_probe_nogem(struct intel_display *display)
|
||||
|
||||
intel_hti_init(display);
|
||||
|
||||
/* Just disable it once at startup */
|
||||
intel_vga_disable(display);
|
||||
intel_setup_outputs(display);
|
||||
|
||||
ret = intel_dp_tunnel_mgr_init(display);
|
||||
@@ -464,7 +467,7 @@ int intel_display_driver_probe_nogem(struct intel_display *display)
|
||||
intel_display_driver_disable_user_access(display);
|
||||
|
||||
drm_modeset_lock_all(display->drm);
|
||||
intel_modeset_setup_hw_state(i915, display->drm->mode_config.acquire_ctx);
|
||||
intel_modeset_setup_hw_state(display, display->drm->mode_config.acquire_ctx);
|
||||
intel_acpi_assign_connector_fwnodes(display);
|
||||
drm_modeset_unlock_all(display->drm);
|
||||
|
||||
@@ -525,7 +528,6 @@ int intel_display_driver_probe(struct intel_display *display)
|
||||
|
||||
void intel_display_driver_register(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct drm_printer p = drm_dbg_printer(display->drm, DRM_UT_KMS,
|
||||
"i915 display info:");
|
||||
|
||||
@@ -552,7 +554,7 @@ void intel_display_driver_register(struct intel_display *display)
|
||||
drm_kms_helper_poll_init(display->drm);
|
||||
intel_hpd_poll_disable(display);
|
||||
|
||||
intel_fbdev_setup(i915);
|
||||
intel_fbdev_setup(display);
|
||||
|
||||
intel_display_device_info_print(DISPLAY_INFO(display),
|
||||
DISPLAY_RUNTIME_INFO(display), &p);
|
||||
@@ -687,13 +689,11 @@ __intel_display_driver_resume(struct intel_display *display,
|
||||
struct drm_atomic_state *state,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_crtc *crtc;
|
||||
int ret, i;
|
||||
|
||||
intel_modeset_setup_hw_state(i915, ctx);
|
||||
intel_vga_redisable(display);
|
||||
intel_modeset_setup_hw_state(display, ctx);
|
||||
|
||||
if (!state)
|
||||
return 0;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "gt/intel_rps.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_irq.h"
|
||||
#include "i915_reg.h"
|
||||
@@ -15,6 +14,7 @@
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_irq.h"
|
||||
#include "intel_display_rpm.h"
|
||||
#include "intel_display_rps.h"
|
||||
#include "intel_display_trace.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dmc_wl.h"
|
||||
@@ -135,7 +135,7 @@ void ilk_update_display_irq(struct intel_display *display,
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 new_val;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask);
|
||||
|
||||
new_val = dev_priv->irq_mask;
|
||||
@@ -173,7 +173,7 @@ void bdw_update_port_irq(struct intel_display *display,
|
||||
u32 new_val;
|
||||
u32 old_val;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask);
|
||||
|
||||
@@ -206,7 +206,7 @@ static void bdw_update_pipe_irq(struct intel_display *display,
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 new_val;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask);
|
||||
|
||||
@@ -254,7 +254,7 @@ void ibx_display_interrupt_update(struct intel_display *display,
|
||||
|
||||
drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask);
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv)))
|
||||
return;
|
||||
@@ -276,11 +276,10 @@ void ibx_disable_display_interrupt(struct intel_display *display, u32 bits)
|
||||
u32 i915_pipestat_enable_mask(struct intel_display *display,
|
||||
enum pipe pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 status_mask = display->irq.pipestat_irq_mask[pipe];
|
||||
u32 enable_mask = status_mask << 16;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if (DISPLAY_VER(display) < 5)
|
||||
goto out;
|
||||
@@ -329,7 +328,7 @@ void i915_enable_pipestat(struct intel_display *display,
|
||||
"pipe %c: status_mask=0x%x\n",
|
||||
pipe_name(pipe), status_mask);
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv));
|
||||
|
||||
if ((display->irq.pipestat_irq_mask[pipe] & status_mask) == status_mask)
|
||||
@@ -353,7 +352,7 @@ void i915_disable_pipestat(struct intel_display *display,
|
||||
"pipe %c: status_mask=0x%x\n",
|
||||
pipe_name(pipe), status_mask);
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv));
|
||||
|
||||
if ((display->irq.pipestat_irq_mask[pipe] & status_mask) == 0)
|
||||
@@ -377,28 +376,23 @@ static bool i915_has_legacy_blc_interrupt(struct intel_display *display)
|
||||
return IS_DISPLAY_VER(display, 3, 4) && display->platform.mobile;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_enable_asle_pipestat - enable ASLE pipestat for OpRegion
|
||||
* @display: display device
|
||||
*/
|
||||
void i915_enable_asle_pipestat(struct intel_display *display)
|
||||
/* enable ASLE pipestat for OpRegion */
|
||||
static void i915_enable_asle_pipestat(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (!intel_opregion_asle_present(display))
|
||||
return;
|
||||
|
||||
if (!i915_has_legacy_blc_interrupt(display))
|
||||
return;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
i915_enable_pipestat(display, PIPE_B, PIPE_LEGACY_BLC_EVENT_STATUS);
|
||||
if (DISPLAY_VER(display) >= 4)
|
||||
i915_enable_pipestat(display, PIPE_A,
|
||||
PIPE_LEGACY_BLC_EVENT_STATUS);
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DEBUG_FS)
|
||||
@@ -517,14 +511,13 @@ static void i9xx_pipestat_irq_reset(struct intel_display *display)
|
||||
void i9xx_pipestat_irq_ack(struct intel_display *display,
|
||||
u32 iir, u32 pipe_stats[I915_MAX_PIPES])
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe pipe;
|
||||
|
||||
spin_lock(&dev_priv->irq_lock);
|
||||
spin_lock(&display->irq.lock);
|
||||
|
||||
if ((display->platform.valleyview || display->platform.cherryview) &&
|
||||
!display->irq.vlv_display_irqs_enabled) {
|
||||
spin_unlock(&dev_priv->irq_lock);
|
||||
spin_unlock(&display->irq.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -579,7 +572,7 @@ void i9xx_pipestat_irq_ack(struct intel_display *display,
|
||||
intel_de_write(display, reg, enable_mask);
|
||||
}
|
||||
}
|
||||
spin_unlock(&dev_priv->irq_lock);
|
||||
spin_unlock(&display->irq.lock);
|
||||
}
|
||||
|
||||
void i915_pipestat_irq_handler(struct intel_display *display,
|
||||
@@ -879,7 +872,6 @@ static void ilk_gtt_fault_irq_handler(struct intel_display *display)
|
||||
|
||||
void ilk_display_irq_handler(struct intel_display *display, u32 de_iir)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe pipe;
|
||||
u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG;
|
||||
|
||||
@@ -916,7 +908,7 @@ void ilk_display_irq_handler(struct intel_display *display, u32 de_iir)
|
||||
if (de_iir & DE_PCH_EVENT) {
|
||||
u32 pch_iir = intel_de_read(display, SDEIIR);
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_CPT(display))
|
||||
cpt_irq_handler(display, pch_iir);
|
||||
else
|
||||
ibx_irq_handler(display, pch_iir);
|
||||
@@ -926,12 +918,11 @@ void ilk_display_irq_handler(struct intel_display *display, u32 de_iir)
|
||||
}
|
||||
|
||||
if (DISPLAY_VER(display) == 5 && de_iir & DE_PCU_EVENT)
|
||||
gen5_rps_irq_handler(&to_gt(dev_priv)->rps);
|
||||
ilk_display_rps_irq_handler(display);
|
||||
}
|
||||
|
||||
void ivb_display_irq_handler(struct intel_display *display, u32 de_iir)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe pipe;
|
||||
u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB;
|
||||
|
||||
@@ -969,7 +960,7 @@ void ivb_display_irq_handler(struct intel_display *display, u32 de_iir)
|
||||
}
|
||||
|
||||
/* check event from PCH */
|
||||
if (!HAS_PCH_NOP(dev_priv) && (de_iir & DE_PCH_EVENT_IVB)) {
|
||||
if (!HAS_PCH_NOP(display) && (de_iir & DE_PCH_EVENT_IVB)) {
|
||||
u32 pch_iir = intel_de_read(display, SDEIIR);
|
||||
|
||||
cpt_irq_handler(display, pch_iir);
|
||||
@@ -1311,7 +1302,6 @@ static u32 gen8_de_pipe_flip_done_mask(struct intel_display *display)
|
||||
|
||||
static void gen8_read_and_ack_pch_irqs(struct intel_display *display, u32 *pch_iir, u32 *pica_iir)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
u32 pica_ier = 0;
|
||||
|
||||
*pica_iir = 0;
|
||||
@@ -1325,7 +1315,7 @@ static void gen8_read_and_ack_pch_irqs(struct intel_display *display, u32 *pch_i
|
||||
* their flags both in the PICA and SDE IIR.
|
||||
*/
|
||||
if (*pch_iir & SDE_PICAINTERRUPT) {
|
||||
drm_WARN_ON(display->drm, INTEL_PCH_TYPE(i915) < PCH_MTL);
|
||||
drm_WARN_ON(display->drm, INTEL_PCH_TYPE(display) < PCH_MTL);
|
||||
|
||||
pica_ier = intel_de_rmw(display, PICAINTERRUPT_IER, ~0, 0);
|
||||
*pica_iir = intel_de_read(display, PICAINTERRUPT_IIR);
|
||||
@@ -1340,7 +1330,6 @@ static void gen8_read_and_ack_pch_irqs(struct intel_display *display, u32 *pch_i
|
||||
|
||||
void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 iir;
|
||||
enum pipe pipe;
|
||||
|
||||
@@ -1465,7 +1454,7 @@ void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl)
|
||||
pipe, fault_errors);
|
||||
}
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
|
||||
if (HAS_PCH_SPLIT(display) && !HAS_PCH_NOP(display) &&
|
||||
master_ctl & GEN8_DE_PCH_IRQ) {
|
||||
u32 pica_iir;
|
||||
|
||||
@@ -1479,9 +1468,9 @@ void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl)
|
||||
if (pica_iir)
|
||||
xelpdp_pica_irq_handler(display, pica_iir);
|
||||
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
icp_irq_handler(display, iir);
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_SPT)
|
||||
spt_irq_handler(display, iir);
|
||||
else
|
||||
cpt_irq_handler(display, iir);
|
||||
@@ -1573,13 +1562,12 @@ void i915gm_irq_cstate_wa(struct intel_display *display, bool enable)
|
||||
int i8xx_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
i915_enable_pipestat(display, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, irqflags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1587,13 +1575,12 @@ int i8xx_enable_vblank(struct drm_crtc *crtc)
|
||||
void i8xx_disable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
i915_disable_pipestat(display, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, irqflags);
|
||||
}
|
||||
|
||||
int i915gm_enable_vblank(struct drm_crtc *crtc)
|
||||
@@ -1617,14 +1604,13 @@ void i915gm_disable_vblank(struct drm_crtc *crtc)
|
||||
int i965_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
i915_enable_pipestat(display, pipe,
|
||||
PIPE_START_VBLANK_INTERRUPT_STATUS);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, irqflags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1632,28 +1618,26 @@ int i965_enable_vblank(struct drm_crtc *crtc)
|
||||
void i965_disable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
i915_disable_pipestat(display, pipe,
|
||||
PIPE_START_VBLANK_INTERRUPT_STATUS);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, irqflags);
|
||||
}
|
||||
|
||||
int ilk_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
||||
unsigned long irqflags;
|
||||
u32 bit = DISPLAY_VER(display) >= 7 ?
|
||||
DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
ilk_enable_display_irq(display, bit);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, irqflags);
|
||||
|
||||
/* Even though there is no DMC, frame counter can get stuck when
|
||||
* PSR is active as no frames are generated.
|
||||
@@ -1667,15 +1651,14 @@ int ilk_enable_vblank(struct drm_crtc *crtc)
|
||||
void ilk_disable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
||||
unsigned long irqflags;
|
||||
u32 bit = DISPLAY_VER(display) >= 7 ?
|
||||
DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
ilk_disable_display_irq(display, bit);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, irqflags);
|
||||
}
|
||||
|
||||
static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
|
||||
@@ -1701,39 +1684,31 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void intel_display_vblank_dc_work(struct work_struct *work)
|
||||
static void intel_display_vblank_notify_work(struct work_struct *work)
|
||||
{
|
||||
struct intel_display *display =
|
||||
container_of(work, typeof(*display), irq.vblank_dc_work);
|
||||
int vblank_wa_num_pipes = READ_ONCE(display->irq.vblank_wa_num_pipes);
|
||||
container_of(work, typeof(*display), irq.vblank_notify_work);
|
||||
int vblank_enable_count = READ_ONCE(display->irq.vblank_enable_count);
|
||||
|
||||
/*
|
||||
* NOTE: intel_display_power_set_target_dc_state is used only by PSR
|
||||
* code for DC3CO handling. DC3CO target state is currently disabled in
|
||||
* PSR code. If DC3CO is taken into use we need take that into account
|
||||
* here as well.
|
||||
*/
|
||||
intel_display_power_set_target_dc_state(display, vblank_wa_num_pipes ? DC_STATE_DISABLE :
|
||||
DC_STATE_EN_UPTO_DC6);
|
||||
intel_psr_notify_vblank_enable_disable(display, vblank_enable_count);
|
||||
}
|
||||
|
||||
int bdw_enable_vblank(struct drm_crtc *_crtc)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(_crtc);
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (gen11_dsi_configure_te(crtc, true))
|
||||
return 0;
|
||||
|
||||
if (crtc->block_dc_for_vblank && display->irq.vblank_wa_num_pipes++ == 0)
|
||||
schedule_work(&display->irq.vblank_dc_work);
|
||||
if (crtc->vblank_psr_notify && display->irq.vblank_enable_count++ == 0)
|
||||
schedule_work(&display->irq.vblank_notify_work);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
bdw_enable_pipe_irq(display, pipe, GEN8_PIPE_VBLANK);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, irqflags);
|
||||
|
||||
/* Even if there is no DMC, frame counter can get stuck when
|
||||
* PSR is active as no frames are generated, so check only for PSR.
|
||||
@@ -1748,19 +1723,18 @@ void bdw_disable_vblank(struct drm_crtc *_crtc)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(_crtc);
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (gen11_dsi_configure_te(crtc, false))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
||||
spin_lock_irqsave(&display->irq.lock, irqflags);
|
||||
bdw_disable_pipe_irq(display, pipe, GEN8_PIPE_VBLANK);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, irqflags);
|
||||
|
||||
if (crtc->block_dc_for_vblank && --display->irq.vblank_wa_num_pipes == 0)
|
||||
schedule_work(&display->irq.vblank_dc_work);
|
||||
if (crtc->vblank_psr_notify && --display->irq.vblank_enable_count == 0)
|
||||
schedule_work(&display->irq.vblank_notify_work);
|
||||
}
|
||||
|
||||
static u32 vlv_dpinvgtt_pipe_fault_mask(enum pipe pipe)
|
||||
@@ -1894,8 +1868,10 @@ static void _vlv_display_irq_reset(struct intel_display *display)
|
||||
|
||||
void vlv_display_irq_reset(struct intel_display *display)
|
||||
{
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
if (display->irq.vlv_display_irqs_enabled)
|
||||
_vlv_display_irq_reset(display);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
void i9xx_display_irq_reset(struct intel_display *display)
|
||||
@@ -1908,22 +1884,48 @@ void i9xx_display_irq_reset(struct intel_display *display)
|
||||
i9xx_pipestat_irq_reset(display);
|
||||
}
|
||||
|
||||
void i915_display_irq_postinstall(struct intel_display *display)
|
||||
{
|
||||
/*
|
||||
* Interrupt setup is already guaranteed to be single-threaded, this is
|
||||
* just to make the assert_spin_locked check happy.
|
||||
*/
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
i915_enable_pipestat(display, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
|
||||
i915_enable_pipestat(display, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
i915_enable_asle_pipestat(display);
|
||||
}
|
||||
|
||||
void i965_display_irq_postinstall(struct intel_display *display)
|
||||
{
|
||||
/*
|
||||
* Interrupt setup is already guaranteed to be single-threaded, this is
|
||||
* just to make the assert_spin_locked check happy.
|
||||
*/
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
i915_enable_pipestat(display, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
|
||||
i915_enable_pipestat(display, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS);
|
||||
i915_enable_pipestat(display, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
i915_enable_asle_pipestat(display);
|
||||
}
|
||||
|
||||
static u32 vlv_error_mask(void)
|
||||
{
|
||||
/* TODO enable other errors too? */
|
||||
return VLV_ERROR_PAGE_TABLE;
|
||||
}
|
||||
|
||||
void vlv_display_irq_postinstall(struct intel_display *display)
|
||||
static void _vlv_display_irq_postinstall(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 pipestat_mask;
|
||||
u32 enable_mask;
|
||||
enum pipe pipe;
|
||||
|
||||
if (!display->irq.vlv_display_irqs_enabled)
|
||||
return;
|
||||
|
||||
if (display->platform.cherryview)
|
||||
intel_de_write(display, DPINVGTT,
|
||||
DPINVGTT_STATUS_MASK_CHV |
|
||||
@@ -1960,8 +1962,30 @@ void vlv_display_irq_postinstall(struct intel_display *display)
|
||||
intel_display_irq_regs_init(display, VLV_IRQ_REGS, dev_priv->irq_mask, enable_mask);
|
||||
}
|
||||
|
||||
void vlv_display_irq_postinstall(struct intel_display *display)
|
||||
{
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
if (display->irq.vlv_display_irqs_enabled)
|
||||
_vlv_display_irq_postinstall(display);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
void ibx_display_irq_reset(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (HAS_PCH_NOP(i915))
|
||||
return;
|
||||
|
||||
gen2_irq_reset(to_intel_uncore(display->drm), SDE_IRQ_REGS);
|
||||
|
||||
if (HAS_PCH_CPT(i915) || HAS_PCH_LPT(i915))
|
||||
intel_de_write(display, SERR_INT, 0xffffffff);
|
||||
}
|
||||
|
||||
void gen8_display_irq_reset(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
enum pipe pipe;
|
||||
|
||||
if (!HAS_DISPLAY(display))
|
||||
@@ -1977,11 +2001,13 @@ void gen8_display_irq_reset(struct intel_display *display)
|
||||
|
||||
intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS);
|
||||
intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS);
|
||||
|
||||
if (HAS_PCH_SPLIT(i915))
|
||||
ibx_display_irq_reset(display);
|
||||
}
|
||||
|
||||
void gen11_display_irq_reset(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe pipe;
|
||||
u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
|
||||
BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
|
||||
@@ -2026,7 +2052,7 @@ void gen11_display_irq_reset(struct intel_display *display)
|
||||
else
|
||||
intel_display_irq_regs_reset(display, GEN11_DE_HPD_IRQ_REGS);
|
||||
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
intel_display_irq_regs_reset(display, SDE_IRQ_REGS);
|
||||
}
|
||||
|
||||
@@ -2038,10 +2064,10 @@ void gen8_irq_power_well_post_enable(struct intel_display *display,
|
||||
gen8_de_pipe_flip_done_mask(display);
|
||||
enum pipe pipe;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
if (!intel_irqs_enabled(dev_priv)) {
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2050,7 +2076,7 @@ void gen8_irq_power_well_post_enable(struct intel_display *display,
|
||||
display->irq.de_irq_mask[pipe],
|
||||
~display->irq.de_irq_mask[pipe] | extra_ier);
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
void gen8_irq_power_well_pre_disable(struct intel_display *display,
|
||||
@@ -2059,17 +2085,17 @@ void gen8_irq_power_well_pre_disable(struct intel_display *display,
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe pipe;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
if (!intel_irqs_enabled(dev_priv)) {
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
for_each_pipe_masked(display, pipe, pipe_mask)
|
||||
intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe));
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
/* make sure we're done processing display irqs */
|
||||
intel_synchronize_irq(dev_priv);
|
||||
@@ -2088,15 +2114,14 @@ void gen8_irq_power_well_pre_disable(struct intel_display *display,
|
||||
*/
|
||||
static void ibx_irq_postinstall(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 mask;
|
||||
|
||||
if (HAS_PCH_NOP(dev_priv))
|
||||
if (HAS_PCH_NOP(display))
|
||||
return;
|
||||
|
||||
if (HAS_PCH_IBX(dev_priv))
|
||||
if (HAS_PCH_IBX(display))
|
||||
mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
|
||||
else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
|
||||
else if (HAS_PCH_CPT(display) || HAS_PCH_LPT(display))
|
||||
mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
|
||||
else
|
||||
mask = SDE_GMBUS_CPT;
|
||||
@@ -2108,32 +2133,37 @@ void valleyview_enable_display_irqs(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
if (display->irq.vlv_display_irqs_enabled)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
display->irq.vlv_display_irqs_enabled = true;
|
||||
|
||||
if (intel_irqs_enabled(dev_priv)) {
|
||||
_vlv_display_irq_reset(display);
|
||||
vlv_display_irq_postinstall(display);
|
||||
_vlv_display_irq_postinstall(display);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
void valleyview_disable_display_irqs(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
if (!display->irq.vlv_display_irqs_enabled)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
display->irq.vlv_display_irqs_enabled = false;
|
||||
|
||||
if (intel_irqs_enabled(dev_priv))
|
||||
_vlv_display_irq_reset(display);
|
||||
out:
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
void ilk_de_irq_postinstall(struct intel_display *display)
|
||||
@@ -2184,8 +2214,6 @@ static void icp_irq_postinstall(struct intel_display *display);
|
||||
|
||||
void gen8_de_irq_postinstall(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
u32 de_pipe_masked = gen8_de_pipe_fault_mask(display) |
|
||||
GEN8_PIPE_CDCLK_CRC_DONE;
|
||||
u32 de_pipe_enables;
|
||||
@@ -2201,9 +2229,9 @@ void gen8_de_irq_postinstall(struct intel_display *display)
|
||||
|
||||
if (DISPLAY_VER(display) >= 14)
|
||||
mtp_irq_postinstall(display);
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
icp_irq_postinstall(display);
|
||||
else if (HAS_PCH_SPLIT(dev_priv))
|
||||
else if (HAS_PCH_SPLIT(display))
|
||||
ibx_irq_postinstall(display);
|
||||
|
||||
if (DISPLAY_VER(display) < 11)
|
||||
@@ -2323,9 +2351,40 @@ void dg1_de_irq_postinstall(struct intel_display *display)
|
||||
|
||||
void intel_display_irq_init(struct intel_display *display)
|
||||
{
|
||||
spin_lock_init(&display->irq.lock);
|
||||
|
||||
display->drm->vblank_disable_immediate = true;
|
||||
|
||||
intel_hotplug_irq_init(display);
|
||||
|
||||
INIT_WORK(&display->irq.vblank_dc_work, intel_display_vblank_dc_work);
|
||||
INIT_WORK(&display->irq.vblank_notify_work,
|
||||
intel_display_vblank_notify_work);
|
||||
}
|
||||
|
||||
struct intel_display_irq_snapshot {
|
||||
u32 derrmr;
|
||||
};
|
||||
|
||||
struct intel_display_irq_snapshot *
|
||||
intel_display_irq_snapshot_capture(struct intel_display *display)
|
||||
{
|
||||
struct intel_display_irq_snapshot *snapshot;
|
||||
|
||||
snapshot = kzalloc(sizeof(*snapshot), GFP_ATOMIC);
|
||||
if (!snapshot)
|
||||
return NULL;
|
||||
|
||||
if (DISPLAY_VER(display) >= 6 && DISPLAY_VER(display) < 20 && !HAS_GMCH(display))
|
||||
snapshot->derrmr = intel_de_read(display, DERRMR);
|
||||
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
void intel_display_irq_snapshot_print(const struct intel_display_irq_snapshot *snapshot,
|
||||
struct drm_printer *p)
|
||||
{
|
||||
if (!snapshot)
|
||||
return;
|
||||
|
||||
drm_printf(p, "DERRMR: 0x%08x\n", snapshot->derrmr);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
|
||||
enum pipe;
|
||||
struct drm_crtc;
|
||||
struct drm_printer;
|
||||
struct intel_display;
|
||||
struct intel_display_irq_snapshot;
|
||||
|
||||
void valleyview_enable_display_irqs(struct intel_display *display);
|
||||
void valleyview_disable_display_irqs(struct intel_display *display);
|
||||
@@ -54,10 +56,13 @@ u32 gen11_gu_misc_irq_ack(struct intel_display *display, const u32 master_ctl);
|
||||
void gen11_gu_misc_irq_handler(struct intel_display *display, const u32 iir);
|
||||
|
||||
void i9xx_display_irq_reset(struct intel_display *display);
|
||||
void ibx_display_irq_reset(struct intel_display *display);
|
||||
void vlv_display_irq_reset(struct intel_display *display);
|
||||
void gen8_display_irq_reset(struct intel_display *display);
|
||||
void gen11_display_irq_reset(struct intel_display *display);
|
||||
|
||||
void i915_display_irq_postinstall(struct intel_display *display);
|
||||
void i965_display_irq_postinstall(struct intel_display *display);
|
||||
void vlv_display_irq_postinstall(struct intel_display *display);
|
||||
void ilk_de_irq_postinstall(struct intel_display *display);
|
||||
void gen8_de_irq_postinstall(struct intel_display *display);
|
||||
@@ -67,7 +72,6 @@ void dg1_de_irq_postinstall(struct intel_display *display);
|
||||
u32 i915_pipestat_enable_mask(struct intel_display *display, enum pipe pipe);
|
||||
void i915_enable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask);
|
||||
void i915_disable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask);
|
||||
void i915_enable_asle_pipestat(struct intel_display *display);
|
||||
|
||||
void i9xx_pipestat_irq_ack(struct intel_display *display, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
|
||||
|
||||
@@ -82,4 +86,7 @@ void intel_display_irq_init(struct intel_display *display);
|
||||
|
||||
void i915gm_irq_cstate_wa(struct intel_display *display, bool enable);
|
||||
|
||||
struct intel_display_irq_snapshot *intel_display_irq_snapshot_capture(struct intel_display *display);
|
||||
void intel_display_irq_snapshot_print(const struct intel_display_irq_snapshot *snapshot, struct drm_printer *p);
|
||||
|
||||
#endif /* __INTEL_DISPLAY_IRQ_H__ */
|
||||
|
||||
@@ -323,6 +323,35 @@ unlock:
|
||||
mutex_unlock(&power_domains->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_display_power_get_current_dc_state - Set target dc state.
|
||||
* @display: display device
|
||||
*
|
||||
* This function set the "DC off" power well target_dc_state,
|
||||
* based upon this target_dc_stste, "DC off" power well will
|
||||
* enable desired DC state.
|
||||
*/
|
||||
u32 intel_display_power_get_current_dc_state(struct intel_display *display)
|
||||
{
|
||||
struct i915_power_well *power_well;
|
||||
struct i915_power_domains *power_domains = &display->power.domains;
|
||||
u32 current_dc_state = DC_STATE_DISABLE;
|
||||
|
||||
mutex_lock(&power_domains->lock);
|
||||
power_well = lookup_power_well(display, SKL_DISP_DC_OFF);
|
||||
|
||||
if (drm_WARN_ON(display->drm, !power_well))
|
||||
goto unlock;
|
||||
|
||||
current_dc_state = intel_power_well_is_enabled(display, power_well) ?
|
||||
DC_STATE_DISABLE : power_domains->target_dc_state;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&power_domains->lock);
|
||||
|
||||
return current_dc_state;
|
||||
}
|
||||
|
||||
static void __async_put_domains_mask(struct i915_power_domains *power_domains,
|
||||
struct intel_power_domain_mask *mask)
|
||||
{
|
||||
@@ -1365,11 +1394,9 @@ static void hsw_restore_lcpll(struct intel_display *display)
|
||||
*/
|
||||
static void hsw_enable_pc8(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
drm_dbg_kms(display->drm, "Enabling package C8+\n");
|
||||
|
||||
if (HAS_PCH_LPT_LP(dev_priv))
|
||||
if (HAS_PCH_LPT_LP(display))
|
||||
intel_de_rmw(display, SOUTH_DSPCLK_GATE_D,
|
||||
PCH_LP_PARTITION_LEVEL_DISABLE, 0);
|
||||
|
||||
@@ -1415,14 +1442,13 @@ static void intel_pch_reset_handshake(struct intel_display *display,
|
||||
static void skl_display_core_init(struct intel_display *display,
|
||||
bool resume)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct i915_power_domains *power_domains = &display->power.domains;
|
||||
struct i915_power_well *well;
|
||||
|
||||
gen9_set_dc_state(display, DC_STATE_DISABLE);
|
||||
|
||||
/* enable PCH reset handshake */
|
||||
intel_pch_reset_handshake(display, !HAS_PCH_NOP(dev_priv));
|
||||
intel_pch_reset_handshake(display, !HAS_PCH_NOP(display));
|
||||
|
||||
if (!HAS_DISPLAY(display))
|
||||
return;
|
||||
@@ -1624,20 +1650,19 @@ static void tgl_bw_buddy_init(struct intel_display *display)
|
||||
static void icl_display_core_init(struct intel_display *display,
|
||||
bool resume)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct i915_power_domains *power_domains = &display->power.domains;
|
||||
struct i915_power_well *well;
|
||||
|
||||
gen9_set_dc_state(display, DC_STATE_DISABLE);
|
||||
|
||||
/* Wa_14011294188:ehl,jsl,tgl,rkl,adl-s */
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP &&
|
||||
INTEL_PCH_TYPE(dev_priv) < PCH_DG1)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_TGP &&
|
||||
INTEL_PCH_TYPE(display) < PCH_DG1)
|
||||
intel_de_rmw(display, SOUTH_DSPCLK_GATE_D, 0,
|
||||
PCH_DPMGUNIT_CLOCK_GATE_DISABLE);
|
||||
|
||||
/* 1. Enable PCH reset handshake. */
|
||||
intel_pch_reset_handshake(display, !HAS_PCH_NOP(dev_priv));
|
||||
intel_pch_reset_handshake(display, !HAS_PCH_NOP(display));
|
||||
|
||||
if (!HAS_DISPLAY(display))
|
||||
return;
|
||||
@@ -1908,7 +1933,6 @@ static void intel_power_domains_verify_state(struct intel_display *display);
|
||||
*/
|
||||
void intel_power_domains_init_hw(struct intel_display *display, bool resume)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct i915_power_domains *power_domains = &display->power.domains;
|
||||
|
||||
power_domains->initializing = true;
|
||||
@@ -1932,9 +1956,9 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume)
|
||||
assert_isp_power_gated(display);
|
||||
} else if (display->platform.broadwell || display->platform.haswell) {
|
||||
hsw_assert_cdclk(display);
|
||||
intel_pch_reset_handshake(display, !HAS_PCH_NOP(i915));
|
||||
intel_pch_reset_handshake(display, !HAS_PCH_NOP(display));
|
||||
} else if (display->platform.ivybridge) {
|
||||
intel_pch_reset_handshake(display, !HAS_PCH_NOP(i915));
|
||||
intel_pch_reset_handshake(display, !HAS_PCH_NOP(display));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2229,8 +2253,6 @@ static void intel_power_domains_verify_state(struct intel_display *display)
|
||||
|
||||
void intel_display_power_suspend_late(struct intel_display *display, bool s2idle)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
intel_power_domains_suspend(display, s2idle);
|
||||
|
||||
if (DISPLAY_VER(display) >= 11 || display->platform.geminilake ||
|
||||
@@ -2241,14 +2263,12 @@ void intel_display_power_suspend_late(struct intel_display *display, bool s2idle
|
||||
}
|
||||
|
||||
/* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1)
|
||||
intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS);
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_CNP && INTEL_PCH_TYPE(display) < PCH_DG1)
|
||||
intel_de_rmw(display, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS);
|
||||
}
|
||||
|
||||
void intel_display_power_resume_early(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (DISPLAY_VER(display) >= 11 || display->platform.geminilake ||
|
||||
display->platform.broxton) {
|
||||
gen9_sanitize_dc_state(display);
|
||||
@@ -2258,8 +2278,8 @@ void intel_display_power_resume_early(struct intel_display *display)
|
||||
}
|
||||
|
||||
/* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1)
|
||||
intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_CNP && INTEL_PCH_TYPE(display) < PCH_DG1)
|
||||
intel_de_rmw(display, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);
|
||||
|
||||
intel_power_domains_resume(display);
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ void intel_display_power_suspend(struct intel_display *display);
|
||||
void intel_display_power_resume(struct intel_display *display);
|
||||
void intel_display_power_set_target_dc_state(struct intel_display *display,
|
||||
u32 state);
|
||||
u32 intel_display_power_get_current_dc_state(struct intel_display *display);
|
||||
|
||||
bool intel_display_power_is_enabled(struct intel_display *display,
|
||||
enum intel_display_power_domain domain);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_pcode.h"
|
||||
#include "intel_pps.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_tc.h"
|
||||
#include "intel_vga.h"
|
||||
#include "skl_watermark.h"
|
||||
@@ -760,6 +761,9 @@ void gen9_set_dc_state(struct intel_display *display, u32 state)
|
||||
state & ~power_domains->allowed_dc_mask))
|
||||
state &= power_domains->allowed_dc_mask;
|
||||
|
||||
if (!power_domains->initializing)
|
||||
intel_psr_notify_dc5_dc6(display);
|
||||
|
||||
val = intel_de_read(display, DC_STATE_EN);
|
||||
mask = gen9_dc_mask(display);
|
||||
drm_dbg_kms(display->drm, "Setting DC state from %02x to %02x\n",
|
||||
@@ -1208,7 +1212,6 @@ static void vlv_init_display_clock_gating(struct intel_display *display)
|
||||
|
||||
static void vlv_display_power_well_init(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_encoder *encoder;
|
||||
enum pipe pipe;
|
||||
|
||||
@@ -1232,9 +1235,7 @@ static void vlv_display_power_well_init(struct intel_display *display)
|
||||
|
||||
vlv_init_display_clock_gating(display);
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
valleyview_enable_display_irqs(display);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
|
||||
/*
|
||||
* During driver initialization/resume we can avoid restoring the
|
||||
@@ -1252,7 +1253,7 @@ static void vlv_display_power_well_init(struct intel_display *display)
|
||||
intel_crt_reset(&encoder->base);
|
||||
}
|
||||
|
||||
intel_vga_redisable_power_on(display);
|
||||
intel_vga_disable(display);
|
||||
|
||||
intel_pps_unlock_regs_wa(display);
|
||||
}
|
||||
@@ -1261,9 +1262,7 @@ static void vlv_display_power_well_deinit(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
valleyview_disable_display_irqs(display);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
|
||||
/* make sure we're done processing display irqs */
|
||||
intel_synchronize_irq(dev_priv);
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "gt/intel_rps.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_display_irq.h"
|
||||
#include "intel_display_rps.h"
|
||||
#include "intel_display_types.h"
|
||||
|
||||
@@ -81,3 +83,24 @@ void intel_display_rps_mark_interactive(struct intel_display *display,
|
||||
intel_rps_mark_interactive(&to_gt(i915)->rps, interactive);
|
||||
state->rps_interactive = interactive;
|
||||
}
|
||||
|
||||
void ilk_display_rps_enable(struct intel_display *display)
|
||||
{
|
||||
spin_lock(&display->irq.lock);
|
||||
ilk_enable_display_irq(display, DE_PCU_EVENT);
|
||||
spin_unlock(&display->irq.lock);
|
||||
}
|
||||
|
||||
void ilk_display_rps_disable(struct intel_display *display)
|
||||
{
|
||||
spin_lock(&display->irq.lock);
|
||||
ilk_disable_display_irq(display, DE_PCU_EVENT);
|
||||
spin_unlock(&display->irq.lock);
|
||||
}
|
||||
|
||||
void ilk_display_rps_irq_handler(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
gen5_rps_irq_handler(&to_gt(i915)->rps);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,34 @@ struct drm_crtc;
|
||||
struct intel_atomic_state;
|
||||
struct intel_display;
|
||||
|
||||
#ifdef I915
|
||||
void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc,
|
||||
struct dma_fence *fence);
|
||||
void intel_display_rps_mark_interactive(struct intel_display *display,
|
||||
struct intel_atomic_state *state,
|
||||
bool interactive);
|
||||
void ilk_display_rps_enable(struct intel_display *display);
|
||||
void ilk_display_rps_disable(struct intel_display *display);
|
||||
void ilk_display_rps_irq_handler(struct intel_display *display);
|
||||
#else
|
||||
static inline void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc,
|
||||
struct dma_fence *fence)
|
||||
{
|
||||
}
|
||||
static inline void intel_display_rps_mark_interactive(struct intel_display *display,
|
||||
struct intel_atomic_state *state,
|
||||
bool interactive)
|
||||
{
|
||||
}
|
||||
static inline void ilk_display_rps_enable(struct intel_display *display)
|
||||
{
|
||||
}
|
||||
static inline void ilk_display_rps_disable(struct intel_display *display)
|
||||
{
|
||||
}
|
||||
static inline void ilk_display_rps_irq_handler(struct intel_display *display)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INTEL_DISPLAY_RPS_H__ */
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_display_device.h"
|
||||
#include "intel_display_irq.h"
|
||||
#include "intel_display_params.h"
|
||||
#include "intel_display_snapshot.h"
|
||||
#include "intel_dmc.h"
|
||||
@@ -20,6 +21,7 @@ struct intel_display_snapshot {
|
||||
struct intel_display_params params;
|
||||
struct intel_overlay_snapshot *overlay;
|
||||
struct intel_dmc_snapshot *dmc;
|
||||
struct intel_display_irq_snapshot *irq;
|
||||
};
|
||||
|
||||
struct intel_display_snapshot *intel_display_snapshot_capture(struct intel_display *display)
|
||||
@@ -38,6 +40,7 @@ struct intel_display_snapshot *intel_display_snapshot_capture(struct intel_displ
|
||||
|
||||
intel_display_params_copy(&snapshot->params);
|
||||
|
||||
snapshot->irq = intel_display_irq_snapshot_capture(display);
|
||||
snapshot->overlay = intel_overlay_snapshot_capture(display);
|
||||
snapshot->dmc = intel_dmc_snapshot_capture(display);
|
||||
|
||||
@@ -57,6 +60,7 @@ void intel_display_snapshot_print(const struct intel_display_snapshot *snapshot,
|
||||
intel_display_device_info_print(&snapshot->info, &snapshot->runtime_info, p);
|
||||
intel_display_params_dump(&snapshot->params, display->drm->driver->name, p);
|
||||
|
||||
intel_display_irq_snapshot_print(snapshot->irq, p);
|
||||
intel_overlay_snapshot_print(snapshot->overlay, p);
|
||||
intel_dmc_snapshot_print(snapshot->dmc, p);
|
||||
}
|
||||
@@ -68,6 +72,7 @@ void intel_display_snapshot_free(struct intel_display_snapshot *snapshot)
|
||||
|
||||
intel_display_params_free(&snapshot->params);
|
||||
|
||||
kfree(snapshot->irq);
|
||||
kfree(snapshot->overlay);
|
||||
kfree(snapshot->dmc);
|
||||
kfree(snapshot);
|
||||
|
||||
@@ -1114,6 +1114,7 @@ struct intel_crtc_state {
|
||||
bool wm_level_disabled;
|
||||
u32 dc3co_exitline;
|
||||
u16 su_y_granularity;
|
||||
u8 active_non_psr_pipes;
|
||||
|
||||
/*
|
||||
* Frequency the dpll for the port should run at. Differs from the
|
||||
@@ -1387,7 +1388,7 @@ struct intel_crtc {
|
||||
/* armed event for DSB based updates */
|
||||
struct drm_pending_vblank_event *dsb_event;
|
||||
|
||||
/* Access to these should be protected by dev_priv->irq_lock. */
|
||||
/* Access to these should be protected by display->irq.lock. */
|
||||
bool cpu_fifo_underrun_disabled;
|
||||
bool pch_fifo_underrun_disabled;
|
||||
|
||||
@@ -1439,7 +1440,7 @@ struct intel_crtc {
|
||||
struct intel_pipe_crc pipe_crc;
|
||||
#endif
|
||||
|
||||
bool block_dc_for_vblank;
|
||||
bool vblank_psr_notify;
|
||||
};
|
||||
|
||||
struct intel_plane_error {
|
||||
@@ -1650,6 +1651,8 @@ struct intel_psr {
|
||||
u8 entry_setup_frames;
|
||||
|
||||
bool link_ok;
|
||||
|
||||
u8 active_non_psr_pipes;
|
||||
};
|
||||
|
||||
struct intel_dp {
|
||||
@@ -1805,12 +1808,16 @@ struct intel_dp {
|
||||
struct {
|
||||
u8 io_wake_lines;
|
||||
u8 fast_wake_lines;
|
||||
enum transcoder transcoder;
|
||||
struct mutex lock;
|
||||
|
||||
/* LNL and beyond */
|
||||
u8 check_entry_lines;
|
||||
u8 aux_less_wake_lines;
|
||||
u8 silence_period_sym_clocks;
|
||||
u8 lfps_half_cycle_num_of_syms;
|
||||
bool lobf_disable_debug;
|
||||
bool sink_alpm_error;
|
||||
} alpm_parameters;
|
||||
|
||||
u8 alpm_dpcd;
|
||||
|
||||
@@ -173,7 +173,6 @@ MODULE_FIRMWARE(BXT_DMC_PATH);
|
||||
|
||||
static const char *dmc_firmware_default(struct intel_display *display, u32 *size)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
const char *fw_path = NULL;
|
||||
u32 max_fw_size = 0;
|
||||
|
||||
@@ -189,39 +188,39 @@ static const char *dmc_firmware_default(struct intel_display *display, u32 *size
|
||||
} else if (DISPLAY_VERx100(display) == 1400) {
|
||||
fw_path = MTL_DMC_PATH;
|
||||
max_fw_size = XELPDP_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_DG2(i915)) {
|
||||
} else if (display->platform.dg2) {
|
||||
fw_path = DG2_DMC_PATH;
|
||||
max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_ALDERLAKE_P(i915)) {
|
||||
} else if (display->platform.alderlake_p) {
|
||||
fw_path = ADLP_DMC_PATH;
|
||||
max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_ALDERLAKE_S(i915)) {
|
||||
} else if (display->platform.alderlake_s) {
|
||||
fw_path = ADLS_DMC_PATH;
|
||||
max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_DG1(i915)) {
|
||||
} else if (display->platform.dg1) {
|
||||
fw_path = DG1_DMC_PATH;
|
||||
max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_ROCKETLAKE(i915)) {
|
||||
} else if (display->platform.rocketlake) {
|
||||
fw_path = RKL_DMC_PATH;
|
||||
max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_TIGERLAKE(i915)) {
|
||||
} else if (display->platform.tigerlake) {
|
||||
fw_path = TGL_DMC_PATH;
|
||||
max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
|
||||
} else if (DISPLAY_VER(display) == 11) {
|
||||
fw_path = ICL_DMC_PATH;
|
||||
max_fw_size = ICL_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_GEMINILAKE(i915)) {
|
||||
} else if (display->platform.geminilake) {
|
||||
fw_path = GLK_DMC_PATH;
|
||||
max_fw_size = GLK_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_KABYLAKE(i915) ||
|
||||
IS_COFFEELAKE(i915) ||
|
||||
IS_COMETLAKE(i915)) {
|
||||
} else if (display->platform.kabylake ||
|
||||
display->platform.coffeelake ||
|
||||
display->platform.cometlake) {
|
||||
fw_path = KBL_DMC_PATH;
|
||||
max_fw_size = KBL_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_SKYLAKE(i915)) {
|
||||
} else if (display->platform.skylake) {
|
||||
fw_path = SKL_DMC_PATH;
|
||||
max_fw_size = SKL_DMC_MAX_FW_SIZE;
|
||||
} else if (IS_BROXTON(i915)) {
|
||||
} else if (display->platform.broxton) {
|
||||
fw_path = BXT_DMC_PATH;
|
||||
max_fw_size = BXT_DMC_MAX_FW_SIZE;
|
||||
}
|
||||
@@ -517,6 +516,54 @@ void intel_dmc_disable_pipe(struct intel_display *display, enum pipe pipe)
|
||||
intel_de_rmw(display, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_dmc_block_pkgc() - block PKG C-state
|
||||
* @display: display instance
|
||||
* @pipe: pipe which register use to block
|
||||
* @block: block/unblock
|
||||
*
|
||||
* This interface is target for Wa_16025596647 usage. I.e. to set/clear
|
||||
* PIPEDMC_BLOCK_PKGC_SW_BLOCK_PKGC_ALWAYS bit in PIPEDMC_BLOCK_PKGC_SW register.
|
||||
*/
|
||||
void intel_dmc_block_pkgc(struct intel_display *display, enum pipe pipe,
|
||||
bool block)
|
||||
{
|
||||
intel_de_rmw(display, PIPEDMC_BLOCK_PKGC_SW(pipe),
|
||||
PIPEDMC_BLOCK_PKGC_SW_BLOCK_PKGC_ALWAYS, block ?
|
||||
PIPEDMC_BLOCK_PKGC_SW_BLOCK_PKGC_ALWAYS : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank() - start of PKG
|
||||
* C-state exit
|
||||
* @display: display instance
|
||||
* @pipe: pipe which register use to block
|
||||
* @enable: enable/disable
|
||||
*
|
||||
* This interface is target for Wa_16025596647 usage. I.e. start the package C
|
||||
* exit at the start of the undelayed vblank
|
||||
*/
|
||||
void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display *display,
|
||||
enum pipe pipe, bool enable)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (enable)
|
||||
val = DMC_EVT_CTL_ENABLE | DMC_EVT_CTL_RECURRING |
|
||||
REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK,
|
||||
DMC_EVT_CTL_TYPE_EDGE_0_1) |
|
||||
REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK,
|
||||
DMC_EVT_CTL_EVENT_ID_VBLANK_A);
|
||||
else
|
||||
val = REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK,
|
||||
DMC_EVT_CTL_EVENT_ID_FALSE) |
|
||||
REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK,
|
||||
DMC_EVT_CTL_TYPE_EDGE_0_1);
|
||||
|
||||
intel_de_write(display, MTL_PIPEDMC_EVT_CTL_4(pipe),
|
||||
val);
|
||||
}
|
||||
|
||||
static bool is_dmc_evt_ctl_reg(struct intel_display *display,
|
||||
enum intel_dmc_id dmc_id, i915_reg_t reg)
|
||||
{
|
||||
@@ -541,8 +588,6 @@ static bool disable_dmc_evt(struct intel_display *display,
|
||||
enum intel_dmc_id dmc_id,
|
||||
i915_reg_t reg, u32 data)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (!is_dmc_evt_ctl_reg(display, dmc_id, reg))
|
||||
return false;
|
||||
|
||||
@@ -551,12 +596,12 @@ static bool disable_dmc_evt(struct intel_display *display,
|
||||
return true;
|
||||
|
||||
/* also disable the flip queue event on the main DMC on TGL */
|
||||
if (IS_TIGERLAKE(i915) &&
|
||||
if (display->platform.tigerlake &&
|
||||
REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == DMC_EVT_CTL_EVENT_ID_CLK_MSEC)
|
||||
return true;
|
||||
|
||||
/* also disable the HRR event on the main DMC on TGL/ADLS */
|
||||
if ((IS_TIGERLAKE(i915) || IS_ALDERLAKE_S(i915)) &&
|
||||
if ((display->platform.tigerlake || display->platform.alderlake_s) &&
|
||||
REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == DMC_EVT_CTL_EVENT_ID_VBLANK_A)
|
||||
return true;
|
||||
|
||||
@@ -588,7 +633,6 @@ static u32 dmc_mmiodata(struct intel_display *display,
|
||||
*/
|
||||
void intel_dmc_load_program(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 __maybe_unused = to_i915(display->drm);
|
||||
struct i915_power_domains *power_domains = &display->power.domains;
|
||||
struct intel_dmc *dmc = display_to_dmc(display);
|
||||
enum intel_dmc_id dmc_id;
|
||||
@@ -1012,9 +1056,7 @@ static void intel_dmc_runtime_pm_put(struct intel_display *display)
|
||||
|
||||
static const char *dmc_fallback_path(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (IS_ALDERLAKE_P(i915))
|
||||
if (display->platform.alderlake_p)
|
||||
return ADLP_DMC_FALLBACK_PATH;
|
||||
|
||||
return NULL;
|
||||
@@ -1279,7 +1321,6 @@ static bool intel_dmc_get_dc6_allowed_count(struct intel_display *display, u32 *
|
||||
static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct intel_display *display = m->private;
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_dmc *dmc = display_to_dmc(display);
|
||||
struct ref_tracker *wakeref;
|
||||
i915_reg_t dc5_reg, dc6_reg = INVALID_MMIO_REG;
|
||||
@@ -1299,7 +1340,7 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
|
||||
seq_printf(m, "Pipe A fw loaded: %s\n",
|
||||
str_yes_no(has_dmc_id_fw(display, DMC_FW_PIPEA)));
|
||||
seq_printf(m, "Pipe B fw needed: %s\n",
|
||||
str_yes_no(IS_ALDERLAKE_P(i915) ||
|
||||
str_yes_no(display->platform.alderlake_p ||
|
||||
DISPLAY_VER(display) >= 14));
|
||||
seq_printf(m, "Pipe B fw loaded: %s\n",
|
||||
str_yes_no(has_dmc_id_fw(display, DMC_FW_PIPEB)));
|
||||
@@ -1313,7 +1354,7 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
|
||||
if (DISPLAY_VER(display) >= 12) {
|
||||
i915_reg_t dc3co_reg;
|
||||
|
||||
if (IS_DGFX(i915) || DISPLAY_VER(display) >= 14) {
|
||||
if (display->platform.dgfx || DISPLAY_VER(display) >= 14) {
|
||||
dc3co_reg = DG1_DMC_DEBUG3;
|
||||
dc5_reg = DG1_DMC_DEBUG_DC5_COUNT;
|
||||
} else {
|
||||
@@ -1325,9 +1366,9 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
|
||||
seq_printf(m, "DC3CO count: %d\n",
|
||||
intel_de_read(display, dc3co_reg));
|
||||
} else {
|
||||
dc5_reg = IS_BROXTON(i915) ? BXT_DMC_DC3_DC5_COUNT :
|
||||
dc5_reg = display->platform.broxton ? BXT_DMC_DC3_DC5_COUNT :
|
||||
SKL_DMC_DC3_DC5_COUNT;
|
||||
if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915))
|
||||
if (!display->platform.geminilake && !display->platform.broxton)
|
||||
dc6_reg = SKL_DMC_DC5_DC6_COUNT;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ void intel_dmc_load_program(struct intel_display *display);
|
||||
void intel_dmc_disable_program(struct intel_display *display);
|
||||
void intel_dmc_enable_pipe(struct intel_display *display, enum pipe pipe);
|
||||
void intel_dmc_disable_pipe(struct intel_display *display, enum pipe pipe);
|
||||
void intel_dmc_block_pkgc(struct intel_display *display, enum pipe pipe,
|
||||
bool block);
|
||||
void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display *display,
|
||||
enum pipe pipe, bool enable);
|
||||
void intel_dmc_fini(struct intel_display *display);
|
||||
void intel_dmc_suspend(struct intel_display *display);
|
||||
void intel_dmc_resume(struct intel_display *display);
|
||||
|
||||
@@ -21,6 +21,20 @@
|
||||
#define MTL_PIPEDMC_CONTROL _MMIO(0x45250)
|
||||
#define PIPEDMC_ENABLE_MTL(pipe) REG_BIT(((pipe) - PIPE_A) * 4)
|
||||
|
||||
#define _MTL_PIPEDMC_EVT_CTL_4_A 0x5f044
|
||||
#define _MTL_PIPEDMC_EVT_CTL_4_B 0x5f444
|
||||
#define MTL_PIPEDMC_EVT_CTL_4(pipe) _MMIO_PIPE(pipe, \
|
||||
_MTL_PIPEDMC_EVT_CTL_4_A, \
|
||||
_MTL_PIPEDMC_EVT_CTL_4_B)
|
||||
|
||||
#define PIPEDMC_BLOCK_PKGC_SW_A 0x5f1d0
|
||||
#define PIPEDMC_BLOCK_PKGC_SW_B 0x5F5d0
|
||||
#define PIPEDMC_BLOCK_PKGC_SW(pipe) _MMIO_PIPE(pipe, \
|
||||
PIPEDMC_BLOCK_PKGC_SW_A, \
|
||||
PIPEDMC_BLOCK_PKGC_SW_B)
|
||||
#define PIPEDMC_BLOCK_PKGC_SW_BLOCK_PKGC_ALWAYS BIT(31)
|
||||
#define PIPEDMC_BLOCK_PKGC_SW_BLOCK_PKGC_UNTIL_NEXT_FRAMESTART BIT(15)
|
||||
|
||||
#define _ADLP_PIPEDMC_REG_MMIO_BASE_A 0x5f000
|
||||
#define _TGL_PIPEDMC_REG_MMIO_BASE_A 0x92000
|
||||
|
||||
|
||||
@@ -45,12 +45,13 @@
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_fixed.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "g4x_dp.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_irq.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_alpm.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
@@ -58,6 +59,7 @@
|
||||
#include "intel_combo_phy_regs.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_crtc_state_dump.h"
|
||||
#include "intel_cx0_phy.h"
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_de.h"
|
||||
@@ -92,7 +94,6 @@
|
||||
#include "intel_tc.h"
|
||||
#include "intel_vdsc.h"
|
||||
#include "intel_vrr.h"
|
||||
#include "intel_crtc_state_dump.h"
|
||||
|
||||
/* DP DSC throughput values used for slice count calculations KPixels/s */
|
||||
#define DP_DSC_PEAK_PIXEL_RATE 2720000
|
||||
@@ -3104,6 +3105,76 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
|
||||
}
|
||||
}
|
||||
|
||||
int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
struct intel_connector *connector = to_intel_connector(conn_state->connector);
|
||||
int symbol_size = intel_dp_is_uhbr(crtc_state) ? 32 : 8;
|
||||
/*
|
||||
* min symbol cycles is 3(BS,VBID, BE) for 128b/132b and
|
||||
* 5(BS, VBID, MVID, MAUD, BE) for 8b/10b
|
||||
*/
|
||||
int min_sym_cycles = intel_dp_is_uhbr(crtc_state) ? 3 : 5;
|
||||
bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
|
||||
int num_joined_pipes = intel_crtc_num_joined_pipes(crtc_state);
|
||||
int min_hblank;
|
||||
int max_lane_count = 4;
|
||||
int hactive_sym_cycles, htotal_sym_cycles;
|
||||
int dsc_slices = 0;
|
||||
int link_bpp_x16;
|
||||
|
||||
if (DISPLAY_VER(display) < 30)
|
||||
return 0;
|
||||
|
||||
/* MIN_HBLANK should be set only for 8b/10b MST or for 128b/132b SST/MST */
|
||||
if (!is_mst && !intel_dp_is_uhbr(crtc_state))
|
||||
return 0;
|
||||
|
||||
if (crtc_state->dsc.compression_enable) {
|
||||
dsc_slices = intel_dp_dsc_get_slice_count(connector,
|
||||
adjusted_mode->crtc_clock,
|
||||
adjusted_mode->crtc_hdisplay,
|
||||
num_joined_pipes);
|
||||
if (!dsc_slices) {
|
||||
drm_dbg(display->drm, "failed to calculate dsc slice count\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (crtc_state->dsc.compression_enable)
|
||||
link_bpp_x16 = crtc_state->dsc.compressed_bpp_x16;
|
||||
else
|
||||
link_bpp_x16 = fxp_q4_from_int(intel_dp_output_bpp(crtc_state->output_format,
|
||||
crtc_state->pipe_bpp));
|
||||
|
||||
/* Calculate min Hblank Link Layer Symbol Cycle Count for 8b/10b MST & 128b/132b */
|
||||
hactive_sym_cycles = drm_dp_link_symbol_cycles(max_lane_count,
|
||||
adjusted_mode->hdisplay,
|
||||
dsc_slices,
|
||||
link_bpp_x16,
|
||||
symbol_size, is_mst);
|
||||
htotal_sym_cycles = adjusted_mode->htotal * hactive_sym_cycles /
|
||||
adjusted_mode->hdisplay;
|
||||
|
||||
min_hblank = htotal_sym_cycles - hactive_sym_cycles;
|
||||
/* minimum Hblank calculation: https://groups.vesa.org/wg/DP/document/20494 */
|
||||
min_hblank = max(min_hblank, min_sym_cycles);
|
||||
|
||||
/*
|
||||
* adjust the BlankingStart/BlankingEnd framing control from
|
||||
* the calculated value
|
||||
*/
|
||||
min_hblank = min_hblank - 2;
|
||||
|
||||
min_hblank = min(10, min_hblank);
|
||||
crtc_state->min_hblank = min_hblank;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
intel_dp_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
@@ -3203,6 +3274,10 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
||||
&pipe_config->dp_m_n);
|
||||
}
|
||||
|
||||
ret = intel_dp_compute_min_hblank(pipe_config, conn_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* FIXME: abstract this better */
|
||||
if (pipe_config->splitter.enable)
|
||||
pipe_config->dp_m_n.data_m *= pipe_config->splitter.link_count;
|
||||
@@ -5392,6 +5467,11 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
|
||||
|
||||
intel_psr_short_pulse(intel_dp);
|
||||
|
||||
if (intel_alpm_get_error(intel_dp)) {
|
||||
intel_alpm_disable(intel_dp);
|
||||
intel_dp->alpm_parameters.sink_alpm_error = true;
|
||||
}
|
||||
|
||||
if (intel_dp_test_short_pulse(intel_dp))
|
||||
reprobe_needed = true;
|
||||
|
||||
@@ -5827,20 +5907,21 @@ out_vdd_off:
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_force(struct drm_connector *connector)
|
||||
intel_dp_force(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
|
||||
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n",
|
||||
connector->base.id, connector->name);
|
||||
connector->base.base.id, connector->base.name);
|
||||
|
||||
if (!intel_display_driver_check_access(display))
|
||||
return;
|
||||
|
||||
intel_dp_unset_edid(intel_dp);
|
||||
|
||||
if (connector->status != connector_status_connected)
|
||||
if (connector->base.status != connector_status_connected)
|
||||
return;
|
||||
|
||||
intel_dp_set_edid(intel_dp);
|
||||
@@ -5879,24 +5960,25 @@ static int intel_dp_get_modes(struct drm_connector *_connector)
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_connector_register(struct drm_connector *connector)
|
||||
intel_dp_connector_register(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
int ret;
|
||||
|
||||
ret = intel_connector_register(connector);
|
||||
ret = intel_connector_register(&connector->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_dbg_kms(display->drm, "registering %s bus for %s\n",
|
||||
intel_dp->aux.name, connector->kdev->kobj.name);
|
||||
intel_dp->aux.name, connector->base.kdev->kobj.name);
|
||||
|
||||
intel_dp->aux.dev = connector->kdev;
|
||||
intel_dp->aux.dev = connector->base.kdev;
|
||||
ret = drm_dp_aux_register(&intel_dp->aux);
|
||||
if (!ret)
|
||||
drm_dp_cec_register_connector(&intel_dp->aux, connector);
|
||||
drm_dp_cec_register_connector(&intel_dp->aux, &connector->base);
|
||||
|
||||
if (!intel_bios_encoder_is_lspcon(dig_port->base.devdata))
|
||||
return ret;
|
||||
@@ -5907,20 +5989,21 @@ intel_dp_connector_register(struct drm_connector *connector)
|
||||
*/
|
||||
if (intel_lspcon_init(dig_port)) {
|
||||
if (intel_lspcon_detect_hdr_capability(dig_port))
|
||||
drm_connector_attach_hdr_output_metadata_property(connector);
|
||||
drm_connector_attach_hdr_output_metadata_property(&connector->base);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_connector_unregister(struct drm_connector *connector)
|
||||
intel_dp_connector_unregister(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
|
||||
drm_dp_cec_unregister_connector(&intel_dp->aux);
|
||||
drm_dp_aux_unregister(&intel_dp->aux);
|
||||
intel_connector_unregister(connector);
|
||||
intel_connector_unregister(&connector->base);
|
||||
}
|
||||
|
||||
void intel_dp_connector_sync_state(struct intel_connector *connector,
|
||||
@@ -5981,21 +6064,21 @@ static int intel_modeset_tile_group(struct intel_atomic_state *state,
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct drm_connector *connector;
|
||||
struct intel_connector *connector;
|
||||
int ret = 0;
|
||||
|
||||
drm_connector_list_iter_begin(display->drm, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
struct drm_connector_state *conn_state;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
if (!connector->has_tile ||
|
||||
connector->tile_group->id != tile_group_id)
|
||||
if (!connector->base.has_tile ||
|
||||
connector->base.tile_group->id != tile_group_id)
|
||||
continue;
|
||||
|
||||
conn_state = drm_atomic_get_connector_state(&state->base,
|
||||
connector);
|
||||
&connector->base);
|
||||
if (IS_ERR(conn_state)) {
|
||||
ret = PTR_ERR(conn_state);
|
||||
break;
|
||||
@@ -6059,10 +6142,11 @@ static int intel_modeset_affected_transcoders(struct intel_atomic_state *state,
|
||||
}
|
||||
|
||||
static int intel_modeset_synced_crtcs(struct intel_atomic_state *state,
|
||||
struct drm_connector *connector)
|
||||
struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
const struct drm_connector_state *old_conn_state =
|
||||
drm_atomic_get_old_connector_state(&state->base, connector);
|
||||
drm_atomic_get_old_connector_state(&state->base, &connector->base);
|
||||
const struct intel_crtc_state *old_crtc_state;
|
||||
struct intel_crtc *crtc;
|
||||
u8 transcoders;
|
||||
@@ -6084,17 +6168,18 @@ static int intel_modeset_synced_crtcs(struct intel_atomic_state *state,
|
||||
transcoders);
|
||||
}
|
||||
|
||||
static int intel_dp_connector_atomic_check(struct drm_connector *conn,
|
||||
static int intel_dp_connector_atomic_check(struct drm_connector *_connector,
|
||||
struct drm_atomic_state *_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(conn->dev);
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct intel_atomic_state *state = to_intel_atomic_state(_state);
|
||||
struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(_state, conn);
|
||||
struct intel_connector *intel_conn = to_intel_connector(conn);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(intel_conn->encoder);
|
||||
struct drm_connector_state *conn_state =
|
||||
drm_atomic_get_new_connector_state(_state, &connector->base);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
|
||||
int ret;
|
||||
|
||||
ret = intel_digital_connector_atomic_check(conn, &state->base);
|
||||
ret = intel_digital_connector_atomic_check(&connector->base, &state->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -6104,12 +6189,12 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!intel_connector_needs_modeset(state, conn))
|
||||
if (!intel_connector_needs_modeset(state, &connector->base))
|
||||
return 0;
|
||||
|
||||
ret = intel_dp_tunnel_atomic_check_state(state,
|
||||
intel_dp,
|
||||
intel_conn);
|
||||
connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -6120,26 +6205,26 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn,
|
||||
if (DISPLAY_VER(display) < 9)
|
||||
return 0;
|
||||
|
||||
if (conn->has_tile) {
|
||||
ret = intel_modeset_tile_group(state, conn->tile_group->id);
|
||||
if (connector->base.has_tile) {
|
||||
ret = intel_modeset_tile_group(state, connector->base.tile_group->id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return intel_modeset_synced_crtcs(state, conn);
|
||||
return intel_modeset_synced_crtcs(state, &connector->base);
|
||||
}
|
||||
|
||||
static void intel_dp_oob_hotplug_event(struct drm_connector *connector,
|
||||
static void intel_dp_oob_hotplug_event(struct drm_connector *_connector,
|
||||
enum drm_connector_status hpd_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
|
||||
struct drm_i915_private *i915 = to_i915(connector->dev);
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct intel_encoder *encoder = intel_attached_encoder(connector);
|
||||
bool hpd_high = hpd_state == connector_status_connected;
|
||||
unsigned int hpd_pin = encoder->hpd_pin;
|
||||
bool need_work = false;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
if (hpd_high != test_bit(hpd_pin, &display->hotplug.oob_hotplug_last_state)) {
|
||||
display->hotplug.event_bits |= BIT(hpd_pin);
|
||||
|
||||
@@ -6148,7 +6233,7 @@ static void intel_dp_oob_hotplug_event(struct drm_connector *connector,
|
||||
hpd_high);
|
||||
need_work = true;
|
||||
}
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
if (need_work)
|
||||
intel_hpd_schedule_detection(display);
|
||||
@@ -6280,36 +6365,37 @@ intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder)
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
|
||||
intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
enum port port = dp_to_dig_port(intel_dp)->base.port;
|
||||
|
||||
if (!intel_dp_is_edp(intel_dp))
|
||||
drm_connector_attach_dp_subconnector_property(connector);
|
||||
drm_connector_attach_dp_subconnector_property(&connector->base);
|
||||
|
||||
if (!display->platform.g4x && port != PORT_A)
|
||||
intel_attach_force_audio_property(connector);
|
||||
intel_attach_force_audio_property(&connector->base);
|
||||
|
||||
intel_attach_broadcast_rgb_property(connector);
|
||||
intel_attach_broadcast_rgb_property(&connector->base);
|
||||
if (HAS_GMCH(display))
|
||||
drm_connector_attach_max_bpc_property(connector, 6, 10);
|
||||
drm_connector_attach_max_bpc_property(&connector->base, 6, 10);
|
||||
else if (DISPLAY_VER(display) >= 5)
|
||||
drm_connector_attach_max_bpc_property(connector, 6, 12);
|
||||
drm_connector_attach_max_bpc_property(&connector->base, 6, 12);
|
||||
|
||||
/* Register HDMI colorspace for case of lspcon */
|
||||
if (intel_bios_encoder_is_lspcon(dp_to_dig_port(intel_dp)->base.devdata)) {
|
||||
drm_connector_attach_content_type_property(connector);
|
||||
intel_attach_hdmi_colorspace_property(connector);
|
||||
drm_connector_attach_content_type_property(&connector->base);
|
||||
intel_attach_hdmi_colorspace_property(&connector->base);
|
||||
} else {
|
||||
intel_attach_dp_colorspace_property(connector);
|
||||
intel_attach_dp_colorspace_property(&connector->base);
|
||||
}
|
||||
|
||||
if (intel_dp_has_gamut_metadata_dip(&dp_to_dig_port(intel_dp)->base))
|
||||
drm_connector_attach_hdr_output_metadata_property(connector);
|
||||
drm_connector_attach_hdr_output_metadata_property(&connector->base);
|
||||
|
||||
if (HAS_VRR(display))
|
||||
drm_connector_attach_vrr_capable_property(connector);
|
||||
drm_connector_attach_vrr_capable_property(&connector->base);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -6344,7 +6430,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
struct intel_connector *connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct drm_display_mode *fixed_mode;
|
||||
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
|
||||
bool has_dpcd;
|
||||
@@ -6361,7 +6446,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
*/
|
||||
if (intel_get_lvds_encoder(display)) {
|
||||
drm_WARN_ON(display->drm,
|
||||
!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
|
||||
!(HAS_PCH_IBX(display) || HAS_PCH_CPT(display)));
|
||||
drm_info(display->drm,
|
||||
"LVDS was detected, not registering eDP\n");
|
||||
|
||||
@@ -6392,7 +6477,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
*/
|
||||
intel_hpd_enable_detection(encoder);
|
||||
|
||||
intel_alpm_init_dpcd(intel_dp);
|
||||
intel_alpm_init(intel_dp);
|
||||
|
||||
/* Cache DPCD and EDID for edp. */
|
||||
has_dpcd = intel_edp_init_dpcd(intel_dp, connector);
|
||||
|
||||
@@ -208,5 +208,7 @@ bool intel_dp_has_connector(struct intel_dp *intel_dp,
|
||||
const struct drm_connector_state *conn_state);
|
||||
int intel_dp_dsc_max_src_input_bpc(struct intel_display *display);
|
||||
int intel_dp_dsc_min_src_input_bpc(void);
|
||||
int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
|
||||
#endif /* __INTEL_DP_H__ */
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
* Copyright © 2020-2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dp.h"
|
||||
@@ -111,10 +113,9 @@ static u32 ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
|
||||
static u32 hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
|
||||
if (dig_port->aux_ch != AUX_CH_A && HAS_PCH_LPT_H(i915)) {
|
||||
if (dig_port->aux_ch != AUX_CH_A && HAS_PCH_LPT_H(display)) {
|
||||
/* Workaround for non-ULT HSW */
|
||||
switch (index) {
|
||||
case 0: return 63;
|
||||
@@ -177,12 +178,11 @@ static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
|
||||
int send_bytes,
|
||||
u32 aux_clock_divider)
|
||||
{
|
||||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
u32 timeout;
|
||||
|
||||
/* Max timeout value on G4x-BDW: 1.6ms */
|
||||
if (IS_BROADWELL(i915))
|
||||
if (display->platform.broadwell)
|
||||
timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
|
||||
else
|
||||
timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
|
||||
@@ -786,7 +786,6 @@ void intel_dp_aux_fini(struct intel_dp *intel_dp)
|
||||
void intel_dp_aux_init(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
struct intel_encoder *encoder = &dig_port->base;
|
||||
enum aux_ch aux_ch = dig_port->aux_ch;
|
||||
@@ -801,10 +800,10 @@ void intel_dp_aux_init(struct intel_dp *intel_dp)
|
||||
} else if (DISPLAY_VER(display) >= 9) {
|
||||
intel_dp->aux_ch_ctl_reg = skl_aux_ctl_reg;
|
||||
intel_dp->aux_ch_data_reg = skl_aux_data_reg;
|
||||
} else if (HAS_PCH_SPLIT(i915)) {
|
||||
} else if (HAS_PCH_SPLIT(display)) {
|
||||
intel_dp->aux_ch_ctl_reg = ilk_aux_ctl_reg;
|
||||
intel_dp->aux_ch_data_reg = ilk_aux_data_reg;
|
||||
} else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
|
||||
} else if (display->platform.valleyview || display->platform.cherryview) {
|
||||
intel_dp->aux_ch_ctl_reg = vlv_aux_ctl_reg;
|
||||
intel_dp->aux_ch_data_reg = vlv_aux_data_reg;
|
||||
} else {
|
||||
@@ -814,9 +813,9 @@ void intel_dp_aux_init(struct intel_dp *intel_dp)
|
||||
|
||||
if (DISPLAY_VER(display) >= 9)
|
||||
intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
|
||||
else if (IS_BROADWELL(i915) || IS_HASWELL(i915))
|
||||
else if (display->platform.broadwell || display->platform.haswell)
|
||||
intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
|
||||
else if (HAS_PCH_SPLIT(i915))
|
||||
else if (HAS_PCH_SPLIT(display))
|
||||
intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
|
||||
else
|
||||
intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_utils.h"
|
||||
#include "intel_backlight.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_display_types.h"
|
||||
@@ -149,7 +148,7 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector)
|
||||
!(connector->base.hdr_sink_metadata.hdmi_type1.metadata_type &
|
||||
BIT(HDMI_STATIC_METADATA_TYPE1))) {
|
||||
drm_info(display->drm,
|
||||
"[CONNECTOR:%d:%s] Panel is missing HDR static metadata. Possible support for Intel HDR backlight interface is not used. If your backlight controls don't work try booting with i915.enable_dpcd_backlight=%d. needs this, please file a _new_ bug report on drm/i915, see " FDO_BUG_URL " for details.\n",
|
||||
"[CONNECTOR:%d:%s] Panel is missing HDR static metadata. Possible support for Intel HDR backlight interface is not used. If your backlight controls don't work try booting with i915.enable_dpcd_backlight=%d.\n",
|
||||
connector->base.base.id, connector->base.name,
|
||||
INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL);
|
||||
return false;
|
||||
|
||||
@@ -27,10 +27,11 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_fixed.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_connector.h"
|
||||
@@ -51,6 +52,7 @@
|
||||
#include "intel_link_bw.h"
|
||||
#include "intel_pfit.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_step.h"
|
||||
#include "intel_vdsc.h"
|
||||
#include "intel_vrr.h"
|
||||
#include "skl_scaler.h"
|
||||
@@ -239,26 +241,6 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec
|
||||
num_joined_pipes);
|
||||
}
|
||||
|
||||
static void intel_dp_mst_compute_min_hblank(struct intel_crtc_state *crtc_state,
|
||||
int bpp_x16)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
int symbol_size = intel_dp_is_uhbr(crtc_state) ? 32 : 8;
|
||||
int hblank;
|
||||
|
||||
if (DISPLAY_VER(display) < 20)
|
||||
return;
|
||||
|
||||
/* Calculate min Hblank Link Layer Symbol Cycle Count for 8b/10b MST & 128b/132b */
|
||||
hblank = DIV_ROUND_UP((DIV_ROUND_UP
|
||||
(adjusted_mode->htotal - adjusted_mode->hdisplay, 4) * bpp_x16),
|
||||
symbol_size);
|
||||
|
||||
crtc_state->min_hblank = hblank;
|
||||
}
|
||||
|
||||
int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state,
|
||||
@@ -329,8 +311,6 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
|
||||
local_bw_overhead = intel_dp_mst_bw_overhead(crtc_state,
|
||||
false, dsc_slice_count, link_bpp_x16);
|
||||
|
||||
intel_dp_mst_compute_min_hblank(crtc_state, link_bpp_x16);
|
||||
|
||||
intel_dp_mst_compute_m_n(crtc_state,
|
||||
local_bw_overhead,
|
||||
link_bpp_x16,
|
||||
@@ -739,6 +719,10 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
|
||||
pipe_config->lane_lat_optim_mask =
|
||||
bxt_dpio_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
|
||||
|
||||
ret = intel_dp_compute_min_hblank(pipe_config, conn_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
intel_vrr_compute_config(pipe_config, conn_state);
|
||||
|
||||
intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
|
||||
@@ -1021,12 +1005,10 @@ static void mst_stream_disable(struct intel_atomic_state *state,
|
||||
const struct intel_crtc_state *old_crtc_state,
|
||||
const struct drm_connector_state *old_conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
|
||||
struct intel_dp *intel_dp = to_primary_dp(encoder);
|
||||
struct intel_connector *connector =
|
||||
to_intel_connector(old_conn_state->connector);
|
||||
enum transcoder trans = old_crtc_state->cpu_transcoder;
|
||||
|
||||
if (intel_dp_mst_active_streams(intel_dp) == 1)
|
||||
intel_dp->link.active = false;
|
||||
@@ -1034,9 +1016,6 @@ static void mst_stream_disable(struct intel_atomic_state *state,
|
||||
intel_hdcp_disable(intel_mst->connector);
|
||||
|
||||
intel_dp_sink_disable_decompression(state, connector, old_crtc_state);
|
||||
|
||||
if (DISPLAY_VER(display) >= 20)
|
||||
intel_de_write(display, DP_MIN_HBLANK_CTL(trans), 0);
|
||||
}
|
||||
|
||||
static void mst_stream_post_disable(struct intel_atomic_state *state,
|
||||
@@ -1305,7 +1284,7 @@ static void mst_stream_enable(struct intel_atomic_state *state,
|
||||
enum transcoder trans = pipe_config->cpu_transcoder;
|
||||
bool first_mst_stream = intel_dp_mst_active_streams(intel_dp) == 1;
|
||||
struct intel_crtc *pipe_crtc;
|
||||
int ret, i, min_hblank;
|
||||
int ret, i;
|
||||
|
||||
drm_WARN_ON(display->drm, pipe_config->has_pch_encoder);
|
||||
|
||||
@@ -1320,29 +1299,6 @@ static void mst_stream_enable(struct intel_atomic_state *state,
|
||||
TRANS_DP2_VFREQ_PIXEL_CLOCK(crtc_clock_hz & 0xffffff));
|
||||
}
|
||||
|
||||
if (DISPLAY_VER(display) >= 20) {
|
||||
/*
|
||||
* adjust the BlankingStart/BlankingEnd framing control from
|
||||
* the calculated value
|
||||
*/
|
||||
min_hblank = pipe_config->min_hblank - 2;
|
||||
|
||||
/* Maximum value to be programmed is limited to 0x10 */
|
||||
min_hblank = min(0x10, min_hblank);
|
||||
|
||||
/*
|
||||
* Minimum hblank accepted for 128b/132b would be 5 and for
|
||||
* 8b/10b would be 3 symbol count
|
||||
*/
|
||||
if (intel_dp_is_uhbr(pipe_config))
|
||||
min_hblank = max(min_hblank, 5);
|
||||
else
|
||||
min_hblank = max(min_hblank, 3);
|
||||
|
||||
intel_de_write(display, DP_MIN_HBLANK_CTL(trans),
|
||||
min_hblank);
|
||||
}
|
||||
|
||||
enable_bs_jitter_was(pipe_config);
|
||||
|
||||
intel_ddi_enable_transcoder_func(encoder, pipe_config);
|
||||
|
||||
@@ -222,9 +222,7 @@ static const struct bxt_dpio_phy_info glk_dpio_phy_info[] = {
|
||||
static const struct bxt_dpio_phy_info *
|
||||
bxt_get_phy_list(struct intel_display *display, int *count)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (IS_GEMINILAKE(dev_priv)) {
|
||||
if (display->platform.geminilake) {
|
||||
*count = ARRAY_SIZE(glk_dpio_phy_info);
|
||||
return glk_dpio_phy_info;
|
||||
} else {
|
||||
@@ -808,9 +806,9 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder,
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void chv_data_lane_soft_reset(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
bool reset)
|
||||
static void __chv_data_lane_soft_reset(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
bool reset)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
|
||||
@@ -853,6 +851,17 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder,
|
||||
}
|
||||
}
|
||||
|
||||
void chv_data_lane_soft_reset(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
bool reset)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
|
||||
vlv_dpio_get(i915);
|
||||
__chv_data_lane_soft_reset(encoder, crtc_state, reset);
|
||||
vlv_dpio_put(i915);
|
||||
}
|
||||
|
||||
void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
@@ -880,7 +889,7 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Assert data lane reset */
|
||||
chv_data_lane_soft_reset(encoder, crtc_state, true);
|
||||
__chv_data_lane_soft_reset(encoder, crtc_state, true);
|
||||
|
||||
/* program left/right clock distribution */
|
||||
if (pipe != PIPE_B) {
|
||||
@@ -1008,7 +1017,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
}
|
||||
|
||||
/* Deassert data lane reset */
|
||||
chv_data_lane_soft_reset(encoder, crtc_state, false);
|
||||
__chv_data_lane_soft_reset(encoder, crtc_state, false);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
@@ -374,12 +374,11 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock)
|
||||
static int i9xx_pll_refclk(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx;
|
||||
|
||||
if ((hw_state->dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
|
||||
return display->vbt.lvds_ssc_freq;
|
||||
else if (HAS_PCH_SPLIT(i915))
|
||||
else if (HAS_PCH_SPLIT(display))
|
||||
return 120000;
|
||||
else if (DISPLAY_VER(display) != 2)
|
||||
return 96000;
|
||||
@@ -1235,12 +1234,10 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state,
|
||||
static int ilk_fb_cb_factor(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
|
||||
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
|
||||
((intel_panel_use_ssc(display) && display->vbt.lvds_ssc_freq == 100000) ||
|
||||
(HAS_PCH_IBX(i915) && intel_is_dual_link_lvds(display))))
|
||||
(HAS_PCH_IBX(display) && intel_is_dual_link_lvds(display))))
|
||||
return 25;
|
||||
|
||||
if (crtc_state->sdvo_tv_clock)
|
||||
@@ -1791,15 +1788,13 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state,
|
||||
void
|
||||
intel_dpll_init_clock_hook(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (DISPLAY_VER(display) >= 14)
|
||||
display->funcs.dpll = &mtl_dpll_funcs;
|
||||
else if (display->platform.dg2)
|
||||
display->funcs.dpll = &dg2_dpll_funcs;
|
||||
else if (DISPLAY_VER(display) >= 9 || HAS_DDI(display))
|
||||
display->funcs.dpll = &hsw_dpll_funcs;
|
||||
else if (HAS_PCH_SPLIT(dev_priv))
|
||||
else if (HAS_PCH_SPLIT(display))
|
||||
display->funcs.dpll = &ilk_dpll_funcs;
|
||||
else if (display->platform.cherryview)
|
||||
display->funcs.dpll = &chv_dpll_funcs;
|
||||
|
||||
@@ -24,9 +24,11 @@
|
||||
#include <linux/math.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "bxt_dpio_phy_regs.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_cx0_phy.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
@@ -38,6 +40,7 @@
|
||||
#include "intel_hti.h"
|
||||
#include "intel_mg_phy_regs.h"
|
||||
#include "intel_pch_refclk.h"
|
||||
#include "intel_step.h"
|
||||
#include "intel_tc.h"
|
||||
|
||||
/**
|
||||
@@ -609,13 +612,12 @@ static int ibx_get_dpll(struct intel_atomic_state *state,
|
||||
struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_crtc_state *crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
struct intel_shared_dpll *pll;
|
||||
enum intel_dpll_id id;
|
||||
|
||||
if (HAS_PCH_IBX(i915)) {
|
||||
if (HAS_PCH_IBX(display)) {
|
||||
/* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
|
||||
id = (enum intel_dpll_id) crtc->pipe;
|
||||
pll = intel_get_shared_dpll_by_id(display, id);
|
||||
@@ -4305,7 +4307,6 @@ static const struct intel_dpll_mgr adlp_pll_mgr = {
|
||||
*/
|
||||
void intel_shared_dpll_init(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
const struct intel_dpll_mgr *dpll_mgr = NULL;
|
||||
const struct dpll_info *dpll_info;
|
||||
int i;
|
||||
@@ -4335,7 +4336,7 @@ void intel_shared_dpll_init(struct intel_display *display)
|
||||
dpll_mgr = &skl_pll_mgr;
|
||||
else if (HAS_DDI(display))
|
||||
dpll_mgr = &hsw_pll_mgr;
|
||||
else if (HAS_PCH_IBX(i915) || HAS_PCH_CPT(i915))
|
||||
else if (HAS_PCH_IBX(display) || HAS_PCH_CPT(display))
|
||||
dpll_mgr = &pch_pll_mgr;
|
||||
|
||||
if (!dpll_mgr)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
@@ -12,9 +11,9 @@
|
||||
|
||||
void intel_dpt_configure(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
|
||||
if (DISPLAY_VER(i915) == 14) {
|
||||
if (DISPLAY_VER(display) == 14) {
|
||||
enum pipe pipe = crtc->pipe;
|
||||
enum plane_id plane_id;
|
||||
|
||||
@@ -22,15 +21,15 @@ void intel_dpt_configure(struct intel_crtc *crtc)
|
||||
if (plane_id == PLANE_CURSOR)
|
||||
continue;
|
||||
|
||||
intel_de_rmw(i915, PLANE_CHICKEN(pipe, plane_id),
|
||||
intel_de_rmw(display, PLANE_CHICKEN(pipe, plane_id),
|
||||
PLANE_CHICKEN_DISABLE_DPT,
|
||||
i915->display.params.enable_dpt ? 0 :
|
||||
display->params.enable_dpt ? 0 :
|
||||
PLANE_CHICKEN_DISABLE_DPT);
|
||||
}
|
||||
} else if (DISPLAY_VER(i915) == 13) {
|
||||
intel_de_rmw(i915, CHICKEN_MISC_2,
|
||||
} else if (DISPLAY_VER(display) == 13) {
|
||||
intel_de_rmw(display, CHICKEN_MISC_2,
|
||||
CHICKEN_MISC_DISABLE_DPT,
|
||||
i915->display.params.enable_dpt ? 0 :
|
||||
display->params.enable_dpt ? 0 :
|
||||
CHICKEN_MISC_DISABLE_DPT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_irq.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_rpm.h"
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
*/
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_panel.h"
|
||||
|
||||
@@ -116,14 +117,14 @@ struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
|
||||
enum drm_panel_orientation
|
||||
intel_dsi_get_panel_orientation(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
enum drm_panel_orientation orientation;
|
||||
|
||||
orientation = connector->panel.vbt.dsi.orientation;
|
||||
if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
|
||||
return orientation;
|
||||
|
||||
orientation = dev_priv->display.vbt.orientation;
|
||||
orientation = display->vbt.orientation;
|
||||
if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
|
||||
return orientation;
|
||||
|
||||
|
||||
@@ -31,16 +31,16 @@
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dsi.h"
|
||||
@@ -321,7 +321,6 @@ enum {
|
||||
static void icl_native_gpio_set_value(struct intel_display *display,
|
||||
int gpio, bool value)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
int index;
|
||||
|
||||
if (drm_WARN_ON(display->drm, DISPLAY_VER(display) == 11 && gpio >= MIPI_RESET_2))
|
||||
@@ -341,12 +340,12 @@ static void icl_native_gpio_set_value(struct intel_display *display,
|
||||
* The locking protects against concurrent SHOTPLUG_CTL_DDI
|
||||
* modifications in irq setup and handling.
|
||||
*/
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
intel_de_rmw(display, SHOTPLUG_CTL_DDI,
|
||||
SHOTPLUG_CTL_DDI_HPD_ENABLE(index) |
|
||||
SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index),
|
||||
value ? SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index) : 0);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
break;
|
||||
case MIPI_AVDD_EN_1:
|
||||
case MIPI_AVDD_EN_2:
|
||||
|
||||
@@ -560,11 +560,11 @@ static bool plane_has_modifier(struct intel_display *display,
|
||||
return false;
|
||||
|
||||
if (md->modifier == I915_FORMAT_MOD_4_TILED_BMG_CCS &&
|
||||
(GRAPHICS_VER(i915) < 20 || !IS_DGFX(i915)))
|
||||
(GRAPHICS_VER(i915) < 20 || !display->platform.dgfx))
|
||||
return false;
|
||||
|
||||
if (md->modifier == I915_FORMAT_MOD_4_TILED_LNL_CCS &&
|
||||
(GRAPHICS_VER(i915) < 20 || IS_DGFX(i915)))
|
||||
(GRAPHICS_VER(i915) < 20 || display->platform.dgfx))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -252,9 +252,12 @@ static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_s
|
||||
* Gen9 hw miscalculates cfb stride for linear as
|
||||
* PLANE_STRIDE*512 instead of PLANE_STRIDE*64, so
|
||||
* we always need to use the override there.
|
||||
*
|
||||
* wa_14022269668 For bmg, always program the FBC_STRIDE before fbc enable
|
||||
*/
|
||||
if (stride != stride_aligned ||
|
||||
(DISPLAY_VER(display) == 9 && fb->modifier == DRM_FORMAT_MOD_LINEAR))
|
||||
(DISPLAY_VER(display) == 9 && fb->modifier == DRM_FORMAT_MOD_LINEAR) ||
|
||||
display->platform.battlemage)
|
||||
return stride_aligned * 4 / 64;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_vma.h"
|
||||
#include "intel_bo.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_display_rpm.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fb.h"
|
||||
@@ -66,9 +66,9 @@ struct intel_fbdev {
|
||||
|
||||
static struct intel_fbdev *to_intel_fbdev(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(fb_helper->client.dev);
|
||||
struct intel_display *display = to_intel_display(fb_helper->client.dev);
|
||||
|
||||
return i915->display.fbdev.fbdev;
|
||||
return display->fbdev.fbdev;
|
||||
}
|
||||
|
||||
static struct intel_frontbuffer *to_frontbuffer(struct intel_fbdev *ifbdev)
|
||||
@@ -210,11 +210,9 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
|
||||
int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(helper->dev);
|
||||
struct intel_fbdev *ifbdev = to_intel_fbdev(helper);
|
||||
struct intel_framebuffer *fb = ifbdev->fb;
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_display *display = to_intel_display(dev);
|
||||
struct ref_tracker *wakeref;
|
||||
struct fb_info *info;
|
||||
struct i915_vma *vma;
|
||||
@@ -228,7 +226,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
if (fb &&
|
||||
(sizes->fb_width > fb->base.width ||
|
||||
sizes->fb_height > fb->base.height)) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"BIOS fb too small (%dx%d), we require (%dx%d),"
|
||||
" releasing it\n",
|
||||
fb->base.width, fb->base.height,
|
||||
@@ -236,14 +234,14 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
drm_framebuffer_put(&fb->base);
|
||||
fb = NULL;
|
||||
}
|
||||
if (!fb || drm_WARN_ON(dev, !intel_fb_bo(&fb->base))) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
if (!fb || drm_WARN_ON(display->drm, !intel_fb_bo(&fb->base))) {
|
||||
drm_dbg_kms(display->drm,
|
||||
"no BIOS fb, allocating a new one\n");
|
||||
fb = intel_fbdev_fb_alloc(helper, sizes);
|
||||
if (IS_ERR(fb))
|
||||
return PTR_ERR(fb);
|
||||
} else {
|
||||
drm_dbg_kms(&dev_priv->drm, "re-using BIOS fb\n");
|
||||
drm_dbg_kms(display->drm, "re-using BIOS fb\n");
|
||||
prealloc = true;
|
||||
sizes->fb_width = fb->base.width;
|
||||
sizes->fb_height = fb->base.height;
|
||||
@@ -267,7 +265,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
|
||||
info = drm_fb_helper_alloc_info(helper);
|
||||
if (IS_ERR(info)) {
|
||||
drm_err(&dev_priv->drm, "Failed to allocate fb_info (%pe)\n", info);
|
||||
drm_err(display->drm, "Failed to allocate fb_info (%pe)\n", info);
|
||||
ret = PTR_ERR(info);
|
||||
goto out_unpin;
|
||||
}
|
||||
@@ -279,11 +277,11 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
|
||||
obj = intel_fb_bo(&fb->base);
|
||||
|
||||
ret = intel_fbdev_fb_fill_info(dev_priv, info, obj, vma);
|
||||
ret = intel_fbdev_fb_fill_info(display, info, obj, vma);
|
||||
if (ret)
|
||||
goto out_unpin;
|
||||
|
||||
drm_fb_helper_fill_info(info, dev->fb_helper, sizes);
|
||||
drm_fb_helper_fill_info(info, display->drm->fb_helper, sizes);
|
||||
|
||||
/* If the object is shmemfs backed, it will have given us zeroed pages.
|
||||
* If the object is stolen however, it will be full of whatever
|
||||
@@ -294,7 +292,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
|
||||
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "allocated %dx%d fb: 0x%08x\n",
|
||||
drm_dbg_kms(display->drm, "allocated %dx%d fb: 0x%08x\n",
|
||||
fb->base.width, fb->base.height,
|
||||
i915_ggtt_offset(vma));
|
||||
ifbdev->fb = fb;
|
||||
@@ -322,16 +320,15 @@ out_unlock:
|
||||
* Note we only support a single fb shared across pipes for boot (mostly for
|
||||
* fbcon), so we just find the biggest and use that.
|
||||
*/
|
||||
static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
static bool intel_fbdev_init_bios(struct intel_display *display,
|
||||
struct intel_fbdev *ifbdev)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dev);
|
||||
struct intel_framebuffer *fb = NULL;
|
||||
struct intel_crtc *crtc;
|
||||
unsigned int max_size = 0;
|
||||
|
||||
/* Find the largest fb */
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
struct intel_plane *plane =
|
||||
@@ -341,21 +338,21 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
struct drm_gem_object *obj = intel_fb_bo(plane_state->uapi.fb);
|
||||
|
||||
if (!crtc_state->uapi.active) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[CRTC:%d:%s] not active, skipping\n",
|
||||
crtc->base.base.id, crtc->base.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!obj) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[PLANE:%d:%s] no fb, skipping\n",
|
||||
plane->base.base.id, plane->base.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (obj->size > max_size) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"found possible fb from [PLANE:%d:%s]\n",
|
||||
plane->base.base.id, plane->base.name);
|
||||
fb = to_intel_framebuffer(plane_state->uapi.fb);
|
||||
@@ -364,13 +361,13 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"no active fbs found, not using BIOS config\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Now make sure all the pipes will fit into it */
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
struct intel_plane *plane =
|
||||
@@ -378,13 +375,13 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
unsigned int cur_size;
|
||||
|
||||
if (!crtc_state->uapi.active) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[CRTC:%d:%s] not active, skipping\n",
|
||||
crtc->base.base.id, crtc->base.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
drm_dbg_kms(&i915->drm, "checking [PLANE:%d:%s] for BIOS fb\n",
|
||||
drm_dbg_kms(display->drm, "checking [PLANE:%d:%s] for BIOS fb\n",
|
||||
plane->base.base.id, plane->base.name);
|
||||
|
||||
/*
|
||||
@@ -395,7 +392,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
cur_size = crtc_state->uapi.adjusted_mode.crtc_hdisplay;
|
||||
cur_size = cur_size * fb->base.format->cpp[0];
|
||||
if (fb->base.pitches[0] < cur_size) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"fb not wide enough for [PLANE:%d:%s] (%d vs %d)\n",
|
||||
plane->base.base.id, plane->base.name,
|
||||
cur_size, fb->base.pitches[0]);
|
||||
@@ -406,7 +403,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
cur_size = crtc_state->uapi.adjusted_mode.crtc_vdisplay;
|
||||
cur_size = intel_fb_align_height(&fb->base, 0, cur_size);
|
||||
cur_size *= fb->base.pitches[0];
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n",
|
||||
crtc->base.base.id, crtc->base.name,
|
||||
crtc_state->uapi.adjusted_mode.crtc_hdisplay,
|
||||
@@ -415,7 +412,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
cur_size);
|
||||
|
||||
if (cur_size > max_size) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"fb not big enough for [PLANE:%d:%s] (%d vs %d)\n",
|
||||
plane->base.base.id, plane->base.name,
|
||||
cur_size, max_size);
|
||||
@@ -423,14 +420,14 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
break;
|
||||
}
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"fb big enough [PLANE:%d:%s] (%d >= %d)\n",
|
||||
plane->base.base.id, plane->base.name,
|
||||
max_size, cur_size);
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"BIOS fb not suitable for all pipes, not using\n");
|
||||
goto out;
|
||||
}
|
||||
@@ -440,7 +437,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
drm_framebuffer_get(&ifbdev->fb->base);
|
||||
|
||||
/* Final pass to check if any active pipes don't have fbs */
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
struct intel_plane *plane =
|
||||
@@ -451,13 +448,13 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
if (!crtc_state->uapi.active)
|
||||
continue;
|
||||
|
||||
drm_WARN(dev, !plane_state->uapi.fb,
|
||||
drm_WARN(display->drm, !plane_state->uapi.fb,
|
||||
"re-used BIOS config but lost an fb on [PLANE:%d:%s]\n",
|
||||
plane->base.base.id, plane->base.name);
|
||||
}
|
||||
|
||||
|
||||
drm_dbg_kms(&i915->drm, "using BIOS fb for initial console\n");
|
||||
drm_dbg_kms(display->drm, "using BIOS fb for initial console\n");
|
||||
return true;
|
||||
|
||||
out:
|
||||
@@ -482,26 +479,25 @@ static unsigned int intel_fbdev_color_mode(const struct drm_format_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
void intel_fbdev_setup(struct drm_i915_private *i915)
|
||||
void intel_fbdev_setup(struct intel_display *display)
|
||||
{
|
||||
struct drm_device *dev = &i915->drm;
|
||||
struct intel_fbdev *ifbdev;
|
||||
unsigned int preferred_bpp = 0;
|
||||
|
||||
if (!HAS_DISPLAY(i915))
|
||||
if (!HAS_DISPLAY(display))
|
||||
return;
|
||||
|
||||
ifbdev = drmm_kzalloc(dev, sizeof(*ifbdev), GFP_KERNEL);
|
||||
ifbdev = drmm_kzalloc(display->drm, sizeof(*ifbdev), GFP_KERNEL);
|
||||
if (!ifbdev)
|
||||
return;
|
||||
|
||||
i915->display.fbdev.fbdev = ifbdev;
|
||||
if (intel_fbdev_init_bios(dev, ifbdev))
|
||||
display->fbdev.fbdev = ifbdev;
|
||||
if (intel_fbdev_init_bios(display, ifbdev))
|
||||
preferred_bpp = intel_fbdev_color_mode(ifbdev->fb->base.format);
|
||||
if (!preferred_bpp)
|
||||
preferred_bpp = 32;
|
||||
|
||||
drm_client_setup_with_color_mode(dev, preferred_bpp);
|
||||
drm_client_setup_with_color_mode(display->drm, preferred_bpp);
|
||||
}
|
||||
|
||||
struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
struct drm_fb_helper;
|
||||
struct drm_fb_helper_surface_size;
|
||||
struct drm_i915_private;
|
||||
struct intel_display;
|
||||
struct intel_fbdev;
|
||||
struct intel_framebuffer;
|
||||
|
||||
@@ -19,14 +19,14 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes);
|
||||
#define INTEL_FBDEV_DRIVER_OPS \
|
||||
.fbdev_probe = intel_fbdev_driver_fbdev_probe
|
||||
void intel_fbdev_setup(struct drm_i915_private *dev_priv);
|
||||
void intel_fbdev_setup(struct intel_display *display);
|
||||
struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev);
|
||||
struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev);
|
||||
|
||||
#else
|
||||
#define INTEL_FBDEV_DRIVER_OPS \
|
||||
.fbdev_probe = NULL
|
||||
static inline void intel_fbdev_setup(struct drm_i915_private *dev_priv)
|
||||
static inline void intel_fbdev_setup(struct intel_display *display)
|
||||
{
|
||||
}
|
||||
static inline struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev)
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(helper->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_mode_fb_cmd2 mode_cmd = {};
|
||||
struct drm_i915_gem_object *obj;
|
||||
int size;
|
||||
@@ -50,14 +50,14 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
|
||||
*
|
||||
* Also skip stolen on MTL as Wa_22018444074 mitigation.
|
||||
*/
|
||||
if (!(IS_METEORLAKE(dev_priv)) && size * 2 < dev_priv->dsm.usable_size)
|
||||
if (!display->platform.meteorlake && size * 2 < dev_priv->dsm.usable_size)
|
||||
obj = i915_gem_object_create_stolen(dev_priv, size);
|
||||
if (IS_ERR(obj))
|
||||
obj = i915_gem_object_create_shmem(dev_priv, size);
|
||||
}
|
||||
|
||||
if (IS_ERR(obj)) {
|
||||
drm_err(&dev_priv->drm, "failed to allocate framebuffer (%pe)\n", obj);
|
||||
drm_err(display->drm, "failed to allocate framebuffer (%pe)\n", obj);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
@@ -67,9 +67,10 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
|
||||
return to_intel_framebuffer(fb);
|
||||
}
|
||||
|
||||
int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info,
|
||||
int intel_fbdev_fb_fill_info(struct intel_display *display, struct fb_info *info,
|
||||
struct drm_gem_object *_obj, struct i915_vma *vma)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
|
||||
struct i915_gem_ww_ctx ww;
|
||||
void __iomem *vaddr;
|
||||
@@ -101,7 +102,7 @@ int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info
|
||||
|
||||
vaddr = i915_vma_pin_iomap(vma);
|
||||
if (IS_ERR(vaddr)) {
|
||||
drm_err(&i915->drm,
|
||||
drm_err(display->drm,
|
||||
"Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
|
||||
ret = PTR_ERR(vaddr);
|
||||
continue;
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
struct drm_fb_helper;
|
||||
struct drm_fb_helper_surface_size;
|
||||
struct drm_gem_object;
|
||||
struct drm_i915_private;
|
||||
struct fb_info;
|
||||
struct i915_vma;
|
||||
struct intel_display;
|
||||
|
||||
struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes);
|
||||
int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info,
|
||||
int intel_fbdev_fb_fill_info(struct intel_display *display, struct fb_info *info,
|
||||
struct drm_gem_object *obj, struct i915_vma *vma);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,15 +6,16 @@
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <drm/drm_fixed.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_fdi_regs.h"
|
||||
#include "intel_link_bw.h"
|
||||
@@ -464,7 +465,6 @@ static void ivb_update_fdi_bc_bifurcation(const struct intel_crtc_state *crtc_st
|
||||
void intel_fdi_normal_train(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
i915_reg_t reg;
|
||||
u32 temp;
|
||||
@@ -483,7 +483,7 @@ void intel_fdi_normal_train(struct intel_crtc *crtc)
|
||||
|
||||
reg = FDI_RX_CTL(pipe);
|
||||
temp = intel_de_read(display, reg);
|
||||
if (HAS_PCH_CPT(dev_priv)) {
|
||||
if (HAS_PCH_CPT(display)) {
|
||||
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
||||
temp |= FDI_LINK_TRAIN_NORMAL_CPT;
|
||||
} else {
|
||||
@@ -607,7 +607,6 @@ static void gen6_fdi_link_train(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
i915_reg_t reg;
|
||||
u32 temp, i, retry;
|
||||
@@ -647,7 +646,7 @@ static void gen6_fdi_link_train(struct intel_crtc *crtc,
|
||||
|
||||
reg = FDI_RX_CTL(pipe);
|
||||
temp = intel_de_read(display, reg);
|
||||
if (HAS_PCH_CPT(dev_priv)) {
|
||||
if (HAS_PCH_CPT(display)) {
|
||||
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
||||
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
|
||||
} else {
|
||||
@@ -698,7 +697,7 @@ static void gen6_fdi_link_train(struct intel_crtc *crtc,
|
||||
|
||||
reg = FDI_RX_CTL(pipe);
|
||||
temp = intel_de_read(display, reg);
|
||||
if (HAS_PCH_CPT(dev_priv)) {
|
||||
if (HAS_PCH_CPT(display)) {
|
||||
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
||||
temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
|
||||
} else {
|
||||
@@ -1077,7 +1076,6 @@ void ilk_fdi_pll_disable(struct intel_crtc *crtc)
|
||||
void ilk_fdi_disable(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
i915_reg_t reg;
|
||||
u32 temp;
|
||||
@@ -1096,7 +1094,7 @@ void ilk_fdi_disable(struct intel_crtc *crtc)
|
||||
udelay(100);
|
||||
|
||||
/* Ironlake workaround, disable clock pointer after downing FDI */
|
||||
if (HAS_PCH_IBX(dev_priv))
|
||||
if (HAS_PCH_IBX(display))
|
||||
intel_de_write(display, FDI_RX_CHICKEN(pipe),
|
||||
FDI_RX_PHASE_SYNC_POINTER_OVR);
|
||||
|
||||
@@ -1106,7 +1104,7 @@ void ilk_fdi_disable(struct intel_crtc *crtc)
|
||||
|
||||
reg = FDI_RX_CTL(pipe);
|
||||
temp = intel_de_read(display, reg);
|
||||
if (HAS_PCH_CPT(dev_priv)) {
|
||||
if (HAS_PCH_CPT(display)) {
|
||||
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
||||
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
|
||||
} else {
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_irq.h"
|
||||
@@ -57,11 +58,10 @@
|
||||
|
||||
static bool ivb_can_enable_err_int(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_crtc *crtc;
|
||||
enum pipe pipe;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
for_each_pipe(display, pipe) {
|
||||
crtc = intel_crtc_for_pipe(display, pipe);
|
||||
@@ -75,11 +75,10 @@ static bool ivb_can_enable_err_int(struct intel_display *display)
|
||||
|
||||
static bool cpt_can_enable_serr_int(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe pipe;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
for_each_pipe(display, pipe) {
|
||||
crtc = intel_crtc_for_pipe(display, pipe);
|
||||
@@ -94,11 +93,10 @@ static bool cpt_can_enable_serr_int(struct intel_display *display)
|
||||
static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
i915_reg_t reg = PIPESTAT(display, crtc->pipe);
|
||||
u32 enable_mask;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if ((intel_de_read(display, reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0)
|
||||
return;
|
||||
@@ -115,10 +113,9 @@ static void i9xx_set_fifo_underrun_reporting(struct intel_display *display,
|
||||
enum pipe pipe,
|
||||
bool enable, bool old)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
i915_reg_t reg = PIPESTAT(display, pipe);
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if (enable) {
|
||||
u32 enable_mask = i915_pipestat_enable_mask(display, pipe);
|
||||
@@ -148,11 +145,10 @@ static void ilk_set_fifo_underrun_reporting(struct intel_display *display,
|
||||
static void ivb_check_fifo_underruns(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 err_int = intel_de_read(display, GEN7_ERR_INT);
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0)
|
||||
return;
|
||||
@@ -213,11 +209,10 @@ static void ibx_set_fifo_underrun_reporting(struct intel_display *display,
|
||||
static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pch_transcoder = crtc->pipe;
|
||||
u32 serr_int = intel_de_read(display, SERR_INT);
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0)
|
||||
return;
|
||||
@@ -258,11 +253,10 @@ static void cpt_set_fifo_underrun_reporting(struct intel_display *display,
|
||||
static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *display,
|
||||
enum pipe pipe, bool enable)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
|
||||
bool old;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
old = !crtc->cpu_fifo_underrun_disabled;
|
||||
crtc->cpu_fifo_underrun_disabled = !enable;
|
||||
@@ -298,13 +292,12 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *displa
|
||||
bool intel_set_cpu_fifo_underrun_reporting(struct intel_display *display,
|
||||
enum pipe pipe, bool enable)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
unsigned long flags;
|
||||
bool ret;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, flags);
|
||||
spin_lock_irqsave(&display->irq.lock, flags);
|
||||
ret = __intel_set_cpu_fifo_underrun_reporting(display, pipe, enable);
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -327,7 +320,6 @@ bool intel_set_pch_fifo_underrun_reporting(struct intel_display *display,
|
||||
enum pipe pch_transcoder,
|
||||
bool enable)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pch_transcoder);
|
||||
unsigned long flags;
|
||||
bool old;
|
||||
@@ -341,12 +333,12 @@ bool intel_set_pch_fifo_underrun_reporting(struct intel_display *display,
|
||||
* crtc on LPT won't cause issues.
|
||||
*/
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irq_lock, flags);
|
||||
spin_lock_irqsave(&display->irq.lock, flags);
|
||||
|
||||
old = !crtc->pch_fifo_underrun_disabled;
|
||||
crtc->pch_fifo_underrun_disabled = !enable;
|
||||
|
||||
if (HAS_PCH_IBX(dev_priv))
|
||||
if (HAS_PCH_IBX(display))
|
||||
ibx_set_fifo_underrun_reporting(display,
|
||||
pch_transcoder,
|
||||
enable);
|
||||
@@ -355,7 +347,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct intel_display *display,
|
||||
pch_transcoder,
|
||||
enable, old);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, flags);
|
||||
return old;
|
||||
}
|
||||
|
||||
@@ -422,10 +414,9 @@ void intel_pch_fifo_underrun_irq_handler(struct intel_display *display,
|
||||
*/
|
||||
void intel_check_cpu_fifo_underruns(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
if (crtc->cpu_fifo_underrun_disabled)
|
||||
@@ -437,7 +428,7 @@ void intel_check_cpu_fifo_underruns(struct intel_display *display)
|
||||
ivb_check_fifo_underruns(crtc);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -450,20 +441,19 @@ void intel_check_cpu_fifo_underruns(struct intel_display *display)
|
||||
*/
|
||||
void intel_check_pch_fifo_underruns(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
if (crtc->pch_fifo_underrun_disabled)
|
||||
continue;
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_CPT(display))
|
||||
cpt_check_pch_fifo_underruns(crtc);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
void intel_init_fifo_underrun_reporting(struct intel_display *display,
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
#include <drm/drm_gem.h>
|
||||
|
||||
#include "i915_active.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_vma.h"
|
||||
#include "intel_bo.h"
|
||||
#include "intel_display_trace.h"
|
||||
@@ -72,7 +71,7 @@
|
||||
|
||||
/**
|
||||
* frontbuffer_flush - flush frontbuffer
|
||||
* @i915: i915 device
|
||||
* @display: display device
|
||||
* @frontbuffer_bits: frontbuffer plane tracking bits
|
||||
* @origin: which operation caused the flush
|
||||
*
|
||||
@@ -82,16 +81,14 @@
|
||||
*
|
||||
* Can be called without any locks held.
|
||||
*/
|
||||
static void frontbuffer_flush(struct drm_i915_private *i915,
|
||||
static void frontbuffer_flush(struct intel_display *display,
|
||||
unsigned int frontbuffer_bits,
|
||||
enum fb_op_origin origin)
|
||||
{
|
||||
struct intel_display *display = &i915->display;
|
||||
|
||||
/* Delay flushing when rings are still busy.*/
|
||||
spin_lock(&i915->display.fb_tracking.lock);
|
||||
frontbuffer_bits &= ~i915->display.fb_tracking.busy_bits;
|
||||
spin_unlock(&i915->display.fb_tracking.lock);
|
||||
spin_lock(&display->fb_tracking.lock);
|
||||
frontbuffer_bits &= ~display->fb_tracking.busy_bits;
|
||||
spin_unlock(&display->fb_tracking.lock);
|
||||
|
||||
if (!frontbuffer_bits)
|
||||
return;
|
||||
@@ -107,7 +104,7 @@ static void frontbuffer_flush(struct drm_i915_private *i915,
|
||||
|
||||
/**
|
||||
* intel_frontbuffer_flip_prepare - prepare asynchronous frontbuffer flip
|
||||
* @i915: i915 device
|
||||
* @display: display device
|
||||
* @frontbuffer_bits: frontbuffer plane tracking bits
|
||||
*
|
||||
* This function gets called after scheduling a flip on @obj. The actual
|
||||
@@ -117,19 +114,19 @@ static void frontbuffer_flush(struct drm_i915_private *i915,
|
||||
*
|
||||
* Can be called without any locks held.
|
||||
*/
|
||||
void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
|
||||
void intel_frontbuffer_flip_prepare(struct intel_display *display,
|
||||
unsigned frontbuffer_bits)
|
||||
{
|
||||
spin_lock(&i915->display.fb_tracking.lock);
|
||||
i915->display.fb_tracking.flip_bits |= frontbuffer_bits;
|
||||
spin_lock(&display->fb_tracking.lock);
|
||||
display->fb_tracking.flip_bits |= frontbuffer_bits;
|
||||
/* Remove stale busy bits due to the old buffer. */
|
||||
i915->display.fb_tracking.busy_bits &= ~frontbuffer_bits;
|
||||
spin_unlock(&i915->display.fb_tracking.lock);
|
||||
display->fb_tracking.busy_bits &= ~frontbuffer_bits;
|
||||
spin_unlock(&display->fb_tracking.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flip
|
||||
* @i915: i915 device
|
||||
* @display: display device
|
||||
* @frontbuffer_bits: frontbuffer plane tracking bits
|
||||
*
|
||||
* This function gets called after the flip has been latched and will complete
|
||||
@@ -137,22 +134,22 @@ void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
|
||||
*
|
||||
* Can be called without any locks held.
|
||||
*/
|
||||
void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
|
||||
void intel_frontbuffer_flip_complete(struct intel_display *display,
|
||||
unsigned frontbuffer_bits)
|
||||
{
|
||||
spin_lock(&i915->display.fb_tracking.lock);
|
||||
spin_lock(&display->fb_tracking.lock);
|
||||
/* Mask any cancelled flips. */
|
||||
frontbuffer_bits &= i915->display.fb_tracking.flip_bits;
|
||||
i915->display.fb_tracking.flip_bits &= ~frontbuffer_bits;
|
||||
spin_unlock(&i915->display.fb_tracking.lock);
|
||||
frontbuffer_bits &= display->fb_tracking.flip_bits;
|
||||
display->fb_tracking.flip_bits &= ~frontbuffer_bits;
|
||||
spin_unlock(&display->fb_tracking.lock);
|
||||
|
||||
if (frontbuffer_bits)
|
||||
frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
|
||||
frontbuffer_flush(display, frontbuffer_bits, ORIGIN_FLIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_frontbuffer_flip - synchronous frontbuffer flip
|
||||
* @i915: i915 device
|
||||
* @display: display device
|
||||
* @frontbuffer_bits: frontbuffer plane tracking bits
|
||||
*
|
||||
* This function gets called after scheduling a flip on @obj. This is for
|
||||
@@ -161,15 +158,15 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
|
||||
*
|
||||
* Can be called without any locks held.
|
||||
*/
|
||||
void intel_frontbuffer_flip(struct drm_i915_private *i915,
|
||||
void intel_frontbuffer_flip(struct intel_display *display,
|
||||
unsigned frontbuffer_bits)
|
||||
{
|
||||
spin_lock(&i915->display.fb_tracking.lock);
|
||||
spin_lock(&display->fb_tracking.lock);
|
||||
/* Remove stale busy bits due to the old buffer. */
|
||||
i915->display.fb_tracking.busy_bits &= ~frontbuffer_bits;
|
||||
spin_unlock(&i915->display.fb_tracking.lock);
|
||||
display->fb_tracking.busy_bits &= ~frontbuffer_bits;
|
||||
spin_unlock(&display->fb_tracking.lock);
|
||||
|
||||
frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
|
||||
frontbuffer_flush(display, frontbuffer_bits, ORIGIN_FLIP);
|
||||
}
|
||||
|
||||
void __intel_fb_invalidate(struct intel_frontbuffer *front,
|
||||
@@ -198,7 +195,6 @@ void __intel_fb_flush(struct intel_frontbuffer *front,
|
||||
unsigned int frontbuffer_bits)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(front->obj->dev);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (origin == ORIGIN_CS) {
|
||||
spin_lock(&display->fb_tracking.lock);
|
||||
@@ -209,7 +205,7 @@ void __intel_fb_flush(struct intel_frontbuffer *front,
|
||||
}
|
||||
|
||||
if (frontbuffer_bits)
|
||||
frontbuffer_flush(i915, frontbuffer_bits, origin);
|
||||
frontbuffer_flush(display, frontbuffer_bits, origin);
|
||||
}
|
||||
|
||||
static void intel_frontbuffer_flush_work(struct work_struct *work)
|
||||
@@ -280,7 +276,7 @@ static void frontbuffer_release(struct kref *ref)
|
||||
struct intel_frontbuffer *
|
||||
intel_frontbuffer_get(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(obj->dev);
|
||||
struct intel_display *display = to_intel_display(obj->dev);
|
||||
struct intel_frontbuffer *front, *cur;
|
||||
|
||||
front = intel_bo_get_frontbuffer(obj);
|
||||
@@ -300,9 +296,9 @@ intel_frontbuffer_get(struct drm_gem_object *obj)
|
||||
I915_ACTIVE_RETIRE_SLEEPS);
|
||||
INIT_WORK(&front->flush_work, intel_frontbuffer_flush_work);
|
||||
|
||||
spin_lock(&i915->display.fb_tracking.lock);
|
||||
spin_lock(&display->fb_tracking.lock);
|
||||
cur = intel_bo_set_frontbuffer(obj, front);
|
||||
spin_unlock(&i915->display.fb_tracking.lock);
|
||||
spin_unlock(&display->fb_tracking.lock);
|
||||
if (cur != front)
|
||||
kfree(front);
|
||||
return cur;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "i915_active_types.h"
|
||||
|
||||
struct drm_gem_object;
|
||||
struct drm_i915_private;
|
||||
struct intel_display;
|
||||
|
||||
enum fb_op_origin {
|
||||
ORIGIN_CPU = 0,
|
||||
@@ -68,11 +68,11 @@ struct intel_frontbuffer {
|
||||
GENMASK(INTEL_FRONTBUFFER_BITS_PER_PIPE * ((pipe) + 1) - 1, \
|
||||
INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))
|
||||
|
||||
void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
|
||||
void intel_frontbuffer_flip_prepare(struct intel_display *display,
|
||||
unsigned frontbuffer_bits);
|
||||
void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
|
||||
void intel_frontbuffer_flip_complete(struct intel_display *display,
|
||||
unsigned frontbuffer_bits);
|
||||
void intel_frontbuffer_flip(struct drm_i915_private *i915,
|
||||
void intel_frontbuffer_flip(struct intel_display *display,
|
||||
unsigned frontbuffer_bits);
|
||||
|
||||
void intel_frontbuffer_put(struct intel_frontbuffer *front);
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
* Copyright © 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_global_state.h"
|
||||
|
||||
|
||||
@@ -152,32 +152,31 @@ static const struct gmbus_pin gmbus_pins_mtp[] = {
|
||||
static const struct gmbus_pin *get_gmbus_pin(struct intel_display *display,
|
||||
unsigned int pin)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
const struct gmbus_pin *pins;
|
||||
size_t size;
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_MTL) {
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_MTL) {
|
||||
pins = gmbus_pins_mtp;
|
||||
size = ARRAY_SIZE(gmbus_pins_mtp);
|
||||
} else if (INTEL_PCH_TYPE(i915) >= PCH_DG2) {
|
||||
} else if (INTEL_PCH_TYPE(display) >= PCH_DG2) {
|
||||
pins = gmbus_pins_dg2;
|
||||
size = ARRAY_SIZE(gmbus_pins_dg2);
|
||||
} else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) {
|
||||
} else if (INTEL_PCH_TYPE(display) >= PCH_DG1) {
|
||||
pins = gmbus_pins_dg1;
|
||||
size = ARRAY_SIZE(gmbus_pins_dg1);
|
||||
} else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) {
|
||||
} else if (INTEL_PCH_TYPE(display) >= PCH_ICP) {
|
||||
pins = gmbus_pins_icp;
|
||||
size = ARRAY_SIZE(gmbus_pins_icp);
|
||||
} else if (HAS_PCH_CNP(i915)) {
|
||||
} else if (HAS_PCH_CNP(display)) {
|
||||
pins = gmbus_pins_cnp;
|
||||
size = ARRAY_SIZE(gmbus_pins_cnp);
|
||||
} else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
|
||||
} else if (display->platform.geminilake || display->platform.broxton) {
|
||||
pins = gmbus_pins_bxt;
|
||||
size = ARRAY_SIZE(gmbus_pins_bxt);
|
||||
} else if (DISPLAY_VER(display) == 9) {
|
||||
pins = gmbus_pins_skl;
|
||||
size = ARRAY_SIZE(gmbus_pins_skl);
|
||||
} else if (IS_BROADWELL(i915)) {
|
||||
} else if (display->platform.broadwell) {
|
||||
pins = gmbus_pins_bdw;
|
||||
size = ARRAY_SIZE(gmbus_pins_bdw);
|
||||
} else {
|
||||
@@ -240,11 +239,10 @@ static void bxt_gmbus_clock_gating(struct intel_display *display,
|
||||
static u32 get_reserved(struct intel_gmbus *bus)
|
||||
{
|
||||
struct intel_display *display = bus->display;
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
u32 reserved = 0;
|
||||
|
||||
/* On most chips, these bits must be preserved in software. */
|
||||
if (!IS_I830(i915) && !IS_I845G(i915))
|
||||
if (!display->platform.i830 && !display->platform.i845g)
|
||||
reserved = intel_de_read_notrace(display, bus->gpio_reg) &
|
||||
(GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE);
|
||||
|
||||
@@ -314,11 +312,10 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
struct intel_display *display = bus->display;
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
intel_gmbus_reset(display);
|
||||
|
||||
if (IS_PINEVIEW(i915))
|
||||
if (display->platform.pineview)
|
||||
pnv_gmbus_clock_gating(display, false);
|
||||
|
||||
set_data(bus, 1);
|
||||
@@ -332,12 +329,11 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
struct intel_display *display = bus->display;
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
set_data(bus, 1);
|
||||
set_clock(bus, 1);
|
||||
|
||||
if (IS_PINEVIEW(i915))
|
||||
if (display->platform.pineview)
|
||||
pnv_gmbus_clock_gating(display, true);
|
||||
}
|
||||
|
||||
@@ -630,14 +626,13 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
|
||||
{
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
struct intel_display *display = bus->display;
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
int i = 0, inc, try = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* Display WA #0868: skl,bxt,kbl,cfl,glk */
|
||||
if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
|
||||
if (display->platform.geminilake || display->platform.broxton)
|
||||
bxt_gmbus_clock_gating(display, false);
|
||||
else if (HAS_PCH_SPT(i915) || HAS_PCH_CNP(i915))
|
||||
else if (HAS_PCH_SPT(display) || HAS_PCH_CNP(display))
|
||||
pch_gmbus_clock_gating(display, false);
|
||||
|
||||
retry:
|
||||
@@ -748,9 +743,9 @@ timeout:
|
||||
|
||||
out:
|
||||
/* Display WA #0868: skl,bxt,kbl,cfl,glk */
|
||||
if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
|
||||
if (display->platform.geminilake || display->platform.broxton)
|
||||
bxt_gmbus_clock_gating(display, true);
|
||||
else if (HAS_PCH_SPT(i915) || HAS_PCH_CNP(i915))
|
||||
else if (HAS_PCH_SPT(display) || HAS_PCH_CNP(display))
|
||||
pch_gmbus_clock_gating(display, true);
|
||||
|
||||
return ret;
|
||||
@@ -873,12 +868,11 @@ static const struct i2c_lock_operations gmbus_lock_ops = {
|
||||
*/
|
||||
int intel_gmbus_setup(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
|
||||
unsigned int pin;
|
||||
int ret;
|
||||
|
||||
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
|
||||
if (display->platform.valleyview || display->platform.cherryview)
|
||||
display->gmbus.mmio_base = VLV_DISPLAY_BASE;
|
||||
else if (!HAS_GMCH(display))
|
||||
/*
|
||||
@@ -925,7 +919,7 @@ int intel_gmbus_setup(struct intel_display *display)
|
||||
bus->reg0 = pin | GMBUS_RATE_100KHZ;
|
||||
|
||||
/* gmbus seems to be broken on i830 */
|
||||
if (IS_I830(i915))
|
||||
if (display->platform.i830)
|
||||
bus->force_bit = 1;
|
||||
|
||||
intel_gpio_setup(bus, GPIO(display, gmbus_pin->gpio));
|
||||
|
||||
@@ -27,10 +27,13 @@
|
||||
#include "intel_dp_mst.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_hdcp_gsc.h"
|
||||
#include "intel_hdcp_gsc_message.h"
|
||||
#include "intel_hdcp_regs.h"
|
||||
#include "intel_hdcp_shim.h"
|
||||
#include "intel_pcode.h"
|
||||
|
||||
#define USE_HDCP_GSC(__display) (DISPLAY_VER(__display) >= 14)
|
||||
|
||||
#define KEY_LOAD_TRIES 5
|
||||
#define HDCP2_LC_RETRY_CNT 3
|
||||
|
||||
@@ -250,8 +253,8 @@ static bool intel_hdcp2_prerequisite(struct intel_connector *connector)
|
||||
return false;
|
||||
|
||||
/* If MTL+ make sure gsc is loaded and proxy is setup */
|
||||
if (intel_hdcp_gsc_cs_required(display)) {
|
||||
if (!intel_hdcp_gsc_check_status(display))
|
||||
if (USE_HDCP_GSC(display)) {
|
||||
if (!intel_hdcp_gsc_check_status(display->drm))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2339,7 +2342,7 @@ static int initialize_hdcp_port_data(struct intel_connector *connector,
|
||||
|
||||
static bool is_hdcp2_supported(struct intel_display *display)
|
||||
{
|
||||
if (intel_hdcp_gsc_cs_required(display))
|
||||
if (USE_HDCP_GSC(display))
|
||||
return true;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP))
|
||||
@@ -2363,7 +2366,7 @@ void intel_hdcp_component_init(struct intel_display *display)
|
||||
|
||||
display->hdcp.comp_added = true;
|
||||
mutex_unlock(&display->hdcp.hdcp_mutex);
|
||||
if (intel_hdcp_gsc_cs_required(display))
|
||||
if (USE_HDCP_GSC(display))
|
||||
ret = intel_hdcp_gsc_init(display);
|
||||
else
|
||||
ret = component_add_typed(display->drm->dev, &i915_hdcp_ops,
|
||||
@@ -2638,7 +2641,7 @@ void intel_hdcp_component_fini(struct intel_display *display)
|
||||
display->hdcp.comp_added = false;
|
||||
mutex_unlock(&display->hdcp.hdcp_mutex);
|
||||
|
||||
if (intel_hdcp_gsc_cs_required(display))
|
||||
if (USE_HDCP_GSC(display))
|
||||
intel_hdcp_gsc_fini(display);
|
||||
else
|
||||
component_del(display->drm->dev, &i915_hdcp_ops);
|
||||
|
||||
@@ -11,27 +11,22 @@
|
||||
#include "i915_drv.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_hdcp_gsc.h"
|
||||
#include "intel_hdcp_gsc_message.h"
|
||||
|
||||
struct intel_hdcp_gsc_message {
|
||||
struct intel_hdcp_gsc_context {
|
||||
struct drm_i915_private *i915;
|
||||
struct i915_vma *vma;
|
||||
void *hdcp_cmd_in;
|
||||
void *hdcp_cmd_out;
|
||||
};
|
||||
|
||||
bool intel_hdcp_gsc_cs_required(struct intel_display *display)
|
||||
bool intel_hdcp_gsc_check_status(struct drm_device *drm)
|
||||
{
|
||||
return DISPLAY_VER(display) >= 14;
|
||||
}
|
||||
|
||||
bool intel_hdcp_gsc_check_status(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct drm_i915_private *i915 = to_i915(drm);
|
||||
struct intel_gt *gt = i915->media_gt;
|
||||
struct intel_gsc_uc *gsc = gt ? >->uc.gsc : NULL;
|
||||
|
||||
if (!gsc || !intel_uc_fw_is_running(&gsc->fw)) {
|
||||
drm_dbg_kms(display->drm,
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"GSC components required for HDCP2.2 are not ready\n");
|
||||
return false;
|
||||
}
|
||||
@@ -41,7 +36,7 @@ bool intel_hdcp_gsc_check_status(struct intel_display *display)
|
||||
|
||||
/*This function helps allocate memory for the command that we will send to gsc cs */
|
||||
static int intel_hdcp_gsc_initialize_message(struct drm_i915_private *i915,
|
||||
struct intel_hdcp_gsc_message *hdcp_message)
|
||||
struct intel_hdcp_gsc_context *gsc_context)
|
||||
{
|
||||
struct intel_gt *gt = i915->media_gt;
|
||||
struct drm_i915_gem_object *obj = NULL;
|
||||
@@ -78,9 +73,10 @@ static int intel_hdcp_gsc_initialize_message(struct drm_i915_private *i915,
|
||||
|
||||
memset(cmd_in, 0, obj->base.size);
|
||||
|
||||
hdcp_message->hdcp_cmd_in = cmd_in;
|
||||
hdcp_message->hdcp_cmd_out = cmd_out;
|
||||
hdcp_message->vma = vma;
|
||||
gsc_context->hdcp_cmd_in = cmd_in;
|
||||
gsc_context->hdcp_cmd_out = cmd_out;
|
||||
gsc_context->vma = vma;
|
||||
gsc_context->i915 = i915;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -91,80 +87,37 @@ out_unpin:
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct i915_hdcp_ops gsc_hdcp_ops = {
|
||||
.initiate_hdcp2_session = intel_hdcp_gsc_initiate_session,
|
||||
.verify_receiver_cert_prepare_km =
|
||||
intel_hdcp_gsc_verify_receiver_cert_prepare_km,
|
||||
.verify_hprime = intel_hdcp_gsc_verify_hprime,
|
||||
.store_pairing_info = intel_hdcp_gsc_store_pairing_info,
|
||||
.initiate_locality_check = intel_hdcp_gsc_initiate_locality_check,
|
||||
.verify_lprime = intel_hdcp_gsc_verify_lprime,
|
||||
.get_session_key = intel_hdcp_gsc_get_session_key,
|
||||
.repeater_check_flow_prepare_ack =
|
||||
intel_hdcp_gsc_repeater_check_flow_prepare_ack,
|
||||
.verify_mprime = intel_hdcp_gsc_verify_mprime,
|
||||
.enable_hdcp_authentication = intel_hdcp_gsc_enable_authentication,
|
||||
.close_hdcp_session = intel_hdcp_gsc_close_session,
|
||||
};
|
||||
|
||||
static int intel_hdcp_gsc_hdcp2_init(struct intel_display *display)
|
||||
struct intel_hdcp_gsc_context *intel_hdcp_gsc_context_alloc(struct drm_device *drm)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_hdcp_gsc_message *hdcp_message;
|
||||
struct drm_i915_private *i915 = to_i915(drm);
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
int ret;
|
||||
|
||||
hdcp_message = kzalloc(sizeof(*hdcp_message), GFP_KERNEL);
|
||||
|
||||
if (!hdcp_message)
|
||||
return -ENOMEM;
|
||||
gsc_context = kzalloc(sizeof(*gsc_context), GFP_KERNEL);
|
||||
if (!gsc_context)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/*
|
||||
* NOTE: No need to lock the comp mutex here as it is already
|
||||
* going to be taken before this function called
|
||||
*/
|
||||
display->hdcp.hdcp_message = hdcp_message;
|
||||
ret = intel_hdcp_gsc_initialize_message(i915, hdcp_message);
|
||||
ret = intel_hdcp_gsc_initialize_message(i915, gsc_context);
|
||||
if (ret) {
|
||||
drm_err(&i915->drm, "Could not initialize gsc_context\n");
|
||||
kfree(gsc_context);
|
||||
gsc_context = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
drm_err(display->drm, "Could not initialize hdcp_message\n");
|
||||
|
||||
return ret;
|
||||
return gsc_context;
|
||||
}
|
||||
|
||||
static void intel_hdcp_gsc_free_message(struct intel_display *display)
|
||||
void intel_hdcp_gsc_context_free(struct intel_hdcp_gsc_context *gsc_context)
|
||||
{
|
||||
struct intel_hdcp_gsc_message *hdcp_message =
|
||||
display->hdcp.hdcp_message;
|
||||
if (!gsc_context)
|
||||
return;
|
||||
|
||||
hdcp_message->hdcp_cmd_in = NULL;
|
||||
hdcp_message->hdcp_cmd_out = NULL;
|
||||
i915_vma_unpin_and_release(&hdcp_message->vma, I915_VMA_RELEASE_MAP);
|
||||
kfree(hdcp_message);
|
||||
}
|
||||
|
||||
int intel_hdcp_gsc_init(struct intel_display *display)
|
||||
{
|
||||
struct i915_hdcp_arbiter *data;
|
||||
int ret;
|
||||
|
||||
data = kzalloc(sizeof(struct i915_hdcp_arbiter), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&display->hdcp.hdcp_mutex);
|
||||
display->hdcp.arbiter = data;
|
||||
display->hdcp.arbiter->hdcp_dev = display->drm->dev;
|
||||
display->hdcp.arbiter->ops = &gsc_hdcp_ops;
|
||||
ret = intel_hdcp_gsc_hdcp2_init(display);
|
||||
mutex_unlock(&display->hdcp.hdcp_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void intel_hdcp_gsc_fini(struct intel_display *display)
|
||||
{
|
||||
intel_hdcp_gsc_free_message(display);
|
||||
kfree(display->hdcp.arbiter);
|
||||
i915_vma_unpin_and_release(&gsc_context->vma, I915_VMA_RELEASE_MAP);
|
||||
kfree(gsc_context);
|
||||
}
|
||||
|
||||
static int intel_gsc_send_sync(struct drm_i915_private *i915,
|
||||
@@ -211,18 +164,18 @@ static int intel_gsc_send_sync(struct drm_i915_private *i915,
|
||||
/*
|
||||
* This function can now be used for sending requests and will also handle
|
||||
* receipt of reply messages hence no different function of message retrieval
|
||||
* is required. We will initialize intel_hdcp_gsc_message structure then add
|
||||
* is required. We will initialize intel_hdcp_gsc_context structure then add
|
||||
* gsc cs memory header as stated in specs after which the normal HDCP payload
|
||||
* will follow
|
||||
*/
|
||||
ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
|
||||
size_t msg_in_len, u8 *msg_out,
|
||||
size_t msg_out_len)
|
||||
ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context,
|
||||
void *msg_in, size_t msg_in_len,
|
||||
void *msg_out, size_t msg_out_len)
|
||||
{
|
||||
struct drm_i915_private *i915 = gsc_context->i915;
|
||||
struct intel_gt *gt = i915->media_gt;
|
||||
struct intel_gsc_mtl_header *header_in, *header_out;
|
||||
const size_t max_msg_size = PAGE_SIZE - sizeof(*header_in);
|
||||
struct intel_hdcp_gsc_message *hdcp_message;
|
||||
u64 addr_in, addr_out, host_session_id;
|
||||
u32 reply_size, msg_size_in, msg_size_out;
|
||||
int ret, tries = 0;
|
||||
@@ -235,10 +188,9 @@ ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
|
||||
|
||||
msg_size_in = msg_in_len + sizeof(*header_in);
|
||||
msg_size_out = msg_out_len + sizeof(*header_out);
|
||||
hdcp_message = i915->display.hdcp.hdcp_message;
|
||||
header_in = hdcp_message->hdcp_cmd_in;
|
||||
header_out = hdcp_message->hdcp_cmd_out;
|
||||
addr_in = i915_ggtt_offset(hdcp_message->vma);
|
||||
header_in = gsc_context->hdcp_cmd_in;
|
||||
header_out = gsc_context->hdcp_cmd_out;
|
||||
addr_in = i915_ggtt_offset(gsc_context->vma);
|
||||
addr_out = addr_in + PAGE_SIZE;
|
||||
|
||||
memset(header_in, 0, msg_size_in);
|
||||
@@ -246,7 +198,7 @@ ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
|
||||
get_random_bytes(&host_session_id, sizeof(u64));
|
||||
intel_gsc_uc_heci_cmd_emit_mtl_header(header_in, HECI_MEADDRESS_HDCP,
|
||||
msg_size_in, host_session_id);
|
||||
memcpy(hdcp_message->hdcp_cmd_in + sizeof(*header_in), msg_in, msg_in_len);
|
||||
memcpy(gsc_context->hdcp_cmd_in + sizeof(*header_in), msg_in, msg_in_len);
|
||||
|
||||
/*
|
||||
* Keep sending request in case the pending bit is set no need to add
|
||||
@@ -280,7 +232,7 @@ ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
|
||||
reply_size, (u32)msg_out_len);
|
||||
}
|
||||
|
||||
memcpy(msg_out, hdcp_message->hdcp_cmd_out + sizeof(*header_out), msg_out_len);
|
||||
memcpy(msg_out, gsc_context->hdcp_cmd_out + sizeof(*header_out), msg_out_len);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
|
||||
@@ -6,19 +6,17 @@
|
||||
#ifndef __INTEL_HDCP_GSC_H__
|
||||
#define __INTEL_HDCP_GSC_H__
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_display;
|
||||
struct intel_hdcp_gsc_message;
|
||||
struct drm_device;
|
||||
struct intel_hdcp_gsc_context;
|
||||
|
||||
bool intel_hdcp_gsc_cs_required(struct intel_display *display);
|
||||
ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
|
||||
size_t msg_in_len, u8 *msg_out,
|
||||
size_t msg_out_len);
|
||||
int intel_hdcp_gsc_init(struct intel_display *display);
|
||||
void intel_hdcp_gsc_fini(struct intel_display *display);
|
||||
bool intel_hdcp_gsc_check_status(struct intel_display *display);
|
||||
ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context,
|
||||
void *msg_in, size_t msg_in_len,
|
||||
void *msg_out, size_t msg_out_len);
|
||||
bool intel_hdcp_gsc_check_status(struct drm_device *drm);
|
||||
|
||||
struct intel_hdcp_gsc_context *intel_hdcp_gsc_context_alloc(struct drm_device *drm);
|
||||
void intel_hdcp_gsc_context_free(struct intel_hdcp_gsc_context *gsc_context);
|
||||
|
||||
#endif /* __INTEL_HDCP_GCS_H__ */
|
||||
|
||||
@@ -4,20 +4,23 @@
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/intel/i915_hdcp_interface.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_hdcp_gsc.h"
|
||||
#include "intel_hdcp_gsc_message.h"
|
||||
|
||||
int
|
||||
static int
|
||||
intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
|
||||
struct hdcp2_ake_init *ake_data)
|
||||
{
|
||||
struct wired_cmd_initiate_hdcp2_session_in session_init_in = {};
|
||||
struct wired_cmd_initiate_hdcp2_session_out session_init_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !data || !ake_data)
|
||||
@@ -28,7 +31,7 @@ intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
session_init_in.header.api_version = HDCP_API_VERSION;
|
||||
session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION;
|
||||
@@ -41,9 +44,9 @@ intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
|
||||
session_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
|
||||
session_init_in.protocol = data->protocol;
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&session_init_in,
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &session_init_in,
|
||||
sizeof(session_init_in),
|
||||
(u8 *)&session_init_out,
|
||||
&session_init_out,
|
||||
sizeof(session_init_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
|
||||
@@ -64,7 +67,7 @@ intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_ake_send_cert *rx_cert,
|
||||
@@ -75,8 +78,8 @@ intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
|
||||
{
|
||||
struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = {};
|
||||
struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)
|
||||
@@ -87,7 +90,7 @@ intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
verify_rxcert_in.header.api_version = HDCP_API_VERSION;
|
||||
verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT;
|
||||
@@ -103,9 +106,9 @@ intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
|
||||
memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, HDCP_2_2_RRX_LEN);
|
||||
memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_rxcert_in,
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &verify_rxcert_in,
|
||||
sizeof(verify_rxcert_in),
|
||||
(u8 *)&verify_rxcert_out,
|
||||
&verify_rxcert_out,
|
||||
sizeof(verify_rxcert_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed: %zd\n", byte);
|
||||
@@ -134,14 +137,14 @@ intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
intel_hdcp_gsc_verify_hprime(struct device *dev, struct hdcp_port_data *data,
|
||||
struct hdcp2_ake_send_hprime *rx_hprime)
|
||||
{
|
||||
struct wired_cmd_ake_send_hprime_in send_hprime_in = {};
|
||||
struct wired_cmd_ake_send_hprime_out send_hprime_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !data || !rx_hprime)
|
||||
@@ -152,7 +155,7 @@ intel_hdcp_gsc_verify_hprime(struct device *dev, struct hdcp_port_data *data,
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
send_hprime_in.header.api_version = HDCP_API_VERSION;
|
||||
send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME;
|
||||
@@ -166,9 +169,9 @@ intel_hdcp_gsc_verify_hprime(struct device *dev, struct hdcp_port_data *data,
|
||||
memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
|
||||
HDCP_2_2_H_PRIME_LEN);
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&send_hprime_in,
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &send_hprime_in,
|
||||
sizeof(send_hprime_in),
|
||||
(u8 *)&send_hprime_out,
|
||||
&send_hprime_out,
|
||||
sizeof(send_hprime_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
|
||||
@@ -184,14 +187,14 @@ intel_hdcp_gsc_verify_hprime(struct device *dev, struct hdcp_port_data *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
intel_hdcp_gsc_store_pairing_info(struct device *dev, struct hdcp_port_data *data,
|
||||
struct hdcp2_ake_send_pairing_info *pairing_info)
|
||||
{
|
||||
struct wired_cmd_ake_send_pairing_info_in pairing_info_in = {};
|
||||
struct wired_cmd_ake_send_pairing_info_out pairing_info_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !data || !pairing_info)
|
||||
@@ -202,7 +205,7 @@ intel_hdcp_gsc_store_pairing_info(struct device *dev, struct hdcp_port_data *dat
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
pairing_info_in.header.api_version = HDCP_API_VERSION;
|
||||
pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO;
|
||||
@@ -217,9 +220,9 @@ intel_hdcp_gsc_store_pairing_info(struct device *dev, struct hdcp_port_data *dat
|
||||
memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
|
||||
HDCP_2_2_E_KH_KM_LEN);
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&pairing_info_in,
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &pairing_info_in,
|
||||
sizeof(pairing_info_in),
|
||||
(u8 *)&pairing_info_out,
|
||||
&pairing_info_out,
|
||||
sizeof(pairing_info_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
|
||||
@@ -236,15 +239,15 @@ intel_hdcp_gsc_store_pairing_info(struct device *dev, struct hdcp_port_data *dat
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
intel_hdcp_gsc_initiate_locality_check(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_lc_init *lc_init_data)
|
||||
{
|
||||
struct wired_cmd_init_locality_check_in lc_init_in = {};
|
||||
struct wired_cmd_init_locality_check_out lc_init_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !data || !lc_init_data)
|
||||
@@ -255,7 +258,7 @@ intel_hdcp_gsc_initiate_locality_check(struct device *dev,
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
lc_init_in.header.api_version = HDCP_API_VERSION;
|
||||
lc_init_in.header.command_id = WIRED_INIT_LOCALITY_CHECK;
|
||||
@@ -266,8 +269,8 @@ intel_hdcp_gsc_initiate_locality_check(struct device *dev,
|
||||
lc_init_in.port.physical_port = (u8)data->hdcp_ddi;
|
||||
lc_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&lc_init_in, sizeof(lc_init_in),
|
||||
(u8 *)&lc_init_out, sizeof(lc_init_out));
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &lc_init_in, sizeof(lc_init_in),
|
||||
&lc_init_out, sizeof(lc_init_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
|
||||
return byte;
|
||||
@@ -285,14 +288,14 @@ intel_hdcp_gsc_initiate_locality_check(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
intel_hdcp_gsc_verify_lprime(struct device *dev, struct hdcp_port_data *data,
|
||||
struct hdcp2_lc_send_lprime *rx_lprime)
|
||||
{
|
||||
struct wired_cmd_validate_locality_in verify_lprime_in = {};
|
||||
struct wired_cmd_validate_locality_out verify_lprime_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !data || !rx_lprime)
|
||||
@@ -303,7 +306,7 @@ intel_hdcp_gsc_verify_lprime(struct device *dev, struct hdcp_port_data *data,
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
verify_lprime_in.header.api_version = HDCP_API_VERSION;
|
||||
verify_lprime_in.header.command_id = WIRED_VALIDATE_LOCALITY;
|
||||
@@ -318,9 +321,9 @@ intel_hdcp_gsc_verify_lprime(struct device *dev, struct hdcp_port_data *data,
|
||||
memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
|
||||
HDCP_2_2_L_PRIME_LEN);
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_lprime_in,
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &verify_lprime_in,
|
||||
sizeof(verify_lprime_in),
|
||||
(u8 *)&verify_lprime_out,
|
||||
&verify_lprime_out,
|
||||
sizeof(verify_lprime_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
|
||||
@@ -337,14 +340,15 @@ intel_hdcp_gsc_verify_lprime(struct device *dev, struct hdcp_port_data *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intel_hdcp_gsc_get_session_key(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_ske_send_eks *ske_data)
|
||||
static int
|
||||
intel_hdcp_gsc_get_session_key(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_ske_send_eks *ske_data)
|
||||
{
|
||||
struct wired_cmd_get_session_key_in get_skey_in = {};
|
||||
struct wired_cmd_get_session_key_out get_skey_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !data || !ske_data)
|
||||
@@ -355,7 +359,7 @@ int intel_hdcp_gsc_get_session_key(struct device *dev,
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
get_skey_in.header.api_version = HDCP_API_VERSION;
|
||||
get_skey_in.header.command_id = WIRED_GET_SESSION_KEY;
|
||||
@@ -366,8 +370,8 @@ int intel_hdcp_gsc_get_session_key(struct device *dev,
|
||||
get_skey_in.port.physical_port = (u8)data->hdcp_ddi;
|
||||
get_skey_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&get_skey_in, sizeof(get_skey_in),
|
||||
(u8 *)&get_skey_out, sizeof(get_skey_out));
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &get_skey_in, sizeof(get_skey_in),
|
||||
&get_skey_out, sizeof(get_skey_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
|
||||
return byte;
|
||||
@@ -387,7 +391,7 @@ int intel_hdcp_gsc_get_session_key(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_rep_send_receiverid_list
|
||||
@@ -397,8 +401,8 @@ intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
|
||||
{
|
||||
struct wired_cmd_verify_repeater_in verify_repeater_in = {};
|
||||
struct wired_cmd_verify_repeater_out verify_repeater_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !rep_topology || !rep_send_ack || !data)
|
||||
@@ -409,7 +413,7 @@ intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
verify_repeater_in.header.api_version = HDCP_API_VERSION;
|
||||
verify_repeater_in.header.command_id = WIRED_VERIFY_REPEATER;
|
||||
@@ -430,9 +434,9 @@ intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
|
||||
memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,
|
||||
HDCP_2_2_RECEIVER_IDS_MAX_LEN);
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_repeater_in,
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &verify_repeater_in,
|
||||
sizeof(verify_repeater_in),
|
||||
(u8 *)&verify_repeater_out,
|
||||
&verify_repeater_out,
|
||||
sizeof(verify_repeater_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
|
||||
@@ -453,14 +457,15 @@ intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intel_hdcp_gsc_verify_mprime(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_rep_stream_ready *stream_ready)
|
||||
static int
|
||||
intel_hdcp_gsc_verify_mprime(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_rep_stream_ready *stream_ready)
|
||||
{
|
||||
struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
|
||||
struct wired_cmd_repeater_auth_stream_req_out verify_mprime_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
size_t cmd_size;
|
||||
|
||||
@@ -472,7 +477,7 @@ int intel_hdcp_gsc_verify_mprime(struct device *dev,
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
cmd_size = struct_size(verify_mprime_in, streams, data->k);
|
||||
if (cmd_size == SIZE_MAX)
|
||||
@@ -499,8 +504,8 @@ int intel_hdcp_gsc_verify_mprime(struct device *dev,
|
||||
|
||||
verify_mprime_in->k = cpu_to_be16(data->k);
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)verify_mprime_in, cmd_size,
|
||||
(u8 *)&verify_mprime_out,
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, verify_mprime_in, cmd_size,
|
||||
&verify_mprime_out,
|
||||
sizeof(verify_mprime_out));
|
||||
kfree(verify_mprime_in);
|
||||
if (byte < 0) {
|
||||
@@ -518,13 +523,13 @@ int intel_hdcp_gsc_verify_mprime(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intel_hdcp_gsc_enable_authentication(struct device *dev,
|
||||
struct hdcp_port_data *data)
|
||||
static int intel_hdcp_gsc_enable_authentication(struct device *dev,
|
||||
struct hdcp_port_data *data)
|
||||
{
|
||||
struct wired_cmd_enable_auth_in enable_auth_in = {};
|
||||
struct wired_cmd_enable_auth_out enable_auth_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !data)
|
||||
@@ -535,7 +540,7 @@ int intel_hdcp_gsc_enable_authentication(struct device *dev,
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
enable_auth_in.header.api_version = HDCP_API_VERSION;
|
||||
enable_auth_in.header.command_id = WIRED_ENABLE_AUTH;
|
||||
@@ -547,9 +552,9 @@ int intel_hdcp_gsc_enable_authentication(struct device *dev,
|
||||
enable_auth_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
|
||||
enable_auth_in.stream_type = data->streams[0].stream_type;
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&enable_auth_in,
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &enable_auth_in,
|
||||
sizeof(enable_auth_in),
|
||||
(u8 *)&enable_auth_out,
|
||||
&enable_auth_out,
|
||||
sizeof(enable_auth_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
|
||||
@@ -565,13 +570,13 @@ int intel_hdcp_gsc_enable_authentication(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
intel_hdcp_gsc_close_session(struct device *dev, struct hdcp_port_data *data)
|
||||
{
|
||||
struct wired_cmd_close_session_in session_close_in = {};
|
||||
struct wired_cmd_close_session_out session_close_out = {};
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct intel_display *display;
|
||||
struct drm_i915_private *i915;
|
||||
ssize_t byte;
|
||||
|
||||
if (!dev || !data)
|
||||
@@ -582,7 +587,7 @@ intel_hdcp_gsc_close_session(struct device *dev, struct hdcp_port_data *data)
|
||||
dev_err(dev, "DRM not initialized, aborting HDCP.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
i915 = to_i915(display->drm);
|
||||
gsc_context = display->hdcp.gsc_context;
|
||||
|
||||
session_close_in.header.api_version = HDCP_API_VERSION;
|
||||
session_close_in.header.command_id = WIRED_CLOSE_SESSION;
|
||||
@@ -594,9 +599,9 @@ intel_hdcp_gsc_close_session(struct device *dev, struct hdcp_port_data *data)
|
||||
session_close_in.port.physical_port = (u8)data->hdcp_ddi;
|
||||
session_close_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
|
||||
|
||||
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&session_close_in,
|
||||
byte = intel_hdcp_gsc_msg_send(gsc_context, &session_close_in,
|
||||
sizeof(session_close_in),
|
||||
(u8 *)&session_close_out,
|
||||
&session_close_out,
|
||||
sizeof(session_close_out));
|
||||
if (byte < 0) {
|
||||
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
|
||||
@@ -611,3 +616,57 @@ intel_hdcp_gsc_close_session(struct device *dev, struct hdcp_port_data *data)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i915_hdcp_ops gsc_hdcp_ops = {
|
||||
.initiate_hdcp2_session = intel_hdcp_gsc_initiate_session,
|
||||
.verify_receiver_cert_prepare_km =
|
||||
intel_hdcp_gsc_verify_receiver_cert_prepare_km,
|
||||
.verify_hprime = intel_hdcp_gsc_verify_hprime,
|
||||
.store_pairing_info = intel_hdcp_gsc_store_pairing_info,
|
||||
.initiate_locality_check = intel_hdcp_gsc_initiate_locality_check,
|
||||
.verify_lprime = intel_hdcp_gsc_verify_lprime,
|
||||
.get_session_key = intel_hdcp_gsc_get_session_key,
|
||||
.repeater_check_flow_prepare_ack =
|
||||
intel_hdcp_gsc_repeater_check_flow_prepare_ack,
|
||||
.verify_mprime = intel_hdcp_gsc_verify_mprime,
|
||||
.enable_hdcp_authentication = intel_hdcp_gsc_enable_authentication,
|
||||
.close_hdcp_session = intel_hdcp_gsc_close_session,
|
||||
};
|
||||
|
||||
int intel_hdcp_gsc_init(struct intel_display *display)
|
||||
{
|
||||
struct intel_hdcp_gsc_context *gsc_context;
|
||||
struct i915_hdcp_arbiter *arbiter;
|
||||
int ret = 0;
|
||||
|
||||
arbiter = kzalloc(sizeof(*arbiter), GFP_KERNEL);
|
||||
if (!arbiter)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&display->hdcp.hdcp_mutex);
|
||||
|
||||
gsc_context = intel_hdcp_gsc_context_alloc(display->drm);
|
||||
if (IS_ERR(gsc_context)) {
|
||||
ret = PTR_ERR(gsc_context);
|
||||
kfree(arbiter);
|
||||
goto out;
|
||||
}
|
||||
|
||||
display->hdcp.arbiter = arbiter;
|
||||
display->hdcp.arbiter->hdcp_dev = display->drm->dev;
|
||||
display->hdcp.arbiter->ops = &gsc_hdcp_ops;
|
||||
display->hdcp.gsc_context = gsc_context;
|
||||
|
||||
out:
|
||||
mutex_unlock(&display->hdcp.hdcp_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void intel_hdcp_gsc_fini(struct intel_display *display)
|
||||
{
|
||||
intel_hdcp_gsc_context_free(display->hdcp.gsc_context);
|
||||
display->hdcp.gsc_context = NULL;
|
||||
kfree(display->hdcp.arbiter);
|
||||
display->hdcp.arbiter = NULL;
|
||||
}
|
||||
|
||||
@@ -6,68 +6,9 @@
|
||||
#ifndef __INTEL_HDCP_GSC_MESSAGE_H__
|
||||
#define __INTEL_HDCP_GSC_MESSAGE_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct device;
|
||||
struct drm_i915_private;
|
||||
struct hdcp_port_data;
|
||||
struct hdcp2_ake_init;
|
||||
struct hdcp2_ake_send_cert;
|
||||
struct hdcp2_ake_no_stored_km;
|
||||
struct hdcp2_ake_send_hprime;
|
||||
struct hdcp2_ake_send_pairing_info;
|
||||
struct hdcp2_lc_init;
|
||||
struct hdcp2_lc_send_lprime;
|
||||
struct hdcp2_ske_send_eks;
|
||||
struct hdcp2_rep_send_receiverid_list;
|
||||
struct hdcp2_rep_send_ack;
|
||||
struct hdcp2_rep_stream_ready;
|
||||
struct intel_display;
|
||||
|
||||
ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
|
||||
size_t msg_in_len, u8 *msg_out,
|
||||
size_t msg_out_len);
|
||||
bool intel_hdcp_gsc_check_status(struct intel_display *display);
|
||||
int
|
||||
intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
|
||||
struct hdcp2_ake_init *ake_data);
|
||||
int
|
||||
intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_ake_send_cert *rx_cert,
|
||||
bool *km_stored,
|
||||
struct hdcp2_ake_no_stored_km
|
||||
*ek_pub_km,
|
||||
size_t *msg_sz);
|
||||
int
|
||||
intel_hdcp_gsc_verify_hprime(struct device *dev, struct hdcp_port_data *data,
|
||||
struct hdcp2_ake_send_hprime *rx_hprime);
|
||||
int
|
||||
intel_hdcp_gsc_store_pairing_info(struct device *dev, struct hdcp_port_data *data,
|
||||
struct hdcp2_ake_send_pairing_info *pairing_info);
|
||||
int
|
||||
intel_hdcp_gsc_initiate_locality_check(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_lc_init *lc_init_data);
|
||||
int
|
||||
intel_hdcp_gsc_verify_lprime(struct device *dev, struct hdcp_port_data *data,
|
||||
struct hdcp2_lc_send_lprime *rx_lprime);
|
||||
int intel_hdcp_gsc_get_session_key(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_ske_send_eks *ske_data);
|
||||
int
|
||||
intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_rep_send_receiverid_list
|
||||
*rep_topology,
|
||||
struct hdcp2_rep_send_ack
|
||||
*rep_send_ack);
|
||||
int intel_hdcp_gsc_verify_mprime(struct device *dev,
|
||||
struct hdcp_port_data *data,
|
||||
struct hdcp2_rep_stream_ready *stream_ready);
|
||||
int intel_hdcp_gsc_enable_authentication(struct device *dev,
|
||||
struct hdcp_port_data *data);
|
||||
int
|
||||
intel_hdcp_gsc_close_session(struct device *dev, struct hdcp_port_data *data);
|
||||
int intel_hdcp_gsc_init(struct intel_display *display);
|
||||
void intel_hdcp_gsc_fini(struct intel_display *display);
|
||||
|
||||
#endif /* __INTEL_HDCP_GSC_MESSAGE_H__ */
|
||||
|
||||
@@ -38,14 +38,15 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/intel/intel_lpe_audio.h>
|
||||
|
||||
#include <media/cec-notifier.h>
|
||||
|
||||
#include "g4x_hdmi.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_connector.h"
|
||||
@@ -715,7 +716,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder,
|
||||
struct hdmi_avi_infoframe *frame = &crtc_state->infoframes.avi.avi;
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
struct drm_connector *connector = conn_state->connector;
|
||||
struct intel_connector *connector = to_intel_connector(conn_state->connector);
|
||||
int ret;
|
||||
|
||||
if (!crtc_state->has_infoframe)
|
||||
@@ -724,7 +725,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder,
|
||||
crtc_state->infoframes.enable |=
|
||||
intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI);
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector,
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(frame, &connector->base,
|
||||
adjusted_mode);
|
||||
if (ret)
|
||||
return false;
|
||||
@@ -743,7 +744,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder,
|
||||
crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB);
|
||||
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_RGB) {
|
||||
drm_hdmi_avi_infoframe_quant_range(frame, connector,
|
||||
drm_hdmi_avi_infoframe_quant_range(frame, &connector->base,
|
||||
adjusted_mode,
|
||||
crtc_state->limited_color_range ?
|
||||
HDMI_QUANTIZATION_RANGE_LIMITED :
|
||||
@@ -769,7 +770,7 @@ intel_hdmi_compute_spd_infoframe(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
struct hdmi_spd_infoframe *frame = &crtc_state->infoframes.spd.spd;
|
||||
int ret;
|
||||
|
||||
@@ -779,7 +780,7 @@ intel_hdmi_compute_spd_infoframe(struct intel_encoder *encoder,
|
||||
crtc_state->infoframes.enable |=
|
||||
intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD);
|
||||
|
||||
if (IS_DGFX(i915))
|
||||
if (display->platform.dgfx)
|
||||
ret = hdmi_spd_infoframe_init(frame, "Intel", "Discrete gfx");
|
||||
else
|
||||
ret = hdmi_spd_infoframe_init(frame, "Intel", "Integrated gfx");
|
||||
@@ -979,7 +980,6 @@ static bool intel_hdmi_set_gcp_infoframe(struct intel_encoder *encoder,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
i915_reg_t reg;
|
||||
|
||||
@@ -989,9 +989,9 @@ static bool intel_hdmi_set_gcp_infoframe(struct intel_encoder *encoder,
|
||||
|
||||
if (HAS_DDI(display))
|
||||
reg = HSW_TVIDEO_DIP_GCP(display, crtc_state->cpu_transcoder);
|
||||
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
else if (display->platform.valleyview || display->platform.cherryview)
|
||||
reg = VLV_TVIDEO_DIP_GCP(crtc->pipe);
|
||||
else if (HAS_PCH_SPLIT(dev_priv))
|
||||
else if (HAS_PCH_SPLIT(display))
|
||||
reg = TVIDEO_DIP_GCP(crtc->pipe);
|
||||
else
|
||||
return false;
|
||||
@@ -1005,7 +1005,6 @@ void intel_hdmi_read_gcp_infoframe(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
i915_reg_t reg;
|
||||
|
||||
@@ -1015,9 +1014,9 @@ void intel_hdmi_read_gcp_infoframe(struct intel_encoder *encoder,
|
||||
|
||||
if (HAS_DDI(display))
|
||||
reg = HSW_TVIDEO_DIP_GCP(display, crtc_state->cpu_transcoder);
|
||||
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
else if (display->platform.valleyview || display->platform.cherryview)
|
||||
reg = VLV_TVIDEO_DIP_GCP(crtc->pipe);
|
||||
else if (HAS_PCH_SPLIT(dev_priv))
|
||||
else if (HAS_PCH_SPLIT(display))
|
||||
reg = TVIDEO_DIP_GCP(crtc->pipe);
|
||||
else
|
||||
return;
|
||||
@@ -1029,9 +1028,9 @@ static void intel_hdmi_compute_gcp_infoframe(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
|
||||
if (IS_G4X(dev_priv) || !crtc_state->has_infoframe)
|
||||
if (display->platform.g4x || !crtc_state->has_infoframe)
|
||||
return;
|
||||
|
||||
crtc_state->infoframes.enable |=
|
||||
@@ -1539,7 +1538,6 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *dig_port,
|
||||
struct intel_display *display = to_intel_display(dig_port);
|
||||
struct intel_hdmi *hdmi = &dig_port->hdmi;
|
||||
struct intel_connector *connector = hdmi->attached_connector;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
int ret;
|
||||
|
||||
if (!enable)
|
||||
@@ -1558,7 +1556,7 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *dig_port,
|
||||
* WA: To fix incorrect positioning of the window of
|
||||
* opportunity and enc_en signalling in KABYLAKE.
|
||||
*/
|
||||
if (IS_KABYLAKE(dev_priv) && enable)
|
||||
if (display->platform.kabylake && enable)
|
||||
return kbl_repositioning_enc_en_signal(connector,
|
||||
cpu_transcoder);
|
||||
|
||||
@@ -1570,7 +1568,6 @@ bool intel_hdmi_hdcp_check_link_once(struct intel_digital_port *dig_port,
|
||||
struct intel_connector *connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(dig_port);
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
enum port port = dig_port->base.port;
|
||||
enum transcoder cpu_transcoder = connector->hdcp.cpu_transcoder;
|
||||
int ret;
|
||||
@@ -1583,15 +1580,15 @@ bool intel_hdmi_hdcp_check_link_once(struct intel_digital_port *dig_port,
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
intel_de_write(i915, HDCP_RPRIME(i915, cpu_transcoder, port), ri.reg);
|
||||
intel_de_write(display, HDCP_RPRIME(display, cpu_transcoder, port), ri.reg);
|
||||
|
||||
/* Wait for Ri prime match */
|
||||
if (wait_for((intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)) &
|
||||
if (wait_for((intel_de_read(display, HDCP_STATUS(display, cpu_transcoder, port)) &
|
||||
(HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC)) ==
|
||||
(HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) {
|
||||
drm_dbg_kms(display->drm, "Ri' mismatch detected (%x)\n",
|
||||
intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder,
|
||||
port)));
|
||||
intel_de_read(display, HDCP_STATUS(display, cpu_transcoder,
|
||||
port)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -1814,14 +1811,13 @@ static const struct intel_hdcp_shim intel_hdmi_hdcp_shim = {
|
||||
static int intel_hdmi_source_max_tmds_clock(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
int max_tmds_clock, vbt_max_tmds_clock;
|
||||
|
||||
if (DISPLAY_VER(display) >= 13 || IS_ALDERLAKE_S(dev_priv))
|
||||
if (DISPLAY_VER(display) >= 13 || display->platform.alderlake_s)
|
||||
max_tmds_clock = 600000;
|
||||
else if (DISPLAY_VER(display) >= 10)
|
||||
max_tmds_clock = 594000;
|
||||
else if (DISPLAY_VER(display) >= 8 || IS_HASWELL(dev_priv))
|
||||
else if (DISPLAY_VER(display) >= 8 || display->platform.haswell)
|
||||
max_tmds_clock = 300000;
|
||||
else if (DISPLAY_VER(display) >= 5)
|
||||
max_tmds_clock = 225000;
|
||||
@@ -1880,7 +1876,6 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
|
||||
bool has_hdmi_sink)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(hdmi);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_encoder *encoder = &hdmi_to_dig_port(hdmi)->base;
|
||||
|
||||
if (clock < 25000)
|
||||
@@ -1890,16 +1885,16 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
/* GLK DPLL can't generate 446-480 MHz */
|
||||
if (IS_GEMINILAKE(dev_priv) && clock > 446666 && clock < 480000)
|
||||
if (display->platform.geminilake && clock > 446666 && clock < 480000)
|
||||
return MODE_CLOCK_RANGE;
|
||||
|
||||
/* BXT/GLK DPLL can't generate 223-240 MHz */
|
||||
if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
|
||||
if ((display->platform.geminilake || display->platform.broxton) &&
|
||||
clock > 223333 && clock < 240000)
|
||||
return MODE_CLOCK_RANGE;
|
||||
|
||||
/* CHV DPLL can't generate 216-240 MHz */
|
||||
if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000)
|
||||
if (display->platform.cherryview && clock > 216000 && clock < 240000)
|
||||
return MODE_CLOCK_RANGE;
|
||||
|
||||
/* ICL+ combo PHY PLL can't generate 500-533.2 MHz */
|
||||
@@ -1943,11 +1938,12 @@ static bool intel_hdmi_source_bpc_possible(struct intel_display *display, int bp
|
||||
}
|
||||
}
|
||||
|
||||
static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector,
|
||||
static bool intel_hdmi_sink_bpc_possible(struct drm_connector *_connector,
|
||||
int bpc, bool has_hdmi_sink,
|
||||
enum intel_output_format sink_format)
|
||||
{
|
||||
const struct drm_display_info *info = &connector->display_info;
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
const struct drm_hdmi_info *hdmi = &info->hdmi;
|
||||
|
||||
switch (bpc) {
|
||||
@@ -1976,12 +1972,13 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector,
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock,
|
||||
intel_hdmi_mode_clock_valid(struct drm_connector *_connector, int clock,
|
||||
bool has_hdmi_sink,
|
||||
enum intel_output_format sink_format)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
|
||||
enum drm_mode_status status = MODE_OK;
|
||||
int bpc;
|
||||
|
||||
@@ -1996,7 +1993,8 @@ intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock,
|
||||
if (!intel_hdmi_source_bpc_possible(display, bpc))
|
||||
continue;
|
||||
|
||||
if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, sink_format))
|
||||
if (!intel_hdmi_sink_bpc_possible(&connector->base, bpc, has_hdmi_sink,
|
||||
sink_format))
|
||||
continue;
|
||||
|
||||
status = hdmi_port_clock_valid(hdmi, tmds_clock, true, has_hdmi_sink);
|
||||
@@ -2011,15 +2009,16 @@ intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock,
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
intel_hdmi_mode_valid(struct drm_connector *connector,
|
||||
intel_hdmi_mode_valid(struct drm_connector *_connector,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
|
||||
enum drm_mode_status status;
|
||||
int clock = mode->clock;
|
||||
int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
|
||||
bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state);
|
||||
int max_dotclk = display->cdclk.max_dotclk_freq;
|
||||
bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->base.state);
|
||||
bool ycbcr_420_only;
|
||||
enum intel_output_format sink_format;
|
||||
|
||||
@@ -2048,22 +2047,23 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
|
||||
if (clock > 600000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, mode);
|
||||
ycbcr_420_only = drm_mode_is_420_only(&connector->base.display_info, mode);
|
||||
|
||||
if (ycbcr_420_only)
|
||||
sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
|
||||
else
|
||||
sink_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
|
||||
status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, sink_format);
|
||||
status = intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink, sink_format);
|
||||
if (status != MODE_OK) {
|
||||
if (ycbcr_420_only ||
|
||||
!connector->ycbcr_420_allowed ||
|
||||
!drm_mode_is_420_also(&connector->display_info, mode))
|
||||
!connector->base.ycbcr_420_allowed ||
|
||||
!drm_mode_is_420_also(&connector->base.display_info, mode))
|
||||
return status;
|
||||
|
||||
sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
|
||||
status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, sink_format);
|
||||
status = intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink,
|
||||
sink_format);
|
||||
if (status != MODE_OK)
|
||||
return status;
|
||||
}
|
||||
@@ -2074,16 +2074,16 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
|
||||
bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
|
||||
int bpc, bool has_hdmi_sink)
|
||||
{
|
||||
struct drm_atomic_state *state = crtc_state->uapi.state;
|
||||
struct drm_connector_state *connector_state;
|
||||
struct drm_connector *connector;
|
||||
struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
|
||||
struct intel_digital_connector_state *connector_state;
|
||||
struct intel_connector *connector;
|
||||
int i;
|
||||
|
||||
for_each_new_connector_in_state(state, connector, connector_state, i) {
|
||||
if (connector_state->crtc != crtc_state->uapi.crtc)
|
||||
for_each_new_intel_connector_in_state(state, connector, connector_state, i) {
|
||||
if (connector_state->base.crtc != crtc_state->uapi.crtc)
|
||||
continue;
|
||||
|
||||
if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink,
|
||||
if (!intel_hdmi_sink_bpc_possible(&connector->base, bpc, has_hdmi_sink,
|
||||
crtc_state->sink_format))
|
||||
return false;
|
||||
}
|
||||
@@ -2211,7 +2211,7 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_connector *connector = conn_state->connector;
|
||||
struct intel_connector *connector = to_intel_connector(conn_state->connector);
|
||||
const struct intel_digital_connector_state *intel_conn_state =
|
||||
to_intel_digital_connector_state(conn_state);
|
||||
|
||||
@@ -2219,7 +2219,7 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
|
||||
return false;
|
||||
|
||||
if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
|
||||
return connector->display_info.has_audio;
|
||||
return connector->base.display_info.has_audio;
|
||||
else
|
||||
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
|
||||
}
|
||||
@@ -2323,14 +2323,14 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
|
||||
struct drm_connector *connector = conn_state->connector;
|
||||
struct drm_scdc *scdc = &connector->display_info.hdmi.scdc;
|
||||
struct intel_connector *connector = to_intel_connector(conn_state->connector);
|
||||
struct drm_scdc *scdc = &connector->base.display_info.hdmi.scdc;
|
||||
int ret;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return -EINVAL;
|
||||
|
||||
if (!connector->interlace_allowed &&
|
||||
if (!connector->base.interlace_allowed &&
|
||||
adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -2425,25 +2425,26 @@ void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder)
|
||||
}
|
||||
|
||||
static void
|
||||
intel_hdmi_unset_edid(struct drm_connector *connector)
|
||||
intel_hdmi_unset_edid(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
|
||||
intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE;
|
||||
intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
|
||||
|
||||
drm_edid_free(to_intel_connector(connector)->detect_edid);
|
||||
to_intel_connector(connector)->detect_edid = NULL;
|
||||
drm_edid_free(connector->detect_edid);
|
||||
connector->detect_edid = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
|
||||
intel_hdmi_dp_dual_mode_detect(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
|
||||
struct intel_encoder *encoder = &hdmi_to_dig_port(hdmi)->base;
|
||||
struct i2c_adapter *ddc = connector->ddc;
|
||||
struct i2c_adapter *ddc = connector->base.ddc;
|
||||
enum drm_dp_dual_mode_type type;
|
||||
|
||||
type = drm_dp_dual_mode_detect(display->drm, ddc);
|
||||
@@ -2458,7 +2459,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
|
||||
* if the port is a dual mode capable DP port.
|
||||
*/
|
||||
if (type == DRM_DP_DUAL_MODE_UNKNOWN) {
|
||||
if (!connector->force &&
|
||||
if (!connector->base.force &&
|
||||
intel_bios_encoder_supports_dp_dual_mode(encoder->devdata)) {
|
||||
drm_dbg_kms(display->drm,
|
||||
"Assuming DP dual mode adaptor presence based on VBT\n");
|
||||
@@ -2481,7 +2482,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
|
||||
hdmi->dp_dual_mode.max_tmds_clock);
|
||||
|
||||
/* Older VBTs are often buggy and can't be trusted :( Play it safe. */
|
||||
if ((DISPLAY_VER(display) >= 8 || IS_HASWELL(dev_priv)) &&
|
||||
if ((DISPLAY_VER(display) >= 8 || display->platform.haswell) &&
|
||||
!intel_bios_encoder_supports_dp_dual_mode(encoder->devdata)) {
|
||||
drm_dbg_kms(display->drm,
|
||||
"Ignoring DP dual mode adaptor max TMDS clock for native HDMI port\n");
|
||||
@@ -2490,34 +2491,35 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_hdmi_set_edid(struct drm_connector *connector)
|
||||
intel_hdmi_set_edid(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
|
||||
struct i2c_adapter *ddc = connector->ddc;
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
struct i2c_adapter *ddc = connector->base.ddc;
|
||||
intel_wakeref_t wakeref;
|
||||
const struct drm_edid *drm_edid;
|
||||
bool connected = false;
|
||||
|
||||
wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS);
|
||||
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
drm_edid = drm_edid_read_ddc(&connector->base, ddc);
|
||||
|
||||
if (!drm_edid && !intel_gmbus_is_forced_bit(ddc)) {
|
||||
drm_dbg_kms(display->drm,
|
||||
"HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n");
|
||||
intel_gmbus_force_bit(ddc, true);
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
drm_edid = drm_edid_read_ddc(&connector->base, ddc);
|
||||
intel_gmbus_force_bit(ddc, false);
|
||||
}
|
||||
|
||||
/* Below we depend on display info having been updated */
|
||||
drm_edid_connector_update(connector, drm_edid);
|
||||
drm_edid_connector_update(&connector->base, drm_edid);
|
||||
|
||||
to_intel_connector(connector)->detect_edid = drm_edid;
|
||||
connector->detect_edid = drm_edid;
|
||||
|
||||
if (drm_edid_is_digital(drm_edid)) {
|
||||
intel_hdmi_dp_dual_mode_detect(connector);
|
||||
intel_hdmi_dp_dual_mode_detect(&connector->base);
|
||||
|
||||
connected = true;
|
||||
}
|
||||
@@ -2525,28 +2527,29 @@ intel_hdmi_set_edid(struct drm_connector *connector)
|
||||
intel_display_power_put(display, POWER_DOMAIN_GMBUS, wakeref);
|
||||
|
||||
cec_notifier_set_phys_addr(intel_hdmi->cec_notifier,
|
||||
connector->display_info.source_physical_address);
|
||||
connector->base.display_info.source_physical_address);
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
intel_hdmi_detect(struct drm_connector *connector, bool force)
|
||||
intel_hdmi_detect(struct drm_connector *_connector, bool force)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
enum drm_connector_status status = connector_status_disconnected;
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n",
|
||||
connector->base.id, connector->name);
|
||||
connector->base.base.id, connector->base.name);
|
||||
|
||||
if (!intel_display_device_enabled(display))
|
||||
return connector_status_disconnected;
|
||||
|
||||
if (!intel_display_driver_check_access(display))
|
||||
return connector->status;
|
||||
return connector->base.status;
|
||||
|
||||
wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS);
|
||||
|
||||
@@ -2554,9 +2557,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
|
||||
!intel_digital_port_connected(encoder))
|
||||
goto out;
|
||||
|
||||
intel_hdmi_unset_edid(connector);
|
||||
intel_hdmi_unset_edid(&connector->base);
|
||||
|
||||
if (intel_hdmi_set_edid(connector))
|
||||
if (intel_hdmi_set_edid(&connector->base))
|
||||
status = connector_status_connected;
|
||||
|
||||
out:
|
||||
@@ -2569,49 +2572,54 @@ out:
|
||||
}
|
||||
|
||||
static void
|
||||
intel_hdmi_force(struct drm_connector *connector)
|
||||
intel_hdmi_force(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
|
||||
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n",
|
||||
connector->base.id, connector->name);
|
||||
connector->base.base.id, connector->base.name);
|
||||
|
||||
if (!intel_display_driver_check_access(display))
|
||||
return;
|
||||
|
||||
intel_hdmi_unset_edid(connector);
|
||||
intel_hdmi_unset_edid(&connector->base);
|
||||
|
||||
if (connector->status != connector_status_connected)
|
||||
if (connector->base.status != connector_status_connected)
|
||||
return;
|
||||
|
||||
intel_hdmi_set_edid(connector);
|
||||
intel_hdmi_set_edid(&connector->base);
|
||||
}
|
||||
|
||||
static int intel_hdmi_get_modes(struct drm_connector *connector)
|
||||
static int intel_hdmi_get_modes(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
|
||||
/* drm_edid_connector_update() done in ->detect() or ->force() */
|
||||
return drm_edid_connector_add_modes(connector);
|
||||
return drm_edid_connector_add_modes(&connector->base);
|
||||
}
|
||||
|
||||
static int
|
||||
intel_hdmi_connector_register(struct drm_connector *connector)
|
||||
intel_hdmi_connector_register(struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
int ret;
|
||||
|
||||
ret = intel_connector_register(connector);
|
||||
ret = intel_connector_register(&connector->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void intel_hdmi_connector_unregister(struct drm_connector *connector)
|
||||
static void intel_hdmi_connector_unregister(struct drm_connector *_connector)
|
||||
{
|
||||
struct cec_notifier *n = intel_attached_hdmi(to_intel_connector(connector))->cec_notifier;
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct cec_notifier *n = intel_attached_hdmi(connector)->cec_notifier;
|
||||
|
||||
cec_notifier_conn_unregister(n);
|
||||
|
||||
intel_connector_unregister(connector);
|
||||
intel_connector_unregister(&connector->base);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
||||
@@ -2627,15 +2635,16 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
||||
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
|
||||
};
|
||||
|
||||
static int intel_hdmi_connector_atomic_check(struct drm_connector *connector,
|
||||
static int intel_hdmi_connector_atomic_check(struct drm_connector *_connector,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
|
||||
if (HAS_DDI(display))
|
||||
return intel_digital_connector_atomic_check(connector, state);
|
||||
return intel_digital_connector_atomic_check(&connector->base, state);
|
||||
else
|
||||
return g4x_hdmi_connector_atomic_check(connector, state);
|
||||
return g4x_hdmi_connector_atomic_check(&connector->base, state);
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = {
|
||||
@@ -2645,22 +2654,23 @@ static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs
|
||||
};
|
||||
|
||||
static void
|
||||
intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
|
||||
intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *_connector)
|
||||
{
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(intel_hdmi);
|
||||
|
||||
intel_attach_force_audio_property(connector);
|
||||
intel_attach_broadcast_rgb_property(connector);
|
||||
intel_attach_aspect_ratio_property(connector);
|
||||
intel_attach_force_audio_property(&connector->base);
|
||||
intel_attach_broadcast_rgb_property(&connector->base);
|
||||
intel_attach_aspect_ratio_property(&connector->base);
|
||||
|
||||
intel_attach_hdmi_colorspace_property(connector);
|
||||
drm_connector_attach_content_type_property(connector);
|
||||
intel_attach_hdmi_colorspace_property(&connector->base);
|
||||
drm_connector_attach_content_type_property(&connector->base);
|
||||
|
||||
if (DISPLAY_VER(display) >= 10)
|
||||
drm_connector_attach_hdr_output_metadata_property(connector);
|
||||
drm_connector_attach_hdr_output_metadata_property(&connector->base);
|
||||
|
||||
if (!HAS_GMCH(display))
|
||||
drm_connector_attach_max_bpc_property(connector, 8, 12);
|
||||
drm_connector_attach_max_bpc_property(&connector->base, 8, 12);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2682,25 +2692,26 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
|
||||
* True on success, false on failure.
|
||||
*/
|
||||
bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder,
|
||||
struct drm_connector *connector,
|
||||
struct drm_connector *_connector,
|
||||
bool high_tmds_clock_ratio,
|
||||
bool scrambling)
|
||||
{
|
||||
struct intel_connector *connector = to_intel_connector(_connector);
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_scrambling *sink_scrambling =
|
||||
&connector->display_info.hdmi.scdc.scrambling;
|
||||
&connector->base.display_info.hdmi.scdc.scrambling;
|
||||
|
||||
if (!sink_scrambling->supported)
|
||||
return true;
|
||||
|
||||
drm_dbg_kms(display->drm,
|
||||
"[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n",
|
||||
connector->base.id, connector->name,
|
||||
connector->base.base.id, connector->base.name,
|
||||
str_yes_no(scrambling), high_tmds_clock_ratio ? 40 : 10);
|
||||
|
||||
/* Set TMDS bit clock ratio to 1/40 or 1/10, and enable/disable scrambling */
|
||||
return drm_scdc_set_high_tmds_clock_ratio(connector, high_tmds_clock_ratio) &&
|
||||
drm_scdc_set_scrambling(connector, scrambling);
|
||||
return drm_scdc_set_high_tmds_clock_ratio(&connector->base, high_tmds_clock_ratio) &&
|
||||
drm_scdc_set_scrambling(&connector->base, scrambling);
|
||||
}
|
||||
|
||||
static u8 chv_encoder_to_ddc_pin(struct intel_encoder *encoder)
|
||||
@@ -2811,7 +2822,7 @@ static u8 mcc_encoder_to_ddc_pin(struct intel_encoder *encoder)
|
||||
|
||||
static u8 rkl_encoder_to_ddc_pin(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
enum phy phy = intel_encoder_to_phy(encoder);
|
||||
|
||||
WARN_ON(encoder->port == PORT_C);
|
||||
@@ -2822,7 +2833,7 @@ static u8 rkl_encoder_to_ddc_pin(struct intel_encoder *encoder)
|
||||
* combo outputs. With CMP, the traditional DDI A-D pins are used for
|
||||
* all outputs.
|
||||
*/
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP && phy >= PHY_C)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_TGP && phy >= PHY_C)
|
||||
return GMBUS_PIN_9_TC1_ICP + phy - PHY_C;
|
||||
|
||||
return GMBUS_PIN_1_BXT + phy;
|
||||
@@ -2831,7 +2842,6 @@ static u8 rkl_encoder_to_ddc_pin(struct intel_encoder *encoder)
|
||||
static u8 gen9bc_tgp_encoder_to_ddc_pin(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
enum phy phy = intel_encoder_to_phy(encoder);
|
||||
|
||||
drm_WARN_ON(display->drm, encoder->port == PORT_A);
|
||||
@@ -2842,7 +2852,7 @@ static u8 gen9bc_tgp_encoder_to_ddc_pin(struct intel_encoder *encoder)
|
||||
* combo outputs. With CMP, the traditional DDI A-D pins are used for
|
||||
* all outputs.
|
||||
*/
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_TGP && phy >= PHY_C)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_TGP && phy >= PHY_C)
|
||||
return GMBUS_PIN_9_TC1_ICP + phy - PHY_C;
|
||||
|
||||
return GMBUS_PIN_1_BXT + phy;
|
||||
@@ -2895,27 +2905,26 @@ static u8 g4x_encoder_to_ddc_pin(struct intel_encoder *encoder)
|
||||
static u8 intel_hdmi_default_ddc_pin(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u8 ddc_pin;
|
||||
|
||||
if (IS_ALDERLAKE_S(dev_priv))
|
||||
if (display->platform.alderlake_s)
|
||||
ddc_pin = adls_encoder_to_ddc_pin(encoder);
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_DG1)
|
||||
ddc_pin = dg1_encoder_to_ddc_pin(encoder);
|
||||
else if (IS_ROCKETLAKE(dev_priv))
|
||||
else if (display->platform.rocketlake)
|
||||
ddc_pin = rkl_encoder_to_ddc_pin(encoder);
|
||||
else if (DISPLAY_VER(display) == 9 && HAS_PCH_TGP(dev_priv))
|
||||
else if (DISPLAY_VER(display) == 9 && HAS_PCH_TGP(display))
|
||||
ddc_pin = gen9bc_tgp_encoder_to_ddc_pin(encoder);
|
||||
else if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) &&
|
||||
HAS_PCH_TGP(dev_priv))
|
||||
else if ((display->platform.jasperlake || display->platform.elkhartlake) &&
|
||||
HAS_PCH_TGP(display))
|
||||
ddc_pin = mcc_encoder_to_ddc_pin(encoder);
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
ddc_pin = icl_encoder_to_ddc_pin(encoder);
|
||||
else if (HAS_PCH_CNP(dev_priv))
|
||||
else if (HAS_PCH_CNP(display))
|
||||
ddc_pin = cnp_encoder_to_ddc_pin(encoder);
|
||||
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
|
||||
else if (display->platform.geminilake || display->platform.broxton)
|
||||
ddc_pin = bxt_encoder_to_ddc_pin(encoder);
|
||||
else if (IS_CHERRYVIEW(dev_priv))
|
||||
else if (display->platform.cherryview)
|
||||
ddc_pin = chv_encoder_to_ddc_pin(encoder);
|
||||
else
|
||||
ddc_pin = g4x_encoder_to_ddc_pin(encoder);
|
||||
@@ -2989,15 +2998,13 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder)
|
||||
void intel_infoframe_init(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(dig_port);
|
||||
struct drm_i915_private *dev_priv =
|
||||
to_i915(dig_port->base.base.dev);
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
if (display->platform.valleyview || display->platform.cherryview) {
|
||||
dig_port->write_infoframe = vlv_write_infoframe;
|
||||
dig_port->read_infoframe = vlv_read_infoframe;
|
||||
dig_port->set_infoframes = vlv_set_infoframes;
|
||||
dig_port->infoframes_enabled = vlv_infoframes_enabled;
|
||||
} else if (IS_G4X(dev_priv)) {
|
||||
} else if (display->platform.g4x) {
|
||||
dig_port->write_infoframe = g4x_write_infoframe;
|
||||
dig_port->read_infoframe = g4x_read_infoframe;
|
||||
dig_port->set_infoframes = g4x_set_infoframes;
|
||||
@@ -3014,7 +3021,7 @@ void intel_infoframe_init(struct intel_digital_port *dig_port)
|
||||
dig_port->set_infoframes = hsw_set_infoframes;
|
||||
dig_port->infoframes_enabled = hsw_infoframes_enabled;
|
||||
}
|
||||
} else if (HAS_PCH_IBX(dev_priv)) {
|
||||
} else if (HAS_PCH_IBX(display)) {
|
||||
dig_port->write_infoframe = ibx_write_infoframe;
|
||||
dig_port->read_infoframe = ibx_read_infoframe;
|
||||
dig_port->set_infoframes = ibx_set_infoframes;
|
||||
|
||||
@@ -183,9 +183,7 @@ static bool intel_hpd_irq_storm_detect(struct intel_display *display,
|
||||
|
||||
static bool detection_work_enabled(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
lockdep_assert_held(&i915->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
return display->hotplug.detection_work_enabled;
|
||||
}
|
||||
@@ -195,7 +193,7 @@ mod_delayed_detection_work(struct intel_display *display, struct delayed_work *w
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
lockdep_assert_held(&i915->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if (!detection_work_enabled(display))
|
||||
return false;
|
||||
@@ -208,7 +206,7 @@ queue_delayed_detection_work(struct intel_display *display, struct delayed_work
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
lockdep_assert_held(&i915->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if (!detection_work_enabled(display))
|
||||
return false;
|
||||
@@ -221,7 +219,7 @@ queue_detection_work(struct intel_display *display, struct work_struct *work)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
lockdep_assert_held(&i915->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if (!detection_work_enabled(display))
|
||||
return false;
|
||||
@@ -232,12 +230,11 @@ queue_detection_work(struct intel_display *display, struct work_struct *work)
|
||||
static void
|
||||
intel_hpd_irq_storm_switch_to_polling(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_connector *connector;
|
||||
bool hpd_disabled = false;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
drm_connector_list_iter_begin(display->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
@@ -276,7 +273,6 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
|
||||
{
|
||||
struct intel_display *display =
|
||||
container_of(work, typeof(*display), hotplug.reenable_work.work);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_connector *connector;
|
||||
struct ref_tracker *wakeref;
|
||||
@@ -284,7 +280,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
|
||||
|
||||
wakeref = intel_display_rpm_get(display);
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
drm_connector_list_iter_begin(display->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
@@ -308,7 +304,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
|
||||
|
||||
intel_hpd_irq_setup(display);
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
intel_display_rpm_put(display, wakeref);
|
||||
}
|
||||
@@ -376,9 +372,7 @@ static bool hpd_pin_has_pulse(struct intel_display *display, enum hpd_pin pin)
|
||||
|
||||
static bool hpd_pin_is_blocked(struct intel_display *display, enum hpd_pin pin)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
lockdep_assert_held(&i915->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
return display->hotplug.stats[pin].blocked_count;
|
||||
}
|
||||
@@ -400,14 +394,13 @@ static void i915_digport_work_func(struct work_struct *work)
|
||||
{
|
||||
struct intel_display *display =
|
||||
container_of(work, struct intel_display, hotplug.dig_port_work);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
u32 long_hpd_pin_mask, short_hpd_pin_mask;
|
||||
struct intel_encoder *encoder;
|
||||
u32 blocked_hpd_pin_mask;
|
||||
u32 old_bits = 0;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
blocked_hpd_pin_mask = get_blocked_hpd_pin_mask(display);
|
||||
long_hpd_pin_mask = hotplug->long_hpd_pin_mask & ~blocked_hpd_pin_mask;
|
||||
@@ -415,7 +408,7 @@ static void i915_digport_work_func(struct work_struct *work)
|
||||
short_hpd_pin_mask = hotplug->short_hpd_pin_mask & ~blocked_hpd_pin_mask;
|
||||
hotplug->short_hpd_pin_mask &= ~short_hpd_pin_mask;
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
for_each_intel_encoder(display->drm, encoder) {
|
||||
struct intel_digital_port *dig_port;
|
||||
@@ -442,11 +435,11 @@ static void i915_digport_work_func(struct work_struct *work)
|
||||
}
|
||||
|
||||
if (old_bits) {
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
display->hotplug.event_bits |= old_bits;
|
||||
queue_delayed_detection_work(display,
|
||||
&display->hotplug.hotplug_work, 0);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,17 +453,16 @@ static void i915_digport_work_func(struct work_struct *work)
|
||||
void intel_hpd_trigger_irq(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(dig_port);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
struct intel_encoder *encoder = &dig_port->base;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
hotplug->short_hpd_pin_mask |= BIT(encoder->hpd_pin);
|
||||
if (!hpd_pin_is_blocked(display, encoder->hpd_pin))
|
||||
queue_work(hotplug->dp_wq, &hotplug->dig_port_work);
|
||||
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -480,7 +472,6 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
{
|
||||
struct intel_display *display =
|
||||
container_of(work, struct intel_display, hotplug.hotplug_work.work);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_connector *connector;
|
||||
@@ -494,7 +485,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
mutex_lock(&display->drm->mode_config.mutex);
|
||||
drm_dbg_kms(display->drm, "running encoder hotplug functions\n");
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
blocked_hpd_pin_mask = get_blocked_hpd_pin_mask(display);
|
||||
hpd_event_bits = hotplug->event_bits & ~blocked_hpd_pin_mask;
|
||||
@@ -505,7 +496,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
/* Enable polling for connectors which had HPD IRQ storms */
|
||||
intel_hpd_irq_storm_switch_to_polling(display);
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
/* Skip calling encode hotplug handlers if ignore long HPD set*/
|
||||
if (display->hotplug.ignore_long_hpd) {
|
||||
@@ -569,13 +560,13 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
/* Remove shared HPD pins that have changed */
|
||||
retry &= ~changed;
|
||||
if (retry) {
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
display->hotplug.retry_bits |= retry;
|
||||
|
||||
mod_delayed_detection_work(display,
|
||||
&display->hotplug.hotplug_work,
|
||||
msecs_to_jiffies(HPD_RETRY_DELAY));
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,7 +590,6 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
void intel_hpd_irq_handler(struct intel_display *display,
|
||||
u32 pin_mask, u32 long_mask)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_encoder *encoder;
|
||||
bool storm_detected = false;
|
||||
bool queue_dig = false, queue_hp = false;
|
||||
@@ -610,7 +600,7 @@ void intel_hpd_irq_handler(struct intel_display *display,
|
||||
if (!pin_mask)
|
||||
return;
|
||||
|
||||
spin_lock(&dev_priv->irq_lock);
|
||||
spin_lock(&display->irq.lock);
|
||||
|
||||
/*
|
||||
* Determine whether ->hpd_pulse() exists for each pin, and
|
||||
@@ -711,7 +701,7 @@ void intel_hpd_irq_handler(struct intel_display *display,
|
||||
queue_delayed_detection_work(display,
|
||||
&display->hotplug.hotplug_work, 0);
|
||||
|
||||
spin_unlock(&dev_priv->irq_lock);
|
||||
spin_unlock(&display->irq.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -730,7 +720,6 @@ void intel_hpd_irq_handler(struct intel_display *display,
|
||||
*/
|
||||
void intel_hpd_init(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
int i;
|
||||
|
||||
if (!HAS_DISPLAY(display))
|
||||
@@ -745,9 +734,9 @@ void intel_hpd_init(struct intel_display *display)
|
||||
* Interrupt setup is already guaranteed to be single-threaded, this is
|
||||
* just to make the assert_spin_locked checks happy.
|
||||
*/
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
intel_hpd_irq_setup(display);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static void i915_hpd_poll_detect_connectors(struct intel_display *display)
|
||||
@@ -797,7 +786,6 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
|
||||
{
|
||||
struct intel_display *display =
|
||||
container_of(work, typeof(*display), hotplug.poll_init_work);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_connector *connector;
|
||||
intel_wakeref_t wakeref;
|
||||
@@ -820,7 +808,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
|
||||
cancel_work(&display->hotplug.poll_init_work);
|
||||
}
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
drm_connector_list_iter_begin(display->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
@@ -841,7 +829,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
if (enabled)
|
||||
drm_kms_helper_poll_reschedule(display->drm);
|
||||
@@ -879,8 +867,6 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
|
||||
*/
|
||||
void intel_hpd_poll_enable(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (!HAS_DISPLAY(display) || !intel_display_device_enabled(display))
|
||||
return;
|
||||
|
||||
@@ -892,10 +878,10 @@ void intel_hpd_poll_enable(struct intel_display *display)
|
||||
* As well, there's no issue if we race here since we always reschedule
|
||||
* this worker anyway
|
||||
*/
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
queue_detection_work(display,
|
||||
&display->hotplug.poll_init_work);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -919,17 +905,15 @@ void intel_hpd_poll_enable(struct intel_display *display)
|
||||
*/
|
||||
void intel_hpd_poll_disable(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (!HAS_DISPLAY(display))
|
||||
return;
|
||||
|
||||
WRITE_ONCE(display->hotplug.poll_enabled, false);
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
queue_detection_work(display,
|
||||
&display->hotplug.poll_init_work);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
void intel_hpd_poll_fini(struct intel_display *display)
|
||||
@@ -981,12 +965,10 @@ static bool cancel_all_detection_work(struct intel_display *display)
|
||||
|
||||
void intel_hpd_cancel_work(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (!HAS_DISPLAY(display))
|
||||
return;
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
drm_WARN_ON(display->drm, get_blocked_hpd_pin_mask(display));
|
||||
|
||||
@@ -995,7 +977,7 @@ void intel_hpd_cancel_work(struct intel_display *display)
|
||||
display->hotplug.event_bits = 0;
|
||||
display->hotplug.retry_bits = 0;
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
cancel_work_sync(&display->hotplug.dig_port_work);
|
||||
|
||||
@@ -1009,13 +991,12 @@ void intel_hpd_cancel_work(struct intel_display *display)
|
||||
|
||||
static void queue_work_for_missed_irqs(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
bool queue_hp_work = false;
|
||||
u32 blocked_hpd_pin_mask;
|
||||
enum hpd_pin pin;
|
||||
|
||||
lockdep_assert_held(&i915->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
blocked_hpd_pin_mask = get_blocked_hpd_pin_mask(display);
|
||||
if ((hotplug->event_bits | hotplug->retry_bits) & ~blocked_hpd_pin_mask)
|
||||
@@ -1043,10 +1024,9 @@ static void queue_work_for_missed_irqs(struct intel_display *display)
|
||||
|
||||
static bool block_hpd_pin(struct intel_display *display, enum hpd_pin pin)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
|
||||
lockdep_assert_held(&i915->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
hotplug->stats[pin].blocked_count++;
|
||||
|
||||
@@ -1055,10 +1035,9 @@ static bool block_hpd_pin(struct intel_display *display, enum hpd_pin pin)
|
||||
|
||||
static bool unblock_hpd_pin(struct intel_display *display, enum hpd_pin pin)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
|
||||
lockdep_assert_held(&i915->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
if (drm_WARN_ON(display->drm, hotplug->stats[pin].blocked_count == 0))
|
||||
return true;
|
||||
@@ -1095,19 +1074,18 @@ static bool unblock_hpd_pin(struct intel_display *display, enum hpd_pin pin)
|
||||
void intel_hpd_block(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
bool do_flush = false;
|
||||
|
||||
if (encoder->hpd_pin == HPD_NONE)
|
||||
return;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
if (block_hpd_pin(display, encoder->hpd_pin))
|
||||
do_flush = true;
|
||||
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
if (do_flush && hpd_pin_has_pulse(display, encoder->hpd_pin))
|
||||
flush_work(&hotplug->dig_port_work);
|
||||
@@ -1125,17 +1103,16 @@ void intel_hpd_block(struct intel_encoder *encoder)
|
||||
void intel_hpd_unblock(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (encoder->hpd_pin == HPD_NONE)
|
||||
return;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
if (unblock_hpd_pin(display, encoder->hpd_pin))
|
||||
queue_work_for_missed_irqs(display);
|
||||
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1149,14 +1126,13 @@ void intel_hpd_unblock(struct intel_encoder *encoder)
|
||||
void intel_hpd_clear_and_unblock(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
enum hpd_pin pin = encoder->hpd_pin;
|
||||
|
||||
if (pin == HPD_NONE)
|
||||
return;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
|
||||
if (unblock_hpd_pin(display, pin)) {
|
||||
hotplug->event_bits &= ~BIT(pin);
|
||||
@@ -1165,39 +1141,34 @@ void intel_hpd_clear_and_unblock(struct intel_encoder *encoder)
|
||||
hotplug->long_hpd_pin_mask &= ~BIT(pin);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
void intel_hpd_enable_detection_work(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
display->hotplug.detection_work_enabled = true;
|
||||
queue_work_for_missed_irqs(display);
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
void intel_hpd_disable_detection_work(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
display->hotplug.detection_work_enabled = false;
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
cancel_all_detection_work(display);
|
||||
}
|
||||
|
||||
bool intel_hpd_schedule_detection(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
unsigned long flags;
|
||||
bool ret;
|
||||
|
||||
spin_lock_irqsave(&i915->irq_lock, flags);
|
||||
spin_lock_irqsave(&display->irq.lock, flags);
|
||||
ret = queue_delayed_detection_work(display, &display->hotplug.hotplug_work, 0);
|
||||
spin_unlock_irqrestore(&i915->irq_lock, flags);
|
||||
spin_unlock_irqrestore(&display->irq.lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1228,7 +1199,6 @@ static ssize_t i915_hpd_storm_ctl_write(struct file *file,
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
struct intel_display *display = m->private;
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
unsigned int new_threshold;
|
||||
int i;
|
||||
@@ -1260,12 +1230,12 @@ static ssize_t i915_hpd_storm_ctl_write(struct file *file,
|
||||
else
|
||||
drm_dbg_kms(display->drm, "Disabling HPD storm detection\n");
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
hotplug->hpd_storm_threshold = new_threshold;
|
||||
/* Reset the HPD storm stats so we don't accidentally trigger a storm */
|
||||
for_each_hpd_pin(i)
|
||||
hotplug->stats[i].count = 0;
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
/* Re-enable hpd immediately if we were in an irq storm */
|
||||
flush_delayed_work(&display->hotplug.reenable_work);
|
||||
@@ -1310,7 +1280,6 @@ static ssize_t i915_hpd_short_storm_ctl_write(struct file *file,
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
struct intel_display *display = m->private;
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_hotplug *hotplug = &display->hotplug;
|
||||
char *newline;
|
||||
char tmp[16];
|
||||
@@ -1339,12 +1308,12 @@ static ssize_t i915_hpd_short_storm_ctl_write(struct file *file,
|
||||
drm_dbg_kms(display->drm, "%sabling HPD short storm detection\n",
|
||||
new_state ? "En" : "Dis");
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
hotplug->hpd_short_storm_enabled = new_state;
|
||||
/* Reset the HPD storm stats so we don't accidentally trigger a storm */
|
||||
for_each_hpd_pin(i)
|
||||
hotplug->stats[i].count = 0;
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
|
||||
/* Re-enable hpd immediately if we were in an irq storm */
|
||||
flush_delayed_work(&display->hotplug.reenable_work);
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_irq.h"
|
||||
#include "intel_display_types.h"
|
||||
@@ -133,7 +135,6 @@ static const u32 hpd_mtp[HPD_NUM_PINS] = {
|
||||
|
||||
static void intel_hpd_init_pins(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_hotplug *hpd = &display->hotplug;
|
||||
|
||||
if (HAS_GMCH(display)) {
|
||||
@@ -160,33 +161,31 @@ static void intel_hpd_init_pins(struct intel_display *display)
|
||||
else
|
||||
hpd->hpd = hpd_ilk;
|
||||
|
||||
if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) &&
|
||||
(!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
|
||||
if ((INTEL_PCH_TYPE(display) < PCH_DG1) &&
|
||||
(!HAS_PCH_SPLIT(display) || HAS_PCH_NOP(display)))
|
||||
return;
|
||||
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTL)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_MTL)
|
||||
hpd->pch_hpd = hpd_mtp;
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_DG1)
|
||||
hpd->pch_hpd = hpd_sde_dg1;
|
||||
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
hpd->pch_hpd = hpd_icp;
|
||||
else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
|
||||
else if (HAS_PCH_CNP(display) || HAS_PCH_SPT(display))
|
||||
hpd->pch_hpd = hpd_spt;
|
||||
else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv))
|
||||
else if (HAS_PCH_LPT(display) || HAS_PCH_CPT(display))
|
||||
hpd->pch_hpd = hpd_cpt;
|
||||
else if (HAS_PCH_IBX(dev_priv))
|
||||
else if (HAS_PCH_IBX(display))
|
||||
hpd->pch_hpd = hpd_ibx;
|
||||
else
|
||||
MISSING_CASE(INTEL_PCH_TYPE(dev_priv));
|
||||
MISSING_CASE(INTEL_PCH_TYPE(display));
|
||||
}
|
||||
|
||||
/* For display hotplug interrupt */
|
||||
void i915_hotplug_interrupt_update_locked(struct intel_display *display,
|
||||
u32 mask, u32 bits)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
drm_WARN_ON(display->drm, bits & ~mask);
|
||||
|
||||
intel_de_rmw(display, PORT_HOTPLUG_EN(display), mask, bits);
|
||||
@@ -208,11 +207,9 @@ void i915_hotplug_interrupt_update(struct intel_display *display,
|
||||
u32 mask,
|
||||
u32 bits)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
i915_hotplug_interrupt_update_locked(display, mask, bits);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val)
|
||||
@@ -557,7 +554,6 @@ void xelpdp_pica_irq_handler(struct intel_display *display, u32 iir)
|
||||
|
||||
void icp_irq_handler(struct intel_display *display, u32 pch_iir)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP;
|
||||
u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP;
|
||||
u32 pin_mask = 0, long_mask = 0;
|
||||
@@ -566,9 +562,9 @@ void icp_irq_handler(struct intel_display *display, u32 pch_iir)
|
||||
u32 dig_hotplug_reg;
|
||||
|
||||
/* Locking due to DSI native GPIO sequences */
|
||||
spin_lock(&dev_priv->irq_lock);
|
||||
spin_lock(&display->irq.lock);
|
||||
dig_hotplug_reg = intel_de_rmw(display, SHOTPLUG_CTL_DDI, 0, 0);
|
||||
spin_unlock(&dev_priv->irq_lock);
|
||||
spin_unlock(&display->irq.lock);
|
||||
|
||||
intel_get_hpd_pins(display, &pin_mask, &long_mask,
|
||||
ddi_hotplug_trigger, dig_hotplug_reg,
|
||||
@@ -711,7 +707,7 @@ static u32 ibx_hotplug_mask(enum hpd_pin hpd_pin)
|
||||
|
||||
static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
|
||||
switch (encoder->hpd_pin) {
|
||||
case HPD_PORT_A:
|
||||
@@ -719,7 +715,7 @@ static u32 ibx_hotplug_enables(struct intel_encoder *encoder)
|
||||
* When CPU and PCH are on the same package, port A
|
||||
* HPD must be enabled in both north and south.
|
||||
*/
|
||||
return HAS_PCH_LPT_LP(i915) ?
|
||||
return HAS_PCH_LPT_LP(display) ?
|
||||
PORTA_HOTPLUG_ENABLE : 0;
|
||||
case HPD_PORT_B:
|
||||
return PORTB_HOTPLUG_ENABLE |
|
||||
@@ -940,18 +936,17 @@ static void gen11_tbt_hpd_enable_detection(struct intel_encoder *encoder)
|
||||
|
||||
static void gen11_hpd_enable_detection(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
|
||||
gen11_tc_hpd_enable_detection(encoder);
|
||||
gen11_tbt_hpd_enable_detection(encoder);
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
icp_hpd_enable_detection(encoder);
|
||||
}
|
||||
|
||||
static void gen11_hpd_irq_setup(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 hotplug_irqs, enabled_irqs;
|
||||
|
||||
enabled_irqs = intel_hpd_enabled_irqs(display, display->hotplug.hpd);
|
||||
@@ -964,7 +959,7 @@ static void gen11_hpd_irq_setup(struct intel_display *display)
|
||||
gen11_tc_hpd_detection_setup(display);
|
||||
gen11_tbt_hpd_detection_setup(display);
|
||||
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
icp_hpd_irq_setup(display);
|
||||
}
|
||||
|
||||
@@ -1138,7 +1133,6 @@ static void xelpdp_hpd_enable_detection(struct intel_encoder *encoder)
|
||||
|
||||
static void xelpdp_hpd_irq_setup(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
u32 hotplug_irqs, enabled_irqs;
|
||||
|
||||
enabled_irqs = intel_hpd_enabled_irqs(display, display->hotplug.hpd);
|
||||
@@ -1150,9 +1144,9 @@ static void xelpdp_hpd_irq_setup(struct intel_display *display)
|
||||
|
||||
xelpdp_pica_hpd_detection_setup(display);
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_LNL)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_LNL)
|
||||
xe2lpd_sde_hpd_irq_setup(display);
|
||||
else if (INTEL_PCH_TYPE(i915) >= PCH_MTL)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_MTL)
|
||||
mtp_hpd_irq_setup(display);
|
||||
}
|
||||
|
||||
@@ -1194,10 +1188,8 @@ static u32 spt_hotplug2_enables(struct intel_encoder *encoder)
|
||||
|
||||
static void spt_hpd_detection_setup(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
/* Display WA #1179 WaHardHangonHotPlug: cnp */
|
||||
if (HAS_PCH_CNP(dev_priv)) {
|
||||
if (HAS_PCH_CNP(display)) {
|
||||
intel_de_rmw(display, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
|
||||
CHASSIS_CLK_REQ_DURATION(0xf));
|
||||
}
|
||||
@@ -1215,10 +1207,9 @@ static void spt_hpd_detection_setup(struct intel_display *display)
|
||||
static void spt_hpd_enable_detection(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
|
||||
/* Display WA #1179 WaHardHangonHotPlug: cnp */
|
||||
if (HAS_PCH_CNP(i915)) {
|
||||
if (HAS_PCH_CNP(display)) {
|
||||
intel_de_rmw(display, SOUTH_CHICKEN1,
|
||||
CHASSIS_CLK_REQ_DURATION_MASK,
|
||||
CHASSIS_CLK_REQ_DURATION(0xf));
|
||||
@@ -1235,10 +1226,9 @@ static void spt_hpd_enable_detection(struct intel_encoder *encoder)
|
||||
|
||||
static void spt_hpd_irq_setup(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 hotplug_irqs, enabled_irqs;
|
||||
|
||||
if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_CNP)
|
||||
intel_de_write(display, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
|
||||
|
||||
enabled_irqs = intel_hpd_enabled_irqs(display, display->hotplug.pch_hpd);
|
||||
@@ -1402,10 +1392,9 @@ static void i915_hpd_enable_detection(struct intel_encoder *encoder)
|
||||
|
||||
static void i915_hpd_irq_setup(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 hotplug_en;
|
||||
|
||||
lockdep_assert_held(&dev_priv->irq_lock);
|
||||
lockdep_assert_held(&display->irq.lock);
|
||||
|
||||
/*
|
||||
* Note HDMI and DP share hotplug bits. Enable bits are the same for all
|
||||
@@ -1474,8 +1463,6 @@ void intel_hpd_irq_setup(struct intel_display *display)
|
||||
|
||||
void intel_hotplug_irq_init(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
intel_hpd_init_pins(display);
|
||||
|
||||
intel_hpd_init_early(display);
|
||||
@@ -1484,9 +1471,9 @@ void intel_hotplug_irq_init(struct intel_display *display)
|
||||
if (HAS_HOTPLUG(display))
|
||||
display->funcs.hotplug = &i915_hpd_funcs;
|
||||
} else {
|
||||
if (HAS_PCH_DG2(i915))
|
||||
if (HAS_PCH_DG2(display))
|
||||
display->funcs.hotplug = &icp_hpd_funcs;
|
||||
else if (HAS_PCH_DG1(i915))
|
||||
else if (HAS_PCH_DG1(display))
|
||||
display->funcs.hotplug = &dg1_hpd_funcs;
|
||||
else if (DISPLAY_VER(display) >= 14)
|
||||
display->funcs.hotplug = &xelpdp_hpd_funcs;
|
||||
@@ -1494,9 +1481,9 @@ void intel_hotplug_irq_init(struct intel_display *display)
|
||||
display->funcs.hotplug = &gen11_hpd_funcs;
|
||||
else if (display->platform.geminilake || display->platform.broxton)
|
||||
display->funcs.hotplug = &bxt_hpd_funcs;
|
||||
else if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
display->funcs.hotplug = &icp_hpd_funcs;
|
||||
else if (INTEL_PCH_TYPE(i915) >= PCH_SPT)
|
||||
else if (INTEL_PCH_TYPE(display) >= PCH_SPT)
|
||||
display->funcs.hotplug = &spt_hpd_funcs;
|
||||
else
|
||||
display->funcs.hotplug = &ilk_hpd_funcs;
|
||||
|
||||
@@ -179,7 +179,7 @@ static int lpe_audio_irq_init(struct intel_display *display)
|
||||
handle_simple_irq,
|
||||
"hdmi_lpe_audio_irq_handler");
|
||||
|
||||
return irq_set_chip_data(irq, dev_priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool lpe_audio_detect(struct intel_display *display)
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_backlight.h"
|
||||
@@ -87,13 +87,12 @@ static struct intel_lvds_encoder *to_lvds_encoder(struct intel_encoder *encoder)
|
||||
bool intel_lvds_port_enabled(struct intel_display *display,
|
||||
i915_reg_t lvds_reg, enum pipe *pipe)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
u32 val;
|
||||
|
||||
val = intel_de_read(display, lvds_reg);
|
||||
|
||||
/* asserts want to know the pipe even if the port is disabled */
|
||||
if (HAS_PCH_CPT(i915))
|
||||
if (HAS_PCH_CPT(display))
|
||||
*pipe = REG_FIELD_GET(LVDS_PIPE_SEL_MASK_CPT, val);
|
||||
else
|
||||
*pipe = REG_FIELD_GET(LVDS_PIPE_SEL_MASK, val);
|
||||
@@ -243,13 +242,12 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state,
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 temp;
|
||||
|
||||
if (HAS_PCH_SPLIT(i915)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
assert_fdi_rx_pll_disabled(display, pipe);
|
||||
assert_shared_dpll_disabled(display, crtc_state->shared_dpll);
|
||||
} else {
|
||||
@@ -261,7 +259,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state,
|
||||
temp = lvds_encoder->init_lvds_val;
|
||||
temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
|
||||
|
||||
if (HAS_PCH_CPT(i915)) {
|
||||
if (HAS_PCH_CPT(display)) {
|
||||
temp &= ~LVDS_PIPE_SEL_MASK_CPT;
|
||||
temp |= LVDS_PIPE_SEL_CPT(pipe);
|
||||
} else {
|
||||
@@ -421,7 +419,6 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
|
||||
struct intel_connector *connector = lvds_encoder->attached_connector;
|
||||
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
@@ -435,7 +432,7 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (HAS_PCH_SPLIT(i915)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
crtc_state->has_pch_encoder = true;
|
||||
if (!intel_fdi_compute_pipe_bpp(crtc_state))
|
||||
return -EINVAL;
|
||||
@@ -798,7 +795,6 @@ bool intel_is_dual_link_lvds(struct intel_display *display)
|
||||
static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(&lvds_encoder->base);
|
||||
struct drm_i915_private *i915 = to_i915(lvds_encoder->base.base.dev);
|
||||
struct intel_connector *connector = lvds_encoder->attached_connector;
|
||||
const struct drm_display_mode *fixed_mode =
|
||||
intel_panel_preferred_fixed_mode(connector);
|
||||
@@ -822,7 +818,7 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
|
||||
* register is uninitialized.
|
||||
*/
|
||||
val = intel_de_read(display, lvds_encoder->reg);
|
||||
if (HAS_PCH_CPT(i915))
|
||||
if (HAS_PCH_CPT(display))
|
||||
val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK_CPT);
|
||||
else
|
||||
val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK);
|
||||
@@ -846,7 +842,6 @@ static void intel_lvds_add_properties(struct drm_connector *connector)
|
||||
*/
|
||||
void intel_lvds_init(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct intel_lvds_encoder *lvds_encoder;
|
||||
struct intel_connector *connector;
|
||||
const struct drm_edid *drm_edid;
|
||||
@@ -868,14 +863,14 @@ void intel_lvds_init(struct intel_display *display)
|
||||
return;
|
||||
}
|
||||
|
||||
if (HAS_PCH_SPLIT(i915))
|
||||
if (HAS_PCH_SPLIT(display))
|
||||
lvds_reg = PCH_LVDS;
|
||||
else
|
||||
lvds_reg = LVDS;
|
||||
|
||||
lvds = intel_de_read(display, lvds_reg);
|
||||
|
||||
if (HAS_PCH_SPLIT(i915)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
if ((lvds & LVDS_DETECTED) == 0)
|
||||
return;
|
||||
}
|
||||
@@ -915,7 +910,7 @@ void intel_lvds_init(struct intel_display *display)
|
||||
encoder->enable = intel_enable_lvds;
|
||||
encoder->pre_enable = intel_pre_enable_lvds;
|
||||
encoder->compute_config = intel_lvds_compute_config;
|
||||
if (HAS_PCH_SPLIT(i915)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
encoder->disable = pch_disable_lvds;
|
||||
encoder->post_disable = pch_post_disable_lvds;
|
||||
} else {
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
* state.
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i9xx_wm.h"
|
||||
#include "intel_atomic.h"
|
||||
@@ -31,13 +31,14 @@
|
||||
#include "intel_pmdemand.h"
|
||||
#include "intel_tc.h"
|
||||
#include "intel_vblank.h"
|
||||
#include "intel_vga.h"
|
||||
#include "intel_wm.h"
|
||||
#include "skl_watermark.h"
|
||||
|
||||
static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
struct intel_plane *plane;
|
||||
@@ -48,7 +49,7 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc,
|
||||
if (!crtc_state->hw.active)
|
||||
return;
|
||||
|
||||
for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) {
|
||||
for_each_intel_plane_on_crtc(display->drm, crtc, plane) {
|
||||
const struct intel_plane_state *plane_state =
|
||||
to_intel_plane_state(plane->base.state);
|
||||
|
||||
@@ -56,9 +57,9 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc,
|
||||
intel_plane_disable_noatomic(crtc, plane);
|
||||
}
|
||||
|
||||
state = drm_atomic_state_alloc(&i915->drm);
|
||||
state = drm_atomic_state_alloc(display->drm);
|
||||
if (!state) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"failed to disable [CRTC:%d:%s], out of memory",
|
||||
crtc->base.base.id, crtc->base.name);
|
||||
return;
|
||||
@@ -68,7 +69,7 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc,
|
||||
to_intel_atomic_state(state)->internal = true;
|
||||
|
||||
/* Everything's already locked, -EDEADLK can't happen. */
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc,
|
||||
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc,
|
||||
BIT(pipe) |
|
||||
intel_crtc_joiner_secondary_pipes(crtc_state)) {
|
||||
struct intel_crtc_state *temp_crtc_state =
|
||||
@@ -77,14 +78,14 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc,
|
||||
|
||||
ret = drm_atomic_add_affected_connectors(state, &temp_crtc->base);
|
||||
|
||||
drm_WARN_ON(&i915->drm, IS_ERR(temp_crtc_state) || ret);
|
||||
drm_WARN_ON(display->drm, IS_ERR(temp_crtc_state) || ret);
|
||||
}
|
||||
|
||||
i915->display.funcs.display->crtc_disable(to_intel_atomic_state(state), crtc);
|
||||
display->funcs.display->crtc_disable(to_intel_atomic_state(state), crtc);
|
||||
|
||||
drm_atomic_state_put(state);
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n",
|
||||
crtc->base.base.id, crtc->base.name);
|
||||
|
||||
@@ -118,13 +119,12 @@ static void set_encoder_for_connector(struct intel_connector *connector,
|
||||
static void reset_encoder_connector_state(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_pmdemand_state *pmdemand_state =
|
||||
to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
|
||||
to_intel_pmdemand_state(display->pmdemand.obj.state);
|
||||
struct intel_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
|
||||
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
|
||||
drm_connector_list_iter_begin(display->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
if (connector->base.encoder != &encoder->base)
|
||||
continue;
|
||||
@@ -143,10 +143,10 @@ static void reset_encoder_connector_state(struct intel_encoder *encoder)
|
||||
|
||||
static void reset_crtc_encoder_state(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
for_each_encoder_on_crtc(&i915->drm, &crtc->base, encoder) {
|
||||
for_each_encoder_on_crtc(display->drm, &crtc->base, encoder) {
|
||||
reset_encoder_connector_state(encoder);
|
||||
encoder->base.crtc = NULL;
|
||||
}
|
||||
@@ -183,13 +183,13 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc)
|
||||
* Return all the pipes using a transcoder in @transcoder_mask.
|
||||
* For joiner configs return only the joiner primary.
|
||||
*/
|
||||
static u8 get_transcoder_pipes(struct drm_i915_private *i915,
|
||||
static u8 get_transcoder_pipes(struct intel_display *display,
|
||||
u8 transcoder_mask)
|
||||
{
|
||||
struct intel_crtc *temp_crtc;
|
||||
u8 pipes = 0;
|
||||
|
||||
for_each_intel_crtc(&i915->drm, temp_crtc) {
|
||||
for_each_intel_crtc(display->drm, temp_crtc) {
|
||||
struct intel_crtc_state *temp_crtc_state =
|
||||
to_intel_crtc_state(temp_crtc->base.state);
|
||||
|
||||
@@ -214,7 +214,6 @@ static void get_portsync_pipes(struct intel_crtc *crtc,
|
||||
u8 *master_pipe_mask, u8 *slave_pipes_mask)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
struct intel_crtc *master_crtc;
|
||||
@@ -233,20 +232,20 @@ static void get_portsync_pipes(struct intel_crtc *crtc,
|
||||
else
|
||||
master_transcoder = crtc_state->master_transcoder;
|
||||
|
||||
*master_pipe_mask = get_transcoder_pipes(i915, BIT(master_transcoder));
|
||||
drm_WARN_ON(&i915->drm, !is_power_of_2(*master_pipe_mask));
|
||||
*master_pipe_mask = get_transcoder_pipes(display, BIT(master_transcoder));
|
||||
drm_WARN_ON(display->drm, !is_power_of_2(*master_pipe_mask));
|
||||
|
||||
master_crtc = intel_crtc_for_pipe(display, ffs(*master_pipe_mask) - 1);
|
||||
master_crtc_state = to_intel_crtc_state(master_crtc->base.state);
|
||||
*slave_pipes_mask = get_transcoder_pipes(i915, master_crtc_state->sync_mode_slaves_mask);
|
||||
*slave_pipes_mask = get_transcoder_pipes(display, master_crtc_state->sync_mode_slaves_mask);
|
||||
}
|
||||
|
||||
static u8 get_joiner_secondary_pipes(struct drm_i915_private *i915, u8 primary_pipes_mask)
|
||||
static u8 get_joiner_secondary_pipes(struct intel_display *display, u8 primary_pipes_mask)
|
||||
{
|
||||
struct intel_crtc *primary_crtc;
|
||||
u8 pipes = 0;
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, primary_crtc, primary_pipes_mask) {
|
||||
for_each_intel_crtc_in_pipe_mask(display->drm, primary_crtc, primary_pipes_mask) {
|
||||
struct intel_crtc_state *primary_crtc_state =
|
||||
to_intel_crtc_state(primary_crtc->base.state);
|
||||
|
||||
@@ -259,45 +258,45 @@ static u8 get_joiner_secondary_pipes(struct drm_i915_private *i915, u8 primary_p
|
||||
static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct intel_crtc *temp_crtc;
|
||||
u8 portsync_master_mask;
|
||||
u8 portsync_slaves_mask;
|
||||
u8 joiner_secondaries_mask;
|
||||
struct intel_crtc *temp_crtc;
|
||||
|
||||
/* TODO: Add support for MST */
|
||||
get_portsync_pipes(crtc, &portsync_master_mask, &portsync_slaves_mask);
|
||||
joiner_secondaries_mask = get_joiner_secondary_pipes(i915,
|
||||
joiner_secondaries_mask = get_joiner_secondary_pipes(display,
|
||||
portsync_master_mask |
|
||||
portsync_slaves_mask);
|
||||
|
||||
drm_WARN_ON(&i915->drm,
|
||||
drm_WARN_ON(display->drm,
|
||||
portsync_master_mask & portsync_slaves_mask ||
|
||||
portsync_master_mask & joiner_secondaries_mask ||
|
||||
portsync_slaves_mask & joiner_secondaries_mask);
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, joiner_secondaries_mask)
|
||||
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, joiner_secondaries_mask)
|
||||
intel_crtc_disable_noatomic_begin(temp_crtc, ctx);
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, portsync_slaves_mask)
|
||||
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, portsync_slaves_mask)
|
||||
intel_crtc_disable_noatomic_begin(temp_crtc, ctx);
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc, portsync_master_mask)
|
||||
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, portsync_master_mask)
|
||||
intel_crtc_disable_noatomic_begin(temp_crtc, ctx);
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, temp_crtc,
|
||||
for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc,
|
||||
joiner_secondaries_mask |
|
||||
portsync_slaves_mask |
|
||||
portsync_master_mask)
|
||||
intel_crtc_disable_noatomic_complete(temp_crtc);
|
||||
}
|
||||
|
||||
static void intel_modeset_update_connector_atomic_state(struct drm_i915_private *i915)
|
||||
static void intel_modeset_update_connector_atomic_state(struct intel_display *display)
|
||||
{
|
||||
struct intel_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
|
||||
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
|
||||
drm_connector_list_iter_begin(display->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
struct drm_connector_state *conn_state = connector->base.state;
|
||||
struct intel_encoder *encoder =
|
||||
@@ -319,7 +318,7 @@ static void intel_modeset_update_connector_atomic_state(struct drm_i915_private
|
||||
|
||||
static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
|
||||
if (intel_crtc_is_joiner_secondary(crtc_state))
|
||||
return;
|
||||
@@ -332,7 +331,7 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
|
||||
crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode;
|
||||
crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter;
|
||||
|
||||
if (DISPLAY_INFO(i915)->color.degamma_lut_size) {
|
||||
if (DISPLAY_INFO(display)->color.degamma_lut_size) {
|
||||
/* assume 1:1 mapping */
|
||||
drm_property_replace_blob(&crtc_state->hw.degamma_lut,
|
||||
crtc_state->pre_csc_lut);
|
||||
@@ -347,7 +346,7 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
|
||||
* to gamma_lut as that is the only valid source of LUTs
|
||||
* in the uapi.
|
||||
*/
|
||||
drm_WARN_ON(&i915->drm, crtc_state->post_csc_lut &&
|
||||
drm_WARN_ON(display->drm, crtc_state->post_csc_lut &&
|
||||
crtc_state->pre_csc_lut);
|
||||
|
||||
drm_property_replace_blob(&crtc_state->hw.degamma_lut,
|
||||
@@ -366,15 +365,14 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
|
||||
}
|
||||
|
||||
static void
|
||||
intel_sanitize_plane_mapping(struct drm_i915_private *i915)
|
||||
intel_sanitize_plane_mapping(struct intel_display *display)
|
||||
{
|
||||
struct intel_display *display = &i915->display;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
if (DISPLAY_VER(i915) >= 4)
|
||||
if (DISPLAY_VER(display) >= 4)
|
||||
return;
|
||||
|
||||
for_each_intel_crtc(&i915->drm, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_plane *plane =
|
||||
to_intel_plane(crtc->base.primary);
|
||||
struct intel_crtc *plane_crtc;
|
||||
@@ -386,7 +384,7 @@ intel_sanitize_plane_mapping(struct drm_i915_private *i915)
|
||||
if (pipe == crtc->pipe)
|
||||
continue;
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[PLANE:%d:%s] attached to the wrong pipe, disabling plane\n",
|
||||
plane->base.base.id, plane->base.name);
|
||||
|
||||
@@ -423,12 +421,12 @@ static bool intel_crtc_needs_link_reset(struct intel_crtc *crtc)
|
||||
|
||||
static struct intel_connector *intel_encoder_find_connector(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_connector *connector;
|
||||
struct intel_connector *found_connector = NULL;
|
||||
|
||||
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
|
||||
drm_connector_list_iter_begin(display->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
if (&encoder->base == connector->base.encoder) {
|
||||
found_connector = connector;
|
||||
@@ -466,7 +464,7 @@ static void intel_sanitize_fifo_underrun_reporting(const struct intel_crtc_state
|
||||
static bool intel_sanitize_crtc(struct intel_crtc *crtc,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
|
||||
bool needs_link_reset;
|
||||
|
||||
@@ -474,7 +472,7 @@ static bool intel_sanitize_crtc(struct intel_crtc *crtc,
|
||||
struct intel_plane *plane;
|
||||
|
||||
/* Disable everything but the primary plane */
|
||||
for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) {
|
||||
for_each_intel_plane_on_crtc(display->drm, crtc, plane) {
|
||||
const struct intel_plane_state *plane_state =
|
||||
to_intel_plane_state(plane->base.state);
|
||||
|
||||
@@ -515,7 +513,7 @@ static bool intel_sanitize_crtc(struct intel_crtc *crtc,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void intel_sanitize_all_crtcs(struct drm_i915_private *i915,
|
||||
static void intel_sanitize_all_crtcs(struct intel_display *display,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct intel_crtc *crtc;
|
||||
@@ -530,7 +528,7 @@ static void intel_sanitize_all_crtcs(struct drm_i915_private *i915,
|
||||
for (;;) {
|
||||
u32 old_mask = crtcs_forced_off;
|
||||
|
||||
for_each_intel_crtc(&i915->drm, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
u32 crtc_mask = drm_crtc_mask(&crtc->base);
|
||||
|
||||
if (crtcs_forced_off & crtc_mask)
|
||||
@@ -543,7 +541,7 @@ static void intel_sanitize_all_crtcs(struct drm_i915_private *i915,
|
||||
break;
|
||||
}
|
||||
|
||||
for_each_intel_crtc(&i915->drm, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
|
||||
@@ -553,7 +551,7 @@ static void intel_sanitize_all_crtcs(struct drm_i915_private *i915,
|
||||
|
||||
static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
|
||||
/*
|
||||
* Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram
|
||||
@@ -565,7 +563,7 @@ static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
|
||||
* without several WARNs, but for now let's take the easy
|
||||
* road.
|
||||
*/
|
||||
return IS_SANDYBRIDGE(i915) &&
|
||||
return display->platform.sandybridge &&
|
||||
crtc_state->hw.active &&
|
||||
crtc_state->shared_dpll &&
|
||||
crtc_state->port_clock == 0;
|
||||
@@ -574,13 +572,12 @@ static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
|
||||
static void intel_sanitize_encoder(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_connector *connector;
|
||||
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
|
||||
struct intel_crtc_state *crtc_state = crtc ?
|
||||
to_intel_crtc_state(crtc->base.state) : NULL;
|
||||
struct intel_pmdemand_state *pmdemand_state =
|
||||
to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
|
||||
to_intel_pmdemand_state(display->pmdemand.obj.state);
|
||||
|
||||
/*
|
||||
* We need to check both for a crtc link (meaning that the encoder is
|
||||
@@ -591,7 +588,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
|
||||
crtc_state->hw.active;
|
||||
|
||||
if (crtc_state && has_bogus_dpll_config(crtc_state)) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"BIOS has misprogrammed the hardware. Disabling pipe %c\n",
|
||||
pipe_name(crtc->pipe));
|
||||
has_active_crtc = false;
|
||||
@@ -599,7 +596,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
|
||||
|
||||
connector = intel_encoder_find_connector(encoder);
|
||||
if (connector && !has_active_crtc) {
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[ENCODER:%d:%s] has active connectors but no active pipe!\n",
|
||||
encoder->base.base.id,
|
||||
encoder->base.name);
|
||||
@@ -616,7 +613,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
|
||||
if (crtc_state) {
|
||||
struct drm_encoder *best_encoder;
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[ENCODER:%d:%s] manually disabled\n",
|
||||
encoder->base.base.id,
|
||||
encoder->base.name);
|
||||
@@ -650,18 +647,17 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
|
||||
/* notify opregion of the sanitized encoder state */
|
||||
intel_opregion_notify_encoder(encoder, connector && has_active_crtc);
|
||||
|
||||
if (HAS_DDI(i915))
|
||||
if (HAS_DDI(display))
|
||||
intel_ddi_sanitize_encoder_pll_mapping(encoder);
|
||||
}
|
||||
|
||||
/* FIXME read out full plane state for all planes */
|
||||
static void readout_plane_state(struct drm_i915_private *i915)
|
||||
static void readout_plane_state(struct intel_display *display)
|
||||
{
|
||||
struct intel_display *display = &i915->display;
|
||||
struct intel_plane *plane;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
for_each_intel_plane(&i915->drm, plane) {
|
||||
for_each_intel_plane(display->drm, plane) {
|
||||
struct intel_plane_state *plane_state =
|
||||
to_intel_plane_state(plane->base.state);
|
||||
struct intel_crtc_state *crtc_state;
|
||||
@@ -675,13 +671,13 @@ static void readout_plane_state(struct drm_i915_private *i915)
|
||||
|
||||
intel_set_plane_visible(crtc_state, plane_state, visible);
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[PLANE:%d:%s] hw state readout: %s, pipe %c\n",
|
||||
plane->base.base.id, plane->base.name,
|
||||
str_enabled_disabled(visible), pipe_name(pipe));
|
||||
}
|
||||
|
||||
for_each_intel_crtc(&i915->drm, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
|
||||
@@ -689,18 +685,17 @@ static void readout_plane_state(struct drm_i915_private *i915)
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
|
||||
static void intel_modeset_readout_hw_state(struct intel_display *display)
|
||||
{
|
||||
struct intel_display *display = &i915->display;
|
||||
struct intel_pmdemand_state *pmdemand_state =
|
||||
to_intel_pmdemand_state(i915->display.pmdemand.obj.state);
|
||||
to_intel_pmdemand_state(display->pmdemand.obj.state);
|
||||
enum pipe pipe;
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
|
||||
for_each_intel_crtc(&i915->drm, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
|
||||
@@ -715,15 +710,15 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
|
||||
crtc->base.enabled = crtc_state->hw.enable;
|
||||
crtc->active = crtc_state->hw.active;
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[CRTC:%d:%s] hw state readout: %s\n",
|
||||
crtc->base.base.id, crtc->base.name,
|
||||
str_enabled_disabled(crtc_state->hw.active));
|
||||
}
|
||||
|
||||
readout_plane_state(i915);
|
||||
readout_plane_state(display);
|
||||
|
||||
for_each_intel_encoder(&i915->drm, encoder) {
|
||||
for_each_intel_encoder(display->drm, encoder) {
|
||||
struct intel_crtc_state *crtc_state = NULL;
|
||||
|
||||
pipe = 0;
|
||||
@@ -742,7 +737,7 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
|
||||
/* encoder should read be linked to joiner primary */
|
||||
WARN_ON(intel_crtc_is_joiner_secondary(crtc_state));
|
||||
|
||||
for_each_intel_crtc_in_pipe_mask(&i915->drm, secondary_crtc,
|
||||
for_each_intel_crtc_in_pipe_mask(display->drm, secondary_crtc,
|
||||
intel_crtc_joiner_secondary_pipes(crtc_state)) {
|
||||
struct intel_crtc_state *secondary_crtc_state;
|
||||
|
||||
@@ -765,7 +760,7 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
|
||||
if (encoder->sync_state)
|
||||
encoder->sync_state(encoder, crtc_state);
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[ENCODER:%d:%s] hw state readout: %s, pipe %c\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
str_enabled_disabled(encoder->base.crtc),
|
||||
@@ -774,7 +769,7 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
|
||||
|
||||
intel_dpll_readout_hw_state(display);
|
||||
|
||||
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
|
||||
drm_connector_list_iter_begin(display->drm, &conn_iter);
|
||||
for_each_intel_connector_iter(connector, &conn_iter) {
|
||||
struct intel_crtc_state *crtc_state = NULL;
|
||||
|
||||
@@ -808,14 +803,14 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
|
||||
if (connector->sync_state)
|
||||
connector->sync_state(connector, crtc_state);
|
||||
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[CONNECTOR:%d:%s] hw state readout: %s\n",
|
||||
connector->base.base.id, connector->base.name,
|
||||
str_enabled_disabled(connector->base.encoder));
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
for_each_intel_crtc(&i915->drm, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
struct intel_plane *plane;
|
||||
@@ -838,7 +833,7 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
|
||||
intel_crtc_copy_hw_to_uapi_state(crtc_state);
|
||||
}
|
||||
|
||||
for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) {
|
||||
for_each_intel_plane_on_crtc(display->drm, crtc, plane) {
|
||||
const struct intel_plane_state *plane_state =
|
||||
to_intel_plane_state(plane->base.state);
|
||||
|
||||
@@ -854,14 +849,14 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
|
||||
* use plane->min_cdclk() :(
|
||||
*/
|
||||
if (plane_state->uapi.visible && plane->min_cdclk) {
|
||||
if (crtc_state->double_wide || DISPLAY_VER(i915) >= 10)
|
||||
if (crtc_state->double_wide || DISPLAY_VER(display) >= 10)
|
||||
crtc_state->min_cdclk[plane->id] =
|
||||
DIV_ROUND_UP(crtc_state->pixel_rate, 2);
|
||||
else
|
||||
crtc_state->min_cdclk[plane->id] =
|
||||
crtc_state->pixel_rate;
|
||||
}
|
||||
drm_dbg_kms(&i915->drm,
|
||||
drm_dbg_kms(display->drm,
|
||||
"[PLANE:%d:%s] min_cdclk %d kHz\n",
|
||||
plane->base.base.id, plane->base.name,
|
||||
crtc_state->min_cdclk[plane->id]);
|
||||
@@ -882,11 +877,11 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
|
||||
}
|
||||
|
||||
static void
|
||||
get_encoder_power_domains(struct drm_i915_private *i915)
|
||||
get_encoder_power_domains(struct intel_display *display)
|
||||
{
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
for_each_intel_encoder(&i915->drm, encoder) {
|
||||
for_each_intel_encoder(display->drm, encoder) {
|
||||
struct intel_crtc_state *crtc_state;
|
||||
|
||||
if (!encoder->get_power_domains)
|
||||
@@ -904,47 +899,49 @@ get_encoder_power_domains(struct drm_i915_private *i915)
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_early_display_was(struct drm_i915_private *i915)
|
||||
static void intel_early_display_was(struct intel_display *display)
|
||||
{
|
||||
/*
|
||||
* Display WA #1185 WaDisableDARBFClkGating:glk,icl,ehl,tgl
|
||||
* Also known as Wa_14010480278.
|
||||
*/
|
||||
if (IS_DISPLAY_VER(i915, 10, 12))
|
||||
intel_de_rmw(i915, GEN9_CLKGATE_DIS_0, 0, DARBF_GATING_DIS);
|
||||
if (IS_DISPLAY_VER(display, 10, 12))
|
||||
intel_de_rmw(display, GEN9_CLKGATE_DIS_0, 0, DARBF_GATING_DIS);
|
||||
|
||||
/*
|
||||
* WaRsPkgCStateDisplayPMReq:hsw
|
||||
* System hang if this isn't done before disabling all planes!
|
||||
*/
|
||||
if (IS_HASWELL(i915))
|
||||
intel_de_rmw(i915, CHICKEN_PAR1_1, 0, FORCE_ARB_IDLE_PLANES);
|
||||
if (display->platform.haswell)
|
||||
intel_de_rmw(display, CHICKEN_PAR1_1, 0, FORCE_ARB_IDLE_PLANES);
|
||||
|
||||
if (IS_KABYLAKE(i915) || IS_COFFEELAKE(i915) || IS_COMETLAKE(i915)) {
|
||||
if (display->platform.kabylake || display->platform.coffeelake ||
|
||||
display->platform.cometlake) {
|
||||
/* Display WA #1142:kbl,cfl,cml */
|
||||
intel_de_rmw(i915, CHICKEN_PAR1_1,
|
||||
intel_de_rmw(display, CHICKEN_PAR1_1,
|
||||
KBL_ARB_FILL_SPARE_22, KBL_ARB_FILL_SPARE_22);
|
||||
intel_de_rmw(i915, CHICKEN_MISC_2,
|
||||
intel_de_rmw(display, CHICKEN_MISC_2,
|
||||
KBL_ARB_FILL_SPARE_13 | KBL_ARB_FILL_SPARE_14,
|
||||
KBL_ARB_FILL_SPARE_14);
|
||||
}
|
||||
}
|
||||
|
||||
void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
|
||||
void intel_modeset_setup_hw_state(struct intel_display *display,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct intel_display *display = &i915->display;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_crtc *crtc;
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
wakeref = intel_display_power_get(display, POWER_DOMAIN_INIT);
|
||||
|
||||
intel_early_display_was(i915);
|
||||
intel_modeset_readout_hw_state(i915);
|
||||
intel_early_display_was(display);
|
||||
intel_vga_disable(display);
|
||||
|
||||
intel_modeset_readout_hw_state(display);
|
||||
|
||||
/* HW state is read out, now we need to sanitize this mess. */
|
||||
get_encoder_power_domains(i915);
|
||||
get_encoder_power_domains(display);
|
||||
|
||||
intel_pch_sanitize(display);
|
||||
|
||||
@@ -954,7 +951,7 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
|
||||
* intel_sanitize_plane_mapping() may need to do vblank
|
||||
* waits, so we need vblank interrupts restored beforehand.
|
||||
*/
|
||||
for_each_intel_crtc(&i915->drm, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
|
||||
@@ -968,20 +965,20 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
|
||||
}
|
||||
}
|
||||
|
||||
intel_fbc_sanitize(&i915->display);
|
||||
intel_fbc_sanitize(display);
|
||||
|
||||
intel_sanitize_plane_mapping(i915);
|
||||
intel_sanitize_plane_mapping(display);
|
||||
|
||||
for_each_intel_encoder(&i915->drm, encoder)
|
||||
for_each_intel_encoder(display->drm, encoder)
|
||||
intel_sanitize_encoder(encoder);
|
||||
|
||||
/*
|
||||
* Sanitizing CRTCs needs their connector atomic state to be
|
||||
* up-to-date, so ensure that already here.
|
||||
*/
|
||||
intel_modeset_update_connector_atomic_state(i915);
|
||||
intel_modeset_update_connector_atomic_state(display);
|
||||
|
||||
intel_sanitize_all_crtcs(i915, ctx);
|
||||
intel_sanitize_all_crtcs(display, ctx);
|
||||
|
||||
intel_dpll_sanitize_state(display);
|
||||
|
||||
@@ -990,13 +987,13 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
|
||||
intel_wm_get_hw_state(display);
|
||||
intel_wm_sanitize(display);
|
||||
|
||||
for_each_intel_crtc(&i915->drm, crtc) {
|
||||
for_each_intel_crtc(display->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
struct intel_power_domain_mask put_domains;
|
||||
|
||||
intel_modeset_get_crtc_power_domains(crtc_state, &put_domains);
|
||||
if (drm_WARN_ON(&i915->drm, !bitmap_empty(put_domains.bits, POWER_DOMAIN_NUM)))
|
||||
if (drm_WARN_ON(display->drm, !bitmap_empty(put_domains.bits, POWER_DOMAIN_NUM)))
|
||||
intel_modeset_put_crtc_power_domains(crtc, &put_domains);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
#ifndef __INTEL_MODESET_SETUP_H__
|
||||
#define __INTEL_MODESET_SETUP_H__
|
||||
|
||||
struct drm_i915_private;
|
||||
struct drm_modeset_acquire_ctx;
|
||||
struct intel_display;
|
||||
|
||||
void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
|
||||
void intel_modeset_setup_hw_state(struct intel_display *display,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
#endif /* __INTEL_MODESET_SETUP_H__ */
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_crtc_state_dump.h"
|
||||
#include "intel_cx0_phy.h"
|
||||
#include "intel_display.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_modeset_verify.h"
|
||||
@@ -28,9 +29,8 @@ static void intel_connector_verify_state(const struct intel_crtc_state *crtc_sta
|
||||
{
|
||||
struct intel_connector *connector = to_intel_connector(conn_state->connector);
|
||||
struct intel_display *display = to_intel_display(connector);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
|
||||
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",
|
||||
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n",
|
||||
connector->base.base.id, connector->base.name);
|
||||
|
||||
if (connector->get_hw_state(connector)) {
|
||||
@@ -91,7 +91,6 @@ verify_connector_state(struct intel_atomic_state *state,
|
||||
static void intel_pipe_config_sanity_check(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
|
||||
|
||||
if (crtc_state->has_pch_encoder) {
|
||||
int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(display, crtc_state),
|
||||
@@ -103,7 +102,7 @@ static void intel_pipe_config_sanity_check(const struct intel_crtc_state *crtc_s
|
||||
* Yell if the encoder disagrees. Allow for slight
|
||||
* rounding differences.
|
||||
*/
|
||||
drm_WARN(&i915->drm, abs(fdi_dotclock - dotclock) > 1,
|
||||
drm_WARN(display->drm, abs(fdi_dotclock - dotclock) > 1,
|
||||
"FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n",
|
||||
fdi_dotclock, dotclock);
|
||||
}
|
||||
@@ -113,17 +112,16 @@ static void
|
||||
verify_encoder_state(struct intel_atomic_state *state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
struct intel_encoder *encoder;
|
||||
struct drm_connector *connector;
|
||||
const struct drm_connector_state *old_conn_state, *new_conn_state;
|
||||
int i;
|
||||
|
||||
for_each_intel_encoder(&i915->drm, encoder) {
|
||||
for_each_intel_encoder(display->drm, encoder) {
|
||||
bool enabled = false, found = false;
|
||||
enum pipe pipe;
|
||||
|
||||
drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s]\n",
|
||||
drm_dbg_kms(display->drm, "[ENCODER:%d:%s]\n",
|
||||
encoder->base.base.id,
|
||||
encoder->base.name);
|
||||
|
||||
@@ -166,7 +164,6 @@ verify_crtc_state(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
const struct intel_crtc_state *sw_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
struct intel_crtc_state *hw_crtc_state;
|
||||
@@ -185,7 +182,7 @@ verify_crtc_state(struct intel_atomic_state *state,
|
||||
intel_crtc_get_pipe_config(hw_crtc_state);
|
||||
|
||||
/* we keep both pipes enabled on 830 */
|
||||
if (IS_I830(i915) && hw_crtc_state->hw.active)
|
||||
if (display->platform.i830 && hw_crtc_state->hw.active)
|
||||
hw_crtc_state->hw.active = sw_crtc_state->hw.active;
|
||||
|
||||
INTEL_DISPLAY_STATE_WARN(display,
|
||||
|
||||
@@ -291,7 +291,6 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
|
||||
struct i915_vma *vma)
|
||||
{
|
||||
struct intel_display *display = overlay->display;
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
enum pipe pipe = overlay->crtc->pipe;
|
||||
struct intel_frontbuffer *frontbuffer = NULL;
|
||||
|
||||
@@ -307,7 +306,7 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
|
||||
intel_frontbuffer_put(overlay->frontbuffer);
|
||||
overlay->frontbuffer = frontbuffer;
|
||||
|
||||
intel_frontbuffer_flip_prepare(i915, INTEL_FRONTBUFFER_OVERLAY(pipe));
|
||||
intel_frontbuffer_flip_prepare(display, INTEL_FRONTBUFFER_OVERLAY(pipe));
|
||||
|
||||
overlay->old_vma = overlay->vma;
|
||||
if (vma)
|
||||
@@ -359,14 +358,13 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
|
||||
static void intel_overlay_release_old_vma(struct intel_overlay *overlay)
|
||||
{
|
||||
struct intel_display *display = overlay->display;
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
struct i915_vma *vma;
|
||||
|
||||
vma = fetch_and_zero(&overlay->old_vma);
|
||||
if (drm_WARN_ON(display->drm, !vma))
|
||||
return;
|
||||
|
||||
intel_frontbuffer_flip_complete(i915, INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
|
||||
intel_frontbuffer_flip_complete(display, INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
|
||||
|
||||
i915_vma_unpin(vma);
|
||||
i915_vma_put(vma);
|
||||
|
||||
340
drivers/gpu/drm/i915/display/intel_pch.c
Normal file
340
drivers/gpu/drm/i915/display/intel_pch.c
Normal file
@@ -0,0 +1,340 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright 2025 Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_utils.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_pch.h"
|
||||
|
||||
#define INTEL_PCH_DEVICE_ID_MASK 0xff80
|
||||
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
|
||||
#define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00
|
||||
#define INTEL_PCH_PPT_DEVICE_ID_TYPE 0x1e00
|
||||
#define INTEL_PCH_LPT_DEVICE_ID_TYPE 0x8c00
|
||||
#define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE 0x9c00
|
||||
#define INTEL_PCH_WPT_DEVICE_ID_TYPE 0x8c80
|
||||
#define INTEL_PCH_WPT_LP_DEVICE_ID_TYPE 0x9c80
|
||||
#define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100
|
||||
#define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00
|
||||
#define INTEL_PCH_KBP_DEVICE_ID_TYPE 0xA280
|
||||
#define INTEL_PCH_CNP_DEVICE_ID_TYPE 0xA300
|
||||
#define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE 0x9D80
|
||||
#define INTEL_PCH_CMP_DEVICE_ID_TYPE 0x0280
|
||||
#define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680
|
||||
#define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380
|
||||
#define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480
|
||||
#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880
|
||||
#define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00
|
||||
#define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080
|
||||
#define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380
|
||||
#define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80
|
||||
#define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80
|
||||
#define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180
|
||||
#define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00
|
||||
#define INTEL_PCH_ADP4_DEVICE_ID_TYPE 0x5480
|
||||
#define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100
|
||||
#define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000
|
||||
#define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */
|
||||
|
||||
/*
|
||||
* Check for platforms where the south display is on the same PCI device or SoC
|
||||
* die as the north display. The PCH (if it even exists) is not involved in
|
||||
* display. Return a fake PCH type for south display handling on these
|
||||
* platforms, without actually detecting the PCH, and PCH_NONE otherwise.
|
||||
*/
|
||||
static enum intel_pch intel_pch_fake_for_south_display(struct intel_display *display)
|
||||
{
|
||||
enum intel_pch pch_type = PCH_NONE;
|
||||
|
||||
if (DISPLAY_VER(display) >= 20)
|
||||
pch_type = PCH_LNL;
|
||||
else if (display->platform.battlemage || display->platform.meteorlake)
|
||||
pch_type = PCH_MTL;
|
||||
else if (display->platform.dg2)
|
||||
pch_type = PCH_DG2;
|
||||
else if (display->platform.dg1)
|
||||
pch_type = PCH_DG1;
|
||||
|
||||
return pch_type;
|
||||
}
|
||||
|
||||
/* Map PCH device id to PCH type, or PCH_NONE if unknown. */
|
||||
static enum intel_pch
|
||||
intel_pch_type(const struct intel_display *display, unsigned short id)
|
||||
{
|
||||
switch (id) {
|
||||
case INTEL_PCH_IBX_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Ibex Peak PCH\n");
|
||||
drm_WARN_ON(display->drm, DISPLAY_VER(display) != 5);
|
||||
return PCH_IBX;
|
||||
case INTEL_PCH_CPT_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found CougarPoint PCH\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
DISPLAY_VER(display) != 6 &&
|
||||
!display->platform.ivybridge);
|
||||
return PCH_CPT;
|
||||
case INTEL_PCH_PPT_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found PantherPoint PCH\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
DISPLAY_VER(display) != 6 &&
|
||||
!display->platform.ivybridge);
|
||||
/* PPT is CPT compatible */
|
||||
return PCH_CPT;
|
||||
case INTEL_PCH_LPT_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found LynxPoint PCH\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.haswell &&
|
||||
!display->platform.broadwell);
|
||||
drm_WARN_ON(display->drm,
|
||||
display->platform.haswell_ult ||
|
||||
display->platform.broadwell_ult);
|
||||
return PCH_LPT_H;
|
||||
case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found LynxPoint LP PCH\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.haswell &&
|
||||
!display->platform.broadwell);
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.haswell_ult &&
|
||||
!display->platform.broadwell_ult);
|
||||
return PCH_LPT_LP;
|
||||
case INTEL_PCH_WPT_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found WildcatPoint PCH\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.haswell &&
|
||||
!display->platform.broadwell);
|
||||
drm_WARN_ON(display->drm,
|
||||
display->platform.haswell_ult ||
|
||||
display->platform.broadwell_ult);
|
||||
/* WPT is LPT compatible */
|
||||
return PCH_LPT_H;
|
||||
case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found WildcatPoint LP PCH\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.haswell &&
|
||||
!display->platform.broadwell);
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.haswell_ult &&
|
||||
!display->platform.broadwell_ult);
|
||||
/* WPT is LPT compatible */
|
||||
return PCH_LPT_LP;
|
||||
case INTEL_PCH_SPT_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found SunrisePoint PCH\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.skylake &&
|
||||
!display->platform.kabylake &&
|
||||
!display->platform.coffeelake);
|
||||
return PCH_SPT;
|
||||
case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found SunrisePoint LP PCH\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.skylake &&
|
||||
!display->platform.kabylake &&
|
||||
!display->platform.coffeelake &&
|
||||
!display->platform.cometlake);
|
||||
return PCH_SPT;
|
||||
case INTEL_PCH_KBP_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Kaby Lake PCH (KBP)\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.skylake &&
|
||||
!display->platform.kabylake &&
|
||||
!display->platform.coffeelake &&
|
||||
!display->platform.cometlake);
|
||||
/* KBP is SPT compatible */
|
||||
return PCH_SPT;
|
||||
case INTEL_PCH_CNP_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Cannon Lake PCH (CNP)\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.coffeelake &&
|
||||
!display->platform.cometlake);
|
||||
return PCH_CNP;
|
||||
case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm,
|
||||
"Found Cannon Lake LP PCH (CNP-LP)\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.coffeelake &&
|
||||
!display->platform.cometlake);
|
||||
return PCH_CNP;
|
||||
case INTEL_PCH_CMP_DEVICE_ID_TYPE:
|
||||
case INTEL_PCH_CMP2_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Comet Lake PCH (CMP)\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.coffeelake &&
|
||||
!display->platform.cometlake &&
|
||||
!display->platform.rocketlake);
|
||||
/* CMP is CNP compatible */
|
||||
return PCH_CNP;
|
||||
case INTEL_PCH_CMP_V_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Comet Lake V PCH (CMP-V)\n");
|
||||
drm_WARN_ON(display->drm,
|
||||
!display->platform.coffeelake &&
|
||||
!display->platform.cometlake);
|
||||
/* CMP-V is based on KBP, which is SPT compatible */
|
||||
return PCH_SPT;
|
||||
case INTEL_PCH_ICP_DEVICE_ID_TYPE:
|
||||
case INTEL_PCH_ICP2_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Ice Lake PCH\n");
|
||||
drm_WARN_ON(display->drm, !display->platform.icelake);
|
||||
return PCH_ICP;
|
||||
case INTEL_PCH_MCC_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Mule Creek Canyon PCH\n");
|
||||
drm_WARN_ON(display->drm, !(display->platform.jasperlake ||
|
||||
display->platform.elkhartlake));
|
||||
/* MCC is TGP compatible */
|
||||
return PCH_TGP;
|
||||
case INTEL_PCH_TGP_DEVICE_ID_TYPE:
|
||||
case INTEL_PCH_TGP2_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Tiger Lake LP PCH\n");
|
||||
drm_WARN_ON(display->drm, !display->platform.tigerlake &&
|
||||
!display->platform.rocketlake &&
|
||||
!display->platform.skylake &&
|
||||
!display->platform.kabylake &&
|
||||
!display->platform.coffeelake &&
|
||||
!display->platform.cometlake);
|
||||
return PCH_TGP;
|
||||
case INTEL_PCH_JSP_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Jasper Lake PCH\n");
|
||||
drm_WARN_ON(display->drm, !(display->platform.jasperlake ||
|
||||
display->platform.elkhartlake));
|
||||
/* JSP is ICP compatible */
|
||||
return PCH_ICP;
|
||||
case INTEL_PCH_ADP_DEVICE_ID_TYPE:
|
||||
case INTEL_PCH_ADP2_DEVICE_ID_TYPE:
|
||||
case INTEL_PCH_ADP3_DEVICE_ID_TYPE:
|
||||
case INTEL_PCH_ADP4_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(display->drm, "Found Alder Lake PCH\n");
|
||||
drm_WARN_ON(display->drm, !display->platform.alderlake_s &&
|
||||
!display->platform.alderlake_p);
|
||||
return PCH_ADP;
|
||||
default:
|
||||
return PCH_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static bool intel_is_virt_pch(unsigned short id,
|
||||
unsigned short svendor, unsigned short sdevice)
|
||||
{
|
||||
return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE ||
|
||||
id == INTEL_PCH_P3X_DEVICE_ID_TYPE ||
|
||||
(id == INTEL_PCH_QEMU_DEVICE_ID_TYPE &&
|
||||
svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
|
||||
sdevice == PCI_SUBDEVICE_ID_QEMU));
|
||||
}
|
||||
|
||||
static void
|
||||
intel_virt_detect_pch(const struct intel_display *display,
|
||||
unsigned short *pch_id, enum intel_pch *pch_type)
|
||||
{
|
||||
unsigned short id = 0;
|
||||
|
||||
/*
|
||||
* In a virtualized passthrough environment we can be in a
|
||||
* setup where the ISA bridge is not able to be passed through.
|
||||
* In this case, a south bridge can be emulated and we have to
|
||||
* make an educated guess as to which PCH is really there.
|
||||
*/
|
||||
|
||||
if (display->platform.alderlake_s || display->platform.alderlake_p)
|
||||
id = INTEL_PCH_ADP_DEVICE_ID_TYPE;
|
||||
else if (display->platform.tigerlake || display->platform.rocketlake)
|
||||
id = INTEL_PCH_TGP_DEVICE_ID_TYPE;
|
||||
else if (display->platform.jasperlake || display->platform.elkhartlake)
|
||||
id = INTEL_PCH_MCC_DEVICE_ID_TYPE;
|
||||
else if (display->platform.icelake)
|
||||
id = INTEL_PCH_ICP_DEVICE_ID_TYPE;
|
||||
else if (display->platform.coffeelake ||
|
||||
display->platform.cometlake)
|
||||
id = INTEL_PCH_CNP_DEVICE_ID_TYPE;
|
||||
else if (display->platform.kabylake || display->platform.skylake)
|
||||
id = INTEL_PCH_SPT_DEVICE_ID_TYPE;
|
||||
else if (display->platform.haswell_ult ||
|
||||
display->platform.broadwell_ult)
|
||||
id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE;
|
||||
else if (display->platform.haswell || display->platform.broadwell)
|
||||
id = INTEL_PCH_LPT_DEVICE_ID_TYPE;
|
||||
else if (DISPLAY_VER(display) == 6 || display->platform.ivybridge)
|
||||
id = INTEL_PCH_CPT_DEVICE_ID_TYPE;
|
||||
else if (DISPLAY_VER(display) == 5)
|
||||
id = INTEL_PCH_IBX_DEVICE_ID_TYPE;
|
||||
|
||||
if (id)
|
||||
drm_dbg_kms(display->drm, "Assuming PCH ID %04x\n", id);
|
||||
else
|
||||
drm_dbg_kms(display->drm, "Assuming no PCH\n");
|
||||
|
||||
*pch_type = intel_pch_type(display, id);
|
||||
|
||||
/* Sanity check virtual PCH id */
|
||||
if (drm_WARN_ON(display->drm,
|
||||
id && *pch_type == PCH_NONE))
|
||||
id = 0;
|
||||
|
||||
*pch_id = id;
|
||||
}
|
||||
|
||||
void intel_pch_detect(struct intel_display *display)
|
||||
{
|
||||
struct pci_dev *pch = NULL;
|
||||
unsigned short id;
|
||||
enum intel_pch pch_type;
|
||||
|
||||
pch_type = intel_pch_fake_for_south_display(display);
|
||||
if (pch_type != PCH_NONE) {
|
||||
display->pch_type = pch_type;
|
||||
drm_dbg_kms(display->drm,
|
||||
"PCH not involved in display, using fake PCH type %d for south display\n",
|
||||
pch_type);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The reason to probe ISA bridge instead of Dev31:Fun0 is to
|
||||
* make graphics device passthrough work easy for VMM, that only
|
||||
* need to expose ISA bridge to let driver know the real hardware
|
||||
* underneath. This is a requirement from virtualization team.
|
||||
*
|
||||
* In some virtualized environments (e.g. XEN), there is irrelevant
|
||||
* ISA bridge in the system. To work reliably, we should scan through
|
||||
* all the ISA bridge devices and check for the first match, instead
|
||||
* of only checking the first one.
|
||||
*/
|
||||
while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
|
||||
if (pch->vendor != PCI_VENDOR_ID_INTEL)
|
||||
continue;
|
||||
|
||||
id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
|
||||
|
||||
pch_type = intel_pch_type(display, id);
|
||||
if (pch_type != PCH_NONE) {
|
||||
display->pch_type = pch_type;
|
||||
break;
|
||||
} else if (intel_is_virt_pch(id, pch->subsystem_vendor,
|
||||
pch->subsystem_device)) {
|
||||
intel_virt_detect_pch(display, &id, &pch_type);
|
||||
display->pch_type = pch_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Use PCH_NOP (PCH but no South Display) for PCH platforms without
|
||||
* display.
|
||||
*/
|
||||
if (pch && !HAS_DISPLAY(display)) {
|
||||
drm_dbg_kms(display->drm,
|
||||
"Display disabled, reverting to NOP PCH\n");
|
||||
display->pch_type = PCH_NOP;
|
||||
} else if (!pch) {
|
||||
if (i915_run_as_guest() && HAS_DISPLAY(display)) {
|
||||
intel_virt_detect_pch(display, &id, &pch_type);
|
||||
display->pch_type = pch_type;
|
||||
} else {
|
||||
drm_dbg_kms(display->drm, "No PCH found.\n");
|
||||
}
|
||||
}
|
||||
|
||||
pci_dev_put(pch);
|
||||
}
|
||||
58
drivers/gpu/drm/i915/display/intel_pch.h
Normal file
58
drivers/gpu/drm/i915/display/intel_pch.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright 2025 Intel Corporation.
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_PCH__
|
||||
#define __INTEL_PCH__
|
||||
|
||||
#include "intel_display_conversion.h"
|
||||
|
||||
struct intel_display;
|
||||
|
||||
/*
|
||||
* Sorted by south display engine compatibility.
|
||||
* If the new PCH comes with a south display engine that is not
|
||||
* inherited from the latest item, please do not add it to the
|
||||
* end. Instead, add it right after its "parent" PCH.
|
||||
*/
|
||||
enum intel_pch {
|
||||
PCH_NOP = -1, /* PCH without south display */
|
||||
PCH_NONE = 0, /* No PCH present */
|
||||
PCH_IBX, /* Ibexpeak PCH */
|
||||
PCH_CPT, /* Cougarpoint/Pantherpoint PCH */
|
||||
PCH_LPT_H, /* Lynxpoint/Wildcatpoint H PCH */
|
||||
PCH_LPT_LP, /* Lynxpoint/Wildcatpoint LP PCH */
|
||||
PCH_SPT, /* Sunrisepoint/Kaby Lake PCH */
|
||||
PCH_CNP, /* Cannon/Comet Lake PCH */
|
||||
PCH_ICP, /* Ice Lake/Jasper Lake PCH */
|
||||
PCH_TGP, /* Tiger Lake/Mule Creek Canyon PCH */
|
||||
PCH_ADP, /* Alder Lake PCH */
|
||||
|
||||
/* Fake PCHs, functionality handled on the same PCI dev */
|
||||
PCH_DG1 = 1024,
|
||||
PCH_DG2,
|
||||
PCH_MTL,
|
||||
PCH_LNL,
|
||||
};
|
||||
|
||||
#define INTEL_PCH_TYPE(_display) (__to_intel_display(_display)->pch_type)
|
||||
#define HAS_PCH_DG2(display) (INTEL_PCH_TYPE(display) == PCH_DG2)
|
||||
#define HAS_PCH_ADP(display) (INTEL_PCH_TYPE(display) == PCH_ADP)
|
||||
#define HAS_PCH_DG1(display) (INTEL_PCH_TYPE(display) == PCH_DG1)
|
||||
#define HAS_PCH_TGP(display) (INTEL_PCH_TYPE(display) == PCH_TGP)
|
||||
#define HAS_PCH_ICP(display) (INTEL_PCH_TYPE(display) == PCH_ICP)
|
||||
#define HAS_PCH_CNP(display) (INTEL_PCH_TYPE(display) == PCH_CNP)
|
||||
#define HAS_PCH_SPT(display) (INTEL_PCH_TYPE(display) == PCH_SPT)
|
||||
#define HAS_PCH_LPT_H(display) (INTEL_PCH_TYPE(display) == PCH_LPT_H)
|
||||
#define HAS_PCH_LPT_LP(display) (INTEL_PCH_TYPE(display) == PCH_LPT_LP)
|
||||
#define HAS_PCH_LPT(display) (INTEL_PCH_TYPE(display) == PCH_LPT_H || \
|
||||
INTEL_PCH_TYPE(display) == PCH_LPT_LP)
|
||||
#define HAS_PCH_CPT(display) (INTEL_PCH_TYPE(display) == PCH_CPT)
|
||||
#define HAS_PCH_IBX(display) (INTEL_PCH_TYPE(display) == PCH_IBX)
|
||||
#define HAS_PCH_NOP(display) (INTEL_PCH_TYPE(display) == PCH_NOP)
|
||||
#define HAS_PCH_SPLIT(display) (INTEL_PCH_TYPE(display) != PCH_NONE)
|
||||
|
||||
void intel_pch_detect(struct intel_display *display);
|
||||
|
||||
#endif /* __INTEL_PCH__ */
|
||||
@@ -3,8 +3,9 @@
|
||||
* Copyright © 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "g4x_dp.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_crt.h"
|
||||
#include "intel_crt_regs.h"
|
||||
@@ -23,17 +24,15 @@
|
||||
bool intel_has_pch_trancoder(struct intel_display *display,
|
||||
enum pipe pch_transcoder)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
return HAS_PCH_IBX(i915) || HAS_PCH_CPT(i915) ||
|
||||
(HAS_PCH_LPT_H(i915) && pch_transcoder == PIPE_A);
|
||||
return HAS_PCH_IBX(display) || HAS_PCH_CPT(display) ||
|
||||
(HAS_PCH_LPT_H(display) && pch_transcoder == PIPE_A);
|
||||
}
|
||||
|
||||
enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
|
||||
if (HAS_PCH_LPT(i915))
|
||||
if (HAS_PCH_LPT(display))
|
||||
return PIPE_A;
|
||||
else
|
||||
return crtc->pipe;
|
||||
@@ -43,7 +42,6 @@ static void assert_pch_dp_disabled(struct intel_display *display,
|
||||
enum pipe pipe, enum port port,
|
||||
i915_reg_t dp_reg)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe port_pipe;
|
||||
bool state;
|
||||
|
||||
@@ -54,7 +52,7 @@ static void assert_pch_dp_disabled(struct intel_display *display,
|
||||
port_name(port), pipe_name(pipe));
|
||||
|
||||
INTEL_DISPLAY_STATE_WARN(display,
|
||||
HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
|
||||
HAS_PCH_IBX(display) && !state && port_pipe == PIPE_B,
|
||||
"IBX PCH DP %c still using transcoder B\n",
|
||||
port_name(port));
|
||||
}
|
||||
@@ -63,7 +61,6 @@ static void assert_pch_hdmi_disabled(struct intel_display *display,
|
||||
enum pipe pipe, enum port port,
|
||||
i915_reg_t hdmi_reg)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
enum pipe port_pipe;
|
||||
bool state;
|
||||
|
||||
@@ -74,7 +71,7 @@ static void assert_pch_hdmi_disabled(struct intel_display *display,
|
||||
port_name(port), pipe_name(pipe));
|
||||
|
||||
INTEL_DISPLAY_STATE_WARN(display,
|
||||
HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
|
||||
HAS_PCH_IBX(display) && !state && port_pipe == PIPE_B,
|
||||
"IBX PCH HDMI %c still using transcoder B\n",
|
||||
port_name(port));
|
||||
}
|
||||
@@ -249,7 +246,6 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
i915_reg_t reg;
|
||||
u32 val, pipeconf_val;
|
||||
@@ -261,7 +257,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
|
||||
assert_fdi_tx_enabled(display, pipe);
|
||||
assert_fdi_rx_enabled(display, pipe);
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv)) {
|
||||
if (HAS_PCH_CPT(display)) {
|
||||
reg = TRANS_CHICKEN2(pipe);
|
||||
val = intel_de_read(display, reg);
|
||||
/*
|
||||
@@ -279,7 +275,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
|
||||
val = intel_de_read(display, reg);
|
||||
pipeconf_val = intel_de_read(display, TRANSCONF(display, pipe));
|
||||
|
||||
if (HAS_PCH_IBX(dev_priv)) {
|
||||
if (HAS_PCH_IBX(display)) {
|
||||
/* Configure frame start delay to match the CPU */
|
||||
val &= ~TRANS_FRAME_START_DELAY_MASK;
|
||||
val |= TRANS_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
|
||||
@@ -298,7 +294,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
|
||||
|
||||
val &= ~TRANS_INTERLACE_MASK;
|
||||
if ((pipeconf_val & TRANSCONF_INTERLACE_MASK_ILK) == TRANSCONF_INTERLACE_IF_ID_ILK) {
|
||||
if (HAS_PCH_IBX(dev_priv) &&
|
||||
if (HAS_PCH_IBX(display) &&
|
||||
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO))
|
||||
val |= TRANS_INTERLACE_LEGACY_VSYNC_IBX;
|
||||
else
|
||||
@@ -316,7 +312,6 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
|
||||
static void ilk_disable_pch_transcoder(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
i915_reg_t reg;
|
||||
|
||||
@@ -334,7 +329,7 @@ static void ilk_disable_pch_transcoder(struct intel_crtc *crtc)
|
||||
drm_err(display->drm, "failed to disable transcoder %c\n",
|
||||
pipe_name(pipe));
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_CPT(display))
|
||||
/* Workaround: Clear the timing override chicken bit again. */
|
||||
intel_de_rmw(display, TRANS_CHICKEN2(pipe),
|
||||
TRANS_CHICKEN2_TIMING_OVERRIDE, 0);
|
||||
@@ -366,7 +361,6 @@ void ilk_pch_enable(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct intel_crtc_state *crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
@@ -381,7 +375,7 @@ void ilk_pch_enable(struct intel_atomic_state *state,
|
||||
* We need to program the right clock selection
|
||||
* before writing the pixel multiplier into the DPLL.
|
||||
*/
|
||||
if (HAS_PCH_CPT(dev_priv)) {
|
||||
if (HAS_PCH_CPT(display)) {
|
||||
u32 sel;
|
||||
|
||||
temp = intel_de_read(display, PCH_DPLL_SEL);
|
||||
@@ -417,7 +411,7 @@ void ilk_pch_enable(struct intel_atomic_state *state,
|
||||
intel_fdi_normal_train(crtc);
|
||||
|
||||
/* For PCH DP, enable TRANS_DP_CTL */
|
||||
if (HAS_PCH_CPT(dev_priv) &&
|
||||
if (HAS_PCH_CPT(display) &&
|
||||
intel_crtc_has_dp_encoder(crtc_state)) {
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
@@ -459,14 +453,13 @@ void ilk_pch_post_disable(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct intel_crtc_state *old_crtc_state =
|
||||
intel_atomic_get_old_crtc_state(state, crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
ilk_disable_pch_transcoder(crtc);
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv)) {
|
||||
if (HAS_PCH_CPT(display)) {
|
||||
/* disable TRANS_DP_CTL */
|
||||
intel_de_rmw(display, TRANS_DP_CTL(pipe),
|
||||
TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK,
|
||||
@@ -503,7 +496,6 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
struct intel_shared_dpll *pll;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
enum intel_dpll_id pll_id;
|
||||
@@ -522,7 +514,7 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state)
|
||||
intel_cpu_transcoder_get_m1_n1(crtc, crtc_state->cpu_transcoder,
|
||||
&crtc_state->fdi_m_n);
|
||||
|
||||
if (HAS_PCH_IBX(dev_priv)) {
|
||||
if (HAS_PCH_IBX(display)) {
|
||||
/*
|
||||
* The pipe->pch transcoder and pch transcoder->pll
|
||||
* mapping is fixed.
|
||||
@@ -646,8 +638,6 @@ void lpt_pch_get_config(struct intel_crtc_state *crtc_state)
|
||||
|
||||
void intel_pch_sanitize(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (HAS_PCH_IBX(i915))
|
||||
if (HAS_PCH_IBX(display))
|
||||
ibx_sanitize_pch_ports(display);
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ static void lpt_enable_clkout_dp(struct intel_display *display,
|
||||
if (drm_WARN(display->drm, with_fdi && !with_spread,
|
||||
"FDI requires downspread\n"))
|
||||
with_spread = true;
|
||||
if (drm_WARN(display->drm, HAS_PCH_LPT_LP(dev_priv) &&
|
||||
if (drm_WARN(display->drm, HAS_PCH_LPT_LP(display) &&
|
||||
with_fdi, "LP PCH doesn't have FDI\n"))
|
||||
with_fdi = false;
|
||||
|
||||
@@ -303,7 +303,7 @@ static void lpt_enable_clkout_dp(struct intel_display *display,
|
||||
lpt_fdi_program_mphy(display);
|
||||
}
|
||||
|
||||
reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
|
||||
reg = HAS_PCH_LPT_LP(display) ? SBI_GEN0 : SBI_DBUFF0;
|
||||
tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
|
||||
tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE;
|
||||
intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
|
||||
@@ -319,7 +319,7 @@ void lpt_disable_clkout_dp(struct intel_display *display)
|
||||
|
||||
intel_sbi_lock(dev_priv);
|
||||
|
||||
reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
|
||||
reg = HAS_PCH_LPT_LP(display) ? SBI_GEN0 : SBI_DBUFF0;
|
||||
tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
|
||||
tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE;
|
||||
intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
|
||||
@@ -498,7 +498,6 @@ static void lpt_init_pch_refclk(struct intel_display *display)
|
||||
|
||||
static void ilk_init_pch_refclk(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_shared_dpll *pll;
|
||||
int i;
|
||||
@@ -527,7 +526,7 @@ static void ilk_init_pch_refclk(struct intel_display *display)
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_PCH_IBX(dev_priv)) {
|
||||
if (HAS_PCH_IBX(display)) {
|
||||
has_ck505 = display->vbt.display_clock_mode;
|
||||
can_ssc = has_ck505;
|
||||
} else {
|
||||
@@ -678,10 +677,8 @@ static void ilk_init_pch_refclk(struct intel_display *display)
|
||||
*/
|
||||
void intel_init_pch_refclk(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_IBX(display) || HAS_PCH_CPT(display))
|
||||
ilk_init_pch_refclk(display);
|
||||
else if (HAS_PCH_LPT(dev_priv))
|
||||
else if (HAS_PCH_LPT(display))
|
||||
lpt_init_pch_refclk(display);
|
||||
}
|
||||
|
||||
@@ -53,9 +53,11 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this,
|
||||
}
|
||||
|
||||
static enum intel_memory_type
|
||||
initial_plane_memory_type(struct drm_i915_private *i915)
|
||||
initial_plane_memory_type(struct intel_display *display)
|
||||
{
|
||||
if (IS_DGFX(i915))
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (display->platform.dgfx)
|
||||
return INTEL_MEMORY_LOCAL;
|
||||
else if (HAS_LMEMBAR_SMEM_STOLEN(i915))
|
||||
return INTEL_MEMORY_STOLEN_LOCAL;
|
||||
@@ -75,7 +77,7 @@ initial_plane_phys(struct intel_display *display,
|
||||
dma_addr_t dma_addr;
|
||||
u32 base;
|
||||
|
||||
mem_type = initial_plane_memory_type(i915);
|
||||
mem_type = initial_plane_memory_type(display);
|
||||
mem = intel_memory_region_by_type(i915, mem_type);
|
||||
if (!mem) {
|
||||
drm_dbg_kms(display->drm,
|
||||
|
||||
@@ -478,13 +478,34 @@ static bool intel_pmdemand_req_complete(struct intel_display *display)
|
||||
XELPDP_PMDEMAND_REQ_ENABLE);
|
||||
}
|
||||
|
||||
static void intel_pmdemand_poll(struct intel_display *display)
|
||||
{
|
||||
const unsigned int timeout_ms = 10;
|
||||
u32 status;
|
||||
int ret;
|
||||
|
||||
ret = intel_de_wait_custom(display, XELPDP_INITIATE_PMDEMAND_REQUEST(1),
|
||||
XELPDP_PMDEMAND_REQ_ENABLE, 0,
|
||||
50, timeout_ms, &status);
|
||||
|
||||
if (ret == -ETIMEDOUT)
|
||||
drm_err(display->drm,
|
||||
"timed out waiting for Punit PM Demand Response within %ums (status 0x%08x)\n",
|
||||
timeout_ms, status);
|
||||
}
|
||||
|
||||
static void intel_pmdemand_wait(struct intel_display *display)
|
||||
{
|
||||
if (!wait_event_timeout(display->pmdemand.waitqueue,
|
||||
intel_pmdemand_req_complete(display),
|
||||
msecs_to_jiffies_timeout(10)))
|
||||
drm_err(display->drm,
|
||||
"timed out waiting for Punit PM Demand Response\n");
|
||||
/* Wa_14024400148 For lnl use polling method */
|
||||
if (DISPLAY_VER(display) == 20) {
|
||||
intel_pmdemand_poll(display);
|
||||
} else {
|
||||
if (!wait_event_timeout(display->pmdemand.waitqueue,
|
||||
intel_pmdemand_req_complete(display),
|
||||
msecs_to_jiffies_timeout(10)))
|
||||
drm_err(display->drm,
|
||||
"timed out waiting for Punit PM Demand Response\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Required to be programmed during Display Init Sequences. */
|
||||
|
||||
@@ -350,21 +350,19 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
|
||||
|
||||
static int intel_num_pps(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (display->platform.valleyview || display->platform.cherryview)
|
||||
return 2;
|
||||
|
||||
if (display->platform.geminilake || display->platform.broxton)
|
||||
return 2;
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_MTL)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_MTL)
|
||||
return 2;
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_DG1)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_DG1)
|
||||
return 1;
|
||||
|
||||
if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
|
||||
if (INTEL_PCH_TYPE(display) >= PCH_ICP)
|
||||
return 2;
|
||||
|
||||
return 1;
|
||||
@@ -373,11 +371,10 @@ static int intel_num_pps(struct intel_display *display)
|
||||
static bool intel_pps_is_valid(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (intel_dp->pps.pps_idx == 1 &&
|
||||
INTEL_PCH_TYPE(i915) >= PCH_ICP &&
|
||||
INTEL_PCH_TYPE(i915) <= PCH_ADP)
|
||||
INTEL_PCH_TYPE(display) >= PCH_ICP &&
|
||||
INTEL_PCH_TYPE(display) <= PCH_ADP)
|
||||
return intel_de_read(display, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT;
|
||||
|
||||
return true;
|
||||
@@ -499,7 +496,6 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp,
|
||||
struct pps_registers *regs)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
int pps_idx;
|
||||
|
||||
memset(regs, 0, sizeof(*regs));
|
||||
@@ -518,7 +514,7 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp,
|
||||
|
||||
/* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
|
||||
if (display->platform.geminilake || display->platform.broxton ||
|
||||
INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
|
||||
INTEL_PCH_TYPE(display) >= PCH_CNP)
|
||||
regs->pp_div = INVALID_MMIO_REG;
|
||||
else
|
||||
regs->pp_div = PP_DIVISOR(display, pps_idx);
|
||||
@@ -1591,7 +1587,6 @@ static void pps_init_delays(struct intel_dp *intel_dp)
|
||||
static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 pp_on, pp_off, port_sel = 0;
|
||||
int div = DISPLAY_RUNTIME_INFO(display)->rawclk_freq / 1000;
|
||||
struct pps_registers regs;
|
||||
@@ -1638,7 +1633,7 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
|
||||
* power sequencer any more. */
|
||||
if (display->platform.valleyview || display->platform.cherryview) {
|
||||
port_sel = PANEL_PORT_SELECT_VLV(port);
|
||||
} else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
|
||||
} else if (HAS_PCH_IBX(display) || HAS_PCH_CPT(display)) {
|
||||
switch (port) {
|
||||
case PORT_A:
|
||||
port_sel = PANEL_PORT_SELECT_DPA;
|
||||
@@ -1791,9 +1786,7 @@ void intel_pps_unlock_regs_wa(struct intel_display *display)
|
||||
|
||||
void intel_pps_setup(struct intel_display *display)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(display->drm);
|
||||
|
||||
if (HAS_PCH_SPLIT(i915) || display->platform.geminilake || display->platform.broxton)
|
||||
if (HAS_PCH_SPLIT(display) || display->platform.geminilake || display->platform.broxton)
|
||||
display->pps.mmio_base = PCH_PPS_BASE;
|
||||
else if (display->platform.valleyview || display->platform.cherryview)
|
||||
display->pps.mmio_base = VLV_PPS_BASE;
|
||||
@@ -1836,7 +1829,6 @@ void intel_pps_connector_debugfs_add(struct intel_connector *connector)
|
||||
|
||||
void assert_pps_unlocked(struct intel_display *display, enum pipe pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
i915_reg_t pp_reg;
|
||||
u32 val;
|
||||
enum pipe panel_pipe = INVALID_PIPE;
|
||||
@@ -1845,7 +1837,7 @@ void assert_pps_unlocked(struct intel_display *display, enum pipe pipe)
|
||||
if (drm_WARN_ON(display->drm, HAS_DDI(display)))
|
||||
return;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
u32 port_sel;
|
||||
|
||||
pp_reg = PP_CONTROL(display, 0);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
@@ -38,6 +39,7 @@
|
||||
#include "intel_display_irq.h"
|
||||
#include "intel_display_rpm.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dmc.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dp_aux.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
@@ -46,6 +48,7 @@
|
||||
#include "intel_psr_regs.h"
|
||||
#include "intel_snps_phy.h"
|
||||
#include "intel_vblank.h"
|
||||
#include "intel_vrr.h"
|
||||
#include "skl_universal_plane.h"
|
||||
|
||||
/**
|
||||
@@ -794,32 +797,9 @@ static void _psr_enable_sink(struct intel_dp *intel_dp,
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val);
|
||||
}
|
||||
|
||||
static void intel_psr_enable_sink_alpm(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
/*
|
||||
* eDP Panel Replay uses always ALPM
|
||||
* PSR2 uses ALPM but PSR1 doesn't
|
||||
*/
|
||||
if (!intel_dp_is_edp(intel_dp) || (!crtc_state->has_panel_replay &&
|
||||
!crtc_state->has_sel_update))
|
||||
return;
|
||||
|
||||
val = DP_ALPM_ENABLE | DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE;
|
||||
|
||||
if (crtc_state->has_panel_replay)
|
||||
val |= DP_ALPM_MODE_AUX_LESS;
|
||||
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val);
|
||||
}
|
||||
|
||||
static void intel_psr_enable_sink(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
intel_psr_enable_sink_alpm(intel_dp, crtc_state);
|
||||
|
||||
crtc_state->has_panel_replay ?
|
||||
_panel_replay_enable_sink(intel_dp, crtc_state) :
|
||||
_psr_enable_sink(intel_dp, crtc_state);
|
||||
@@ -905,6 +885,18 @@ static u8 psr_compute_idle_frames(struct intel_dp *intel_dp)
|
||||
return idle_frames;
|
||||
}
|
||||
|
||||
static bool is_dc5_dc6_blocked(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
u32 current_dc_state = intel_display_power_get_current_dc_state(display);
|
||||
struct drm_vblank_crtc *vblank = &display->drm->vblank[intel_dp->psr.pipe];
|
||||
|
||||
return (current_dc_state != DC_STATE_EN_UPTO_DC5 &&
|
||||
current_dc_state != DC_STATE_EN_UPTO_DC6) ||
|
||||
intel_dp->psr.active_non_psr_pipes ||
|
||||
READ_ONCE(vblank->enabled);
|
||||
}
|
||||
|
||||
static void hsw_activate_psr1(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
@@ -933,6 +925,14 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
|
||||
|
||||
intel_de_rmw(display, psr_ctl_reg(display, cpu_transcoder),
|
||||
~EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK, val);
|
||||
|
||||
/* Wa_16025596647 */
|
||||
if ((DISPLAY_VER(display) == 20 ||
|
||||
IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) &&
|
||||
is_dc5_dc6_blocked(intel_dp))
|
||||
intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(display,
|
||||
intel_dp->psr.pipe,
|
||||
true);
|
||||
}
|
||||
|
||||
static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
|
||||
@@ -1014,8 +1014,16 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
|
||||
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
|
||||
u32 val = EDP_PSR2_ENABLE;
|
||||
u32 psr_val = 0;
|
||||
u8 idle_frames;
|
||||
|
||||
val |= EDP_PSR2_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
|
||||
/* Wa_16025596647 */
|
||||
if ((DISPLAY_VER(display) == 20 ||
|
||||
IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) &&
|
||||
is_dc5_dc6_blocked(intel_dp))
|
||||
idle_frames = 0;
|
||||
else
|
||||
idle_frames = psr_compute_idle_frames(intel_dp);
|
||||
val |= EDP_PSR2_IDLE_FRAMES(idle_frames);
|
||||
|
||||
if (DISPLAY_VER(display) < 14 && !display->platform.alderlake_p)
|
||||
val |= EDP_SU_TRACK_ENABLE;
|
||||
@@ -1649,6 +1657,9 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
|
||||
struct intel_crtc *crtc;
|
||||
u8 active_pipes = 0;
|
||||
|
||||
if (!psr_global_enabled(intel_dp)) {
|
||||
drm_dbg_kms(display->drm, "PSR disabled by flag\n");
|
||||
@@ -1702,6 +1713,24 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
|
||||
drm_dbg_kms(display->drm,
|
||||
"PSR disabled to workaround PSR FSM hang issue\n");
|
||||
}
|
||||
|
||||
/* Rest is for Wa_16025596647 */
|
||||
if (DISPLAY_VER(display) != 20 &&
|
||||
!IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0))
|
||||
return;
|
||||
|
||||
/* Not needed by Panel Replay */
|
||||
if (crtc_state->has_panel_replay)
|
||||
return;
|
||||
|
||||
/* We ignore possible secondary PSR/Panel Replay capable eDP */
|
||||
for_each_intel_crtc(display->drm, crtc)
|
||||
active_pipes |= crtc->active ? BIT(crtc->pipe) : 0;
|
||||
|
||||
active_pipes = intel_calc_active_pipes(state, active_pipes);
|
||||
|
||||
crtc_state->active_non_psr_pipes = active_pipes &
|
||||
~BIT(to_intel_crtc(crtc_state->uapi.crtc)->pipe);
|
||||
}
|
||||
|
||||
void intel_psr_get_config(struct intel_encoder *encoder,
|
||||
@@ -1893,9 +1922,6 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
|
||||
intel_dp->psr.psr2_sel_fetch_enabled ?
|
||||
IGNORE_PSR2_HW_TRACKING : 0);
|
||||
|
||||
if (intel_dp_is_edp(intel_dp))
|
||||
intel_alpm_configure(intel_dp, crtc_state);
|
||||
|
||||
/*
|
||||
* Wa_16013835468
|
||||
* Wa_14015648006
|
||||
@@ -1930,6 +1956,12 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
|
||||
intel_de_rmw(display, CLKGATE_DIS_MISC, 0,
|
||||
CLKGATE_DIS_MISC_DMASC_GATING_DIS);
|
||||
}
|
||||
|
||||
/* Wa_16025596647 */
|
||||
if ((DISPLAY_VER(display) == 20 ||
|
||||
IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) &&
|
||||
!intel_dp->psr.panel_replay_enabled)
|
||||
intel_dmc_block_pkgc(display, intel_dp->psr.pipe, true);
|
||||
}
|
||||
|
||||
static bool psr_interrupt_error_check(struct intel_dp *intel_dp)
|
||||
@@ -1985,6 +2017,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
|
||||
intel_dp->psr.psr2_sel_fetch_cff_enabled = false;
|
||||
intel_dp->psr.req_psr2_sdp_prior_scanline =
|
||||
crtc_state->req_psr2_sdp_prior_scanline;
|
||||
intel_dp->psr.active_non_psr_pipes = crtc_state->active_non_psr_pipes;
|
||||
|
||||
if (!psr_interrupt_error_check(intel_dp))
|
||||
return;
|
||||
@@ -2060,6 +2093,12 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
|
||||
|
||||
drm_WARN_ON(display->drm, !(val & EDP_PSR2_ENABLE));
|
||||
} else {
|
||||
if (DISPLAY_VER(display) == 20 ||
|
||||
IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0))
|
||||
intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(display,
|
||||
intel_dp->psr.pipe,
|
||||
false);
|
||||
|
||||
val = intel_de_rmw(display,
|
||||
psr_ctl_reg(display, cpu_transcoder),
|
||||
EDP_PSR_ENABLE, 0);
|
||||
@@ -2133,17 +2172,6 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
|
||||
if (intel_dp_is_edp(intel_dp))
|
||||
intel_snps_phy_update_psr_power_state(&dp_to_dig_port(intel_dp)->base, false);
|
||||
|
||||
/* Panel Replay on eDP is always using ALPM aux less. */
|
||||
if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) {
|
||||
intel_de_rmw(display, ALPM_CTL(display, cpu_transcoder),
|
||||
ALPM_CTL_ALPM_ENABLE |
|
||||
ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
|
||||
|
||||
intel_de_rmw(display,
|
||||
PORT_ALPM_CTL(cpu_transcoder),
|
||||
PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
|
||||
}
|
||||
|
||||
/* Disable PSR on Sink */
|
||||
if (!intel_dp->psr.panel_replay_enabled) {
|
||||
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
|
||||
@@ -2153,12 +2181,19 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
|
||||
DP_RECEIVER_ALPM_CONFIG, 0);
|
||||
}
|
||||
|
||||
/* Wa_16025596647 */
|
||||
if ((DISPLAY_VER(display) == 20 ||
|
||||
IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) &&
|
||||
!intel_dp->psr.panel_replay_enabled)
|
||||
intel_dmc_block_pkgc(display, intel_dp->psr.pipe, false);
|
||||
|
||||
intel_dp->psr.enabled = false;
|
||||
intel_dp->psr.panel_replay_enabled = false;
|
||||
intel_dp->psr.sel_update_enabled = false;
|
||||
intel_dp->psr.psr2_sel_fetch_enabled = false;
|
||||
intel_dp->psr.su_region_et_enabled = false;
|
||||
intel_dp->psr.psr2_sel_fetch_cff_enabled = false;
|
||||
intel_dp->psr.active_non_psr_pipes = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2254,17 +2289,20 @@ out:
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_needs_block_dc_vblank - Check if block dc entry is needed
|
||||
* intel_psr_needs_vblank_notification - Check if PSR need vblank enable/disable
|
||||
* notification.
|
||||
* @crtc_state: CRTC status
|
||||
*
|
||||
* We need to block DC6 entry in case of Panel Replay as enabling VBI doesn't
|
||||
* prevent it in case of Panel Replay. Panel Replay switches main link off on
|
||||
* DC entry. This means vblank interrupts are not fired and is a problem if
|
||||
* user-space is polling for vblank events.
|
||||
* user-space is polling for vblank events. Also Wa_16025596647 needs
|
||||
* information when vblank is enabled/disabled.
|
||||
*/
|
||||
bool intel_psr_needs_block_dc_vblank(const struct intel_crtc_state *crtc_state)
|
||||
bool intel_psr_needs_vblank_notification(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
for_each_encoder_on_crtc(crtc->base.dev, &crtc->base, encoder) {
|
||||
@@ -2275,8 +2313,15 @@ bool intel_psr_needs_block_dc_vblank(const struct intel_crtc_state *crtc_state)
|
||||
|
||||
intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
if (intel_dp_is_edp(intel_dp) &&
|
||||
CAN_PANEL_REPLAY(intel_dp))
|
||||
if (!intel_dp_is_edp(intel_dp))
|
||||
continue;
|
||||
|
||||
if (CAN_PANEL_REPLAY(intel_dp))
|
||||
return true;
|
||||
|
||||
if ((DISPLAY_VER(display) == 20 ||
|
||||
IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) &&
|
||||
CAN_PSR(intel_dp))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2304,6 +2349,53 @@ void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb,
|
||||
CURSURFLIVE(display, crtc->pipe), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_min_vblank_delay - Minimum vblank delay needed by PSR
|
||||
* @crtc_state: the crtc state
|
||||
*
|
||||
* Return minimum vblank delay needed by PSR.
|
||||
*/
|
||||
int intel_psr_min_vblank_delay(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
|
||||
if (!crtc_state->has_psr)
|
||||
return 0;
|
||||
|
||||
/* Wa_14015401596 */
|
||||
if (intel_vrr_possible(crtc_state) && IS_DISPLAY_VER(display, 13, 14))
|
||||
return 1;
|
||||
|
||||
/* Rest is for SRD_STATUS needed on LunarLake and onwards */
|
||||
if (DISPLAY_VER(display) < 20)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Comment on SRD_STATUS register in Bspec for LunarLake and onwards:
|
||||
*
|
||||
* To deterministically capture the transition of the state machine
|
||||
* going from SRDOFFACK to IDLE, the delayed V. Blank should be at least
|
||||
* one line after the non-delayed V. Blank.
|
||||
*
|
||||
* Legacy TG: TRANS_SET_CONTEXT_LATENCY > 0
|
||||
* VRR TG: TRANS_VRR_CTL[ VRR Guardband ] < (TRANS_VRR_VMAX[ VRR Vmax ]
|
||||
* - TRANS_VTOTAL[ Vertical Active ])
|
||||
*
|
||||
* SRD_STATUS is used only by PSR1 on PantherLake.
|
||||
* SRD_STATUS is used by PSR1 and Panel Replay DP on LunarLake.
|
||||
*/
|
||||
|
||||
if (DISPLAY_VER(display) >= 30 && (crtc_state->has_panel_replay ||
|
||||
crtc_state->has_sel_update))
|
||||
return 0;
|
||||
else if (DISPLAY_VER(display) < 30 && (crtc_state->has_sel_update ||
|
||||
intel_crtc_has_type(crtc_state,
|
||||
INTEL_OUTPUT_EDP)))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 man_trk_ctl_enable_bit_get(struct intel_display *display)
|
||||
{
|
||||
return display->platform.alderlake_p || DISPLAY_VER(display) >= 14 ? 0 :
|
||||
@@ -3398,29 +3490,15 @@ static int psr_get_status_and_error_status(struct intel_dp *intel_dp,
|
||||
|
||||
static void psr_alpm_check(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
struct drm_dp_aux *aux = &intel_dp->aux;
|
||||
struct intel_psr *psr = &intel_dp->psr;
|
||||
u8 val;
|
||||
int r;
|
||||
|
||||
if (!psr->sel_update_enabled)
|
||||
return;
|
||||
|
||||
r = drm_dp_dpcd_readb(aux, DP_RECEIVER_ALPM_STATUS, &val);
|
||||
if (r != 1) {
|
||||
drm_err(display->drm, "Error reading ALPM status\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (val & DP_ALPM_LOCK_TIMEOUT_ERROR) {
|
||||
if (intel_alpm_get_error(intel_dp)) {
|
||||
intel_psr_disable_locked(intel_dp);
|
||||
psr->sink_not_reliable = true;
|
||||
drm_dbg_kms(display->drm,
|
||||
"ALPM lock timeout error, disabling PSR\n");
|
||||
|
||||
/* Clearing error */
|
||||
drm_dp_dpcd_writeb(aux, DP_RECEIVER_ALPM_STATUS, val);
|
||||
intel_alpm_disable(intel_dp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3605,6 +3683,168 @@ void intel_psr_unlock(const struct intel_crtc_state *crtc_state)
|
||||
}
|
||||
}
|
||||
|
||||
/* Wa_16025596647 */
|
||||
static void intel_psr_apply_underrun_on_idle_wa_locked(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
bool dc5_dc6_blocked;
|
||||
|
||||
if (!intel_dp->psr.active)
|
||||
return;
|
||||
|
||||
dc5_dc6_blocked = is_dc5_dc6_blocked(intel_dp);
|
||||
|
||||
if (intel_dp->psr.sel_update_enabled)
|
||||
psr2_program_idle_frames(intel_dp, dc5_dc6_blocked ? 0 :
|
||||
psr_compute_idle_frames(intel_dp));
|
||||
else
|
||||
intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(display,
|
||||
intel_dp->psr.pipe,
|
||||
dc5_dc6_blocked);
|
||||
}
|
||||
|
||||
static void psr_dc5_dc6_wa_work(struct work_struct *work)
|
||||
{
|
||||
struct intel_display *display = container_of(work, typeof(*display),
|
||||
psr_dc5_dc6_wa_work);
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
for_each_intel_encoder_with_psr(display->drm, encoder) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
mutex_lock(&intel_dp->psr.lock);
|
||||
|
||||
if (intel_dp->psr.enabled && !intel_dp->psr.panel_replay_enabled)
|
||||
intel_psr_apply_underrun_on_idle_wa_locked(intel_dp);
|
||||
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_notify_dc5_dc6 - Notify PSR about enable/disable dc5/dc6
|
||||
* @display: intel atomic state
|
||||
*
|
||||
* This is targeted for underrun on idle PSR HW bug (Wa_16025596647) to schedule
|
||||
* psr_dc5_dc6_wa_work used for applying/removing the workaround.
|
||||
*/
|
||||
void intel_psr_notify_dc5_dc6(struct intel_display *display)
|
||||
{
|
||||
if (DISPLAY_VER(display) != 20 &&
|
||||
!IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0))
|
||||
return;
|
||||
|
||||
schedule_work(&display->psr_dc5_dc6_wa_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_dc5_dc6_wa_init - Init work for underrun on idle PSR HW bug wa
|
||||
* @display: intel atomic state
|
||||
*
|
||||
* This is targeted for underrun on idle PSR HW bug (Wa_16025596647) to init
|
||||
* psr_dc5_dc6_wa_work used for applying the workaround.
|
||||
*/
|
||||
void intel_psr_dc5_dc6_wa_init(struct intel_display *display)
|
||||
{
|
||||
if (DISPLAY_VER(display) != 20 &&
|
||||
!IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0))
|
||||
return;
|
||||
|
||||
INIT_WORK(&display->psr_dc5_dc6_wa_work, psr_dc5_dc6_wa_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_notify_pipe_change - Notify PSR about enable/disable of a pipe
|
||||
* @state: intel atomic state
|
||||
* @crtc: intel crtc
|
||||
* @enable: enable/disable
|
||||
*
|
||||
* This is targeted for underrun on idle PSR HW bug (Wa_16025596647) to apply
|
||||
* remove the workaround when pipe is getting enabled/disabled
|
||||
*/
|
||||
void intel_psr_notify_pipe_change(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc, bool enable)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
if (DISPLAY_VER(display) != 20 &&
|
||||
!IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0))
|
||||
return;
|
||||
|
||||
for_each_intel_encoder_with_psr(display->drm, encoder) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
u8 active_non_psr_pipes;
|
||||
|
||||
mutex_lock(&intel_dp->psr.lock);
|
||||
|
||||
if (!intel_dp->psr.enabled || intel_dp->psr.panel_replay_enabled)
|
||||
goto unlock;
|
||||
|
||||
active_non_psr_pipes = intel_dp->psr.active_non_psr_pipes;
|
||||
|
||||
if (enable)
|
||||
active_non_psr_pipes |= BIT(crtc->pipe);
|
||||
else
|
||||
active_non_psr_pipes &= ~BIT(crtc->pipe);
|
||||
|
||||
if (active_non_psr_pipes == intel_dp->psr.active_non_psr_pipes)
|
||||
goto unlock;
|
||||
|
||||
if ((enable && intel_dp->psr.active_non_psr_pipes) ||
|
||||
(!enable && !intel_dp->psr.active_non_psr_pipes)) {
|
||||
intel_dp->psr.active_non_psr_pipes = active_non_psr_pipes;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
intel_dp->psr.active_non_psr_pipes = active_non_psr_pipes;
|
||||
|
||||
intel_psr_apply_underrun_on_idle_wa_locked(intel_dp);
|
||||
unlock:
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_psr_notify_vblank_enable_disable - Notify PSR about enable/disable of vblank
|
||||
* @display: intel display struct
|
||||
* @enable: enable/disable
|
||||
*
|
||||
* This is targeted for underrun on idle PSR HW bug (Wa_16025596647) to apply
|
||||
* remove the workaround when vblank is getting enabled/disabled
|
||||
*/
|
||||
void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
|
||||
bool enable)
|
||||
{
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
for_each_intel_encoder_with_psr(display->drm, encoder) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
mutex_lock(&intel_dp->psr.lock);
|
||||
if (intel_dp->psr.panel_replay_enabled) {
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (intel_dp->psr.enabled)
|
||||
intel_psr_apply_underrun_on_idle_wa_locked(intel_dp);
|
||||
|
||||
mutex_unlock(&intel_dp->psr.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: intel_display_power_set_target_dc_state is used
|
||||
* only by PSR * code for DC3CO handling. DC3CO target
|
||||
* state is currently disabled in * PSR code. If DC3CO
|
||||
* is taken into use we need take that into account here
|
||||
* as well.
|
||||
*/
|
||||
intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
|
||||
DC_STATE_EN_UPTO_DC6);
|
||||
}
|
||||
|
||||
static void
|
||||
psr_source_status(struct intel_dp *intel_dp, struct seq_file *m)
|
||||
{
|
||||
@@ -3977,3 +4217,13 @@ void intel_psr_connector_debugfs_add(struct intel_connector *connector)
|
||||
debugfs_create_file("i915_psr_status", 0444, root,
|
||||
connector, &i915_psr_status_fops);
|
||||
}
|
||||
|
||||
bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
/*
|
||||
* eDP Panel Replay uses always ALPM
|
||||
* PSR2 uses ALPM but PSR1 doesn't
|
||||
*/
|
||||
return intel_dp_is_edp(intel_dp) && (crtc_state->has_sel_update ||
|
||||
crtc_state->has_panel_replay);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,13 @@ void intel_psr2_program_trans_man_trk_ctl(struct intel_dsb *dsb,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_psr_pause(struct intel_dp *intel_dp);
|
||||
void intel_psr_resume(struct intel_dp *intel_dp);
|
||||
bool intel_psr_needs_block_dc_vblank(const struct intel_crtc_state *crtc_state);
|
||||
bool intel_psr_needs_vblank_notification(const struct intel_crtc_state *crtc_state);
|
||||
void intel_psr_notify_pipe_change(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc, bool enable);
|
||||
void intel_psr_notify_dc5_dc6(struct intel_display *display);
|
||||
void intel_psr_dc5_dc6_wa_init(struct intel_display *display);
|
||||
void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
|
||||
bool enable);
|
||||
bool intel_psr_link_ok(struct intel_dp *intel_dp);
|
||||
|
||||
void intel_psr_lock(const struct intel_crtc_state *crtc_state);
|
||||
@@ -67,7 +73,9 @@ void intel_psr_unlock(const struct intel_crtc_state *crtc_state);
|
||||
void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb,
|
||||
struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
int intel_psr_min_vblank_delay(const struct intel_crtc_state *crtc_state);
|
||||
void intel_psr_connector_debugfs_add(struct intel_connector *connector);
|
||||
void intel_psr_debugfs_register(struct intel_display *display);
|
||||
bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state);
|
||||
|
||||
#endif /* __INTEL_PSR_H__ */
|
||||
|
||||
@@ -36,9 +36,9 @@
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_eld.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
@@ -214,18 +214,17 @@ intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo,
|
||||
static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(&intel_sdvo->base);
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 bval = val, cval = val;
|
||||
int i;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
intel_de_write(display, intel_sdvo->sdvo_reg, val);
|
||||
intel_de_posting_read(display, intel_sdvo->sdvo_reg);
|
||||
/*
|
||||
* HW workaround, need to write this twice for issue
|
||||
* that may result in first write getting masked.
|
||||
*/
|
||||
if (HAS_PCH_IBX(dev_priv)) {
|
||||
if (HAS_PCH_IBX(display)) {
|
||||
intel_de_write(display, intel_sdvo->sdvo_reg, val);
|
||||
intel_de_posting_read(display, intel_sdvo->sdvo_reg);
|
||||
}
|
||||
@@ -1360,14 +1359,13 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
|
||||
struct intel_sdvo_connector *intel_sdvo_connector =
|
||||
to_intel_sdvo_connector(conn_state->connector);
|
||||
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
|
||||
struct drm_display_mode *mode = &pipe_config->hw.mode;
|
||||
|
||||
if (HAS_PCH_SPLIT(i915)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
pipe_config->has_pch_encoder = true;
|
||||
if (!intel_fdi_compute_pipe_bpp(pipe_config))
|
||||
return -EINVAL;
|
||||
@@ -1527,7 +1525,6 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
|
||||
const struct intel_sdvo_connector_state *sdvo_state =
|
||||
@@ -1634,7 +1631,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
|
||||
sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
|
||||
}
|
||||
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_CPT(display))
|
||||
sdvox |= SDVO_PIPE_SEL_CPT(crtc->pipe);
|
||||
else
|
||||
sdvox |= SDVO_PIPE_SEL(crtc->pipe);
|
||||
@@ -1670,13 +1667,12 @@ static bool intel_sdvo_connector_get_hw_state(struct intel_connector *connector)
|
||||
bool intel_sdvo_port_enabled(struct intel_display *display,
|
||||
i915_reg_t sdvo_reg, enum pipe *pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
u32 val;
|
||||
|
||||
val = intel_de_read(display, sdvo_reg);
|
||||
|
||||
/* asserts want to know the pipe even if the port is disabled */
|
||||
if (HAS_PCH_CPT(dev_priv))
|
||||
if (HAS_PCH_CPT(display))
|
||||
*pipe = (val & SDVO_PIPE_SEL_MASK_CPT) >> SDVO_PIPE_SEL_SHIFT_CPT;
|
||||
else if (display->platform.cherryview)
|
||||
*pipe = (val & SDVO_PIPE_SEL_MASK_CHV) >> SDVO_PIPE_SEL_SHIFT_CHV;
|
||||
@@ -1841,7 +1837,6 @@ static void intel_disable_sdvo(struct intel_atomic_state *state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
|
||||
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
|
||||
u32 temp;
|
||||
@@ -1861,7 +1856,7 @@ static void intel_disable_sdvo(struct intel_atomic_state *state,
|
||||
* to transcoder A after disabling it to allow the
|
||||
* matching DP port to be enabled on transcoder A.
|
||||
*/
|
||||
if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) {
|
||||
if (HAS_PCH_IBX(display) && crtc->pipe == PIPE_B) {
|
||||
/*
|
||||
* We get CPU/PCH FIFO underruns on the other pipe when
|
||||
* doing the workaround. Sweep them under the rug.
|
||||
@@ -3367,9 +3362,7 @@ intel_sdvo_init_ddc_proxy(struct intel_sdvo_ddc *ddc,
|
||||
|
||||
static bool is_sdvo_port_valid(struct intel_display *display, enum port port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv))
|
||||
if (HAS_PCH_SPLIT(display))
|
||||
return port == PORT_B;
|
||||
else
|
||||
return port == PORT_B || port == PORT_C;
|
||||
@@ -3384,7 +3377,6 @@ static bool assert_sdvo_port_valid(struct intel_display *display, enum port port
|
||||
bool intel_sdvo_init(struct intel_display *display,
|
||||
i915_reg_t sdvo_reg, enum port port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(display->drm);
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_sdvo *intel_sdvo;
|
||||
int i;
|
||||
@@ -3427,7 +3419,7 @@ bool intel_sdvo_init(struct intel_display *display,
|
||||
}
|
||||
|
||||
intel_encoder->compute_config = intel_sdvo_compute_config;
|
||||
if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
if (HAS_PCH_SPLIT(display)) {
|
||||
intel_encoder->disable = pch_disable_sdvo;
|
||||
intel_encoder->post_disable = pch_post_disable_sdvo;
|
||||
} else {
|
||||
|
||||
@@ -36,9 +36,10 @@
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_rect.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_utils.h"
|
||||
#include "i9xx_plane.h"
|
||||
#include "intel_atomic_plane.h"
|
||||
#include "intel_de.h"
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_display_core.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_sprite_uapi.h"
|
||||
|
||||
static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
|
||||
static bool has_dst_key_in_primary_plane(struct intel_display *display)
|
||||
{
|
||||
return DISPLAY_VER(dev_priv) >= 9;
|
||||
return DISPLAY_VER(display) >= 9;
|
||||
}
|
||||
|
||||
static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
|
||||
const struct drm_intel_sprite_colorkey *set)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane_state);
|
||||
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
|
||||
|
||||
*key = *set;
|
||||
@@ -34,7 +34,7 @@ static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
|
||||
* On SKL+ we want dst key enabled on
|
||||
* the primary and not on the sprite.
|
||||
*/
|
||||
if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
|
||||
if (DISPLAY_VER(display) >= 9 && plane->id != PLANE_PRIMARY &&
|
||||
set->flags & I915_SET_COLORKEY_DESTINATION)
|
||||
key->flags = 0;
|
||||
}
|
||||
@@ -43,7 +43,6 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_intel_sprite_colorkey *set = data;
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_state *plane_state;
|
||||
@@ -61,7 +60,7 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
|
||||
if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
|
||||
return -EINVAL;
|
||||
|
||||
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
|
||||
if ((display->platform.valleyview || display->platform.cherryview) &&
|
||||
set->flags & I915_SET_COLORKEY_DESTINATION)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -74,7 +73,7 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
|
||||
* Also multiple planes can't do destination keying on the same
|
||||
* pipe simultaneously.
|
||||
*/
|
||||
if (DISPLAY_VER(dev_priv) >= 9 &&
|
||||
if (DISPLAY_VER(display) >= 9 &&
|
||||
to_intel_plane(plane)->id >= PLANE_3 &&
|
||||
set->flags & I915_SET_COLORKEY_DESTINATION)
|
||||
return -EINVAL;
|
||||
@@ -99,7 +98,7 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
|
||||
* On some platforms we have to configure
|
||||
* the dst colorkey on the primary plane.
|
||||
*/
|
||||
if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
|
||||
if (!ret && has_dst_key_in_primary_plane(display)) {
|
||||
struct intel_crtc *crtc =
|
||||
intel_crtc_for_pipe(display,
|
||||
to_intel_plane(plane)->pipe);
|
||||
|
||||
@@ -33,15 +33,15 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_crtc.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_irq.h"
|
||||
#include "intel_display_driver.h"
|
||||
#include "intel_display_irq.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dpll.h"
|
||||
#include "intel_hotplug.h"
|
||||
@@ -1585,19 +1585,17 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
|
||||
{
|
||||
struct intel_display *display = to_intel_display(connector->dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(connector->state->crtc);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
u32 tv_ctl, save_tv_ctl;
|
||||
u32 tv_dac, save_tv_dac;
|
||||
int type;
|
||||
|
||||
/* Disable TV interrupts around load detect or we'll recurse */
|
||||
if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
i915_disable_pipestat(display, 0,
|
||||
PIPE_HOTPLUG_INTERRUPT_STATUS |
|
||||
PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
save_tv_dac = tv_dac = intel_de_read(display, TV_DAC);
|
||||
@@ -1668,11 +1666,11 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
|
||||
|
||||
/* Restore interrupt config */
|
||||
if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
i915_enable_pipestat(display, 0,
|
||||
PIPE_HOTPLUG_INTERRUPT_STATUS |
|
||||
PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
return type;
|
||||
|
||||
@@ -4,15 +4,20 @@
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/vgaarb.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <video/vga.h>
|
||||
|
||||
#include "soc/intel_gmch.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display.h"
|
||||
#include "intel_vga.h"
|
||||
#include "intel_vga_regs.h"
|
||||
|
||||
static i915_reg_t intel_vga_cntrl_reg(struct intel_display *display)
|
||||
{
|
||||
@@ -24,16 +29,42 @@ static i915_reg_t intel_vga_cntrl_reg(struct intel_display *display)
|
||||
return VGACNTRL;
|
||||
}
|
||||
|
||||
static bool has_vga_pipe_sel(struct intel_display *display)
|
||||
{
|
||||
if (display->platform.i845g ||
|
||||
display->platform.i865g)
|
||||
return false;
|
||||
|
||||
if (display->platform.valleyview ||
|
||||
display->platform.cherryview)
|
||||
return true;
|
||||
|
||||
return DISPLAY_VER(display) < 7;
|
||||
}
|
||||
|
||||
/* Disable the VGA plane that we never use */
|
||||
void intel_vga_disable(struct intel_display *display)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
|
||||
i915_reg_t vga_reg = intel_vga_cntrl_reg(display);
|
||||
enum pipe pipe;
|
||||
u32 tmp;
|
||||
u8 sr1;
|
||||
|
||||
if (intel_de_read(display, vga_reg) & VGA_DISP_DISABLE)
|
||||
tmp = intel_de_read(display, vga_reg);
|
||||
if (tmp & VGA_DISP_DISABLE)
|
||||
return;
|
||||
|
||||
if (display->platform.cherryview)
|
||||
pipe = REG_FIELD_GET(VGA_PIPE_SEL_MASK_CHV, tmp);
|
||||
else if (has_vga_pipe_sel(display))
|
||||
pipe = REG_FIELD_GET(VGA_PIPE_SEL_MASK, tmp);
|
||||
else
|
||||
pipe = PIPE_A;
|
||||
|
||||
drm_dbg_kms(display->drm, "Disabling VGA plane on pipe %c\n",
|
||||
pipe_name(pipe));
|
||||
|
||||
/* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
|
||||
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
|
||||
outb(0x01, VGA_SEQ_I);
|
||||
@@ -46,39 +77,6 @@ void intel_vga_disable(struct intel_display *display)
|
||||
intel_de_posting_read(display, vga_reg);
|
||||
}
|
||||
|
||||
void intel_vga_redisable_power_on(struct intel_display *display)
|
||||
{
|
||||
i915_reg_t vga_reg = intel_vga_cntrl_reg(display);
|
||||
|
||||
if (!(intel_de_read(display, vga_reg) & VGA_DISP_DISABLE)) {
|
||||
drm_dbg_kms(display->drm,
|
||||
"Something enabled VGA plane, disabling it\n");
|
||||
intel_vga_disable(display);
|
||||
}
|
||||
}
|
||||
|
||||
void intel_vga_redisable(struct intel_display *display)
|
||||
{
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
/*
|
||||
* This function can be called both from intel_modeset_setup_hw_state or
|
||||
* at a very early point in our resume sequence, where the power well
|
||||
* structures are not yet restored. Since this function is at a very
|
||||
* paranoid "someone might have enabled VGA while we were not looking"
|
||||
* level, just check if the power well is enabled instead of trying to
|
||||
* follow the "don't touch the power well if we don't need it" policy
|
||||
* the rest of the driver uses.
|
||||
*/
|
||||
wakeref = intel_display_power_get_if_enabled(display, POWER_DOMAIN_VGA);
|
||||
if (!wakeref)
|
||||
return;
|
||||
|
||||
intel_vga_redisable_power_on(display);
|
||||
|
||||
intel_display_power_put(display, POWER_DOMAIN_VGA, wakeref);
|
||||
}
|
||||
|
||||
void intel_vga_reset_io_mem(struct intel_display *display)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
|
||||
|
||||
@@ -10,8 +10,6 @@ struct intel_display;
|
||||
|
||||
void intel_vga_reset_io_mem(struct intel_display *display);
|
||||
void intel_vga_disable(struct intel_display *display);
|
||||
void intel_vga_redisable(struct intel_display *display);
|
||||
void intel_vga_redisable_power_on(struct intel_display *display);
|
||||
int intel_vga_register(struct intel_display *display);
|
||||
void intel_vga_unregister(struct intel_display *display);
|
||||
|
||||
|
||||
36
drivers/gpu/drm/i915/display/intel_vga_regs.h
Normal file
36
drivers/gpu/drm/i915/display/intel_vga_regs.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_VGA_REGS_H__
|
||||
#define __INTEL_VGA_REGS_H__
|
||||
|
||||
#include "intel_display_reg_defs.h"
|
||||
|
||||
#define VGACNTRL _MMIO(0x71400)
|
||||
#define VLV_VGACNTRL _MMIO(VLV_DISPLAY_BASE + 0x71400)
|
||||
#define CPU_VGACNTRL _MMIO(0x41000)
|
||||
#define VGA_DISP_DISABLE REG_BIT(31)
|
||||
#define VGA_2X_MODE REG_BIT(30) /* pre-ilk */
|
||||
#define VGA_PIPE_SEL_MASK REG_BIT(29) /* pre-ivb */
|
||||
#define VGA_PIPE_SEL(pipe) REG_FIELD_PREP(VGA_PIPE_SEL_MASK, (pipe))
|
||||
#define VGA_PIPE_SEL_MASK_CHV REG_GENMASK(29, 28) /* chv */
|
||||
#define VGA_PIPE_SEL_CHV(pipe) REG_FIELD_PREP(VGA_PIPE_SEL_MASK_CHV, (pipe))
|
||||
#define VGA_BORDER_ENABLE REG_BIT(26)
|
||||
#define VGA_PIPE_CSC_ENABLE REG_BIT(24) /* ilk+ */
|
||||
#define VGA_CENTERING_ENABLE_MASK REG_GENMASK(25, 24) /* pre-ilk */
|
||||
#define VGA_PALETTE_READ_SEL REG_BIT(23) /* pre-ivb */
|
||||
#define VGA_PALETTE_A_WRITE_DISABLE REG_BIT(22) /* pre-ivb */
|
||||
#define VGA_PALETTE_B_WRITE_DISABLE REG_BIT(21) /* pre-ivb */
|
||||
#define VGA_LEGACY_8BIT_PALETTE_ENABLE REG_BIT(20)
|
||||
#define VGA_PALETTE_BYPASS REG_BIT(19)
|
||||
#define VGA_NINE_DOT_DISABLE REG_BIT(18)
|
||||
#define VGA_PALETTE_READ_SEL_HI_CHV REG_BIT(15) /* chv */
|
||||
#define VGA_PALETTE_C_WRITE_DISABLE_CHV REG_BIT(14) /* chv */
|
||||
#define VGA_ACTIVE_THROTTLING_MASK REG_GENMASK(15, 12) /* ilk+ */
|
||||
#define VGA_BLANK_THROTTLING_MASK REG_GENMASK(11, 8) /* ilk+ */
|
||||
#define VGA_BLINK_DUTY_CYCLE_MASK REG_GENMASK(7, 6)
|
||||
#define VGA_VSYNC_BLINK_RATE_MASK REG_GENMASK(5, 0)
|
||||
|
||||
#endif /* __INTEL_VGA_REGS_H__ */
|
||||
@@ -444,7 +444,10 @@ static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(crtc_state);
|
||||
|
||||
if (DISPLAY_VER(display) >= 13)
|
||||
if (DISPLAY_VER(display) >= 14)
|
||||
return VRR_CTL_FLIP_LINE_EN |
|
||||
XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband);
|
||||
else if (DISPLAY_VER(display) >= 13)
|
||||
return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
|
||||
XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband);
|
||||
else
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
* Copyright © 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_trace.h"
|
||||
#include "intel_display_types.h"
|
||||
|
||||
@@ -2690,24 +2690,22 @@ static void
|
||||
skl_plane_enable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
bdw_enable_pipe_irq(display, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
skl_plane_disable_flip_done(struct intel_plane *plane)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(plane);
|
||||
struct drm_i915_private *i915 = to_i915(plane->base.dev);
|
||||
enum pipe pipe = plane->pipe;
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
spin_lock_irq(&display->irq.lock);
|
||||
bdw_disable_pipe_irq(display, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
spin_unlock_irq(&display->irq.lock);
|
||||
}
|
||||
|
||||
static bool skl_plane_has_rc_ccs(struct intel_display *display,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <drm/intel/i915_drm.h>
|
||||
|
||||
#include "display/intel_display.h"
|
||||
#include "display/intel_display_irq.h"
|
||||
#include "display/intel_display_rps.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_irq.h"
|
||||
#include "i915_reg.h"
|
||||
@@ -608,9 +608,7 @@ static bool gen5_rps_enable(struct intel_rps *rps)
|
||||
rps->ips.last_count2 = intel_uncore_read(uncore, GFXEC);
|
||||
rps->ips.last_time2 = ktime_get_raw_ns();
|
||||
|
||||
spin_lock(&i915->irq_lock);
|
||||
ilk_enable_display_irq(display, DE_PCU_EVENT);
|
||||
spin_unlock(&i915->irq_lock);
|
||||
ilk_display_rps_enable(display);
|
||||
|
||||
spin_unlock_irq(&mchdev_lock);
|
||||
|
||||
@@ -628,9 +626,7 @@ static void gen5_rps_disable(struct intel_rps *rps)
|
||||
|
||||
spin_lock_irq(&mchdev_lock);
|
||||
|
||||
spin_lock(&i915->irq_lock);
|
||||
ilk_disable_display_irq(display, DE_PCU_EVENT);
|
||||
spin_unlock(&i915->irq_lock);
|
||||
ilk_display_rps_disable(display);
|
||||
|
||||
rgvswctl = intel_uncore_read16(uncore, MEMSWCTL);
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ struct intel_rps {
|
||||
|
||||
/*
|
||||
* work, interrupts_enabled and pm_iir are protected by
|
||||
* i915->irq_lock
|
||||
* gt->irq_lock
|
||||
*/
|
||||
struct timer_list timer;
|
||||
struct work_struct work;
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "display/intel_pps_regs.h"
|
||||
#include "display/intel_psr_regs.h"
|
||||
#include "display/intel_sprite_regs.h"
|
||||
#include "display/intel_vga_regs.h"
|
||||
#include "display/skl_universal_plane_regs.h"
|
||||
#include "display/skl_watermark_regs.h"
|
||||
#include "display/vlv_dsi_pll_regs.h"
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
#include "display/intel_pch_refclk.h"
|
||||
#include "display/intel_pps.h"
|
||||
#include "display/intel_sprite_uapi.h"
|
||||
#include "display/intel_vga.h"
|
||||
#include "display/skl_watermark.h"
|
||||
|
||||
#include "gem/i915_gem_context.h"
|
||||
@@ -235,7 +234,6 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
|
||||
|
||||
intel_uncore_mmio_debug_init_early(dev_priv);
|
||||
|
||||
spin_lock_init(&dev_priv->irq_lock);
|
||||
spin_lock_init(&dev_priv->gpu_error.lock);
|
||||
|
||||
intel_sbi_init(dev_priv);
|
||||
@@ -263,9 +261,6 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
|
||||
|
||||
i915_gem_init_early(dev_priv);
|
||||
|
||||
/* This must be called before any calls to HAS_PCH_* */
|
||||
intel_detect_pch(dev_priv);
|
||||
|
||||
intel_irq_init(dev_priv);
|
||||
intel_display_driver_early_probe(display);
|
||||
intel_clock_gating_hooks_init(dev_priv);
|
||||
@@ -1205,8 +1200,6 @@ static int i915_drm_resume(struct drm_device *dev)
|
||||
|
||||
i9xx_display_sr_restore(display);
|
||||
|
||||
intel_vga_redisable(display);
|
||||
|
||||
intel_gmbus_reset(display);
|
||||
|
||||
intel_pps_unlock_regs_wa(display);
|
||||
|
||||
@@ -15,7 +15,6 @@ struct drm_printer;
|
||||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_TIMESTAMP 1695980603
|
||||
|
||||
extern const struct dev_pm_ops i915_pm_ops;
|
||||
|
||||
|
||||
@@ -49,8 +49,6 @@
|
||||
#include "gt/intel_workarounds.h"
|
||||
#include "gt/uc/intel_uc.h"
|
||||
|
||||
#include "soc/intel_pch.h"
|
||||
|
||||
#include "i915_drm_client.h"
|
||||
#include "i915_gem.h"
|
||||
#include "i915_gpu_error.h"
|
||||
@@ -224,8 +222,6 @@ struct drm_i915_private {
|
||||
};
|
||||
unsigned int engine_uabi_class_count[I915_LAST_UABI_ENGINE_CLASS + 1];
|
||||
|
||||
/* protects the irq masks */
|
||||
spinlock_t irq_lock;
|
||||
bool irqs_enabled;
|
||||
|
||||
/* LPT/WPT IOSF sideband protection */
|
||||
@@ -272,9 +268,6 @@ struct drm_i915_private {
|
||||
/* pm private clock gating functions */
|
||||
const struct drm_i915_clock_gating_funcs *clock_gating_funcs;
|
||||
|
||||
/* PCH chipset type */
|
||||
enum intel_pch pch_type;
|
||||
|
||||
unsigned long gem_quirks;
|
||||
|
||||
struct i915_gem_mm mm;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user