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,
int tfw_exit_latency = 20; /* eDP spec */
int phy_wake = 4; /* 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;
io_wake_time = max(precharge, io_buffer_wake_time(crtc_state)) +
......
......@@ -1885,6 +1885,10 @@ struct intel_dp {
} alpm_parameters;
u8 alpm_dpcd;
struct {
unsigned long mask;
} quirks;
};
enum lspcon_vendor {
......
......@@ -82,6 +82,7 @@
#include "intel_pch_display.h"
#include "intel_pps.h"
#include "intel_psr.h"
#include "intel_quirks.h"
#include "intel_tc.h"
#include "intel_vdsc.h"
#include "intel_vrr.h"
......@@ -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_is_branch(intel_dp->dpcd));
intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
/*
* Read the eDP display control registers.
......@@ -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_is_branch(intel_dp->dpcd));
intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
intel_dp_update_sink_caps(intel_dp);
}
......
......@@ -13,6 +13,7 @@
#include "intel_dp_aux.h"
#include "intel_dp_aux_regs.h"
#include "intel_pps.h"
#include "intel_quirks.h"
#include "intel_tc.h"
#define AUX_CH_NAME_BUFSIZE 6
......@@ -142,16 +143,21 @@ static int intel_dp_aux_sync_len(void)
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:
* "Manufacturer: AUO, Model: 63898" when using HW default 18. Using 20
* 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 */
int preamble = 8;
if (intel_has_dpcd_quirk(intel_dp, QUIRK_FW_SYNC_LEN))
precharge += 2;
return precharge + preamble;
}
......@@ -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_RECEIVE_ERROR |
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());
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);
void intel_dp_aux_irq_handler(struct drm_i915_private *i915);
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__ */
......@@ -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)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
if (intel_crtc_is_joiner_secondary(crtc_state))
return;
......@@ -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.scaling_filter = crtc_state->hw.scaling_filter;
if (DISPLAY_INFO(i915)->color.degamma_lut_size) {
/* assume 1:1 mapping */
drm_property_replace_blob(&crtc_state->hw.degamma_lut,
crtc_state->pre_csc_lut);
drm_property_replace_blob(&crtc_state->hw.gamma_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,
crtc_state->hw.degamma_lut);
......
......@@ -14,6 +14,11 @@ static void intel_set_quirk(struct intel_display *display, enum intel_quirk_id q
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
*/
......@@ -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");
}
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 {
int device;
int subsystem_vendor;
......@@ -72,6 +85,21 @@ struct intel_quirk {
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 */
struct intel_dmi_quirk {
void (*hook)(struct intel_display *display);
......@@ -203,6 +231,18 @@ static struct intel_quirk intel_quirks[] = {
{ 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)
{
struct pci_dev *d = to_pci_dev(display->drm->dev);
......@@ -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)
{
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 @@
#include <linux/types.h>
struct intel_display;
struct intel_dp;
struct drm_dp_dpcd_ident;
enum intel_quirk_id {
QUIRK_BACKLIGHT_PRESENT,
......@@ -17,9 +19,13 @@ enum intel_quirk_id {
QUIRK_INVERT_BRIGHTNESS,
QUIRK_LVDS_SSC_DISABLE,
QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK,
QUIRK_FW_SYNC_LEN,
};
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_dpcd_quirk(struct intel_dp *intel_dp, enum intel_quirk_id quirk);
#endif /* __INTEL_QUIRKS_H__ */
......@@ -302,7 +302,7 @@ void intel_gsc_uc_load_start(struct intel_gsc_uc *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;
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)
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)
{
return uc_fw->user_overridden;
......
......@@ -51,7 +51,7 @@ static inline void debug_fence_init(struct i915_sw_fence *fence)
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);
}
......@@ -77,7 +77,7 @@ static inline void debug_fence_destroy(struct i915_sw_fence *fence)
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);
smp_wmb(); /* flush the change in state before reallocation */
......@@ -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)
{
}
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