Commit f2064ae3 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2024-09-05' of...

Merge tag 'drm-intel-fixes-2024-09-05' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-fixes

- drm/i915: Do not attempt to load the GSC multiple times (Daniele Ceraolo Spurio)
- drm/i915: Fix readout degamma_lut mismatch on ilk/snb (Ville Syrjälä)
- drm/i915/fence: Mark debug_fence_init_onstack() with __maybe_unused (Andy Shevchenko)
- drm/i915/fence: Mark debug_fence_free() with __maybe_unused (Andy Shevchenko)
- drm/i915/display: Add mechanism to use sink model when applying quirk [display] (Jouni Högander)
- drm/i915/display: Increase Fast Wake Sync length as a quirk [display] (Jouni Högander)
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Tvrtko Ursulin <tursulin@igalia.com>
Link: https://patchwork.freedesktop.org/patch/msgid/Ztlo2hVO4SBvfAnq@linux
parents 431c1646 a13494de
...@@ -228,7 +228,7 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp, ...@@ -228,7 +228,7 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
int tfw_exit_latency = 20; /* eDP spec */ int tfw_exit_latency = 20; /* eDP spec */
int phy_wake = 4; /* eDP spec */ int phy_wake = 4; /* eDP spec */
int preamble = 8; /* eDP spec */ int preamble = 8; /* eDP spec */
int precharge = intel_dp_aux_fw_sync_len() - preamble; int precharge = intel_dp_aux_fw_sync_len(intel_dp) - preamble;
u8 max_wake_lines; u8 max_wake_lines;
io_wake_time = max(precharge, io_buffer_wake_time(crtc_state)) + io_wake_time = max(precharge, io_buffer_wake_time(crtc_state)) +
......
...@@ -1885,6 +1885,10 @@ struct intel_dp { ...@@ -1885,6 +1885,10 @@ struct intel_dp {
} alpm_parameters; } alpm_parameters;
u8 alpm_dpcd; u8 alpm_dpcd;
struct {
unsigned long mask;
} quirks;
}; };
enum lspcon_vendor { enum lspcon_vendor {
......
...@@ -82,6 +82,7 @@ ...@@ -82,6 +82,7 @@
#include "intel_pch_display.h" #include "intel_pch_display.h"
#include "intel_pps.h" #include "intel_pps.h"
#include "intel_psr.h" #include "intel_psr.h"
#include "intel_quirks.h"
#include "intel_tc.h" #include "intel_tc.h"
#include "intel_vdsc.h" #include "intel_vdsc.h"
#include "intel_vrr.h" #include "intel_vrr.h"
...@@ -3952,6 +3953,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector ...@@ -3952,6 +3953,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector
drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc,
drm_dp_is_branch(intel_dp->dpcd)); drm_dp_is_branch(intel_dp->dpcd));
intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
/* /*
* Read the eDP display control registers. * Read the eDP display control registers.
...@@ -4064,6 +4066,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) ...@@ -4064,6 +4066,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc,
drm_dp_is_branch(intel_dp->dpcd)); drm_dp_is_branch(intel_dp->dpcd));
intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
intel_dp_update_sink_caps(intel_dp); intel_dp_update_sink_caps(intel_dp);
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "intel_dp_aux.h" #include "intel_dp_aux.h"
#include "intel_dp_aux_regs.h" #include "intel_dp_aux_regs.h"
#include "intel_pps.h" #include "intel_pps.h"
#include "intel_quirks.h"
#include "intel_tc.h" #include "intel_tc.h"
#define AUX_CH_NAME_BUFSIZE 6 #define AUX_CH_NAME_BUFSIZE 6
...@@ -142,16 +143,21 @@ static int intel_dp_aux_sync_len(void) ...@@ -142,16 +143,21 @@ static int intel_dp_aux_sync_len(void)
return precharge + preamble; return precharge + preamble;
} }
int intel_dp_aux_fw_sync_len(void) int intel_dp_aux_fw_sync_len(struct intel_dp *intel_dp)
{ {
int precharge = 10; /* 10-16 */
int preamble = 8;
/* /*
* We faced some glitches on Dell Precision 5490 MTL laptop with panel: * We faced some glitches on Dell Precision 5490 MTL laptop with panel:
* "Manufacturer: AUO, Model: 63898" when using HW default 18. Using 20 * "Manufacturer: AUO, Model: 63898" when using HW default 18. Using 20
* is fixing these problems with the panel. It is still within range * is fixing these problems with the panel. It is still within range
* mentioned in eDP specification. * mentioned in eDP specification. Increasing Fast Wake sync length is
* causing problems with other panels: increase length as a quirk for
* this specific laptop.
*/ */
int precharge = 12; /* 10-16 */ if (intel_has_dpcd_quirk(intel_dp, QUIRK_FW_SYNC_LEN))
int preamble = 8; precharge += 2;
return precharge + preamble; return precharge + preamble;
} }
...@@ -211,7 +217,7 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp, ...@@ -211,7 +217,7 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
DP_AUX_CH_CTL_TIME_OUT_MAX | DP_AUX_CH_CTL_TIME_OUT_MAX |
DP_AUX_CH_CTL_RECEIVE_ERROR | DP_AUX_CH_CTL_RECEIVE_ERROR |
DP_AUX_CH_CTL_MESSAGE_SIZE(send_bytes) | DP_AUX_CH_CTL_MESSAGE_SIZE(send_bytes) |
DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(intel_dp_aux_fw_sync_len()) | DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(intel_dp_aux_fw_sync_len(intel_dp)) |
DP_AUX_CH_CTL_SYNC_PULSE_SKL(intel_dp_aux_sync_len()); DP_AUX_CH_CTL_SYNC_PULSE_SKL(intel_dp_aux_sync_len());
if (intel_tc_port_in_tbt_alt_mode(dig_port)) if (intel_tc_port_in_tbt_alt_mode(dig_port))
......
...@@ -20,6 +20,6 @@ enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder); ...@@ -20,6 +20,6 @@ enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder);
void intel_dp_aux_irq_handler(struct drm_i915_private *i915); void intel_dp_aux_irq_handler(struct drm_i915_private *i915);
u32 intel_dp_aux_pack(const u8 *src, int src_bytes); u32 intel_dp_aux_pack(const u8 *src, int src_bytes);
int intel_dp_aux_fw_sync_len(void); int intel_dp_aux_fw_sync_len(struct intel_dp *intel_dp);
#endif /* __INTEL_DP_AUX_H__ */ #endif /* __INTEL_DP_AUX_H__ */
...@@ -326,6 +326,8 @@ static void intel_modeset_update_connector_atomic_state(struct drm_i915_private ...@@ -326,6 +326,8 @@ 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) 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);
if (intel_crtc_is_joiner_secondary(crtc_state)) if (intel_crtc_is_joiner_secondary(crtc_state))
return; return;
...@@ -337,11 +339,30 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state ...@@ -337,11 +339,30 @@ 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.adjusted_mode = crtc_state->hw.adjusted_mode;
crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter; crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter;
if (DISPLAY_INFO(i915)->color.degamma_lut_size) {
/* assume 1:1 mapping */ /* assume 1:1 mapping */
drm_property_replace_blob(&crtc_state->hw.degamma_lut, drm_property_replace_blob(&crtc_state->hw.degamma_lut,
crtc_state->pre_csc_lut); crtc_state->pre_csc_lut);
drm_property_replace_blob(&crtc_state->hw.gamma_lut, drm_property_replace_blob(&crtc_state->hw.gamma_lut,
crtc_state->post_csc_lut); crtc_state->post_csc_lut);
} else {
/*
* ilk/snb hw may be configured for either pre_csc_lut
* or post_csc_lut, but we don't advertise degamma_lut as
* being available in the uapi since there is only one
* hardware LUT. Always assign the result of the readout
* 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 &&
crtc_state->pre_csc_lut);
drm_property_replace_blob(&crtc_state->hw.degamma_lut,
NULL);
drm_property_replace_blob(&crtc_state->hw.gamma_lut,
crtc_state->post_csc_lut ?:
crtc_state->pre_csc_lut);
}
drm_property_replace_blob(&crtc_state->uapi.degamma_lut, drm_property_replace_blob(&crtc_state->uapi.degamma_lut,
crtc_state->hw.degamma_lut); crtc_state->hw.degamma_lut);
......
...@@ -14,6 +14,11 @@ static void intel_set_quirk(struct intel_display *display, enum intel_quirk_id q ...@@ -14,6 +14,11 @@ static void intel_set_quirk(struct intel_display *display, enum intel_quirk_id q
display->quirks.mask |= BIT(quirk); display->quirks.mask |= BIT(quirk);
} }
static void intel_set_dpcd_quirk(struct intel_dp *intel_dp, enum intel_quirk_id quirk)
{
intel_dp->quirks.mask |= BIT(quirk);
}
/* /*
* Some machines (Lenovo U160) do not work with SSC on LVDS for some reason * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason
*/ */
...@@ -65,6 +70,14 @@ static void quirk_no_pps_backlight_power_hook(struct intel_display *display) ...@@ -65,6 +70,14 @@ static void quirk_no_pps_backlight_power_hook(struct intel_display *display)
drm_info(display->drm, "Applying no pps backlight power quirk\n"); drm_info(display->drm, "Applying no pps backlight power quirk\n");
} }
static void quirk_fw_sync_len(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
intel_set_dpcd_quirk(intel_dp, QUIRK_FW_SYNC_LEN);
drm_info(display->drm, "Applying Fast Wake sync pulse count quirk\n");
}
struct intel_quirk { struct intel_quirk {
int device; int device;
int subsystem_vendor; int subsystem_vendor;
...@@ -72,6 +85,21 @@ struct intel_quirk { ...@@ -72,6 +85,21 @@ struct intel_quirk {
void (*hook)(struct intel_display *display); void (*hook)(struct intel_display *display);
}; };
struct intel_dpcd_quirk {
int device;
int subsystem_vendor;
int subsystem_device;
u8 sink_oui[3];
u8 sink_device_id[6];
void (*hook)(struct intel_dp *intel_dp);
};
#define SINK_OUI(first, second, third) { (first), (second), (third) }
#define SINK_DEVICE_ID(first, second, third, fourth, fifth, sixth) \
{ (first), (second), (third), (fourth), (fifth), (sixth) }
#define SINK_DEVICE_ID_ANY SINK_DEVICE_ID(0, 0, 0, 0, 0, 0)
/* For systems that don't have a meaningful PCI subdevice/subvendor ID */ /* For systems that don't have a meaningful PCI subdevice/subvendor ID */
struct intel_dmi_quirk { struct intel_dmi_quirk {
void (*hook)(struct intel_display *display); void (*hook)(struct intel_display *display);
...@@ -203,6 +231,18 @@ static struct intel_quirk intel_quirks[] = { ...@@ -203,6 +231,18 @@ static struct intel_quirk intel_quirks[] = {
{ 0x0f31, 0x103c, 0x220f, quirk_invert_brightness }, { 0x0f31, 0x103c, 0x220f, quirk_invert_brightness },
}; };
static struct intel_dpcd_quirk intel_dpcd_quirks[] = {
/* Dell Precision 5490 */
{
.device = 0x7d55,
.subsystem_vendor = 0x1028,
.subsystem_device = 0x0cc7,
.sink_oui = SINK_OUI(0x38, 0xec, 0x11),
.hook = quirk_fw_sync_len,
},
};
void intel_init_quirks(struct intel_display *display) void intel_init_quirks(struct intel_display *display)
{ {
struct pci_dev *d = to_pci_dev(display->drm->dev); struct pci_dev *d = to_pci_dev(display->drm->dev);
...@@ -224,7 +264,35 @@ void intel_init_quirks(struct intel_display *display) ...@@ -224,7 +264,35 @@ void intel_init_quirks(struct intel_display *display)
} }
} }
void intel_init_dpcd_quirks(struct intel_dp *intel_dp,
const struct drm_dp_dpcd_ident *ident)
{
struct intel_display *display = to_intel_display(intel_dp);
struct pci_dev *d = to_pci_dev(display->drm->dev);
int i;
for (i = 0; i < ARRAY_SIZE(intel_dpcd_quirks); i++) {
struct intel_dpcd_quirk *q = &intel_dpcd_quirks[i];
if (d->device == q->device &&
(d->subsystem_vendor == q->subsystem_vendor ||
q->subsystem_vendor == PCI_ANY_ID) &&
(d->subsystem_device == q->subsystem_device ||
q->subsystem_device == PCI_ANY_ID) &&
!memcmp(q->sink_oui, ident->oui, sizeof(ident->oui)) &&
(!memcmp(q->sink_device_id, ident->device_id,
sizeof(ident->device_id)) ||
!memchr_inv(q->sink_device_id, 0, sizeof(q->sink_device_id))))
q->hook(intel_dp);
}
}
bool intel_has_quirk(struct intel_display *display, enum intel_quirk_id quirk) bool intel_has_quirk(struct intel_display *display, enum intel_quirk_id quirk)
{ {
return display->quirks.mask & BIT(quirk); return display->quirks.mask & BIT(quirk);
} }
bool intel_has_dpcd_quirk(struct intel_dp *intel_dp, enum intel_quirk_id quirk)
{
return intel_dp->quirks.mask & BIT(quirk);
}
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <linux/types.h> #include <linux/types.h>
struct intel_display; struct intel_display;
struct intel_dp;
struct drm_dp_dpcd_ident;
enum intel_quirk_id { enum intel_quirk_id {
QUIRK_BACKLIGHT_PRESENT, QUIRK_BACKLIGHT_PRESENT,
...@@ -17,9 +19,13 @@ enum intel_quirk_id { ...@@ -17,9 +19,13 @@ enum intel_quirk_id {
QUIRK_INVERT_BRIGHTNESS, QUIRK_INVERT_BRIGHTNESS,
QUIRK_LVDS_SSC_DISABLE, QUIRK_LVDS_SSC_DISABLE,
QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK,
QUIRK_FW_SYNC_LEN,
}; };
void intel_init_quirks(struct intel_display *display); void intel_init_quirks(struct intel_display *display);
void intel_init_dpcd_quirks(struct intel_dp *intel_dp,
const struct drm_dp_dpcd_ident *ident);
bool intel_has_quirk(struct intel_display *display, enum intel_quirk_id quirk); bool intel_has_quirk(struct intel_display *display, enum intel_quirk_id quirk);
bool intel_has_dpcd_quirk(struct intel_dp *intel_dp, enum intel_quirk_id quirk);
#endif /* __INTEL_QUIRKS_H__ */ #endif /* __INTEL_QUIRKS_H__ */
...@@ -302,7 +302,7 @@ void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc) ...@@ -302,7 +302,7 @@ void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc)
{ {
struct intel_gt *gt = gsc_uc_to_gt(gsc); struct intel_gt *gt = gsc_uc_to_gt(gsc);
if (!intel_uc_fw_is_loadable(&gsc->fw)) if (!intel_uc_fw_is_loadable(&gsc->fw) || intel_uc_fw_is_in_error(&gsc->fw))
return; return;
if (intel_gsc_uc_fw_init_done(gsc)) if (intel_gsc_uc_fw_init_done(gsc))
......
...@@ -258,6 +258,11 @@ static inline bool intel_uc_fw_is_running(struct intel_uc_fw *uc_fw) ...@@ -258,6 +258,11 @@ static inline bool intel_uc_fw_is_running(struct intel_uc_fw *uc_fw)
return __intel_uc_fw_status(uc_fw) == INTEL_UC_FIRMWARE_RUNNING; return __intel_uc_fw_status(uc_fw) == INTEL_UC_FIRMWARE_RUNNING;
} }
static inline bool intel_uc_fw_is_in_error(struct intel_uc_fw *uc_fw)
{
return intel_uc_fw_status_to_error(__intel_uc_fw_status(uc_fw)) != 0;
}
static inline bool intel_uc_fw_is_overridden(const struct intel_uc_fw *uc_fw) static inline bool intel_uc_fw_is_overridden(const struct intel_uc_fw *uc_fw)
{ {
return uc_fw->user_overridden; return uc_fw->user_overridden;
......
...@@ -51,7 +51,7 @@ static inline void debug_fence_init(struct i915_sw_fence *fence) ...@@ -51,7 +51,7 @@ static inline void debug_fence_init(struct i915_sw_fence *fence)
debug_object_init(fence, &i915_sw_fence_debug_descr); debug_object_init(fence, &i915_sw_fence_debug_descr);
} }
static inline void debug_fence_init_onstack(struct i915_sw_fence *fence) static inline __maybe_unused void debug_fence_init_onstack(struct i915_sw_fence *fence)
{ {
debug_object_init_on_stack(fence, &i915_sw_fence_debug_descr); debug_object_init_on_stack(fence, &i915_sw_fence_debug_descr);
} }
...@@ -77,7 +77,7 @@ static inline void debug_fence_destroy(struct i915_sw_fence *fence) ...@@ -77,7 +77,7 @@ static inline void debug_fence_destroy(struct i915_sw_fence *fence)
debug_object_destroy(fence, &i915_sw_fence_debug_descr); debug_object_destroy(fence, &i915_sw_fence_debug_descr);
} }
static inline void debug_fence_free(struct i915_sw_fence *fence) static inline __maybe_unused void debug_fence_free(struct i915_sw_fence *fence)
{ {
debug_object_free(fence, &i915_sw_fence_debug_descr); debug_object_free(fence, &i915_sw_fence_debug_descr);
smp_wmb(); /* flush the change in state before reallocation */ smp_wmb(); /* flush the change in state before reallocation */
...@@ -94,7 +94,7 @@ static inline void debug_fence_init(struct i915_sw_fence *fence) ...@@ -94,7 +94,7 @@ static inline void debug_fence_init(struct i915_sw_fence *fence)
{ {
} }
static inline void debug_fence_init_onstack(struct i915_sw_fence *fence) static inline __maybe_unused void debug_fence_init_onstack(struct i915_sw_fence *fence)
{ {
} }
...@@ -115,7 +115,7 @@ static inline void debug_fence_destroy(struct i915_sw_fence *fence) ...@@ -115,7 +115,7 @@ static inline void debug_fence_destroy(struct i915_sw_fence *fence)
{ {
} }
static inline void debug_fence_free(struct i915_sw_fence *fence) static inline __maybe_unused void debug_fence_free(struct i915_sw_fence *fence)
{ {
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment