Merge tag 'drm-next-2018-12-14' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie: "Core: - shared fencing staging removal - drop transactional atomic helpers and move helpers to new location - DP/MST atomic cleanup - Leasing cleanups and drop EXPORT_SYMBOL - Convert drivers to atomic helpers and generic fbdev. - removed deprecated obj_ref/unref in favour of get/put - Improve dumb callback documentation - MODESET_LOCK_BEGIN/END helpers panels: - CDTech panels, Banana Pi Panel, DLC1010GIG, - Olimex LCD-O-LinuXino, Samsung S6D16D0, Truly NT35597 WQXGA, - Himax HX8357D, simulated RTSM AEMv8. - GPD Win2 panel - AUO G101EVN010 vgem: - render node support ttm: - move global init out of drivers - fix LRU handling for ghost objects - Support for simultaneous submissions to multiple engines scheduler: - timeout/fault handling changes to help GPU recovery - helpers for hw with preemption support i915: - Scaler/Watermark fixes - DP MST + powerwell fixes - PSR fixes - Break long get/put shmemfs pages - Icelake fixes - Icelake DSI video mode enablement - Engine workaround improvements amdgpu: - freesync support - GPU reset enabled on CI, VI, SOC15 dGPUs - ABM support in DC - KFD support for vega12/polaris12 - SDMA paging queue on vega - More amdkfd code sharing - DCC scanout on GFX9 - DC kerneldoc - Updated SMU firmware for GFX8 chips - XGMI PSP + hive reset support - GPU reset - DC trace support - Powerplay updates for newer Polaris - Cursor plane update fast path - kfd dma-buf support virtio-gpu: - add EDID support vmwgfx: - pageflip with damage support nouveau: - Initial Turing TU104/TU106 modesetting support msm: - a2xx gpu support for apq8060 and imx5 - a2xx gpummu support - mdp4 display support for apq8060 - DPU fixes and cleanups - enhanced profiling support - debug object naming interface - get_iova/page pinning decoupling tegra: - Tegra194 host1x, VIC and display support enabled - Audio over HDMI for Tegra186 and Tegra194 exynos: - DMA/IOMMU refactoring - plane alpha + blend mode support - Color format fixes for mixer driver rcar-du: - R8A7744 and R8A77470 support - R8A77965 LVDS support imx: - fbdev emulation fix - multi-tiled scalling fixes - SPDX identifiers rockchip - dw_hdmi support - dw-mipi-dsi + dual dsi support - mailbox read size fix qxl: - fix cursor pinning vc4: - YUV support (scaling + cursor) v3d: - enable TFU (Texture Formatting Unit) mali-dp: - add support for linear tiled formats sun4i: - Display Engine 3 support - H6 DE3 mixer 0 support - H6 display engine support - dw-hdmi support - H6 HDMI phy support - implicit fence waiting - BGRX8888 support meson: - Overlay plane support - implicit fence waiting - HDMI 1.4 4k modes bridge: - i2c fixes for sii902x" * tag 'drm-next-2018-12-14' of git://anongit.freedesktop.org/drm/drm: (1403 commits) drm/amd/display: Add fast path for cursor plane updates drm/amdgpu: Enable GPU recovery by default for CI drm/amd/display: Fix duplicating scaling/underscan connector state drm/amd/display: Fix unintialized max_bpc state values Revert "drm/amd/display: Set RMX_ASPECT as default" drm/amdgpu: Fix stub function name drm/msm/dpu: Fix clock issue after bind failure drm/msm/dpu: Clean up dpu_media_info.h static inline functions drm/msm/dpu: Further cleanups for static inline functions drm/msm/dpu: Cleanup the debugfs functions drm/msm/dpu: Remove dpu_irq and unused functions drm/msm: Make irq_postinstall optional drm/msm/dpu: Cleanup callers of dpu_hw_blk_init drm/msm/dpu: Remove unused functions drm/msm/dpu: Remove dpu_crtc_is_enabled() drm/msm/dpu: Remove dpu_crtc_get_mixer_height drm/msm/dpu: Remove dpu_dbg drm/msm: dpu: Remove crtc_lock drm/msm: dpu: Remove vblank_requested flag from dpu_crtc drm/msm: dpu: Separate crtc assignment from vblank enable ...
This commit is contained in:
@@ -75,6 +75,7 @@ i915-y += i915_cmd_parser.o \
|
||||
i915_gemfs.o \
|
||||
i915_query.o \
|
||||
i915_request.o \
|
||||
i915_scheduler.o \
|
||||
i915_timeline.o \
|
||||
i915_trace_points.o \
|
||||
i915_vma.o \
|
||||
@@ -112,6 +113,8 @@ i915-y += intel_audio.o \
|
||||
intel_bios.o \
|
||||
intel_cdclk.o \
|
||||
intel_color.o \
|
||||
intel_combo_phy.o \
|
||||
intel_connector.o \
|
||||
intel_display.o \
|
||||
intel_dpio_phy.o \
|
||||
intel_dpll_mgr.o \
|
||||
@@ -120,9 +123,9 @@ i915-y += intel_audio.o \
|
||||
intel_frontbuffer.o \
|
||||
intel_hdcp.o \
|
||||
intel_hotplug.o \
|
||||
intel_modes.o \
|
||||
intel_overlay.o \
|
||||
intel_psr.o \
|
||||
intel_quirks.o \
|
||||
intel_sideband.o \
|
||||
intel_sprite.o
|
||||
i915-$(CONFIG_ACPI) += intel_acpi.o intel_opregion.o
|
||||
@@ -142,6 +145,7 @@ i915-y += dvo_ch7017.o \
|
||||
intel_dp_link_training.o \
|
||||
intel_dp_mst.o \
|
||||
intel_dp.o \
|
||||
intel_dsi.o \
|
||||
intel_dsi_dcs_backlight.o \
|
||||
intel_dsi_vbt.o \
|
||||
intel_dvo.o \
|
||||
@@ -153,14 +157,17 @@ i915-y += dvo_ch7017.o \
|
||||
intel_sdvo.o \
|
||||
intel_tv.o \
|
||||
vlv_dsi.o \
|
||||
vlv_dsi_pll.o
|
||||
vlv_dsi_pll.o \
|
||||
intel_vdsc.o
|
||||
|
||||
# Post-mortem debug and GPU hang state capture
|
||||
i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
|
||||
i915-$(CONFIG_DRM_I915_SELFTEST) += \
|
||||
selftests/i915_random.o \
|
||||
selftests/i915_selftest.o \
|
||||
selftests/igt_flush_test.o
|
||||
selftests/igt_flush_test.o \
|
||||
selftests/igt_reset.o \
|
||||
selftests/igt_spinner.o
|
||||
|
||||
# virtual gpu code
|
||||
i915-y += i915_vgpu.o
|
||||
|
@@ -334,6 +334,28 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
|
||||
i915_gem_object_put(wa_ctx->indirect_ctx.obj);
|
||||
}
|
||||
|
||||
static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
|
||||
struct i915_gem_context *ctx)
|
||||
{
|
||||
struct intel_vgpu_mm *mm = workload->shadow_mm;
|
||||
struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
|
||||
int i = 0;
|
||||
|
||||
if (mm->type != INTEL_GVT_MM_PPGTT || !mm->ppgtt_mm.shadowed)
|
||||
return -1;
|
||||
|
||||
if (mm->ppgtt_mm.root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
|
||||
px_dma(&ppgtt->pml4) = mm->ppgtt_mm.shadow_pdps[0];
|
||||
} else {
|
||||
for (i = 0; i < GVT_RING_CTX_NR_PDPS; i++) {
|
||||
px_dma(ppgtt->pdp.page_directory[i]) =
|
||||
mm->ppgtt_mm.shadow_pdps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_gvt_scan_and_shadow_workload - audit the workload by scanning and
|
||||
* shadow it as well, include ringbuffer,wa_ctx and ctx.
|
||||
@@ -358,6 +380,12 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
|
||||
if (workload->req)
|
||||
return 0;
|
||||
|
||||
ret = set_context_ppgtt_from_shadow(workload, shadow_ctx);
|
||||
if (ret < 0) {
|
||||
gvt_vgpu_err("workload shadow ppgtt isn't ready\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* pin shadow context by gvt even the shadow context will be pinned
|
||||
* when i915 alloc request. That is because gvt will update the guest
|
||||
* context from shadow context when workload is completed, and at that
|
||||
|
@@ -943,30 +943,30 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
|
||||
static ssize_t gpu_state_read(struct file *file, char __user *ubuf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
struct i915_gpu_state *error = file->private_data;
|
||||
struct drm_i915_error_state_buf str;
|
||||
struct i915_gpu_state *error;
|
||||
ssize_t ret;
|
||||
loff_t tmp;
|
||||
void *buf;
|
||||
|
||||
error = file->private_data;
|
||||
if (!error)
|
||||
return 0;
|
||||
|
||||
ret = i915_error_state_buf_init(&str, error->i915, count, *pos);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Bounce buffer required because of kernfs __user API convenience. */
|
||||
buf = kmalloc(count, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = i915_error_state_to_str(&str, error);
|
||||
if (ret)
|
||||
ret = i915_gpu_state_copy_to_buffer(error, buf, *pos, count);
|
||||
if (ret <= 0)
|
||||
goto out;
|
||||
|
||||
tmp = 0;
|
||||
ret = simple_read_from_buffer(ubuf, count, &tmp, str.buf, str.bytes);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (!copy_to_user(ubuf, buf, ret))
|
||||
*pos += ret;
|
||||
else
|
||||
ret = -EFAULT;
|
||||
|
||||
*pos = str.start + ret;
|
||||
out:
|
||||
i915_error_state_buf_release(&str);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1788,6 +1788,8 @@ static int i915_emon_status(struct seq_file *m, void *unused)
|
||||
if (!IS_GEN5(dev_priv))
|
||||
return -ENODEV;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1802,6 +1804,8 @@ static int i915_emon_status(struct seq_file *m, void *unused)
|
||||
seq_printf(m, "GFX power: %ld\n", gfx);
|
||||
seq_printf(m, "Total power: %ld\n", chipset + gfx);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2215,8 +2219,23 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
|
||||
struct drm_i915_private *dev_priv = node_to_i915(m->private);
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
struct intel_rps *rps = &dev_priv->gt_pm.rps;
|
||||
u32 act_freq = rps->cur_freq;
|
||||
struct drm_file *file;
|
||||
|
||||
if (intel_runtime_pm_get_if_in_use(dev_priv)) {
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
act_freq = vlv_punit_read(dev_priv,
|
||||
PUNIT_REG_GPU_FREQ_STS);
|
||||
act_freq = (act_freq >> 8) & 0xff;
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
} else {
|
||||
act_freq = intel_get_cagf(dev_priv,
|
||||
I915_READ(GEN6_RPSTAT1));
|
||||
}
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
}
|
||||
|
||||
seq_printf(m, "RPS enabled? %d\n", rps->enabled);
|
||||
seq_printf(m, "GPU busy? %s [%d requests]\n",
|
||||
yesno(dev_priv->gt.awake), dev_priv->gt.active_requests);
|
||||
@@ -2224,8 +2243,9 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
|
||||
seq_printf(m, "Boosts outstanding? %d\n",
|
||||
atomic_read(&rps->num_waiters));
|
||||
seq_printf(m, "Interactive? %d\n", READ_ONCE(rps->power.interactive));
|
||||
seq_printf(m, "Frequency requested %d\n",
|
||||
intel_gpu_freq(dev_priv, rps->cur_freq));
|
||||
seq_printf(m, "Frequency requested %d, actual %d\n",
|
||||
intel_gpu_freq(dev_priv, rps->cur_freq),
|
||||
intel_gpu_freq(dev_priv, act_freq));
|
||||
seq_printf(m, " min hard:%d, soft:%d; max soft:%d, hard:%d\n",
|
||||
intel_gpu_freq(dev_priv, rps->min_freq),
|
||||
intel_gpu_freq(dev_priv, rps->min_freq_softlimit),
|
||||
@@ -2900,16 +2920,15 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
|
||||
seq_printf(m, "version: %d.%d\n", CSR_VERSION_MAJOR(csr->version),
|
||||
CSR_VERSION_MINOR(csr->version));
|
||||
|
||||
if (IS_KABYLAKE(dev_priv) ||
|
||||
(IS_SKYLAKE(dev_priv) && csr->version >= CSR_VERSION(1, 6))) {
|
||||
seq_printf(m, "DC3 -> DC5 count: %d\n",
|
||||
I915_READ(SKL_CSR_DC3_DC5_COUNT));
|
||||
if (WARN_ON(INTEL_GEN(dev_priv) > 11))
|
||||
goto out;
|
||||
|
||||
seq_printf(m, "DC3 -> DC5 count: %d\n",
|
||||
I915_READ(IS_BROXTON(dev_priv) ? BXT_CSR_DC3_DC5_COUNT :
|
||||
SKL_CSR_DC3_DC5_COUNT));
|
||||
if (!IS_GEN9_LP(dev_priv))
|
||||
seq_printf(m, "DC5 -> DC6 count: %d\n",
|
||||
I915_READ(SKL_CSR_DC5_DC6_COUNT));
|
||||
} else if (IS_BROXTON(dev_priv) && csr->version >= CSR_VERSION(1, 4)) {
|
||||
seq_printf(m, "DC3 -> DC5 count: %d\n",
|
||||
I915_READ(BXT_CSR_DC3_DC5_COUNT));
|
||||
}
|
||||
|
||||
out:
|
||||
seq_printf(m, "program base: 0x%08x\n", I915_READ(CSR_PROGRAM(0)));
|
||||
@@ -3049,16 +3068,17 @@ static void intel_connector_info(struct seq_file *m,
|
||||
seq_printf(m, "connector %d: type %s, status: %s\n",
|
||||
connector->base.id, connector->name,
|
||||
drm_get_connector_status_name(connector->status));
|
||||
if (connector->status == connector_status_connected) {
|
||||
seq_printf(m, "\tname: %s\n", connector->display_info.name);
|
||||
seq_printf(m, "\tphysical dimensions: %dx%dmm\n",
|
||||
connector->display_info.width_mm,
|
||||
connector->display_info.height_mm);
|
||||
seq_printf(m, "\tsubpixel order: %s\n",
|
||||
drm_get_subpixel_order_name(connector->display_info.subpixel_order));
|
||||
seq_printf(m, "\tCEA rev: %d\n",
|
||||
connector->display_info.cea_rev);
|
||||
}
|
||||
|
||||
if (connector->status == connector_status_disconnected)
|
||||
return;
|
||||
|
||||
seq_printf(m, "\tname: %s\n", connector->display_info.name);
|
||||
seq_printf(m, "\tphysical dimensions: %dx%dmm\n",
|
||||
connector->display_info.width_mm,
|
||||
connector->display_info.height_mm);
|
||||
seq_printf(m, "\tsubpixel order: %s\n",
|
||||
drm_get_subpixel_order_name(connector->display_info.subpixel_order));
|
||||
seq_printf(m, "\tCEA rev: %d\n", connector->display_info.cea_rev);
|
||||
|
||||
if (!intel_encoder)
|
||||
return;
|
||||
@@ -3355,13 +3375,15 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
|
||||
|
||||
static int i915_wa_registers(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct i915_workarounds *wa = &node_to_i915(m->private)->workarounds;
|
||||
int i;
|
||||
struct drm_i915_private *i915 = node_to_i915(m->private);
|
||||
const struct i915_wa_list *wal = &i915->engine[RCS]->ctx_wa_list;
|
||||
struct i915_wa *wa;
|
||||
unsigned int i;
|
||||
|
||||
seq_printf(m, "Workarounds applied: %d\n", wa->count);
|
||||
for (i = 0; i < wa->count; ++i)
|
||||
seq_printf(m, "Workarounds applied: %u\n", wal->count);
|
||||
for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
|
||||
seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n",
|
||||
wa->reg[i].addr, wa->reg[i].value, wa->reg[i].mask);
|
||||
i915_mmio_reg_offset(wa->reg), wa->val, wa->mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3421,31 +3443,32 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = node_to_i915(m->private);
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
struct skl_ddb_allocation *ddb;
|
||||
struct skl_ddb_entry *entry;
|
||||
enum pipe pipe;
|
||||
int plane;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
if (INTEL_GEN(dev_priv) < 9)
|
||||
return -ENODEV;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
|
||||
ddb = &dev_priv->wm.skl_hw.ddb;
|
||||
|
||||
seq_printf(m, "%-15s%8s%8s%8s\n", "", "Start", "End", "Size");
|
||||
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
for_each_intel_crtc(&dev_priv->drm, crtc) {
|
||||
struct intel_crtc_state *crtc_state =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
enum plane_id plane_id;
|
||||
|
||||
seq_printf(m, "Pipe %c\n", pipe_name(pipe));
|
||||
|
||||
for_each_universal_plane(dev_priv, pipe, plane) {
|
||||
entry = &ddb->plane[pipe][plane];
|
||||
seq_printf(m, " Plane%-8d%8u%8u%8u\n", plane + 1,
|
||||
for_each_plane_id_on_crtc(crtc, plane_id) {
|
||||
entry = &crtc_state->wm.skl.plane_ddb_y[plane_id];
|
||||
seq_printf(m, " Plane%-8d%8u%8u%8u\n", plane_id + 1,
|
||||
entry->start, entry->end,
|
||||
skl_ddb_entry_size(entry));
|
||||
}
|
||||
|
||||
entry = &ddb->plane[pipe][PLANE_CURSOR];
|
||||
entry = &crtc_state->wm.skl.plane_ddb_y[PLANE_CURSOR];
|
||||
seq_printf(m, " %-13s%8u%8u%8u\n", "Cursor", entry->start,
|
||||
entry->end, skl_ddb_entry_size(entry));
|
||||
}
|
||||
@@ -4172,6 +4195,7 @@ i915_drop_caches_set(void *data, u64 val)
|
||||
|
||||
DRM_DEBUG("Dropping caches: 0x%08llx [0x%08llx]\n",
|
||||
val, val & DROP_ALL);
|
||||
intel_runtime_pm_get(i915);
|
||||
|
||||
if (val & DROP_RESET_ACTIVE && !intel_engines_are_idle(i915))
|
||||
i915_gem_set_wedged(i915);
|
||||
@@ -4181,7 +4205,7 @@ i915_drop_caches_set(void *data, u64 val)
|
||||
if (val & (DROP_ACTIVE | DROP_RETIRE | DROP_RESET_SEQNO)) {
|
||||
ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
if (val & DROP_ACTIVE)
|
||||
ret = i915_gem_wait_for_idle(i915,
|
||||
@@ -4189,11 +4213,8 @@ i915_drop_caches_set(void *data, u64 val)
|
||||
I915_WAIT_LOCKED,
|
||||
MAX_SCHEDULE_TIMEOUT);
|
||||
|
||||
if (ret == 0 && val & DROP_RESET_SEQNO) {
|
||||
intel_runtime_pm_get(i915);
|
||||
if (ret == 0 && val & DROP_RESET_SEQNO)
|
||||
ret = i915_gem_set_global_seqno(&i915->drm, 1);
|
||||
intel_runtime_pm_put(i915);
|
||||
}
|
||||
|
||||
if (val & DROP_RETIRE)
|
||||
i915_retire_requests(i915);
|
||||
@@ -4231,6 +4252,9 @@ i915_drop_caches_set(void *data, u64 val)
|
||||
if (val & DROP_FREED)
|
||||
i915_gem_drain_freed_objects(i915);
|
||||
|
||||
out:
|
||||
intel_runtime_pm_put(i915);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -4331,7 +4355,7 @@ static void gen10_sseu_device_status(struct drm_i915_private *dev_priv,
|
||||
for (s = 0; s < info->sseu.max_slices; s++) {
|
||||
/*
|
||||
* FIXME: Valid SS Mask respects the spec and read
|
||||
* only valid bits for those registers, excluding reserverd
|
||||
* only valid bits for those registers, excluding reserved
|
||||
* although this seems wrong because it would leave many
|
||||
* subslices without ACK.
|
||||
*/
|
||||
@@ -4571,6 +4595,13 @@ static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data)
|
||||
struct drm_i915_private *dev_priv = m->private;
|
||||
struct i915_hotplug *hotplug = &dev_priv->hotplug;
|
||||
|
||||
/* Synchronize with everything first in case there's been an HPD
|
||||
* storm, but we haven't finished handling it in the kernel yet
|
||||
*/
|
||||
synchronize_irq(dev_priv->drm.irq);
|
||||
flush_work(&dev_priv->hotplug.dig_port_work);
|
||||
flush_work(&dev_priv->hotplug.hotplug_work);
|
||||
|
||||
seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold);
|
||||
seq_printf(m, "Detected: %s\n",
|
||||
yesno(delayed_work_pending(&hotplug->reenable_work)));
|
||||
@@ -4641,24 +4672,122 @@ static const struct file_operations i915_hpd_storm_ctl_fops = {
|
||||
.write = i915_hpd_storm_ctl_write
|
||||
};
|
||||
|
||||
static int i915_hpd_short_storm_ctl_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = m->private;
|
||||
|
||||
seq_printf(m, "Enabled: %s\n",
|
||||
yesno(dev_priv->hotplug.hpd_short_storm_enabled));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_hpd_short_storm_ctl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, i915_hpd_short_storm_ctl_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t i915_hpd_short_storm_ctl_write(struct file *file,
|
||||
const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
struct drm_i915_private *dev_priv = m->private;
|
||||
struct i915_hotplug *hotplug = &dev_priv->hotplug;
|
||||
char *newline;
|
||||
char tmp[16];
|
||||
int i;
|
||||
bool new_state;
|
||||
|
||||
if (len >= sizeof(tmp))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(tmp, ubuf, len))
|
||||
return -EFAULT;
|
||||
|
||||
tmp[len] = '\0';
|
||||
|
||||
/* Strip newline, if any */
|
||||
newline = strchr(tmp, '\n');
|
||||
if (newline)
|
||||
*newline = '\0';
|
||||
|
||||
/* Reset to the "default" state for this system */
|
||||
if (strcmp(tmp, "reset") == 0)
|
||||
new_state = !HAS_DP_MST(dev_priv);
|
||||
else if (kstrtobool(tmp, &new_state) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG_KMS("%sabling HPD short storm detection\n",
|
||||
new_state ? "En" : "Dis");
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
hotplug->hpd_short_storm_enabled = new_state;
|
||||
/* Reset the HPD storm stats so we don't accidentally trigger a storm */
|
||||
for_each_hpd_pin(i)
|
||||
hotplug->stats[i].count = 0;
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
|
||||
/* Re-enable hpd immediately if we were in an irq storm */
|
||||
flush_delayed_work(&dev_priv->hotplug.reenable_work);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations i915_hpd_short_storm_ctl_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = i915_hpd_short_storm_ctl_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.write = i915_hpd_short_storm_ctl_write,
|
||||
};
|
||||
|
||||
static int i915_drrs_ctl_set(void *data, u64 val)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = data;
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
struct intel_crtc *intel_crtc;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_dp *intel_dp;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
if (INTEL_GEN(dev_priv) < 7)
|
||||
return -ENODEV;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
for_each_intel_crtc(dev, intel_crtc) {
|
||||
if (!intel_crtc->base.state->active ||
|
||||
!intel_crtc->config->has_drrs)
|
||||
continue;
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_crtc_commit *commit;
|
||||
int ret;
|
||||
|
||||
for_each_encoder_on_crtc(dev, &intel_crtc->base, encoder) {
|
||||
ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state = to_intel_crtc_state(crtc->base.state);
|
||||
|
||||
if (!crtc_state->base.active ||
|
||||
!crtc_state->has_drrs)
|
||||
goto out;
|
||||
|
||||
commit = crtc_state->base.commit;
|
||||
if (commit) {
|
||||
ret = wait_for_completion_interruptible(&commit->hw_done);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
if (!(crtc_state->base.connector_mask &
|
||||
drm_connector_mask(connector)))
|
||||
continue;
|
||||
|
||||
encoder = intel_attached_encoder(connector);
|
||||
if (encoder->type != INTEL_OUTPUT_EDP)
|
||||
continue;
|
||||
|
||||
@@ -4668,13 +4797,18 @@ static int i915_drrs_ctl_set(void *data, u64 val)
|
||||
intel_dp = enc_to_intel_dp(&encoder->base);
|
||||
if (val)
|
||||
intel_edp_drrs_enable(intel_dp,
|
||||
intel_crtc->config);
|
||||
crtc_state);
|
||||
else
|
||||
intel_edp_drrs_disable(intel_dp,
|
||||
intel_crtc->config);
|
||||
crtc_state);
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
||||
out:
|
||||
drm_modeset_unlock(&crtc->base.mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4818,6 +4952,7 @@ static const struct i915_debugfs_files {
|
||||
{"i915_guc_log_level", &i915_guc_log_level_fops},
|
||||
{"i915_guc_log_relay", &i915_guc_log_relay_fops},
|
||||
{"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops},
|
||||
{"i915_hpd_short_storm_ctl", &i915_hpd_short_storm_ctl_fops},
|
||||
{"i915_ipc_status", &i915_ipc_status_fops},
|
||||
{"i915_drrs_ctl", &i915_drrs_ctl_fops},
|
||||
{"i915_edp_psr_debug", &i915_edp_psr_debug_fops}
|
||||
@@ -4899,13 +5034,10 @@ static int i915_dpcd_show(struct seq_file *m, void *data)
|
||||
continue;
|
||||
|
||||
err = drm_dp_dpcd_read(&intel_dp->aux, b->offset, buf, size);
|
||||
if (err <= 0) {
|
||||
DRM_ERROR("dpcd read (%zu bytes at %u) failed (%zd)\n",
|
||||
size, b->offset, err);
|
||||
continue;
|
||||
}
|
||||
|
||||
seq_printf(m, "%04x: %*ph\n", b->offset, (int) size, buf);
|
||||
if (err < 0)
|
||||
seq_printf(m, "%04x: ERROR %d\n", b->offset, (int)err);
|
||||
else
|
||||
seq_printf(m, "%04x: %*ph\n", b->offset, (int)err, buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -4934,6 +5066,28 @@ static int i915_panel_show(struct seq_file *m, void *data)
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(i915_panel);
|
||||
|
||||
static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_connector *connector = m->private;
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
|
||||
if (connector->status != connector_status_connected)
|
||||
return -ENODEV;
|
||||
|
||||
/* HDCP is supported by connector */
|
||||
if (!intel_connector->hdcp.shim)
|
||||
return -EINVAL;
|
||||
|
||||
seq_printf(m, "%s:%d HDCP version: ", connector->name,
|
||||
connector->base.id);
|
||||
seq_printf(m, "%s ", !intel_hdcp_capable(intel_connector) ?
|
||||
"None" : "HDCP1.4");
|
||||
seq_puts(m, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability);
|
||||
|
||||
/**
|
||||
* i915_debugfs_connector_add - add i915 specific connector debugfs files
|
||||
* @connector: pointer to a registered drm_connector
|
||||
@@ -4963,5 +5117,12 @@ int i915_debugfs_connector_add(struct drm_connector *connector)
|
||||
connector, &i915_psr_sink_status_fops);
|
||||
}
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
|
||||
debugfs_create_file("i915_hdcp_sink_capability", S_IRUGO, root,
|
||||
connector, &i915_hdcp_sink_capability_fops);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -53,6 +53,7 @@
|
||||
#include "i915_vgpu.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_uc.h"
|
||||
#include "intel_workarounds.h"
|
||||
|
||||
static struct drm_driver driver;
|
||||
|
||||
@@ -287,7 +288,7 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv)
|
||||
* Use PCH_NOP (PCH but no South Display) for PCH platforms without
|
||||
* display.
|
||||
*/
|
||||
if (pch && INTEL_INFO(dev_priv)->num_pipes == 0) {
|
||||
if (pch && !HAS_DISPLAY(dev_priv)) {
|
||||
DRM_DEBUG_KMS("Display disabled, reverting to NOP PCH\n");
|
||||
dev_priv->pch_type = PCH_NOP;
|
||||
dev_priv->pch_id = 0;
|
||||
@@ -345,7 +346,7 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
|
||||
value = HAS_WT(dev_priv);
|
||||
break;
|
||||
case I915_PARAM_HAS_ALIASING_PPGTT:
|
||||
value = USES_PPGTT(dev_priv);
|
||||
value = min_t(int, INTEL_PPGTT(dev_priv), I915_GEM_PPGTT_FULL);
|
||||
break;
|
||||
case I915_PARAM_HAS_SEMAPHORES:
|
||||
value = HAS_LEGACY_SEMAPHORES(dev_priv);
|
||||
@@ -645,6 +646,13 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
||||
if (i915_inject_load_failure())
|
||||
return -ENODEV;
|
||||
|
||||
if (HAS_DISPLAY(dev_priv)) {
|
||||
ret = drm_vblank_init(&dev_priv->drm,
|
||||
INTEL_INFO(dev_priv)->num_pipes);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
intel_bios_init(dev_priv);
|
||||
|
||||
/* If we have > 1 VGA cards, then we need to arbitrate access
|
||||
@@ -687,9 +695,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
||||
if (ret)
|
||||
goto cleanup_modeset;
|
||||
|
||||
intel_setup_overlay(dev_priv);
|
||||
intel_overlay_setup(dev_priv);
|
||||
|
||||
if (INTEL_INFO(dev_priv)->num_pipes == 0)
|
||||
if (!HAS_DISPLAY(dev_priv))
|
||||
return 0;
|
||||
|
||||
ret = intel_fbdev_init(dev);
|
||||
@@ -699,6 +707,8 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
||||
/* Only enable hotplug handling once the fbdev is fully set up. */
|
||||
intel_hpd_init(dev_priv);
|
||||
|
||||
intel_init_ipc(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_gem:
|
||||
@@ -859,6 +869,7 @@ static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv)
|
||||
pre |= IS_HSW_EARLY_SDV(dev_priv);
|
||||
pre |= IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0);
|
||||
pre |= IS_BXT_REVID(dev_priv, 0, BXT_REVID_B_LAST);
|
||||
pre |= IS_KBL_REVID(dev_priv, 0, KBL_REVID_A0);
|
||||
|
||||
if (pre) {
|
||||
DRM_ERROR("This is a pre-production stepping. "
|
||||
@@ -1030,6 +1041,7 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
|
||||
|
||||
err_uncore:
|
||||
intel_uncore_fini(dev_priv);
|
||||
i915_mmio_cleanup(dev_priv);
|
||||
err_bridge:
|
||||
pci_dev_put(dev_priv->bridge_dev);
|
||||
|
||||
@@ -1049,17 +1061,6 @@ static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
|
||||
|
||||
static void intel_sanitize_options(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
/*
|
||||
* i915.enable_ppgtt is read-only, so do an early pass to validate the
|
||||
* user's requested state against the hardware/driver capabilities. We
|
||||
* do this now so that we can print out any log messages once rather
|
||||
* than every time we check intel_enable_ppgtt().
|
||||
*/
|
||||
i915_modparams.enable_ppgtt =
|
||||
intel_sanitize_enable_ppgtt(dev_priv,
|
||||
i915_modparams.enable_ppgtt);
|
||||
DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915_modparams.enable_ppgtt);
|
||||
|
||||
intel_gvt_sanitize_options(dev_priv);
|
||||
}
|
||||
|
||||
@@ -1340,7 +1341,7 @@ intel_get_dram_info(struct drm_i915_private *dev_priv)
|
||||
/* Need to calculate bandwidth only for Gen9 */
|
||||
if (IS_BROXTON(dev_priv))
|
||||
ret = bxt_get_dram_info(dev_priv);
|
||||
else if (INTEL_GEN(dev_priv) == 9)
|
||||
else if (IS_GEN9(dev_priv))
|
||||
ret = skl_get_dram_info(dev_priv);
|
||||
else
|
||||
ret = skl_dram_get_channels_info(dev_priv);
|
||||
@@ -1375,6 +1376,29 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
|
||||
|
||||
intel_device_info_runtime_init(mkwrite_device_info(dev_priv));
|
||||
|
||||
if (HAS_PPGTT(dev_priv)) {
|
||||
if (intel_vgpu_active(dev_priv) &&
|
||||
!intel_vgpu_has_full_48bit_ppgtt(dev_priv)) {
|
||||
i915_report_error(dev_priv,
|
||||
"incompatible vGPU found, support for isolated ppGTT required\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_EXECLISTS(dev_priv)) {
|
||||
/*
|
||||
* Older GVT emulation depends upon intercepting CSB mmio,
|
||||
* which we no longer use, preferring to use the HWSP cache
|
||||
* instead.
|
||||
*/
|
||||
if (intel_vgpu_active(dev_priv) &&
|
||||
!intel_vgpu_has_hwsp_emulation(dev_priv)) {
|
||||
i915_report_error(dev_priv,
|
||||
"old vGPU host found, support for HWSP emulation required\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
intel_sanitize_options(dev_priv);
|
||||
|
||||
i915_perf_init(dev_priv);
|
||||
@@ -1544,7 +1568,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
|
||||
} else
|
||||
DRM_ERROR("Failed to register driver for userspace access!\n");
|
||||
|
||||
if (INTEL_INFO(dev_priv)->num_pipes) {
|
||||
if (HAS_DISPLAY(dev_priv)) {
|
||||
/* Must be done after probing outputs */
|
||||
intel_opregion_register(dev_priv);
|
||||
acpi_video_register();
|
||||
@@ -1568,7 +1592,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
|
||||
* We need to coordinate the hotplugs with the asynchronous fbdev
|
||||
* configuration, for which we use the fbdev->async_cookie.
|
||||
*/
|
||||
if (INTEL_INFO(dev_priv)->num_pipes)
|
||||
if (HAS_DISPLAY(dev_priv))
|
||||
drm_kms_helper_poll_init(dev);
|
||||
|
||||
intel_power_domains_enable(dev_priv);
|
||||
@@ -1631,14 +1655,16 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
(struct intel_device_info *)ent->driver_data;
|
||||
struct intel_device_info *device_info;
|
||||
struct drm_i915_private *i915;
|
||||
int err;
|
||||
|
||||
i915 = kzalloc(sizeof(*i915), GFP_KERNEL);
|
||||
if (!i915)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (drm_dev_init(&i915->drm, &driver, &pdev->dev)) {
|
||||
err = drm_dev_init(&i915->drm, &driver, &pdev->dev);
|
||||
if (err) {
|
||||
kfree(i915);
|
||||
return NULL;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
i915->drm.pdev = pdev;
|
||||
@@ -1651,8 +1677,8 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
device_info->device_id = pdev->device;
|
||||
|
||||
BUILD_BUG_ON(INTEL_MAX_PLATFORMS >
|
||||
sizeof(device_info->platform_mask) * BITS_PER_BYTE);
|
||||
BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE);
|
||||
BITS_PER_TYPE(device_info->platform_mask));
|
||||
BUG_ON(device_info->gen > BITS_PER_TYPE(device_info->gen_mask));
|
||||
|
||||
return i915;
|
||||
}
|
||||
@@ -1687,8 +1713,8 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
int ret;
|
||||
|
||||
dev_priv = i915_driver_create(pdev, ent);
|
||||
if (!dev_priv)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(dev_priv))
|
||||
return PTR_ERR(dev_priv);
|
||||
|
||||
/* Disable nuclear pageflip by default on pre-ILK */
|
||||
if (!i915_modparams.nuclear_pageflip && match_info->gen < 5)
|
||||
@@ -1712,26 +1738,12 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (ret < 0)
|
||||
goto out_cleanup_mmio;
|
||||
|
||||
/*
|
||||
* TODO: move the vblank init and parts of modeset init steps into one
|
||||
* of the i915_driver_init_/i915_driver_register functions according
|
||||
* to the role/effect of the given init step.
|
||||
*/
|
||||
if (INTEL_INFO(dev_priv)->num_pipes) {
|
||||
ret = drm_vblank_init(&dev_priv->drm,
|
||||
INTEL_INFO(dev_priv)->num_pipes);
|
||||
if (ret)
|
||||
goto out_cleanup_hw;
|
||||
}
|
||||
|
||||
ret = i915_load_modeset_init(&dev_priv->drm);
|
||||
if (ret < 0)
|
||||
goto out_cleanup_hw;
|
||||
|
||||
i915_driver_register(dev_priv);
|
||||
|
||||
intel_init_ipc(dev_priv);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
i915_welcome_messages(dev_priv);
|
||||
@@ -1783,7 +1795,6 @@ void i915_driver_unload(struct drm_device *dev)
|
||||
i915_reset_error_state(dev_priv);
|
||||
|
||||
i915_gem_fini(dev_priv);
|
||||
intel_fbc_cleanup_cfb(dev_priv);
|
||||
|
||||
intel_power_domains_fini_hw(dev_priv);
|
||||
|
||||
@@ -1921,9 +1932,7 @@ static int i915_drm_suspend(struct drm_device *dev)
|
||||
i915_save_state(dev_priv);
|
||||
|
||||
opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
|
||||
intel_opregion_notify_adapter(dev_priv, opregion_target_state);
|
||||
|
||||
intel_opregion_unregister(dev_priv);
|
||||
intel_opregion_suspend(dev_priv, opregion_target_state);
|
||||
|
||||
intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
|
||||
|
||||
@@ -1964,7 +1973,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
|
||||
get_suspend_mode(dev_priv, hibernation));
|
||||
|
||||
ret = 0;
|
||||
if (IS_GEN9_LP(dev_priv))
|
||||
if (INTEL_GEN(dev_priv) >= 11 || IS_GEN9_LP(dev_priv))
|
||||
bxt_enable_dc9(dev_priv);
|
||||
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
hsw_enable_pc8(dev_priv);
|
||||
@@ -2042,7 +2051,6 @@ static int i915_drm_resume(struct drm_device *dev)
|
||||
|
||||
i915_restore_state(dev_priv);
|
||||
intel_pps_unlock_regs_wa(dev_priv);
|
||||
intel_opregion_setup(dev_priv);
|
||||
|
||||
intel_init_pch_refclk(dev_priv);
|
||||
|
||||
@@ -2084,12 +2092,10 @@ static int i915_drm_resume(struct drm_device *dev)
|
||||
* */
|
||||
intel_hpd_init(dev_priv);
|
||||
|
||||
intel_opregion_register(dev_priv);
|
||||
intel_opregion_resume(dev_priv);
|
||||
|
||||
intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
|
||||
|
||||
intel_opregion_notify_adapter(dev_priv, PCI_D0);
|
||||
|
||||
intel_power_domains_enable(dev_priv);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
@@ -2157,7 +2163,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
|
||||
|
||||
intel_uncore_resume_early(dev_priv);
|
||||
|
||||
if (IS_GEN9_LP(dev_priv)) {
|
||||
if (INTEL_GEN(dev_priv) >= 11 || IS_GEN9_LP(dev_priv)) {
|
||||
gen9_sanitize_dc_state(dev_priv);
|
||||
bxt_disable_dc9(dev_priv);
|
||||
} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
|
||||
@@ -2924,7 +2930,10 @@ static int intel_runtime_suspend(struct device *kdev)
|
||||
intel_uncore_suspend(dev_priv);
|
||||
|
||||
ret = 0;
|
||||
if (IS_GEN9_LP(dev_priv)) {
|
||||
if (INTEL_GEN(dev_priv) >= 11) {
|
||||
icl_display_core_uninit(dev_priv);
|
||||
bxt_enable_dc9(dev_priv);
|
||||
} else if (IS_GEN9_LP(dev_priv)) {
|
||||
bxt_display_core_uninit(dev_priv);
|
||||
bxt_enable_dc9(dev_priv);
|
||||
} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
|
||||
@@ -3009,7 +3018,18 @@ static int intel_runtime_resume(struct device *kdev)
|
||||
if (intel_uncore_unclaimed_mmio(dev_priv))
|
||||
DRM_DEBUG_DRIVER("Unclaimed access during suspend, bios?\n");
|
||||
|
||||
if (IS_GEN9_LP(dev_priv)) {
|
||||
if (INTEL_GEN(dev_priv) >= 11) {
|
||||
bxt_disable_dc9(dev_priv);
|
||||
icl_display_core_init(dev_priv, true);
|
||||
if (dev_priv->csr.dmc_payload) {
|
||||
if (dev_priv->csr.allowed_dc_mask &
|
||||
DC_STATE_EN_UPTO_DC6)
|
||||
skl_enable_dc6(dev_priv);
|
||||
else if (dev_priv->csr.allowed_dc_mask &
|
||||
DC_STATE_EN_UPTO_DC5)
|
||||
gen9_enable_dc5(dev_priv);
|
||||
}
|
||||
} else if (IS_GEN9_LP(dev_priv)) {
|
||||
bxt_disable_dc9(dev_priv);
|
||||
bxt_display_core_init(dev_priv, true);
|
||||
if (dev_priv->csr.dmc_payload &&
|
||||
|
@@ -53,7 +53,9 @@
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_cache.h>
|
||||
#include <drm/drm_util.h>
|
||||
#include <drm/drm_dsc.h>
|
||||
|
||||
#include "i915_fixed.h"
|
||||
#include "i915_params.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_utils.h"
|
||||
@@ -88,8 +90,8 @@
|
||||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20180921"
|
||||
#define DRIVER_TIMESTAMP 1537521997
|
||||
#define DRIVER_DATE "20181204"
|
||||
#define DRIVER_TIMESTAMP 1543944377
|
||||
|
||||
/* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and
|
||||
* WARN_ON()) for hw state sanity checks to check for unexpected conditions
|
||||
@@ -128,144 +130,6 @@ bool i915_error_injected(void);
|
||||
__i915_printk(i915, i915_error_injected() ? KERN_DEBUG : KERN_ERR, \
|
||||
fmt, ##__VA_ARGS__)
|
||||
|
||||
typedef struct {
|
||||
uint32_t val;
|
||||
} uint_fixed_16_16_t;
|
||||
|
||||
#define FP_16_16_MAX ({ \
|
||||
uint_fixed_16_16_t fp; \
|
||||
fp.val = UINT_MAX; \
|
||||
fp; \
|
||||
})
|
||||
|
||||
static inline bool is_fixed16_zero(uint_fixed_16_16_t val)
|
||||
{
|
||||
if (val.val == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t u32_to_fixed16(uint32_t val)
|
||||
{
|
||||
uint_fixed_16_16_t fp;
|
||||
|
||||
WARN_ON(val > U16_MAX);
|
||||
|
||||
fp.val = val << 16;
|
||||
return fp;
|
||||
}
|
||||
|
||||
static inline uint32_t fixed16_to_u32_round_up(uint_fixed_16_16_t fp)
|
||||
{
|
||||
return DIV_ROUND_UP(fp.val, 1 << 16);
|
||||
}
|
||||
|
||||
static inline uint32_t fixed16_to_u32(uint_fixed_16_16_t fp)
|
||||
{
|
||||
return fp.val >> 16;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t min_fixed16(uint_fixed_16_16_t min1,
|
||||
uint_fixed_16_16_t min2)
|
||||
{
|
||||
uint_fixed_16_16_t min;
|
||||
|
||||
min.val = min(min1.val, min2.val);
|
||||
return min;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t max_fixed16(uint_fixed_16_16_t max1,
|
||||
uint_fixed_16_16_t max2)
|
||||
{
|
||||
uint_fixed_16_16_t max;
|
||||
|
||||
max.val = max(max1.val, max2.val);
|
||||
return max;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t clamp_u64_to_fixed16(uint64_t val)
|
||||
{
|
||||
uint_fixed_16_16_t fp;
|
||||
WARN_ON(val > U32_MAX);
|
||||
fp.val = (uint32_t) val;
|
||||
return fp;
|
||||
}
|
||||
|
||||
static inline uint32_t div_round_up_fixed16(uint_fixed_16_16_t val,
|
||||
uint_fixed_16_16_t d)
|
||||
{
|
||||
return DIV_ROUND_UP(val.val, d.val);
|
||||
}
|
||||
|
||||
static inline uint32_t mul_round_up_u32_fixed16(uint32_t val,
|
||||
uint_fixed_16_16_t mul)
|
||||
{
|
||||
uint64_t intermediate_val;
|
||||
|
||||
intermediate_val = (uint64_t) val * mul.val;
|
||||
intermediate_val = DIV_ROUND_UP_ULL(intermediate_val, 1 << 16);
|
||||
WARN_ON(intermediate_val > U32_MAX);
|
||||
return (uint32_t) intermediate_val;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val,
|
||||
uint_fixed_16_16_t mul)
|
||||
{
|
||||
uint64_t intermediate_val;
|
||||
|
||||
intermediate_val = (uint64_t) val.val * mul.val;
|
||||
intermediate_val = intermediate_val >> 16;
|
||||
return clamp_u64_to_fixed16(intermediate_val);
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t div_fixed16(uint32_t val, uint32_t d)
|
||||
{
|
||||
uint64_t interm_val;
|
||||
|
||||
interm_val = (uint64_t)val << 16;
|
||||
interm_val = DIV_ROUND_UP_ULL(interm_val, d);
|
||||
return clamp_u64_to_fixed16(interm_val);
|
||||
}
|
||||
|
||||
static inline uint32_t div_round_up_u32_fixed16(uint32_t val,
|
||||
uint_fixed_16_16_t d)
|
||||
{
|
||||
uint64_t interm_val;
|
||||
|
||||
interm_val = (uint64_t)val << 16;
|
||||
interm_val = DIV_ROUND_UP_ULL(interm_val, d.val);
|
||||
WARN_ON(interm_val > U32_MAX);
|
||||
return (uint32_t) interm_val;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t mul_u32_fixed16(uint32_t val,
|
||||
uint_fixed_16_16_t mul)
|
||||
{
|
||||
uint64_t intermediate_val;
|
||||
|
||||
intermediate_val = (uint64_t) val * mul.val;
|
||||
return clamp_u64_to_fixed16(intermediate_val);
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t add_fixed16(uint_fixed_16_16_t add1,
|
||||
uint_fixed_16_16_t add2)
|
||||
{
|
||||
uint64_t interm_sum;
|
||||
|
||||
interm_sum = (uint64_t) add1.val + add2.val;
|
||||
return clamp_u64_to_fixed16(interm_sum);
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t add_fixed16_u32(uint_fixed_16_16_t add1,
|
||||
uint32_t add2)
|
||||
{
|
||||
uint64_t interm_sum;
|
||||
uint_fixed_16_16_t interm_add2 = u32_to_fixed16(add2);
|
||||
|
||||
interm_sum = (uint64_t) add1.val + interm_add2.val;
|
||||
return clamp_u64_to_fixed16(interm_sum);
|
||||
}
|
||||
|
||||
enum hpd_pin {
|
||||
HPD_NONE = 0,
|
||||
HPD_TV = HPD_NONE, /* TV is known to be unreliable */
|
||||
@@ -284,7 +148,8 @@ enum hpd_pin {
|
||||
#define for_each_hpd_pin(__pin) \
|
||||
for ((__pin) = (HPD_NONE + 1); (__pin) < HPD_NUM_PINS; (__pin)++)
|
||||
|
||||
#define HPD_STORM_DEFAULT_THRESHOLD 5
|
||||
/* Threshold == 5 for long IRQs, 50 for short */
|
||||
#define HPD_STORM_DEFAULT_THRESHOLD 50
|
||||
|
||||
struct i915_hotplug {
|
||||
struct work_struct hotplug_work;
|
||||
@@ -309,6 +174,8 @@ struct i915_hotplug {
|
||||
bool poll_enabled;
|
||||
|
||||
unsigned int hpd_storm_threshold;
|
||||
/* Whether or not to count short HPD IRQs in HPD storms */
|
||||
u8 hpd_short_storm_enabled;
|
||||
|
||||
/*
|
||||
* if we get a HPD irq from DP and a HPD irq from non-DP
|
||||
@@ -466,8 +333,10 @@ struct drm_i915_display_funcs {
|
||||
struct intel_csr {
|
||||
struct work_struct work;
|
||||
const char *fw_path;
|
||||
uint32_t required_version;
|
||||
uint32_t max_fw_size; /* bytes */
|
||||
uint32_t *dmc_payload;
|
||||
uint32_t dmc_fw_size;
|
||||
uint32_t dmc_fw_size; /* dwords */
|
||||
uint32_t version;
|
||||
uint32_t mmio_count;
|
||||
i915_reg_t mmioaddr[8];
|
||||
@@ -547,6 +416,8 @@ struct intel_fbc {
|
||||
int adjusted_y;
|
||||
|
||||
int y;
|
||||
|
||||
uint16_t pixel_blend_mode;
|
||||
} plane;
|
||||
|
||||
struct {
|
||||
@@ -625,17 +496,19 @@ struct i915_psr {
|
||||
bool sink_support;
|
||||
bool prepared, enabled;
|
||||
struct intel_dp *dp;
|
||||
enum pipe pipe;
|
||||
bool active;
|
||||
struct work_struct work;
|
||||
unsigned busy_frontbuffer_bits;
|
||||
bool sink_psr2_support;
|
||||
bool link_standby;
|
||||
bool colorimetry_support;
|
||||
bool alpm;
|
||||
bool psr2_enabled;
|
||||
u8 sink_sync_latency;
|
||||
ktime_t last_entry_attempt;
|
||||
ktime_t last_exit;
|
||||
bool sink_not_reliable;
|
||||
bool irq_aux_error;
|
||||
};
|
||||
|
||||
enum intel_pch {
|
||||
@@ -919,6 +792,11 @@ struct i915_power_well_desc {
|
||||
/* The pw is backing the VGA functionality */
|
||||
bool has_vga:1;
|
||||
bool has_fuses:1;
|
||||
/*
|
||||
* The pw is for an ICL+ TypeC PHY port in
|
||||
* Thunderbolt mode.
|
||||
*/
|
||||
bool is_tc_tbt:1;
|
||||
} hsw;
|
||||
};
|
||||
const struct i915_power_well_ops *ops;
|
||||
@@ -1043,17 +921,6 @@ struct i915_gem_mm {
|
||||
|
||||
#define I915_ENGINE_WEDGED_TIMEOUT (60 * HZ) /* Reset but no recovery? */
|
||||
|
||||
#define DP_AUX_A 0x40
|
||||
#define DP_AUX_B 0x10
|
||||
#define DP_AUX_C 0x20
|
||||
#define DP_AUX_D 0x30
|
||||
#define DP_AUX_E 0x50
|
||||
#define DP_AUX_F 0x60
|
||||
|
||||
#define DDC_PIN_B 0x05
|
||||
#define DDC_PIN_C 0x04
|
||||
#define DDC_PIN_D 0x06
|
||||
|
||||
struct ddi_vbt_port_info {
|
||||
int max_tmds_clock;
|
||||
|
||||
@@ -1100,6 +967,7 @@ struct intel_vbt_data {
|
||||
unsigned int panel_type:4;
|
||||
int lvds_ssc_freq;
|
||||
unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
|
||||
enum drm_panel_orientation orientation;
|
||||
|
||||
enum drrs_support_type drrs_type;
|
||||
|
||||
@@ -1145,6 +1013,7 @@ struct intel_vbt_data {
|
||||
u8 *data;
|
||||
const u8 *sequence[MIPI_SEQ_MAX];
|
||||
u8 *deassert_seq; /* Used by fixup_mipi_sequences() */
|
||||
enum drm_panel_orientation orientation;
|
||||
} dsi;
|
||||
|
||||
int crt_ddc_pin;
|
||||
@@ -1229,9 +1098,6 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1,
|
||||
}
|
||||
|
||||
struct skl_ddb_allocation {
|
||||
/* packed/y */
|
||||
struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES];
|
||||
struct skl_ddb_entry uv_plane[I915_MAX_PIPES][I915_MAX_PLANES];
|
||||
u8 enabled_slices; /* GEN11 has configurable 2 slices */
|
||||
};
|
||||
|
||||
@@ -1241,9 +1107,9 @@ struct skl_ddb_values {
|
||||
};
|
||||
|
||||
struct skl_wm_level {
|
||||
bool plane_en;
|
||||
uint16_t plane_res_b;
|
||||
uint8_t plane_res_l;
|
||||
bool plane_en;
|
||||
};
|
||||
|
||||
/* Stores plane specific WM parameters */
|
||||
@@ -1324,20 +1190,6 @@ struct i915_frontbuffer_tracking {
|
||||
unsigned flip_bits;
|
||||
};
|
||||
|
||||
struct i915_wa_reg {
|
||||
u32 addr;
|
||||
u32 value;
|
||||
/* bitmask representing WA bits */
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
#define I915_MAX_WA_REGS 16
|
||||
|
||||
struct i915_workarounds {
|
||||
struct i915_wa_reg reg[I915_MAX_WA_REGS];
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct i915_virtual_gpu {
|
||||
bool active;
|
||||
u32 caps;
|
||||
@@ -1520,31 +1372,13 @@ struct i915_oa_ops {
|
||||
*/
|
||||
bool (*is_valid_flex_reg)(struct drm_i915_private *dev_priv, u32 addr);
|
||||
|
||||
/**
|
||||
* @init_oa_buffer: Resets the head and tail pointers of the
|
||||
* circular buffer for periodic OA reports.
|
||||
*
|
||||
* Called when first opening a stream for OA metrics, but also may be
|
||||
* called in response to an OA buffer overflow or other error
|
||||
* condition.
|
||||
*
|
||||
* Note it may be necessary to clear the full OA buffer here as part of
|
||||
* maintaining the invariable that new reports must be written to
|
||||
* zeroed memory for us to be able to reliable detect if an expected
|
||||
* report has not yet landed in memory. (At least on Haswell the OA
|
||||
* buffer tail pointer is not synchronized with reports being visible
|
||||
* to the CPU)
|
||||
*/
|
||||
void (*init_oa_buffer)(struct drm_i915_private *dev_priv);
|
||||
|
||||
/**
|
||||
* @enable_metric_set: Selects and applies any MUX configuration to set
|
||||
* up the Boolean and Custom (B/C) counters that are part of the
|
||||
* counter reports being sampled. May apply system constraints such as
|
||||
* disabling EU clock gating as required.
|
||||
*/
|
||||
int (*enable_metric_set)(struct drm_i915_private *dev_priv,
|
||||
const struct i915_oa_config *oa_config);
|
||||
int (*enable_metric_set)(struct i915_perf_stream *stream);
|
||||
|
||||
/**
|
||||
* @disable_metric_set: Remove system constraints associated with using
|
||||
@@ -1555,12 +1389,12 @@ struct i915_oa_ops {
|
||||
/**
|
||||
* @oa_enable: Enable periodic sampling
|
||||
*/
|
||||
void (*oa_enable)(struct drm_i915_private *dev_priv);
|
||||
void (*oa_enable)(struct i915_perf_stream *stream);
|
||||
|
||||
/**
|
||||
* @oa_disable: Disable periodic sampling
|
||||
*/
|
||||
void (*oa_disable)(struct drm_i915_private *dev_priv);
|
||||
void (*oa_disable)(struct i915_perf_stream *stream);
|
||||
|
||||
/**
|
||||
* @read: Copy data from the circular OA buffer into a given userspace
|
||||
@@ -1805,7 +1639,6 @@ struct drm_i915_private {
|
||||
|
||||
int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
|
||||
|
||||
struct i915_workarounds workarounds;
|
||||
struct i915_wa_list gt_wa_list;
|
||||
|
||||
struct i915_frontbuffer_tracking fb_tracking;
|
||||
@@ -2326,6 +2159,8 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg)
|
||||
(((__iter).curr += PAGE_SIZE) >= (__iter).max) ? \
|
||||
(__iter) = __sgt_iter(__sg_next((__iter).sgp), false), 0 : 0)
|
||||
|
||||
bool i915_sg_trim(struct sg_table *orig_st);
|
||||
|
||||
static inline unsigned int i915_sg_page_sizes(struct scatterlist *sg)
|
||||
{
|
||||
unsigned int page_sizes;
|
||||
@@ -2371,20 +2206,12 @@ intel_info(const struct drm_i915_private *dev_priv)
|
||||
#define REVID_FOREVER 0xff
|
||||
#define INTEL_REVID(dev_priv) ((dev_priv)->drm.pdev->revision)
|
||||
|
||||
#define GEN_FOREVER (0)
|
||||
|
||||
#define INTEL_GEN_MASK(s, e) ( \
|
||||
BUILD_BUG_ON_ZERO(!__builtin_constant_p(s)) + \
|
||||
BUILD_BUG_ON_ZERO(!__builtin_constant_p(e)) + \
|
||||
GENMASK((e) != GEN_FOREVER ? (e) - 1 : BITS_PER_LONG - 1, \
|
||||
(s) != GEN_FOREVER ? (s) - 1 : 0) \
|
||||
)
|
||||
GENMASK((e) - 1, (s) - 1))
|
||||
|
||||
/*
|
||||
* Returns true if Gen is in inclusive range [Start, End].
|
||||
*
|
||||
* Use GEN_FOREVER for unbound start and or end.
|
||||
*/
|
||||
/* Returns true if Gen is in inclusive range [Start, End] */
|
||||
#define IS_GEN(dev_priv, s, e) \
|
||||
(!!((dev_priv)->info.gen_mask & INTEL_GEN_MASK((s), (e))))
|
||||
|
||||
@@ -2465,6 +2292,8 @@ intel_info(const struct drm_i915_private *dev_priv)
|
||||
#define IS_KBL_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x590E || \
|
||||
INTEL_DEVID(dev_priv) == 0x5915 || \
|
||||
INTEL_DEVID(dev_priv) == 0x591E)
|
||||
#define IS_AML_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x591C || \
|
||||
INTEL_DEVID(dev_priv) == 0x87C0)
|
||||
#define IS_SKL_GT2(dev_priv) (IS_SKYLAKE(dev_priv) && \
|
||||
(dev_priv)->info.gt == 2)
|
||||
#define IS_SKL_GT3(dev_priv) (IS_SKYLAKE(dev_priv) && \
|
||||
@@ -2596,17 +2425,22 @@ intel_info(const struct drm_i915_private *dev_priv)
|
||||
|
||||
#define HAS_EXECLISTS(dev_priv) HAS_LOGICAL_RING_CONTEXTS(dev_priv)
|
||||
|
||||
#define USES_PPGTT(dev_priv) (i915_modparams.enable_ppgtt)
|
||||
#define USES_FULL_PPGTT(dev_priv) (i915_modparams.enable_ppgtt >= 2)
|
||||
#define USES_FULL_48BIT_PPGTT(dev_priv) (i915_modparams.enable_ppgtt == 3)
|
||||
#define INTEL_PPGTT(dev_priv) (INTEL_INFO(dev_priv)->ppgtt)
|
||||
#define HAS_PPGTT(dev_priv) \
|
||||
(INTEL_PPGTT(dev_priv) != INTEL_PPGTT_NONE)
|
||||
#define HAS_FULL_PPGTT(dev_priv) \
|
||||
(INTEL_PPGTT(dev_priv) >= INTEL_PPGTT_FULL)
|
||||
#define HAS_FULL_48BIT_PPGTT(dev_priv) \
|
||||
(INTEL_PPGTT(dev_priv) >= INTEL_PPGTT_FULL_4LVL)
|
||||
|
||||
#define HAS_PAGE_SIZES(dev_priv, sizes) ({ \
|
||||
GEM_BUG_ON((sizes) == 0); \
|
||||
((sizes) & ~(dev_priv)->info.page_sizes) == 0; \
|
||||
})
|
||||
|
||||
#define HAS_OVERLAY(dev_priv) ((dev_priv)->info.has_overlay)
|
||||
#define HAS_OVERLAY(dev_priv) ((dev_priv)->info.display.has_overlay)
|
||||
#define OVERLAY_NEEDS_PHYSICAL(dev_priv) \
|
||||
((dev_priv)->info.overlay_needs_physical)
|
||||
((dev_priv)->info.display.overlay_needs_physical)
|
||||
|
||||
/* Early gen2 have a totally busted CS tlb and require pinned batches. */
|
||||
#define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_I845G(dev_priv))
|
||||
@@ -2627,31 +2461,31 @@ intel_info(const struct drm_i915_private *dev_priv)
|
||||
#define HAS_128_BYTE_Y_TILING(dev_priv) (!IS_GEN2(dev_priv) && \
|
||||
!(IS_I915G(dev_priv) || \
|
||||
IS_I915GM(dev_priv)))
|
||||
#define SUPPORTS_TV(dev_priv) ((dev_priv)->info.supports_tv)
|
||||
#define I915_HAS_HOTPLUG(dev_priv) ((dev_priv)->info.has_hotplug)
|
||||
#define SUPPORTS_TV(dev_priv) ((dev_priv)->info.display.supports_tv)
|
||||
#define I915_HAS_HOTPLUG(dev_priv) ((dev_priv)->info.display.has_hotplug)
|
||||
|
||||
#define HAS_FW_BLC(dev_priv) (INTEL_GEN(dev_priv) > 2)
|
||||
#define HAS_FBC(dev_priv) ((dev_priv)->info.has_fbc)
|
||||
#define HAS_FBC(dev_priv) ((dev_priv)->info.display.has_fbc)
|
||||
#define HAS_CUR_FBC(dev_priv) (!HAS_GMCH_DISPLAY(dev_priv) && INTEL_GEN(dev_priv) >= 7)
|
||||
|
||||
#define HAS_IPS(dev_priv) (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
|
||||
#define HAS_DP_MST(dev_priv) ((dev_priv)->info.has_dp_mst)
|
||||
#define HAS_DP_MST(dev_priv) ((dev_priv)->info.display.has_dp_mst)
|
||||
|
||||
#define HAS_DDI(dev_priv) ((dev_priv)->info.has_ddi)
|
||||
#define HAS_DDI(dev_priv) ((dev_priv)->info.display.has_ddi)
|
||||
#define HAS_FPGA_DBG_UNCLAIMED(dev_priv) ((dev_priv)->info.has_fpga_dbg)
|
||||
#define HAS_PSR(dev_priv) ((dev_priv)->info.has_psr)
|
||||
#define HAS_PSR(dev_priv) ((dev_priv)->info.display.has_psr)
|
||||
|
||||
#define HAS_RC6(dev_priv) ((dev_priv)->info.has_rc6)
|
||||
#define HAS_RC6p(dev_priv) ((dev_priv)->info.has_rc6p)
|
||||
#define HAS_RC6pp(dev_priv) (false) /* HW was never validated */
|
||||
|
||||
#define HAS_CSR(dev_priv) ((dev_priv)->info.has_csr)
|
||||
#define HAS_CSR(dev_priv) ((dev_priv)->info.display.has_csr)
|
||||
|
||||
#define HAS_RUNTIME_PM(dev_priv) ((dev_priv)->info.has_runtime_pm)
|
||||
#define HAS_64BIT_RELOC(dev_priv) ((dev_priv)->info.has_64bit_reloc)
|
||||
|
||||
#define HAS_IPC(dev_priv) ((dev_priv)->info.has_ipc)
|
||||
#define HAS_IPC(dev_priv) ((dev_priv)->info.display.has_ipc)
|
||||
|
||||
/*
|
||||
* For now, anything with a GuC requires uCode loading, and then supports
|
||||
@@ -2712,7 +2546,7 @@ intel_info(const struct drm_i915_private *dev_priv)
|
||||
#define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP)
|
||||
#define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE)
|
||||
|
||||
#define HAS_GMCH_DISPLAY(dev_priv) ((dev_priv)->info.has_gmch_display)
|
||||
#define HAS_GMCH_DISPLAY(dev_priv) ((dev_priv)->info.display.has_gmch_display)
|
||||
|
||||
#define HAS_LSPCON(dev_priv) (INTEL_GEN(dev_priv) >= 9)
|
||||
|
||||
@@ -2724,6 +2558,8 @@ intel_info(const struct drm_i915_private *dev_priv)
|
||||
#define GT_FREQUENCY_MULTIPLIER 50
|
||||
#define GEN9_FREQ_SCALER 3
|
||||
|
||||
#define HAS_DISPLAY(dev_priv) (INTEL_INFO(dev_priv)->num_pipes > 0)
|
||||
|
||||
#include "i915_trace.h"
|
||||
|
||||
static inline bool intel_vtd_active(void)
|
||||
@@ -2746,9 +2582,6 @@ intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *dev_priv)
|
||||
return IS_BROXTON(dev_priv) && intel_vtd_active();
|
||||
}
|
||||
|
||||
int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
|
||||
int enable_ppgtt);
|
||||
|
||||
/* i915_drv.c */
|
||||
void __printf(3, 4)
|
||||
__i915_printk(struct drm_i915_private *dev_priv, const char *level,
|
||||
@@ -3233,7 +3066,7 @@ int i915_gem_object_wait(struct drm_i915_gem_object *obj,
|
||||
int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
|
||||
unsigned int flags,
|
||||
const struct i915_sched_attr *attr);
|
||||
#define I915_PRIORITY_DISPLAY I915_PRIORITY_MAX
|
||||
#define I915_PRIORITY_DISPLAY I915_USER_PRIORITY(I915_PRIORITY_MAX)
|
||||
|
||||
int __must_check
|
||||
i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write);
|
||||
@@ -3465,6 +3298,7 @@ bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
|
||||
enum port port);
|
||||
bool intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv,
|
||||
enum port port);
|
||||
enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv, enum port port);
|
||||
|
||||
/* intel_acpi.c */
|
||||
#ifdef CONFIG_ACPI
|
||||
@@ -3486,8 +3320,6 @@ mkwrite_device_info(struct drm_i915_private *dev_priv)
|
||||
extern void intel_modeset_init_hw(struct drm_device *dev);
|
||||
extern int intel_modeset_init(struct drm_device *dev);
|
||||
extern void intel_modeset_cleanup(struct drm_device *dev);
|
||||
extern int intel_connector_register(struct drm_connector *);
|
||||
extern void intel_connector_unregister(struct drm_connector *);
|
||||
extern int intel_modeset_vga_set_state(struct drm_i915_private *dev_priv,
|
||||
bool state);
|
||||
extern void intel_display_resume(struct drm_device *dev);
|
||||
@@ -3500,6 +3332,9 @@ extern void intel_rps_mark_interactive(struct drm_i915_private *i915,
|
||||
bool interactive);
|
||||
extern bool intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
|
||||
bool enable);
|
||||
void intel_dsc_enable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_dsc_disable(const struct intel_crtc_state *crtc_state);
|
||||
|
||||
int i915_reg_read_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file);
|
||||
@@ -3587,6 +3422,12 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
void vlv_phy_reset_lanes(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *old_crtc_state);
|
||||
|
||||
/* intel_combo_phy.c */
|
||||
void icl_combo_phys_init(struct drm_i915_private *dev_priv);
|
||||
void icl_combo_phys_uninit(struct drm_i915_private *dev_priv);
|
||||
void cnl_combo_phys_init(struct drm_i915_private *dev_priv);
|
||||
void cnl_combo_phys_uninit(struct drm_i915_private *dev_priv);
|
||||
|
||||
int intel_gpu_freq(struct drm_i915_private *dev_priv, int val);
|
||||
int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
|
||||
u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv,
|
||||
|
143
drivers/gpu/drm/i915/i915_fixed.h
Normal file
143
drivers/gpu/drm/i915/i915_fixed.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef _I915_FIXED_H_
|
||||
#define _I915_FIXED_H_
|
||||
|
||||
typedef struct {
|
||||
u32 val;
|
||||
} uint_fixed_16_16_t;
|
||||
|
||||
#define FP_16_16_MAX ((uint_fixed_16_16_t){ .val = UINT_MAX })
|
||||
|
||||
static inline bool is_fixed16_zero(uint_fixed_16_16_t val)
|
||||
{
|
||||
return val.val == 0;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t u32_to_fixed16(u32 val)
|
||||
{
|
||||
uint_fixed_16_16_t fp = { .val = val << 16 };
|
||||
|
||||
WARN_ON(val > U16_MAX);
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
static inline u32 fixed16_to_u32_round_up(uint_fixed_16_16_t fp)
|
||||
{
|
||||
return DIV_ROUND_UP(fp.val, 1 << 16);
|
||||
}
|
||||
|
||||
static inline u32 fixed16_to_u32(uint_fixed_16_16_t fp)
|
||||
{
|
||||
return fp.val >> 16;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t min_fixed16(uint_fixed_16_16_t min1,
|
||||
uint_fixed_16_16_t min2)
|
||||
{
|
||||
uint_fixed_16_16_t min = { .val = min(min1.val, min2.val) };
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t max_fixed16(uint_fixed_16_16_t max1,
|
||||
uint_fixed_16_16_t max2)
|
||||
{
|
||||
uint_fixed_16_16_t max = { .val = max(max1.val, max2.val) };
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t clamp_u64_to_fixed16(u64 val)
|
||||
{
|
||||
uint_fixed_16_16_t fp = { .val = (u32)val };
|
||||
|
||||
WARN_ON(val > U32_MAX);
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
static inline u32 div_round_up_fixed16(uint_fixed_16_16_t val,
|
||||
uint_fixed_16_16_t d)
|
||||
{
|
||||
return DIV_ROUND_UP(val.val, d.val);
|
||||
}
|
||||
|
||||
static inline u32 mul_round_up_u32_fixed16(u32 val, uint_fixed_16_16_t mul)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
tmp = (u64)val * mul.val;
|
||||
tmp = DIV_ROUND_UP_ULL(tmp, 1 << 16);
|
||||
WARN_ON(tmp > U32_MAX);
|
||||
|
||||
return (u32)tmp;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val,
|
||||
uint_fixed_16_16_t mul)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
tmp = (u64)val.val * mul.val;
|
||||
tmp = tmp >> 16;
|
||||
|
||||
return clamp_u64_to_fixed16(tmp);
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t div_fixed16(u32 val, u32 d)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
tmp = (u64)val << 16;
|
||||
tmp = DIV_ROUND_UP_ULL(tmp, d);
|
||||
|
||||
return clamp_u64_to_fixed16(tmp);
|
||||
}
|
||||
|
||||
static inline u32 div_round_up_u32_fixed16(u32 val, uint_fixed_16_16_t d)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
tmp = (u64)val << 16;
|
||||
tmp = DIV_ROUND_UP_ULL(tmp, d.val);
|
||||
WARN_ON(tmp > U32_MAX);
|
||||
|
||||
return (u32)tmp;
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t mul_u32_fixed16(u32 val, uint_fixed_16_16_t mul)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
tmp = (u64)val * mul.val;
|
||||
|
||||
return clamp_u64_to_fixed16(tmp);
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t add_fixed16(uint_fixed_16_16_t add1,
|
||||
uint_fixed_16_16_t add2)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
tmp = (u64)add1.val + add2.val;
|
||||
|
||||
return clamp_u64_to_fixed16(tmp);
|
||||
}
|
||||
|
||||
static inline uint_fixed_16_16_t add_fixed16_u32(uint_fixed_16_16_t add1,
|
||||
u32 add2)
|
||||
{
|
||||
uint_fixed_16_16_t tmp_add2 = u32_to_fixed16(add2);
|
||||
u64 tmp;
|
||||
|
||||
tmp = (u64)add1.val + tmp_add2.val;
|
||||
|
||||
return clamp_u64_to_fixed16(tmp);
|
||||
}
|
||||
|
||||
#endif /* _I915_FIXED_H_ */
|
@@ -1740,6 +1740,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
|
||||
*/
|
||||
err = i915_gem_object_wait(obj,
|
||||
I915_WAIT_INTERRUPTIBLE |
|
||||
I915_WAIT_PRIORITY |
|
||||
(write_domain ? I915_WAIT_ALL : 0),
|
||||
MAX_SCHEDULE_TIMEOUT,
|
||||
to_rps_client(file));
|
||||
@@ -2381,11 +2382,23 @@ void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj)
|
||||
invalidate_mapping_pages(mapping, 0, (loff_t)-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move pages to appropriate lru and release the pagevec, decrementing the
|
||||
* ref count of those pages.
|
||||
*/
|
||||
static void check_release_pagevec(struct pagevec *pvec)
|
||||
{
|
||||
check_move_unevictable_pages(pvec);
|
||||
__pagevec_release(pvec);
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
static void
|
||||
i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj,
|
||||
struct sg_table *pages)
|
||||
{
|
||||
struct sgt_iter sgt_iter;
|
||||
struct pagevec pvec;
|
||||
struct page *page;
|
||||
|
||||
__i915_gem_object_release_shmem(obj, pages, true);
|
||||
@@ -2395,6 +2408,9 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj,
|
||||
if (i915_gem_object_needs_bit17_swizzle(obj))
|
||||
i915_gem_object_save_bit_17_swizzle(obj, pages);
|
||||
|
||||
mapping_clear_unevictable(file_inode(obj->base.filp)->i_mapping);
|
||||
|
||||
pagevec_init(&pvec);
|
||||
for_each_sgt_page(page, sgt_iter, pages) {
|
||||
if (obj->mm.dirty)
|
||||
set_page_dirty(page);
|
||||
@@ -2402,8 +2418,11 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj,
|
||||
if (obj->mm.madv == I915_MADV_WILLNEED)
|
||||
mark_page_accessed(page);
|
||||
|
||||
put_page(page);
|
||||
if (!pagevec_add(&pvec, page))
|
||||
check_release_pagevec(&pvec);
|
||||
}
|
||||
if (pagevec_count(&pvec))
|
||||
check_release_pagevec(&pvec);
|
||||
obj->mm.dirty = false;
|
||||
|
||||
sg_free_table(pages);
|
||||
@@ -2483,7 +2502,7 @@ unlock:
|
||||
mutex_unlock(&obj->mm.lock);
|
||||
}
|
||||
|
||||
static bool i915_sg_trim(struct sg_table *orig_st)
|
||||
bool i915_sg_trim(struct sg_table *orig_st)
|
||||
{
|
||||
struct sg_table new_st;
|
||||
struct scatterlist *sg, *new_sg;
|
||||
@@ -2524,6 +2543,7 @@ static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
|
||||
unsigned long last_pfn = 0; /* suppress gcc warning */
|
||||
unsigned int max_segment = i915_sg_segment_size();
|
||||
unsigned int sg_page_sizes;
|
||||
struct pagevec pvec;
|
||||
gfp_t noreclaim;
|
||||
int ret;
|
||||
|
||||
@@ -2559,6 +2579,7 @@ rebuild_st:
|
||||
* Fail silently without starting the shrinker
|
||||
*/
|
||||
mapping = obj->base.filp->f_mapping;
|
||||
mapping_set_unevictable(mapping);
|
||||
noreclaim = mapping_gfp_constraint(mapping, ~__GFP_RECLAIM);
|
||||
noreclaim |= __GFP_NORETRY | __GFP_NOWARN;
|
||||
|
||||
@@ -2573,6 +2594,7 @@ rebuild_st:
|
||||
gfp_t gfp = noreclaim;
|
||||
|
||||
do {
|
||||
cond_resched();
|
||||
page = shmem_read_mapping_page_gfp(mapping, i, gfp);
|
||||
if (likely(!IS_ERR(page)))
|
||||
break;
|
||||
@@ -2583,7 +2605,6 @@ rebuild_st:
|
||||
}
|
||||
|
||||
i915_gem_shrink(dev_priv, 2 * page_count, NULL, *s++);
|
||||
cond_resched();
|
||||
|
||||
/*
|
||||
* We've tried hard to allocate the memory by reaping
|
||||
@@ -2673,8 +2694,14 @@ rebuild_st:
|
||||
err_sg:
|
||||
sg_mark_end(sg);
|
||||
err_pages:
|
||||
for_each_sgt_page(page, sgt_iter, st)
|
||||
put_page(page);
|
||||
mapping_clear_unevictable(mapping);
|
||||
pagevec_init(&pvec);
|
||||
for_each_sgt_page(page, sgt_iter, st) {
|
||||
if (!pagevec_add(&pvec, page))
|
||||
check_release_pagevec(&pvec);
|
||||
}
|
||||
if (pagevec_count(&pvec))
|
||||
check_release_pagevec(&pvec);
|
||||
sg_free_table(st);
|
||||
kfree(st);
|
||||
|
||||
@@ -3281,16 +3308,6 @@ void i915_gem_reset_finish(struct drm_i915_private *dev_priv)
|
||||
}
|
||||
|
||||
static void nop_submit_request(struct i915_request *request)
|
||||
{
|
||||
GEM_TRACE("%s fence %llx:%d -> -EIO\n",
|
||||
request->engine->name,
|
||||
request->fence.context, request->fence.seqno);
|
||||
dma_fence_set_error(&request->fence, -EIO);
|
||||
|
||||
i915_request_submit(request);
|
||||
}
|
||||
|
||||
static void nop_complete_submit_request(struct i915_request *request)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@@ -3327,57 +3344,33 @@ void i915_gem_set_wedged(struct drm_i915_private *i915)
|
||||
* rolling the global seqno forward (since this would complete requests
|
||||
* for which we haven't set the fence error to EIO yet).
|
||||
*/
|
||||
for_each_engine(engine, i915, id) {
|
||||
for_each_engine(engine, i915, id)
|
||||
i915_gem_reset_prepare_engine(engine);
|
||||
|
||||
engine->submit_request = nop_submit_request;
|
||||
engine->schedule = NULL;
|
||||
}
|
||||
i915->caps.scheduler = 0;
|
||||
|
||||
/* Even if the GPU reset fails, it should still stop the engines */
|
||||
if (INTEL_GEN(i915) >= 5)
|
||||
intel_gpu_reset(i915, ALL_ENGINES);
|
||||
|
||||
/*
|
||||
* Make sure no one is running the old callback before we proceed with
|
||||
* cancelling requests and resetting the completion tracking. Otherwise
|
||||
* we might submit a request to the hardware which never completes.
|
||||
*/
|
||||
synchronize_rcu();
|
||||
|
||||
for_each_engine(engine, i915, id) {
|
||||
/* Mark all executing requests as skipped */
|
||||
engine->cancel_requests(engine);
|
||||
|
||||
/*
|
||||
* Only once we've force-cancelled all in-flight requests can we
|
||||
* start to complete all requests.
|
||||
*/
|
||||
engine->submit_request = nop_complete_submit_request;
|
||||
engine->submit_request = nop_submit_request;
|
||||
engine->schedule = NULL;
|
||||
}
|
||||
i915->caps.scheduler = 0;
|
||||
|
||||
/*
|
||||
* Make sure no request can slip through without getting completed by
|
||||
* either this call here to intel_engine_init_global_seqno, or the one
|
||||
* in nop_complete_submit_request.
|
||||
* in nop_submit_request.
|
||||
*/
|
||||
synchronize_rcu();
|
||||
|
||||
/* Mark all executing requests as skipped */
|
||||
for_each_engine(engine, i915, id)
|
||||
engine->cancel_requests(engine);
|
||||
|
||||
for_each_engine(engine, i915, id) {
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Mark all pending requests as complete so that any concurrent
|
||||
* (lockless) lookup doesn't try and wait upon the request as we
|
||||
* reset it.
|
||||
*/
|
||||
spin_lock_irqsave(&engine->timeline.lock, flags);
|
||||
intel_engine_init_global_seqno(engine,
|
||||
intel_engine_last_submit(engine));
|
||||
spin_unlock_irqrestore(&engine->timeline.lock, flags);
|
||||
|
||||
i915_gem_reset_finish_engine(engine);
|
||||
intel_engine_wakeup(engine);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -3530,6 +3523,8 @@ static void __sleep_rcu(struct rcu_head *rcu)
|
||||
struct sleep_rcu_work *s = container_of(rcu, typeof(*s), rcu);
|
||||
struct drm_i915_private *i915 = s->i915;
|
||||
|
||||
destroy_rcu_head(&s->rcu);
|
||||
|
||||
if (same_epoch(i915, s->epoch)) {
|
||||
INIT_WORK(&s->work, __sleep_work);
|
||||
queue_work(i915->wq, &s->work);
|
||||
@@ -3646,6 +3641,7 @@ out_rearm:
|
||||
if (same_epoch(dev_priv, epoch)) {
|
||||
struct sleep_rcu_work *s = kmalloc(sizeof(*s), GFP_KERNEL);
|
||||
if (s) {
|
||||
init_rcu_head(&s->rcu);
|
||||
s->i915 = dev_priv;
|
||||
s->epoch = epoch;
|
||||
call_rcu(&s->rcu, __sleep_rcu);
|
||||
@@ -3743,7 +3739,9 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
|
||||
start = ktime_get();
|
||||
|
||||
ret = i915_gem_object_wait(obj,
|
||||
I915_WAIT_INTERRUPTIBLE | I915_WAIT_ALL,
|
||||
I915_WAIT_INTERRUPTIBLE |
|
||||
I915_WAIT_PRIORITY |
|
||||
I915_WAIT_ALL,
|
||||
to_wait_timeout(args->timeout_ns),
|
||||
to_rps_client(file));
|
||||
|
||||
@@ -4710,6 +4708,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
|
||||
INIT_LIST_HEAD(&obj->lut_list);
|
||||
INIT_LIST_HEAD(&obj->batch_pool_link);
|
||||
|
||||
init_rcu_head(&obj->rcu);
|
||||
|
||||
obj->ops = ops;
|
||||
|
||||
reservation_object_init(&obj->__builtin_resv);
|
||||
@@ -4976,6 +4976,13 @@ static void __i915_gem_free_object_rcu(struct rcu_head *head)
|
||||
container_of(head, typeof(*obj), rcu);
|
||||
struct drm_i915_private *i915 = to_i915(obj->base.dev);
|
||||
|
||||
/*
|
||||
* We reuse obj->rcu for the freed list, so we had better not treat
|
||||
* it like a rcu_head from this point forwards. And we expect all
|
||||
* objects to be freed via this path.
|
||||
*/
|
||||
destroy_rcu_head(&obj->rcu);
|
||||
|
||||
/*
|
||||
* Since we require blocking on struct_mutex to unbind the freed
|
||||
* object from the GPU before releasing resources back to the
|
||||
@@ -5293,19 +5300,10 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
|
||||
I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev_priv) ?
|
||||
LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED);
|
||||
|
||||
if (HAS_PCH_NOP(dev_priv)) {
|
||||
if (IS_IVYBRIDGE(dev_priv)) {
|
||||
u32 temp = I915_READ(GEN7_MSG_CTL);
|
||||
temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK);
|
||||
I915_WRITE(GEN7_MSG_CTL, temp);
|
||||
} else if (INTEL_GEN(dev_priv) >= 7) {
|
||||
u32 temp = I915_READ(HSW_NDE_RSTWRN_OPT);
|
||||
temp &= ~RESET_PCH_HANDSHAKE_ENABLE;
|
||||
I915_WRITE(HSW_NDE_RSTWRN_OPT, temp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply the GT workarounds... */
|
||||
intel_gt_apply_workarounds(dev_priv);
|
||||
/* ...and determine whether they are sticking. */
|
||||
intel_gt_verify_workarounds(dev_priv, "init");
|
||||
|
||||
i915_gem_init_swizzling(dev_priv);
|
||||
|
||||
@@ -6001,7 +5999,7 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old,
|
||||
* the bits.
|
||||
*/
|
||||
BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES >
|
||||
sizeof(atomic_t) * BITS_PER_BYTE);
|
||||
BITS_PER_TYPE(atomic_t));
|
||||
|
||||
if (old) {
|
||||
WARN_ON(!(atomic_read(&old->frontbuffer_bits) & frontbuffer_bits));
|
||||
|
@@ -47,17 +47,19 @@ struct drm_i915_private;
|
||||
#define GEM_DEBUG_DECL(var) var
|
||||
#define GEM_DEBUG_EXEC(expr) expr
|
||||
#define GEM_DEBUG_BUG_ON(expr) GEM_BUG_ON(expr)
|
||||
#define GEM_DEBUG_WARN_ON(expr) GEM_WARN_ON(expr)
|
||||
|
||||
#else
|
||||
|
||||
#define GEM_SHOW_DEBUG() (0)
|
||||
|
||||
#define GEM_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr)
|
||||
#define GEM_WARN_ON(expr) (BUILD_BUG_ON_INVALID(expr), 0)
|
||||
#define GEM_WARN_ON(expr) ({ unlikely(!!(expr)); })
|
||||
|
||||
#define GEM_DEBUG_DECL(var)
|
||||
#define GEM_DEBUG_EXEC(expr) do { } while (0)
|
||||
#define GEM_DEBUG_BUG_ON(expr)
|
||||
#define GEM_DEBUG_WARN_ON(expr) ({ BUILD_BUG_ON_INVALID(expr); 0; })
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_TRACE_GEM)
|
||||
|
@@ -337,7 +337,7 @@ __create_hw_context(struct drm_i915_private *dev_priv,
|
||||
kref_init(&ctx->ref);
|
||||
list_add_tail(&ctx->link, &dev_priv->contexts.list);
|
||||
ctx->i915 = dev_priv;
|
||||
ctx->sched.priority = I915_PRIORITY_NORMAL;
|
||||
ctx->sched.priority = I915_USER_PRIORITY(I915_PRIORITY_NORMAL);
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) {
|
||||
struct intel_context *ce = &ctx->__engine[n];
|
||||
@@ -414,7 +414,7 @@ i915_gem_create_context(struct drm_i915_private *dev_priv,
|
||||
if (IS_ERR(ctx))
|
||||
return ctx;
|
||||
|
||||
if (USES_FULL_PPGTT(dev_priv)) {
|
||||
if (HAS_FULL_PPGTT(dev_priv)) {
|
||||
struct i915_hw_ppgtt *ppgtt;
|
||||
|
||||
ppgtt = i915_ppgtt_create(dev_priv, file_priv);
|
||||
@@ -457,7 +457,7 @@ i915_gem_context_create_gvt(struct drm_device *dev)
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ctx = __create_hw_context(to_i915(dev), NULL);
|
||||
ctx = i915_gem_create_context(to_i915(dev), NULL);
|
||||
if (IS_ERR(ctx))
|
||||
goto out;
|
||||
|
||||
@@ -504,7 +504,7 @@ i915_gem_context_create_kernel(struct drm_i915_private *i915, int prio)
|
||||
}
|
||||
|
||||
i915_gem_context_clear_bannable(ctx);
|
||||
ctx->sched.priority = prio;
|
||||
ctx->sched.priority = I915_USER_PRIORITY(prio);
|
||||
ctx->ring_size = PAGE_SIZE;
|
||||
|
||||
GEM_BUG_ON(!i915_gem_context_is_kernel(ctx));
|
||||
@@ -535,16 +535,12 @@ static bool needs_preempt_context(struct drm_i915_private *i915)
|
||||
int i915_gem_contexts_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct i915_gem_context *ctx;
|
||||
int ret;
|
||||
|
||||
/* Reassure ourselves we are only called once */
|
||||
GEM_BUG_ON(dev_priv->kernel_context);
|
||||
GEM_BUG_ON(dev_priv->preempt_context);
|
||||
|
||||
ret = intel_ctx_workarounds_init(dev_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
intel_engine_init_ctx_wa(dev_priv->engine[RCS]);
|
||||
init_contexts(dev_priv);
|
||||
|
||||
/* lowest priority; idle task */
|
||||
@@ -879,7 +875,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
|
||||
args->value = i915_gem_context_is_bannable(ctx);
|
||||
break;
|
||||
case I915_CONTEXT_PARAM_PRIORITY:
|
||||
args->value = ctx->sched.priority;
|
||||
args->value = ctx->sched.priority >> I915_USER_PRIORITY_SHIFT;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@@ -948,7 +944,8 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
|
||||
!capable(CAP_SYS_NICE))
|
||||
ret = -EPERM;
|
||||
else
|
||||
ctx->sched.priority = priority;
|
||||
ctx->sched.priority =
|
||||
I915_USER_PRIORITY(priority);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@@ -163,6 +163,7 @@ struct i915_gem_context {
|
||||
/** engine: per-engine logical HW state */
|
||||
struct intel_context {
|
||||
struct i915_gem_context *gem_context;
|
||||
struct intel_engine_cs *active;
|
||||
struct i915_vma *state;
|
||||
struct intel_ring *ring;
|
||||
u32 *lrc_reg_state;
|
||||
|
@@ -2186,7 +2186,7 @@ signal_fence_array(struct i915_execbuffer *eb,
|
||||
if (!(flags & I915_EXEC_FENCE_SIGNAL))
|
||||
continue;
|
||||
|
||||
drm_syncobj_replace_fence(syncobj, 0, fence);
|
||||
drm_syncobj_replace_fence(syncobj, fence);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -133,55 +133,6 @@ static inline void i915_ggtt_invalidate(struct drm_i915_private *i915)
|
||||
i915->ggtt.invalidate(i915);
|
||||
}
|
||||
|
||||
int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
|
||||
int enable_ppgtt)
|
||||
{
|
||||
bool has_full_ppgtt;
|
||||
bool has_full_48bit_ppgtt;
|
||||
|
||||
if (!dev_priv->info.has_aliasing_ppgtt)
|
||||
return 0;
|
||||
|
||||
has_full_ppgtt = dev_priv->info.has_full_ppgtt;
|
||||
has_full_48bit_ppgtt = dev_priv->info.has_full_48bit_ppgtt;
|
||||
|
||||
if (intel_vgpu_active(dev_priv)) {
|
||||
/* GVT-g has no support for 32bit ppgtt */
|
||||
has_full_ppgtt = false;
|
||||
has_full_48bit_ppgtt = intel_vgpu_has_full_48bit_ppgtt(dev_priv);
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't allow disabling PPGTT for gen9+ as it's a requirement for
|
||||
* execlists, the sole mechanism available to submit work.
|
||||
*/
|
||||
if (enable_ppgtt == 0 && INTEL_GEN(dev_priv) < 9)
|
||||
return 0;
|
||||
|
||||
if (enable_ppgtt == 1)
|
||||
return 1;
|
||||
|
||||
if (enable_ppgtt == 2 && has_full_ppgtt)
|
||||
return 2;
|
||||
|
||||
if (enable_ppgtt == 3 && has_full_48bit_ppgtt)
|
||||
return 3;
|
||||
|
||||
/* Disable ppgtt on SNB if VT-d is on. */
|
||||
if (IS_GEN6(dev_priv) && intel_vtd_active()) {
|
||||
DRM_INFO("Disabling PPGTT because VT-d is on\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (has_full_48bit_ppgtt)
|
||||
return 3;
|
||||
|
||||
if (has_full_ppgtt)
|
||||
return 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ppgtt_bind_vma(struct i915_vma *vma,
|
||||
enum i915_cache_level cache_level,
|
||||
u32 unused)
|
||||
@@ -235,9 +186,9 @@ static void clear_pages(struct i915_vma *vma)
|
||||
memset(&vma->page_sizes, 0, sizeof(vma->page_sizes));
|
||||
}
|
||||
|
||||
static gen8_pte_t gen8_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
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;
|
||||
|
||||
@@ -274,9 +225,9 @@ static gen8_pde_t gen8_pde_encode(const dma_addr_t addr,
|
||||
#define gen8_pdpe_encode gen8_pde_encode
|
||||
#define gen8_pml4e_encode gen8_pde_encode
|
||||
|
||||
static gen6_pte_t snb_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 unused)
|
||||
static u64 snb_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
gen6_pte_t pte = GEN6_PTE_VALID;
|
||||
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
||||
@@ -296,9 +247,9 @@ static gen6_pte_t snb_pte_encode(dma_addr_t addr,
|
||||
return pte;
|
||||
}
|
||||
|
||||
static gen6_pte_t ivb_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 unused)
|
||||
static u64 ivb_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
gen6_pte_t pte = GEN6_PTE_VALID;
|
||||
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
||||
@@ -320,9 +271,9 @@ static gen6_pte_t ivb_pte_encode(dma_addr_t addr,
|
||||
return pte;
|
||||
}
|
||||
|
||||
static gen6_pte_t byt_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
static u64 byt_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
gen6_pte_t pte = GEN6_PTE_VALID;
|
||||
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
||||
@@ -336,9 +287,9 @@ static gen6_pte_t byt_pte_encode(dma_addr_t addr,
|
||||
return pte;
|
||||
}
|
||||
|
||||
static gen6_pte_t hsw_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 unused)
|
||||
static u64 hsw_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
gen6_pte_t pte = GEN6_PTE_VALID;
|
||||
pte |= HSW_PTE_ADDR_ENCODE(addr);
|
||||
@@ -349,9 +300,9 @@ static gen6_pte_t hsw_pte_encode(dma_addr_t addr,
|
||||
return pte;
|
||||
}
|
||||
|
||||
static gen6_pte_t iris_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 unused)
|
||||
static u64 iris_pte_encode(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
gen6_pte_t pte = GEN6_PTE_VALID;
|
||||
pte |= HSW_PTE_ADDR_ENCODE(addr);
|
||||
@@ -629,10 +580,9 @@ setup_scratch_page(struct i915_address_space *vm, gfp_t gfp)
|
||||
* region, including any PTEs which happen to point to scratch.
|
||||
*
|
||||
* This is only relevant for the 48b PPGTT where we support
|
||||
* huge-gtt-pages, see also i915_vma_insert().
|
||||
*
|
||||
* TODO: we should really consider write-protecting the scratch-page and
|
||||
* sharing between ppgtt
|
||||
* huge-gtt-pages, see also i915_vma_insert(). However, as we share the
|
||||
* scratch (read-only) between all vm, we create one 64k scratch page
|
||||
* for all.
|
||||
*/
|
||||
size = I915_GTT_PAGE_SIZE_4K;
|
||||
if (i915_vm_is_48bit(vm) &&
|
||||
@@ -715,14 +665,13 @@ static void free_pt(struct i915_address_space *vm, struct i915_page_table *pt)
|
||||
static void gen8_initialize_pt(struct i915_address_space *vm,
|
||||
struct i915_page_table *pt)
|
||||
{
|
||||
fill_px(vm, pt,
|
||||
gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, 0));
|
||||
fill_px(vm, pt, vm->scratch_pte);
|
||||
}
|
||||
|
||||
static void gen6_initialize_pt(struct gen6_hw_ppgtt *ppgtt,
|
||||
static void gen6_initialize_pt(struct i915_address_space *vm,
|
||||
struct i915_page_table *pt)
|
||||
{
|
||||
fill32_px(&ppgtt->base.vm, pt, ppgtt->scratch_pte);
|
||||
fill32_px(vm, pt, vm->scratch_pte);
|
||||
}
|
||||
|
||||
static struct i915_page_directory *alloc_pd(struct i915_address_space *vm)
|
||||
@@ -856,15 +805,13 @@ static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
|
||||
/* Removes entries from a single page table, releasing it if it's empty.
|
||||
* Caller can use the return value to update higher-level entries.
|
||||
*/
|
||||
static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm,
|
||||
static bool gen8_ppgtt_clear_pt(const struct i915_address_space *vm,
|
||||
struct i915_page_table *pt,
|
||||
u64 start, u64 length)
|
||||
{
|
||||
unsigned int num_entries = gen8_pte_count(start, length);
|
||||
unsigned int pte = gen8_pte_index(start);
|
||||
unsigned int pte_end = pte + num_entries;
|
||||
const gen8_pte_t scratch_pte =
|
||||
gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, 0);
|
||||
gen8_pte_t *vaddr;
|
||||
|
||||
GEM_BUG_ON(num_entries > pt->used_ptes);
|
||||
@@ -875,7 +822,7 @@ static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm,
|
||||
|
||||
vaddr = kmap_atomic_px(pt);
|
||||
while (pte < pte_end)
|
||||
vaddr[pte++] = scratch_pte;
|
||||
vaddr[pte++] = vm->scratch_pte;
|
||||
kunmap_atomic(vaddr);
|
||||
|
||||
return false;
|
||||
@@ -1208,7 +1155,7 @@ static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma,
|
||||
if (I915_SELFTEST_ONLY(vma->vm->scrub_64K)) {
|
||||
u16 i;
|
||||
|
||||
encode = pte_encode | vma->vm->scratch_page.daddr;
|
||||
encode = vma->vm->scratch_pte;
|
||||
vaddr = kmap_atomic_px(pd->page_table[idx.pde]);
|
||||
|
||||
for (i = 1; i < index; i += 16)
|
||||
@@ -1261,10 +1208,35 @@ static int gen8_init_scratch(struct i915_address_space *vm)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If everybody agrees to not to write into the scratch page,
|
||||
* we can reuse it for all vm, keeping contexts and processes separate.
|
||||
*/
|
||||
if (vm->has_read_only &&
|
||||
vm->i915->kernel_context &&
|
||||
vm->i915->kernel_context->ppgtt) {
|
||||
struct i915_address_space *clone =
|
||||
&vm->i915->kernel_context->ppgtt->vm;
|
||||
|
||||
GEM_BUG_ON(!clone->has_read_only);
|
||||
|
||||
vm->scratch_page.order = clone->scratch_page.order;
|
||||
vm->scratch_pte = clone->scratch_pte;
|
||||
vm->scratch_pt = clone->scratch_pt;
|
||||
vm->scratch_pd = clone->scratch_pd;
|
||||
vm->scratch_pdp = clone->scratch_pdp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = setup_scratch_page(vm, __GFP_HIGHMEM);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vm->scratch_pte =
|
||||
gen8_pte_encode(vm->scratch_page.daddr,
|
||||
I915_CACHE_LLC,
|
||||
PTE_READ_ONLY);
|
||||
|
||||
vm->scratch_pt = alloc_pt(vm);
|
||||
if (IS_ERR(vm->scratch_pt)) {
|
||||
ret = PTR_ERR(vm->scratch_pt);
|
||||
@@ -1336,6 +1308,9 @@ static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
|
||||
|
||||
static void gen8_free_scratch(struct i915_address_space *vm)
|
||||
{
|
||||
if (!vm->scratch_page.daddr)
|
||||
return;
|
||||
|
||||
if (use_4lvl(vm))
|
||||
free_pdp(vm, vm->scratch_pdp);
|
||||
free_pd(vm, vm->scratch_pd);
|
||||
@@ -1573,8 +1548,7 @@ static void gen8_dump_pdp(struct i915_hw_ppgtt *ppgtt,
|
||||
static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
|
||||
{
|
||||
struct i915_address_space *vm = &ppgtt->vm;
|
||||
const gen8_pte_t scratch_pte =
|
||||
gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, 0);
|
||||
const gen8_pte_t scratch_pte = vm->scratch_pte;
|
||||
u64 start = 0, length = ppgtt->vm.total;
|
||||
|
||||
if (use_4lvl(vm)) {
|
||||
@@ -1647,16 +1621,12 @@ static struct i915_hw_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
|
||||
ppgtt->vm.i915 = i915;
|
||||
ppgtt->vm.dma = &i915->drm.pdev->dev;
|
||||
|
||||
ppgtt->vm.total = USES_FULL_48BIT_PPGTT(i915) ?
|
||||
ppgtt->vm.total = HAS_FULL_48BIT_PPGTT(i915) ?
|
||||
1ULL << 48 :
|
||||
1ULL << 32;
|
||||
|
||||
/*
|
||||
* From bdw, there is support for read-only pages in the PPGTT.
|
||||
*
|
||||
* XXX GVT is not honouring the lack of RW in the PTE bits.
|
||||
*/
|
||||
ppgtt->vm.has_read_only = !intel_vgpu_active(i915);
|
||||
/* From bdw, there is support for read-only pages in the PPGTT. */
|
||||
ppgtt->vm.has_read_only = true;
|
||||
|
||||
i915_address_space_init(&ppgtt->vm, i915);
|
||||
|
||||
@@ -1721,7 +1691,7 @@ err_free:
|
||||
static void gen6_dump_ppgtt(struct i915_hw_ppgtt *base, struct seq_file *m)
|
||||
{
|
||||
struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);
|
||||
const gen6_pte_t scratch_pte = ppgtt->scratch_pte;
|
||||
const gen6_pte_t scratch_pte = base->vm.scratch_pte;
|
||||
struct i915_page_table *pt;
|
||||
u32 pte, pde;
|
||||
|
||||
@@ -1782,19 +1752,6 @@ static inline void gen6_write_pde(const struct gen6_hw_ppgtt *ppgtt,
|
||||
ppgtt->pd_addr + pde);
|
||||
}
|
||||
|
||||
static void gen8_ppgtt_enable(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_engine_cs *engine;
|
||||
enum intel_engine_id id;
|
||||
|
||||
for_each_engine(engine, dev_priv, id) {
|
||||
u32 four_level = USES_FULL_48BIT_PPGTT(dev_priv) ?
|
||||
GEN8_GFX_PPGTT_48B : 0;
|
||||
I915_WRITE(RING_MODE_GEN7(engine),
|
||||
_MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level));
|
||||
}
|
||||
}
|
||||
|
||||
static void gen7_ppgtt_enable(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_engine_cs *engine;
|
||||
@@ -1834,7 +1791,8 @@ static void gen6_ppgtt_enable(struct drm_i915_private *dev_priv)
|
||||
ecochk = I915_READ(GAM_ECOCHK);
|
||||
I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | ECOCHK_PPGTT_CACHE64B);
|
||||
|
||||
I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
|
||||
if (HAS_PPGTT(dev_priv)) /* may be disabled for VT-d */
|
||||
I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
|
||||
}
|
||||
|
||||
/* PPGTT support for Sandybdrige/Gen6 and later */
|
||||
@@ -1846,7 +1804,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
|
||||
unsigned int pde = first_entry / GEN6_PTES;
|
||||
unsigned int pte = first_entry % GEN6_PTES;
|
||||
unsigned int num_entries = length / I915_GTT_PAGE_SIZE;
|
||||
const gen6_pte_t scratch_pte = ppgtt->scratch_pte;
|
||||
const gen6_pte_t scratch_pte = vm->scratch_pte;
|
||||
|
||||
while (num_entries) {
|
||||
struct i915_page_table *pt = ppgtt->base.pd.page_table[pde++];
|
||||
@@ -1937,7 +1895,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm,
|
||||
if (IS_ERR(pt))
|
||||
goto unwind_out;
|
||||
|
||||
gen6_initialize_pt(ppgtt, pt);
|
||||
gen6_initialize_pt(vm, pt);
|
||||
ppgtt->base.pd.page_table[pde] = pt;
|
||||
|
||||
if (i915_vma_is_bound(ppgtt->vma,
|
||||
@@ -1975,9 +1933,9 @@ static int gen6_ppgtt_init_scratch(struct gen6_hw_ppgtt *ppgtt)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ppgtt->scratch_pte =
|
||||
vm->pte_encode(vm->scratch_page.daddr,
|
||||
I915_CACHE_NONE, PTE_READ_ONLY);
|
||||
vm->scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
|
||||
I915_CACHE_NONE,
|
||||
PTE_READ_ONLY);
|
||||
|
||||
vm->scratch_pt = alloc_pt(vm);
|
||||
if (IS_ERR(vm->scratch_pt)) {
|
||||
@@ -1985,7 +1943,7 @@ static int gen6_ppgtt_init_scratch(struct gen6_hw_ppgtt *ppgtt)
|
||||
return PTR_ERR(vm->scratch_pt);
|
||||
}
|
||||
|
||||
gen6_initialize_pt(ppgtt, vm->scratch_pt);
|
||||
gen6_initialize_pt(vm, vm->scratch_pt);
|
||||
gen6_for_all_pdes(unused, &ppgtt->base.pd, pde)
|
||||
ppgtt->base.pd.page_table[pde] = vm->scratch_pt;
|
||||
|
||||
@@ -2237,23 +2195,10 @@ int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
gtt_write_workarounds(dev_priv);
|
||||
|
||||
/* In the case of execlists, PPGTT is enabled by the context descriptor
|
||||
* and the PDPs are contained within the context itself. We don't
|
||||
* need to do anything here. */
|
||||
if (HAS_LOGICAL_RING_CONTEXTS(dev_priv))
|
||||
return 0;
|
||||
|
||||
if (!USES_PPGTT(dev_priv))
|
||||
return 0;
|
||||
|
||||
if (IS_GEN6(dev_priv))
|
||||
gen6_ppgtt_enable(dev_priv);
|
||||
else if (IS_GEN7(dev_priv))
|
||||
gen7_ppgtt_enable(dev_priv);
|
||||
else if (INTEL_GEN(dev_priv) >= 8)
|
||||
gen8_ppgtt_enable(dev_priv);
|
||||
else
|
||||
MISSING_CASE(INTEL_GEN(dev_priv));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2543,8 +2488,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
||||
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
|
||||
unsigned first_entry = start / I915_GTT_PAGE_SIZE;
|
||||
unsigned num_entries = length / I915_GTT_PAGE_SIZE;
|
||||
const gen8_pte_t scratch_pte =
|
||||
gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, 0);
|
||||
const gen8_pte_t scratch_pte = vm->scratch_pte;
|
||||
gen8_pte_t __iomem *gtt_base =
|
||||
(gen8_pte_t __iomem *)ggtt->gsm + first_entry;
|
||||
const int max_entries = ggtt_total_entries(ggtt) - first_entry;
|
||||
@@ -2669,8 +2613,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
|
||||
first_entry, num_entries, max_entries))
|
||||
num_entries = max_entries;
|
||||
|
||||
scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
|
||||
I915_CACHE_LLC, 0);
|
||||
scratch_pte = vm->scratch_pte;
|
||||
|
||||
for (i = 0; i < num_entries; i++)
|
||||
iowrite32(scratch_pte, >t_base[i]);
|
||||
@@ -2952,7 +2895,7 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv)
|
||||
/* And finally clear the reserved guard page */
|
||||
ggtt->vm.clear_range(&ggtt->vm, ggtt->vm.total - PAGE_SIZE, PAGE_SIZE);
|
||||
|
||||
if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) {
|
||||
if (INTEL_PPGTT(dev_priv) == INTEL_PPGTT_ALIASING) {
|
||||
ret = i915_gem_init_aliasing_ppgtt(dev_priv);
|
||||
if (ret)
|
||||
goto err;
|
||||
@@ -3076,6 +3019,10 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ggtt->vm.scratch_pte =
|
||||
ggtt->vm.pte_encode(ggtt->vm.scratch_page.daddr,
|
||||
I915_CACHE_NONE, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3275,7 +3222,7 @@ static void bdw_setup_private_ppat(struct intel_ppat *ppat)
|
||||
ppat->match = bdw_private_pat_match;
|
||||
ppat->clear_value = GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3);
|
||||
|
||||
if (!USES_PPGTT(ppat->i915)) {
|
||||
if (!HAS_PPGTT(ppat->i915)) {
|
||||
/* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry,
|
||||
* so RTL will always use the value corresponding to
|
||||
* pat_sel = 000".
|
||||
@@ -3402,7 +3349,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
|
||||
ggtt->vm.cleanup = gen6_gmch_remove;
|
||||
ggtt->vm.insert_page = gen8_ggtt_insert_page;
|
||||
ggtt->vm.clear_range = nop_clear_range;
|
||||
if (!USES_FULL_PPGTT(dev_priv) || intel_scanout_needs_vtd_wa(dev_priv))
|
||||
if (intel_scanout_needs_vtd_wa(dev_priv))
|
||||
ggtt->vm.clear_range = gen8_ggtt_clear_range;
|
||||
|
||||
ggtt->vm.insert_entries = gen8_ggtt_insert_entries;
|
||||
@@ -3427,6 +3374,8 @@ 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;
|
||||
|
||||
setup_private_pat(dev_priv);
|
||||
|
||||
return ggtt_probe_common(ggtt, size);
|
||||
@@ -3614,7 +3563,7 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
|
||||
/* Only VLV supports read-only GGTT mappings */
|
||||
ggtt->vm.has_read_only = IS_VALLEYVIEW(dev_priv);
|
||||
|
||||
if (!HAS_LLC(dev_priv) && !USES_PPGTT(dev_priv))
|
||||
if (!HAS_LLC(dev_priv) && !HAS_PPGTT(dev_priv))
|
||||
ggtt->vm.mm.color_adjust = i915_gtt_color_adjust;
|
||||
mutex_unlock(&dev_priv->drm.struct_mutex);
|
||||
|
||||
@@ -3716,7 +3665,7 @@ void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
|
||||
}
|
||||
|
||||
static struct scatterlist *
|
||||
rotate_pages(const dma_addr_t *in, unsigned int offset,
|
||||
rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
|
||||
unsigned int width, unsigned int height,
|
||||
unsigned int stride,
|
||||
struct sg_table *st, struct scatterlist *sg)
|
||||
@@ -3725,7 +3674,7 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
|
||||
unsigned int src_idx;
|
||||
|
||||
for (column = 0; column < width; column++) {
|
||||
src_idx = stride * (height - 1) + column;
|
||||
src_idx = stride * (height - 1) + column + offset;
|
||||
for (row = 0; row < height; row++) {
|
||||
st->nents++;
|
||||
/* We don't need the pages, but need to initialize
|
||||
@@ -3733,7 +3682,8 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
|
||||
* The only thing we need are DMA addresses.
|
||||
*/
|
||||
sg_set_page(sg, NULL, I915_GTT_PAGE_SIZE, 0);
|
||||
sg_dma_address(sg) = in[offset + src_idx];
|
||||
sg_dma_address(sg) =
|
||||
i915_gem_object_get_dma_address(obj, src_idx);
|
||||
sg_dma_len(sg) = I915_GTT_PAGE_SIZE;
|
||||
sg = sg_next(sg);
|
||||
src_idx -= stride;
|
||||
@@ -3747,22 +3697,11 @@ static noinline struct sg_table *
|
||||
intel_rotate_pages(struct intel_rotation_info *rot_info,
|
||||
struct drm_i915_gem_object *obj)
|
||||
{
|
||||
const unsigned long n_pages = obj->base.size / I915_GTT_PAGE_SIZE;
|
||||
unsigned int size = intel_rotation_info_size(rot_info);
|
||||
struct sgt_iter sgt_iter;
|
||||
dma_addr_t dma_addr;
|
||||
unsigned long i;
|
||||
dma_addr_t *page_addr_list;
|
||||
struct sg_table *st;
|
||||
struct scatterlist *sg;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
/* Allocate a temporary list of source pages for random access. */
|
||||
page_addr_list = kvmalloc_array(n_pages,
|
||||
sizeof(dma_addr_t),
|
||||
GFP_KERNEL);
|
||||
if (!page_addr_list)
|
||||
return ERR_PTR(ret);
|
||||
int i;
|
||||
|
||||
/* Allocate target SG list. */
|
||||
st = kmalloc(sizeof(*st), GFP_KERNEL);
|
||||
@@ -3773,29 +3712,20 @@ intel_rotate_pages(struct intel_rotation_info *rot_info,
|
||||
if (ret)
|
||||
goto err_sg_alloc;
|
||||
|
||||
/* Populate source page list from the object. */
|
||||
i = 0;
|
||||
for_each_sgt_dma(dma_addr, sgt_iter, obj->mm.pages)
|
||||
page_addr_list[i++] = dma_addr;
|
||||
|
||||
GEM_BUG_ON(i != n_pages);
|
||||
st->nents = 0;
|
||||
sg = st->sgl;
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++) {
|
||||
sg = rotate_pages(page_addr_list, rot_info->plane[i].offset,
|
||||
sg = rotate_pages(obj, rot_info->plane[i].offset,
|
||||
rot_info->plane[i].width, rot_info->plane[i].height,
|
||||
rot_info->plane[i].stride, st, sg);
|
||||
}
|
||||
|
||||
kvfree(page_addr_list);
|
||||
|
||||
return st;
|
||||
|
||||
err_sg_alloc:
|
||||
kfree(st);
|
||||
err_st_alloc:
|
||||
kvfree(page_addr_list);
|
||||
|
||||
DRM_DEBUG_DRIVER("Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n",
|
||||
obj->base.size, rot_info->plane[0].width, rot_info->plane[0].height, size);
|
||||
@@ -3840,6 +3770,8 @@ intel_partial_pages(const struct i915_ggtt_view *view,
|
||||
count -= len >> PAGE_SHIFT;
|
||||
if (count == 0) {
|
||||
sg_mark_end(sg);
|
||||
i915_sg_trim(st); /* Drop any unused tail entries. */
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
|
@@ -289,6 +289,7 @@ struct i915_address_space {
|
||||
|
||||
struct mutex mutex; /* protects vma and our lists */
|
||||
|
||||
u64 scratch_pte;
|
||||
struct i915_page_dma scratch_page;
|
||||
struct i915_page_table *scratch_pt;
|
||||
struct i915_page_directory *scratch_pd;
|
||||
@@ -335,12 +336,11 @@ struct i915_address_space {
|
||||
/* Some systems support read-only mappings for GGTT and/or PPGTT */
|
||||
bool has_read_only:1;
|
||||
|
||||
/* FIXME: Need a more generic return type */
|
||||
gen6_pte_t (*pte_encode)(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags); /* Create a valid PTE */
|
||||
/* flags for pte_encode */
|
||||
u64 (*pte_encode)(dma_addr_t addr,
|
||||
enum i915_cache_level level,
|
||||
u32 flags); /* Create a valid PTE */
|
||||
#define PTE_READ_ONLY (1<<0)
|
||||
|
||||
int (*allocate_va_range)(struct i915_address_space *vm,
|
||||
u64 start, u64 length);
|
||||
void (*clear_range)(struct i915_address_space *vm,
|
||||
@@ -422,7 +422,6 @@ struct gen6_hw_ppgtt {
|
||||
|
||||
struct i915_vma *vma;
|
||||
gen6_pte_t __iomem *pd_addr;
|
||||
gen6_pte_t scratch_pte;
|
||||
|
||||
unsigned int pin_count;
|
||||
bool scan_for_unused_pt;
|
||||
|
@@ -27,11 +27,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <generated/utsrelease.h>
|
||||
#include <linux/stop_machine.h>
|
||||
#include <linux/zlib.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <linux/ascii85.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/stop_machine.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/zlib.h>
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_gpu_error.h"
|
||||
#include "i915_drv.h"
|
||||
@@ -77,112 +80,110 @@ static const char *purgeable_flag(int purgeable)
|
||||
return purgeable ? " purgeable" : "";
|
||||
}
|
||||
|
||||
static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
|
||||
static void __sg_set_buf(struct scatterlist *sg,
|
||||
void *addr, unsigned int len, loff_t it)
|
||||
{
|
||||
|
||||
if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
|
||||
e->err = -ENOSPC;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e->bytes == e->size - 1 || e->err)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
sg->page_link = (unsigned long)virt_to_page(addr);
|
||||
sg->offset = offset_in_page(addr);
|
||||
sg->length = len;
|
||||
sg->dma_address = it;
|
||||
}
|
||||
|
||||
static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
|
||||
unsigned len)
|
||||
static bool __i915_error_grow(struct drm_i915_error_state_buf *e, size_t len)
|
||||
{
|
||||
if (e->pos + len <= e->start) {
|
||||
e->pos += len;
|
||||
if (!len)
|
||||
return false;
|
||||
|
||||
if (e->bytes + len + 1 <= e->size)
|
||||
return true;
|
||||
|
||||
if (e->bytes) {
|
||||
__sg_set_buf(e->cur++, e->buf, e->bytes, e->iter);
|
||||
e->iter += e->bytes;
|
||||
e->buf = NULL;
|
||||
e->bytes = 0;
|
||||
}
|
||||
|
||||
/* First vsnprintf needs to fit in its entirety for memmove */
|
||||
if (len >= e->size) {
|
||||
e->err = -EIO;
|
||||
return false;
|
||||
}
|
||||
if (e->cur == e->end) {
|
||||
struct scatterlist *sgl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void __i915_error_advance(struct drm_i915_error_state_buf *e,
|
||||
unsigned len)
|
||||
{
|
||||
/* If this is first printf in this window, adjust it so that
|
||||
* start position matches start of the buffer
|
||||
*/
|
||||
|
||||
if (e->pos < e->start) {
|
||||
const size_t off = e->start - e->pos;
|
||||
|
||||
/* Should not happen but be paranoid */
|
||||
if (off > len || e->bytes) {
|
||||
e->err = -EIO;
|
||||
return;
|
||||
sgl = (typeof(sgl))__get_free_page(GFP_KERNEL);
|
||||
if (!sgl) {
|
||||
e->err = -ENOMEM;
|
||||
return false;
|
||||
}
|
||||
|
||||
memmove(e->buf, e->buf + off, len - off);
|
||||
e->bytes = len - off;
|
||||
e->pos = e->start;
|
||||
return;
|
||||
if (e->cur) {
|
||||
e->cur->offset = 0;
|
||||
e->cur->length = 0;
|
||||
e->cur->page_link =
|
||||
(unsigned long)sgl | SG_CHAIN;
|
||||
} else {
|
||||
e->sgl = sgl;
|
||||
}
|
||||
|
||||
e->cur = sgl;
|
||||
e->end = sgl + SG_MAX_SINGLE_ALLOC - 1;
|
||||
}
|
||||
|
||||
e->bytes += len;
|
||||
e->pos += len;
|
||||
e->size = ALIGN(len + 1, SZ_64K);
|
||||
e->buf = kmalloc(e->size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
|
||||
if (!e->buf) {
|
||||
e->size = PAGE_ALIGN(len + 1);
|
||||
e->buf = kmalloc(e->size, GFP_KERNEL);
|
||||
}
|
||||
if (!e->buf) {
|
||||
e->err = -ENOMEM;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__printf(2, 0)
|
||||
static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
|
||||
const char *f, va_list args)
|
||||
const char *fmt, va_list args)
|
||||
{
|
||||
unsigned len;
|
||||
va_list ap;
|
||||
int len;
|
||||
|
||||
if (!__i915_error_ok(e))
|
||||
if (e->err)
|
||||
return;
|
||||
|
||||
/* Seek the first printf which is hits start position */
|
||||
if (e->pos < e->start) {
|
||||
va_list tmp;
|
||||
|
||||
va_copy(tmp, args);
|
||||
len = vsnprintf(NULL, 0, f, tmp);
|
||||
va_end(tmp);
|
||||
|
||||
if (!__i915_error_seek(e, len))
|
||||
return;
|
||||
va_copy(ap, args);
|
||||
len = vsnprintf(NULL, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
if (len <= 0) {
|
||||
e->err = len;
|
||||
return;
|
||||
}
|
||||
|
||||
len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
|
||||
if (len >= e->size - e->bytes)
|
||||
len = e->size - e->bytes - 1;
|
||||
if (!__i915_error_grow(e, len))
|
||||
return;
|
||||
|
||||
__i915_error_advance(e, len);
|
||||
GEM_BUG_ON(e->bytes >= e->size);
|
||||
len = vscnprintf(e->buf + e->bytes, e->size - e->bytes, fmt, args);
|
||||
if (len < 0) {
|
||||
e->err = len;
|
||||
return;
|
||||
}
|
||||
e->bytes += len;
|
||||
}
|
||||
|
||||
static void i915_error_puts(struct drm_i915_error_state_buf *e,
|
||||
const char *str)
|
||||
static void i915_error_puts(struct drm_i915_error_state_buf *e, const char *str)
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
if (!__i915_error_ok(e))
|
||||
if (e->err || !str)
|
||||
return;
|
||||
|
||||
len = strlen(str);
|
||||
if (!__i915_error_grow(e, len))
|
||||
return;
|
||||
|
||||
/* Seek the first printf which is hits start position */
|
||||
if (e->pos < e->start) {
|
||||
if (!__i915_error_seek(e, len))
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= e->size - e->bytes)
|
||||
len = e->size - e->bytes - 1;
|
||||
GEM_BUG_ON(e->bytes + len > e->size);
|
||||
memcpy(e->buf + e->bytes, str, len);
|
||||
|
||||
__i915_error_advance(e, len);
|
||||
e->bytes += len;
|
||||
}
|
||||
|
||||
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
|
||||
@@ -268,6 +269,8 @@ static int compress_page(struct compress *c,
|
||||
|
||||
if (zlib_deflate(zstream, Z_NO_FLUSH) != Z_OK)
|
||||
return -EIO;
|
||||
|
||||
touch_nmi_watchdog();
|
||||
} while (zstream->avail_in);
|
||||
|
||||
/* Fallback to uncompressed if we increase size? */
|
||||
@@ -512,7 +515,7 @@ static void error_print_engine(struct drm_i915_error_state_buf *m,
|
||||
err_printf(m, " SYNC_2: 0x%08x\n",
|
||||
ee->semaphore_mboxes[2]);
|
||||
}
|
||||
if (USES_PPGTT(m->i915)) {
|
||||
if (HAS_PPGTT(m->i915)) {
|
||||
err_printf(m, " GFX_MODE: 0x%08x\n", ee->vm_info.gfx_mode);
|
||||
|
||||
if (INTEL_GEN(m->i915) >= 8) {
|
||||
@@ -635,25 +638,33 @@ static void err_print_uc(struct drm_i915_error_state_buf *m,
|
||||
print_error_obj(m, NULL, "GuC log buffer", error_uc->guc_log);
|
||||
}
|
||||
|
||||
int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
const struct i915_gpu_state *error)
|
||||
static void err_free_sgl(struct scatterlist *sgl)
|
||||
{
|
||||
while (sgl) {
|
||||
struct scatterlist *sg;
|
||||
|
||||
for (sg = sgl; !sg_is_chain(sg); sg++) {
|
||||
kfree(sg_virt(sg));
|
||||
if (sg_is_last(sg))
|
||||
break;
|
||||
}
|
||||
|
||||
sg = sg_is_last(sg) ? NULL : sg_chain_ptr(sg);
|
||||
free_page((unsigned long)sgl);
|
||||
sgl = sg;
|
||||
}
|
||||
}
|
||||
|
||||
static void __err_print_to_sgl(struct drm_i915_error_state_buf *m,
|
||||
struct i915_gpu_state *error)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = m->i915;
|
||||
struct drm_i915_error_object *obj;
|
||||
struct timespec64 ts;
|
||||
int i, j;
|
||||
|
||||
if (!error) {
|
||||
err_printf(m, "No error state collected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IS_ERR(error))
|
||||
return PTR_ERR(error);
|
||||
|
||||
if (*error->error_msg)
|
||||
err_printf(m, "%s\n", error->error_msg);
|
||||
err_printf(m, "Kernel: " UTS_RELEASE "\n");
|
||||
err_printf(m, "Kernel: %s\n", init_utsname()->release);
|
||||
ts = ktime_to_timespec64(error->time);
|
||||
err_printf(m, "Time: %lld s %ld us\n",
|
||||
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
|
||||
@@ -683,12 +694,12 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
err_printf(m, "Reset count: %u\n", error->reset_count);
|
||||
err_printf(m, "Suspend count: %u\n", error->suspend_count);
|
||||
err_printf(m, "Platform: %s\n", intel_platform_name(error->device_info.platform));
|
||||
err_print_pciid(m, error->i915);
|
||||
err_print_pciid(m, m->i915);
|
||||
|
||||
err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
|
||||
|
||||
if (HAS_CSR(dev_priv)) {
|
||||
struct intel_csr *csr = &dev_priv->csr;
|
||||
if (HAS_CSR(m->i915)) {
|
||||
struct intel_csr *csr = &m->i915->csr;
|
||||
|
||||
err_printf(m, "DMC loaded: %s\n",
|
||||
yesno(csr->dmc_payload != NULL));
|
||||
@@ -708,22 +719,23 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
|
||||
err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
|
||||
err_printf(m, "CCID: 0x%08x\n", error->ccid);
|
||||
err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings);
|
||||
err_printf(m, "Missed interrupts: 0x%08lx\n",
|
||||
m->i915->gpu_error.missed_irq_rings);
|
||||
|
||||
for (i = 0; i < error->nfence; i++)
|
||||
err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 6) {
|
||||
if (INTEL_GEN(m->i915) >= 6) {
|
||||
err_printf(m, "ERROR: 0x%08x\n", error->error);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 8)
|
||||
if (INTEL_GEN(m->i915) >= 8)
|
||||
err_printf(m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
|
||||
error->fault_data1, error->fault_data0);
|
||||
|
||||
err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
|
||||
}
|
||||
|
||||
if (IS_GEN7(dev_priv))
|
||||
if (IS_GEN7(m->i915))
|
||||
err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
|
||||
@@ -745,7 +757,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
|
||||
len += scnprintf(buf + len, sizeof(buf), "%s%s",
|
||||
first ? "" : ", ",
|
||||
dev_priv->engine[j]->name);
|
||||
m->i915->engine[j]->name);
|
||||
first = 0;
|
||||
}
|
||||
scnprintf(buf + len, sizeof(buf), ")");
|
||||
@@ -763,7 +775,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
|
||||
obj = ee->batchbuffer;
|
||||
if (obj) {
|
||||
err_puts(m, dev_priv->engine[i]->name);
|
||||
err_puts(m, m->i915->engine[i]->name);
|
||||
if (ee->context.pid)
|
||||
err_printf(m, " (submitted by %s [%d], ctx %d [%d], score %d%s)",
|
||||
ee->context.comm,
|
||||
@@ -775,16 +787,16 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
|
||||
upper_32_bits(obj->gtt_offset),
|
||||
lower_32_bits(obj->gtt_offset));
|
||||
print_error_obj(m, dev_priv->engine[i], NULL, obj);
|
||||
print_error_obj(m, m->i915->engine[i], NULL, obj);
|
||||
}
|
||||
|
||||
for (j = 0; j < ee->user_bo_count; j++)
|
||||
print_error_obj(m, dev_priv->engine[i],
|
||||
print_error_obj(m, m->i915->engine[i],
|
||||
"user", ee->user_bo[j]);
|
||||
|
||||
if (ee->num_requests) {
|
||||
err_printf(m, "%s --- %d requests\n",
|
||||
dev_priv->engine[i]->name,
|
||||
m->i915->engine[i]->name,
|
||||
ee->num_requests);
|
||||
for (j = 0; j < ee->num_requests; j++)
|
||||
error_print_request(m, " ",
|
||||
@@ -794,10 +806,10 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
|
||||
if (IS_ERR(ee->waiters)) {
|
||||
err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n",
|
||||
dev_priv->engine[i]->name);
|
||||
m->i915->engine[i]->name);
|
||||
} else if (ee->num_waiters) {
|
||||
err_printf(m, "%s --- %d waiters\n",
|
||||
dev_priv->engine[i]->name,
|
||||
m->i915->engine[i]->name,
|
||||
ee->num_waiters);
|
||||
for (j = 0; j < ee->num_waiters; j++) {
|
||||
err_printf(m, " seqno 0x%08x for %s [%d]\n",
|
||||
@@ -807,22 +819,22 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
}
|
||||
}
|
||||
|
||||
print_error_obj(m, dev_priv->engine[i],
|
||||
print_error_obj(m, m->i915->engine[i],
|
||||
"ringbuffer", ee->ringbuffer);
|
||||
|
||||
print_error_obj(m, dev_priv->engine[i],
|
||||
print_error_obj(m, m->i915->engine[i],
|
||||
"HW Status", ee->hws_page);
|
||||
|
||||
print_error_obj(m, dev_priv->engine[i],
|
||||
print_error_obj(m, m->i915->engine[i],
|
||||
"HW context", ee->ctx);
|
||||
|
||||
print_error_obj(m, dev_priv->engine[i],
|
||||
print_error_obj(m, m->i915->engine[i],
|
||||
"WA context", ee->wa_ctx);
|
||||
|
||||
print_error_obj(m, dev_priv->engine[i],
|
||||
print_error_obj(m, m->i915->engine[i],
|
||||
"WA batchbuffer", ee->wa_batchbuffer);
|
||||
|
||||
print_error_obj(m, dev_priv->engine[i],
|
||||
print_error_obj(m, m->i915->engine[i],
|
||||
"NULL context", ee->default_state);
|
||||
}
|
||||
|
||||
@@ -835,43 +847,107 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
||||
err_print_capabilities(m, &error->device_info, &error->driver_caps);
|
||||
err_print_params(m, &error->params);
|
||||
err_print_uc(m, &error->uc);
|
||||
}
|
||||
|
||||
if (m->bytes == 0 && m->err)
|
||||
return m->err;
|
||||
static int err_print_to_sgl(struct i915_gpu_state *error)
|
||||
{
|
||||
struct drm_i915_error_state_buf m;
|
||||
|
||||
if (IS_ERR(error))
|
||||
return PTR_ERR(error);
|
||||
|
||||
if (READ_ONCE(error->sgl))
|
||||
return 0;
|
||||
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.i915 = error->i915;
|
||||
|
||||
__err_print_to_sgl(&m, error);
|
||||
|
||||
if (m.buf) {
|
||||
__sg_set_buf(m.cur++, m.buf, m.bytes, m.iter);
|
||||
m.bytes = 0;
|
||||
m.buf = NULL;
|
||||
}
|
||||
if (m.cur) {
|
||||
GEM_BUG_ON(m.end < m.cur);
|
||||
sg_mark_end(m.cur - 1);
|
||||
}
|
||||
GEM_BUG_ON(m.sgl && !m.cur);
|
||||
|
||||
if (m.err) {
|
||||
err_free_sgl(m.sgl);
|
||||
return m.err;
|
||||
}
|
||||
|
||||
if (cmpxchg(&error->sgl, NULL, m.sgl))
|
||||
err_free_sgl(m.sgl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i915_error_state_buf_init(struct drm_i915_error_state_buf *ebuf,
|
||||
struct drm_i915_private *i915,
|
||||
size_t count, loff_t pos)
|
||||
ssize_t i915_gpu_state_copy_to_buffer(struct i915_gpu_state *error,
|
||||
char *buf, loff_t off, size_t rem)
|
||||
{
|
||||
memset(ebuf, 0, sizeof(*ebuf));
|
||||
ebuf->i915 = i915;
|
||||
struct scatterlist *sg;
|
||||
size_t count;
|
||||
loff_t pos;
|
||||
int err;
|
||||
|
||||
/* We need to have enough room to store any i915_error_state printf
|
||||
* so that we can move it to start position.
|
||||
*/
|
||||
ebuf->size = count + 1 > PAGE_SIZE ? count + 1 : PAGE_SIZE;
|
||||
ebuf->buf = kmalloc(ebuf->size,
|
||||
GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
|
||||
if (!error || !rem)
|
||||
return 0;
|
||||
|
||||
if (ebuf->buf == NULL) {
|
||||
ebuf->size = PAGE_SIZE;
|
||||
ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
|
||||
}
|
||||
err = err_print_to_sgl(error);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ebuf->buf == NULL) {
|
||||
ebuf->size = 128;
|
||||
ebuf->buf = kmalloc(ebuf->size, GFP_KERNEL);
|
||||
}
|
||||
sg = READ_ONCE(error->fit);
|
||||
if (!sg || off < sg->dma_address)
|
||||
sg = error->sgl;
|
||||
if (!sg)
|
||||
return 0;
|
||||
|
||||
if (ebuf->buf == NULL)
|
||||
return -ENOMEM;
|
||||
pos = sg->dma_address;
|
||||
count = 0;
|
||||
do {
|
||||
size_t len, start;
|
||||
|
||||
ebuf->start = pos;
|
||||
if (sg_is_chain(sg)) {
|
||||
sg = sg_chain_ptr(sg);
|
||||
GEM_BUG_ON(sg_is_chain(sg));
|
||||
}
|
||||
|
||||
return 0;
|
||||
len = sg->length;
|
||||
if (pos + len <= off) {
|
||||
pos += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
start = sg->offset;
|
||||
if (pos < off) {
|
||||
GEM_BUG_ON(off - pos > len);
|
||||
len -= off - pos;
|
||||
start += off - pos;
|
||||
pos = off;
|
||||
}
|
||||
|
||||
len = min(len, rem);
|
||||
GEM_BUG_ON(!len || len > sg->length);
|
||||
|
||||
memcpy(buf, page_address(sg_page(sg)) + start, len);
|
||||
|
||||
count += len;
|
||||
pos += len;
|
||||
|
||||
buf += len;
|
||||
rem -= len;
|
||||
if (!rem) {
|
||||
WRITE_ONCE(error->fit, sg);
|
||||
break;
|
||||
}
|
||||
} while (!sg_is_last(sg++));
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void i915_error_object_free(struct drm_i915_error_object *obj)
|
||||
@@ -944,6 +1020,7 @@ void __i915_gpu_state_free(struct kref *error_ref)
|
||||
cleanup_params(error);
|
||||
cleanup_uc_state(error);
|
||||
|
||||
err_free_sgl(error->sgl);
|
||||
kfree(error);
|
||||
}
|
||||
|
||||
@@ -1002,7 +1079,6 @@ i915_error_object_create(struct drm_i915_private *i915,
|
||||
}
|
||||
|
||||
compress_fini(&compress, dst);
|
||||
ggtt->vm.clear_range(&ggtt->vm, slot, PAGE_SIZE);
|
||||
return dst;
|
||||
}
|
||||
|
||||
@@ -1271,7 +1347,7 @@ static void error_record_engine_registers(struct i915_gpu_state *error,
|
||||
ee->reset_count = i915_reset_engine_count(&dev_priv->gpu_error,
|
||||
engine);
|
||||
|
||||
if (USES_PPGTT(dev_priv)) {
|
||||
if (HAS_PPGTT(dev_priv)) {
|
||||
int i;
|
||||
|
||||
ee->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(engine));
|
||||
@@ -1788,6 +1864,14 @@ static unsigned long capture_find_epoch(const struct i915_gpu_state *error)
|
||||
return epoch;
|
||||
}
|
||||
|
||||
static void capture_finish(struct i915_gpu_state *error)
|
||||
{
|
||||
struct i915_ggtt *ggtt = &error->i915->ggtt;
|
||||
const u64 slot = ggtt->error_capture.start;
|
||||
|
||||
ggtt->vm.clear_range(&ggtt->vm, slot, PAGE_SIZE);
|
||||
}
|
||||
|
||||
static int capture(void *data)
|
||||
{
|
||||
struct i915_gpu_state *error = data;
|
||||
@@ -1812,6 +1896,7 @@ static int capture(void *data)
|
||||
|
||||
error->epoch = capture_find_epoch(error);
|
||||
|
||||
capture_finish(error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -192,6 +192,8 @@ struct i915_gpu_state {
|
||||
} *active_bo[I915_NUM_ENGINES], *pinned_bo;
|
||||
u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count;
|
||||
struct i915_address_space *active_vm[I915_NUM_ENGINES];
|
||||
|
||||
struct scatterlist *sgl, *fit;
|
||||
};
|
||||
|
||||
struct i915_gpu_error {
|
||||
@@ -298,29 +300,20 @@ struct i915_gpu_error {
|
||||
|
||||
struct drm_i915_error_state_buf {
|
||||
struct drm_i915_private *i915;
|
||||
unsigned int bytes;
|
||||
unsigned int size;
|
||||
struct scatterlist *sgl, *cur, *end;
|
||||
|
||||
char *buf;
|
||||
size_t bytes;
|
||||
size_t size;
|
||||
loff_t iter;
|
||||
|
||||
int err;
|
||||
u8 *buf;
|
||||
loff_t start;
|
||||
loff_t pos;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
|
||||
|
||||
__printf(2, 3)
|
||||
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
|
||||
int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
|
||||
const struct i915_gpu_state *gpu);
|
||||
int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb,
|
||||
struct drm_i915_private *i915,
|
||||
size_t count, loff_t pos);
|
||||
|
||||
static inline void
|
||||
i915_error_state_buf_release(struct drm_i915_error_state_buf *eb)
|
||||
{
|
||||
kfree(eb->buf);
|
||||
}
|
||||
|
||||
struct i915_gpu_state *i915_capture_gpu_state(struct drm_i915_private *i915);
|
||||
void i915_capture_error_state(struct drm_i915_private *dev_priv,
|
||||
@@ -334,6 +327,9 @@ i915_gpu_state_get(struct i915_gpu_state *gpu)
|
||||
return gpu;
|
||||
}
|
||||
|
||||
ssize_t i915_gpu_state_copy_to_buffer(struct i915_gpu_state *error,
|
||||
char *buf, loff_t offset, size_t count);
|
||||
|
||||
void __i915_gpu_state_free(struct kref *kref);
|
||||
static inline void i915_gpu_state_put(struct i915_gpu_state *gpu)
|
||||
{
|
||||
|
@@ -2887,21 +2887,39 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline u32 gen8_master_intr_disable(void __iomem * const regs)
|
||||
{
|
||||
raw_reg_write(regs, GEN8_MASTER_IRQ, 0);
|
||||
|
||||
/*
|
||||
* Now with master disabled, get a sample of level indications
|
||||
* for this interrupt. Indications will be cleared on related acks.
|
||||
* New indications can and will light up during processing,
|
||||
* and will generate new interrupt after enabling master.
|
||||
*/
|
||||
return raw_reg_read(regs, GEN8_MASTER_IRQ);
|
||||
}
|
||||
|
||||
static inline void gen8_master_intr_enable(void __iomem * const regs)
|
||||
{
|
||||
raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
|
||||
}
|
||||
|
||||
static irqreturn_t gen8_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(arg);
|
||||
void __iomem * const regs = dev_priv->regs;
|
||||
u32 master_ctl;
|
||||
u32 gt_iir[4];
|
||||
|
||||
if (!intel_irqs_enabled(dev_priv))
|
||||
return IRQ_NONE;
|
||||
|
||||
master_ctl = I915_READ_FW(GEN8_MASTER_IRQ);
|
||||
master_ctl &= ~GEN8_MASTER_IRQ_CONTROL;
|
||||
if (!master_ctl)
|
||||
master_ctl = gen8_master_intr_disable(regs);
|
||||
if (!master_ctl) {
|
||||
gen8_master_intr_enable(regs);
|
||||
return IRQ_NONE;
|
||||
|
||||
I915_WRITE_FW(GEN8_MASTER_IRQ, 0);
|
||||
}
|
||||
|
||||
/* Find, clear, then process each source of interrupt */
|
||||
gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir);
|
||||
@@ -2913,7 +2931,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
}
|
||||
|
||||
I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
|
||||
gen8_master_intr_enable(regs);
|
||||
|
||||
gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir);
|
||||
|
||||
@@ -3111,6 +3129,24 @@ gen11_gu_misc_irq_handler(struct drm_i915_private *dev_priv, const u32 iir)
|
||||
intel_opregion_asle_intr(dev_priv);
|
||||
}
|
||||
|
||||
static inline u32 gen11_master_intr_disable(void __iomem * const regs)
|
||||
{
|
||||
raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0);
|
||||
|
||||
/*
|
||||
* Now with master disabled, get a sample of level indications
|
||||
* for this interrupt. Indications will be cleared on related acks.
|
||||
* New indications can and will light up during processing,
|
||||
* and will generate new interrupt after enabling master.
|
||||
*/
|
||||
return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
|
||||
}
|
||||
|
||||
static inline void gen11_master_intr_enable(void __iomem * const regs)
|
||||
{
|
||||
raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ);
|
||||
}
|
||||
|
||||
static irqreturn_t gen11_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct drm_i915_private * const i915 = to_i915(arg);
|
||||
@@ -3121,13 +3157,11 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg)
|
||||
if (!intel_irqs_enabled(i915))
|
||||
return IRQ_NONE;
|
||||
|
||||
master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
|
||||
master_ctl &= ~GEN11_MASTER_IRQ;
|
||||
if (!master_ctl)
|
||||
master_ctl = gen11_master_intr_disable(regs);
|
||||
if (!master_ctl) {
|
||||
gen11_master_intr_enable(regs);
|
||||
return IRQ_NONE;
|
||||
|
||||
/* Disable interrupts. */
|
||||
raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0);
|
||||
}
|
||||
|
||||
/* Find, clear, then process each source of interrupt. */
|
||||
gen11_gt_irq_handler(i915, master_ctl);
|
||||
@@ -3147,8 +3181,7 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg)
|
||||
|
||||
gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl);
|
||||
|
||||
/* Acknowledge and enable interrupts. */
|
||||
raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ | master_ctl);
|
||||
gen11_master_intr_enable(regs);
|
||||
|
||||
gen11_gu_misc_irq_handler(i915, gu_misc_iir);
|
||||
|
||||
@@ -3598,8 +3631,7 @@ static void gen8_irq_reset(struct drm_device *dev)
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
int pipe;
|
||||
|
||||
I915_WRITE(GEN8_MASTER_IRQ, 0);
|
||||
POSTING_READ(GEN8_MASTER_IRQ);
|
||||
gen8_master_intr_disable(dev_priv->regs);
|
||||
|
||||
gen8_gt_irq_reset(dev_priv);
|
||||
|
||||
@@ -3641,13 +3673,15 @@ static void gen11_irq_reset(struct drm_device *dev)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int pipe;
|
||||
|
||||
I915_WRITE(GEN11_GFX_MSTR_IRQ, 0);
|
||||
POSTING_READ(GEN11_GFX_MSTR_IRQ);
|
||||
gen11_master_intr_disable(dev_priv->regs);
|
||||
|
||||
gen11_gt_irq_reset(dev_priv);
|
||||
|
||||
I915_WRITE(GEN11_DISPLAY_INT_CTL, 0);
|
||||
|
||||
I915_WRITE(EDP_PSR_IMR, 0xffffffff);
|
||||
I915_WRITE(EDP_PSR_IIR, 0xffffffff);
|
||||
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
if (intel_display_power_is_enabled(dev_priv,
|
||||
POWER_DOMAIN_PIPE(pipe)))
|
||||
@@ -4244,8 +4278,7 @@ static int gen8_irq_postinstall(struct drm_device *dev)
|
||||
if (HAS_PCH_SPLIT(dev_priv))
|
||||
ibx_irq_postinstall(dev);
|
||||
|
||||
I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
|
||||
POSTING_READ(GEN8_MASTER_IRQ);
|
||||
gen8_master_intr_enable(dev_priv->regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4307,8 +4340,7 @@ static int gen11_irq_postinstall(struct drm_device *dev)
|
||||
|
||||
I915_WRITE(GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE);
|
||||
|
||||
I915_WRITE(GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ);
|
||||
POSTING_READ(GEN11_GFX_MSTR_IRQ);
|
||||
gen11_master_intr_enable(dev_priv->regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4834,6 +4866,13 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
|
||||
dev_priv->display_irqs_enabled = false;
|
||||
|
||||
dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD;
|
||||
/* If we have MST support, we want to avoid doing short HPD IRQ storm
|
||||
* detection, as short HPD storms will occur as a natural part of
|
||||
* sideband messaging with MST.
|
||||
* On older platforms however, IRQ storms can occur with both long and
|
||||
* short pulses, as seen on some G4x systems.
|
||||
*/
|
||||
dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv);
|
||||
|
||||
dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos;
|
||||
dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_BDW_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_BXT_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_CFLGT2_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_CFLGT3_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_CHV_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_CNL_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_GLK_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_HSW_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_ICL_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_KBLGT2_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_KBLGT3_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_SKLGT2_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_SKLGT3_H__
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sysfs.h>
|
||||
|
@@ -1,29 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*
|
||||
* Autogenerated file by GPU Top : https://github.com/rib/gputop
|
||||
* DO NOT EDIT manually!
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __I915_OA_SKLGT4_H__
|
||||
|
@@ -82,10 +82,6 @@ i915_param_named_unsafe(enable_hangcheck, bool, 0644,
|
||||
"WARNING: Disabling this can cause system wide hangs. "
|
||||
"(default: true)");
|
||||
|
||||
i915_param_named_unsafe(enable_ppgtt, int, 0400,
|
||||
"Override PPGTT usage. "
|
||||
"(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)");
|
||||
|
||||
i915_param_named_unsafe(enable_psr, int, 0600,
|
||||
"Enable PSR "
|
||||
"(0=disabled, 1=enabled) "
|
||||
@@ -171,8 +167,10 @@ i915_param_named_unsafe(inject_load_failure, uint, 0400,
|
||||
i915_param_named(enable_dpcd_backlight, bool, 0600,
|
||||
"Enable support for DPCD backlight control (default:false)");
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_GVT)
|
||||
i915_param_named(enable_gvt, bool, 0400,
|
||||
"Enable support for Intel GVT-g graphics virtualization host support(default:false)");
|
||||
#endif
|
||||
|
||||
static __always_inline void _print_param(struct drm_printer *p,
|
||||
const char *name,
|
||||
@@ -188,7 +186,8 @@ static __always_inline void _print_param(struct drm_printer *p,
|
||||
else if (!__builtin_strcmp(type, "char *"))
|
||||
drm_printf(p, "i915.%s=%s\n", name, *(const char **)x);
|
||||
else
|
||||
BUILD_BUG();
|
||||
WARN_ONCE(1, "no printer defined for param type %s (i915.%s)\n",
|
||||
type, name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -41,7 +41,6 @@ struct drm_printer;
|
||||
param(int, vbt_sdvo_panel_type, -1) \
|
||||
param(int, enable_dc, -1) \
|
||||
param(int, enable_fbc, -1) \
|
||||
param(int, enable_ppgtt, -1) \
|
||||
param(int, enable_psr, -1) \
|
||||
param(int, disable_power_well, -1) \
|
||||
param(int, enable_ips, 1) \
|
||||
|
@@ -33,19 +33,30 @@
|
||||
#define GEN(x) .gen = (x), .gen_mask = BIT((x) - 1)
|
||||
|
||||
#define GEN_DEFAULT_PIPEOFFSETS \
|
||||
.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
|
||||
PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
|
||||
.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
|
||||
TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
|
||||
.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }
|
||||
.pipe_offsets = { \
|
||||
[TRANSCODER_A] = PIPE_A_OFFSET, \
|
||||
[TRANSCODER_B] = PIPE_B_OFFSET, \
|
||||
[TRANSCODER_C] = PIPE_C_OFFSET, \
|
||||
[TRANSCODER_EDP] = PIPE_EDP_OFFSET, \
|
||||
}, \
|
||||
.trans_offsets = { \
|
||||
[TRANSCODER_A] = TRANSCODER_A_OFFSET, \
|
||||
[TRANSCODER_B] = TRANSCODER_B_OFFSET, \
|
||||
[TRANSCODER_C] = TRANSCODER_C_OFFSET, \
|
||||
[TRANSCODER_EDP] = TRANSCODER_EDP_OFFSET, \
|
||||
}
|
||||
|
||||
#define GEN_CHV_PIPEOFFSETS \
|
||||
.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
|
||||
CHV_PIPE_C_OFFSET }, \
|
||||
.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
|
||||
CHV_TRANSCODER_C_OFFSET, }, \
|
||||
.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET, \
|
||||
CHV_PALETTE_C_OFFSET }
|
||||
.pipe_offsets = { \
|
||||
[TRANSCODER_A] = PIPE_A_OFFSET, \
|
||||
[TRANSCODER_B] = PIPE_B_OFFSET, \
|
||||
[TRANSCODER_C] = CHV_PIPE_C_OFFSET, \
|
||||
}, \
|
||||
.trans_offsets = { \
|
||||
[TRANSCODER_A] = TRANSCODER_A_OFFSET, \
|
||||
[TRANSCODER_B] = TRANSCODER_B_OFFSET, \
|
||||
[TRANSCODER_C] = CHV_TRANSCODER_C_OFFSET, \
|
||||
}
|
||||
|
||||
#define CURSOR_OFFSETS \
|
||||
.cursor_offsets = { CURSOR_A_OFFSET, CURSOR_B_OFFSET, CHV_CURSOR_C_OFFSET }
|
||||
@@ -68,8 +79,9 @@
|
||||
#define GEN2_FEATURES \
|
||||
GEN(2), \
|
||||
.num_pipes = 1, \
|
||||
.has_overlay = 1, .overlay_needs_physical = 1, \
|
||||
.has_gmch_display = 1, \
|
||||
.display.has_overlay = 1, \
|
||||
.display.overlay_needs_physical = 1, \
|
||||
.display.has_gmch_display = 1, \
|
||||
.hws_needs_physical = 1, \
|
||||
.unfenced_needs_alignment = 1, \
|
||||
.ring_mask = RENDER_RING, \
|
||||
@@ -82,7 +94,8 @@
|
||||
static const struct intel_device_info intel_i830_info = {
|
||||
GEN2_FEATURES,
|
||||
PLATFORM(INTEL_I830),
|
||||
.is_mobile = 1, .cursor_needs_physical = 1,
|
||||
.is_mobile = 1,
|
||||
.display.cursor_needs_physical = 1,
|
||||
.num_pipes = 2, /* legal, last one wins */
|
||||
};
|
||||
|
||||
@@ -96,8 +109,8 @@ static const struct intel_device_info intel_i85x_info = {
|
||||
PLATFORM(INTEL_I85X),
|
||||
.is_mobile = 1,
|
||||
.num_pipes = 2, /* legal, last one wins */
|
||||
.cursor_needs_physical = 1,
|
||||
.has_fbc = 1,
|
||||
.display.cursor_needs_physical = 1,
|
||||
.display.has_fbc = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_i865g_info = {
|
||||
@@ -108,7 +121,7 @@ static const struct intel_device_info intel_i865g_info = {
|
||||
#define GEN3_FEATURES \
|
||||
GEN(3), \
|
||||
.num_pipes = 2, \
|
||||
.has_gmch_display = 1, \
|
||||
.display.has_gmch_display = 1, \
|
||||
.ring_mask = RENDER_RING, \
|
||||
.has_snoop = true, \
|
||||
.has_coherent_ggtt = true, \
|
||||
@@ -120,8 +133,9 @@ static const struct intel_device_info intel_i915g_info = {
|
||||
GEN3_FEATURES,
|
||||
PLATFORM(INTEL_I915G),
|
||||
.has_coherent_ggtt = false,
|
||||
.cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
.display.cursor_needs_physical = 1,
|
||||
.display.has_overlay = 1,
|
||||
.display.overlay_needs_physical = 1,
|
||||
.hws_needs_physical = 1,
|
||||
.unfenced_needs_alignment = 1,
|
||||
};
|
||||
@@ -130,10 +144,11 @@ static const struct intel_device_info intel_i915gm_info = {
|
||||
GEN3_FEATURES,
|
||||
PLATFORM(INTEL_I915GM),
|
||||
.is_mobile = 1,
|
||||
.cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
.supports_tv = 1,
|
||||
.has_fbc = 1,
|
||||
.display.cursor_needs_physical = 1,
|
||||
.display.has_overlay = 1,
|
||||
.display.overlay_needs_physical = 1,
|
||||
.display.supports_tv = 1,
|
||||
.display.has_fbc = 1,
|
||||
.hws_needs_physical = 1,
|
||||
.unfenced_needs_alignment = 1,
|
||||
};
|
||||
@@ -141,8 +156,10 @@ static const struct intel_device_info intel_i915gm_info = {
|
||||
static const struct intel_device_info intel_i945g_info = {
|
||||
GEN3_FEATURES,
|
||||
PLATFORM(INTEL_I945G),
|
||||
.has_hotplug = 1, .cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
.display.has_hotplug = 1,
|
||||
.display.cursor_needs_physical = 1,
|
||||
.display.has_overlay = 1,
|
||||
.display.overlay_needs_physical = 1,
|
||||
.hws_needs_physical = 1,
|
||||
.unfenced_needs_alignment = 1,
|
||||
};
|
||||
@@ -151,10 +168,12 @@ static const struct intel_device_info intel_i945gm_info = {
|
||||
GEN3_FEATURES,
|
||||
PLATFORM(INTEL_I945GM),
|
||||
.is_mobile = 1,
|
||||
.has_hotplug = 1, .cursor_needs_physical = 1,
|
||||
.has_overlay = 1, .overlay_needs_physical = 1,
|
||||
.supports_tv = 1,
|
||||
.has_fbc = 1,
|
||||
.display.has_hotplug = 1,
|
||||
.display.cursor_needs_physical = 1,
|
||||
.display.has_overlay = 1,
|
||||
.display.overlay_needs_physical = 1,
|
||||
.display.supports_tv = 1,
|
||||
.display.has_fbc = 1,
|
||||
.hws_needs_physical = 1,
|
||||
.unfenced_needs_alignment = 1,
|
||||
};
|
||||
@@ -162,23 +181,23 @@ static const struct intel_device_info intel_i945gm_info = {
|
||||
static const struct intel_device_info intel_g33_info = {
|
||||
GEN3_FEATURES,
|
||||
PLATFORM(INTEL_G33),
|
||||
.has_hotplug = 1,
|
||||
.has_overlay = 1,
|
||||
.display.has_hotplug = 1,
|
||||
.display.has_overlay = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_pineview_info = {
|
||||
GEN3_FEATURES,
|
||||
PLATFORM(INTEL_PINEVIEW),
|
||||
.is_mobile = 1,
|
||||
.has_hotplug = 1,
|
||||
.has_overlay = 1,
|
||||
.display.has_hotplug = 1,
|
||||
.display.has_overlay = 1,
|
||||
};
|
||||
|
||||
#define GEN4_FEATURES \
|
||||
GEN(4), \
|
||||
.num_pipes = 2, \
|
||||
.has_hotplug = 1, \
|
||||
.has_gmch_display = 1, \
|
||||
.display.has_hotplug = 1, \
|
||||
.display.has_gmch_display = 1, \
|
||||
.ring_mask = RENDER_RING, \
|
||||
.has_snoop = true, \
|
||||
.has_coherent_ggtt = true, \
|
||||
@@ -189,7 +208,7 @@ static const struct intel_device_info intel_pineview_info = {
|
||||
static const struct intel_device_info intel_i965g_info = {
|
||||
GEN4_FEATURES,
|
||||
PLATFORM(INTEL_I965G),
|
||||
.has_overlay = 1,
|
||||
.display.has_overlay = 1,
|
||||
.hws_needs_physical = 1,
|
||||
.has_snoop = false,
|
||||
};
|
||||
@@ -197,9 +216,10 @@ static const struct intel_device_info intel_i965g_info = {
|
||||
static const struct intel_device_info intel_i965gm_info = {
|
||||
GEN4_FEATURES,
|
||||
PLATFORM(INTEL_I965GM),
|
||||
.is_mobile = 1, .has_fbc = 1,
|
||||
.has_overlay = 1,
|
||||
.supports_tv = 1,
|
||||
.is_mobile = 1,
|
||||
.display.has_fbc = 1,
|
||||
.display.has_overlay = 1,
|
||||
.display.supports_tv = 1,
|
||||
.hws_needs_physical = 1,
|
||||
.has_snoop = false,
|
||||
};
|
||||
@@ -213,15 +233,16 @@ static const struct intel_device_info intel_g45_info = {
|
||||
static const struct intel_device_info intel_gm45_info = {
|
||||
GEN4_FEATURES,
|
||||
PLATFORM(INTEL_GM45),
|
||||
.is_mobile = 1, .has_fbc = 1,
|
||||
.supports_tv = 1,
|
||||
.is_mobile = 1,
|
||||
.display.has_fbc = 1,
|
||||
.display.supports_tv = 1,
|
||||
.ring_mask = RENDER_RING | BSD_RING,
|
||||
};
|
||||
|
||||
#define GEN5_FEATURES \
|
||||
GEN(5), \
|
||||
.num_pipes = 2, \
|
||||
.has_hotplug = 1, \
|
||||
.display.has_hotplug = 1, \
|
||||
.ring_mask = RENDER_RING | BSD_RING, \
|
||||
.has_snoop = true, \
|
||||
.has_coherent_ggtt = true, \
|
||||
@@ -239,20 +260,21 @@ static const struct intel_device_info intel_ironlake_d_info = {
|
||||
static const struct intel_device_info intel_ironlake_m_info = {
|
||||
GEN5_FEATURES,
|
||||
PLATFORM(INTEL_IRONLAKE),
|
||||
.is_mobile = 1, .has_fbc = 1,
|
||||
.is_mobile = 1,
|
||||
.display.has_fbc = 1,
|
||||
};
|
||||
|
||||
#define GEN6_FEATURES \
|
||||
GEN(6), \
|
||||
.num_pipes = 2, \
|
||||
.has_hotplug = 1, \
|
||||
.has_fbc = 1, \
|
||||
.display.has_hotplug = 1, \
|
||||
.display.has_fbc = 1, \
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
|
||||
.has_coherent_ggtt = true, \
|
||||
.has_llc = 1, \
|
||||
.has_rc6 = 1, \
|
||||
.has_rc6p = 1, \
|
||||
.has_aliasing_ppgtt = 1, \
|
||||
.ppgtt = INTEL_PPGTT_ALIASING, \
|
||||
GEN_DEFAULT_PIPEOFFSETS, \
|
||||
GEN_DEFAULT_PAGE_SIZES, \
|
||||
CURSOR_OFFSETS
|
||||
@@ -290,15 +312,14 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info = {
|
||||
#define GEN7_FEATURES \
|
||||
GEN(7), \
|
||||
.num_pipes = 3, \
|
||||
.has_hotplug = 1, \
|
||||
.has_fbc = 1, \
|
||||
.display.has_hotplug = 1, \
|
||||
.display.has_fbc = 1, \
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
|
||||
.has_coherent_ggtt = true, \
|
||||
.has_llc = 1, \
|
||||
.has_rc6 = 1, \
|
||||
.has_rc6p = 1, \
|
||||
.has_aliasing_ppgtt = 1, \
|
||||
.has_full_ppgtt = 1, \
|
||||
.ppgtt = INTEL_PPGTT_FULL, \
|
||||
GEN_DEFAULT_PIPEOFFSETS, \
|
||||
GEN_DEFAULT_PAGE_SIZES, \
|
||||
IVB_CURSOR_OFFSETS
|
||||
@@ -349,10 +370,9 @@ static const struct intel_device_info intel_valleyview_info = {
|
||||
.num_pipes = 2,
|
||||
.has_runtime_pm = 1,
|
||||
.has_rc6 = 1,
|
||||
.has_gmch_display = 1,
|
||||
.has_hotplug = 1,
|
||||
.has_aliasing_ppgtt = 1,
|
||||
.has_full_ppgtt = 1,
|
||||
.display.has_gmch_display = 1,
|
||||
.display.has_hotplug = 1,
|
||||
.ppgtt = INTEL_PPGTT_FULL,
|
||||
.has_snoop = true,
|
||||
.has_coherent_ggtt = false,
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
|
||||
@@ -365,10 +385,10 @@ static const struct intel_device_info intel_valleyview_info = {
|
||||
#define G75_FEATURES \
|
||||
GEN7_FEATURES, \
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \
|
||||
.has_ddi = 1, \
|
||||
.display.has_ddi = 1, \
|
||||
.has_fpga_dbg = 1, \
|
||||
.has_psr = 1, \
|
||||
.has_dp_mst = 1, \
|
||||
.display.has_psr = 1, \
|
||||
.display.has_dp_mst = 1, \
|
||||
.has_rc6p = 0 /* RC6p removed-by HSW */, \
|
||||
.has_runtime_pm = 1
|
||||
|
||||
@@ -399,7 +419,7 @@ static const struct intel_device_info intel_haswell_gt3_info = {
|
||||
.page_sizes = I915_GTT_PAGE_SIZE_4K | \
|
||||
I915_GTT_PAGE_SIZE_2M, \
|
||||
.has_logical_ring_contexts = 1, \
|
||||
.has_full_48bit_ppgtt = 1, \
|
||||
.ppgtt = INTEL_PPGTT_FULL_4LVL, \
|
||||
.has_64bit_reloc = 1, \
|
||||
.has_reset_engine = 1
|
||||
|
||||
@@ -435,16 +455,15 @@ static const struct intel_device_info intel_cherryview_info = {
|
||||
PLATFORM(INTEL_CHERRYVIEW),
|
||||
GEN(8),
|
||||
.num_pipes = 3,
|
||||
.has_hotplug = 1,
|
||||
.display.has_hotplug = 1,
|
||||
.is_lp = 1,
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
|
||||
.has_64bit_reloc = 1,
|
||||
.has_runtime_pm = 1,
|
||||
.has_rc6 = 1,
|
||||
.has_logical_ring_contexts = 1,
|
||||
.has_gmch_display = 1,
|
||||
.has_aliasing_ppgtt = 1,
|
||||
.has_full_ppgtt = 1,
|
||||
.display.has_gmch_display = 1,
|
||||
.ppgtt = INTEL_PPGTT_FULL,
|
||||
.has_reset_engine = 1,
|
||||
.has_snoop = true,
|
||||
.has_coherent_ggtt = false,
|
||||
@@ -465,13 +484,15 @@ static const struct intel_device_info intel_cherryview_info = {
|
||||
GEN(9), \
|
||||
GEN9_DEFAULT_PAGE_SIZES, \
|
||||
.has_logical_ring_preemption = 1, \
|
||||
.has_csr = 1, \
|
||||
.display.has_csr = 1, \
|
||||
.has_guc = 1, \
|
||||
.has_ipc = 1, \
|
||||
.display.has_ipc = 1, \
|
||||
.ddb_size = 896
|
||||
|
||||
#define SKL_PLATFORM \
|
||||
GEN9_FEATURES, \
|
||||
/* Display WA #0477 WaDisableIPC: skl */ \
|
||||
.display.has_ipc = 0, \
|
||||
PLATFORM(INTEL_SKYLAKE)
|
||||
|
||||
static const struct intel_device_info intel_skylake_gt1_info = {
|
||||
@@ -502,29 +523,27 @@ static const struct intel_device_info intel_skylake_gt4_info = {
|
||||
#define GEN9_LP_FEATURES \
|
||||
GEN(9), \
|
||||
.is_lp = 1, \
|
||||
.has_hotplug = 1, \
|
||||
.display.has_hotplug = 1, \
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \
|
||||
.num_pipes = 3, \
|
||||
.has_64bit_reloc = 1, \
|
||||
.has_ddi = 1, \
|
||||
.display.has_ddi = 1, \
|
||||
.has_fpga_dbg = 1, \
|
||||
.has_fbc = 1, \
|
||||
.has_psr = 1, \
|
||||
.display.has_fbc = 1, \
|
||||
.display.has_psr = 1, \
|
||||
.has_runtime_pm = 1, \
|
||||
.has_pooled_eu = 0, \
|
||||
.has_csr = 1, \
|
||||
.display.has_csr = 1, \
|
||||
.has_rc6 = 1, \
|
||||
.has_dp_mst = 1, \
|
||||
.display.has_dp_mst = 1, \
|
||||
.has_logical_ring_contexts = 1, \
|
||||
.has_logical_ring_preemption = 1, \
|
||||
.has_guc = 1, \
|
||||
.has_aliasing_ppgtt = 1, \
|
||||
.has_full_ppgtt = 1, \
|
||||
.has_full_48bit_ppgtt = 1, \
|
||||
.ppgtt = INTEL_PPGTT_FULL_4LVL, \
|
||||
.has_reset_engine = 1, \
|
||||
.has_snoop = true, \
|
||||
.has_coherent_ggtt = false, \
|
||||
.has_ipc = 1, \
|
||||
.display.has_ipc = 1, \
|
||||
GEN9_DEFAULT_PAGE_SIZES, \
|
||||
GEN_DEFAULT_PIPEOFFSETS, \
|
||||
IVB_CURSOR_OFFSETS, \
|
||||
@@ -598,6 +617,22 @@ static const struct intel_device_info intel_cannonlake_info = {
|
||||
|
||||
#define GEN11_FEATURES \
|
||||
GEN10_FEATURES, \
|
||||
.pipe_offsets = { \
|
||||
[TRANSCODER_A] = PIPE_A_OFFSET, \
|
||||
[TRANSCODER_B] = PIPE_B_OFFSET, \
|
||||
[TRANSCODER_C] = PIPE_C_OFFSET, \
|
||||
[TRANSCODER_EDP] = PIPE_EDP_OFFSET, \
|
||||
[TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
|
||||
[TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
|
||||
}, \
|
||||
.trans_offsets = { \
|
||||
[TRANSCODER_A] = TRANSCODER_A_OFFSET, \
|
||||
[TRANSCODER_B] = TRANSCODER_B_OFFSET, \
|
||||
[TRANSCODER_C] = TRANSCODER_C_OFFSET, \
|
||||
[TRANSCODER_EDP] = TRANSCODER_EDP_OFFSET, \
|
||||
[TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
|
||||
[TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
|
||||
}, \
|
||||
GEN(11), \
|
||||
.ddb_size = 2048, \
|
||||
.has_logical_ring_elsq = 1
|
||||
@@ -663,7 +698,7 @@ static const struct pci_device_id pciidlist[] = {
|
||||
INTEL_KBL_GT2_IDS(&intel_kabylake_gt2_info),
|
||||
INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
|
||||
INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
|
||||
INTEL_AML_GT2_IDS(&intel_kabylake_gt2_info),
|
||||
INTEL_AML_KBL_GT2_IDS(&intel_kabylake_gt2_info),
|
||||
INTEL_CFL_S_GT1_IDS(&intel_coffeelake_gt1_info),
|
||||
INTEL_CFL_S_GT2_IDS(&intel_coffeelake_gt2_info),
|
||||
INTEL_CFL_H_GT2_IDS(&intel_coffeelake_gt2_info),
|
||||
@@ -671,6 +706,7 @@ static const struct pci_device_id pciidlist[] = {
|
||||
INTEL_CFL_U_GT3_IDS(&intel_coffeelake_gt3_info),
|
||||
INTEL_WHL_U_GT1_IDS(&intel_coffeelake_gt1_info),
|
||||
INTEL_WHL_U_GT2_IDS(&intel_coffeelake_gt2_info),
|
||||
INTEL_AML_CFL_GT2_IDS(&intel_coffeelake_gt2_info),
|
||||
INTEL_WHL_U_GT3_IDS(&intel_coffeelake_gt3_info),
|
||||
INTEL_CNL_IDS(&intel_cannonlake_info),
|
||||
INTEL_ICL_11_IDS(&intel_icelake_11_info),
|
||||
|
@@ -890,8 +890,8 @@ static int gen8_oa_read(struct i915_perf_stream *stream,
|
||||
DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n",
|
||||
dev_priv->perf.oa.period_exponent);
|
||||
|
||||
dev_priv->perf.oa.ops.oa_disable(dev_priv);
|
||||
dev_priv->perf.oa.ops.oa_enable(dev_priv);
|
||||
dev_priv->perf.oa.ops.oa_disable(stream);
|
||||
dev_priv->perf.oa.ops.oa_enable(stream);
|
||||
|
||||
/*
|
||||
* Note: .oa_enable() is expected to re-init the oabuffer and
|
||||
@@ -1114,8 +1114,8 @@ static int gen7_oa_read(struct i915_perf_stream *stream,
|
||||
DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n",
|
||||
dev_priv->perf.oa.period_exponent);
|
||||
|
||||
dev_priv->perf.oa.ops.oa_disable(dev_priv);
|
||||
dev_priv->perf.oa.ops.oa_enable(dev_priv);
|
||||
dev_priv->perf.oa.ops.oa_disable(stream);
|
||||
dev_priv->perf.oa.ops.oa_enable(stream);
|
||||
|
||||
oastatus1 = I915_READ(GEN7_OASTATUS1);
|
||||
}
|
||||
@@ -1528,8 +1528,6 @@ static int alloc_oa_buffer(struct drm_i915_private *dev_priv)
|
||||
goto err_unpin;
|
||||
}
|
||||
|
||||
dev_priv->perf.oa.ops.init_oa_buffer(dev_priv);
|
||||
|
||||
DRM_DEBUG_DRIVER("OA Buffer initialized, gtt offset = 0x%x, vaddr = %p\n",
|
||||
i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma),
|
||||
dev_priv->perf.oa.oa_buffer.vaddr);
|
||||
@@ -1563,9 +1561,11 @@ static void config_oa_regs(struct drm_i915_private *dev_priv,
|
||||
}
|
||||
}
|
||||
|
||||
static int hsw_enable_metric_set(struct drm_i915_private *dev_priv,
|
||||
const struct i915_oa_config *oa_config)
|
||||
static int hsw_enable_metric_set(struct i915_perf_stream *stream)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = stream->dev_priv;
|
||||
const struct i915_oa_config *oa_config = stream->oa_config;
|
||||
|
||||
/* PRM:
|
||||
*
|
||||
* OA unit is using “crclk” for its functionality. When trunk
|
||||
@@ -1767,9 +1767,10 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gen8_enable_metric_set(struct drm_i915_private *dev_priv,
|
||||
const struct i915_oa_config *oa_config)
|
||||
static int gen8_enable_metric_set(struct i915_perf_stream *stream)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = stream->dev_priv;
|
||||
const struct i915_oa_config *oa_config = stream->oa_config;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@@ -1837,10 +1838,10 @@ static void gen10_disable_metric_set(struct drm_i915_private *dev_priv)
|
||||
I915_READ(RPM_CONFIG1) & ~GEN10_GT_NOA_ENABLE);
|
||||
}
|
||||
|
||||
static void gen7_oa_enable(struct drm_i915_private *dev_priv)
|
||||
static void gen7_oa_enable(struct i915_perf_stream *stream)
|
||||
{
|
||||
struct i915_gem_context *ctx =
|
||||
dev_priv->perf.oa.exclusive_stream->ctx;
|
||||
struct drm_i915_private *dev_priv = stream->dev_priv;
|
||||
struct i915_gem_context *ctx = stream->ctx;
|
||||
u32 ctx_id = dev_priv->perf.oa.specific_ctx_id;
|
||||
bool periodic = dev_priv->perf.oa.periodic;
|
||||
u32 period_exponent = dev_priv->perf.oa.period_exponent;
|
||||
@@ -1867,8 +1868,9 @@ static void gen7_oa_enable(struct drm_i915_private *dev_priv)
|
||||
GEN7_OACONTROL_ENABLE);
|
||||
}
|
||||
|
||||
static void gen8_oa_enable(struct drm_i915_private *dev_priv)
|
||||
static void gen8_oa_enable(struct i915_perf_stream *stream)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = stream->dev_priv;
|
||||
u32 report_format = dev_priv->perf.oa.oa_buffer.format;
|
||||
|
||||
/*
|
||||
@@ -1905,7 +1907,7 @@ static void i915_oa_stream_enable(struct i915_perf_stream *stream)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = stream->dev_priv;
|
||||
|
||||
dev_priv->perf.oa.ops.oa_enable(dev_priv);
|
||||
dev_priv->perf.oa.ops.oa_enable(stream);
|
||||
|
||||
if (dev_priv->perf.oa.periodic)
|
||||
hrtimer_start(&dev_priv->perf.oa.poll_check_timer,
|
||||
@@ -1913,8 +1915,10 @@ static void i915_oa_stream_enable(struct i915_perf_stream *stream)
|
||||
HRTIMER_MODE_REL_PINNED);
|
||||
}
|
||||
|
||||
static void gen7_oa_disable(struct drm_i915_private *dev_priv)
|
||||
static void gen7_oa_disable(struct i915_perf_stream *stream)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = stream->dev_priv;
|
||||
|
||||
I915_WRITE(GEN7_OACONTROL, 0);
|
||||
if (intel_wait_for_register(dev_priv,
|
||||
GEN7_OACONTROL, GEN7_OACONTROL_ENABLE, 0,
|
||||
@@ -1922,8 +1926,10 @@ static void gen7_oa_disable(struct drm_i915_private *dev_priv)
|
||||
DRM_ERROR("wait for OA to be disabled timed out\n");
|
||||
}
|
||||
|
||||
static void gen8_oa_disable(struct drm_i915_private *dev_priv)
|
||||
static void gen8_oa_disable(struct i915_perf_stream *stream)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = stream->dev_priv;
|
||||
|
||||
I915_WRITE(GEN8_OACONTROL, 0);
|
||||
if (intel_wait_for_register(dev_priv,
|
||||
GEN8_OACONTROL, GEN8_OA_COUNTER_ENABLE, 0,
|
||||
@@ -1943,7 +1949,7 @@ static void i915_oa_stream_disable(struct i915_perf_stream *stream)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = stream->dev_priv;
|
||||
|
||||
dev_priv->perf.oa.ops.oa_disable(dev_priv);
|
||||
dev_priv->perf.oa.ops.oa_disable(stream);
|
||||
|
||||
if (dev_priv->perf.oa.periodic)
|
||||
hrtimer_cancel(&dev_priv->perf.oa.poll_check_timer);
|
||||
@@ -1998,7 +2004,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!dev_priv->perf.oa.ops.init_oa_buffer) {
|
||||
if (!dev_priv->perf.oa.ops.enable_metric_set) {
|
||||
DRM_DEBUG("OA unit not supported\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -2092,8 +2098,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
|
||||
if (ret)
|
||||
goto err_lock;
|
||||
|
||||
ret = dev_priv->perf.oa.ops.enable_metric_set(dev_priv,
|
||||
stream->oa_config);
|
||||
ret = dev_priv->perf.oa.ops.enable_metric_set(stream);
|
||||
if (ret) {
|
||||
DRM_DEBUG("Unable to enable metric set\n");
|
||||
goto err_enable;
|
||||
@@ -3387,7 +3392,6 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
|
||||
dev_priv->perf.oa.ops.is_valid_mux_reg =
|
||||
hsw_is_valid_mux_addr;
|
||||
dev_priv->perf.oa.ops.is_valid_flex_reg = NULL;
|
||||
dev_priv->perf.oa.ops.init_oa_buffer = gen7_init_oa_buffer;
|
||||
dev_priv->perf.oa.ops.enable_metric_set = hsw_enable_metric_set;
|
||||
dev_priv->perf.oa.ops.disable_metric_set = hsw_disable_metric_set;
|
||||
dev_priv->perf.oa.ops.oa_enable = gen7_oa_enable;
|
||||
@@ -3406,7 +3410,6 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
|
||||
*/
|
||||
dev_priv->perf.oa.oa_formats = gen8_plus_oa_formats;
|
||||
|
||||
dev_priv->perf.oa.ops.init_oa_buffer = gen8_init_oa_buffer;
|
||||
dev_priv->perf.oa.ops.oa_enable = gen8_oa_enable;
|
||||
dev_priv->perf.oa.ops.oa_disable = gen8_oa_disable;
|
||||
dev_priv->perf.oa.ops.read = gen8_oa_read;
|
||||
|
@@ -27,8 +27,7 @@ static int query_topology_info(struct drm_i915_private *dev_priv,
|
||||
|
||||
slice_length = sizeof(sseu->slice_mask);
|
||||
subslice_length = sseu->max_slices *
|
||||
DIV_ROUND_UP(sseu->max_subslices,
|
||||
sizeof(sseu->subslice_mask[0]) * BITS_PER_BYTE);
|
||||
DIV_ROUND_UP(sseu->max_subslices, BITS_PER_BYTE);
|
||||
eu_length = sseu->max_slices * sseu->max_subslices *
|
||||
DIV_ROUND_UP(sseu->max_eus_per_subslice, BITS_PER_BYTE);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -111,91 +111,6 @@ i915_request_remove_from_client(struct i915_request *request)
|
||||
spin_unlock(&file_priv->mm.lock);
|
||||
}
|
||||
|
||||
static struct i915_dependency *
|
||||
i915_dependency_alloc(struct drm_i915_private *i915)
|
||||
{
|
||||
return kmem_cache_alloc(i915->dependencies, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void
|
||||
i915_dependency_free(struct drm_i915_private *i915,
|
||||
struct i915_dependency *dep)
|
||||
{
|
||||
kmem_cache_free(i915->dependencies, dep);
|
||||
}
|
||||
|
||||
static void
|
||||
__i915_sched_node_add_dependency(struct i915_sched_node *node,
|
||||
struct i915_sched_node *signal,
|
||||
struct i915_dependency *dep,
|
||||
unsigned long flags)
|
||||
{
|
||||
INIT_LIST_HEAD(&dep->dfs_link);
|
||||
list_add(&dep->wait_link, &signal->waiters_list);
|
||||
list_add(&dep->signal_link, &node->signalers_list);
|
||||
dep->signaler = signal;
|
||||
dep->flags = flags;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_sched_node_add_dependency(struct drm_i915_private *i915,
|
||||
struct i915_sched_node *node,
|
||||
struct i915_sched_node *signal)
|
||||
{
|
||||
struct i915_dependency *dep;
|
||||
|
||||
dep = i915_dependency_alloc(i915);
|
||||
if (!dep)
|
||||
return -ENOMEM;
|
||||
|
||||
__i915_sched_node_add_dependency(node, signal, dep,
|
||||
I915_DEPENDENCY_ALLOC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
i915_sched_node_fini(struct drm_i915_private *i915,
|
||||
struct i915_sched_node *node)
|
||||
{
|
||||
struct i915_dependency *dep, *tmp;
|
||||
|
||||
GEM_BUG_ON(!list_empty(&node->link));
|
||||
|
||||
/*
|
||||
* Everyone we depended upon (the fences we wait to be signaled)
|
||||
* should retire before us and remove themselves from our list.
|
||||
* However, retirement is run independently on each timeline and
|
||||
* so we may be called out-of-order.
|
||||
*/
|
||||
list_for_each_entry_safe(dep, tmp, &node->signalers_list, signal_link) {
|
||||
GEM_BUG_ON(!i915_sched_node_signaled(dep->signaler));
|
||||
GEM_BUG_ON(!list_empty(&dep->dfs_link));
|
||||
|
||||
list_del(&dep->wait_link);
|
||||
if (dep->flags & I915_DEPENDENCY_ALLOC)
|
||||
i915_dependency_free(i915, dep);
|
||||
}
|
||||
|
||||
/* Remove ourselves from everyone who depends upon us */
|
||||
list_for_each_entry_safe(dep, tmp, &node->waiters_list, wait_link) {
|
||||
GEM_BUG_ON(dep->signaler != node);
|
||||
GEM_BUG_ON(!list_empty(&dep->dfs_link));
|
||||
|
||||
list_del(&dep->signal_link);
|
||||
if (dep->flags & I915_DEPENDENCY_ALLOC)
|
||||
i915_dependency_free(i915, dep);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
i915_sched_node_init(struct i915_sched_node *node)
|
||||
{
|
||||
INIT_LIST_HEAD(&node->signalers_list);
|
||||
INIT_LIST_HEAD(&node->waiters_list);
|
||||
INIT_LIST_HEAD(&node->link);
|
||||
node->attr.priority = I915_PRIORITY_INVALID;
|
||||
}
|
||||
|
||||
static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno)
|
||||
{
|
||||
struct intel_engine_cs *engine;
|
||||
@@ -221,6 +136,11 @@ static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno)
|
||||
intel_engine_get_seqno(engine),
|
||||
seqno);
|
||||
|
||||
if (seqno == engine->timeline.seqno)
|
||||
continue;
|
||||
|
||||
kthread_park(engine->breadcrumbs.signaler);
|
||||
|
||||
if (!i915_seqno_passed(seqno, engine->timeline.seqno)) {
|
||||
/* Flush any waiters before we reuse the seqno */
|
||||
intel_engine_disarm_breadcrumbs(engine);
|
||||
@@ -235,6 +155,8 @@ static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno)
|
||||
/* Finally reset hw state */
|
||||
intel_engine_init_global_seqno(engine, seqno);
|
||||
engine->timeline.seqno = seqno;
|
||||
|
||||
kthread_unpark(engine->breadcrumbs.signaler);
|
||||
}
|
||||
|
||||
list_for_each_entry(timeline, &i915->gt.timelines, link)
|
||||
@@ -740,17 +662,6 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx)
|
||||
if (rq)
|
||||
cond_synchronize_rcu(rq->rcustate);
|
||||
|
||||
/*
|
||||
* We've forced the client to stall and catch up with whatever
|
||||
* backlog there might have been. As we are assuming that we
|
||||
* caused the mempressure, now is an opportune time to
|
||||
* recover as much memory from the request pool as is possible.
|
||||
* Having already penalized the client to stall, we spend
|
||||
* a little extra time to re-optimise page allocation.
|
||||
*/
|
||||
kmem_cache_shrink(i915->requests);
|
||||
rcu_barrier(); /* Recover the TYPESAFE_BY_RCU pages */
|
||||
|
||||
rq = kmem_cache_alloc(i915->requests, GFP_KERNEL);
|
||||
if (!rq) {
|
||||
ret = -ENOMEM;
|
||||
@@ -1127,8 +1038,20 @@ void i915_request_add(struct i915_request *request)
|
||||
*/
|
||||
local_bh_disable();
|
||||
rcu_read_lock(); /* RCU serialisation for set-wedged protection */
|
||||
if (engine->schedule)
|
||||
engine->schedule(request, &request->gem_context->sched);
|
||||
if (engine->schedule) {
|
||||
struct i915_sched_attr attr = request->gem_context->sched;
|
||||
|
||||
/*
|
||||
* Boost priorities to new clients (new request flows).
|
||||
*
|
||||
* Allow interactive/synchronous clients to jump ahead of
|
||||
* the bulk clients. (FQ_CODEL)
|
||||
*/
|
||||
if (!prev || i915_request_completed(prev))
|
||||
attr.priority |= I915_PRIORITY_NEWCLIENT;
|
||||
|
||||
engine->schedule(request, &attr);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
i915_sw_fence_commit(&request->submit);
|
||||
local_bh_enable(); /* Kick the execlists tasklet if just scheduled */
|
||||
@@ -1310,6 +1233,8 @@ long i915_request_wait(struct i915_request *rq,
|
||||
add_wait_queue(errq, &reset);
|
||||
|
||||
intel_wait_init(&wait);
|
||||
if (flags & I915_WAIT_PRIORITY)
|
||||
i915_schedule_bump_priority(rq, I915_PRIORITY_WAIT);
|
||||
|
||||
restart:
|
||||
do {
|
||||
|
@@ -277,8 +277,9 @@ long i915_request_wait(struct i915_request *rq,
|
||||
__attribute__((nonnull(1)));
|
||||
#define I915_WAIT_INTERRUPTIBLE BIT(0)
|
||||
#define I915_WAIT_LOCKED BIT(1) /* struct_mutex held, handle GPU reset */
|
||||
#define I915_WAIT_ALL BIT(2) /* used by i915_gem_object_wait() */
|
||||
#define I915_WAIT_FOR_IDLE_BOOST BIT(3)
|
||||
#define I915_WAIT_PRIORITY BIT(2) /* small priority bump for the request */
|
||||
#define I915_WAIT_ALL BIT(3) /* used by i915_gem_object_wait() */
|
||||
#define I915_WAIT_FOR_IDLE_BOOST BIT(4)
|
||||
|
||||
static inline bool intel_engine_has_started(struct intel_engine_cs *engine,
|
||||
u32 seqno);
|
||||
@@ -332,14 +333,6 @@ static inline bool i915_request_completed(const struct i915_request *rq)
|
||||
return __i915_request_completed(rq, seqno);
|
||||
}
|
||||
|
||||
static inline bool i915_sched_node_signaled(const struct i915_sched_node *node)
|
||||
{
|
||||
const struct i915_request *rq =
|
||||
container_of(node, const struct i915_request, sched);
|
||||
|
||||
return i915_request_completed(rq);
|
||||
}
|
||||
|
||||
void i915_retire_requests(struct drm_i915_private *i915);
|
||||
|
||||
/*
|
||||
|
399
drivers/gpu/drm/i915/i915_scheduler.c
Normal file
399
drivers/gpu/drm/i915/i915_scheduler.c
Normal file
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_request.h"
|
||||
#include "i915_scheduler.h"
|
||||
|
||||
static DEFINE_SPINLOCK(schedule_lock);
|
||||
|
||||
static const struct i915_request *
|
||||
node_to_request(const struct i915_sched_node *node)
|
||||
{
|
||||
return container_of(node, const struct i915_request, sched);
|
||||
}
|
||||
|
||||
static inline bool node_signaled(const struct i915_sched_node *node)
|
||||
{
|
||||
return i915_request_completed(node_to_request(node));
|
||||
}
|
||||
|
||||
void i915_sched_node_init(struct i915_sched_node *node)
|
||||
{
|
||||
INIT_LIST_HEAD(&node->signalers_list);
|
||||
INIT_LIST_HEAD(&node->waiters_list);
|
||||
INIT_LIST_HEAD(&node->link);
|
||||
node->attr.priority = I915_PRIORITY_INVALID;
|
||||
}
|
||||
|
||||
static struct i915_dependency *
|
||||
i915_dependency_alloc(struct drm_i915_private *i915)
|
||||
{
|
||||
return kmem_cache_alloc(i915->dependencies, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void
|
||||
i915_dependency_free(struct drm_i915_private *i915,
|
||||
struct i915_dependency *dep)
|
||||
{
|
||||
kmem_cache_free(i915->dependencies, dep);
|
||||
}
|
||||
|
||||
bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
|
||||
struct i915_sched_node *signal,
|
||||
struct i915_dependency *dep,
|
||||
unsigned long flags)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
spin_lock(&schedule_lock);
|
||||
|
||||
if (!node_signaled(signal)) {
|
||||
INIT_LIST_HEAD(&dep->dfs_link);
|
||||
list_add(&dep->wait_link, &signal->waiters_list);
|
||||
list_add(&dep->signal_link, &node->signalers_list);
|
||||
dep->signaler = signal;
|
||||
dep->flags = flags;
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
||||
spin_unlock(&schedule_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i915_sched_node_add_dependency(struct drm_i915_private *i915,
|
||||
struct i915_sched_node *node,
|
||||
struct i915_sched_node *signal)
|
||||
{
|
||||
struct i915_dependency *dep;
|
||||
|
||||
dep = i915_dependency_alloc(i915);
|
||||
if (!dep)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!__i915_sched_node_add_dependency(node, signal, dep,
|
||||
I915_DEPENDENCY_ALLOC))
|
||||
i915_dependency_free(i915, dep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_sched_node_fini(struct drm_i915_private *i915,
|
||||
struct i915_sched_node *node)
|
||||
{
|
||||
struct i915_dependency *dep, *tmp;
|
||||
|
||||
GEM_BUG_ON(!list_empty(&node->link));
|
||||
|
||||
spin_lock(&schedule_lock);
|
||||
|
||||
/*
|
||||
* Everyone we depended upon (the fences we wait to be signaled)
|
||||
* should retire before us and remove themselves from our list.
|
||||
* However, retirement is run independently on each timeline and
|
||||
* so we may be called out-of-order.
|
||||
*/
|
||||
list_for_each_entry_safe(dep, tmp, &node->signalers_list, signal_link) {
|
||||
GEM_BUG_ON(!node_signaled(dep->signaler));
|
||||
GEM_BUG_ON(!list_empty(&dep->dfs_link));
|
||||
|
||||
list_del(&dep->wait_link);
|
||||
if (dep->flags & I915_DEPENDENCY_ALLOC)
|
||||
i915_dependency_free(i915, dep);
|
||||
}
|
||||
|
||||
/* Remove ourselves from everyone who depends upon us */
|
||||
list_for_each_entry_safe(dep, tmp, &node->waiters_list, wait_link) {
|
||||
GEM_BUG_ON(dep->signaler != node);
|
||||
GEM_BUG_ON(!list_empty(&dep->dfs_link));
|
||||
|
||||
list_del(&dep->signal_link);
|
||||
if (dep->flags & I915_DEPENDENCY_ALLOC)
|
||||
i915_dependency_free(i915, dep);
|
||||
}
|
||||
|
||||
spin_unlock(&schedule_lock);
|
||||
}
|
||||
|
||||
static inline struct i915_priolist *to_priolist(struct rb_node *rb)
|
||||
{
|
||||
return rb_entry(rb, struct i915_priolist, node);
|
||||
}
|
||||
|
||||
static void assert_priolists(struct intel_engine_execlists * const execlists,
|
||||
long queue_priority)
|
||||
{
|
||||
struct rb_node *rb;
|
||||
long last_prio, i;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
|
||||
return;
|
||||
|
||||
GEM_BUG_ON(rb_first_cached(&execlists->queue) !=
|
||||
rb_first(&execlists->queue.rb_root));
|
||||
|
||||
last_prio = (queue_priority >> I915_USER_PRIORITY_SHIFT) + 1;
|
||||
for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
|
||||
const struct i915_priolist *p = to_priolist(rb);
|
||||
|
||||
GEM_BUG_ON(p->priority >= last_prio);
|
||||
last_prio = p->priority;
|
||||
|
||||
GEM_BUG_ON(!p->used);
|
||||
for (i = 0; i < ARRAY_SIZE(p->requests); i++) {
|
||||
if (list_empty(&p->requests[i]))
|
||||
continue;
|
||||
|
||||
GEM_BUG_ON(!(p->used & BIT(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct list_head *
|
||||
i915_sched_lookup_priolist(struct intel_engine_cs *engine, int prio)
|
||||
{
|
||||
struct intel_engine_execlists * const execlists = &engine->execlists;
|
||||
struct i915_priolist *p;
|
||||
struct rb_node **parent, *rb;
|
||||
bool first = true;
|
||||
int idx, i;
|
||||
|
||||
lockdep_assert_held(&engine->timeline.lock);
|
||||
assert_priolists(execlists, INT_MAX);
|
||||
|
||||
/* buckets sorted from highest [in slot 0] to lowest priority */
|
||||
idx = I915_PRIORITY_COUNT - (prio & I915_PRIORITY_MASK) - 1;
|
||||
prio >>= I915_USER_PRIORITY_SHIFT;
|
||||
if (unlikely(execlists->no_priolist))
|
||||
prio = I915_PRIORITY_NORMAL;
|
||||
|
||||
find_priolist:
|
||||
/* most positive priority is scheduled first, equal priorities fifo */
|
||||
rb = NULL;
|
||||
parent = &execlists->queue.rb_root.rb_node;
|
||||
while (*parent) {
|
||||
rb = *parent;
|
||||
p = to_priolist(rb);
|
||||
if (prio > p->priority) {
|
||||
parent = &rb->rb_left;
|
||||
} else if (prio < p->priority) {
|
||||
parent = &rb->rb_right;
|
||||
first = false;
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (prio == I915_PRIORITY_NORMAL) {
|
||||
p = &execlists->default_priolist;
|
||||
} else {
|
||||
p = kmem_cache_alloc(engine->i915->priorities, GFP_ATOMIC);
|
||||
/* Convert an allocation failure to a priority bump */
|
||||
if (unlikely(!p)) {
|
||||
prio = I915_PRIORITY_NORMAL; /* recurses just once */
|
||||
|
||||
/* To maintain ordering with all rendering, after an
|
||||
* allocation failure we have to disable all scheduling.
|
||||
* Requests will then be executed in fifo, and schedule
|
||||
* will ensure that dependencies are emitted in fifo.
|
||||
* There will be still some reordering with existing
|
||||
* requests, so if userspace lied about their
|
||||
* dependencies that reordering may be visible.
|
||||
*/
|
||||
execlists->no_priolist = true;
|
||||
goto find_priolist;
|
||||
}
|
||||
}
|
||||
|
||||
p->priority = prio;
|
||||
for (i = 0; i < ARRAY_SIZE(p->requests); i++)
|
||||
INIT_LIST_HEAD(&p->requests[i]);
|
||||
rb_link_node(&p->node, rb, parent);
|
||||
rb_insert_color_cached(&p->node, &execlists->queue, first);
|
||||
p->used = 0;
|
||||
|
||||
out:
|
||||
p->used |= BIT(idx);
|
||||
return &p->requests[idx];
|
||||
}
|
||||
|
||||
static struct intel_engine_cs *
|
||||
sched_lock_engine(struct i915_sched_node *node, struct intel_engine_cs *locked)
|
||||
{
|
||||
struct intel_engine_cs *engine = node_to_request(node)->engine;
|
||||
|
||||
GEM_BUG_ON(!locked);
|
||||
|
||||
if (engine != locked) {
|
||||
spin_unlock(&locked->timeline.lock);
|
||||
spin_lock(&engine->timeline.lock);
|
||||
}
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
static void __i915_schedule(struct i915_request *rq,
|
||||
const struct i915_sched_attr *attr)
|
||||
{
|
||||
struct list_head *uninitialized_var(pl);
|
||||
struct intel_engine_cs *engine, *last;
|
||||
struct i915_dependency *dep, *p;
|
||||
struct i915_dependency stack;
|
||||
const int prio = attr->priority;
|
||||
LIST_HEAD(dfs);
|
||||
|
||||
/* Needed in order to use the temporary link inside i915_dependency */
|
||||
lockdep_assert_held(&schedule_lock);
|
||||
GEM_BUG_ON(prio == I915_PRIORITY_INVALID);
|
||||
|
||||
if (i915_request_completed(rq))
|
||||
return;
|
||||
|
||||
if (prio <= READ_ONCE(rq->sched.attr.priority))
|
||||
return;
|
||||
|
||||
stack.signaler = &rq->sched;
|
||||
list_add(&stack.dfs_link, &dfs);
|
||||
|
||||
/*
|
||||
* Recursively bump all dependent priorities to match the new request.
|
||||
*
|
||||
* A naive approach would be to use recursion:
|
||||
* static void update_priorities(struct i915_sched_node *node, prio) {
|
||||
* list_for_each_entry(dep, &node->signalers_list, signal_link)
|
||||
* update_priorities(dep->signal, prio)
|
||||
* queue_request(node);
|
||||
* }
|
||||
* but that may have unlimited recursion depth and so runs a very
|
||||
* real risk of overunning the kernel stack. Instead, we build
|
||||
* a flat list of all dependencies starting with the current request.
|
||||
* As we walk the list of dependencies, we add all of its dependencies
|
||||
* to the end of the list (this may include an already visited
|
||||
* request) and continue to walk onwards onto the new dependencies. The
|
||||
* end result is a topological list of requests in reverse order, the
|
||||
* last element in the list is the request we must execute first.
|
||||
*/
|
||||
list_for_each_entry(dep, &dfs, dfs_link) {
|
||||
struct i915_sched_node *node = dep->signaler;
|
||||
|
||||
/*
|
||||
* Within an engine, there can be no cycle, but we may
|
||||
* refer to the same dependency chain multiple times
|
||||
* (redundant dependencies are not eliminated) and across
|
||||
* engines.
|
||||
*/
|
||||
list_for_each_entry(p, &node->signalers_list, signal_link) {
|
||||
GEM_BUG_ON(p == dep); /* no cycles! */
|
||||
|
||||
if (node_signaled(p->signaler))
|
||||
continue;
|
||||
|
||||
GEM_BUG_ON(p->signaler->attr.priority < node->attr.priority);
|
||||
if (prio > READ_ONCE(p->signaler->attr.priority))
|
||||
list_move_tail(&p->dfs_link, &dfs);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we didn't need to bump any existing priorities, and we haven't
|
||||
* yet submitted this request (i.e. there is no potential race with
|
||||
* execlists_submit_request()), we can set our own priority and skip
|
||||
* acquiring the engine locks.
|
||||
*/
|
||||
if (rq->sched.attr.priority == I915_PRIORITY_INVALID) {
|
||||
GEM_BUG_ON(!list_empty(&rq->sched.link));
|
||||
rq->sched.attr = *attr;
|
||||
|
||||
if (stack.dfs_link.next == stack.dfs_link.prev)
|
||||
return;
|
||||
|
||||
__list_del_entry(&stack.dfs_link);
|
||||
}
|
||||
|
||||
last = NULL;
|
||||
engine = rq->engine;
|
||||
spin_lock_irq(&engine->timeline.lock);
|
||||
|
||||
/* Fifo and depth-first replacement ensure our deps execute before us */
|
||||
list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) {
|
||||
struct i915_sched_node *node = dep->signaler;
|
||||
|
||||
INIT_LIST_HEAD(&dep->dfs_link);
|
||||
|
||||
engine = sched_lock_engine(node, engine);
|
||||
|
||||
/* Recheck after acquiring the engine->timeline.lock */
|
||||
if (prio <= node->attr.priority || node_signaled(node))
|
||||
continue;
|
||||
|
||||
node->attr.priority = prio;
|
||||
if (!list_empty(&node->link)) {
|
||||
if (last != engine) {
|
||||
pl = i915_sched_lookup_priolist(engine, prio);
|
||||
last = engine;
|
||||
}
|
||||
list_move_tail(&node->link, pl);
|
||||
} else {
|
||||
/*
|
||||
* If the request is not in the priolist queue because
|
||||
* it is not yet runnable, then it doesn't contribute
|
||||
* to our preemption decisions. On the other hand,
|
||||
* if the request is on the HW, it too is not in the
|
||||
* queue; but in that case we may still need to reorder
|
||||
* the inflight requests.
|
||||
*/
|
||||
if (!i915_sw_fence_done(&node_to_request(node)->submit))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prio <= engine->execlists.queue_priority)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we are already the currently executing context, don't
|
||||
* bother evaluating if we should preempt ourselves.
|
||||
*/
|
||||
if (node_to_request(node)->global_seqno &&
|
||||
i915_seqno_passed(port_request(engine->execlists.port)->global_seqno,
|
||||
node_to_request(node)->global_seqno))
|
||||
continue;
|
||||
|
||||
/* Defer (tasklet) submission until after all of our updates. */
|
||||
engine->execlists.queue_priority = prio;
|
||||
tasklet_hi_schedule(&engine->execlists.tasklet);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&engine->timeline.lock);
|
||||
}
|
||||
|
||||
void i915_schedule(struct i915_request *rq, const struct i915_sched_attr *attr)
|
||||
{
|
||||
spin_lock(&schedule_lock);
|
||||
__i915_schedule(rq, attr);
|
||||
spin_unlock(&schedule_lock);
|
||||
}
|
||||
|
||||
void i915_schedule_bump_priority(struct i915_request *rq, unsigned int bump)
|
||||
{
|
||||
struct i915_sched_attr attr;
|
||||
|
||||
GEM_BUG_ON(bump & ~I915_PRIORITY_MASK);
|
||||
|
||||
if (READ_ONCE(rq->sched.attr.priority) == I915_PRIORITY_INVALID)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&schedule_lock);
|
||||
|
||||
attr = rq->sched.attr;
|
||||
attr.priority |= bump;
|
||||
__i915_schedule(rq, &attr);
|
||||
|
||||
spin_unlock_bh(&schedule_lock);
|
||||
}
|
@@ -8,9 +8,14 @@
|
||||
#define _I915_SCHEDULER_H_
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <uapi/drm/i915_drm.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
struct i915_request;
|
||||
struct intel_engine_cs;
|
||||
|
||||
enum {
|
||||
I915_PRIORITY_MIN = I915_CONTEXT_MIN_USER_PRIORITY - 1,
|
||||
I915_PRIORITY_NORMAL = I915_CONTEXT_DEFAULT_PRIORITY,
|
||||
@@ -19,6 +24,15 @@ enum {
|
||||
I915_PRIORITY_INVALID = INT_MIN
|
||||
};
|
||||
|
||||
#define I915_USER_PRIORITY_SHIFT 2
|
||||
#define I915_USER_PRIORITY(x) ((x) << I915_USER_PRIORITY_SHIFT)
|
||||
|
||||
#define I915_PRIORITY_COUNT BIT(I915_USER_PRIORITY_SHIFT)
|
||||
#define I915_PRIORITY_MASK (I915_PRIORITY_COUNT - 1)
|
||||
|
||||
#define I915_PRIORITY_WAIT ((u8)BIT(0))
|
||||
#define I915_PRIORITY_NEWCLIENT ((u8)BIT(1))
|
||||
|
||||
struct i915_sched_attr {
|
||||
/**
|
||||
* @priority: execution and service priority
|
||||
@@ -69,4 +83,26 @@ struct i915_dependency {
|
||||
#define I915_DEPENDENCY_ALLOC BIT(0)
|
||||
};
|
||||
|
||||
void i915_sched_node_init(struct i915_sched_node *node);
|
||||
|
||||
bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
|
||||
struct i915_sched_node *signal,
|
||||
struct i915_dependency *dep,
|
||||
unsigned long flags);
|
||||
|
||||
int i915_sched_node_add_dependency(struct drm_i915_private *i915,
|
||||
struct i915_sched_node *node,
|
||||
struct i915_sched_node *signal);
|
||||
|
||||
void i915_sched_node_fini(struct drm_i915_private *i915,
|
||||
struct i915_sched_node *node);
|
||||
|
||||
void i915_schedule(struct i915_request *request,
|
||||
const struct i915_sched_attr *attr);
|
||||
|
||||
void i915_schedule_bump_priority(struct i915_request *rq, unsigned int bump);
|
||||
|
||||
struct list_head *
|
||||
i915_sched_lookup_priolist(struct intel_engine_cs *engine, int prio);
|
||||
|
||||
#endif /* _I915_SCHEDULER_H_ */
|
||||
|
@@ -1,10 +1,7 @@
|
||||
/*
|
||||
* (C) Copyright 2016 Intel Corporation
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; version 2
|
||||
* of the License.
|
||||
* (C) Copyright 2016 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
@@ -1,10 +1,9 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* i915_sw_fence.h - library routines for N:M synchronisation points
|
||||
*
|
||||
* Copyright (C) 2016 Intel Corporation
|
||||
*
|
||||
* This file is released under the GPLv2.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _I915_SW_FENCE_H_
|
||||
|
@@ -92,7 +92,7 @@ void i915_syncmap_init(struct i915_syncmap **root)
|
||||
{
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(KSYNCMAP);
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(SHIFT);
|
||||
BUILD_BUG_ON(KSYNCMAP > BITS_PER_BYTE * sizeof((*root)->bitmap));
|
||||
BUILD_BUG_ON(KSYNCMAP > BITS_PER_TYPE((*root)->bitmap));
|
||||
*root = NULL;
|
||||
}
|
||||
|
||||
|
@@ -483,7 +483,7 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", val);
|
||||
}
|
||||
|
||||
static const struct attribute *gen6_attrs[] = {
|
||||
static const struct attribute * const gen6_attrs[] = {
|
||||
&dev_attr_gt_act_freq_mhz.attr,
|
||||
&dev_attr_gt_cur_freq_mhz.attr,
|
||||
&dev_attr_gt_boost_freq_mhz.attr,
|
||||
@@ -495,7 +495,7 @@ static const struct attribute *gen6_attrs[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute *vlv_attrs[] = {
|
||||
static const struct attribute * const vlv_attrs[] = {
|
||||
&dev_attr_gt_act_freq_mhz.attr,
|
||||
&dev_attr_gt_cur_freq_mhz.attr,
|
||||
&dev_attr_gt_boost_freq_mhz.attr,
|
||||
@@ -516,26 +516,21 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
|
||||
{
|
||||
|
||||
struct device *kdev = kobj_to_dev(kobj);
|
||||
struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
|
||||
struct drm_i915_error_state_buf error_str;
|
||||
struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
|
||||
struct i915_gpu_state *gpu;
|
||||
ssize_t ret;
|
||||
|
||||
ret = i915_error_state_buf_init(&error_str, dev_priv, count, off);
|
||||
if (ret)
|
||||
return ret;
|
||||
gpu = i915_first_error_state(i915);
|
||||
if (gpu) {
|
||||
ret = i915_gpu_state_copy_to_buffer(gpu, buf, off, count);
|
||||
i915_gpu_state_put(gpu);
|
||||
} else {
|
||||
const char *str = "No error state collected\n";
|
||||
size_t len = strlen(str);
|
||||
|
||||
gpu = i915_first_error_state(dev_priv);
|
||||
ret = i915_error_state_to_str(&error_str, gpu);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = count < error_str.bytes ? count : error_str.bytes;
|
||||
memcpy(buf, error_str.buf, ret);
|
||||
|
||||
out:
|
||||
i915_gpu_state_put(gpu);
|
||||
i915_error_state_buf_release(&error_str);
|
||||
ret = min_t(size_t, count, len - off);
|
||||
memcpy(buf, str + off, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -83,6 +83,25 @@ void i915_timeline_init(struct drm_i915_private *i915,
|
||||
const char *name);
|
||||
void i915_timeline_fini(struct i915_timeline *tl);
|
||||
|
||||
static inline void
|
||||
i915_timeline_set_subclass(struct i915_timeline *timeline,
|
||||
unsigned int subclass)
|
||||
{
|
||||
lockdep_set_subclass(&timeline->lock, subclass);
|
||||
|
||||
/*
|
||||
* Due to an interesting quirk in lockdep's internal debug tracking,
|
||||
* after setting a subclass we must ensure the lock is used. Otherwise,
|
||||
* nr_unused_locks is incremented once too often.
|
||||
*/
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
local_irq_disable();
|
||||
lock_map_acquire(&timeline->lock.dep_map);
|
||||
lock_map_release(&timeline->lock.dep_map);
|
||||
local_irq_enable();
|
||||
#endif
|
||||
}
|
||||
|
||||
struct i915_timeline *
|
||||
i915_timeline_create(struct drm_i915_private *i915, const char *name);
|
||||
|
||||
|
@@ -44,16 +44,19 @@
|
||||
__stringify(x), (long)(x))
|
||||
|
||||
#if defined(GCC_VERSION) && GCC_VERSION >= 70000
|
||||
#define add_overflows(A, B) \
|
||||
__builtin_add_overflow_p((A), (B), (typeof((A) + (B)))0)
|
||||
#define add_overflows_t(T, A, B) \
|
||||
__builtin_add_overflow_p((A), (B), (T)0)
|
||||
#else
|
||||
#define add_overflows(A, B) ({ \
|
||||
#define add_overflows_t(T, A, B) ({ \
|
||||
typeof(A) a = (A); \
|
||||
typeof(B) b = (B); \
|
||||
a + b < a; \
|
||||
(T)(a + b) < a; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define add_overflows(A, B) \
|
||||
add_overflows_t(typeof((A) + (B)), (A), (B))
|
||||
|
||||
#define range_overflows(start, size, max) ({ \
|
||||
typeof(start) start__ = (start); \
|
||||
typeof(size) size__ = (size); \
|
||||
@@ -68,7 +71,7 @@
|
||||
|
||||
/* Note we don't consider signbits :| */
|
||||
#define overflows_type(x, T) \
|
||||
(sizeof(x) > sizeof(T) && (x) >> (sizeof(T) * BITS_PER_BYTE))
|
||||
(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
|
||||
|
||||
#define ptr_mask_bits(ptr, n) ({ \
|
||||
unsigned long __v = (unsigned long)(ptr); \
|
||||
|
@@ -305,12 +305,12 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
|
||||
GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
|
||||
GEM_BUG_ON(vma->size > vma->node.size);
|
||||
|
||||
if (GEM_WARN_ON(range_overflows(vma->node.start,
|
||||
vma->node.size,
|
||||
vma->vm->total)))
|
||||
if (GEM_DEBUG_WARN_ON(range_overflows(vma->node.start,
|
||||
vma->node.size,
|
||||
vma->vm->total)))
|
||||
return -ENODEV;
|
||||
|
||||
if (GEM_WARN_ON(!flags))
|
||||
if (GEM_DEBUG_WARN_ON(!flags))
|
||||
return -EINVAL;
|
||||
|
||||
bind_flags = 0;
|
||||
@@ -892,7 +892,7 @@ static void export_fence(struct i915_vma *vma,
|
||||
reservation_object_lock(resv, NULL);
|
||||
if (flags & EXEC_OBJECT_WRITE)
|
||||
reservation_object_add_excl_fence(resv, &rq->fence);
|
||||
else if (reservation_object_reserve_shared(resv) == 0)
|
||||
else if (reservation_object_reserve_shared(resv, 1) == 0)
|
||||
reservation_object_add_shared_fence(resv, &rq->fence);
|
||||
reservation_object_unlock(resv);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -184,6 +184,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||
crtc_state->fifo_changed = false;
|
||||
crtc_state->wm.need_postvbl_update = false;
|
||||
crtc_state->fb_bits = 0;
|
||||
crtc_state->update_planes = 0;
|
||||
|
||||
return &crtc_state->base;
|
||||
}
|
||||
@@ -203,6 +204,72 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
|
||||
drm_atomic_helper_crtc_destroy_state(crtc, state);
|
||||
}
|
||||
|
||||
static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
|
||||
int num_scalers_need, struct intel_crtc *intel_crtc,
|
||||
const char *name, int idx,
|
||||
struct intel_plane_state *plane_state,
|
||||
int *scaler_id)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
|
||||
int j;
|
||||
u32 mode;
|
||||
|
||||
if (*scaler_id < 0) {
|
||||
/* find a free scaler */
|
||||
for (j = 0; j < intel_crtc->num_scalers; j++) {
|
||||
if (scaler_state->scalers[j].in_use)
|
||||
continue;
|
||||
|
||||
*scaler_id = j;
|
||||
scaler_state->scalers[*scaler_id].in_use = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN(*scaler_id < 0, "Cannot find scaler for %s:%d\n", name, idx))
|
||||
return;
|
||||
|
||||
/* set scaler mode */
|
||||
if (plane_state && plane_state->base.fb &&
|
||||
plane_state->base.fb->format->is_yuv &&
|
||||
plane_state->base.fb->format->num_planes > 1) {
|
||||
if (IS_GEN9(dev_priv) &&
|
||||
!IS_GEMINILAKE(dev_priv)) {
|
||||
mode = SKL_PS_SCALER_MODE_NV12;
|
||||
} else if (icl_is_hdr_plane(to_intel_plane(plane_state->base.plane))) {
|
||||
/*
|
||||
* On gen11+'s HDR planes we only use the scaler for
|
||||
* scaling. They have a dedicated chroma upsampler, so
|
||||
* we don't need the scaler to upsample the UV plane.
|
||||
*/
|
||||
mode = PS_SCALER_MODE_NORMAL;
|
||||
} else {
|
||||
mode = PS_SCALER_MODE_PLANAR;
|
||||
|
||||
if (plane_state->linked_plane)
|
||||
mode |= PS_PLANE_Y_SEL(plane_state->linked_plane->id);
|
||||
}
|
||||
} else if (INTEL_GEN(dev_priv) > 9 || IS_GEMINILAKE(dev_priv)) {
|
||||
mode = PS_SCALER_MODE_NORMAL;
|
||||
} else if (num_scalers_need == 1 && intel_crtc->num_scalers > 1) {
|
||||
/*
|
||||
* when only 1 scaler is in use on a pipe with 2 scalers
|
||||
* scaler 0 operates in high quality (HQ) mode.
|
||||
* In this case use scaler 0 to take advantage of HQ mode
|
||||
*/
|
||||
scaler_state->scalers[*scaler_id].in_use = 0;
|
||||
*scaler_id = 0;
|
||||
scaler_state->scalers[0].in_use = 1;
|
||||
mode = SKL_PS_SCALER_MODE_HQ;
|
||||
} else {
|
||||
mode = SKL_PS_SCALER_MODE_DYN;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("Attached scaler id %u.%u to %s:%d\n",
|
||||
intel_crtc->pipe, *scaler_id, name, idx);
|
||||
scaler_state->scalers[*scaler_id].mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
|
||||
* @dev_priv: i915 device
|
||||
@@ -232,7 +299,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
|
||||
struct drm_atomic_state *drm_state = crtc_state->base.state;
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state);
|
||||
int num_scalers_need;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
num_scalers_need = hweight32(scaler_state->scaler_users);
|
||||
|
||||
@@ -304,59 +371,17 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
|
||||
idx = plane->base.id;
|
||||
|
||||
/* plane on different crtc cannot be a scaler user of this crtc */
|
||||
if (WARN_ON(intel_plane->pipe != intel_crtc->pipe)) {
|
||||
if (WARN_ON(intel_plane->pipe != intel_crtc->pipe))
|
||||
continue;
|
||||
}
|
||||
|
||||
plane_state = intel_atomic_get_new_plane_state(intel_state,
|
||||
intel_plane);
|
||||
scaler_id = &plane_state->scaler_id;
|
||||
}
|
||||
|
||||
if (*scaler_id < 0) {
|
||||
/* find a free scaler */
|
||||
for (j = 0; j < intel_crtc->num_scalers; j++) {
|
||||
if (!scaler_state->scalers[j].in_use) {
|
||||
scaler_state->scalers[j].in_use = 1;
|
||||
*scaler_id = j;
|
||||
DRM_DEBUG_KMS("Attached scaler id %u.%u to %s:%d\n",
|
||||
intel_crtc->pipe, *scaler_id, name, idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN_ON(*scaler_id < 0)) {
|
||||
DRM_DEBUG_KMS("Cannot find scaler for %s:%d\n", name, idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* set scaler mode */
|
||||
if ((INTEL_GEN(dev_priv) >= 9) &&
|
||||
plane_state && plane_state->base.fb &&
|
||||
plane_state->base.fb->format->format ==
|
||||
DRM_FORMAT_NV12) {
|
||||
if (INTEL_GEN(dev_priv) == 9 &&
|
||||
!IS_GEMINILAKE(dev_priv) &&
|
||||
!IS_SKYLAKE(dev_priv))
|
||||
scaler_state->scalers[*scaler_id].mode =
|
||||
SKL_PS_SCALER_MODE_NV12;
|
||||
else
|
||||
scaler_state->scalers[*scaler_id].mode =
|
||||
PS_SCALER_MODE_PLANAR;
|
||||
} else if (num_scalers_need == 1 && intel_crtc->pipe != PIPE_C) {
|
||||
/*
|
||||
* when only 1 scaler is in use on either pipe A or B,
|
||||
* scaler 0 operates in high quality (HQ) mode.
|
||||
* In this case use scaler 0 to take advantage of HQ mode
|
||||
*/
|
||||
*scaler_id = 0;
|
||||
scaler_state->scalers[0].in_use = 1;
|
||||
scaler_state->scalers[0].mode = PS_SCALER_MODE_HQ;
|
||||
scaler_state->scalers[1].in_use = 0;
|
||||
} else {
|
||||
scaler_state->scalers[*scaler_id].mode = PS_SCALER_MODE_DYN;
|
||||
}
|
||||
intel_atomic_setup_scaler(scaler_state, num_scalers_need,
|
||||
intel_crtc, name, idx,
|
||||
plane_state, scaler_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@@ -36,28 +36,31 @@
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include "intel_drv.h"
|
||||
|
||||
/**
|
||||
* intel_create_plane_state - create plane state object
|
||||
* @plane: drm plane
|
||||
*
|
||||
* Allocates a fresh plane state for the given plane and sets some of
|
||||
* the state values to sensible initial values.
|
||||
*
|
||||
* Returns: A newly allocated plane state, or NULL on failure
|
||||
*/
|
||||
struct intel_plane_state *
|
||||
intel_create_plane_state(struct drm_plane *plane)
|
||||
struct intel_plane *intel_plane_alloc(void)
|
||||
{
|
||||
struct intel_plane_state *state;
|
||||
struct intel_plane_state *plane_state;
|
||||
struct intel_plane *plane;
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return NULL;
|
||||
plane = kzalloc(sizeof(*plane), GFP_KERNEL);
|
||||
if (!plane)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
state->base.plane = plane;
|
||||
state->base.rotation = DRM_MODE_ROTATE_0;
|
||||
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
|
||||
if (!plane_state) {
|
||||
kfree(plane);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
return state;
|
||||
__drm_atomic_helper_plane_reset(&plane->base, &plane_state->base);
|
||||
plane_state->scaler_id = -1;
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
void intel_plane_free(struct intel_plane *plane)
|
||||
{
|
||||
intel_plane_destroy_state(&plane->base, plane->base.state);
|
||||
kfree(plane);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,10 +120,14 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
int ret;
|
||||
|
||||
crtc_state->active_planes &= ~BIT(intel_plane->id);
|
||||
crtc_state->nv12_planes &= ~BIT(intel_plane->id);
|
||||
intel_state->base.visible = false;
|
||||
|
||||
/* If this is a cursor plane, no further checks are needed. */
|
||||
if (!intel_state->base.crtc && !old_plane_state->base.crtc)
|
||||
return 0;
|
||||
|
||||
intel_state->base.visible = false;
|
||||
ret = intel_plane->check_plane(crtc_state, intel_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -128,13 +135,12 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
|
||||
/* FIXME pre-g4x don't work like this */
|
||||
if (state->visible)
|
||||
crtc_state->active_planes |= BIT(intel_plane->id);
|
||||
else
|
||||
crtc_state->active_planes &= ~BIT(intel_plane->id);
|
||||
|
||||
if (state->visible && state->fb->format->format == DRM_FORMAT_NV12)
|
||||
crtc_state->nv12_planes |= BIT(intel_plane->id);
|
||||
else
|
||||
crtc_state->nv12_planes &= ~BIT(intel_plane->id);
|
||||
|
||||
if (state->visible || old_plane_state->base.visible)
|
||||
crtc_state->update_planes |= BIT(intel_plane->id);
|
||||
|
||||
return intel_plane_atomic_calc_changes(old_crtc_state,
|
||||
&crtc_state->base,
|
||||
@@ -152,6 +158,7 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
|
||||
const struct drm_crtc_state *old_crtc_state;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
|
||||
new_plane_state->visible = false;
|
||||
if (!crtc)
|
||||
return 0;
|
||||
|
||||
@@ -164,29 +171,123 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
|
||||
to_intel_plane_state(new_plane_state));
|
||||
}
|
||||
|
||||
static void intel_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
static struct intel_plane *
|
||||
skl_next_plane_to_commit(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc,
|
||||
struct skl_ddb_entry entries_y[I915_MAX_PLANES],
|
||||
struct skl_ddb_entry entries_uv[I915_MAX_PLANES],
|
||||
unsigned int *update_mask)
|
||||
{
|
||||
struct intel_atomic_state *state = to_intel_atomic_state(old_state->state);
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
const struct intel_plane_state *new_plane_state =
|
||||
intel_atomic_get_new_plane_state(state, intel_plane);
|
||||
struct drm_crtc *crtc = new_plane_state->base.crtc ?: old_state->crtc;
|
||||
struct intel_crtc_state *crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
struct intel_plane_state *plane_state;
|
||||
struct intel_plane *plane;
|
||||
int i;
|
||||
|
||||
if (new_plane_state->base.visible) {
|
||||
const struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, to_intel_crtc(crtc));
|
||||
if (*update_mask == 0)
|
||||
return NULL;
|
||||
|
||||
trace_intel_update_plane(plane,
|
||||
to_intel_crtc(crtc));
|
||||
for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
|
||||
enum plane_id plane_id = plane->id;
|
||||
|
||||
intel_plane->update_plane(intel_plane,
|
||||
new_crtc_state, new_plane_state);
|
||||
} else {
|
||||
trace_intel_disable_plane(plane,
|
||||
to_intel_crtc(crtc));
|
||||
if (crtc->pipe != plane->pipe ||
|
||||
!(*update_mask & BIT(plane_id)))
|
||||
continue;
|
||||
|
||||
intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
|
||||
if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id],
|
||||
entries_y,
|
||||
I915_MAX_PLANES, plane_id) ||
|
||||
skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id],
|
||||
entries_uv,
|
||||
I915_MAX_PLANES, plane_id))
|
||||
continue;
|
||||
|
||||
*update_mask &= ~BIT(plane_id);
|
||||
entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id];
|
||||
entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id];
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
/* should never happen */
|
||||
WARN_ON(1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void skl_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc_state *old_crtc_state =
|
||||
intel_atomic_get_old_crtc_state(state, crtc);
|
||||
struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
struct skl_ddb_entry entries_y[I915_MAX_PLANES];
|
||||
struct skl_ddb_entry entries_uv[I915_MAX_PLANES];
|
||||
u32 update_mask = new_crtc_state->update_planes;
|
||||
struct intel_plane *plane;
|
||||
|
||||
memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y,
|
||||
sizeof(old_crtc_state->wm.skl.plane_ddb_y));
|
||||
memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv,
|
||||
sizeof(old_crtc_state->wm.skl.plane_ddb_uv));
|
||||
|
||||
while ((plane = skl_next_plane_to_commit(state, crtc,
|
||||
entries_y, entries_uv,
|
||||
&update_mask))) {
|
||||
struct intel_plane_state *new_plane_state =
|
||||
intel_atomic_get_new_plane_state(state, plane);
|
||||
|
||||
if (new_plane_state->base.visible) {
|
||||
trace_intel_update_plane(&plane->base, crtc);
|
||||
plane->update_plane(plane, new_crtc_state, new_plane_state);
|
||||
} else if (new_plane_state->slave) {
|
||||
struct intel_plane *master =
|
||||
new_plane_state->linked_plane;
|
||||
|
||||
/*
|
||||
* We update the slave plane from this function because
|
||||
* programming it from the master plane's update_plane
|
||||
* callback runs into issues when the Y plane is
|
||||
* reassigned, disabled or used by a different plane.
|
||||
*
|
||||
* The slave plane is updated with the master plane's
|
||||
* plane_state.
|
||||
*/
|
||||
new_plane_state =
|
||||
intel_atomic_get_new_plane_state(state, master);
|
||||
|
||||
trace_intel_update_plane(&plane->base, crtc);
|
||||
plane->update_slave(plane, new_crtc_state, new_plane_state);
|
||||
} else {
|
||||
trace_intel_disable_plane(&plane->base, crtc);
|
||||
plane->disable_plane(plane, new_crtc_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
u32 update_mask = new_crtc_state->update_planes;
|
||||
struct intel_plane_state *new_plane_state;
|
||||
struct intel_plane *plane;
|
||||
int i;
|
||||
|
||||
for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
|
||||
if (crtc->pipe != plane->pipe ||
|
||||
!(update_mask & BIT(plane->id)))
|
||||
continue;
|
||||
|
||||
if (new_plane_state->base.visible) {
|
||||
trace_intel_update_plane(&plane->base, crtc);
|
||||
plane->update_plane(plane, new_crtc_state, new_plane_state);
|
||||
} else {
|
||||
trace_intel_disable_plane(&plane->base, crtc);
|
||||
plane->disable_plane(plane, new_crtc_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +295,6 @@ const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
|
||||
.prepare_fb = intel_prepare_plane_fb,
|
||||
.cleanup_fb = intel_cleanup_plane_fb,
|
||||
.atomic_check = intel_plane_atomic_check,
|
||||
.atomic_update = intel_plane_atomic_update,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -153,32 +153,32 @@ static const struct {
|
||||
int n;
|
||||
int cts;
|
||||
} hdmi_aud_ncts[] = {
|
||||
{ 44100, TMDS_296M, 4459, 234375 },
|
||||
{ 44100, TMDS_297M, 4704, 247500 },
|
||||
{ 48000, TMDS_296M, 5824, 281250 },
|
||||
{ 48000, TMDS_297M, 5120, 247500 },
|
||||
{ 32000, TMDS_296M, 5824, 421875 },
|
||||
{ 32000, TMDS_297M, 3072, 222750 },
|
||||
{ 88200, TMDS_296M, 8918, 234375 },
|
||||
{ 88200, TMDS_297M, 9408, 247500 },
|
||||
{ 96000, TMDS_296M, 11648, 281250 },
|
||||
{ 96000, TMDS_297M, 10240, 247500 },
|
||||
{ 176400, TMDS_296M, 17836, 234375 },
|
||||
{ 176400, TMDS_297M, 18816, 247500 },
|
||||
{ 192000, TMDS_296M, 23296, 281250 },
|
||||
{ 192000, TMDS_297M, 20480, 247500 },
|
||||
{ 44100, TMDS_593M, 8918, 937500 },
|
||||
{ 44100, TMDS_594M, 9408, 990000 },
|
||||
{ 48000, TMDS_593M, 5824, 562500 },
|
||||
{ 48000, TMDS_594M, 6144, 594000 },
|
||||
{ 32000, TMDS_593M, 5824, 843750 },
|
||||
{ 32000, TMDS_594M, 3072, 445500 },
|
||||
{ 44100, TMDS_296M, 4459, 234375 },
|
||||
{ 44100, TMDS_297M, 4704, 247500 },
|
||||
{ 44100, TMDS_593M, 8918, 937500 },
|
||||
{ 44100, TMDS_594M, 9408, 990000 },
|
||||
{ 88200, TMDS_296M, 8918, 234375 },
|
||||
{ 88200, TMDS_297M, 9408, 247500 },
|
||||
{ 88200, TMDS_593M, 17836, 937500 },
|
||||
{ 88200, TMDS_594M, 18816, 990000 },
|
||||
{ 96000, TMDS_593M, 11648, 562500 },
|
||||
{ 96000, TMDS_594M, 12288, 594000 },
|
||||
{ 176400, TMDS_296M, 17836, 234375 },
|
||||
{ 176400, TMDS_297M, 18816, 247500 },
|
||||
{ 176400, TMDS_593M, 35672, 937500 },
|
||||
{ 176400, TMDS_594M, 37632, 990000 },
|
||||
{ 48000, TMDS_296M, 5824, 281250 },
|
||||
{ 48000, TMDS_297M, 5120, 247500 },
|
||||
{ 48000, TMDS_593M, 5824, 562500 },
|
||||
{ 48000, TMDS_594M, 6144, 594000 },
|
||||
{ 96000, TMDS_296M, 11648, 281250 },
|
||||
{ 96000, TMDS_297M, 10240, 247500 },
|
||||
{ 96000, TMDS_593M, 11648, 562500 },
|
||||
{ 96000, TMDS_594M, 12288, 594000 },
|
||||
{ 192000, TMDS_296M, 23296, 281250 },
|
||||
{ 192000, TMDS_297M, 20480, 247500 },
|
||||
{ 192000, TMDS_593M, 23296, 562500 },
|
||||
{ 192000, TMDS_594M, 24576, 594000 },
|
||||
};
|
||||
@@ -929,6 +929,9 @@ static int i915_audio_component_bind(struct device *i915_kdev,
|
||||
if (WARN_ON(acomp->base.ops || acomp->base.dev))
|
||||
return -EEXIST;
|
||||
|
||||
if (WARN_ON(!device_link_add(hda_kdev, i915_kdev, DL_FLAG_STATELESS)))
|
||||
return -ENOMEM;
|
||||
|
||||
drm_modeset_lock_all(&dev_priv->drm);
|
||||
acomp->base.ops = &i915_audio_component_ops;
|
||||
acomp->base.dev = i915_kdev;
|
||||
@@ -952,6 +955,8 @@ static void i915_audio_component_unbind(struct device *i915_kdev,
|
||||
acomp->base.dev = NULL;
|
||||
dev_priv->audio_component = NULL;
|
||||
drm_modeset_unlock_all(&dev_priv->drm);
|
||||
|
||||
device_link_remove(hda_kdev, i915_kdev);
|
||||
}
|
||||
|
||||
static const struct component_ops i915_audio_component_bind_ops = {
|
||||
|
@@ -420,6 +420,13 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
||||
intel_bios_ssc_frequency(dev_priv, general->ssc_freq);
|
||||
dev_priv->vbt.display_clock_mode = general->display_clock_mode;
|
||||
dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
|
||||
if (bdb->version >= 181) {
|
||||
dev_priv->vbt.orientation = general->rotate_180 ?
|
||||
DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP :
|
||||
DRM_MODE_PANEL_ORIENTATION_NORMAL;
|
||||
} else {
|
||||
dev_priv->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
||||
}
|
||||
DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
|
||||
dev_priv->vbt.int_tv_support,
|
||||
dev_priv->vbt.int_crt_support,
|
||||
@@ -852,6 +859,30 @@ parse_mipi_config(struct drm_i915_private *dev_priv,
|
||||
|
||||
parse_dsi_backlight_ports(dev_priv, bdb->version, port);
|
||||
|
||||
/* FIXME is the 90 vs. 270 correct? */
|
||||
switch (config->rotation) {
|
||||
case ENABLE_ROTATION_0:
|
||||
/*
|
||||
* Most (all?) VBTs claim 0 degrees despite having
|
||||
* an upside down panel, thus we do not trust this.
|
||||
*/
|
||||
dev_priv->vbt.dsi.orientation =
|
||||
DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
||||
break;
|
||||
case ENABLE_ROTATION_90:
|
||||
dev_priv->vbt.dsi.orientation =
|
||||
DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
|
||||
break;
|
||||
case ENABLE_ROTATION_180:
|
||||
dev_priv->vbt.dsi.orientation =
|
||||
DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
|
||||
break;
|
||||
case ENABLE_ROTATION_270:
|
||||
dev_priv->vbt.dsi.orientation =
|
||||
DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We have mandatory mipi config blocks. Initialize as generic panel */
|
||||
dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
|
||||
}
|
||||
@@ -1721,7 +1752,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
|
||||
const struct bdb_header *bdb;
|
||||
u8 __iomem *bios = NULL;
|
||||
|
||||
if (INTEL_INFO(dev_priv)->num_pipes == 0) {
|
||||
if (!HAS_DISPLAY(dev_priv)) {
|
||||
DRM_DEBUG_KMS("Skipping VBT init due to disabled display.\n");
|
||||
return;
|
||||
}
|
||||
@@ -2039,17 +2070,17 @@ bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv,
|
||||
|
||||
dvo_port = child->dvo_port;
|
||||
|
||||
switch (dvo_port) {
|
||||
case DVO_PORT_MIPIA:
|
||||
case DVO_PORT_MIPIC:
|
||||
if (dvo_port == DVO_PORT_MIPIA ||
|
||||
(dvo_port == DVO_PORT_MIPIB && IS_ICELAKE(dev_priv)) ||
|
||||
(dvo_port == DVO_PORT_MIPIC && !IS_ICELAKE(dev_priv))) {
|
||||
if (port)
|
||||
*port = dvo_port - DVO_PORT_MIPIA;
|
||||
return true;
|
||||
case DVO_PORT_MIPIB:
|
||||
case DVO_PORT_MIPID:
|
||||
} else if (dvo_port == DVO_PORT_MIPIB ||
|
||||
dvo_port == DVO_PORT_MIPIC ||
|
||||
dvo_port == DVO_PORT_MIPID) {
|
||||
DRM_DEBUG_KMS("VBT has unsupported DSI port %c\n",
|
||||
port_name(dvo_port - DVO_PORT_MIPIA));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2159,3 +2190,49 @@ intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
const struct ddi_vbt_port_info *info =
|
||||
&dev_priv->vbt.ddi_port_info[port];
|
||||
enum aux_ch aux_ch;
|
||||
|
||||
if (!info->alternate_aux_channel) {
|
||||
aux_ch = (enum aux_ch)port;
|
||||
|
||||
DRM_DEBUG_KMS("using AUX %c for port %c (platform default)\n",
|
||||
aux_ch_name(aux_ch), port_name(port));
|
||||
return aux_ch;
|
||||
}
|
||||
|
||||
switch (info->alternate_aux_channel) {
|
||||
case DP_AUX_A:
|
||||
aux_ch = AUX_CH_A;
|
||||
break;
|
||||
case DP_AUX_B:
|
||||
aux_ch = AUX_CH_B;
|
||||
break;
|
||||
case DP_AUX_C:
|
||||
aux_ch = AUX_CH_C;
|
||||
break;
|
||||
case DP_AUX_D:
|
||||
aux_ch = AUX_CH_D;
|
||||
break;
|
||||
case DP_AUX_E:
|
||||
aux_ch = AUX_CH_E;
|
||||
break;
|
||||
case DP_AUX_F:
|
||||
aux_ch = AUX_CH_F;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(info->alternate_aux_channel);
|
||||
aux_ch = AUX_CH_A;
|
||||
break;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("using AUX %c for port %c (VBT)\n",
|
||||
aux_ch_name(aux_ch), port_name(port));
|
||||
|
||||
return aux_ch;
|
||||
}
|
||||
|
@@ -27,11 +27,7 @@
|
||||
|
||||
#include "i915_drv.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define task_asleep(tsk) ((tsk)->state & TASK_NORMAL && !(tsk)->on_cpu)
|
||||
#else
|
||||
#define task_asleep(tsk) ((tsk)->state & TASK_NORMAL)
|
||||
#endif
|
||||
#define task_asleep(tsk) ((tsk)->state & TASK_NORMAL && !(tsk)->on_rq)
|
||||
|
||||
static unsigned int __intel_breadcrumbs_wakeup(struct intel_breadcrumbs *b)
|
||||
{
|
||||
|
@@ -2660,39 +2660,20 @@ static int cnp_rawclk(struct drm_i915_private *dev_priv)
|
||||
fraction = 200;
|
||||
}
|
||||
|
||||
rawclk = CNP_RAWCLK_DIV((divider / 1000) - 1);
|
||||
if (fraction)
|
||||
rawclk |= CNP_RAWCLK_FRAC(DIV_ROUND_CLOSEST(1000,
|
||||
fraction) - 1);
|
||||
rawclk = CNP_RAWCLK_DIV(divider / 1000);
|
||||
if (fraction) {
|
||||
int numerator = 1;
|
||||
|
||||
rawclk |= CNP_RAWCLK_DEN(DIV_ROUND_CLOSEST(numerator * 1000,
|
||||
fraction) - 1);
|
||||
if (HAS_PCH_ICP(dev_priv))
|
||||
rawclk |= ICP_RAWCLK_NUM(numerator);
|
||||
}
|
||||
|
||||
I915_WRITE(PCH_RAWCLK_FREQ, rawclk);
|
||||
return divider + fraction;
|
||||
}
|
||||
|
||||
static int icp_rawclk(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 rawclk;
|
||||
int divider, numerator, denominator, frequency;
|
||||
|
||||
if (I915_READ(SFUSE_STRAP) & SFUSE_STRAP_RAW_FREQUENCY) {
|
||||
frequency = 24000;
|
||||
divider = 23;
|
||||
numerator = 0;
|
||||
denominator = 0;
|
||||
} else {
|
||||
frequency = 19200;
|
||||
divider = 18;
|
||||
numerator = 1;
|
||||
denominator = 4;
|
||||
}
|
||||
|
||||
rawclk = CNP_RAWCLK_DIV(divider) | ICP_RAWCLK_NUM(numerator) |
|
||||
ICP_RAWCLK_DEN(denominator);
|
||||
|
||||
I915_WRITE(PCH_RAWCLK_FREQ, rawclk);
|
||||
return frequency;
|
||||
}
|
||||
|
||||
static int pch_rawclk(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
|
||||
@@ -2740,9 +2721,7 @@ static int g4x_hrawclk(struct drm_i915_private *dev_priv)
|
||||
*/
|
||||
void intel_update_rawclk(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (HAS_PCH_ICP(dev_priv))
|
||||
dev_priv->rawclk_freq = icp_rawclk(dev_priv);
|
||||
else if (HAS_PCH_CNP(dev_priv))
|
||||
if (HAS_PCH_CNP(dev_priv) || HAS_PCH_ICP(dev_priv))
|
||||
dev_priv->rawclk_freq = cnp_rawclk(dev_priv);
|
||||
else if (HAS_PCH_SPLIT(dev_priv))
|
||||
dev_priv->rawclk_freq = pch_rawclk(dev_priv);
|
||||
|
@@ -149,7 +149,8 @@ static void ilk_load_csc_matrix(struct drm_crtc_state *crtc_state)
|
||||
if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv))
|
||||
limited_color_range = intel_crtc_state->limited_color_range;
|
||||
|
||||
if (intel_crtc_state->ycbcr420) {
|
||||
if (intel_crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
|
||||
intel_crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) {
|
||||
ilk_load_ycbcr_conversion_matrix(intel_crtc);
|
||||
return;
|
||||
} else if (crtc_state->ctm) {
|
||||
|
254
drivers/gpu/drm/i915/intel_combo_phy.c
Normal file
254
drivers/gpu/drm/i915/intel_combo_phy.c
Normal file
@@ -0,0 +1,254 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "intel_drv.h"
|
||||
|
||||
#define for_each_combo_port(__dev_priv, __port) \
|
||||
for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++) \
|
||||
for_each_if(intel_port_is_combophy(__dev_priv, __port))
|
||||
|
||||
#define for_each_combo_port_reverse(__dev_priv, __port) \
|
||||
for ((__port) = I915_MAX_PORTS; (__port)-- > PORT_A;) \
|
||||
for_each_if(intel_port_is_combophy(__dev_priv, __port))
|
||||
|
||||
enum {
|
||||
PROCMON_0_85V_DOT_0,
|
||||
PROCMON_0_95V_DOT_0,
|
||||
PROCMON_0_95V_DOT_1,
|
||||
PROCMON_1_05V_DOT_0,
|
||||
PROCMON_1_05V_DOT_1,
|
||||
};
|
||||
|
||||
static const struct cnl_procmon {
|
||||
u32 dw1, dw9, dw10;
|
||||
} cnl_procmon_values[] = {
|
||||
[PROCMON_0_85V_DOT_0] =
|
||||
{ .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, },
|
||||
[PROCMON_0_95V_DOT_0] =
|
||||
{ .dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB, },
|
||||
[PROCMON_0_95V_DOT_1] =
|
||||
{ .dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5, },
|
||||
[PROCMON_1_05V_DOT_0] =
|
||||
{ .dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1, },
|
||||
[PROCMON_1_05V_DOT_1] =
|
||||
{ .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, },
|
||||
};
|
||||
|
||||
/*
|
||||
* CNL has just one set of registers, while ICL has two sets: one for port A and
|
||||
* the other for port B. The CNL registers are equivalent to the ICL port A
|
||||
* registers, that's why we call the ICL macros even though the function has CNL
|
||||
* on its name.
|
||||
*/
|
||||
static const struct cnl_procmon *
|
||||
cnl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum port port)
|
||||
{
|
||||
const struct cnl_procmon *procmon;
|
||||
u32 val;
|
||||
|
||||
val = I915_READ(ICL_PORT_COMP_DW3(port));
|
||||
switch (val & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) {
|
||||
default:
|
||||
MISSING_CASE(val);
|
||||
/* fall through */
|
||||
case VOLTAGE_INFO_0_85V | PROCESS_INFO_DOT_0:
|
||||
procmon = &cnl_procmon_values[PROCMON_0_85V_DOT_0];
|
||||
break;
|
||||
case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_0:
|
||||
procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_0];
|
||||
break;
|
||||
case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_1:
|
||||
procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_1];
|
||||
break;
|
||||
case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_0:
|
||||
procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_0];
|
||||
break;
|
||||
case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_1:
|
||||
procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_1];
|
||||
break;
|
||||
}
|
||||
|
||||
return procmon;
|
||||
}
|
||||
|
||||
static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
const struct cnl_procmon *procmon;
|
||||
u32 val;
|
||||
|
||||
procmon = cnl_get_procmon_ref_values(dev_priv, port);
|
||||
|
||||
val = I915_READ(ICL_PORT_COMP_DW1(port));
|
||||
val &= ~((0xff << 16) | 0xff);
|
||||
val |= procmon->dw1;
|
||||
I915_WRITE(ICL_PORT_COMP_DW1(port), val);
|
||||
|
||||
I915_WRITE(ICL_PORT_COMP_DW9(port), procmon->dw9);
|
||||
I915_WRITE(ICL_PORT_COMP_DW10(port), procmon->dw10);
|
||||
}
|
||||
|
||||
static bool check_phy_reg(struct drm_i915_private *dev_priv,
|
||||
enum port port, i915_reg_t reg, u32 mask,
|
||||
u32 expected_val)
|
||||
{
|
||||
u32 val = I915_READ(reg);
|
||||
|
||||
if ((val & mask) != expected_val) {
|
||||
DRM_DEBUG_DRIVER("Port %c combo PHY reg %08x state mismatch: "
|
||||
"current %08x mask %08x expected %08x\n",
|
||||
port_name(port),
|
||||
reg.reg, val, mask, expected_val);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cnl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
const struct cnl_procmon *procmon;
|
||||
bool ret;
|
||||
|
||||
procmon = cnl_get_procmon_ref_values(dev_priv, port);
|
||||
|
||||
ret = check_phy_reg(dev_priv, port, ICL_PORT_COMP_DW1(port),
|
||||
(0xff << 16) | 0xff, procmon->dw1);
|
||||
ret &= check_phy_reg(dev_priv, port, ICL_PORT_COMP_DW9(port),
|
||||
-1U, procmon->dw9);
|
||||
ret &= check_phy_reg(dev_priv, port, ICL_PORT_COMP_DW10(port),
|
||||
-1U, procmon->dw10);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool cnl_combo_phy_enabled(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return !(I915_READ(CHICKEN_MISC_2) & CNL_COMP_PWR_DOWN) &&
|
||||
(I915_READ(CNL_PORT_COMP_DW0) & COMP_INIT);
|
||||
}
|
||||
|
||||
static bool cnl_combo_phy_verify_state(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
enum port port = PORT_A;
|
||||
bool ret;
|
||||
|
||||
if (!cnl_combo_phy_enabled(dev_priv))
|
||||
return false;
|
||||
|
||||
ret = cnl_verify_procmon_ref_values(dev_priv, port);
|
||||
|
||||
ret &= check_phy_reg(dev_priv, port, CNL_PORT_CL1CM_DW5,
|
||||
CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cnl_combo_phys_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = I915_READ(CHICKEN_MISC_2);
|
||||
val &= ~CNL_COMP_PWR_DOWN;
|
||||
I915_WRITE(CHICKEN_MISC_2, val);
|
||||
|
||||
/* Dummy PORT_A to get the correct CNL register from the ICL macro */
|
||||
cnl_set_procmon_ref_values(dev_priv, PORT_A);
|
||||
|
||||
val = I915_READ(CNL_PORT_COMP_DW0);
|
||||
val |= COMP_INIT;
|
||||
I915_WRITE(CNL_PORT_COMP_DW0, val);
|
||||
|
||||
val = I915_READ(CNL_PORT_CL1CM_DW5);
|
||||
val |= CL_POWER_DOWN_ENABLE;
|
||||
I915_WRITE(CNL_PORT_CL1CM_DW5, val);
|
||||
}
|
||||
|
||||
void cnl_combo_phys_uninit(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (!cnl_combo_phy_verify_state(dev_priv))
|
||||
DRM_WARN("Combo PHY HW state changed unexpectedly.\n");
|
||||
|
||||
val = I915_READ(CHICKEN_MISC_2);
|
||||
val |= CNL_COMP_PWR_DOWN;
|
||||
I915_WRITE(CHICKEN_MISC_2, val);
|
||||
}
|
||||
|
||||
static bool icl_combo_phy_enabled(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
return !(I915_READ(ICL_PHY_MISC(port)) &
|
||||
ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN) &&
|
||||
(I915_READ(ICL_PORT_COMP_DW0(port)) & COMP_INIT);
|
||||
}
|
||||
|
||||
static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (!icl_combo_phy_enabled(dev_priv, port))
|
||||
return false;
|
||||
|
||||
ret = cnl_verify_procmon_ref_values(dev_priv, port);
|
||||
|
||||
ret &= check_phy_reg(dev_priv, port, ICL_PORT_CL_DW5(port),
|
||||
CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void icl_combo_phys_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
enum port port;
|
||||
|
||||
for_each_combo_port(dev_priv, port) {
|
||||
u32 val;
|
||||
|
||||
if (icl_combo_phy_verify_state(dev_priv, port)) {
|
||||
DRM_DEBUG_DRIVER("Port %c combo PHY already enabled, won't reprogram it.\n",
|
||||
port_name(port));
|
||||
continue;
|
||||
}
|
||||
|
||||
val = I915_READ(ICL_PHY_MISC(port));
|
||||
val &= ~ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN;
|
||||
I915_WRITE(ICL_PHY_MISC(port), val);
|
||||
|
||||
cnl_set_procmon_ref_values(dev_priv, port);
|
||||
|
||||
val = I915_READ(ICL_PORT_COMP_DW0(port));
|
||||
val |= COMP_INIT;
|
||||
I915_WRITE(ICL_PORT_COMP_DW0(port), val);
|
||||
|
||||
val = I915_READ(ICL_PORT_CL_DW5(port));
|
||||
val |= CL_POWER_DOWN_ENABLE;
|
||||
I915_WRITE(ICL_PORT_CL_DW5(port), val);
|
||||
}
|
||||
}
|
||||
|
||||
void icl_combo_phys_uninit(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
enum port port;
|
||||
|
||||
for_each_combo_port_reverse(dev_priv, port) {
|
||||
u32 val;
|
||||
|
||||
if (!icl_combo_phy_verify_state(dev_priv, port))
|
||||
DRM_WARN("Port %c combo PHY HW state changed unexpectedly\n",
|
||||
port_name(port));
|
||||
|
||||
val = I915_READ(ICL_PHY_MISC(port));
|
||||
val |= ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN;
|
||||
I915_WRITE(ICL_PHY_MISC(port), val);
|
||||
|
||||
val = I915_READ(ICL_PORT_COMP_DW0(port));
|
||||
val &= ~COMP_INIT;
|
||||
I915_WRITE(ICL_PORT_COMP_DW0(port), val);
|
||||
}
|
||||
}
|
@@ -25,11 +25,140 @@
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drmP.h>
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
int intel_connector_init(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_connector_state *conn_state;
|
||||
|
||||
/*
|
||||
* Allocate enough memory to hold intel_digital_connector_state,
|
||||
* This might be a few bytes too many, but for connectors that don't
|
||||
* need it we'll free the state and allocate a smaller one on the first
|
||||
* successful commit anyway.
|
||||
*/
|
||||
conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
|
||||
if (!conn_state)
|
||||
return -ENOMEM;
|
||||
|
||||
__drm_atomic_helper_connector_reset(&connector->base,
|
||||
&conn_state->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct intel_connector *intel_connector_alloc(void)
|
||||
{
|
||||
struct intel_connector *connector;
|
||||
|
||||
connector = kzalloc(sizeof(*connector), GFP_KERNEL);
|
||||
if (!connector)
|
||||
return NULL;
|
||||
|
||||
if (intel_connector_init(connector) < 0) {
|
||||
kfree(connector);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return connector;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the bits allocated by intel_connector_alloc.
|
||||
* This should only be used after intel_connector_alloc has returned
|
||||
* successfully, and before drm_connector_init returns successfully.
|
||||
* Otherwise the destroy callbacks for the connector and the state should
|
||||
* take care of proper cleanup/free (see intel_connector_destroy).
|
||||
*/
|
||||
void intel_connector_free(struct intel_connector *connector)
|
||||
{
|
||||
kfree(to_intel_digital_connector_state(connector->base.state));
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
/*
|
||||
* Connector type independent destroy hook for drm_connector_funcs.
|
||||
*/
|
||||
void intel_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
|
||||
kfree(intel_connector->detect_edid);
|
||||
|
||||
if (!IS_ERR_OR_NULL(intel_connector->edid))
|
||||
kfree(intel_connector->edid);
|
||||
|
||||
intel_panel_fini(&intel_connector->panel);
|
||||
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
int intel_connector_register(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
int ret;
|
||||
|
||||
ret = intel_backlight_device_register(intel_connector);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (i915_inject_load_failure()) {
|
||||
ret = -EFAULT;
|
||||
goto err_backlight;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_backlight:
|
||||
intel_backlight_device_unregister(intel_connector);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void intel_connector_unregister(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
|
||||
intel_backlight_device_unregister(intel_connector);
|
||||
}
|
||||
|
||||
void intel_connector_attach_encoder(struct intel_connector *connector,
|
||||
struct intel_encoder *encoder)
|
||||
{
|
||||
connector->encoder = encoder;
|
||||
drm_connector_attach_encoder(&connector->base, &encoder->base);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple connector->get_hw_state implementation for encoders that support only
|
||||
* one connector and no cloning and hence the encoder state determines the state
|
||||
* of the connector.
|
||||
*/
|
||||
bool intel_connector_get_hw_state(struct intel_connector *connector)
|
||||
{
|
||||
enum pipe pipe = 0;
|
||||
struct intel_encoder *encoder = connector->encoder;
|
||||
|
||||
return encoder->get_hw_state(encoder, &pipe);
|
||||
}
|
||||
|
||||
enum pipe intel_connector_get_pipe(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
|
||||
|
||||
if (!connector->base.state->crtc)
|
||||
return INVALID_PIPE;
|
||||
|
||||
return to_intel_crtc(connector->base.state->crtc)->pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_connector_update_modes - update connector from edid
|
||||
* @connector: DRM connector device to use
|
@@ -354,6 +354,7 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return false;
|
||||
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -368,6 +369,7 @@ static bool pch_crt_compute_config(struct intel_encoder *encoder,
|
||||
return false;
|
||||
|
||||
pipe_config->has_pch_encoder = true;
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -389,6 +391,7 @@ static bool hsw_crt_compute_config(struct intel_encoder *encoder,
|
||||
return false;
|
||||
|
||||
pipe_config->has_pch_encoder = true;
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
|
||||
/* LPT FDI RX only supports 8bpc. */
|
||||
if (HAS_PCH_LPT(dev_priv)) {
|
||||
@@ -849,12 +852,6 @@ out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void intel_crt_destroy(struct drm_connector *connector)
|
||||
{
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
static int intel_crt_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
@@ -909,7 +906,7 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = {
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.late_register = intel_connector_register,
|
||||
.early_unregister = intel_connector_unregister,
|
||||
.destroy = intel_crt_destroy,
|
||||
.destroy = intel_connector_destroy,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
};
|
||||
|
@@ -34,34 +34,38 @@
|
||||
* low-power state and comes back to normal.
|
||||
*/
|
||||
|
||||
#define I915_CSR_ICL "i915/icl_dmc_ver1_07.bin"
|
||||
MODULE_FIRMWARE(I915_CSR_ICL);
|
||||
#define GEN12_CSR_MAX_FW_SIZE ICL_CSR_MAX_FW_SIZE
|
||||
|
||||
#define ICL_CSR_PATH "i915/icl_dmc_ver1_07.bin"
|
||||
#define ICL_CSR_VERSION_REQUIRED CSR_VERSION(1, 7)
|
||||
|
||||
#define I915_CSR_GLK "i915/glk_dmc_ver1_04.bin"
|
||||
MODULE_FIRMWARE(I915_CSR_GLK);
|
||||
#define GLK_CSR_VERSION_REQUIRED CSR_VERSION(1, 4)
|
||||
|
||||
#define I915_CSR_CNL "i915/cnl_dmc_ver1_07.bin"
|
||||
MODULE_FIRMWARE(I915_CSR_CNL);
|
||||
#define CNL_CSR_VERSION_REQUIRED CSR_VERSION(1, 7)
|
||||
|
||||
#define I915_CSR_KBL "i915/kbl_dmc_ver1_04.bin"
|
||||
MODULE_FIRMWARE(I915_CSR_KBL);
|
||||
#define KBL_CSR_VERSION_REQUIRED CSR_VERSION(1, 4)
|
||||
|
||||
#define I915_CSR_SKL "i915/skl_dmc_ver1_27.bin"
|
||||
MODULE_FIRMWARE(I915_CSR_SKL);
|
||||
#define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 27)
|
||||
|
||||
#define I915_CSR_BXT "i915/bxt_dmc_ver1_07.bin"
|
||||
MODULE_FIRMWARE(I915_CSR_BXT);
|
||||
#define BXT_CSR_VERSION_REQUIRED CSR_VERSION(1, 7)
|
||||
|
||||
|
||||
#define BXT_CSR_MAX_FW_SIZE 0x3000
|
||||
#define GLK_CSR_MAX_FW_SIZE 0x4000
|
||||
#define ICL_CSR_MAX_FW_SIZE 0x6000
|
||||
MODULE_FIRMWARE(ICL_CSR_PATH);
|
||||
|
||||
#define CNL_CSR_PATH "i915/cnl_dmc_ver1_07.bin"
|
||||
#define CNL_CSR_VERSION_REQUIRED CSR_VERSION(1, 7)
|
||||
#define CNL_CSR_MAX_FW_SIZE GLK_CSR_MAX_FW_SIZE
|
||||
MODULE_FIRMWARE(CNL_CSR_PATH);
|
||||
|
||||
#define GLK_CSR_PATH "i915/glk_dmc_ver1_04.bin"
|
||||
#define GLK_CSR_VERSION_REQUIRED CSR_VERSION(1, 4)
|
||||
#define GLK_CSR_MAX_FW_SIZE 0x4000
|
||||
MODULE_FIRMWARE(GLK_CSR_PATH);
|
||||
|
||||
#define KBL_CSR_PATH "i915/kbl_dmc_ver1_04.bin"
|
||||
#define KBL_CSR_VERSION_REQUIRED CSR_VERSION(1, 4)
|
||||
#define KBL_CSR_MAX_FW_SIZE BXT_CSR_MAX_FW_SIZE
|
||||
MODULE_FIRMWARE(KBL_CSR_PATH);
|
||||
|
||||
#define SKL_CSR_PATH "i915/skl_dmc_ver1_27.bin"
|
||||
#define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 27)
|
||||
#define SKL_CSR_MAX_FW_SIZE BXT_CSR_MAX_FW_SIZE
|
||||
MODULE_FIRMWARE(SKL_CSR_PATH);
|
||||
|
||||
#define BXT_CSR_PATH "i915/bxt_dmc_ver1_07.bin"
|
||||
#define BXT_CSR_VERSION_REQUIRED CSR_VERSION(1, 7)
|
||||
#define BXT_CSR_MAX_FW_SIZE 0x3000
|
||||
MODULE_FIRMWARE(BXT_CSR_PATH);
|
||||
|
||||
#define CSR_DEFAULT_FW_OFFSET 0xFFFFFFFF
|
||||
|
||||
struct intel_css_header {
|
||||
@@ -190,6 +194,12 @@ static const struct stepping_info bxt_stepping_info[] = {
|
||||
{'B', '0'}, {'B', '1'}, {'B', '2'}
|
||||
};
|
||||
|
||||
static const struct stepping_info icl_stepping_info[] = {
|
||||
{'A', '0'}, {'A', '1'}, {'A', '2'},
|
||||
{'B', '0'}, {'B', '2'},
|
||||
{'C', '0'}
|
||||
};
|
||||
|
||||
static const struct stepping_info no_stepping_info = { '*', '*' };
|
||||
|
||||
static const struct stepping_info *
|
||||
@@ -198,7 +208,10 @@ intel_get_stepping_info(struct drm_i915_private *dev_priv)
|
||||
const struct stepping_info *si;
|
||||
unsigned int size;
|
||||
|
||||
if (IS_SKYLAKE(dev_priv)) {
|
||||
if (IS_ICELAKE(dev_priv)) {
|
||||
size = ARRAY_SIZE(icl_stepping_info);
|
||||
si = icl_stepping_info;
|
||||
} else if (IS_SKYLAKE(dev_priv)) {
|
||||
size = ARRAY_SIZE(skl_stepping_info);
|
||||
si = skl_stepping_info;
|
||||
} else if (IS_BROXTON(dev_priv)) {
|
||||
@@ -285,10 +298,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||
struct intel_csr *csr = &dev_priv->csr;
|
||||
const struct stepping_info *si = intel_get_stepping_info(dev_priv);
|
||||
uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
|
||||
uint32_t max_fw_size = 0;
|
||||
uint32_t i;
|
||||
uint32_t *dmc_payload;
|
||||
uint32_t required_version;
|
||||
|
||||
if (!fw)
|
||||
return NULL;
|
||||
@@ -303,38 +314,19 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
csr->version = css_header->version;
|
||||
|
||||
if (csr->fw_path == i915_modparams.dmc_firmware_path) {
|
||||
/* Bypass version check for firmware override. */
|
||||
required_version = csr->version;
|
||||
} else if (IS_ICELAKE(dev_priv)) {
|
||||
required_version = ICL_CSR_VERSION_REQUIRED;
|
||||
} else if (IS_CANNONLAKE(dev_priv)) {
|
||||
required_version = CNL_CSR_VERSION_REQUIRED;
|
||||
} else if (IS_GEMINILAKE(dev_priv)) {
|
||||
required_version = GLK_CSR_VERSION_REQUIRED;
|
||||
} else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) {
|
||||
required_version = KBL_CSR_VERSION_REQUIRED;
|
||||
} else if (IS_SKYLAKE(dev_priv)) {
|
||||
required_version = SKL_CSR_VERSION_REQUIRED;
|
||||
} else if (IS_BROXTON(dev_priv)) {
|
||||
required_version = BXT_CSR_VERSION_REQUIRED;
|
||||
} else {
|
||||
MISSING_CASE(INTEL_REVID(dev_priv));
|
||||
required_version = 0;
|
||||
}
|
||||
|
||||
if (csr->version != required_version) {
|
||||
if (csr->required_version &&
|
||||
css_header->version != csr->required_version) {
|
||||
DRM_INFO("Refusing to load DMC firmware v%u.%u,"
|
||||
" please use v%u.%u\n",
|
||||
CSR_VERSION_MAJOR(csr->version),
|
||||
CSR_VERSION_MINOR(csr->version),
|
||||
CSR_VERSION_MAJOR(required_version),
|
||||
CSR_VERSION_MINOR(required_version));
|
||||
CSR_VERSION_MAJOR(css_header->version),
|
||||
CSR_VERSION_MINOR(css_header->version),
|
||||
CSR_VERSION_MAJOR(csr->required_version),
|
||||
CSR_VERSION_MINOR(csr->required_version));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
csr->version = css_header->version;
|
||||
|
||||
readcount += sizeof(struct intel_css_header);
|
||||
|
||||
/* Extract Package Header information*/
|
||||
@@ -402,15 +394,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||
|
||||
/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
|
||||
nbytes = dmc_header->fw_size * 4;
|
||||
if (INTEL_GEN(dev_priv) >= 11)
|
||||
max_fw_size = ICL_CSR_MAX_FW_SIZE;
|
||||
else if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
|
||||
max_fw_size = GLK_CSR_MAX_FW_SIZE;
|
||||
else if (IS_GEN9(dev_priv))
|
||||
max_fw_size = BXT_CSR_MAX_FW_SIZE;
|
||||
else
|
||||
MISSING_CASE(INTEL_REVID(dev_priv));
|
||||
if (nbytes > max_fw_size) {
|
||||
if (nbytes > csr->max_fw_size) {
|
||||
DRM_ERROR("DMC FW too big (%u bytes)\n", nbytes);
|
||||
return NULL;
|
||||
}
|
||||
@@ -475,27 +459,57 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
|
||||
if (!HAS_CSR(dev_priv))
|
||||
return;
|
||||
|
||||
if (i915_modparams.dmc_firmware_path)
|
||||
csr->fw_path = i915_modparams.dmc_firmware_path;
|
||||
else if (IS_ICELAKE(dev_priv))
|
||||
csr->fw_path = I915_CSR_ICL;
|
||||
else if (IS_CANNONLAKE(dev_priv))
|
||||
csr->fw_path = I915_CSR_CNL;
|
||||
else if (IS_GEMINILAKE(dev_priv))
|
||||
csr->fw_path = I915_CSR_GLK;
|
||||
else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv))
|
||||
csr->fw_path = I915_CSR_KBL;
|
||||
else if (IS_SKYLAKE(dev_priv))
|
||||
csr->fw_path = I915_CSR_SKL;
|
||||
else if (IS_BROXTON(dev_priv))
|
||||
csr->fw_path = I915_CSR_BXT;
|
||||
|
||||
/*
|
||||
* Obtain a runtime pm reference, until CSR is loaded,
|
||||
* to avoid entering runtime-suspend.
|
||||
* Obtain a runtime pm reference, until CSR is loaded, to avoid entering
|
||||
* runtime-suspend.
|
||||
*
|
||||
* On error, we return with the rpm wakeref held to prevent runtime
|
||||
* suspend as runtime suspend *requires* a working CSR for whatever
|
||||
* reason.
|
||||
*/
|
||||
intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 12) {
|
||||
/* Allow to load fw via parameter using the last known size */
|
||||
csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE;
|
||||
} else if (IS_ICELAKE(dev_priv)) {
|
||||
csr->fw_path = ICL_CSR_PATH;
|
||||
csr->required_version = ICL_CSR_VERSION_REQUIRED;
|
||||
csr->max_fw_size = ICL_CSR_MAX_FW_SIZE;
|
||||
} else if (IS_CANNONLAKE(dev_priv)) {
|
||||
csr->fw_path = CNL_CSR_PATH;
|
||||
csr->required_version = CNL_CSR_VERSION_REQUIRED;
|
||||
csr->max_fw_size = CNL_CSR_MAX_FW_SIZE;
|
||||
} else if (IS_GEMINILAKE(dev_priv)) {
|
||||
csr->fw_path = GLK_CSR_PATH;
|
||||
csr->required_version = GLK_CSR_VERSION_REQUIRED;
|
||||
csr->max_fw_size = GLK_CSR_MAX_FW_SIZE;
|
||||
} else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) {
|
||||
csr->fw_path = KBL_CSR_PATH;
|
||||
csr->required_version = KBL_CSR_VERSION_REQUIRED;
|
||||
csr->max_fw_size = KBL_CSR_MAX_FW_SIZE;
|
||||
} else if (IS_SKYLAKE(dev_priv)) {
|
||||
csr->fw_path = SKL_CSR_PATH;
|
||||
csr->required_version = SKL_CSR_VERSION_REQUIRED;
|
||||
csr->max_fw_size = SKL_CSR_MAX_FW_SIZE;
|
||||
} else if (IS_BROXTON(dev_priv)) {
|
||||
csr->fw_path = BXT_CSR_PATH;
|
||||
csr->required_version = BXT_CSR_VERSION_REQUIRED;
|
||||
csr->max_fw_size = BXT_CSR_MAX_FW_SIZE;
|
||||
}
|
||||
|
||||
if (i915_modparams.dmc_firmware_path) {
|
||||
if (strlen(i915_modparams.dmc_firmware_path) == 0) {
|
||||
csr->fw_path = NULL;
|
||||
DRM_INFO("Disabling CSR firmware and runtime PM\n");
|
||||
return;
|
||||
}
|
||||
|
||||
csr->fw_path = i915_modparams.dmc_firmware_path;
|
||||
/* Bypass version check for firmware override. */
|
||||
csr->required_version = 0;
|
||||
}
|
||||
|
||||
if (csr->fw_path == NULL) {
|
||||
DRM_DEBUG_KMS("No known CSR firmware for platform, disabling runtime PM\n");
|
||||
WARN_ON(!IS_ALPHA_SUPPORT(INTEL_INFO(dev_priv)));
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -77,6 +77,10 @@ void intel_device_info_dump_flags(const struct intel_device_info *info,
|
||||
#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->name));
|
||||
DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG);
|
||||
#undef PRINT_FLAG
|
||||
|
||||
#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->display.name));
|
||||
DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG);
|
||||
#undef PRINT_FLAG
|
||||
}
|
||||
|
||||
static void sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
|
||||
@@ -744,27 +748,30 @@ void intel_device_info_runtime_init(struct intel_device_info *info)
|
||||
if (INTEL_GEN(dev_priv) >= 10) {
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
info->num_scalers[pipe] = 2;
|
||||
} else if (INTEL_GEN(dev_priv) == 9) {
|
||||
} else if (IS_GEN9(dev_priv)) {
|
||||
info->num_scalers[PIPE_A] = 2;
|
||||
info->num_scalers[PIPE_B] = 2;
|
||||
info->num_scalers[PIPE_C] = 1;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(I915_NUM_ENGINES >
|
||||
sizeof(intel_ring_mask_t) * BITS_PER_BYTE);
|
||||
BUILD_BUG_ON(I915_NUM_ENGINES > BITS_PER_TYPE(intel_ring_mask_t));
|
||||
|
||||
/*
|
||||
* Skylake and Broxton currently don't expose the topmost plane as its
|
||||
* use is exclusive with the legacy cursor and we only want to expose
|
||||
* one of those, not both. Until we can safely expose the topmost plane
|
||||
* as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported,
|
||||
* we don't expose the topmost plane at all to prevent ABI breakage
|
||||
* down the line.
|
||||
*/
|
||||
if (IS_GEN10(dev_priv) || IS_GEMINILAKE(dev_priv))
|
||||
if (IS_GEN11(dev_priv))
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
info->num_sprites[pipe] = 6;
|
||||
else if (IS_GEN10(dev_priv) || IS_GEMINILAKE(dev_priv))
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
info->num_sprites[pipe] = 3;
|
||||
else if (IS_BROXTON(dev_priv)) {
|
||||
/*
|
||||
* Skylake and Broxton currently don't expose the topmost plane as its
|
||||
* use is exclusive with the legacy cursor and we only want to expose
|
||||
* one of those, not both. Until we can safely expose the topmost plane
|
||||
* as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported,
|
||||
* we don't expose the topmost plane at all to prevent ABI breakage
|
||||
* down the line.
|
||||
*/
|
||||
|
||||
info->num_sprites[PIPE_A] = 2;
|
||||
info->num_sprites[PIPE_B] = 2;
|
||||
info->num_sprites[PIPE_C] = 1;
|
||||
@@ -779,7 +786,7 @@ void intel_device_info_runtime_init(struct intel_device_info *info)
|
||||
if (i915_modparams.disable_display) {
|
||||
DRM_INFO("Display disabled (module parameter)\n");
|
||||
info->num_pipes = 0;
|
||||
} else if (info->num_pipes > 0 &&
|
||||
} else if (HAS_DISPLAY(dev_priv) &&
|
||||
(IS_GEN7(dev_priv) || IS_GEN8(dev_priv)) &&
|
||||
HAS_PCH_SPLIT(dev_priv)) {
|
||||
u32 fuse_strap = I915_READ(FUSE_STRAP);
|
||||
@@ -804,7 +811,7 @@ void intel_device_info_runtime_init(struct intel_device_info *info)
|
||||
DRM_INFO("PipeC fused off\n");
|
||||
info->num_pipes -= 1;
|
||||
}
|
||||
} else if (info->num_pipes > 0 && IS_GEN9(dev_priv)) {
|
||||
} else if (HAS_DISPLAY(dev_priv) && IS_GEN9(dev_priv)) {
|
||||
u32 dfsm = I915_READ(SKL_DFSM);
|
||||
u8 disabled_mask = 0;
|
||||
bool invalid;
|
||||
@@ -844,13 +851,18 @@ void intel_device_info_runtime_init(struct intel_device_info *info)
|
||||
cherryview_sseu_info_init(dev_priv);
|
||||
else if (IS_BROADWELL(dev_priv))
|
||||
broadwell_sseu_info_init(dev_priv);
|
||||
else if (INTEL_GEN(dev_priv) == 9)
|
||||
else if (IS_GEN9(dev_priv))
|
||||
gen9_sseu_info_init(dev_priv);
|
||||
else if (INTEL_GEN(dev_priv) == 10)
|
||||
else if (IS_GEN10(dev_priv))
|
||||
gen10_sseu_info_init(dev_priv);
|
||||
else if (INTEL_GEN(dev_priv) >= 11)
|
||||
gen11_sseu_info_init(dev_priv);
|
||||
|
||||
if (IS_GEN6(dev_priv) && intel_vtd_active()) {
|
||||
DRM_INFO("Disabling ppGTT for VT-d support\n");
|
||||
info->ppgtt = INTEL_PPGTT_NONE;
|
||||
}
|
||||
|
||||
/* Initialize command stream timestamp frequency */
|
||||
info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv);
|
||||
}
|
||||
@@ -872,40 +884,37 @@ void intel_driver_caps_print(const struct intel_driver_caps *caps,
|
||||
void intel_device_info_init_mmio(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_device_info *info = mkwrite_device_info(dev_priv);
|
||||
u8 vdbox_disable, vebox_disable;
|
||||
u32 media_fuse;
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
if (INTEL_GEN(dev_priv) < 11)
|
||||
return;
|
||||
|
||||
media_fuse = I915_READ(GEN11_GT_VEBOX_VDBOX_DISABLE);
|
||||
media_fuse = ~I915_READ(GEN11_GT_VEBOX_VDBOX_DISABLE);
|
||||
|
||||
vdbox_disable = media_fuse & GEN11_GT_VDBOX_DISABLE_MASK;
|
||||
vebox_disable = (media_fuse & GEN11_GT_VEBOX_DISABLE_MASK) >>
|
||||
GEN11_GT_VEBOX_DISABLE_SHIFT;
|
||||
info->vdbox_enable = media_fuse & GEN11_GT_VDBOX_DISABLE_MASK;
|
||||
info->vebox_enable = (media_fuse & GEN11_GT_VEBOX_DISABLE_MASK) >>
|
||||
GEN11_GT_VEBOX_DISABLE_SHIFT;
|
||||
|
||||
DRM_DEBUG_DRIVER("vdbox disable: %04x\n", vdbox_disable);
|
||||
DRM_DEBUG_DRIVER("vdbox enable: %04x\n", info->vdbox_enable);
|
||||
for (i = 0; i < I915_MAX_VCS; i++) {
|
||||
if (!HAS_ENGINE(dev_priv, _VCS(i)))
|
||||
continue;
|
||||
|
||||
if (!(BIT(i) & vdbox_disable))
|
||||
continue;
|
||||
|
||||
info->ring_mask &= ~ENGINE_MASK(_VCS(i));
|
||||
DRM_DEBUG_DRIVER("vcs%u fused off\n", i);
|
||||
if (!(BIT(i) & info->vdbox_enable)) {
|
||||
info->ring_mask &= ~ENGINE_MASK(_VCS(i));
|
||||
DRM_DEBUG_DRIVER("vcs%u fused off\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("vebox disable: %04x\n", vebox_disable);
|
||||
DRM_DEBUG_DRIVER("vebox enable: %04x\n", info->vebox_enable);
|
||||
for (i = 0; i < I915_MAX_VECS; i++) {
|
||||
if (!HAS_ENGINE(dev_priv, _VECS(i)))
|
||||
continue;
|
||||
|
||||
if (!(BIT(i) & vebox_disable))
|
||||
continue;
|
||||
|
||||
info->ring_mask &= ~ENGINE_MASK(_VECS(i));
|
||||
DRM_DEBUG_DRIVER("vecs%u fused off\n", i);
|
||||
if (!(BIT(i) & info->vebox_enable)) {
|
||||
info->ring_mask &= ~ENGINE_MASK(_VECS(i));
|
||||
DRM_DEBUG_DRIVER("vecs%u fused off\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#ifndef _INTEL_DEVICE_INFO_H_
|
||||
#define _INTEL_DEVICE_INFO_H_
|
||||
|
||||
#include <uapi/drm/i915_drm.h>
|
||||
|
||||
#include "intel_display.h"
|
||||
|
||||
struct drm_printer;
|
||||
@@ -74,51 +76,58 @@ enum intel_platform {
|
||||
INTEL_MAX_PLATFORMS
|
||||
};
|
||||
|
||||
enum intel_ppgtt {
|
||||
INTEL_PPGTT_NONE = I915_GEM_PPGTT_NONE,
|
||||
INTEL_PPGTT_ALIASING = I915_GEM_PPGTT_ALIASING,
|
||||
INTEL_PPGTT_FULL = I915_GEM_PPGTT_FULL,
|
||||
INTEL_PPGTT_FULL_4LVL,
|
||||
};
|
||||
|
||||
#define DEV_INFO_FOR_EACH_FLAG(func) \
|
||||
func(is_mobile); \
|
||||
func(is_lp); \
|
||||
func(is_alpha_support); \
|
||||
/* Keep has_* in alphabetical order */ \
|
||||
func(has_64bit_reloc); \
|
||||
func(has_aliasing_ppgtt); \
|
||||
func(has_csr); \
|
||||
func(has_ddi); \
|
||||
func(has_dp_mst); \
|
||||
func(has_reset_engine); \
|
||||
func(has_fbc); \
|
||||
func(has_fpga_dbg); \
|
||||
func(has_full_ppgtt); \
|
||||
func(has_full_48bit_ppgtt); \
|
||||
func(has_gmch_display); \
|
||||
func(has_guc); \
|
||||
func(has_guc_ct); \
|
||||
func(has_hotplug); \
|
||||
func(has_l3_dpf); \
|
||||
func(has_llc); \
|
||||
func(has_logical_ring_contexts); \
|
||||
func(has_logical_ring_elsq); \
|
||||
func(has_logical_ring_preemption); \
|
||||
func(has_overlay); \
|
||||
func(has_pooled_eu); \
|
||||
func(has_psr); \
|
||||
func(has_rc6); \
|
||||
func(has_rc6p); \
|
||||
func(has_runtime_pm); \
|
||||
func(has_snoop); \
|
||||
func(has_coherent_ggtt); \
|
||||
func(unfenced_needs_alignment); \
|
||||
func(hws_needs_physical);
|
||||
|
||||
#define DEV_INFO_DISPLAY_FOR_EACH_FLAG(func) \
|
||||
/* Keep in alphabetical order */ \
|
||||
func(cursor_needs_physical); \
|
||||
func(hws_needs_physical); \
|
||||
func(has_csr); \
|
||||
func(has_ddi); \
|
||||
func(has_dp_mst); \
|
||||
func(has_fbc); \
|
||||
func(has_gmch_display); \
|
||||
func(has_hotplug); \
|
||||
func(has_ipc); \
|
||||
func(has_overlay); \
|
||||
func(has_psr); \
|
||||
func(overlay_needs_physical); \
|
||||
func(supports_tv); \
|
||||
func(has_ipc);
|
||||
func(supports_tv);
|
||||
|
||||
#define GEN_MAX_SLICES (6) /* CNL upper bound */
|
||||
#define GEN_MAX_SUBSLICES (8) /* ICL upper bound */
|
||||
|
||||
struct sseu_dev_info {
|
||||
u8 slice_mask;
|
||||
u8 subslice_mask[GEN_MAX_SUBSLICES];
|
||||
u8 subslice_mask[GEN_MAX_SLICES];
|
||||
u16 eu_total;
|
||||
u8 eu_per_subslice;
|
||||
u8 min_eu_in_pool;
|
||||
@@ -154,6 +163,7 @@ struct intel_device_info {
|
||||
enum intel_platform platform;
|
||||
u32 platform_mask;
|
||||
|
||||
enum intel_ppgtt ppgtt;
|
||||
unsigned int page_sizes; /* page sizes supported by the HW */
|
||||
|
||||
u32 display_mmio_offset;
|
||||
@@ -165,12 +175,18 @@ struct intel_device_info {
|
||||
#define DEFINE_FLAG(name) u8 name:1
|
||||
DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG);
|
||||
#undef DEFINE_FLAG
|
||||
|
||||
struct {
|
||||
#define DEFINE_FLAG(name) u8 name:1
|
||||
DEV_INFO_DISPLAY_FOR_EACH_FLAG(DEFINE_FLAG);
|
||||
#undef DEFINE_FLAG
|
||||
} display;
|
||||
|
||||
u16 ddb_size; /* in blocks */
|
||||
|
||||
/* Register offsets for the various display pipes and transcoders */
|
||||
int pipe_offsets[I915_MAX_TRANSCODERS];
|
||||
int trans_offsets[I915_MAX_TRANSCODERS];
|
||||
int palette_offsets[I915_MAX_PIPES];
|
||||
int cursor_offsets[I915_MAX_PIPES];
|
||||
|
||||
/* Slice/subslice/EU info */
|
||||
@@ -178,6 +194,10 @@ struct intel_device_info {
|
||||
|
||||
u32 cs_timestamp_frequency_khz;
|
||||
|
||||
/* Enabled (not fused off) media engine bitmasks. */
|
||||
u8 vdbox_enable;
|
||||
u8 vebox_enable;
|
||||
|
||||
struct color_luts {
|
||||
u16 degamma_lut_size;
|
||||
u16 gamma_lut_size;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,11 @@ enum i915_gpio {
|
||||
GPIOM,
|
||||
};
|
||||
|
||||
/*
|
||||
* Keep the pipe enum values fixed: the code assumes that PIPE_A=0, the
|
||||
* rest have consecutive values and match the enum values of transcoders
|
||||
* with a 1:1 transcoder -> pipe mapping.
|
||||
*/
|
||||
enum pipe {
|
||||
INVALID_PIPE = -1,
|
||||
|
||||
@@ -57,12 +62,25 @@ enum pipe {
|
||||
#define pipe_name(p) ((p) + 'A')
|
||||
|
||||
enum transcoder {
|
||||
TRANSCODER_A = 0,
|
||||
TRANSCODER_B,
|
||||
TRANSCODER_C,
|
||||
/*
|
||||
* The following transcoders have a 1:1 transcoder -> pipe mapping,
|
||||
* keep their values fixed: the code assumes that TRANSCODER_A=0, the
|
||||
* rest have consecutive values and match the enum values of the pipes
|
||||
* they map to.
|
||||
*/
|
||||
TRANSCODER_A = PIPE_A,
|
||||
TRANSCODER_B = PIPE_B,
|
||||
TRANSCODER_C = PIPE_C,
|
||||
|
||||
/*
|
||||
* The following transcoders can map to any pipe, their enum value
|
||||
* doesn't need to stay fixed.
|
||||
*/
|
||||
TRANSCODER_EDP,
|
||||
TRANSCODER_DSI_A,
|
||||
TRANSCODER_DSI_C,
|
||||
TRANSCODER_DSI_0,
|
||||
TRANSCODER_DSI_1,
|
||||
TRANSCODER_DSI_A = TRANSCODER_DSI_0, /* legacy DSI */
|
||||
TRANSCODER_DSI_C = TRANSCODER_DSI_1, /* legacy DSI */
|
||||
|
||||
I915_MAX_TRANSCODERS
|
||||
};
|
||||
@@ -120,6 +138,9 @@ enum plane_id {
|
||||
PLANE_SPRITE0,
|
||||
PLANE_SPRITE1,
|
||||
PLANE_SPRITE2,
|
||||
PLANE_SPRITE3,
|
||||
PLANE_SPRITE4,
|
||||
PLANE_SPRITE5,
|
||||
PLANE_CURSOR,
|
||||
|
||||
I915_MAX_PLANES,
|
||||
@@ -221,6 +242,7 @@ enum intel_display_power_domain {
|
||||
POWER_DOMAIN_TRANSCODER_B,
|
||||
POWER_DOMAIN_TRANSCODER_C,
|
||||
POWER_DOMAIN_TRANSCODER_EDP,
|
||||
POWER_DOMAIN_TRANSCODER_EDP_VDSC,
|
||||
POWER_DOMAIN_TRANSCODER_DSI_A,
|
||||
POWER_DOMAIN_TRANSCODER_DSI_C,
|
||||
POWER_DOMAIN_PORT_DDI_A_LANES,
|
||||
@@ -363,7 +385,7 @@ struct intel_link_m_n {
|
||||
(__dev_priv)->power_domains.power_well_count; \
|
||||
(__power_well)++)
|
||||
|
||||
#define for_each_power_well_rev(__dev_priv, __power_well) \
|
||||
#define for_each_power_well_reverse(__dev_priv, __power_well) \
|
||||
for ((__power_well) = (__dev_priv)->power_domains.power_wells + \
|
||||
(__dev_priv)->power_domains.power_well_count - 1; \
|
||||
(__power_well) - (__dev_priv)->power_domains.power_wells >= 0; \
|
||||
@@ -373,10 +395,18 @@ struct intel_link_m_n {
|
||||
for_each_power_well(__dev_priv, __power_well) \
|
||||
for_each_if((__power_well)->desc->domains & (__domain_mask))
|
||||
|
||||
#define for_each_power_domain_well_rev(__dev_priv, __power_well, __domain_mask) \
|
||||
for_each_power_well_rev(__dev_priv, __power_well) \
|
||||
#define for_each_power_domain_well_reverse(__dev_priv, __power_well, __domain_mask) \
|
||||
for_each_power_well_reverse(__dev_priv, __power_well) \
|
||||
for_each_if((__power_well)->desc->domains & (__domain_mask))
|
||||
|
||||
#define for_each_old_intel_plane_in_state(__state, plane, old_plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
|
||||
((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
|
||||
(old_plane_state) = to_intel_plane_state((__state)->base.planes[__i].old_state), 1); \
|
||||
(__i)++) \
|
||||
for_each_if(plane)
|
||||
|
||||
#define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
|
||||
@@ -402,10 +432,18 @@ struct intel_link_m_n {
|
||||
(__i)++) \
|
||||
for_each_if(plane)
|
||||
|
||||
void intel_link_compute_m_n(int bpp, int nlanes,
|
||||
#define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_crtc && \
|
||||
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
|
||||
(old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
|
||||
(new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
|
||||
(__i)++) \
|
||||
for_each_if(crtc)
|
||||
|
||||
void intel_link_compute_m_n(u16 bpp, int nlanes,
|
||||
int pixel_clock, int link_clock,
|
||||
struct intel_link_m_n *m_n,
|
||||
bool constant_n);
|
||||
|
||||
bool is_ccs_modifier(u64 modifier);
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return false;
|
||||
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
pipe_config->has_pch_encoder = false;
|
||||
bpp = 24;
|
||||
if (intel_dp->compliance.test_data.bpc) {
|
||||
@@ -208,12 +209,25 @@ static void intel_mst_pre_pll_enable_dp(struct intel_encoder *encoder,
|
||||
struct intel_digital_port *intel_dig_port = intel_mst->primary;
|
||||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||
|
||||
if (intel_dp->active_mst_links == 0 &&
|
||||
intel_dig_port->base.pre_pll_enable)
|
||||
if (intel_dp->active_mst_links == 0)
|
||||
intel_dig_port->base.pre_pll_enable(&intel_dig_port->base,
|
||||
pipe_config, NULL);
|
||||
}
|
||||
|
||||
static void intel_mst_post_pll_disable_dp(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *old_crtc_state,
|
||||
const struct drm_connector_state *old_conn_state)
|
||||
{
|
||||
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
|
||||
struct intel_digital_port *intel_dig_port = intel_mst->primary;
|
||||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||
|
||||
if (intel_dp->active_mst_links == 0)
|
||||
intel_dig_port->base.post_pll_disable(&intel_dig_port->base,
|
||||
old_crtc_state,
|
||||
old_conn_state);
|
||||
}
|
||||
|
||||
static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config,
|
||||
const struct drm_connector_state *conn_state)
|
||||
@@ -335,24 +349,12 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force)
|
||||
intel_connector->port);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_mst_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
|
||||
if (!IS_ERR_OR_NULL(intel_connector->edid))
|
||||
kfree(intel_connector->edid);
|
||||
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
|
||||
.detect = intel_dp_mst_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.late_register = intel_connector_register,
|
||||
.early_unregister = intel_connector_unregister,
|
||||
.destroy = intel_dp_mst_connector_destroy,
|
||||
.destroy = intel_connector_destroy,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
};
|
||||
@@ -560,6 +562,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum
|
||||
intel_encoder->disable = intel_mst_disable_dp;
|
||||
intel_encoder->post_disable = intel_mst_post_disable_dp;
|
||||
intel_encoder->pre_pll_enable = intel_mst_pre_pll_enable_dp;
|
||||
intel_encoder->post_pll_disable = intel_mst_post_pll_disable_dp;
|
||||
intel_encoder->pre_enable = intel_mst_pre_enable_dp;
|
||||
intel_encoder->enable = intel_mst_enable_dp;
|
||||
intel_encoder->get_hw_state = intel_dp_mst_enc_get_hw_state;
|
||||
|
@@ -748,7 +748,7 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder,
|
||||
val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
|
||||
|
||||
if (crtc->config->lane_count > 2) {
|
||||
if (crtc_state->lane_count > 2) {
|
||||
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
|
||||
if (reset)
|
||||
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
|
||||
@@ -765,7 +765,7 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder,
|
||||
val |= DPIO_PCS_CLK_SOFT_RESET;
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
|
||||
|
||||
if (crtc->config->lane_count > 2) {
|
||||
if (crtc_state->lane_count > 2) {
|
||||
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
|
||||
val |= CHV_PCS_REQ_SOFTRESET_EN;
|
||||
if (reset)
|
||||
|
@@ -126,16 +126,16 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
|
||||
|
||||
/**
|
||||
* intel_prepare_shared_dpll - call a dpll's prepare hook
|
||||
* @crtc: CRTC which has a shared dpll
|
||||
* @crtc_state: CRTC, and its state, which has a shared dpll
|
||||
*
|
||||
* This calls the PLL's prepare hook if it has one and if the PLL is not
|
||||
* already enabled. The prepare hook is platform specific.
|
||||
*/
|
||||
void intel_prepare_shared_dpll(struct intel_crtc *crtc)
|
||||
void intel_prepare_shared_dpll(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_shared_dpll *pll = crtc->config->shared_dpll;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
|
||||
|
||||
if (WARN_ON(pll == NULL))
|
||||
return;
|
||||
@@ -154,15 +154,15 @@ void intel_prepare_shared_dpll(struct intel_crtc *crtc)
|
||||
|
||||
/**
|
||||
* intel_enable_shared_dpll - enable a CRTC's shared DPLL
|
||||
* @crtc: CRTC which has a shared DPLL
|
||||
* @crtc_state: CRTC, and its state, which has a shared DPLL
|
||||
*
|
||||
* Enable the shared DPLL used by @crtc.
|
||||
*/
|
||||
void intel_enable_shared_dpll(struct intel_crtc *crtc)
|
||||
void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_shared_dpll *pll = crtc->config->shared_dpll;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
|
||||
unsigned int crtc_mask = drm_crtc_mask(&crtc->base);
|
||||
unsigned int old_mask;
|
||||
|
||||
@@ -199,14 +199,15 @@ out:
|
||||
|
||||
/**
|
||||
* intel_disable_shared_dpll - disable a CRTC's shared DPLL
|
||||
* @crtc: CRTC which has a shared DPLL
|
||||
* @crtc_state: CRTC, and its state, which has a shared DPLL
|
||||
*
|
||||
* Disable the shared DPLL used by @crtc.
|
||||
*/
|
||||
void intel_disable_shared_dpll(struct intel_crtc *crtc)
|
||||
void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
struct intel_shared_dpll *pll = crtc->config->shared_dpll;
|
||||
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
|
||||
unsigned int crtc_mask = drm_crtc_mask(&crtc->base);
|
||||
|
||||
/* PCH only available on ILK+ */
|
||||
@@ -409,14 +410,6 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll)
|
||||
{
|
||||
const enum intel_dpll_id id = pll->info->id;
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
/* Make sure no transcoder isn't still depending on us. */
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
if (crtc->config->shared_dpll == pll)
|
||||
assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
|
||||
}
|
||||
|
||||
I915_WRITE(PCH_DPLL(id), 0);
|
||||
POSTING_READ(PCH_DPLL(id));
|
||||
@@ -2530,7 +2523,8 @@ static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
|
||||
|
||||
if (intel_port_is_tc(dev_priv, encoder->port))
|
||||
ret = icl_calc_tbt_pll(dev_priv, clock, &pll_params);
|
||||
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
|
||||
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) ||
|
||||
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
|
||||
ret = cnl_ddi_calculate_wrpll(clock, dev_priv, &pll_params);
|
||||
else
|
||||
ret = icl_calc_dp_combo_pll(dev_priv, clock, &pll_params);
|
||||
@@ -2628,11 +2622,16 @@ static enum port icl_mg_pll_id_to_port(enum intel_dpll_id id)
|
||||
return id - DPLL_ID_ICL_MGPLL1 + PORT_C;
|
||||
}
|
||||
|
||||
static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
|
||||
enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
|
||||
{
|
||||
return port - PORT_C + DPLL_ID_ICL_MGPLL1;
|
||||
}
|
||||
|
||||
bool intel_dpll_is_combophy(enum intel_dpll_id id)
|
||||
{
|
||||
return id == DPLL_ID_ICL_DPLL0 || id == DPLL_ID_ICL_DPLL1;
|
||||
}
|
||||
|
||||
static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
|
||||
uint32_t *target_dco_khz,
|
||||
struct intel_dpll_hw_state *state)
|
||||
@@ -2874,8 +2873,8 @@ static struct intel_shared_dpll *
|
||||
icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
|
||||
struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port =
|
||||
enc_to_dig_port(&encoder->base);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_digital_port *intel_dig_port;
|
||||
struct intel_shared_dpll *pll;
|
||||
struct intel_dpll_hw_state pll_state = {};
|
||||
enum port port = encoder->port;
|
||||
@@ -2883,18 +2882,21 @@ icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
|
||||
int clock = crtc_state->port_clock;
|
||||
bool ret;
|
||||
|
||||
switch (port) {
|
||||
case PORT_A:
|
||||
case PORT_B:
|
||||
if (intel_port_is_combophy(dev_priv, port)) {
|
||||
min = DPLL_ID_ICL_DPLL0;
|
||||
max = DPLL_ID_ICL_DPLL1;
|
||||
ret = icl_calc_dpll_state(crtc_state, encoder, clock,
|
||||
&pll_state);
|
||||
break;
|
||||
case PORT_C:
|
||||
case PORT_D:
|
||||
case PORT_E:
|
||||
case PORT_F:
|
||||
} else if (intel_port_is_tc(dev_priv, port)) {
|
||||
if (encoder->type == INTEL_OUTPUT_DP_MST) {
|
||||
struct intel_dp_mst_encoder *mst_encoder;
|
||||
|
||||
mst_encoder = enc_to_mst(&encoder->base);
|
||||
intel_dig_port = mst_encoder->primary;
|
||||
} else {
|
||||
intel_dig_port = enc_to_dig_port(&encoder->base);
|
||||
}
|
||||
|
||||
if (intel_dig_port->tc_type == TC_PORT_TBT) {
|
||||
min = DPLL_ID_ICL_TBTPLL;
|
||||
max = min;
|
||||
@@ -2906,8 +2908,7 @@ icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
|
||||
ret = icl_calc_mg_pll_state(crtc_state, encoder, clock,
|
||||
&pll_state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
MISSING_CASE(port);
|
||||
return NULL;
|
||||
}
|
||||
@@ -2932,21 +2933,16 @@ icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
|
||||
|
||||
static i915_reg_t icl_pll_id_to_enable_reg(enum intel_dpll_id id)
|
||||
{
|
||||
switch (id) {
|
||||
default:
|
||||
MISSING_CASE(id);
|
||||
/* fall through */
|
||||
case DPLL_ID_ICL_DPLL0:
|
||||
case DPLL_ID_ICL_DPLL1:
|
||||
if (intel_dpll_is_combophy(id))
|
||||
return CNL_DPLL_ENABLE(id);
|
||||
case DPLL_ID_ICL_TBTPLL:
|
||||
else if (id == DPLL_ID_ICL_TBTPLL)
|
||||
return TBT_PLL_ENABLE;
|
||||
case DPLL_ID_ICL_MGPLL1:
|
||||
case DPLL_ID_ICL_MGPLL2:
|
||||
case DPLL_ID_ICL_MGPLL3:
|
||||
case DPLL_ID_ICL_MGPLL4:
|
||||
else
|
||||
/*
|
||||
* TODO: Make MG_PLL macros use
|
||||
* tc port id instead of port id
|
||||
*/
|
||||
return MG_PLL_ENABLE(icl_mg_pll_id_to_port(id));
|
||||
}
|
||||
}
|
||||
|
||||
static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
@@ -2965,17 +2961,11 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
if (!(val & PLL_ENABLE))
|
||||
goto out;
|
||||
|
||||
switch (id) {
|
||||
case DPLL_ID_ICL_DPLL0:
|
||||
case DPLL_ID_ICL_DPLL1:
|
||||
case DPLL_ID_ICL_TBTPLL:
|
||||
if (intel_dpll_is_combophy(id) ||
|
||||
id == DPLL_ID_ICL_TBTPLL) {
|
||||
hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id));
|
||||
hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id));
|
||||
break;
|
||||
case DPLL_ID_ICL_MGPLL1:
|
||||
case DPLL_ID_ICL_MGPLL2:
|
||||
case DPLL_ID_ICL_MGPLL3:
|
||||
case DPLL_ID_ICL_MGPLL4:
|
||||
} else {
|
||||
port = icl_mg_pll_id_to_port(id);
|
||||
hw_state->mg_refclkin_ctl = I915_READ(MG_REFCLKIN_CTL(port));
|
||||
hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK;
|
||||
@@ -3013,9 +3003,6 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
|
||||
hw_state->mg_pll_tdc_coldst_bias &= hw_state->mg_pll_tdc_coldst_bias_mask;
|
||||
hw_state->mg_pll_bias &= hw_state->mg_pll_bias_mask;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(id);
|
||||
}
|
||||
|
||||
ret = true;
|
||||
@@ -3104,21 +3091,10 @@ static void icl_pll_enable(struct drm_i915_private *dev_priv,
|
||||
PLL_POWER_STATE, 1))
|
||||
DRM_ERROR("PLL %d Power not enabled\n", id);
|
||||
|
||||
switch (id) {
|
||||
case DPLL_ID_ICL_DPLL0:
|
||||
case DPLL_ID_ICL_DPLL1:
|
||||
case DPLL_ID_ICL_TBTPLL:
|
||||
if (intel_dpll_is_combophy(id) || id == DPLL_ID_ICL_TBTPLL)
|
||||
icl_dpll_write(dev_priv, pll);
|
||||
break;
|
||||
case DPLL_ID_ICL_MGPLL1:
|
||||
case DPLL_ID_ICL_MGPLL2:
|
||||
case DPLL_ID_ICL_MGPLL3:
|
||||
case DPLL_ID_ICL_MGPLL4:
|
||||
else
|
||||
icl_mg_pll_write(dev_priv, pll);
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(id);
|
||||
}
|
||||
|
||||
/*
|
||||
* DVFS pre sequence would be here, but in our driver the cdclk code
|
||||
|
@@ -334,9 +334,9 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
|
||||
void intel_release_shared_dpll(struct intel_shared_dpll *dpll,
|
||||
struct intel_crtc *crtc,
|
||||
struct drm_atomic_state *state);
|
||||
void intel_prepare_shared_dpll(struct intel_crtc *crtc);
|
||||
void intel_enable_shared_dpll(struct intel_crtc *crtc);
|
||||
void intel_disable_shared_dpll(struct intel_crtc *crtc);
|
||||
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 drm_atomic_state *state);
|
||||
void intel_shared_dpll_init(struct drm_device *dev);
|
||||
|
||||
@@ -345,5 +345,7 @@ void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
int icl_calc_dp_combo_pll_link(struct drm_i915_private *dev_priv,
|
||||
uint32_t pll_id);
|
||||
int cnl_hdmi_pll_ref_clock(struct drm_i915_private *dev_priv);
|
||||
enum intel_dpll_id icl_port_to_mg_pll_id(enum port port);
|
||||
bool intel_dpll_is_combophy(enum intel_dpll_id id);
|
||||
|
||||
#endif /* _INTEL_DPLL_MGR_H_ */
|
||||
|
@@ -381,6 +381,15 @@ struct intel_hdcp_shim {
|
||||
bool *hdcp_capable);
|
||||
};
|
||||
|
||||
struct intel_hdcp {
|
||||
const struct intel_hdcp_shim *shim;
|
||||
/* Mutex for hdcp state of the connector */
|
||||
struct mutex mutex;
|
||||
u64 value;
|
||||
struct delayed_work check_work;
|
||||
struct work_struct prop_work;
|
||||
};
|
||||
|
||||
struct intel_connector {
|
||||
struct drm_connector base;
|
||||
/*
|
||||
@@ -413,11 +422,7 @@ struct intel_connector {
|
||||
/* Work struct to schedule a uevent on link train failure */
|
||||
struct work_struct modeset_retry_work;
|
||||
|
||||
const struct intel_hdcp_shim *hdcp_shim;
|
||||
struct mutex hdcp_mutex;
|
||||
uint64_t hdcp_value; /* protected by hdcp_mutex */
|
||||
struct delayed_work hdcp_check_work;
|
||||
struct work_struct hdcp_prop_work;
|
||||
struct intel_hdcp hdcp;
|
||||
};
|
||||
|
||||
struct intel_digital_connector_state {
|
||||
@@ -539,6 +544,26 @@ struct intel_plane_state {
|
||||
*/
|
||||
int scaler_id;
|
||||
|
||||
/*
|
||||
* linked_plane:
|
||||
*
|
||||
* ICL planar formats require 2 planes that are updated as pairs.
|
||||
* This member is used to make sure the other plane is also updated
|
||||
* when required, and for update_slave() to find the correct
|
||||
* plane_state to pass as argument.
|
||||
*/
|
||||
struct intel_plane *linked_plane;
|
||||
|
||||
/*
|
||||
* slave:
|
||||
* If set don't update use the linked plane's state for updating
|
||||
* this plane during atomic commit with the update_slave() callback.
|
||||
*
|
||||
* It's also used by the watermark code to ignore wm calculations on
|
||||
* this plane. They're calculated by the linked plane's wm code.
|
||||
*/
|
||||
u32 slave;
|
||||
|
||||
struct drm_intel_sprite_colorkey ckey;
|
||||
};
|
||||
|
||||
@@ -681,6 +706,8 @@ struct intel_crtc_wm_state {
|
||||
/* gen9+ only needs 1-step wm programming */
|
||||
struct skl_pipe_wm optimal;
|
||||
struct skl_ddb_entry ddb;
|
||||
struct skl_ddb_entry plane_ddb_y[I915_MAX_PLANES];
|
||||
struct skl_ddb_entry plane_ddb_uv[I915_MAX_PLANES];
|
||||
} skl;
|
||||
|
||||
struct {
|
||||
@@ -713,6 +740,13 @@ struct intel_crtc_wm_state {
|
||||
bool need_postvbl_update;
|
||||
};
|
||||
|
||||
enum intel_output_format {
|
||||
INTEL_OUTPUT_FORMAT_INVALID,
|
||||
INTEL_OUTPUT_FORMAT_RGB,
|
||||
INTEL_OUTPUT_FORMAT_YCBCR420,
|
||||
INTEL_OUTPUT_FORMAT_YCBCR444,
|
||||
};
|
||||
|
||||
struct intel_crtc_state {
|
||||
struct drm_crtc_state base;
|
||||
|
||||
@@ -894,14 +928,32 @@ struct intel_crtc_state {
|
||||
u8 active_planes;
|
||||
u8 nv12_planes;
|
||||
|
||||
/* bitmask of planes that will be updated during the commit */
|
||||
u8 update_planes;
|
||||
|
||||
/* HDMI scrambling status */
|
||||
bool hdmi_scrambling;
|
||||
|
||||
/* HDMI High TMDS char rate ratio */
|
||||
bool hdmi_high_tmds_clock_ratio;
|
||||
|
||||
/* output format is YCBCR 4:2:0 */
|
||||
bool ycbcr420;
|
||||
/* Output format RGB/YCBCR etc */
|
||||
enum intel_output_format output_format;
|
||||
|
||||
/* Output down scaling is done in LSPCON device */
|
||||
bool lspcon_downsampling;
|
||||
|
||||
/* Display Stream compression state */
|
||||
struct {
|
||||
bool compression_enable;
|
||||
bool dsc_split;
|
||||
u16 compressed_bpp;
|
||||
u8 slice_count;
|
||||
} dsc_params;
|
||||
struct drm_dsc_config dp_dsc_cfg;
|
||||
|
||||
/* Forward Error correction State */
|
||||
bool fec_enable;
|
||||
};
|
||||
|
||||
struct intel_crtc {
|
||||
@@ -974,8 +1026,11 @@ struct intel_plane {
|
||||
void (*update_plane)(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
void (*update_slave)(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
void (*disable_plane)(struct intel_plane *plane,
|
||||
struct intel_crtc *crtc);
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe);
|
||||
int (*check_plane)(struct intel_crtc_state *crtc_state,
|
||||
struct intel_plane_state *plane_state);
|
||||
@@ -1071,13 +1126,13 @@ struct intel_dp {
|
||||
bool link_mst;
|
||||
bool link_trained;
|
||||
bool has_audio;
|
||||
bool detect_done;
|
||||
bool reset_link_params;
|
||||
enum aux_ch aux_ch;
|
||||
uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
|
||||
uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
|
||||
uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
|
||||
uint8_t edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
|
||||
u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
|
||||
u8 fec_capable;
|
||||
/* source rates */
|
||||
int num_source_rates;
|
||||
const int *source_rates;
|
||||
@@ -1095,7 +1150,6 @@ struct intel_dp {
|
||||
/* sink or branch descriptor */
|
||||
struct drm_dp_desc desc;
|
||||
struct drm_dp_aux aux;
|
||||
enum intel_display_power_domain aux_power_domain;
|
||||
uint8_t train_set[4];
|
||||
int panel_power_up_delay;
|
||||
int panel_power_down_delay;
|
||||
@@ -1157,9 +1211,15 @@ struct intel_dp {
|
||||
struct intel_dp_compliance compliance;
|
||||
};
|
||||
|
||||
enum lspcon_vendor {
|
||||
LSPCON_VENDOR_MCA,
|
||||
LSPCON_VENDOR_PARADE
|
||||
};
|
||||
|
||||
struct intel_lspcon {
|
||||
bool active;
|
||||
enum drm_lspcon_mode mode;
|
||||
enum lspcon_vendor vendor;
|
||||
};
|
||||
|
||||
struct intel_digital_port {
|
||||
@@ -1171,18 +1231,20 @@ struct intel_digital_port {
|
||||
enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
|
||||
bool release_cl2_override;
|
||||
uint8_t max_lanes;
|
||||
/* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */
|
||||
enum aux_ch aux_ch;
|
||||
enum intel_display_power_domain ddi_io_power_domain;
|
||||
enum tc_port_type tc_type;
|
||||
|
||||
void (*write_infoframe)(struct drm_encoder *encoder,
|
||||
void (*write_infoframe)(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
unsigned int type,
|
||||
const void *frame, ssize_t len);
|
||||
void (*set_infoframes)(struct drm_encoder *encoder,
|
||||
void (*set_infoframes)(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
bool (*infoframe_enabled)(struct drm_encoder *encoder,
|
||||
bool (*infoframe_enabled)(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
};
|
||||
|
||||
@@ -1282,6 +1344,12 @@ enc_to_dig_port(struct drm_encoder *encoder)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct intel_digital_port *
|
||||
conn_to_dig_port(struct intel_connector *connector)
|
||||
{
|
||||
return enc_to_dig_port(&intel_attached_encoder(&connector->base)->base);
|
||||
}
|
||||
|
||||
static inline struct intel_dp_mst_encoder *
|
||||
enc_to_mst(struct drm_encoder *encoder)
|
||||
{
|
||||
@@ -1307,6 +1375,12 @@ static inline bool intel_encoder_is_dp(struct intel_encoder *encoder)
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct intel_lspcon *
|
||||
enc_to_intel_lspcon(struct drm_encoder *encoder)
|
||||
{
|
||||
return &enc_to_dig_port(encoder)->lspcon;
|
||||
}
|
||||
|
||||
static inline struct intel_digital_port *
|
||||
dp_to_dig_port(struct intel_dp *intel_dp)
|
||||
{
|
||||
@@ -1331,6 +1405,27 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
|
||||
return container_of(intel_hdmi, struct intel_digital_port, hdmi);
|
||||
}
|
||||
|
||||
static inline struct intel_plane_state *
|
||||
intel_atomic_get_plane_state(struct intel_atomic_state *state,
|
||||
struct intel_plane *plane)
|
||||
{
|
||||
struct drm_plane_state *ret =
|
||||
drm_atomic_get_plane_state(&state->base, &plane->base);
|
||||
|
||||
if (IS_ERR(ret))
|
||||
return ERR_CAST(ret);
|
||||
|
||||
return to_intel_plane_state(ret);
|
||||
}
|
||||
|
||||
static inline struct intel_plane_state *
|
||||
intel_atomic_get_old_plane_state(struct intel_atomic_state *state,
|
||||
struct intel_plane *plane)
|
||||
{
|
||||
return to_intel_plane_state(drm_atomic_get_old_plane_state(&state->base,
|
||||
&plane->base));
|
||||
}
|
||||
|
||||
static inline struct intel_plane_state *
|
||||
intel_atomic_get_new_plane_state(struct intel_atomic_state *state,
|
||||
struct intel_plane *plane)
|
||||
@@ -1439,12 +1534,9 @@ u8 intel_ddi_dp_pre_emphasis_max(struct intel_encoder *encoder,
|
||||
u8 voltage_swing);
|
||||
int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
|
||||
bool enable);
|
||||
void icl_map_plls_to_ports(struct drm_crtc *crtc,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct drm_atomic_state *old_state);
|
||||
void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct drm_atomic_state *old_state);
|
||||
void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder);
|
||||
int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
|
||||
enum intel_dpll_id pll_id);
|
||||
|
||||
unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
|
||||
int color_plane, unsigned int height);
|
||||
@@ -1489,7 +1581,6 @@ void intel_dump_cdclk_state(const struct intel_cdclk_state *cdclk_state,
|
||||
void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc);
|
||||
void intel_update_rawclk(struct drm_i915_private *dev_priv);
|
||||
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
|
||||
int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
|
||||
const char *name, u32 reg, int ref_freq);
|
||||
@@ -1510,20 +1601,12 @@ void intel_mark_idle(struct drm_i915_private *dev_priv);
|
||||
int intel_display_suspend(struct drm_device *dev);
|
||||
void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
|
||||
void intel_encoder_destroy(struct drm_encoder *encoder);
|
||||
int intel_connector_init(struct intel_connector *);
|
||||
struct intel_connector *intel_connector_alloc(void);
|
||||
void intel_connector_free(struct intel_connector *connector);
|
||||
bool intel_connector_get_hw_state(struct intel_connector *connector);
|
||||
void intel_connector_attach_encoder(struct intel_connector *connector,
|
||||
struct intel_encoder *encoder);
|
||||
struct drm_display_mode *
|
||||
intel_encoder_current_mode(struct intel_encoder *encoder);
|
||||
bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port);
|
||||
bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port);
|
||||
enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
|
||||
enum port port);
|
||||
|
||||
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector);
|
||||
int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
|
||||
@@ -1629,9 +1712,11 @@ void bxt_enable_dc9(struct drm_i915_private *dev_priv);
|
||||
void bxt_disable_dc9(struct drm_i915_private *dev_priv);
|
||||
void gen9_enable_dc5(struct drm_i915_private *dev_priv);
|
||||
unsigned int skl_cdclk_get_vco(unsigned int freq);
|
||||
void skl_enable_dc6(struct drm_i915_private *dev_priv);
|
||||
void intel_dp_get_m_n(struct intel_crtc *crtc,
|
||||
struct intel_crtc_state *pipe_config);
|
||||
void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
|
||||
void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state,
|
||||
enum link_m_n_set m_n);
|
||||
int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
|
||||
bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
|
||||
struct dpll *best_clock);
|
||||
@@ -1642,6 +1727,8 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state);
|
||||
void hsw_enable_ips(const struct intel_crtc_state *crtc_state);
|
||||
void hsw_disable_ips(const struct intel_crtc_state *crtc_state);
|
||||
enum intel_display_power_domain intel_port_to_power_domain(enum port port);
|
||||
enum intel_display_power_domain
|
||||
intel_aux_power_domain(struct intel_digital_port *dig_port);
|
||||
void intel_mode_from_pipe_config(struct drm_display_mode *mode,
|
||||
struct intel_crtc_state *pipe_config);
|
||||
void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
|
||||
@@ -1671,6 +1758,24 @@ unsigned int i9xx_plane_max_stride(struct intel_plane *plane,
|
||||
u32 pixel_format, u64 modifier,
|
||||
unsigned int rotation);
|
||||
|
||||
/* intel_connector.c */
|
||||
int intel_connector_init(struct intel_connector *connector);
|
||||
struct intel_connector *intel_connector_alloc(void);
|
||||
void intel_connector_free(struct intel_connector *connector);
|
||||
void intel_connector_destroy(struct drm_connector *connector);
|
||||
int intel_connector_register(struct drm_connector *connector);
|
||||
void intel_connector_unregister(struct drm_connector *connector);
|
||||
void intel_connector_attach_encoder(struct intel_connector *connector,
|
||||
struct intel_encoder *encoder);
|
||||
bool intel_connector_get_hw_state(struct intel_connector *connector);
|
||||
enum pipe intel_connector_get_pipe(struct intel_connector *connector);
|
||||
int intel_connector_update_modes(struct drm_connector *connector,
|
||||
struct edid *edid);
|
||||
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
|
||||
void intel_attach_force_audio_property(struct drm_connector *connector);
|
||||
void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
|
||||
void intel_attach_aspect_ratio_property(struct drm_connector *connector);
|
||||
|
||||
/* intel_csr.c */
|
||||
void intel_csr_ucode_init(struct drm_i915_private *);
|
||||
void intel_csr_load_program(struct drm_i915_private *);
|
||||
@@ -1696,6 +1801,9 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp);
|
||||
int intel_dp_retrain_link(struct intel_encoder *encoder,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
|
||||
void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
bool enable);
|
||||
void intel_dp_encoder_reset(struct drm_encoder *encoder);
|
||||
void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder);
|
||||
void intel_dp_encoder_destroy(struct drm_encoder *encoder);
|
||||
@@ -1729,9 +1837,6 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits);
|
||||
void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits);
|
||||
void icl_program_mg_dp_mode(struct intel_dp *intel_dp);
|
||||
void icl_enable_phy_clock_gating(struct intel_digital_port *dig_port);
|
||||
void icl_disable_phy_clock_gating(struct intel_digital_port *dig_port);
|
||||
|
||||
void
|
||||
intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
|
||||
@@ -1749,6 +1854,16 @@ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp);
|
||||
bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp);
|
||||
bool
|
||||
intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]);
|
||||
uint16_t intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count,
|
||||
int mode_clock, int mode_hdisplay);
|
||||
uint8_t intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock,
|
||||
int mode_hdisplay);
|
||||
|
||||
/* intel_vdsc.c */
|
||||
int intel_dp_compute_dsc_params(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *pipe_config);
|
||||
enum intel_display_power_domain
|
||||
intel_dsc_power_domain(const struct intel_crtc_state *crtc_state);
|
||||
|
||||
static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
|
||||
{
|
||||
@@ -1769,6 +1884,9 @@ void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
|
||||
/* vlv_dsi.c */
|
||||
void vlv_dsi_init(struct drm_i915_private *dev_priv);
|
||||
|
||||
/* icl_dsi.c */
|
||||
void icl_dsi_init(struct drm_i915_private *dev_priv);
|
||||
|
||||
/* intel_dsi_dcs_backlight.c */
|
||||
int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector);
|
||||
|
||||
@@ -1859,7 +1977,6 @@ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder,
|
||||
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
|
||||
void intel_infoframe_init(struct intel_digital_port *intel_dig_port);
|
||||
|
||||
|
||||
/* intel_lvds.c */
|
||||
bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv,
|
||||
i915_reg_t lvds_reg, enum pipe *pipe);
|
||||
@@ -1867,19 +1984,9 @@ void intel_lvds_init(struct drm_i915_private *dev_priv);
|
||||
struct intel_encoder *intel_get_lvds_encoder(struct drm_device *dev);
|
||||
bool intel_is_dual_link_lvds(struct drm_device *dev);
|
||||
|
||||
|
||||
/* intel_modes.c */
|
||||
int intel_connector_update_modes(struct drm_connector *connector,
|
||||
struct edid *edid);
|
||||
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
|
||||
void intel_attach_force_audio_property(struct drm_connector *connector);
|
||||
void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
|
||||
void intel_attach_aspect_ratio_property(struct drm_connector *connector);
|
||||
|
||||
|
||||
/* intel_overlay.c */
|
||||
void intel_setup_overlay(struct drm_i915_private *dev_priv);
|
||||
void intel_cleanup_overlay(struct drm_i915_private *dev_priv);
|
||||
void intel_overlay_setup(struct drm_i915_private *dev_priv);
|
||||
void intel_overlay_cleanup(struct drm_i915_private *dev_priv);
|
||||
int intel_overlay_switch_off(struct intel_overlay *overlay);
|
||||
int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
@@ -1908,7 +2015,6 @@ int intel_panel_setup_backlight(struct drm_connector *connector,
|
||||
void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
void intel_panel_disable_backlight(const struct drm_connector_state *old_conn_state);
|
||||
void intel_panel_destroy_backlight(struct drm_connector *connector);
|
||||
extern struct drm_display_mode *intel_find_panel_downclock(
|
||||
struct drm_i915_private *dev_priv,
|
||||
struct drm_display_mode *fixed_mode,
|
||||
@@ -1937,6 +2043,7 @@ int intel_hdcp_enable(struct intel_connector *connector);
|
||||
int intel_hdcp_disable(struct intel_connector *connector);
|
||||
int intel_hdcp_check_link(struct intel_connector *connector);
|
||||
bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
|
||||
bool intel_hdcp_capable(struct intel_connector *connector);
|
||||
|
||||
/* intel_psr.c */
|
||||
#define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
|
||||
@@ -1962,12 +2069,18 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir);
|
||||
void intel_psr_short_pulse(struct intel_dp *intel_dp);
|
||||
int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state,
|
||||
u32 *out_value);
|
||||
bool intel_psr_enabled(struct intel_dp *intel_dp);
|
||||
|
||||
/* intel_quirks.c */
|
||||
void intel_init_quirks(struct drm_i915_private *dev_priv);
|
||||
|
||||
/* intel_runtime_pm.c */
|
||||
int intel_power_domains_init(struct drm_i915_private *);
|
||||
void intel_power_domains_cleanup(struct drm_i915_private *dev_priv);
|
||||
void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume);
|
||||
void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv);
|
||||
void icl_display_core_init(struct drm_i915_private *dev_priv, bool resume);
|
||||
void icl_display_core_uninit(struct drm_i915_private *dev_priv);
|
||||
void intel_power_domains_enable(struct drm_i915_private *dev_priv);
|
||||
void intel_power_domains_disable(struct drm_i915_private *dev_priv);
|
||||
|
||||
@@ -2091,6 +2204,9 @@ void g4x_wm_get_hw_state(struct drm_device *dev);
|
||||
void vlv_wm_get_hw_state(struct drm_device *dev);
|
||||
void ilk_wm_get_hw_state(struct drm_device *dev);
|
||||
void skl_wm_get_hw_state(struct drm_device *dev);
|
||||
void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
|
||||
struct skl_ddb_entry *ddb_y,
|
||||
struct skl_ddb_entry *ddb_uv);
|
||||
void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct skl_ddb_allocation *ddb /* out */);
|
||||
void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
|
||||
@@ -2102,10 +2218,13 @@ int intel_enable_sagv(struct drm_i915_private *dev_priv);
|
||||
int intel_disable_sagv(struct drm_i915_private *dev_priv);
|
||||
bool skl_wm_level_equals(const struct skl_wm_level *l1,
|
||||
const struct skl_wm_level *l2);
|
||||
bool skl_ddb_allocation_overlaps(struct drm_i915_private *dev_priv,
|
||||
const struct skl_ddb_entry **entries,
|
||||
const struct skl_ddb_entry *ddb,
|
||||
int ignore);
|
||||
bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb,
|
||||
const struct skl_ddb_entry entries[],
|
||||
int num_entries, int ignore_idx);
|
||||
void skl_write_plane_wm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void skl_write_cursor_wm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
bool ilk_disable_lp_wm(struct drm_device *dev);
|
||||
int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc,
|
||||
struct intel_crtc_state *cstate);
|
||||
@@ -2128,23 +2247,29 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state);
|
||||
void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state);
|
||||
void skl_update_plane(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
void skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc);
|
||||
bool skl_plane_get_hw_state(struct intel_plane *plane, enum pipe *pipe);
|
||||
bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, enum plane_id plane_id);
|
||||
bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, enum plane_id plane_id);
|
||||
unsigned int skl_plane_max_stride(struct intel_plane *plane,
|
||||
u32 pixel_format, u64 modifier,
|
||||
unsigned int rotation);
|
||||
int skl_plane_check(struct intel_crtc_state *crtc_state,
|
||||
struct intel_plane_state *plane_state);
|
||||
int intel_plane_check_stride(const struct intel_plane_state *plane_state);
|
||||
int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state);
|
||||
int chv_plane_check_rotation(const struct intel_plane_state *plane_state);
|
||||
struct intel_plane *
|
||||
skl_universal_plane_create(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, enum plane_id plane_id);
|
||||
|
||||
static inline bool icl_is_nv12_y_plane(enum plane_id id)
|
||||
{
|
||||
/* Don't need to do a gen check, these planes are only available on gen11 */
|
||||
if (id == PLANE_SPRITE4 || id == PLANE_SPRITE5)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool icl_is_hdr_plane(struct intel_plane *plane)
|
||||
{
|
||||
if (INTEL_GEN(to_i915(plane->base.dev)) < 11)
|
||||
return false;
|
||||
|
||||
return plane->id < PLANE_SPRITE2;
|
||||
}
|
||||
|
||||
/* intel_tv.c */
|
||||
void intel_tv_init(struct drm_i915_private *dev_priv);
|
||||
@@ -2186,11 +2311,16 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
|
||||
struct intel_crtc_state *crtc_state);
|
||||
|
||||
/* intel_atomic_plane.c */
|
||||
struct intel_plane_state *intel_create_plane_state(struct drm_plane *plane);
|
||||
struct intel_plane *intel_plane_alloc(void);
|
||||
void intel_plane_free(struct intel_plane *plane);
|
||||
struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
|
||||
void intel_plane_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state);
|
||||
extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
|
||||
void skl_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *old_plane_state,
|
||||
@@ -2206,6 +2336,18 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state);
|
||||
bool lspcon_init(struct intel_digital_port *intel_dig_port);
|
||||
void lspcon_resume(struct intel_lspcon *lspcon);
|
||||
void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
|
||||
void lspcon_write_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
unsigned int type,
|
||||
const void *buf, ssize_t len);
|
||||
void lspcon_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
bool lspcon_infoframe_enabled(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config);
|
||||
void lspcon_ycbcr420_config(struct drm_connector *connector,
|
||||
struct intel_crtc_state *crtc_state);
|
||||
|
||||
/* intel_pipe_crc.c */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
128
drivers/gpu/drm/i915/intel_dsi.c
Normal file
128
drivers/gpu/drm/i915/intel_dsi.c
Normal file
@@ -0,0 +1,128 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include "intel_dsi.h"
|
||||
|
||||
int intel_dsi_bitrate(const struct intel_dsi *intel_dsi)
|
||||
{
|
||||
int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
|
||||
|
||||
if (WARN_ON(bpp < 0))
|
||||
bpp = 16;
|
||||
|
||||
return intel_dsi->pclk * bpp / intel_dsi->lane_count;
|
||||
}
|
||||
|
||||
int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi)
|
||||
{
|
||||
switch (intel_dsi->escape_clk_div) {
|
||||
default:
|
||||
case 0:
|
||||
return 50;
|
||||
case 1:
|
||||
return 100;
|
||||
case 2:
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
|
||||
int intel_dsi_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (!intel_connector->panel.fixed_mode) {
|
||||
DRM_DEBUG_KMS("no fixed mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev,
|
||||
intel_connector->panel.fixed_mode);
|
||||
if (!mode) {
|
||||
DRM_DEBUG_KMS("drm_mode_duplicate failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
drm_mode_probed_add(connector, mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
|
||||
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
||||
if (fixed_mode) {
|
||||
if (mode->hdisplay > fixed_mode->hdisplay)
|
||||
return MODE_PANEL;
|
||||
if (mode->vdisplay > fixed_mode->vdisplay)
|
||||
return MODE_PANEL;
|
||||
if (fixed_mode->clock > max_dotclk)
|
||||
return MODE_CLOCK_HIGH;
|
||||
}
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
|
||||
const struct mipi_dsi_host_ops *funcs,
|
||||
enum port port)
|
||||
{
|
||||
struct intel_dsi_host *host;
|
||||
struct mipi_dsi_device *device;
|
||||
|
||||
host = kzalloc(sizeof(*host), GFP_KERNEL);
|
||||
if (!host)
|
||||
return NULL;
|
||||
|
||||
host->base.ops = funcs;
|
||||
host->intel_dsi = intel_dsi;
|
||||
host->port = port;
|
||||
|
||||
/*
|
||||
* We should call mipi_dsi_host_register(&host->base) here, but we don't
|
||||
* have a host->dev, and we don't have OF stuff either. So just use the
|
||||
* dsi framework as a library and hope for the best. Create the dsi
|
||||
* devices by ourselves here too. Need to be careful though, because we
|
||||
* don't initialize any of the driver model devices here.
|
||||
*/
|
||||
device = kzalloc(sizeof(*device), GFP_KERNEL);
|
||||
if (!device) {
|
||||
kfree(host);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
device->host = &host->base;
|
||||
host->device = device;
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
enum drm_panel_orientation
|
||||
intel_dsi_get_panel_orientation(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
enum drm_panel_orientation orientation;
|
||||
|
||||
orientation = dev_priv->vbt.dsi.orientation;
|
||||
if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
|
||||
return orientation;
|
||||
|
||||
orientation = dev_priv->vbt.orientation;
|
||||
if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
|
||||
return orientation;
|
||||
|
||||
return DRM_MODE_PANEL_ORIENTATION_NORMAL;
|
||||
}
|
@@ -81,14 +81,21 @@ struct intel_dsi {
|
||||
u16 dcs_backlight_ports;
|
||||
u16 dcs_cabc_ports;
|
||||
|
||||
/* RGB or BGR */
|
||||
bool bgr_enabled;
|
||||
|
||||
u8 pixel_overlap;
|
||||
u32 port_bits;
|
||||
u32 bw_timer;
|
||||
u32 dphy_reg;
|
||||
|
||||
/* data lanes dphy timing */
|
||||
u32 dphy_data_lane_reg;
|
||||
u32 video_frmt_cfg_bits;
|
||||
u16 lp_byte_clk;
|
||||
|
||||
/* timeouts in byte clocks */
|
||||
u16 hs_tx_timeout;
|
||||
u16 lp_rx_timeout;
|
||||
u16 turn_arnd_val;
|
||||
u16 rst_timer_val;
|
||||
@@ -129,9 +136,36 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
|
||||
return container_of(encoder, struct intel_dsi, base.base);
|
||||
}
|
||||
|
||||
static inline bool is_vid_mode(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
return intel_dsi->operation_mode == INTEL_DSI_VIDEO_MODE;
|
||||
}
|
||||
|
||||
static inline bool is_cmd_mode(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
return intel_dsi->operation_mode == INTEL_DSI_COMMAND_MODE;
|
||||
}
|
||||
|
||||
static inline u16 intel_dsi_encoder_ports(struct intel_encoder *encoder)
|
||||
{
|
||||
return enc_to_intel_dsi(&encoder->base)->ports;
|
||||
}
|
||||
|
||||
/* intel_dsi.c */
|
||||
int intel_dsi_bitrate(const struct intel_dsi *intel_dsi);
|
||||
int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi);
|
||||
enum drm_panel_orientation
|
||||
intel_dsi_get_panel_orientation(struct intel_connector *connector);
|
||||
|
||||
/* vlv_dsi.c */
|
||||
void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port);
|
||||
enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt);
|
||||
int intel_dsi_get_modes(struct drm_connector *connector);
|
||||
enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
|
||||
const struct mipi_dsi_host_ops *funcs,
|
||||
enum port port);
|
||||
|
||||
/* vlv_dsi_pll.c */
|
||||
int vlv_dsi_pll_compute(struct intel_encoder *encoder,
|
||||
@@ -158,5 +192,6 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id);
|
||||
int intel_dsi_vbt_get_modes(struct intel_dsi *intel_dsi);
|
||||
void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
|
||||
enum mipi_seq seq_id);
|
||||
void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec);
|
||||
|
||||
#endif /* _INTEL_DSI_H */
|
||||
|
@@ -103,6 +103,18 @@ static struct gpio_map vlv_gpio_table[] = {
|
||||
#define CHV_GPIO_PAD_CFG1(f, i) (0x4400 + (f) * 0x400 + (i) * 8 + 4)
|
||||
#define CHV_GPIO_CFGLOCK (1 << 31)
|
||||
|
||||
/* ICL DSI Display GPIO Pins */
|
||||
#define ICL_GPIO_DDSP_HPD_A 0
|
||||
#define ICL_GPIO_L_VDDEN_1 1
|
||||
#define ICL_GPIO_L_BKLTEN_1 2
|
||||
#define ICL_GPIO_DDPA_CTRLCLK_1 3
|
||||
#define ICL_GPIO_DDPA_CTRLDATA_1 4
|
||||
#define ICL_GPIO_DDSP_HPD_B 5
|
||||
#define ICL_GPIO_L_VDDEN_2 6
|
||||
#define ICL_GPIO_L_BKLTEN_2 7
|
||||
#define ICL_GPIO_DDPA_CTRLCLK_2 8
|
||||
#define ICL_GPIO_DDPA_CTRLDATA_2 9
|
||||
|
||||
static inline enum port intel_dsi_seq_port_to_port(u8 port)
|
||||
{
|
||||
return port ? PORT_C : PORT_A;
|
||||
@@ -111,6 +123,7 @@ static inline enum port intel_dsi_seq_port_to_port(u8 port)
|
||||
static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi,
|
||||
const u8 *data)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
|
||||
struct mipi_dsi_device *dsi_device;
|
||||
u8 type, flags, seq_port;
|
||||
u16 len;
|
||||
@@ -181,7 +194,8 @@ static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi,
|
||||
break;
|
||||
}
|
||||
|
||||
vlv_dsi_wait_for_fifo_empty(intel_dsi, port);
|
||||
if (!IS_ICELAKE(dev_priv))
|
||||
vlv_dsi_wait_for_fifo_empty(intel_dsi, port);
|
||||
|
||||
out:
|
||||
data += len;
|
||||
@@ -322,6 +336,12 @@ static void bxt_exec_gpio(struct drm_i915_private *dev_priv,
|
||||
gpiod_set_value(gpio_desc, value);
|
||||
}
|
||||
|
||||
static void icl_exec_gpio(struct drm_i915_private *dev_priv,
|
||||
u8 gpio_source, u8 gpio_index, bool value)
|
||||
{
|
||||
DRM_DEBUG_KMS("Skipping ICL GPIO element execution\n");
|
||||
}
|
||||
|
||||
static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
|
||||
{
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
@@ -345,7 +365,9 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
|
||||
/* pull up/down */
|
||||
value = *data++ & 1;
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv))
|
||||
if (IS_ICELAKE(dev_priv))
|
||||
icl_exec_gpio(dev_priv, gpio_source, gpio_index, value);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
vlv_exec_gpio(dev_priv, gpio_source, gpio_number, value);
|
||||
else if (IS_CHERRYVIEW(dev_priv))
|
||||
chv_exec_gpio(dev_priv, gpio_source, gpio_number, value);
|
||||
@@ -481,6 +503,17 @@ void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
|
||||
}
|
||||
}
|
||||
|
||||
void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
|
||||
|
||||
/* For v3 VBTs in vid-mode the delays are part of the VBT sequences */
|
||||
if (is_vid_mode(intel_dsi) && dev_priv->vbt.dsi.seq_version >= 3)
|
||||
return;
|
||||
|
||||
msleep(msec);
|
||||
}
|
||||
|
||||
int intel_dsi_vbt_get_modes(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
struct intel_connector *connector = intel_dsi->attached_connector;
|
||||
@@ -499,110 +532,125 @@ int intel_dsi_vbt_get_modes(struct intel_dsi *intel_dsi)
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
|
||||
#define ICL_PREPARE_CNT_MAX 0x7
|
||||
#define ICL_CLK_ZERO_CNT_MAX 0xf
|
||||
#define ICL_TRAIL_CNT_MAX 0x7
|
||||
#define ICL_TCLK_PRE_CNT_MAX 0x3
|
||||
#define ICL_TCLK_POST_CNT_MAX 0x7
|
||||
#define ICL_HS_ZERO_CNT_MAX 0xf
|
||||
#define ICL_EXIT_ZERO_CNT_MAX 0x7
|
||||
|
||||
static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
|
||||
struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps;
|
||||
struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode;
|
||||
u32 bpp;
|
||||
u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui;
|
||||
u32 tlpx_ns;
|
||||
u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
|
||||
u32 ths_prepare_ns, tclk_trail_ns;
|
||||
u32 hs_zero_cnt;
|
||||
u32 tclk_pre_cnt, tclk_post_cnt;
|
||||
|
||||
tlpx_ns = intel_dsi_tlpx_ns(intel_dsi);
|
||||
|
||||
tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
|
||||
ths_prepare_ns = max(mipi_config->ths_prepare,
|
||||
mipi_config->tclk_prepare);
|
||||
|
||||
/*
|
||||
* prepare cnt in escape clocks
|
||||
* this field represents a hexadecimal value with a precision
|
||||
* of 1.2 – i.e. the most significant bit is the integer
|
||||
* and the least significant 2 bits are fraction bits.
|
||||
* so, the field can represent a range of 0.25 to 1.75
|
||||
*/
|
||||
prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns);
|
||||
if (prepare_cnt > ICL_PREPARE_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("prepare_cnt out of range (%d)\n", prepare_cnt);
|
||||
prepare_cnt = ICL_PREPARE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* clk zero count in escape clocks */
|
||||
clk_zero_cnt = DIV_ROUND_UP(mipi_config->tclk_prepare_clkzero -
|
||||
ths_prepare_ns, tlpx_ns);
|
||||
if (clk_zero_cnt > ICL_CLK_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("clk_zero_cnt out of range (%d)\n", clk_zero_cnt);
|
||||
clk_zero_cnt = ICL_CLK_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* trail cnt in escape clocks*/
|
||||
trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns);
|
||||
if (trail_cnt > ICL_TRAIL_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("trail_cnt out of range (%d)\n", trail_cnt);
|
||||
trail_cnt = ICL_TRAIL_CNT_MAX;
|
||||
}
|
||||
|
||||
/* tclk pre count in escape clocks */
|
||||
tclk_pre_cnt = DIV_ROUND_UP(mipi_config->tclk_pre, tlpx_ns);
|
||||
if (tclk_pre_cnt > ICL_TCLK_PRE_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("tclk_pre_cnt out of range (%d)\n", tclk_pre_cnt);
|
||||
tclk_pre_cnt = ICL_TCLK_PRE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* tclk post count in escape clocks */
|
||||
tclk_post_cnt = DIV_ROUND_UP(mipi_config->tclk_post, tlpx_ns);
|
||||
if (tclk_post_cnt > ICL_TCLK_POST_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("tclk_post_cnt out of range (%d)\n", tclk_post_cnt);
|
||||
tclk_post_cnt = ICL_TCLK_POST_CNT_MAX;
|
||||
}
|
||||
|
||||
/* hs zero cnt in escape clocks */
|
||||
hs_zero_cnt = DIV_ROUND_UP(mipi_config->ths_prepare_hszero -
|
||||
ths_prepare_ns, tlpx_ns);
|
||||
if (hs_zero_cnt > ICL_HS_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("hs_zero_cnt out of range (%d)\n", hs_zero_cnt);
|
||||
hs_zero_cnt = ICL_HS_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* hs exit zero cnt in escape clocks */
|
||||
exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit, tlpx_ns);
|
||||
if (exit_zero_cnt > ICL_EXIT_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("exit_zero_cnt out of range (%d)\n", exit_zero_cnt);
|
||||
exit_zero_cnt = ICL_EXIT_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* clock lane dphy timings */
|
||||
intel_dsi->dphy_reg = (CLK_PREPARE_OVERRIDE |
|
||||
CLK_PREPARE(prepare_cnt) |
|
||||
CLK_ZERO_OVERRIDE |
|
||||
CLK_ZERO(clk_zero_cnt) |
|
||||
CLK_PRE_OVERRIDE |
|
||||
CLK_PRE(tclk_pre_cnt) |
|
||||
CLK_POST_OVERRIDE |
|
||||
CLK_POST(tclk_post_cnt) |
|
||||
CLK_TRAIL_OVERRIDE |
|
||||
CLK_TRAIL(trail_cnt));
|
||||
|
||||
/* data lanes dphy timings */
|
||||
intel_dsi->dphy_data_lane_reg = (HS_PREPARE_OVERRIDE |
|
||||
HS_PREPARE(prepare_cnt) |
|
||||
HS_ZERO_OVERRIDE |
|
||||
HS_ZERO(hs_zero_cnt) |
|
||||
HS_TRAIL_OVERRIDE |
|
||||
HS_TRAIL(trail_cnt) |
|
||||
HS_EXIT_OVERRIDE |
|
||||
HS_EXIT(exit_zero_cnt));
|
||||
}
|
||||
|
||||
static void vlv_dphy_param_init(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
|
||||
u32 tlpx_ns, extra_byte_count, tlpx_ui;
|
||||
u32 ui_num, ui_den;
|
||||
u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
|
||||
u32 ths_prepare_ns, tclk_trail_ns;
|
||||
u32 tclk_prepare_clkzero, ths_prepare_hszero;
|
||||
u32 lp_to_hs_switch, hs_to_lp_switch;
|
||||
u32 pclk, computed_ddr;
|
||||
u32 mul;
|
||||
u16 burst_mode_ratio;
|
||||
enum port port;
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
|
||||
intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
|
||||
intel_dsi->lane_count = mipi_config->lane_cnt + 1;
|
||||
intel_dsi->pixel_format =
|
||||
pixel_format_from_register_bits(
|
||||
mipi_config->videomode_color_format << 7);
|
||||
bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
|
||||
|
||||
intel_dsi->dual_link = mipi_config->dual_link;
|
||||
intel_dsi->pixel_overlap = mipi_config->pixel_overlap;
|
||||
intel_dsi->operation_mode = mipi_config->is_cmd_mode;
|
||||
intel_dsi->video_mode_format = mipi_config->video_transfer_mode;
|
||||
intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
|
||||
intel_dsi->lp_rx_timeout = mipi_config->lp_rx_timeout;
|
||||
intel_dsi->turn_arnd_val = mipi_config->turn_around_timeout;
|
||||
intel_dsi->rst_timer_val = mipi_config->device_reset_timer;
|
||||
intel_dsi->init_count = mipi_config->master_init_timer;
|
||||
intel_dsi->bw_timer = mipi_config->dbi_bw_timer;
|
||||
intel_dsi->video_frmt_cfg_bits =
|
||||
mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
|
||||
|
||||
pclk = mode->clock;
|
||||
|
||||
/* In dual link mode each port needs half of pixel clock */
|
||||
if (intel_dsi->dual_link) {
|
||||
pclk = pclk / 2;
|
||||
|
||||
/* we can enable pixel_overlap if needed by panel. In this
|
||||
* case we need to increase the pixelclock for extra pixels
|
||||
*/
|
||||
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
|
||||
pclk += DIV_ROUND_UP(mode->vtotal *
|
||||
intel_dsi->pixel_overlap *
|
||||
60, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/* Burst Mode Ratio
|
||||
* Target ddr frequency from VBT / non burst ddr freq
|
||||
* multiply by 100 to preserve remainder
|
||||
*/
|
||||
if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
|
||||
if (mipi_config->target_burst_mode_freq) {
|
||||
computed_ddr = (pclk * bpp) / intel_dsi->lane_count;
|
||||
|
||||
if (mipi_config->target_burst_mode_freq <
|
||||
computed_ddr) {
|
||||
DRM_ERROR("Burst mode freq is less than computed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
burst_mode_ratio = DIV_ROUND_UP(
|
||||
mipi_config->target_burst_mode_freq * 100,
|
||||
computed_ddr);
|
||||
|
||||
pclk = DIV_ROUND_UP(pclk * burst_mode_ratio, 100);
|
||||
} else {
|
||||
DRM_ERROR("Burst mode target is not set\n");
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
burst_mode_ratio = 100;
|
||||
|
||||
intel_dsi->burst_mode_ratio = burst_mode_ratio;
|
||||
intel_dsi->pclk = pclk;
|
||||
|
||||
bitrate = (pclk * bpp) / intel_dsi->lane_count;
|
||||
|
||||
switch (intel_dsi->escape_clk_div) {
|
||||
case 0:
|
||||
tlpx_ns = 50;
|
||||
break;
|
||||
case 1:
|
||||
tlpx_ns = 100;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
tlpx_ns = 200;
|
||||
break;
|
||||
default:
|
||||
tlpx_ns = 50;
|
||||
break;
|
||||
}
|
||||
tlpx_ns = intel_dsi_tlpx_ns(intel_dsi);
|
||||
|
||||
switch (intel_dsi->lane_count) {
|
||||
case 1:
|
||||
@@ -620,7 +668,7 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
|
||||
|
||||
/* in Kbps */
|
||||
ui_num = NS_KHZ_RATIO;
|
||||
ui_den = bitrate;
|
||||
ui_den = intel_dsi_bitrate(intel_dsi);
|
||||
|
||||
tclk_prepare_clkzero = mipi_config->tclk_prepare_clkzero;
|
||||
ths_prepare_hszero = mipi_config->ths_prepare_hszero;
|
||||
@@ -746,6 +794,88 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
|
||||
DIV_ROUND_UP(2 * tlpx_ui + trail_cnt * 2 + 8,
|
||||
8);
|
||||
intel_dsi->clk_hs_to_lp_count += extra_byte_count;
|
||||
}
|
||||
|
||||
bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
|
||||
{
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
|
||||
struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps;
|
||||
struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode;
|
||||
u16 burst_mode_ratio;
|
||||
enum port port;
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
|
||||
intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
|
||||
intel_dsi->lane_count = mipi_config->lane_cnt + 1;
|
||||
intel_dsi->pixel_format =
|
||||
pixel_format_from_register_bits(
|
||||
mipi_config->videomode_color_format << 7);
|
||||
|
||||
intel_dsi->dual_link = mipi_config->dual_link;
|
||||
intel_dsi->pixel_overlap = mipi_config->pixel_overlap;
|
||||
intel_dsi->operation_mode = mipi_config->is_cmd_mode;
|
||||
intel_dsi->video_mode_format = mipi_config->video_transfer_mode;
|
||||
intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
|
||||
intel_dsi->lp_rx_timeout = mipi_config->lp_rx_timeout;
|
||||
intel_dsi->hs_tx_timeout = mipi_config->hs_tx_timeout;
|
||||
intel_dsi->turn_arnd_val = mipi_config->turn_around_timeout;
|
||||
intel_dsi->rst_timer_val = mipi_config->device_reset_timer;
|
||||
intel_dsi->init_count = mipi_config->master_init_timer;
|
||||
intel_dsi->bw_timer = mipi_config->dbi_bw_timer;
|
||||
intel_dsi->video_frmt_cfg_bits =
|
||||
mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
|
||||
intel_dsi->bgr_enabled = mipi_config->rgb_flip;
|
||||
|
||||
/* Starting point, adjusted depending on dual link and burst mode */
|
||||
intel_dsi->pclk = mode->clock;
|
||||
|
||||
/* In dual link mode each port needs half of pixel clock */
|
||||
if (intel_dsi->dual_link) {
|
||||
intel_dsi->pclk /= 2;
|
||||
|
||||
/* we can enable pixel_overlap if needed by panel. In this
|
||||
* case we need to increase the pixelclock for extra pixels
|
||||
*/
|
||||
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
|
||||
intel_dsi->pclk += DIV_ROUND_UP(mode->vtotal * intel_dsi->pixel_overlap * 60, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/* Burst Mode Ratio
|
||||
* Target ddr frequency from VBT / non burst ddr freq
|
||||
* multiply by 100 to preserve remainder
|
||||
*/
|
||||
if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
|
||||
if (mipi_config->target_burst_mode_freq) {
|
||||
u32 bitrate = intel_dsi_bitrate(intel_dsi);
|
||||
|
||||
if (mipi_config->target_burst_mode_freq < bitrate) {
|
||||
DRM_ERROR("Burst mode freq is less than computed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
burst_mode_ratio = DIV_ROUND_UP(
|
||||
mipi_config->target_burst_mode_freq * 100,
|
||||
bitrate);
|
||||
|
||||
intel_dsi->pclk = DIV_ROUND_UP(intel_dsi->pclk * burst_mode_ratio, 100);
|
||||
} else {
|
||||
DRM_ERROR("Burst mode target is not set\n");
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
burst_mode_ratio = 100;
|
||||
|
||||
intel_dsi->burst_mode_ratio = burst_mode_ratio;
|
||||
|
||||
if (IS_ICELAKE(dev_priv))
|
||||
icl_dphy_param_init(intel_dsi);
|
||||
else
|
||||
vlv_dphy_param_init(intel_dsi);
|
||||
|
||||
DRM_DEBUG_KMS("Pclk %d\n", intel_dsi->pclk);
|
||||
DRM_DEBUG_KMS("Pixel overlap %d\n", intel_dsi->pixel_overlap);
|
||||
|
@@ -256,6 +256,7 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder,
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return false;
|
||||
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -333,18 +334,11 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_dvo_destroy(struct drm_connector *connector)
|
||||
{
|
||||
drm_connector_cleanup(connector);
|
||||
intel_panel_fini(&to_intel_connector(connector)->panel);
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs intel_dvo_connector_funcs = {
|
||||
.detect = intel_dvo_detect,
|
||||
.late_register = intel_connector_register,
|
||||
.early_unregister = intel_connector_unregister,
|
||||
.destroy = intel_dvo_destroy,
|
||||
.destroy = intel_connector_destroy,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
|
@@ -273,13 +273,13 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
|
||||
BUILD_BUG_ON(MAX_ENGINE_CLASS >= BIT(GEN11_ENGINE_CLASS_WIDTH));
|
||||
BUILD_BUG_ON(MAX_ENGINE_INSTANCE >= BIT(GEN11_ENGINE_INSTANCE_WIDTH));
|
||||
|
||||
if (GEM_WARN_ON(info->class > MAX_ENGINE_CLASS))
|
||||
if (GEM_DEBUG_WARN_ON(info->class > MAX_ENGINE_CLASS))
|
||||
return -EINVAL;
|
||||
|
||||
if (GEM_WARN_ON(info->instance > MAX_ENGINE_INSTANCE))
|
||||
if (GEM_DEBUG_WARN_ON(info->instance > MAX_ENGINE_INSTANCE))
|
||||
return -EINVAL;
|
||||
|
||||
if (GEM_WARN_ON(dev_priv->engine_class[info->class][info->instance]))
|
||||
if (GEM_DEBUG_WARN_ON(dev_priv->engine_class[info->class][info->instance]))
|
||||
return -EINVAL;
|
||||
|
||||
GEM_BUG_ON(dev_priv->engine[id]);
|
||||
@@ -335,7 +335,10 @@ int intel_engines_init_mmio(struct drm_i915_private *dev_priv)
|
||||
|
||||
WARN_ON(ring_mask == 0);
|
||||
WARN_ON(ring_mask &
|
||||
GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES));
|
||||
GENMASK(BITS_PER_TYPE(mask) - 1, I915_NUM_ENGINES));
|
||||
|
||||
if (i915_inject_load_failure())
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
|
||||
if (!HAS_ENGINE(dev_priv, i))
|
||||
@@ -399,7 +402,7 @@ int intel_engines_init(struct drm_i915_private *dev_priv)
|
||||
err = -EINVAL;
|
||||
err_id = id;
|
||||
|
||||
if (GEM_WARN_ON(!init))
|
||||
if (GEM_DEBUG_WARN_ON(!init))
|
||||
goto cleanup;
|
||||
|
||||
err = init(engine);
|
||||
@@ -463,7 +466,7 @@ static void intel_engine_init_execlist(struct intel_engine_cs *engine)
|
||||
struct intel_engine_execlists * const execlists = &engine->execlists;
|
||||
|
||||
execlists->port_mask = 1;
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(execlists_num_ports(execlists));
|
||||
GEM_BUG_ON(!is_power_of_2(execlists_num_ports(execlists)));
|
||||
GEM_BUG_ON(execlists_num_ports(execlists) > EXECLIST_MAX_PORTS);
|
||||
|
||||
execlists->queue_priority = INT_MIN;
|
||||
@@ -482,7 +485,7 @@ static void intel_engine_init_execlist(struct intel_engine_cs *engine)
|
||||
void intel_engine_setup_common(struct intel_engine_cs *engine)
|
||||
{
|
||||
i915_timeline_init(engine->i915, &engine->timeline, engine->name);
|
||||
lockdep_set_subclass(&engine->timeline.lock, TIMELINE_ENGINE);
|
||||
i915_timeline_set_subclass(&engine->timeline, TIMELINE_ENGINE);
|
||||
|
||||
intel_engine_init_execlist(engine);
|
||||
intel_engine_init_hangcheck(engine);
|
||||
@@ -679,7 +682,9 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
|
||||
|
||||
i915_timeline_fini(&engine->timeline);
|
||||
|
||||
intel_wa_list_free(&engine->ctx_wa_list);
|
||||
intel_wa_list_free(&engine->wa_list);
|
||||
intel_wa_list_free(&engine->whitelist);
|
||||
}
|
||||
|
||||
u64 intel_engine_get_active_head(const struct intel_engine_cs *engine)
|
||||
@@ -769,7 +774,7 @@ u32 intel_calculate_mcr_s_ss_select(struct drm_i915_private *dev_priv)
|
||||
u32 slice = fls(sseu->slice_mask);
|
||||
u32 subslice = fls(sseu->subslice_mask[slice]);
|
||||
|
||||
if (INTEL_GEN(dev_priv) == 10)
|
||||
if (IS_GEN10(dev_priv))
|
||||
mcr_s_ss_select = GEN8_MCR_SLICE(slice) |
|
||||
GEN8_MCR_SUBSLICE(subslice);
|
||||
else if (INTEL_GEN(dev_priv) >= 11)
|
||||
@@ -1494,10 +1499,10 @@ void intel_engine_dump(struct intel_engine_cs *engine,
|
||||
count = 0;
|
||||
drm_printf(m, "\t\tQueue priority: %d\n", execlists->queue_priority);
|
||||
for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
|
||||
struct i915_priolist *p =
|
||||
rb_entry(rb, typeof(*p), node);
|
||||
struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
|
||||
int i;
|
||||
|
||||
list_for_each_entry(rq, &p->requests, sched.link) {
|
||||
priolist_for_each_request(rq, p, i) {
|
||||
if (count++ < MAX_REQUESTS_TO_SHOW - 1)
|
||||
print_request(m, rq, "\t\tQ ");
|
||||
else
|
||||
@@ -1519,8 +1524,10 @@ void intel_engine_dump(struct intel_engine_cs *engine,
|
||||
for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
|
||||
struct intel_wait *w = rb_entry(rb, typeof(*w), node);
|
||||
|
||||
drm_printf(m, "\t%s [%d] waiting for %x\n",
|
||||
w->tsk->comm, w->tsk->pid, w->seqno);
|
||||
drm_printf(m, "\t%s [%d:%c] waiting for %x\n",
|
||||
w->tsk->comm, w->tsk->pid,
|
||||
task_state_to_char(w->tsk),
|
||||
w->seqno);
|
||||
}
|
||||
spin_unlock(&b->rb_lock);
|
||||
local_irq_restore(flags);
|
||||
|
@@ -84,7 +84,7 @@ static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,
|
||||
int lines;
|
||||
|
||||
intel_fbc_get_plane_source_size(cache, NULL, &lines);
|
||||
if (INTEL_GEN(dev_priv) == 7)
|
||||
if (IS_GEN7(dev_priv))
|
||||
lines = min(lines, 2048);
|
||||
else if (INTEL_GEN(dev_priv) >= 8)
|
||||
lines = min(lines, 2560);
|
||||
@@ -674,6 +674,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
|
||||
cache->plane.adjusted_y = plane_state->color_plane[0].y;
|
||||
cache->plane.y = plane_state->base.src.y1 >> 16;
|
||||
|
||||
cache->plane.pixel_blend_mode = plane_state->base.pixel_blend_mode;
|
||||
|
||||
if (!cache->plane.visible)
|
||||
return;
|
||||
|
||||
@@ -748,6 +750,12 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cache->plane.pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE &&
|
||||
cache->fb.format->has_alpha) {
|
||||
fbc->no_fbc_reason = "per-pixel alpha blending is incompatible with FBC";
|
||||
return false;
|
||||
}
|
||||
|
||||
/* WaFbcExceedCdClockThreshold:hsw,bdw */
|
||||
if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
|
||||
cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) {
|
||||
@@ -1301,7 +1309,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
|
||||
fbc->active = false;
|
||||
|
||||
if (need_fbc_vtd_wa(dev_priv))
|
||||
mkwrite_device_info(dev_priv)->has_fbc = false;
|
||||
mkwrite_device_info(dev_priv)->display.has_fbc = false;
|
||||
|
||||
i915_modparams.enable_fbc = intel_sanitize_fbc_option(dev_priv);
|
||||
DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n",
|
||||
|
@@ -593,7 +593,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
* pipe. Note we need to use the selected fb's pitch and bpp
|
||||
* rather than the current pipe's, since they differ.
|
||||
*/
|
||||
cur_size = intel_crtc->config->base.adjusted_mode.crtc_hdisplay;
|
||||
cur_size = crtc->state->adjusted_mode.crtc_hdisplay;
|
||||
cur_size = cur_size * fb->base.format->cpp[0];
|
||||
if (fb->base.pitches[0] < cur_size) {
|
||||
DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs %d)\n",
|
||||
@@ -603,13 +603,13 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
|
||||
break;
|
||||
}
|
||||
|
||||
cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay;
|
||||
cur_size = crtc->state->adjusted_mode.crtc_vdisplay;
|
||||
cur_size = intel_fb_align_height(&fb->base, 0, cur_size);
|
||||
cur_size *= fb->base.pitches[0];
|
||||
DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
|
||||
pipe_name(intel_crtc->pipe),
|
||||
intel_crtc->config->base.adjusted_mode.crtc_hdisplay,
|
||||
intel_crtc->config->base.adjusted_mode.crtc_vdisplay,
|
||||
crtc->state->adjusted_mode.crtc_hdisplay,
|
||||
crtc->state->adjusted_mode.crtc_vdisplay,
|
||||
fb->base.format->cpp[0] * 8,
|
||||
cur_size);
|
||||
|
||||
@@ -672,7 +672,7 @@ int intel_fbdev_init(struct drm_device *dev)
|
||||
struct intel_fbdev *ifbdev;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(INTEL_INFO(dev_priv)->num_pipes == 0))
|
||||
if (WARN_ON(!HAS_DISPLAY(dev_priv)))
|
||||
return -ENODEV;
|
||||
|
||||
ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
|
||||
|
@@ -50,7 +50,8 @@ void intel_guc_init_send_regs(struct intel_guc *guc)
|
||||
unsigned int i;
|
||||
|
||||
guc->send_regs.base = i915_mmio_reg_offset(SOFT_SCRATCH(0));
|
||||
guc->send_regs.count = SOFT_SCRATCH_COUNT - 1;
|
||||
guc->send_regs.count = GUC_MAX_MMIO_MSG_LEN;
|
||||
BUILD_BUG_ON(GUC_MAX_MMIO_MSG_LEN > SOFT_SCRATCH_COUNT);
|
||||
|
||||
for (i = 0; i < guc->send_regs.count; i++) {
|
||||
fw_domains |= intel_uncore_forcewake_for_reg(dev_priv,
|
||||
@@ -521,6 +522,44 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset)
|
||||
return intel_guc_send(guc, action, ARRAY_SIZE(action));
|
||||
}
|
||||
|
||||
/*
|
||||
* The ENTER/EXIT_S_STATE actions queue the save/restore operation in GuC FW and
|
||||
* then return, so waiting on the H2G is not enough to guarantee GuC is done.
|
||||
* When all the processing is done, GuC writes INTEL_GUC_SLEEP_STATE_SUCCESS to
|
||||
* scratch register 14, so we can poll on that. Note that GuC does not ensure
|
||||
* that the value in the register is different from
|
||||
* INTEL_GUC_SLEEP_STATE_SUCCESS while the action is in progress so we need to
|
||||
* take care of that ourselves as well.
|
||||
*/
|
||||
static int guc_sleep_state_action(struct intel_guc *guc,
|
||||
const u32 *action, u32 len)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = guc_to_i915(guc);
|
||||
int ret;
|
||||
u32 status;
|
||||
|
||||
I915_WRITE(SOFT_SCRATCH(14), INTEL_GUC_SLEEP_STATE_INVALID_MASK);
|
||||
|
||||
ret = intel_guc_send(guc, action, len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = __intel_wait_for_register(dev_priv, SOFT_SCRATCH(14),
|
||||
INTEL_GUC_SLEEP_STATE_INVALID_MASK,
|
||||
0, 0, 10, &status);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (status != INTEL_GUC_SLEEP_STATE_SUCCESS) {
|
||||
DRM_ERROR("GuC failed to change sleep state. "
|
||||
"action=0x%x, err=%u\n",
|
||||
action[0], status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_guc_suspend() - notify GuC entering suspend state
|
||||
* @guc: the guc
|
||||
@@ -533,7 +572,7 @@ int intel_guc_suspend(struct intel_guc *guc)
|
||||
intel_guc_ggtt_offset(guc, guc->shared_data)
|
||||
};
|
||||
|
||||
return intel_guc_send(guc, data, ARRAY_SIZE(data));
|
||||
return guc_sleep_state_action(guc, data, ARRAY_SIZE(data));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -571,7 +610,7 @@ int intel_guc_resume(struct intel_guc *guc)
|
||||
intel_guc_ggtt_offset(guc, guc->shared_data)
|
||||
};
|
||||
|
||||
return intel_guc_send(guc, data, ARRAY_SIZE(data));
|
||||
return guc_sleep_state_action(guc, data, ARRAY_SIZE(data));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -95,6 +95,11 @@ struct intel_guc {
|
||||
void (*notify)(struct intel_guc *guc);
|
||||
};
|
||||
|
||||
static inline bool intel_guc_is_alive(struct intel_guc *guc)
|
||||
{
|
||||
return intel_uc_fw_is_loaded(&guc->fw);
|
||||
}
|
||||
|
||||
static
|
||||
inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len)
|
||||
{
|
||||
|
@@ -78,7 +78,8 @@ static void guc_fw_select(struct intel_uc_fw *guc_fw)
|
||||
guc_fw->major_ver_wanted = KBL_FW_MAJOR;
|
||||
guc_fw->minor_ver_wanted = KBL_FW_MINOR;
|
||||
} else {
|
||||
DRM_WARN("%s: No firmware known for this platform!\n",
|
||||
dev_info(dev_priv->drm.dev,
|
||||
"%s: No firmware known for this platform!\n",
|
||||
intel_uc_fw_type_repr(guc_fw->type));
|
||||
}
|
||||
}
|
||||
@@ -125,66 +126,26 @@ static void guc_prepare_xfer(struct intel_guc *guc)
|
||||
}
|
||||
|
||||
/* Copy RSA signature from the fw image to HW for verification */
|
||||
static int guc_xfer_rsa(struct intel_guc *guc, struct i915_vma *vma)
|
||||
static void guc_xfer_rsa(struct intel_guc *guc, struct i915_vma *vma)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = guc_to_i915(guc);
|
||||
struct intel_uc_fw *guc_fw = &guc->fw;
|
||||
struct sg_table *sg = vma->pages;
|
||||
u32 rsa[UOS_RSA_SCRATCH_COUNT];
|
||||
int i;
|
||||
|
||||
if (sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, sizeof(rsa),
|
||||
guc_fw->rsa_offset) != sizeof(rsa))
|
||||
return -EINVAL;
|
||||
sg_pcopy_to_buffer(vma->pages->sgl, vma->pages->nents,
|
||||
rsa, sizeof(rsa), guc->fw.rsa_offset);
|
||||
|
||||
for (i = 0; i < UOS_RSA_SCRATCH_COUNT; i++)
|
||||
I915_WRITE(UOS_RSA_SCRATCH(i), rsa[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transfer the firmware image to RAM for execution by the microcontroller.
|
||||
*
|
||||
* Architecturally, the DMA engine is bidirectional, and can potentially even
|
||||
* transfer between GTT locations. This functionality is left out of the API
|
||||
* for now as there is no need for it.
|
||||
*/
|
||||
static int guc_xfer_ucode(struct intel_guc *guc, struct i915_vma *vma)
|
||||
static bool guc_xfer_completed(struct intel_guc *guc, u32 *status)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = guc_to_i915(guc);
|
||||
struct intel_uc_fw *guc_fw = &guc->fw;
|
||||
unsigned long offset;
|
||||
u32 status;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The header plus uCode will be copied to WOPCM via DMA, excluding any
|
||||
* other components
|
||||
*/
|
||||
I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size);
|
||||
|
||||
/* Set the source address for the new blob */
|
||||
offset = intel_guc_ggtt_offset(guc, vma) + guc_fw->header_offset;
|
||||
I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset));
|
||||
I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF);
|
||||
|
||||
/*
|
||||
* Set the DMA destination. Current uCode expects the code to be
|
||||
* loaded at 8k; locations below this are used for the stack.
|
||||
*/
|
||||
I915_WRITE(DMA_ADDR_1_LOW, 0x2000);
|
||||
I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
|
||||
|
||||
/* Finally start the DMA */
|
||||
I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA));
|
||||
|
||||
/* Wait for DMA to finish */
|
||||
ret = __intel_wait_for_register_fw(dev_priv, DMA_CTRL, START_DMA, 0,
|
||||
2, 100, &status);
|
||||
DRM_DEBUG_DRIVER("GuC DMA status %#x\n", status);
|
||||
|
||||
return ret;
|
||||
/* Did we complete the xfer? */
|
||||
*status = I915_READ(DMA_CTRL);
|
||||
return !(*status & START_DMA);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -217,8 +178,8 @@ static int guc_wait_ucode(struct intel_guc *guc)
|
||||
* NB: Docs recommend not using the interrupt for completion.
|
||||
* Measurements indicate this should take no more than 20ms, so a
|
||||
* timeout here indicates that the GuC has failed and is unusable.
|
||||
* (Higher levels of the driver will attempt to fall back to
|
||||
* execlist mode if this happens.)
|
||||
* (Higher levels of the driver may decide to reset the GuC and
|
||||
* attempt the ucode load again if this happens.)
|
||||
*/
|
||||
ret = wait_for(guc_ready(guc, &status), 100);
|
||||
DRM_DEBUG_DRIVER("GuC status %#x\n", status);
|
||||
@@ -228,9 +189,51 @@ static int guc_wait_ucode(struct intel_guc *guc)
|
||||
ret = -ENOEXEC;
|
||||
}
|
||||
|
||||
if (ret == 0 && !guc_xfer_completed(guc, &status)) {
|
||||
DRM_ERROR("GuC is ready, but the xfer %08x is incomplete\n",
|
||||
status);
|
||||
ret = -ENXIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transfer the firmware image to RAM for execution by the microcontroller.
|
||||
*
|
||||
* Architecturally, the DMA engine is bidirectional, and can potentially even
|
||||
* transfer between GTT locations. This functionality is left out of the API
|
||||
* for now as there is no need for it.
|
||||
*/
|
||||
static int guc_xfer_ucode(struct intel_guc *guc, struct i915_vma *vma)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = guc_to_i915(guc);
|
||||
struct intel_uc_fw *guc_fw = &guc->fw;
|
||||
unsigned long offset;
|
||||
|
||||
/*
|
||||
* The header plus uCode will be copied to WOPCM via DMA, excluding any
|
||||
* other components
|
||||
*/
|
||||
I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size);
|
||||
|
||||
/* Set the source address for the new blob */
|
||||
offset = intel_guc_ggtt_offset(guc, vma) + guc_fw->header_offset;
|
||||
I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset));
|
||||
I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF);
|
||||
|
||||
/*
|
||||
* Set the DMA destination. Current uCode expects the code to be
|
||||
* loaded at 8k; locations below this are used for the stack.
|
||||
*/
|
||||
I915_WRITE(DMA_ADDR_1_LOW, 0x2000);
|
||||
I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
|
||||
|
||||
/* Finally start the DMA */
|
||||
I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(UOS_MOVE | START_DMA));
|
||||
|
||||
return guc_wait_ucode(guc);
|
||||
}
|
||||
/*
|
||||
* Load the GuC firmware blob into the MinuteIA.
|
||||
*/
|
||||
@@ -251,17 +254,9 @@ static int guc_fw_xfer(struct intel_uc_fw *guc_fw, struct i915_vma *vma)
|
||||
* by the DMA engine in one operation, whereas the RSA signature is
|
||||
* loaded via MMIO.
|
||||
*/
|
||||
ret = guc_xfer_rsa(guc, vma);
|
||||
if (ret)
|
||||
DRM_WARN("GuC firmware signature xfer error %d\n", ret);
|
||||
guc_xfer_rsa(guc, vma);
|
||||
|
||||
ret = guc_xfer_ucode(guc, vma);
|
||||
if (ret)
|
||||
DRM_WARN("GuC firmware code xfer error %d\n", ret);
|
||||
|
||||
ret = guc_wait_ucode(guc);
|
||||
if (ret)
|
||||
DRM_ERROR("GuC firmware xfer error %d\n", ret);
|
||||
|
||||
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
|
||||
|
||||
|
@@ -39,6 +39,11 @@
|
||||
#define GUC_VIDEO_ENGINE2 4
|
||||
#define GUC_MAX_ENGINES_NUM (GUC_VIDEO_ENGINE2 + 1)
|
||||
|
||||
#define GUC_DOORBELL_INVALID 256
|
||||
|
||||
#define GUC_DB_SIZE (PAGE_SIZE)
|
||||
#define GUC_WQ_SIZE (PAGE_SIZE * 2)
|
||||
|
||||
/* Work queue item header definitions */
|
||||
#define WQ_STATUS_ACTIVE 1
|
||||
#define WQ_STATUS_SUSPENDED 2
|
||||
@@ -59,9 +64,6 @@
|
||||
#define WQ_RING_TAIL_MAX 0x7FF /* 2^11 QWords */
|
||||
#define WQ_RING_TAIL_MASK (WQ_RING_TAIL_MAX << WQ_RING_TAIL_SHIFT)
|
||||
|
||||
#define GUC_DOORBELL_ENABLED 1
|
||||
#define GUC_DOORBELL_DISABLED 0
|
||||
|
||||
#define GUC_STAGE_DESC_ATTR_ACTIVE BIT(0)
|
||||
#define GUC_STAGE_DESC_ATTR_PENDING_DB BIT(1)
|
||||
#define GUC_STAGE_DESC_ATTR_KERNEL BIT(2)
|
||||
@@ -219,26 +221,6 @@ struct uc_css_header {
|
||||
u32 header_info;
|
||||
} __packed;
|
||||
|
||||
struct guc_doorbell_info {
|
||||
u32 db_status;
|
||||
u32 cookie;
|
||||
u32 reserved[14];
|
||||
} __packed;
|
||||
|
||||
union guc_doorbell_qw {
|
||||
struct {
|
||||
u32 db_status;
|
||||
u32 cookie;
|
||||
};
|
||||
u64 value_qw;
|
||||
} __packed;
|
||||
|
||||
#define GUC_NUM_DOORBELLS 256
|
||||
#define GUC_DOORBELL_INVALID (GUC_NUM_DOORBELLS)
|
||||
|
||||
#define GUC_DB_SIZE (PAGE_SIZE)
|
||||
#define GUC_WQ_SIZE (PAGE_SIZE * 2)
|
||||
|
||||
/* Work item for submitting workloads into work queue of GuC. */
|
||||
struct guc_wq_item {
|
||||
u32 header;
|
||||
@@ -601,7 +583,9 @@ struct guc_shared_ctx_data {
|
||||
* registers, where first register holds data treated as message header,
|
||||
* and other registers are used to hold message payload.
|
||||
*
|
||||
* For Gen9+, GuC uses software scratch registers 0xC180-0xC1B8
|
||||
* For Gen9+, GuC uses software scratch registers 0xC180-0xC1B8,
|
||||
* but no H2G command takes more than 8 parameters and the GuC FW
|
||||
* itself uses an 8-element array to store the H2G message.
|
||||
*
|
||||
* +-----------+---------+---------+---------+
|
||||
* | MMIO[0] | MMIO[1] | ... | MMIO[n] |
|
||||
@@ -633,6 +617,8 @@ struct guc_shared_ctx_data {
|
||||
* field.
|
||||
*/
|
||||
|
||||
#define GUC_MAX_MMIO_MSG_LEN 8
|
||||
|
||||
#define INTEL_GUC_MSG_TYPE_SHIFT 28
|
||||
#define INTEL_GUC_MSG_TYPE_MASK (0xF << INTEL_GUC_MSG_TYPE_SHIFT)
|
||||
#define INTEL_GUC_MSG_DATA_SHIFT 16
|
||||
@@ -687,6 +673,13 @@ enum intel_guc_report_status {
|
||||
INTEL_GUC_REPORT_STATUS_COMPLETE = 0x4,
|
||||
};
|
||||
|
||||
enum intel_guc_sleep_state_status {
|
||||
INTEL_GUC_SLEEP_STATE_SUCCESS = 0x0,
|
||||
INTEL_GUC_SLEEP_STATE_PREEMPT_TO_IDLE_FAILED = 0x1,
|
||||
INTEL_GUC_SLEEP_STATE_ENGINE_RESET_FAILED = 0x2
|
||||
#define INTEL_GUC_SLEEP_STATE_INVALID_MASK 0x80000000
|
||||
};
|
||||
|
||||
#define GUC_LOG_CONTROL_LOGGING_ENABLED (1 << 0)
|
||||
#define GUC_LOG_CONTROL_VERBOSITY_SHIFT 4
|
||||
#define GUC_LOG_CONTROL_VERBOSITY_MASK (0xF << GUC_LOG_CONTROL_VERBOSITY_SHIFT)
|
||||
|
@@ -104,6 +104,18 @@
|
||||
#define GUC_SEND_INTERRUPT _MMIO(0xc4c8)
|
||||
#define GUC_SEND_TRIGGER (1<<0)
|
||||
|
||||
#define GUC_NUM_DOORBELLS 256
|
||||
|
||||
/* format of the HW-monitored doorbell cacheline */
|
||||
struct guc_doorbell_info {
|
||||
u32 db_status;
|
||||
#define GUC_DOORBELL_DISABLED 0
|
||||
#define GUC_DOORBELL_ENABLED 1
|
||||
|
||||
u32 cookie;
|
||||
u32 reserved[14];
|
||||
} __packed;
|
||||
|
||||
#define GEN8_DRBREGL(x) _MMIO(0x1000 + (x) * 8)
|
||||
#define GEN8_DRB_VALID (1<<0)
|
||||
#define GEN8_DRBREGU(x) _MMIO(0x1000 + (x) * 8 + 4)
|
||||
|
@@ -192,7 +192,15 @@ static struct guc_doorbell_info *__get_doorbell(struct intel_guc_client *client)
|
||||
return client->vaddr + client->doorbell_offset;
|
||||
}
|
||||
|
||||
static void __create_doorbell(struct intel_guc_client *client)
|
||||
static bool __doorbell_valid(struct intel_guc *guc, u16 db_id)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = guc_to_i915(guc);
|
||||
|
||||
GEM_BUG_ON(db_id >= GUC_NUM_DOORBELLS);
|
||||
return I915_READ(GEN8_DRBREGL(db_id)) & GEN8_DRB_VALID;
|
||||
}
|
||||
|
||||
static void __init_doorbell(struct intel_guc_client *client)
|
||||
{
|
||||
struct guc_doorbell_info *doorbell;
|
||||
|
||||
@@ -201,21 +209,19 @@ static void __create_doorbell(struct intel_guc_client *client)
|
||||
doorbell->cookie = 0;
|
||||
}
|
||||
|
||||
static void __destroy_doorbell(struct intel_guc_client *client)
|
||||
static void __fini_doorbell(struct intel_guc_client *client)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = guc_to_i915(client->guc);
|
||||
struct guc_doorbell_info *doorbell;
|
||||
u16 db_id = client->doorbell_id;
|
||||
|
||||
doorbell = __get_doorbell(client);
|
||||
doorbell->db_status = GUC_DOORBELL_DISABLED;
|
||||
doorbell->cookie = 0;
|
||||
|
||||
/* Doorbell release flow requires that we wait for GEN8_DRB_VALID bit
|
||||
* to go to zero after updating db_status before we call the GuC to
|
||||
* release the doorbell
|
||||
*/
|
||||
if (wait_for_us(!(I915_READ(GEN8_DRBREGL(db_id)) & GEN8_DRB_VALID), 10))
|
||||
if (wait_for_us(!__doorbell_valid(client->guc, db_id), 10))
|
||||
WARN_ONCE(true, "Doorbell never became invalid after disable\n");
|
||||
}
|
||||
|
||||
@@ -227,11 +233,11 @@ static int create_doorbell(struct intel_guc_client *client)
|
||||
return -ENODEV; /* internal setup error, should never happen */
|
||||
|
||||
__update_doorbell_desc(client, client->doorbell_id);
|
||||
__create_doorbell(client);
|
||||
__init_doorbell(client);
|
||||
|
||||
ret = __guc_allocate_doorbell(client->guc, client->stage_id);
|
||||
if (ret) {
|
||||
__destroy_doorbell(client);
|
||||
__fini_doorbell(client);
|
||||
__update_doorbell_desc(client, GUC_DOORBELL_INVALID);
|
||||
DRM_DEBUG_DRIVER("Couldn't create client %u doorbell: %d\n",
|
||||
client->stage_id, ret);
|
||||
@@ -247,7 +253,7 @@ static int destroy_doorbell(struct intel_guc_client *client)
|
||||
|
||||
GEM_BUG_ON(!has_doorbell(client));
|
||||
|
||||
__destroy_doorbell(client);
|
||||
__fini_doorbell(client);
|
||||
ret = __guc_deallocate_doorbell(client->guc, client->stage_id);
|
||||
if (ret)
|
||||
DRM_ERROR("Couldn't destroy client %u doorbell: %d\n",
|
||||
@@ -282,8 +288,7 @@ __get_process_desc(struct intel_guc_client *client)
|
||||
/*
|
||||
* Initialise the process descriptor shared with the GuC firmware.
|
||||
*/
|
||||
static void guc_proc_desc_init(struct intel_guc *guc,
|
||||
struct intel_guc_client *client)
|
||||
static void guc_proc_desc_init(struct intel_guc_client *client)
|
||||
{
|
||||
struct guc_process_desc *desc;
|
||||
|
||||
@@ -304,6 +309,14 @@ static void guc_proc_desc_init(struct intel_guc *guc,
|
||||
desc->priority = client->priority;
|
||||
}
|
||||
|
||||
static void guc_proc_desc_fini(struct intel_guc_client *client)
|
||||
{
|
||||
struct guc_process_desc *desc;
|
||||
|
||||
desc = __get_process_desc(client);
|
||||
memset(desc, 0, sizeof(*desc));
|
||||
}
|
||||
|
||||
static int guc_stage_desc_pool_create(struct intel_guc *guc)
|
||||
{
|
||||
struct i915_vma *vma;
|
||||
@@ -341,9 +354,9 @@ static void guc_stage_desc_pool_destroy(struct intel_guc *guc)
|
||||
* data structures relating to this client (doorbell, process descriptor,
|
||||
* write queue, etc).
|
||||
*/
|
||||
static void guc_stage_desc_init(struct intel_guc *guc,
|
||||
struct intel_guc_client *client)
|
||||
static void guc_stage_desc_init(struct intel_guc_client *client)
|
||||
{
|
||||
struct intel_guc *guc = client->guc;
|
||||
struct drm_i915_private *dev_priv = guc_to_i915(guc);
|
||||
struct intel_engine_cs *engine;
|
||||
struct i915_gem_context *ctx = client->owner;
|
||||
@@ -424,8 +437,7 @@ static void guc_stage_desc_init(struct intel_guc *guc,
|
||||
desc->desc_private = ptr_to_u64(client);
|
||||
}
|
||||
|
||||
static void guc_stage_desc_fini(struct intel_guc *guc,
|
||||
struct intel_guc_client *client)
|
||||
static void guc_stage_desc_fini(struct intel_guc_client *client)
|
||||
{
|
||||
struct guc_stage_desc *desc;
|
||||
|
||||
@@ -486,14 +498,6 @@ static void guc_wq_item_append(struct intel_guc_client *client,
|
||||
WRITE_ONCE(desc->tail, (wq_off + wqi_size) & (GUC_WQ_SIZE - 1));
|
||||
}
|
||||
|
||||
static void guc_reset_wq(struct intel_guc_client *client)
|
||||
{
|
||||
struct guc_process_desc *desc = __get_process_desc(client);
|
||||
|
||||
desc->head = 0;
|
||||
desc->tail = 0;
|
||||
}
|
||||
|
||||
static void guc_ring_doorbell(struct intel_guc_client *client)
|
||||
{
|
||||
struct guc_doorbell_info *db;
|
||||
@@ -746,30 +750,28 @@ static bool __guc_dequeue(struct intel_engine_cs *engine)
|
||||
while ((rb = rb_first_cached(&execlists->queue))) {
|
||||
struct i915_priolist *p = to_priolist(rb);
|
||||
struct i915_request *rq, *rn;
|
||||
int i;
|
||||
|
||||
list_for_each_entry_safe(rq, rn, &p->requests, sched.link) {
|
||||
priolist_for_each_request_consume(rq, rn, p, i) {
|
||||
if (last && rq->hw_context != last->hw_context) {
|
||||
if (port == last_port) {
|
||||
__list_del_many(&p->requests,
|
||||
&rq->sched.link);
|
||||
if (port == last_port)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (submit)
|
||||
port_assign(port, last);
|
||||
port++;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&rq->sched.link);
|
||||
list_del_init(&rq->sched.link);
|
||||
|
||||
__i915_request_submit(rq);
|
||||
trace_i915_request_in(rq, port_index(port, execlists));
|
||||
|
||||
last = rq;
|
||||
submit = true;
|
||||
}
|
||||
|
||||
rb_erase_cached(&p->node, &execlists->queue);
|
||||
INIT_LIST_HEAD(&p->requests);
|
||||
if (p->priority != I915_PRIORITY_NORMAL)
|
||||
kmem_cache_free(engine->i915->priorities, p);
|
||||
}
|
||||
@@ -791,19 +793,8 @@ done:
|
||||
|
||||
static void guc_dequeue(struct intel_engine_cs *engine)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool submit;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
spin_lock(&engine->timeline.lock);
|
||||
submit = __guc_dequeue(engine);
|
||||
spin_unlock(&engine->timeline.lock);
|
||||
|
||||
if (submit)
|
||||
if (__guc_dequeue(engine))
|
||||
guc_submit(engine);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void guc_submission_tasklet(unsigned long data)
|
||||
@@ -812,6 +803,9 @@ static void guc_submission_tasklet(unsigned long data)
|
||||
struct intel_engine_execlists * const execlists = &engine->execlists;
|
||||
struct execlist_port *port = execlists->port;
|
||||
struct i915_request *rq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&engine->timeline.lock, flags);
|
||||
|
||||
rq = port_request(port);
|
||||
while (rq && i915_request_completed(rq)) {
|
||||
@@ -835,6 +829,8 @@ static void guc_submission_tasklet(unsigned long data)
|
||||
|
||||
if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT))
|
||||
guc_dequeue(engine);
|
||||
|
||||
spin_unlock_irqrestore(&engine->timeline.lock, flags);
|
||||
}
|
||||
|
||||
static struct i915_request *
|
||||
@@ -877,72 +873,31 @@ guc_reset_prepare(struct intel_engine_cs *engine)
|
||||
/* Check that a doorbell register is in the expected state */
|
||||
static bool doorbell_ok(struct intel_guc *guc, u16 db_id)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = guc_to_i915(guc);
|
||||
u32 drbregl;
|
||||
bool valid;
|
||||
|
||||
GEM_BUG_ON(db_id >= GUC_DOORBELL_INVALID);
|
||||
GEM_BUG_ON(db_id >= GUC_NUM_DOORBELLS);
|
||||
|
||||
drbregl = I915_READ(GEN8_DRBREGL(db_id));
|
||||
valid = drbregl & GEN8_DRB_VALID;
|
||||
valid = __doorbell_valid(guc, db_id);
|
||||
|
||||
if (test_bit(db_id, guc->doorbell_bitmap) == valid)
|
||||
return true;
|
||||
|
||||
DRM_DEBUG_DRIVER("Doorbell %d has unexpected state (0x%x): valid=%s\n",
|
||||
db_id, drbregl, yesno(valid));
|
||||
DRM_DEBUG_DRIVER("Doorbell %u has unexpected state: valid=%s\n",
|
||||
db_id, yesno(valid));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool guc_verify_doorbells(struct intel_guc *guc)
|
||||
{
|
||||
bool doorbells_ok = true;
|
||||
u16 db_id;
|
||||
|
||||
for (db_id = 0; db_id < GUC_NUM_DOORBELLS; ++db_id)
|
||||
if (!doorbell_ok(guc, db_id))
|
||||
return false;
|
||||
doorbells_ok = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int guc_clients_doorbell_init(struct intel_guc *guc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = create_doorbell(guc->execbuf_client);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (guc->preempt_client) {
|
||||
ret = create_doorbell(guc->preempt_client);
|
||||
if (ret) {
|
||||
destroy_doorbell(guc->execbuf_client);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void guc_clients_doorbell_fini(struct intel_guc *guc)
|
||||
{
|
||||
/*
|
||||
* By the time we're here, GuC has already been reset.
|
||||
* Instead of trying (in vain) to communicate with it, let's just
|
||||
* cleanup the doorbell HW and our internal state.
|
||||
*/
|
||||
if (guc->preempt_client) {
|
||||
__destroy_doorbell(guc->preempt_client);
|
||||
__update_doorbell_desc(guc->preempt_client,
|
||||
GUC_DOORBELL_INVALID);
|
||||
}
|
||||
|
||||
if (guc->execbuf_client) {
|
||||
__destroy_doorbell(guc->execbuf_client);
|
||||
__update_doorbell_desc(guc->execbuf_client,
|
||||
GUC_DOORBELL_INVALID);
|
||||
}
|
||||
return doorbells_ok;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1005,6 +960,10 @@ guc_client_alloc(struct drm_i915_private *dev_priv,
|
||||
}
|
||||
client->vaddr = vaddr;
|
||||
|
||||
ret = reserve_doorbell(client);
|
||||
if (ret)
|
||||
goto err_vaddr;
|
||||
|
||||
client->doorbell_offset = __select_cacheline(guc);
|
||||
|
||||
/*
|
||||
@@ -1017,13 +976,6 @@ guc_client_alloc(struct drm_i915_private *dev_priv,
|
||||
else
|
||||
client->proc_desc_offset = (GUC_DB_SIZE / 2);
|
||||
|
||||
guc_proc_desc_init(guc, client);
|
||||
guc_stage_desc_init(guc, client);
|
||||
|
||||
ret = reserve_doorbell(client);
|
||||
if (ret)
|
||||
goto err_vaddr;
|
||||
|
||||
DRM_DEBUG_DRIVER("new priority %u client %p for engine(s) 0x%x: stage_id %u\n",
|
||||
priority, client, client->engines, client->stage_id);
|
||||
DRM_DEBUG_DRIVER("doorbell id %u, cacheline offset 0x%lx\n",
|
||||
@@ -1045,7 +997,6 @@ err_client:
|
||||
static void guc_client_free(struct intel_guc_client *client)
|
||||
{
|
||||
unreserve_doorbell(client);
|
||||
guc_stage_desc_fini(client->guc, client);
|
||||
i915_vma_unpin_and_release(&client->vma, I915_VMA_RELEASE_MAP);
|
||||
ida_simple_remove(&client->guc->stage_ids, client->stage_id);
|
||||
kfree(client);
|
||||
@@ -1112,6 +1063,69 @@ static void guc_clients_destroy(struct intel_guc *guc)
|
||||
guc_client_free(client);
|
||||
}
|
||||
|
||||
static int __guc_client_enable(struct intel_guc_client *client)
|
||||
{
|
||||
int ret;
|
||||
|
||||
guc_proc_desc_init(client);
|
||||
guc_stage_desc_init(client);
|
||||
|
||||
ret = create_doorbell(client);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
guc_stage_desc_fini(client);
|
||||
guc_proc_desc_fini(client);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __guc_client_disable(struct intel_guc_client *client)
|
||||
{
|
||||
/*
|
||||
* By the time we're here, GuC may have already been reset. if that is
|
||||
* the case, instead of trying (in vain) to communicate with it, let's
|
||||
* just cleanup the doorbell HW and our internal state.
|
||||
*/
|
||||
if (intel_guc_is_alive(client->guc))
|
||||
destroy_doorbell(client);
|
||||
else
|
||||
__fini_doorbell(client);
|
||||
|
||||
guc_stage_desc_fini(client);
|
||||
guc_proc_desc_fini(client);
|
||||
}
|
||||
|
||||
static int guc_clients_enable(struct intel_guc *guc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = __guc_client_enable(guc->execbuf_client);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (guc->preempt_client) {
|
||||
ret = __guc_client_enable(guc->preempt_client);
|
||||
if (ret) {
|
||||
__guc_client_disable(guc->execbuf_client);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void guc_clients_disable(struct intel_guc *guc)
|
||||
{
|
||||
if (guc->preempt_client)
|
||||
__guc_client_disable(guc->preempt_client);
|
||||
|
||||
if (guc->execbuf_client)
|
||||
__guc_client_disable(guc->execbuf_client);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the memory resources to be shared with the GuC (via the GGTT)
|
||||
* at firmware loading time.
|
||||
@@ -1295,15 +1309,11 @@ int intel_guc_submission_enable(struct intel_guc *guc)
|
||||
|
||||
GEM_BUG_ON(!guc->execbuf_client);
|
||||
|
||||
guc_reset_wq(guc->execbuf_client);
|
||||
if (guc->preempt_client)
|
||||
guc_reset_wq(guc->preempt_client);
|
||||
|
||||
err = intel_guc_sample_forcewake(guc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = guc_clients_doorbell_init(guc);
|
||||
err = guc_clients_enable(guc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1325,7 +1335,7 @@ void intel_guc_submission_disable(struct intel_guc *guc)
|
||||
GEM_BUG_ON(dev_priv->gt.awake); /* GT should be parked first */
|
||||
|
||||
guc_interrupts_release(dev_priv);
|
||||
guc_clients_doorbell_fini(guc);
|
||||
guc_clients_disable(guc);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
|
||||
|
@@ -16,6 +16,62 @@
|
||||
|
||||
#define KEY_LOAD_TRIES 5
|
||||
|
||||
static
|
||||
bool intel_hdcp_is_ksv_valid(u8 *ksv)
|
||||
{
|
||||
int i, ones = 0;
|
||||
/* KSV has 20 1's and 20 0's */
|
||||
for (i = 0; i < DRM_HDCP_KSV_LEN; i++)
|
||||
ones += hweight8(ksv[i]);
|
||||
if (ones != 20)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port,
|
||||
const struct intel_hdcp_shim *shim, u8 *bksv)
|
||||
{
|
||||
int ret, i, tries = 2;
|
||||
|
||||
/* HDCP spec states that we must retry the bksv if it is invalid */
|
||||
for (i = 0; i < tries; i++) {
|
||||
ret = shim->read_bksv(intel_dig_port, bksv);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (intel_hdcp_is_ksv_valid(bksv))
|
||||
break;
|
||||
}
|
||||
if (i == tries) {
|
||||
DRM_DEBUG_KMS("Bksv is invalid\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is HDCP1.4 capable on Platform and Sink */
|
||||
bool intel_hdcp_capable(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
|
||||
const struct intel_hdcp_shim *shim = connector->hdcp.shim;
|
||||
bool capable = false;
|
||||
u8 bksv[5];
|
||||
|
||||
if (!shim)
|
||||
return capable;
|
||||
|
||||
if (shim->hdcp_capable) {
|
||||
shim->hdcp_capable(intel_dig_port, &capable);
|
||||
} else {
|
||||
if (!intel_hdcp_read_valid_bksv(intel_dig_port, shim, bksv))
|
||||
capable = true;
|
||||
}
|
||||
|
||||
return capable;
|
||||
}
|
||||
|
||||
static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
|
||||
const struct intel_hdcp_shim *shim)
|
||||
{
|
||||
@@ -167,18 +223,6 @@ u32 intel_hdcp_get_repeater_ctl(struct intel_digital_port *intel_dig_port)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static
|
||||
bool intel_hdcp_is_ksv_valid(u8 *ksv)
|
||||
{
|
||||
int i, ones = 0;
|
||||
/* KSV has 20 1's and 20 0's */
|
||||
for (i = 0; i < DRM_HDCP_KSV_LEN; i++)
|
||||
ones += hweight8(ksv[i]);
|
||||
if (ones != 20)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port,
|
||||
const struct intel_hdcp_shim *shim,
|
||||
@@ -383,7 +427,7 @@ int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port,
|
||||
if (intel_wait_for_register(dev_priv, HDCP_REP_CTL,
|
||||
HDCP_SHA1_COMPLETE,
|
||||
HDCP_SHA1_COMPLETE, 1)) {
|
||||
DRM_DEBUG_KMS("Timed out waiting for SHA1 complete\n");
|
||||
DRM_ERROR("Timed out waiting for SHA1 complete\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
if (!(I915_READ(HDCP_REP_CTL) & HDCP_SHA1_V_MATCH)) {
|
||||
@@ -404,7 +448,7 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
|
||||
|
||||
ret = intel_hdcp_poll_ksv_fifo(intel_dig_port, shim);
|
||||
if (ret) {
|
||||
DRM_ERROR("KSV list failed to become ready (%d)\n", ret);
|
||||
DRM_DEBUG_KMS("KSV list failed to become ready (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -414,7 +458,7 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
|
||||
|
||||
if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) ||
|
||||
DRM_HDCP_MAX_CASCADE_EXCEEDED(bstatus[1])) {
|
||||
DRM_ERROR("Max Topology Limit Exceeded\n");
|
||||
DRM_DEBUG_KMS("Max Topology Limit Exceeded\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@@ -450,7 +494,7 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
|
||||
}
|
||||
|
||||
if (i == tries) {
|
||||
DRM_ERROR("V Prime validation failed.(%d)\n", ret);
|
||||
DRM_DEBUG_KMS("V Prime validation failed.(%d)\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -499,7 +543,7 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!hdcp_capable) {
|
||||
DRM_ERROR("Panel is not HDCP capable\n");
|
||||
DRM_DEBUG_KMS("Panel is not HDCP capable\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -527,18 +571,9 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
|
||||
|
||||
memset(&bksv, 0, sizeof(bksv));
|
||||
|
||||
/* HDCP spec states that we must retry the bksv if it is invalid */
|
||||
for (i = 0; i < tries; i++) {
|
||||
ret = shim->read_bksv(intel_dig_port, bksv.shim);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (intel_hdcp_is_ksv_valid(bksv.shim))
|
||||
break;
|
||||
}
|
||||
if (i == tries) {
|
||||
DRM_ERROR("HDCP failed, Bksv is invalid\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = intel_hdcp_read_valid_bksv(intel_dig_port, shim, bksv.shim);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
I915_WRITE(PORT_HDCP_BKSVLO(port), bksv.reg[0]);
|
||||
I915_WRITE(PORT_HDCP_BKSVHI(port), bksv.reg[1]);
|
||||
@@ -594,8 +629,8 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
|
||||
}
|
||||
|
||||
if (i == tries) {
|
||||
DRM_ERROR("Timed out waiting for Ri prime match (%x)\n",
|
||||
I915_READ(PORT_HDCP_STATUS(port)));
|
||||
DRM_DEBUG_KMS("Timed out waiting for Ri prime match (%x)\n",
|
||||
I915_READ(PORT_HDCP_STATUS(port)));
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@@ -618,14 +653,9 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
struct intel_digital_port *conn_to_dig_port(struct intel_connector *connector)
|
||||
{
|
||||
return enc_to_dig_port(&intel_attached_encoder(&connector->base)->base);
|
||||
}
|
||||
|
||||
static int _intel_hdcp_disable(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
|
||||
struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
|
||||
enum port port = intel_dig_port->base.port;
|
||||
@@ -641,7 +671,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
ret = connector->hdcp_shim->toggle_signalling(intel_dig_port, false);
|
||||
ret = hdcp->shim->toggle_signalling(intel_dig_port, false);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to disable HDCP signalling\n");
|
||||
return ret;
|
||||
@@ -653,6 +683,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
|
||||
|
||||
static int _intel_hdcp_enable(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
|
||||
int i, ret, tries = 3;
|
||||
|
||||
@@ -677,8 +708,7 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
|
||||
|
||||
/* Incase of authentication failures, HDCP spec expects reauth. */
|
||||
for (i = 0; i < tries; i++) {
|
||||
ret = intel_hdcp_auth(conn_to_dig_port(connector),
|
||||
connector->hdcp_shim);
|
||||
ret = intel_hdcp_auth(conn_to_dig_port(connector), hdcp->shim);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
@@ -688,42 +718,50 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
|
||||
_intel_hdcp_disable(connector);
|
||||
}
|
||||
|
||||
DRM_ERROR("HDCP authentication failed (%d tries/%d)\n", tries, ret);
|
||||
DRM_DEBUG_KMS("HDCP authentication failed (%d tries/%d)\n", tries, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct intel_connector *intel_hdcp_to_connector(struct intel_hdcp *hdcp)
|
||||
{
|
||||
return container_of(hdcp, struct intel_connector, hdcp);
|
||||
}
|
||||
|
||||
static void intel_hdcp_check_work(struct work_struct *work)
|
||||
{
|
||||
struct intel_connector *connector = container_of(to_delayed_work(work),
|
||||
struct intel_connector,
|
||||
hdcp_check_work);
|
||||
struct intel_hdcp *hdcp = container_of(to_delayed_work(work),
|
||||
struct intel_hdcp,
|
||||
check_work);
|
||||
struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
|
||||
|
||||
if (!intel_hdcp_check_link(connector))
|
||||
schedule_delayed_work(&connector->hdcp_check_work,
|
||||
schedule_delayed_work(&hdcp->check_work,
|
||||
DRM_HDCP_CHECK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static void intel_hdcp_prop_work(struct work_struct *work)
|
||||
{
|
||||
struct intel_connector *connector = container_of(work,
|
||||
struct intel_connector,
|
||||
hdcp_prop_work);
|
||||
struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
|
||||
prop_work);
|
||||
struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_connector_state *state;
|
||||
|
||||
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
|
||||
mutex_lock(&connector->hdcp_mutex);
|
||||
mutex_lock(&hdcp->mutex);
|
||||
|
||||
/*
|
||||
* This worker is only used to flip between ENABLED/DESIRED. Either of
|
||||
* those to UNDESIRED is handled by core. If hdcp_value == UNDESIRED,
|
||||
* those to UNDESIRED is handled by core. If value == UNDESIRED,
|
||||
* we're running just after hdcp has been disabled, so just exit
|
||||
*/
|
||||
if (connector->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
state = connector->base.state;
|
||||
state->content_protection = connector->hdcp_value;
|
||||
state->content_protection = hdcp->value;
|
||||
}
|
||||
|
||||
mutex_unlock(&connector->hdcp_mutex);
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
||||
}
|
||||
|
||||
@@ -735,8 +773,9 @@ bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
|
||||
}
|
||||
|
||||
int intel_hdcp_init(struct intel_connector *connector,
|
||||
const struct intel_hdcp_shim *hdcp_shim)
|
||||
const struct intel_hdcp_shim *shim)
|
||||
{
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_attach_content_protection_property(
|
||||
@@ -744,51 +783,53 @@ int intel_hdcp_init(struct intel_connector *connector,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
connector->hdcp_shim = hdcp_shim;
|
||||
mutex_init(&connector->hdcp_mutex);
|
||||
INIT_DELAYED_WORK(&connector->hdcp_check_work, intel_hdcp_check_work);
|
||||
INIT_WORK(&connector->hdcp_prop_work, intel_hdcp_prop_work);
|
||||
hdcp->shim = shim;
|
||||
mutex_init(&hdcp->mutex);
|
||||
INIT_DELAYED_WORK(&hdcp->check_work, intel_hdcp_check_work);
|
||||
INIT_WORK(&hdcp->prop_work, intel_hdcp_prop_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intel_hdcp_enable(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
int ret;
|
||||
|
||||
if (!connector->hdcp_shim)
|
||||
if (!hdcp->shim)
|
||||
return -ENOENT;
|
||||
|
||||
mutex_lock(&connector->hdcp_mutex);
|
||||
mutex_lock(&hdcp->mutex);
|
||||
|
||||
ret = _intel_hdcp_enable(connector);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
schedule_work(&connector->hdcp_prop_work);
|
||||
schedule_delayed_work(&connector->hdcp_check_work,
|
||||
hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
schedule_work(&hdcp->prop_work);
|
||||
schedule_delayed_work(&hdcp->check_work,
|
||||
DRM_HDCP_CHECK_PERIOD_MS);
|
||||
out:
|
||||
mutex_unlock(&connector->hdcp_mutex);
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int intel_hdcp_disable(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
int ret = 0;
|
||||
|
||||
if (!connector->hdcp_shim)
|
||||
if (!hdcp->shim)
|
||||
return -ENOENT;
|
||||
|
||||
mutex_lock(&connector->hdcp_mutex);
|
||||
mutex_lock(&hdcp->mutex);
|
||||
|
||||
if (connector->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
ret = _intel_hdcp_disable(connector);
|
||||
}
|
||||
|
||||
mutex_unlock(&connector->hdcp_mutex);
|
||||
cancel_delayed_work_sync(&connector->hdcp_check_work);
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
cancel_delayed_work_sync(&hdcp->check_work);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -828,17 +869,18 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
|
||||
/* Implements Part 3 of the HDCP authorization procedure */
|
||||
int intel_hdcp_check_link(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
|
||||
struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
|
||||
enum port port = intel_dig_port->base.port;
|
||||
int ret = 0;
|
||||
|
||||
if (!connector->hdcp_shim)
|
||||
if (!hdcp->shim)
|
||||
return -ENOENT;
|
||||
|
||||
mutex_lock(&connector->hdcp_mutex);
|
||||
mutex_lock(&hdcp->mutex);
|
||||
|
||||
if (connector->hdcp_value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
goto out;
|
||||
|
||||
if (!(I915_READ(PORT_HDCP_STATUS(port)) & HDCP_STATUS_ENC)) {
|
||||
@@ -846,17 +888,15 @@ int intel_hdcp_check_link(struct intel_connector *connector)
|
||||
connector->base.name, connector->base.base.id,
|
||||
I915_READ(PORT_HDCP_STATUS(port)));
|
||||
ret = -ENXIO;
|
||||
connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
schedule_work(&connector->hdcp_prop_work);
|
||||
hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
schedule_work(&hdcp->prop_work);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (connector->hdcp_shim->check_link(intel_dig_port)) {
|
||||
if (connector->hdcp_value !=
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
connector->hdcp_value =
|
||||
DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
schedule_work(&connector->hdcp_prop_work);
|
||||
if (hdcp->shim->check_link(intel_dig_port)) {
|
||||
if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
schedule_work(&hdcp->prop_work);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
@@ -867,20 +907,20 @@ int intel_hdcp_check_link(struct intel_connector *connector)
|
||||
ret = _intel_hdcp_disable(connector);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to disable hdcp (%d)\n", ret);
|
||||
connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
schedule_work(&connector->hdcp_prop_work);
|
||||
hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
schedule_work(&hdcp->prop_work);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = _intel_hdcp_enable(connector);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to enable hdcp (%d)\n", ret);
|
||||
connector->hdcp_value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
schedule_work(&connector->hdcp_prop_work);
|
||||
DRM_DEBUG_KMS("Failed to enable hdcp (%d)\n", ret);
|
||||
hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
schedule_work(&hdcp->prop_work);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&connector->hdcp_mutex);
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -115,6 +115,8 @@ static u32 hsw_infoframe_enable(unsigned int type)
|
||||
switch (type) {
|
||||
case DP_SDP_VSC:
|
||||
return VIDEO_DIP_ENABLE_VSC_HSW;
|
||||
case DP_SDP_PPS:
|
||||
return VDIP_ENABLE_PPS;
|
||||
case HDMI_INFOFRAME_TYPE_AVI:
|
||||
return VIDEO_DIP_ENABLE_AVI_HSW;
|
||||
case HDMI_INFOFRAME_TYPE_SPD:
|
||||
@@ -136,6 +138,8 @@ hsw_dip_data_reg(struct drm_i915_private *dev_priv,
|
||||
switch (type) {
|
||||
case DP_SDP_VSC:
|
||||
return HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, i);
|
||||
case DP_SDP_PPS:
|
||||
return ICL_VIDEO_DIP_PPS_DATA(cpu_transcoder, i);
|
||||
case HDMI_INFOFRAME_TYPE_AVI:
|
||||
return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder, i);
|
||||
case HDMI_INFOFRAME_TYPE_SPD:
|
||||
@@ -148,14 +152,25 @@ hsw_dip_data_reg(struct drm_i915_private *dev_priv,
|
||||
}
|
||||
}
|
||||
|
||||
static void g4x_write_infoframe(struct drm_encoder *encoder,
|
||||
static int hsw_dip_data_size(unsigned int type)
|
||||
{
|
||||
switch (type) {
|
||||
case DP_SDP_VSC:
|
||||
return VIDEO_DIP_VSC_DATA_SIZE;
|
||||
case DP_SDP_PPS:
|
||||
return VIDEO_DIP_PPS_DATA_SIZE;
|
||||
default:
|
||||
return VIDEO_DIP_DATA_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
static void g4x_write_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
unsigned int type,
|
||||
const void *frame, ssize_t len)
|
||||
{
|
||||
const u32 *data = frame;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 val = I915_READ(VIDEO_DIP_CTL);
|
||||
int i;
|
||||
|
||||
@@ -186,31 +201,29 @@ static void g4x_write_infoframe(struct drm_encoder *encoder,
|
||||
POSTING_READ(VIDEO_DIP_CTL);
|
||||
}
|
||||
|
||||
static bool g4x_infoframe_enabled(struct drm_encoder *encoder,
|
||||
static bool g4x_infoframe_enabled(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 val = I915_READ(VIDEO_DIP_CTL);
|
||||
|
||||
if ((val & VIDEO_DIP_ENABLE) == 0)
|
||||
return false;
|
||||
|
||||
if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->base.port))
|
||||
if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(encoder->port))
|
||||
return false;
|
||||
|
||||
return val & (VIDEO_DIP_ENABLE_AVI |
|
||||
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_SPD);
|
||||
}
|
||||
|
||||
static void ibx_write_infoframe(struct drm_encoder *encoder,
|
||||
static void ibx_write_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
unsigned int type,
|
||||
const void *frame, ssize_t len)
|
||||
{
|
||||
const u32 *data = frame;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
|
||||
u32 val = I915_READ(reg);
|
||||
@@ -243,11 +256,10 @@ static void ibx_write_infoframe(struct drm_encoder *encoder,
|
||||
POSTING_READ(reg);
|
||||
}
|
||||
|
||||
static bool ibx_infoframe_enabled(struct drm_encoder *encoder,
|
||||
static bool ibx_infoframe_enabled(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
enum pipe pipe = to_intel_crtc(pipe_config->base.crtc)->pipe;
|
||||
i915_reg_t reg = TVIDEO_DIP_CTL(pipe);
|
||||
u32 val = I915_READ(reg);
|
||||
@@ -255,7 +267,7 @@ static bool ibx_infoframe_enabled(struct drm_encoder *encoder,
|
||||
if ((val & VIDEO_DIP_ENABLE) == 0)
|
||||
return false;
|
||||
|
||||
if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->base.port))
|
||||
if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(encoder->port))
|
||||
return false;
|
||||
|
||||
return val & (VIDEO_DIP_ENABLE_AVI |
|
||||
@@ -263,14 +275,13 @@ static bool ibx_infoframe_enabled(struct drm_encoder *encoder,
|
||||
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP);
|
||||
}
|
||||
|
||||
static void cpt_write_infoframe(struct drm_encoder *encoder,
|
||||
static void cpt_write_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
unsigned int type,
|
||||
const void *frame, ssize_t len)
|
||||
{
|
||||
const u32 *data = frame;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
|
||||
u32 val = I915_READ(reg);
|
||||
@@ -306,10 +317,10 @@ static void cpt_write_infoframe(struct drm_encoder *encoder,
|
||||
POSTING_READ(reg);
|
||||
}
|
||||
|
||||
static bool cpt_infoframe_enabled(struct drm_encoder *encoder,
|
||||
static bool cpt_infoframe_enabled(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
enum pipe pipe = to_intel_crtc(pipe_config->base.crtc)->pipe;
|
||||
u32 val = I915_READ(TVIDEO_DIP_CTL(pipe));
|
||||
|
||||
@@ -321,14 +332,13 @@ static bool cpt_infoframe_enabled(struct drm_encoder *encoder,
|
||||
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP);
|
||||
}
|
||||
|
||||
static void vlv_write_infoframe(struct drm_encoder *encoder,
|
||||
static void vlv_write_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
unsigned int type,
|
||||
const void *frame, ssize_t len)
|
||||
{
|
||||
const u32 *data = frame;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
|
||||
u32 val = I915_READ(reg);
|
||||
@@ -361,18 +371,17 @@ static void vlv_write_infoframe(struct drm_encoder *encoder,
|
||||
POSTING_READ(reg);
|
||||
}
|
||||
|
||||
static bool vlv_infoframe_enabled(struct drm_encoder *encoder,
|
||||
static bool vlv_infoframe_enabled(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
enum pipe pipe = to_intel_crtc(pipe_config->base.crtc)->pipe;
|
||||
u32 val = I915_READ(VLV_TVIDEO_DIP_CTL(pipe));
|
||||
|
||||
if ((val & VIDEO_DIP_ENABLE) == 0)
|
||||
return false;
|
||||
|
||||
if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->base.port))
|
||||
if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(encoder->port))
|
||||
return false;
|
||||
|
||||
return val & (VIDEO_DIP_ENABLE_AVI |
|
||||
@@ -380,21 +389,21 @@ static bool vlv_infoframe_enabled(struct drm_encoder *encoder,
|
||||
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP);
|
||||
}
|
||||
|
||||
static void hsw_write_infoframe(struct drm_encoder *encoder,
|
||||
static void hsw_write_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
unsigned int type,
|
||||
const void *frame, ssize_t len)
|
||||
{
|
||||
const u32 *data = frame;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
|
||||
int data_size = type == DP_SDP_VSC ?
|
||||
VIDEO_DIP_VSC_DATA_SIZE : VIDEO_DIP_DATA_SIZE;
|
||||
int data_size;
|
||||
int i;
|
||||
u32 val = I915_READ(ctl_reg);
|
||||
|
||||
data_size = hsw_dip_data_size(type);
|
||||
|
||||
val &= ~hsw_infoframe_enable(type);
|
||||
I915_WRITE(ctl_reg, val);
|
||||
|
||||
@@ -415,10 +424,10 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
|
||||
POSTING_READ(ctl_reg);
|
||||
}
|
||||
|
||||
static bool hsw_infoframe_enabled(struct drm_encoder *encoder,
|
||||
static bool hsw_infoframe_enabled(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 val = I915_READ(HSW_TVIDEO_DIP_CTL(pipe_config->cpu_transcoder));
|
||||
|
||||
return val & (VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW |
|
||||
@@ -443,11 +452,11 @@ static bool hsw_infoframe_enabled(struct drm_encoder *encoder,
|
||||
* trick them by giving an offset into the buffer and moving back the header
|
||||
* bytes by one.
|
||||
*/
|
||||
static void intel_write_infoframe(struct drm_encoder *encoder,
|
||||
static void intel_write_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
union hdmi_infoframe *frame)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base);
|
||||
u8 buffer[VIDEO_DIP_DATA_SIZE];
|
||||
ssize_t len;
|
||||
|
||||
@@ -457,24 +466,25 @@ static void intel_write_infoframe(struct drm_encoder *encoder,
|
||||
return;
|
||||
|
||||
/* Insert the 'hole' (see big comment above) at position 3 */
|
||||
buffer[0] = buffer[1];
|
||||
buffer[1] = buffer[2];
|
||||
buffer[2] = buffer[3];
|
||||
memmove(&buffer[0], &buffer[1], 3);
|
||||
buffer[3] = 0;
|
||||
len++;
|
||||
|
||||
intel_dig_port->write_infoframe(encoder, crtc_state, frame->any.type, buffer, len);
|
||||
intel_dig_port->write_infoframe(encoder,
|
||||
crtc_state,
|
||||
frame->any.type, buffer, len);
|
||||
}
|
||||
|
||||
static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
|
||||
static void intel_hdmi_set_avi_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->base.adjusted_mode;
|
||||
struct drm_connector *connector = &intel_hdmi->attached_connector->base;
|
||||
bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
|
||||
bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported ||
|
||||
connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420;
|
||||
union hdmi_infoframe frame;
|
||||
int ret;
|
||||
|
||||
@@ -486,8 +496,10 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
|
||||
return;
|
||||
}
|
||||
|
||||
if (crtc_state->ycbcr420)
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
|
||||
frame.avi.colorspace = HDMI_COLORSPACE_YUV420;
|
||||
else if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
|
||||
frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
|
||||
else
|
||||
frame.avi.colorspace = HDMI_COLORSPACE_RGB;
|
||||
|
||||
@@ -502,10 +514,11 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
|
||||
conn_state);
|
||||
|
||||
/* TODO: handle pixel repetition for YCBCR420 outputs */
|
||||
intel_write_infoframe(encoder, crtc_state, &frame);
|
||||
intel_write_infoframe(encoder, crtc_state,
|
||||
&frame);
|
||||
}
|
||||
|
||||
static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder,
|
||||
static void intel_hdmi_set_spd_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
union hdmi_infoframe frame;
|
||||
@@ -519,11 +532,12 @@ static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder,
|
||||
|
||||
frame.spd.sdi = HDMI_SPD_SDI_PC;
|
||||
|
||||
intel_write_infoframe(encoder, crtc_state, &frame);
|
||||
intel_write_infoframe(encoder, crtc_state,
|
||||
&frame);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder,
|
||||
intel_hdmi_set_hdmi_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
@@ -536,20 +550,21 @@ intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder,
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
intel_write_infoframe(encoder, crtc_state, &frame);
|
||||
intel_write_infoframe(encoder, crtc_state,
|
||||
&frame);
|
||||
}
|
||||
|
||||
static void g4x_set_infoframes(struct drm_encoder *encoder,
|
||||
static void g4x_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base);
|
||||
struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
|
||||
i915_reg_t reg = VIDEO_DIP_CTL;
|
||||
u32 val = I915_READ(reg);
|
||||
u32 port = VIDEO_DIP_PORT(intel_dig_port->base.port);
|
||||
u32 port = VIDEO_DIP_PORT(encoder->port);
|
||||
|
||||
assert_hdmi_port_disabled(intel_hdmi);
|
||||
|
||||
@@ -657,11 +672,11 @@ static bool gcp_default_phase_possible(int pipe_bpp,
|
||||
mode->crtc_htotal/2 % pixels_per_group == 0);
|
||||
}
|
||||
|
||||
static bool intel_hdmi_set_gcp_infoframe(struct drm_encoder *encoder,
|
||||
static bool intel_hdmi_set_gcp_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
i915_reg_t reg;
|
||||
u32 val = 0;
|
||||
@@ -689,18 +704,18 @@ static bool intel_hdmi_set_gcp_infoframe(struct drm_encoder *encoder,
|
||||
return val != 0;
|
||||
}
|
||||
|
||||
static void ibx_set_infoframes(struct drm_encoder *encoder,
|
||||
static void ibx_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base);
|
||||
struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
|
||||
i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
|
||||
u32 val = I915_READ(reg);
|
||||
u32 port = VIDEO_DIP_PORT(intel_dig_port->base.port);
|
||||
u32 port = VIDEO_DIP_PORT(encoder->port);
|
||||
|
||||
assert_hdmi_port_disabled(intel_hdmi);
|
||||
|
||||
@@ -742,14 +757,14 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
|
||||
intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
|
||||
}
|
||||
|
||||
static void cpt_set_infoframes(struct drm_encoder *encoder,
|
||||
static void cpt_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
|
||||
i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
|
||||
u32 val = I915_READ(reg);
|
||||
|
||||
@@ -785,18 +800,17 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
|
||||
intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
|
||||
}
|
||||
|
||||
static void vlv_set_infoframes(struct drm_encoder *encoder,
|
||||
static void vlv_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
|
||||
i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
|
||||
u32 val = I915_READ(reg);
|
||||
u32 port = VIDEO_DIP_PORT(intel_dig_port->base.port);
|
||||
u32 port = VIDEO_DIP_PORT(encoder->port);
|
||||
|
||||
assert_hdmi_port_disabled(intel_hdmi);
|
||||
|
||||
@@ -838,12 +852,12 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
|
||||
intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
|
||||
}
|
||||
|
||||
static void hsw_set_infoframes(struct drm_encoder *encoder,
|
||||
static void hsw_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder);
|
||||
u32 val = I915_READ(reg);
|
||||
|
||||
@@ -965,13 +979,13 @@ int intel_hdmi_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
|
||||
ret = intel_hdmi_hdcp_write(intel_dig_port, DRM_HDCP_DDC_AN, an,
|
||||
DRM_HDCP_AN_LEN);
|
||||
if (ret) {
|
||||
DRM_ERROR("Write An over DDC failed (%d)\n", ret);
|
||||
DRM_DEBUG_KMS("Write An over DDC failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = intel_gmbus_output_aksv(adapter);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("Failed to output aksv (%d)\n", ret);
|
||||
DRM_DEBUG_KMS("Failed to output aksv (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
@@ -984,7 +998,7 @@ static int intel_hdmi_hdcp_read_bksv(struct intel_digital_port *intel_dig_port,
|
||||
ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_BKSV, bksv,
|
||||
DRM_HDCP_KSV_LEN);
|
||||
if (ret)
|
||||
DRM_ERROR("Read Bksv over DDC failed (%d)\n", ret);
|
||||
DRM_DEBUG_KMS("Read Bksv over DDC failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -996,7 +1010,7 @@ int intel_hdmi_hdcp_read_bstatus(struct intel_digital_port *intel_dig_port,
|
||||
ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_BSTATUS,
|
||||
bstatus, DRM_HDCP_BSTATUS_LEN);
|
||||
if (ret)
|
||||
DRM_ERROR("Read bstatus over DDC failed (%d)\n", ret);
|
||||
DRM_DEBUG_KMS("Read bstatus over DDC failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1009,7 +1023,7 @@ int intel_hdmi_hdcp_repeater_present(struct intel_digital_port *intel_dig_port,
|
||||
|
||||
ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_BCAPS, &val, 1);
|
||||
if (ret) {
|
||||
DRM_ERROR("Read bcaps over DDC failed (%d)\n", ret);
|
||||
DRM_DEBUG_KMS("Read bcaps over DDC failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
*repeater_present = val & DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT;
|
||||
@@ -1024,7 +1038,7 @@ int intel_hdmi_hdcp_read_ri_prime(struct intel_digital_port *intel_dig_port,
|
||||
ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_RI_PRIME,
|
||||
ri_prime, DRM_HDCP_RI_LEN);
|
||||
if (ret)
|
||||
DRM_ERROR("Read Ri' over DDC failed (%d)\n", ret);
|
||||
DRM_DEBUG_KMS("Read Ri' over DDC failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1037,7 +1051,7 @@ int intel_hdmi_hdcp_read_ksv_ready(struct intel_digital_port *intel_dig_port,
|
||||
|
||||
ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_BCAPS, &val, 1);
|
||||
if (ret) {
|
||||
DRM_ERROR("Read bcaps over DDC failed (%d)\n", ret);
|
||||
DRM_DEBUG_KMS("Read bcaps over DDC failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
*ksv_ready = val & DRM_HDCP_DDC_BCAPS_KSV_FIFO_READY;
|
||||
@@ -1052,7 +1066,7 @@ int intel_hdmi_hdcp_read_ksv_fifo(struct intel_digital_port *intel_dig_port,
|
||||
ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_KSV_FIFO,
|
||||
ksv_fifo, num_downstream * DRM_HDCP_KSV_LEN);
|
||||
if (ret) {
|
||||
DRM_ERROR("Read ksv fifo over DDC failed (%d)\n", ret);
|
||||
DRM_DEBUG_KMS("Read ksv fifo over DDC failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
@@ -1070,7 +1084,7 @@ int intel_hdmi_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port,
|
||||
ret = intel_hdmi_hdcp_read(intel_dig_port, DRM_HDCP_DDC_V_PRIME(i),
|
||||
part, DRM_HDCP_V_PRIME_PART_LEN);
|
||||
if (ret)
|
||||
DRM_ERROR("Read V'[%d] over DDC failed (%d)\n", i, ret);
|
||||
DRM_DEBUG_KMS("Read V'[%d] over DDC failed (%d)\n", i, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1217,7 +1231,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
|
||||
if (tmp & HDMI_MODE_SELECT_HDMI)
|
||||
pipe_config->has_hdmi_sink = true;
|
||||
|
||||
if (intel_dig_port->infoframe_enabled(&encoder->base, pipe_config))
|
||||
if (intel_dig_port->infoframe_enabled(encoder, pipe_config))
|
||||
pipe_config->has_infoframe = true;
|
||||
|
||||
if (tmp & SDVO_AUDIO_ENABLE)
|
||||
@@ -1438,7 +1452,8 @@ static void intel_disable_hdmi(struct intel_encoder *encoder,
|
||||
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
|
||||
}
|
||||
|
||||
intel_dig_port->set_infoframes(&encoder->base, false,
|
||||
intel_dig_port->set_infoframes(encoder,
|
||||
false,
|
||||
old_crtc_state, old_conn_state);
|
||||
|
||||
intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
|
||||
@@ -1597,6 +1612,8 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
||||
struct drm_atomic_state *state = crtc_state->base.state;
|
||||
struct drm_connector_state *connector_state;
|
||||
struct drm_connector *connector;
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->base.adjusted_mode;
|
||||
int i;
|
||||
|
||||
if (HAS_GMCH_DISPLAY(dev_priv))
|
||||
@@ -1624,7 +1641,7 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
||||
if (connector_state->crtc != crtc_state->base.crtc)
|
||||
continue;
|
||||
|
||||
if (crtc_state->ycbcr420) {
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
|
||||
const struct drm_hdmi_info *hdmi = &info->hdmi;
|
||||
|
||||
if (bpc == 12 && !(hdmi->y420_dc_modes &
|
||||
@@ -1645,7 +1662,14 @@ 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) &&
|
||||
crtc_state->base.adjusted_mode.htotal > 5460)
|
||||
adjusted_mode->htotal > 5460)
|
||||
return false;
|
||||
|
||||
/* Display Wa_1405510057:icl */
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
|
||||
bpc == 10 && IS_ICELAKE(dev_priv) &&
|
||||
(adjusted_mode->crtc_hblank_end -
|
||||
adjusted_mode->crtc_hblank_start) % 8 == 2)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -1669,7 +1693,7 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
|
||||
*clock_12bpc /= 2;
|
||||
*clock_10bpc /= 2;
|
||||
*clock_8bpc /= 2;
|
||||
config->ycbcr420 = true;
|
||||
config->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
|
||||
|
||||
/* YCBCR 420 output conversion needs a scaler */
|
||||
if (skl_update_scaler_crtc(config)) {
|
||||
@@ -1703,6 +1727,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return false;
|
||||
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
pipe_config->has_hdmi_sink = !force_dvi && intel_hdmi->has_hdmi_sink;
|
||||
|
||||
if (pipe_config->has_hdmi_sink)
|
||||
@@ -1973,7 +1998,7 @@ static void intel_hdmi_pre_enable(struct intel_encoder *encoder,
|
||||
|
||||
intel_hdmi_prepare(encoder, pipe_config);
|
||||
|
||||
intel_dig_port->set_infoframes(&encoder->base,
|
||||
intel_dig_port->set_infoframes(encoder,
|
||||
pipe_config->has_infoframe,
|
||||
pipe_config, conn_state);
|
||||
}
|
||||
@@ -1991,7 +2016,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder,
|
||||
vlv_set_phy_signal_level(encoder, 0x2b245f5f, 0x00002000, 0x5578b83a,
|
||||
0x2b247878);
|
||||
|
||||
dport->set_infoframes(&encoder->base,
|
||||
dport->set_infoframes(encoder,
|
||||
pipe_config->has_infoframe,
|
||||
pipe_config, conn_state);
|
||||
|
||||
@@ -2062,7 +2087,7 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
|
||||
/* Use 800mV-0dB */
|
||||
chv_set_phy_signal_level(encoder, 128, 102, false);
|
||||
|
||||
dport->set_infoframes(&encoder->base,
|
||||
dport->set_infoframes(encoder,
|
||||
pipe_config->has_infoframe,
|
||||
pipe_config, conn_state);
|
||||
|
||||
@@ -2074,13 +2099,26 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
|
||||
chv_phy_release_cl2_override(encoder);
|
||||
}
|
||||
|
||||
static int
|
||||
intel_hdmi_connector_register(struct drm_connector *connector)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = intel_connector_register(connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
i915_debugfs_connector_add(connector);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void intel_hdmi_destroy(struct drm_connector *connector)
|
||||
{
|
||||
if (intel_attached_hdmi(connector)->cec_notifier)
|
||||
cec_notifier_put(intel_attached_hdmi(connector)->cec_notifier);
|
||||
kfree(to_intel_connector(connector)->detect_edid);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
|
||||
intel_connector_destroy(connector);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
||||
@@ -2089,7 +2127,7 @@ static const struct drm_connector_funcs intel_hdmi_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,
|
||||
.late_register = intel_hdmi_connector_register,
|
||||
.early_unregister = intel_connector_unregister,
|
||||
.destroy = intel_hdmi_destroy,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
@@ -2109,11 +2147,16 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
|
||||
static void
|
||||
intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
|
||||
intel_attach_force_audio_property(connector);
|
||||
intel_attach_broadcast_rgb_property(connector);
|
||||
intel_attach_aspect_ratio_property(connector);
|
||||
drm_connector_attach_content_type_property(connector);
|
||||
connector->state->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
|
||||
|
||||
if (!HAS_GMCH_DISPLAY(dev_priv))
|
||||
drm_connector_attach_max_bpc_property(connector, 8, 12);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2324,9 +2367,18 @@ void intel_infoframe_init(struct intel_digital_port *intel_dig_port)
|
||||
intel_dig_port->set_infoframes = g4x_set_infoframes;
|
||||
intel_dig_port->infoframe_enabled = g4x_infoframe_enabled;
|
||||
} else if (HAS_DDI(dev_priv)) {
|
||||
intel_dig_port->write_infoframe = hsw_write_infoframe;
|
||||
intel_dig_port->set_infoframes = hsw_set_infoframes;
|
||||
intel_dig_port->infoframe_enabled = hsw_infoframe_enabled;
|
||||
if (intel_dig_port->lspcon.active) {
|
||||
intel_dig_port->write_infoframe =
|
||||
lspcon_write_infoframe;
|
||||
intel_dig_port->set_infoframes = lspcon_set_infoframes;
|
||||
intel_dig_port->infoframe_enabled =
|
||||
lspcon_infoframe_enabled;
|
||||
} else {
|
||||
intel_dig_port->set_infoframes = hsw_set_infoframes;
|
||||
intel_dig_port->infoframe_enabled =
|
||||
hsw_infoframe_enabled;
|
||||
intel_dig_port->write_infoframe = hsw_write_infoframe;
|
||||
}
|
||||
} else if (HAS_PCH_IBX(dev_priv)) {
|
||||
intel_dig_port->write_infoframe = ibx_write_infoframe;
|
||||
intel_dig_port->set_infoframes = ibx_set_infoframes;
|
||||
@@ -2485,5 +2537,6 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv,
|
||||
|
||||
intel_infoframe_init(intel_dig_port);
|
||||
|
||||
intel_dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port);
|
||||
intel_hdmi_init_connector(intel_dig_port, intel_connector);
|
||||
}
|
||||
|
@@ -114,51 +114,68 @@ enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
|
||||
#define HPD_STORM_REENABLE_DELAY (2 * 60 * 1000)
|
||||
|
||||
/**
|
||||
* intel_hpd_irq_storm_detect - gather stats and detect HPD irq storm on a pin
|
||||
* intel_hpd_irq_storm_detect - gather stats and detect HPD IRQ storm on a pin
|
||||
* @dev_priv: private driver data pointer
|
||||
* @pin: the pin to gather stats on
|
||||
* @long_hpd: whether the HPD IRQ was long or short
|
||||
*
|
||||
* Gather stats about HPD irqs from the specified @pin, and detect irq
|
||||
* Gather stats about HPD IRQs from the specified @pin, and detect IRQ
|
||||
* storms. Only the pin specific stats and state are changed, the caller is
|
||||
* responsible for further action.
|
||||
*
|
||||
* The number of irqs that are allowed within @HPD_STORM_DETECT_PERIOD is
|
||||
* The number of IRQs that are allowed within @HPD_STORM_DETECT_PERIOD is
|
||||
* stored in @dev_priv->hotplug.hpd_storm_threshold which defaults to
|
||||
* @HPD_STORM_DEFAULT_THRESHOLD. If this threshold is exceeded, it's
|
||||
* considered an irq storm and the irq state is set to @HPD_MARK_DISABLED.
|
||||
* @HPD_STORM_DEFAULT_THRESHOLD. Long IRQs count as +10 to this threshold, and
|
||||
* short IRQs count as +1. If this threshold is exceeded, it's considered an
|
||||
* IRQ storm and the IRQ state is set to @HPD_MARK_DISABLED.
|
||||
*
|
||||
* By default, most systems will only count long IRQs towards
|
||||
* &dev_priv->hotplug.hpd_storm_threshold. However, some older systems also
|
||||
* suffer from short IRQ storms and must also track these. Because short IRQ
|
||||
* storms are naturally caused by sideband interactions with DP MST devices,
|
||||
* short IRQ detection is only enabled for systems without DP MST support.
|
||||
* Systems which are new enough to support DP MST are far less likely to
|
||||
* suffer from IRQ storms at all, so this is fine.
|
||||
*
|
||||
* The HPD threshold can be controlled through i915_hpd_storm_ctl in debugfs,
|
||||
* and should only be adjusted for automated hotplug testing.
|
||||
*
|
||||
* Return true if an irq storm was detected on @pin.
|
||||
* Return true if an IRQ storm was detected on @pin.
|
||||
*/
|
||||
static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv,
|
||||
enum hpd_pin pin)
|
||||
enum hpd_pin pin, bool long_hpd)
|
||||
{
|
||||
unsigned long start = dev_priv->hotplug.stats[pin].last_jiffies;
|
||||
struct i915_hotplug *hpd = &dev_priv->hotplug;
|
||||
unsigned long start = hpd->stats[pin].last_jiffies;
|
||||
unsigned long end = start + msecs_to_jiffies(HPD_STORM_DETECT_PERIOD);
|
||||
const int threshold = dev_priv->hotplug.hpd_storm_threshold;
|
||||
const int increment = long_hpd ? 10 : 1;
|
||||
const int threshold = hpd->hpd_storm_threshold;
|
||||
bool storm = false;
|
||||
|
||||
if (!threshold ||
|
||||
(!long_hpd && !dev_priv->hotplug.hpd_short_storm_enabled))
|
||||
return false;
|
||||
|
||||
if (!time_in_range(jiffies, start, end)) {
|
||||
dev_priv->hotplug.stats[pin].last_jiffies = jiffies;
|
||||
dev_priv->hotplug.stats[pin].count = 0;
|
||||
DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: 0\n", pin);
|
||||
} else if (dev_priv->hotplug.stats[pin].count > threshold &&
|
||||
threshold) {
|
||||
dev_priv->hotplug.stats[pin].state = HPD_MARK_DISABLED;
|
||||
hpd->stats[pin].last_jiffies = jiffies;
|
||||
hpd->stats[pin].count = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
storm = true;
|
||||
} else {
|
||||
dev_priv->hotplug.stats[pin].count++;
|
||||
DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: %d\n", pin,
|
||||
dev_priv->hotplug.stats[pin].count);
|
||||
hpd->stats[pin].count);
|
||||
}
|
||||
|
||||
return storm;
|
||||
}
|
||||
|
||||
static void intel_hpd_irq_storm_disable(struct drm_i915_private *dev_priv)
|
||||
static void
|
||||
intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
struct intel_connector *intel_connector;
|
||||
@@ -348,8 +365,8 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
||||
hpd_event_bits = dev_priv->hotplug.event_bits;
|
||||
dev_priv->hotplug.event_bits = 0;
|
||||
|
||||
/* Disable hotplug on connectors that hit an irq storm. */
|
||||
intel_hpd_irq_storm_disable(dev_priv);
|
||||
/* Enable polling for connectors which had HPD IRQ storms */
|
||||
intel_hpd_irq_storm_switch_to_polling(dev_priv);
|
||||
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
|
||||
@@ -474,15 +491,17 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
|
||||
queue_hp = true;
|
||||
}
|
||||
|
||||
if (!long_hpd)
|
||||
continue;
|
||||
|
||||
if (intel_hpd_irq_storm_detect(dev_priv, pin)) {
|
||||
if (intel_hpd_irq_storm_detect(dev_priv, pin, long_hpd)) {
|
||||
dev_priv->hotplug.event_bits &= ~BIT(pin);
|
||||
storm_detected = true;
|
||||
queue_hp = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable any IRQs that storms were detected on. Polling enablement
|
||||
* happens later in our hotplug work.
|
||||
*/
|
||||
if (storm_detected && dev_priv->display_irqs_enabled)
|
||||
dev_priv->display.hpd_irq_setup(dev_priv);
|
||||
spin_unlock(&dev_priv->irq_lock);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user