mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 13:15:57 +00:00
Merge tag 'drm-intel-next-2014-11-07-fixups' of git://anongit.freedesktop.org/drm-intel into drm-next
- skl watermarks code (Damien, Vandana, Pradeep) - reworked audio codec /eld handling code (Jani) - rework the mmio_flip code to use the vblank evade logic and wait for rendering using the standard wait_seqno interface (Ander) - skl forcewake support (Zhe Wang) - refactor the chv interrupt code to use functions shared with vlv (Ville) - prep work for different global gtt views (Tvrtko Ursulin) - precompute the display PLL config before touching hw state (Ander) - completely reworked panel power sequencer code for chv/vlv (Ville) - pre work to split the plane update code into a prepare and commit phase (Gustavo Padovan) - golden context for skl (Armin Reese) - as usual tons of fixes and improvements all over * tag 'drm-intel-next-2014-11-07-fixups' of git://anongit.freedesktop.org/drm-intel: (135 commits) drm/i915: Use correct pipe config to update pll dividers. V2 drm/i915: Plug memory leak in intel_shared_dpll_start_config() drm/i915: Update DRIVER_DATE to 20141107 drm/i915: Add gen to the gpu hang ecode drm/i915: Cache HPLL frequency on VLV/CHV Revert "drm/i915/vlv: Remove check for Old Ack during forcewake" drm/i915: Make mmio flip wait for seqno in the work function drm/i915: Make __wait_seqno non-static and rename to __i915_wait_seqno drm/i915: Move the .global_resources() hook call into modeset_update_crtc_power_domains() drm/i915/audio: add DOC comment describing HDA over HDMI/DP drm/i915: make pipe/port based audio valid accessors easier to use drm/i915/audio: add audio codec enable debug log for g4x drm/i915/audio: add audio codec disable on g4x drm/i915: enable audio codec after port drm/i915/audio: add vlv/chv/gen5-7 audio codec disable sequence drm/i915/audio: rewrite vlv/chv and gen 5-7 audio codec enable sequence drm/i915/skl: Enable Gen9 RC6 drm/i915/skl: Gen9 Forcewake drm/i915/skl: Log the order in which we flush the pipes in the WM code drm/i915/skl: Flush the WM configuration ...
This commit is contained in:
commit
fd172d0c47
@ -3887,6 +3887,11 @@ int num_ioctls;</synopsis>
|
||||
probing, so those sections fully apply.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>High Definition Audio</title>
|
||||
!Pdrivers/gpu/drm/i915/intel_audio.c High Definition Audio over HDMI and Display Port
|
||||
!Idrivers/gpu/drm/i915/intel_audio.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>DPIO</title>
|
||||
!Pdrivers/gpu/drm/i915/i915_reg.h DPIO
|
||||
|
@ -155,6 +155,11 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
*visible = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale);
|
||||
if (!*visible)
|
||||
/*
|
||||
|
@ -40,10 +40,12 @@ i915-y += i915_cmd_parser.o \
|
||||
# autogenerated null render state
|
||||
i915-y += intel_renderstate_gen6.o \
|
||||
intel_renderstate_gen7.o \
|
||||
intel_renderstate_gen8.o
|
||||
intel_renderstate_gen8.o \
|
||||
intel_renderstate_gen9.o
|
||||
|
||||
# modesetting core code
|
||||
i915-y += intel_bios.o \
|
||||
i915-y += intel_audio.o \
|
||||
intel_bios.o \
|
||||
intel_display.o \
|
||||
intel_fifo_underrun.o \
|
||||
intel_frontbuffer.o \
|
||||
|
@ -138,6 +138,11 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
|
||||
.mask = MI_GLOBAL_GTT,
|
||||
.expected = 0,
|
||||
}}, ),
|
||||
/*
|
||||
* MI_BATCH_BUFFER_START requires some special handling. It's not
|
||||
* really a 'skip' action but it doesn't seem like it's worth adding
|
||||
* a new action. See i915_parse_cmds().
|
||||
*/
|
||||
CMD( MI_BATCH_BUFFER_START, SMI, !F, 0xFF, S ),
|
||||
};
|
||||
|
||||
@ -955,7 +960,8 @@ static bool check_cmd(const struct intel_engine_cs *ring,
|
||||
* Parses the specified batch buffer looking for privilege violations as
|
||||
* described in the overview.
|
||||
*
|
||||
* Return: non-zero if the parser finds violations or otherwise fails
|
||||
* Return: non-zero if the parser finds violations or otherwise fails; -EACCES
|
||||
* if the batch appears legal but should use hardware parsing
|
||||
*/
|
||||
int i915_parse_cmds(struct intel_engine_cs *ring,
|
||||
struct drm_i915_gem_object *batch_obj,
|
||||
@ -1002,6 +1008,16 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the batch buffer contains a chained batch, return an
|
||||
* error that tells the caller to abort and dispatch the
|
||||
* workload as a non-secure batch.
|
||||
*/
|
||||
if (desc->cmd.value == MI_BATCH_BUFFER_START) {
|
||||
ret = -EACCES;
|
||||
break;
|
||||
}
|
||||
|
||||
if (desc->flags & CMD_DESC_FIXED)
|
||||
length = desc->length.fixed;
|
||||
else
|
||||
|
@ -116,7 +116,7 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
|
||||
|
||||
static inline const char *get_global_flag(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
return obj->has_global_gtt_mapping ? "g" : " ";
|
||||
return i915_gem_obj_to_ggtt(obj) ? "g" : " ";
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2630,14 +2630,15 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
|
||||
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
||||
|
||||
seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->name, pll->id);
|
||||
seq_printf(m, " refcount: %i, active: %i, on: %s\n", pll->refcount,
|
||||
pll->active, yesno(pll->on));
|
||||
seq_printf(m, " crtc_mask: 0x%08x, active: %d, on: %s\n",
|
||||
pll->config.crtc_mask, pll->active, yesno(pll->on));
|
||||
seq_printf(m, " tracked hardware state:\n");
|
||||
seq_printf(m, " dpll: 0x%08x\n", pll->hw_state.dpll);
|
||||
seq_printf(m, " dpll_md: 0x%08x\n", pll->hw_state.dpll_md);
|
||||
seq_printf(m, " fp0: 0x%08x\n", pll->hw_state.fp0);
|
||||
seq_printf(m, " fp1: 0x%08x\n", pll->hw_state.fp1);
|
||||
seq_printf(m, " wrpll: 0x%08x\n", pll->hw_state.wrpll);
|
||||
seq_printf(m, " dpll: 0x%08x\n", pll->config.hw_state.dpll);
|
||||
seq_printf(m, " dpll_md: 0x%08x\n",
|
||||
pll->config.hw_state.dpll_md);
|
||||
seq_printf(m, " fp0: 0x%08x\n", pll->config.hw_state.fp0);
|
||||
seq_printf(m, " fp1: 0x%08x\n", pll->config.hw_state.fp1);
|
||||
seq_printf(m, " wrpll: 0x%08x\n", pll->config.hw_state.wrpll);
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
@ -2678,6 +2679,42 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_ddb_info(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct skl_ddb_allocation *ddb;
|
||||
struct skl_ddb_entry *entry;
|
||||
enum pipe pipe;
|
||||
int plane;
|
||||
|
||||
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) {
|
||||
seq_printf(m, "Pipe %c\n", pipe_name(pipe));
|
||||
|
||||
for_each_plane(pipe, plane) {
|
||||
entry = &ddb->plane[pipe][plane];
|
||||
seq_printf(m, " Plane%-8d%8u%8u%8u\n", plane + 1,
|
||||
entry->start, entry->end,
|
||||
skl_ddb_entry_size(entry));
|
||||
}
|
||||
|
||||
entry = &ddb->cursor[pipe];
|
||||
seq_printf(m, " %-13s%8u%8u%8u\n", "Cursor", entry->start,
|
||||
entry->end, skl_ddb_entry_size(entry));
|
||||
}
|
||||
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pipe_crc_info {
|
||||
const char *name;
|
||||
struct drm_device *dev;
|
||||
@ -2971,6 +3008,8 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
@ -3520,7 +3559,7 @@ static const struct file_operations i915_display_crc_ctl_fops = {
|
||||
.write = display_crc_ctl_write
|
||||
};
|
||||
|
||||
static void wm_latency_show(struct seq_file *m, const uint16_t wm[5])
|
||||
static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
|
||||
{
|
||||
struct drm_device *dev = m->private;
|
||||
int num_levels = ilk_wm_max_level(dev) + 1;
|
||||
@ -3531,13 +3570,17 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[5])
|
||||
for (level = 0; level < num_levels; level++) {
|
||||
unsigned int latency = wm[level];
|
||||
|
||||
/* WM1+ latency values in 0.5us units */
|
||||
if (level > 0)
|
||||
/*
|
||||
* - WM1+ latency values in 0.5us units
|
||||
* - latencies are in us on gen9
|
||||
*/
|
||||
if (INTEL_INFO(dev)->gen >= 9)
|
||||
latency *= 10;
|
||||
else if (level > 0)
|
||||
latency *= 5;
|
||||
|
||||
seq_printf(m, "WM%d %u (%u.%u usec)\n",
|
||||
level, wm[level],
|
||||
latency / 10, latency % 10);
|
||||
level, wm[level], latency / 10, latency % 10);
|
||||
}
|
||||
|
||||
drm_modeset_unlock_all(dev);
|
||||
@ -3546,8 +3589,15 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[5])
|
||||
static int pri_wm_latency_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_device *dev = m->private;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
const uint16_t *latencies;
|
||||
|
||||
wm_latency_show(m, to_i915(dev)->wm.pri_latency);
|
||||
if (INTEL_INFO(dev)->gen >= 9)
|
||||
latencies = dev_priv->wm.skl_latency;
|
||||
else
|
||||
latencies = to_i915(dev)->wm.pri_latency;
|
||||
|
||||
wm_latency_show(m, latencies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3555,8 +3605,15 @@ static int pri_wm_latency_show(struct seq_file *m, void *data)
|
||||
static int spr_wm_latency_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_device *dev = m->private;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
const uint16_t *latencies;
|
||||
|
||||
wm_latency_show(m, to_i915(dev)->wm.spr_latency);
|
||||
if (INTEL_INFO(dev)->gen >= 9)
|
||||
latencies = dev_priv->wm.skl_latency;
|
||||
else
|
||||
latencies = to_i915(dev)->wm.spr_latency;
|
||||
|
||||
wm_latency_show(m, latencies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3564,8 +3621,15 @@ static int spr_wm_latency_show(struct seq_file *m, void *data)
|
||||
static int cur_wm_latency_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_device *dev = m->private;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
const uint16_t *latencies;
|
||||
|
||||
wm_latency_show(m, to_i915(dev)->wm.cur_latency);
|
||||
if (INTEL_INFO(dev)->gen >= 9)
|
||||
latencies = dev_priv->wm.skl_latency;
|
||||
else
|
||||
latencies = to_i915(dev)->wm.cur_latency;
|
||||
|
||||
wm_latency_show(m, latencies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3601,11 +3665,11 @@ static int cur_wm_latency_open(struct inode *inode, struct file *file)
|
||||
}
|
||||
|
||||
static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp, uint16_t wm[5])
|
||||
size_t len, loff_t *offp, uint16_t wm[8])
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
struct drm_device *dev = m->private;
|
||||
uint16_t new[5] = { 0 };
|
||||
uint16_t new[8] = { 0 };
|
||||
int num_levels = ilk_wm_max_level(dev) + 1;
|
||||
int level;
|
||||
int ret;
|
||||
@ -3619,7 +3683,9 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
|
||||
|
||||
tmp[len] = '\0';
|
||||
|
||||
ret = sscanf(tmp, "%hu %hu %hu %hu %hu", &new[0], &new[1], &new[2], &new[3], &new[4]);
|
||||
ret = sscanf(tmp, "%hu %hu %hu %hu %hu %hu %hu %hu",
|
||||
&new[0], &new[1], &new[2], &new[3],
|
||||
&new[4], &new[5], &new[6], &new[7]);
|
||||
if (ret != num_levels)
|
||||
return -EINVAL;
|
||||
|
||||
@ -3639,8 +3705,15 @@ static ssize_t pri_wm_latency_write(struct file *file, const char __user *ubuf,
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
struct drm_device *dev = m->private;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint16_t *latencies;
|
||||
|
||||
return wm_latency_write(file, ubuf, len, offp, to_i915(dev)->wm.pri_latency);
|
||||
if (INTEL_INFO(dev)->gen >= 9)
|
||||
latencies = dev_priv->wm.skl_latency;
|
||||
else
|
||||
latencies = to_i915(dev)->wm.pri_latency;
|
||||
|
||||
return wm_latency_write(file, ubuf, len, offp, latencies);
|
||||
}
|
||||
|
||||
static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf,
|
||||
@ -3648,8 +3721,15 @@ static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf,
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
struct drm_device *dev = m->private;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint16_t *latencies;
|
||||
|
||||
return wm_latency_write(file, ubuf, len, offp, to_i915(dev)->wm.spr_latency);
|
||||
if (INTEL_INFO(dev)->gen >= 9)
|
||||
latencies = dev_priv->wm.skl_latency;
|
||||
else
|
||||
latencies = to_i915(dev)->wm.spr_latency;
|
||||
|
||||
return wm_latency_write(file, ubuf, len, offp, latencies);
|
||||
}
|
||||
|
||||
static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf,
|
||||
@ -3657,8 +3737,15 @@ static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf,
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
struct drm_device *dev = m->private;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint16_t *latencies;
|
||||
|
||||
return wm_latency_write(file, ubuf, len, offp, to_i915(dev)->wm.cur_latency);
|
||||
if (INTEL_INFO(dev)->gen >= 9)
|
||||
latencies = dev_priv->wm.skl_latency;
|
||||
else
|
||||
latencies = to_i915(dev)->wm.cur_latency;
|
||||
|
||||
return wm_latency_write(file, ubuf, len, offp, latencies);
|
||||
}
|
||||
|
||||
static const struct file_operations i915_pri_wm_latency_fops = {
|
||||
@ -4201,6 +4288,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
|
||||
{"i915_shared_dplls_info", i915_shared_dplls_info, 0},
|
||||
{"i915_dp_mst_info", i915_dp_mst_info, 0},
|
||||
{"i915_wa_registers", i915_wa_registers, 0},
|
||||
{"i915_ddb_info", i915_ddb_info, 0},
|
||||
};
|
||||
#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
|
||||
|
||||
|
@ -551,8 +551,8 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
|
||||
}
|
||||
|
||||
static int intel_suspend_complete(struct drm_i915_private *dev_priv);
|
||||
static int intel_resume_prepare(struct drm_i915_private *dev_priv,
|
||||
bool rpm_resume);
|
||||
static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
|
||||
bool rpm_resume);
|
||||
|
||||
static int i915_drm_suspend(struct drm_device *dev)
|
||||
{
|
||||
@ -744,7 +744,7 @@ static int i915_drm_resume(struct drm_device *dev)
|
||||
static int i915_drm_resume_early(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* We have a resume ordering issue with the snd-hda driver also
|
||||
@ -760,11 +760,16 @@ static int i915_drm_resume_early(struct drm_device *dev)
|
||||
|
||||
pci_set_master(dev->pdev);
|
||||
|
||||
ret = intel_resume_prepare(dev_priv, false);
|
||||
if (IS_VALLEYVIEW(dev_priv))
|
||||
ret = vlv_resume_prepare(dev_priv, false);
|
||||
if (ret)
|
||||
DRM_ERROR("Resume prepare failed: %d,Continuing resume\n", ret);
|
||||
|
||||
intel_uncore_early_sanitize(dev, true);
|
||||
|
||||
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
hsw_disable_pc8(dev_priv);
|
||||
|
||||
intel_uncore_sanitize(dev);
|
||||
intel_power_domains_init_hw(dev_priv);
|
||||
|
||||
@ -986,25 +991,6 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snb_resume_prepare(struct drm_i915_private *dev_priv,
|
||||
bool rpm_resume)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
|
||||
if (rpm_resume)
|
||||
intel_init_pch_refclk(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hsw_resume_prepare(struct drm_i915_private *dev_priv,
|
||||
bool rpm_resume)
|
||||
{
|
||||
hsw_disable_pc8(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save all Gunit registers that may be lost after a D3 and a subsequent
|
||||
* S0i[R123] transition. The list of registers needing a save/restore is
|
||||
@ -1409,13 +1395,9 @@ static int intel_runtime_suspend(struct device *device)
|
||||
i915_gem_release_all_mmaps(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
/*
|
||||
* rps.work can't be rearmed here, since we get here only after making
|
||||
* sure the GPU is idle and the RPS freq is set to the minimum. See
|
||||
* intel_mark_idle().
|
||||
*/
|
||||
cancel_work_sync(&dev_priv->rps.work);
|
||||
flush_delayed_work(&dev_priv->rps.delayed_resume_work);
|
||||
intel_runtime_pm_disable_interrupts(dev_priv);
|
||||
intel_suspend_gt_powersave(dev);
|
||||
|
||||
ret = intel_suspend_complete(dev_priv);
|
||||
if (ret) {
|
||||
@ -1462,7 +1444,7 @@ static int intel_runtime_resume(struct device *device)
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev)))
|
||||
return -ENODEV;
|
||||
@ -1472,7 +1454,13 @@ static int intel_runtime_resume(struct device *device)
|
||||
intel_opregion_notify_adapter(dev, PCI_D0);
|
||||
dev_priv->pm.suspended = false;
|
||||
|
||||
ret = intel_resume_prepare(dev_priv, true);
|
||||
if (IS_GEN6(dev_priv))
|
||||
intel_init_pch_refclk(dev);
|
||||
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
hsw_disable_pc8(dev_priv);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
ret = vlv_resume_prepare(dev_priv, true);
|
||||
|
||||
/*
|
||||
* No point of rolling back things in case of an error, as the best
|
||||
* we can do is to hope that things will still work (and disable RPM).
|
||||
@ -1481,7 +1469,7 @@ static int intel_runtime_resume(struct device *device)
|
||||
gen6_update_ring_freq(dev);
|
||||
|
||||
intel_runtime_pm_enable_interrupts(dev_priv);
|
||||
intel_reset_gt_powersave(dev);
|
||||
intel_enable_gt_powersave(dev);
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
|
||||
@ -1510,29 +1498,6 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function implements common functionality of runtime and system
|
||||
* resume sequence. Variable rpm_resume used for implementing different
|
||||
* code paths.
|
||||
*/
|
||||
static int intel_resume_prepare(struct drm_i915_private *dev_priv,
|
||||
bool rpm_resume)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
int ret;
|
||||
|
||||
if (IS_GEN6(dev))
|
||||
ret = snb_resume_prepare(dev_priv, rpm_resume);
|
||||
else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
||||
ret = hsw_resume_prepare(dev_priv, rpm_resume);
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
ret = vlv_resume_prepare(dev_priv, rpm_resume);
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops i915_pm_ops = {
|
||||
/*
|
||||
* S0ix (via system suspend) and S3 event handlers [PMSG_SUSPEND,
|
||||
|
@ -55,7 +55,10 @@
|
||||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20141024"
|
||||
#define DRIVER_DATE "20141107"
|
||||
|
||||
#undef WARN_ON
|
||||
#define WARN_ON(x) WARN(x, "WARN_ON(" #x ")")
|
||||
|
||||
enum pipe {
|
||||
INVALID_PIPE = -1,
|
||||
@ -226,14 +229,20 @@ struct intel_dpll_hw_state {
|
||||
uint32_t wrpll;
|
||||
};
|
||||
|
||||
struct intel_shared_dpll_config {
|
||||
unsigned crtc_mask; /* mask of CRTCs sharing this PLL */
|
||||
struct intel_dpll_hw_state hw_state;
|
||||
};
|
||||
|
||||
struct intel_shared_dpll {
|
||||
int refcount; /* count of number of CRTCs sharing this PLL */
|
||||
struct intel_shared_dpll_config config;
|
||||
struct intel_shared_dpll_config *new_config;
|
||||
|
||||
int active; /* count of number of active CRTCs (i.e. DPMS on) */
|
||||
bool on; /* is the PLL actually active? Disabled during modeset */
|
||||
const char *name;
|
||||
/* should match the index in the dev_priv->shared_dplls array */
|
||||
enum intel_dpll_id id;
|
||||
struct intel_dpll_hw_state hw_state;
|
||||
/* The mode_set hook is optional and should be used together with the
|
||||
* intel_prepare_shared_dpll function. */
|
||||
void (*mode_set)(struct drm_i915_private *dev_priv,
|
||||
@ -275,7 +284,6 @@ void intel_link_compute_m_n(int bpp, int nlanes,
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
#define WATCH_LISTS 0
|
||||
#define WATCH_GTT 0
|
||||
|
||||
struct opregion_header;
|
||||
struct opregion_acpi;
|
||||
@ -434,6 +442,7 @@ struct drm_i915_error_state {
|
||||
};
|
||||
|
||||
struct intel_connector;
|
||||
struct intel_encoder;
|
||||
struct intel_crtc_config;
|
||||
struct intel_plane_config;
|
||||
struct intel_crtc;
|
||||
@ -476,15 +485,14 @@ struct drm_i915_display_funcs {
|
||||
struct intel_crtc_config *);
|
||||
void (*get_plane_config)(struct intel_crtc *,
|
||||
struct intel_plane_config *);
|
||||
int (*crtc_mode_set)(struct intel_crtc *crtc,
|
||||
int x, int y,
|
||||
struct drm_framebuffer *old_fb);
|
||||
int (*crtc_compute_clock)(struct intel_crtc *crtc);
|
||||
void (*crtc_enable)(struct drm_crtc *crtc);
|
||||
void (*crtc_disable)(struct drm_crtc *crtc);
|
||||
void (*off)(struct drm_crtc *crtc);
|
||||
void (*write_eld)(struct drm_connector *connector,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode);
|
||||
void (*audio_codec_enable)(struct drm_connector *connector,
|
||||
struct intel_encoder *encoder,
|
||||
struct drm_display_mode *mode);
|
||||
void (*audio_codec_disable)(struct intel_encoder *encoder);
|
||||
void (*fdi_link_train)(struct drm_crtc *crtc);
|
||||
void (*init_clock_gating)(struct drm_device *dev);
|
||||
int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
@ -541,6 +549,7 @@ struct intel_uncore {
|
||||
|
||||
unsigned fw_rendercount;
|
||||
unsigned fw_mediacount;
|
||||
unsigned fw_blittercount;
|
||||
|
||||
struct timer_list force_wake_timer;
|
||||
};
|
||||
@ -1379,6 +1388,49 @@ struct ilk_wm_values {
|
||||
enum intel_ddb_partitioning partitioning;
|
||||
};
|
||||
|
||||
struct skl_ddb_entry {
|
||||
uint16_t start, end; /* in number of blocks, 'end' is exclusive */
|
||||
};
|
||||
|
||||
static inline uint16_t skl_ddb_entry_size(const struct skl_ddb_entry *entry)
|
||||
{
|
||||
return entry->end - entry->start;
|
||||
}
|
||||
|
||||
static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1,
|
||||
const struct skl_ddb_entry *e2)
|
||||
{
|
||||
if (e1->start == e2->start && e1->end == e2->end)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct skl_ddb_allocation {
|
||||
struct skl_ddb_entry pipe[I915_MAX_PIPES];
|
||||
struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES];
|
||||
struct skl_ddb_entry cursor[I915_MAX_PIPES];
|
||||
};
|
||||
|
||||
struct skl_wm_values {
|
||||
bool dirty[I915_MAX_PIPES];
|
||||
struct skl_ddb_allocation ddb;
|
||||
uint32_t wm_linetime[I915_MAX_PIPES];
|
||||
uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8];
|
||||
uint32_t cursor[I915_MAX_PIPES][8];
|
||||
uint32_t plane_trans[I915_MAX_PIPES][I915_MAX_PLANES];
|
||||
uint32_t cursor_trans[I915_MAX_PIPES];
|
||||
};
|
||||
|
||||
struct skl_wm_level {
|
||||
bool plane_en[I915_MAX_PLANES];
|
||||
bool cursor_en;
|
||||
uint16_t plane_res_b[I915_MAX_PLANES];
|
||||
uint8_t plane_res_l[I915_MAX_PLANES];
|
||||
uint16_t cursor_res_b;
|
||||
uint8_t cursor_res_l;
|
||||
};
|
||||
|
||||
/*
|
||||
* This struct helps tracking the state needed for runtime PM, which puts the
|
||||
* device in PCI D3 state. Notice that when this happens, nothing on the
|
||||
@ -1561,6 +1613,7 @@ struct drm_i915_private {
|
||||
|
||||
unsigned int fsb_freq, mem_freq, is_ddr3;
|
||||
unsigned int vlv_cdclk_freq;
|
||||
unsigned int hpll_freq;
|
||||
|
||||
/**
|
||||
* wq - Driver workqueue for GEM.
|
||||
@ -1670,9 +1723,25 @@ struct drm_i915_private {
|
||||
uint16_t spr_latency[5];
|
||||
/* cursor */
|
||||
uint16_t cur_latency[5];
|
||||
/*
|
||||
* Raw watermark memory latency values
|
||||
* for SKL for all 8 levels
|
||||
* in 1us units.
|
||||
*/
|
||||
uint16_t skl_latency[8];
|
||||
|
||||
/*
|
||||
* The skl_wm_values structure is a bit too big for stack
|
||||
* allocation, so we keep the staging struct where we store
|
||||
* intermediate results here instead.
|
||||
*/
|
||||
struct skl_wm_values skl_results;
|
||||
|
||||
/* current hardware state */
|
||||
struct ilk_wm_values hw;
|
||||
union {
|
||||
struct ilk_wm_values hw;
|
||||
struct skl_wm_values skl_hw;
|
||||
};
|
||||
} wm;
|
||||
|
||||
struct i915_runtime_pm pm;
|
||||
@ -1856,8 +1925,6 @@ struct drm_i915_gem_object {
|
||||
unsigned long gt_ro:1;
|
||||
unsigned int cache_level:3;
|
||||
|
||||
unsigned int has_aliasing_ppgtt_mapping:1;
|
||||
unsigned int has_global_gtt_mapping:1;
|
||||
unsigned int has_dma_mapping:1;
|
||||
|
||||
unsigned int frontbuffer_bits:INTEL_FRONTBUFFER_BITS;
|
||||
@ -2292,8 +2359,6 @@ __printf(3, 4)
|
||||
void i915_handle_error(struct drm_device *dev, bool wedged,
|
||||
const char *fmt, ...);
|
||||
|
||||
void gen6_set_pm_mask(struct drm_i915_private *dev_priv, u32 pm_iir,
|
||||
int new_delay);
|
||||
extern void intel_irq_init(struct drm_i915_private *dev_priv);
|
||||
extern void intel_hpd_init(struct drm_i915_private *dev_priv);
|
||||
int intel_irq_install(struct drm_i915_private *dev_priv);
|
||||
@ -2531,6 +2596,11 @@ int __i915_add_request(struct intel_engine_cs *ring,
|
||||
u32 *seqno);
|
||||
#define i915_add_request(ring, seqno) \
|
||||
__i915_add_request(ring, NULL, NULL, seqno)
|
||||
int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno,
|
||||
unsigned reset_counter,
|
||||
bool interruptible,
|
||||
s64 *timeout,
|
||||
struct drm_i915_file_private *file_priv);
|
||||
int __must_check i915_wait_seqno(struct intel_engine_cs *ring,
|
||||
uint32_t seqno);
|
||||
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
|
||||
@ -2800,7 +2870,6 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
|
||||
extern void intel_i2c_reset(struct drm_device *dev);
|
||||
|
||||
/* intel_opregion.c */
|
||||
struct intel_encoder;
|
||||
#ifdef CONFIG_ACPI
|
||||
extern int intel_opregion_setup(struct drm_device *dev);
|
||||
extern void intel_opregion_init(struct drm_device *dev);
|
||||
@ -2917,7 +2986,9 @@ int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val);
|
||||
|
||||
#define FORCEWAKE_RENDER (1 << 0)
|
||||
#define FORCEWAKE_MEDIA (1 << 1)
|
||||
#define FORCEWAKE_ALL (FORCEWAKE_RENDER | FORCEWAKE_MEDIA)
|
||||
#define FORCEWAKE_BLITTER (1 << 2)
|
||||
#define FORCEWAKE_ALL (FORCEWAKE_RENDER | FORCEWAKE_MEDIA | \
|
||||
FORCEWAKE_BLITTER)
|
||||
|
||||
|
||||
#define I915_READ8(reg) dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true)
|
||||
|
@ -1134,7 +1134,7 @@ static bool can_wait_boost(struct drm_i915_file_private *file_priv)
|
||||
}
|
||||
|
||||
/**
|
||||
* __wait_seqno - wait until execution of seqno has finished
|
||||
* __i915_wait_seqno - wait until execution of seqno has finished
|
||||
* @ring: the ring expected to report seqno
|
||||
* @seqno: duh!
|
||||
* @reset_counter: reset sequence associated with the given seqno
|
||||
@ -1151,7 +1151,7 @@ static bool can_wait_boost(struct drm_i915_file_private *file_priv)
|
||||
* Returns 0 if the seqno was found within the alloted time. Else returns the
|
||||
* errno with remaining time filled in timeout argument.
|
||||
*/
|
||||
static int __wait_seqno(struct intel_engine_cs *ring, u32 seqno,
|
||||
int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno,
|
||||
unsigned reset_counter,
|
||||
bool interruptible,
|
||||
s64 *timeout,
|
||||
@ -1262,6 +1262,7 @@ i915_wait_seqno(struct intel_engine_cs *ring, uint32_t seqno)
|
||||
struct drm_device *dev = ring->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
bool interruptible = dev_priv->mm.interruptible;
|
||||
unsigned reset_counter;
|
||||
int ret;
|
||||
|
||||
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
|
||||
@ -1275,14 +1276,13 @@ i915_wait_seqno(struct intel_engine_cs *ring, uint32_t seqno)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return __wait_seqno(ring, seqno,
|
||||
atomic_read(&dev_priv->gpu_error.reset_counter),
|
||||
interruptible, NULL, NULL);
|
||||
reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
|
||||
return __i915_wait_seqno(ring, seqno, reset_counter, interruptible,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
i915_gem_object_wait_rendering__tail(struct drm_i915_gem_object *obj,
|
||||
struct intel_engine_cs *ring)
|
||||
i915_gem_object_wait_rendering__tail(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
if (!obj->active)
|
||||
return 0;
|
||||
@ -1319,7 +1319,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return i915_gem_object_wait_rendering__tail(obj, ring);
|
||||
return i915_gem_object_wait_rendering__tail(obj);
|
||||
}
|
||||
|
||||
/* A nonblocking variant of the above wait. This is a highly dangerous routine
|
||||
@ -1354,12 +1354,13 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
|
||||
|
||||
reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, file_priv);
|
||||
ret = __i915_wait_seqno(ring, seqno, reset_counter, true, NULL,
|
||||
file_priv);
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return i915_gem_object_wait_rendering__tail(obj, ring);
|
||||
return i915_gem_object_wait_rendering__tail(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2848,8 +2849,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
|
||||
reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return __wait_seqno(ring, seqno, reset_counter, true, &args->timeout_ns,
|
||||
file->driver_priv);
|
||||
return __i915_wait_seqno(ring, seqno, reset_counter, true,
|
||||
&args->timeout_ns, file->driver_priv);
|
||||
|
||||
out:
|
||||
drm_gem_object_unreference(&obj->base);
|
||||
@ -3477,23 +3478,9 @@ search_free:
|
||||
list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
|
||||
list_add_tail(&vma->mm_list, &vm->inactive_list);
|
||||
|
||||
if (i915_is_ggtt(vm)) {
|
||||
bool mappable, fenceable;
|
||||
|
||||
fenceable = (vma->node.size == fence_size &&
|
||||
(vma->node.start & (fence_alignment - 1)) == 0);
|
||||
|
||||
mappable = (vma->node.start + obj->base.size <=
|
||||
dev_priv->gtt.mappable_end);
|
||||
|
||||
obj->map_and_fenceable = mappable && fenceable;
|
||||
}
|
||||
|
||||
WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable);
|
||||
|
||||
trace_i915_vma_bind(vma, flags);
|
||||
vma->bind_vma(vma, obj->cache_level,
|
||||
flags & (PIN_MAPPABLE | PIN_GLOBAL) ? GLOBAL_BIND : 0);
|
||||
flags & PIN_GLOBAL ? GLOBAL_BIND : 0);
|
||||
|
||||
return vma;
|
||||
|
||||
@ -3701,7 +3688,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
|
||||
list_for_each_entry(vma, &obj->vma_list, vma_link)
|
||||
if (drm_mm_node_allocated(&vma->node))
|
||||
vma->bind_vma(vma, cache_level,
|
||||
obj->has_global_gtt_mapping ? GLOBAL_BIND : 0);
|
||||
vma->bound & GLOBAL_BIND);
|
||||
}
|
||||
|
||||
list_for_each_entry(vma, &obj->vma_list, vma_link)
|
||||
@ -4028,7 +4015,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
|
||||
if (seqno == 0)
|
||||
return 0;
|
||||
|
||||
ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, NULL);
|
||||
ret = __i915_wait_seqno(ring, seqno, reset_counter, true, NULL, NULL);
|
||||
if (ret == 0)
|
||||
queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0);
|
||||
|
||||
@ -4062,6 +4049,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
|
||||
{
|
||||
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
|
||||
struct i915_vma *vma;
|
||||
unsigned bound;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base))
|
||||
@ -4070,6 +4058,9 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
|
||||
if (WARN_ON(flags & (PIN_GLOBAL | PIN_MAPPABLE) && !i915_is_ggtt(vm)))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON((flags & (PIN_MAPPABLE | PIN_GLOBAL)) == PIN_MAPPABLE))
|
||||
return -EINVAL;
|
||||
|
||||
vma = i915_gem_obj_to_vma(obj, vm);
|
||||
if (vma) {
|
||||
if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
|
||||
@ -4091,15 +4082,39 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
|
||||
}
|
||||
}
|
||||
|
||||
bound = vma ? vma->bound : 0;
|
||||
if (vma == NULL || !drm_mm_node_allocated(&vma->node)) {
|
||||
vma = i915_gem_object_bind_to_vm(obj, vm, alignment, flags);
|
||||
if (IS_ERR(vma))
|
||||
return PTR_ERR(vma);
|
||||
}
|
||||
|
||||
if (flags & PIN_GLOBAL && !obj->has_global_gtt_mapping)
|
||||
if (flags & PIN_GLOBAL && !(vma->bound & GLOBAL_BIND))
|
||||
vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND);
|
||||
|
||||
if ((bound ^ vma->bound) & GLOBAL_BIND) {
|
||||
bool mappable, fenceable;
|
||||
u32 fence_size, fence_alignment;
|
||||
|
||||
fence_size = i915_gem_get_gtt_size(obj->base.dev,
|
||||
obj->base.size,
|
||||
obj->tiling_mode);
|
||||
fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev,
|
||||
obj->base.size,
|
||||
obj->tiling_mode,
|
||||
true);
|
||||
|
||||
fenceable = (vma->node.size == fence_size &&
|
||||
(vma->node.start & (fence_alignment - 1)) == 0);
|
||||
|
||||
mappable = (vma->node.start + obj->base.size <=
|
||||
dev_priv->gtt.mappable_end);
|
||||
|
||||
obj->map_and_fenceable = mappable && fenceable;
|
||||
}
|
||||
|
||||
WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable);
|
||||
|
||||
vma->pin_count++;
|
||||
if (flags & PIN_MAPPABLE)
|
||||
obj->pin_mappable |= true;
|
||||
|
@ -522,6 +522,7 @@ static int do_switch(struct intel_engine_cs *ring,
|
||||
struct intel_context *from = ring->last_context;
|
||||
u32 hw_flags = 0;
|
||||
bool uninitialized = false;
|
||||
struct i915_vma *vma;
|
||||
int ret, i;
|
||||
|
||||
if (from != NULL && ring == &dev_priv->ring[RCS]) {
|
||||
@ -571,11 +572,10 @@ static int do_switch(struct intel_engine_cs *ring,
|
||||
if (ret)
|
||||
goto unpin_out;
|
||||
|
||||
if (!to->legacy_hw_ctx.rcs_state->has_global_gtt_mapping) {
|
||||
struct i915_vma *vma = i915_gem_obj_to_vma(to->legacy_hw_ctx.rcs_state,
|
||||
&dev_priv->gtt.base);
|
||||
vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level, GLOBAL_BIND);
|
||||
}
|
||||
vma = i915_gem_obj_to_ggtt(to->legacy_hw_ctx.rcs_state);
|
||||
if (!(vma->bound & GLOBAL_BIND))
|
||||
vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level,
|
||||
GLOBAL_BIND);
|
||||
|
||||
if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to))
|
||||
hw_flags |= MI_RESTORE_INHIBIT;
|
||||
|
@ -357,12 +357,9 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
|
||||
* through the ppgtt for non_secure batchbuffers. */
|
||||
if (unlikely(IS_GEN6(dev) &&
|
||||
reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
|
||||
!target_i915_obj->has_global_gtt_mapping)) {
|
||||
struct i915_vma *vma =
|
||||
list_first_entry(&target_i915_obj->vma_list,
|
||||
typeof(*vma), vma_link);
|
||||
vma->bind_vma(vma, target_i915_obj->cache_level, GLOBAL_BIND);
|
||||
}
|
||||
!(target_vma->bound & GLOBAL_BIND)))
|
||||
target_vma->bind_vma(target_vma, target_i915_obj->cache_level,
|
||||
GLOBAL_BIND);
|
||||
|
||||
/* Validate that the target is in a valid r/w GPU domain */
|
||||
if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) {
|
||||
@ -531,7 +528,7 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
|
||||
|
||||
flags = 0;
|
||||
if (entry->flags & __EXEC_OBJECT_NEEDS_MAP)
|
||||
flags |= PIN_MAPPABLE;
|
||||
flags |= PIN_GLOBAL | PIN_MAPPABLE;
|
||||
if (entry->flags & EXEC_OBJECT_NEEDS_GTT)
|
||||
flags |= PIN_GLOBAL;
|
||||
if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS)
|
||||
@ -1368,17 +1365,19 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
batch_obj,
|
||||
args->batch_start_offset,
|
||||
file->is_master);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* XXX: Actually do this when enabling batch copy...
|
||||
*
|
||||
* Set the DISPATCH_SECURE bit to remove the NON_SECURE bit
|
||||
* from MI_BATCH_BUFFER_START commands issued in the
|
||||
* dispatch_execbuffer implementations. We specifically don't
|
||||
* want that set when the command parser is enabled.
|
||||
*/
|
||||
if (ret) {
|
||||
if (ret != -EACCES)
|
||||
goto err;
|
||||
} else {
|
||||
/*
|
||||
* XXX: Actually do this when enabling batch copy...
|
||||
*
|
||||
* Set the DISPATCH_SECURE bit to remove the NON_SECURE bit
|
||||
* from MI_BATCH_BUFFER_START commands issued in the
|
||||
* dispatch_execbuffer implementations. We specifically don't
|
||||
* want that set when the command parser is enabled.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
|
||||
|
@ -1266,7 +1266,7 @@ void i915_check_and_clear_faults(struct drm_device *dev)
|
||||
fault_reg = I915_READ(RING_FAULT_REG(ring));
|
||||
if (fault_reg & RING_FAULT_VALID) {
|
||||
DRM_DEBUG_DRIVER("Unexpected fault\n"
|
||||
"\tAddr: 0x%08lx\\n"
|
||||
"\tAddr: 0x%08lx\n"
|
||||
"\tAddress space: %s\n"
|
||||
"\tSource ID: %d\n"
|
||||
"\tType: %d\n",
|
||||
@ -1336,7 +1336,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
|
||||
* Unfortunately above, we've just wiped out the mappings
|
||||
* without telling our object about it. So we need to fake it.
|
||||
*/
|
||||
obj->has_global_gtt_mapping = 0;
|
||||
vma->bound &= ~GLOBAL_BIND;
|
||||
vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND);
|
||||
}
|
||||
|
||||
@ -1533,7 +1533,7 @@ static void i915_ggtt_bind_vma(struct i915_vma *vma,
|
||||
|
||||
BUG_ON(!i915_is_ggtt(vma->vm));
|
||||
intel_gtt_insert_sg_entries(vma->obj->pages, entry, flags);
|
||||
vma->obj->has_global_gtt_mapping = 1;
|
||||
vma->bound = GLOBAL_BIND;
|
||||
}
|
||||
|
||||
static void i915_ggtt_clear_range(struct i915_address_space *vm,
|
||||
@ -1552,7 +1552,7 @@ static void i915_ggtt_unbind_vma(struct i915_vma *vma)
|
||||
const unsigned int size = vma->obj->base.size >> PAGE_SHIFT;
|
||||
|
||||
BUG_ON(!i915_is_ggtt(vma->vm));
|
||||
vma->obj->has_global_gtt_mapping = 0;
|
||||
vma->bound = 0;
|
||||
intel_gtt_clear_range(first, size);
|
||||
}
|
||||
|
||||
@ -1580,24 +1580,24 @@ static void ggtt_bind_vma(struct i915_vma *vma,
|
||||
* flags. At all other times, the GPU will use the aliasing PPGTT.
|
||||
*/
|
||||
if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) {
|
||||
if (!obj->has_global_gtt_mapping ||
|
||||
if (!(vma->bound & GLOBAL_BIND) ||
|
||||
(cache_level != obj->cache_level)) {
|
||||
vma->vm->insert_entries(vma->vm, obj->pages,
|
||||
vma->node.start,
|
||||
cache_level, flags);
|
||||
obj->has_global_gtt_mapping = 1;
|
||||
vma->bound |= GLOBAL_BIND;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev_priv->mm.aliasing_ppgtt &&
|
||||
(!obj->has_aliasing_ppgtt_mapping ||
|
||||
(!(vma->bound & LOCAL_BIND) ||
|
||||
(cache_level != obj->cache_level))) {
|
||||
struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
|
||||
appgtt->base.insert_entries(&appgtt->base,
|
||||
vma->obj->pages,
|
||||
vma->node.start,
|
||||
cache_level, flags);
|
||||
vma->obj->has_aliasing_ppgtt_mapping = 1;
|
||||
vma->bound |= LOCAL_BIND;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1607,21 +1607,21 @@ static void ggtt_unbind_vma(struct i915_vma *vma)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
|
||||
if (obj->has_global_gtt_mapping) {
|
||||
if (vma->bound & GLOBAL_BIND) {
|
||||
vma->vm->clear_range(vma->vm,
|
||||
vma->node.start,
|
||||
obj->base.size,
|
||||
true);
|
||||
obj->has_global_gtt_mapping = 0;
|
||||
vma->bound &= ~GLOBAL_BIND;
|
||||
}
|
||||
|
||||
if (obj->has_aliasing_ppgtt_mapping) {
|
||||
if (vma->bound & LOCAL_BIND) {
|
||||
struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
|
||||
appgtt->base.clear_range(&appgtt->base,
|
||||
vma->node.start,
|
||||
obj->base.size,
|
||||
true);
|
||||
obj->has_aliasing_ppgtt_mapping = 0;
|
||||
vma->bound &= ~LOCAL_BIND;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1699,7 +1699,7 @@ int i915_gem_setup_global_gtt(struct drm_device *dev,
|
||||
DRM_DEBUG_KMS("Reservation failed: %i\n", ret);
|
||||
return ret;
|
||||
}
|
||||
obj->has_global_gtt_mapping = 1;
|
||||
vma->bound |= GLOBAL_BIND;
|
||||
}
|
||||
|
||||
dev_priv->gtt.base.start = start;
|
||||
|
@ -123,6 +123,12 @@ struct i915_vma {
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_address_space *vm;
|
||||
|
||||
/** Flags and address space this VMA is bound to */
|
||||
#define GLOBAL_BIND (1<<0)
|
||||
#define LOCAL_BIND (1<<1)
|
||||
#define PTE_READ_ONLY (1<<2)
|
||||
unsigned int bound : 4;
|
||||
|
||||
/** This object's place on the active/inactive lists */
|
||||
struct list_head mm_list;
|
||||
|
||||
@ -155,8 +161,6 @@ struct i915_vma {
|
||||
* setting the valid PTE entries to a reserved scratch page. */
|
||||
void (*unbind_vma)(struct i915_vma *vma);
|
||||
/* Map an object into an address space with the given cache flags. */
|
||||
#define GLOBAL_BIND (1<<0)
|
||||
#define PTE_READ_ONLY (1<<1)
|
||||
void (*bind_vma)(struct i915_vma *vma,
|
||||
enum i915_cache_level cache_level,
|
||||
u32 flags);
|
||||
|
@ -38,6 +38,8 @@ render_state_get_rodata(struct drm_device *dev, const int gen)
|
||||
return &gen7_null_state;
|
||||
case 8:
|
||||
return &gen8_null_state;
|
||||
case 9:
|
||||
return &gen9_null_state;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -533,7 +533,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
obj->has_global_gtt_mapping = 1;
|
||||
vma->bound |= GLOBAL_BIND;
|
||||
|
||||
list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
|
||||
list_add_tail(&vma->mm_list, &ggtt->inactive_list);
|
||||
|
@ -458,6 +458,7 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
/* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
|
||||
args->phys_swizzle_mode = args->swizzle_mode;
|
||||
if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
|
||||
args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
|
||||
if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
|
||||
|
@ -565,6 +565,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
|
||||
struct i915_address_space *vm)
|
||||
{
|
||||
struct drm_i915_error_object *dst;
|
||||
struct i915_vma *vma = NULL;
|
||||
int num_pages;
|
||||
bool use_ggtt;
|
||||
int i = 0;
|
||||
@ -585,16 +586,17 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
|
||||
dst->gtt_offset = -1;
|
||||
|
||||
reloc_offset = dst->gtt_offset;
|
||||
if (i915_is_ggtt(vm))
|
||||
vma = i915_gem_obj_to_ggtt(src);
|
||||
use_ggtt = (src->cache_level == I915_CACHE_NONE &&
|
||||
i915_is_ggtt(vm) &&
|
||||
src->has_global_gtt_mapping &&
|
||||
reloc_offset + num_pages * PAGE_SIZE <= dev_priv->gtt.mappable_end);
|
||||
vma && (vma->bound & GLOBAL_BIND) &&
|
||||
reloc_offset + num_pages * PAGE_SIZE <= dev_priv->gtt.mappable_end);
|
||||
|
||||
/* Cannot access stolen address directly, try to use the aperture */
|
||||
if (src->stolen) {
|
||||
use_ggtt = true;
|
||||
|
||||
if (!src->has_global_gtt_mapping)
|
||||
if (!(vma && vma->bound & GLOBAL_BIND))
|
||||
goto unwind;
|
||||
|
||||
reloc_offset = i915_gem_obj_ggtt_offset(src);
|
||||
@ -1240,7 +1242,8 @@ static void i915_error_capture_msg(struct drm_device *dev,
|
||||
ecode = i915_error_generate_code(dev_priv, error, &ring_id);
|
||||
|
||||
len = scnprintf(error->error_msg, sizeof(error->error_msg),
|
||||
"GPU HANG: ecode %d:0x%08x", ring_id, ecode);
|
||||
"GPU HANG: ecode %d:%d:0x%08x",
|
||||
INTEL_INFO(dev)->gen, ring_id, ecode);
|
||||
|
||||
if (ring_id != -1 && error->ring[ring_id].pid != -1)
|
||||
len += scnprintf(error->error_msg + len,
|
||||
|
@ -126,16 +126,16 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
|
||||
|
||||
#define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \
|
||||
GEN5_ASSERT_IIR_IS_ZERO(GEN8_##type##_IIR(which)); \
|
||||
I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \
|
||||
I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \
|
||||
POSTING_READ(GEN8_##type##_IER(which)); \
|
||||
I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \
|
||||
POSTING_READ(GEN8_##type##_IMR(which)); \
|
||||
} while (0)
|
||||
|
||||
#define GEN5_IRQ_INIT(type, imr_val, ier_val) do { \
|
||||
GEN5_ASSERT_IIR_IS_ZERO(type##IIR); \
|
||||
I915_WRITE(type##IMR, (imr_val)); \
|
||||
I915_WRITE(type##IER, (ier_val)); \
|
||||
POSTING_READ(type##IER); \
|
||||
I915_WRITE(type##IMR, (imr_val)); \
|
||||
POSTING_READ(type##IMR); \
|
||||
} while (0)
|
||||
|
||||
/* For display hotplug interrupt */
|
||||
@ -979,9 +979,6 @@ static void notify_ring(struct drm_device *dev,
|
||||
|
||||
trace_i915_gem_request_complete(ring);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
intel_notify_mmio_flip(ring);
|
||||
|
||||
wake_up_all(&ring->irq_queue);
|
||||
i915_queue_hangcheck(dev);
|
||||
}
|
||||
@ -3105,10 +3102,22 @@ static void ironlake_irq_reset(struct drm_device *dev)
|
||||
ibx_irq_reset(dev);
|
||||
}
|
||||
|
||||
static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
enum pipe pipe;
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
I915_WRITE(PIPESTAT(pipe), 0xffff);
|
||||
|
||||
GEN5_IRQ_RESET(VLV_);
|
||||
}
|
||||
|
||||
static void valleyview_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int pipe;
|
||||
|
||||
/* VLV magic */
|
||||
I915_WRITE(VLV_IMR, 0);
|
||||
@ -3116,22 +3125,11 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
|
||||
I915_WRITE(RING_IMR(GEN6_BSD_RING_BASE), 0);
|
||||
I915_WRITE(RING_IMR(BLT_RING_BASE), 0);
|
||||
|
||||
/* and GT */
|
||||
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
||||
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
||||
|
||||
gen5_gt_irq_reset(dev);
|
||||
|
||||
I915_WRITE(DPINVGTT, 0xff);
|
||||
I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK);
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
I915_WRITE(PIPESTAT(pipe), 0xffff);
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
I915_WRITE(VLV_IMR, 0xffffffff);
|
||||
I915_WRITE(VLV_IER, 0x0);
|
||||
POSTING_READ(VLV_IER);
|
||||
vlv_display_irq_reset(dev_priv);
|
||||
}
|
||||
|
||||
static void gen8_gt_irq_reset(struct drm_i915_private *dev_priv)
|
||||
@ -3179,7 +3177,6 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv)
|
||||
static void cherryview_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int pipe;
|
||||
|
||||
I915_WRITE(GEN8_MASTER_IRQ, 0);
|
||||
POSTING_READ(GEN8_MASTER_IRQ);
|
||||
@ -3188,20 +3185,9 @@ static void cherryview_irq_preinstall(struct drm_device *dev)
|
||||
|
||||
GEN5_IRQ_RESET(GEN8_PCU_);
|
||||
|
||||
POSTING_READ(GEN8_PCU_IIR);
|
||||
|
||||
I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
I915_WRITE(PIPESTAT(pipe), 0xffff);
|
||||
|
||||
I915_WRITE(VLV_IMR, 0xffffffff);
|
||||
I915_WRITE(VLV_IER, 0x0);
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
POSTING_READ(VLV_IIR);
|
||||
vlv_display_irq_reset(dev_priv);
|
||||
}
|
||||
|
||||
static void ibx_hpd_irq_setup(struct drm_device *dev)
|
||||
@ -3342,45 +3328,51 @@ static void valleyview_display_irqs_install(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 pipestat_mask;
|
||||
u32 iir_mask;
|
||||
enum pipe pipe;
|
||||
|
||||
pipestat_mask = PIPESTAT_INT_STATUS_MASK |
|
||||
PIPE_FIFO_UNDERRUN_STATUS;
|
||||
|
||||
I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
|
||||
I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
I915_WRITE(PIPESTAT(pipe), pipestat_mask);
|
||||
POSTING_READ(PIPESTAT(PIPE_A));
|
||||
|
||||
pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
|
||||
PIPE_CRC_DONE_INTERRUPT_STATUS;
|
||||
|
||||
i915_enable_pipestat(dev_priv, PIPE_A, pipestat_mask |
|
||||
PIPE_GMBUS_INTERRUPT_STATUS);
|
||||
i915_enable_pipestat(dev_priv, PIPE_B, pipestat_mask);
|
||||
i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
|
||||
|
||||
iir_mask = I915_DISPLAY_PORT_INTERRUPT |
|
||||
I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
|
||||
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
|
||||
if (IS_CHERRYVIEW(dev_priv))
|
||||
iir_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
|
||||
dev_priv->irq_mask &= ~iir_mask;
|
||||
|
||||
I915_WRITE(VLV_IIR, iir_mask);
|
||||
I915_WRITE(VLV_IIR, iir_mask);
|
||||
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
|
||||
I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
|
||||
POSTING_READ(VLV_IER);
|
||||
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
|
||||
POSTING_READ(VLV_IMR);
|
||||
}
|
||||
|
||||
static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 pipestat_mask;
|
||||
u32 iir_mask;
|
||||
enum pipe pipe;
|
||||
|
||||
iir_mask = I915_DISPLAY_PORT_INTERRUPT |
|
||||
I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
|
||||
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
|
||||
if (IS_CHERRYVIEW(dev_priv))
|
||||
iir_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
|
||||
|
||||
dev_priv->irq_mask |= iir_mask;
|
||||
I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
|
||||
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
|
||||
I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
|
||||
I915_WRITE(VLV_IIR, iir_mask);
|
||||
I915_WRITE(VLV_IIR, iir_mask);
|
||||
POSTING_READ(VLV_IIR);
|
||||
@ -3388,14 +3380,15 @@ static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
|
||||
pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
|
||||
PIPE_CRC_DONE_INTERRUPT_STATUS;
|
||||
|
||||
i915_disable_pipestat(dev_priv, PIPE_A, pipestat_mask |
|
||||
PIPE_GMBUS_INTERRUPT_STATUS);
|
||||
i915_disable_pipestat(dev_priv, PIPE_B, pipestat_mask);
|
||||
i915_disable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
i915_disable_pipestat(dev_priv, pipe, pipestat_mask);
|
||||
|
||||
pipestat_mask = PIPESTAT_INT_STATUS_MASK |
|
||||
PIPE_FIFO_UNDERRUN_STATUS;
|
||||
I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
|
||||
I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
|
||||
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
I915_WRITE(PIPESTAT(pipe), pipestat_mask);
|
||||
POSTING_READ(PIPESTAT(PIPE_A));
|
||||
}
|
||||
|
||||
@ -3425,19 +3418,18 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
|
||||
valleyview_display_irqs_uninstall(dev_priv);
|
||||
}
|
||||
|
||||
static int valleyview_irq_postinstall(struct drm_device *dev)
|
||||
static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
dev_priv->irq_mask = ~0;
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
POSTING_READ(PORT_HOTPLUG_EN);
|
||||
|
||||
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
|
||||
I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
POSTING_READ(VLV_IER);
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
|
||||
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
|
||||
POSTING_READ(VLV_IMR);
|
||||
|
||||
/* Interrupt setup is already guaranteed to be single-threaded, this is
|
||||
* just to make the assert_spin_locked check happy. */
|
||||
@ -3445,9 +3437,13 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
|
||||
if (dev_priv->display_irqs_enabled)
|
||||
valleyview_display_irqs_install(dev_priv);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
}
|
||||
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
static int valleyview_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
vlv_display_irq_postinstall(dev_priv);
|
||||
|
||||
gen5_gt_irq_postinstall(dev);
|
||||
|
||||
@ -3561,8 +3557,10 @@ static int cherryview_irq_postinstall(struct drm_device *dev)
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
I915_WRITE(VLV_IER, enable_mask);
|
||||
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
|
||||
POSTING_READ(VLV_IMR);
|
||||
|
||||
gen8_gt_irq_postinstall(dev_priv);
|
||||
|
||||
@ -3585,19 +3583,15 @@ static void gen8_irq_uninstall(struct drm_device *dev)
|
||||
static void valleyview_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int pipe;
|
||||
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
I915_WRITE(VLV_MASTER_IER, 0);
|
||||
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
I915_WRITE(PIPESTAT(pipe), 0xffff);
|
||||
gen5_gt_irq_reset(dev);
|
||||
|
||||
I915_WRITE(HWSTAM, 0xffffffff);
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
|
||||
/* Interrupt setup is already guaranteed to be single-threaded, this is
|
||||
* just to make the assert_spin_locked check happy. */
|
||||
@ -3606,12 +3600,9 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
|
||||
valleyview_display_irqs_uninstall(dev_priv);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
|
||||
dev_priv->irq_mask = 0;
|
||||
vlv_display_irq_reset(dev_priv);
|
||||
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
I915_WRITE(VLV_IMR, 0xffffffff);
|
||||
I915_WRITE(VLV_IER, 0x0);
|
||||
POSTING_READ(VLV_IER);
|
||||
dev_priv->irq_mask = 0;
|
||||
}
|
||||
|
||||
static void cherryview_irq_uninstall(struct drm_device *dev)
|
||||
@ -3625,33 +3616,9 @@ static void cherryview_irq_uninstall(struct drm_device *dev)
|
||||
I915_WRITE(GEN8_MASTER_IRQ, 0);
|
||||
POSTING_READ(GEN8_MASTER_IRQ);
|
||||
|
||||
#define GEN8_IRQ_FINI_NDX(type, which) \
|
||||
do { \
|
||||
I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
|
||||
I915_WRITE(GEN8_##type##_IER(which), 0); \
|
||||
I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
|
||||
POSTING_READ(GEN8_##type##_IIR(which)); \
|
||||
I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
|
||||
} while (0)
|
||||
gen8_gt_irq_reset(dev_priv);
|
||||
|
||||
#define GEN8_IRQ_FINI(type) \
|
||||
do { \
|
||||
I915_WRITE(GEN8_##type##_IMR, 0xffffffff); \
|
||||
I915_WRITE(GEN8_##type##_IER, 0); \
|
||||
I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \
|
||||
POSTING_READ(GEN8_##type##_IIR); \
|
||||
I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \
|
||||
} while (0)
|
||||
|
||||
GEN8_IRQ_FINI_NDX(GT, 0);
|
||||
GEN8_IRQ_FINI_NDX(GT, 1);
|
||||
GEN8_IRQ_FINI_NDX(GT, 2);
|
||||
GEN8_IRQ_FINI_NDX(GT, 3);
|
||||
|
||||
GEN8_IRQ_FINI(PCU);
|
||||
|
||||
#undef GEN8_IRQ_FINI
|
||||
#undef GEN8_IRQ_FINI_NDX
|
||||
GEN5_IRQ_RESET(GEN8_PCU_);
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN, 0);
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
@ -3659,10 +3626,7 @@ do { \
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
I915_WRITE(PIPESTAT(pipe), 0xffff);
|
||||
|
||||
I915_WRITE(VLV_IMR, 0xffffffff);
|
||||
I915_WRITE(VLV_IER, 0x0);
|
||||
I915_WRITE(VLV_IIR, 0xffffffff);
|
||||
POSTING_READ(VLV_IIR);
|
||||
GEN5_IRQ_RESET(VLV_);
|
||||
}
|
||||
|
||||
static void ironlake_irq_uninstall(struct drm_device *dev)
|
||||
|
@ -4102,6 +4102,41 @@ enum punit_power_well {
|
||||
#define I965_CURSOR_MAX_WM 32
|
||||
#define I965_CURSOR_DFT_WM 8
|
||||
|
||||
/* Watermark register definitions for SKL */
|
||||
#define CUR_WM_A_0 0x70140
|
||||
#define CUR_WM_B_0 0x71140
|
||||
#define PLANE_WM_1_A_0 0x70240
|
||||
#define PLANE_WM_1_B_0 0x71240
|
||||
#define PLANE_WM_2_A_0 0x70340
|
||||
#define PLANE_WM_2_B_0 0x71340
|
||||
#define PLANE_WM_TRANS_1_A_0 0x70268
|
||||
#define PLANE_WM_TRANS_1_B_0 0x71268
|
||||
#define PLANE_WM_TRANS_2_A_0 0x70368
|
||||
#define PLANE_WM_TRANS_2_B_0 0x71368
|
||||
#define CUR_WM_TRANS_A_0 0x70168
|
||||
#define CUR_WM_TRANS_B_0 0x71168
|
||||
#define PLANE_WM_EN (1 << 31)
|
||||
#define PLANE_WM_LINES_SHIFT 14
|
||||
#define PLANE_WM_LINES_MASK 0x1f
|
||||
#define PLANE_WM_BLOCKS_MASK 0x3ff
|
||||
|
||||
#define CUR_WM_0(pipe) _PIPE(pipe, CUR_WM_A_0, CUR_WM_B_0)
|
||||
#define CUR_WM(pipe, level) (CUR_WM_0(pipe) + ((4) * (level)))
|
||||
#define CUR_WM_TRANS(pipe) _PIPE(pipe, CUR_WM_TRANS_A_0, CUR_WM_TRANS_B_0)
|
||||
|
||||
#define _PLANE_WM_1(pipe) _PIPE(pipe, PLANE_WM_1_A_0, PLANE_WM_1_B_0)
|
||||
#define _PLANE_WM_2(pipe) _PIPE(pipe, PLANE_WM_2_A_0, PLANE_WM_2_B_0)
|
||||
#define _PLANE_WM_BASE(pipe, plane) \
|
||||
_PLANE(plane, _PLANE_WM_1(pipe), _PLANE_WM_2(pipe))
|
||||
#define PLANE_WM(pipe, plane, level) \
|
||||
(_PLANE_WM_BASE(pipe, plane) + ((4) * (level)))
|
||||
#define _PLANE_WM_TRANS_1(pipe) \
|
||||
_PIPE(pipe, PLANE_WM_TRANS_1_A_0, PLANE_WM_TRANS_1_B_0)
|
||||
#define _PLANE_WM_TRANS_2(pipe) \
|
||||
_PIPE(pipe, PLANE_WM_TRANS_2_A_0, PLANE_WM_TRANS_2_B_0)
|
||||
#define PLANE_WM_TRANS(pipe, plane) \
|
||||
_PLANE(plane, _PLANE_WM_TRANS_1(pipe), _PLANE_WM_TRANS_2(pipe))
|
||||
|
||||
/* define the Watermark register on Ironlake */
|
||||
#define WM0_PIPEA_ILK 0x45100
|
||||
#define WM0_PIPE_PLANE_MASK (0xffff<<16)
|
||||
@ -4272,9 +4307,11 @@ enum punit_power_well {
|
||||
#define DISPPLANE_NO_LINE_DOUBLE 0
|
||||
#define DISPPLANE_STEREO_POLARITY_FIRST 0
|
||||
#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
|
||||
#define DISPPLANE_ROTATE_180 (1<<15)
|
||||
#define DISPPLANE_ALPHA_PREMULTIPLY (1<<16) /* CHV pipe B */
|
||||
#define DISPPLANE_ROTATE_180 (1<<15)
|
||||
#define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* Ironlake */
|
||||
#define DISPPLANE_TILED (1<<10)
|
||||
#define DISPPLANE_MIRROR (1<<8) /* CHV pipe B */
|
||||
#define _DSPAADDR 0x70184
|
||||
#define _DSPASTRIDE 0x70188
|
||||
#define _DSPAPOS 0x7018C /* reserved */
|
||||
@ -4295,6 +4332,24 @@ enum punit_power_well {
|
||||
#define DSPOFFSET(plane) _PIPE2(plane, _DSPAOFFSET)
|
||||
#define DSPSURFLIVE(plane) _PIPE2(plane, _DSPASURFLIVE)
|
||||
|
||||
/* CHV pipe B blender and primary plane */
|
||||
#define _CHV_BLEND_A 0x60a00
|
||||
#define CHV_BLEND_LEGACY (0<<30)
|
||||
#define CHV_BLEND_ANDROID (1<<30)
|
||||
#define CHV_BLEND_MPO (2<<30)
|
||||
#define CHV_BLEND_MASK (3<<30)
|
||||
#define _CHV_CANVAS_A 0x60a04
|
||||
#define _PRIMPOS_A 0x60a08
|
||||
#define _PRIMSIZE_A 0x60a0c
|
||||
#define _PRIMCNSTALPHA_A 0x60a10
|
||||
#define PRIM_CONST_ALPHA_ENABLE (1<<31)
|
||||
|
||||
#define CHV_BLEND(pipe) _TRANSCODER2(pipe, _CHV_BLEND_A)
|
||||
#define CHV_CANVAS(pipe) _TRANSCODER2(pipe, _CHV_CANVAS_A)
|
||||
#define PRIMPOS(plane) _TRANSCODER2(plane, _PRIMPOS_A)
|
||||
#define PRIMSIZE(plane) _TRANSCODER2(plane, _PRIMSIZE_A)
|
||||
#define PRIMCNSTALPHA(plane) _TRANSCODER2(plane, _PRIMCNSTALPHA_A)
|
||||
|
||||
/* Display/Sprite base address macros */
|
||||
#define DISP_BASEADDR_MASK (0xfffff000)
|
||||
#define I915_LO_DISPBASE(val) (val & ~DISP_BASEADDR_MASK)
|
||||
@ -4496,6 +4551,7 @@ enum punit_power_well {
|
||||
#define SP_FORMAT_RGBA1010102 (9<<26)
|
||||
#define SP_FORMAT_RGBX8888 (0xe<<26)
|
||||
#define SP_FORMAT_RGBA8888 (0xf<<26)
|
||||
#define SP_ALPHA_PREMULTIPLY (1<<23) /* CHV pipe B */
|
||||
#define SP_SOURCE_KEY (1<<22)
|
||||
#define SP_YUV_BYTE_ORDER_MASK (3<<16)
|
||||
#define SP_YUV_ORDER_YUYV (0<<16)
|
||||
@ -4504,6 +4560,7 @@ enum punit_power_well {
|
||||
#define SP_YUV_ORDER_VYUY (3<<16)
|
||||
#define SP_ROTATE_180 (1<<15)
|
||||
#define SP_TILED (1<<10)
|
||||
#define SP_MIRROR (1<<8) /* CHV pipe B */
|
||||
#define _SPALINOFF (VLV_DISPLAY_BASE + 0x72184)
|
||||
#define _SPASTRIDE (VLV_DISPLAY_BASE + 0x72188)
|
||||
#define _SPAPOS (VLV_DISPLAY_BASE + 0x7218c)
|
||||
@ -4514,6 +4571,7 @@ enum punit_power_well {
|
||||
#define _SPAKEYMAXVAL (VLV_DISPLAY_BASE + 0x721a0)
|
||||
#define _SPATILEOFF (VLV_DISPLAY_BASE + 0x721a4)
|
||||
#define _SPACONSTALPHA (VLV_DISPLAY_BASE + 0x721a8)
|
||||
#define SP_CONST_ALPHA_ENABLE (1<<31)
|
||||
#define _SPAGAMC (VLV_DISPLAY_BASE + 0x721f4)
|
||||
|
||||
#define _SPBCNTR (VLV_DISPLAY_BASE + 0x72280)
|
||||
@ -4542,6 +4600,39 @@ enum punit_power_well {
|
||||
#define SPCONSTALPHA(pipe, plane) _PIPE(pipe * 2 + plane, _SPACONSTALPHA, _SPBCONSTALPHA)
|
||||
#define SPGAMC(pipe, plane) _PIPE(pipe * 2 + plane, _SPAGAMC, _SPBGAMC)
|
||||
|
||||
/*
|
||||
* CHV pipe B sprite CSC
|
||||
*
|
||||
* |cr| |c0 c1 c2| |cr + cr_ioff| |cr_ooff|
|
||||
* |yg| = |c3 c4 c5| x |yg + yg_ioff| + |yg_ooff|
|
||||
* |cb| |c6 c7 c8| |cb + cr_ioff| |cb_ooff|
|
||||
*/
|
||||
#define SPCSCYGOFF(sprite) (VLV_DISPLAY_BASE + 0x6d900 + (sprite) * 0x1000)
|
||||
#define SPCSCCBOFF(sprite) (VLV_DISPLAY_BASE + 0x6d904 + (sprite) * 0x1000)
|
||||
#define SPCSCCROFF(sprite) (VLV_DISPLAY_BASE + 0x6d908 + (sprite) * 0x1000)
|
||||
#define SPCSC_OOFF(x) (((x) & 0x7ff) << 16) /* s11 */
|
||||
#define SPCSC_IOFF(x) (((x) & 0x7ff) << 0) /* s11 */
|
||||
|
||||
#define SPCSCC01(sprite) (VLV_DISPLAY_BASE + 0x6d90c + (sprite) * 0x1000)
|
||||
#define SPCSCC23(sprite) (VLV_DISPLAY_BASE + 0x6d910 + (sprite) * 0x1000)
|
||||
#define SPCSCC45(sprite) (VLV_DISPLAY_BASE + 0x6d914 + (sprite) * 0x1000)
|
||||
#define SPCSCC67(sprite) (VLV_DISPLAY_BASE + 0x6d918 + (sprite) * 0x1000)
|
||||
#define SPCSCC8(sprite) (VLV_DISPLAY_BASE + 0x6d91c + (sprite) * 0x1000)
|
||||
#define SPCSC_C1(x) (((x) & 0x7fff) << 16) /* s3.12 */
|
||||
#define SPCSC_C0(x) (((x) & 0x7fff) << 0) /* s3.12 */
|
||||
|
||||
#define SPCSCYGICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d920 + (sprite) * 0x1000)
|
||||
#define SPCSCCBICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d924 + (sprite) * 0x1000)
|
||||
#define SPCSCCRICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d928 + (sprite) * 0x1000)
|
||||
#define SPCSC_IMAX(x) (((x) & 0x7ff) << 16) /* s11 */
|
||||
#define SPCSC_IMIN(x) (((x) & 0x7ff) << 0) /* s11 */
|
||||
|
||||
#define SPCSCYGOCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d92c + (sprite) * 0x1000)
|
||||
#define SPCSCCBOCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d930 + (sprite) * 0x1000)
|
||||
#define SPCSCCROCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d934 + (sprite) * 0x1000)
|
||||
#define SPCSC_OMAX(x) ((x) << 16) /* u10 */
|
||||
#define SPCSC_OMIN(x) ((x) << 0) /* u10 */
|
||||
|
||||
/* Skylake plane registers */
|
||||
|
||||
#define _PLANE_CTL_1_A 0x70180
|
||||
@ -4605,6 +4696,8 @@ enum punit_power_well {
|
||||
#define _PLANE_KEYMSK_2_A 0x70298
|
||||
#define _PLANE_KEYMAX_1_A 0x701a0
|
||||
#define _PLANE_KEYMAX_2_A 0x702a0
|
||||
#define _PLANE_BUF_CFG_1_A 0x7027c
|
||||
#define _PLANE_BUF_CFG_2_A 0x7037c
|
||||
|
||||
#define _PLANE_CTL_1_B 0x71180
|
||||
#define _PLANE_CTL_2_B 0x71280
|
||||
@ -4682,6 +4775,20 @@ enum punit_power_well {
|
||||
#define PLANE_KEYMAX(pipe, plane) \
|
||||
_PLANE(plane, _PLANE_KEYMAX_1(pipe), _PLANE_KEYMAX_2(pipe))
|
||||
|
||||
#define _PLANE_BUF_CFG_1_B 0x7127c
|
||||
#define _PLANE_BUF_CFG_2_B 0x7137c
|
||||
#define _PLANE_BUF_CFG_1(pipe) \
|
||||
_PIPE(pipe, _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B)
|
||||
#define _PLANE_BUF_CFG_2(pipe) \
|
||||
_PIPE(pipe, _PLANE_BUF_CFG_2_A, _PLANE_BUF_CFG_2_B)
|
||||
#define PLANE_BUF_CFG(pipe, plane) \
|
||||
_PLANE(plane, _PLANE_BUF_CFG_1(pipe), _PLANE_BUF_CFG_2(pipe))
|
||||
|
||||
/* SKL new cursor registers */
|
||||
#define _CUR_BUF_CFG_A 0x7017c
|
||||
#define _CUR_BUF_CFG_B 0x7117c
|
||||
#define CUR_BUF_CFG(pipe) _PIPE(pipe, _CUR_BUF_CFG_A, _CUR_BUF_CFG_B)
|
||||
|
||||
/* VBIOS regs */
|
||||
#define VGACNTRL 0x71400
|
||||
# define VGA_DISP_DISABLE (1 << 31)
|
||||
@ -5726,6 +5833,12 @@ enum punit_power_well {
|
||||
#define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5)
|
||||
#define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7)
|
||||
#define FORCEWAKE_MT 0xa188 /* multi-threaded */
|
||||
#define FORCEWAKE_MEDIA_GEN9 0xa270
|
||||
#define FORCEWAKE_RENDER_GEN9 0xa278
|
||||
#define FORCEWAKE_BLITTER_GEN9 0xa188
|
||||
#define FORCEWAKE_ACK_MEDIA_GEN9 0x0D88
|
||||
#define FORCEWAKE_ACK_RENDER_GEN9 0x0D84
|
||||
#define FORCEWAKE_ACK_BLITTER_GEN9 0x130044
|
||||
#define FORCEWAKE_KERNEL 0x1
|
||||
#define FORCEWAKE_USER 0x2
|
||||
#define FORCEWAKE_MT_ACK 0x130040
|
||||
@ -5901,6 +6014,13 @@ enum punit_power_well {
|
||||
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
|
||||
#define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16
|
||||
|
||||
#define GEN9_PCODE_DATA1 0x13812C
|
||||
#define GEN9_PCODE_READ_MEM_LATENCY 0x6
|
||||
#define GEN9_MEM_LATENCY_LEVEL_MASK 0xFF
|
||||
#define GEN9_MEM_LATENCY_LEVEL_1_5_SHIFT 8
|
||||
#define GEN9_MEM_LATENCY_LEVEL_2_6_SHIFT 16
|
||||
#define GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT 24
|
||||
|
||||
#define GEN6_GT_CORE_STATUS 0x138060
|
||||
#define GEN6_CORE_CPD_STATE_MASK (7<<4)
|
||||
#define GEN6_RCn_MASK 7
|
||||
@ -5955,57 +6075,58 @@ enum punit_power_well {
|
||||
#define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8)
|
||||
#define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1)
|
||||
|
||||
/* Audio */
|
||||
#define G4X_AUD_VID_DID (dev_priv->info.display_mmio_offset + 0x62020)
|
||||
#define INTEL_AUDIO_DEVCL 0x808629FB
|
||||
#define INTEL_AUDIO_DEVBLC 0x80862801
|
||||
#define INTEL_AUDIO_DEVCTG 0x80862802
|
||||
#define INTEL_AUDIO_DEVCL 0x808629FB
|
||||
#define INTEL_AUDIO_DEVBLC 0x80862801
|
||||
#define INTEL_AUDIO_DEVCTG 0x80862802
|
||||
|
||||
#define G4X_AUD_CNTL_ST 0x620B4
|
||||
#define G4X_ELDV_DEVCL_DEVBLC (1 << 13)
|
||||
#define G4X_ELDV_DEVCTG (1 << 14)
|
||||
#define G4X_ELD_ADDR (0xf << 5)
|
||||
#define G4X_ELD_ACK (1 << 4)
|
||||
#define G4X_ELDV_DEVCL_DEVBLC (1 << 13)
|
||||
#define G4X_ELDV_DEVCTG (1 << 14)
|
||||
#define G4X_ELD_ADDR_MASK (0xf << 5)
|
||||
#define G4X_ELD_ACK (1 << 4)
|
||||
#define G4X_HDMIW_HDMIEDID 0x6210C
|
||||
|
||||
#define IBX_HDMIW_HDMIEDID_A 0xE2050
|
||||
#define IBX_HDMIW_HDMIEDID_B 0xE2150
|
||||
#define _IBX_HDMIW_HDMIEDID_A 0xE2050
|
||||
#define _IBX_HDMIW_HDMIEDID_B 0xE2150
|
||||
#define IBX_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
|
||||
IBX_HDMIW_HDMIEDID_A, \
|
||||
IBX_HDMIW_HDMIEDID_B)
|
||||
#define IBX_AUD_CNTL_ST_A 0xE20B4
|
||||
#define IBX_AUD_CNTL_ST_B 0xE21B4
|
||||
_IBX_HDMIW_HDMIEDID_A, \
|
||||
_IBX_HDMIW_HDMIEDID_B)
|
||||
#define _IBX_AUD_CNTL_ST_A 0xE20B4
|
||||
#define _IBX_AUD_CNTL_ST_B 0xE21B4
|
||||
#define IBX_AUD_CNTL_ST(pipe) _PIPE(pipe, \
|
||||
IBX_AUD_CNTL_ST_A, \
|
||||
IBX_AUD_CNTL_ST_B)
|
||||
#define IBX_ELD_BUFFER_SIZE (0x1f << 10)
|
||||
#define IBX_ELD_ADDRESS (0x1f << 5)
|
||||
#define IBX_ELD_ACK (1 << 4)
|
||||
_IBX_AUD_CNTL_ST_A, \
|
||||
_IBX_AUD_CNTL_ST_B)
|
||||
#define IBX_ELD_BUFFER_SIZE_MASK (0x1f << 10)
|
||||
#define IBX_ELD_ADDRESS_MASK (0x1f << 5)
|
||||
#define IBX_ELD_ACK (1 << 4)
|
||||
#define IBX_AUD_CNTL_ST2 0xE20C0
|
||||
#define IBX_ELD_VALIDB (1 << 0)
|
||||
#define IBX_CP_READYB (1 << 1)
|
||||
#define IBX_CP_READY(port) ((1 << 1) << (((port) - 1) * 4))
|
||||
#define IBX_ELD_VALID(port) ((1 << 0) << (((port) - 1) * 4))
|
||||
|
||||
#define CPT_HDMIW_HDMIEDID_A 0xE5050
|
||||
#define CPT_HDMIW_HDMIEDID_B 0xE5150
|
||||
#define _CPT_HDMIW_HDMIEDID_A 0xE5050
|
||||
#define _CPT_HDMIW_HDMIEDID_B 0xE5150
|
||||
#define CPT_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
|
||||
CPT_HDMIW_HDMIEDID_A, \
|
||||
CPT_HDMIW_HDMIEDID_B)
|
||||
#define CPT_AUD_CNTL_ST_A 0xE50B4
|
||||
#define CPT_AUD_CNTL_ST_B 0xE51B4
|
||||
_CPT_HDMIW_HDMIEDID_A, \
|
||||
_CPT_HDMIW_HDMIEDID_B)
|
||||
#define _CPT_AUD_CNTL_ST_A 0xE50B4
|
||||
#define _CPT_AUD_CNTL_ST_B 0xE51B4
|
||||
#define CPT_AUD_CNTL_ST(pipe) _PIPE(pipe, \
|
||||
CPT_AUD_CNTL_ST_A, \
|
||||
CPT_AUD_CNTL_ST_B)
|
||||
_CPT_AUD_CNTL_ST_A, \
|
||||
_CPT_AUD_CNTL_ST_B)
|
||||
#define CPT_AUD_CNTRL_ST2 0xE50C0
|
||||
|
||||
#define VLV_HDMIW_HDMIEDID_A (VLV_DISPLAY_BASE + 0x62050)
|
||||
#define VLV_HDMIW_HDMIEDID_B (VLV_DISPLAY_BASE + 0x62150)
|
||||
#define _VLV_HDMIW_HDMIEDID_A (VLV_DISPLAY_BASE + 0x62050)
|
||||
#define _VLV_HDMIW_HDMIEDID_B (VLV_DISPLAY_BASE + 0x62150)
|
||||
#define VLV_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
|
||||
VLV_HDMIW_HDMIEDID_A, \
|
||||
VLV_HDMIW_HDMIEDID_B)
|
||||
#define VLV_AUD_CNTL_ST_A (VLV_DISPLAY_BASE + 0x620B4)
|
||||
#define VLV_AUD_CNTL_ST_B (VLV_DISPLAY_BASE + 0x621B4)
|
||||
_VLV_HDMIW_HDMIEDID_A, \
|
||||
_VLV_HDMIW_HDMIEDID_B)
|
||||
#define _VLV_AUD_CNTL_ST_A (VLV_DISPLAY_BASE + 0x620B4)
|
||||
#define _VLV_AUD_CNTL_ST_B (VLV_DISPLAY_BASE + 0x621B4)
|
||||
#define VLV_AUD_CNTL_ST(pipe) _PIPE(pipe, \
|
||||
VLV_AUD_CNTL_ST_A, \
|
||||
VLV_AUD_CNTL_ST_B)
|
||||
_VLV_AUD_CNTL_ST_A, \
|
||||
_VLV_AUD_CNTL_ST_B)
|
||||
#define VLV_AUD_CNTL_ST2 (VLV_DISPLAY_BASE + 0x620C0)
|
||||
|
||||
/* These are the 4 32-bit write offset registers for each stream
|
||||
@ -6014,28 +6135,28 @@ enum punit_power_well {
|
||||
*/
|
||||
#define GEN7_SO_WRITE_OFFSET(n) (0x5280 + (n) * 4)
|
||||
|
||||
#define IBX_AUD_CONFIG_A 0xe2000
|
||||
#define IBX_AUD_CONFIG_B 0xe2100
|
||||
#define _IBX_AUD_CONFIG_A 0xe2000
|
||||
#define _IBX_AUD_CONFIG_B 0xe2100
|
||||
#define IBX_AUD_CFG(pipe) _PIPE(pipe, \
|
||||
IBX_AUD_CONFIG_A, \
|
||||
IBX_AUD_CONFIG_B)
|
||||
#define CPT_AUD_CONFIG_A 0xe5000
|
||||
#define CPT_AUD_CONFIG_B 0xe5100
|
||||
_IBX_AUD_CONFIG_A, \
|
||||
_IBX_AUD_CONFIG_B)
|
||||
#define _CPT_AUD_CONFIG_A 0xe5000
|
||||
#define _CPT_AUD_CONFIG_B 0xe5100
|
||||
#define CPT_AUD_CFG(pipe) _PIPE(pipe, \
|
||||
CPT_AUD_CONFIG_A, \
|
||||
CPT_AUD_CONFIG_B)
|
||||
#define VLV_AUD_CONFIG_A (VLV_DISPLAY_BASE + 0x62000)
|
||||
#define VLV_AUD_CONFIG_B (VLV_DISPLAY_BASE + 0x62100)
|
||||
_CPT_AUD_CONFIG_A, \
|
||||
_CPT_AUD_CONFIG_B)
|
||||
#define _VLV_AUD_CONFIG_A (VLV_DISPLAY_BASE + 0x62000)
|
||||
#define _VLV_AUD_CONFIG_B (VLV_DISPLAY_BASE + 0x62100)
|
||||
#define VLV_AUD_CFG(pipe) _PIPE(pipe, \
|
||||
VLV_AUD_CONFIG_A, \
|
||||
VLV_AUD_CONFIG_B)
|
||||
_VLV_AUD_CONFIG_A, \
|
||||
_VLV_AUD_CONFIG_B)
|
||||
|
||||
#define AUD_CONFIG_N_VALUE_INDEX (1 << 29)
|
||||
#define AUD_CONFIG_N_PROG_ENABLE (1 << 28)
|
||||
#define AUD_CONFIG_UPPER_N_SHIFT 20
|
||||
#define AUD_CONFIG_UPPER_N_VALUE (0xff << 20)
|
||||
#define AUD_CONFIG_UPPER_N_MASK (0xff << 20)
|
||||
#define AUD_CONFIG_LOWER_N_SHIFT 4
|
||||
#define AUD_CONFIG_LOWER_N_VALUE (0xfff << 4)
|
||||
#define AUD_CONFIG_LOWER_N_MASK (0xfff << 4)
|
||||
#define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16
|
||||
#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16)
|
||||
#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16)
|
||||
@ -6051,52 +6172,44 @@ enum punit_power_well {
|
||||
#define AUD_CONFIG_DISABLE_NCTS (1 << 3)
|
||||
|
||||
/* HSW Audio */
|
||||
#define HSW_AUD_CONFIG_A 0x65000 /* Audio Configuration Transcoder A */
|
||||
#define HSW_AUD_CONFIG_B 0x65100 /* Audio Configuration Transcoder B */
|
||||
#define HSW_AUD_CFG(pipe) _PIPE(pipe, \
|
||||
HSW_AUD_CONFIG_A, \
|
||||
HSW_AUD_CONFIG_B)
|
||||
#define _HSW_AUD_CONFIG_A 0x65000
|
||||
#define _HSW_AUD_CONFIG_B 0x65100
|
||||
#define HSW_AUD_CFG(pipe) _PIPE(pipe, \
|
||||
_HSW_AUD_CONFIG_A, \
|
||||
_HSW_AUD_CONFIG_B)
|
||||
|
||||
#define HSW_AUD_MISC_CTRL_A 0x65010 /* Audio Misc Control Convert 1 */
|
||||
#define HSW_AUD_MISC_CTRL_B 0x65110 /* Audio Misc Control Convert 2 */
|
||||
#define HSW_AUD_MISC_CTRL(pipe) _PIPE(pipe, \
|
||||
HSW_AUD_MISC_CTRL_A, \
|
||||
HSW_AUD_MISC_CTRL_B)
|
||||
#define _HSW_AUD_MISC_CTRL_A 0x65010
|
||||
#define _HSW_AUD_MISC_CTRL_B 0x65110
|
||||
#define HSW_AUD_MISC_CTRL(pipe) _PIPE(pipe, \
|
||||
_HSW_AUD_MISC_CTRL_A, \
|
||||
_HSW_AUD_MISC_CTRL_B)
|
||||
|
||||
#define HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4 /* Audio DIP and ELD Control State Transcoder A */
|
||||
#define HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4 /* Audio DIP and ELD Control State Transcoder B */
|
||||
#define HSW_AUD_DIP_ELD_CTRL(pipe) _PIPE(pipe, \
|
||||
HSW_AUD_DIP_ELD_CTRL_ST_A, \
|
||||
HSW_AUD_DIP_ELD_CTRL_ST_B)
|
||||
#define _HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4
|
||||
#define _HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4
|
||||
#define HSW_AUD_DIP_ELD_CTRL(pipe) _PIPE(pipe, \
|
||||
_HSW_AUD_DIP_ELD_CTRL_ST_A, \
|
||||
_HSW_AUD_DIP_ELD_CTRL_ST_B)
|
||||
|
||||
/* Audio Digital Converter */
|
||||
#define HSW_AUD_DIG_CNVT_1 0x65080 /* Audio Converter 1 */
|
||||
#define HSW_AUD_DIG_CNVT_2 0x65180 /* Audio Converter 1 */
|
||||
#define AUD_DIG_CNVT(pipe) _PIPE(pipe, \
|
||||
HSW_AUD_DIG_CNVT_1, \
|
||||
HSW_AUD_DIG_CNVT_2)
|
||||
#define DIP_PORT_SEL_MASK 0x3
|
||||
#define _HSW_AUD_DIG_CNVT_1 0x65080
|
||||
#define _HSW_AUD_DIG_CNVT_2 0x65180
|
||||
#define AUD_DIG_CNVT(pipe) _PIPE(pipe, \
|
||||
_HSW_AUD_DIG_CNVT_1, \
|
||||
_HSW_AUD_DIG_CNVT_2)
|
||||
#define DIP_PORT_SEL_MASK 0x3
|
||||
|
||||
#define HSW_AUD_EDID_DATA_A 0x65050
|
||||
#define HSW_AUD_EDID_DATA_B 0x65150
|
||||
#define HSW_AUD_EDID_DATA(pipe) _PIPE(pipe, \
|
||||
HSW_AUD_EDID_DATA_A, \
|
||||
HSW_AUD_EDID_DATA_B)
|
||||
#define _HSW_AUD_EDID_DATA_A 0x65050
|
||||
#define _HSW_AUD_EDID_DATA_B 0x65150
|
||||
#define HSW_AUD_EDID_DATA(pipe) _PIPE(pipe, \
|
||||
_HSW_AUD_EDID_DATA_A, \
|
||||
_HSW_AUD_EDID_DATA_B)
|
||||
|
||||
#define HSW_AUD_PIPE_CONV_CFG 0x6507c /* Audio pipe and converter configs */
|
||||
#define HSW_AUD_PIN_ELD_CP_VLD 0x650c0 /* Audio ELD and CP Ready Status */
|
||||
#define AUDIO_INACTIVE_C (1<<11)
|
||||
#define AUDIO_INACTIVE_B (1<<7)
|
||||
#define AUDIO_INACTIVE_A (1<<3)
|
||||
#define AUDIO_OUTPUT_ENABLE_A (1<<2)
|
||||
#define AUDIO_OUTPUT_ENABLE_B (1<<6)
|
||||
#define AUDIO_OUTPUT_ENABLE_C (1<<10)
|
||||
#define AUDIO_ELD_VALID_A (1<<0)
|
||||
#define AUDIO_ELD_VALID_B (1<<4)
|
||||
#define AUDIO_ELD_VALID_C (1<<8)
|
||||
#define AUDIO_CP_READY_A (1<<1)
|
||||
#define AUDIO_CP_READY_B (1<<5)
|
||||
#define AUDIO_CP_READY_C (1<<9)
|
||||
#define HSW_AUD_PIPE_CONV_CFG 0x6507c
|
||||
#define HSW_AUD_PIN_ELD_CP_VLD 0x650c0
|
||||
#define AUDIO_INACTIVE(trans) ((1 << 3) << ((trans) * 4))
|
||||
#define AUDIO_OUTPUT_ENABLE(trans) ((1 << 2) << ((trans) * 4))
|
||||
#define AUDIO_CP_READY(trans) ((1 << 1) << ((trans) * 4))
|
||||
#define AUDIO_ELD_VALID(trans) ((1 << 0) << ((trans) * 4))
|
||||
|
||||
/* HSW Power Wells */
|
||||
#define HSW_PWR_WELL_BIOS 0x45400 /* CTL1 */
|
||||
|
462
drivers/gpu/drm/i915/intel_audio.c
Normal file
462
drivers/gpu/drm/i915/intel_audio.c
Normal file
@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright © 2014 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/kernel.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
/**
|
||||
* DOC: High Definition Audio over HDMI and Display Port
|
||||
*
|
||||
* The graphics and audio drivers together support High Definition Audio over
|
||||
* HDMI and Display Port. The audio programming sequences are divided into audio
|
||||
* codec and controller enable and disable sequences. The graphics driver
|
||||
* handles the audio codec sequences, while the audio driver handles the audio
|
||||
* controller sequences.
|
||||
*
|
||||
* The disable sequences must be performed before disabling the transcoder or
|
||||
* port. The enable sequences may only be performed after enabling the
|
||||
* transcoder and port, and after completed link training.
|
||||
*
|
||||
* The codec and controller sequences could be done either parallel or serial,
|
||||
* but generally the ELDV/PD change in the codec sequence indicates to the audio
|
||||
* driver that the controller sequence should start. Indeed, most of the
|
||||
* co-operation between the graphics and audio drivers is handled via audio
|
||||
* related registers. (The notable exception is the power management, not
|
||||
* covered here.)
|
||||
*/
|
||||
|
||||
static const struct {
|
||||
int clock;
|
||||
u32 config;
|
||||
} hdmi_audio_clock[] = {
|
||||
{ DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 },
|
||||
{ 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */
|
||||
{ 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 },
|
||||
{ 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 },
|
||||
{ 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 },
|
||||
{ 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 },
|
||||
{ DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 },
|
||||
{ 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 },
|
||||
{ DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 },
|
||||
{ 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 },
|
||||
};
|
||||
|
||||
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
|
||||
static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) {
|
||||
if (mode->clock == hdmi_audio_clock[i].clock)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(hdmi_audio_clock)) {
|
||||
DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", mode->clock);
|
||||
i = 1;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("Configuring HDMI audio for pixel clock %d (0x%08x)\n",
|
||||
hdmi_audio_clock[i].clock,
|
||||
hdmi_audio_clock[i].config);
|
||||
|
||||
return hdmi_audio_clock[i].config;
|
||||
}
|
||||
|
||||
static bool intel_eld_uptodate(struct drm_connector *connector,
|
||||
int reg_eldv, uint32_t bits_eldv,
|
||||
int reg_elda, uint32_t bits_elda,
|
||||
int reg_edid)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
uint8_t *eld = connector->eld;
|
||||
uint32_t tmp;
|
||||
int i;
|
||||
|
||||
tmp = I915_READ(reg_eldv);
|
||||
tmp &= bits_eldv;
|
||||
|
||||
if (!tmp)
|
||||
return false;
|
||||
|
||||
tmp = I915_READ(reg_elda);
|
||||
tmp &= ~bits_elda;
|
||||
I915_WRITE(reg_elda, tmp);
|
||||
|
||||
for (i = 0; i < eld[2]; i++)
|
||||
if (I915_READ(reg_edid) != *((uint32_t *)eld + i))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void g4x_audio_codec_disable(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
||||
uint32_t eldv, tmp;
|
||||
|
||||
DRM_DEBUG_KMS("Disable audio codec\n");
|
||||
|
||||
tmp = I915_READ(G4X_AUD_VID_DID);
|
||||
if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL)
|
||||
eldv = G4X_ELDV_DEVCL_DEVBLC;
|
||||
else
|
||||
eldv = G4X_ELDV_DEVCTG;
|
||||
|
||||
/* Invalidate ELD */
|
||||
tmp = I915_READ(G4X_AUD_CNTL_ST);
|
||||
tmp &= ~eldv;
|
||||
I915_WRITE(G4X_AUD_CNTL_ST, tmp);
|
||||
}
|
||||
|
||||
static void g4x_audio_codec_enable(struct drm_connector *connector,
|
||||
struct intel_encoder *encoder,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
uint8_t *eld = connector->eld;
|
||||
uint32_t eldv;
|
||||
uint32_t tmp;
|
||||
int len, i;
|
||||
|
||||
DRM_DEBUG_KMS("Enable audio codec, %u bytes ELD\n", eld[2]);
|
||||
|
||||
tmp = I915_READ(G4X_AUD_VID_DID);
|
||||
if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL)
|
||||
eldv = G4X_ELDV_DEVCL_DEVBLC;
|
||||
else
|
||||
eldv = G4X_ELDV_DEVCTG;
|
||||
|
||||
if (intel_eld_uptodate(connector,
|
||||
G4X_AUD_CNTL_ST, eldv,
|
||||
G4X_AUD_CNTL_ST, G4X_ELD_ADDR_MASK,
|
||||
G4X_HDMIW_HDMIEDID))
|
||||
return;
|
||||
|
||||
tmp = I915_READ(G4X_AUD_CNTL_ST);
|
||||
tmp &= ~(eldv | G4X_ELD_ADDR_MASK);
|
||||
len = (tmp >> 9) & 0x1f; /* ELD buffer size */
|
||||
I915_WRITE(G4X_AUD_CNTL_ST, tmp);
|
||||
|
||||
len = min_t(int, eld[2], len);
|
||||
DRM_DEBUG_DRIVER("ELD size %d\n", len);
|
||||
for (i = 0; i < len; i++)
|
||||
I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i));
|
||||
|
||||
tmp = I915_READ(G4X_AUD_CNTL_ST);
|
||||
tmp |= eldv;
|
||||
I915_WRITE(G4X_AUD_CNTL_ST, tmp);
|
||||
}
|
||||
|
||||
static void hsw_audio_codec_disable(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
uint32_t tmp;
|
||||
|
||||
DRM_DEBUG_KMS("Disable audio codec on pipe %c\n", pipe_name(pipe));
|
||||
|
||||
/* Disable timestamps */
|
||||
tmp = I915_READ(HSW_AUD_CFG(pipe));
|
||||
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
|
||||
tmp |= AUD_CONFIG_N_PROG_ENABLE;
|
||||
tmp &= ~AUD_CONFIG_UPPER_N_MASK;
|
||||
tmp &= ~AUD_CONFIG_LOWER_N_MASK;
|
||||
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
|
||||
tmp |= AUD_CONFIG_N_VALUE_INDEX;
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
|
||||
/* Invalidate ELD */
|
||||
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
tmp &= ~AUDIO_ELD_VALID(pipe);
|
||||
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
}
|
||||
|
||||
static void hsw_audio_codec_enable(struct drm_connector *connector,
|
||||
struct intel_encoder *encoder,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
const uint8_t *eld = connector->eld;
|
||||
uint32_t tmp;
|
||||
int len, i;
|
||||
|
||||
DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n",
|
||||
pipe_name(pipe), eld[2]);
|
||||
|
||||
/* Enable audio presence detect, invalidate ELD */
|
||||
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
tmp |= AUDIO_OUTPUT_ENABLE(pipe);
|
||||
tmp &= ~AUDIO_ELD_VALID(pipe);
|
||||
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
|
||||
/*
|
||||
* FIXME: We're supposed to wait for vblank here, but we have vblanks
|
||||
* disabled during the mode set. The proper fix would be to push the
|
||||
* rest of the setup into a vblank work item, queued here, but the
|
||||
* infrastructure is not there yet.
|
||||
*/
|
||||
|
||||
/* Reset ELD write address */
|
||||
tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe));
|
||||
tmp &= ~IBX_ELD_ADDRESS_MASK;
|
||||
I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp);
|
||||
|
||||
/* Up to 84 bytes of hw ELD buffer */
|
||||
len = min_t(int, eld[2], 21);
|
||||
for (i = 0; i < len; i++)
|
||||
I915_WRITE(HSW_AUD_EDID_DATA(pipe), *((uint32_t *)eld + i));
|
||||
|
||||
/* ELD valid */
|
||||
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
tmp |= AUDIO_ELD_VALID(pipe);
|
||||
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
|
||||
/* Enable timestamps */
|
||||
tmp = I915_READ(HSW_AUD_CFG(pipe));
|
||||
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
|
||||
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
|
||||
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
|
||||
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
|
||||
tmp |= AUD_CONFIG_N_VALUE_INDEX;
|
||||
else
|
||||
tmp |= audio_config_hdmi_pixel_clock(mode);
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
}
|
||||
|
||||
static void ilk_audio_codec_disable(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
||||
struct intel_digital_port *intel_dig_port =
|
||||
enc_to_dig_port(&encoder->base);
|
||||
enum port port = intel_dig_port->port;
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
uint32_t tmp, eldv;
|
||||
int aud_config;
|
||||
int aud_cntrl_st2;
|
||||
|
||||
DRM_DEBUG_KMS("Disable audio codec on port %c, pipe %c\n",
|
||||
port_name(port), pipe_name(pipe));
|
||||
|
||||
if (HAS_PCH_IBX(dev_priv->dev)) {
|
||||
aud_config = IBX_AUD_CFG(pipe);
|
||||
aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
|
||||
} else if (IS_VALLEYVIEW(dev_priv)) {
|
||||
aud_config = VLV_AUD_CFG(pipe);
|
||||
aud_cntrl_st2 = VLV_AUD_CNTL_ST2;
|
||||
} else {
|
||||
aud_config = CPT_AUD_CFG(pipe);
|
||||
aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
|
||||
}
|
||||
|
||||
/* Disable timestamps */
|
||||
tmp = I915_READ(aud_config);
|
||||
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
|
||||
tmp |= AUD_CONFIG_N_PROG_ENABLE;
|
||||
tmp &= ~AUD_CONFIG_UPPER_N_MASK;
|
||||
tmp &= ~AUD_CONFIG_LOWER_N_MASK;
|
||||
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
|
||||
tmp |= AUD_CONFIG_N_VALUE_INDEX;
|
||||
I915_WRITE(aud_config, tmp);
|
||||
|
||||
if (WARN_ON(!port)) {
|
||||
eldv = IBX_ELD_VALID(PORT_B) | IBX_ELD_VALID(PORT_C) |
|
||||
IBX_ELD_VALID(PORT_D);
|
||||
} else {
|
||||
eldv = IBX_ELD_VALID(port);
|
||||
}
|
||||
|
||||
/* Invalidate ELD */
|
||||
tmp = I915_READ(aud_cntrl_st2);
|
||||
tmp &= ~eldv;
|
||||
I915_WRITE(aud_cntrl_st2, tmp);
|
||||
}
|
||||
|
||||
static void ilk_audio_codec_enable(struct drm_connector *connector,
|
||||
struct intel_encoder *encoder,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
|
||||
struct intel_digital_port *intel_dig_port =
|
||||
enc_to_dig_port(&encoder->base);
|
||||
enum port port = intel_dig_port->port;
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
uint8_t *eld = connector->eld;
|
||||
uint32_t eldv;
|
||||
uint32_t tmp;
|
||||
int len, i;
|
||||
int hdmiw_hdmiedid;
|
||||
int aud_config;
|
||||
int aud_cntl_st;
|
||||
int aud_cntrl_st2;
|
||||
|
||||
DRM_DEBUG_KMS("Enable audio codec on port %c, pipe %c, %u bytes ELD\n",
|
||||
port_name(port), pipe_name(pipe), eld[2]);
|
||||
|
||||
/*
|
||||
* FIXME: We're supposed to wait for vblank here, but we have vblanks
|
||||
* disabled during the mode set. The proper fix would be to push the
|
||||
* rest of the setup into a vblank work item, queued here, but the
|
||||
* infrastructure is not there yet.
|
||||
*/
|
||||
|
||||
if (HAS_PCH_IBX(connector->dev)) {
|
||||
hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
|
||||
aud_config = IBX_AUD_CFG(pipe);
|
||||
aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
|
||||
aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
|
||||
} else if (IS_VALLEYVIEW(connector->dev)) {
|
||||
hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe);
|
||||
aud_config = VLV_AUD_CFG(pipe);
|
||||
aud_cntl_st = VLV_AUD_CNTL_ST(pipe);
|
||||
aud_cntrl_st2 = VLV_AUD_CNTL_ST2;
|
||||
} else {
|
||||
hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe);
|
||||
aud_config = CPT_AUD_CFG(pipe);
|
||||
aud_cntl_st = CPT_AUD_CNTL_ST(pipe);
|
||||
aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
|
||||
}
|
||||
|
||||
if (WARN_ON(!port)) {
|
||||
eldv = IBX_ELD_VALID(PORT_B) | IBX_ELD_VALID(PORT_C) |
|
||||
IBX_ELD_VALID(PORT_D);
|
||||
} else {
|
||||
eldv = IBX_ELD_VALID(port);
|
||||
}
|
||||
|
||||
/* Invalidate ELD */
|
||||
tmp = I915_READ(aud_cntrl_st2);
|
||||
tmp &= ~eldv;
|
||||
I915_WRITE(aud_cntrl_st2, tmp);
|
||||
|
||||
/* Reset ELD write address */
|
||||
tmp = I915_READ(aud_cntl_st);
|
||||
tmp &= ~IBX_ELD_ADDRESS_MASK;
|
||||
I915_WRITE(aud_cntl_st, tmp);
|
||||
|
||||
/* Up to 84 bytes of hw ELD buffer */
|
||||
len = min_t(int, eld[2], 21);
|
||||
for (i = 0; i < len; i++)
|
||||
I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
|
||||
|
||||
/* ELD valid */
|
||||
tmp = I915_READ(aud_cntrl_st2);
|
||||
tmp |= eldv;
|
||||
I915_WRITE(aud_cntrl_st2, tmp);
|
||||
|
||||
/* Enable timestamps */
|
||||
tmp = I915_READ(aud_config);
|
||||
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
|
||||
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
|
||||
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
|
||||
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT))
|
||||
tmp |= AUD_CONFIG_N_VALUE_INDEX;
|
||||
else
|
||||
tmp |= audio_config_hdmi_pixel_clock(mode);
|
||||
I915_WRITE(aud_config, tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_audio_codec_enable - Enable the audio codec for HD audio
|
||||
* @intel_encoder: encoder on which to enable audio
|
||||
*
|
||||
* The enable sequences may only be performed after enabling the transcoder and
|
||||
* port, and after completed link training.
|
||||
*/
|
||||
void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
|
||||
{
|
||||
struct drm_encoder *encoder = &intel_encoder->base;
|
||||
struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
|
||||
struct drm_display_mode *mode = &crtc->config.adjusted_mode;
|
||||
struct drm_connector *connector;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
connector = drm_select_eld(encoder, mode);
|
||||
if (!connector)
|
||||
return;
|
||||
|
||||
DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
|
||||
connector->base.id,
|
||||
connector->name,
|
||||
connector->encoder->base.id,
|
||||
connector->encoder->name);
|
||||
|
||||
/* ELD Conn_Type */
|
||||
connector->eld[5] &= ~(3 << 2);
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
|
||||
connector->eld[5] |= (1 << 2);
|
||||
|
||||
connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
|
||||
|
||||
if (dev_priv->display.audio_codec_enable)
|
||||
dev_priv->display.audio_codec_enable(connector, intel_encoder, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_audio_codec_disable - Disable the audio codec for HD audio
|
||||
* @encoder: encoder on which to disable audio
|
||||
*
|
||||
* The disable sequences must be performed before disabling the transcoder or
|
||||
* port.
|
||||
*/
|
||||
void intel_audio_codec_disable(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (dev_priv->display.audio_codec_disable)
|
||||
dev_priv->display.audio_codec_disable(encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_init_audio - Set up chip specific audio functions
|
||||
* @dev: drm device
|
||||
*/
|
||||
void intel_init_audio(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_G4X(dev)) {
|
||||
dev_priv->display.audio_codec_enable = g4x_audio_codec_enable;
|
||||
dev_priv->display.audio_codec_disable = g4x_audio_codec_disable;
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
dev_priv->display.audio_codec_enable = ilk_audio_codec_enable;
|
||||
dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
|
||||
} else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) {
|
||||
dev_priv->display.audio_codec_enable = hsw_audio_codec_enable;
|
||||
dev_priv->display.audio_codec_disable = hsw_audio_codec_disable;
|
||||
} else if (HAS_PCH_SPLIT(dev)) {
|
||||
dev_priv->display.audio_codec_enable = ilk_audio_codec_enable;
|
||||
dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
|
||||
}
|
||||
}
|
@ -459,6 +459,27 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct intel_encoder *
|
||||
intel_ddi_get_crtc_new_encoder(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
struct intel_encoder *intel_encoder, *ret = NULL;
|
||||
int num_encoders = 0;
|
||||
|
||||
for_each_intel_encoder(dev, intel_encoder) {
|
||||
if (intel_encoder->new_crtc == crtc) {
|
||||
ret = intel_encoder;
|
||||
num_encoders++;
|
||||
}
|
||||
}
|
||||
|
||||
WARN(num_encoders != 1, "%d encoders on crtc for pipe %c\n", num_encoders,
|
||||
pipe_name(crtc->pipe));
|
||||
|
||||
BUG_ON(ret == NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define LC_FREQ 2700
|
||||
#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
|
||||
|
||||
@ -792,7 +813,7 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
|
||||
WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
|
||||
WRPLL_DIVIDER_POST(p);
|
||||
|
||||
intel_crtc->config.dpll_hw_state.wrpll = val;
|
||||
intel_crtc->new_config->dpll_hw_state.wrpll = val;
|
||||
|
||||
pll = intel_get_shared_dpll(intel_crtc);
|
||||
if (pll == NULL) {
|
||||
@ -801,7 +822,7 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
|
||||
return false;
|
||||
}
|
||||
|
||||
intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
|
||||
intel_crtc->new_config->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -817,11 +838,9 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
|
||||
*/
|
||||
bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
|
||||
{
|
||||
struct drm_crtc *crtc = &intel_crtc->base;
|
||||
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
|
||||
int clock = intel_crtc->config.port_clock;
|
||||
|
||||
intel_put_shared_dpll(intel_crtc);
|
||||
struct intel_encoder *intel_encoder =
|
||||
intel_ddi_get_crtc_new_encoder(intel_crtc);
|
||||
int clock = intel_crtc->new_config->port_clock;
|
||||
|
||||
return hsw_ddi_pll_select(intel_crtc, intel_encoder, clock);
|
||||
}
|
||||
@ -1120,15 +1139,6 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
|
||||
enum port port = intel_ddi_get_encoder_port(intel_encoder);
|
||||
int type = intel_encoder->type;
|
||||
|
||||
if (crtc->config.has_audio) {
|
||||
DRM_DEBUG_DRIVER("Audio on pipe %c on DDI\n",
|
||||
pipe_name(crtc->pipe));
|
||||
|
||||
/* write eld */
|
||||
DRM_DEBUG_DRIVER("DDI audio: write eld information\n");
|
||||
intel_write_eld(encoder, &crtc->config.adjusted_mode);
|
||||
}
|
||||
|
||||
if (type == INTEL_OUTPUT_EDP) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
intel_edp_panel_on(intel_dp);
|
||||
@ -1195,12 +1205,10 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
|
||||
struct drm_encoder *encoder = &intel_encoder->base;
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
enum port port = intel_ddi_get_encoder_port(intel_encoder);
|
||||
int type = intel_encoder->type;
|
||||
uint32_t tmp;
|
||||
|
||||
if (type == INTEL_OUTPUT_HDMI) {
|
||||
struct intel_digital_port *intel_dig_port =
|
||||
@ -1225,9 +1233,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
|
||||
|
||||
if (intel_crtc->config.has_audio) {
|
||||
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
|
||||
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
|
||||
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
intel_audio_codec_enable(intel_encoder);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1236,19 +1242,12 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
|
||||
struct drm_encoder *encoder = &intel_encoder->base;
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
int type = intel_encoder->type;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t tmp;
|
||||
|
||||
/* We can't touch HSW_AUD_PIN_ELD_CP_VLD uncionditionally because this
|
||||
* register is part of the power well on Haswell. */
|
||||
if (intel_crtc->config.has_audio) {
|
||||
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) <<
|
||||
(pipe * 4));
|
||||
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
intel_audio_codec_disable(intel_encoder);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
|
||||
}
|
||||
|
||||
@ -1311,7 +1310,7 @@ int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
|
||||
static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll)
|
||||
{
|
||||
I915_WRITE(WRPLL_CTL(pll->id), pll->hw_state.wrpll);
|
||||
I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
|
||||
POSTING_READ(WRPLL_CTL(pll->id));
|
||||
udelay(20);
|
||||
}
|
||||
@ -1524,7 +1523,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
|
||||
|
||||
if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
|
||||
temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
if (temp & (AUDIO_OUTPUT_ENABLE_A << (intel_crtc->pipe * 4)))
|
||||
if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe))
|
||||
pipe_config->has_audio = true;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -113,6 +113,9 @@ static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
|
||||
static void intel_dp_link_down(struct intel_dp *intel_dp);
|
||||
static bool edp_panel_vdd_on(struct intel_dp *intel_dp);
|
||||
static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
|
||||
static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp);
|
||||
static void vlv_steal_power_sequencer(struct drm_device *dev,
|
||||
enum pipe pipe);
|
||||
|
||||
int
|
||||
intel_dp_max_link_bw(struct intel_dp *intel_dp)
|
||||
@ -283,12 +286,10 @@ intel_hrawclk(struct drm_device *dev)
|
||||
|
||||
static void
|
||||
intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
||||
struct intel_dp *intel_dp,
|
||||
struct edp_power_seq *out);
|
||||
struct intel_dp *intel_dp);
|
||||
static void
|
||||
intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
|
||||
struct intel_dp *intel_dp,
|
||||
struct edp_power_seq *out);
|
||||
struct intel_dp *intel_dp);
|
||||
|
||||
static void pps_lock(struct intel_dp *intel_dp)
|
||||
{
|
||||
@ -322,6 +323,66 @@ static void pps_unlock(struct intel_dp *intel_dp)
|
||||
intel_display_power_put(dev_priv, power_domain);
|
||||
}
|
||||
|
||||
static void
|
||||
vlv_power_sequencer_kick(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_device *dev = intel_dig_port->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
enum pipe pipe = intel_dp->pps_pipe;
|
||||
bool pll_enabled;
|
||||
uint32_t DP;
|
||||
|
||||
if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN,
|
||||
"skipping pipe %c power seqeuncer kick due to port %c being active\n",
|
||||
pipe_name(pipe), port_name(intel_dig_port->port)))
|
||||
return;
|
||||
|
||||
DRM_DEBUG_KMS("kicking pipe %c power sequencer for port %c\n",
|
||||
pipe_name(pipe), port_name(intel_dig_port->port));
|
||||
|
||||
/* Preserve the BIOS-computed detected bit. This is
|
||||
* supposed to be read-only.
|
||||
*/
|
||||
DP = I915_READ(intel_dp->output_reg) & DP_DETECTED;
|
||||
DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
|
||||
DP |= DP_PORT_WIDTH(1);
|
||||
DP |= DP_LINK_TRAIN_PAT_1;
|
||||
|
||||
if (IS_CHERRYVIEW(dev))
|
||||
DP |= DP_PIPE_SELECT_CHV(pipe);
|
||||
else if (pipe == PIPE_B)
|
||||
DP |= DP_PIPEB_SELECT;
|
||||
|
||||
pll_enabled = I915_READ(DPLL(pipe)) & DPLL_VCO_ENABLE;
|
||||
|
||||
/*
|
||||
* The DPLL for the pipe must be enabled for this to work.
|
||||
* So enable temporarily it if it's not already enabled.
|
||||
*/
|
||||
if (!pll_enabled)
|
||||
vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ?
|
||||
&chv_dpll[0].dpll : &vlv_dpll[0].dpll);
|
||||
|
||||
/*
|
||||
* Similar magic as in intel_dp_enable_port().
|
||||
* We _must_ do this port enable + disable trick
|
||||
* to make this power seqeuencer lock onto the port.
|
||||
* Otherwise even VDD force bit won't work.
|
||||
*/
|
||||
I915_WRITE(intel_dp->output_reg, DP);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
|
||||
I915_WRITE(intel_dp->output_reg, DP | DP_PORT_EN);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
|
||||
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
|
||||
if (!pll_enabled)
|
||||
vlv_force_pll_off(dev, pipe);
|
||||
}
|
||||
|
||||
static enum pipe
|
||||
vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
|
||||
{
|
||||
@ -330,10 +391,13 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_encoder *encoder;
|
||||
unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
|
||||
struct edp_power_seq power_seq;
|
||||
enum pipe pipe;
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
/* We should never land here with regular DP ports */
|
||||
WARN_ON(!is_edp(intel_dp));
|
||||
|
||||
if (intel_dp->pps_pipe != INVALID_PIPE)
|
||||
return intel_dp->pps_pipe;
|
||||
|
||||
@ -359,18 +423,26 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
|
||||
* are two power sequencers and up to two eDP ports.
|
||||
*/
|
||||
if (WARN_ON(pipes == 0))
|
||||
return PIPE_A;
|
||||
pipe = PIPE_A;
|
||||
else
|
||||
pipe = ffs(pipes) - 1;
|
||||
|
||||
intel_dp->pps_pipe = ffs(pipes) - 1;
|
||||
vlv_steal_power_sequencer(dev, pipe);
|
||||
intel_dp->pps_pipe = pipe;
|
||||
|
||||
DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n",
|
||||
pipe_name(intel_dp->pps_pipe),
|
||||
port_name(intel_dig_port->port));
|
||||
|
||||
/* init power sequencer on this pipe and port */
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
|
||||
&power_seq);
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp);
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
|
||||
|
||||
/*
|
||||
* Even vdd force doesn't work until we've made
|
||||
* the power sequencer lock in on the port.
|
||||
*/
|
||||
vlv_power_sequencer_kick(intel_dp);
|
||||
|
||||
return intel_dp->pps_pipe;
|
||||
}
|
||||
@ -425,7 +497,6 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_device *dev = intel_dig_port->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct edp_power_seq power_seq;
|
||||
enum port port = intel_dig_port->port;
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
@ -453,9 +524,8 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
|
||||
DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n",
|
||||
port_name(port), pipe_name(intel_dp->pps_pipe));
|
||||
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
|
||||
&power_seq);
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp);
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
|
||||
}
|
||||
|
||||
void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
|
||||
@ -550,6 +620,10 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (IS_VALLEYVIEW(dev) &&
|
||||
intel_dp->pps_pipe == INVALID_PIPE)
|
||||
return false;
|
||||
|
||||
return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
|
||||
}
|
||||
|
||||
@ -560,6 +634,10 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (IS_VALLEYVIEW(dev) &&
|
||||
intel_dp->pps_pipe == INVALID_PIPE)
|
||||
return false;
|
||||
|
||||
return I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
|
||||
}
|
||||
|
||||
@ -1246,12 +1324,8 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
|
||||
intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
|
||||
intel_dp->DP |= DP_PORT_WIDTH(intel_dp->lane_count);
|
||||
|
||||
if (crtc->config.has_audio) {
|
||||
DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
|
||||
pipe_name(crtc->pipe));
|
||||
if (crtc->config.has_audio)
|
||||
intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
|
||||
intel_write_eld(&encoder->base, adjusted_mode);
|
||||
}
|
||||
|
||||
/* Split out the IBX/CPU vs CPT settings */
|
||||
|
||||
@ -1409,7 +1483,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
|
||||
power_domain = intel_display_port_power_domain(intel_encoder);
|
||||
intel_display_power_get(dev_priv, power_domain);
|
||||
|
||||
DRM_DEBUG_KMS("Turning eDP VDD on\n");
|
||||
DRM_DEBUG_KMS("Turning eDP port %c VDD on\n",
|
||||
port_name(intel_dig_port->port));
|
||||
|
||||
if (!edp_have_panel_power(intel_dp))
|
||||
wait_panel_power_cycle(intel_dp);
|
||||
@ -1428,7 +1503,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
|
||||
* If the panel wasn't on, delay before accessing aux channel
|
||||
*/
|
||||
if (!edp_have_panel_power(intel_dp)) {
|
||||
DRM_DEBUG_KMS("eDP was not running\n");
|
||||
DRM_DEBUG_KMS("eDP port %c panel power wasn't enabled\n",
|
||||
port_name(intel_dig_port->port));
|
||||
msleep(intel_dp->panel_power_up_delay);
|
||||
}
|
||||
|
||||
@ -1453,7 +1529,8 @@ void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
|
||||
vdd = edp_panel_vdd_on(intel_dp);
|
||||
pps_unlock(intel_dp);
|
||||
|
||||
WARN(!vdd, "eDP VDD already requested on\n");
|
||||
WARN(!vdd, "eDP port %c VDD already requested on\n",
|
||||
port_name(dp_to_dig_port(intel_dp)->port));
|
||||
}
|
||||
|
||||
static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
|
||||
@ -1474,7 +1551,8 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
|
||||
if (!edp_have_panel_vdd(intel_dp))
|
||||
return;
|
||||
|
||||
DRM_DEBUG_KMS("Turning eDP VDD off\n");
|
||||
DRM_DEBUG_KMS("Turning eDP port %c VDD off\n",
|
||||
port_name(intel_dig_port->port));
|
||||
|
||||
pp = ironlake_get_pp_control(intel_dp);
|
||||
pp &= ~EDP_FORCE_VDD;
|
||||
@ -1535,7 +1613,8 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
|
||||
if (!is_edp(intel_dp))
|
||||
return;
|
||||
|
||||
WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on");
|
||||
WARN(!intel_dp->want_panel_vdd, "eDP port %c VDD not forced on",
|
||||
port_name(dp_to_dig_port(intel_dp)->port));
|
||||
|
||||
intel_dp->want_panel_vdd = false;
|
||||
|
||||
@ -1545,40 +1624,25 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
|
||||
edp_panel_vdd_schedule_off(intel_dp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be paired with intel_edp_panel_vdd_on().
|
||||
* Nested calls to these functions are not allowed since
|
||||
* we drop the lock. Caller must use some higher level
|
||||
* locking to prevent nested calls from other threads.
|
||||
*/
|
||||
static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
|
||||
{
|
||||
if (!is_edp(intel_dp))
|
||||
return;
|
||||
|
||||
pps_lock(intel_dp);
|
||||
edp_panel_vdd_off(intel_dp, sync);
|
||||
pps_unlock(intel_dp);
|
||||
}
|
||||
|
||||
void intel_edp_panel_on(struct intel_dp *intel_dp)
|
||||
static void edp_panel_on(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_device *dev = intel_dp_to_dev(intel_dp);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp;
|
||||
u32 pp_ctrl_reg;
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (!is_edp(intel_dp))
|
||||
return;
|
||||
|
||||
DRM_DEBUG_KMS("Turn eDP power on\n");
|
||||
DRM_DEBUG_KMS("Turn eDP port %c panel power on\n",
|
||||
port_name(dp_to_dig_port(intel_dp)->port));
|
||||
|
||||
pps_lock(intel_dp);
|
||||
|
||||
if (edp_have_panel_power(intel_dp)) {
|
||||
DRM_DEBUG_KMS("eDP power already on\n");
|
||||
goto out;
|
||||
}
|
||||
if (WARN(edp_have_panel_power(intel_dp),
|
||||
"eDP port %c panel power already on\n",
|
||||
port_name(dp_to_dig_port(intel_dp)->port)))
|
||||
return;
|
||||
|
||||
wait_panel_power_cycle(intel_dp);
|
||||
|
||||
@ -1606,12 +1670,20 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
|
||||
I915_WRITE(pp_ctrl_reg, pp);
|
||||
POSTING_READ(pp_ctrl_reg);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
void intel_edp_panel_on(struct intel_dp *intel_dp)
|
||||
{
|
||||
if (!is_edp(intel_dp))
|
||||
return;
|
||||
|
||||
pps_lock(intel_dp);
|
||||
edp_panel_on(intel_dp);
|
||||
pps_unlock(intel_dp);
|
||||
}
|
||||
|
||||
void intel_edp_panel_off(struct intel_dp *intel_dp)
|
||||
|
||||
static void edp_panel_off(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct intel_encoder *intel_encoder = &intel_dig_port->base;
|
||||
@ -1621,14 +1693,16 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
|
||||
u32 pp;
|
||||
u32 pp_ctrl_reg;
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (!is_edp(intel_dp))
|
||||
return;
|
||||
|
||||
DRM_DEBUG_KMS("Turn eDP power off\n");
|
||||
DRM_DEBUG_KMS("Turn eDP port %c panel power off\n",
|
||||
port_name(dp_to_dig_port(intel_dp)->port));
|
||||
|
||||
pps_lock(intel_dp);
|
||||
|
||||
WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
|
||||
WARN(!intel_dp->want_panel_vdd, "Need eDP port %c VDD to turn off panel\n",
|
||||
port_name(dp_to_dig_port(intel_dp)->port));
|
||||
|
||||
pp = ironlake_get_pp_control(intel_dp);
|
||||
/* We need to switch off panel power _and_ force vdd, for otherwise some
|
||||
@ -1649,7 +1723,15 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
|
||||
/* We got a reference when we enabled the VDD. */
|
||||
power_domain = intel_display_port_power_domain(intel_encoder);
|
||||
intel_display_power_put(dev_priv, power_domain);
|
||||
}
|
||||
|
||||
void intel_edp_panel_off(struct intel_dp *intel_dp)
|
||||
{
|
||||
if (!is_edp(intel_dp))
|
||||
return;
|
||||
|
||||
pps_lock(intel_dp);
|
||||
edp_panel_off(intel_dp);
|
||||
pps_unlock(intel_dp);
|
||||
}
|
||||
|
||||
@ -2368,6 +2450,10 @@ static void intel_disable_dp(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
|
||||
|
||||
if (crtc->config.has_audio)
|
||||
intel_audio_codec_disable(encoder);
|
||||
|
||||
/* Make sure the panel is off before trying to change the mode. But also
|
||||
* ensure that we have vdd while we switch off the panel. */
|
||||
@ -2522,14 +2608,23 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp)
|
||||
struct drm_device *dev = intel_dp_to_dev(intel_dp);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
intel_dp->DP |= DP_PORT_EN;
|
||||
|
||||
/* enable with pattern 1 (as per spec) */
|
||||
_intel_dp_set_link_train(intel_dp, &intel_dp->DP,
|
||||
DP_TRAINING_PATTERN_1);
|
||||
|
||||
I915_WRITE(intel_dp->output_reg, intel_dp->DP);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
|
||||
/*
|
||||
* Magic for VLV/CHV. We _must_ first set up the register
|
||||
* without actually enabling the port, and then do another
|
||||
* write to enable the port. Otherwise link training will
|
||||
* fail when the power sequencer is freshly used for this port.
|
||||
*/
|
||||
intel_dp->DP |= DP_PORT_EN;
|
||||
|
||||
I915_WRITE(intel_dp->output_reg, intel_dp->DP);
|
||||
POSTING_READ(intel_dp->output_reg);
|
||||
}
|
||||
|
||||
static void intel_enable_dp(struct intel_encoder *encoder)
|
||||
@ -2537,19 +2632,38 @@ static void intel_enable_dp(struct intel_encoder *encoder)
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
|
||||
uint32_t dp_reg = I915_READ(intel_dp->output_reg);
|
||||
|
||||
if (WARN_ON(dp_reg & DP_PORT_EN))
|
||||
return;
|
||||
|
||||
pps_lock(intel_dp);
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
vlv_init_panel_power_sequencer(intel_dp);
|
||||
|
||||
intel_dp_enable_port(intel_dp);
|
||||
intel_edp_panel_vdd_on(intel_dp);
|
||||
intel_edp_panel_on(intel_dp);
|
||||
intel_edp_panel_vdd_off(intel_dp, true);
|
||||
|
||||
edp_panel_vdd_on(intel_dp);
|
||||
edp_panel_on(intel_dp);
|
||||
edp_panel_vdd_off(intel_dp, true);
|
||||
|
||||
pps_unlock(intel_dp);
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp));
|
||||
|
||||
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
|
||||
intel_dp_start_link_train(intel_dp);
|
||||
intel_dp_complete_link_train(intel_dp);
|
||||
intel_dp_stop_link_train(intel_dp);
|
||||
|
||||
if (crtc->config.has_audio) {
|
||||
DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
|
||||
pipe_name(crtc->pipe));
|
||||
intel_audio_codec_enable(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
static void g4x_enable_dp(struct intel_encoder *encoder)
|
||||
@ -2581,6 +2695,32 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder)
|
||||
}
|
||||
}
|
||||
|
||||
static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_i915_private *dev_priv = intel_dig_port->base.base.dev->dev_private;
|
||||
enum pipe pipe = intel_dp->pps_pipe;
|
||||
int pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
|
||||
|
||||
edp_panel_vdd_off_sync(intel_dp);
|
||||
|
||||
/*
|
||||
* VLV seems to get confused when multiple power seqeuencers
|
||||
* have the same port selected (even if only one has power/vdd
|
||||
* enabled). The failure manifests as vlv_wait_port_ready() failing
|
||||
* CHV on the other hand doesn't seem to mind having the same port
|
||||
* selected in multiple power seqeuencers, but let's clear the
|
||||
* port select always when logically disconnecting a power sequencer
|
||||
* from a port.
|
||||
*/
|
||||
DRM_DEBUG_KMS("detaching pipe %c power sequencer from port %c\n",
|
||||
pipe_name(pipe), port_name(intel_dig_port->port));
|
||||
I915_WRITE(pp_on_reg, 0);
|
||||
POSTING_READ(pp_on_reg);
|
||||
|
||||
intel_dp->pps_pipe = INVALID_PIPE;
|
||||
}
|
||||
|
||||
static void vlv_steal_power_sequencer(struct drm_device *dev,
|
||||
enum pipe pipe)
|
||||
{
|
||||
@ -2589,6 +2729,9 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
|
||||
return;
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
||||
base.head) {
|
||||
struct intel_dp *intel_dp;
|
||||
@ -2606,10 +2749,12 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
|
||||
DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
|
||||
pipe_name(pipe), port_name(port));
|
||||
|
||||
/* make sure vdd is off before we steal it */
|
||||
edp_panel_vdd_off_sync(intel_dp);
|
||||
WARN(encoder->connectors_active,
|
||||
"stealing pipe %c power sequencer from active eDP port %c\n",
|
||||
pipe_name(pipe), port_name(port));
|
||||
|
||||
intel_dp->pps_pipe = INVALID_PIPE;
|
||||
/* make sure vdd is off before we steal it */
|
||||
vlv_detach_power_sequencer(intel_dp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2620,10 +2765,12 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
|
||||
struct edp_power_seq power_seq;
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (!is_edp(intel_dp))
|
||||
return;
|
||||
|
||||
if (intel_dp->pps_pipe == crtc->pipe)
|
||||
return;
|
||||
|
||||
@ -2633,7 +2780,7 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
|
||||
* we still have control of it.
|
||||
*/
|
||||
if (intel_dp->pps_pipe != INVALID_PIPE)
|
||||
edp_panel_vdd_off_sync(intel_dp);
|
||||
vlv_detach_power_sequencer(intel_dp);
|
||||
|
||||
/*
|
||||
* We may be stealing the power
|
||||
@ -2648,9 +2795,8 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
|
||||
pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
|
||||
|
||||
/* init power sequencer on this pipe and port */
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
|
||||
&power_seq);
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp);
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
|
||||
}
|
||||
|
||||
static void vlv_pre_enable_dp(struct intel_encoder *encoder)
|
||||
@ -2679,15 +2825,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
|
||||
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
|
||||
if (is_edp(intel_dp)) {
|
||||
pps_lock(intel_dp);
|
||||
vlv_init_panel_power_sequencer(intel_dp);
|
||||
pps_unlock(intel_dp);
|
||||
}
|
||||
|
||||
intel_enable_dp(encoder);
|
||||
|
||||
vlv_wait_port_ready(dev_priv, dport);
|
||||
}
|
||||
|
||||
static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
|
||||
@ -2779,15 +2917,7 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
|
||||
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
|
||||
if (is_edp(intel_dp)) {
|
||||
pps_lock(intel_dp);
|
||||
vlv_init_panel_power_sequencer(intel_dp);
|
||||
pps_unlock(intel_dp);
|
||||
}
|
||||
|
||||
intel_enable_dp(encoder);
|
||||
|
||||
vlv_wait_port_ready(dev_priv, dport);
|
||||
}
|
||||
|
||||
static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
|
||||
@ -3696,7 +3826,6 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
|
||||
|
||||
/* Try 5 times, then try clock recovery if that fails */
|
||||
if (tries > 5) {
|
||||
intel_dp_link_down(intel_dp);
|
||||
intel_dp_start_link_train(intel_dp);
|
||||
intel_dp_set_link_train(intel_dp, &DP,
|
||||
training_pattern |
|
||||
@ -3854,8 +3983,6 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
|
||||
if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
|
||||
return;
|
||||
|
||||
intel_edp_panel_vdd_on(intel_dp);
|
||||
|
||||
if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3)
|
||||
DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
|
||||
buf[0], buf[1], buf[2]);
|
||||
@ -3863,8 +3990,6 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
|
||||
if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3)
|
||||
DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
|
||||
buf[0], buf[1], buf[2]);
|
||||
|
||||
intel_edp_panel_vdd_off(intel_dp, false);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -3878,7 +4003,6 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
|
||||
if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
|
||||
return false;
|
||||
|
||||
intel_edp_panel_vdd_on(intel_dp);
|
||||
if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
|
||||
if (buf[0] & DP_MST_CAP) {
|
||||
DRM_DEBUG_KMS("Sink is MST capable\n");
|
||||
@ -3888,7 +4012,6 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
|
||||
intel_dp->is_mst = false;
|
||||
}
|
||||
}
|
||||
intel_edp_panel_vdd_off(intel_dp, false);
|
||||
|
||||
drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
|
||||
return intel_dp->is_mst;
|
||||
@ -4568,9 +4691,52 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
|
||||
pps_unlock(intel_dp);
|
||||
}
|
||||
|
||||
static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_device *dev = intel_dig_port->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
enum intel_display_power_domain power_domain;
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (!edp_have_panel_vdd(intel_dp))
|
||||
return;
|
||||
|
||||
/*
|
||||
* The VDD bit needs a power domain reference, so if the bit is
|
||||
* already enabled when we boot or resume, grab this reference and
|
||||
* schedule a vdd off, so we don't hold on to the reference
|
||||
* indefinitely.
|
||||
*/
|
||||
DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n");
|
||||
power_domain = intel_display_port_power_domain(&intel_dig_port->base);
|
||||
intel_display_power_get(dev_priv, power_domain);
|
||||
|
||||
edp_panel_vdd_schedule_off(intel_dp);
|
||||
}
|
||||
|
||||
static void intel_dp_encoder_reset(struct drm_encoder *encoder)
|
||||
{
|
||||
intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder));
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP)
|
||||
return;
|
||||
|
||||
intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
pps_lock(intel_dp);
|
||||
|
||||
/*
|
||||
* Read out the current power sequencer assignment,
|
||||
* in case the BIOS did something with it.
|
||||
*/
|
||||
if (IS_VALLEYVIEW(encoder->dev))
|
||||
vlv_initial_power_sequencer_setup(intel_dp);
|
||||
|
||||
intel_edp_panel_vdd_sanitize(intel_dp);
|
||||
|
||||
pps_unlock(intel_dp);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs intel_dp_connector_funcs = {
|
||||
@ -4757,16 +4923,20 @@ static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
|
||||
|
||||
static void
|
||||
intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
||||
struct intel_dp *intel_dp,
|
||||
struct edp_power_seq *out)
|
||||
struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct edp_power_seq cur, vbt, spec, final;
|
||||
struct edp_power_seq cur, vbt, spec,
|
||||
*final = &intel_dp->pps_delays;
|
||||
u32 pp_on, pp_off, pp_div, pp;
|
||||
int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
/* already initialized? */
|
||||
if (final->t11_t12 != 0)
|
||||
return;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
pp_ctrl_reg = PCH_PP_CONTROL;
|
||||
pp_on_reg = PCH_PP_ON_DELAYS;
|
||||
@ -4828,7 +4998,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
||||
|
||||
/* Use the max of the register settings and vbt. If both are
|
||||
* unset, fall back to the spec limits. */
|
||||
#define assign_final(field) final.field = (max(cur.field, vbt.field) == 0 ? \
|
||||
#define assign_final(field) final->field = (max(cur.field, vbt.field) == 0 ? \
|
||||
spec.field : \
|
||||
max(cur.field, vbt.field))
|
||||
assign_final(t1_t3);
|
||||
@ -4838,7 +5008,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
||||
assign_final(t11_t12);
|
||||
#undef assign_final
|
||||
|
||||
#define get_delay(field) (DIV_ROUND_UP(final.field, 10))
|
||||
#define get_delay(field) (DIV_ROUND_UP(final->field, 10))
|
||||
intel_dp->panel_power_up_delay = get_delay(t1_t3);
|
||||
intel_dp->backlight_on_delay = get_delay(t8);
|
||||
intel_dp->backlight_off_delay = get_delay(t9);
|
||||
@ -4852,21 +5022,18 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
||||
|
||||
DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
|
||||
intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
|
||||
|
||||
if (out)
|
||||
*out = final;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
|
||||
struct intel_dp *intel_dp,
|
||||
struct edp_power_seq *seq)
|
||||
struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp_on, pp_off, pp_div, port_sel = 0;
|
||||
int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
|
||||
int pp_on_reg, pp_off_reg, pp_div_reg;
|
||||
enum port port = dp_to_dig_port(intel_dp)->port;
|
||||
const struct edp_power_seq *seq = &intel_dp->pps_delays;
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
@ -5052,40 +5219,8 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
|
||||
return downclock_mode;
|
||||
}
|
||||
|
||||
void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
|
||||
{
|
||||
struct drm_device *dev = intel_encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp *intel_dp;
|
||||
enum intel_display_power_domain power_domain;
|
||||
|
||||
if (intel_encoder->type != INTEL_OUTPUT_EDP)
|
||||
return;
|
||||
|
||||
intel_dp = enc_to_intel_dp(&intel_encoder->base);
|
||||
|
||||
pps_lock(intel_dp);
|
||||
|
||||
if (!edp_have_panel_vdd(intel_dp))
|
||||
goto out;
|
||||
/*
|
||||
* The VDD bit needs a power domain reference, so if the bit is
|
||||
* already enabled when we boot or resume, grab this reference and
|
||||
* schedule a vdd off, so we don't hold on to the reference
|
||||
* indefinitely.
|
||||
*/
|
||||
DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n");
|
||||
power_domain = intel_display_port_power_domain(intel_encoder);
|
||||
intel_display_power_get(dev_priv, power_domain);
|
||||
|
||||
edp_panel_vdd_schedule_off(intel_dp);
|
||||
out:
|
||||
pps_unlock(intel_dp);
|
||||
}
|
||||
|
||||
static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
struct intel_connector *intel_connector,
|
||||
struct edp_power_seq *power_seq)
|
||||
struct intel_connector *intel_connector)
|
||||
{
|
||||
struct drm_connector *connector = &intel_connector->base;
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
@ -5103,12 +5238,12 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
if (!is_edp(intel_dp))
|
||||
return true;
|
||||
|
||||
intel_edp_panel_vdd_sanitize(intel_encoder);
|
||||
pps_lock(intel_dp);
|
||||
intel_edp_panel_vdd_sanitize(intel_dp);
|
||||
pps_unlock(intel_dp);
|
||||
|
||||
/* Cache DPCD and EDID for edp. */
|
||||
intel_edp_panel_vdd_on(intel_dp);
|
||||
has_dpcd = intel_dp_get_dpcd(intel_dp);
|
||||
intel_edp_panel_vdd_off(intel_dp, false);
|
||||
|
||||
if (has_dpcd) {
|
||||
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
|
||||
@ -5123,7 +5258,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
|
||||
/* We now know it's not a ghost, init power sequence regs. */
|
||||
pps_lock(intel_dp);
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
|
||||
pps_unlock(intel_dp);
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
@ -5184,7 +5319,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
||||
struct drm_device *dev = intel_encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
enum port port = intel_dig_port->port;
|
||||
struct edp_power_seq power_seq = { 0 };
|
||||
int type;
|
||||
|
||||
intel_dp->pps_pipe = INVALID_PIPE;
|
||||
@ -5223,6 +5357,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
||||
if (type == DRM_MODE_CONNECTOR_eDP)
|
||||
intel_encoder->type = INTEL_OUTPUT_EDP;
|
||||
|
||||
/* eDP only on port B and/or C on vlv/chv */
|
||||
if (WARN_ON(IS_VALLEYVIEW(dev) && is_edp(intel_dp) &&
|
||||
port != PORT_B && port != PORT_C))
|
||||
return false;
|
||||
|
||||
DRM_DEBUG_KMS("Adding %s connector on port %c\n",
|
||||
type == DRM_MODE_CONNECTOR_eDP ? "eDP" : "DP",
|
||||
port_name(port));
|
||||
@ -5265,13 +5404,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
||||
|
||||
if (is_edp(intel_dp)) {
|
||||
pps_lock(intel_dp);
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
intel_dp_init_panel_power_timestamps(intel_dp);
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
vlv_initial_power_sequencer_setup(intel_dp);
|
||||
} else {
|
||||
intel_dp_init_panel_power_timestamps(intel_dp);
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp,
|
||||
&power_seq);
|
||||
}
|
||||
else
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp);
|
||||
pps_unlock(intel_dp);
|
||||
}
|
||||
|
||||
@ -5285,7 +5422,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
||||
}
|
||||
}
|
||||
|
||||
if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
|
||||
if (!intel_edp_init_connector(intel_dp, intel_connector)) {
|
||||
drm_dp_aux_unregister(&intel_dp->aux);
|
||||
if (is_edp(intel_dp)) {
|
||||
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
|
||||
|
@ -94,18 +94,20 @@
|
||||
|
||||
/* these are outputs from the chip - integrated only
|
||||
external chips are via DVO or SDVO output */
|
||||
#define INTEL_OUTPUT_UNUSED 0
|
||||
#define INTEL_OUTPUT_ANALOG 1
|
||||
#define INTEL_OUTPUT_DVO 2
|
||||
#define INTEL_OUTPUT_SDVO 3
|
||||
#define INTEL_OUTPUT_LVDS 4
|
||||
#define INTEL_OUTPUT_TVOUT 5
|
||||
#define INTEL_OUTPUT_HDMI 6
|
||||
#define INTEL_OUTPUT_DISPLAYPORT 7
|
||||
#define INTEL_OUTPUT_EDP 8
|
||||
#define INTEL_OUTPUT_DSI 9
|
||||
#define INTEL_OUTPUT_UNKNOWN 10
|
||||
#define INTEL_OUTPUT_DP_MST 11
|
||||
enum intel_output_type {
|
||||
INTEL_OUTPUT_UNUSED = 0,
|
||||
INTEL_OUTPUT_ANALOG = 1,
|
||||
INTEL_OUTPUT_DVO = 2,
|
||||
INTEL_OUTPUT_SDVO = 3,
|
||||
INTEL_OUTPUT_LVDS = 4,
|
||||
INTEL_OUTPUT_TVOUT = 5,
|
||||
INTEL_OUTPUT_HDMI = 6,
|
||||
INTEL_OUTPUT_DISPLAYPORT = 7,
|
||||
INTEL_OUTPUT_EDP = 8,
|
||||
INTEL_OUTPUT_DSI = 9,
|
||||
INTEL_OUTPUT_UNKNOWN = 10,
|
||||
INTEL_OUTPUT_DP_MST = 11,
|
||||
};
|
||||
|
||||
#define INTEL_DVO_CHIP_NONE 0
|
||||
#define INTEL_DVO_CHIP_LVDS 1
|
||||
@ -136,7 +138,7 @@ struct intel_encoder {
|
||||
*/
|
||||
struct intel_crtc *new_crtc;
|
||||
|
||||
int type;
|
||||
enum intel_output_type type;
|
||||
unsigned int cloneable;
|
||||
bool connectors_active;
|
||||
void (*hot_plug)(struct intel_encoder *);
|
||||
@ -399,7 +401,14 @@ struct intel_pipe_wm {
|
||||
|
||||
struct intel_mmio_flip {
|
||||
u32 seqno;
|
||||
u32 ring_id;
|
||||
struct intel_engine_cs *ring;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
struct skl_pipe_wm {
|
||||
struct skl_wm_level wm[8];
|
||||
struct skl_wm_level trans_wm;
|
||||
uint32_t linetime;
|
||||
};
|
||||
|
||||
struct intel_crtc {
|
||||
@ -449,6 +458,8 @@ struct intel_crtc {
|
||||
struct {
|
||||
/* watermarks currently being used */
|
||||
struct intel_pipe_wm active;
|
||||
/* SKL wm values currently in use */
|
||||
struct skl_pipe_wm skl_active;
|
||||
} wm;
|
||||
|
||||
int scanline_offset;
|
||||
@ -590,6 +601,7 @@ struct intel_dp {
|
||||
* this port. Only relevant on VLV/CHV.
|
||||
*/
|
||||
enum pipe pps_pipe;
|
||||
struct edp_power_seq pps_delays;
|
||||
|
||||
bool use_tps3;
|
||||
bool can_mst; /* this port supports mst */
|
||||
@ -848,6 +860,11 @@ void intel_frontbuffer_flip(struct drm_device *dev,
|
||||
void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
|
||||
|
||||
|
||||
/* intel_audio.c */
|
||||
void intel_init_audio(struct drm_device *dev);
|
||||
void intel_audio_codec_enable(struct intel_encoder *encoder);
|
||||
void intel_audio_codec_disable(struct intel_encoder *encoder);
|
||||
|
||||
/* intel_display.c */
|
||||
const char *intel_output_name(int output);
|
||||
bool intel_has_pending_fb_unpin(struct drm_device *dev);
|
||||
@ -873,6 +890,7 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe);
|
||||
bool intel_pipe_has_type(struct intel_crtc *crtc, enum intel_output_type type);
|
||||
static inline void
|
||||
intel_wait_for_vblank(struct drm_device *dev, int pipe)
|
||||
{
|
||||
@ -887,8 +905,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
void intel_release_load_detect_pipe(struct drm_connector *connector,
|
||||
struct intel_load_detect_pipe *old);
|
||||
int intel_pin_and_fence_fb_obj(struct drm_device *dev,
|
||||
struct drm_i915_gem_object *obj,
|
||||
int intel_pin_and_fence_fb_obj(struct drm_plane *plane,
|
||||
struct drm_framebuffer *fb,
|
||||
struct intel_engine_cs *pipelined);
|
||||
void intel_unpin_fb_obj(struct drm_i915_gem_object *obj);
|
||||
struct drm_framebuffer *
|
||||
@ -910,6 +928,10 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc);
|
||||
void intel_put_shared_dpll(struct intel_crtc *crtc);
|
||||
|
||||
void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
|
||||
const struct dpll *dpll);
|
||||
void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe);
|
||||
|
||||
/* modesetting asserts */
|
||||
void assert_panel_unlocked(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe);
|
||||
@ -924,8 +946,6 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
|
||||
void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
|
||||
#define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
|
||||
#define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
|
||||
void intel_write_eld(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode);
|
||||
unsigned long intel_gen4_compute_page_offset(int *x, int *y,
|
||||
unsigned int tiling_mode,
|
||||
unsigned int bpp,
|
||||
@ -970,7 +990,6 @@ bool intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port,
|
||||
void intel_edp_backlight_on(struct intel_dp *intel_dp);
|
||||
void intel_edp_backlight_off(struct intel_dp *intel_dp);
|
||||
void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
|
||||
void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder);
|
||||
void intel_edp_panel_on(struct intel_dp *intel_dp);
|
||||
void intel_edp_panel_off(struct intel_dp *intel_dp);
|
||||
void intel_edp_psr_enable(struct intel_dp *intel_dp);
|
||||
@ -982,7 +1001,6 @@ void intel_edp_psr_flush(struct drm_device *dev,
|
||||
unsigned frontbuffer_bits);
|
||||
void intel_edp_psr_init(struct drm_device *dev);
|
||||
|
||||
int intel_dp_handle_hpd_irq(struct intel_digital_port *digport, bool long_hpd);
|
||||
void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector);
|
||||
void intel_dp_mst_suspend(struct drm_device *dev);
|
||||
void intel_dp_mst_resume(struct drm_device *dev);
|
||||
@ -1139,6 +1157,9 @@ void gen6_update_ring_freq(struct drm_device *dev);
|
||||
void gen6_rps_idle(struct drm_i915_private *dev_priv);
|
||||
void gen6_rps_boost(struct drm_i915_private *dev_priv);
|
||||
void ilk_wm_get_hw_state(struct drm_device *dev);
|
||||
void skl_wm_get_hw_state(struct drm_device *dev);
|
||||
void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct skl_ddb_allocation *ddb /* out */);
|
||||
|
||||
|
||||
/* intel_sdvo.c */
|
||||
@ -1158,7 +1179,9 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
bool intel_pipe_update_start(struct intel_crtc *crtc,
|
||||
uint32_t *start_vbl_count);
|
||||
void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count);
|
||||
|
||||
/* intel_tv.c */
|
||||
void intel_tv_init(struct drm_device *dev);
|
||||
|
@ -119,25 +119,25 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Flush everything out, we'll be doing GTT only from now on */
|
||||
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to pin obj: %d\n", ret);
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
|
||||
if (IS_ERR(fb)) {
|
||||
ret = PTR_ERR(fb);
|
||||
goto out_unpin;
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
/* Flush everything out, we'll be doing GTT only from now on */
|
||||
ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to pin obj: %d\n", ret);
|
||||
goto out_fb;
|
||||
}
|
||||
|
||||
ifbdev->fb = to_intel_framebuffer(fb);
|
||||
|
||||
return 0;
|
||||
|
||||
out_unpin:
|
||||
i915_gem_object_ggtt_unpin(obj);
|
||||
out_fb:
|
||||
drm_framebuffer_remove(fb);
|
||||
out_unref:
|
||||
drm_gem_object_unreference(&obj->base);
|
||||
out:
|
||||
|
@ -661,14 +661,6 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder)
|
||||
if (crtc->config.has_hdmi_sink)
|
||||
hdmi_val |= HDMI_MODE_SELECT_HDMI;
|
||||
|
||||
if (crtc->config.has_audio) {
|
||||
WARN_ON(!crtc->config.has_hdmi_sink);
|
||||
DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
|
||||
pipe_name(crtc->pipe));
|
||||
hdmi_val |= SDVO_AUDIO_ENABLE;
|
||||
intel_write_eld(&encoder->base, adjusted_mode);
|
||||
}
|
||||
|
||||
if (HAS_PCH_CPT(dev))
|
||||
hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe);
|
||||
else if (IS_CHERRYVIEW(dev))
|
||||
@ -791,6 +783,13 @@ static void intel_enable_hdmi(struct intel_encoder *encoder)
|
||||
I915_WRITE(intel_hdmi->hdmi_reg, temp);
|
||||
POSTING_READ(intel_hdmi->hdmi_reg);
|
||||
}
|
||||
|
||||
if (intel_crtc->config.has_audio) {
|
||||
WARN_ON(!intel_crtc->config.has_hdmi_sink);
|
||||
DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
|
||||
pipe_name(intel_crtc->pipe));
|
||||
intel_audio_codec_enable(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
static void vlv_enable_hdmi(struct intel_encoder *encoder)
|
||||
@ -802,9 +801,13 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
|
||||
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
|
||||
u32 temp;
|
||||
u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE;
|
||||
|
||||
if (crtc->config.has_audio)
|
||||
intel_audio_codec_disable(encoder);
|
||||
|
||||
temp = I915_READ(intel_hdmi->hdmi_reg);
|
||||
|
||||
/* HW workaround for IBX, we need to move the port to transcoder A
|
||||
|
@ -356,9 +356,9 @@ static int execlists_ctx_write_tail(struct drm_i915_gem_object *ctx_obj, u32 tai
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int execlists_submit_context(struct intel_engine_cs *ring,
|
||||
struct intel_context *to0, u32 tail0,
|
||||
struct intel_context *to1, u32 tail1)
|
||||
static void execlists_submit_contexts(struct intel_engine_cs *ring,
|
||||
struct intel_context *to0, u32 tail0,
|
||||
struct intel_context *to1, u32 tail1)
|
||||
{
|
||||
struct drm_i915_gem_object *ctx_obj0;
|
||||
struct drm_i915_gem_object *ctx_obj1 = NULL;
|
||||
@ -378,8 +378,6 @@ static int execlists_submit_context(struct intel_engine_cs *ring,
|
||||
}
|
||||
|
||||
execlists_elsp_write(ring, ctx_obj0, ctx_obj1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void execlists_context_unqueue(struct intel_engine_cs *ring)
|
||||
@ -413,9 +411,9 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)
|
||||
|
||||
WARN_ON(req1 && req1->elsp_submitted);
|
||||
|
||||
WARN_ON(execlists_submit_context(ring, req0->ctx, req0->tail,
|
||||
req1 ? req1->ctx : NULL,
|
||||
req1 ? req1->tail : 0));
|
||||
execlists_submit_contexts(ring, req0->ctx, req0->tail,
|
||||
req1 ? req1->ctx : NULL,
|
||||
req1 ? req1->tail : 0);
|
||||
|
||||
req0->elsp_submitted++;
|
||||
if (req1)
|
||||
@ -1214,11 +1212,13 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf)
|
||||
*/
|
||||
void intel_logical_ring_cleanup(struct intel_engine_cs *ring)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
||||
struct drm_i915_private *dev_priv;
|
||||
|
||||
if (!intel_ring_initialized(ring))
|
||||
return;
|
||||
|
||||
dev_priv = ring->dev->dev_private;
|
||||
|
||||
intel_logical_ring_stop(ring);
|
||||
WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
|
||||
ring->preallocated_lazy_request = NULL;
|
||||
@ -1649,6 +1649,27 @@ static uint32_t get_lr_context_size(struct intel_engine_cs *ring)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
|
||||
struct drm_i915_gem_object *default_ctx_obj)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
||||
|
||||
/* The status page is offset 0 from the default context object
|
||||
* in LRC mode. */
|
||||
ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj);
|
||||
ring->status_page.page_addr =
|
||||
kmap(sg_page(default_ctx_obj->pages->sgl));
|
||||
if (ring->status_page.page_addr == NULL)
|
||||
return -ENOMEM;
|
||||
ring->status_page.obj = default_ctx_obj;
|
||||
|
||||
I915_WRITE(RING_HWS_PGA(ring->mmio_base),
|
||||
(u32)ring->status_page.gfx_addr);
|
||||
POSTING_READ(RING_HWS_PGA(ring->mmio_base));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_lr_context_deferred_create() - create the LRC specific bits of a context
|
||||
* @ctx: LR context to create.
|
||||
@ -1734,14 +1755,11 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,
|
||||
ctx->engine[ring->id].state = ctx_obj;
|
||||
|
||||
if (ctx == ring->default_context) {
|
||||
/* The status page is offset 0 from the default context object
|
||||
* in LRC mode. */
|
||||
ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(ctx_obj);
|
||||
ring->status_page.page_addr =
|
||||
kmap(sg_page(ctx_obj->pages->sgl));
|
||||
if (ring->status_page.page_addr == NULL)
|
||||
return -ENOMEM;
|
||||
ring->status_page.obj = ctx_obj;
|
||||
ret = lrc_setup_hardware_status_page(ring, ctx_obj);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to setup hardware status page\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (ring->id == RCS && !ctx->rcs_initialized) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,7 @@
|
||||
extern const struct intel_renderstate_rodata gen6_null_state;
|
||||
extern const struct intel_renderstate_rodata gen7_null_state;
|
||||
extern const struct intel_renderstate_rodata gen8_null_state;
|
||||
extern const struct intel_renderstate_rodata gen9_null_state;
|
||||
|
||||
#define RO_RENDERSTATE(_g) \
|
||||
const struct intel_renderstate_rodata gen ## _g ## _null_state = { \
|
||||
|
File diff suppressed because it is too large
Load Diff
974
drivers/gpu/drm/i915/intel_renderstate_gen9.c
Normal file
974
drivers/gpu/drm/i915/intel_renderstate_gen9.c
Normal file
@ -0,0 +1,974 @@
|
||||
#include "intel_renderstate.h"
|
||||
|
||||
static const u32 gen9_null_state_relocs[] = {
|
||||
0x000007a8,
|
||||
0x000007b4,
|
||||
0x000007bc,
|
||||
0x000007cc,
|
||||
-1,
|
||||
};
|
||||
|
||||
static const u32 gen9_null_state_batch[] = {
|
||||
0x7a000004,
|
||||
0x01000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x69040300,
|
||||
0x78140000,
|
||||
0x04000000,
|
||||
0x7820000a,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x80000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78130002,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x02001808,
|
||||
0x781f0004,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78510009,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78100007,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00010000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x781b0007,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000800,
|
||||
0x00000000,
|
||||
0x78110008,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x781e0003,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x781d0009,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78120002,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78500003,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x781c0002,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x780c0000,
|
||||
0x00000000,
|
||||
0x78520003,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78300000,
|
||||
0x08010040,
|
||||
0x78310000,
|
||||
0x1e000000,
|
||||
0x78320000,
|
||||
0x1e000000,
|
||||
0x78330000,
|
||||
0x1e000000,
|
||||
0x79190002,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x791a0002,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x791b0002,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79120000,
|
||||
0x00000000,
|
||||
0x79130000,
|
||||
0x00000000,
|
||||
0x79140000,
|
||||
0x00000000,
|
||||
0x79150000,
|
||||
0x00000000,
|
||||
0x79160000,
|
||||
0x00000000,
|
||||
0x78150009,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78190009,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x781a0009,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78160009,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78170009,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78490001,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x784a0000,
|
||||
0x00000000,
|
||||
0x784b0000,
|
||||
0x00000004,
|
||||
0x79170101,
|
||||
0x00000000,
|
||||
0x00000080,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79180006,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79180006,
|
||||
0x20000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79180006,
|
||||
0x40000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79180006,
|
||||
0x60000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x61010011,
|
||||
0x00000001, /* reloc */
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000001, /* reloc */
|
||||
0x00000000,
|
||||
0x00000001, /* reloc */
|
||||
0x00000000,
|
||||
0x00000001,
|
||||
0x00000000,
|
||||
0x00000001, /* reloc */
|
||||
0x00000000,
|
||||
0x00001001,
|
||||
0x00001001,
|
||||
0x00000001,
|
||||
0x00001001,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x61020001,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79000002,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78050006,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79040002,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79040002,
|
||||
0x40000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79040002,
|
||||
0x80000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79040002,
|
||||
0xc0000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79080001,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x790a0001,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78060003,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78070003,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78040001,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x79110000,
|
||||
0x00000000,
|
||||
0x780d0000,
|
||||
0x00000000,
|
||||
0x79060000,
|
||||
0x00000000,
|
||||
0x7907001f,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x7902000f,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x790c000f,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x780a0003,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78080083,
|
||||
0x00004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x04004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x08004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0c004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x10004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x14004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x18004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x1c004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x20004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x24004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x28004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x2c004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x30004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x34004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x38004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x3c004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x40004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x44004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x48004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x4c004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x50004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x54004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x58004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x5c004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x60004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x64004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x68004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x6c004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x70004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x74004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x7c004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x80004000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78090043,
|
||||
0x02000000,
|
||||
0x22220000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x78550003,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x680b0001,
|
||||
0x780e0000,
|
||||
0x00000e01,
|
||||
0x78240000,
|
||||
0x00000e41,
|
||||
0x784f0000,
|
||||
0x80000100,
|
||||
0x784d0000,
|
||||
0x40000000,
|
||||
0x782b0000,
|
||||
0x00000000,
|
||||
0x782c0000,
|
||||
0x00000000,
|
||||
0x782d0000,
|
||||
0x00000000,
|
||||
0x782e0000,
|
||||
0x00000000,
|
||||
0x782f0000,
|
||||
0x00000000,
|
||||
0x780f0000,
|
||||
0x00000000,
|
||||
0x78230000,
|
||||
0x00000ea0,
|
||||
0x78210000,
|
||||
0x00000ec0,
|
||||
0x78260000,
|
||||
0x00000000,
|
||||
0x78270000,
|
||||
0x00000000,
|
||||
0x78280000,
|
||||
0x00000000,
|
||||
0x78290000,
|
||||
0x00000000,
|
||||
0x782a0000,
|
||||
0x00000000,
|
||||
0x7b000005,
|
||||
0x00000004,
|
||||
0x00000001,
|
||||
0x00000000,
|
||||
0x00000001,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x05000000, /* cmds end */
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000, /* state start */
|
||||
0x00000000,
|
||||
0x3f800000,
|
||||
0x3f800000,
|
||||
0x3f800000,
|
||||
0x3f800000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000, /* state end */
|
||||
};
|
||||
|
||||
RO_RENDERSTATE(9);
|
@ -1845,12 +1845,15 @@ error:
|
||||
|
||||
void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(ring->dev);
|
||||
struct intel_ringbuffer *ringbuf = ring->buffer;
|
||||
struct drm_i915_private *dev_priv;
|
||||
struct intel_ringbuffer *ringbuf;
|
||||
|
||||
if (!intel_ring_initialized(ring))
|
||||
return;
|
||||
|
||||
dev_priv = to_i915(ring->dev);
|
||||
ringbuf = ring->buffer;
|
||||
|
||||
intel_stop_ring_buffer(ring);
|
||||
WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
|
||||
|
||||
|
@ -587,6 +587,9 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
|
||||
power_well->data != PIPE_C);
|
||||
|
||||
chv_set_pipe_power_well(dev_priv, power_well, false);
|
||||
|
||||
if (power_well->data == PIPE_A)
|
||||
vlv_power_sequencer_reset(dev_priv);
|
||||
}
|
||||
|
||||
static void check_power_well_state(struct drm_i915_private *dev_priv,
|
||||
@ -938,12 +941,20 @@ static struct i915_power_well chv_power_wells[] = {
|
||||
.data = PUNIT_POWER_WELL_DISP2D,
|
||||
.ops = &vlv_display_power_well_ops,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.name = "pipe-a",
|
||||
.domains = CHV_PIPE_A_POWER_DOMAINS,
|
||||
/*
|
||||
* FIXME: pipe A power well seems to be the new disp2d well.
|
||||
* At least all registers seem to be housed there. Figure
|
||||
* out if this a a temporary situation in pre-production
|
||||
* hardware or a permanent state of affairs.
|
||||
*/
|
||||
.domains = CHV_PIPE_A_POWER_DOMAINS | VLV_DISPLAY_POWER_DOMAINS,
|
||||
.data = PIPE_A,
|
||||
.ops = &chv_pipe_power_well_ops,
|
||||
},
|
||||
#if 0
|
||||
{
|
||||
.name = "pipe-b",
|
||||
.domains = CHV_PIPE_B_POWER_DOMAINS,
|
||||
@ -1137,12 +1148,9 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
|
||||
struct i915_power_well *disp2d =
|
||||
lookup_power_well(dev_priv, PUNIT_POWER_WELL_DISP2D);
|
||||
|
||||
/* nothing to do if common lane is already off */
|
||||
if (!cmn->ops->is_enabled(dev_priv, cmn))
|
||||
return;
|
||||
|
||||
/* If the display might be already active skip this */
|
||||
if (disp2d->ops->is_enabled(dev_priv, disp2d) &&
|
||||
if (cmn->ops->is_enabled(dev_priv, cmn) &&
|
||||
disp2d->ops->is_enabled(dev_priv, disp2d) &&
|
||||
I915_READ(DPIO_CTL) & DPIO_CMNRST)
|
||||
return;
|
||||
|
||||
|
@ -37,6 +37,20 @@
|
||||
#include <drm/i915_drm.h>
|
||||
#include "i915_drv.h"
|
||||
|
||||
static bool
|
||||
format_is_yuv(uint32_t format)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_YUYV:
|
||||
case DRM_FORMAT_UYVY:
|
||||
case DRM_FORMAT_VYUY:
|
||||
case DRM_FORMAT_YVYU:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
|
||||
{
|
||||
/* paranoia */
|
||||
@ -46,7 +60,23 @@ static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
|
||||
return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal);
|
||||
}
|
||||
|
||||
static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
|
||||
/**
|
||||
* intel_pipe_update_start() - start update of a set of display registers
|
||||
* @crtc: the crtc of which the registers are going to be updated
|
||||
* @start_vbl_count: vblank counter return pointer used for error checking
|
||||
*
|
||||
* Mark the start of an update to pipe registers that should be updated
|
||||
* atomically regarding vblank. If the next vblank will happens within
|
||||
* the next 100 us, this function waits until the vblank passes.
|
||||
*
|
||||
* After a successful call to this function, interrupts will be disabled
|
||||
* until a subsequent call to intel_pipe_update_end(). That is done to
|
||||
* avoid random delays. The value written to @start_vbl_count should be
|
||||
* supplied to intel_pipe_update_end() for error checking.
|
||||
*
|
||||
* Return: true if the call was successful
|
||||
*/
|
||||
bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
|
||||
@ -56,8 +86,6 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
|
||||
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex));
|
||||
|
||||
vblank_start = mode->crtc_vblank_start;
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
vblank_start = DIV_ROUND_UP(vblank_start, 2);
|
||||
@ -112,7 +140,16 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
|
||||
return true;
|
||||
}
|
||||
|
||||
static void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
|
||||
/**
|
||||
* intel_pipe_update_end() - end update of a set of display registers
|
||||
* @crtc: the crtc of which the registers were updated
|
||||
* @start_vbl_count: start vblank counter (used for error checking)
|
||||
*
|
||||
* Mark the end of an update started with intel_pipe_update_start(). This
|
||||
* re-enables interrupts and verifies the update was actually completed
|
||||
* before a vblank using the value of @start_vbl_count.
|
||||
*/
|
||||
void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
@ -319,6 +356,45 @@ skl_get_colorkey(struct drm_plane *drm_plane,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private;
|
||||
int plane = intel_plane->plane;
|
||||
|
||||
/* Seems RGB data bypasses the CSC always */
|
||||
if (!format_is_yuv(format))
|
||||
return;
|
||||
|
||||
/*
|
||||
* BT.601 limited range YCbCr -> full range RGB
|
||||
*
|
||||
* |r| | 6537 4769 0| |cr |
|
||||
* |g| = |-3330 4769 -1605| x |y-64|
|
||||
* |b| | 0 4769 8263| |cb |
|
||||
*
|
||||
* Cb and Cr apparently come in as signed already, so no
|
||||
* need for any offset. For Y we need to remove the offset.
|
||||
*/
|
||||
I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
|
||||
I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
|
||||
I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
|
||||
|
||||
I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537));
|
||||
I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0));
|
||||
I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769));
|
||||
I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0));
|
||||
I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263));
|
||||
|
||||
I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64));
|
||||
I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
|
||||
I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
|
||||
|
||||
I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
|
||||
I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
|
||||
I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
|
||||
}
|
||||
|
||||
static void
|
||||
vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
@ -430,6 +506,9 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
|
||||
|
||||
intel_update_primary_plane(intel_crtc);
|
||||
|
||||
if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
|
||||
chv_update_csc(intel_plane, fb->pixel_format);
|
||||
|
||||
I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
|
||||
I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
|
||||
|
||||
@ -438,6 +517,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
|
||||
else
|
||||
I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
|
||||
|
||||
I915_WRITE(SPCONSTALPHA(pipe, plane), 0);
|
||||
|
||||
I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
|
||||
I915_WRITE(SPCNTR(pipe, plane), sprctl);
|
||||
I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
|
||||
@ -1002,20 +1083,6 @@ ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
|
||||
key->flags = I915_SET_COLORKEY_NONE;
|
||||
}
|
||||
|
||||
static bool
|
||||
format_is_yuv(uint32_t format)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_YUYV:
|
||||
case DRM_FORMAT_UYVY:
|
||||
case DRM_FORMAT_VYUY:
|
||||
case DRM_FORMAT_YVYU:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool colorkey_enabled(struct intel_plane *intel_plane)
|
||||
{
|
||||
struct drm_intel_sprite_colorkey key;
|
||||
@ -1032,8 +1099,7 @@ intel_check_sprite_plane(struct drm_plane *plane,
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(state->crtc);
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
||||
struct drm_i915_gem_object *obj = intel_fb->obj;
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
int crtc_x, crtc_y;
|
||||
unsigned int crtc_w, crtc_h;
|
||||
uint32_t src_x, src_y, src_w, src_h;
|
||||
@ -1192,34 +1258,18 @@ intel_check_sprite_plane(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
static int
|
||||
intel_commit_sprite_plane(struct drm_plane *plane,
|
||||
struct intel_plane_state *state)
|
||||
intel_prepare_sprite_plane(struct drm_plane *plane,
|
||||
struct intel_plane_state *state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
||||
struct drm_i915_gem_object *obj = intel_fb->obj;
|
||||
struct drm_i915_gem_object *old_obj = intel_plane->obj;
|
||||
int crtc_x, crtc_y;
|
||||
unsigned int crtc_w, crtc_h;
|
||||
uint32_t src_x, src_y, src_w, src_h;
|
||||
struct drm_rect *dst = &state->dst;
|
||||
const struct drm_rect *clip = &state->clip;
|
||||
bool primary_enabled;
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If the sprite is completely covering the primary plane,
|
||||
* we can disable the primary and save power.
|
||||
*/
|
||||
primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane);
|
||||
WARN_ON(!primary_enabled && !state->visible && intel_crtc->active);
|
||||
|
||||
|
||||
if (old_obj != obj) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
@ -1229,7 +1279,7 @@ intel_commit_sprite_plane(struct drm_plane *plane,
|
||||
* the sprite planes only require 128KiB alignment and 32 PTE
|
||||
* padding.
|
||||
*/
|
||||
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
|
||||
ret = intel_pin_and_fence_fb_obj(plane, fb, NULL);
|
||||
if (ret == 0)
|
||||
i915_gem_track_fb(old_obj, obj,
|
||||
INTEL_FRONTBUFFER_SPRITE(pipe));
|
||||
@ -1238,6 +1288,35 @@ intel_commit_sprite_plane(struct drm_plane *plane,
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_commit_sprite_plane(struct drm_plane *plane,
|
||||
struct intel_plane_state *state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_plane *intel_plane = to_intel_plane(plane);
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
|
||||
int crtc_x, crtc_y;
|
||||
unsigned int crtc_w, crtc_h;
|
||||
uint32_t src_x, src_y, src_w, src_h;
|
||||
struct drm_rect *dst = &state->dst;
|
||||
const struct drm_rect *clip = &state->clip;
|
||||
bool primary_enabled;
|
||||
|
||||
/*
|
||||
* If the sprite is completely covering the primary plane,
|
||||
* we can disable the primary and save power.
|
||||
*/
|
||||
primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane);
|
||||
WARN_ON(!primary_enabled && !state->visible && intel_crtc->active);
|
||||
|
||||
intel_plane->crtc_x = state->orig_dst.x1;
|
||||
intel_plane->crtc_y = state->orig_dst.y1;
|
||||
intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
|
||||
@ -1298,8 +1377,6 @@ intel_commit_sprite_plane(struct drm_plane *plane,
|
||||
intel_unpin_fb_obj(old_obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1339,7 +1416,12 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return intel_commit_sprite_plane(plane, &state);
|
||||
ret = intel_prepare_sprite_plane(plane, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
intel_commit_sprite_plane(plane, &state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -194,15 +194,13 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
|
||||
static void __vlv_force_wake_get(struct drm_i915_private *dev_priv,
|
||||
int fw_engine)
|
||||
{
|
||||
/*
|
||||
* WaRsDontPollForAckOnClearingFWBits:vlv
|
||||
* Hardware clears ack bits lazily (only when all ack
|
||||
* bits become 0) so don't poll for individiual ack
|
||||
* bits to be clear here like on other platforms.
|
||||
*/
|
||||
|
||||
/* Check for Render Engine */
|
||||
if (FORCEWAKE_RENDER & fw_engine) {
|
||||
if (wait_for_atomic((__raw_i915_read32(dev_priv,
|
||||
FORCEWAKE_ACK_VLV) &
|
||||
FORCEWAKE_KERNEL) == 0,
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
DRM_ERROR("Timed out: Render forcewake old ack to clear.\n");
|
||||
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_VLV,
|
||||
_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
|
||||
@ -216,6 +214,11 @@ static void __vlv_force_wake_get(struct drm_i915_private *dev_priv,
|
||||
|
||||
/* Check for Media Engine */
|
||||
if (FORCEWAKE_MEDIA & fw_engine) {
|
||||
if (wait_for_atomic((__raw_i915_read32(dev_priv,
|
||||
FORCEWAKE_ACK_MEDIA_VLV) &
|
||||
FORCEWAKE_KERNEL) == 0,
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
DRM_ERROR("Timed out: Media forcewake old ack to clear.\n");
|
||||
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
|
||||
_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
|
||||
@ -296,6 +299,154 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void __gen9_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_RENDER_GEN9,
|
||||
_MASKED_BIT_DISABLE(0xffff));
|
||||
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_GEN9,
|
||||
_MASKED_BIT_DISABLE(0xffff));
|
||||
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_BLITTER_GEN9,
|
||||
_MASKED_BIT_DISABLE(0xffff));
|
||||
}
|
||||
|
||||
static void
|
||||
__gen9_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
|
||||
{
|
||||
/* Check for Render Engine */
|
||||
if (FORCEWAKE_RENDER & fw_engine) {
|
||||
if (wait_for_atomic((__raw_i915_read32(dev_priv,
|
||||
FORCEWAKE_ACK_RENDER_GEN9) &
|
||||
FORCEWAKE_KERNEL) == 0,
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
DRM_ERROR("Timed out: Render forcewake old ack to clear.\n");
|
||||
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_RENDER_GEN9,
|
||||
_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
|
||||
|
||||
if (wait_for_atomic((__raw_i915_read32(dev_priv,
|
||||
FORCEWAKE_ACK_RENDER_GEN9) &
|
||||
FORCEWAKE_KERNEL),
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
DRM_ERROR("Timed out: waiting for Render to ack.\n");
|
||||
}
|
||||
|
||||
/* Check for Media Engine */
|
||||
if (FORCEWAKE_MEDIA & fw_engine) {
|
||||
if (wait_for_atomic((__raw_i915_read32(dev_priv,
|
||||
FORCEWAKE_ACK_MEDIA_GEN9) &
|
||||
FORCEWAKE_KERNEL) == 0,
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
DRM_ERROR("Timed out: Media forcewake old ack to clear.\n");
|
||||
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_GEN9,
|
||||
_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
|
||||
|
||||
if (wait_for_atomic((__raw_i915_read32(dev_priv,
|
||||
FORCEWAKE_ACK_MEDIA_GEN9) &
|
||||
FORCEWAKE_KERNEL),
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
DRM_ERROR("Timed out: waiting for Media to ack.\n");
|
||||
}
|
||||
|
||||
/* Check for Blitter Engine */
|
||||
if (FORCEWAKE_BLITTER & fw_engine) {
|
||||
if (wait_for_atomic((__raw_i915_read32(dev_priv,
|
||||
FORCEWAKE_ACK_BLITTER_GEN9) &
|
||||
FORCEWAKE_KERNEL) == 0,
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
DRM_ERROR("Timed out: Blitter forcewake old ack to clear.\n");
|
||||
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_BLITTER_GEN9,
|
||||
_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
|
||||
|
||||
if (wait_for_atomic((__raw_i915_read32(dev_priv,
|
||||
FORCEWAKE_ACK_BLITTER_GEN9) &
|
||||
FORCEWAKE_KERNEL),
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
DRM_ERROR("Timed out: waiting for Blitter to ack.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
__gen9_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
|
||||
{
|
||||
/* Check for Render Engine */
|
||||
if (FORCEWAKE_RENDER & fw_engine)
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_RENDER_GEN9,
|
||||
_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
|
||||
|
||||
/* Check for Media Engine */
|
||||
if (FORCEWAKE_MEDIA & fw_engine)
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_GEN9,
|
||||
_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
|
||||
|
||||
/* Check for Blitter Engine */
|
||||
if (FORCEWAKE_BLITTER & fw_engine)
|
||||
__raw_i915_write32(dev_priv, FORCEWAKE_BLITTER_GEN9,
|
||||
_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
|
||||
}
|
||||
|
||||
static void
|
||||
gen9_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
if (FORCEWAKE_RENDER & fw_engine) {
|
||||
if (dev_priv->uncore.fw_rendercount++ == 0)
|
||||
dev_priv->uncore.funcs.force_wake_get(dev_priv,
|
||||
FORCEWAKE_RENDER);
|
||||
}
|
||||
|
||||
if (FORCEWAKE_MEDIA & fw_engine) {
|
||||
if (dev_priv->uncore.fw_mediacount++ == 0)
|
||||
dev_priv->uncore.funcs.force_wake_get(dev_priv,
|
||||
FORCEWAKE_MEDIA);
|
||||
}
|
||||
|
||||
if (FORCEWAKE_BLITTER & fw_engine) {
|
||||
if (dev_priv->uncore.fw_blittercount++ == 0)
|
||||
dev_priv->uncore.funcs.force_wake_get(dev_priv,
|
||||
FORCEWAKE_BLITTER);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void
|
||||
gen9_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
if (FORCEWAKE_RENDER & fw_engine) {
|
||||
WARN_ON(dev_priv->uncore.fw_rendercount == 0);
|
||||
if (--dev_priv->uncore.fw_rendercount == 0)
|
||||
dev_priv->uncore.funcs.force_wake_put(dev_priv,
|
||||
FORCEWAKE_RENDER);
|
||||
}
|
||||
|
||||
if (FORCEWAKE_MEDIA & fw_engine) {
|
||||
WARN_ON(dev_priv->uncore.fw_mediacount == 0);
|
||||
if (--dev_priv->uncore.fw_mediacount == 0)
|
||||
dev_priv->uncore.funcs.force_wake_put(dev_priv,
|
||||
FORCEWAKE_MEDIA);
|
||||
}
|
||||
|
||||
if (FORCEWAKE_BLITTER & fw_engine) {
|
||||
WARN_ON(dev_priv->uncore.fw_blittercount == 0);
|
||||
if (--dev_priv->uncore.fw_blittercount == 0)
|
||||
dev_priv->uncore.funcs.force_wake_put(dev_priv,
|
||||
FORCEWAKE_BLITTER);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void gen6_force_wake_timer(unsigned long arg)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = (void *)arg;
|
||||
@ -334,6 +485,9 @@ void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
|
||||
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev))
|
||||
__gen7_gt_force_wake_mt_reset(dev_priv);
|
||||
|
||||
if (IS_GEN9(dev))
|
||||
__gen9_gt_force_wake_mt_reset(dev_priv);
|
||||
|
||||
if (restore) { /* If reset with a user forcewake, try to restore */
|
||||
unsigned fw = 0;
|
||||
|
||||
@ -343,6 +497,15 @@ void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
|
||||
|
||||
if (dev_priv->uncore.fw_mediacount)
|
||||
fw |= FORCEWAKE_MEDIA;
|
||||
} else if (IS_GEN9(dev)) {
|
||||
if (dev_priv->uncore.fw_rendercount)
|
||||
fw |= FORCEWAKE_RENDER;
|
||||
|
||||
if (dev_priv->uncore.fw_mediacount)
|
||||
fw |= FORCEWAKE_MEDIA;
|
||||
|
||||
if (dev_priv->uncore.fw_blittercount)
|
||||
fw |= FORCEWAKE_BLITTER;
|
||||
} else {
|
||||
if (dev_priv->uncore.forcewake_count)
|
||||
fw = FORCEWAKE_ALL;
|
||||
@ -414,6 +577,10 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
/* Redirect to Gen9 specific routine */
|
||||
if (IS_GEN9(dev_priv->dev))
|
||||
return gen9_force_wake_get(dev_priv, fw_engine);
|
||||
|
||||
/* Redirect to VLV specific routine */
|
||||
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
return vlv_force_wake_get(dev_priv, fw_engine);
|
||||
@ -435,6 +602,12 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
|
||||
if (!dev_priv->uncore.funcs.force_wake_put)
|
||||
return;
|
||||
|
||||
/* Redirect to Gen9 specific routine */
|
||||
if (IS_GEN9(dev_priv->dev)) {
|
||||
gen9_force_wake_put(dev_priv, fw_engine);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Redirect to VLV specific routine */
|
||||
if (IS_VALLEYVIEW(dev_priv->dev)) {
|
||||
vlv_force_wake_put(dev_priv, fw_engine);
|
||||
@ -855,7 +1028,10 @@ void intel_uncore_init(struct drm_device *dev)
|
||||
|
||||
__intel_uncore_early_sanitize(dev, false);
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_GEN9(dev)) {
|
||||
dev_priv->uncore.funcs.force_wake_get = __gen9_force_wake_get;
|
||||
dev_priv->uncore.funcs.force_wake_put = __gen9_force_wake_put;
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get;
|
||||
dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put;
|
||||
} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
|
||||
|
@ -876,6 +876,12 @@ struct drm_i915_gem_get_tiling {
|
||||
* mmap mapping.
|
||||
*/
|
||||
__u32 swizzle_mode;
|
||||
|
||||
/**
|
||||
* Returned address bit 6 swizzling required for CPU access through
|
||||
* mmap mapping whilst bound.
|
||||
*/
|
||||
__u32 phys_swizzle_mode;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_get_aperture {
|
||||
|
Loading…
x
Reference in New Issue
Block a user