mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 04:34:08 +08:00
UAPI Changes:
On i915 we have a new UAPI to allow userspace to specify CS ring buffer size on construction (I915_CONTEXT_PARAM_RINGSIZE) and also new sysfs entries exposing various engine properties GVT Changes: VFIO edid getting expanded to all platforms and a big cleanup around attr group, unused vblank complete, kvmgt, Intel engine and dev_priv usages. i915 Changes: - new UAPI to allow userspace to specify CS ring buffer size on construction (I915_CONTEXT_PARAM_RINGSIZE) - (Chris) - New sysfs entries exposing various engine properties (Chris) - Tiger Lake is out of require_force_probe protection (Jose) - Changes in many places around active requests, reset and heartbeat (Chris) - Stop assigning drm-dev_private pointer (Jani) - Many code refactor in many places, including intel_modeset_init, increasing use of intel_uncore_*, vgpu, and gvt stuff (Jani) - Fixes around display pipe iterators (Anshuman) - Tigerlake enabling work (Matt Ropper, Matt Atwood, Ville, Lucas, Daniele, Jose, Anusha, Vivek, Swathi, Caz. Kai) - Code clean-up like reducing use of drm/i915_drv.h, removing unused registers, removing garbage warns, and some other code polishing (Jani, Lucas, Ville) - Selftests fixes, improvements and additions (Chris, Dan, Aditya, Matt Auld) - Fix plane possible_crtcs bit mask (Anshuman) - Fixes and cleanup on GLK pre production identification and w/a (Ville) - Fix display orientation on few cases (Hans, Ville) - dbuf clean-up and improvements for slice arrays handling (Ville) - Improvement around min cdclk calculation (Stanislav) - Fixes and refactor around display PLLs (Imre) - Other execlists and perf fixes (Chris) - Documentation fixes (Jani, Chris) - Fix build issue (Anshuman) - Many more fixes around the locking mechanisms (Chris) - Other fixes and debugability info around preemption (Chris, Tvrtko) - Add mechanism to submit a context WA on ring submission (Mika) - Clear all Eu/L3 resitual context (Prathap) - More changes around local memory (Abdiel, Matt, Chris) - Fix RPS (Chris) - DP MST fix (Lyude) - Display FBC fixes (Jose, RK) - debugfs cleanup (Tvrtko) - More convertion towards drm_debive based loggin (Wambui, Ram) - Avoid potential buffer overflow (Takashi) - Ice Lake and Elkhart Lake workarounds (Matt Roper) -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAl5sIZ0ACgkQ+mJfZA7r E8o1LQf+L/Vpm46QQGEyzHINf/gTQvFvumuNAX352vEHaKUgLtTuI7xfpd0c83G1 5VI+L0Q/ARvakkgfZuHYInlxc9azkcPF1wXb3bLqkoiJ15ydwx5GWjVpZ8uFT+fG xzaHBqhqUcvw/kXI1Cy5kIDAlFO9rKLsoLS2qQF9BsYHyxa52ok9/hW+lM7C+vfR aYvEr7aAK0o06mqgwc3DHXGuzaS1S9kxtvj9ZkHNsD9iwD4rrEIvW3BPuDqEVkGq TkKfThhzJp2FDjXkgCQbLm2BQmxBS0aihwNsQ/lDUUAxcFiuRYwMSoT63vPD1OYI lgG0BuJkwK7csJIMrnOs/ZAMeKyTQA== =vrB8 -----END PGP SIGNATURE----- Merge tag 'drm-intel-next-2020-03-13' of git://anongit.freedesktop.org/drm/drm-intel into drm-next UAPI Changes: On i915 we have a new UAPI to allow userspace to specify CS ring buffer size on construction (I915_CONTEXT_PARAM_RINGSIZE) and also new sysfs entries exposing various engine properties GVT Changes: VFIO edid getting expanded to all platforms and a big cleanup around attr group, unused vblank complete, kvmgt, Intel engine and dev_priv usages. i915 Changes: - new UAPI to allow userspace to specify CS ring buffer size on construction (I915_CONTEXT_PARAM_RINGSIZE) - (Chris) - New sysfs entries exposing various engine properties (Chris) - Tiger Lake is out of require_force_probe protection (Jose) - Changes in many places around active requests, reset and heartbeat (Chris) - Stop assigning drm-dev_private pointer (Jani) - Many code refactor in many places, including intel_modeset_init, increasing use of intel_uncore_*, vgpu, and gvt stuff (Jani) - Fixes around display pipe iterators (Anshuman) - Tigerlake enabling work (Matt Ropper, Matt Atwood, Ville, Lucas, Daniele, Jose, Anusha, Vivek, Swathi, Caz. Kai) - Code clean-up like reducing use of drm/i915_drv.h, removing unused registers, removing garbage warns, and some other code polishing (Jani, Lucas, Ville) - Selftests fixes, improvements and additions (Chris, Dan, Aditya, Matt Auld) - Fix plane possible_crtcs bit mask (Anshuman) - Fixes and cleanup on GLK pre production identification and w/a (Ville) - Fix display orientation on few cases (Hans, Ville) - dbuf clean-up and improvements for slice arrays handling (Ville) - Improvement around min cdclk calculation (Stanislav) - Fixes and refactor around display PLLs (Imre) - Other execlists and perf fixes (Chris) - Documentation fixes (Jani, Chris) - Fix build issue (Anshuman) - Many more fixes around the locking mechanisms (Chris) - Other fixes and debugability info around preemption (Chris, Tvrtko) - Add mechanism to submit a context WA on ring submission (Mika) - Clear all Eu/L3 resitual context (Prathap) - More changes around local memory (Abdiel, Matt, Chris) - Fix RPS (Chris) - DP MST fix (Lyude) - Display FBC fixes (Jose, RK) - debugfs cleanup (Tvrtko) - More convertion towards drm_debive based loggin (Wambui, Ram) - Avoid potential buffer overflow (Takashi) - Ice Lake and Elkhart Lake workarounds (Matt Roper) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200314001535.GA2969344@intel.com
This commit is contained in:
commit
9001b17698
@ -207,10 +207,10 @@ DPIO
|
||||
CSR firmware support for DMC
|
||||
----------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_csr.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_csr.c
|
||||
:doc: csr support for dmc
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_csr.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_csr.c
|
||||
:internal:
|
||||
|
||||
Video BIOS Table (VBT)
|
||||
@ -332,7 +332,7 @@ This process is dubbed relocation.
|
||||
GEM BO Management Implementation Details
|
||||
----------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_vma.h
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_vma_types.h
|
||||
:doc: Virtual Memory Address
|
||||
|
||||
Buffer Object Eviction
|
||||
@ -382,7 +382,7 @@ Logical Rings, Logical Ring Contexts and Execlists
|
||||
Global GTT views
|
||||
----------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_gtt.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_vma_types.h
|
||||
:doc: Global GTT views
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_gtt.c
|
||||
|
@ -1280,6 +1280,85 @@ drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch)
|
||||
#undef DEVICE_ID_ANY
|
||||
#undef DEVICE_ID
|
||||
|
||||
struct edid_quirk {
|
||||
u8 mfg_id[2];
|
||||
u8 prod_id[2];
|
||||
u32 quirks;
|
||||
};
|
||||
|
||||
#define MFG(first, second) { (first), (second) }
|
||||
#define PROD_ID(first, second) { (first), (second) }
|
||||
|
||||
/*
|
||||
* Some devices have unreliable OUIDs where they don't set the device ID
|
||||
* correctly, and as a result we need to use the EDID for finding additional
|
||||
* DP quirks in such cases.
|
||||
*/
|
||||
static const struct edid_quirk edid_quirk_list[] = {
|
||||
/* Optional 4K AMOLED panel in the ThinkPad X1 Extreme 2nd Generation
|
||||
* only supports DPCD backlight controls
|
||||
*/
|
||||
{ MFG(0x4c, 0x83), PROD_ID(0x41, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
|
||||
/*
|
||||
* Some Dell CML 2020 systems have panels support both AUX and PWM
|
||||
* backlight control, and some only support AUX backlight control. All
|
||||
* said panels start up in AUX mode by default, and we don't have any
|
||||
* support for disabling HDR mode on these panels which would be
|
||||
* required to switch to PWM backlight control mode (plus, I'm not
|
||||
* even sure we want PWM backlight controls over DPCD backlight
|
||||
* controls anyway...). Until we have a better way of detecting these,
|
||||
* force DPCD backlight mode on all of them.
|
||||
*/
|
||||
{ MFG(0x06, 0xaf), PROD_ID(0x9b, 0x32), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
|
||||
{ MFG(0x06, 0xaf), PROD_ID(0xeb, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
|
||||
{ MFG(0x4d, 0x10), PROD_ID(0xc7, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
|
||||
{ MFG(0x4d, 0x10), PROD_ID(0xe6, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
|
||||
};
|
||||
|
||||
#undef MFG
|
||||
#undef PROD_ID
|
||||
|
||||
/**
|
||||
* drm_dp_get_edid_quirks() - Check the EDID of a DP device to find additional
|
||||
* DP-specific quirks
|
||||
* @edid: The EDID to check
|
||||
*
|
||||
* While OUIDs are meant to be used to recognize a DisplayPort device, a lot
|
||||
* of manufacturers don't seem to like following standards and neglect to fill
|
||||
* the dev-ID in, making it impossible to only use OUIDs for determining
|
||||
* quirks in some cases. This function can be used to check the EDID and look
|
||||
* up any additional DP quirks. The bits returned by this function correspond
|
||||
* to the quirk bits in &drm_dp_quirk.
|
||||
*
|
||||
* Returns: a bitmask of quirks, if any. The driver can check this using
|
||||
* drm_dp_has_quirk().
|
||||
*/
|
||||
u32 drm_dp_get_edid_quirks(const struct edid *edid)
|
||||
{
|
||||
const struct edid_quirk *quirk;
|
||||
u32 quirks = 0;
|
||||
int i;
|
||||
|
||||
if (!edid)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
|
||||
quirk = &edid_quirk_list[i];
|
||||
if (memcmp(quirk->mfg_id, edid->mfg_id,
|
||||
sizeof(edid->mfg_id)) == 0 &&
|
||||
memcmp(quirk->prod_id, edid->prod_code,
|
||||
sizeof(edid->prod_code)) == 0)
|
||||
quirks |= quirk->quirks;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("DP sink: EDID mfg %*phD prod-ID %*phD quirks: 0x%04x\n",
|
||||
(int)sizeof(edid->mfg_id), edid->mfg_id,
|
||||
(int)sizeof(edid->prod_code), edid->prod_code, quirks);
|
||||
|
||||
return quirks;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_get_edid_quirks);
|
||||
|
||||
/**
|
||||
* drm_dp_read_desc - read sink/branch descriptor from DPCD
|
||||
* @aux: DisplayPort AUX channel
|
||||
|
@ -5472,7 +5472,8 @@ struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port)
|
||||
if (drm_dp_read_desc(port->mgr->aux, &desc, true))
|
||||
return NULL;
|
||||
|
||||
if (drm_dp_has_quirk(&desc, DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) &&
|
||||
if (drm_dp_has_quirk(&desc, 0,
|
||||
DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) &&
|
||||
port->mgr->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14 &&
|
||||
port->parent == port->mgr->mst_primary) {
|
||||
u8 downstreamport;
|
||||
|
@ -20,6 +20,9 @@ config DRM_I915_HEARTBEAT_INTERVAL
|
||||
check the health of the GPU and undertake regular house-keeping of
|
||||
internal driver state.
|
||||
|
||||
This is adjustable via
|
||||
/sys/class/drm/card?/engine/*/heartbeat_interval_ms
|
||||
|
||||
May be 0 to disable heartbeats and therefore disable automatic GPU
|
||||
hang detection.
|
||||
|
||||
@ -33,11 +36,18 @@ config DRM_I915_PREEMPT_TIMEOUT
|
||||
expires, the HW will be reset to allow the more important context
|
||||
to execute.
|
||||
|
||||
This is adjustable via
|
||||
/sys/class/drm/card?/engine/*/preempt_timeout_ms
|
||||
|
||||
May be 0 to disable the timeout.
|
||||
|
||||
config DRM_I915_SPIN_REQUEST
|
||||
int "Busywait for request completion (us)"
|
||||
default 5 # microseconds
|
||||
The compiled in default may get overridden at driver probe time on
|
||||
certain platforms and certain engines which will be reflected in the
|
||||
sysfs control.
|
||||
|
||||
config DRM_I915_MAX_REQUEST_BUSYWAIT
|
||||
int "Busywait for request completion limit (ns)"
|
||||
default 8000 # nanoseconds
|
||||
help
|
||||
Before sleeping waiting for a request (GPU operation) to complete,
|
||||
we may spend some time polling for its completion. As the IRQ may
|
||||
@ -45,6 +55,9 @@ config DRM_I915_SPIN_REQUEST
|
||||
check if the request will complete in the time it would have taken
|
||||
us to enable the interrupt.
|
||||
|
||||
This is adjustable via
|
||||
/sys/class/drm/card?/engine/*/max_busywait_duration_ns
|
||||
|
||||
May be 0 to disable the initial spin. In practice, we estimate
|
||||
the cost of enabling the interrupt (if currently disabled) to be
|
||||
a few microseconds.
|
||||
@ -60,6 +73,9 @@ config DRM_I915_STOP_TIMEOUT
|
||||
that the reset itself may take longer and so be more disruptive to
|
||||
interactive or low latency workloads.
|
||||
|
||||
This is adjustable via
|
||||
/sys/class/drm/card?/engine/*/stop_timeout_ms
|
||||
|
||||
config DRM_I915_TIMESLICE_DURATION
|
||||
int "Scheduling quantum for userspace batches (ms, jiffy granularity)"
|
||||
default 1 # milliseconds
|
||||
@ -73,4 +89,7 @@ config DRM_I915_TIMESLICE_DURATION
|
||||
is scheduled for execution for the timeslice duration, before
|
||||
switching to the next context.
|
||||
|
||||
This is adjustable via
|
||||
/sys/class/drm/card?/engine/*/timeslice_duration_ms
|
||||
|
||||
May be 0 to disable timeslicing.
|
||||
|
@ -47,6 +47,7 @@ i915-y += i915_drv.o \
|
||||
i915_sysfs.o \
|
||||
i915_utils.o \
|
||||
intel_device_info.o \
|
||||
intel_dram.o \
|
||||
intel_memory_region.o \
|
||||
intel_pch.o \
|
||||
intel_pm.o \
|
||||
@ -79,9 +80,11 @@ gt-y += \
|
||||
gt/debugfs_gt.o \
|
||||
gt/debugfs_gt_pm.o \
|
||||
gt/gen6_ppgtt.o \
|
||||
gt/gen7_renderclear.o \
|
||||
gt/gen8_ppgtt.o \
|
||||
gt/intel_breadcrumbs.o \
|
||||
gt/intel_context.o \
|
||||
gt/intel_context_param.o \
|
||||
gt/intel_context_sseu.o \
|
||||
gt/intel_engine_cs.o \
|
||||
gt/intel_engine_heartbeat.o \
|
||||
@ -107,7 +110,8 @@ gt-y += \
|
||||
gt/intel_rps.o \
|
||||
gt/intel_sseu.o \
|
||||
gt/intel_timeline.o \
|
||||
gt/intel_workarounds.o
|
||||
gt/intel_workarounds.o \
|
||||
gt/sysfs_engines.o
|
||||
# autogenerated null render state
|
||||
gt-y += \
|
||||
gt/gen6_renderstate.o \
|
||||
|
@ -599,13 +599,13 @@ static void gen11_dsi_gate_clocks(struct intel_encoder *encoder)
|
||||
u32 tmp;
|
||||
enum phy phy;
|
||||
|
||||
mutex_lock(&dev_priv->dpll_lock);
|
||||
mutex_lock(&dev_priv->dpll.lock);
|
||||
tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
|
||||
for_each_dsi_phy(phy, intel_dsi->phys)
|
||||
tmp |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
|
||||
|
||||
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp);
|
||||
mutex_unlock(&dev_priv->dpll_lock);
|
||||
mutex_unlock(&dev_priv->dpll.lock);
|
||||
}
|
||||
|
||||
static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder)
|
||||
@ -615,13 +615,13 @@ static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder)
|
||||
u32 tmp;
|
||||
enum phy phy;
|
||||
|
||||
mutex_lock(&dev_priv->dpll_lock);
|
||||
mutex_lock(&dev_priv->dpll.lock);
|
||||
tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
|
||||
for_each_dsi_phy(phy, intel_dsi->phys)
|
||||
tmp &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
|
||||
|
||||
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp);
|
||||
mutex_unlock(&dev_priv->dpll_lock);
|
||||
mutex_unlock(&dev_priv->dpll.lock);
|
||||
}
|
||||
|
||||
static void gen11_dsi_map_pll(struct intel_encoder *encoder,
|
||||
@ -633,7 +633,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder,
|
||||
enum phy phy;
|
||||
u32 val;
|
||||
|
||||
mutex_lock(&dev_priv->dpll_lock);
|
||||
mutex_lock(&dev_priv->dpll.lock);
|
||||
|
||||
val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
|
||||
for_each_dsi_phy(phy, intel_dsi->phys) {
|
||||
@ -652,7 +652,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder,
|
||||
|
||||
intel_de_posting_read(dev_priv, ICL_DPCLKA_CFGCR0);
|
||||
|
||||
mutex_unlock(&dev_priv->dpll_lock);
|
||||
mutex_unlock(&dev_priv->dpll.lock);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1350,15 +1350,15 @@ static void gen11_dsi_get_timings(struct intel_encoder *encoder,
|
||||
static void gen11_dsi_get_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
|
||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
|
||||
|
||||
intel_dsc_get_config(encoder, pipe_config);
|
||||
|
||||
/* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */
|
||||
pipe_config->port_clock =
|
||||
cnl_calc_wrpll_link(dev_priv, &pipe_config->dpll_hw_state);
|
||||
pipe_config->port_clock = intel_dpll_get_freq(i915,
|
||||
pipe_config->shared_dpll);
|
||||
|
||||
pipe_config->hw.adjusted_mode.crtc_clock = intel_dsi->pclk;
|
||||
if (intel_dsi->dual_link)
|
||||
|
@ -133,15 +133,37 @@ intel_plane_destroy_state(struct drm_plane *plane,
|
||||
kfree(plane_state);
|
||||
}
|
||||
|
||||
unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
unsigned int src_w, src_h, dst_w, dst_h;
|
||||
unsigned int pixel_rate = crtc_state->pixel_rate;
|
||||
|
||||
src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
|
||||
src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
|
||||
dst_w = drm_rect_width(&plane_state->uapi.dst);
|
||||
dst_h = drm_rect_height(&plane_state->uapi.dst);
|
||||
|
||||
/* Downscaling limits the maximum pixel rate */
|
||||
dst_w = min(src_w, dst_w);
|
||||
dst_h = min(src_h, dst_h);
|
||||
|
||||
return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, src_w * src_h),
|
||||
dst_w * dst_h);
|
||||
}
|
||||
|
||||
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
const struct drm_framebuffer *fb = plane_state->hw.fb;
|
||||
unsigned int cpp;
|
||||
unsigned int pixel_rate;
|
||||
|
||||
if (!plane_state->uapi.visible)
|
||||
return 0;
|
||||
|
||||
pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
|
||||
|
||||
cpp = fb->format->cpp[0];
|
||||
|
||||
/*
|
||||
@ -153,7 +175,7 @@ unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
|
||||
if (fb->format->is_yuv && fb->format->num_planes > 1)
|
||||
cpp *= 4;
|
||||
|
||||
return cpp * crtc_state->pixel_rate;
|
||||
return pixel_rate * cpp;
|
||||
}
|
||||
|
||||
int intel_plane_calc_min_cdclk(struct intel_atomic_state *state,
|
||||
|
@ -18,6 +18,9 @@ struct intel_plane_state;
|
||||
|
||||
extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
|
||||
|
||||
unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
|
||||
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
|
||||
|
@ -149,6 +149,10 @@ static const struct {
|
||||
{ 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 },
|
||||
{ 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 },
|
||||
{ 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 },
|
||||
{ 296703, AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 },
|
||||
{ 297000, AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 },
|
||||
{ 593407, AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 },
|
||||
{ 594000, AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 },
|
||||
};
|
||||
|
||||
/* HDMI N/CTS table */
|
||||
@ -234,6 +238,7 @@ static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = {
|
||||
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
|
||||
static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
int i;
|
||||
@ -243,6 +248,9 @@ static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_sta
|
||||
break;
|
||||
}
|
||||
|
||||
if (INTEL_GEN(dev_priv) < 12 && adjusted_mode->crtc_clock > 148500)
|
||||
i = ARRAY_SIZE(hdmi_audio_clock);
|
||||
|
||||
if (i == ARRAY_SIZE(hdmi_audio_clock)) {
|
||||
DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n",
|
||||
adjusted_mode->crtc_clock);
|
||||
@ -844,7 +852,7 @@ static void glk_force_audio_cdclk(struct drm_i915_private *dev_priv,
|
||||
struct intel_crtc *crtc;
|
||||
int ret;
|
||||
|
||||
crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
|
||||
crtc = intel_get_first_crtc(dev_priv);
|
||||
if (!crtc)
|
||||
return;
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
*/
|
||||
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "display/intel_display.h"
|
||||
#include "display/intel_display_types.h"
|
||||
|
@ -32,8 +32,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_crtc_state;
|
||||
struct intel_encoder;
|
||||
|
@ -1868,6 +1868,8 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
const struct intel_cdclk_config *cdclk_config,
|
||||
enum pipe pipe)
|
||||
{
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
if (!intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config))
|
||||
return;
|
||||
|
||||
@ -1876,8 +1878,28 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
|
||||
intel_dump_cdclk_config(cdclk_config, "Changing CDCLK to");
|
||||
|
||||
/*
|
||||
* Lock aux/gmbus while we change cdclk in case those
|
||||
* functions use cdclk. Not all platforms/ports do,
|
||||
* but we'll lock them all for simplicity.
|
||||
*/
|
||||
mutex_lock(&dev_priv->gmbus_mutex);
|
||||
for_each_intel_dp(&dev_priv->drm, encoder) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
mutex_lock_nest_lock(&intel_dp->aux.hw_mutex,
|
||||
&dev_priv->gmbus_mutex);
|
||||
}
|
||||
|
||||
dev_priv->display.set_cdclk(dev_priv, cdclk_config, pipe);
|
||||
|
||||
for_each_intel_dp(&dev_priv->drm, encoder) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
mutex_unlock(&intel_dp->aux.hw_mutex);
|
||||
}
|
||||
mutex_unlock(&dev_priv->gmbus_mutex);
|
||||
|
||||
if (drm_WARN(&dev_priv->drm,
|
||||
intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config),
|
||||
"cdclk state doesn't match!\n")) {
|
||||
|
@ -348,48 +348,56 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
|
||||
crtc_state->csc_mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the pipe CSC unit on CherryView.
|
||||
*/
|
||||
static void cherryview_load_csc_matrix(const struct intel_crtc_state *crtc_state)
|
||||
static void chv_load_cgm_csc(struct intel_crtc *crtc,
|
||||
const struct drm_property_blob *blob)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_color_ctm *ctm = blob->data;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u16 coeffs[9];
|
||||
int i;
|
||||
|
||||
if (crtc_state->hw.ctm) {
|
||||
const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
|
||||
u16 coeffs[9] = {};
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
|
||||
u64 abs_coeff = ((1ULL << 63) - 1) & ctm->matrix[i];
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
|
||||
u64 abs_coeff =
|
||||
((1ULL << 63) - 1) & ctm->matrix[i];
|
||||
/* Round coefficient. */
|
||||
abs_coeff += 1 << (32 - 13);
|
||||
/* Clamp to hardware limits. */
|
||||
abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
|
||||
|
||||
/* Round coefficient. */
|
||||
abs_coeff += 1 << (32 - 13);
|
||||
/* Clamp to hardware limits. */
|
||||
abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
|
||||
coeffs[i] = 0;
|
||||
|
||||
/* Write coefficients in S3.12 format. */
|
||||
if (ctm->matrix[i] & (1ULL << 63))
|
||||
coeffs[i] = 1 << 15;
|
||||
coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
|
||||
coeffs[i] |= (abs_coeff >> 20) & 0xfff;
|
||||
}
|
||||
/* Write coefficients in S3.12 format. */
|
||||
if (ctm->matrix[i] & (1ULL << 63))
|
||||
coeffs[i] |= 1 << 15;
|
||||
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF01(pipe),
|
||||
coeffs[1] << 16 | coeffs[0]);
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF23(pipe),
|
||||
coeffs[3] << 16 | coeffs[2]);
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF45(pipe),
|
||||
coeffs[5] << 16 | coeffs[4]);
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF67(pipe),
|
||||
coeffs[7] << 16 | coeffs[6]);
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
|
||||
coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
|
||||
coeffs[i] |= (abs_coeff >> 20) & 0xfff;
|
||||
}
|
||||
|
||||
intel_de_write(dev_priv, CGM_PIPE_MODE(pipe), crtc_state->cgm_mode);
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF01(pipe),
|
||||
coeffs[1] << 16 | coeffs[0]);
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF23(pipe),
|
||||
coeffs[3] << 16 | coeffs[2]);
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF45(pipe),
|
||||
coeffs[5] << 16 | coeffs[4]);
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF67(pipe),
|
||||
coeffs[7] << 16 | coeffs[6]);
|
||||
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF8(pipe),
|
||||
coeffs[8]);
|
||||
}
|
||||
|
||||
/* convert hw value with given bit_precision to lut property val */
|
||||
static u32 intel_color_lut_pack(u32 val, int bit_precision)
|
||||
{
|
||||
u32 max = 0xffff >> (16 - bit_precision);
|
||||
|
||||
val = clamp_val(val, 0, max);
|
||||
|
||||
if (bit_precision < 16)
|
||||
val <<= 16 - bit_precision;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 i9xx_lut_8(const struct drm_color_lut *color)
|
||||
@ -399,6 +407,13 @@ static u32 i9xx_lut_8(const struct drm_color_lut *color)
|
||||
drm_color_lut_extract(color->blue, 8);
|
||||
}
|
||||
|
||||
static void i9xx_lut_8_pack(struct drm_color_lut *entry, u32 val)
|
||||
{
|
||||
entry->red = intel_color_lut_pack(REG_FIELD_GET(LGC_PALETTE_RED_MASK, val), 8);
|
||||
entry->green = intel_color_lut_pack(REG_FIELD_GET(LGC_PALETTE_GREEN_MASK, val), 8);
|
||||
entry->blue = intel_color_lut_pack(REG_FIELD_GET(LGC_PALETTE_BLUE_MASK, val), 8);
|
||||
}
|
||||
|
||||
/* i965+ "10.6" bit interpolated format "even DW" (low 8 bits) */
|
||||
static u32 i965_lut_10p6_ldw(const struct drm_color_lut *color)
|
||||
{
|
||||
@ -415,6 +430,22 @@ static u32 i965_lut_10p6_udw(const struct drm_color_lut *color)
|
||||
(color->blue >> 8);
|
||||
}
|
||||
|
||||
static void i965_lut_10p6_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
|
||||
{
|
||||
entry->red = REG_FIELD_GET(PALETTE_RED_MASK, udw) << 8 |
|
||||
REG_FIELD_GET(PALETTE_RED_MASK, ldw);
|
||||
entry->green = REG_FIELD_GET(PALETTE_GREEN_MASK, udw) << 8 |
|
||||
REG_FIELD_GET(PALETTE_GREEN_MASK, ldw);
|
||||
entry->blue = REG_FIELD_GET(PALETTE_BLUE_MASK, udw) << 8 |
|
||||
REG_FIELD_GET(PALETTE_BLUE_MASK, ldw);
|
||||
}
|
||||
|
||||
static u16 i965_lut_11p6_max_pack(u32 val)
|
||||
{
|
||||
/* PIPEGCMAX is 11.6, clamp to 10.6 */
|
||||
return clamp_val(val, 0, 0xffff);
|
||||
}
|
||||
|
||||
static u32 ilk_lut_10(const struct drm_color_lut *color)
|
||||
{
|
||||
return drm_color_lut_extract(color->red, 10) << 20 |
|
||||
@ -422,41 +453,11 @@ static u32 ilk_lut_10(const struct drm_color_lut *color)
|
||||
drm_color_lut_extract(color->blue, 10);
|
||||
}
|
||||
|
||||
/* Loads the legacy palette/gamma unit for the CRTC. */
|
||||
static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_property_blob *blob)
|
||||
static void ilk_lut_10_pack(struct drm_color_lut *entry, u32 val)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
int i;
|
||||
|
||||
if (HAS_GMCH(dev_priv)) {
|
||||
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
|
||||
assert_dsi_pll_enabled(dev_priv);
|
||||
else
|
||||
assert_pll_enabled(dev_priv, pipe);
|
||||
}
|
||||
|
||||
if (blob) {
|
||||
const struct drm_color_lut *lut = blob->data;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
u32 word = i9xx_lut_8(&lut[i]);
|
||||
|
||||
if (HAS_GMCH(dev_priv))
|
||||
intel_de_write(dev_priv, PALETTE(pipe, i),
|
||||
word);
|
||||
else
|
||||
intel_de_write(dev_priv, LGC_PALETTE(pipe, i),
|
||||
word);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void i9xx_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
i9xx_load_luts_internal(crtc_state, crtc_state->hw.gamma_lut);
|
||||
entry->red = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_RED_MASK, val), 10);
|
||||
entry->green = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_GREEN_MASK, val), 10);
|
||||
entry->blue = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_BLUE_MASK, val), 10);
|
||||
}
|
||||
|
||||
static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
|
||||
@ -525,6 +526,35 @@ static void skl_color_commit(const struct intel_crtc_state *crtc_state)
|
||||
ilk_load_csc_matrix(crtc_state);
|
||||
}
|
||||
|
||||
static void i9xx_load_lut_8(struct intel_crtc *crtc,
|
||||
const struct drm_property_blob *blob)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_color_lut *lut;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
int i;
|
||||
|
||||
if (!blob)
|
||||
return;
|
||||
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
intel_de_write(dev_priv, PALETTE(pipe, i),
|
||||
i9xx_lut_8(&lut[i]));
|
||||
}
|
||||
|
||||
static void i9xx_load_luts(const struct intel_crtc_state *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 drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
|
||||
|
||||
assert_pll_enabled(dev_priv, crtc->pipe);
|
||||
|
||||
i9xx_load_lut_8(crtc, gamma_lut);
|
||||
}
|
||||
|
||||
static void i965_load_lut_10p6(struct intel_crtc *crtc,
|
||||
const struct drm_property_blob *blob)
|
||||
{
|
||||
@ -548,14 +578,38 @@ static void i965_load_lut_10p6(struct intel_crtc *crtc,
|
||||
static void i965_load_luts(const struct intel_crtc_state *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 drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
|
||||
|
||||
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
|
||||
assert_dsi_pll_enabled(dev_priv);
|
||||
else
|
||||
assert_pll_enabled(dev_priv, crtc->pipe);
|
||||
|
||||
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
|
||||
i9xx_load_luts(crtc_state);
|
||||
i9xx_load_lut_8(crtc, gamma_lut);
|
||||
else
|
||||
i965_load_lut_10p6(crtc, gamma_lut);
|
||||
}
|
||||
|
||||
static void ilk_load_lut_8(struct intel_crtc *crtc,
|
||||
const struct drm_property_blob *blob)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_color_lut *lut;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
int i;
|
||||
|
||||
if (!blob)
|
||||
return;
|
||||
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
intel_de_write(dev_priv, LGC_PALETTE(pipe, i),
|
||||
i9xx_lut_8(&lut[i]));
|
||||
}
|
||||
|
||||
static void ilk_load_lut_10(struct intel_crtc *crtc,
|
||||
const struct drm_property_blob *blob)
|
||||
{
|
||||
@ -566,7 +620,7 @@ static void ilk_load_lut_10(struct intel_crtc *crtc,
|
||||
|
||||
for (i = 0; i < lut_size; i++)
|
||||
intel_de_write(dev_priv, PREC_PALETTE(pipe, i),
|
||||
ilk_lut_10(&lut[i]));
|
||||
ilk_lut_10(&lut[i]));
|
||||
}
|
||||
|
||||
static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
@ -575,7 +629,7 @@ static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
|
||||
|
||||
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
|
||||
i9xx_load_luts(crtc_state);
|
||||
ilk_load_lut_8(crtc, gamma_lut);
|
||||
else
|
||||
ilk_load_lut_10(crtc, gamma_lut);
|
||||
}
|
||||
@ -685,7 +739,7 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
|
||||
|
||||
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
|
||||
i9xx_load_luts(crtc_state);
|
||||
ilk_load_lut_8(crtc, gamma_lut);
|
||||
} else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
|
||||
ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
|
||||
PAL_PREC_INDEX_VALUE(0));
|
||||
@ -708,7 +762,7 @@ static void bdw_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
|
||||
|
||||
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
|
||||
i9xx_load_luts(crtc_state);
|
||||
ilk_load_lut_8(crtc, gamma_lut);
|
||||
} else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
|
||||
bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
|
||||
PAL_PREC_INDEX_VALUE(0));
|
||||
@ -729,9 +783,8 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
|
||||
int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
|
||||
const struct drm_color_lut *lut = crtc_state->hw.degamma_lut->data;
|
||||
u32 i;
|
||||
|
||||
/*
|
||||
* When setting the auto-increment bit, the hardware seems to
|
||||
@ -770,8 +823,7 @@ static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_stat
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
|
||||
u32 i;
|
||||
int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
|
||||
|
||||
/*
|
||||
* When setting the auto-increment bit, the hardware seems to
|
||||
@ -812,7 +864,7 @@ static void glk_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
glk_load_degamma_lut_linear(crtc_state);
|
||||
|
||||
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
|
||||
i9xx_load_luts(crtc_state);
|
||||
ilk_load_lut_8(crtc, gamma_lut);
|
||||
} else {
|
||||
bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
|
||||
ivb_load_lut_ext_max(crtc);
|
||||
@ -856,7 +908,7 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state)
|
||||
const struct drm_color_lut *lut = blob->data;
|
||||
struct intel_dsb *dsb = intel_dsb_get(crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 i;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Program Super Fine segment (let's call it seg1)...
|
||||
@ -889,7 +941,7 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
|
||||
const struct drm_color_lut *entry;
|
||||
struct intel_dsb *dsb = intel_dsb_get(crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 i;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Program Fine segment (let's call it seg2)...
|
||||
@ -948,7 +1000,7 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
|
||||
switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
|
||||
case GAMMA_MODE_MODE_8BIT:
|
||||
i9xx_load_luts(crtc_state);
|
||||
ilk_load_lut_8(crtc, gamma_lut);
|
||||
break;
|
||||
case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED:
|
||||
icl_program_gamma_superfine_segment(crtc_state);
|
||||
@ -974,6 +1026,13 @@ static u32 chv_cgm_degamma_udw(const struct drm_color_lut *color)
|
||||
return drm_color_lut_extract(color->red, 14);
|
||||
}
|
||||
|
||||
static void chv_cgm_gamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
|
||||
{
|
||||
entry->green = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_GREEN_MASK, ldw), 10);
|
||||
entry->blue = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_BLUE_MASK, ldw), 10);
|
||||
entry->red = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_RED_MASK, udw), 10);
|
||||
}
|
||||
|
||||
static void chv_load_cgm_degamma(struct intel_crtc *crtc,
|
||||
const struct drm_property_blob *blob)
|
||||
{
|
||||
@ -1020,21 +1079,24 @@ static void chv_load_cgm_gamma(struct intel_crtc *crtc,
|
||||
static void chv_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
|
||||
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
|
||||
const struct drm_property_blob *ctm = crtc_state->hw.ctm;
|
||||
|
||||
cherryview_load_csc_matrix(crtc_state);
|
||||
if (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC)
|
||||
chv_load_cgm_csc(crtc, ctm);
|
||||
|
||||
if (crtc_state_is_legacy_gamma(crtc_state)) {
|
||||
i9xx_load_luts(crtc_state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (degamma_lut)
|
||||
if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
|
||||
chv_load_cgm_degamma(crtc, degamma_lut);
|
||||
|
||||
if (gamma_lut)
|
||||
if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
|
||||
chv_load_cgm_gamma(crtc, gamma_lut);
|
||||
else
|
||||
i965_load_luts(crtc_state);
|
||||
|
||||
intel_de_write(dev_priv, CGM_PIPE_MODE(crtc->pipe),
|
||||
crtc_state->cgm_mode);
|
||||
}
|
||||
|
||||
void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
@ -1660,28 +1722,13 @@ bool intel_color_lut_equal(struct drm_property_blob *blob1,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* convert hw value with given bit_precision to lut property val */
|
||||
static u32 intel_color_lut_pack(u32 val, u32 bit_precision)
|
||||
static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
|
||||
{
|
||||
u32 max = 0xffff >> (16 - bit_precision);
|
||||
|
||||
val = clamp_val(val, 0, max);
|
||||
|
||||
if (bit_precision < 16)
|
||||
val <<= 16 - bit_precision;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static struct drm_property_blob *
|
||||
i9xx_read_lut_8(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
struct drm_property_blob *blob;
|
||||
struct drm_color_lut *blob_data;
|
||||
u32 i, val;
|
||||
struct drm_color_lut *lut;
|
||||
int i;
|
||||
|
||||
blob = drm_property_create_blob(&dev_priv->drm,
|
||||
sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH,
|
||||
@ -1689,20 +1736,12 @@ i9xx_read_lut_8(const struct intel_crtc_state *crtc_state)
|
||||
if (IS_ERR(blob))
|
||||
return NULL;
|
||||
|
||||
blob_data = blob->data;
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
|
||||
if (HAS_GMCH(dev_priv))
|
||||
val = intel_de_read(dev_priv, PALETTE(pipe, i));
|
||||
else
|
||||
val = intel_de_read(dev_priv, LGC_PALETTE(pipe, i));
|
||||
u32 val = intel_de_read(dev_priv, PALETTE(pipe, i));
|
||||
|
||||
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
|
||||
LGC_PALETTE_RED_MASK, val), 8);
|
||||
blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
|
||||
LGC_PALETTE_GREEN_MASK, val), 8);
|
||||
blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
|
||||
LGC_PALETTE_BLUE_MASK, val), 8);
|
||||
i9xx_lut_8_pack(&lut[i], val);
|
||||
}
|
||||
|
||||
return blob;
|
||||
@ -1710,22 +1749,21 @@ i9xx_read_lut_8(const struct intel_crtc_state *crtc_state)
|
||||
|
||||
static void i9xx_read_luts(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
if (!crtc_state->gamma_enable)
|
||||
return;
|
||||
|
||||
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
|
||||
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc);
|
||||
}
|
||||
|
||||
static struct drm_property_blob *
|
||||
i965_read_lut_10p6(const struct intel_crtc_state *crtc_state)
|
||||
static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
|
||||
int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
struct drm_property_blob *blob;
|
||||
struct drm_color_lut *blob_data;
|
||||
u32 i, val1, val2;
|
||||
struct drm_color_lut *lut;
|
||||
|
||||
blob = drm_property_create_blob(&dev_priv->drm,
|
||||
sizeof(struct drm_color_lut) * lut_size,
|
||||
@ -1733,51 +1771,42 @@ i965_read_lut_10p6(const struct intel_crtc_state *crtc_state)
|
||||
if (IS_ERR(blob))
|
||||
return NULL;
|
||||
|
||||
blob_data = blob->data;
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < lut_size - 1; i++) {
|
||||
val1 = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 0));
|
||||
val2 = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 1));
|
||||
u32 ldw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 0));
|
||||
u32 udw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 1));
|
||||
|
||||
blob_data[i].red = REG_FIELD_GET(PALETTE_RED_MASK, val2) << 8 |
|
||||
REG_FIELD_GET(PALETTE_RED_MASK, val1);
|
||||
blob_data[i].green = REG_FIELD_GET(PALETTE_GREEN_MASK, val2) << 8 |
|
||||
REG_FIELD_GET(PALETTE_GREEN_MASK, val1);
|
||||
blob_data[i].blue = REG_FIELD_GET(PALETTE_BLUE_MASK, val2) << 8 |
|
||||
REG_FIELD_GET(PALETTE_BLUE_MASK, val1);
|
||||
i965_lut_10p6_pack(&lut[i], ldw, udw);
|
||||
}
|
||||
|
||||
blob_data[i].red = REG_FIELD_GET(PIPEGCMAX_RGB_MASK,
|
||||
intel_de_read(dev_priv, PIPEGCMAX(pipe, 0)));
|
||||
blob_data[i].green = REG_FIELD_GET(PIPEGCMAX_RGB_MASK,
|
||||
intel_de_read(dev_priv, PIPEGCMAX(pipe, 1)));
|
||||
blob_data[i].blue = REG_FIELD_GET(PIPEGCMAX_RGB_MASK,
|
||||
intel_de_read(dev_priv, PIPEGCMAX(pipe, 2)));
|
||||
lut[i].red = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 0)));
|
||||
lut[i].green = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 1)));
|
||||
lut[i].blue = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 2)));
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
static void i965_read_luts(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
if (!crtc_state->gamma_enable)
|
||||
return;
|
||||
|
||||
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
|
||||
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
|
||||
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc);
|
||||
else
|
||||
crtc_state->hw.gamma_lut = i965_read_lut_10p6(crtc_state);
|
||||
crtc_state->hw.gamma_lut = i965_read_lut_10p6(crtc);
|
||||
}
|
||||
|
||||
static struct drm_property_blob *
|
||||
chv_read_cgm_lut(const struct intel_crtc_state *crtc_state)
|
||||
static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
|
||||
int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
struct drm_property_blob *blob;
|
||||
struct drm_color_lut *blob_data;
|
||||
u32 i, val;
|
||||
struct drm_color_lut *lut;
|
||||
|
||||
blob = drm_property_create_blob(&dev_priv->drm,
|
||||
sizeof(struct drm_color_lut) * lut_size,
|
||||
@ -1785,18 +1814,13 @@ chv_read_cgm_lut(const struct intel_crtc_state *crtc_state)
|
||||
if (IS_ERR(blob))
|
||||
return NULL;
|
||||
|
||||
blob_data = blob->data;
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
val = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0));
|
||||
blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
|
||||
CGM_PIPE_GAMMA_GREEN_MASK, val), 10);
|
||||
blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
|
||||
CGM_PIPE_GAMMA_BLUE_MASK, val), 10);
|
||||
u32 ldw = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0));
|
||||
u32 udw = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1));
|
||||
|
||||
val = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1));
|
||||
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
|
||||
CGM_PIPE_GAMMA_RED_MASK, val), 10);
|
||||
chv_cgm_gamma_pack(&lut[i], ldw, udw);
|
||||
}
|
||||
|
||||
return blob;
|
||||
@ -1804,22 +1828,46 @@ chv_read_cgm_lut(const struct intel_crtc_state *crtc_state)
|
||||
|
||||
static void chv_read_luts(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
|
||||
crtc_state->hw.gamma_lut = chv_read_cgm_lut(crtc_state);
|
||||
crtc_state->hw.gamma_lut = chv_read_cgm_gamma(crtc);
|
||||
else
|
||||
i965_read_luts(crtc_state);
|
||||
}
|
||||
|
||||
static struct drm_property_blob *
|
||||
ilk_read_lut_10(const struct intel_crtc_state *crtc_state)
|
||||
static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
struct drm_property_blob *blob;
|
||||
struct drm_color_lut *blob_data;
|
||||
u32 i, val;
|
||||
struct drm_color_lut *lut;
|
||||
int i;
|
||||
|
||||
blob = drm_property_create_blob(&dev_priv->drm,
|
||||
sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH,
|
||||
NULL);
|
||||
if (IS_ERR(blob))
|
||||
return NULL;
|
||||
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
|
||||
u32 val = intel_de_read(dev_priv, LGC_PALETTE(pipe, i));
|
||||
|
||||
i9xx_lut_8_pack(&lut[i], val);
|
||||
}
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
struct drm_property_blob *blob;
|
||||
struct drm_color_lut *lut;
|
||||
|
||||
blob = drm_property_create_blob(&dev_priv->drm,
|
||||
sizeof(struct drm_color_lut) * lut_size,
|
||||
@ -1827,17 +1875,12 @@ ilk_read_lut_10(const struct intel_crtc_state *crtc_state)
|
||||
if (IS_ERR(blob))
|
||||
return NULL;
|
||||
|
||||
blob_data = blob->data;
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
val = intel_de_read(dev_priv, PREC_PALETTE(pipe, i));
|
||||
u32 val = intel_de_read(dev_priv, PREC_PALETTE(pipe, i));
|
||||
|
||||
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
|
||||
PREC_PALETTE_RED_MASK, val), 10);
|
||||
blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
|
||||
PREC_PALETTE_GREEN_MASK, val), 10);
|
||||
blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
|
||||
PREC_PALETTE_BLUE_MASK, val), 10);
|
||||
ilk_lut_10_pack(&lut[i], val);
|
||||
}
|
||||
|
||||
return blob;
|
||||
@ -1845,6 +1888,8 @@ ilk_read_lut_10(const struct intel_crtc_state *crtc_state)
|
||||
|
||||
static void ilk_read_luts(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
if (!crtc_state->gamma_enable)
|
||||
return;
|
||||
|
||||
@ -1852,21 +1897,19 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state)
|
||||
return;
|
||||
|
||||
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
|
||||
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
|
||||
crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc);
|
||||
else
|
||||
crtc_state->hw.gamma_lut = ilk_read_lut_10(crtc_state);
|
||||
crtc_state->hw.gamma_lut = ilk_read_lut_10(crtc);
|
||||
}
|
||||
|
||||
static struct drm_property_blob *
|
||||
glk_read_lut_10(const struct intel_crtc_state *crtc_state, u32 prec_index)
|
||||
static struct drm_property_blob *glk_read_lut_10(struct intel_crtc *crtc,
|
||||
u32 prec_index)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
int hw_lut_size = ivb_lut_10_size(prec_index);
|
||||
int i, hw_lut_size = ivb_lut_10_size(prec_index);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
struct drm_property_blob *blob;
|
||||
struct drm_color_lut *blob_data;
|
||||
u32 i, val;
|
||||
struct drm_color_lut *lut;
|
||||
|
||||
blob = drm_property_create_blob(&dev_priv->drm,
|
||||
sizeof(struct drm_color_lut) * hw_lut_size,
|
||||
@ -1874,20 +1917,15 @@ glk_read_lut_10(const struct intel_crtc_state *crtc_state, u32 prec_index)
|
||||
if (IS_ERR(blob))
|
||||
return NULL;
|
||||
|
||||
blob_data = blob->data;
|
||||
lut = blob->data;
|
||||
|
||||
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe),
|
||||
prec_index | PAL_PREC_AUTO_INCREMENT);
|
||||
|
||||
for (i = 0; i < hw_lut_size; i++) {
|
||||
val = intel_de_read(dev_priv, PREC_PAL_DATA(pipe));
|
||||
u32 val = intel_de_read(dev_priv, PREC_PAL_DATA(pipe));
|
||||
|
||||
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
|
||||
PREC_PAL_DATA_RED_MASK, val), 10);
|
||||
blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
|
||||
PREC_PAL_DATA_GREEN_MASK, val), 10);
|
||||
blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
|
||||
PREC_PAL_DATA_BLUE_MASK, val), 10);
|
||||
ilk_lut_10_pack(&lut[i], val);
|
||||
}
|
||||
|
||||
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0);
|
||||
@ -1897,13 +1935,15 @@ glk_read_lut_10(const struct intel_crtc_state *crtc_state, u32 prec_index)
|
||||
|
||||
static void glk_read_luts(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
if (!crtc_state->gamma_enable)
|
||||
return;
|
||||
|
||||
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
|
||||
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
|
||||
crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc);
|
||||
else
|
||||
crtc_state->hw.gamma_lut = glk_read_lut_10(crtc_state, PAL_PREC_INDEX_VALUE(0));
|
||||
crtc_state->hw.gamma_lut = glk_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
|
||||
}
|
||||
|
||||
void intel_color_init(struct intel_crtc *crtc)
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_connector.h"
|
||||
|
@ -40,8 +40,8 @@
|
||||
|
||||
#define GEN12_CSR_MAX_FW_SIZE ICL_CSR_MAX_FW_SIZE
|
||||
|
||||
#define TGL_CSR_PATH "i915/tgl_dmc_ver2_04.bin"
|
||||
#define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 4)
|
||||
#define TGL_CSR_PATH "i915/tgl_dmc_ver2_06.bin"
|
||||
#define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 6)
|
||||
#define TGL_CSR_MAX_FW_SIZE 0x6000
|
||||
MODULE_FIRMWARE(TGL_CSR_PATH);
|
||||
|
||||
|
@ -1325,164 +1325,6 @@ intel_ddi_get_crtc_encoder(struct intel_crtc *crtc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
|
||||
i915_reg_t reg)
|
||||
{
|
||||
int refclk;
|
||||
int n, p, r;
|
||||
u32 wrpll;
|
||||
|
||||
wrpll = intel_de_read(dev_priv, reg);
|
||||
switch (wrpll & WRPLL_REF_MASK) {
|
||||
case WRPLL_REF_SPECIAL_HSW:
|
||||
/*
|
||||
* muxed-SSC for BDW.
|
||||
* non-SSC for non-ULT HSW. Check FUSE_STRAP3
|
||||
* for the non-SSC reference frequency.
|
||||
*/
|
||||
if (IS_HASWELL(dev_priv) && !IS_HSW_ULT(dev_priv)) {
|
||||
if (intel_de_read(dev_priv, FUSE_STRAP3) & HSW_REF_CLK_SELECT)
|
||||
refclk = 24;
|
||||
else
|
||||
refclk = 135;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case WRPLL_REF_PCH_SSC:
|
||||
/*
|
||||
* We could calculate spread here, but our checking
|
||||
* code only cares about 5% accuracy, and spread is a max of
|
||||
* 0.5% downspread.
|
||||
*/
|
||||
refclk = 135;
|
||||
break;
|
||||
case WRPLL_REF_LCPLL:
|
||||
refclk = 2700;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(wrpll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = wrpll & WRPLL_DIVIDER_REF_MASK;
|
||||
p = (wrpll & WRPLL_DIVIDER_POST_MASK) >> WRPLL_DIVIDER_POST_SHIFT;
|
||||
n = (wrpll & WRPLL_DIVIDER_FB_MASK) >> WRPLL_DIVIDER_FB_SHIFT;
|
||||
|
||||
/* Convert to KHz, p & r have a fixed point portion */
|
||||
return (refclk * n * 100) / (p * r);
|
||||
}
|
||||
|
||||
static int skl_calc_wrpll_link(const struct intel_dpll_hw_state *pll_state)
|
||||
{
|
||||
u32 p0, p1, p2, dco_freq;
|
||||
|
||||
p0 = pll_state->cfgcr2 & DPLL_CFGCR2_PDIV_MASK;
|
||||
p2 = pll_state->cfgcr2 & DPLL_CFGCR2_KDIV_MASK;
|
||||
|
||||
if (pll_state->cfgcr2 & DPLL_CFGCR2_QDIV_MODE(1))
|
||||
p1 = (pll_state->cfgcr2 & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8;
|
||||
else
|
||||
p1 = 1;
|
||||
|
||||
|
||||
switch (p0) {
|
||||
case DPLL_CFGCR2_PDIV_1:
|
||||
p0 = 1;
|
||||
break;
|
||||
case DPLL_CFGCR2_PDIV_2:
|
||||
p0 = 2;
|
||||
break;
|
||||
case DPLL_CFGCR2_PDIV_3:
|
||||
p0 = 3;
|
||||
break;
|
||||
case DPLL_CFGCR2_PDIV_7:
|
||||
p0 = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (p2) {
|
||||
case DPLL_CFGCR2_KDIV_5:
|
||||
p2 = 5;
|
||||
break;
|
||||
case DPLL_CFGCR2_KDIV_2:
|
||||
p2 = 2;
|
||||
break;
|
||||
case DPLL_CFGCR2_KDIV_3:
|
||||
p2 = 3;
|
||||
break;
|
||||
case DPLL_CFGCR2_KDIV_1:
|
||||
p2 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
dco_freq = (pll_state->cfgcr1 & DPLL_CFGCR1_DCO_INTEGER_MASK)
|
||||
* 24 * 1000;
|
||||
|
||||
dco_freq += (((pll_state->cfgcr1 & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9)
|
||||
* 24 * 1000) / 0x8000;
|
||||
|
||||
if (WARN_ON(p0 == 0 || p1 == 0 || p2 == 0))
|
||||
return 0;
|
||||
|
||||
return dco_freq / (p0 * p1 * p2 * 5);
|
||||
}
|
||||
|
||||
int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *pll_state)
|
||||
{
|
||||
u32 p0, p1, p2, dco_freq, ref_clock;
|
||||
|
||||
p0 = pll_state->cfgcr1 & DPLL_CFGCR1_PDIV_MASK;
|
||||
p2 = pll_state->cfgcr1 & DPLL_CFGCR1_KDIV_MASK;
|
||||
|
||||
if (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1))
|
||||
p1 = (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >>
|
||||
DPLL_CFGCR1_QDIV_RATIO_SHIFT;
|
||||
else
|
||||
p1 = 1;
|
||||
|
||||
|
||||
switch (p0) {
|
||||
case DPLL_CFGCR1_PDIV_2:
|
||||
p0 = 2;
|
||||
break;
|
||||
case DPLL_CFGCR1_PDIV_3:
|
||||
p0 = 3;
|
||||
break;
|
||||
case DPLL_CFGCR1_PDIV_5:
|
||||
p0 = 5;
|
||||
break;
|
||||
case DPLL_CFGCR1_PDIV_7:
|
||||
p0 = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (p2) {
|
||||
case DPLL_CFGCR1_KDIV_1:
|
||||
p2 = 1;
|
||||
break;
|
||||
case DPLL_CFGCR1_KDIV_2:
|
||||
p2 = 2;
|
||||
break;
|
||||
case DPLL_CFGCR1_KDIV_3:
|
||||
p2 = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
ref_clock = cnl_hdmi_pll_ref_clock(dev_priv);
|
||||
|
||||
dco_freq = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK)
|
||||
* ref_clock;
|
||||
|
||||
dco_freq += (((pll_state->cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >>
|
||||
DPLL_CFGCR0_DCO_FRACTION_SHIFT) * ref_clock) / 0x8000;
|
||||
|
||||
if (drm_WARN_ON(&dev_priv->drm, p0 == 0 || p1 == 0 || p2 == 0))
|
||||
return 0;
|
||||
|
||||
return dco_freq / (p0 * p1 * p2 * 5);
|
||||
}
|
||||
|
||||
static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
@ -1505,77 +1347,6 @@ static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
|
||||
}
|
||||
}
|
||||
|
||||
static int icl_calc_mg_pll_link(struct drm_i915_private *dev_priv,
|
||||
const struct intel_dpll_hw_state *pll_state)
|
||||
{
|
||||
u32 m1, m2_int, m2_frac, div1, div2, ref_clock;
|
||||
u64 tmp;
|
||||
|
||||
ref_clock = dev_priv->cdclk.hw.ref;
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 12) {
|
||||
m1 = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBPREDIV_MASK;
|
||||
m1 = m1 >> DKL_PLL_DIV0_FBPREDIV_SHIFT;
|
||||
m2_int = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBDIV_INT_MASK;
|
||||
|
||||
if (pll_state->mg_pll_bias & DKL_PLL_BIAS_FRAC_EN_H) {
|
||||
m2_frac = pll_state->mg_pll_bias &
|
||||
DKL_PLL_BIAS_FBDIV_FRAC_MASK;
|
||||
m2_frac = m2_frac >> DKL_PLL_BIAS_FBDIV_SHIFT;
|
||||
} else {
|
||||
m2_frac = 0;
|
||||
}
|
||||
} else {
|
||||
m1 = pll_state->mg_pll_div1 & MG_PLL_DIV1_FBPREDIV_MASK;
|
||||
m2_int = pll_state->mg_pll_div0 & MG_PLL_DIV0_FBDIV_INT_MASK;
|
||||
|
||||
if (pll_state->mg_pll_div0 & MG_PLL_DIV0_FRACNEN_H) {
|
||||
m2_frac = pll_state->mg_pll_div0 &
|
||||
MG_PLL_DIV0_FBDIV_FRAC_MASK;
|
||||
m2_frac = m2_frac >> MG_PLL_DIV0_FBDIV_FRAC_SHIFT;
|
||||
} else {
|
||||
m2_frac = 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (pll_state->mg_clktop2_hsclkctl &
|
||||
MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK) {
|
||||
case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2:
|
||||
div1 = 2;
|
||||
break;
|
||||
case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_3:
|
||||
div1 = 3;
|
||||
break;
|
||||
case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_5:
|
||||
div1 = 5;
|
||||
break;
|
||||
case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_7:
|
||||
div1 = 7;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(pll_state->mg_clktop2_hsclkctl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
div2 = (pll_state->mg_clktop2_hsclkctl &
|
||||
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK) >>
|
||||
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_SHIFT;
|
||||
|
||||
/* div2 value of 0 is same as 1 means no div */
|
||||
if (div2 == 0)
|
||||
div2 = 1;
|
||||
|
||||
/*
|
||||
* Adjust the original formula to delay the division by 2^22 in order to
|
||||
* minimize possible rounding errors.
|
||||
*/
|
||||
tmp = (u64)m1 * m2_int * ref_clock +
|
||||
(((u64)m1 * m2_frac * ref_clock) >> 22);
|
||||
tmp = div_u64(tmp, 5 * div1 * div2);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
int dotclock;
|
||||
@ -1601,215 +1372,22 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
|
||||
pipe_config->hw.adjusted_mode.crtc_clock = dotclock;
|
||||
}
|
||||
|
||||
static void icl_ddi_clock_get(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_dpll_hw_state *pll_state = &pipe_config->dpll_hw_state;
|
||||
enum port port = encoder->port;
|
||||
enum phy phy = intel_port_to_phy(dev_priv, port);
|
||||
int link_clock;
|
||||
|
||||
if (intel_phy_is_combo(dev_priv, phy)) {
|
||||
link_clock = cnl_calc_wrpll_link(dev_priv, pll_state);
|
||||
} else {
|
||||
enum intel_dpll_id pll_id = intel_get_shared_dpll_id(dev_priv,
|
||||
pipe_config->shared_dpll);
|
||||
|
||||
if (pll_id == DPLL_ID_ICL_TBTPLL)
|
||||
link_clock = icl_calc_tbt_pll_link(dev_priv, port);
|
||||
else
|
||||
link_clock = icl_calc_mg_pll_link(dev_priv, pll_state);
|
||||
}
|
||||
|
||||
pipe_config->port_clock = link_clock;
|
||||
|
||||
ddi_dotclock_get(pipe_config);
|
||||
}
|
||||
|
||||
static void cnl_ddi_clock_get(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_dpll_hw_state *pll_state = &pipe_config->dpll_hw_state;
|
||||
int link_clock;
|
||||
|
||||
if (pll_state->cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
|
||||
link_clock = cnl_calc_wrpll_link(dev_priv, pll_state);
|
||||
} else {
|
||||
link_clock = pll_state->cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK;
|
||||
|
||||
switch (link_clock) {
|
||||
case DPLL_CFGCR0_LINK_RATE_810:
|
||||
link_clock = 81000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_1080:
|
||||
link_clock = 108000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_1350:
|
||||
link_clock = 135000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_1620:
|
||||
link_clock = 162000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_2160:
|
||||
link_clock = 216000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_2700:
|
||||
link_clock = 270000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_3240:
|
||||
link_clock = 324000;
|
||||
break;
|
||||
case DPLL_CFGCR0_LINK_RATE_4050:
|
||||
link_clock = 405000;
|
||||
break;
|
||||
default:
|
||||
drm_WARN(&dev_priv->drm, 1, "Unsupported link rate\n");
|
||||
break;
|
||||
}
|
||||
link_clock *= 2;
|
||||
}
|
||||
|
||||
pipe_config->port_clock = link_clock;
|
||||
|
||||
ddi_dotclock_get(pipe_config);
|
||||
}
|
||||
|
||||
static void skl_ddi_clock_get(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct intel_dpll_hw_state *pll_state = &pipe_config->dpll_hw_state;
|
||||
int link_clock;
|
||||
|
||||
/*
|
||||
* ctrl1 register is already shifted for each pll, just use 0 to get
|
||||
* the internal shift for each field
|
||||
*/
|
||||
if (pll_state->ctrl1 & DPLL_CTRL1_HDMI_MODE(0)) {
|
||||
link_clock = skl_calc_wrpll_link(pll_state);
|
||||
} else {
|
||||
link_clock = pll_state->ctrl1 & DPLL_CTRL1_LINK_RATE_MASK(0);
|
||||
link_clock >>= DPLL_CTRL1_LINK_RATE_SHIFT(0);
|
||||
|
||||
switch (link_clock) {
|
||||
case DPLL_CTRL1_LINK_RATE_810:
|
||||
link_clock = 81000;
|
||||
break;
|
||||
case DPLL_CTRL1_LINK_RATE_1080:
|
||||
link_clock = 108000;
|
||||
break;
|
||||
case DPLL_CTRL1_LINK_RATE_1350:
|
||||
link_clock = 135000;
|
||||
break;
|
||||
case DPLL_CTRL1_LINK_RATE_1620:
|
||||
link_clock = 162000;
|
||||
break;
|
||||
case DPLL_CTRL1_LINK_RATE_2160:
|
||||
link_clock = 216000;
|
||||
break;
|
||||
case DPLL_CTRL1_LINK_RATE_2700:
|
||||
link_clock = 270000;
|
||||
break;
|
||||
default:
|
||||
drm_WARN(encoder->base.dev, 1,
|
||||
"Unsupported link rate\n");
|
||||
break;
|
||||
}
|
||||
link_clock *= 2;
|
||||
}
|
||||
|
||||
pipe_config->port_clock = link_clock;
|
||||
|
||||
ddi_dotclock_get(pipe_config);
|
||||
}
|
||||
|
||||
static void hsw_ddi_clock_get(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
int link_clock = 0;
|
||||
u32 val, pll;
|
||||
|
||||
val = hsw_pll_to_ddi_pll_sel(pipe_config->shared_dpll);
|
||||
switch (val & PORT_CLK_SEL_MASK) {
|
||||
case PORT_CLK_SEL_LCPLL_810:
|
||||
link_clock = 81000;
|
||||
break;
|
||||
case PORT_CLK_SEL_LCPLL_1350:
|
||||
link_clock = 135000;
|
||||
break;
|
||||
case PORT_CLK_SEL_LCPLL_2700:
|
||||
link_clock = 270000;
|
||||
break;
|
||||
case PORT_CLK_SEL_WRPLL1:
|
||||
link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(0));
|
||||
break;
|
||||
case PORT_CLK_SEL_WRPLL2:
|
||||
link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(1));
|
||||
break;
|
||||
case PORT_CLK_SEL_SPLL:
|
||||
pll = intel_de_read(dev_priv, SPLL_CTL) & SPLL_FREQ_MASK;
|
||||
if (pll == SPLL_FREQ_810MHz)
|
||||
link_clock = 81000;
|
||||
else if (pll == SPLL_FREQ_1350MHz)
|
||||
link_clock = 135000;
|
||||
else if (pll == SPLL_FREQ_2700MHz)
|
||||
link_clock = 270000;
|
||||
else {
|
||||
drm_WARN(&dev_priv->drm, 1, "bad spll freq\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
drm_WARN(&dev_priv->drm, 1, "bad port clock sel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pipe_config->port_clock = link_clock * 2;
|
||||
|
||||
ddi_dotclock_get(pipe_config);
|
||||
}
|
||||
|
||||
static int bxt_calc_pll_link(const struct intel_dpll_hw_state *pll_state)
|
||||
{
|
||||
struct dpll clock;
|
||||
|
||||
clock.m1 = 2;
|
||||
clock.m2 = (pll_state->pll0 & PORT_PLL_M2_MASK) << 22;
|
||||
if (pll_state->pll3 & PORT_PLL_M2_FRAC_ENABLE)
|
||||
clock.m2 |= pll_state->pll2 & PORT_PLL_M2_FRAC_MASK;
|
||||
clock.n = (pll_state->pll1 & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT;
|
||||
clock.p1 = (pll_state->ebb0 & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT;
|
||||
clock.p2 = (pll_state->ebb0 & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT;
|
||||
|
||||
return chv_calc_dpll_params(100000, &clock);
|
||||
}
|
||||
|
||||
static void bxt_ddi_clock_get(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
pipe_config->port_clock =
|
||||
bxt_calc_pll_link(&pipe_config->dpll_hw_state);
|
||||
|
||||
ddi_dotclock_get(pipe_config);
|
||||
}
|
||||
|
||||
static void intel_ddi_clock_get(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 11)
|
||||
icl_ddi_clock_get(encoder, pipe_config);
|
||||
else if (IS_CANNONLAKE(dev_priv))
|
||||
cnl_ddi_clock_get(encoder, pipe_config);
|
||||
else if (IS_GEN9_LP(dev_priv))
|
||||
bxt_ddi_clock_get(encoder, pipe_config);
|
||||
else if (IS_GEN9_BC(dev_priv))
|
||||
skl_ddi_clock_get(encoder, pipe_config);
|
||||
else if (INTEL_GEN(dev_priv) <= 8)
|
||||
hsw_ddi_clock_get(encoder, pipe_config);
|
||||
if (intel_phy_is_tc(dev_priv, phy) &&
|
||||
intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll) ==
|
||||
DPLL_ID_ICL_TBTPLL)
|
||||
pipe_config->port_clock = icl_calc_tbt_pll_link(dev_priv,
|
||||
encoder->port);
|
||||
else
|
||||
pipe_config->port_clock =
|
||||
intel_dpll_get_freq(dev_priv, pipe_config->shared_dpll);
|
||||
|
||||
ddi_dotclock_get(pipe_config);
|
||||
}
|
||||
|
||||
void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
|
||||
@ -3049,7 +2627,7 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder,
|
||||
enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
|
||||
u32 val;
|
||||
|
||||
mutex_lock(&dev_priv->dpll_lock);
|
||||
mutex_lock(&dev_priv->dpll.lock);
|
||||
|
||||
val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
|
||||
drm_WARN_ON(&dev_priv->drm,
|
||||
@ -3075,7 +2653,7 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder,
|
||||
val &= ~icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
|
||||
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
|
||||
|
||||
mutex_unlock(&dev_priv->dpll_lock);
|
||||
mutex_unlock(&dev_priv->dpll.lock);
|
||||
}
|
||||
|
||||
static void icl_unmap_plls_to_ports(struct intel_encoder *encoder)
|
||||
@ -3084,13 +2662,13 @@ static void icl_unmap_plls_to_ports(struct intel_encoder *encoder)
|
||||
enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
|
||||
u32 val;
|
||||
|
||||
mutex_lock(&dev_priv->dpll_lock);
|
||||
mutex_lock(&dev_priv->dpll.lock);
|
||||
|
||||
val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
|
||||
val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
|
||||
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
|
||||
|
||||
mutex_unlock(&dev_priv->dpll_lock);
|
||||
mutex_unlock(&dev_priv->dpll.lock);
|
||||
}
|
||||
|
||||
static void icl_sanitize_port_clk_off(struct drm_i915_private *dev_priv,
|
||||
@ -3189,7 +2767,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
|
||||
if (drm_WARN_ON(&dev_priv->drm, !pll))
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->dpll_lock);
|
||||
mutex_lock(&dev_priv->dpll.lock);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 11) {
|
||||
if (!intel_phy_is_combo(dev_priv, phy))
|
||||
@ -3233,7 +2811,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
|
||||
hsw_pll_to_ddi_pll_sel(pll));
|
||||
}
|
||||
|
||||
mutex_unlock(&dev_priv->dpll_lock);
|
||||
mutex_unlock(&dev_priv->dpll.lock);
|
||||
}
|
||||
|
||||
static void intel_ddi_clk_disable(struct intel_encoder *encoder)
|
||||
@ -3987,8 +3565,9 @@ static void intel_enable_ddi_hdmi(struct intel_encoder *encoder,
|
||||
if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
|
||||
crtc_state->hdmi_high_tmds_clock_ratio,
|
||||
crtc_state->hdmi_scrambling))
|
||||
DRM_ERROR("[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n",
|
||||
connector->base.id, connector->name);
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Failed to configure sink "
|
||||
"scrambling/TMDS bit clock ratio\n",
|
||||
connector->base.id, connector->name);
|
||||
|
||||
/* Display WA #1143: skl,kbl,cfl */
|
||||
if (IS_GEN9_BC(dev_priv)) {
|
||||
|
@ -6,8 +6,6 @@
|
||||
#ifndef __INTEL_DDI_H__
|
||||
#define __INTEL_DDI_H__
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "intel_display.h"
|
||||
|
||||
struct drm_connector_state;
|
||||
@ -47,7 +45,5 @@ u8 intel_ddi_dp_pre_emphasis_max(struct intel_encoder *encoder,
|
||||
int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
|
||||
bool enable);
|
||||
void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder);
|
||||
int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *state);
|
||||
|
||||
#endif /* __INTEL_DDI_H__ */
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "display/intel_crt.h"
|
||||
#include "display/intel_ddi.h"
|
||||
@ -2720,9 +2719,10 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
|
||||
|
||||
/*
|
||||
* We assume the primary plane for pipe A has
|
||||
* the highest stride limits of them all.
|
||||
* the highest stride limits of them all,
|
||||
* if in case pipe A is disabled, use the first pipe from pipe_mask.
|
||||
*/
|
||||
crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
|
||||
crtc = intel_get_first_crtc(dev_priv);
|
||||
if (!crtc)
|
||||
return 0;
|
||||
|
||||
@ -9542,7 +9542,7 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
|
||||
}
|
||||
|
||||
/* Check if any DPLLs are using the SSC source */
|
||||
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
||||
for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) {
|
||||
u32 temp = intel_de_read(dev_priv, PCH_DPLL(i));
|
||||
|
||||
if (!(temp & DPLL_VCO_ENABLE))
|
||||
@ -10129,6 +10129,9 @@ static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
|
||||
BIT(PLANE_CURSOR))) == 0)
|
||||
val |= PIPEMISC_HDR_MODE_PRECISION;
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 12)
|
||||
val |= PIPEMISC_PIXEL_ROUNDING_TRUNC;
|
||||
|
||||
intel_de_write(dev_priv, PIPEMISC(crtc->pipe), val);
|
||||
}
|
||||
|
||||
@ -14299,11 +14302,11 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,
|
||||
if (new_crtc_state->hw.active)
|
||||
I915_STATE_WARN(!(pll->active_mask & crtc_mask),
|
||||
"pll active mismatch (expected pipe %c in active mask 0x%02x)\n",
|
||||
pipe_name(drm_crtc_index(&crtc->base)), pll->active_mask);
|
||||
pipe_name(crtc->pipe), pll->active_mask);
|
||||
else
|
||||
I915_STATE_WARN(pll->active_mask & crtc_mask,
|
||||
"pll active mismatch (didn't expect pipe %c in active mask 0x%02x)\n",
|
||||
pipe_name(drm_crtc_index(&crtc->base)), pll->active_mask);
|
||||
pipe_name(crtc->pipe), pll->active_mask);
|
||||
|
||||
I915_STATE_WARN(!(pll->state.crtc_mask & crtc_mask),
|
||||
"pll enabled crtcs mismatch (expected 0x%x in 0x%02x)\n",
|
||||
@ -14332,10 +14335,10 @@ verify_shared_dpll_state(struct intel_crtc *crtc,
|
||||
|
||||
I915_STATE_WARN(pll->active_mask & crtc_mask,
|
||||
"pll active mismatch (didn't expect pipe %c in active mask)\n",
|
||||
pipe_name(drm_crtc_index(&crtc->base)));
|
||||
pipe_name(crtc->pipe));
|
||||
I915_STATE_WARN(pll->state.crtc_mask & crtc_mask,
|
||||
"pll enabled crtcs mismatch (found %x in enabled mask)\n",
|
||||
pipe_name(drm_crtc_index(&crtc->base)));
|
||||
pipe_name(crtc->pipe));
|
||||
}
|
||||
}
|
||||
|
||||
@ -14359,8 +14362,10 @@ verify_disabled_dpll_state(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev_priv->num_shared_dpll; i++)
|
||||
verify_single_dpll_state(dev_priv, &dev_priv->shared_dplls[i], NULL, NULL);
|
||||
for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++)
|
||||
verify_single_dpll_state(dev_priv,
|
||||
&dev_priv->dpll.shared_dplls[i],
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -15318,7 +15323,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
|
||||
const u8 num_pipes = INTEL_NUM_PIPES(dev_priv);
|
||||
u8 update_pipes = 0, modeset_pipes = 0;
|
||||
int i;
|
||||
|
||||
@ -15355,7 +15359,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
|
||||
continue;
|
||||
|
||||
if (skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb,
|
||||
entries, num_pipes, pipe))
|
||||
entries, I915_MAX_PIPES, pipe))
|
||||
continue;
|
||||
|
||||
entries[pipe] = new_crtc_state->wm.skl.ddb;
|
||||
@ -15393,7 +15397,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
|
||||
continue;
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb,
|
||||
entries, num_pipes, pipe));
|
||||
entries, I915_MAX_PIPES, pipe));
|
||||
|
||||
entries[pipe] = new_crtc_state->wm.skl.ddb;
|
||||
modeset_pipes &= ~BIT(pipe);
|
||||
@ -15428,7 +15432,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
|
||||
continue;
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb,
|
||||
entries, num_pipes, pipe));
|
||||
entries, I915_MAX_PIPES, pipe));
|
||||
|
||||
entries[pipe] = new_crtc_state->wm.skl.ddb;
|
||||
modeset_pipes &= ~BIT(pipe);
|
||||
@ -16320,7 +16324,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
struct intel_plane *plane;
|
||||
const struct drm_plane_funcs *plane_funcs;
|
||||
unsigned int supported_rotations;
|
||||
unsigned int possible_crtcs;
|
||||
const u32 *formats;
|
||||
int num_formats;
|
||||
int ret, zpos;
|
||||
@ -16401,18 +16404,16 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
plane->get_hw_state = i9xx_plane_get_hw_state;
|
||||
plane->check_plane = i9xx_plane_check;
|
||||
|
||||
possible_crtcs = BIT(pipe);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
|
||||
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
|
||||
possible_crtcs, plane_funcs,
|
||||
0, plane_funcs,
|
||||
formats, num_formats,
|
||||
i9xx_format_modifiers,
|
||||
DRM_PLANE_TYPE_PRIMARY,
|
||||
"primary %c", pipe_name(pipe));
|
||||
else
|
||||
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
|
||||
possible_crtcs, plane_funcs,
|
||||
0, plane_funcs,
|
||||
formats, num_formats,
|
||||
i9xx_format_modifiers,
|
||||
DRM_PLANE_TYPE_PRIMARY,
|
||||
@ -16454,7 +16455,6 @@ static struct intel_plane *
|
||||
intel_cursor_plane_create(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe)
|
||||
{
|
||||
unsigned int possible_crtcs;
|
||||
struct intel_plane *cursor;
|
||||
int ret, zpos;
|
||||
|
||||
@ -16487,10 +16487,8 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
|
||||
if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
|
||||
cursor->cursor.size = ~0;
|
||||
|
||||
possible_crtcs = BIT(pipe);
|
||||
|
||||
ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
|
||||
possible_crtcs, &intel_cursor_plane_funcs,
|
||||
0, &intel_cursor_plane_funcs,
|
||||
intel_cursor_formats,
|
||||
ARRAY_SIZE(intel_cursor_formats),
|
||||
cursor_format_modifiers,
|
||||
@ -16619,6 +16617,18 @@ static void intel_crtc_free(struct intel_crtc *crtc)
|
||||
kfree(crtc);
|
||||
}
|
||||
|
||||
static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_plane *plane;
|
||||
|
||||
for_each_intel_plane(&dev_priv->drm, plane) {
|
||||
struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
|
||||
plane->pipe);
|
||||
|
||||
plane->base.possible_crtcs = drm_crtc_mask(&crtc->base);
|
||||
}
|
||||
}
|
||||
|
||||
static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
{
|
||||
struct intel_plane *primary, *cursor;
|
||||
@ -16697,6 +16707,8 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
|
||||
intel_color_init(crtc);
|
||||
|
||||
intel_crtc_crc_init(crtc);
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
|
||||
|
||||
return 0;
|
||||
@ -17785,11 +17797,9 @@ static void plane_config_fini(struct intel_initial_plane_config *plane_config)
|
||||
i915_vma_put(plane_config->vma);
|
||||
}
|
||||
|
||||
int intel_modeset_init(struct drm_i915_private *i915)
|
||||
/* part #1: call before irq install */
|
||||
int intel_modeset_init_noirq(struct drm_i915_private *i915)
|
||||
{
|
||||
struct drm_device *dev = &i915->drm;
|
||||
enum pipe pipe;
|
||||
struct intel_crtc *crtc;
|
||||
int ret;
|
||||
|
||||
i915->modeset_wq = alloc_ordered_workqueue("i915_modeset", 0);
|
||||
@ -17814,6 +17824,17 @@ int intel_modeset_init(struct drm_i915_private *i915)
|
||||
|
||||
intel_fbc_init(i915);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* part #2: call after irq install */
|
||||
int intel_modeset_init(struct drm_i915_private *i915)
|
||||
{
|
||||
struct drm_device *dev = &i915->drm;
|
||||
enum pipe pipe;
|
||||
struct intel_crtc *crtc;
|
||||
int ret;
|
||||
|
||||
intel_init_pm(i915);
|
||||
|
||||
intel_panel_sanitize_ssc(i915);
|
||||
@ -17834,6 +17855,7 @@ int intel_modeset_init(struct drm_i915_private *i915)
|
||||
}
|
||||
}
|
||||
|
||||
intel_plane_possible_crtcs_init(i915);
|
||||
intel_shared_dpll_init(dev);
|
||||
intel_update_fdi_pll_freq(i915);
|
||||
|
||||
@ -18311,7 +18333,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
||||
struct intel_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
u8 active_pipes = 0;
|
||||
int i;
|
||||
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
@ -18340,33 +18361,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
||||
|
||||
readout_plane_state(dev_priv);
|
||||
|
||||
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
||||
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
||||
|
||||
pll->on = pll->info->funcs->get_hw_state(dev_priv, pll,
|
||||
&pll->state.hw_state);
|
||||
|
||||
if (IS_ELKHARTLAKE(dev_priv) && pll->on &&
|
||||
pll->info->id == DPLL_ID_EHL_DPLL4) {
|
||||
pll->wakeref = intel_display_power_get(dev_priv,
|
||||
POWER_DOMAIN_DPLL_DC_OFF);
|
||||
}
|
||||
|
||||
pll->state.crtc_mask = 0;
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
|
||||
if (crtc_state->hw.active &&
|
||||
crtc_state->shared_dpll == pll)
|
||||
pll->state.crtc_mask |= 1 << crtc->pipe;
|
||||
}
|
||||
pll->active_mask = pll->state.crtc_mask;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"%s hw state readout: crtc_mask 0x%08x, on %i\n",
|
||||
pll->info->name, pll->state.crtc_mask, pll->on);
|
||||
}
|
||||
intel_dpll_readout_hw_state(dev_priv);
|
||||
|
||||
for_each_intel_encoder(dev, encoder) {
|
||||
pipe = 0;
|
||||
@ -18623,7 +18618,6 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_crtc *crtc;
|
||||
intel_wakeref_t wakeref;
|
||||
int i;
|
||||
|
||||
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
||||
|
||||
@ -18676,19 +18670,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
|
||||
|
||||
intel_modeset_update_connector_atomic_state(dev);
|
||||
|
||||
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
||||
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
||||
|
||||
if (!pll->on || pll->active_mask)
|
||||
continue;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"%s enabled but not in use, disabling\n",
|
||||
pll->info->name);
|
||||
|
||||
pll->info->funcs->disable(dev_priv, pll);
|
||||
pll->on = false;
|
||||
}
|
||||
intel_dpll_sanitize_state(dev_priv);
|
||||
|
||||
if (IS_G4X(dev_priv)) {
|
||||
g4x_wm_get_hw_state(dev_priv);
|
||||
@ -18820,6 +18802,15 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
|
||||
|
||||
static bool
|
||||
has_transcoder(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder)
|
||||
{
|
||||
if (cpu_transcoder == TRANSCODER_EDP)
|
||||
return HAS_TRANSCODER_EDP(dev_priv);
|
||||
else
|
||||
return INTEL_INFO(dev_priv)->pipe_mask & BIT(cpu_transcoder);
|
||||
}
|
||||
|
||||
struct intel_display_error_state {
|
||||
|
||||
u32 power_well_driver;
|
||||
@ -18928,7 +18919,7 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv)
|
||||
for (i = 0; i < ARRAY_SIZE(error->transcoder); i++) {
|
||||
enum transcoder cpu_transcoder = transcoders[i];
|
||||
|
||||
if (!INTEL_INFO(dev_priv)->trans_offsets[cpu_transcoder])
|
||||
if (!has_transcoder(dev_priv, cpu_transcoder))
|
||||
continue;
|
||||
|
||||
error->transcoder[i].available = true;
|
||||
|
@ -26,7 +26,6 @@
|
||||
#define _INTEL_DISPLAY_H_
|
||||
|
||||
#include <drm/drm_util.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
enum link_m_n_set;
|
||||
struct dpll;
|
||||
@ -40,6 +39,7 @@ struct drm_framebuffer;
|
||||
struct drm_i915_error_state_buf;
|
||||
struct drm_i915_gem_object;
|
||||
struct drm_i915_private;
|
||||
struct drm_mode_fb_cmd2;
|
||||
struct drm_modeset_acquire_ctx;
|
||||
struct drm_plane;
|
||||
struct drm_plane_state;
|
||||
@ -47,6 +47,7 @@ struct i915_ggtt_view;
|
||||
struct intel_atomic_state;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
struct intel_crtc_state;
|
||||
struct intel_digital_port;
|
||||
struct intel_dp;
|
||||
struct intel_encoder;
|
||||
@ -55,7 +56,6 @@ struct intel_plane;
|
||||
struct intel_plane_state;
|
||||
struct intel_remapped_info;
|
||||
struct intel_rotation_info;
|
||||
struct intel_crtc_state;
|
||||
|
||||
enum i915_gpio {
|
||||
GPIOA,
|
||||
@ -313,10 +313,11 @@ enum phy_fia {
|
||||
};
|
||||
|
||||
#define for_each_pipe(__dev_priv, __p) \
|
||||
for ((__p) = 0; (__p) < INTEL_NUM_PIPES(__dev_priv); (__p)++)
|
||||
for ((__p) = 0; (__p) < I915_MAX_PIPES; (__p)++) \
|
||||
for_each_if(INTEL_INFO(__dev_priv)->pipe_mask & BIT(__p))
|
||||
|
||||
#define for_each_pipe_masked(__dev_priv, __p, __mask) \
|
||||
for ((__p) = 0; (__p) < INTEL_NUM_PIPES(__dev_priv); (__p)++) \
|
||||
for_each_pipe(__dev_priv, __p) \
|
||||
for_each_if((__mask) & BIT(__p))
|
||||
|
||||
#define for_each_cpu_transcoder_masked(__dev_priv, __t, __mask) \
|
||||
@ -614,6 +615,7 @@ intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info,
|
||||
|
||||
/* modesetting */
|
||||
void intel_modeset_init_hw(struct drm_i915_private *i915);
|
||||
int intel_modeset_init_noirq(struct drm_i915_private *i915);
|
||||
int intel_modeset_init(struct drm_i915_private *i915);
|
||||
void intel_modeset_driver_remove(struct drm_i915_private *i915);
|
||||
void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915);
|
||||
|
@ -920,8 +920,13 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
|
||||
int i;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
||||
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
||||
|
||||
seq_printf(m, "PLL refclks: non-SSC: %d kHz, SSC: %d kHz\n",
|
||||
dev_priv->dpll.ref_clks.nssc,
|
||||
dev_priv->dpll.ref_clks.ssc);
|
||||
|
||||
for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) {
|
||||
struct intel_shared_dpll *pll = &dev_priv->dpll.shared_dplls[i];
|
||||
|
||||
seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name,
|
||||
pll->info->id);
|
||||
|
@ -939,11 +939,17 @@ unlock:
|
||||
|
||||
static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
|
||||
SKL_DISP_PW_2);
|
||||
enum i915_power_well_id high_pg;
|
||||
|
||||
drm_WARN_ONCE(&dev_priv->drm, pg2_enabled,
|
||||
"PG2 not disabled to enable DC5.\n");
|
||||
/* Power wells at this level and above must be disabled for DC5 entry */
|
||||
if (INTEL_GEN(dev_priv) >= 12)
|
||||
high_pg = TGL_DISP_PW_3;
|
||||
else
|
||||
high_pg = SKL_DISP_PW_2;
|
||||
|
||||
drm_WARN_ONCE(&dev_priv->drm,
|
||||
intel_display_power_well_is_enabled(dev_priv, high_pg),
|
||||
"Power wells above platform's DC5 limit still enabled.\n");
|
||||
|
||||
drm_WARN_ONCE(&dev_priv->drm,
|
||||
(intel_de_read(dev_priv, DC_STATE_EN) &
|
||||
@ -2740,7 +2746,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
|
||||
BIT_ULL(POWER_DOMAIN_INIT))
|
||||
|
||||
#define TGL_DISPLAY_DC_OFF_POWER_DOMAINS ( \
|
||||
TGL_PW_2_POWER_DOMAINS | \
|
||||
TGL_PW_3_POWER_DOMAINS | \
|
||||
BIT_ULL(POWER_DOMAIN_MODESET) | \
|
||||
BIT_ULL(POWER_DOMAIN_AUX_A) | \
|
||||
BIT_ULL(POWER_DOMAIN_AUX_B) | \
|
||||
@ -3936,7 +3942,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
|
||||
.name = "power well 3",
|
||||
.domains = TGL_PW_3_POWER_DOMAINS,
|
||||
.ops = &hsw_power_well_ops,
|
||||
.id = DISP_PW_ID_NONE,
|
||||
.id = TGL_DISP_PW_3,
|
||||
{
|
||||
.hsw.regs = &hsw_power_well_regs,
|
||||
.hsw.idx = ICL_PW_CTL_IDX_PW_3,
|
||||
|
@ -100,6 +100,7 @@ enum i915_power_well_id {
|
||||
SKL_DISP_PW_MISC_IO,
|
||||
SKL_DISP_PW_1,
|
||||
SKL_DISP_PW_2,
|
||||
TGL_DISP_PW_3,
|
||||
SKL_DISP_DC_OFF,
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/i915_drm.h>
|
||||
#include <drm/i915_mei_hdcp_interface.h>
|
||||
#include <media/cec-notifier.h>
|
||||
|
||||
@ -642,6 +641,14 @@ struct intel_crtc_scaler_state {
|
||||
/* Flag to use the scanline counter instead of the pixel counter */
|
||||
#define I915_MODE_FLAG_USE_SCANLINE_COUNTER (1<<2)
|
||||
|
||||
struct intel_wm_level {
|
||||
bool enable;
|
||||
u32 pri_val;
|
||||
u32 spr_val;
|
||||
u32 cur_val;
|
||||
u32 fbc_val;
|
||||
};
|
||||
|
||||
struct intel_pipe_wm {
|
||||
struct intel_wm_level wm[5];
|
||||
bool fbc_wm_enabled;
|
||||
@ -650,6 +657,14 @@ struct intel_pipe_wm {
|
||||
bool sprites_scaled;
|
||||
};
|
||||
|
||||
struct skl_wm_level {
|
||||
u16 min_ddb_alloc;
|
||||
u16 plane_res_b;
|
||||
u8 plane_res_l;
|
||||
bool plane_en;
|
||||
bool ignore_lines;
|
||||
};
|
||||
|
||||
struct skl_plane_wm {
|
||||
struct skl_wm_level wm[8];
|
||||
struct skl_wm_level uv_wm[8];
|
||||
@ -1046,6 +1061,32 @@ struct intel_crtc_state {
|
||||
enum transcoder mst_master_transcoder;
|
||||
};
|
||||
|
||||
enum intel_pipe_crc_source {
|
||||
INTEL_PIPE_CRC_SOURCE_NONE,
|
||||
INTEL_PIPE_CRC_SOURCE_PLANE1,
|
||||
INTEL_PIPE_CRC_SOURCE_PLANE2,
|
||||
INTEL_PIPE_CRC_SOURCE_PLANE3,
|
||||
INTEL_PIPE_CRC_SOURCE_PLANE4,
|
||||
INTEL_PIPE_CRC_SOURCE_PLANE5,
|
||||
INTEL_PIPE_CRC_SOURCE_PLANE6,
|
||||
INTEL_PIPE_CRC_SOURCE_PLANE7,
|
||||
INTEL_PIPE_CRC_SOURCE_PIPE,
|
||||
/* TV/DP on pre-gen5/vlv can't use the pipe source. */
|
||||
INTEL_PIPE_CRC_SOURCE_TV,
|
||||
INTEL_PIPE_CRC_SOURCE_DP_B,
|
||||
INTEL_PIPE_CRC_SOURCE_DP_C,
|
||||
INTEL_PIPE_CRC_SOURCE_DP_D,
|
||||
INTEL_PIPE_CRC_SOURCE_AUTO,
|
||||
INTEL_PIPE_CRC_SOURCE_MAX,
|
||||
};
|
||||
|
||||
#define INTEL_PIPE_CRC_ENTRIES_NR 128
|
||||
struct intel_pipe_crc {
|
||||
spinlock_t lock;
|
||||
int skipped;
|
||||
enum intel_pipe_crc_source source;
|
||||
};
|
||||
|
||||
struct intel_crtc {
|
||||
struct drm_crtc base;
|
||||
enum pipe pipe;
|
||||
@ -1089,6 +1130,10 @@ struct intel_crtc {
|
||||
|
||||
/* per pipe DSB related info */
|
||||
struct intel_dsb dsb;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct intel_pipe_crc pipe_crc;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct intel_plane {
|
||||
@ -1235,6 +1280,7 @@ struct intel_dp {
|
||||
int max_link_rate;
|
||||
/* sink or branch descriptor */
|
||||
struct drm_dp_desc desc;
|
||||
u32 edid_quirks;
|
||||
struct drm_dp_aux aux;
|
||||
u32 aux_busy_last_status;
|
||||
u8 train_set[4];
|
||||
@ -1406,9 +1452,18 @@ vlv_pipe_to_channel(enum pipe pipe)
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct intel_crtc *
|
||||
intel_get_first_crtc(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return to_intel_crtc(drm_crtc_from_index(&dev_priv->drm, 0));
|
||||
}
|
||||
|
||||
static inline struct intel_crtc *
|
||||
intel_get_crtc_for_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
{
|
||||
/* pipe_to_crtc_mapping may have hole on any of 3 display pipe system */
|
||||
drm_WARN_ON(&dev_priv->drm,
|
||||
!(INTEL_INFO(dev_priv)->pipe_mask & BIT(pipe)));
|
||||
return dev_priv->pipe_to_crtc_mapping[pipe];
|
||||
}
|
||||
|
||||
@ -1598,11 +1653,15 @@ intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state)
|
||||
(1 << INTEL_OUTPUT_DP_MST) |
|
||||
(1 << INTEL_OUTPUT_EDP));
|
||||
}
|
||||
|
||||
static inline void
|
||||
intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
{
|
||||
drm_wait_one_vblank(&dev_priv->drm, pipe);
|
||||
struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
|
||||
|
||||
drm_crtc_wait_one_vblank(&crtc->base);
|
||||
}
|
||||
|
||||
static inline void
|
||||
intel_wait_for_vblank_if_active(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
{
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_hdcp.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_debugfs.h"
|
||||
#include "i915_drv.h"
|
||||
@ -2399,7 +2398,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_connector *intel_connector = intel_dp->attached_connector;
|
||||
struct intel_digital_connector_state *intel_conn_state =
|
||||
to_intel_digital_connector_state(conn_state);
|
||||
bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
|
||||
bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 0,
|
||||
DP_DPCD_QUIRK_CONSTANT_N);
|
||||
int ret = 0, output_bpp;
|
||||
|
||||
@ -4515,7 +4514,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
|
||||
* it don't care about read it here and in intel_edp_init_dpcd().
|
||||
*/
|
||||
if (!intel_dp_is_edp(intel_dp) &&
|
||||
!drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_SINK_COUNT)) {
|
||||
!drm_dp_has_quirk(&intel_dp->desc, 0,
|
||||
DP_DPCD_QUIRK_NO_SINK_COUNT)) {
|
||||
u8 count;
|
||||
ssize_t r;
|
||||
|
||||
@ -5682,6 +5682,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
|
||||
|
||||
intel_dp->has_audio = drm_detect_monitor_audio(edid);
|
||||
drm_dp_cec_set_edid(&intel_dp->aux, edid);
|
||||
intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5694,6 +5695,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
|
||||
intel_connector->detect_edid = NULL;
|
||||
|
||||
intel_dp->has_audio = false;
|
||||
intel_dp->edid_quirks = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -6449,6 +6451,7 @@ static
|
||||
int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port,
|
||||
bool is_repeater, u8 content_type)
|
||||
{
|
||||
int ret;
|
||||
struct hdcp2_dp_errata_stream_type stream_type_msg;
|
||||
|
||||
if (is_repeater)
|
||||
@ -6464,8 +6467,11 @@ int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port,
|
||||
stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE;
|
||||
stream_type_msg.stream_type = content_type;
|
||||
|
||||
return intel_dp_hdcp2_write_msg(intel_dig_port, &stream_type_msg,
|
||||
ret = intel_dp_hdcp2_write_msg(intel_dig_port, &stream_type_msg,
|
||||
sizeof(stream_type_msg));
|
||||
|
||||
return ret < 0 ? ret : 0;
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
@ -7562,8 +7568,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
edid = drm_get_edid(connector, &intel_dp->aux.ddc);
|
||||
if (edid) {
|
||||
if (drm_add_edid_modes(connector, edid)) {
|
||||
drm_connector_update_edid_property(connector,
|
||||
edid);
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
|
||||
} else {
|
||||
kfree(edid);
|
||||
edid = ERR_PTR(-EINVAL);
|
||||
@ -7609,9 +7615,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
intel_panel_setup_backlight(connector, pipe);
|
||||
|
||||
if (fixed_mode) {
|
||||
/* We do not know the orientation, but their might be a quirk */
|
||||
drm_connector_set_panel_orientation_with_quirk(connector,
|
||||
DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
|
||||
dev_priv->vbt.orientation,
|
||||
fixed_mode->hdisplay, fixed_mode->vdisplay);
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
|
||||
enum pipe;
|
||||
|
@ -328,15 +328,31 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector)
|
||||
int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
|
||||
{
|
||||
struct intel_panel *panel = &intel_connector->panel;
|
||||
struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev);
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(intel_connector->encoder);
|
||||
struct drm_device *dev = intel_connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
|
||||
if (i915_modparams.enable_dpcd_backlight == 0 ||
|
||||
(i915_modparams.enable_dpcd_backlight == -1 &&
|
||||
dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
|
||||
!intel_dp_aux_display_control_capable(intel_connector))
|
||||
return -ENODEV;
|
||||
|
||||
if (!intel_dp_aux_display_control_capable(intel_connector))
|
||||
/*
|
||||
* There are a lot of machines that don't advertise the backlight
|
||||
* control interface to use properly in their VBIOS, :\
|
||||
*/
|
||||
if (dev_priv->vbt.backlight.type !=
|
||||
INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE &&
|
||||
!drm_dp_has_quirk(&intel_dp->desc, intel_dp->edid_quirks,
|
||||
DP_QUIRK_FORCE_DPCD_BACKLIGHT)) {
|
||||
DRM_DEV_INFO(dev->dev,
|
||||
"Panel advertises DPCD backlight support, but "
|
||||
"VBT disagrees. If your backlight controls "
|
||||
"don't work try booting with "
|
||||
"i915.enable_dpcd_backlight=1. If your machine "
|
||||
"needs this, please file a _new_ bug report on "
|
||||
"drm/i915, see " FDO_BUG_URL " for details.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
panel->backlight.setup = intel_dp_aux_setup_backlight;
|
||||
panel->backlight.enable = intel_dp_aux_enable_backlight;
|
||||
|
@ -50,7 +50,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->hw.adjusted_mode;
|
||||
void *port = connector->port;
|
||||
bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
|
||||
bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 0,
|
||||
DP_DPCD_QUIRK_CONSTANT_N);
|
||||
int bpp, slots = -EINVAL;
|
||||
|
||||
@ -548,12 +548,41 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_mst_connector_late_register(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
int ret;
|
||||
|
||||
ret = drm_dp_mst_connector_late_register(connector,
|
||||
intel_connector->port);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = intel_connector_register(connector);
|
||||
if (ret < 0)
|
||||
drm_dp_mst_connector_early_unregister(connector,
|
||||
intel_connector->port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_mst_connector_early_unregister(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
|
||||
intel_connector_unregister(connector);
|
||||
drm_dp_mst_connector_early_unregister(connector,
|
||||
intel_connector->port);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.atomic_get_property = intel_digital_connector_atomic_get_property,
|
||||
.atomic_set_property = intel_digital_connector_atomic_set_property,
|
||||
.late_register = intel_connector_register,
|
||||
.early_unregister = intel_connector_unregister,
|
||||
.late_register = intel_dp_mst_connector_late_register,
|
||||
.early_unregister = intel_dp_mst_connector_early_unregister,
|
||||
.destroy = intel_connector_destroy,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -278,6 +278,15 @@ struct intel_shared_dpll_funcs {
|
||||
bool (*get_hw_state)(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll,
|
||||
struct intel_dpll_hw_state *hw_state);
|
||||
|
||||
/**
|
||||
* @get_freq:
|
||||
*
|
||||
* Hook for calculating the pll's output frequency based on its
|
||||
* current state.
|
||||
*/
|
||||
int (*get_freq)(struct drm_i915_private *i915,
|
||||
const struct intel_shared_dpll *pll);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -372,15 +381,18 @@ void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state,
|
||||
void intel_update_active_dpll(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc,
|
||||
struct intel_encoder *encoder);
|
||||
int intel_dpll_get_freq(struct drm_i915_private *i915,
|
||||
const struct intel_shared_dpll *pll);
|
||||
void intel_prepare_shared_dpll(const struct intel_crtc_state *crtc_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 drm_device *dev);
|
||||
void intel_dpll_readout_hw_state(struct drm_i915_private *dev_priv);
|
||||
void intel_dpll_sanitize_state(struct drm_i915_private *dev_priv);
|
||||
|
||||
void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
const struct intel_dpll_hw_state *hw_state);
|
||||
int cnl_hdmi_pll_ref_clock(struct drm_i915_private *dev_priv);
|
||||
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);
|
||||
|
||||
|
@ -52,7 +52,7 @@ static inline bool intel_dsb_enable_engine(struct intel_dsb *dsb)
|
||||
|
||||
dsb_ctrl = intel_de_read(dev_priv, DSB_CTRL(pipe, dsb->id));
|
||||
if (DSB_STATUS & dsb_ctrl) {
|
||||
DRM_DEBUG_KMS("DSB engine is busy.\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "DSB engine is busy.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ static inline bool intel_dsb_disable_engine(struct intel_dsb *dsb)
|
||||
|
||||
dsb_ctrl = intel_de_read(dev_priv, DSB_CTRL(pipe, dsb->id));
|
||||
if (DSB_STATUS & dsb_ctrl) {
|
||||
DRM_DEBUG_KMS("DSB engine is busy.\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "DSB engine is busy.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -115,20 +115,20 @@ intel_dsb_get(struct intel_crtc *crtc)
|
||||
|
||||
obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
|
||||
if (IS_ERR(obj)) {
|
||||
DRM_ERROR("Gem object creation failed\n");
|
||||
drm_err(&i915->drm, "Gem object creation failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
|
||||
if (IS_ERR(vma)) {
|
||||
DRM_ERROR("Vma creation failed\n");
|
||||
drm_err(&i915->drm, "Vma creation failed\n");
|
||||
i915_gem_object_put(obj);
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC);
|
||||
if (IS_ERR(buf)) {
|
||||
DRM_ERROR("Command buffer creation failed\n");
|
||||
drm_err(&i915->drm, "Command buffer creation failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -203,7 +203,7 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg,
|
||||
}
|
||||
|
||||
if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) {
|
||||
DRM_DEBUG_KMS("DSB buffer overflow\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -277,7 +277,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val)
|
||||
}
|
||||
|
||||
if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) {
|
||||
DRM_DEBUG_KMS("DSB buffer overflow\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -310,7 +310,8 @@ void intel_dsb_commit(struct intel_dsb *dsb)
|
||||
goto reset;
|
||||
|
||||
if (is_dsb_busy(dsb)) {
|
||||
DRM_ERROR("HEAD_PTR write failed - dsb engine is busy.\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"HEAD_PTR write failed - dsb engine is busy.\n");
|
||||
goto reset;
|
||||
}
|
||||
intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id),
|
||||
@ -322,15 +323,18 @@ void intel_dsb_commit(struct intel_dsb *dsb)
|
||||
(tail - dsb->free_pos * 4));
|
||||
|
||||
if (is_dsb_busy(dsb)) {
|
||||
DRM_ERROR("TAIL_PTR write failed - dsb engine is busy.\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"TAIL_PTR write failed - dsb engine is busy.\n");
|
||||
goto reset;
|
||||
}
|
||||
DRM_DEBUG_KMS("DSB execution started - head 0x%x, tail 0x%x\n",
|
||||
i915_ggtt_offset(dsb->vma), tail);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DSB execution started - head 0x%x, tail 0x%x\n",
|
||||
i915_ggtt_offset(dsb->vma), tail);
|
||||
intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id),
|
||||
i915_ggtt_offset(dsb->vma) + tail);
|
||||
if (wait_for(!is_dsb_busy(dsb), 1)) {
|
||||
DRM_ERROR("Timed out waiting for DSB workload completion.\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"Timed out waiting for DSB workload completion.\n");
|
||||
goto reset;
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_connector.h"
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_trace.h"
|
||||
#include "i915_vgpu.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fbc.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
@ -320,7 +321,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
|
||||
SNB_CPU_FENCE_ENABLE | params->fence_id);
|
||||
intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET,
|
||||
params->crtc.fence_y_offset);
|
||||
} else {
|
||||
} else if (dev_priv->ggtt.num_fences) {
|
||||
intel_de_write(dev_priv, SNB_DPFC_CTL_SA, 0);
|
||||
intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, 0);
|
||||
}
|
||||
@ -508,12 +509,12 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv,
|
||||
|
||||
fbc->compressed_llb = compressed_llb;
|
||||
|
||||
GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start,
|
||||
fbc->compressed_fb.start,
|
||||
U32_MAX));
|
||||
GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start,
|
||||
fbc->compressed_llb->start,
|
||||
U32_MAX));
|
||||
GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start,
|
||||
fbc->compressed_fb.start,
|
||||
U32_MAX));
|
||||
GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start,
|
||||
fbc->compressed_llb->start,
|
||||
U32_MAX));
|
||||
intel_de_write(dev_priv, FBC_CFB_BASE,
|
||||
dev_priv->dsm.start + fbc->compressed_fb.start);
|
||||
intel_de_write(dev_priv, FBC_LL_BASE,
|
||||
@ -691,12 +692,37 @@ static bool intel_fbc_cfb_size_changed(struct drm_i915_private *dev_priv)
|
||||
fbc->compressed_fb.size * fbc->threshold;
|
||||
}
|
||||
|
||||
static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_fbc *fbc = &dev_priv->fbc;
|
||||
|
||||
if (intel_vgpu_active(dev_priv)) {
|
||||
fbc->no_fbc_reason = "VGPU is active";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!i915_modparams.enable_fbc) {
|
||||
fbc->no_fbc_reason = "disabled per module param or by default";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fbc->underrun_detected) {
|
||||
fbc->no_fbc_reason = "underrun detected";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool intel_fbc_can_activate(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
struct intel_fbc *fbc = &dev_priv->fbc;
|
||||
struct intel_fbc_state_cache *cache = &fbc->state_cache;
|
||||
|
||||
if (!intel_fbc_can_enable(dev_priv))
|
||||
return false;
|
||||
|
||||
if (!cache->plane.visible) {
|
||||
fbc->no_fbc_reason = "primary plane not visible";
|
||||
return false;
|
||||
@ -795,28 +821,6 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_fbc *fbc = &dev_priv->fbc;
|
||||
|
||||
if (intel_vgpu_active(dev_priv)) {
|
||||
fbc->no_fbc_reason = "VGPU is active";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!i915_modparams.enable_fbc) {
|
||||
fbc->no_fbc_reason = "disabled per module param or by default";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fbc->underrun_detected) {
|
||||
fbc->no_fbc_reason = "underrun detected";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
|
||||
struct intel_fbc_reg_params *params)
|
||||
{
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_types.h"
|
||||
|
@ -103,7 +103,7 @@ static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
|
||||
intel_de_posting_read(dev_priv, reg);
|
||||
|
||||
trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe);
|
||||
DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
|
||||
drm_err(&dev_priv->drm, "pipe %c underrun\n", pipe_name(crtc->pipe));
|
||||
}
|
||||
|
||||
static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
@ -123,7 +123,8 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
intel_de_posting_read(dev_priv, reg);
|
||||
} else {
|
||||
if (old && intel_de_read(dev_priv, reg) & PIPE_FIFO_UNDERRUN_STATUS)
|
||||
DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
|
||||
drm_err(&dev_priv->drm, "pipe %c underrun\n",
|
||||
pipe_name(pipe));
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +156,7 @@ static void ivb_check_fifo_underruns(struct intel_crtc *crtc)
|
||||
intel_de_posting_read(dev_priv, GEN7_ERR_INT);
|
||||
|
||||
trace_intel_cpu_fifo_underrun(dev_priv, pipe);
|
||||
DRM_ERROR("fifo underrun on pipe %c\n", pipe_name(pipe));
|
||||
drm_err(&dev_priv->drm, "fifo underrun on pipe %c\n", pipe_name(pipe));
|
||||
}
|
||||
|
||||
static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
@ -176,8 +177,9 @@ static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
|
||||
if (old &&
|
||||
intel_de_read(dev_priv, GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
|
||||
DRM_ERROR("uncleared fifo underrun on pipe %c\n",
|
||||
pipe_name(pipe));
|
||||
drm_err(&dev_priv->drm,
|
||||
"uncleared fifo underrun on pipe %c\n",
|
||||
pipe_name(pipe));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -223,8 +225,8 @@ static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
|
||||
intel_de_posting_read(dev_priv, SERR_INT);
|
||||
|
||||
trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
|
||||
DRM_ERROR("pch fifo underrun on pch transcoder %c\n",
|
||||
pipe_name(pch_transcoder));
|
||||
drm_err(&dev_priv->drm, "pch fifo underrun on pch transcoder %c\n",
|
||||
pipe_name(pch_transcoder));
|
||||
}
|
||||
|
||||
static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
@ -246,8 +248,9 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
|
||||
|
||||
if (old && intel_de_read(dev_priv, SERR_INT) &
|
||||
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
|
||||
DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
|
||||
pipe_name(pch_transcoder));
|
||||
drm_err(&dev_priv->drm,
|
||||
"uncleared pch fifo underrun on pch transcoder %c\n",
|
||||
pipe_name(pch_transcoder));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -381,8 +384,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
|
||||
|
||||
if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
|
||||
trace_intel_cpu_fifo_underrun(dev_priv, pipe);
|
||||
DRM_ERROR("CPU pipe %c FIFO underrun\n",
|
||||
pipe_name(pipe));
|
||||
drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n",
|
||||
pipe_name(pipe));
|
||||
}
|
||||
|
||||
intel_fbc_handle_fifo_underrun_irq(dev_priv);
|
||||
@ -403,8 +406,8 @@ void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
|
||||
if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
|
||||
false)) {
|
||||
trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
|
||||
DRM_ERROR("PCH transcoder %c FIFO underrun\n",
|
||||
pipe_name(pch_transcoder));
|
||||
drm_err(&dev_priv->drm, "PCH transcoder %c FIFO underrun\n",
|
||||
pipe_name(pch_transcoder));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <drm/drm_hdcp.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_types.h"
|
||||
@ -632,8 +631,9 @@ retry:
|
||||
* till then let it sleep.
|
||||
*/
|
||||
if (gmbus_wait_idle(dev_priv)) {
|
||||
DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n",
|
||||
adapter->name);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"GMBUS [%s] timed out waiting for idle\n",
|
||||
adapter->name);
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
intel_de_write_fw(dev_priv, GMBUS0, 0);
|
||||
@ -656,8 +656,9 @@ clear_err:
|
||||
*/
|
||||
ret = -ENXIO;
|
||||
if (gmbus_wait_idle(dev_priv)) {
|
||||
DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n",
|
||||
adapter->name);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"GMBUS [%s] timed out after NAK\n",
|
||||
adapter->name);
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -669,9 +670,9 @@ clear_err:
|
||||
intel_de_write_fw(dev_priv, GMBUS1, 0);
|
||||
intel_de_write_fw(dev_priv, GMBUS0, 0);
|
||||
|
||||
DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n",
|
||||
adapter->name, msgs[i].addr,
|
||||
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
|
||||
drm_dbg_kms(&dev_priv->drm, "GMBUS [%s] NAK for addr: %04x %c(%d)\n",
|
||||
adapter->name, msgs[i].addr,
|
||||
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
|
||||
|
||||
/*
|
||||
* Passive adapters sometimes NAK the first probe. Retry the first
|
||||
@ -680,16 +681,18 @@ clear_err:
|
||||
* drm_do_probe_ddc_edid, which bails out on the first -ENXIO.
|
||||
*/
|
||||
if (ret == -ENXIO && i == 0 && try++ == 0) {
|
||||
DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n",
|
||||
adapter->name);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"GMBUS [%s] NAK on first message, retry\n",
|
||||
adapter->name);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
timeout:
|
||||
DRM_DEBUG_KMS("GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
|
||||
bus->adapter.name, bus->reg0 & 0xff);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
|
||||
bus->adapter.name, bus->reg0 & 0xff);
|
||||
intel_de_write_fw(dev_priv, GMBUS0, 0);
|
||||
|
||||
/*
|
||||
@ -926,9 +929,10 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
|
||||
mutex_lock(&dev_priv->gmbus_mutex);
|
||||
|
||||
bus->force_bit += force_bit ? 1 : -1;
|
||||
DRM_DEBUG_KMS("%sabling bit-banging on %s. force bit now %d\n",
|
||||
force_bit ? "en" : "dis", adapter->name,
|
||||
bus->force_bit);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"%sabling bit-banging on %s. force bit now %d\n",
|
||||
force_bit ? "en" : "dis", adapter->name,
|
||||
bus->force_bit);
|
||||
|
||||
mutex_unlock(&dev_priv->gmbus_mutex);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ static
|
||||
int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port,
|
||||
const struct intel_hdcp_shim *shim, u8 *bksv)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev);
|
||||
int ret, i, tries = 2;
|
||||
|
||||
/* HDCP spec states that we must retry the bksv if it is invalid */
|
||||
@ -54,7 +55,7 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port,
|
||||
break;
|
||||
}
|
||||
if (i == tries) {
|
||||
DRM_DEBUG_KMS("Bksv is invalid\n");
|
||||
drm_dbg_kms(&i915->drm, "Bksv is invalid\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -485,8 +486,8 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
|
||||
return ret;
|
||||
sha_idx += sizeof(sha_text);
|
||||
} else {
|
||||
DRM_DEBUG_KMS("Invalid number of leftovers %d\n",
|
||||
sha_leftovers);
|
||||
drm_dbg_kms(&dev_priv->drm, "Invalid number of leftovers %d\n",
|
||||
sha_leftovers);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -514,11 +515,11 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
|
||||
rep_ctl | HDCP_SHA1_COMPLETE_HASH);
|
||||
if (intel_de_wait_for_set(dev_priv, HDCP_REP_CTL,
|
||||
HDCP_SHA1_COMPLETE, 1)) {
|
||||
DRM_ERROR("Timed out waiting for SHA1 complete\n");
|
||||
drm_err(&dev_priv->drm, "Timed out waiting for SHA1 complete\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
if (!(intel_de_read(dev_priv, HDCP_REP_CTL) & HDCP_SHA1_V_MATCH)) {
|
||||
DRM_DEBUG_KMS("SHA-1 mismatch, HDCP failed\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "SHA-1 mismatch, HDCP failed\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
@ -537,7 +538,8 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
|
||||
|
||||
ret = intel_hdcp_poll_ksv_fifo(intel_dig_port, shim);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("KSV list failed to become ready (%d)\n", ret);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"KSV list failed to become ready (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -547,7 +549,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
|
||||
|
||||
if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) ||
|
||||
DRM_HDCP_MAX_CASCADE_EXCEEDED(bstatus[1])) {
|
||||
DRM_DEBUG_KMS("Max Topology Limit Exceeded\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "Max Topology Limit Exceeded\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@ -560,13 +562,14 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
|
||||
*/
|
||||
num_downstream = DRM_HDCP_NUM_DOWNSTREAM(bstatus[0]);
|
||||
if (num_downstream == 0) {
|
||||
DRM_DEBUG_KMS("Repeater with zero downstream devices\n");
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Repeater with zero downstream devices\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL);
|
||||
if (!ksv_fifo) {
|
||||
DRM_DEBUG_KMS("Out of mem: ksv_fifo\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "Out of mem: ksv_fifo\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -576,7 +579,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
|
||||
|
||||
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, ksv_fifo,
|
||||
num_downstream)) {
|
||||
DRM_ERROR("Revoked Ksv(s) in ksv_fifo\n");
|
||||
drm_err(&dev_priv->drm, "Revoked Ksv(s) in ksv_fifo\n");
|
||||
ret = -EPERM;
|
||||
goto err;
|
||||
}
|
||||
@ -594,12 +597,13 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
|
||||
}
|
||||
|
||||
if (i == tries) {
|
||||
DRM_DEBUG_KMS("V Prime validation failed.(%d)\n", ret);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"V Prime validation failed.(%d)\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("HDCP is enabled (%d downstream devices)\n",
|
||||
num_downstream);
|
||||
drm_dbg_kms(&dev_priv->drm, "HDCP is enabled (%d downstream devices)\n",
|
||||
num_downstream);
|
||||
ret = 0;
|
||||
err:
|
||||
kfree(ksv_fifo);
|
||||
@ -642,7 +646,8 @@ static int intel_hdcp_auth(struct intel_connector *connector)
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!hdcp_capable) {
|
||||
DRM_DEBUG_KMS("Panel is not HDCP capable\n");
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Panel is not HDCP capable\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -659,7 +664,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
|
||||
if (intel_de_wait_for_set(dev_priv,
|
||||
HDCP_STATUS(dev_priv, cpu_transcoder, port),
|
||||
HDCP_STATUS_AN_READY, 1)) {
|
||||
DRM_ERROR("Timed out waiting for An\n");
|
||||
drm_err(&dev_priv->drm, "Timed out waiting for An\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -680,7 +685,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
|
||||
return ret;
|
||||
|
||||
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, bksv.shim, 1)) {
|
||||
DRM_ERROR("BKSV is revoked\n");
|
||||
drm_err(&dev_priv->drm, "BKSV is revoked\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@ -706,7 +711,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
|
||||
/* Wait for R0 ready */
|
||||
if (wait_for(intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port)) &
|
||||
(HDCP_STATUS_R0_READY | HDCP_STATUS_ENC), 1)) {
|
||||
DRM_ERROR("Timed out waiting for R0 ready\n");
|
||||
drm_err(&dev_priv->drm, "Timed out waiting for R0 ready\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -743,8 +748,10 @@ static int intel_hdcp_auth(struct intel_connector *connector)
|
||||
}
|
||||
|
||||
if (i == tries) {
|
||||
DRM_DEBUG_KMS("Timed out waiting for Ri prime match (%x)\n",
|
||||
intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port)));
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Timed out waiting for Ri prime match (%x)\n",
|
||||
intel_de_read(dev_priv, HDCP_STATUS(dev_priv,
|
||||
cpu_transcoder, port)));
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -753,7 +760,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
|
||||
HDCP_STATUS(dev_priv, cpu_transcoder, port),
|
||||
HDCP_STATUS_ENC,
|
||||
ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
|
||||
DRM_ERROR("Timed out waiting for encryption\n");
|
||||
drm_err(&dev_priv->drm, "Timed out waiting for encryption\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -765,7 +772,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
|
||||
if (repeater_present)
|
||||
return intel_hdcp_auth_downstream(connector);
|
||||
|
||||
DRM_DEBUG_KMS("HDCP is enabled (no repeater present)\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "HDCP is enabled (no repeater present)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1271,7 +1278,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
|
||||
return ret;
|
||||
|
||||
if (msgs.send_cert.rx_caps[0] != HDCP_2_2_RX_CAPS_VERSION_VAL) {
|
||||
DRM_DEBUG_KMS("cert.rx_caps dont claim HDCP2.2\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "cert.rx_caps dont claim HDCP2.2\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1280,7 +1287,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
|
||||
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm,
|
||||
msgs.send_cert.cert_rx.receiver_id,
|
||||
1)) {
|
||||
DRM_ERROR("Receiver ID is revoked\n");
|
||||
drm_err(&dev_priv->drm, "Receiver ID is revoked\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@ -1455,7 +1462,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
|
||||
|
||||
if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
|
||||
HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
|
||||
DRM_DEBUG_KMS("Topology Max Size Exceeded\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "Topology Max Size Exceeded\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1463,9 +1470,15 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
|
||||
seq_num_v =
|
||||
drm_hdcp_be24_to_cpu((const u8 *)msgs.recvid_list.seq_num_v);
|
||||
|
||||
if (!hdcp->hdcp2_encrypted && seq_num_v) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Non zero Seq_num_v at first RecvId_List msg\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (seq_num_v < hdcp->seq_num_v) {
|
||||
/* Roll over of the seq_num_v from repeater. Reauthenticate. */
|
||||
DRM_DEBUG_KMS("Seq_num_v roll over.\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "Seq_num_v roll over.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1474,7 +1487,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
|
||||
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm,
|
||||
msgs.recvid_list.receiver_ids,
|
||||
device_cnt)) {
|
||||
DRM_ERROR("Revoked receiver ID(s) is in list\n");
|
||||
drm_err(&dev_priv->drm, "Revoked receiver ID(s) is in list\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@ -1507,25 +1520,27 @@ static int hdcp2_authenticate_repeater(struct intel_connector *connector)
|
||||
static int hdcp2_authenticate_sink(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector);
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
const struct intel_hdcp_shim *shim = hdcp->shim;
|
||||
int ret;
|
||||
|
||||
ret = hdcp2_authentication_key_exchange(connector);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_KMS("AKE Failed. Err : %d\n", ret);
|
||||
drm_dbg_kms(&i915->drm, "AKE Failed. Err : %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hdcp2_locality_check(connector);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_KMS("Locality Check failed. Err : %d\n", ret);
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Locality Check failed. Err : %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hdcp2_session_key_exchange(connector);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_KMS("SKE Failed. Err : %d\n", ret);
|
||||
drm_dbg_kms(&i915->drm, "SKE Failed. Err : %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1540,7 +1555,8 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
|
||||
if (hdcp->is_repeater) {
|
||||
ret = hdcp2_authenticate_repeater(connector);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n", ret);
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Repeater Auth Failed. Err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1630,6 +1646,7 @@ static int hdcp2_disable_encryption(struct intel_connector *connector)
|
||||
|
||||
static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
int ret, i, tries = 3;
|
||||
|
||||
for (i = 0; i < tries; i++) {
|
||||
@ -1638,10 +1655,10 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
|
||||
break;
|
||||
|
||||
/* Clearing the mei hdcp session */
|
||||
DRM_DEBUG_KMS("HDCP2.2 Auth %d of %d Failed.(%d)\n",
|
||||
i + 1, tries, ret);
|
||||
drm_dbg_kms(&i915->drm, "HDCP2.2 Auth %d of %d Failed.(%d)\n",
|
||||
i + 1, tries, ret);
|
||||
if (hdcp2_deauthenticate_port(connector) < 0)
|
||||
DRM_DEBUG_KMS("Port deauth failed.\n");
|
||||
drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
|
||||
}
|
||||
|
||||
if (i != tries) {
|
||||
@ -1652,9 +1669,10 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
|
||||
msleep(HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN);
|
||||
ret = hdcp2_enable_encryption(connector);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_KMS("Encryption Enable Failed.(%d)\n", ret);
|
||||
drm_dbg_kms(&i915->drm,
|
||||
"Encryption Enable Failed.(%d)\n", ret);
|
||||
if (hdcp2_deauthenticate_port(connector) < 0)
|
||||
DRM_DEBUG_KMS("Port deauth failed.\n");
|
||||
drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1663,23 +1681,24 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
|
||||
|
||||
static int _intel_hdcp2_enable(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
|
||||
connector->base.name, connector->base.base.id,
|
||||
hdcp->content_type);
|
||||
drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
|
||||
connector->base.name, connector->base.base.id,
|
||||
hdcp->content_type);
|
||||
|
||||
ret = hdcp2_authenticate_and_encrypt(connector);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("HDCP2 Type%d Enabling Failed. (%d)\n",
|
||||
hdcp->content_type, ret);
|
||||
drm_dbg_kms(&i915->drm, "HDCP2 Type%d Enabling Failed. (%d)\n",
|
||||
hdcp->content_type, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is enabled. Type %d\n",
|
||||
connector->base.name, connector->base.base.id,
|
||||
hdcp->content_type);
|
||||
drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is enabled. Type %d\n",
|
||||
connector->base.name, connector->base.base.id,
|
||||
hdcp->content_type);
|
||||
|
||||
hdcp->hdcp2_encrypted = true;
|
||||
return 0;
|
||||
@ -1687,15 +1706,16 @@ static int _intel_hdcp2_enable(struct intel_connector *connector)
|
||||
|
||||
static int _intel_hdcp2_disable(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being Disabled\n",
|
||||
connector->base.name, connector->base.base.id);
|
||||
drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being Disabled\n",
|
||||
connector->base.name, connector->base.base.id);
|
||||
|
||||
ret = hdcp2_disable_encryption(connector);
|
||||
|
||||
if (hdcp2_deauthenticate_port(connector) < 0)
|
||||
DRM_DEBUG_KMS("Port deauth failed.\n");
|
||||
drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
|
||||
|
||||
connector->hdcp.hdcp2_encrypted = false;
|
||||
|
||||
@ -1938,12 +1958,13 @@ void intel_hdcp_component_init(struct drm_i915_private *dev_priv)
|
||||
static void intel_hdcp2_init(struct intel_connector *connector,
|
||||
const struct intel_hdcp_shim *shim)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(connector->base.dev);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
int ret;
|
||||
|
||||
ret = initialize_hdcp_port_data(connector, shim);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("Mei hdcp data init failed\n");
|
||||
drm_dbg_kms(&i915->drm, "Mei hdcp data init failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
struct drm_connector;
|
||||
struct drm_connector_state;
|
||||
struct drm_i915_private;
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_hdcp.h>
|
||||
#include <drm/drm_scdc_helper.h>
|
||||
#include <drm/i915_drm.h>
|
||||
#include <drm/intel_lpe_audio.h>
|
||||
|
||||
#include "i915_debugfs.h"
|
||||
@ -2276,14 +2275,9 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
||||
}
|
||||
}
|
||||
|
||||
/* Display WA #1139: glk */
|
||||
if (bpc == 12 && IS_GLK_REVID(dev_priv, 0, GLK_REVID_A1) &&
|
||||
adjusted_mode->htotal > 5460)
|
||||
return false;
|
||||
|
||||
/* Display Wa_1405510057:icl */
|
||||
/* Display Wa_1405510057:icl,ehl */
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
|
||||
bpc == 10 && INTEL_GEN(dev_priv) >= 11 &&
|
||||
bpc == 10 && IS_GEN(dev_priv, 11) &&
|
||||
(adjusted_mode->crtc_hblank_end -
|
||||
adjusted_mode->crtc_hblank_start) % 8 == 2)
|
||||
return false;
|
||||
|
@ -9,8 +9,6 @@
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
|
||||
struct drm_connector;
|
||||
|
@ -23,8 +23,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_hotplug.h"
|
||||
@ -89,29 +87,16 @@
|
||||
enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
switch (port) {
|
||||
case PORT_A:
|
||||
return HPD_PORT_A;
|
||||
case PORT_B:
|
||||
return HPD_PORT_B;
|
||||
case PORT_C:
|
||||
return HPD_PORT_C;
|
||||
case PORT_D:
|
||||
return HPD_PORT_D;
|
||||
case PORT_E:
|
||||
return HPD_PORT_E;
|
||||
case PORT_F:
|
||||
if (IS_CNL_WITH_PORT_F(dev_priv))
|
||||
return HPD_PORT_E;
|
||||
return HPD_PORT_F;
|
||||
case PORT_G:
|
||||
return HPD_PORT_G;
|
||||
case PORT_H:
|
||||
return HPD_PORT_H;
|
||||
case PORT_I:
|
||||
return HPD_PORT_I;
|
||||
enum phy phy = intel_port_to_phy(dev_priv, port);
|
||||
|
||||
switch (phy) {
|
||||
case PHY_F:
|
||||
return IS_CNL_WITH_PORT_F(dev_priv) ? HPD_PORT_E : HPD_PORT_F;
|
||||
case PHY_A ... PHY_E:
|
||||
case PHY_G ... PHY_I:
|
||||
return HPD_PORT_A + phy - PHY_A;
|
||||
default:
|
||||
MISSING_CASE(port);
|
||||
MISSING_CASE(phy);
|
||||
return HPD_NONE;
|
||||
}
|
||||
}
|
||||
@ -185,10 +170,13 @@ static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv,
|
||||
hpd->stats[pin].count += increment;
|
||||
if (hpd->stats[pin].count > threshold) {
|
||||
hpd->stats[pin].state = HPD_MARK_DISABLED;
|
||||
DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", pin);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"HPD interrupt storm detected on PIN %d\n", pin);
|
||||
storm = true;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: %d\n", pin,
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Received HPD interrupt on PIN %d - cnt: %d\n",
|
||||
pin,
|
||||
hpd->stats[pin].count);
|
||||
}
|
||||
|
||||
@ -217,7 +205,8 @@ intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv)
|
||||
dev_priv->hotplug.stats[pin].state != HPD_MARK_DISABLED)
|
||||
continue;
|
||||
|
||||
DRM_INFO("HPD interrupt storm detected on connector %s: "
|
||||
drm_info(&dev_priv->drm,
|
||||
"HPD interrupt storm detected on connector %s: "
|
||||
"switching from hotplug detection to polling\n",
|
||||
connector->base.name);
|
||||
|
||||
@ -259,8 +248,9 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
|
||||
continue;
|
||||
|
||||
if (connector->base.polled != connector->polled)
|
||||
DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
|
||||
connector->base.name);
|
||||
drm_dbg(&dev_priv->drm,
|
||||
"Reenabling HPD on connector %s\n",
|
||||
connector->base.name);
|
||||
connector->base.polled = connector->polled;
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
@ -295,11 +285,12 @@ intel_encoder_hotplug(struct intel_encoder *encoder,
|
||||
if (old_status == connector->base.status)
|
||||
return INTEL_HOTPLUG_UNCHANGED;
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
|
||||
connector->base.base.id,
|
||||
connector->base.name,
|
||||
drm_get_connector_status_name(old_status),
|
||||
drm_get_connector_status_name(connector->base.status));
|
||||
drm_dbg_kms(&to_i915(dev)->drm,
|
||||
"[CONNECTOR:%d:%s] status updated from %s to %s\n",
|
||||
connector->base.base.id,
|
||||
connector->base.name,
|
||||
drm_get_connector_status_name(old_status),
|
||||
drm_get_connector_status_name(connector->base.status));
|
||||
|
||||
return INTEL_HOTPLUG_CHANGED;
|
||||
}
|
||||
@ -373,7 +364,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
u32 hpd_retry_bits;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
DRM_DEBUG_KMS("running encoder hotplug functions\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "running encoder hotplug functions\n");
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
|
||||
@ -401,8 +392,9 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
struct intel_encoder *encoder =
|
||||
intel_attached_encoder(connector);
|
||||
|
||||
DRM_DEBUG_KMS("Connector %s (pin %i) received hotplug event.\n",
|
||||
connector->base.name, pin);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Connector %s (pin %i) received hotplug event.\n",
|
||||
connector->base.name, pin);
|
||||
|
||||
switch (encoder->hotplug(encoder, connector,
|
||||
hpd_event_bits & hpd_bit)) {
|
||||
@ -487,9 +479,10 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
|
||||
|
||||
long_hpd = long_mask & BIT(pin);
|
||||
|
||||
DRM_DEBUG_DRIVER("digital hpd on [ENCODER:%d:%s] - %s\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
long_hpd ? "long" : "short");
|
||||
drm_dbg(&dev_priv->drm,
|
||||
"digital hpd on [ENCODER:%d:%s] - %s\n",
|
||||
encoder->base.base.id, encoder->base.name,
|
||||
long_hpd ? "long" : "short");
|
||||
queue_dig = true;
|
||||
|
||||
if (long_hpd) {
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_connector;
|
||||
struct intel_encoder;
|
||||
|
@ -127,7 +127,8 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
|
||||
kfree(pdata);
|
||||
|
||||
if (IS_ERR(platdev)) {
|
||||
DRM_ERROR("Failed to allocate LPE audio platform device\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"Failed to allocate LPE audio platform device\n");
|
||||
return platdev;
|
||||
}
|
||||
|
||||
@ -190,7 +191,8 @@ static bool lpe_audio_detect(struct drm_i915_private *dev_priv)
|
||||
};
|
||||
|
||||
if (!pci_dev_present(atom_hdaudio_ids)) {
|
||||
DRM_INFO("HDaudio controller not detected, using LPE audio instead\n");
|
||||
drm_info(&dev_priv->drm,
|
||||
"HDaudio controller not detected, using LPE audio instead\n");
|
||||
lpe_present = true;
|
||||
}
|
||||
}
|
||||
@ -203,18 +205,19 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv)
|
||||
|
||||
dev_priv->lpe_audio.irq = irq_alloc_desc(0);
|
||||
if (dev_priv->lpe_audio.irq < 0) {
|
||||
DRM_ERROR("Failed to allocate IRQ desc: %d\n",
|
||||
drm_err(&dev_priv->drm, "Failed to allocate IRQ desc: %d\n",
|
||||
dev_priv->lpe_audio.irq);
|
||||
ret = dev_priv->lpe_audio.irq;
|
||||
goto err;
|
||||
}
|
||||
|
||||
DRM_DEBUG("irq = %d\n", dev_priv->lpe_audio.irq);
|
||||
drm_dbg(&dev_priv->drm, "irq = %d\n", dev_priv->lpe_audio.irq);
|
||||
|
||||
ret = lpe_audio_irq_init(dev_priv);
|
||||
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize irqchip for lpe audio: %d\n",
|
||||
drm_err(&dev_priv->drm,
|
||||
"Failed to initialize irqchip for lpe audio: %d\n",
|
||||
ret);
|
||||
goto err_free_irq;
|
||||
}
|
||||
@ -223,7 +226,8 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv)
|
||||
|
||||
if (IS_ERR(dev_priv->lpe_audio.platdev)) {
|
||||
ret = PTR_ERR(dev_priv->lpe_audio.platdev);
|
||||
DRM_ERROR("Failed to create lpe audio platform device: %d\n",
|
||||
drm_err(&dev_priv->drm,
|
||||
"Failed to create lpe audio platform device: %d\n",
|
||||
ret);
|
||||
goto err_free_irq;
|
||||
}
|
||||
@ -259,8 +263,8 @@ void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv)
|
||||
|
||||
ret = generic_handle_irq(dev_priv->lpe_audio.irq);
|
||||
if (ret)
|
||||
DRM_ERROR_RATELIMITED("error handling LPE audio irq: %d\n",
|
||||
ret);
|
||||
drm_err_ratelimited(&dev_priv->drm,
|
||||
"error handling LPE audio irq: %d\n", ret);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -278,7 +282,8 @@ int intel_lpe_audio_init(struct drm_i915_private *dev_priv)
|
||||
if (lpe_audio_detect(dev_priv)) {
|
||||
ret = lpe_audio_setup(dev_priv);
|
||||
if (ret < 0)
|
||||
DRM_ERROR("failed to setup LPE Audio bridge\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"failed to setup LPE Audio bridge\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -37,7 +37,6 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
@ -182,8 +181,9 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
|
||||
if (INTEL_GEN(dev_priv) <= 4 &&
|
||||
pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
|
||||
DRM_DEBUG_KMS("Panel power timings uninitialized, "
|
||||
"setting defaults\n");
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Panel power timings uninitialized, "
|
||||
"setting defaults\n");
|
||||
/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
|
||||
pps->t1_t2 = 40 * 10;
|
||||
pps->t5 = 200 * 10;
|
||||
@ -192,10 +192,10 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
pps->tx = 200 * 10;
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
|
||||
"divider %d port %d powerdown_on_reset %d\n",
|
||||
pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
|
||||
pps->divider, pps->port, pps->powerdown_on_reset);
|
||||
drm_dbg(&dev_priv->drm, "LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
|
||||
"divider %d port %d powerdown_on_reset %d\n",
|
||||
pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
|
||||
pps->divider, pps->port, pps->powerdown_on_reset);
|
||||
}
|
||||
|
||||
static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
|
||||
@ -317,7 +317,8 @@ static void intel_enable_lvds(struct intel_encoder *encoder,
|
||||
intel_de_posting_read(dev_priv, lvds_encoder->reg);
|
||||
|
||||
if (intel_de_wait_for_set(dev_priv, PP_STATUS(0), PP_ON, 5000))
|
||||
DRM_ERROR("timed out waiting for panel to power on\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"timed out waiting for panel to power on\n");
|
||||
|
||||
intel_panel_enable_backlight(pipe_config, conn_state);
|
||||
}
|
||||
@ -332,7 +333,8 @@ static void intel_disable_lvds(struct intel_encoder *encoder,
|
||||
intel_de_write(dev_priv, PP_CONTROL(0),
|
||||
intel_de_read(dev_priv, PP_CONTROL(0)) & ~PANEL_POWER_ON);
|
||||
if (intel_de_wait_for_clear(dev_priv, PP_STATUS(0), PP_ON, 1000))
|
||||
DRM_ERROR("timed out waiting for panel to power off\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"timed out waiting for panel to power off\n");
|
||||
|
||||
intel_de_write(dev_priv, lvds_encoder->reg,
|
||||
intel_de_read(dev_priv, lvds_encoder->reg) & ~LVDS_PORT_EN);
|
||||
@ -398,7 +400,7 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
|
||||
|
||||
/* Should never happen!! */
|
||||
if (INTEL_GEN(dev_priv) < 4 && intel_crtc->pipe == 0) {
|
||||
DRM_ERROR("Can't support LVDS on pipe A\n");
|
||||
drm_err(&dev_priv->drm, "Can't support LVDS on pipe A\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -408,8 +410,9 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
|
||||
lvds_bpp = 6*3;
|
||||
|
||||
if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) {
|
||||
DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n",
|
||||
pipe_config->pipe_bpp, lvds_bpp);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"forcing display bpp (was %d) to LVDS (%d)\n",
|
||||
pipe_config->pipe_bpp, lvds_bpp);
|
||||
pipe_config->pipe_bpp = lvds_bpp;
|
||||
}
|
||||
|
||||
@ -833,7 +836,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
|
||||
}
|
||||
|
||||
if (!dev_priv->vbt.int_lvds_support) {
|
||||
DRM_DEBUG_KMS("Internal LVDS support disabled by VBT\n");
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Internal LVDS support disabled by VBT\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -852,10 +856,12 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
|
||||
pin = GMBUS_PIN_PANEL;
|
||||
if (!intel_bios_is_lvds_present(dev_priv, &pin)) {
|
||||
if ((lvds & LVDS_PORT_EN) == 0) {
|
||||
DRM_DEBUG_KMS("LVDS is not present in VBT\n");
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"LVDS is not present in VBT\n");
|
||||
return;
|
||||
}
|
||||
DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"LVDS is not present in VBT, but enabled anyway\n");
|
||||
}
|
||||
|
||||
lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
|
||||
@ -969,7 +975,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
|
||||
*/
|
||||
fixed_mode = intel_encoder_current_mode(intel_encoder);
|
||||
if (fixed_mode) {
|
||||
DRM_DEBUG_KMS("using current (BIOS) mode: ");
|
||||
drm_dbg_kms(&dev_priv->drm, "using current (BIOS) mode: ");
|
||||
drm_mode_debug_printmodeline(fixed_mode);
|
||||
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
}
|
||||
@ -985,8 +991,8 @@ out:
|
||||
intel_panel_setup_backlight(connector, INVALID_PIPE);
|
||||
|
||||
lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
|
||||
DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
|
||||
lvds_encoder->is_dual_link ? "dual" : "single");
|
||||
drm_dbg_kms(&dev_priv->drm, "detected %s-link lvds configuration\n",
|
||||
lvds_encoder->is_dual_link ? "dual" : "single");
|
||||
|
||||
lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;
|
||||
|
||||
@ -995,7 +1001,7 @@ out:
|
||||
failed:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
|
||||
drm_dbg_kms(&dev_priv->drm, "No LVDS modes found, disabling.\n");
|
||||
drm_connector_cleanup(connector);
|
||||
drm_encoder_cleanup(encoder);
|
||||
kfree(lvds_encoder);
|
||||
|
@ -30,8 +30,6 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "display/intel_panel.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
|
@ -27,7 +27,6 @@
|
||||
*/
|
||||
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "gem/i915_gem_pm.h"
|
||||
#include "gt/intel_ring.h"
|
||||
@ -324,7 +323,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
|
||||
/* check for underruns */
|
||||
tmp = intel_de_read(dev_priv, DOVSTA);
|
||||
if (tmp & (1 << 17))
|
||||
DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
|
||||
drm_dbg(&dev_priv->drm, "overlay underrun, DOVSTA: %x\n", tmp);
|
||||
|
||||
rq = alloc_request(overlay, NULL);
|
||||
if (IS_ERR(rq))
|
||||
@ -1069,7 +1068,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
overlay = dev_priv->overlay;
|
||||
if (!overlay) {
|
||||
DRM_DEBUG("userspace bug: no overlay\n");
|
||||
drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -1093,7 +1092,8 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
|
||||
drm_modeset_lock_all(dev);
|
||||
|
||||
if (i915_gem_object_is_tiled(new_bo)) {
|
||||
DRM_DEBUG_KMS("buffer used for overlay image can not be tiled\n");
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"buffer used for overlay image can not be tiled\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
@ -1228,7 +1228,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
overlay = dev_priv->overlay;
|
||||
if (!overlay) {
|
||||
DRM_DEBUG("userspace bug: no overlay\n");
|
||||
drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -1372,7 +1372,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
|
||||
update_reg_attrs(overlay, overlay->regs);
|
||||
|
||||
dev_priv->overlay = overlay;
|
||||
DRM_INFO("Initialized overlay support.\n");
|
||||
drm_info(&dev_priv->drm, "Initialized overlay support.\n");
|
||||
return;
|
||||
|
||||
out_free:
|
||||
|
@ -1882,6 +1882,7 @@ static int pwm_setup_backlight(struct intel_connector *connector,
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
const char *desc;
|
||||
u32 level, ns;
|
||||
int retval;
|
||||
|
||||
/* Get the right PWM chip for DSI backlight according to VBT */
|
||||
@ -1906,8 +1907,12 @@ static int pwm_setup_backlight(struct intel_connector *connector,
|
||||
*/
|
||||
pwm_apply_args(panel->backlight.pwm);
|
||||
|
||||
retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS,
|
||||
CRC_PMIC_PWM_PERIOD_NS);
|
||||
panel->backlight.min = 0; /* 0% */
|
||||
panel->backlight.max = 100; /* 100% */
|
||||
level = intel_panel_compute_brightness(connector, 100);
|
||||
ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100);
|
||||
|
||||
retval = pwm_config(panel->backlight.pwm, ns, CRC_PMIC_PWM_PERIOD_NS);
|
||||
if (retval < 0) {
|
||||
drm_err(&dev_priv->drm, "Failed to configure the pwm chip\n");
|
||||
pwm_put(panel->backlight.pwm);
|
||||
@ -1915,11 +1920,10 @@ static int pwm_setup_backlight(struct intel_connector *connector,
|
||||
return retval;
|
||||
}
|
||||
|
||||
panel->backlight.min = 0; /* 0% */
|
||||
panel->backlight.max = 100; /* 100% */
|
||||
panel->backlight.level = DIV_ROUND_UP(
|
||||
pwm_get_duty_cycle(panel->backlight.pwm) * 100,
|
||||
CRC_PMIC_PWM_PERIOD_NS);
|
||||
level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100,
|
||||
CRC_PMIC_PWM_PERIOD_NS);
|
||||
panel->backlight.level =
|
||||
intel_panel_compute_brightness(connector, level);
|
||||
panel->backlight.enabled = panel->backlight.level != 0;
|
||||
|
||||
drm_info(&dev_priv->drm, "Using %s PWM for LCD backlight control\n",
|
||||
|
@ -441,15 +441,11 @@ display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void intel_display_crc_init(struct drm_i915_private *dev_priv)
|
||||
void intel_crtc_crc_init(struct intel_crtc *crtc)
|
||||
{
|
||||
enum pipe pipe;
|
||||
struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
|
||||
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
|
||||
|
||||
spin_lock_init(&pipe_crc->lock);
|
||||
}
|
||||
spin_lock_init(&pipe_crc->lock);
|
||||
}
|
||||
|
||||
static int i8xx_crc_source_valid(struct drm_i915_private *dev_priv,
|
||||
@ -587,7 +583,8 @@ int intel_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
|
||||
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_pipe_crc *pipe_crc = &intel_crtc->pipe_crc;
|
||||
enum intel_display_power_domain power_domain;
|
||||
enum intel_pipe_crc_source source;
|
||||
intel_wakeref_t wakeref;
|
||||
@ -640,7 +637,7 @@ void intel_crtc_enable_pipe_crc(struct intel_crtc *intel_crtc)
|
||||
{
|
||||
struct drm_crtc *crtc = &intel_crtc->base;
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
|
||||
struct intel_pipe_crc *pipe_crc = &intel_crtc->pipe_crc;
|
||||
u32 val = 0;
|
||||
|
||||
if (!crtc->crc.opened)
|
||||
@ -660,7 +657,7 @@ void intel_crtc_disable_pipe_crc(struct intel_crtc *intel_crtc)
|
||||
{
|
||||
struct drm_crtc *crtc = &intel_crtc->base;
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
|
||||
struct intel_pipe_crc *pipe_crc = &intel_crtc->pipe_crc;
|
||||
|
||||
/* Swallow crc's until we stop generating them. */
|
||||
spin_lock_irq(&pipe_crc->lock);
|
||||
|
@ -13,7 +13,7 @@ struct drm_i915_private;
|
||||
struct intel_crtc;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void intel_display_crc_init(struct drm_i915_private *dev_priv);
|
||||
void intel_crtc_crc_init(struct intel_crtc *crtc);
|
||||
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name);
|
||||
int intel_crtc_verify_crc_source(struct drm_crtc *crtc,
|
||||
const char *source_name, size_t *values_cnt);
|
||||
@ -22,7 +22,7 @@ const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc,
|
||||
void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc);
|
||||
void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc);
|
||||
#else
|
||||
static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {}
|
||||
static inline void intel_crtc_crc_init(struct intel_crtc *crtc) {}
|
||||
#define intel_crtc_set_crc_source NULL
|
||||
#define intel_crtc_verify_crc_source NULL
|
||||
#define intel_crtc_get_crc_sources NULL
|
||||
|
@ -304,7 +304,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
|
||||
drm_dbg_kms(&dev_priv->drm, "eDP panel supports PSR version %x\n",
|
||||
intel_dp->psr_dpcd[0]);
|
||||
|
||||
if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
|
||||
if (drm_dp_has_quirk(&intel_dp->desc, 0, DP_DPCD_QUIRK_NO_PSR)) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"PSR support not currently available for this panel\n");
|
||||
return;
|
||||
|
@ -82,6 +82,16 @@ static const struct intel_dmi_quirk intel_dmi_quirks[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, ""),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = intel_dmi_reverse_brightness,
|
||||
.ident = "Thundersoft TST178 tablet",
|
||||
/* DMI strings are too generic, also match on BIOS date */
|
||||
.matches = {DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."),
|
||||
DMI_EXACT_MATCH(DMI_BIOS_DATE, "04/15/2014"),
|
||||
},
|
||||
},
|
||||
{ } /* terminating entry */
|
||||
},
|
||||
.hook = quirk_invert_brightness,
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
|
||||
struct drm_i915_private;
|
||||
|
@ -37,10 +37,10 @@
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_trace.h"
|
||||
#include "i915_vgpu.h"
|
||||
#include "intel_atomic_plane.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
@ -283,6 +283,16 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
|
||||
u32 src_x, src_y, src_w, src_h, hsub, vsub;
|
||||
bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
|
||||
|
||||
/*
|
||||
* FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
|
||||
* abuses hsub/vsub so we can't use them here. But as they
|
||||
* are limited to 32bpp RGB formats we don't actually need
|
||||
* to check anything.
|
||||
*/
|
||||
if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
|
||||
fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Hardware doesn't handle subpixel coordinates.
|
||||
* Adjust to (macro)pixel boundary, but be careful not to
|
||||
@ -297,26 +307,26 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
|
||||
drm_rect_init(src, src_x << 16, src_y << 16,
|
||||
src_w << 16, src_h << 16);
|
||||
|
||||
if (!fb->format->is_yuv)
|
||||
return 0;
|
||||
|
||||
/* YUV specific checks */
|
||||
if (!rotated) {
|
||||
if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
|
||||
hsub = 2;
|
||||
vsub = 2;
|
||||
} else {
|
||||
hsub = fb->format->hsub;
|
||||
vsub = fb->format->vsub;
|
||||
} else {
|
||||
hsub = vsub = max(fb->format->hsub, fb->format->vsub);
|
||||
}
|
||||
|
||||
if (rotated)
|
||||
hsub = vsub = max(hsub, vsub);
|
||||
|
||||
if (src_x % hsub || src_w % hsub) {
|
||||
DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
|
||||
src_x, src_w, hsub, rotated ? "rotated " : "");
|
||||
DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
|
||||
src_x, src_w, hsub, yesno(rotated));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (src_y % vsub || src_h % vsub) {
|
||||
DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
|
||||
src_y, src_h, vsub, rotated ? "rotated " : "");
|
||||
DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
|
||||
src_y, src_h, vsub, yesno(rotated));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -355,9 +365,8 @@ static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
|
||||
unsigned int pixel_rate = crtc_state->pixel_rate;
|
||||
unsigned int src_w, src_h, dst_w, dst_h;
|
||||
unsigned int num, den;
|
||||
unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
|
||||
|
||||
skl_plane_ratio(crtc_state, plane_state, &num, &den);
|
||||
|
||||
@ -365,17 +374,7 @@ static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
|
||||
if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
|
||||
den *= 2;
|
||||
|
||||
src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
|
||||
src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
|
||||
dst_w = drm_rect_width(&plane_state->uapi.dst);
|
||||
dst_h = drm_rect_height(&plane_state->uapi.dst);
|
||||
|
||||
/* Downscaling limits the maximum pixel rate */
|
||||
dst_w = min(src_w, dst_w);
|
||||
dst_h = min(src_h, dst_h);
|
||||
|
||||
return DIV64_U64_ROUND_UP(mul_u32_u32(pixel_rate * num, src_w * src_h),
|
||||
mul_u32_u32(den, dst_w * dst_h));
|
||||
return DIV_ROUND_UP(pixel_rate * num, den);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
@ -2077,6 +2076,18 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool intel_format_is_p01x(u32 format)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_P010:
|
||||
case DRM_FORMAT_P012:
|
||||
case DRM_FORMAT_P016:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
@ -2155,6 +2166,15 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Wa_1606054188:tgl */
|
||||
if (IS_TIGERLAKE(dev_priv) &&
|
||||
plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
|
||||
intel_format_is_p01x(fb->format->format)) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Source color keying not supported with P01x formats\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3011,7 +3031,6 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
|
||||
struct intel_plane *plane;
|
||||
enum drm_plane_type plane_type;
|
||||
unsigned int supported_rotations;
|
||||
unsigned int possible_crtcs;
|
||||
const u64 *modifiers;
|
||||
const u32 *formats;
|
||||
int num_formats;
|
||||
@ -3066,10 +3085,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
|
||||
else
|
||||
plane_type = DRM_PLANE_TYPE_OVERLAY;
|
||||
|
||||
possible_crtcs = BIT(pipe);
|
||||
|
||||
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
|
||||
possible_crtcs, plane_funcs,
|
||||
0, plane_funcs,
|
||||
formats, num_formats, modifiers,
|
||||
plane_type,
|
||||
"plane %d%c", plane_id + 1,
|
||||
@ -3120,7 +3137,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
|
||||
{
|
||||
struct intel_plane *plane;
|
||||
const struct drm_plane_funcs *plane_funcs;
|
||||
unsigned long possible_crtcs;
|
||||
unsigned int supported_rotations;
|
||||
const u64 *modifiers;
|
||||
const u32 *formats;
|
||||
@ -3205,10 +3221,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
|
||||
plane->id = PLANE_SPRITE0 + sprite;
|
||||
plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
|
||||
|
||||
possible_crtcs = BIT(pipe);
|
||||
|
||||
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
|
||||
possible_crtcs, plane_funcs,
|
||||
0, plane_funcs,
|
||||
formats, num_formats, modifiers,
|
||||
DRM_PLANE_TYPE_OVERLAY,
|
||||
"sprite %c", sprite_name(pipe, sprite));
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_connector.h"
|
||||
|
@ -6,8 +6,6 @@
|
||||
* Manasi Navare <manasi.d.navare@intel.com>
|
||||
*/
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dsi.h"
|
||||
|
@ -1591,59 +1591,6 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = {
|
||||
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
|
||||
};
|
||||
|
||||
static enum drm_panel_orientation
|
||||
vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_encoder *encoder = intel_attached_encoder(connector);
|
||||
enum intel_display_power_domain power_domain;
|
||||
enum drm_panel_orientation orientation;
|
||||
struct intel_plane *plane;
|
||||
struct intel_crtc *crtc;
|
||||
intel_wakeref_t wakeref;
|
||||
enum pipe pipe;
|
||||
u32 val;
|
||||
|
||||
if (!encoder->get_hw_state(encoder, &pipe))
|
||||
return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
||||
|
||||
crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
|
||||
plane = to_intel_plane(crtc->base.primary);
|
||||
|
||||
power_domain = POWER_DOMAIN_PIPE(pipe);
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
|
||||
if (!wakeref)
|
||||
return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
||||
|
||||
val = intel_de_read(dev_priv, DSPCNTR(plane->i9xx_plane));
|
||||
|
||||
if (!(val & DISPLAY_PLANE_ENABLE))
|
||||
orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
||||
else if (val & DISPPLANE_ROTATE_180)
|
||||
orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
|
||||
else
|
||||
orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
|
||||
|
||||
intel_display_power_put(dev_priv, power_domain, wakeref);
|
||||
|
||||
return orientation;
|
||||
}
|
||||
|
||||
static enum drm_panel_orientation
|
||||
vlv_dsi_get_panel_orientation(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
enum drm_panel_orientation orientation;
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
orientation = vlv_dsi_get_hw_panel_orientation(connector);
|
||||
if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
|
||||
return orientation;
|
||||
}
|
||||
|
||||
return intel_dsi_get_panel_orientation(connector);
|
||||
}
|
||||
|
||||
static void vlv_dsi_add_properties(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
@ -1662,7 +1609,7 @@ static void vlv_dsi_add_properties(struct intel_connector *connector)
|
||||
|
||||
drm_connector_set_panel_orientation_with_quirk(
|
||||
&connector->base,
|
||||
vlv_dsi_get_panel_orientation(connector),
|
||||
intel_dsi_get_panel_orientation(connector),
|
||||
connector->panel.fixed_mode->hdisplay,
|
||||
connector->panel.fixed_mode->vdisplay);
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ static void clear_pages_worker(struct work_struct *work)
|
||||
0);
|
||||
out_request:
|
||||
if (unlikely(err)) {
|
||||
i915_request_skip(rq, err);
|
||||
i915_request_set_error_once(rq, err);
|
||||
err = 0;
|
||||
}
|
||||
|
||||
|
@ -67,10 +67,9 @@
|
||||
#include <linux/log2.h>
|
||||
#include <linux/nospec.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "gt/gen6_ppgtt.h"
|
||||
#include "gt/intel_context.h"
|
||||
#include "gt/intel_context_param.h"
|
||||
#include "gt/intel_engine_heartbeat.h"
|
||||
#include "gt/intel_engine_user.h"
|
||||
#include "gt/intel_ring.h"
|
||||
@ -243,7 +242,6 @@ static void __free_engines(struct i915_gem_engines *e, unsigned int count)
|
||||
if (!e->engines[count])
|
||||
continue;
|
||||
|
||||
RCU_INIT_POINTER(e->engines[count]->gem_context, NULL);
|
||||
intel_context_put(e->engines[count]);
|
||||
}
|
||||
kfree(e);
|
||||
@ -256,7 +254,51 @@ static void free_engines(struct i915_gem_engines *e)
|
||||
|
||||
static void free_engines_rcu(struct rcu_head *rcu)
|
||||
{
|
||||
free_engines(container_of(rcu, struct i915_gem_engines, rcu));
|
||||
struct i915_gem_engines *engines =
|
||||
container_of(rcu, struct i915_gem_engines, rcu);
|
||||
|
||||
i915_sw_fence_fini(&engines->fence);
|
||||
free_engines(engines);
|
||||
}
|
||||
|
||||
static int __i915_sw_fence_call
|
||||
engines_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
|
||||
{
|
||||
struct i915_gem_engines *engines =
|
||||
container_of(fence, typeof(*engines), fence);
|
||||
|
||||
switch (state) {
|
||||
case FENCE_COMPLETE:
|
||||
if (!list_empty(&engines->link)) {
|
||||
struct i915_gem_context *ctx = engines->ctx;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ctx->stale.lock, flags);
|
||||
list_del(&engines->link);
|
||||
spin_unlock_irqrestore(&ctx->stale.lock, flags);
|
||||
}
|
||||
i915_gem_context_put(engines->ctx);
|
||||
break;
|
||||
|
||||
case FENCE_FREE:
|
||||
init_rcu_head(&engines->rcu);
|
||||
call_rcu(&engines->rcu, free_engines_rcu);
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct i915_gem_engines *alloc_engines(unsigned int count)
|
||||
{
|
||||
struct i915_gem_engines *e;
|
||||
|
||||
e = kzalloc(struct_size(e, engines, count), GFP_KERNEL);
|
||||
if (!e)
|
||||
return NULL;
|
||||
|
||||
i915_sw_fence_init(&e->fence, engines_notify);
|
||||
return e;
|
||||
}
|
||||
|
||||
static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
|
||||
@ -266,12 +308,10 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
|
||||
struct i915_gem_engines *e;
|
||||
enum intel_engine_id id;
|
||||
|
||||
e = kzalloc(struct_size(e, engines, I915_NUM_ENGINES), GFP_KERNEL);
|
||||
e = alloc_engines(I915_NUM_ENGINES);
|
||||
if (!e)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
e->ctx = ctx;
|
||||
|
||||
for_each_engine(engine, gt, id) {
|
||||
struct intel_context *ce;
|
||||
|
||||
@ -305,7 +345,6 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
|
||||
list_del(&ctx->link);
|
||||
spin_unlock(&ctx->i915->gem.contexts.lock);
|
||||
|
||||
free_engines(rcu_access_pointer(ctx->engines));
|
||||
mutex_destroy(&ctx->engines_mutex);
|
||||
|
||||
if (ctx->timeline)
|
||||
@ -492,30 +531,75 @@ static void kill_engines(struct i915_gem_engines *engines)
|
||||
static void kill_stale_engines(struct i915_gem_context *ctx)
|
||||
{
|
||||
struct i915_gem_engines *pos, *next;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ctx->stale.lock, flags);
|
||||
spin_lock_irq(&ctx->stale.lock);
|
||||
GEM_BUG_ON(!i915_gem_context_is_closed(ctx));
|
||||
list_for_each_entry_safe(pos, next, &ctx->stale.engines, link) {
|
||||
if (!i915_sw_fence_await(&pos->fence))
|
||||
if (!i915_sw_fence_await(&pos->fence)) {
|
||||
list_del_init(&pos->link);
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ctx->stale.lock, flags);
|
||||
spin_unlock_irq(&ctx->stale.lock);
|
||||
|
||||
kill_engines(pos);
|
||||
|
||||
spin_lock_irqsave(&ctx->stale.lock, flags);
|
||||
spin_lock_irq(&ctx->stale.lock);
|
||||
GEM_BUG_ON(i915_sw_fence_signaled(&pos->fence));
|
||||
list_safe_reset_next(pos, next, link);
|
||||
list_del_init(&pos->link); /* decouple from FENCE_COMPLETE */
|
||||
|
||||
i915_sw_fence_complete(&pos->fence);
|
||||
}
|
||||
spin_unlock_irqrestore(&ctx->stale.lock, flags);
|
||||
spin_unlock_irq(&ctx->stale.lock);
|
||||
}
|
||||
|
||||
static void kill_context(struct i915_gem_context *ctx)
|
||||
{
|
||||
kill_stale_engines(ctx);
|
||||
kill_engines(__context_engines_static(ctx));
|
||||
}
|
||||
|
||||
static void engines_idle_release(struct i915_gem_context *ctx,
|
||||
struct i915_gem_engines *engines)
|
||||
{
|
||||
struct i915_gem_engines_iter it;
|
||||
struct intel_context *ce;
|
||||
|
||||
INIT_LIST_HEAD(&engines->link);
|
||||
|
||||
engines->ctx = i915_gem_context_get(ctx);
|
||||
|
||||
for_each_gem_engine(ce, engines, it) {
|
||||
struct dma_fence *fence;
|
||||
int err = 0;
|
||||
|
||||
/* serialises with execbuf */
|
||||
RCU_INIT_POINTER(ce->gem_context, NULL);
|
||||
if (!intel_context_pin_if_active(ce))
|
||||
continue;
|
||||
|
||||
fence = i915_active_fence_get(&ce->timeline->last_request);
|
||||
if (fence) {
|
||||
err = i915_sw_fence_await_dma_fence(&engines->fence,
|
||||
fence, 0,
|
||||
GFP_KERNEL);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
intel_context_unpin(ce);
|
||||
if (err < 0)
|
||||
goto kill;
|
||||
}
|
||||
|
||||
spin_lock_irq(&ctx->stale.lock);
|
||||
if (!i915_gem_context_is_closed(ctx))
|
||||
list_add_tail(&engines->link, &ctx->stale.engines);
|
||||
spin_unlock_irq(&ctx->stale.lock);
|
||||
|
||||
kill:
|
||||
if (list_empty(&engines->link)) /* raced, already closed */
|
||||
kill_engines(engines);
|
||||
|
||||
i915_sw_fence_commit(&engines->fence);
|
||||
}
|
||||
|
||||
static void set_closed_name(struct i915_gem_context *ctx)
|
||||
@ -539,11 +623,16 @@ static void context_close(struct i915_gem_context *ctx)
|
||||
{
|
||||
struct i915_address_space *vm;
|
||||
|
||||
/* Flush any concurrent set_engines() */
|
||||
mutex_lock(&ctx->engines_mutex);
|
||||
engines_idle_release(ctx, rcu_replace_pointer(ctx->engines, NULL, 1));
|
||||
i915_gem_context_set_closed(ctx);
|
||||
set_closed_name(ctx);
|
||||
mutex_unlock(&ctx->engines_mutex);
|
||||
|
||||
mutex_lock(&ctx->mutex);
|
||||
|
||||
set_closed_name(ctx);
|
||||
|
||||
vm = i915_gem_context_vm(ctx);
|
||||
if (vm)
|
||||
i915_vm_close(vm);
|
||||
@ -668,23 +757,30 @@ err_free:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
context_apply_all(struct i915_gem_context *ctx,
|
||||
void (*fn)(struct intel_context *ce, void *data),
|
||||
int (*fn)(struct intel_context *ce, void *data),
|
||||
void *data)
|
||||
{
|
||||
struct i915_gem_engines_iter it;
|
||||
struct intel_context *ce;
|
||||
int err = 0;
|
||||
|
||||
for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it)
|
||||
fn(ce, data);
|
||||
for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
|
||||
err = fn(ce, data);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
i915_gem_context_unlock_engines(ctx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __apply_ppgtt(struct intel_context *ce, void *vm)
|
||||
static int __apply_ppgtt(struct intel_context *ce, void *vm)
|
||||
{
|
||||
i915_vm_put(ce->vm);
|
||||
ce->vm = i915_vm_get(vm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i915_address_space *
|
||||
@ -722,9 +818,10 @@ static void __set_timeline(struct intel_timeline **dst,
|
||||
intel_timeline_put(old);
|
||||
}
|
||||
|
||||
static void __apply_timeline(struct intel_context *ce, void *timeline)
|
||||
static int __apply_timeline(struct intel_context *ce, void *timeline)
|
||||
{
|
||||
__set_timeline(&ce->timeline, timeline);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __assign_timeline(struct i915_gem_context *ctx,
|
||||
@ -806,6 +903,7 @@ void i915_gem_init__contexts(struct drm_i915_private *i915)
|
||||
void i915_gem_driver_release__contexts(struct drm_i915_private *i915)
|
||||
{
|
||||
flush_work(&i915->gem.contexts.free_work);
|
||||
rcu_barrier(); /* and flush the left over RCU frees */
|
||||
}
|
||||
|
||||
static int gem_context_register(struct i915_gem_context *ctx,
|
||||
@ -971,6 +1069,30 @@ static void cb_retire(struct i915_active *base)
|
||||
kfree(cb);
|
||||
}
|
||||
|
||||
static inline struct i915_gem_engines *
|
||||
__context_engines_await(const struct i915_gem_context *ctx)
|
||||
{
|
||||
struct i915_gem_engines *engines;
|
||||
|
||||
rcu_read_lock();
|
||||
do {
|
||||
engines = rcu_dereference(ctx->engines);
|
||||
if (unlikely(!engines))
|
||||
break;
|
||||
|
||||
if (unlikely(!i915_sw_fence_await(&engines->fence)))
|
||||
continue;
|
||||
|
||||
if (likely(engines == rcu_access_pointer(ctx->engines)))
|
||||
break;
|
||||
|
||||
i915_sw_fence_complete(&engines->fence);
|
||||
} while (1);
|
||||
rcu_read_unlock();
|
||||
|
||||
return engines;
|
||||
}
|
||||
|
||||
I915_SELFTEST_DECLARE(static intel_engine_mask_t context_barrier_inject_fault);
|
||||
static int context_barrier_task(struct i915_gem_context *ctx,
|
||||
intel_engine_mask_t engines,
|
||||
@ -981,6 +1103,7 @@ static int context_barrier_task(struct i915_gem_context *ctx,
|
||||
{
|
||||
struct context_barrier_task *cb;
|
||||
struct i915_gem_engines_iter it;
|
||||
struct i915_gem_engines *e;
|
||||
struct intel_context *ce;
|
||||
int err = 0;
|
||||
|
||||
@ -997,7 +1120,13 @@ static int context_barrier_task(struct i915_gem_context *ctx,
|
||||
return err;
|
||||
}
|
||||
|
||||
for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
|
||||
e = __context_engines_await(ctx);
|
||||
if (!e) {
|
||||
i915_active_release(&cb->base);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
for_each_gem_engine(ce, e, it) {
|
||||
struct i915_request *rq;
|
||||
|
||||
if (I915_SELFTEST_ONLY(context_barrier_inject_fault &
|
||||
@ -1028,7 +1157,7 @@ static int context_barrier_task(struct i915_gem_context *ctx,
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
i915_gem_context_unlock_engines(ctx);
|
||||
i915_sw_fence_complete(&e->fence);
|
||||
|
||||
cb->task = err ? NULL : task; /* caller needs to unwind instead */
|
||||
cb->data = data;
|
||||
@ -1215,6 +1344,63 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __apply_ringsize(struct intel_context *ce, void *sz)
|
||||
{
|
||||
return intel_context_set_ring_size(ce, (unsigned long)sz);
|
||||
}
|
||||
|
||||
static int set_ringsize(struct i915_gem_context *ctx,
|
||||
struct drm_i915_gem_context_param *args)
|
||||
{
|
||||
if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
|
||||
return -ENODEV;
|
||||
|
||||
if (args->size)
|
||||
return -EINVAL;
|
||||
|
||||
if (!IS_ALIGNED(args->value, I915_GTT_PAGE_SIZE))
|
||||
return -EINVAL;
|
||||
|
||||
if (args->value < I915_GTT_PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (args->value > 128 * I915_GTT_PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
return context_apply_all(ctx,
|
||||
__apply_ringsize,
|
||||
__intel_context_ring_size(args->value));
|
||||
}
|
||||
|
||||
static int __get_ringsize(struct intel_context *ce, void *arg)
|
||||
{
|
||||
long sz;
|
||||
|
||||
sz = intel_context_get_ring_size(ce);
|
||||
GEM_BUG_ON(sz > INT_MAX);
|
||||
|
||||
return sz; /* stop on first engine */
|
||||
}
|
||||
|
||||
static int get_ringsize(struct i915_gem_context *ctx,
|
||||
struct drm_i915_gem_context_param *args)
|
||||
{
|
||||
int sz;
|
||||
|
||||
if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
|
||||
return -ENODEV;
|
||||
|
||||
if (args->size)
|
||||
return -EINVAL;
|
||||
|
||||
sz = context_apply_all(ctx, __get_ringsize, NULL);
|
||||
if (sz < 0)
|
||||
return sz;
|
||||
|
||||
args->value = sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
user_to_context_sseu(struct drm_i915_private *i915,
|
||||
const struct drm_i915_gem_context_param_sseu *user,
|
||||
@ -1562,77 +1748,6 @@ static const i915_user_extension_fn set_engines__extensions[] = {
|
||||
[I915_CONTEXT_ENGINES_EXT_BOND] = set_engines__bond,
|
||||
};
|
||||
|
||||
static int engines_notify(struct i915_sw_fence *fence,
|
||||
enum i915_sw_fence_notify state)
|
||||
{
|
||||
struct i915_gem_engines *engines =
|
||||
container_of(fence, typeof(*engines), fence);
|
||||
|
||||
switch (state) {
|
||||
case FENCE_COMPLETE:
|
||||
if (!list_empty(&engines->link)) {
|
||||
struct i915_gem_context *ctx = engines->ctx;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ctx->stale.lock, flags);
|
||||
list_del(&engines->link);
|
||||
spin_unlock_irqrestore(&ctx->stale.lock, flags);
|
||||
}
|
||||
break;
|
||||
|
||||
case FENCE_FREE:
|
||||
init_rcu_head(&engines->rcu);
|
||||
call_rcu(&engines->rcu, free_engines_rcu);
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static void engines_idle_release(struct i915_gem_engines *engines)
|
||||
{
|
||||
struct i915_gem_engines_iter it;
|
||||
struct intel_context *ce;
|
||||
unsigned long flags;
|
||||
|
||||
GEM_BUG_ON(!engines);
|
||||
i915_sw_fence_init(&engines->fence, engines_notify);
|
||||
|
||||
INIT_LIST_HEAD(&engines->link);
|
||||
spin_lock_irqsave(&engines->ctx->stale.lock, flags);
|
||||
if (!i915_gem_context_is_closed(engines->ctx))
|
||||
list_add(&engines->link, &engines->ctx->stale.engines);
|
||||
spin_unlock_irqrestore(&engines->ctx->stale.lock, flags);
|
||||
if (list_empty(&engines->link)) /* raced, already closed */
|
||||
goto kill;
|
||||
|
||||
for_each_gem_engine(ce, engines, it) {
|
||||
struct dma_fence *fence;
|
||||
int err;
|
||||
|
||||
if (!ce->timeline)
|
||||
continue;
|
||||
|
||||
fence = i915_active_fence_get(&ce->timeline->last_request);
|
||||
if (!fence)
|
||||
continue;
|
||||
|
||||
err = i915_sw_fence_await_dma_fence(&engines->fence,
|
||||
fence, 0,
|
||||
GFP_KERNEL);
|
||||
|
||||
dma_fence_put(fence);
|
||||
if (err < 0)
|
||||
goto kill;
|
||||
}
|
||||
goto out;
|
||||
|
||||
kill:
|
||||
kill_engines(engines);
|
||||
out:
|
||||
i915_sw_fence_commit(&engines->fence);
|
||||
}
|
||||
|
||||
static int
|
||||
set_engines(struct i915_gem_context *ctx,
|
||||
const struct drm_i915_gem_context_param *args)
|
||||
@ -1669,14 +1784,10 @@ set_engines(struct i915_gem_context *ctx,
|
||||
* first 64 engines defined here.
|
||||
*/
|
||||
num_engines = (args->size - sizeof(*user)) / sizeof(*user->engines);
|
||||
|
||||
set.engines = kmalloc(struct_size(set.engines, engines, num_engines),
|
||||
GFP_KERNEL);
|
||||
set.engines = alloc_engines(num_engines);
|
||||
if (!set.engines)
|
||||
return -ENOMEM;
|
||||
|
||||
set.engines->ctx = ctx;
|
||||
|
||||
for (n = 0; n < num_engines; n++) {
|
||||
struct i915_engine_class_instance ci;
|
||||
struct intel_engine_cs *engine;
|
||||
@ -1729,6 +1840,11 @@ set_engines(struct i915_gem_context *ctx,
|
||||
|
||||
replace:
|
||||
mutex_lock(&ctx->engines_mutex);
|
||||
if (i915_gem_context_is_closed(ctx)) {
|
||||
mutex_unlock(&ctx->engines_mutex);
|
||||
free_engines(set.engines);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (args->size)
|
||||
i915_gem_context_set_user_engines(ctx);
|
||||
else
|
||||
@ -1737,7 +1853,7 @@ replace:
|
||||
mutex_unlock(&ctx->engines_mutex);
|
||||
|
||||
/* Keep track of old engine sets for kill_context() */
|
||||
engines_idle_release(set.engines);
|
||||
engines_idle_release(ctx, set.engines);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1748,7 +1864,7 @@ __copy_engines(struct i915_gem_engines *e)
|
||||
struct i915_gem_engines *copy;
|
||||
unsigned int n;
|
||||
|
||||
copy = kmalloc(struct_size(e, engines, e->num_engines), GFP_KERNEL);
|
||||
copy = alloc_engines(e->num_engines);
|
||||
if (!copy)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -1852,17 +1968,19 @@ set_persistence(struct i915_gem_context *ctx,
|
||||
return __context_set_persistence(ctx, args->value);
|
||||
}
|
||||
|
||||
static void __apply_priority(struct intel_context *ce, void *arg)
|
||||
static int __apply_priority(struct intel_context *ce, void *arg)
|
||||
{
|
||||
struct i915_gem_context *ctx = arg;
|
||||
|
||||
if (!intel_engine_has_semaphores(ce->engine))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (ctx->sched.priority >= I915_PRIORITY_NORMAL)
|
||||
intel_context_set_use_semaphores(ce);
|
||||
else
|
||||
intel_context_clear_use_semaphores(ce);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_priority(struct i915_gem_context *ctx,
|
||||
@ -1955,6 +2073,10 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
|
||||
ret = set_persistence(ctx, args);
|
||||
break;
|
||||
|
||||
case I915_CONTEXT_PARAM_RINGSIZE:
|
||||
ret = set_ringsize(ctx, args);
|
||||
break;
|
||||
|
||||
case I915_CONTEXT_PARAM_BAN_PERIOD:
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@ -1983,6 +2105,18 @@ static int create_setparam(struct i915_user_extension __user *ext, void *data)
|
||||
return ctx_setparam(arg->fpriv, arg->ctx, &local.param);
|
||||
}
|
||||
|
||||
static int copy_ring_size(struct intel_context *dst,
|
||||
struct intel_context *src)
|
||||
{
|
||||
long sz;
|
||||
|
||||
sz = intel_context_get_ring_size(src);
|
||||
if (sz < 0)
|
||||
return sz;
|
||||
|
||||
return intel_context_set_ring_size(dst, sz);
|
||||
}
|
||||
|
||||
static int clone_engines(struct i915_gem_context *dst,
|
||||
struct i915_gem_context *src)
|
||||
{
|
||||
@ -1991,12 +2125,10 @@ static int clone_engines(struct i915_gem_context *dst,
|
||||
bool user_engines;
|
||||
unsigned long n;
|
||||
|
||||
clone = kmalloc(struct_size(e, engines, e->num_engines), GFP_KERNEL);
|
||||
clone = alloc_engines(e->num_engines);
|
||||
if (!clone)
|
||||
goto err_unlock;
|
||||
|
||||
clone->ctx = dst;
|
||||
|
||||
for (n = 0; n < e->num_engines; n++) {
|
||||
struct intel_engine_cs *engine;
|
||||
|
||||
@ -2026,6 +2158,12 @@ static int clone_engines(struct i915_gem_context *dst,
|
||||
}
|
||||
|
||||
intel_context_set_gem(clone->engines[n], dst);
|
||||
|
||||
/* Copy across the preferred ringsize */
|
||||
if (copy_ring_size(clone->engines[n], e->engines[n])) {
|
||||
__free_engines(clone, n + 1);
|
||||
goto err_unlock;
|
||||
}
|
||||
}
|
||||
clone->num_engines = n;
|
||||
|
||||
@ -2033,8 +2171,7 @@ static int clone_engines(struct i915_gem_context *dst,
|
||||
i915_gem_context_unlock_engines(src);
|
||||
|
||||
/* Serialised by constructor */
|
||||
free_engines(__context_engines_static(dst));
|
||||
RCU_INIT_POINTER(dst->engines, clone);
|
||||
engines_idle_release(dst, rcu_replace_pointer(dst->engines, clone, 1));
|
||||
if (user_engines)
|
||||
i915_gem_context_set_user_engines(dst);
|
||||
else
|
||||
@ -2388,6 +2525,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
|
||||
args->value = i915_gem_context_is_persistent(ctx);
|
||||
break;
|
||||
|
||||
case I915_CONTEXT_PARAM_RINGSIZE:
|
||||
ret = get_ringsize(ctx, args);
|
||||
break;
|
||||
|
||||
case I915_CONTEXT_PARAM_BAN_PERIOD:
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@ -2461,6 +2602,9 @@ i915_gem_engines_iter_next(struct i915_gem_engines_iter *it)
|
||||
const struct i915_gem_engines *e = it->engines;
|
||||
struct intel_context *ctx;
|
||||
|
||||
if (unlikely(!e))
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
if (it->idx >= e->num_engines)
|
||||
return NULL;
|
||||
|
@ -207,7 +207,6 @@ static inline void
|
||||
i915_gem_engines_iter_init(struct i915_gem_engines_iter *it,
|
||||
struct i915_gem_engines *engines)
|
||||
{
|
||||
GEM_BUG_ON(!engines);
|
||||
it->engines = engines;
|
||||
it->idx = 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,8 +8,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/swiotlb.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gem.h"
|
||||
#include "i915_gem_object.h"
|
||||
|
@ -775,7 +775,7 @@ static struct file *mmap_singleton(struct drm_i915_private *i915)
|
||||
struct file *file;
|
||||
|
||||
rcu_read_lock();
|
||||
file = i915->gem.mmap_singleton;
|
||||
file = READ_ONCE(i915->gem.mmap_singleton);
|
||||
if (file && !get_file_rcu(file))
|
||||
file = NULL;
|
||||
rcu_read_unlock();
|
||||
|
@ -11,8 +11,6 @@
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_device.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "display/intel_frontbuffer.h"
|
||||
#include "i915_gem_object_types.h"
|
||||
#include "i915_gem_gtt.h"
|
||||
|
@ -186,7 +186,7 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj,
|
||||
0);
|
||||
out_request:
|
||||
if (unlikely(err))
|
||||
i915_request_skip(rq, err);
|
||||
i915_request_set_error_once(rq, err);
|
||||
|
||||
i915_request_add(rq);
|
||||
out_batch:
|
||||
@ -196,6 +196,17 @@ out_unpin:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Wa_1209644611:icl,ehl */
|
||||
static bool wa_1209644611_applies(struct drm_i915_private *i915, u32 size)
|
||||
{
|
||||
u32 height = size >> PAGE_SHIFT;
|
||||
|
||||
if (!IS_GEN(i915, 11))
|
||||
return false;
|
||||
|
||||
return height % 4 == 3 && height <= 8;
|
||||
}
|
||||
|
||||
struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce,
|
||||
struct i915_vma *src,
|
||||
struct i915_vma *dst)
|
||||
@ -237,7 +248,8 @@ struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce,
|
||||
size = min_t(u64, rem, block_size);
|
||||
GEM_BUG_ON(size >> PAGE_SHIFT > S16_MAX);
|
||||
|
||||
if (INTEL_GEN(i915) >= 9) {
|
||||
if (INTEL_GEN(i915) >= 9 &&
|
||||
!wa_1209644611_applies(i915, size)) {
|
||||
*cmd++ = GEN9_XY_FAST_COPY_BLT_CMD | (10 - 2);
|
||||
*cmd++ = BLT_DEPTH_32 | PAGE_SIZE;
|
||||
*cmd++ = 0;
|
||||
@ -385,7 +397,7 @@ out_unlock:
|
||||
drm_gem_unlock_reservations(objs, ARRAY_SIZE(objs), &acquire);
|
||||
out_request:
|
||||
if (unlikely(err))
|
||||
i915_request_skip(rq, err);
|
||||
i915_request_set_error_once(rq, err);
|
||||
|
||||
i915_request_add(rq);
|
||||
out_batch:
|
||||
|
@ -194,10 +194,11 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align)
|
||||
/* Perma-pin (until release) the physical set of pages */
|
||||
__i915_gem_object_pin_pages(obj);
|
||||
|
||||
if (!IS_ERR_OR_NULL(pages)) {
|
||||
if (!IS_ERR_OR_NULL(pages))
|
||||
i915_gem_shmem_ops.put_pages(obj, pages);
|
||||
i915_gem_object_release_memory_region(obj);
|
||||
}
|
||||
|
||||
i915_gem_object_release_memory_region(obj);
|
||||
|
||||
mutex_unlock(&obj->mm.lock);
|
||||
return 0;
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_trace.h"
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "gem/i915_gem_region.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gem_stolen.h"
|
||||
#include "i915_vgpu.h"
|
||||
|
||||
/*
|
||||
* The BIOS typically reserves some of the system's memory for the exclusive
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gem.h"
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include <linux/swap.h>
|
||||
#include <linux/sched/mm.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gem_ioctls.h"
|
||||
#include "i915_gem_object.h"
|
||||
|
@ -1004,7 +1004,7 @@ emit_rpcs_query(struct drm_i915_gem_object *obj,
|
||||
return 0;
|
||||
|
||||
skip_request:
|
||||
i915_request_skip(rq, err);
|
||||
i915_request_set_error_once(rq, err);
|
||||
err_request:
|
||||
i915_request_add(rq);
|
||||
err_batch:
|
||||
@ -1559,7 +1559,7 @@ static int write_to_scratch(struct i915_gem_context *ctx,
|
||||
|
||||
goto out_vm;
|
||||
skip_request:
|
||||
i915_request_skip(rq, err);
|
||||
i915_request_set_error_once(rq, err);
|
||||
err_request:
|
||||
i915_request_add(rq);
|
||||
err_unpin:
|
||||
@ -1708,7 +1708,7 @@ static int read_from_scratch(struct i915_gem_context *ctx,
|
||||
|
||||
goto out_vm;
|
||||
skip_request:
|
||||
i915_request_skip(rq, err);
|
||||
i915_request_set_error_once(rq, err);
|
||||
err_request:
|
||||
i915_request_add(rq);
|
||||
err_unpin:
|
||||
@ -1809,7 +1809,6 @@ static int igt_vm_isolation(void *arg)
|
||||
|
||||
vm_total = ctx_vm(ctx_a)->total;
|
||||
GEM_BUG_ON(ctx_vm(ctx_b)->total != vm_total);
|
||||
vm_total -= I915_GTT_PAGE_SIZE;
|
||||
|
||||
count = 0;
|
||||
num_engines = 0;
|
||||
@ -1828,10 +1827,10 @@ static int igt_vm_isolation(void *arg)
|
||||
u32 value = 0xc5c5c5c5;
|
||||
u64 offset;
|
||||
|
||||
div64_u64_rem(i915_prandom_u64_state(&prng),
|
||||
vm_total, &offset);
|
||||
offset = round_down(offset, alignof_dword);
|
||||
offset += I915_GTT_PAGE_SIZE;
|
||||
/* Leave enough space at offset 0 for the batch */
|
||||
offset = igt_random_offset(&prng,
|
||||
I915_GTT_PAGE_SIZE, vm_total,
|
||||
sizeof(u32), alignof_dword);
|
||||
|
||||
err = write_to_scratch(ctx_a, engine,
|
||||
offset, 0xdeadbeef);
|
||||
|
@ -159,7 +159,7 @@ int igt_gpu_fill_dw(struct intel_context *ce,
|
||||
return 0;
|
||||
|
||||
skip_request:
|
||||
i915_request_skip(rq, err);
|
||||
i915_request_set_error_once(rq, err);
|
||||
err_request:
|
||||
i915_request_add(rq);
|
||||
err_batch:
|
||||
|
@ -23,6 +23,9 @@ mock_context(struct drm_i915_private *i915,
|
||||
INIT_LIST_HEAD(&ctx->link);
|
||||
ctx->i915 = i915;
|
||||
|
||||
spin_lock_init(&ctx->stale.lock);
|
||||
INIT_LIST_HEAD(&ctx->stale.engines);
|
||||
|
||||
i915_gem_context_set_persistence(ctx);
|
||||
|
||||
mutex_init(&ctx->engines_mutex);
|
||||
|
402
drivers/gpu/drm/i915/gt/gen7_renderclear.c
Normal file
402
drivers/gpu/drm/i915/gt/gen7_renderclear.c
Normal file
@ -0,0 +1,402 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "gen7_renderclear.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_gpu_commands.h"
|
||||
|
||||
#define MAX_URB_ENTRIES 64
|
||||
#define STATE_SIZE (4 * 1024)
|
||||
#define GT3_INLINE_DATA_DELAYS 0x1E00
|
||||
#define batch_advance(Y, CS) GEM_BUG_ON((Y)->end != (CS))
|
||||
|
||||
struct cb_kernel {
|
||||
const void *data;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
#define CB_KERNEL(name) { .data = (name), .size = sizeof(name) }
|
||||
|
||||
#include "ivb_clear_kernel.c"
|
||||
static const struct cb_kernel cb_kernel_ivb = CB_KERNEL(ivb_clear_kernel);
|
||||
|
||||
#include "hsw_clear_kernel.c"
|
||||
static const struct cb_kernel cb_kernel_hsw = CB_KERNEL(hsw_clear_kernel);
|
||||
|
||||
struct batch_chunk {
|
||||
struct i915_vma *vma;
|
||||
u32 offset;
|
||||
u32 *start;
|
||||
u32 *end;
|
||||
u32 max_items;
|
||||
};
|
||||
|
||||
struct batch_vals {
|
||||
u32 max_primitives;
|
||||
u32 max_urb_entries;
|
||||
u32 cmd_size;
|
||||
u32 state_size;
|
||||
u32 state_start;
|
||||
u32 batch_size;
|
||||
u32 surface_height;
|
||||
u32 surface_width;
|
||||
u32 scratch_size;
|
||||
u32 max_size;
|
||||
};
|
||||
|
||||
static void
|
||||
batch_get_defaults(struct drm_i915_private *i915, struct batch_vals *bv)
|
||||
{
|
||||
if (IS_HASWELL(i915)) {
|
||||
bv->max_primitives = 280;
|
||||
bv->max_urb_entries = MAX_URB_ENTRIES;
|
||||
bv->surface_height = 16 * 16;
|
||||
bv->surface_width = 32 * 2 * 16;
|
||||
} else {
|
||||
bv->max_primitives = 128;
|
||||
bv->max_urb_entries = MAX_URB_ENTRIES / 2;
|
||||
bv->surface_height = 16 * 8;
|
||||
bv->surface_width = 32 * 16;
|
||||
}
|
||||
bv->cmd_size = bv->max_primitives * 4096;
|
||||
bv->state_size = STATE_SIZE;
|
||||
bv->state_start = bv->cmd_size;
|
||||
bv->batch_size = bv->cmd_size + bv->state_size;
|
||||
bv->scratch_size = bv->surface_height * bv->surface_width;
|
||||
bv->max_size = bv->batch_size + bv->scratch_size;
|
||||
}
|
||||
|
||||
static void batch_init(struct batch_chunk *bc,
|
||||
struct i915_vma *vma,
|
||||
u32 *start, u32 offset, u32 max_bytes)
|
||||
{
|
||||
bc->vma = vma;
|
||||
bc->offset = offset;
|
||||
bc->start = start + bc->offset / sizeof(*bc->start);
|
||||
bc->end = bc->start;
|
||||
bc->max_items = max_bytes / sizeof(*bc->start);
|
||||
}
|
||||
|
||||
static u32 batch_offset(const struct batch_chunk *bc, u32 *cs)
|
||||
{
|
||||
return (cs - bc->start) * sizeof(*bc->start) + bc->offset;
|
||||
}
|
||||
|
||||
static u32 batch_addr(const struct batch_chunk *bc)
|
||||
{
|
||||
return bc->vma->node.start;
|
||||
}
|
||||
|
||||
static void batch_add(struct batch_chunk *bc, const u32 d)
|
||||
{
|
||||
GEM_BUG_ON((bc->end - bc->start) >= bc->max_items);
|
||||
*bc->end++ = d;
|
||||
}
|
||||
|
||||
static u32 *batch_alloc_items(struct batch_chunk *bc, u32 align, u32 items)
|
||||
{
|
||||
u32 *map;
|
||||
|
||||
if (align) {
|
||||
u32 *end = PTR_ALIGN(bc->end, align);
|
||||
|
||||
memset32(bc->end, 0, end - bc->end);
|
||||
bc->end = end;
|
||||
}
|
||||
|
||||
map = bc->end;
|
||||
bc->end += items;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static u32 *batch_alloc_bytes(struct batch_chunk *bc, u32 align, u32 bytes)
|
||||
{
|
||||
GEM_BUG_ON(!IS_ALIGNED(bytes, sizeof(*bc->start)));
|
||||
return batch_alloc_items(bc, align, bytes / sizeof(*bc->start));
|
||||
}
|
||||
|
||||
static u32
|
||||
gen7_fill_surface_state(struct batch_chunk *state,
|
||||
const u32 dst_offset,
|
||||
const struct batch_vals *bv)
|
||||
{
|
||||
u32 surface_h = bv->surface_height;
|
||||
u32 surface_w = bv->surface_width;
|
||||
u32 *cs = batch_alloc_items(state, 32, 8);
|
||||
u32 offset = batch_offset(state, cs);
|
||||
|
||||
#define SURFACE_2D 1
|
||||
#define SURFACEFORMAT_B8G8R8A8_UNORM 0x0C0
|
||||
#define RENDER_CACHE_READ_WRITE 1
|
||||
|
||||
*cs++ = SURFACE_2D << 29 |
|
||||
(SURFACEFORMAT_B8G8R8A8_UNORM << 18) |
|
||||
(RENDER_CACHE_READ_WRITE << 8);
|
||||
|
||||
*cs++ = batch_addr(state) + dst_offset;
|
||||
|
||||
*cs++ = ((surface_h / 4 - 1) << 16) | (surface_w / 4 - 1);
|
||||
*cs++ = surface_w;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
#define SHADER_CHANNELS(r, g, b, a) \
|
||||
(((r) << 25) | ((g) << 22) | ((b) << 19) | ((a) << 16))
|
||||
*cs++ = SHADER_CHANNELS(4, 5, 6, 7);
|
||||
batch_advance(state, cs);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static u32
|
||||
gen7_fill_binding_table(struct batch_chunk *state,
|
||||
const struct batch_vals *bv)
|
||||
{
|
||||
u32 surface_start = gen7_fill_surface_state(state, bv->batch_size, bv);
|
||||
u32 *cs = batch_alloc_items(state, 32, 8);
|
||||
u32 offset = batch_offset(state, cs);
|
||||
|
||||
*cs++ = surface_start - state->offset;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
batch_advance(state, cs);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static u32
|
||||
gen7_fill_kernel_data(struct batch_chunk *state,
|
||||
const u32 *data,
|
||||
const u32 size)
|
||||
{
|
||||
return batch_offset(state,
|
||||
memcpy(batch_alloc_bytes(state, 64, size),
|
||||
data, size));
|
||||
}
|
||||
|
||||
static u32
|
||||
gen7_fill_interface_descriptor(struct batch_chunk *state,
|
||||
const struct batch_vals *bv,
|
||||
const struct cb_kernel *kernel,
|
||||
unsigned int count)
|
||||
{
|
||||
u32 kernel_offset =
|
||||
gen7_fill_kernel_data(state, kernel->data, kernel->size);
|
||||
u32 binding_table = gen7_fill_binding_table(state, bv);
|
||||
u32 *cs = batch_alloc_items(state, 32, 8 * count);
|
||||
u32 offset = batch_offset(state, cs);
|
||||
|
||||
*cs++ = kernel_offset;
|
||||
*cs++ = (1 << 7) | (1 << 13);
|
||||
*cs++ = 0;
|
||||
*cs++ = (binding_table - state->offset) | 1;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
|
||||
/* 1 - 63dummy idds */
|
||||
memset32(cs, 0x00, (count - 1) * 8);
|
||||
batch_advance(state, cs + (count - 1) * 8);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void
|
||||
gen7_emit_state_base_address(struct batch_chunk *batch,
|
||||
u32 surface_state_base)
|
||||
{
|
||||
u32 *cs = batch_alloc_items(batch, 0, 12);
|
||||
|
||||
*cs++ = STATE_BASE_ADDRESS | (12 - 2);
|
||||
/* general */
|
||||
*cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY;
|
||||
/* surface */
|
||||
*cs++ = batch_addr(batch) | surface_state_base | BASE_ADDRESS_MODIFY;
|
||||
/* dynamic */
|
||||
*cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY;
|
||||
/* indirect */
|
||||
*cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY;
|
||||
/* instruction */
|
||||
*cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY;
|
||||
|
||||
/* general/dynamic/indirect/instruction access Bound */
|
||||
*cs++ = 0;
|
||||
*cs++ = BASE_ADDRESS_MODIFY;
|
||||
*cs++ = 0;
|
||||
*cs++ = BASE_ADDRESS_MODIFY;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
batch_advance(batch, cs);
|
||||
}
|
||||
|
||||
static void
|
||||
gen7_emit_vfe_state(struct batch_chunk *batch,
|
||||
const struct batch_vals *bv,
|
||||
u32 urb_size, u32 curbe_size,
|
||||
u32 mode)
|
||||
{
|
||||
u32 urb_entries = bv->max_urb_entries;
|
||||
u32 threads = bv->max_primitives - 1;
|
||||
u32 *cs = batch_alloc_items(batch, 32, 8);
|
||||
|
||||
*cs++ = MEDIA_VFE_STATE | (8 - 2);
|
||||
|
||||
/* scratch buffer */
|
||||
*cs++ = 0;
|
||||
|
||||
/* number of threads & urb entries for GPGPU vs Media Mode */
|
||||
*cs++ = threads << 16 | urb_entries << 8 | mode << 2;
|
||||
|
||||
*cs++ = 0;
|
||||
|
||||
/* urb entry size & curbe size in 256 bits unit */
|
||||
*cs++ = urb_size << 16 | curbe_size;
|
||||
|
||||
/* scoreboard */
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
batch_advance(batch, cs);
|
||||
}
|
||||
|
||||
static void
|
||||
gen7_emit_interface_descriptor_load(struct batch_chunk *batch,
|
||||
const u32 interface_descriptor,
|
||||
unsigned int count)
|
||||
{
|
||||
u32 *cs = batch_alloc_items(batch, 8, 4);
|
||||
|
||||
*cs++ = MEDIA_INTERFACE_DESCRIPTOR_LOAD | (4 - 2);
|
||||
*cs++ = 0;
|
||||
*cs++ = count * 8 * sizeof(*cs);
|
||||
|
||||
/*
|
||||
* interface descriptor address - it is relative to the dynamics base
|
||||
* address
|
||||
*/
|
||||
*cs++ = interface_descriptor;
|
||||
batch_advance(batch, cs);
|
||||
}
|
||||
|
||||
static void
|
||||
gen7_emit_media_object(struct batch_chunk *batch,
|
||||
unsigned int media_object_index)
|
||||
{
|
||||
unsigned int x_offset = (media_object_index % 16) * 64;
|
||||
unsigned int y_offset = (media_object_index / 16) * 16;
|
||||
unsigned int inline_data_size;
|
||||
unsigned int media_batch_size;
|
||||
unsigned int i;
|
||||
u32 *cs;
|
||||
|
||||
inline_data_size = 112 * 8;
|
||||
media_batch_size = inline_data_size + 6;
|
||||
|
||||
cs = batch_alloc_items(batch, 8, media_batch_size);
|
||||
|
||||
*cs++ = MEDIA_OBJECT | (media_batch_size - 2);
|
||||
|
||||
/* interface descriptor offset */
|
||||
*cs++ = 0;
|
||||
|
||||
/* without indirect data */
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
|
||||
/* scoreboard */
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
|
||||
/* inline */
|
||||
*cs++ = (y_offset << 16) | (x_offset);
|
||||
*cs++ = 0;
|
||||
*cs++ = GT3_INLINE_DATA_DELAYS;
|
||||
for (i = 3; i < inline_data_size; i++)
|
||||
*cs++ = 0;
|
||||
|
||||
batch_advance(batch, cs);
|
||||
}
|
||||
|
||||
static void gen7_emit_pipeline_flush(struct batch_chunk *batch)
|
||||
{
|
||||
u32 *cs = batch_alloc_items(batch, 0, 5);
|
||||
|
||||
*cs++ = GFX_OP_PIPE_CONTROL(5);
|
||||
*cs++ = PIPE_CONTROL_STATE_CACHE_INVALIDATE |
|
||||
PIPE_CONTROL_GLOBAL_GTT_IVB;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
*cs++ = 0;
|
||||
batch_advance(batch, cs);
|
||||
}
|
||||
|
||||
static void emit_batch(struct i915_vma * const vma,
|
||||
u32 *start,
|
||||
const struct batch_vals *bv)
|
||||
{
|
||||
struct drm_i915_private *i915 = vma->vm->i915;
|
||||
unsigned int desc_count = 64;
|
||||
const u32 urb_size = 112;
|
||||
struct batch_chunk cmds, state;
|
||||
u32 interface_descriptor;
|
||||
unsigned int i;
|
||||
|
||||
batch_init(&cmds, vma, start, 0, bv->cmd_size);
|
||||
batch_init(&state, vma, start, bv->state_start, bv->state_size);
|
||||
|
||||
interface_descriptor =
|
||||
gen7_fill_interface_descriptor(&state, bv,
|
||||
IS_HASWELL(i915) ?
|
||||
&cb_kernel_hsw :
|
||||
&cb_kernel_ivb,
|
||||
desc_count);
|
||||
gen7_emit_pipeline_flush(&cmds);
|
||||
batch_add(&cmds, PIPELINE_SELECT | PIPELINE_SELECT_MEDIA);
|
||||
batch_add(&cmds, MI_NOOP);
|
||||
gen7_emit_state_base_address(&cmds, interface_descriptor);
|
||||
gen7_emit_pipeline_flush(&cmds);
|
||||
|
||||
gen7_emit_vfe_state(&cmds, bv, urb_size - 1, 0, 0);
|
||||
|
||||
gen7_emit_interface_descriptor_load(&cmds,
|
||||
interface_descriptor,
|
||||
desc_count);
|
||||
|
||||
for (i = 0; i < bv->max_primitives; i++)
|
||||
gen7_emit_media_object(&cmds, i);
|
||||
|
||||
batch_add(&cmds, MI_BATCH_BUFFER_END);
|
||||
}
|
||||
|
||||
int gen7_setup_clear_gpr_bb(struct intel_engine_cs * const engine,
|
||||
struct i915_vma * const vma)
|
||||
{
|
||||
struct batch_vals bv;
|
||||
u32 *batch;
|
||||
|
||||
batch_get_defaults(engine->i915, &bv);
|
||||
if (!vma)
|
||||
return bv.max_size;
|
||||
|
||||
GEM_BUG_ON(vma->obj->base.size < bv.max_size);
|
||||
|
||||
batch = i915_gem_object_pin_map(vma->obj, I915_MAP_WC);
|
||||
if (IS_ERR(batch))
|
||||
return PTR_ERR(batch);
|
||||
|
||||
emit_batch(vma, memset(batch, 0, bv.max_size), &bv);
|
||||
|
||||
i915_gem_object_flush_map(vma->obj);
|
||||
i915_gem_object_unpin_map(vma->obj);
|
||||
|
||||
return 0;
|
||||
}
|
15
drivers/gpu/drm/i915/gt/gen7_renderclear.h
Normal file
15
drivers/gpu/drm/i915/gt/gen7_renderclear.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __GEN7_RENDERCLEAR_H__
|
||||
#define __GEN7_RENDERCLEAR_H__
|
||||
|
||||
struct intel_engine_cs;
|
||||
struct i915_vma;
|
||||
|
||||
int gen7_setup_clear_gpr_bb(struct intel_engine_cs * const engine,
|
||||
struct i915_vma * const vma);
|
||||
|
||||
#endif /* __GEN7_RENDERCLEAR_H__ */
|
@ -8,6 +8,7 @@
|
||||
#include "gen8_ppgtt.h"
|
||||
#include "i915_scatterlist.h"
|
||||
#include "i915_trace.h"
|
||||
#include "i915_pvinfo.h"
|
||||
#include "i915_vgpu.h"
|
||||
#include "intel_gt.h"
|
||||
#include "intel_gtt.h"
|
||||
@ -25,6 +26,30 @@ static u64 gen8_pde_encode(const dma_addr_t addr,
|
||||
return pde;
|
||||
}
|
||||
|
||||
static u64 gen8_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
gen8_pte_t pte = addr | _PAGE_PRESENT | _PAGE_RW;
|
||||
|
||||
if (unlikely(flags & PTE_READ_ONLY))
|
||||
pte &= ~_PAGE_RW;
|
||||
|
||||
switch (level) {
|
||||
case I915_CACHE_NONE:
|
||||
pte |= PPAT_UNCACHED;
|
||||
break;
|
||||
case I915_CACHE_WT:
|
||||
pte |= PPAT_DISPLAY_ELLC;
|
||||
break;
|
||||
default:
|
||||
pte |= PPAT_CACHED;
|
||||
break;
|
||||
}
|
||||
|
||||
return pte;
|
||||
}
|
||||
|
||||
static void gen8_ppgtt_notify_vgt(struct i915_ppgtt *ppgtt, bool create)
|
||||
{
|
||||
struct drm_i915_private *i915 = ppgtt->vm.i915;
|
||||
@ -706,6 +731,8 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt)
|
||||
ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
|
||||
ppgtt->vm.clear_range = gen8_ppgtt_clear;
|
||||
|
||||
ppgtt->vm.pte_encode = gen8_pte_encode;
|
||||
|
||||
if (intel_vgpu_active(gt->i915))
|
||||
gen8_ppgtt_notify_vgt(ppgtt, true);
|
||||
|
||||
|
61
drivers/gpu/drm/i915/gt/hsw_clear_kernel.c
Normal file
61
drivers/gpu/drm/i915/gt/hsw_clear_kernel.c
Normal file
@ -0,0 +1,61 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2020 Intel Corporation
|
||||
*
|
||||
* Generated by: IGT Gpu Tools on Fri 21 Feb 2020 05:30:13 AM UTC
|
||||
*/
|
||||
|
||||
static const u32 hsw_clear_kernel[] = {
|
||||
0x00000001, 0x26020128, 0x00000024, 0x00000000,
|
||||
0x00000040, 0x20280c21, 0x00000028, 0x00000001,
|
||||
0x01000010, 0x20000c20, 0x0000002c, 0x00000000,
|
||||
0x00010220, 0x34001c00, 0x00001400, 0x00000160,
|
||||
0x00600001, 0x20600061, 0x00000000, 0x00000000,
|
||||
0x00000008, 0x20601c85, 0x00000e00, 0x0000000c,
|
||||
0x00000005, 0x20601ca5, 0x00000060, 0x00000001,
|
||||
0x00000008, 0x20641c85, 0x00000e00, 0x0000000d,
|
||||
0x00000005, 0x20641ca5, 0x00000064, 0x00000003,
|
||||
0x00000041, 0x207424a5, 0x00000064, 0x00000034,
|
||||
0x00000040, 0x206014a5, 0x00000060, 0x00000074,
|
||||
0x00000008, 0x20681c85, 0x00000e00, 0x00000008,
|
||||
0x00000005, 0x20681ca5, 0x00000068, 0x0000000f,
|
||||
0x00000041, 0x20701ca5, 0x00000060, 0x00000010,
|
||||
0x00000040, 0x206814a5, 0x00000068, 0x00000070,
|
||||
0x00600001, 0x20a00061, 0x00000000, 0x00000000,
|
||||
0x00000005, 0x206c1c85, 0x00000e00, 0x00000007,
|
||||
0x00000041, 0x206c1ca5, 0x0000006c, 0x00000004,
|
||||
0x00600001, 0x20800021, 0x008d0000, 0x00000000,
|
||||
0x00000001, 0x20800021, 0x0000006c, 0x00000000,
|
||||
0x00000001, 0x20840021, 0x00000068, 0x00000000,
|
||||
0x00000001, 0x20880061, 0x00000000, 0x00000003,
|
||||
0x00000005, 0x208c0d21, 0x00000086, 0xffffffff,
|
||||
0x05600032, 0x20a00fa1, 0x008d0080, 0x02190001,
|
||||
0x00000040, 0x20a01ca5, 0x000000a0, 0x00000001,
|
||||
0x05600032, 0x20a00fa1, 0x008d0080, 0x040a8001,
|
||||
0x02000040, 0x20281c21, 0x00000028, 0xffffffff,
|
||||
0x00010220, 0x34001c00, 0x00001400, 0xffffffe0,
|
||||
0x00000001, 0x26020128, 0x00000024, 0x00000000,
|
||||
0x00000001, 0x220010e4, 0x00000000, 0x00000000,
|
||||
0x00000001, 0x220831ec, 0x00000000, 0x007f007f,
|
||||
0x00600001, 0x20400021, 0x008d0000, 0x00000000,
|
||||
0x00600001, 0x2fe00021, 0x008d0000, 0x00000000,
|
||||
0x00200001, 0x20400121, 0x00450020, 0x00000000,
|
||||
0x00000001, 0x20480061, 0x00000000, 0x000f000f,
|
||||
0x00000005, 0x204c0d21, 0x00000046, 0xffffffef,
|
||||
0x00800001, 0x20600061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x20800061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x20a00061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x20c00061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x20e00061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x21000061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x21200061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x21400061, 0x00000000, 0x00000000,
|
||||
0x05600032, 0x20000fa0, 0x008d0040, 0x120a8000,
|
||||
0x00000040, 0x20402d21, 0x00000020, 0x00100010,
|
||||
0x05600032, 0x20000fa0, 0x008d0040, 0x120a8000,
|
||||
0x02000040, 0x22083d8c, 0x00000208, 0xffffffff,
|
||||
0x00800001, 0xa0000109, 0x00000602, 0x00000000,
|
||||
0x00000040, 0x22001c84, 0x00000200, 0x00000020,
|
||||
0x00010220, 0x34001c00, 0x00001400, 0xffffffc0,
|
||||
0x07600032, 0x20000fa0, 0x008d0fe0, 0x82000010,
|
||||
};
|
@ -51,6 +51,11 @@ int intel_context_alloc_state(struct intel_context *ce)
|
||||
return -EINTR;
|
||||
|
||||
if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
|
||||
if (intel_context_is_banned(ce)) {
|
||||
err = -EIO;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = ce->ops->alloc(ce);
|
||||
if (unlikely(err))
|
||||
goto unlock;
|
||||
|
63
drivers/gpu/drm/i915/gt/intel_context_param.c
Normal file
63
drivers/gpu/drm/i915/gt/intel_context_param.c
Normal file
@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_active.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_context_param.h"
|
||||
#include "intel_ring.h"
|
||||
|
||||
int intel_context_set_ring_size(struct intel_context *ce, long sz)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (intel_context_lock_pinned(ce))
|
||||
return -EINTR;
|
||||
|
||||
err = i915_active_wait(&ce->active);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
|
||||
if (intel_context_is_pinned(ce)) {
|
||||
err = -EBUSY; /* In active use, come back later! */
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
|
||||
struct intel_ring *ring;
|
||||
|
||||
/* Replace the existing ringbuffer */
|
||||
ring = intel_engine_create_ring(ce->engine, sz);
|
||||
if (IS_ERR(ring)) {
|
||||
err = PTR_ERR(ring);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
intel_ring_put(ce->ring);
|
||||
ce->ring = ring;
|
||||
|
||||
/* Context image will be updated on next pin */
|
||||
} else {
|
||||
ce->ring = __intel_context_ring_size(sz);
|
||||
}
|
||||
|
||||
unlock:
|
||||
intel_context_unlock_pinned(ce);
|
||||
return err;
|
||||
}
|
||||
|
||||
long intel_context_get_ring_size(struct intel_context *ce)
|
||||
{
|
||||
long sz = (unsigned long)READ_ONCE(ce->ring);
|
||||
|
||||
if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
|
||||
if (intel_context_lock_pinned(ce))
|
||||
return -EINTR;
|
||||
|
||||
sz = ce->ring->size;
|
||||
intel_context_unlock_pinned(ce);
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
14
drivers/gpu/drm/i915/gt/intel_context_param.h
Normal file
14
drivers/gpu/drm/i915/gt/intel_context_param.h
Normal file
@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef INTEL_CONTEXT_PARAM_H
|
||||
#define INTEL_CONTEXT_PARAM_H
|
||||
|
||||
struct intel_context;
|
||||
|
||||
int intel_context_set_ring_size(struct intel_context *ce, long sz);
|
||||
long intel_context_get_ring_size(struct intel_context *ce);
|
||||
|
||||
#endif /* INTEL_CONTEXT_PARAM_H */
|
@ -45,8 +45,8 @@ struct intel_context {
|
||||
|
||||
struct intel_engine_cs *engine;
|
||||
struct intel_engine_cs *inflight;
|
||||
#define intel_context_inflight(ce) ptr_mask_bits((ce)->inflight, 2)
|
||||
#define intel_context_inflight_count(ce) ptr_unmask_bits((ce)->inflight, 2)
|
||||
#define intel_context_inflight(ce) ptr_mask_bits(READ_ONCE((ce)->inflight), 2)
|
||||
#define intel_context_inflight_count(ce) ptr_unmask_bits(READ_ONCE((ce)->inflight), 2)
|
||||
|
||||
struct i915_address_space *vm;
|
||||
struct i915_gem_context __rcu *gem_context;
|
||||
|
@ -107,7 +107,20 @@ execlists_num_ports(const struct intel_engine_execlists * const execlists)
|
||||
static inline struct i915_request *
|
||||
execlists_active(const struct intel_engine_execlists *execlists)
|
||||
{
|
||||
return *READ_ONCE(execlists->active);
|
||||
struct i915_request * const *cur, * const *old, *active;
|
||||
|
||||
cur = READ_ONCE(execlists->active);
|
||||
smp_rmb(); /* pairs with overwrite protection in process_csb() */
|
||||
do {
|
||||
old = cur;
|
||||
|
||||
active = READ_ONCE(*cur);
|
||||
cur = READ_ONCE(execlists->active);
|
||||
|
||||
smp_rmb(); /* and complete the seqlock retry */
|
||||
} while (unlikely(cur != old));
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -275,6 +275,7 @@ static void intel_engine_sanitize_mmio(struct intel_engine_cs *engine)
|
||||
static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
|
||||
{
|
||||
const struct engine_info *info = &intel_engines[id];
|
||||
struct drm_i915_private *i915 = gt->i915;
|
||||
struct intel_engine_cs *engine;
|
||||
|
||||
BUILD_BUG_ON(MAX_ENGINE_CLASS >= BIT(GEN11_ENGINE_CLASS_WIDTH));
|
||||
@ -301,11 +302,11 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
|
||||
engine->id = id;
|
||||
engine->legacy_idx = INVALID_ENGINE;
|
||||
engine->mask = BIT(id);
|
||||
engine->i915 = gt->i915;
|
||||
engine->i915 = i915;
|
||||
engine->gt = gt;
|
||||
engine->uncore = gt->uncore;
|
||||
engine->hw_id = engine->guc_id = info->hw_id;
|
||||
engine->mmio_base = __engine_mmio_base(gt->i915, info->mmio_bases);
|
||||
engine->mmio_base = __engine_mmio_base(i915, info->mmio_bases);
|
||||
|
||||
engine->class = info->class;
|
||||
engine->instance = info->instance;
|
||||
@ -313,6 +314,8 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
|
||||
|
||||
engine->props.heartbeat_interval_ms =
|
||||
CONFIG_DRM_I915_HEARTBEAT_INTERVAL;
|
||||
engine->props.max_busywait_duration_ns =
|
||||
CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT;
|
||||
engine->props.preempt_timeout_ms =
|
||||
CONFIG_DRM_I915_PREEMPT_TIMEOUT;
|
||||
engine->props.stop_timeout_ms =
|
||||
@ -320,11 +323,15 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
|
||||
engine->props.timeslice_duration_ms =
|
||||
CONFIG_DRM_I915_TIMESLICE_DURATION;
|
||||
|
||||
/* Override to uninterruptible for OpenCL workloads. */
|
||||
if (INTEL_GEN(i915) == 12 && engine->class == RENDER_CLASS)
|
||||
engine->props.preempt_timeout_ms = 0;
|
||||
|
||||
engine->context_size = intel_engine_context_size(gt, engine->class);
|
||||
if (WARN_ON(engine->context_size > BIT(20)))
|
||||
engine->context_size = 0;
|
||||
if (engine->context_size)
|
||||
DRIVER_CAPS(gt->i915)->has_logical_contexts = true;
|
||||
DRIVER_CAPS(i915)->has_logical_contexts = true;
|
||||
|
||||
/* Nothing to do here, execute in order of dependencies */
|
||||
engine->schedule = NULL;
|
||||
@ -340,7 +347,7 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
|
||||
gt->engine_class[info->class][info->instance] = engine;
|
||||
gt->engine[id] = engine;
|
||||
|
||||
gt->i915->engine[id] = engine;
|
||||
i915->engine[id] = engine;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1379,24 +1386,24 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
|
||||
char hdr[160];
|
||||
int len;
|
||||
|
||||
len = snprintf(hdr, sizeof(hdr),
|
||||
"\t\tActive[%d]: ",
|
||||
(int)(port - execlists->active));
|
||||
len = scnprintf(hdr, sizeof(hdr),
|
||||
"\t\tActive[%d]: ",
|
||||
(int)(port - execlists->active));
|
||||
if (!i915_request_signaled(rq)) {
|
||||
struct intel_timeline *tl = get_timeline(rq);
|
||||
|
||||
len += snprintf(hdr + len, sizeof(hdr) - len,
|
||||
"ring:{start:%08x, hwsp:%08x, seqno:%08x, runtime:%llums}, ",
|
||||
i915_ggtt_offset(rq->ring->vma),
|
||||
tl ? tl->hwsp_offset : 0,
|
||||
hwsp_seqno(rq),
|
||||
DIV_ROUND_CLOSEST_ULL(intel_context_get_total_runtime_ns(rq->context),
|
||||
1000 * 1000));
|
||||
len += scnprintf(hdr + len, sizeof(hdr) - len,
|
||||
"ring:{start:%08x, hwsp:%08x, seqno:%08x, runtime:%llums}, ",
|
||||
i915_ggtt_offset(rq->ring->vma),
|
||||
tl ? tl->hwsp_offset : 0,
|
||||
hwsp_seqno(rq),
|
||||
DIV_ROUND_CLOSEST_ULL(intel_context_get_total_runtime_ns(rq->context),
|
||||
1000 * 1000));
|
||||
|
||||
if (tl)
|
||||
intel_timeline_put(tl);
|
||||
}
|
||||
snprintf(hdr + len, sizeof(hdr) - len, "rq: ");
|
||||
scnprintf(hdr + len, sizeof(hdr) - len, "rq: ");
|
||||
print_request(m, rq, hdr);
|
||||
}
|
||||
for (port = execlists->pending; (rq = *port); port++) {
|
||||
|
@ -547,6 +547,7 @@ struct intel_engine_cs {
|
||||
|
||||
struct {
|
||||
unsigned long heartbeat_interval_ms;
|
||||
unsigned long max_busywait_duration_ns;
|
||||
unsigned long preempt_timeout_ms;
|
||||
unsigned long stop_timeout_ms;
|
||||
unsigned long timeslice_duration_ms;
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <asm/set_memory.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "intel_gt.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_scatterlist.h"
|
||||
@ -157,6 +159,13 @@ static void gmch_ggtt_invalidate(struct i915_ggtt *ggtt)
|
||||
intel_gtt_chipset_flush();
|
||||
}
|
||||
|
||||
static u64 gen8_ggtt_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
return addr | _PAGE_PRESENT;
|
||||
}
|
||||
|
||||
static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
|
||||
{
|
||||
writeq(pte, addr);
|
||||
@ -172,7 +181,7 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm,
|
||||
gen8_pte_t __iomem *pte =
|
||||
(gen8_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE;
|
||||
|
||||
gen8_set_pte(pte, gen8_pte_encode(addr, level, 0));
|
||||
gen8_set_pte(pte, gen8_ggtt_pte_encode(addr, level, 0));
|
||||
|
||||
ggtt->invalidate(ggtt);
|
||||
}
|
||||
@ -185,7 +194,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
|
||||
struct sgt_iter sgt_iter;
|
||||
gen8_pte_t __iomem *gtt_entries;
|
||||
const gen8_pte_t pte_encode = gen8_pte_encode(0, level, 0);
|
||||
const gen8_pte_t pte_encode = gen8_ggtt_pte_encode(0, level, 0);
|
||||
dma_addr_t addr;
|
||||
|
||||
/*
|
||||
@ -857,7 +866,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
|
||||
ggtt->vm.vma_ops.set_pages = ggtt_set_pages;
|
||||
ggtt->vm.vma_ops.clear_pages = clear_pages;
|
||||
|
||||
ggtt->vm.pte_encode = gen8_pte_encode;
|
||||
ggtt->vm.pte_encode = gen8_ggtt_pte_encode;
|
||||
|
||||
setup_private_pat(ggtt->vm.gt->uncore);
|
||||
|
||||
|
@ -292,10 +292,21 @@
|
||||
#define MI_STORE_URB_MEM MI_INSTR(0x2D, 0)
|
||||
#define MI_CONDITIONAL_BATCH_BUFFER_END MI_INSTR(0x36, 0)
|
||||
|
||||
#define PIPELINE_SELECT ((0x3<<29)|(0x1<<27)|(0x1<<24)|(0x4<<16))
|
||||
#define GFX_OP_3DSTATE_VF_STATISTICS ((0x3<<29)|(0x1<<27)|(0x0<<24)|(0xB<<16))
|
||||
#define MEDIA_VFE_STATE ((0x3<<29)|(0x2<<27)|(0x0<<24)|(0x0<<16))
|
||||
#define STATE_BASE_ADDRESS \
|
||||
((0x3 << 29) | (0x0 << 27) | (0x1 << 24) | (0x1 << 16))
|
||||
#define BASE_ADDRESS_MODIFY REG_BIT(0)
|
||||
#define PIPELINE_SELECT \
|
||||
((0x3 << 29) | (0x1 << 27) | (0x1 << 24) | (0x4 << 16))
|
||||
#define PIPELINE_SELECT_MEDIA REG_BIT(0)
|
||||
#define GFX_OP_3DSTATE_VF_STATISTICS \
|
||||
((0x3 << 29) | (0x1 << 27) | (0x0 << 24) | (0xB << 16))
|
||||
#define MEDIA_VFE_STATE \
|
||||
((0x3 << 29) | (0x2 << 27) | (0x0 << 24) | (0x0 << 16))
|
||||
#define MEDIA_VFE_STATE_MMIO_ACCESS_MASK (0x18)
|
||||
#define MEDIA_INTERFACE_DESCRIPTOR_LOAD \
|
||||
((0x3 << 29) | (0x2 << 27) | (0x0 << 24) | (0x2 << 16))
|
||||
#define MEDIA_OBJECT \
|
||||
((0x3 << 29) | (0x2 << 27) | (0x1 << 24) | (0x0 << 16))
|
||||
#define GPGPU_OBJECT ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
|
||||
#define GPGPU_WALKER ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
|
||||
#define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \
|
||||
|
@ -667,6 +667,9 @@ void intel_gt_driver_release(struct intel_gt *gt)
|
||||
|
||||
void intel_gt_driver_late_release(struct intel_gt *gt)
|
||||
{
|
||||
/* We need to wait for inflight RCU frees to release their grip */
|
||||
rcu_barrier();
|
||||
|
||||
intel_uc_driver_late_release(>->uc);
|
||||
intel_gt_fini_requests(gt);
|
||||
intel_gt_fini_reset(gt);
|
||||
|
@ -171,7 +171,9 @@ void __i915_vm_close(struct i915_address_space *vm)
|
||||
{
|
||||
struct i915_vma *vma, *vn;
|
||||
|
||||
mutex_lock(&vm->mutex);
|
||||
if (!atomic_dec_and_mutex_lock(&vm->open, &vm->mutex))
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(vma, vn, &vm->bound_list, vm_link) {
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
|
||||
@ -186,6 +188,7 @@ void __i915_vm_close(struct i915_address_space *vm)
|
||||
i915_gem_object_put(obj);
|
||||
}
|
||||
GEM_BUG_ON(!list_empty(&vm->bound_list));
|
||||
|
||||
mutex_unlock(&vm->mutex);
|
||||
}
|
||||
|
||||
@ -484,30 +487,6 @@ void gtt_write_workarounds(struct intel_gt *gt)
|
||||
}
|
||||
}
|
||||
|
||||
u64 gen8_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
gen8_pte_t pte = addr | _PAGE_PRESENT | _PAGE_RW;
|
||||
|
||||
if (unlikely(flags & PTE_READ_ONLY))
|
||||
pte &= ~_PAGE_RW;
|
||||
|
||||
switch (level) {
|
||||
case I915_CACHE_NONE:
|
||||
pte |= PPAT_UNCACHED;
|
||||
break;
|
||||
case I915_CACHE_WT:
|
||||
pte |= PPAT_DISPLAY_ELLC;
|
||||
break;
|
||||
default:
|
||||
pte |= PPAT_CACHED;
|
||||
break;
|
||||
}
|
||||
|
||||
return pte;
|
||||
}
|
||||
|
||||
static void tgl_setup_private_ppat(struct intel_uncore *uncore)
|
||||
{
|
||||
/* TGL doesn't support LLC or AGE settings */
|
||||
|
@ -429,8 +429,7 @@ static inline void
|
||||
i915_vm_close(struct i915_address_space *vm)
|
||||
{
|
||||
GEM_BUG_ON(!atomic_read(&vm->open));
|
||||
if (atomic_dec_and_test(&vm->open))
|
||||
__i915_vm_close(vm);
|
||||
__i915_vm_close(vm);
|
||||
|
||||
i915_vm_put(vm);
|
||||
}
|
||||
@ -515,10 +514,6 @@ struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt);
|
||||
void i915_ggtt_suspend(struct i915_ggtt *gtt);
|
||||
void i915_ggtt_resume(struct i915_ggtt *ggtt);
|
||||
|
||||
u64 gen8_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags);
|
||||
|
||||
int setup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p);
|
||||
void cleanup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p);
|
||||
|
||||
|
@ -245,7 +245,7 @@ static void mark_eio(struct i915_request *rq)
|
||||
|
||||
GEM_BUG_ON(i915_request_signaled(rq));
|
||||
|
||||
dma_fence_set_error(&rq->fence, -EIO);
|
||||
i915_request_set_error_once(rq, -EIO);
|
||||
i915_request_mark_complete(rq);
|
||||
}
|
||||
|
||||
@ -293,7 +293,7 @@ static inline struct i915_priolist *to_priolist(struct rb_node *rb)
|
||||
|
||||
static inline int rq_prio(const struct i915_request *rq)
|
||||
{
|
||||
return rq->sched.attr.priority;
|
||||
return READ_ONCE(rq->sched.attr.priority);
|
||||
}
|
||||
|
||||
static int effective_prio(const struct i915_request *rq)
|
||||
@ -1004,7 +1004,7 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
|
||||
i915_request_cancel_breadcrumb(rq);
|
||||
spin_unlock(&rq->lock);
|
||||
}
|
||||
rq->engine = owner;
|
||||
WRITE_ONCE(rq->engine, owner);
|
||||
owner->submit_request(rq);
|
||||
active = NULL;
|
||||
}
|
||||
@ -1316,7 +1316,7 @@ __execlists_schedule_out(struct i915_request *rq,
|
||||
* If we have just completed this context, the engine may now be
|
||||
* idle and we want to re-enter powersaving.
|
||||
*/
|
||||
if (list_is_last(&rq->link, &ce->timeline->requests) &&
|
||||
if (list_is_last_rcu(&rq->link, &ce->timeline->requests) &&
|
||||
i915_request_completed(rq))
|
||||
intel_engine_add_retire(engine, ce->timeline);
|
||||
|
||||
@ -1448,6 +1448,7 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
|
||||
{
|
||||
struct i915_request * const *port, *rq;
|
||||
struct intel_context *ce = NULL;
|
||||
bool sentinel = false;
|
||||
|
||||
trace_ports(execlists, msg, execlists->pending);
|
||||
|
||||
@ -1481,6 +1482,26 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
|
||||
}
|
||||
ce = rq->context;
|
||||
|
||||
/*
|
||||
* Sentinels are supposed to be lonely so they flush the
|
||||
* current exection off the HW. Check that they are the
|
||||
* only request in the pending submission.
|
||||
*/
|
||||
if (sentinel) {
|
||||
GEM_TRACE_ERR("context:%llx after sentinel in pending[%zd]\n",
|
||||
ce->timeline->fence_context,
|
||||
port - execlists->pending);
|
||||
return false;
|
||||
}
|
||||
|
||||
sentinel = i915_request_has_sentinel(rq);
|
||||
if (sentinel && port != execlists->pending) {
|
||||
GEM_TRACE_ERR("sentinel context:%llx not in prime position[%zd]\n",
|
||||
ce->timeline->fence_context,
|
||||
port - execlists->pending);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Hold tightly onto the lock to prevent concurrent retires! */
|
||||
if (!spin_trylock_irqsave(&rq->lock, flags))
|
||||
continue;
|
||||
@ -1576,6 +1597,11 @@ static bool can_merge_ctx(const struct intel_context *prev,
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned long i915_request_flags(const struct i915_request *rq)
|
||||
{
|
||||
return READ_ONCE(rq->fence.flags);
|
||||
}
|
||||
|
||||
static bool can_merge_rq(const struct i915_request *prev,
|
||||
const struct i915_request *next)
|
||||
{
|
||||
@ -1593,7 +1619,7 @@ static bool can_merge_rq(const struct i915_request *prev,
|
||||
if (i915_request_completed(next))
|
||||
return true;
|
||||
|
||||
if (unlikely((prev->fence.flags ^ next->fence.flags) &
|
||||
if (unlikely((i915_request_flags(prev) ^ i915_request_flags(next)) &
|
||||
(BIT(I915_FENCE_FLAG_NOPREEMPT) |
|
||||
BIT(I915_FENCE_FLAG_SENTINEL))))
|
||||
return false;
|
||||
@ -1601,6 +1627,7 @@ static bool can_merge_rq(const struct i915_request *prev,
|
||||
if (!can_merge_ctx(prev->context, next->context))
|
||||
return false;
|
||||
|
||||
GEM_BUG_ON(i915_seqno_passed(prev->fence.seqno, next->fence.seqno));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1651,17 +1678,6 @@ static void virtual_xfer_breadcrumbs(struct virtual_engine *ve,
|
||||
spin_unlock(&old->breadcrumbs.irq_lock);
|
||||
}
|
||||
|
||||
static struct i915_request *
|
||||
last_active(const struct intel_engine_execlists *execlists)
|
||||
{
|
||||
struct i915_request * const *last = READ_ONCE(execlists->active);
|
||||
|
||||
while (*last && i915_request_completed(*last))
|
||||
last++;
|
||||
|
||||
return *last;
|
||||
}
|
||||
|
||||
#define for_each_waiter(p__, rq__) \
|
||||
list_for_each_entry_lockless(p__, \
|
||||
&(rq__)->sched.waiters_list, \
|
||||
@ -1735,11 +1751,9 @@ need_timeslice(struct intel_engine_cs *engine, const struct i915_request *rq)
|
||||
if (!intel_engine_has_timeslices(engine))
|
||||
return false;
|
||||
|
||||
if (list_is_last(&rq->sched.link, &engine->active.requests))
|
||||
return false;
|
||||
|
||||
hint = max(rq_prio(list_next_entry(rq, sched.link)),
|
||||
engine->execlists.queue_priority_hint);
|
||||
hint = engine->execlists.queue_priority_hint;
|
||||
if (!list_is_last(&rq->sched.link, &engine->active.requests))
|
||||
hint = max(hint, rq_prio(list_next_entry(rq, sched.link)));
|
||||
|
||||
return hint >= effective_prio(rq);
|
||||
}
|
||||
@ -1762,12 +1776,13 @@ timeslice(const struct intel_engine_cs *engine)
|
||||
static unsigned long
|
||||
active_timeslice(const struct intel_engine_cs *engine)
|
||||
{
|
||||
const struct i915_request *rq = *engine->execlists.active;
|
||||
const struct intel_engine_execlists *execlists = &engine->execlists;
|
||||
const struct i915_request *rq = *execlists->active;
|
||||
|
||||
if (!rq || i915_request_completed(rq))
|
||||
return 0;
|
||||
|
||||
if (engine->execlists.switch_priority_hint < effective_prio(rq))
|
||||
if (READ_ONCE(execlists->switch_priority_hint) < effective_prio(rq))
|
||||
return 0;
|
||||
|
||||
return timeslice(engine);
|
||||
@ -1781,16 +1796,29 @@ static void set_timeslice(struct intel_engine_cs *engine)
|
||||
set_timer_ms(&engine->execlists.timer, active_timeslice(engine));
|
||||
}
|
||||
|
||||
static void start_timeslice(struct intel_engine_cs *engine)
|
||||
{
|
||||
struct intel_engine_execlists *execlists = &engine->execlists;
|
||||
int prio = queue_prio(execlists);
|
||||
|
||||
WRITE_ONCE(execlists->switch_priority_hint, prio);
|
||||
if (prio == INT_MIN)
|
||||
return;
|
||||
|
||||
if (timer_pending(&execlists->timer))
|
||||
return;
|
||||
|
||||
set_timer_ms(&execlists->timer, timeslice(engine));
|
||||
}
|
||||
|
||||
static void record_preemption(struct intel_engine_execlists *execlists)
|
||||
{
|
||||
(void)I915_SELFTEST_ONLY(execlists->preempt_hang.count++);
|
||||
}
|
||||
|
||||
static unsigned long active_preempt_timeout(struct intel_engine_cs *engine)
|
||||
static unsigned long active_preempt_timeout(struct intel_engine_cs *engine,
|
||||
const struct i915_request *rq)
|
||||
{
|
||||
struct i915_request *rq;
|
||||
|
||||
rq = last_active(&engine->execlists);
|
||||
if (!rq)
|
||||
return 0;
|
||||
|
||||
@ -1801,13 +1829,14 @@ static unsigned long active_preempt_timeout(struct intel_engine_cs *engine)
|
||||
return READ_ONCE(engine->props.preempt_timeout_ms);
|
||||
}
|
||||
|
||||
static void set_preempt_timeout(struct intel_engine_cs *engine)
|
||||
static void set_preempt_timeout(struct intel_engine_cs *engine,
|
||||
const struct i915_request *rq)
|
||||
{
|
||||
if (!intel_engine_has_preempt_reset(engine))
|
||||
return;
|
||||
|
||||
set_timer_ms(&engine->execlists.preempt,
|
||||
active_preempt_timeout(engine));
|
||||
active_preempt_timeout(engine, rq));
|
||||
}
|
||||
|
||||
static inline void clear_ports(struct i915_request **ports, int count)
|
||||
@ -1820,6 +1849,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
||||
struct intel_engine_execlists * const execlists = &engine->execlists;
|
||||
struct i915_request **port = execlists->pending;
|
||||
struct i915_request ** const last_port = port + execlists->port_mask;
|
||||
struct i915_request * const *active;
|
||||
struct i915_request *last;
|
||||
struct rb_node *rb;
|
||||
bool submit = false;
|
||||
@ -1874,7 +1904,10 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
||||
* i.e. we will retrigger preemption following the ack in case
|
||||
* of trouble.
|
||||
*/
|
||||
last = last_active(execlists);
|
||||
active = READ_ONCE(execlists->active);
|
||||
while ((last = *active) && i915_request_completed(last))
|
||||
active++;
|
||||
|
||||
if (last) {
|
||||
if (need_preempt(engine, last, rb)) {
|
||||
ENGINE_TRACE(engine,
|
||||
@ -1944,11 +1977,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
||||
* Even if ELSP[1] is occupied and not worthy
|
||||
* of timeslices, our queue might be.
|
||||
*/
|
||||
if (!execlists->timer.expires &&
|
||||
need_timeslice(engine, last))
|
||||
set_timer_ms(&execlists->timer,
|
||||
timeslice(engine));
|
||||
|
||||
start_timeslice(engine);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1983,7 +2012,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
||||
|
||||
if (last && !can_merge_rq(last, rq)) {
|
||||
spin_unlock(&ve->base.active.lock);
|
||||
return; /* leave this for another */
|
||||
start_timeslice(engine);
|
||||
return; /* leave this for another sibling */
|
||||
}
|
||||
|
||||
ENGINE_TRACE(engine,
|
||||
@ -1995,13 +2025,14 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
||||
"",
|
||||
yesno(engine != ve->siblings[0]));
|
||||
|
||||
ve->request = NULL;
|
||||
ve->base.execlists.queue_priority_hint = INT_MIN;
|
||||
WRITE_ONCE(ve->request, NULL);
|
||||
WRITE_ONCE(ve->base.execlists.queue_priority_hint,
|
||||
INT_MIN);
|
||||
rb_erase_cached(rb, &execlists->virtual);
|
||||
RB_CLEAR_NODE(rb);
|
||||
|
||||
GEM_BUG_ON(!(rq->execution_mask & engine->mask));
|
||||
rq->engine = engine;
|
||||
WRITE_ONCE(rq->engine, engine);
|
||||
|
||||
if (engine != ve->siblings[0]) {
|
||||
u32 *regs = ve->context.lrc_reg_state;
|
||||
@ -2121,6 +2152,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
||||
GEM_BUG_ON(last &&
|
||||
!can_merge_ctx(last->context,
|
||||
rq->context));
|
||||
GEM_BUG_ON(last &&
|
||||
i915_seqno_passed(last->fence.seqno,
|
||||
rq->fence.seqno));
|
||||
|
||||
submit = true;
|
||||
last = rq;
|
||||
@ -2159,7 +2193,7 @@ done:
|
||||
* Skip if we ended up with exactly the same set of requests,
|
||||
* e.g. trying to timeslice a pair of ordered contexts
|
||||
*/
|
||||
if (!memcmp(execlists->active, execlists->pending,
|
||||
if (!memcmp(active, execlists->pending,
|
||||
(port - execlists->pending + 1) * sizeof(*port))) {
|
||||
do
|
||||
execlists_schedule_out(fetch_and_zero(port));
|
||||
@ -2170,7 +2204,7 @@ done:
|
||||
clear_ports(port + 1, last_port - port);
|
||||
|
||||
execlists_submit_ports(engine);
|
||||
set_preempt_timeout(engine);
|
||||
set_preempt_timeout(engine, *active);
|
||||
} else {
|
||||
skip_submit:
|
||||
ring_set_paused(engine, 0);
|
||||
@ -2191,6 +2225,7 @@ cancel_port_requests(struct intel_engine_execlists * const execlists)
|
||||
execlists_schedule_out(*port);
|
||||
clear_ports(execlists->inflight, ARRAY_SIZE(execlists->inflight));
|
||||
|
||||
smp_wmb(); /* complete the seqlock for execlists_active() */
|
||||
WRITE_ONCE(execlists->active, execlists->inflight);
|
||||
}
|
||||
|
||||
@ -2345,6 +2380,7 @@ static void process_csb(struct intel_engine_cs *engine)
|
||||
|
||||
/* Point active to the new ELSP; prevent overwriting */
|
||||
WRITE_ONCE(execlists->active, execlists->pending);
|
||||
smp_wmb(); /* notify execlists_active() */
|
||||
|
||||
/* cancel old inflight, prepare for switch */
|
||||
trace_ports(execlists, "preempted", old);
|
||||
@ -2352,11 +2388,12 @@ static void process_csb(struct intel_engine_cs *engine)
|
||||
execlists_schedule_out(*old++);
|
||||
|
||||
/* switch pending to inflight */
|
||||
WRITE_ONCE(execlists->active,
|
||||
memcpy(execlists->inflight,
|
||||
execlists->pending,
|
||||
execlists_num_ports(execlists) *
|
||||
sizeof(*execlists->pending)));
|
||||
memcpy(execlists->inflight,
|
||||
execlists->pending,
|
||||
execlists_num_ports(execlists) *
|
||||
sizeof(*execlists->pending));
|
||||
smp_wmb(); /* complete the seqlock */
|
||||
WRITE_ONCE(execlists->active, execlists->inflight);
|
||||
|
||||
WRITE_ONCE(execlists->pending[0], NULL);
|
||||
} else {
|
||||
@ -2579,6 +2616,10 @@ static void __execlists_unhold(struct i915_request *rq)
|
||||
struct i915_request *w =
|
||||
container_of(p->waiter, typeof(*w), sched);
|
||||
|
||||
/* Propagate any change in error status */
|
||||
if (rq->fence.error)
|
||||
i915_request_set_error_once(w, rq->fence.error);
|
||||
|
||||
if (w->engine != rq->engine)
|
||||
continue;
|
||||
|
||||
@ -2966,6 +3007,7 @@ __execlists_update_reg_state(const struct intel_context *ce,
|
||||
regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
|
||||
regs[CTX_RING_HEAD] = head;
|
||||
regs[CTX_RING_TAIL] = ring->tail;
|
||||
regs[CTX_RING_CTL] = RING_CTL_SIZE(ring->size) | RING_VALID;
|
||||
|
||||
/* RPCS */
|
||||
if (engine->class == RENDER_CLASS) {
|
||||
@ -3636,9 +3678,6 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
|
||||
if (!rq)
|
||||
goto unwind;
|
||||
|
||||
/* We still have requests in-flight; the engine should be active */
|
||||
GEM_BUG_ON(!intel_engine_pm_is_awake(engine));
|
||||
|
||||
ce = rq->context;
|
||||
GEM_BUG_ON(!i915_vma_is_pinned(ce->state));
|
||||
|
||||
@ -3648,8 +3687,12 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
|
||||
goto out_replay;
|
||||
}
|
||||
|
||||
/* We still have requests in-flight; the engine should be active */
|
||||
GEM_BUG_ON(!intel_engine_pm_is_awake(engine));
|
||||
|
||||
/* Context has requests still in-flight; it should not be idle! */
|
||||
GEM_BUG_ON(i915_active_is_idle(&ce->active));
|
||||
|
||||
rq = active_request(ce->timeline, rq);
|
||||
head = intel_ring_wrap(ce->ring, rq->head);
|
||||
GEM_BUG_ON(head == ce->ring->tail);
|
||||
@ -3723,7 +3766,10 @@ static void execlists_reset_rewind(struct intel_engine_cs *engine, bool stalled)
|
||||
|
||||
static void nop_submission_tasklet(unsigned long data)
|
||||
{
|
||||
struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
|
||||
|
||||
/* The driver is wedged; don't process any more events. */
|
||||
WRITE_ONCE(engine->execlists.queue_priority_hint, INT_MIN);
|
||||
}
|
||||
|
||||
static void execlists_reset_cancel(struct intel_engine_cs *engine)
|
||||
@ -4119,26 +4165,6 @@ static int gen12_emit_flush_render(struct i915_request *request,
|
||||
|
||||
*cs++ = preparser_disable(false);
|
||||
intel_ring_advance(request, cs);
|
||||
|
||||
/*
|
||||
* Wa_1604544889:tgl
|
||||
*/
|
||||
if (IS_TGL_REVID(request->i915, TGL_REVID_A0, TGL_REVID_A0)) {
|
||||
flags = 0;
|
||||
flags |= PIPE_CONTROL_CS_STALL;
|
||||
flags |= PIPE_CONTROL_HDC_PIPELINE_FLUSH;
|
||||
|
||||
flags |= PIPE_CONTROL_STORE_DATA_INDEX;
|
||||
flags |= PIPE_CONTROL_QW_WRITE;
|
||||
|
||||
cs = intel_ring_begin(request, 6);
|
||||
if (IS_ERR(cs))
|
||||
return PTR_ERR(cs);
|
||||
|
||||
cs = gen8_emit_pipe_control(cs, flags,
|
||||
LRC_PPHWSP_SCRATCH_ADDR);
|
||||
intel_ring_advance(request, cs);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -4877,7 +4903,7 @@ static intel_engine_mask_t virtual_submission_mask(struct virtual_engine *ve)
|
||||
mask = rq->execution_mask;
|
||||
if (unlikely(!mask)) {
|
||||
/* Invalid selection, submit to a random engine in error */
|
||||
i915_request_skip(rq, -ENODEV);
|
||||
i915_request_set_error_once(rq, -ENODEV);
|
||||
mask = ve->siblings[0]->mask;
|
||||
}
|
||||
|
||||
@ -4891,7 +4917,7 @@ static intel_engine_mask_t virtual_submission_mask(struct virtual_engine *ve)
|
||||
static void virtual_submission_tasklet(unsigned long data)
|
||||
{
|
||||
struct virtual_engine * const ve = (struct virtual_engine *)data;
|
||||
const int prio = ve->base.execlists.queue_priority_hint;
|
||||
const int prio = READ_ONCE(ve->base.execlists.queue_priority_hint);
|
||||
intel_engine_mask_t mask;
|
||||
unsigned int n;
|
||||
|
||||
@ -5287,11 +5313,15 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
|
||||
show_request(m, last, "\t\tE ");
|
||||
}
|
||||
|
||||
last = NULL;
|
||||
count = 0;
|
||||
if (execlists->switch_priority_hint != INT_MIN)
|
||||
drm_printf(m, "\t\tSwitch priority hint: %d\n",
|
||||
READ_ONCE(execlists->switch_priority_hint));
|
||||
if (execlists->queue_priority_hint != INT_MIN)
|
||||
drm_printf(m, "\t\tQueue priority hint: %d\n",
|
||||
execlists->queue_priority_hint);
|
||||
READ_ONCE(execlists->queue_priority_hint));
|
||||
|
||||
last = NULL;
|
||||
count = 0;
|
||||
for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
|
||||
struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
|
||||
int i;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_vgpu.h"
|
||||
#include "intel_gt.h"
|
||||
#include "intel_gt_pm.h"
|
||||
#include "intel_rc6.h"
|
||||
@ -319,10 +320,10 @@ static int vlv_rc6_init(struct intel_rc6 *rc6)
|
||||
return PTR_ERR(pctx);
|
||||
}
|
||||
|
||||
GEM_BUG_ON(range_overflows_t(u64,
|
||||
i915->dsm.start,
|
||||
pctx->stolen->start,
|
||||
U32_MAX));
|
||||
GEM_BUG_ON(range_overflows_end_t(u64,
|
||||
i915->dsm.start,
|
||||
pctx->stolen->start,
|
||||
U32_MAX));
|
||||
pctx_paddr = i915->dsm.start + pctx->stolen->start;
|
||||
intel_uncore_write(uncore, VLV_PCBR, pctx_paddr);
|
||||
|
||||
|
@ -48,8 +48,10 @@ static void engine_skip_context(struct i915_request *rq)
|
||||
|
||||
lockdep_assert_held(&engine->active.lock);
|
||||
list_for_each_entry_continue(rq, &engine->active.requests, sched.link)
|
||||
if (rq->context == hung_ctx)
|
||||
i915_request_skip(rq, -EIO);
|
||||
if (rq->context == hung_ctx) {
|
||||
i915_request_set_error_once(rq, -EIO);
|
||||
__i915_request_skip(rq);
|
||||
}
|
||||
}
|
||||
|
||||
static void client_mark_guilty(struct i915_gem_context *ctx, bool banned)
|
||||
@ -92,13 +94,7 @@ static bool mark_guilty(struct i915_request *rq)
|
||||
ctx = NULL;
|
||||
rcu_read_unlock();
|
||||
if (!ctx)
|
||||
return false;
|
||||
|
||||
if (i915_gem_context_is_closed(ctx)) {
|
||||
intel_context_set_banned(rq->context);
|
||||
banned = true;
|
||||
goto out;
|
||||
}
|
||||
return intel_context_is_banned(rq->context);
|
||||
|
||||
atomic_inc(&ctx->guilty_count);
|
||||
|
||||
@ -154,11 +150,12 @@ void __i915_request_reset(struct i915_request *rq, bool guilty)
|
||||
|
||||
rcu_read_lock(); /* protect the GEM context */
|
||||
if (guilty) {
|
||||
i915_request_skip(rq, -EIO);
|
||||
i915_request_set_error_once(rq, -EIO);
|
||||
__i915_request_skip(rq);
|
||||
if (mark_guilty(rq))
|
||||
engine_skip_context(rq);
|
||||
} else {
|
||||
dma_fence_set_error(&rq->fence, -EAGAIN);
|
||||
i915_request_set_error_once(rq, -EAGAIN);
|
||||
mark_innocent(rq);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
@ -785,7 +782,7 @@ static void nop_submit_request(struct i915_request *request)
|
||||
unsigned long flags;
|
||||
|
||||
RQ_TRACE(request, "-EIO\n");
|
||||
dma_fence_set_error(&request->fence, -EIO);
|
||||
i915_request_set_error_once(request, -EIO);
|
||||
|
||||
spin_lock_irqsave(&engine->active.lock, flags);
|
||||
__i915_request_submit(request);
|
||||
|
@ -29,11 +29,10 @@
|
||||
|
||||
#include <linux/log2.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "gem/i915_gem_context.h"
|
||||
|
||||
#include "gen6_ppgtt.h"
|
||||
#include "gen7_renderclear.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_trace.h"
|
||||
#include "intel_context.h"
|
||||
@ -897,9 +896,7 @@ static void reset_cancel(struct intel_engine_cs *engine)
|
||||
|
||||
/* Mark all submitted requests as skipped. */
|
||||
list_for_each_entry(request, &engine->active.requests, sched.link) {
|
||||
if (!i915_request_signaled(request))
|
||||
dma_fence_set_error(&request->fence, -EIO);
|
||||
|
||||
i915_request_set_error_once(request, -EIO);
|
||||
i915_request_mark_complete(request);
|
||||
}
|
||||
|
||||
@ -1360,7 +1357,9 @@ static int load_pd_dir(struct i915_request *rq,
|
||||
return rq->engine->emit_flush(rq, EMIT_FLUSH);
|
||||
}
|
||||
|
||||
static inline int mi_set_context(struct i915_request *rq, u32 flags)
|
||||
static inline int mi_set_context(struct i915_request *rq,
|
||||
struct intel_context *ce,
|
||||
u32 flags)
|
||||
{
|
||||
struct drm_i915_private *i915 = rq->i915;
|
||||
struct intel_engine_cs *engine = rq->engine;
|
||||
@ -1435,7 +1434,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
|
||||
|
||||
*cs++ = MI_NOOP;
|
||||
*cs++ = MI_SET_CONTEXT;
|
||||
*cs++ = i915_ggtt_offset(rq->context->state) | flags;
|
||||
*cs++ = i915_ggtt_offset(ce->state) | flags;
|
||||
/*
|
||||
* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
|
||||
* WaMiSetContext_Hang:snb,ivb,vlv
|
||||
@ -1550,13 +1549,56 @@ static int switch_mm(struct i915_request *rq, struct i915_address_space *vm)
|
||||
return rq->engine->emit_flush(rq, EMIT_INVALIDATE);
|
||||
}
|
||||
|
||||
static int clear_residuals(struct i915_request *rq)
|
||||
{
|
||||
struct intel_engine_cs *engine = rq->engine;
|
||||
int ret;
|
||||
|
||||
ret = switch_mm(rq, vm_alias(engine->kernel_context->vm));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (engine->kernel_context->state) {
|
||||
ret = mi_set_context(rq,
|
||||
engine->kernel_context,
|
||||
MI_MM_SPACE_GTT | MI_RESTORE_INHIBIT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = engine->emit_bb_start(rq,
|
||||
engine->wa_ctx.vma->node.start, 0,
|
||||
0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = engine->emit_flush(rq, EMIT_FLUSH);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Always invalidate before the next switch_mm() */
|
||||
return engine->emit_flush(rq, EMIT_INVALIDATE);
|
||||
}
|
||||
|
||||
static int switch_context(struct i915_request *rq)
|
||||
{
|
||||
struct intel_engine_cs *engine = rq->engine;
|
||||
struct intel_context *ce = rq->context;
|
||||
void **residuals = NULL;
|
||||
int ret;
|
||||
|
||||
GEM_BUG_ON(HAS_EXECLISTS(rq->i915));
|
||||
|
||||
if (engine->wa_ctx.vma && ce != engine->kernel_context) {
|
||||
if (engine->wa_ctx.vma->private != ce) {
|
||||
ret = clear_residuals(rq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
residuals = &engine->wa_ctx.vma->private;
|
||||
}
|
||||
}
|
||||
|
||||
ret = switch_mm(rq, vm_alias(ce->vm));
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1564,7 +1606,7 @@ static int switch_context(struct i915_request *rq)
|
||||
if (ce->state) {
|
||||
u32 flags;
|
||||
|
||||
GEM_BUG_ON(rq->engine->id != RCS0);
|
||||
GEM_BUG_ON(engine->id != RCS0);
|
||||
|
||||
/* For resource streamer on HSW+ and power context elsewhere */
|
||||
BUILD_BUG_ON(HSW_MI_RS_SAVE_STATE_EN != MI_SAVE_EXT_STATE_EN);
|
||||
@ -1576,7 +1618,7 @@ static int switch_context(struct i915_request *rq)
|
||||
else
|
||||
flags |= MI_RESTORE_INHIBIT;
|
||||
|
||||
ret = mi_set_context(rq, flags);
|
||||
ret = mi_set_context(rq, ce, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -1585,6 +1627,20 @@ static int switch_context(struct i915_request *rq)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Now past the point of no return, this request _will_ be emitted.
|
||||
*
|
||||
* Or at least this preamble will be emitted, the request may be
|
||||
* interrupted prior to submitting the user payload. If so, we
|
||||
* still submit the "empty" request in order to preserve global
|
||||
* state tracking such as this, our tracking of the current
|
||||
* dirty context.
|
||||
*/
|
||||
if (residuals) {
|
||||
intel_context_put(*residuals);
|
||||
*residuals = intel_context_get(ce);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1769,6 +1825,11 @@ static void ring_release(struct intel_engine_cs *engine)
|
||||
|
||||
intel_engine_cleanup_common(engine);
|
||||
|
||||
if (engine->wa_ctx.vma) {
|
||||
intel_context_put(engine->wa_ctx.vma->private);
|
||||
i915_vma_unpin_and_release(&engine->wa_ctx.vma, 0);
|
||||
}
|
||||
|
||||
intel_ring_unpin(engine->legacy.ring);
|
||||
intel_ring_put(engine->legacy.ring);
|
||||
|
||||
@ -1916,6 +1977,64 @@ static void setup_vecs(struct intel_engine_cs *engine)
|
||||
engine->emit_fini_breadcrumb = gen7_xcs_emit_breadcrumb;
|
||||
}
|
||||
|
||||
static int gen7_ctx_switch_bb_setup(struct intel_engine_cs * const engine,
|
||||
struct i915_vma * const vma)
|
||||
{
|
||||
return gen7_setup_clear_gpr_bb(engine, vma);
|
||||
}
|
||||
|
||||
static int gen7_ctx_switch_bb_init(struct intel_engine_cs *engine)
|
||||
{
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_vma *vma;
|
||||
int size;
|
||||
int err;
|
||||
|
||||
size = gen7_ctx_switch_bb_setup(engine, NULL /* probe size */);
|
||||
if (size <= 0)
|
||||
return size;
|
||||
|
||||
size = ALIGN(size, PAGE_SIZE);
|
||||
obj = i915_gem_object_create_internal(engine->i915, size);
|
||||
if (IS_ERR(obj))
|
||||
return PTR_ERR(obj);
|
||||
|
||||
vma = i915_vma_instance(obj, engine->gt->vm, NULL);
|
||||
if (IS_ERR(vma)) {
|
||||
err = PTR_ERR(vma);
|
||||
goto err_obj;
|
||||
}
|
||||
|
||||
vma->private = intel_context_create(engine); /* dummy residuals */
|
||||
if (IS_ERR(vma->private)) {
|
||||
err = PTR_ERR(vma->private);
|
||||
goto err_obj;
|
||||
}
|
||||
|
||||
err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_HIGH);
|
||||
if (err)
|
||||
goto err_private;
|
||||
|
||||
err = i915_vma_sync(vma);
|
||||
if (err)
|
||||
goto err_unpin;
|
||||
|
||||
err = gen7_ctx_switch_bb_setup(engine, vma);
|
||||
if (err)
|
||||
goto err_unpin;
|
||||
|
||||
engine->wa_ctx.vma = vma;
|
||||
return 0;
|
||||
|
||||
err_unpin:
|
||||
i915_vma_unpin(vma);
|
||||
err_private:
|
||||
intel_context_put(vma->private);
|
||||
err_obj:
|
||||
i915_gem_object_put(obj);
|
||||
return err;
|
||||
}
|
||||
|
||||
int intel_ring_submission_setup(struct intel_engine_cs *engine)
|
||||
{
|
||||
struct intel_timeline *timeline;
|
||||
@ -1969,11 +2088,19 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine)
|
||||
|
||||
GEM_BUG_ON(timeline->hwsp_ggtt != engine->status_page.vma);
|
||||
|
||||
if (IS_GEN(engine->i915, 7) && engine->class == RENDER_CLASS) {
|
||||
err = gen7_ctx_switch_bb_init(engine);
|
||||
if (err)
|
||||
goto err_ring_unpin;
|
||||
}
|
||||
|
||||
/* Finally, take ownership and responsibility for cleanup! */
|
||||
engine->release = ring_release;
|
||||
|
||||
return 0;
|
||||
|
||||
err_ring_unpin:
|
||||
intel_ring_unpin(ring);
|
||||
err_ring:
|
||||
intel_ring_put(ring);
|
||||
err_timeline_unpin:
|
||||
@ -1984,3 +2111,7 @@ err:
|
||||
intel_engine_cleanup_common(engine);
|
||||
return err;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
|
||||
#include "selftest_ring_submission.c"
|
||||
#endif
|
||||
|
@ -4,6 +4,8 @@
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_gt.h"
|
||||
#include "intel_gt_irq.h"
|
||||
@ -55,7 +57,7 @@ static u32 rps_pm_mask(struct intel_rps *rps, u8 val)
|
||||
if (val < rps->max_freq_softlimit)
|
||||
mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD;
|
||||
|
||||
mask &= rps->pm_events;
|
||||
mask &= READ_ONCE(rps->pm_events);
|
||||
|
||||
return rps_pm_sanitize_mask(rps, ~mask);
|
||||
}
|
||||
@ -68,17 +70,19 @@ static void rps_reset_ei(struct intel_rps *rps)
|
||||
static void rps_enable_interrupts(struct intel_rps *rps)
|
||||
{
|
||||
struct intel_gt *gt = rps_to_gt(rps);
|
||||
u32 events;
|
||||
|
||||
rps_reset_ei(rps);
|
||||
|
||||
if (IS_VALLEYVIEW(gt->i915))
|
||||
/* WaGsvRC0ResidencyMethod:vlv */
|
||||
rps->pm_events = GEN6_PM_RP_UP_EI_EXPIRED;
|
||||
events = GEN6_PM_RP_UP_EI_EXPIRED;
|
||||
else
|
||||
rps->pm_events = (GEN6_PM_RP_UP_THRESHOLD |
|
||||
GEN6_PM_RP_DOWN_THRESHOLD |
|
||||
GEN6_PM_RP_DOWN_TIMEOUT);
|
||||
events = (GEN6_PM_RP_UP_THRESHOLD |
|
||||
GEN6_PM_RP_DOWN_THRESHOLD |
|
||||
GEN6_PM_RP_DOWN_TIMEOUT);
|
||||
|
||||
WRITE_ONCE(rps->pm_events, events);
|
||||
spin_lock_irq(>->irq_lock);
|
||||
gen6_gt_pm_enable_irq(gt, rps->pm_events);
|
||||
spin_unlock_irq(>->irq_lock);
|
||||
@ -115,8 +119,7 @@ static void rps_disable_interrupts(struct intel_rps *rps)
|
||||
{
|
||||
struct intel_gt *gt = rps_to_gt(rps);
|
||||
|
||||
rps->pm_events = 0;
|
||||
|
||||
WRITE_ONCE(rps->pm_events, 0);
|
||||
set(gt->uncore, GEN6_PMINTRMSK, rps_pm_sanitize_mask(rps, ~0u));
|
||||
|
||||
spin_lock_irq(>->irq_lock);
|
||||
@ -642,7 +645,7 @@ void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive)
|
||||
{
|
||||
mutex_lock(&rps->power.mutex);
|
||||
if (interactive) {
|
||||
if (!rps->power.interactive++ && rps->active)
|
||||
if (!rps->power.interactive++ && READ_ONCE(rps->active))
|
||||
rps_set_power(rps, HIGH_POWER);
|
||||
} else {
|
||||
GEM_BUG_ON(!rps->power.interactive);
|
||||
@ -719,11 +722,15 @@ void intel_rps_unpark(struct intel_rps *rps)
|
||||
* performance, jump directly to RPe as our starting frequency.
|
||||
*/
|
||||
mutex_lock(&rps->lock);
|
||||
rps->active = true;
|
||||
|
||||
WRITE_ONCE(rps->active, true);
|
||||
|
||||
freq = max(rps->cur_freq, rps->efficient_freq),
|
||||
freq = clamp(freq, rps->min_freq_softlimit, rps->max_freq_softlimit);
|
||||
intel_rps_set(rps, freq);
|
||||
|
||||
rps->last_adj = 0;
|
||||
|
||||
mutex_unlock(&rps->lock);
|
||||
|
||||
if (INTEL_GEN(rps_to_i915(rps)) >= 6)
|
||||
@ -743,7 +750,7 @@ void intel_rps_park(struct intel_rps *rps)
|
||||
if (INTEL_GEN(i915) >= 6)
|
||||
rps_disable_interrupts(rps);
|
||||
|
||||
rps->active = false;
|
||||
WRITE_ONCE(rps->active, false);
|
||||
if (rps->last_freq <= rps->idle_freq)
|
||||
return;
|
||||
|
||||
@ -767,10 +774,10 @@ void intel_rps_park(struct intel_rps *rps)
|
||||
|
||||
void intel_rps_boost(struct i915_request *rq)
|
||||
{
|
||||
struct intel_rps *rps = &rq->engine->gt->rps;
|
||||
struct intel_rps *rps = &READ_ONCE(rq->engine)->gt->rps;
|
||||
unsigned long flags;
|
||||
|
||||
if (i915_request_signaled(rq) || !rps->active)
|
||||
if (i915_request_signaled(rq) || !READ_ONCE(rps->active))
|
||||
return;
|
||||
|
||||
/* Serializes with i915_request_retire() */
|
||||
@ -1453,12 +1460,12 @@ static void rps_work(struct work_struct *work)
|
||||
u32 pm_iir = 0;
|
||||
|
||||
spin_lock_irq(>->irq_lock);
|
||||
pm_iir = fetch_and_zero(&rps->pm_iir);
|
||||
pm_iir = fetch_and_zero(&rps->pm_iir) & READ_ONCE(rps->pm_events);
|
||||
client_boost = atomic_read(&rps->num_waiters);
|
||||
spin_unlock_irq(>->irq_lock);
|
||||
|
||||
/* Make sure we didn't queue anything we're not going to process. */
|
||||
if ((pm_iir & rps->pm_events) == 0 && !client_boost)
|
||||
if (!pm_iir && !client_boost)
|
||||
goto out;
|
||||
|
||||
mutex_lock(&rps->lock);
|
||||
@ -1554,11 +1561,15 @@ void gen11_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
|
||||
void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
|
||||
{
|
||||
struct intel_gt *gt = rps_to_gt(rps);
|
||||
u32 events;
|
||||
|
||||
if (pm_iir & rps->pm_events) {
|
||||
events = pm_iir & READ_ONCE(rps->pm_events);
|
||||
if (events) {
|
||||
spin_lock(>->irq_lock);
|
||||
gen6_gt_pm_mask_irq(gt, pm_iir & rps->pm_events);
|
||||
rps->pm_iir |= pm_iir & rps->pm_events;
|
||||
|
||||
gen6_gt_pm_mask_irq(gt, events);
|
||||
rps->pm_iir |= events;
|
||||
|
||||
schedule_work(&rps->work);
|
||||
spin_unlock(>->irq_lock);
|
||||
}
|
||||
|
@ -192,11 +192,15 @@ static void cacheline_release(struct intel_timeline_cacheline *cl)
|
||||
|
||||
static void cacheline_free(struct intel_timeline_cacheline *cl)
|
||||
{
|
||||
if (!i915_active_acquire_if_busy(&cl->active)) {
|
||||
__idle_cacheline_free(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
GEM_BUG_ON(ptr_test_bit(cl->vaddr, CACHELINE_FREE));
|
||||
cl->vaddr = ptr_set_bit(cl->vaddr, CACHELINE_FREE);
|
||||
|
||||
if (i915_active_is_idle(&cl->active))
|
||||
__idle_cacheline_free(cl);
|
||||
i915_active_release(&cl->active);
|
||||
}
|
||||
|
||||
int intel_timeline_init(struct intel_timeline *timeline,
|
||||
|
@ -575,12 +575,29 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
|
||||
/* allow headerless messages for preemptible GPGPU context */
|
||||
WA_SET_BIT_MASKED(GEN10_SAMPLER_MODE,
|
||||
GEN11_SAMPLER_ENABLE_HEADLESS_MSG);
|
||||
|
||||
/* Wa_1604278689:icl,ehl */
|
||||
wa_write(wal, IVB_FBC_RT_BASE, 0xFFFFFFFF & ~ILK_FBC_RT_VALID);
|
||||
wa_write_masked_or(wal, IVB_FBC_RT_BASE_UPPER,
|
||||
0, /* write-only register; skip validation */
|
||||
0xFFFFFFFF);
|
||||
|
||||
/* Wa_1406306137:icl,ehl */
|
||||
wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU);
|
||||
}
|
||||
|
||||
static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine,
|
||||
struct i915_wa_list *wal)
|
||||
{
|
||||
/* Wa_1409142259:tgl */
|
||||
/*
|
||||
* Wa_1409142259:tgl
|
||||
* Wa_1409347922:tgl
|
||||
* Wa_1409252684:tgl
|
||||
* Wa_1409217633:tgl
|
||||
* Wa_1409207793:tgl
|
||||
* Wa_1409178076:tgl
|
||||
* Wa_1408979724:tgl
|
||||
*/
|
||||
WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3,
|
||||
GEN12_DISABLE_CPS_AWARE_COLOR_PIPE);
|
||||
|
||||
@ -593,6 +610,11 @@ static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine,
|
||||
*/
|
||||
wa_add(wal, FF_MODE2, FF_MODE2_TDS_TIMER_MASK,
|
||||
FF_MODE2_TDS_TIMER_128, 0);
|
||||
|
||||
/* WaDisableGPGPUMidThreadPreemption:tgl */
|
||||
WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1,
|
||||
GEN9_PREEMPT_GPGPU_LEVEL_MASK,
|
||||
GEN9_PREEMPT_GPGPU_THREAD_GROUP_LEVEL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -898,11 +920,6 @@ icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
|
||||
SLICE_UNIT_LEVEL_CLKGATE,
|
||||
MSCUNIT_CLKGATE_DIS);
|
||||
|
||||
/* Wa_1406680159:icl */
|
||||
wa_write_or(wal,
|
||||
SUBSLICE_UNIT_LEVEL_CLKGATE,
|
||||
GWUNIT_CLKGATE_DIS);
|
||||
|
||||
/* Wa_1406838659:icl (pre-prod) */
|
||||
if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
|
||||
wa_write_or(wal,
|
||||
@ -931,7 +948,7 @@ tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
|
||||
SUBSLICE_UNIT_LEVEL_CLKGATE2,
|
||||
CPSSUNIT_CLKGATE_DIS);
|
||||
|
||||
/* Wa_1409180338:tgl */
|
||||
/* Wa_1607087056:tgl also know as BUG:1409180338 */
|
||||
if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0))
|
||||
wa_write_or(wal,
|
||||
SLICE_UNIT_LEVEL_CLKGATE,
|
||||
@ -1246,6 +1263,7 @@ static void tgl_whitelist_build(struct intel_engine_cs *engine)
|
||||
case RENDER_CLASS:
|
||||
/*
|
||||
* WaAllowPMDepthAndInvocationCountAccessFromUMD:tgl
|
||||
* Wa_1408556865:tgl
|
||||
*
|
||||
* This covers 4 registers which are next to one another :
|
||||
* - PS_INVOCATION_COUNT
|
||||
@ -1259,6 +1277,9 @@ static void tgl_whitelist_build(struct intel_engine_cs *engine)
|
||||
|
||||
/* Wa_1808121037:tgl */
|
||||
whitelist_reg(w, GEN7_COMMON_SLICE_CHICKEN1);
|
||||
|
||||
/* Wa_1806527549:tgl */
|
||||
whitelist_reg(w, HIZ_CHICKEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1325,19 +1346,21 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
|
||||
struct drm_i915_private *i915 = engine->i915;
|
||||
|
||||
if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) {
|
||||
/* Wa_1606700617:tgl */
|
||||
wa_masked_en(wal,
|
||||
GEN9_CS_DEBUG_MODE1,
|
||||
FF_DOP_CLOCK_GATE_DISABLE);
|
||||
|
||||
/* Wa_1607138336:tgl */
|
||||
/*
|
||||
* Wa_1607138336:tgl
|
||||
* Wa_1607063988:tgl
|
||||
*/
|
||||
wa_write_or(wal,
|
||||
GEN9_CTX_PREEMPT_REG,
|
||||
GEN12_DISABLE_POSH_BUSY_FF_DOP_CG);
|
||||
|
||||
/* Wa_1607030317:tgl */
|
||||
/* Wa_1607186500:tgl */
|
||||
/* Wa_1607297627:tgl */
|
||||
/*
|
||||
* Wa_1607030317:tgl
|
||||
* Wa_1607186500:tgl
|
||||
* Wa_1607297627:tgl there is 3 entries for this WA on BSpec, 2
|
||||
* of then says it is fixed on B0 the other one says it is
|
||||
* permanent
|
||||
*/
|
||||
wa_masked_en(wal,
|
||||
GEN6_RC_SLEEP_PSMI_CONTROL,
|
||||
GEN12_WAIT_FOR_EVENT_POWER_DOWN_DISABLE |
|
||||
@ -1356,10 +1379,29 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
|
||||
GEN7_FF_THREAD_MODE,
|
||||
GEN12_FF_TESSELATION_DOP_GATE_DISABLE);
|
||||
|
||||
/*
|
||||
* Wa_1409085225:tgl
|
||||
* Wa_14010229206:tgl
|
||||
*/
|
||||
wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN12_DISABLE_TDL_PUSH);
|
||||
|
||||
/* Wa_1408615072:tgl */
|
||||
wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE2,
|
||||
VSUNIT_CLKGATE_DIS_TGL);
|
||||
}
|
||||
|
||||
if (IS_TIGERLAKE(i915)) {
|
||||
/* Wa_1606931601:tgl */
|
||||
wa_masked_en(wal, GEN7_ROW_CHICKEN2, GEN12_DISABLE_EARLY_READ);
|
||||
|
||||
/* Wa_1409804808:tgl */
|
||||
wa_masked_en(wal, GEN7_ROW_CHICKEN2,
|
||||
GEN12_PUSH_CONST_DEREF_HOLD_DIS);
|
||||
|
||||
/* Wa_1606700617:tgl */
|
||||
wa_masked_en(wal,
|
||||
GEN7_ROW_CHICKEN2,
|
||||
GEN12_DISABLE_EARLY_READ);
|
||||
GEN9_CS_DEBUG_MODE1,
|
||||
FF_DOP_CLOCK_GATE_DISABLE);
|
||||
}
|
||||
|
||||
if (IS_GEN(i915, 11)) {
|
||||
@ -1425,10 +1467,38 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
|
||||
GEN11_SCRATCH2,
|
||||
GEN11_COHERENT_PARTIAL_WRITE_MERGE_ENABLE,
|
||||
0);
|
||||
|
||||
/* WaEnable32PlaneMode:icl */
|
||||
wa_masked_en(wal, GEN9_CSFE_CHICKEN1_RCS,
|
||||
GEN11_ENABLE_32_PLANE_MODE);
|
||||
|
||||
/*
|
||||
* Wa_1408615072:icl,ehl (vsunit)
|
||||
* Wa_1407596294:icl,ehl (hsunit)
|
||||
*/
|
||||
wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE,
|
||||
VSUNIT_CLKGATE_DIS | HSUNIT_CLKGATE_DIS);
|
||||
|
||||
/* Wa_1407352427:icl,ehl */
|
||||
wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE2,
|
||||
PSDUNIT_CLKGATE_DIS);
|
||||
|
||||
/* Wa_1406680159:icl,ehl */
|
||||
wa_write_or(wal,
|
||||
SUBSLICE_UNIT_LEVEL_CLKGATE,
|
||||
GWUNIT_CLKGATE_DIS);
|
||||
|
||||
/*
|
||||
* Wa_1408767742:icl[a2..forever],ehl[all]
|
||||
* Wa_1605460711:icl[a0..c0]
|
||||
*/
|
||||
wa_write_or(wal,
|
||||
GEN7_FF_THREAD_MODE,
|
||||
GEN12_FF_TESSELATION_DOP_GATE_DISABLE);
|
||||
}
|
||||
|
||||
if (IS_GEN_RANGE(i915, 9, 11)) {
|
||||
/* FtrPerCtxtPreemptionGranularityControl:skl,bxt,kbl,cfl,cnl,icl */
|
||||
if (IS_GEN_RANGE(i915, 9, 12)) {
|
||||
/* FtrPerCtxtPreemptionGranularityControl:skl,bxt,kbl,cfl,cnl,icl,tgl */
|
||||
wa_masked_en(wal,
|
||||
GEN7_FF_SLICE_CS_CHICKEN1,
|
||||
GEN9_FFSC_PERCTX_PREEMPT_CTRL);
|
||||
@ -1595,15 +1665,34 @@ err_obj:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
u32 start;
|
||||
u32 end;
|
||||
} mcr_ranges_gen8[] = {
|
||||
{ .start = 0x5500, .end = 0x55ff },
|
||||
{ .start = 0x7000, .end = 0x7fff },
|
||||
{ .start = 0x9400, .end = 0x97ff },
|
||||
{ .start = 0xb000, .end = 0xb3ff },
|
||||
{ .start = 0xe000, .end = 0xe7ff },
|
||||
{},
|
||||
};
|
||||
|
||||
static bool mcr_range(struct drm_i915_private *i915, u32 offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (INTEL_GEN(i915) < 8)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Registers in this range are affected by the MCR selector
|
||||
* Registers in these ranges are affected by the MCR selector
|
||||
* which only controls CPU initiated MMIO. Routing does not
|
||||
* work for CS access so we cannot verify them on this path.
|
||||
*/
|
||||
if (INTEL_GEN(i915) >= 8 && (offset >= 0xb000 && offset <= 0xb4ff))
|
||||
return true;
|
||||
for (i = 0; mcr_ranges_gen8[i].start; i++)
|
||||
if (offset >= mcr_ranges_gen8[i].start &&
|
||||
offset <= mcr_ranges_gen8[i].end)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
61
drivers/gpu/drm/i915/gt/ivb_clear_kernel.c
Normal file
61
drivers/gpu/drm/i915/gt/ivb_clear_kernel.c
Normal file
@ -0,0 +1,61 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2020 Intel Corporation
|
||||
*
|
||||
* Generated by: IGT Gpu Tools on Fri 21 Feb 2020 05:29:32 AM UTC
|
||||
*/
|
||||
|
||||
static const u32 ivb_clear_kernel[] = {
|
||||
0x00000001, 0x26020128, 0x00000024, 0x00000000,
|
||||
0x00000040, 0x20280c21, 0x00000028, 0x00000001,
|
||||
0x01000010, 0x20000c20, 0x0000002c, 0x00000000,
|
||||
0x00010220, 0x34001c00, 0x00001400, 0x0000002c,
|
||||
0x00600001, 0x20600061, 0x00000000, 0x00000000,
|
||||
0x00000008, 0x20601c85, 0x00000e00, 0x0000000c,
|
||||
0x00000005, 0x20601ca5, 0x00000060, 0x00000001,
|
||||
0x00000008, 0x20641c85, 0x00000e00, 0x0000000d,
|
||||
0x00000005, 0x20641ca5, 0x00000064, 0x00000003,
|
||||
0x00000041, 0x207424a5, 0x00000064, 0x00000034,
|
||||
0x00000040, 0x206014a5, 0x00000060, 0x00000074,
|
||||
0x00000008, 0x20681c85, 0x00000e00, 0x00000008,
|
||||
0x00000005, 0x20681ca5, 0x00000068, 0x0000000f,
|
||||
0x00000041, 0x20701ca5, 0x00000060, 0x00000010,
|
||||
0x00000040, 0x206814a5, 0x00000068, 0x00000070,
|
||||
0x00600001, 0x20a00061, 0x00000000, 0x00000000,
|
||||
0x00000005, 0x206c1c85, 0x00000e00, 0x00000007,
|
||||
0x00000041, 0x206c1ca5, 0x0000006c, 0x00000004,
|
||||
0x00600001, 0x20800021, 0x008d0000, 0x00000000,
|
||||
0x00000001, 0x20800021, 0x0000006c, 0x00000000,
|
||||
0x00000001, 0x20840021, 0x00000068, 0x00000000,
|
||||
0x00000001, 0x20880061, 0x00000000, 0x00000003,
|
||||
0x00000005, 0x208c0d21, 0x00000086, 0xffffffff,
|
||||
0x05600032, 0x20a00fa1, 0x008d0080, 0x02190001,
|
||||
0x00000040, 0x20a01ca5, 0x000000a0, 0x00000001,
|
||||
0x05600032, 0x20a00fa1, 0x008d0080, 0x040a8001,
|
||||
0x02000040, 0x20281c21, 0x00000028, 0xffffffff,
|
||||
0x00010220, 0x34001c00, 0x00001400, 0xfffffffc,
|
||||
0x00000001, 0x26020128, 0x00000024, 0x00000000,
|
||||
0x00000001, 0x220010e4, 0x00000000, 0x00000000,
|
||||
0x00000001, 0x220831ec, 0x00000000, 0x007f007f,
|
||||
0x00600001, 0x20400021, 0x008d0000, 0x00000000,
|
||||
0x00600001, 0x2fe00021, 0x008d0000, 0x00000000,
|
||||
0x00200001, 0x20400121, 0x00450020, 0x00000000,
|
||||
0x00000001, 0x20480061, 0x00000000, 0x000f000f,
|
||||
0x00000005, 0x204c0d21, 0x00000046, 0xffffffef,
|
||||
0x00800001, 0x20600061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x20800061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x20a00061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x20c00061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x20e00061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x21000061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x21200061, 0x00000000, 0x00000000,
|
||||
0x00800001, 0x21400061, 0x00000000, 0x00000000,
|
||||
0x05600032, 0x20000fa0, 0x008d0040, 0x120a8000,
|
||||
0x00000040, 0x20402d21, 0x00000020, 0x00100010,
|
||||
0x05600032, 0x20000fa0, 0x008d0040, 0x120a8000,
|
||||
0x02000040, 0x22083d8c, 0x00000208, 0xffffffff,
|
||||
0x00800001, 0xa0000109, 0x00000602, 0x00000000,
|
||||
0x00000040, 0x22001c84, 0x00000200, 0x00000020,
|
||||
0x00010220, 0x34001c00, 0x00001400, 0xfffffff8,
|
||||
0x07600032, 0x20000fa0, 0x008d0fe0, 0x82000010,
|
||||
};
|
@ -244,9 +244,7 @@ static void mock_reset_cancel(struct intel_engine_cs *engine)
|
||||
|
||||
/* Mark all submitted requests as skipped. */
|
||||
list_for_each_entry(request, &engine->active.requests, sched.link) {
|
||||
if (!i915_request_signaled(request))
|
||||
dma_fence_set_error(&request->fence, -EIO);
|
||||
|
||||
i915_request_set_error_once(request, -EIO);
|
||||
i915_request_mark_complete(request);
|
||||
}
|
||||
|
||||
|
@ -142,6 +142,24 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void engine_heartbeat_disable(struct intel_engine_cs *engine,
|
||||
unsigned long *saved)
|
||||
{
|
||||
*saved = engine->props.heartbeat_interval_ms;
|
||||
engine->props.heartbeat_interval_ms = 0;
|
||||
|
||||
intel_engine_pm_get(engine);
|
||||
intel_engine_park_heartbeat(engine);
|
||||
}
|
||||
|
||||
static void engine_heartbeat_enable(struct intel_engine_cs *engine,
|
||||
unsigned long saved)
|
||||
{
|
||||
intel_engine_pm_put(engine);
|
||||
|
||||
engine->props.heartbeat_interval_ms = saved;
|
||||
}
|
||||
|
||||
static int live_idle_flush(void *arg)
|
||||
{
|
||||
struct intel_gt *gt = arg;
|
||||
@ -152,9 +170,11 @@ static int live_idle_flush(void *arg)
|
||||
/* Check that we can flush the idle barriers */
|
||||
|
||||
for_each_engine(engine, gt, id) {
|
||||
intel_engine_pm_get(engine);
|
||||
unsigned long heartbeat;
|
||||
|
||||
engine_heartbeat_disable(engine, &heartbeat);
|
||||
err = __live_idle_pulse(engine, intel_engine_flush_barriers);
|
||||
intel_engine_pm_put(engine);
|
||||
engine_heartbeat_enable(engine, heartbeat);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
@ -172,9 +192,11 @@ static int live_idle_pulse(void *arg)
|
||||
/* Check that heartbeat pulses flush the idle barriers */
|
||||
|
||||
for_each_engine(engine, gt, id) {
|
||||
intel_engine_pm_get(engine);
|
||||
unsigned long heartbeat;
|
||||
|
||||
engine_heartbeat_disable(engine, &heartbeat);
|
||||
err = __live_idle_pulse(engine, intel_engine_pulse);
|
||||
intel_engine_pm_put(engine);
|
||||
engine_heartbeat_enable(engine, heartbeat);
|
||||
if (err && err != -ENODEV)
|
||||
break;
|
||||
|
||||
|
@ -268,7 +268,7 @@ hang_create_request(struct hang *h, struct intel_engine_cs *engine)
|
||||
|
||||
cancel_rq:
|
||||
if (err) {
|
||||
i915_request_skip(rq, err);
|
||||
i915_request_set_error_once(rq, err);
|
||||
i915_request_add(rq);
|
||||
}
|
||||
unpin_hws:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user