Merge tag 'drm-intel-next-2025-06-18' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next

drm/i915 feature pull for v6.17:

Features and functionality:
- Add support for DSC fractional link bpp on DP MST (Imre)
- Add support for simultaneous Panel Replay and Adaptive Sync (Jouni)
- Add support for PTL+ double buffered LUT registers (Chaitanya, Ville)
- Add PIPEDMC event handling in preparation for flip queue (Ville)

Refactoring and cleanups:
- Rename lots of DPLL interfaces to unify them (Suraj)
- Allocate struct intel_display dynamically (Jani)
- Abstract VLV IOSF sideband better (Jani)
- Use str_true_false() helper (Yumeng Fang)
- Refactor DSB code in preparation for flip queue (Ville)
- Use drm_modeset_lock_assert_held() instead of open coding (Luca)
- Remove unused arg from skl_scaler_get_filter_select() (Luca)
- Split out a separate display register header (Jani)
- Abstract DRAM detection better (Jani)
- Convert LPT/WPT SBI sideband to struct intel_display (Jani)

Fixes:
- Fix DSI HS command dispatch with forced pipeline flush (Gareth Yu)
- Fix BMG and LNL+ DP adaptive sync SDP programming (Ankit)
- Fix error path for xe display workqueue allocation (Haoxiang Li)
- Disable DP AUX access probe where not required (Imre)
- Fix DKL PHY access if the port is invalid (Luca)
- Fix PSR2_SU_STATUS access on ADL+ (Jouni)
- Add sanity checks for porch and sync on BXT/GLK DSI (Ville)

DRM core changes:
- Change AUX DPCD access probe address (Imre)
- Refactor EDID quirks, amd make them available to drivers (Imre)
- Add quirk for DPCD access probe (Imre)
- Add DPCD definitions for Panel Replay capabilities (Jouni)

Merges:
- Backmerges to sync with v6.15-rcs and v6.16-rc1 (Jani)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://lore.kernel.org/r/fff9f231850ed410bd81b53de43eff0b98240d31@intel.com
This commit is contained in:
Dave Airlie 2025-06-23 10:49:25 +10:00
commit 36c52fb703
187 changed files with 6326 additions and 5217 deletions

View File

@ -692,6 +692,34 @@ void drm_dp_dpcd_set_powered(struct drm_dp_aux *aux, bool powered)
}
EXPORT_SYMBOL(drm_dp_dpcd_set_powered);
/**
* drm_dp_dpcd_set_probe() - Set whether a probing before DPCD access is done
* @aux: DisplayPort AUX channel
* @enable: Enable the probing if required
*/
void drm_dp_dpcd_set_probe(struct drm_dp_aux *aux, bool enable)
{
WRITE_ONCE(aux->dpcd_probe_disabled, !enable);
}
EXPORT_SYMBOL(drm_dp_dpcd_set_probe);
static bool dpcd_access_needs_probe(struct drm_dp_aux *aux)
{
/*
* HP ZR24w corrupts the first DPCD access after entering power save
* mode. Eg. on a read, the entire buffer will be filled with the same
* byte. Do a throw away read to avoid corrupting anything we care
* about. Afterwards things will work correctly until the monitor
* gets woken up and subsequently re-enters power save mode.
*
* The user pressing any button on the monitor is enough to wake it
* up, so there is no particularly good place to do the workaround.
* We just have to do it before any DPCD access and hope that the
* monitor doesn't power down exactly after the throw away read.
*/
return !aux->is_remote && !READ_ONCE(aux->dpcd_probe_disabled);
}
/**
* drm_dp_dpcd_read() - read a series of bytes from the DPCD
* @aux: DisplayPort AUX channel (SST or MST)
@ -713,20 +741,8 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
{
int ret;
/*
* HP ZR24w corrupts the first DPCD access after entering power save
* mode. Eg. on a read, the entire buffer will be filled with the same
* byte. Do a throw away read to avoid corrupting anything we care
* about. Afterwards things will work correctly until the monitor
* gets woken up and subsequently re-enters power save mode.
*
* The user pressing any button on the monitor is enough to wake it
* up, so there is no particularly good place to do the workaround.
* We just have to do it before any DPCD access and hope that the
* monitor doesn't power down exactly after the throw away read.
*/
if (!aux->is_remote) {
ret = drm_dp_dpcd_probe(aux, DP_DPCD_REV);
if (dpcd_access_needs_probe(aux)) {
ret = drm_dp_dpcd_probe(aux, DP_LANE0_1_STATUS);
if (ret < 0)
return ret;
}

View File

@ -67,34 +67,36 @@ static int oui(u8 first, u8 second, u8 third)
* on as many displays as possible).
*/
/* First detailed mode wrong, use largest 60Hz mode */
#define EDID_QUIRK_PREFER_LARGE_60 (1 << 0)
/* Reported 135MHz pixel clock is too high, needs adjustment */
#define EDID_QUIRK_135_CLOCK_TOO_HIGH (1 << 1)
/* Prefer the largest mode at 75 Hz */
#define EDID_QUIRK_PREFER_LARGE_75 (1 << 2)
/* Detail timing is in cm not mm */
#define EDID_QUIRK_DETAILED_IN_CM (1 << 3)
/* Detailed timing descriptors have bogus size values, so just take the
* maximum size and use that.
*/
#define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4)
/* use +hsync +vsync for detailed mode */
#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
/* Force reduced-blanking timings for detailed modes */
#define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7)
/* Force 8bpc */
#define EDID_QUIRK_FORCE_8BPC (1 << 8)
/* Force 12bpc */
#define EDID_QUIRK_FORCE_12BPC (1 << 9)
/* Force 6bpc */
#define EDID_QUIRK_FORCE_6BPC (1 << 10)
/* Force 10bpc */
#define EDID_QUIRK_FORCE_10BPC (1 << 11)
/* Non desktop display (i.e. HMD) */
#define EDID_QUIRK_NON_DESKTOP (1 << 12)
/* Cap the DSC target bitrate to 15bpp */
#define EDID_QUIRK_CAP_DSC_15BPP (1 << 13)
enum drm_edid_internal_quirk {
/* First detailed mode wrong, use largest 60Hz mode */
EDID_QUIRK_PREFER_LARGE_60 = DRM_EDID_QUIRK_NUM,
/* Reported 135MHz pixel clock is too high, needs adjustment */
EDID_QUIRK_135_CLOCK_TOO_HIGH,
/* Prefer the largest mode at 75 Hz */
EDID_QUIRK_PREFER_LARGE_75,
/* Detail timing is in cm not mm */
EDID_QUIRK_DETAILED_IN_CM,
/* Detailed timing descriptors have bogus size values, so just take the
* maximum size and use that.
*/
EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE,
/* use +hsync +vsync for detailed mode */
EDID_QUIRK_DETAILED_SYNC_PP,
/* Force reduced-blanking timings for detailed modes */
EDID_QUIRK_FORCE_REDUCED_BLANKING,
/* Force 8bpc */
EDID_QUIRK_FORCE_8BPC,
/* Force 12bpc */
EDID_QUIRK_FORCE_12BPC,
/* Force 6bpc */
EDID_QUIRK_FORCE_6BPC,
/* Force 10bpc */
EDID_QUIRK_FORCE_10BPC,
/* Non desktop display (i.e. HMD) */
EDID_QUIRK_NON_DESKTOP,
/* Cap the DSC target bitrate to 15bpp */
EDID_QUIRK_CAP_DSC_15BPP,
};
#define MICROSOFT_IEEE_OUI 0xca125c
@ -129,124 +131,132 @@ static const struct edid_quirk {
u32 quirks;
} edid_quirk_list[] = {
/* Acer AL1706 */
EDID_QUIRK('A', 'C', 'R', 44358, EDID_QUIRK_PREFER_LARGE_60),
EDID_QUIRK('A', 'C', 'R', 44358, BIT(EDID_QUIRK_PREFER_LARGE_60)),
/* Acer F51 */
EDID_QUIRK('A', 'P', 'I', 0x7602, EDID_QUIRK_PREFER_LARGE_60),
EDID_QUIRK('A', 'P', 'I', 0x7602, BIT(EDID_QUIRK_PREFER_LARGE_60)),
/* AEO model 0 reports 8 bpc, but is a 6 bpc panel */
EDID_QUIRK('A', 'E', 'O', 0, EDID_QUIRK_FORCE_6BPC),
EDID_QUIRK('A', 'E', 'O', 0, BIT(EDID_QUIRK_FORCE_6BPC)),
/* BenQ GW2765 */
EDID_QUIRK('B', 'N', 'Q', 0x78d6, EDID_QUIRK_FORCE_8BPC),
EDID_QUIRK('B', 'N', 'Q', 0x78d6, BIT(EDID_QUIRK_FORCE_8BPC)),
/* BOE model on HP Pavilion 15-n233sl reports 8 bpc, but is a 6 bpc panel */
EDID_QUIRK('B', 'O', 'E', 0x78b, EDID_QUIRK_FORCE_6BPC),
EDID_QUIRK('B', 'O', 'E', 0x78b, BIT(EDID_QUIRK_FORCE_6BPC)),
/* CPT panel of Asus UX303LA reports 8 bpc, but is a 6 bpc panel */
EDID_QUIRK('C', 'P', 'T', 0x17df, EDID_QUIRK_FORCE_6BPC),
EDID_QUIRK('C', 'P', 'T', 0x17df, BIT(EDID_QUIRK_FORCE_6BPC)),
/* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */
EDID_QUIRK('S', 'D', 'C', 0x3652, EDID_QUIRK_FORCE_6BPC),
EDID_QUIRK('S', 'D', 'C', 0x3652, BIT(EDID_QUIRK_FORCE_6BPC)),
/* BOE model 0x0771 reports 8 bpc, but is a 6 bpc panel */
EDID_QUIRK('B', 'O', 'E', 0x0771, EDID_QUIRK_FORCE_6BPC),
EDID_QUIRK('B', 'O', 'E', 0x0771, BIT(EDID_QUIRK_FORCE_6BPC)),
/* Belinea 10 15 55 */
EDID_QUIRK('M', 'A', 'X', 1516, EDID_QUIRK_PREFER_LARGE_60),
EDID_QUIRK('M', 'A', 'X', 0x77e, EDID_QUIRK_PREFER_LARGE_60),
EDID_QUIRK('M', 'A', 'X', 1516, BIT(EDID_QUIRK_PREFER_LARGE_60)),
EDID_QUIRK('M', 'A', 'X', 0x77e, BIT(EDID_QUIRK_PREFER_LARGE_60)),
/* Envision Peripherals, Inc. EN-7100e */
EDID_QUIRK('E', 'P', 'I', 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH),
EDID_QUIRK('E', 'P', 'I', 59264, BIT(EDID_QUIRK_135_CLOCK_TOO_HIGH)),
/* Envision EN2028 */
EDID_QUIRK('E', 'P', 'I', 8232, EDID_QUIRK_PREFER_LARGE_60),
EDID_QUIRK('E', 'P', 'I', 8232, BIT(EDID_QUIRK_PREFER_LARGE_60)),
/* Funai Electronics PM36B */
EDID_QUIRK('F', 'C', 'M', 13600, EDID_QUIRK_PREFER_LARGE_75 |
EDID_QUIRK_DETAILED_IN_CM),
EDID_QUIRK('F', 'C', 'M', 13600, BIT(EDID_QUIRK_PREFER_LARGE_75) |
BIT(EDID_QUIRK_DETAILED_IN_CM)),
/* LG 27GP950 */
EDID_QUIRK('G', 'S', 'M', 0x5bbf, EDID_QUIRK_CAP_DSC_15BPP),
EDID_QUIRK('G', 'S', 'M', 0x5bbf, BIT(EDID_QUIRK_CAP_DSC_15BPP)),
/* LG 27GN950 */
EDID_QUIRK('G', 'S', 'M', 0x5b9a, EDID_QUIRK_CAP_DSC_15BPP),
EDID_QUIRK('G', 'S', 'M', 0x5b9a, BIT(EDID_QUIRK_CAP_DSC_15BPP)),
/* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */
EDID_QUIRK('L', 'G', 'D', 764, EDID_QUIRK_FORCE_10BPC),
EDID_QUIRK('L', 'G', 'D', 764, BIT(EDID_QUIRK_FORCE_10BPC)),
/* LG Philips LCD LP154W01-A5 */
EDID_QUIRK('L', 'P', 'L', 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE),
EDID_QUIRK('L', 'P', 'L', 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE),
EDID_QUIRK('L', 'P', 'L', 0, BIT(EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE)),
EDID_QUIRK('L', 'P', 'L', 0x2a00, BIT(EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE)),
/* Samsung SyncMaster 205BW. Note: irony */
EDID_QUIRK('S', 'A', 'M', 541, EDID_QUIRK_DETAILED_SYNC_PP),
EDID_QUIRK('S', 'A', 'M', 541, BIT(EDID_QUIRK_DETAILED_SYNC_PP)),
/* Samsung SyncMaster 22[5-6]BW */
EDID_QUIRK('S', 'A', 'M', 596, EDID_QUIRK_PREFER_LARGE_60),
EDID_QUIRK('S', 'A', 'M', 638, EDID_QUIRK_PREFER_LARGE_60),
EDID_QUIRK('S', 'A', 'M', 596, BIT(EDID_QUIRK_PREFER_LARGE_60)),
EDID_QUIRK('S', 'A', 'M', 638, BIT(EDID_QUIRK_PREFER_LARGE_60)),
/* Sony PVM-2541A does up to 12 bpc, but only reports max 8 bpc */
EDID_QUIRK('S', 'N', 'Y', 0x2541, EDID_QUIRK_FORCE_12BPC),
EDID_QUIRK('S', 'N', 'Y', 0x2541, BIT(EDID_QUIRK_FORCE_12BPC)),
/* ViewSonic VA2026w */
EDID_QUIRK('V', 'S', 'C', 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING),
EDID_QUIRK('V', 'S', 'C', 5020, BIT(EDID_QUIRK_FORCE_REDUCED_BLANKING)),
/* Medion MD 30217 PG */
EDID_QUIRK('M', 'E', 'D', 0x7b8, EDID_QUIRK_PREFER_LARGE_75),
EDID_QUIRK('M', 'E', 'D', 0x7b8, BIT(EDID_QUIRK_PREFER_LARGE_75)),
/* Lenovo G50 */
EDID_QUIRK('S', 'D', 'C', 18514, EDID_QUIRK_FORCE_6BPC),
EDID_QUIRK('S', 'D', 'C', 18514, BIT(EDID_QUIRK_FORCE_6BPC)),
/* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */
EDID_QUIRK('S', 'E', 'C', 0xd033, EDID_QUIRK_FORCE_8BPC),
EDID_QUIRK('S', 'E', 'C', 0xd033, BIT(EDID_QUIRK_FORCE_8BPC)),
/* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/
EDID_QUIRK('E', 'T', 'R', 13896, EDID_QUIRK_FORCE_8BPC),
EDID_QUIRK('E', 'T', 'R', 13896, BIT(EDID_QUIRK_FORCE_8BPC)),
/* Valve Index Headset */
EDID_QUIRK('V', 'L', 'V', 0x91a8, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b0, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b1, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b2, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b3, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b4, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b5, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b6, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b7, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b8, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91b9, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91ba, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91bb, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91bc, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91bd, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91be, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91bf, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('V', 'L', 'V', 0x91a8, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b0, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b1, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b2, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b3, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b4, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b5, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b6, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b7, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b8, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91b9, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91ba, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91bb, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91bc, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91bd, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91be, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('V', 'L', 'V', 0x91bf, BIT(EDID_QUIRK_NON_DESKTOP)),
/* HTC Vive and Vive Pro VR Headsets */
EDID_QUIRK('H', 'V', 'R', 0xaa01, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('H', 'V', 'R', 0xaa02, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('H', 'V', 'R', 0xaa01, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('H', 'V', 'R', 0xaa02, BIT(EDID_QUIRK_NON_DESKTOP)),
/* Oculus Rift DK1, DK2, CV1 and Rift S VR Headsets */
EDID_QUIRK('O', 'V', 'R', 0x0001, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('O', 'V', 'R', 0x0003, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('O', 'V', 'R', 0x0004, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('O', 'V', 'R', 0x0012, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('O', 'V', 'R', 0x0001, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('O', 'V', 'R', 0x0003, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('O', 'V', 'R', 0x0004, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('O', 'V', 'R', 0x0012, BIT(EDID_QUIRK_NON_DESKTOP)),
/* Windows Mixed Reality Headsets */
EDID_QUIRK('A', 'C', 'R', 0x7fce, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('L', 'E', 'N', 0x0408, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('F', 'U', 'J', 0x1970, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('D', 'E', 'L', 0x7fce, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('S', 'E', 'C', 0x144a, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('A', 'U', 'S', 0xc102, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('A', 'C', 'R', 0x7fce, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('L', 'E', 'N', 0x0408, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('F', 'U', 'J', 0x1970, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('D', 'E', 'L', 0x7fce, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('S', 'E', 'C', 0x144a, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('A', 'U', 'S', 0xc102, BIT(EDID_QUIRK_NON_DESKTOP)),
/* Sony PlayStation VR Headset */
EDID_QUIRK('S', 'N', 'Y', 0x0704, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('S', 'N', 'Y', 0x0704, BIT(EDID_QUIRK_NON_DESKTOP)),
/* Sensics VR Headsets */
EDID_QUIRK('S', 'E', 'N', 0x1019, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('S', 'E', 'N', 0x1019, BIT(EDID_QUIRK_NON_DESKTOP)),
/* OSVR HDK and HDK2 VR Headsets */
EDID_QUIRK('S', 'V', 'R', 0x1019, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('A', 'U', 'O', 0x1111, EDID_QUIRK_NON_DESKTOP),
EDID_QUIRK('S', 'V', 'R', 0x1019, BIT(EDID_QUIRK_NON_DESKTOP)),
EDID_QUIRK('A', 'U', 'O', 0x1111, BIT(EDID_QUIRK_NON_DESKTOP)),
/*
* @drm_edid_internal_quirk entries end here, following with the
* @drm_edid_quirk entries.
*/
/* HP ZR24w DP AUX DPCD access requires probing to prevent corruption. */
EDID_QUIRK('H', 'W', 'P', 0x2869, BIT(DRM_EDID_QUIRK_DP_DPCD_PROBE)),
};
/*
@ -2952,6 +2962,18 @@ static u32 edid_get_quirks(const struct drm_edid *drm_edid)
return 0;
}
static bool drm_edid_has_internal_quirk(struct drm_connector *connector,
enum drm_edid_internal_quirk quirk)
{
return connector->display_info.quirks & BIT(quirk);
}
bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk quirk)
{
return connector->display_info.quirks & BIT(quirk);
}
EXPORT_SYMBOL(drm_edid_has_quirk);
#define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay)
#define MODE_REFRESH_DIFF(c,t) (abs((c) - (t)))
@ -2961,7 +2983,6 @@ static u32 edid_get_quirks(const struct drm_edid *drm_edid)
*/
static void edid_fixup_preferred(struct drm_connector *connector)
{
const struct drm_display_info *info = &connector->display_info;
struct drm_display_mode *t, *cur_mode, *preferred_mode;
int target_refresh = 0;
int cur_vrefresh, preferred_vrefresh;
@ -2969,9 +2990,9 @@ static void edid_fixup_preferred(struct drm_connector *connector)
if (list_empty(&connector->probed_modes))
return;
if (info->quirks & EDID_QUIRK_PREFER_LARGE_60)
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_PREFER_LARGE_60))
target_refresh = 60;
if (info->quirks & EDID_QUIRK_PREFER_LARGE_75)
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_PREFER_LARGE_75))
target_refresh = 75;
preferred_mode = list_first_entry(&connector->probed_modes,
@ -3475,7 +3496,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
const struct drm_edid *drm_edid,
const struct detailed_timing *timing)
{
const struct drm_display_info *info = &connector->display_info;
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode;
const struct detailed_pixel_timing *pt = &timing->data.pixel_data;
@ -3509,7 +3529,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
return NULL;
}
if (info->quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) {
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_REDUCED_BLANKING)) {
mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false);
if (!mode)
return NULL;
@ -3521,7 +3541,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
if (!mode)
return NULL;
if (info->quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_135_CLOCK_TOO_HIGH))
mode->clock = 1088 * 10;
else
mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
@ -3552,7 +3572,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
drm_mode_do_interlace_quirk(mode, pt);
if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_DETAILED_SYNC_PP)) {
mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
} else {
mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
@ -3565,12 +3585,12 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto
mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
if (info->quirks & EDID_QUIRK_DETAILED_IN_CM) {
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_DETAILED_IN_CM)) {
mode->width_mm *= 10;
mode->height_mm *= 10;
}
if (info->quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE)) {
mode->width_mm = drm_edid->edid->width_cm * 10;
mode->height_mm = drm_edid->edid->height_cm * 10;
}
@ -6735,26 +6755,26 @@ static void update_display_info(struct drm_connector *connector,
drm_update_mso(connector, drm_edid);
out:
if (info->quirks & EDID_QUIRK_NON_DESKTOP) {
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_NON_DESKTOP)) {
drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Non-desktop display%s\n",
connector->base.id, connector->name,
info->non_desktop ? " (redundant quirk)" : "");
info->non_desktop = true;
}
if (info->quirks & EDID_QUIRK_CAP_DSC_15BPP)
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_CAP_DSC_15BPP))
info->max_dsc_bpp = 15;
if (info->quirks & EDID_QUIRK_FORCE_6BPC)
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_6BPC))
info->bpc = 6;
if (info->quirks & EDID_QUIRK_FORCE_8BPC)
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_8BPC))
info->bpc = 8;
if (info->quirks & EDID_QUIRK_FORCE_10BPC)
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_10BPC))
info->bpc = 10;
if (info->quirks & EDID_QUIRK_FORCE_12BPC)
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_12BPC))
info->bpc = 12;
/* Depends on info->cea_rev set by drm_parse_cea_ext() above */
@ -6919,7 +6939,6 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
static int _drm_edid_connector_add_modes(struct drm_connector *connector,
const struct drm_edid *drm_edid)
{
const struct drm_display_info *info = &connector->display_info;
int num_modes = 0;
if (!drm_edid)
@ -6949,7 +6968,8 @@ static int _drm_edid_connector_add_modes(struct drm_connector *connector,
if (drm_edid->edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ)
num_modes += add_inferred_modes(connector, drm_edid);
if (info->quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_PREFER_LARGE_60) ||
drm_edid_has_internal_quirk(connector, EDID_QUIRK_PREFER_LARGE_75))
edid_fixup_preferred(connector);
return num_modes;

View File

@ -40,12 +40,11 @@ i915-y += \
intel_pcode.o \
intel_region_ttm.o \
intel_runtime_pm.o \
intel_sbi.o \
intel_step.o \
intel_uncore.o \
intel_uncore_trace.o \
intel_wakeref.o \
vlv_sideband.o \
vlv_iosf_sb.o \
vlv_suspend.o
# core peripheral code
@ -288,6 +287,7 @@ i915-y += \
display/intel_pmdemand.o \
display/intel_psr.o \
display/intel_quirks.o \
display/intel_sbi.o \
display/intel_sprite.o \
display/intel_sprite_uapi.o \
display/intel_tc.o \
@ -296,7 +296,8 @@ i915-y += \
display/intel_wm.o \
display/skl_scaler.o \
display/skl_universal_plane.o \
display/skl_watermark.o
display/skl_watermark.o \
display/vlv_sideband.o
i915-$(CONFIG_ACPI) += \
display/intel_acpi.o \
display/intel_opregion.o

View File

@ -18,6 +18,7 @@
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_power.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_aux.h"

View File

@ -15,6 +15,7 @@
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_power.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp_aux.h"
#include "intel_dpio_phy.h"

View File

@ -10,6 +10,7 @@
#include "i915_reg.h"
#include "intel_color_regs.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_pcode.h"

View File

@ -5,10 +5,10 @@
#include <drm/drm_device.h>
#include "i915_reg.h"
#include "i9xx_display_sr.h"
#include "i9xx_wm_regs.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_gmbus.h"
#include "intel_pci_config.h"

View File

@ -2,6 +2,7 @@
/*
* Copyright © 2020 Intel Corporation
*/
#include <linux/kernel.h>
#include <drm/drm_atomic_helper.h>
@ -17,6 +18,7 @@
#include "intel_atomic_plane.h"
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fbc.h"

View File

@ -11,6 +11,7 @@
#include "intel_bo.h"
#include "intel_de.h"
#include "intel_display.h"
#include "intel_display_regs.h"
#include "intel_display_trace.h"
#include "intel_fb.h"
#include "intel_mchbar_regs.h"
@ -107,43 +108,41 @@ static const struct cxsr_latency *pnv_get_cxsr_latency(struct intel_display *dis
static void chv_set_memory_dvfs(struct intel_display *display, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 val;
vlv_punit_get(dev_priv);
vlv_punit_get(display->drm);
val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2);
val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2);
if (enable)
val &= ~FORCE_DDR_HIGH_FREQ;
else
val |= FORCE_DDR_HIGH_FREQ;
val &= ~FORCE_DDR_LOW_FREQ;
val |= FORCE_DDR_FREQ_REQ_ACK;
vlv_punit_write(dev_priv, PUNIT_REG_DDR_SETUP2, val);
vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val);
if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2) &
if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2) &
FORCE_DDR_FREQ_REQ_ACK) == 0, 3))
drm_err(display->drm,
"timed out waiting for Punit DDR DVFS request\n");
vlv_punit_put(dev_priv);
vlv_punit_put(display->drm);
}
static void chv_set_memory_pm5(struct intel_display *display, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 val;
vlv_punit_get(dev_priv);
vlv_punit_get(display->drm);
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
if (enable)
val |= DSP_MAXFIFO_PM5_ENABLE;
else
val &= ~DSP_MAXFIFO_PM5_ENABLE;
vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val);
vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val);
vlv_punit_put(dev_priv);
vlv_punit_put(display->drm);
}
#define FW_WM(value, plane) \
@ -3900,7 +3899,6 @@ static void g4x_wm_sanitize(struct intel_display *display)
static void vlv_wm_get_hw_state(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct vlv_wm_values *wm = &display->wm.vlv;
struct intel_crtc *crtc;
u32 val;
@ -3911,9 +3909,9 @@ static void vlv_wm_get_hw_state(struct intel_display *display)
wm->level = VLV_WM_LEVEL_PM2;
if (display->platform.cherryview) {
vlv_punit_get(dev_priv);
vlv_punit_get(display->drm);
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
if (val & DSP_MAXFIFO_PM5_ENABLE)
wm->level = VLV_WM_LEVEL_PM5;
@ -3926,23 +3924,23 @@ static void vlv_wm_get_hw_state(struct intel_display *display)
* HIGH/LOW bits so that we don't actually change
* the current state.
*/
val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2);
val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2);
val |= FORCE_DDR_FREQ_REQ_ACK;
vlv_punit_write(dev_priv, PUNIT_REG_DDR_SETUP2, val);
vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val);
if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2) &
if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2) &
FORCE_DDR_FREQ_REQ_ACK) == 0, 3)) {
drm_dbg_kms(display->drm,
"Punit not acking DDR DVFS request, "
"assuming DDR DVFS is disabled\n");
display->wm.num_levels = VLV_WM_LEVEL_PM5 + 1;
} else {
val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2);
val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2);
if ((val & FORCE_DDR_HIGH_FREQ) == 0)
wm->level = VLV_WM_LEVEL_DDR_DVFS;
}
vlv_punit_put(dev_priv);
vlv_punit_put(display->drm);
}
for_each_intel_crtc(display->drm, crtc) {

View File

@ -45,6 +45,7 @@
#include "intel_crtc.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_dsi.h"
#include "intel_dsi_vbt.h"
#include "intel_panel.h"
@ -192,12 +193,12 @@ static int dsi_send_pkt_hdr(struct intel_dsi_host *host,
else
tmp &= ~PAYLOAD_PRESENT;
tmp &= ~VBLANK_FENCE;
tmp &= ~(VBLANK_FENCE | LP_DATA_TRANSFER | PIPELINE_FLUSH);
if (enable_lpdt)
tmp |= LP_DATA_TRANSFER;
else
tmp &= ~LP_DATA_TRANSFER;
tmp |= PIPELINE_FLUSH;
tmp &= ~(PARAM_WC_MASK | VC_MASK | DT_MASK);
tmp |= ((packet->header[0] & VC_MASK) << VC_SHIFT);
@ -658,7 +659,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder,
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
struct intel_dpll *pll = crtc_state->intel_dpll;
enum phy phy;
u32 val;

View File

@ -272,6 +272,7 @@
#define PAYLOAD_PRESENT (1 << 31)
#define LP_DATA_TRANSFER (1 << 30)
#define VBLANK_FENCE (1 << 29)
#define PIPELINE_FLUSH (1 << 28)
#define PARAM_WC_MASK (0xffff << 8)
#define PARAM_WC_LOWER_SHIFT 8
#define PARAM_WC_UPPER_SHIFT 16

View File

@ -26,6 +26,13 @@ bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp)
return intel_dp->alpm_dpcd & DP_ALPM_AUX_LESS_CAP;
}
bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
return intel_psr_needs_alpm_aux_less(intel_dp, crtc_state) ||
(crtc_state->has_lobf && intel_alpm_aux_less_wake_supported(intel_dp));
}
void intel_alpm_init(struct intel_dp *intel_dp)
{
u8 dpcd;
@ -329,7 +336,6 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
{
struct intel_display *display = to_intel_display(intel_dp);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum port port = dp_to_dig_port(intel_dp)->base.port;
u32 alpm_ctl;
if (DISPLAY_VER(display) < 20 || (!intel_psr_needs_alpm(intel_dp, crtc_state) &&
@ -341,30 +347,26 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
* Panel Replay on eDP is always using ALPM aux less. I.e. no need to
* check panel support at this point.
*/
if ((crtc_state->has_panel_replay && intel_dp_is_edp(intel_dp)) ||
(crtc_state->has_lobf && intel_alpm_aux_less_wake_supported(intel_dp))) {
if (intel_alpm_is_alpm_aux_less(intel_dp, crtc_state)) {
alpm_ctl = ALPM_CTL_ALPM_ENABLE |
ALPM_CTL_ALPM_AUX_LESS_ENABLE |
ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS |
ALPM_CTL_AUX_LESS_WAKE_TIME(intel_dp->alpm_parameters.aux_less_wake_lines);
intel_de_write(display,
PORT_ALPM_CTL(port),
PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE |
PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) |
PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) |
PORT_ALPM_CTL_SILENCE_PERIOD(
intel_dp->alpm_parameters.silence_period_sym_clocks));
if (intel_dp->as_sdp_supported) {
u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1;
if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP)
pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU;
if (!(intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)] &
DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR))
pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE;
intel_de_write(display, PR_ALPM_CTL(display, cpu_transcoder),
pr_alpm_ctl);
}
intel_de_write(display,
PORT_ALPM_LFPS_CTL(port),
PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) |
PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION(
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) |
PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION(
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) |
PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION(
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms));
} else {
alpm_ctl = ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE |
ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines);
@ -388,6 +390,36 @@ void intel_alpm_configure(struct intel_dp *intel_dp,
intel_dp->alpm_parameters.transcoder = crtc_state->cpu_transcoder;
}
void intel_alpm_port_configure(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(intel_dp);
enum port port = dp_to_dig_port(intel_dp)->base.port;
u32 alpm_ctl_val = 0, lfps_ctl_val = 0;
if (DISPLAY_VER(display) < 20)
return;
if (intel_alpm_is_alpm_aux_less(intel_dp, crtc_state)) {
alpm_ctl_val = PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE |
PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) |
PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) |
PORT_ALPM_CTL_SILENCE_PERIOD(
intel_dp->alpm_parameters.silence_period_sym_clocks);
lfps_ctl_val = PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) |
PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION(
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) |
PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION(
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) |
PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION(
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms);
}
intel_de_write(display, PORT_ALPM_CTL(port), alpm_ctl_val);
intel_de_write(display, PORT_ALPM_LFPS_CTL(port), lfps_ctl_val);
}
void intel_alpm_pre_plane_update(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{

View File

@ -27,11 +27,15 @@ void intel_alpm_enable_sink(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_port_configure(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
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);
bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
void intel_alpm_disable(struct intel_dp *intel_dp);
bool intel_alpm_get_error(struct intel_dp *intel_dp);
#endif

View File

@ -274,7 +274,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
crtc_state->do_async_flip = false;
crtc_state->fb_bits = 0;
crtc_state->update_planes = 0;
crtc_state->dsb_color_vblank = NULL;
crtc_state->dsb_color = NULL;
crtc_state->dsb_commit = NULL;
crtc_state->use_dsb = false;
@ -310,7 +310,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
{
struct intel_crtc_state *crtc_state = to_intel_crtc_state(state);
drm_WARN_ON(crtc->dev, crtc_state->dsb_color_vblank);
drm_WARN_ON(crtc->dev, crtc_state->dsb_color);
drm_WARN_ON(crtc->dev, crtc_state->dsb_commit);
__drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi);

View File

@ -42,7 +42,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include "gem/i915_gem_object.h"
#include "i915_config.h"
#include "i915_scheduler_types.h"
#include "i915_vma.h"
#include "i9xx_plane_regs.h"

View File

@ -7,7 +7,6 @@
#include <linux/kernel.h>
#include <linux/pwm.h>
#include <linux/string_helpers.h>
#include <acpi/video.h>
#include <drm/drm_file.h>
@ -19,6 +18,7 @@
#include "intel_backlight_regs.h"
#include "intel_connector.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dp_aux_backlight.h"

View File

@ -37,6 +37,7 @@
#include "i915_drv.h"
#include "intel_display.h"
#include "intel_display_core.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_gmbus.h"

View File

@ -5,6 +5,8 @@
#include <drm/drm_atomic_state_helper.h>
#include "soc/intel_dram.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_utils.h"
@ -12,10 +14,11 @@
#include "intel_bw.h"
#include "intel_cdclk.h"
#include "intel_display_core.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "skl_watermark.h"
#include "intel_mchbar_regs.h"
#include "intel_pcode.h"
#include "skl_watermark.h"
/* Parameters for Qclk Geyserville (QGV) */
struct intel_qgv_point {
@ -218,11 +221,10 @@ intel_read_qgv_point_info(struct intel_display *display,
}
static int icl_get_qgv_points(struct intel_display *display,
const struct dram_info *dram_info,
struct intel_qgv_info *qi,
bool is_y_tile)
{
struct drm_i915_private *i915 = to_i915(display->drm);
const struct dram_info *dram_info = &i915->dram_info;
int i, ret;
qi->num_points = dram_info->num_qgv_points;
@ -418,19 +420,20 @@ static const struct intel_sa_info xe3lpd_sa_info = {
.derating = 10,
};
static int icl_get_bw_info(struct intel_display *display, const struct intel_sa_info *sa)
static int icl_get_bw_info(struct intel_display *display,
const struct dram_info *dram_info,
const struct intel_sa_info *sa)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_qgv_info qi = {};
bool is_y_tile = true; /* assume y tile may be used */
int num_channels = max_t(u8, 1, i915->dram_info.num_channels);
int num_channels = max_t(u8, 1, dram_info->num_channels);
int ipqdepth, ipqdepthpch = 16;
int dclk_max;
int maxdebw;
int num_groups = ARRAY_SIZE(display->bw.max);
int i, ret;
ret = icl_get_qgv_points(display, &qi, is_y_tile);
ret = icl_get_qgv_points(display, dram_info, &qi, is_y_tile);
if (ret) {
drm_dbg_kms(display->drm,
"Failed to get memory subsystem information, ignoring bandwidth limits");
@ -488,11 +491,11 @@ static int icl_get_bw_info(struct intel_display *display, const struct intel_sa_
return 0;
}
static int tgl_get_bw_info(struct intel_display *display, const struct intel_sa_info *sa)
static int tgl_get_bw_info(struct intel_display *display,
const struct dram_info *dram_info,
const struct intel_sa_info *sa)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_qgv_info qi = {};
const struct dram_info *dram_info = &i915->dram_info;
bool is_y_tile = true; /* assume y tile may be used */
int num_channels = max_t(u8, 1, dram_info->num_channels);
int ipqdepth, ipqdepthpch = 16;
@ -502,7 +505,7 @@ static int tgl_get_bw_info(struct intel_display *display, const struct intel_sa_
int num_groups = ARRAY_SIZE(display->bw.max);
int i, ret;
ret = icl_get_qgv_points(display, &qi, is_y_tile);
ret = icl_get_qgv_points(display, dram_info, &qi, is_y_tile);
if (ret) {
drm_dbg_kms(display->drm,
"Failed to get memory subsystem information, ignoring bandwidth limits");
@ -632,15 +635,15 @@ static void dg2_get_bw_info(struct intel_display *display)
}
static int xe2_hpd_get_bw_info(struct intel_display *display,
const struct dram_info *dram_info,
const struct intel_sa_info *sa)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_qgv_info qi = {};
int num_channels = i915->dram_info.num_channels;
int num_channels = dram_info->num_channels;
int peakbw, maxdebw;
int ret, i;
ret = icl_get_qgv_points(display, &qi, true);
ret = icl_get_qgv_points(display, dram_info, &qi, true);
if (ret) {
drm_dbg_kms(display->drm,
"Failed to get memory subsystem information, ignoring bandwidth limits");
@ -763,32 +766,32 @@ static unsigned int icl_qgv_bw(struct intel_display *display,
void intel_bw_init_hw(struct intel_display *display)
{
const struct dram_info *dram_info = &to_i915(display->drm)->dram_info;
const struct dram_info *dram_info = intel_dram_info(display->drm);
if (!HAS_DISPLAY(display))
return;
if (DISPLAY_VER(display) >= 30)
tgl_get_bw_info(display, &xe3lpd_sa_info);
tgl_get_bw_info(display, dram_info, &xe3lpd_sa_info);
else if (DISPLAY_VERx100(display) >= 1401 && display->platform.dgfx &&
dram_info->type == INTEL_DRAM_GDDR_ECC)
xe2_hpd_get_bw_info(display, &xe2_hpd_ecc_sa_info);
xe2_hpd_get_bw_info(display, dram_info, &xe2_hpd_ecc_sa_info);
else if (DISPLAY_VERx100(display) >= 1401 && display->platform.dgfx)
xe2_hpd_get_bw_info(display, &xe2_hpd_sa_info);
xe2_hpd_get_bw_info(display, dram_info, &xe2_hpd_sa_info);
else if (DISPLAY_VER(display) >= 14)
tgl_get_bw_info(display, &mtl_sa_info);
tgl_get_bw_info(display, dram_info, &mtl_sa_info);
else if (display->platform.dg2)
dg2_get_bw_info(display);
else if (display->platform.alderlake_p)
tgl_get_bw_info(display, &adlp_sa_info);
tgl_get_bw_info(display, dram_info, &adlp_sa_info);
else if (display->platform.alderlake_s)
tgl_get_bw_info(display, &adls_sa_info);
tgl_get_bw_info(display, dram_info, &adls_sa_info);
else if (display->platform.rocketlake)
tgl_get_bw_info(display, &rkl_sa_info);
tgl_get_bw_info(display, dram_info, &rkl_sa_info);
else if (DISPLAY_VER(display) == 12)
tgl_get_bw_info(display, &tgl_sa_info);
tgl_get_bw_info(display, dram_info, &tgl_sa_info);
else if (DISPLAY_VER(display) == 11)
icl_get_bw_info(display, &icl_sa_info);
icl_get_bw_info(display, dram_info, &icl_sa_info);
}
static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_state *crtc_state)

View File

@ -38,6 +38,7 @@
#include "intel_cdclk.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_mchbar_regs.h"
#include "intel_pci_config.h"
@ -567,20 +568,18 @@ static u8 vlv_calc_voltage_level(struct intel_display *display, int cdclk)
static void vlv_get_cdclk(struct intel_display *display,
struct intel_cdclk_config *cdclk_config)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 val;
vlv_iosf_sb_get(dev_priv,
BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
cdclk_config->vco = vlv_get_hpll_vco(dev_priv);
cdclk_config->cdclk = vlv_get_cck_clock(dev_priv, "cdclk",
cdclk_config->vco = vlv_get_hpll_vco(display->drm);
cdclk_config->cdclk = vlv_get_cck_clock(display->drm, "cdclk",
CCK_DISPLAY_CLOCK_CONTROL,
cdclk_config->vco);
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
vlv_iosf_sb_put(dev_priv,
vlv_iosf_sb_put(display->drm,
BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
if (display->platform.valleyview)
@ -658,16 +657,16 @@ static void vlv_set_cdclk(struct intel_display *display,
*/
wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE);
vlv_iosf_sb_get(dev_priv,
vlv_iosf_sb_get(display->drm,
BIT(VLV_IOSF_SB_CCK) |
BIT(VLV_IOSF_SB_BUNIT) |
BIT(VLV_IOSF_SB_PUNIT));
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
val &= ~DSPFREQGUAR_MASK;
val |= (cmd << DSPFREQGUAR_SHIFT);
vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val);
if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) &
vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val);
if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) &
DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
50)) {
drm_err(display->drm,
@ -681,12 +680,12 @@ static void vlv_set_cdclk(struct intel_display *display,
cdclk) - 1;
/* adjust cdclk divider */
val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
val = vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL);
val &= ~CCK_FREQUENCY_VALUES;
val |= divider;
vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
vlv_cck_write(display->drm, CCK_DISPLAY_CLOCK_CONTROL, val);
if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
if (wait_for((vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL) &
CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
50))
drm_err(display->drm,
@ -694,7 +693,7 @@ static void vlv_set_cdclk(struct intel_display *display,
}
/* adjust self-refresh exit latency value */
val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
val = vlv_bunit_read(display->drm, BUNIT_REG_BISOC);
val &= ~0x7f;
/*
@ -705,9 +704,9 @@ static void vlv_set_cdclk(struct intel_display *display,
val |= 4500 / 250; /* 4.5 usec */
else
val |= 3000 / 250; /* 3.0 usec */
vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
vlv_bunit_write(display->drm, BUNIT_REG_BISOC, val);
vlv_iosf_sb_put(dev_priv,
vlv_iosf_sb_put(display->drm,
BIT(VLV_IOSF_SB_CCK) |
BIT(VLV_IOSF_SB_BUNIT) |
BIT(VLV_IOSF_SB_PUNIT));
@ -723,7 +722,6 @@ static void chv_set_cdclk(struct intel_display *display,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
int cdclk = cdclk_config->cdclk;
u32 val, cmd = cdclk_config->voltage_level;
intel_wakeref_t wakeref;
@ -747,19 +745,19 @@ static void chv_set_cdclk(struct intel_display *display,
*/
wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE);
vlv_punit_get(dev_priv);
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
vlv_punit_get(display->drm);
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
val &= ~DSPFREQGUAR_MASK_CHV;
val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val);
if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) &
vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val);
if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) &
DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
50)) {
drm_err(display->drm,
"timed out waiting for CDclk change\n");
}
vlv_punit_put(dev_priv);
vlv_punit_put(display->drm);
intel_update_cdclk(display);
@ -3528,10 +3526,8 @@ static int pch_rawclk(struct intel_display *display)
static int vlv_hrawclk(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
/* RAWCLK_FREQ_VLV register updated from power well code */
return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
return vlv_get_cck_clock_hpll(display->drm, "hrawclk",
CCK_DISPLAY_REF_CLOCK_CONTROL);
}

View File

@ -9,13 +9,13 @@
#include <drm/drm_device.h>
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_crtc.h"
#include "intel_cmtg.h"
#include "intel_cmtg_regs.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_device.h"
#include "intel_display_power.h"
#include "intel_display_regs.h"
/**
* DOC: Common Primary Timing Generator (CMTG)

View File

@ -6,7 +6,7 @@
#ifndef __INTEL_CMTG_REGS_H__
#define __INTEL_CMTG_REGS_H__
#include "i915_reg_defs.h"
#include "intel_display_reg_defs.h"
#define CMTG_CLK_SEL _MMIO(0x46160)
#define CMTG_CLK_SEL_A_MASK REG_GENMASK(31, 29)

View File

@ -1339,8 +1339,8 @@ static void ilk_lut_write(const struct intel_crtc_state *crtc_state,
{
struct intel_display *display = to_intel_display(crtc_state);
if (crtc_state->dsb_color_vblank)
intel_dsb_reg_write(crtc_state->dsb_color_vblank, reg, val);
if (crtc_state->dsb_color)
intel_dsb_reg_write(crtc_state->dsb_color, reg, val);
else
intel_de_write_fw(display, reg, val);
}
@ -1350,8 +1350,8 @@ static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state,
{
struct intel_display *display = to_intel_display(crtc_state);
if (crtc_state->dsb_color_vblank)
intel_dsb_reg_write_indexed(crtc_state->dsb_color_vblank, reg, val);
if (crtc_state->dsb_color)
intel_dsb_reg_write_indexed(crtc_state->dsb_color, reg, val);
else
intel_de_write_fw(display, reg, val);
}
@ -1389,7 +1389,7 @@ static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
for (i = 0; i < 256; i++) {
ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
i9xx_lut_8(&lut[i]));
if (crtc_state->dsb_color_vblank)
if (crtc_state->dsb_color)
ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
i9xx_lut_8(&lut[i]));
}
@ -1917,7 +1917,7 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
if (crtc_state->dsb_color_vblank)
if (crtc_state->dsb_color)
return;
display->funcs.color->load_luts(crtc_state);
@ -1965,6 +1965,25 @@ void intel_color_modeset(const struct intel_crtc_state *crtc_state)
}
}
bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state)
{
return crtc_state->dsb_color;
}
bool intel_color_uses_chained_dsb(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
return crtc_state->dsb_color && !HAS_DOUBLE_BUFFERED_LUT(display);
}
bool intel_color_uses_gosub_dsb(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
return crtc_state->dsb_color && HAS_DOUBLE_BUFFERED_LUT(display);
}
void intel_color_prepare_commit(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@ -1982,47 +2001,53 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut)
return;
crtc_state->dsb_color_vblank = intel_dsb_prepare(state, crtc, INTEL_DSB_1, 1024);
if (!crtc_state->dsb_color_vblank)
if (HAS_DOUBLE_BUFFERED_LUT(display))
crtc_state->dsb_color = intel_dsb_prepare(state, crtc, INTEL_DSB_0, 1024);
else
crtc_state->dsb_color = intel_dsb_prepare(state, crtc, INTEL_DSB_1, 1024);
if (!intel_color_uses_dsb(crtc_state))
return;
display->funcs.color->load_luts(crtc_state);
if (crtc_state->use_dsb) {
intel_vrr_send_push(crtc_state->dsb_color_vblank, crtc_state);
intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color_vblank);
intel_vrr_check_push_sent(crtc_state->dsb_color_vblank, crtc_state);
intel_dsb_interrupt(crtc_state->dsb_color_vblank);
if (crtc_state->use_dsb && intel_color_uses_chained_dsb(crtc_state)) {
intel_vrr_send_push(crtc_state->dsb_color, crtc_state);
intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color);
intel_vrr_check_push_sent(crtc_state->dsb_color, crtc_state);
intel_dsb_interrupt(crtc_state->dsb_color);
}
intel_dsb_finish(crtc_state->dsb_color_vblank);
if (intel_color_uses_gosub_dsb(crtc_state))
intel_dsb_gosub_finish(crtc_state->dsb_color);
else
intel_dsb_finish(crtc_state->dsb_color);
}
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
{
if (crtc_state->dsb_color_vblank) {
intel_dsb_cleanup(crtc_state->dsb_color_vblank);
crtc_state->dsb_color_vblank = NULL;
if (crtc_state->dsb_color) {
intel_dsb_cleanup(crtc_state->dsb_color);
crtc_state->dsb_color = NULL;
}
}
void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
{
if (crtc_state->dsb_color_vblank)
intel_dsb_wait(crtc_state->dsb_color_vblank);
}
bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state)
{
return crtc_state->dsb_color_vblank;
if (crtc_state->dsb_color)
intel_dsb_wait(crtc_state->dsb_color);
}
static bool intel_can_preload_luts(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
if (HAS_DOUBLE_BUFFERED_LUT(display))
return false;
return !old_crtc_state->post_csc_lut &&
!old_crtc_state->pre_csc_lut;
}

View File

@ -24,6 +24,8 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);
bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state);
bool intel_color_uses_chained_dsb(const struct intel_crtc_state *crtc_state);
bool intel_color_uses_gosub_dsb(const struct intel_crtc_state *crtc_state);
void intel_color_wait_commit(const struct intel_crtc_state *crtc_state);
void intel_color_commit_noarm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);

View File

@ -5,11 +5,11 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_combo_phy.h"
#include "intel_combo_phy_regs.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#define for_each_combo_phy(__display, __phy) \

View File

@ -6,7 +6,7 @@
#ifndef __INTEL_COMBO_PHY_REGS__
#define __INTEL_COMBO_PHY_REGS__
#include "i915_reg_defs.h"
#include "intel_display_reg_defs.h"
#define _ICL_COMBOPHY_A 0x162000
#define _ICL_COMBOPHY_B 0x6C000

View File

@ -208,8 +208,7 @@ enum pipe intel_connector_get_pipe(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
drm_WARN_ON(display->drm,
!drm_modeset_is_locked(&display->drm->mode_config.connection_mutex));
drm_modeset_lock_assert_held(&display->drm->mode_config.connection_mutex);
if (!connector->base.state->crtc)
return INVALID_PIPE;

View File

@ -34,8 +34,6 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_connector.h"
#include "intel_crt.h"
#include "intel_crt_regs.h"
@ -44,6 +42,7 @@
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
#include "intel_display_driver.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
#include "intel_fdi_regs.h"

View File

@ -417,10 +417,13 @@ int intel_crtc_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
return crtc_state->hw.active &&
!crtc_state->preload_luts &&
!intel_crtc_needs_modeset(crtc_state) &&
intel_crtc_needs_color_update(crtc_state) &&
(intel_crtc_needs_color_update(crtc_state) &&
!HAS_DOUBLE_BUFFERED_LUT(display)) &&
!intel_color_uses_dsb(crtc_state) &&
!crtc_state->use_dsb;
}

View File

@ -12,7 +12,6 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_atomic.h"
#include "intel_atomic_plane.h"

View File

@ -8,8 +8,8 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_alpm.h"
#include "intel_cx0_phy.h"
#include "intel_cx0_phy_regs.h"
#include "intel_ddi.h"
@ -3224,6 +3224,37 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder,
intel_cx0pll_enable(encoder, crtc_state);
}
/*
* According to HAS we need to enable MAC Transmitting LFPS in the "PHY Common
* Control 0" PIPE register in case of AUX Less ALPM is going to be used. This
* function is doing that and is called by link retrain sequence.
*/
void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
bool enable = intel_alpm_is_alpm_aux_less(enc_to_intel_dp(encoder),
crtc_state);
int i;
if (DISPLAY_VER(display) < 20)
return;
for (i = 0; i < 4; i++) {
int tx = i % 2 + 1;
u8 lane_mask = i < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1;
if (!(owned_lane_mask & lane_mask))
continue;
intel_cx0_rmw(encoder, lane_mask, PHY_CMN1_CONTROL(tx, 0),
CONTROL0_MAC_TRANSMIT_LFPS,
enable ? CONTROL0_MAC_TRANSMIT_LFPS : 0,
MB_WRITE_COMMITTED);
}
}
static u8 cx0_power_control_disable_val(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);

View File

@ -43,5 +43,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
void intel_cx0_pll_power_save_wa(struct intel_display *display);
void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
#endif /* __INTEL_CX0_PHY_H__ */

View File

@ -6,8 +6,8 @@
#ifndef __INTEL_CX0_PHY_REGS_H__
#define __INTEL_CX0_PHY_REGS_H__
#include "i915_reg_defs.h"
#include "intel_display_limits.h"
#include "intel_display_reg_defs.h"
/* DDI Buffer Control */
#define _DDI_CLK_VALFREQ_A 0x64030
@ -285,6 +285,9 @@
#define PHY_CX0_TX_CONTROL(tx, control) (0x400 + ((tx) - 1) * 0x200 + (control))
#define CONTROL2_DISABLE_SINGLE_TX REG_BIT(6)
#define PHY_CMN1_CONTROL(tx, control) (0x800 + ((tx) - 1) * 0x200 + (control))
#define CONTROL0_MAC_TRANSMIT_LFPS REG_BIT(1)
/* C20 Registers */
#define PHY_C20_WR_ADDRESS_L 0xC02
#define PHY_C20_WR_ADDRESS_H 0xC03

View File

@ -50,6 +50,7 @@
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
#include "intel_display_power.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dkl_phy.h"
#include "intel_dkl_phy_regs.h"
@ -236,7 +237,7 @@ static void intel_wait_ddi_buf_active(struct intel_encoder *encoder)
port_name(port));
}
static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
static u32 hsw_pll_to_ddi_pll_sel(const struct intel_dpll *pll)
{
switch (pll->info->id) {
case DPLL_ID_WRPLL1:
@ -260,7 +261,7 @@ static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
int clock = crtc_state->port_clock;
const enum intel_dpll_id id = pll->info->id;
@ -1561,7 +1562,7 @@ static bool _icl_ddi_is_clock_enabled(struct intel_display *display, i915_reg_t
return !(intel_de_read(display, reg) & clk_off);
}
static struct intel_shared_dpll *
static struct intel_dpll *
_icl_ddi_get_pll(struct intel_display *display, i915_reg_t reg,
u32 clk_sel_mask, u32 clk_sel_shift)
{
@ -1569,14 +1570,14 @@ _icl_ddi_get_pll(struct intel_display *display, i915_reg_t reg,
id = (intel_de_read(display, reg) & clk_sel_mask) >> clk_sel_shift;
return intel_get_shared_dpll_by_id(display, id);
return intel_get_dpll_by_id(display, id);
}
static void adls_ddi_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
enum phy phy = intel_encoder_to_phy(encoder);
if (drm_WARN_ON(display->drm, !pll))
@ -1606,7 +1607,7 @@ static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder)
ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
static struct intel_shared_dpll *adls_ddi_get_pll(struct intel_encoder *encoder)
static struct intel_dpll *adls_ddi_get_pll(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
@ -1620,7 +1621,7 @@ static void rkl_ddi_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
enum phy phy = intel_encoder_to_phy(encoder);
if (drm_WARN_ON(display->drm, !pll))
@ -1650,7 +1651,7 @@ static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder)
RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
static struct intel_shared_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder)
static struct intel_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
@ -1664,7 +1665,7 @@ static void dg1_ddi_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
enum phy phy = intel_encoder_to_phy(encoder);
if (drm_WARN_ON(display->drm, !pll))
@ -1703,7 +1704,7 @@ static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder)
DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder)
static struct intel_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
@ -1723,14 +1724,14 @@ static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder)
if (phy >= PHY_C)
id += DPLL_ID_DG1_DPLL2;
return intel_get_shared_dpll_by_id(display, id);
return intel_get_dpll_by_id(display, id);
}
static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
enum phy phy = intel_encoder_to_phy(encoder);
if (drm_WARN_ON(display->drm, !pll))
@ -1760,7 +1761,7 @@ static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder)
ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
}
struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder)
struct intel_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
@ -1774,7 +1775,7 @@ static void jsl_ddi_tc_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
enum port port = encoder->port;
if (drm_WARN_ON(display->drm, !pll))
@ -1817,7 +1818,7 @@ static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
enum tc_port tc_port = intel_encoder_to_tc(encoder);
enum port port = encoder->port;
@ -1868,7 +1869,7 @@ static bool icl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder)
return !(tmp & ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port));
}
static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder)
static struct intel_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
enum tc_port tc_port = intel_encoder_to_tc(encoder);
@ -1895,10 +1896,10 @@ static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encode
return NULL;
}
return intel_get_shared_dpll_by_id(display, id);
return intel_get_dpll_by_id(display, id);
}
static struct intel_shared_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder)
static struct intel_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder->base.dev);
enum intel_dpll_id id;
@ -1918,14 +1919,14 @@ static struct intel_shared_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder)
return NULL;
}
return intel_get_shared_dpll_by_id(display, id);
return intel_get_dpll_by_id(display, id);
}
static void skl_ddi_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
enum port port = encoder->port;
if (drm_WARN_ON(display->drm, !pll))
@ -1967,7 +1968,7 @@ static bool skl_ddi_is_clock_enabled(struct intel_encoder *encoder)
return !(intel_de_read(display, DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_OFF(port));
}
static struct intel_shared_dpll *skl_ddi_get_pll(struct intel_encoder *encoder)
static struct intel_dpll *skl_ddi_get_pll(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
@ -1986,14 +1987,14 @@ static struct intel_shared_dpll *skl_ddi_get_pll(struct intel_encoder *encoder)
id = (tmp & DPLL_CTRL2_DDI_CLK_SEL_MASK(port)) >>
DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port);
return intel_get_shared_dpll_by_id(display, id);
return intel_get_dpll_by_id(display, id);
}
void hsw_ddi_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
enum port port = encoder->port;
if (drm_WARN_ON(display->drm, !pll))
@ -2018,7 +2019,7 @@ bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder)
return intel_de_read(display, PORT_CLK_SEL(port)) != PORT_CLK_SEL_NONE;
}
static struct intel_shared_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder)
static struct intel_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
enum port port = encoder->port;
@ -2053,7 +2054,7 @@ static struct intel_shared_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder)
return NULL;
}
return intel_get_shared_dpll_by_id(display, id);
return intel_get_dpll_by_id(display, id);
}
void intel_ddi_enable_clock(struct intel_encoder *encoder,
@ -2760,7 +2761,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
* 4. Enable the port PLL.
*
* The PLL enabling itself was already done before this function by
* hsw_crtc_enable()->intel_enable_shared_dpll(). We need only
* hsw_crtc_enable()->intel_enable_dpll(). We need only
* configure the PLL to port mapping here.
*/
intel_ddi_enable_clock(encoder, crtc_state);
@ -3647,7 +3648,7 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state,
for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc,
intel_crtc_joined_pipe_mask(crtc_state))
intel_update_active_dpll(state, pipe_crtc, encoder);
intel_dpll_update_active(state, pipe_crtc, encoder);
}
/*
@ -3740,6 +3741,18 @@ static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
intel_ddi_buf_enable(encoder, intel_dp->DP);
intel_dp->DP |= DDI_BUF_CTL_ENABLE;
/*
* 6.k If AUX-Less ALPM is going to be enabled:
* i. Configure PORT_ALPM_CTL and PORT_ALPM_LFPS_CTL here
*/
intel_alpm_port_configure(intel_dp, crtc_state);
/*
* ii. Enable MAC Transmits LFPS in the "PHY Common Control 0" PIPE
* register
*/
intel_lnl_mac_transmit_lfps(encoder, crtc_state);
}
static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
@ -4184,7 +4197,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder,
void intel_ddi_get_clock(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct intel_shared_dpll *pll)
struct intel_dpll *pll)
{
struct intel_display *display = to_intel_display(encoder);
enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT;
@ -4200,7 +4213,7 @@ void intel_ddi_get_clock(struct intel_encoder *encoder,
icl_set_active_port_dpll(crtc_state, port_dpll_id);
crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->shared_dpll,
crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->intel_dpll,
&crtc_state->dpll_hw_state);
}
@ -4254,7 +4267,7 @@ static void icl_ddi_combo_get_config(struct intel_encoder *encoder,
intel_ddi_get_config(encoder, crtc_state);
}
static bool icl_ddi_tc_pll_is_tbt(const struct intel_shared_dpll *pll)
static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll)
{
return pll->info->id == DPLL_ID_ICL_TBTPLL;
}
@ -4264,7 +4277,7 @@ icl_ddi_tc_port_pll_type(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
const struct intel_dpll *pll = crtc_state->intel_dpll;
if (drm_WARN_ON(display->drm, !pll))
return ICL_PORT_DPLL_DEFAULT;
@ -4287,7 +4300,7 @@ intel_ddi_port_pll_type(struct intel_encoder *encoder,
static void icl_ddi_tc_get_clock(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct intel_shared_dpll *pll)
struct intel_dpll *pll)
{
struct intel_display *display = to_intel_display(encoder);
enum icl_port_dpll_id port_dpll_id;
@ -4310,10 +4323,10 @@ static void icl_ddi_tc_get_clock(struct intel_encoder *encoder,
icl_set_active_port_dpll(crtc_state, port_dpll_id);
if (icl_ddi_tc_pll_is_tbt(crtc_state->shared_dpll))
if (icl_ddi_tc_pll_is_tbt(crtc_state->intel_dpll))
crtc_state->port_clock = icl_calc_tbt_pll_link(display, encoder->port);
else
crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->shared_dpll,
crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->intel_dpll,
&crtc_state->dpll_hw_state);
}

View File

@ -16,9 +16,9 @@ struct intel_crtc;
struct intel_crtc_state;
struct intel_display;
struct intel_dp;
struct intel_dpll;
struct intel_dpll_hw_state;
struct intel_encoder;
struct intel_shared_dpll;
enum pipe;
enum port;
enum transcoder;
@ -40,7 +40,7 @@ void intel_ddi_enable_clock(struct intel_encoder *encoder,
void intel_ddi_disable_clock(struct intel_encoder *encoder);
void intel_ddi_get_clock(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct intel_shared_dpll *pll);
struct intel_dpll *pll);
void hsw_ddi_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void hsw_ddi_disable_clock(struct intel_encoder *encoder);
@ -50,7 +50,7 @@ intel_ddi_port_pll_type(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void hsw_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state);
struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder);
struct intel_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder);
void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_wait_ddi_buf_idle(struct intel_display *display, enum port port);

View File

@ -107,10 +107,10 @@ intel_de_rmw(struct intel_display *display, i915_reg_t reg, u32 clear, u32 set)
static inline int
__intel_de_wait_for_register_nowl(struct intel_display *display,
i915_reg_t reg,
u32 mask, u32 value, unsigned int timeout)
u32 mask, u32 value, unsigned int timeout_ms)
{
return intel_wait_for_register(__to_uncore(display), reg, mask,
value, timeout);
value, timeout_ms);
}
static inline int
@ -125,14 +125,14 @@ __intel_de_wait_for_register_atomic_nowl(struct intel_display *display,
static inline int
intel_de_wait(struct intel_display *display, i915_reg_t reg,
u32 mask, u32 value, unsigned int timeout)
u32 mask, u32 value, unsigned int timeout_ms)
{
int ret;
intel_dmc_wl_get(display, reg);
ret = __intel_de_wait_for_register_nowl(display, reg, mask, value,
timeout);
timeout_ms);
intel_dmc_wl_put(display, reg);
@ -141,14 +141,14 @@ intel_de_wait(struct intel_display *display, i915_reg_t reg,
static inline int
intel_de_wait_fw(struct intel_display *display, i915_reg_t reg,
u32 mask, u32 value, unsigned int timeout)
u32 mask, u32 value, unsigned int timeout_ms, u32 *out_value)
{
int ret;
intel_dmc_wl_get(display, reg);
ret = intel_wait_for_register_fw(__to_uncore(display), reg, mask,
value, timeout);
value, timeout_ms, out_value);
intel_dmc_wl_put(display, reg);
@ -176,16 +176,16 @@ intel_de_wait_custom(struct intel_display *display, i915_reg_t reg,
static inline int
intel_de_wait_for_set(struct intel_display *display, i915_reg_t reg,
u32 mask, unsigned int timeout)
u32 mask, unsigned int timeout_ms)
{
return intel_de_wait(display, reg, mask, mask, timeout);
return intel_de_wait(display, reg, mask, mask, timeout_ms);
}
static inline int
intel_de_wait_for_clear(struct intel_display *display, i915_reg_t reg,
u32 mask, unsigned int timeout)
u32 mask, unsigned int timeout_ms)
{
return intel_de_wait(display, reg, mask, 0, timeout);
return intel_de_wait(display, reg, mask, 0, timeout_ms);
}
/*

View File

@ -67,13 +67,14 @@
#include "intel_crt.h"
#include "intel_crtc.h"
#include "intel_crtc_state_dump.h"
#include "intel_cursor.h"
#include "intel_cursor_regs.h"
#include "intel_cx0_phy.h"
#include "intel_cursor.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_driver.h"
#include "intel_display_power.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dmc.h"
@ -105,7 +106,6 @@
#include "intel_panel.h"
#include "intel_pch_display.h"
#include "intel_pch_refclk.h"
#include "intel_pcode.h"
#include "intel_pfit.h"
#include "intel_pipe_crc.h"
#include "intel_plane_initial.h"
@ -140,46 +140,47 @@ static void bdw_set_pipe_misc(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);
/* returns HPLL frequency in kHz */
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
int vlv_get_hpll_vco(struct drm_device *drm)
{
int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
/* Obtain SKU information */
hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) &
hpll_freq = vlv_cck_read(drm, CCK_FUSE_REG) &
CCK_FUSE_HPLL_FREQ_MASK;
return vco_freq[hpll_freq] * 1000;
}
int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
int vlv_get_cck_clock(struct drm_device *drm,
const char *name, u32 reg, int ref_freq)
{
u32 val;
int divider;
val = vlv_cck_read(dev_priv, reg);
val = vlv_cck_read(drm, reg);
divider = val & CCK_FREQUENCY_VALUES;
drm_WARN(&dev_priv->drm, (val & CCK_FREQUENCY_STATUS) !=
drm_WARN(drm, (val & CCK_FREQUENCY_STATUS) !=
(divider << CCK_FREQUENCY_STATUS_SHIFT),
"%s change in progress\n", name);
return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1);
}
int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
int vlv_get_cck_clock_hpll(struct drm_device *drm,
const char *name, u32 reg)
{
struct drm_i915_private *dev_priv = to_i915(drm);
int hpll;
vlv_cck_get(dev_priv);
vlv_cck_get(drm);
if (dev_priv->hpll_freq == 0)
dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv);
dev_priv->hpll_freq = vlv_get_hpll_vco(drm);
hpll = vlv_get_cck_clock(dev_priv, name, reg, dev_priv->hpll_freq);
hpll = vlv_get_cck_clock(drm, name, reg, dev_priv->hpll_freq);
vlv_cck_put(dev_priv);
vlv_cck_put(drm);
return hpll;
}
@ -191,7 +192,7 @@ void intel_update_czclk(struct intel_display *display)
if (!display->platform.valleyview && !display->platform.cherryview)
return;
dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk",
dev_priv->czclk_freq = vlv_get_cck_clock_hpll(display->drm, "czclk",
CCK_CZ_CLOCK_CONTROL);
drm_dbg_kms(display->drm, "CZ clock rate: %d kHz\n", dev_priv->czclk_freq);
@ -1325,7 +1326,7 @@ static void intel_encoders_update_prepare(struct intel_atomic_state *state)
if (intel_crtc_needs_modeset(new_crtc_state))
continue;
new_crtc_state->shared_dpll = old_crtc_state->shared_dpll;
new_crtc_state->intel_dpll = old_crtc_state->intel_dpll;
new_crtc_state->dpll_hw_state = old_crtc_state->dpll_hw_state;
}
}
@ -1663,8 +1664,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
intel_encoders_pre_pll_enable(state, crtc);
if (new_crtc_state->shared_dpll)
intel_enable_shared_dpll(new_crtc_state);
if (new_crtc_state->intel_dpll)
intel_dpll_enable(new_crtc_state);
intel_encoders_pre_enable(state, crtc);
@ -1793,7 +1794,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
intel_encoders_disable(state, crtc);
intel_encoders_post_disable(state, crtc);
intel_disable_shared_dpll(old_crtc_state);
intel_dpll_disable(old_crtc_state);
intel_encoders_post_pll_disable(state, crtc);
@ -1959,7 +1960,7 @@ static void get_crtc_power_domains(struct intel_crtc_state *crtc_state,
if (HAS_DDI(display) && crtc_state->has_audio)
set_bit(POWER_DOMAIN_AUDIO_MMIO, mask->bits);
if (crtc_state->shared_dpll)
if (crtc_state->intel_dpll)
set_bit(POWER_DOMAIN_DISPLAY_CORE, mask->bits);
if (crtc_state->dsc.compression_enable)
@ -4225,7 +4226,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
crtc_state->update_wm_post = true;
if (intel_crtc_needs_modeset(crtc_state)) {
ret = intel_dpll_crtc_get_shared_dpll(state, crtc);
ret = intel_dpll_crtc_get_dpll(state, crtc);
if (ret)
return ret;
}
@ -4318,6 +4319,22 @@ compute_sink_pipe_bpp(const struct drm_connector_state *conn_state,
return 0;
}
int intel_display_min_pipe_bpp(void)
{
return 6 * 3;
}
int intel_display_max_pipe_bpp(struct intel_display *display)
{
if (display->platform.g4x || display->platform.valleyview ||
display->platform.cherryview)
return 10*3;
else if (DISPLAY_VER(display) >= 5)
return 12*3;
else
return 8*3;
}
static int
compute_baseline_pipe_bpp(struct intel_atomic_state *state,
struct intel_crtc *crtc)
@ -4327,17 +4344,9 @@ compute_baseline_pipe_bpp(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
struct drm_connector *connector;
struct drm_connector_state *connector_state;
int bpp, i;
int i;
if (display->platform.g4x || display->platform.valleyview ||
display->platform.cherryview)
bpp = 10*3;
else if (DISPLAY_VER(display) >= 5)
bpp = 12*3;
else
bpp = 8*3;
crtc_state->pipe_bpp = bpp;
crtc_state->pipe_bpp = intel_display_max_pipe_bpp(display);
/* Clamp display bpp to connector max bpp */
for_each_new_connector_in_state(&state->base, connector, connector_state, i) {
@ -4501,7 +4510,7 @@ copy_joiner_crtc_state_modeset(struct intel_atomic_state *state,
/* preserve some things from the slave's original crtc state */
saved_state->uapi = secondary_crtc_state->uapi;
saved_state->scaler_state = secondary_crtc_state->scaler_state;
saved_state->shared_dpll = secondary_crtc_state->shared_dpll;
saved_state->intel_dpll = secondary_crtc_state->intel_dpll;
saved_state->crc_enabled = secondary_crtc_state->crc_enabled;
intel_crtc_free_hw_state(secondary_crtc_state);
@ -4564,7 +4573,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
saved_state->uapi = crtc_state->uapi;
saved_state->inherited = crtc_state->inherited;
saved_state->scaler_state = crtc_state->scaler_state;
saved_state->shared_dpll = crtc_state->shared_dpll;
saved_state->intel_dpll = crtc_state->intel_dpll;
saved_state->dpll_hw_state = crtc_state->dpll_hw_state;
memcpy(saved_state->icl_port_dplls, crtc_state->icl_port_dplls,
sizeof(saved_state->icl_port_dplls));
@ -5318,7 +5327,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_BOOL(double_wide);
if (display->dpll.mgr)
PIPE_CONF_CHECK_P(shared_dpll);
PIPE_CONF_CHECK_P(intel_dpll);
/* FIXME convert everything over the dpll_mgr */
if (display->dpll.mgr || HAS_GMCH(display))
@ -6428,7 +6437,7 @@ int intel_atomic_check(struct drm_device *dev,
any_ms = true;
intel_release_shared_dplls(state, crtc);
intel_dpll_release(state, crtc);
}
if (any_ms && !check_digital_port_conflicts(state)) {
@ -6630,6 +6639,7 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state,
struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
bool modeset = intel_crtc_needs_modeset(new_crtc_state);
drm_WARN_ON(display->drm, new_crtc_state->use_dsb);
@ -6638,10 +6648,15 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state,
* get a catastrophic underrun even if the two operations
* end up happening in two different frames.
*/
if (DISPLAY_VER(display) >= 9 &&
!intel_crtc_needs_modeset(new_crtc_state))
if (DISPLAY_VER(display) >= 9 && !modeset)
skl_detach_scalers(NULL, new_crtc_state);
if (!modeset &&
intel_crtc_needs_color_update(new_crtc_state) &&
!intel_color_uses_dsb(new_crtc_state) &&
HAS_DOUBLE_BUFFERED_LUT(display))
intel_color_load_luts(new_crtc_state);
if (intel_crtc_vrr_enabling(state, crtc))
intel_vrr_enable(new_crtc_state);
}
@ -6733,13 +6748,13 @@ static void intel_update_crtc(struct intel_atomic_state *state,
if (new_crtc_state->use_dsb) {
intel_crtc_prepare_vblank_event(new_crtc_state, &crtc->dsb_event);
intel_dsb_commit(new_crtc_state->dsb_commit, false);
intel_dsb_commit(new_crtc_state->dsb_commit);
} else {
/* Perform vblank evasion around commit operation */
intel_pipe_update_start(state, crtc);
if (new_crtc_state->dsb_commit)
intel_dsb_commit(new_crtc_state->dsb_commit, false);
intel_dsb_commit(new_crtc_state->dsb_commit);
commit_pipe_pre_planes(state, crtc);
@ -7184,7 +7199,7 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
if (!new_crtc_state->use_dsb && !new_crtc_state->dsb_color_vblank)
if (!new_crtc_state->use_dsb && !new_crtc_state->dsb_color)
return;
/*
@ -7230,20 +7245,24 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
if (DISPLAY_VER(display) >= 9)
skl_detach_scalers(new_crtc_state->dsb_commit,
new_crtc_state);
if (!new_crtc_state->dsb_color_vblank) {
intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1);
intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state);
intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit);
intel_vrr_check_push_sent(new_crtc_state->dsb_commit, new_crtc_state);
intel_dsb_interrupt(new_crtc_state->dsb_commit);
}
}
if (new_crtc_state->dsb_color_vblank)
if (intel_color_uses_chained_dsb(new_crtc_state))
intel_dsb_chain(state, new_crtc_state->dsb_commit,
new_crtc_state->dsb_color_vblank, true);
new_crtc_state->dsb_color, true);
else if (intel_color_uses_gosub_dsb(new_crtc_state))
intel_dsb_gosub(new_crtc_state->dsb_commit,
new_crtc_state->dsb_color);
if (new_crtc_state->use_dsb && !intel_color_uses_chained_dsb(new_crtc_state)) {
intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1);
intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state);
intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit);
intel_vrr_check_push_sent(new_crtc_state->dsb_commit,
new_crtc_state);
intel_dsb_interrupt(new_crtc_state->dsb_commit);
}
intel_dsb_finish(new_crtc_state->dsb_commit);
}
@ -7432,7 +7451,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
*
* FIXME get rid of this funny new->old swapping
*/
old_crtc_state->dsb_color_vblank = fetch_and_zero(&new_crtc_state->dsb_color_vblank);
old_crtc_state->dsb_color = fetch_and_zero(&new_crtc_state->dsb_color);
old_crtc_state->dsb_commit = fetch_and_zero(&new_crtc_state->dsb_commit);
}
@ -7525,7 +7544,7 @@ static int intel_atomic_swap_state(struct intel_atomic_state *state)
intel_atomic_swap_global_state(state);
intel_shared_dpll_swap_state(state);
intel_dpll_swap_state(state);
intel_atomic_track_fbs(state);

View File

@ -30,38 +30,21 @@
#include "i915_reg_defs.h"
#include "intel_display_limits.h"
enum drm_scaling_filter;
struct dpll;
struct drm_atomic_state;
struct drm_connector;
struct drm_device;
struct drm_display_mode;
struct drm_encoder;
struct drm_file;
struct drm_format_info;
struct drm_framebuffer;
struct drm_i915_private;
struct drm_mode_fb_cmd2;
struct drm_modeset_acquire_ctx;
struct drm_plane;
struct drm_plane_state;
struct i915_address_space;
struct i915_gtt_view;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_digital_port;
struct intel_display;
struct intel_dp;
struct intel_encoder;
struct intel_initial_plane_config;
struct intel_link_m_n;
struct intel_plane;
struct intel_plane_state;
struct intel_power_domain_mask;
struct pci_dev;
struct work_struct;
#define pipe_name(p) ((p) + 'A')
@ -452,10 +435,10 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state);
void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state);
void i830_enable_pipe(struct intel_display *display, enum pipe pipe);
void i830_disable_pipe(struct intel_display *display, enum pipe pipe);
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
int vlv_get_hpll_vco(struct drm_device *drm);
int vlv_get_cck_clock(struct drm_device *drm,
const char *name, u32 reg, int ref_freq);
int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
int vlv_get_cck_clock_hpll(struct drm_device *drm,
const char *name, u32 reg);
bool intel_has_pending_fb_unpin(struct intel_display *display);
void intel_encoder_destroy(struct drm_encoder *encoder);
@ -524,6 +507,9 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
struct intel_crtc *crtc);
int intel_display_min_pipe_bpp(void);
int intel_display_max_pipe_bpp(struct intel_display *display);
/* modesetting */
int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
const char *reason, u8 pipe_mask);

View File

@ -2,10 +2,11 @@
/* Copyright © 2024 Intel Corporation */
#include "i915_drv.h"
#include "intel_display_conversion.h"
struct intel_display *__i915_to_display(struct drm_i915_private *i915)
{
return &i915->display;
return i915->display;
}
struct intel_display *__drm_to_display(struct drm_device *drm)

View File

@ -42,7 +42,7 @@ struct intel_color_funcs;
struct intel_crtc;
struct intel_crtc_state;
struct intel_dmc;
struct intel_dpll_funcs;
struct intel_dpll_global_funcs;
struct intel_dpll_mgr;
struct intel_fbdev;
struct intel_fdi_funcs;
@ -122,11 +122,11 @@ struct intel_audio {
* intel_{prepare,enable,disable}_shared_dpll. Must be global rather than per
* dpll, because on some platforms plls share registers.
*/
struct intel_dpll {
struct intel_dpll_global {
struct mutex lock;
int num_shared_dpll;
struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
int num_dpll;
struct intel_dpll dplls[I915_NUM_PLLS];
const struct intel_dpll_mgr *mgr;
struct {
@ -300,7 +300,7 @@ struct intel_display {
const struct intel_cdclk_funcs *cdclk;
/* Display pll funcs */
const struct intel_dpll_funcs *dpll;
const struct intel_dpll_global_funcs *dpll;
/* irq display functions */
const struct intel_hotplug_funcs *hotplug;
@ -538,6 +538,11 @@ struct intel_display {
u32 block_time_us;
} sagv;
struct {
/* LPT/WPT IOSF sideband protection */
struct mutex lock;
} sbi;
struct {
/*
* DG2: Mask of PHYs that were not calibrated by the firmware
@ -570,7 +575,7 @@ struct intel_display {
/* Grouping using named structs. Keep sorted. */
struct drm_dp_tunnel_mgr *dp_tunnel_mgr;
struct intel_audio audio;
struct intel_dpll dpll;
struct intel_dpll_global dpll;
struct intel_fbc *fbc[I915_MAX_FBCS];
struct intel_frontbuffer_tracking fb_tracking;
struct intel_hotplug hotplug;

View File

@ -4,6 +4,7 @@
*/
#include <linux/debugfs.h>
#include <linux/string_choices.h>
#include <linux/string_helpers.h>
#include <drm/drm_debugfs.h>
@ -13,7 +14,6 @@
#include <drm/drm_fourcc.h>
#include "hsw_ips.h"
#include "i915_irq.h"
#include "i915_reg.h"
#include "i9xx_wm_regs.h"
#include "intel_alpm.h"
@ -25,6 +25,7 @@
#include "intel_display_debugfs_params.h"
#include "intel_display_power.h"
#include "intel_display_power_well.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dmc.h"
@ -39,6 +40,7 @@
#include "intel_hdcp.h"
#include "intel_hdmi.h"
#include "intel_hotplug.h"
#include "intel_link_bw.h"
#include "intel_panel.h"
#include "intel_pps.h"
#include "intel_psr.h"
@ -618,7 +620,7 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
{
struct intel_display *display = node_to_intel_display(m->private);
struct drm_printer p = drm_seq_file_printer(m);
struct intel_shared_dpll *pll;
struct intel_dpll *pll;
int i;
drm_modeset_lock_all(display->drm);
@ -627,7 +629,7 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
display->dpll.ref_clks.nssc,
display->dpll.ref_clks.ssc);
for_each_shared_dpll(display, pll, i) {
for_each_dpll(display, pll, i) {
drm_printf(&p, "DPLL%i: %s, id: %i\n", pll->index,
pll->info->name, pll->info->id);
drm_printf(&p, " pipe_mask: 0x%x, active: 0x%x, on: %s\n",
@ -972,7 +974,7 @@ static ssize_t i915_dsc_fec_support_write(struct file *file,
return ret;
drm_dbg(display->drm, "Got %s for DSC Enable\n",
(dsc_enable) ? "true" : "false");
str_true_false(dsc_enable));
intel_dp->force_dsc_en = dsc_enable;
*offp += len;
@ -1183,7 +1185,7 @@ static ssize_t i915_dsc_fractional_bpp_write(struct file *file,
return ret;
drm_dbg(display->drm, "Got %s for DSC Fractional BPP Enable\n",
(dsc_fractional_bpp_enable) ? "true" : "false");
str_true_false(dsc_fractional_bpp_enable));
intel_dp->force_dsc_fractional_bpp_en = dsc_fractional_bpp_enable;
*offp += len;
@ -1325,6 +1327,7 @@ void intel_connector_debugfs_add(struct intel_connector *connector)
intel_psr_connector_debugfs_add(connector);
intel_alpm_lobf_debugfs_add(connector);
intel_dp_link_training_debugfs_add(connector);
intel_link_bw_connector_debugfs_add(connector);
if (DISPLAY_VER(display) >= 11 &&
((connector_type == DRM_MODE_CONNECTOR_DisplayPort && !connector->mst.dp) ||

View File

@ -18,6 +18,7 @@
#include "intel_display_params.h"
#include "intel_display_power.h"
#include "intel_display_reg_defs.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_fbc.h"
#include "intel_step.h"
@ -1621,13 +1622,17 @@ static void display_platforms_or(struct intel_display_platforms *dst,
struct intel_display *intel_display_device_probe(struct pci_dev *pdev)
{
struct intel_display *display = to_intel_display(pdev);
struct intel_display *display;
const struct intel_display_device_info *info;
struct intel_display_ip_ver ip_ver = {};
const struct platform_desc *desc;
const struct subplatform_desc *subdesc;
enum intel_step step;
display = kzalloc(sizeof(*display), GFP_KERNEL);
if (!display)
return ERR_PTR(-ENOMEM);
/* Add drm device backpointer as early as possible. */
display->drm = pci_get_drvdata(pdev);
@ -1708,7 +1713,11 @@ struct intel_display *intel_display_device_probe(struct pci_dev *pdev)
void intel_display_device_remove(struct intel_display *display)
{
if (!display)
return;
intel_display_params_free(&display->params);
kfree(display);
}
static void __intel_display_device_info_runtime_init(struct intel_display *display)

View File

@ -157,6 +157,7 @@ struct intel_display_platforms {
#define HAS_DMC(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dmc)
#define HAS_DMC_WAKELOCK(__display) (DISPLAY_VER(__display) >= 20)
#define HAS_DOUBLE_BUFFERED_M_N(__display) (DISPLAY_VER(__display) >= 9 || (__display)->platform.broadwell)
#define HAS_DOUBLE_BUFFERED_LUT(__display) (DISPLAY_VER(__display) >= 30)
#define HAS_DOUBLE_WIDE(__display) (DISPLAY_VER(__display) < 4)
#define HAS_DP20(__display) ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14)
#define HAS_DPT(__display) (DISPLAY_VER(__display) >= 13)
@ -172,6 +173,7 @@ struct intel_display_platforms {
#define HAS_GMBUS_BURST_READ(__display) (DISPLAY_VER(__display) >= 10 || (__display)->platform.kabylake)
#define HAS_GMBUS_IRQ(__display) (DISPLAY_VER(__display) >= 4)
#define HAS_GMCH(__display) (DISPLAY_INFO(__display)->has_gmch)
#define HAS_FDI(__display) (IS_DISPLAY_VER((__display), 5, 8) && !HAS_GMCH(__display))
#define HAS_HOTPLUG(__display) (DISPLAY_INFO(__display)->has_hotplug)
#define HAS_HW_SAGV_WM(__display) (DISPLAY_VER(__display) >= 13 && !(__display)->platform.dgfx)
#define HAS_IPC(__display) (DISPLAY_INFO(__display)->has_ipc)
@ -181,6 +183,7 @@ struct intel_display_platforms {
#define HAS_MBUS_JOINING(__display) ((__display)->platform.alderlake_p || DISPLAY_VER(__display) >= 14)
#define HAS_MSO(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_OVERLAY(__display) (DISPLAY_INFO(__display)->has_overlay)
#define HAS_PIPEDMC(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_PSR(__display) (DISPLAY_INFO(__display)->has_psr)
#define HAS_PSR_HW_TRACKING(__display) (DISPLAY_INFO(__display)->has_psr_hw_tracking)
#define HAS_PSR2_SEL_FETCH(__display) (DISPLAY_VER(__display) >= 12)

View File

@ -27,6 +27,7 @@
#include "intel_cdclk.h"
#include "intel_color.h"
#include "intel_crtc.h"
#include "intel_display_core.h"
#include "intel_display_debugfs.h"
#include "intel_display_driver.h"
#include "intel_display_irq.h"
@ -243,10 +244,16 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
intel_dmc_init(display);
display->hotplug.dp_wq = alloc_ordered_workqueue("intel-dp", 0);
if (!display->hotplug.dp_wq) {
ret = -ENOMEM;
goto cleanup_vga_client_pw_domain_dmc;
}
display->wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
if (!display->wq.modeset) {
ret = -ENOMEM;
goto cleanup_vga_client_pw_domain_dmc;
goto cleanup_wq_dp;
}
display->wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
@ -296,6 +303,8 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
destroy_workqueue(display->wq.flip);
cleanup_wq_modeset:
destroy_workqueue(display->wq.modeset);
cleanup_wq_dp:
destroy_workqueue(display->hotplug.dp_wq);
cleanup_vga_client_pw_domain_dmc:
intel_dmc_fini(display);
intel_power_domains_driver_remove(display);
@ -466,7 +475,7 @@ int intel_display_driver_probe_nogem(struct intel_display *display)
}
intel_plane_possible_crtcs_init(display);
intel_shared_dpll_init(display);
intel_dpll_init(display);
intel_fdi_pll_freq_update(display);
intel_update_czclk(display);
@ -631,6 +640,7 @@ void intel_display_driver_remove_noirq(struct intel_display *display)
intel_gmbus_teardown(display);
destroy_workqueue(display->hotplug.dp_wq);
destroy_workqueue(display->wq.flip);
destroy_workqueue(display->wq.modeset);
destroy_workqueue(display->wq.cleanup);

View File

@ -13,10 +13,12 @@
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_rps.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_dmc.h"
#include "intel_dmc_wl.h"
#include "intel_dp_aux.h"
#include "intel_dsb.h"
@ -1016,7 +1018,15 @@ static u32 gen8_de_port_aux_mask(struct intel_display *display)
static u32 gen8_de_pipe_fault_mask(struct intel_display *display)
{
if (DISPLAY_VER(display) >= 14)
if (DISPLAY_VER(display) >= 20)
return MTL_PLANE_ATS_FAULT |
GEN9_PIPE_CURSOR_FAULT |
GEN11_PIPE_PLANE5_FAULT |
GEN9_PIPE_PLANE4_FAULT |
GEN9_PIPE_PLANE3_FAULT |
GEN9_PIPE_PLANE2_FAULT |
GEN9_PIPE_PLANE1_FAULT;
else if (DISPLAY_VER(display) >= 14)
return MTL_PIPEDMC_ATS_FAULT |
MTL_PLANE_ATS_FAULT |
GEN12_PIPEDMC_FAULT |
@ -1418,7 +1428,8 @@ void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl)
iir = intel_de_read(display, GEN8_DE_PIPE_IIR(pipe));
if (!iir) {
drm_err_ratelimited(display->drm,
"The master control interrupt lied (DE PIPE)!\n");
"The master control interrupt lied (DE PIPE %c)!\n",
pipe_name(pipe));
continue;
}
@ -1441,6 +1452,9 @@ void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl)
intel_dsb_irq_handler(display, pipe, INTEL_DSB_2);
}
if (HAS_PIPEDMC(display) && iir & GEN12_PIPEDMC_INTERRUPT)
intel_pipedmc_irq_handler(display, pipe);
if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
hsw_pipe_crc_irq_handler(display, pipe);
@ -2258,6 +2272,10 @@ void gen8_de_irq_postinstall(struct intel_display *display)
GEN12_DSB_INT(INTEL_DSB_1) |
GEN12_DSB_INT(INTEL_DSB_2);
/* TODO figure PIPEDMC interrupts for pre-LNL */
if (DISPLAY_VER(display) >= 20)
de_pipe_masked |= GEN12_PIPEDMC_INTERRUPT;
de_pipe_enables = de_pipe_masked |
GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN |
gen8_de_pipe_flip_done_mask(display);

View File

@ -5,6 +5,8 @@
#include <linux/string_helpers.h>
#include "soc/intel_dram.h"
#include "i915_drv.h"
#include "i915_irq.h"
#include "i915_reg.h"
@ -16,6 +18,7 @@
#include "intel_display_power.h"
#include "intel_display_power_map.h"
#include "intel_display_power_well.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dmc.h"
@ -1604,9 +1607,7 @@ static const struct buddy_page_mask wa_1409767108_buddy_page_masks[] = {
static void tgl_bw_buddy_init(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum intel_dram_type type = dev_priv->dram_info.type;
u8 num_channels = dev_priv->dram_info.num_channels;
const struct dram_info *dram_info = intel_dram_info(display->drm);
const struct buddy_page_mask *table;
unsigned long abox_mask = DISPLAY_INFO(display)->abox_mask;
int config, i;
@ -1623,8 +1624,8 @@ static void tgl_bw_buddy_init(struct intel_display *display)
table = tgl_buddy_page_masks;
for (config = 0; table[config].page_mask != 0; config++)
if (table[config].num_channels == num_channels &&
table[config].type == type)
if (table[config].num_channels == dram_info->num_channels &&
table[config].type == dram_info->type)
break;
if (table[config].page_mask == 0) {
@ -1883,12 +1884,11 @@ static void vlv_cmnlane_wa(struct intel_display *display)
static bool vlv_punit_is_power_gated(struct intel_display *display, u32 reg0)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
bool ret;
vlv_punit_get(dev_priv);
ret = (vlv_punit_read(dev_priv, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE;
vlv_punit_put(dev_priv);
vlv_punit_get(display->drm);
ret = (vlv_punit_read(display->drm, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE;
vlv_punit_put(display->drm);
return ret;
}

View File

@ -5,12 +5,12 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_display_core.h"
#include "intel_display_power_map.h"
#include "intel_display_power_well.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "vlv_sideband_reg.h"
#include "vlv_iosf_sb_reg.h"
#define __LIST_INLINE_ELEMS(__elem_type, ...) \
((__elem_type[]) { __VA_ARGS__ })

View File

@ -13,6 +13,7 @@
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_power_well.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dkl_phy.h"
@ -30,8 +31,8 @@
#include "intel_vga.h"
#include "skl_watermark.h"
#include "vlv_dpio_phy_regs.h"
#include "vlv_iosf_sb_reg.h"
#include "vlv_sideband.h"
#include "vlv_sideband_reg.h"
struct i915_power_well_regs {
i915_reg_t bios;
@ -809,7 +810,6 @@ static void tgl_disable_dc3co(struct intel_display *display)
static void assert_can_enable_dc5(struct intel_display *display)
{
struct drm_i915_private __maybe_unused *dev_priv = to_i915(display->drm);
enum i915_power_well_id high_pg;
/* Power wells at this level and above must be disabled for DC5 entry */
@ -1102,7 +1102,6 @@ static void i830_pipes_power_well_sync_hw(struct intel_display *display,
static void vlv_set_power_well(struct intel_display *display,
struct i915_power_well *power_well, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
int pw_idx = i915_power_well_instance(power_well)->vlv.idx;
u32 mask;
u32 state;
@ -1112,29 +1111,29 @@ static void vlv_set_power_well(struct intel_display *display,
state = enable ? PUNIT_PWRGT_PWR_ON(pw_idx) :
PUNIT_PWRGT_PWR_GATE(pw_idx);
vlv_punit_get(dev_priv);
vlv_punit_get(display->drm);
#define COND \
((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
((vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS) & mask) == state)
if (COND)
goto out;
ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL);
ctrl &= ~mask;
ctrl |= state;
vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
vlv_punit_write(display->drm, PUNIT_REG_PWRGT_CTRL, ctrl);
if (wait_for(COND, 100))
drm_err(display->drm,
"timeout setting power well state %08x (%08x)\n",
state,
vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL));
#undef COND
out:
vlv_punit_put(dev_priv);
vlv_punit_put(display->drm);
}
static void vlv_power_well_enable(struct intel_display *display,
@ -1152,7 +1151,6 @@ static void vlv_power_well_disable(struct intel_display *display,
static bool vlv_power_well_enabled(struct intel_display *display,
struct i915_power_well *power_well)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
int pw_idx = i915_power_well_instance(power_well)->vlv.idx;
bool enabled = false;
u32 mask;
@ -1162,9 +1160,9 @@ static bool vlv_power_well_enabled(struct intel_display *display,
mask = PUNIT_PWRGT_MASK(pw_idx);
ctrl = PUNIT_PWRGT_PWR_ON(pw_idx);
vlv_punit_get(dev_priv);
vlv_punit_get(display->drm);
state = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask;
state = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS) & mask;
/*
* We only ever set the power-on and power-gate states, anything
* else is unexpected.
@ -1178,10 +1176,10 @@ static bool vlv_power_well_enabled(struct intel_display *display,
* A transient state at this point would mean some unexpected party
* is poking at the power controls too.
*/
ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL) & mask;
ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL) & mask;
drm_WARN_ON(display->drm, ctrl != state);
vlv_punit_put(dev_priv);
vlv_punit_put(display->drm);
return enabled;
}
@ -1437,7 +1435,6 @@ static void assert_chv_phy_status(struct intel_display *display)
static void chv_dpio_cmn_power_well_enable(struct intel_display *display,
struct i915_power_well *power_well)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum i915_power_well_id id = i915_power_well_instance(power_well)->id;
enum dpio_phy phy;
u32 tmp;
@ -1461,30 +1458,30 @@ static void chv_dpio_cmn_power_well_enable(struct intel_display *display,
drm_err(display->drm, "Display PHY %d is not power up\n",
phy);
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* Enable dynamic power down */
tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW28);
tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW28);
tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN |
DPIO_SUS_CLK_CONFIG_GATE_CLKREQ;
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW28, tmp);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW28, tmp);
if (id == VLV_DISP_PW_DPIO_CMN_BC) {
tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW6_CH1);
tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW6_CH1);
tmp |= DPIO_DYNPWRDOWNEN_CH1;
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW6_CH1, tmp);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW6_CH1, tmp);
} else {
/*
* Force the non-existing CL2 off. BXT does this
* too, so maybe it saves some power even though
* CL2 doesn't exist?
*/
tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW30);
tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW30);
tmp |= DPIO_CL2_LDOFUSE_PWRENB;
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW30, tmp);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW30, tmp);
}
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
display->power.chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
intel_de_write(display, DISPLAY_PHY_CONTROL,
@ -1535,7 +1532,6 @@ static void chv_dpio_cmn_power_well_disable(struct intel_display *display,
static void assert_chv_phy_powergate(struct intel_display *display, enum dpio_phy phy,
enum dpio_channel ch, bool override, unsigned int mask)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 reg, val, expected, actual;
/*
@ -1553,9 +1549,9 @@ static void assert_chv_phy_powergate(struct intel_display *display, enum dpio_ph
else
reg = CHV_CMN_DW6_CH1;
vlv_dpio_get(dev_priv);
val = vlv_dpio_read(dev_priv, phy, reg);
vlv_dpio_put(dev_priv);
vlv_dpio_get(display->drm);
val = vlv_dpio_read(display->drm, phy, reg);
vlv_dpio_put(display->drm);
/*
* This assumes !override is only used when the port is disabled.
@ -1665,14 +1661,13 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
static bool chv_pipe_power_well_enabled(struct intel_display *display,
struct i915_power_well *power_well)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum pipe pipe = PIPE_A;
bool enabled;
u32 state, ctrl;
vlv_punit_get(dev_priv);
vlv_punit_get(display->drm);
state = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe);
state = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe);
/*
* We only ever set the power-on and power-gate states, anything
* else is unexpected.
@ -1685,10 +1680,10 @@ static bool chv_pipe_power_well_enabled(struct intel_display *display,
* A transient state at this point would mean some unexpected party
* is poking at the power controls too.
*/
ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe);
ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe);
drm_WARN_ON(display->drm, ctrl << 16 != state);
vlv_punit_put(dev_priv);
vlv_punit_put(display->drm);
return enabled;
}
@ -1697,36 +1692,35 @@ static void chv_set_pipe_power_well(struct intel_display *display,
struct i915_power_well *power_well,
bool enable)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum pipe pipe = PIPE_A;
u32 state;
u32 ctrl;
state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe);
vlv_punit_get(dev_priv);
vlv_punit_get(display->drm);
#define COND \
((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe)) == state)
((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe)) == state)
if (COND)
goto out;
ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
ctrl &= ~DP_SSC_MASK(pipe);
ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe);
vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, ctrl);
vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, ctrl);
if (wait_for(COND, 100))
drm_err(display->drm,
"timeout setting power well state %08x (%08x)\n",
state,
vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM));
vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM));
#undef COND
out:
vlv_punit_put(dev_priv);
vlv_punit_put(display->drm);
}
static void chv_pipe_power_well_sync_hw(struct intel_display *display,

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@
#include "i915_drv.h"
#include "intel_clock_gating.h"
#include "intel_cx0_phy.h"
#include "intel_display_core.h"
#include "intel_display_driver.h"
#include "intel_display_reset.h"
#include "intel_display_types.h"

View File

@ -2,6 +2,7 @@
/* Copyright © 2025 Intel Corporation */
#include "i915_drv.h"
#include "intel_display_core.h"
#include "intel_display_rpm.h"
#include "intel_runtime_pm.h"

View File

@ -9,6 +9,7 @@
#include "gt/intel_rps.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_display_core.h"
#include "intel_display_irq.h"
#include "intel_display_rps.h"
#include "intel_display_types.h"
@ -45,12 +46,13 @@ static int do_rps_boost(struct wait_queue_entry *_wait,
void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc,
struct dma_fence *fence)
{
struct intel_display *display = to_intel_display(crtc->dev);
struct wait_rps_boost *wait;
if (!dma_fence_is_i915(fence))
return;
if (DISPLAY_VER(to_i915(crtc->dev)) < 6)
if (DISPLAY_VER(display) < 6)
return;
if (drm_crtc_vblank_get(crtc))

View File

@ -554,6 +554,10 @@ struct intel_connector {
struct intel_dp *dp;
} mst;
struct {
int force_bpp_x16;
} link;
/* Work struct to schedule a uevent on link train failure */
struct work_struct modeset_retry_work;
@ -595,7 +599,7 @@ struct intel_atomic_state {
bool dpll_set, modeset;
struct intel_shared_dpll_state shared_dpll[I915_NUM_PLLS];
struct intel_dpll_state dpll_state[I915_NUM_PLLS];
struct intel_dp_tunnel_inherited_state *inherited_dp_tunnels;
@ -1079,8 +1083,8 @@ struct intel_crtc_state {
* haswell. */
struct dpll dpll;
/* Selected dpll when shared or NULL. */
struct intel_shared_dpll *shared_dpll;
/* Selected dpll or NULL. */
struct intel_dpll *intel_dpll;
/* Actual register state of the dpll, for shared dpll cross-checking. */
struct intel_dpll_hw_state dpll_hw_state;
@ -1090,7 +1094,7 @@ struct intel_crtc_state {
* setting shared_dpll and dpll_hw_state to one of these reserved ones.
*/
struct icl_port_dpll {
struct intel_shared_dpll *pll;
struct intel_dpll *pll;
struct intel_dpll_hw_state hw_state;
} icl_port_dplls[ICL_PORT_DPLL_COUNT];
@ -1297,7 +1301,7 @@ struct intel_crtc_state {
enum transcoder mst_master_transcoder;
/* For DSB based pipe updates */
struct intel_dsb *dsb_color_vblank, *dsb_commit;
struct intel_dsb *dsb_color, *dsb_commit;
bool use_dsb;
u32 psr2_man_track_ctl;
@ -1669,7 +1673,9 @@ struct intel_dp {
bool use_max_params;
u8 dpcd[DP_RECEIVER_CAP_SIZE];
u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
u8 pr_dpcd;
u8 pr_dpcd[DP_PANEL_REPLAY_CAP_SIZE];
#define INTEL_PR_DPCD_INDEX(pr_dpcd_register) ((pr_dpcd_register) - DP_PANEL_REPLAY_CAP_SUPPORT)
u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];

View File

@ -6,6 +6,7 @@
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_core.h"
#include "intel_display_regs.h"
#include "intel_display_wa.h"
static void gen11_display_wa_apply(struct intel_display *display)

View File

@ -25,7 +25,9 @@ dkl_phy_set_hip_idx(struct intel_display *display, struct intel_dkl_phy_reg reg)
{
enum tc_port tc_port = DKL_REG_TC_PORT(reg);
drm_WARN_ON(display->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS);
if (drm_WARN_ON(display->drm,
tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS))
return;
intel_de_write(display,
HIP_INDEX_REG(tc_port),

View File

@ -8,6 +8,8 @@
#include <linux/types.h>
#include "intel_display_reg_defs.h"
struct intel_dkl_phy_reg {
u32 reg:24;
u32 bank_idx:4;

View File

@ -27,9 +27,12 @@
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_rpm.h"
#include "intel_display_power_well.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dmc.h"
#include "intel_dmc_regs.h"
#include "intel_step.h"
@ -425,7 +428,7 @@ static void disable_event_handler(struct intel_display *display,
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_FALSE));
DMC_EVENT_FALSE));
intel_de_write(display, htp_reg, 0);
}
@ -490,6 +493,17 @@ static void pipedmc_clock_gating_wa(struct intel_display *display, bool enable)
adlp_pipedmc_clock_gating_wa(display, enable);
}
static u32 pipedmc_interrupt_mask(struct intel_display *display)
{
/*
* FIXME PIPEDMC_ERROR not enabled for now due to LNL pipe B
* triggering it during the first DC state transition. Figure
* out what is going on...
*/
return PIPEDMC_GTT_FAULT |
PIPEDMC_ATS_FAULT;
}
void intel_dmc_enable_pipe(struct intel_display *display, enum pipe pipe)
{
enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe);
@ -497,6 +511,11 @@ void intel_dmc_enable_pipe(struct intel_display *display, enum pipe pipe)
if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(display, dmc_id))
return;
if (DISPLAY_VER(display) >= 20) {
intel_de_write(display, PIPEDMC_INTERRUPT(pipe), pipedmc_interrupt_mask(display));
intel_de_write(display, PIPEDMC_INTERRUPT_MASK(pipe), ~pipedmc_interrupt_mask(display));
}
if (DISPLAY_VER(display) >= 14)
intel_de_rmw(display, MTL_PIPEDMC_CONTROL, 0, PIPEDMC_ENABLE_MTL(pipe));
else
@ -514,6 +533,73 @@ void intel_dmc_disable_pipe(struct intel_display *display, enum pipe pipe)
intel_de_rmw(display, MTL_PIPEDMC_CONTROL, PIPEDMC_ENABLE_MTL(pipe), 0);
else
intel_de_rmw(display, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0);
if (DISPLAY_VER(display) >= 20) {
intel_de_write(display, PIPEDMC_INTERRUPT_MASK(pipe), ~0);
intel_de_write(display, PIPEDMC_INTERRUPT(pipe), pipedmc_interrupt_mask(display));
}
}
static u32 dmc_evt_ctl_disable(void)
{
return 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_EVENT_FALSE);
}
static bool is_dmc_evt_ctl_reg(struct intel_display *display,
enum intel_dmc_id dmc_id, i915_reg_t reg)
{
u32 offset = i915_mmio_reg_offset(reg);
u32 start = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, 0));
u32 end = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12));
return offset >= start && offset < end;
}
static bool is_dmc_evt_htp_reg(struct intel_display *display,
enum intel_dmc_id dmc_id, i915_reg_t reg)
{
u32 offset = i915_mmio_reg_offset(reg);
u32 start = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, 0));
u32 end = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12));
return offset >= start && offset < end;
}
static bool is_event_handler(struct intel_display *display,
enum intel_dmc_id dmc_id,
unsigned int event_id,
i915_reg_t reg, u32 data)
{
return is_dmc_evt_ctl_reg(display, dmc_id, reg) &&
REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == event_id;
}
static void dmc_configure_event(struct intel_display *display,
enum intel_dmc_id dmc_id,
unsigned int event_id,
bool enable)
{
struct intel_dmc *dmc = display_to_dmc(display);
int num_handlers = 0;
int i;
for (i = 0; i < dmc->dmc_info[dmc_id].mmio_count; i++) {
i915_reg_t reg = dmc->dmc_info[dmc_id].mmioaddr[i];
u32 data = dmc->dmc_info[dmc_id].mmiodata[i];
if (!is_event_handler(display, dmc_id, event_id, reg, data))
continue;
intel_de_write(display, reg, enable ? data : dmc_evt_ctl_disable());
num_handlers++;
}
drm_WARN_ONCE(display->drm, num_handlers != 1,
"DMC %d has %d handlers for event 0x%x\n",
dmc_id, num_handlers, event_id);
}
/**
@ -546,42 +632,9 @@ void intel_dmc_block_pkgc(struct intel_display *display, enum pipe pipe,
void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display *display,
enum pipe pipe, bool enable)
{
u32 val;
enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe);
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)
{
u32 offset = i915_mmio_reg_offset(reg);
u32 start = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, 0));
u32 end = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12));
return offset >= start && offset < end;
}
static bool is_dmc_evt_htp_reg(struct intel_display *display,
enum intel_dmc_id dmc_id, i915_reg_t reg)
{
u32 offset = i915_mmio_reg_offset(reg);
u32 start = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, 0));
u32 end = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12));
return offset >= start && offset < end;
dmc_configure_event(display, dmc_id, PIPEDMC_EVENT_VBLANK, enable);
}
static bool disable_dmc_evt(struct intel_display *display,
@ -597,12 +650,12 @@ static bool disable_dmc_evt(struct intel_display *display,
/* also disable the flip queue event on the main DMC on TGL */
if (display->platform.tigerlake &&
REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == DMC_EVT_CTL_EVENT_ID_CLK_MSEC)
is_event_handler(display, dmc_id, MAINDMC_EVENT_CLK_MSEC, reg, data))
return true;
/* also disable the HRR event on the main DMC on TGL/ADLS */
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)
is_event_handler(display, dmc_id, MAINDMC_EVENT_VBLANK_A, reg, data))
return true;
return false;
@ -615,10 +668,7 @@ static u32 dmc_mmiodata(struct intel_display *display,
if (disable_dmc_evt(display, dmc_id,
dmc->dmc_info[dmc_id].mmioaddr[i],
dmc->dmc_info[dmc_id].mmiodata[i]))
return 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_FALSE);
return dmc_evt_ctl_disable();
else
return dmc->dmc_info[dmc_id].mmiodata[i];
}
@ -1403,3 +1453,29 @@ void intel_dmc_debugfs_register(struct intel_display *display)
debugfs_create_file("i915_dmc_info", 0444, minor->debugfs_root,
display, &intel_dmc_debugfs_status_fops);
}
void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe)
{
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
u32 tmp;
if (DISPLAY_VER(display) >= 20) {
tmp = intel_de_read(display, PIPEDMC_INTERRUPT(pipe));
intel_de_write(display, PIPEDMC_INTERRUPT(pipe), tmp);
if (tmp & PIPEDMC_ATS_FAULT)
drm_err_ratelimited(display->drm, "[CRTC:%d:%s] PIPEDMC ATS fault\n",
crtc->base.base.id, crtc->base.name);
if (tmp & PIPEDMC_GTT_FAULT)
drm_err_ratelimited(display->drm, "[CRTC:%d:%s] PIPEDMC GTT fault\n",
crtc->base.base.id, crtc->base.name);
if (tmp & PIPEDMC_ERROR)
drm_err(display->drm, "[CRTC:%d:%s]] PIPEDMC error\n",
crtc->base.base.id, crtc->base.name);
}
tmp = intel_de_read(display, PIPEDMC_STATUS(pipe)) & PIPEDMC_INT_VECTOR_MASK;
if (tmp)
drm_err(display->drm, "[CRTC:%d:%s]] PIPEDMC interrupt vector 0x%x\n",
crtc->base.base.id, crtc->base.name, tmp);
}

View File

@ -34,4 +34,6 @@ void intel_dmc_update_dc6_allowed_count(struct intel_display *display, bool star
void assert_dmc_loaded(struct intel_display *display);
void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe);
#endif /* __INTEL_DMC_H__ */

View File

@ -6,7 +6,273 @@
#ifndef __INTEL_DMC_REGS_H__
#define __INTEL_DMC_REGS_H__
#include "i915_reg_defs.h"
#include "intel_display_reg_defs.h"
enum dmc_event_id {
DMC_EVENT_TRUE = 0x0,
DMC_EVENT_FALSE = 0x1,
};
enum maindmc_event_id {
MAINDMC_EVENT_CMP_ZERO = 0x8,
MAINDMC_EVENT_CMP_ODD = 0x9,
MAINDMC_EVENT_CMP_NEG = 0xa,
MAINDMC_EVENT_CMP_CARRY = 0xb,
MAINDMC_EVENT_TMR0_DONE = 0x14,
MAINDMC_EVENT_TMR1_DONE = 0x15,
MAINDMC_EVENT_TMR2_DONE = 0x16,
MAINDMC_EVENT_COUNT0_DONE = 0x17,
MAINDMC_EVENT_COUNT1_DONE = 0x18,
MAINDMC_EVENT_PERF_CNTR_DARBF = 0x19,
MAINDMC_EVENT_SCANLINE_INRANGE_FQ_A_TRIGGER = 0x22,
MAINDMC_EVENT_SCANLINE_INRANGE_FQ_B_TRIGGER = 0x23,
MAINDMC_EVENT_SCANLINE_INRANGE_FQ_C_TRIGGER = 0x24,
MAINDMC_EVENT_SCANLINE_INRANGE_FQ_D_TRIGGER = 0x25,
MAINDMC_EVENT_1KHZ_FQ_A_TRIGGER = 0x26,
MAINDMC_EVENT_1KHZ_FQ_B_TRIGGER = 0x27,
MAINDMC_EVENT_1KHZ_FQ_C_TRIGGER = 0x28,
MAINDMC_EVENT_1KHZ_FQ_D_TRIGGER = 0x29,
MAINDMC_EVENT_SCANLINE_COMP_A = 0x2a,
MAINDMC_EVENT_SCANLINE_COMP_B = 0x2b,
MAINDMC_EVENT_SCANLINE_COMP_C = 0x2c,
MAINDMC_EVENT_SCANLINE_COMP_D = 0x2d,
MAINDMC_EVENT_VBLANK_DELAYED_A = 0x2e,
MAINDMC_EVENT_VBLANK_DELAYED_B = 0x2f,
MAINDMC_EVENT_VBLANK_DELAYED_C = 0x30,
MAINDMC_EVENT_VBLANK_DELAYED_D = 0x31,
MAINDMC_EVENT_VBLANK_A = 0x32,
MAINDMC_EVENT_VBLANK_B = 0x33,
MAINDMC_EVENT_VBLANK_C = 0x34,
MAINDMC_EVENT_VBLANK_D = 0x35,
MAINDMC_EVENT_HBLANK_A = 0x36,
MAINDMC_EVENT_HBLANK_B = 0x37,
MAINDMC_EVENT_HBLANK_C = 0x38,
MAINDMC_EVENT_HBLANK_D = 0x39,
MAINDMC_EVENT_VSYNC_A = 0x3a,
MAINDMC_EVENT_VSYNC_B = 0x3b,
MAINDMC_EVENT_VSYNC_C = 0x3c,
MAINDMC_EVENT_VSYNC_D = 0x3d,
MAINDMC_EVENT_SCANLINE_A = 0x3e,
MAINDMC_EVENT_SCANLINE_B = 0x3f,
MAINDMC_EVENT_SCANLINE_C = 0x40,
MAINDMC_EVENT_SCANLINE_D = 0x41,
MAINDMC_EVENT_PLANE1_FLIP_A = 0x42,
MAINDMC_EVENT_PLANE2_FLIP_A = 0x43,
MAINDMC_EVENT_PLANE3_FLIP_A = 0x44,
MAINDMC_EVENT_PLANE4_FLIP_A = 0x45,
MAINDMC_EVENT_PLANE5_FLIP_A = 0x46,
MAINDMC_EVENT_PLANE6_FLIP_A = 0x47,
MAINDMC_EVENT_PLANE7_FLIP_A = 0x48,
MAINDMC_EVENT_PLANE1_FLIP_B = 0x49,
MAINDMC_EVENT_PLANE2_FLIP_B = 0x4a,
MAINDMC_EVENT_PLANE3_FLIP_B = 0x4b,
MAINDMC_EVENT_PLANE4_FLIP_B = 0x4c,
MAINDMC_EVENT_PLANE5_FLIP_B = 0x4d,
MAINDMC_EVENT_PLANE6_FLIP_B = 0x4e,
MAINDMC_EVENT_PLANE7_FLIP_B = 0x4f,
MAINDMC_EVENT_PLANE1_FLIP_C = 0x50,
MAINDMC_EVENT_PLANE2_FLIP_C = 0x51,
MAINDMC_EVENT_PLANE3_FLIP_C = 0x52,
MAINDMC_EVENT_PLANE4_FLIP_C = 0x53,
MAINDMC_EVENT_PLANE5_FLIP_C = 0x54,
MAINDMC_EVENT_PLANE6_FLIP_C = 0x55,
MAINDMC_EVENT_PLANE7_FLIP_C = 0x56,
MAINDMC_EVENT_PLANE1_FLIP_D = 0x57,
MAINDMC_EVENT_PLANE2_FLIP_D = 0x58,
MAINDMC_EVENT_PLANE3_FLIP_D = 0x59,
MAINDMC_EVENT_PLANE4_FLIP_D = 0x5a,
MAINDMC_EVENT_PLANE5_FLIP_D = 0x5b,
MAINDMC_EVENT_PLANE6_FLIP_D = 0x5c,
MAINDMC_EVENT_PLANE7_FLIP_D = 0x5d,
MAINDMC_EVENT_PLANE1_FLIP_DONE_A = 0x5e,
MAINDMC_EVENT_PLANE2_FLIP_DONE_A = 0x5f,
MAINDMC_EVENT_PLANE3_FLIP_DONE_A = 0x60,
MAINDMC_EVENT_PLANE4_FLIP_DONE_A = 0x61,
MAINDMC_EVENT_PLANE5_FLIP_DONE_A = 0x62,
MAINDMC_EVENT_PLANE6_FLIP_DONE_A = 0x63,
MAINDMC_EVENT_PLANE7_FLIP_DONE_A = 0x64,
MAINDMC_EVENT_PLANE1_FLIP_DONE_B = 0x65,
MAINDMC_EVENT_PLANE2_FLIP_DONE_B = 0x66,
MAINDMC_EVENT_PLANE3_FLIP_DONE_B = 0x67,
MAINDMC_EVENT_PLANE4_FLIP_DONE_B = 0x68,
MAINDMC_EVENT_PLANE5_FLIP_DONE_B = 0x69,
MAINDMC_EVENT_PLANE6_FLIP_DONE_B = 0x6a,
MAINDMC_EVENT_PLANE7_FLIP_DONE_B = 0x6b,
MAINDMC_EVENT_PLANE1_FLIP_DONE_C = 0x6c,
MAINDMC_EVENT_PLANE2_FLIP_DONE_C = 0x6d,
MAINDMC_EVENT_PLANE3_FLIP_DONE_C = 0x6e,
MAINDMC_EVENT_PLANE4_FLIP_DONE_C = 0x6f,
MAINDMC_EVENT_PLANE5_FLIP_DONE_C = 0x70,
MAINDMC_EVENT_PLANE6_FLIP_DONE_C = 0x71,
MAINDMC_EVENT_PLANE7_FLIP_DONE_C = 0x72,
MAINDMC_EVENT_PLANE1_FLIP_DONE_D = 0x73,
MAINDMC_EVENT_PLANE2_FLIP_DONE_D = 0x74,
MAINDMC_EVENT_PLANE3_FLIP_DONE_D = 0x75,
MAINDMC_EVENT_PLANE4_FLIP_DONE_D = 0x76,
MAINDMC_EVENT_PLANE5_FLIP_DONE_D = 0x77,
MAINDMC_EVENT_PLANE6_FLIP_DONE_D = 0x78,
MAINDMC_EVENT_PLANE7_FLIP_DONE_D = 0x79,
MAINDMC_EVENT_WIDI_GTT_FAULT_SL1 = 0x7d,
MAINDMC_EVENT_WIDI_GTT_FAULT_SL2 = 0x7e,
MAINDMC_EVENT_WIDI_CAP_ACTIVE_SL1 = 0x7f,
MAINDMC_EVENT_WIDI_CAP_ACTIVE_SL2 = 0x80,
MAINDMC_EVENT_RENUKE_A = 0x85,
MAINDMC_EVENT_RENUKE_B = 0x86,
MAINDMC_EVENT_RENUKE_C = 0x87,
MAINDMC_EVENT_RENUKE_D = 0x88,
MAINDMC_EVENT_DPFC_FIFO_FULL_A = 0x89,
MAINDMC_EVENT_DPFC_FIFO_FULL_B = 0x8a,
MAINDMC_EVENT_DPFC_FIFO_FULL_C = 0x8b,
MAINDMC_EVENT_DPFC_FIFO_FULL_D = 0x8c,
MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_A = 0x8d,
MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_B = 0x8e,
MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_C = 0x8f,
MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_D = 0x90,
MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_A = 0x91,
MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_B = 0x92,
MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_C = 0x93,
MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_D = 0x94,
MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_A = 0x95,
MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_B = 0x96,
MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_C = 0x97,
MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_D = 0x98,
MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_A = 0x99,
MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_B = 0x9a,
MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_C = 0x9b,
MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_D = 0x9c,
MAINDMC_EVENT_DISP_PCH_INT = 0x9d,
MAINDMC_EVENT_GTT_ERR = 0x9e,
MAINDMC_EVENT_VTD_ERR = 0x9f,
MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_A = 0xa0,
MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_B = 0xa1,
MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_C = 0xa2,
MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_D = 0xa3,
MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_A = 0xa4,
MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_B = 0xa5,
MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_C = 0xa6,
MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_D = 0xa7,
MAINDMC_EVENT_DC_CLOCK_OFF_START_EDP = 0xb2,
MAINDMC_EVENT_DC_CLOCK_OFF_START_DSI = 0xb3,
MAINDMC_EVENT_DCPR_DMC_CSR_START = 0xb4,
MAINDMC_EVENT_IN_PSR = 0xb5,
MAINDMC_EVENT_IN_MEMUP = 0xb7,
MAINDMC_EVENT_IN_VGA = 0xb8,
MAINDMC_EVENT_IN_KVM_SESSION = 0xba,
MAINDMC_EVENT_DEWAKE = 0xbb,
MAINDMC_EVENT_TRAP_HIT = 0xbd,
MAINDMC_EVENT_CLK_USEC = 0xbe,
MAINDMC_EVENT_CLK_MSEC = 0xbf,
MAINDMC_EVENT_CHICKEN1 = 0xc8,
MAINDMC_EVENT_CHICKEN2 = 0xc9,
MAINDMC_EVENT_CHICKEN3 = 0xca,
MAINDMC_EVENT_DDT_UBP = 0xcb,
MAINDMC_EVENT_HP_LATENCY = 0xcd,
MAINDMC_EVENT_LP_LATENCY = 0xce,
MAINDMC_EVENT_WIDI_LP_REQ_SL1 = 0xcf,
MAINDMC_EVENT_WIDI_LP_REQ_SL2 = 0xd0,
MAINDMC_EVENT_DG_DMC_EVT_0 = 0xd3,
MAINDMC_EVENT_DG_DMC_EVT_1 = 0xd4,
MAINDMC_EVENT_DG_DMC_EVT_2 = 0xd5,
MAINDMC_EVENT_DG_DMC_EVT_3 = 0xd6,
MAINDMC_EVENT_DG_DMC_EVT_4 = 0xd7,
MAINDMC_EVENT_DACFE_CLK_STOP = 0xd8,
MAINDMC_EVENT_DACFE_AZILIA_SDI_WAKE = 0xd9,
MAINDMC_EVENT_AUDIO_DOUBLE_FUNC_GRP_RST = 0xda,
MAINDMC_EVENT_AUDIO_CMD_VALID = 0xdb,
MAINDMC_EVENT_AUDIO_FRM_SYNC_BCLK = 0xdc,
MAINDMC_EVENT_AUDIO_FRM_SYNC_CDCLK = 0xdd,
MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_A = 0xde,
MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_B = 0xdf,
MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_C = 0xe0,
MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_E = 0xe1,
MAINDMC_EVENT_CMTG_SCANLINE_IN_GB_DC6v = 0xe2,
MAINDMC_EVENT_DCPR_CMTG_SCANLINE_OUTSIDE_GB = 0xe3,
MAINDMC_EVENT_DC6v_BACKWARD_COMPAT = 0xe4,
MAINDMC_EVENT_DPMA_PM_ABORT = 0xe5,
MAINDMC_EVENT_STACK_OVF = 0xfc,
MAINDMC_EVENT_NO_CLAIM = 0xfd,
MAINDMC_EVENT_UNK_CMD = 0xfe,
MAINDMC_EVENT_HTP_MOD = 0xff,
};
enum pipedmc_event_id {
PIPEDMC_EVENT_TMR0_DONE = 0x14,
PIPEDMC_EVENT_TMR1_DONE = 0x15,
PIPEDMC_EVENT_TMR2_DONE = 0x16,
PIPEDMC_EVENT_COUNT0_DONE = 0x17,
PIPEDMC_EVENT_COUNT1_DONE = 0x18,
PIPEDMC_EVENT_PGA_PGB_RESTORE_DONE = 0x19,
PIPEDMC_EVENT_PG1_PG2_RESTORE_DONE = 0x1a,
PIPEDMC_EVENT_PGA_PGB_SAVE_DONE = 0x1b,
PIPEDMC_EVENT_PG1_PG2_SAVE_DONE = 0x1c,
PIPEDMC_EVENT_FULL_FQ_WAKE_TRIGGER = 0x2b,
PIPEDMC_EVENT_1KHZ_FQ_TRIGGER = 0x2c,
PIPEDMC_EVENT_SCANLINE_INRANGE_FQ_TRIGGER = 0x2d,
PIPEDMC_EVENT_SCANLINE_INRANGE = 0x2e,
PIPEDMC_EVENT_SCANLINE_OUTRANGE = 0x2f,
PIPEDMC_EVENT_SCANLINE_EQUAL = 0x30,
PIPEDMC_EVENT_DELAYED_VBLANK = 0x31,
PIPEDMC_EVENT_VBLANK = 0x32,
PIPEDMC_EVENT_HBLANK = 0x33,
PIPEDMC_EVENT_VSYNC = 0x34,
PIPEDMC_EVENT_SCANLINE_FROM_DMUX = 0x35,
PIPEDMC_EVENT_PLANE1_FLIP = 0x36,
PIPEDMC_EVENT_PLANE2_FLIP = 0x37,
PIPEDMC_EVENT_PLANE3_FLIP = 0x38,
PIPEDMC_EVENT_PLANE4_FLIP = 0x39,
PIPEDMC_EVENT_PLANE5_FLIP = 0x3a,
PIPEDMC_EVENT_PLANE6_FLIP = 0x3b,
PIPEDMC_EVENT_PLANE7_FLIP = 0x3c,
PIPEDMC_EVENT_ADAPTIVE_DCB_TRIGGER = 0x3d,
PIPEDMC_EVENT_PLANE1_FLIP_DONE = 0x56,
PIPEDMC_EVENT_PLANE2_FLIP_DONE = 0x57,
PIPEDMC_EVENT_PLANE3_FLIP_DONE = 0x58,
PIPEDMC_EVENT_PLANE4_FLIP_DONE = 0x59,
PIPEDMC_EVENT_PLANE5_FLIP_DONE = 0x5a,
PIPEDMC_EVENT_PLANE6_FLIP_DONE = 0x5b,
PIPEDMC_EVENT_PLANE7_FLIP_DONE = 0x5c,
PIPEDMC_EVENT_GTT_ERR = 0x9b,
PIPEDMC_EVENT_IN_PSR = 0xb5,
PIPEDMC_EVENT_DSI_DMC_IDLE = 0xb6,
PIPEDMC_EVENT_PSR2_DMC_IDLE = 0xb7,
PIPEDMC_EVENT_IN_VGA = 0xb8,
PIPEDMC_EVENT_TRAP_HIT = 0xbd,
PIPEDMC_EVENT_CLK_USEC = 0xbe,
PIPEDMC_EVENT_CLK_MSEC = 0xbf,
PIPEDMC_EVENT_CHICKEN1 = 0xc8,
PIPEDMC_EVENT_CHICKEN2 = 0xc9,
PIPEDMC_EVENT_CHICKEN3 = 0xca,
PIPEDMC_EVENT_DDT_UBP = 0xcb,
PIPEDMC_EVENT_LP_LATENCY = 0xce,
PIPEDMC_EVENT_LACE_PART_A_HIST_TRIGGER = 0xdf,
PIPEDMC_EVENT_LACE_PART_B_HIST_TRIGGER = 0xe0,
PIPEDMC_EVENT_STACK_OVF = 0xfc,
PIPEDMC_EVENT_NO_CLAIM = 0xfd,
PIPEDMC_EVENT_UNK_CMD = 0xfe,
PIPEDMC_EVENT_HTP_MOD = 0xff,
};
#define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4)
#define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0
@ -21,11 +287,27 @@
#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_STATUS_A 0x5f06c
#define _PIPEDMC_STATUS_B 0x5f46c
#define PIPEDMC_STATUS(pipe) _MMIO_PIPE((pipe), _PIPEDMC_STATUS_A, _PIPEDMC_STATUS_B)
#define PIPEDMC_SSP REG_GENMASK(31, 16)
#define PIPEDMC_INT_VECTOR_MASK REG_GENMASK(15, 8)
/* PIPEDMC_INT_VECTOR values defined by firmware */
#define PIPEDMC_INT_VECTOR_SCANLINE_COMP_ERROR REG_FIELD_PREP(PIPEDMC_INT_VECTOR_MASK, 0x1)
#define PIPEDMC_INT_VECTOR_DC6V_FLIPQ_OVERLAP_ERROR REG_FIELD_PREP(PIPEDMC_INT_VECTOR_MASK, 0x2)
#define PIPEDMC_INT_VECTOR_FLIPQ_PROG_DONE REG_FIELD_PREP(PIPEDMC_INT_VECTOR_MASK, 0xff) /* Wa_16018781658:lnl[a0] */
#define PIPEDMC_EVT_PENDING REG_GENMASK(7, 0)
#define _PIPEDMC_INTERRUPT_A 0x5f190 /* lnl+ */
#define _PIPEDMC_INTERRUPT_B 0x5f590 /* lnl+ */
#define PIPEDMC_INTERRUPT(pipe) _MMIO_PIPE((pipe), _PIPEDMC_INTERRUPT_A, _PIPEDMC_INTERRUPT_B)
#define _PIPEDMC_INTERRUPT_MASK_A 0x5f194 /* lnl+ */
#define _PIPEDMC_INTERRUPT_MASK_B 0x5f594 /* lnl+ */
#define PIPEDMC_INTERRUPT_MASK(pipe) _MMIO_PIPE((pipe), _PIPEDMC_INTERRUPT_MASK_A, _PIPEDMC_INTERRUPT_MASK_B)
#define PIPEDMC_FLIPQ_PROG_DONE REG_BIT(3)
#define PIPEDMC_ERROR REG_BIT(2)
#define PIPEDMC_GTT_FAULT REG_BIT(1)
#define PIPEDMC_ATS_FAULT REG_BIT(0)
#define PIPEDMC_BLOCK_PKGC_SW_A 0x5f1d0
#define PIPEDMC_BLOCK_PKGC_SW_B 0x5F5d0
@ -71,12 +353,7 @@
#define DMC_EVT_CTL_TYPE_LEVEL_1 1
#define DMC_EVT_CTL_TYPE_EDGE_1_0 2
#define DMC_EVT_CTL_TYPE_EDGE_0_1 3
#define DMC_EVT_CTL_EVENT_ID_MASK REG_GENMASK(15, 8)
#define DMC_EVT_CTL_EVENT_ID_FALSE 0x01
#define DMC_EVT_CTL_EVENT_ID_VBLANK_A 0x32 /* main DMC */
/* An event handler scheduled to run at a 1 kHz frequency. */
#define DMC_EVT_CTL_EVENT_ID_CLK_MSEC 0xbf
#define DMC_HTP_ADDR_SKL 0x00500034
#define DMC_SSP_BASE _MMIO(0x8F074)

View File

@ -8,8 +8,8 @@
#include <drm/drm_print.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_dmc_regs.h"
#include "intel_dmc_wl.h"

View File

@ -27,6 +27,8 @@
#include <linux/export.h>
#include <linux/i2c.h>
#include <linux/log2.h>
#include <linux/math.h>
#include <linux/notifier.h>
#include <linux/seq_buf.h>
#include <linux/slab.h>
@ -34,7 +36,6 @@
#include <linux/string_helpers.h>
#include <linux/timekeeping.h>
#include <linux/types.h>
#include <asm/byteorder.h>
#include <drm/display/drm_dp_helper.h>
@ -49,8 +50,6 @@
#include <drm/drm_probe_helper.h>
#include "g4x_dp.h"
#include "i915_irq.h"
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_alpm.h"
#include "intel_atomic.h"
@ -64,6 +63,7 @@
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_driver.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dp.h"
@ -847,7 +847,7 @@ small_joiner_ram_size_bits(struct intel_display *display)
return 6144 * 8;
}
u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp)
static u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp)
{
u32 bits_per_pixel = bpp;
int i;
@ -939,6 +939,7 @@ static u32 ultrajoiner_ram_max_bpp(u32 mode_hdisplay)
return ultrajoiner_ram_bits() / mode_hdisplay;
}
/* TODO: return a bpp_x16 value */
static
u32 get_max_compressed_bpp_with_joiner(struct intel_display *display,
u32 mode_clock, u32 mode_hdisplay,
@ -955,6 +956,7 @@ u32 get_max_compressed_bpp_with_joiner(struct intel_display *display,
return max_bpp;
}
/* TODO: return a bpp_x16 value */
u16 intel_dp_dsc_get_max_compressed_bpp(struct intel_display *display,
u32 link_clock, u32 lane_count,
u32 mode_clock, u32 mode_hdisplay,
@ -1195,7 +1197,7 @@ intel_dp_output_format(struct intel_connector *connector,
int intel_dp_min_bpp(enum intel_output_format output_format)
{
if (output_format == INTEL_OUTPUT_FORMAT_RGB)
return 6 * 3;
return intel_display_min_pipe_bpp();
else
return 8 * 3;
}
@ -2067,7 +2069,7 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
pipe_config, bpc) >> 4;
}
static int dsc_src_min_compressed_bpp(void)
int intel_dp_dsc_min_src_compressed_bpp(void)
{
/* Min Compressed bpp supported by source is 8 */
return 8;
@ -2099,7 +2101,7 @@ static int dsc_src_max_compressed_bpp(struct intel_dp *intel_dp)
/*
* Note: for pre-13 display you still need to check the validity of each step.
*/
static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector)
int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
u8 incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd);
@ -2107,12 +2109,19 @@ static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector)
if (DISPLAY_VER(display) < 14 || !incr)
return fxp_q4_from_int(1);
if (connector->mst.dp &&
!connector->link.force_bpp_x16 && !connector->mst.dp->force_dsc_fractional_bpp_en)
return fxp_q4_from_int(1);
/* fxp q4 */
return fxp_q4_from_int(1) / incr;
}
/* Note: This is not universally usable! */
static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16)
/*
* Note: for bpp_x16 to be valid it must be also within the source/sink's
* min..max bpp capability range.
*/
bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16)
{
struct intel_display *display = to_intel_display(intel_dp);
int i;
@ -2150,24 +2159,16 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
const struct intel_connector *connector = to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
int output_bpp;
int dsc_min_bpp;
int dsc_max_bpp;
int min_bpp_x16, max_bpp_x16, bpp_step_x16;
int dsc_joiner_max_bpp;
int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config);
int bpp_x16;
int ret;
dsc_min_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16);
dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(display, adjusted_mode->clock,
adjusted_mode->hdisplay,
num_joined_pipes);
dsc_max_bpp = min(dsc_joiner_max_bpp, fxp_q4_to_int(limits->link.max_bpp_x16));
/* FIXME: remove the round trip via integers */
min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp);
max_bpp_x16 = fxp_q4_from_int(dsc_max_bpp);
max_bpp_x16 = min(fxp_q4_from_int(dsc_joiner_max_bpp), limits->link.max_bpp_x16);
bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector);
@ -2175,8 +2176,12 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp);
max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16);
drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16));
min_bpp_x16 = round_up(limits->link.min_bpp_x16, bpp_step_x16);
max_bpp_x16 = round_down(max_bpp_x16, bpp_step_x16);
for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) {
if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16))
if (!intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16))
continue;
ret = dsc_compute_link_config(intel_dp,
@ -2479,7 +2484,7 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
int dsc_src_min_bpp, dsc_sink_min_bpp, dsc_min_bpp;
int dsc_src_max_bpp, dsc_sink_max_bpp, dsc_max_bpp;
dsc_src_min_bpp = dsc_src_min_compressed_bpp();
dsc_src_min_bpp = intel_dp_dsc_min_src_compressed_bpp();
dsc_sink_min_bpp = intel_dp_dsc_sink_min_compressed_bpp(crtc_state);
dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp);
limits->link.min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp);
@ -5785,6 +5790,28 @@ intel_dp_detect_sdp_caps(struct intel_dp *intel_dp)
drm_dp_as_sdp_supported(&intel_dp->aux, intel_dp->dpcd);
}
static bool intel_dp_needs_dpcd_probe(struct intel_dp *intel_dp, bool force_on_external)
{
struct intel_connector *connector = intel_dp->attached_connector;
if (intel_dp_is_edp(intel_dp))
return false;
if (force_on_external)
return true;
if (intel_dp->is_mst)
return false;
return drm_edid_has_quirk(&connector->base, DRM_EDID_QUIRK_DP_DPCD_PROBE);
}
void intel_dp_dpcd_set_probe(struct intel_dp *intel_dp, bool force_on_external)
{
drm_dp_dpcd_set_probe(&intel_dp->aux,
intel_dp_needs_dpcd_probe(intel_dp, force_on_external));
}
static int
intel_dp_detect(struct drm_connector *_connector,
struct drm_modeset_acquire_ctx *ctx,
@ -5913,6 +5940,8 @@ intel_dp_detect(struct drm_connector *_connector,
if (status != connector_status_connected && !intel_dp->is_mst)
intel_dp_unset_edid(intel_dp);
intel_dp_dpcd_set_probe(intel_dp, false);
if (!intel_dp_is_edp(intel_dp))
drm_dp_set_subconnector_property(&connector->base,
status,
@ -5943,6 +5972,8 @@ intel_dp_force(struct drm_connector *_connector)
return;
intel_dp_set_edid(intel_dp);
intel_dp_dpcd_set_probe(intel_dp, false);
}
static int intel_dp_get_modes(struct drm_connector *_connector)
@ -6315,10 +6346,11 @@ intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd)
* complete the DP tunnel BW request for the latter connector/encoder
* waiting for this encoder's DPRX read, perform a dummy read here.
*/
if (long_hpd)
if (long_hpd) {
intel_dp_dpcd_set_probe(intel_dp, true);
intel_dp_read_dprx_caps(intel_dp, dpcd);
if (long_hpd) {
intel_dp->reset_link_params = true;
intel_dp_invalidate_source_oui(intel_dp);

View File

@ -147,6 +147,7 @@ int intel_dp_dsc_sink_min_compressed_bpp(const struct intel_crtc_state *pipe_con
int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector,
const struct intel_crtc_state *pipe_config,
int bpc);
bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16);
u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int mode_clock, int mode_hdisplay,
int num_joined_pipes);
@ -173,8 +174,6 @@ bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
const struct intel_connector *connector,
const struct intel_crtc_state *crtc_state);
u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp);
void intel_ddi_update_pipe(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
@ -209,7 +208,11 @@ 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_dsc_min_src_compressed_bpp(void);
int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector);
void intel_dp_dpcd_set_probe(struct intel_dp *intel_dp, bool force_on_external);
#endif /* __INTEL_DP_H__ */

View File

@ -5,7 +5,6 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_de.h"
#include "intel_display_types.h"
@ -835,6 +834,8 @@ void intel_dp_aux_init(struct intel_dp *intel_dp)
intel_dp->aux.transfer = intel_dp_aux_transfer;
cpu_latency_qos_add_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
intel_dp_dpcd_set_probe(intel_dp, true);
}
static enum aux_ch default_aux_ch(struct intel_encoder *encoder)

View File

@ -11,9 +11,9 @@
#include <drm/display/drm_hdcp_helper.h>
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_hdcp.h"

View File

@ -23,6 +23,9 @@
*
*/
#include <linux/log2.h>
#include <linux/math.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
@ -30,7 +33,6 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_atomic.h"
#include "intel_audio.h"
@ -39,6 +41,7 @@
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_driver.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_hdcp.h"
@ -135,6 +138,7 @@ static bool intel_dp_mst_inc_active_streams(struct intel_dp *intel_dp)
return intel_dp->mst.active_streams++ == 0;
}
/* TODO: return a bpp_x16 value */
static int intel_dp_mst_max_dpt_bpp(const struct intel_crtc_state *crtc_state,
bool dsc)
{
@ -241,6 +245,15 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec
num_joined_pipes);
}
static void mst_stream_update_slots(const struct intel_crtc_state *crtc_state,
struct drm_dp_mst_topology_state *topology_state)
{
u8 link_coding_cap = intel_dp_is_uhbr(crtc_state) ?
DP_CAP_ANSI_128B132B : DP_CAP_ANSI_8B10B;
drm_dp_mst_update_slots(topology_state, link_coding_cap);
}
int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
@ -263,6 +276,12 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
fxp_q4_to_frac(max_bpp_x16) ||
fxp_q4_to_frac(bpp_step_x16)));
if (!bpp_step_x16) {
/* Allow using zero step only to indicate single try for a given bpp. */
drm_WARN_ON(display->drm, min_bpp_x16 != max_bpp_x16);
bpp_step_x16 = 1;
}
if (is_mst) {
mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst.mgr);
if (IS_ERR(mst_state))
@ -270,6 +289,8 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
mst_state->pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock,
crtc_state->lane_count);
mst_stream_update_slots(crtc_state, mst_state);
}
if (dsc) {
@ -298,12 +319,20 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
}
}
drm_WARN_ON(display->drm, min_bpp_x16 % bpp_step_x16 || max_bpp_x16 % bpp_step_x16);
for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) {
int local_bw_overhead;
int link_bpp_x16;
drm_dbg_kms(display->drm, "Trying bpp " FXP_Q4_FMT "\n", FXP_Q4_ARGS(bpp_x16));
if (dsc && !intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16)) {
/* SST must have validated the single bpp tried here already earlier. */
drm_WARN_ON(display->drm, !is_mst);
continue;
}
link_bpp_x16 = dsc ? bpp_x16 :
fxp_q4_from_int(intel_dp_output_bpp(crtc_state->output_format,
fxp_q4_to_int(bpp_x16)));
@ -367,6 +396,10 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst.mgr,
connector->mst.port,
dfixed_trunc(pbn));
/* TODO: Check this already in drm_dp_atomic_find_time_slots(). */
if (slots > mst_state->total_avail_slots)
slots = -EINVAL;
} else {
/* Same as above for remote_tu */
crtc_state->dp_m_n.tu = ALIGN(crtc_state->dp_m_n.tu,
@ -386,10 +419,6 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
break;
}
/* Allow using zero step to indicate one try */
if (!bpp_step_x16)
break;
}
if (slots < 0) {
@ -437,7 +466,8 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp,
int num_bpc;
u8 dsc_bpc[3] = {};
int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
int min_compressed_bpp, max_compressed_bpp;
int min_compressed_bpp_x16, max_compressed_bpp_x16;
int bpp_step_x16;
max_bpp = limits->pipe.max_bpp;
min_bpp = limits->pipe.min_bpp;
@ -462,46 +492,28 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp,
crtc_state->pipe_bpp = max_bpp;
max_compressed_bpp = fxp_q4_to_int(limits->link.max_bpp_x16);
min_compressed_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16);
min_compressed_bpp_x16 = limits->link.min_bpp_x16;
max_compressed_bpp_x16 = limits->link.max_bpp_x16;
drm_dbg_kms(display->drm, "DSC Sink supported compressed min bpp %d compressed max bpp %d\n",
min_compressed_bpp, max_compressed_bpp);
drm_dbg_kms(display->drm,
"DSC Sink supported compressed min bpp " FXP_Q4_FMT " compressed max bpp " FXP_Q4_FMT "\n",
FXP_Q4_ARGS(min_compressed_bpp_x16), FXP_Q4_ARGS(max_compressed_bpp_x16));
/* Align compressed bpps according to our own constraints */
max_compressed_bpp = intel_dp_dsc_nearest_valid_bpp(display, max_compressed_bpp,
crtc_state->pipe_bpp);
min_compressed_bpp = intel_dp_dsc_nearest_valid_bpp(display, min_compressed_bpp,
crtc_state->pipe_bpp);
bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector);
max_compressed_bpp_x16 = min(max_compressed_bpp_x16, fxp_q4_from_int(crtc_state->pipe_bpp) - bpp_step_x16);
drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16));
min_compressed_bpp_x16 = round_up(min_compressed_bpp_x16, bpp_step_x16);
max_compressed_bpp_x16 = round_down(max_compressed_bpp_x16, bpp_step_x16);
crtc_state->lane_count = limits->max_lane_count;
crtc_state->port_clock = limits->max_rate;
return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state,
fxp_q4_from_int(min_compressed_bpp),
fxp_q4_from_int(max_compressed_bpp),
fxp_q4_from_int(1), true);
}
static int mst_stream_update_slots(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst.mgr;
struct drm_dp_mst_topology_state *topology_state;
u8 link_coding_cap = intel_dp_is_uhbr(crtc_state) ?
DP_CAP_ANSI_128B132B : DP_CAP_ANSI_8B10B;
topology_state = drm_atomic_get_mst_topology_state(conn_state->state, mgr);
if (IS_ERR(topology_state)) {
drm_dbg_kms(display->drm, "slot update failed\n");
return PTR_ERR(topology_state);
}
drm_dp_mst_update_slots(topology_state, link_coding_cap);
return 0;
min_compressed_bpp_x16,
max_compressed_bpp_x16,
bpp_step_x16, true);
}
static int mode_hblank_period_ns(const struct drm_display_mode *mode)
@ -706,10 +718,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
pipe_config->dp_m_n.tu);
}
if (ret)
return ret;
ret = mst_stream_update_slots(intel_dp, pipe_config, conn_state);
if (ret)
return ret;

View File

@ -10,9 +10,9 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "i915_reg.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_link_training.h"

View File

@ -21,13 +21,15 @@
* DEALINGS IN THE SOFTWARE.
*/
#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_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
#include "intel_display_power_well.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dpio_phy.h"
@ -426,7 +428,7 @@ static void _bxt_dpio_phy_init(struct intel_display *display, enum dpio_phy phy)
* use 1ms due to occasional timeouts observed with that.
*/
if (intel_de_wait_fw(display, BXT_PORT_CL1CM_DW0(phy),
PHY_RESERVED | PHY_POWER_GOOD, PHY_POWER_GOOD, 1))
PHY_RESERVED | PHY_POWER_GOOD, PHY_POWER_GOOD, 1, NULL))
drm_err(display->drm, "timeout during PHY%d power on\n",
phy);
@ -715,53 +717,53 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder,
u32 deemph_reg_value, u32 margin_reg_value,
bool uniq_trans_scale)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
u32 val;
int i;
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* Clear calc init */
val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW10(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch));
val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW10(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW10(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch));
val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW10(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val);
}
val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW9(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW9(ch));
val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW9(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW9(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW9(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW9(ch));
val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW9(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW9(ch), val);
}
/* Program swing deemph */
for (i = 0; i < crtc_state->lane_count; i++) {
val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW4(ch, i));
val = vlv_dpio_read(display->drm, phy, CHV_TX_DW4(ch, i));
val &= ~DPIO_SWING_DEEMPH9P5_MASK;
val |= DPIO_SWING_DEEMPH9P5(deemph_reg_value);
vlv_dpio_write(dev_priv, phy, CHV_TX_DW4(ch, i), val);
vlv_dpio_write(display->drm, phy, CHV_TX_DW4(ch, i), val);
}
/* Program swing margin */
for (i = 0; i < crtc_state->lane_count; i++) {
val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW2(ch, i));
val = vlv_dpio_read(display->drm, phy, CHV_TX_DW2(ch, i));
val &= ~DPIO_SWING_MARGIN000_MASK;
val |= DPIO_SWING_MARGIN000(margin_reg_value);
@ -774,7 +776,7 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder,
val &= ~DPIO_UNIQ_TRANS_SCALE_MASK;
val |= DPIO_UNIQ_TRANS_SCALE(0x9a);
vlv_dpio_write(dev_priv, phy, CHV_TX_DW2(ch, i), val);
vlv_dpio_write(display->drm, phy, CHV_TX_DW2(ch, i), val);
}
/*
@ -784,70 +786,70 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder,
* 27 for ch0 and ch1.
*/
for (i = 0; i < crtc_state->lane_count; i++) {
val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW3(ch, i));
val = vlv_dpio_read(display->drm, phy, CHV_TX_DW3(ch, i));
if (uniq_trans_scale)
val |= DPIO_TX_UNIQ_TRANS_SCALE_EN;
else
val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
vlv_dpio_write(dev_priv, phy, CHV_TX_DW3(ch, i), val);
vlv_dpio_write(display->drm, phy, CHV_TX_DW3(ch, i), val);
}
/* Start swing calculation */
val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW10(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch));
val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW10(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW10(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch));
val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW10(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val);
}
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
}
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_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
u32 val;
val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW0(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW0(ch));
if (reset)
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
else
val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW0(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW0(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW0(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW0(ch));
if (reset)
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
else
val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW0(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW0(ch), val);
}
val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW1(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW1(ch));
val |= CHV_PCS_REQ_SOFTRESET_EN;
if (reset)
val &= ~DPIO_PCS_CLK_SOFT_RESET;
else
val |= DPIO_PCS_CLK_SOFT_RESET;
vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW1(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW1(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW1(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW1(ch));
val |= CHV_PCS_REQ_SOFTRESET_EN;
if (reset)
val &= ~DPIO_PCS_CLK_SOFT_RESET;
else
val |= DPIO_PCS_CLK_SOFT_RESET;
vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW1(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW1(ch), val);
}
}
@ -855,11 +857,11 @@ 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);
struct intel_display *display = to_intel_display(encoder);
vlv_dpio_get(i915);
vlv_dpio_get(display->drm);
__chv_data_lane_soft_reset(encoder, crtc_state, reset);
vlv_dpio_put(i915);
vlv_dpio_put(display->drm);
}
void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
@ -867,7 +869,6 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
@ -886,47 +887,47 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
chv_phy_powergate_lanes(encoder, true, lane_mask);
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* Assert data lane reset */
__chv_data_lane_soft_reset(encoder, crtc_state, true);
/* program left/right clock distribution */
if (pipe != PIPE_B) {
val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW5_CH0);
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0);
val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
if (ch == DPIO_CH0)
val |= CHV_BUFLEFTENA1_FORCE;
if (ch == DPIO_CH1)
val |= CHV_BUFRIGHTENA1_FORCE;
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW5_CH0, val);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val);
} else {
val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW1_CH1);
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1);
val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
if (ch == DPIO_CH0)
val |= CHV_BUFLEFTENA2_FORCE;
if (ch == DPIO_CH1)
val |= CHV_BUFRIGHTENA2_FORCE;
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW1_CH1, val);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val);
}
/* program clock channel usage */
val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW8(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW8(ch));
val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE;
if (pipe == PIPE_B)
val |= DPIO_PCS_USEDCLKCHANNEL;
else
val &= ~DPIO_PCS_USEDCLKCHANNEL;
vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW8(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW8(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW8(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW8(ch));
val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE;
if (pipe == PIPE_B)
val |= DPIO_PCS_USEDCLKCHANNEL;
else
val &= ~DPIO_PCS_USEDCLKCHANNEL;
vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW8(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW8(ch), val);
}
/*
@ -934,38 +935,38 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
* matches the pipe, but here we need to
* pick the CL based on the port.
*/
val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW19(ch));
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW19(ch));
if (pipe == PIPE_B)
val |= CHV_CMN_USEDCLKCHANNEL;
else
val &= ~CHV_CMN_USEDCLKCHANNEL;
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW19(ch), val);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW19(ch), val);
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
}
void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
int data, i, stagger;
u32 val;
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* allow hardware to manage TX FIFO reset source */
val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW11(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch));
val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW11(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW11(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch));
val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW11(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val);
}
/* Program Tx lane latency optimal setting*/
@ -975,7 +976,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
data = 0;
else
data = (i == 1) ? 0 : DPIO_UPAR;
vlv_dpio_write(dev_priv, phy, CHV_TX_DW14(ch, i), data);
vlv_dpio_write(display->drm, phy, CHV_TX_DW14(ch, i), data);
}
/* Data lane stagger programming */
@ -990,17 +991,17 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
else
stagger = 0x2;
val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW11(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch));
val |= DPIO_TX2_STAGGER_MASK(0x1f);
vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW11(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW11(ch));
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch));
val |= DPIO_TX2_STAGGER_MASK(0x1f);
vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW11(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val);
}
vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW12(ch),
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW12(ch),
DPIO_LANESTAGGER_STRAP(stagger) |
DPIO_LANESTAGGER_STRAP_OVRD |
DPIO_TX1_STAGGER_MASK(0x1f) |
@ -1008,7 +1009,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
DPIO_TX2_STAGGER_MULT(0));
if (crtc_state->lane_count > 2) {
vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW12(ch),
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW12(ch),
DPIO_LANESTAGGER_STRAP(stagger) |
DPIO_LANESTAGGER_STRAP_OVRD |
DPIO_TX1_STAGGER_MASK(0x1f) |
@ -1019,7 +1020,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
/* Deassert data lane reset */
__chv_data_lane_soft_reset(encoder, crtc_state, false);
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
}
void chv_phy_release_cl2_override(struct intel_encoder *encoder)
@ -1036,25 +1037,25 @@ void chv_phy_release_cl2_override(struct intel_encoder *encoder)
void chv_phy_post_pll_disable(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
enum dpio_phy phy = vlv_dig_port_to_phy(enc_to_dig_port(encoder));
enum pipe pipe = to_intel_crtc(old_crtc_state->uapi.crtc)->pipe;
u32 val;
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* disable left/right clock distribution */
if (pipe != PIPE_B) {
val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW5_CH0);
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0);
val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW5_CH0, val);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val);
} else {
val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW1_CH1);
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1);
val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW1_CH1, val);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val);
}
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
/*
* Leave the power down bit cleared for at least one
@ -1073,97 +1074,97 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder,
u32 demph_reg_value, u32 preemph_reg_value,
u32 uniqtranscale_reg_value, u32 tx3_demph)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
vlv_dpio_write(dev_priv, phy, VLV_TX_DW5_GRP(ch), 0x00000000);
vlv_dpio_write(dev_priv, phy, VLV_TX_DW4_GRP(ch), demph_reg_value);
vlv_dpio_write(dev_priv, phy, VLV_TX_DW2_GRP(ch),
uniqtranscale_reg_value);
vlv_dpio_write(dev_priv, phy, VLV_TX_DW3_GRP(ch), 0x0C782040);
vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), 0x00000000);
vlv_dpio_write(display->drm, phy, VLV_TX_DW4_GRP(ch), demph_reg_value);
vlv_dpio_write(display->drm, phy, VLV_TX_DW2_GRP(ch),
uniqtranscale_reg_value);
vlv_dpio_write(display->drm, phy, VLV_TX_DW3_GRP(ch), 0x0C782040);
if (tx3_demph)
vlv_dpio_write(dev_priv, phy, VLV_TX_DW4(ch, 3), tx3_demph);
vlv_dpio_write(display->drm, phy, VLV_TX_DW4(ch, 3), tx3_demph);
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW11_GRP(ch), 0x00030000);
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value);
vlv_dpio_write(dev_priv, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW11_GRP(ch), 0x00030000);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value);
vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN);
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
}
void vlv_phy_pre_pll_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
/* Program Tx lane resets to default */
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0_GRP(ch),
vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch),
DPIO_PCS_TX_LANE2_RESET |
DPIO_PCS_TX_LANE1_RESET);
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1_GRP(ch),
vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch),
DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
DPIO_PCS_CLK_DATAWIDTH_8_10 |
DPIO_PCS_CLK_SOFT_RESET);
/* Fix up inter-pair skew failure */
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00);
vlv_dpio_write(dev_priv, phy, VLV_TX_DW11_GRP(ch), 0x00001500);
vlv_dpio_write(dev_priv, phy, VLV_TX_DW14_GRP(ch), 0x40400000);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00);
vlv_dpio_write(display->drm, phy, VLV_TX_DW11_GRP(ch), 0x00001500);
vlv_dpio_write(display->drm, phy, VLV_TX_DW14_GRP(ch), 0x40400000);
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
}
void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
enum pipe pipe = crtc->pipe;
u32 val;
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* Enable clock channels for this port */
val = DPIO_PCS_USEDCLKCHANNEL_OVRRIDE;
if (pipe == PIPE_B)
val |= DPIO_PCS_USEDCLKCHANNEL;
val |= 0xc4;
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW8_GRP(ch), val);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW8_GRP(ch), val);
/* Program lane clock */
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW14_GRP(ch), 0x00760018);
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW23_GRP(ch), 0x00400888);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW14_GRP(ch), 0x00760018);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW23_GRP(ch), 0x00400888);
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
}
void vlv_phy_reset_lanes(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
vlv_dpio_get(dev_priv);
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0_GRP(ch), 0x00000000);
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060);
vlv_dpio_put(dev_priv);
vlv_dpio_get(display->drm);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch), 0x00000000);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060);
vlv_dpio_put(display->drm);
}
void vlv_wait_port_ready(struct intel_encoder *encoder,

View File

@ -6,13 +6,14 @@
#include <linux/kernel.h>
#include <linux/string_helpers.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include <drm/drm_print.h>
#include "intel_atomic.h"
#include "intel_crtc.h"
#include "intel_cx0_phy.h"
#include "intel_de.h"
#include "intel_display.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dpio_phy.h"
#include "intel_dpll.h"
@ -24,11 +25,11 @@
#include "vlv_dpio_phy_regs.h"
#include "vlv_sideband.h"
struct intel_dpll_funcs {
struct intel_dpll_global_funcs {
int (*crtc_compute_clock)(struct intel_atomic_state *state,
struct intel_crtc *crtc);
int (*crtc_get_shared_dpll)(struct intel_atomic_state *state,
struct intel_crtc *crtc);
int (*crtc_get_dpll)(struct intel_atomic_state *state,
struct intel_crtc *crtc);
};
struct intel_limit {
@ -513,8 +514,8 @@ void i9xx_crtc_clock_get(struct intel_crtc_state *crtc_state)
void vlv_crtc_clock_get(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 dpio_channel ch = vlv_pipe_to_channel(crtc->pipe);
enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe);
const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx;
@ -526,9 +527,9 @@ void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state)
if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0)
return;
vlv_dpio_get(dev_priv);
tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW3(ch));
vlv_dpio_put(dev_priv);
vlv_dpio_get(display->drm);
tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW3(ch));
vlv_dpio_put(display->drm);
clock.m1 = REG_FIELD_GET(DPIO_M1_DIV_MASK, tmp);
clock.m2 = REG_FIELD_GET(DPIO_M2_DIV_MASK, tmp);
@ -541,8 +542,8 @@ void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state)
void chv_crtc_clock_get(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 dpio_channel ch = vlv_pipe_to_channel(crtc->pipe);
enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe);
const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx;
@ -554,13 +555,13 @@ void chv_crtc_clock_get(struct intel_crtc_state *crtc_state)
if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0)
return;
vlv_dpio_get(dev_priv);
cmn_dw13 = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW13(ch));
pll_dw0 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW0(ch));
pll_dw1 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW1(ch));
pll_dw2 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW2(ch));
pll_dw3 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW3(ch));
vlv_dpio_put(dev_priv);
vlv_dpio_get(display->drm);
cmn_dw13 = vlv_dpio_read(display->drm, phy, CHV_CMN_DW13(ch));
pll_dw0 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW0(ch));
pll_dw1 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW1(ch));
pll_dw2 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW2(ch));
pll_dw3 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch));
vlv_dpio_put(display->drm);
clock.m1 = REG_FIELD_GET(DPIO_CHV_M1_DIV_MASK, pll_dw1) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0;
clock.m2 = REG_FIELD_GET(DPIO_CHV_M2_DIV_MASK, pll_dw0) << 22;
@ -1161,7 +1162,7 @@ static int hsw_crtc_compute_clock(struct intel_atomic_state *state,
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
return 0;
ret = intel_compute_shared_dplls(state, crtc, encoder);
ret = intel_dpll_compute(state, crtc, encoder);
if (ret)
return ret;
@ -1176,8 +1177,8 @@ static int hsw_crtc_compute_clock(struct intel_atomic_state *state,
return 0;
}
static int hsw_crtc_get_shared_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc)
static int hsw_crtc_get_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state =
@ -1189,7 +1190,7 @@ static int hsw_crtc_get_shared_dpll(struct intel_atomic_state *state,
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
return 0;
return intel_reserve_shared_dplls(state, crtc, encoder);
return intel_dpll_reserve(state, crtc, encoder);
}
static int dg2_crtc_compute_clock(struct intel_atomic_state *state,
@ -1223,7 +1224,7 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state,
if (ret)
return ret;
/* TODO: Do the readback via intel_compute_shared_dplls() */
/* TODO: Do the readback via intel_dpll_compute() */
crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll);
crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state);
@ -1394,7 +1395,7 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state,
ilk_compute_dpll(crtc_state, &crtc_state->dpll,
&crtc_state->dpll);
ret = intel_compute_shared_dplls(state, crtc, NULL);
ret = intel_dpll_compute(state, crtc, NULL);
if (ret)
return ret;
@ -1404,8 +1405,8 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state,
return ret;
}
static int ilk_crtc_get_shared_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc)
static int ilk_crtc_get_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@ -1414,7 +1415,7 @@ static int ilk_crtc_get_shared_dpll(struct intel_atomic_state *state,
if (!crtc_state->has_pch_encoder)
return 0;
return intel_reserve_shared_dplls(state, crtc, NULL);
return intel_dpll_reserve(state, crtc, NULL);
}
static u32 vlv_dpll(const struct intel_crtc_state *crtc_state)
@ -1690,45 +1691,45 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state,
return 0;
}
static const struct intel_dpll_funcs mtl_dpll_funcs = {
static const struct intel_dpll_global_funcs mtl_dpll_funcs = {
.crtc_compute_clock = mtl_crtc_compute_clock,
};
static const struct intel_dpll_funcs dg2_dpll_funcs = {
static const struct intel_dpll_global_funcs dg2_dpll_funcs = {
.crtc_compute_clock = dg2_crtc_compute_clock,
};
static const struct intel_dpll_funcs hsw_dpll_funcs = {
static const struct intel_dpll_global_funcs hsw_dpll_funcs = {
.crtc_compute_clock = hsw_crtc_compute_clock,
.crtc_get_shared_dpll = hsw_crtc_get_shared_dpll,
.crtc_get_dpll = hsw_crtc_get_dpll,
};
static const struct intel_dpll_funcs ilk_dpll_funcs = {
static const struct intel_dpll_global_funcs ilk_dpll_funcs = {
.crtc_compute_clock = ilk_crtc_compute_clock,
.crtc_get_shared_dpll = ilk_crtc_get_shared_dpll,
.crtc_get_dpll = ilk_crtc_get_dpll,
};
static const struct intel_dpll_funcs chv_dpll_funcs = {
static const struct intel_dpll_global_funcs chv_dpll_funcs = {
.crtc_compute_clock = chv_crtc_compute_clock,
};
static const struct intel_dpll_funcs vlv_dpll_funcs = {
static const struct intel_dpll_global_funcs vlv_dpll_funcs = {
.crtc_compute_clock = vlv_crtc_compute_clock,
};
static const struct intel_dpll_funcs g4x_dpll_funcs = {
static const struct intel_dpll_global_funcs g4x_dpll_funcs = {
.crtc_compute_clock = g4x_crtc_compute_clock,
};
static const struct intel_dpll_funcs pnv_dpll_funcs = {
static const struct intel_dpll_global_funcs pnv_dpll_funcs = {
.crtc_compute_clock = pnv_crtc_compute_clock,
};
static const struct intel_dpll_funcs i9xx_dpll_funcs = {
static const struct intel_dpll_global_funcs i9xx_dpll_funcs = {
.crtc_compute_clock = i9xx_crtc_compute_clock,
};
static const struct intel_dpll_funcs i8xx_dpll_funcs = {
static const struct intel_dpll_global_funcs i8xx_dpll_funcs = {
.crtc_compute_clock = i8xx_crtc_compute_clock,
};
@ -1758,8 +1759,8 @@ int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state,
return 0;
}
int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc)
int intel_dpll_crtc_get_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state =
@ -1767,15 +1768,15 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state,
int ret;
drm_WARN_ON(display->drm, !intel_crtc_needs_modeset(crtc_state));
drm_WARN_ON(display->drm, !crtc_state->hw.enable && crtc_state->shared_dpll);
drm_WARN_ON(display->drm, !crtc_state->hw.enable && crtc_state->intel_dpll);
if (!crtc_state->hw.enable || crtc_state->shared_dpll)
if (!crtc_state->hw.enable || crtc_state->intel_dpll)
return 0;
if (!display->funcs.dpll->crtc_get_shared_dpll)
if (!display->funcs.dpll->crtc_get_dpll)
return 0;
ret = display->funcs.dpll->crtc_get_shared_dpll(state, crtc);
ret = display->funcs.dpll->crtc_get_dpll(state, crtc);
if (ret) {
drm_dbg_kms(display->drm, "[CRTC:%d:%s] Couldn't get a shared DPLL\n",
crtc->base.base.id, crtc->base.name);
@ -1871,45 +1872,43 @@ void i9xx_enable_pll(const struct intel_crtc_state *crtc_state)
static void vlv_pllb_recal_opamp(struct intel_display *display,
enum dpio_phy phy, enum dpio_channel ch)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 tmp;
/*
* PLLB opamp always calibrates to max value of 0x3f, force enable it
* and set it to a reasonable value instead.
*/
tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW17(ch));
tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch));
tmp &= 0xffffff00;
tmp |= 0x00000030;
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW17(ch), tmp);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp);
tmp = vlv_dpio_read(dev_priv, phy, VLV_REF_DW11);
tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11);
tmp &= 0x00ffffff;
tmp |= 0x8c000000;
vlv_dpio_write(dev_priv, phy, VLV_REF_DW11, tmp);
vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp);
tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW17(ch));
tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch));
tmp &= 0xffffff00;
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW17(ch), tmp);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp);
tmp = vlv_dpio_read(dev_priv, phy, VLV_REF_DW11);
tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11);
tmp &= 0x00ffffff;
tmp |= 0xb0000000;
vlv_dpio_write(dev_priv, phy, VLV_REF_DW11, tmp);
vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp);
}
static void vlv_prepare_pll(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);
const struct dpll *clock = &crtc_state->dpll;
enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe);
enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe);
enum pipe pipe = crtc->pipe;
u32 tmp, coreclk;
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* See eDP HDMI DPIO driver vbios notes doc */
@ -1918,15 +1917,15 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state)
vlv_pllb_recal_opamp(display, phy, ch);
/* Set up Tx target for periodic Rcomp update */
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW17_BCAST, 0x0100000f);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW17_BCAST, 0x0100000f);
/* Disable target IRef on PLL */
tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW16(ch));
tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW16(ch));
tmp &= 0x00ffffff;
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW16(ch), tmp);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW16(ch), tmp);
/* Disable fast lock */
vlv_dpio_write(dev_priv, phy, VLV_CMN_DW0, 0x610);
vlv_dpio_write(display->drm, phy, VLV_CMN_DW0, 0x610);
/* Set idtafcrecal before PLL is enabled */
tmp = DPIO_M1_DIV(clock->m1) |
@ -1942,48 +1941,42 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state)
* Note: don't use the DAC post divider as it seems unstable.
*/
tmp |= DPIO_S1_DIV(DPIO_S1_DIV_HDMIDP);
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW3(ch), tmp);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp);
tmp |= DPIO_ENABLE_CALIBRATION;
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW3(ch), tmp);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp);
/* Set HBR and RBR LPF coefficients */
if (crtc_state->port_clock == 162000 ||
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG) ||
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW18(ch),
0x009f0003);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x009f0003);
else
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW18(ch),
0x00d0000f);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x00d0000f);
if (intel_crtc_has_dp_encoder(crtc_state)) {
/* Use SSC source */
if (pipe == PIPE_A)
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch),
0x0df40000);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000);
else
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch),
0x0df70000);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000);
} else { /* HDMI or VGA */
/* Use bend source */
if (pipe == PIPE_A)
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch),
0x0df70000);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000);
else
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch),
0x0df40000);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000);
}
coreclk = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW7(ch));
coreclk = vlv_dpio_read(display->drm, phy, VLV_PLL_DW7(ch));
coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
if (intel_crtc_has_dp_encoder(crtc_state))
coreclk |= 0x01000000;
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW7(ch), coreclk);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW7(ch), coreclk);
vlv_dpio_write(dev_priv, phy, VLV_PLL_DW19(ch), 0x87871000);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW19(ch), 0x87871000);
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
}
static void _vlv_enable_pll(const struct intel_crtc_state *crtc_state)
@ -2028,8 +2021,8 @@ void vlv_enable_pll(const struct intel_crtc_state *crtc_state)
static void chv_prepare_pll(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);
const struct dpll *clock = &crtc_state->dpll;
enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe);
enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe);
@ -2038,44 +2031,44 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state)
m2_frac = clock->m2 & 0x3fffff;
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* p1 and p2 divider */
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW13(ch),
vlv_dpio_write(display->drm, phy, CHV_CMN_DW13(ch),
DPIO_CHV_S1_DIV(5) |
DPIO_CHV_P1_DIV(clock->p1) |
DPIO_CHV_P2_DIV(clock->p2) |
DPIO_CHV_K_DIV(1));
/* Feedback post-divider - m2 */
vlv_dpio_write(dev_priv, phy, CHV_PLL_DW0(ch),
vlv_dpio_write(display->drm, phy, CHV_PLL_DW0(ch),
DPIO_CHV_M2_DIV(clock->m2 >> 22));
/* Feedback refclk divider - n and m1 */
vlv_dpio_write(dev_priv, phy, CHV_PLL_DW1(ch),
vlv_dpio_write(display->drm, phy, CHV_PLL_DW1(ch),
DPIO_CHV_M1_DIV(DPIO_CHV_M1_DIV_BY_2) |
DPIO_CHV_N_DIV(1));
/* M2 fraction division */
vlv_dpio_write(dev_priv, phy, CHV_PLL_DW2(ch),
vlv_dpio_write(display->drm, phy, CHV_PLL_DW2(ch),
DPIO_CHV_M2_FRAC_DIV(m2_frac));
/* M2 fraction division enable */
tmp = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW3(ch));
tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch));
tmp &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN);
tmp |= DPIO_CHV_FEEDFWD_GAIN(2);
if (m2_frac)
tmp |= DPIO_CHV_FRAC_DIV_EN;
vlv_dpio_write(dev_priv, phy, CHV_PLL_DW3(ch), tmp);
vlv_dpio_write(display->drm, phy, CHV_PLL_DW3(ch), tmp);
/* Program digital lock detect threshold */
tmp = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW9(ch));
tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW9(ch));
tmp &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK |
DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE);
tmp |= DPIO_CHV_INT_LOCK_THRESHOLD(0x5);
if (!m2_frac)
tmp |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE;
vlv_dpio_write(dev_priv, phy, CHV_PLL_DW9(ch), tmp);
vlv_dpio_write(display->drm, phy, CHV_PLL_DW9(ch), tmp);
/* Loop filter */
if (clock->vco == 5400000) {
@ -2100,40 +2093,39 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state)
DPIO_CHV_GAIN_CTRL(0x3);
tribuf_calcntr = 0;
}
vlv_dpio_write(dev_priv, phy, CHV_PLL_DW6(ch), loopfilter);
vlv_dpio_write(display->drm, phy, CHV_PLL_DW6(ch), loopfilter);
tmp = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW8(ch));
tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW8(ch));
tmp &= ~DPIO_CHV_TDC_TARGET_CNT_MASK;
tmp |= DPIO_CHV_TDC_TARGET_CNT(tribuf_calcntr);
vlv_dpio_write(dev_priv, phy, CHV_PLL_DW8(ch), tmp);
vlv_dpio_write(display->drm, phy, CHV_PLL_DW8(ch), tmp);
/* AFC Recal */
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW14(ch),
vlv_dpio_read(dev_priv, phy, CHV_CMN_DW14(ch)) |
vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch),
vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)) |
DPIO_AFC_RECAL);
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
}
static void _chv_enable_pll(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);
const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx;
enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe);
enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe);
enum pipe pipe = crtc->pipe;
u32 tmp;
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* Enable back the 10bit clock to display controller */
tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW14(ch));
tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch));
tmp |= DPIO_DCLKP_EN;
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW14(ch), tmp);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), tmp);
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
/*
* Need to wait > 100ns between dclkp clock enable bit and PLL enable.
@ -2252,7 +2244,6 @@ void vlv_disable_pll(struct intel_display *display, enum pipe pipe)
void chv_disable_pll(struct intel_display *display, enum pipe pipe)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum dpio_channel ch = vlv_pipe_to_channel(pipe);
enum dpio_phy phy = vlv_pipe_to_phy(pipe);
u32 val;
@ -2268,14 +2259,14 @@ void chv_disable_pll(struct intel_display *display, enum pipe pipe)
intel_de_write(display, DPLL(display, pipe), val);
intel_de_posting_read(display, DPLL(display, pipe));
vlv_dpio_get(dev_priv);
vlv_dpio_get(display->drm);
/* Disable 10bit clock to display controller */
val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW14(ch));
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch));
val &= ~DPIO_DCLKP_EN;
vlv_dpio_write(dev_priv, phy, CHV_CMN_DW14(ch), val);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), val);
vlv_dpio_put(dev_priv);
vlv_dpio_put(display->drm);
}
void i9xx_disable_pll(const struct intel_crtc_state *crtc_state)

View File

@ -19,8 +19,8 @@ struct intel_dpll_hw_state;
void intel_dpll_init_clock_hook(struct intel_display *display);
int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state,
struct intel_crtc *crtc);
int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc);
int intel_dpll_crtc_get_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc);
int i9xx_calc_dpll_params(int refclk, struct dpll *clock);
u32 i9xx_dpll_compute_fp(const struct dpll *dpll);
void i9xx_dpll_get_hw_state(struct intel_crtc *crtc,

File diff suppressed because it is too large Load Diff

View File

@ -30,18 +30,18 @@
#include "intel_display_power.h"
#include "intel_wakeref.h"
#define for_each_shared_dpll(__display, __pll, __i) \
for ((__i) = 0; (__i) < (__display)->dpll.num_shared_dpll && \
((__pll) = &(__display)->dpll.shared_dplls[(__i)]) ; (__i)++)
#define for_each_dpll(__display, __pll, __i) \
for ((__i) = 0; (__i) < (__display)->dpll.num_dpll && \
((__pll) = &(__display)->dpll.dplls[(__i)]) ; (__i)++)
enum tc_port;
struct drm_printer;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_dpll_funcs;
struct intel_encoder;
struct intel_shared_dpll;
struct intel_shared_dpll_funcs;
/**
* enum intel_dpll_id - possible DPLL ids
@ -280,7 +280,7 @@ struct intel_dpll_hw_state {
};
/**
* struct intel_shared_dpll_state - hold the DPLL atomic state
* struct intel_dpll_state - hold the DPLL atomic state
*
* This structure holds an atomic state for the DPLL, that can represent
* either its current state (in struct &intel_shared_dpll) or a desired
@ -289,7 +289,7 @@ struct intel_dpll_hw_state {
*
* See also intel_reserve_shared_dplls() and intel_release_shared_dplls().
*/
struct intel_shared_dpll_state {
struct intel_dpll_state {
/**
* @pipe_mask: mask of pipes using this DPLL, active or not
*/
@ -314,7 +314,7 @@ struct dpll_info {
/**
* @funcs: platform specific hooks
*/
const struct intel_shared_dpll_funcs *funcs;
const struct intel_dpll_funcs *funcs;
/**
* @id: unique identifier for this DPLL
@ -344,16 +344,16 @@ struct dpll_info {
};
/**
* struct intel_shared_dpll - display PLL with tracked state and users
* struct intel_dpll - display PLL with tracked state and users
*/
struct intel_shared_dpll {
struct intel_dpll {
/**
* @state:
*
* Store the state for the pll, including its hw state
* and CRTCs using it.
*/
struct intel_shared_dpll_state state;
struct intel_dpll_state state;
/**
* @index: index for atomic state
@ -387,41 +387,41 @@ struct intel_shared_dpll {
#define SKL_DPLL2 2
#define SKL_DPLL3 3
/* shared dpll functions */
struct intel_shared_dpll *
intel_get_shared_dpll_by_id(struct intel_display *display,
enum intel_dpll_id id);
void assert_shared_dpll(struct intel_display *display,
struct intel_shared_dpll *pll,
bool state);
#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
int intel_compute_shared_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder);
int intel_reserve_shared_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder);
void intel_release_shared_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc,
const struct intel_shared_dpll *pll,
struct intel_shared_dpll_state *shared_dpll_state);
/* dpll functions */
struct intel_dpll *
intel_get_dpll_by_id(struct intel_display *display,
enum intel_dpll_id id);
void assert_dpll(struct intel_display *display,
struct intel_dpll *pll,
bool state);
#define assert_dpll_enabled(d, p) assert_dpll(d, p, true)
#define assert_dpll_disabled(d, p) assert_dpll(d, p, false)
int intel_dpll_compute(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder);
int intel_dpll_reserve(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder);
void intel_dpll_release(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_dpll_crtc_put(const struct intel_crtc *crtc,
const struct intel_dpll *pll,
struct intel_dpll_state *shared_dpll_state);
void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state,
enum icl_port_dpll_id port_dpll_id);
void intel_update_active_dpll(struct intel_atomic_state *state,
void intel_dpll_update_active(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder);
int intel_dpll_get_freq(struct intel_display *display,
const struct intel_shared_dpll *pll,
const struct intel_dpll *pll,
const struct intel_dpll_hw_state *dpll_hw_state);
bool intel_dpll_get_hw_state(struct intel_display *display,
struct intel_shared_dpll *pll,
struct intel_dpll *pll,
struct intel_dpll_hw_state *dpll_hw_state);
void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_shared_dpll_swap_state(struct intel_atomic_state *state);
void intel_shared_dpll_init(struct intel_display *display);
void intel_dpll_enable(const struct intel_crtc_state *crtc_state);
void intel_dpll_disable(const struct intel_crtc_state *crtc_state);
void intel_dpll_swap_state(struct intel_atomic_state *state);
void intel_dpll_init(struct intel_display *display);
void intel_dpll_update_ref_clks(struct intel_display *display);
void intel_dpll_readout_hw_state(struct intel_display *display);
void intel_dpll_sanitize_state(struct intel_display *display);
@ -435,8 +435,8 @@ bool intel_dpll_compare_hw_state(struct intel_display *display,
enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port);
bool intel_dpll_is_combophy(enum intel_dpll_id id);
void intel_shared_dpll_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state);
void intel_dpll_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_dpll_verify_disabled(struct intel_atomic_state *state);
#endif /* _INTEL_DPLL_MGR_H_ */

View File

@ -9,6 +9,7 @@
#include "gt/gen8_ppgtt.h"
#include "i915_drv.h"
#include "intel_display_core.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dpt.h"
@ -126,7 +127,7 @@ struct i915_vma *intel_dpt_pin_to_ggtt(struct i915_address_space *vm,
unsigned int alignment)
{
struct drm_i915_private *i915 = vm->i915;
struct intel_display *display = &i915->display;
struct intel_display *display = i915->display;
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
struct ref_tracker *wakeref;
struct i915_vma *vma;

View File

@ -3,8 +3,8 @@
* Copyright © 2023 Intel Corporation
*/
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dpt_common.h"
#include "skl_universal_plane_regs.h"

View File

@ -6,9 +6,9 @@
#include <linux/debugfs.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_drrs.h"
#include "intel_frontbuffer.h"

View File

@ -7,11 +7,10 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include "i915_irq.h"
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dsb.h"
@ -94,6 +93,10 @@ struct intel_dsb {
/* see DSB_REG_VALUE_MASK */
#define DSB_OPCODE_POLL 0xA
/* see DSB_REG_VALUE_MASK */
#define DSB_OPCODE_GOSUB 0xC /* ptl+ */
#define DSB_GOSUB_HEAD_SHIFT 26
#define DSB_GOSUB_TAIL_SHIFT 0
#define DSB_GOSUB_CONVERT_ADDR(x) ((x) >> 6)
static bool pre_commit_is_vrr_active(struct intel_atomic_state *state,
struct intel_crtc *crtc)
@ -205,6 +208,15 @@ static bool assert_dsb_has_room(struct intel_dsb *dsb)
crtc->base.base.id, crtc->base.name, dsb->id);
}
static bool assert_dsb_tail_is_aligned(struct intel_dsb *dsb)
{
struct intel_crtc *crtc = dsb->crtc;
struct intel_display *display = to_intel_display(crtc->base.dev);
return !drm_WARN_ON(display->drm,
!IS_ALIGNED(dsb->free_pos * 4, CACHELINE_BYTES));
}
static void intel_dsb_dump(struct intel_dsb *dsb)
{
struct intel_crtc *crtc = dsb->crtc;
@ -229,13 +241,40 @@ static bool is_dsb_busy(struct intel_display *display, enum pipe pipe,
return intel_de_read_fw(display, DSB_CTRL(pipe, dsb_id)) & DSB_STATUS_BUSY;
}
unsigned int intel_dsb_size(struct intel_dsb *dsb)
{
return dsb->free_pos * 4;
}
unsigned int intel_dsb_head(struct intel_dsb *dsb)
{
return intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf);
}
static unsigned int intel_dsb_tail(struct intel_dsb *dsb)
{
return intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf) + intel_dsb_size(dsb);
}
static void intel_dsb_ins_align(struct intel_dsb *dsb)
{
/*
* Every instruction should be 8 byte aligned.
*
* The only way to get unaligned free_pos is via
* intel_dsb_reg_write_indexed() which already
* makes sure the next dword is zeroed, so no need
* to clear it here.
*/
dsb->free_pos = ALIGN(dsb->free_pos, 2);
}
static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
{
if (!assert_dsb_has_room(dsb))
return;
/* Every instruction should be 8 byte aligned. */
dsb->free_pos = ALIGN(dsb->free_pos, 2);
intel_dsb_ins_align(dsb);
dsb->ins_start_offset = dsb->free_pos;
dsb->ins[0] = ldw;
@ -493,6 +532,8 @@ static void intel_dsb_align_tail(struct intel_dsb *dsb)
{
u32 aligned_tail, tail;
intel_dsb_ins_align(dsb);
tail = dsb->free_pos * 4;
aligned_tail = ALIGN(tail, CACHELINE_BYTES);
@ -503,20 +544,90 @@ static void intel_dsb_align_tail(struct intel_dsb *dsb)
dsb->free_pos = aligned_tail / 4;
}
void intel_dsb_finish(struct intel_dsb *dsb)
static void intel_dsb_gosub_align(struct intel_dsb *dsb)
{
struct intel_crtc *crtc = dsb->crtc;
u32 aligned_tail, tail;
intel_dsb_ins_align(dsb);
tail = dsb->free_pos * 4;
aligned_tail = ALIGN(tail, CACHELINE_BYTES);
/*
* DSB_FORCE_DEWAKE remains active even after DSB is
* disabled, so make sure to clear it (if set during
* intel_dsb_commit()). And clear DSB_ENABLE_DEWAKE as
* well for good measure.
* Wa_16024917128
* "Ensure GOSUB is not placed in cacheline QW slot 6 or 7 (numbered 0-7)"
*/
intel_dsb_reg_write(dsb, DSB_PMCTRL(crtc->pipe, dsb->id), 0);
intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id),
DSB_FORCE_DEWAKE, 0);
if (aligned_tail - tail <= 2 * 8)
intel_dsb_buffer_memset(&dsb->dsb_buf, dsb->free_pos, 0,
aligned_tail - tail);
dsb->free_pos = aligned_tail / 4;
}
void intel_dsb_gosub(struct intel_dsb *dsb,
struct intel_dsb *sub_dsb)
{
struct intel_crtc *crtc = dsb->crtc;
struct intel_display *display = to_intel_display(crtc->base.dev);
unsigned int head, tail;
u64 head_tail;
if (drm_WARN_ON(display->drm, dsb->id != sub_dsb->id))
return;
if (!assert_dsb_tail_is_aligned(sub_dsb))
return;
intel_dsb_gosub_align(dsb);
head = intel_dsb_head(sub_dsb);
tail = intel_dsb_tail(sub_dsb);
/*
* The GOSUB instruction has the following memory layout.
*
* +------------------------------------------------------------+
* | Opcode | Rsvd | Head Ptr | Tail Ptr |
* | 0x0c | | | |
* +------------------------------------------------------------+
* |<- 8bits->|<- 4bits ->|<-- 26bits -->|<-- 26bits -->|
*
* We have only 26 bits each to represent the head and tail
* pointers even though the addresses itself are of 32 bit. However, this
* is not a problem because the addresses are 64 bit aligned and therefore
* the last 6 bits are always Zero's. Therefore, we right shift the address
* by 6 before embedding it into the GOSUB instruction.
*/
head_tail = ((u64)(DSB_GOSUB_CONVERT_ADDR(head)) << DSB_GOSUB_HEAD_SHIFT) |
((u64)(DSB_GOSUB_CONVERT_ADDR(tail)) << DSB_GOSUB_TAIL_SHIFT);
intel_dsb_emit(dsb, lower_32_bits(head_tail),
(DSB_OPCODE_GOSUB << DSB_OPCODE_SHIFT) |
upper_32_bits(head_tail));
/*
* "NOTE: the instructions within the cacheline
* FOLLOWING the GOSUB instruction must be NOPs."
*/
intel_dsb_align_tail(dsb);
}
void intel_dsb_gosub_finish(struct intel_dsb *dsb)
{
intel_dsb_align_tail(dsb);
/*
* Wa_16024917128
* "Ensure that all subroutines called by GOSUB end with a cacheline of NOPs"
*/
intel_dsb_noop(dsb, 8);
intel_dsb_buffer_flush_map(&dsb->dsb_buf);
}
void intel_dsb_finish(struct intel_dsb *dsb)
{
intel_dsb_align_tail(dsb);
intel_dsb_buffer_flush_map(&dsb->dsb_buf);
@ -539,6 +650,9 @@ static u32 dsb_error_int_status(struct intel_display *display)
if (DISPLAY_VER(display) >= 14)
errors |= DSB_ATS_FAULT_INT_STATUS;
if (DISPLAY_VER(display) >= 30)
errors |= DSB_GOSUB_INT_STATUS;
return errors;
}
@ -553,17 +667,46 @@ static u32 dsb_error_int_en(struct intel_display *display)
if (DISPLAY_VER(display) >= 14)
errors |= DSB_ATS_FAULT_INT_EN;
/*
* Wa_16024917128
* "Disable nested GOSUB interrupt (DSB_INTERRUPT bit 21)"
*/
if (0 && DISPLAY_VER(display) >= 30)
errors |= DSB_GOSUB_INT_EN;
return errors;
}
/*
* FIXME calibrate these sensibly, ideally compute based on
* the number of regisetrs to be written. But that requires
* measuring the actual DSB execution speed on each platform
* (and the speed also depends on CDCLK and memory clock)...
*/
static int intel_dsb_noarm_exec_time_us(void)
{
return 80;
}
static int intel_dsb_arm_exec_time_us(void)
{
return 20;
}
int intel_dsb_exec_time_us(void)
{
return intel_dsb_noarm_exec_time_us() +
intel_dsb_arm_exec_time_us();
}
void intel_dsb_vblank_evade(struct intel_atomic_state *state,
struct intel_dsb *dsb)
{
struct intel_crtc *crtc = dsb->crtc;
const struct intel_crtc_state *crtc_state =
intel_pre_commit_crtc_state(state, crtc);
/* FIXME calibrate sensibly */
int latency = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 20);
int latency = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode,
intel_dsb_arm_exec_time_us());
int start, end;
/*
@ -605,13 +748,11 @@ static void _intel_dsb_chain(struct intel_atomic_state *state,
struct intel_display *display = to_intel_display(state->base.dev);
struct intel_crtc *crtc = dsb->crtc;
enum pipe pipe = crtc->pipe;
u32 tail;
if (drm_WARN_ON(display->drm, dsb->id == chained_dsb->id))
return;
tail = chained_dsb->free_pos * 4;
if (drm_WARN_ON(display->drm, !IS_ALIGNED(tail, CACHELINE_BYTES)))
if (!assert_dsb_tail_is_aligned(chained_dsb))
return;
intel_dsb_reg_write(dsb, DSB_CTRL(pipe, chained_dsb->id),
@ -631,13 +772,15 @@ static void _intel_dsb_chain(struct intel_atomic_state *state,
intel_dsb_reg_write(dsb, DSB_PMCTRL(pipe, chained_dsb->id),
DSB_ENABLE_DEWAKE |
DSB_SCANLINE_FOR_DEWAKE(hw_dewake_scanline));
} else {
intel_dsb_reg_write(dsb, DSB_PMCTRL(pipe, chained_dsb->id), 0);
}
intel_dsb_reg_write(dsb, DSB_HEAD(pipe, chained_dsb->id),
intel_dsb_buffer_ggtt_offset(&chained_dsb->dsb_buf));
intel_dsb_head(chained_dsb));
intel_dsb_reg_write(dsb, DSB_TAIL(pipe, chained_dsb->id),
intel_dsb_buffer_ggtt_offset(&chained_dsb->dsb_buf) + tail);
intel_dsb_tail(chained_dsb));
if (ctrl & DSB_WAIT_FOR_VBLANK) {
/*
@ -652,6 +795,13 @@ static void _intel_dsb_chain(struct intel_atomic_state *state,
intel_dsb_wait_scanline_out(state, dsb,
dsb_dewake_scanline_start(state, crtc),
dsb_dewake_scanline_end(state, crtc));
/*
* DSB_FORCE_DEWAKE remains active even after DSB is
* disabled, so make sure to clear it.
*/
intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id),
DSB_FORCE_DEWAKE, 0);
}
}
@ -676,16 +826,19 @@ void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state,
intel_dsb_wait_usec(dsb, usecs);
}
static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
int hw_dewake_scanline)
/**
* intel_dsb_commit() - Trigger workload execution of DSB.
* @dsb: DSB context
*
* This function is used to do actual write to hardware using DSB.
*/
void intel_dsb_commit(struct intel_dsb *dsb)
{
struct intel_crtc *crtc = dsb->crtc;
struct intel_display *display = to_intel_display(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 tail;
tail = dsb->free_pos * 4;
if (drm_WARN_ON(display->drm, !IS_ALIGNED(tail, CACHELINE_BYTES)))
if (!assert_dsb_tail_is_aligned(dsb))
return;
if (is_dsb_busy(display, pipe, dsb->id)) {
@ -695,7 +848,7 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
}
intel_de_write_fw(display, DSB_CTRL(pipe, dsb->id),
ctrl | DSB_ENABLE);
DSB_ENABLE);
intel_de_write_fw(display, DSB_CHICKEN(pipe, dsb->id),
dsb->chicken);
@ -704,45 +857,13 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
dsb_error_int_status(display) | DSB_PROG_INT_STATUS |
dsb_error_int_en(display) | DSB_PROG_INT_EN);
intel_de_write_fw(display, DSB_PMCTRL(pipe, dsb->id), 0);
intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id),
intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf));
if (hw_dewake_scanline >= 0) {
int diff, position;
intel_de_write_fw(display, DSB_PMCTRL(pipe, dsb->id),
DSB_ENABLE_DEWAKE |
DSB_SCANLINE_FOR_DEWAKE(hw_dewake_scanline));
/*
* Force DEwake immediately if we're already past
* or close to racing past the target scanline.
*/
position = intel_de_read_fw(display, PIPEDSL(display, pipe)) & PIPEDSL_LINE_MASK;
diff = hw_dewake_scanline - position;
intel_de_write_fw(display, DSB_PMCTRL_2(pipe, dsb->id),
(diff >= 0 && diff < 5 ? DSB_FORCE_DEWAKE : 0) |
DSB_BLOCK_DEWAKE_EXTENSION);
}
intel_dsb_head(dsb));
intel_de_write_fw(display, DSB_TAIL(pipe, dsb->id),
intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf) + tail);
}
/**
* intel_dsb_commit() - Trigger workload execution of DSB.
* @dsb: DSB context
* @wait_for_vblank: wait for vblank before executing
*
* This function is used to do actual write to hardware using DSB.
*/
void intel_dsb_commit(struct intel_dsb *dsb,
bool wait_for_vblank)
{
_intel_dsb_commit(dsb,
wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0,
wait_for_vblank ? dsb->hw_dewake_scanline : -1);
intel_dsb_tail(dsb));
}
void intel_dsb_wait(struct intel_dsb *dsb)
@ -895,4 +1016,7 @@ void intel_dsb_irq_handler(struct intel_display *display,
if (errors & DSB_POLL_ERR_INT_STATUS)
drm_err(display->drm, "[CRTC:%d:%s] DSB %d poll error\n",
crtc->base.base.id, crtc->base.name, dsb_id);
if (errors & DSB_GOSUB_INT_STATUS)
drm_err(display->drm, "[CRTC:%d:%s] DSB %d GOSUB programming error\n",
crtc->base.base.id, crtc->base.name, dsb_id);
}

View File

@ -26,12 +26,16 @@ enum intel_dsb_id {
I915_MAX_DSBS,
};
unsigned int intel_dsb_size(struct intel_dsb *dsb);
unsigned int intel_dsb_head(struct intel_dsb *dsb);
struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
struct intel_crtc *crtc,
enum intel_dsb_id dsb_id,
unsigned int max_cmds);
void intel_dsb_finish(struct intel_dsb *dsb);
void intel_dsb_gosub_finish(struct intel_dsb *dsb);
void intel_dsb_cleanup(struct intel_dsb *dsb);
int intel_dsb_exec_time_us(void);
void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val);
void intel_dsb_reg_write_indexed(struct intel_dsb *dsb,
@ -57,13 +61,14 @@ void intel_dsb_vblank_evade(struct intel_atomic_state *state,
void intel_dsb_poll(struct intel_dsb *dsb,
i915_reg_t reg, u32 mask, u32 val,
int wait_us, int count);
void intel_dsb_gosub(struct intel_dsb *dsb,
struct intel_dsb *sub_dsb);
void intel_dsb_chain(struct intel_atomic_state *state,
struct intel_dsb *dsb,
struct intel_dsb *chained_dsb,
bool wait_for_vblank);
void intel_dsb_commit(struct intel_dsb *dsb,
bool wait_for_vblank);
void intel_dsb_commit(struct intel_dsb *dsb);
void intel_dsb_wait(struct intel_dsb *dsb);
void intel_dsb_irq_handler(struct intel_display *display,

View File

@ -51,11 +51,13 @@
#define DSB_RESET_SM_STATE_MASK REG_GENMASK(5, 4)
#define DSB_RUN_SM_STATE_MASK REG_GENMASK(2, 0)
#define DSB_INTERRUPT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x28)
#define DSB_GOSUB_INT_EN REG_BIT(21) /* ptl+ */
#define DSB_ATS_FAULT_INT_EN REG_BIT(20) /* mtl+ */
#define DSB_GTT_FAULT_INT_EN REG_BIT(19)
#define DSB_RSPTIMEOUT_INT_EN REG_BIT(18)
#define DSB_POLL_ERR_INT_EN REG_BIT(17)
#define DSB_PROG_INT_EN REG_BIT(16)
#define DSB_GOSUB_INT_STATUS REG_BIT(5) /* ptl+ */
#define DSB_ATS_FAULT_INT_STATUS REG_BIT(4) /* mtl+ */
#define DSB_GTT_FAULT_INT_STATUS REG_BIT(3)
#define DSB_RSPTIMEOUT_INT_STATUS REG_BIT(2)

View File

@ -36,12 +36,11 @@
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_print.h>
#include <video/mipi_display.h>
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dsi.h"
#include "intel_dsi_vbt.h"

View File

@ -34,11 +34,11 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_connector.h"
#include "intel_de.h"
#include "intel_display_driver.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dvo.h"
#include "intel_dvo_dev.h"

View File

@ -6,7 +6,7 @@
#include <linux/workqueue.h>
#include "i915_drv.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_encoder.h"

View File

@ -14,6 +14,7 @@
#include "intel_atomic_plane.h"
#include "intel_bo.h"
#include "intel_display.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_dpt.h"
#include "intel_fb.h"

View File

@ -8,6 +8,7 @@
#include "gem/i915_gem_object.h"
#include "i915_drv.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fb_bo.h"

View File

@ -12,6 +12,7 @@
#include "i915_drv.h"
#include "intel_atomic_plane.h"
#include "intel_display_core.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dpt.h"

View File

@ -45,9 +45,10 @@
#include <drm/drm_fourcc.h>
#include "gem/i915_gem_stolen.h"
#include "gt/intel_gt_types.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_utils.h"
#include "i915_vgpu.h"
#include "i915_vma.h"
@ -55,6 +56,7 @@
#include "intel_cdclk.h"
#include "intel_de.h"
#include "intel_display_device.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"

View File

@ -8,6 +8,7 @@
#include "gem/i915_gem_lmem.h"
#include "i915_drv.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fbdev_fb.h"

View File

@ -14,6 +14,7 @@
#include "intel_crtc.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_fdi.h"
@ -910,7 +911,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
intel_de_write(display, FDI_RX_CTL(PIPE_A), rx_ctl_val);
/* Configure Port Clock Select */
drm_WARN_ON(display->drm, crtc_state->shared_dpll->info->id != DPLL_ID_SPLL);
drm_WARN_ON(display->drm, crtc_state->intel_dpll->info->id != DPLL_ID_SPLL);
intel_ddi_enable_clock(encoder, crtc_state);
/* Start the training iterating through available voltages and emphasis,

View File

@ -30,6 +30,7 @@
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_regs.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_fbc.h"

View File

@ -37,6 +37,7 @@
#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_gmbus.h"
#include "intel_gmbus_regs.h"
@ -414,7 +415,7 @@ gmbus_wait_idle(struct intel_display *display)
add_wait_queue(&display->gmbus.wait_queue, &wait);
intel_de_write_fw(display, GMBUS4(display), irq_enable);
ret = intel_de_wait_fw(display, GMBUS2(display), GMBUS_ACTIVE, 0, 10);
ret = intel_de_wait_fw(display, GMBUS2(display), GMBUS_ACTIVE, 0, 10, NULL);
intel_de_write_fw(display, GMBUS4(display), 0);
remove_wait_queue(&display->gmbus.wait_queue, &wait);

View File

@ -6,7 +6,7 @@
#ifndef __INTEL_GMBUS_REGS_H__
#define __INTEL_GMBUS_REGS_H__
#include "i915_reg_defs.h"
#include "intel_display_reg_defs.h"
#define __GMBUS_MMIO_BASE(__display) ((__display)->gmbus.mmio_base)

View File

@ -22,6 +22,7 @@
#include "intel_de.h"
#include "intel_display_power.h"
#include "intel_display_power_well.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dp_mst.h"

View File

@ -41,11 +41,9 @@
#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_reg.h"
#include "i915_utils.h"
#include "intel_atomic.h"
#include "intel_audio.h"
@ -54,6 +52,7 @@
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_driver.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_gmbus.h"

View File

@ -30,8 +30,10 @@
#include "i915_irq.h"
#include "intel_connector.h"
#include "intel_display_power.h"
#include "intel_display_core.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_hdcp.h"
#include "intel_hotplug.h"
#include "intel_hotplug_irq.h"
@ -905,9 +907,14 @@ void intel_hpd_poll_enable(struct intel_display *display)
*/
void intel_hpd_poll_disable(struct intel_display *display)
{
struct intel_encoder *encoder;
if (!HAS_DISPLAY(display))
return;
for_each_intel_dp(display->drm, encoder)
intel_dp_dpcd_set_probe(enc_to_intel_dp(encoder), true);
WRITE_ONCE(display->hotplug.poll_enabled, false);
spin_lock_irq(&display->irq.lock);

View File

@ -9,6 +9,7 @@
#include "i915_utils.h"
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp_aux.h"
#include "intel_gmbus.h"

View File

@ -6,7 +6,7 @@
#ifndef __INTEL_HTI_REGS_H__
#define __INTEL_HTI_REGS_H__
#include "i915_reg_defs.h"
#include "intel_display_reg_defs.h"
#define HDPORT_STATE _MMIO(0x45050)
#define HDPORT_DPLL_USED_MASK REG_GENMASK(15, 12)

View File

@ -3,6 +3,11 @@
* Copyright © 2023 Intel Corporation
*/
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/int_log.h>
#include <linux/math.h>
#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
@ -10,11 +15,33 @@
#include "intel_crtc.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_mst.h"
#include "intel_dp_tunnel.h"
#include "intel_fdi.h"
#include "intel_link_bw.h"
static int get_forced_link_bpp_x16(struct intel_atomic_state *state,
const struct intel_crtc *crtc)
{
struct intel_digital_connector_state *conn_state;
struct intel_connector *connector;
int force_bpp_x16 = INT_MAX;
int i;
for_each_new_intel_connector_in_state(state, connector, conn_state, i) {
if (conn_state->base.crtc != &crtc->base)
continue;
if (!connector->link.force_bpp_x16)
continue;
force_bpp_x16 = min(force_bpp_x16, connector->link.force_bpp_x16);
}
return force_bpp_x16 < INT_MAX ? force_bpp_x16 : 0;
}
/**
* intel_link_bw_init_limits - initialize BW limits
* @state: Atomic state
@ -31,9 +58,10 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state,
limits->force_fec_pipes = 0;
limits->bpp_limit_reached_pipes = 0;
for_each_pipe(display, pipe) {
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
const struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state,
intel_crtc_for_pipe(display, pipe));
intel_atomic_get_new_crtc_state(state, crtc);
int forced_bpp_x16 = get_forced_link_bpp_x16(state, crtc);
if (state->base.duplicated && crtc_state) {
limits->max_bpp_x16[pipe] = crtc_state->max_link_bpp_x16;
@ -42,15 +70,19 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state,
} else {
limits->max_bpp_x16[pipe] = INT_MAX;
}
if (forced_bpp_x16)
limits->max_bpp_x16[pipe] = min(limits->max_bpp_x16[pipe], forced_bpp_x16);
}
}
/**
* intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
* __intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
* @state: atomic state
* @limits: link BW limits
* @pipe_mask: mask of pipes to select from
* @reason: explanation of why bpp reduction is needed
* @reduce_forced_bpp: allow reducing bpps below their forced link bpp
*
* Select the pipe from @pipe_mask with the biggest link bpp value and set the
* maximum of link bpp in @limits below this value. Modeset the selected pipe,
@ -64,10 +96,11 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state,
* - %-ENOSPC if no pipe can further reduce its link bpp
* - Other negative error, if modesetting the selected pipe failed
*/
int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
struct intel_link_bw_limits *limits,
u8 pipe_mask,
const char *reason)
static int __intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
struct intel_link_bw_limits *limits,
u8 pipe_mask,
const char *reason,
bool reduce_forced_bpp)
{
struct intel_display *display = to_intel_display(state);
enum pipe max_bpp_pipe = INVALID_PIPE;
@ -97,6 +130,10 @@ int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
*/
link_bpp_x16 = fxp_q4_from_int(crtc_state->pipe_bpp);
if (!reduce_forced_bpp &&
link_bpp_x16 <= get_forced_link_bpp_x16(state, crtc))
continue;
if (link_bpp_x16 > max_bpp_x16) {
max_bpp_x16 = link_bpp_x16;
max_bpp_pipe = crtc->pipe;
@ -112,6 +149,21 @@ int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
BIT(max_bpp_pipe));
}
int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
struct intel_link_bw_limits *limits,
u8 pipe_mask,
const char *reason)
{
int ret;
/* Try to keep any forced link BPP. */
ret = __intel_link_bw_reduce_bpp(state, limits, pipe_mask, reason, false);
if (ret == -ENOSPC)
ret = __intel_link_bw_reduce_bpp(state, limits, pipe_mask, reason, true);
return ret;
}
/**
* intel_link_bw_set_bpp_limit_for_pipe - set link bpp limit for a pipe to its minimum
* @state: atomic state
@ -245,3 +297,176 @@ int intel_link_bw_atomic_check(struct intel_atomic_state *state,
return -EAGAIN;
}
static int force_link_bpp_show(struct seq_file *m, void *data)
{
struct intel_connector *connector = m->private;
seq_printf(m, FXP_Q4_FMT "\n", FXP_Q4_ARGS(connector->link.force_bpp_x16));
return 0;
}
static int str_to_fxp_q4_nonneg_int(const char *str, int *val_x16)
{
unsigned int val;
int err;
err = kstrtouint(str, 10, &val);
if (err)
return err;
if (val > INT_MAX >> 4)
return -ERANGE;
*val_x16 = fxp_q4_from_int(val);
return 0;
}
/* modifies str */
static int str_to_fxp_q4_nonneg(char *str, int *val_x16)
{
const char *int_str;
char *frac_str;
int frac_digits;
int frac_val;
int err;
int_str = strim(str);
frac_str = strchr(int_str, '.');
if (frac_str)
*frac_str++ = '\0';
err = str_to_fxp_q4_nonneg_int(int_str, val_x16);
if (err)
return err;
if (!frac_str)
return 0;
/* prevent negative number/leading +- sign mark */
if (!isdigit(*frac_str))
return -EINVAL;
err = str_to_fxp_q4_nonneg_int(frac_str, &frac_val);
if (err)
return err;
frac_digits = strlen(frac_str);
if (frac_digits > intlog10(INT_MAX) >> 24 ||
frac_val > INT_MAX - int_pow(10, frac_digits) / 2)
return -ERANGE;
frac_val = DIV_ROUND_CLOSEST(frac_val, (int)int_pow(10, frac_digits));
if (*val_x16 > INT_MAX - frac_val)
return -ERANGE;
*val_x16 += frac_val;
return 0;
}
static int user_str_to_fxp_q4_nonneg(const char __user *ubuf, size_t len, int *val_x16)
{
char *kbuf;
int err;
kbuf = memdup_user_nul(ubuf, len);
if (IS_ERR(kbuf))
return PTR_ERR(kbuf);
err = str_to_fxp_q4_nonneg(kbuf, val_x16);
kfree(kbuf);
return err;
}
static bool connector_supports_dsc(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
switch (connector->base.connector_type) {
case DRM_MODE_CONNECTOR_eDP:
return intel_dp_has_dsc(connector);
case DRM_MODE_CONNECTOR_DisplayPort:
if (connector->mst.dp)
return HAS_DSC_MST(display);
return HAS_DSC(display);
default:
return false;
}
}
static ssize_t
force_link_bpp_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp)
{
struct seq_file *m = file->private_data;
struct intel_connector *connector = m->private;
struct intel_display *display = to_intel_display(connector);
int min_bpp;
int bpp_x16;
int err;
err = user_str_to_fxp_q4_nonneg(ubuf, len, &bpp_x16);
if (err)
return err;
/* TODO: Make the non-DSC min_bpp value connector specific. */
if (connector_supports_dsc(connector))
min_bpp = intel_dp_dsc_min_src_compressed_bpp();
else
min_bpp = intel_display_min_pipe_bpp();
if (bpp_x16 &&
(bpp_x16 < fxp_q4_from_int(min_bpp) ||
bpp_x16 > fxp_q4_from_int(intel_display_max_pipe_bpp(display))))
return -EINVAL;
err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
if (err)
return err;
connector->link.force_bpp_x16 = bpp_x16;
drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
*offp += len;
return len;
}
DEFINE_SHOW_STORE_ATTRIBUTE(force_link_bpp);
void intel_link_bw_connector_debugfs_add(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
struct dentry *root = connector->base.debugfs_entry;
switch (connector->base.connector_type) {
case DRM_MODE_CONNECTOR_DisplayPort:
case DRM_MODE_CONNECTOR_eDP:
break;
case DRM_MODE_CONNECTOR_VGA:
case DRM_MODE_CONNECTOR_SVIDEO:
case DRM_MODE_CONNECTOR_LVDS:
case DRM_MODE_CONNECTOR_DVID:
if (HAS_FDI(display))
break;
return;
case DRM_MODE_CONNECTOR_HDMIA:
if (HAS_FDI(display) && !HAS_DDI(display))
break;
return;
default:
return;
}
debugfs_create_file("intel_force_link_bpp", 0644, root,
connector, &force_link_bpp_fops);
}

View File

@ -11,6 +11,7 @@
#include "intel_display_limits.h"
struct intel_atomic_state;
struct intel_connector;
struct intel_crtc_state;
struct intel_link_bw_limits {
@ -32,5 +33,6 @@ bool intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state,
enum pipe pipe);
int intel_link_bw_atomic_check(struct intel_atomic_state *state,
struct intel_link_bw_limits *new_limits);
void intel_link_bw_connector_debugfs_add(struct intel_connector *connector);
#endif

View File

@ -29,9 +29,9 @@
#include <drm/drm_edid.h>
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_hdmi.h"

View File

@ -40,7 +40,6 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_backlight.h"
#include "intel_connector.h"
@ -249,7 +248,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state,
if (HAS_PCH_SPLIT(display)) {
assert_fdi_rx_pll_disabled(display, pipe);
assert_shared_dpll_disabled(display, crtc_state->shared_dpll);
assert_dpll_disabled(display, crtc_state->intel_dpll);
} else {
assert_pll_disabled(display, pipe);
}

View File

@ -23,6 +23,7 @@
#include "intel_de.h"
#include "intel_display.h"
#include "intel_display_power.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dmc.h"
#include "intel_fifo_underrun.h"
@ -92,10 +93,10 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc,
crtc->active = false;
crtc->base.enabled = false;
if (crtc_state->shared_dpll)
intel_unreference_shared_dpll_crtc(crtc,
crtc_state->shared_dpll,
&crtc_state->shared_dpll->state);
if (crtc_state->intel_dpll)
intel_dpll_crtc_put(crtc,
crtc_state->intel_dpll,
&crtc_state->intel_dpll->state);
}
static void set_encoder_for_connector(struct intel_connector *connector,
@ -565,7 +566,7 @@ static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
*/
return display->platform.sandybridge &&
crtc_state->hw.active &&
crtc_state->shared_dpll &&
crtc_state->intel_dpll &&
crtc_state->port_clock == 0;
}

View File

@ -243,7 +243,7 @@ void intel_modeset_verify_crtc(struct intel_atomic_state *state,
intel_wm_state_verify(state, crtc);
verify_connector_state(state, crtc);
verify_crtc_state(state, crtc);
intel_shared_dpll_state_verify(state, crtc);
intel_dpll_state_verify(state, crtc);
intel_mpllb_state_verify(state, crtc);
intel_cx0pll_state_verify(state, crtc);
}
@ -252,5 +252,5 @@ void intel_modeset_verify_disabled(struct intel_atomic_state *state)
{
verify_encoder_state(state);
verify_connector_state(state, NULL);
intel_shared_dpll_verify_disabled(state);
intel_dpll_verify_disabled(state);
}

View File

@ -35,6 +35,7 @@
#include "i915_drv.h"
#include "intel_acpi.h"
#include "intel_backlight.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_opregion.h"
#include "intel_pci_config.h"

Some files were not shown because too many files have changed in this diff Show More