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:
Dave Airlie 2014-11-15 09:33:40 +10:00
commit fd172d0c47
35 changed files with 5167 additions and 1661 deletions

View file

@ -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

View file

@ -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)
/*

View file

@ -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 \

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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)

View file

@ -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 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
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;

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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,

View file

@ -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)

View file

@ -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 */

View 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;
}
}

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View 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);

View file

@ -1845,12 +1845,15 @@ static int intel_init_ring_buffer(struct drm_device *dev,
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);

View file

@ -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;

View file

@ -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

View file

@ -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)) {

View file

@ -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 {