mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 17:59:32 +00:00
Merge tag 'drm-intel-next-2015-12-18' of git://anongit.freedesktop.org/drm-intel into drm-next
- fix atomic watermark recomputation logic (Maarten) - modeset sequence fixes for LPT (Ville) - more kbl enabling&prep work (Rodrigo, Wayne) - first bits for mst audio - page dirty tracking fixes from Dave Gordon - new get_eld hook from Takashi, also included in the sound tree - fixup cursor handling when placed at address 0 (Ville) - refactor VBT parsing code (Jani) - rpm wakelock debug infrastructure ( Imre) - fbdev is pinned again (Chris) - tune the busywait logic to avoid wasting cpu cycles (Chris) * tag 'drm-intel-next-2015-12-18' of git://anongit.freedesktop.org/drm-intel: (81 commits) drm/i915: Update DRIVER_DATE to 20151218 drm/i915/skl: Default to noncoherent access up to F0 drm/i915: Only spin whilst waiting on the current request drm/i915: Limit the busy wait on requests to 5us not 10ms! drm/i915: Break busywaiting for requests on pending signals drm/i915: don't enable autosuspend on platforms without RPM support drm/i915/backlight: prefer dev_priv over dev pointer drm/i915: Disable primary plane if we fail to reconstruct BIOS fb (v2) drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping drm/i915: Set the map-and-fenceable flag for preallocated objects drm/i915: mdelay(10) considered harmful drm/i915: check that we are in an RPM atomic section in GGTT PTE updaters drm/i915: add support for checking RPM atomic sections drm/i915: check that we hold an RPM wakelock ref before we put it drm/i915: add support for checking if we hold an RPM reference drm/i915: use assert_rpm_wakelock_held instead of opencoding it drm/i915: add assert_rpm_wakelock_held helper drm/i915: remove HAS_RUNTIME_PM check from RPM get/put/assert helpers drm/i915: get a permanent RPM reference on platforms w/o RPM support drm/i915: refactor RPM disabling due to RC6 being disabled ...
This commit is contained in:
commit
ade1ba7346
55 changed files with 1488 additions and 808 deletions
|
@ -666,7 +666,9 @@ static int build_enum_path_resources(struct drm_dp_sideband_msg_tx *msg, int por
|
|||
}
|
||||
|
||||
static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_num,
|
||||
u8 vcpi, uint16_t pbn)
|
||||
u8 vcpi, uint16_t pbn,
|
||||
u8 number_sdp_streams,
|
||||
u8 *sdp_stream_sink)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
@ -674,6 +676,9 @@ static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_n
|
|||
req.u.allocate_payload.port_number = port_num;
|
||||
req.u.allocate_payload.vcpi = vcpi;
|
||||
req.u.allocate_payload.pbn = pbn;
|
||||
req.u.allocate_payload.number_sdp_streams = number_sdp_streams;
|
||||
memcpy(req.u.allocate_payload.sdp_stream_sink, sdp_stream_sink,
|
||||
number_sdp_streams);
|
||||
drm_dp_encode_sideband_req(&req, msg);
|
||||
msg->path_msg = true;
|
||||
return 0;
|
||||
|
@ -1562,6 +1567,8 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
|
|||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
struct drm_dp_mst_branch *mstb;
|
||||
int len, ret;
|
||||
u8 sinks[DRM_DP_MAX_SDP_STREAMS];
|
||||
int i;
|
||||
|
||||
mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
|
||||
if (!mstb)
|
||||
|
@ -1573,10 +1580,13 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
|
|||
goto fail_put;
|
||||
}
|
||||
|
||||
for (i = 0; i < port->num_sdp_streams; i++)
|
||||
sinks[i] = i;
|
||||
|
||||
txmsg->dst = mstb;
|
||||
len = build_allocate_payload(txmsg, port->port_num,
|
||||
id,
|
||||
pbn);
|
||||
pbn, port->num_sdp_streams, sinks);
|
||||
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
||||
|
@ -2260,6 +2270,27 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector
|
|||
}
|
||||
EXPORT_SYMBOL(drm_dp_mst_detect_port);
|
||||
|
||||
/**
|
||||
* drm_dp_mst_port_has_audio() - Check whether port has audio capability or not
|
||||
* @mgr: manager for this port
|
||||
* @port: unverified pointer to a port.
|
||||
*
|
||||
* This returns whether the port supports audio or not.
|
||||
*/
|
||||
bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_port *port)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
port = drm_dp_get_validated_port_ref(mgr, port);
|
||||
if (!port)
|
||||
return ret;
|
||||
ret = port->has_audio;
|
||||
drm_dp_put_port(port);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_mst_port_has_audio);
|
||||
|
||||
/**
|
||||
* drm_dp_mst_get_edid() - get EDID for an MST port
|
||||
* @connector: toplevel connector to get EDID for
|
||||
|
@ -2285,6 +2316,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
|
|||
edid = drm_get_edid(connector, &port->aux.ddc);
|
||||
drm_mode_connector_set_tile_property(connector);
|
||||
}
|
||||
port->has_audio = drm_detect_monitor_audio(edid);
|
||||
drm_dp_put_port(port);
|
||||
return edid;
|
||||
}
|
||||
|
@ -2568,7 +2600,7 @@ static void drm_dp_mst_dump_mstb(struct seq_file *m,
|
|||
|
||||
seq_printf(m, "%smst: %p, %d\n", prefix, mstb, mstb->num_ports);
|
||||
list_for_each_entry(port, &mstb->ports, next) {
|
||||
seq_printf(m, "%sport: %d: ddps: %d ldps: %d, %p, conn: %p\n", prefix, port->port_num, port->ddps, port->ldps, port, port->connector);
|
||||
seq_printf(m, "%sport: %d: ddps: %d ldps: %d, sdp: %d/%d, %p, conn: %p\n", prefix, port->port_num, port->ddps, port->ldps, port->num_sdp_streams, port->num_sdp_stream_sinks, port, port->connector);
|
||||
if (port->mstb)
|
||||
drm_dp_mst_dump_mstb(m, port->mstb);
|
||||
}
|
||||
|
|
|
@ -129,11 +129,11 @@ struct intel_dvo_dev_ops {
|
|||
void (*dump_regs)(struct intel_dvo_device *dvo);
|
||||
};
|
||||
|
||||
extern struct intel_dvo_dev_ops sil164_ops;
|
||||
extern struct intel_dvo_dev_ops ch7xxx_ops;
|
||||
extern struct intel_dvo_dev_ops ivch_ops;
|
||||
extern struct intel_dvo_dev_ops tfp410_ops;
|
||||
extern struct intel_dvo_dev_ops ch7017_ops;
|
||||
extern struct intel_dvo_dev_ops ns2501_ops;
|
||||
extern const struct intel_dvo_dev_ops sil164_ops;
|
||||
extern const struct intel_dvo_dev_ops ch7xxx_ops;
|
||||
extern const struct intel_dvo_dev_ops ivch_ops;
|
||||
extern const struct intel_dvo_dev_ops tfp410_ops;
|
||||
extern const struct intel_dvo_dev_ops ch7017_ops;
|
||||
extern const struct intel_dvo_dev_ops ns2501_ops;
|
||||
|
||||
#endif /* _INTEL_DVO_H */
|
||||
|
|
|
@ -402,7 +402,7 @@ static void ch7017_destroy(struct intel_dvo_device *dvo)
|
|||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ch7017_ops = {
|
||||
const struct intel_dvo_dev_ops ch7017_ops = {
|
||||
.init = ch7017_init,
|
||||
.detect = ch7017_detect,
|
||||
.mode_valid = ch7017_mode_valid,
|
||||
|
|
|
@ -356,7 +356,7 @@ static void ch7xxx_destroy(struct intel_dvo_device *dvo)
|
|||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ch7xxx_ops = {
|
||||
const struct intel_dvo_dev_ops ch7xxx_ops = {
|
||||
.init = ch7xxx_init,
|
||||
.detect = ch7xxx_detect,
|
||||
.mode_valid = ch7xxx_mode_valid,
|
||||
|
|
|
@ -490,7 +490,7 @@ static void ivch_destroy(struct intel_dvo_device *dvo)
|
|||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ivch_ops = {
|
||||
const struct intel_dvo_dev_ops ivch_ops = {
|
||||
.init = ivch_init,
|
||||
.dpms = ivch_dpms,
|
||||
.get_hw_state = ivch_get_hw_state,
|
||||
|
|
|
@ -698,7 +698,7 @@ static void ns2501_destroy(struct intel_dvo_device *dvo)
|
|||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ns2501_ops = {
|
||||
const struct intel_dvo_dev_ops ns2501_ops = {
|
||||
.init = ns2501_init,
|
||||
.detect = ns2501_detect,
|
||||
.mode_valid = ns2501_mode_valid,
|
||||
|
|
|
@ -267,7 +267,7 @@ static void sil164_destroy(struct intel_dvo_device *dvo)
|
|||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops sil164_ops = {
|
||||
const struct intel_dvo_dev_ops sil164_ops = {
|
||||
.init = sil164_init,
|
||||
.detect = sil164_detect,
|
||||
.mode_valid = sil164_mode_valid,
|
||||
|
|
|
@ -306,7 +306,7 @@ static void tfp410_destroy(struct intel_dvo_device *dvo)
|
|||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops tfp410_ops = {
|
||||
const struct intel_dvo_dev_ops tfp410_ops = {
|
||||
.init = tfp410_init,
|
||||
.detect = tfp410_detect,
|
||||
.mode_valid = tfp410_mode_valid,
|
||||
|
|
|
@ -1142,8 +1142,34 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
|
|||
MEMSTAT_VID_SHIFT);
|
||||
seq_printf(m, "Current P-state: %d\n",
|
||||
(rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
|
||||
} else if (IS_GEN6(dev) || (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) ||
|
||||
IS_BROADWELL(dev) || IS_GEN9(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
u32 freq_sts;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
|
||||
seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
|
||||
seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
|
||||
|
||||
seq_printf(m, "actual GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
|
||||
|
||||
seq_printf(m, "current GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
|
||||
|
||||
seq_printf(m, "max GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
|
||||
|
||||
seq_printf(m, "min GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.min_freq));
|
||||
|
||||
seq_printf(m, "idle GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq));
|
||||
|
||||
seq_printf(m,
|
||||
"efficient (RPe) frequency: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
} else if (INTEL_INFO(dev)->gen >= 6) {
|
||||
u32 rp_state_limits;
|
||||
u32 gt_perf_status;
|
||||
u32 rp_state_cap;
|
||||
|
@ -1284,33 +1310,6 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
|
|||
seq_printf(m,
|
||||
"efficient (RPe) frequency: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
u32 freq_sts;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
|
||||
seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
|
||||
seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
|
||||
|
||||
seq_printf(m, "actual GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
|
||||
|
||||
seq_printf(m, "current GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
|
||||
|
||||
seq_printf(m, "max GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
|
||||
|
||||
seq_printf(m, "min GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.min_freq));
|
||||
|
||||
seq_printf(m, "idle GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq));
|
||||
|
||||
seq_printf(m,
|
||||
"efficient (RPe) frequency: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
} else {
|
||||
seq_puts(m, "no P-state info available\n");
|
||||
}
|
||||
|
@ -1602,7 +1601,7 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
|
|||
struct drm_info_node *node = m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
return vlv_drpc_info(m);
|
||||
else if (INTEL_INFO(dev)->gen >= 6)
|
||||
return gen6_drpc_info(m);
|
||||
|
@ -1743,7 +1742,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
|
|||
sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
|
||||
else if (IS_PINEVIEW(dev))
|
||||
sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
@ -1843,25 +1842,31 @@ static int i915_opregion(struct seq_file *m, void *unused)
|
|||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_opregion *opregion = &dev_priv->opregion;
|
||||
void *data = kmalloc(OPREGION_SIZE, GFP_KERNEL);
|
||||
int ret;
|
||||
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (opregion->header) {
|
||||
memcpy(data, opregion->header, OPREGION_SIZE);
|
||||
seq_write(m, data, OPREGION_SIZE);
|
||||
}
|
||||
if (opregion->header)
|
||||
seq_write(m, opregion->header, OPREGION_SIZE);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_vbt(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 intel_opregion *opregion = &dev_priv->opregion;
|
||||
|
||||
if (opregion->vbt)
|
||||
seq_write(m, opregion->vbt, opregion->vbt_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2850,6 +2855,20 @@ static void intel_dp_info(struct seq_file *m,
|
|||
intel_panel_info(m, &intel_connector->panel);
|
||||
}
|
||||
|
||||
static void intel_dp_mst_info(struct seq_file *m,
|
||||
struct intel_connector *intel_connector)
|
||||
{
|
||||
struct intel_encoder *intel_encoder = intel_connector->encoder;
|
||||
struct intel_dp_mst_encoder *intel_mst =
|
||||
enc_to_mst(&intel_encoder->base);
|
||||
struct intel_digital_port *intel_dig_port = intel_mst->primary;
|
||||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||
bool has_audio = drm_dp_mst_port_has_audio(&intel_dp->mst_mgr,
|
||||
intel_connector->port);
|
||||
|
||||
seq_printf(m, "\taudio support: %s\n", yesno(has_audio));
|
||||
}
|
||||
|
||||
static void intel_hdmi_info(struct seq_file *m,
|
||||
struct intel_connector *intel_connector)
|
||||
{
|
||||
|
@ -2893,6 +2912,8 @@ static void intel_connector_info(struct seq_file *m,
|
|||
intel_hdmi_info(m, intel_connector);
|
||||
else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
|
||||
intel_lvds_info(m, intel_connector);
|
||||
else if (intel_encoder->type == INTEL_OUTPUT_DP_MST)
|
||||
intel_dp_mst_info(m, intel_connector);
|
||||
}
|
||||
|
||||
seq_printf(m, "\tmodes:\n");
|
||||
|
@ -3983,7 +4004,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
|
|||
ret = i8xx_pipe_crc_ctl_reg(&source, &val);
|
||||
else if (INTEL_INFO(dev)->gen < 5)
|
||||
ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val);
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val);
|
||||
else if (IS_GEN5(dev) || IS_GEN6(dev))
|
||||
ret = ilk_pipe_crc_ctl_reg(&source, &val);
|
||||
|
@ -4052,7 +4073,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
|
|||
|
||||
if (IS_G4X(dev))
|
||||
g4x_undo_pipe_scramble_reset(dev, pipe);
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_undo_pipe_scramble_reset(dev, pipe);
|
||||
else if (IS_HASWELL(dev) && pipe == PIPE_A)
|
||||
hsw_trans_edp_pipe_A_crc_wa(dev, false);
|
||||
|
@ -4442,7 +4463,8 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
|
|||
* - WM1+ latency values in 0.5us units
|
||||
* - latencies are in us on gen9/vlv/chv
|
||||
*/
|
||||
if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev) ||
|
||||
IS_CHERRYVIEW(dev))
|
||||
latency *= 10;
|
||||
else if (level > 0)
|
||||
latency *= 5;
|
||||
|
@ -5316,6 +5338,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
|
|||
{"i915_ips_status", i915_ips_status, 0},
|
||||
{"i915_sr_status", i915_sr_status, 0},
|
||||
{"i915_opregion", i915_opregion, 0},
|
||||
{"i915_vbt", i915_vbt, 0},
|
||||
{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
|
||||
{"i915_context_status", i915_context_status, 0},
|
||||
{"i915_dump_lrc", i915_dump_lrc, 0},
|
||||
|
|
|
@ -169,6 +169,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
|||
case I915_PARAM_HAS_RESOURCE_STREAMER:
|
||||
value = HAS_RESOURCE_STREAMER(dev);
|
||||
break;
|
||||
case I915_PARAM_HAS_EXEC_SOFTPIN:
|
||||
value = 1;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Unknown parameter %d\n", param->param);
|
||||
return -EINVAL;
|
||||
|
@ -256,7 +259,7 @@ intel_setup_mchbar(struct drm_device *dev)
|
|||
u32 temp;
|
||||
bool enabled;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
return;
|
||||
|
||||
dev_priv->mchbar_need_disable = false;
|
||||
|
@ -367,7 +370,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = intel_parse_bios(dev);
|
||||
ret = intel_bios_init(dev_priv);
|
||||
if (ret)
|
||||
DRM_INFO("failed to find VBIOS tables\n");
|
||||
|
||||
|
@ -779,7 +782,7 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
|
|||
info->num_sprites[PIPE_A] = 2;
|
||||
info->num_sprites[PIPE_B] = 2;
|
||||
info->num_sprites[PIPE_C] = 1;
|
||||
} else if (IS_VALLEYVIEW(dev))
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
info->num_sprites[pipe] = 2;
|
||||
else
|
||||
|
@ -791,7 +794,7 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
|
|||
info->num_pipes = 0;
|
||||
} else if (info->num_pipes > 0 &&
|
||||
(INTEL_INFO(dev)->gen == 7 || INTEL_INFO(dev)->gen == 8) &&
|
||||
!IS_VALLEYVIEW(dev)) {
|
||||
HAS_PCH_SPLIT(dev)) {
|
||||
u32 fuse_strap = I915_READ(FUSE_STRAP);
|
||||
u32 sfuse_strap = I915_READ(SFUSE_STRAP);
|
||||
|
||||
|
@ -836,9 +839,6 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
|
|||
|
||||
static void intel_init_dpio(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (!IS_VALLEYVIEW(dev_priv))
|
||||
return;
|
||||
|
||||
/*
|
||||
* IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
|
||||
* CHV x1 PHY (DP/HDMI D)
|
||||
|
@ -847,7 +847,7 @@ static void intel_init_dpio(struct drm_i915_private *dev_priv)
|
|||
if (IS_CHERRYVIEW(dev_priv)) {
|
||||
DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
|
||||
DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
|
||||
} else {
|
||||
} else if (IS_VALLEYVIEW(dev_priv)) {
|
||||
DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
|
||||
}
|
||||
}
|
||||
|
@ -896,6 +896,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
intel_pm_setup(dev);
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
intel_display_crc_init(dev);
|
||||
|
||||
i915_dump_device_info(dev_priv);
|
||||
|
@ -1085,6 +1087,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
i915_audio_component_init(dev_priv);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
out_power_well:
|
||||
|
@ -1120,6 +1124,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
kmem_cache_destroy(dev_priv->requests);
|
||||
kmem_cache_destroy(dev_priv->vmas);
|
||||
kmem_cache_destroy(dev_priv->objects);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
kfree(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -311,7 +311,7 @@ static const struct intel_device_info intel_cherryview_info = {
|
|||
.gen = 8, .num_pipes = 3,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
|
||||
.is_valleyview = 1,
|
||||
.is_cherryview = 1,
|
||||
.display_mmio_offset = VLV_DISPLAY_BASE,
|
||||
GEN_CHV_PIPEOFFSETS,
|
||||
CURSOR_OFFSETS,
|
||||
|
@ -543,15 +543,12 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
|
|||
static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct drm_encoder *encoder;
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
|
||||
|
||||
if (intel_encoder->suspend)
|
||||
intel_encoder->suspend(intel_encoder);
|
||||
}
|
||||
for_each_intel_encoder(dev, encoder)
|
||||
if (encoder->suspend)
|
||||
encoder->suspend(encoder);
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
|
||||
|
@ -580,6 +577,8 @@ static int i915_drm_suspend(struct drm_device *dev)
|
|||
dev_priv->modeset_restore = MODESET_SUSPENDED;
|
||||
mutex_unlock(&dev_priv->modeset_restore_lock);
|
||||
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
/* We do a lot of poking in a lot of registers, make sure they work
|
||||
* properly. */
|
||||
intel_display_set_init_power(dev_priv, true);
|
||||
|
@ -592,7 +591,7 @@ static int i915_drm_suspend(struct drm_device *dev)
|
|||
if (error) {
|
||||
dev_err(&dev->pdev->dev,
|
||||
"GEM idle failed, resume might fail\n");
|
||||
return error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
intel_guc_suspend(dev);
|
||||
|
@ -635,7 +634,10 @@ static int i915_drm_suspend(struct drm_device *dev)
|
|||
if (HAS_CSR(dev_priv))
|
||||
flush_work(&dev_priv->csr.work);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
|
||||
|
@ -644,6 +646,8 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
|
|||
bool fw_csr;
|
||||
int ret;
|
||||
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
fw_csr = suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
|
||||
/*
|
||||
* In case of firmware assisted context save/restore don't manually
|
||||
|
@ -662,7 +666,7 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
|
|||
if (!fw_csr)
|
||||
intel_power_domains_init_hw(dev_priv, true);
|
||||
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pci_disable_device(drm_dev->pdev);
|
||||
|
@ -683,7 +687,10 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
|
|||
|
||||
dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state)
|
||||
|
@ -714,6 +721,8 @@ static int i915_drm_resume(struct drm_device *dev)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_restore_gtt_mappings(dev);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
@ -778,6 +787,8 @@ static int i915_drm_resume(struct drm_device *dev)
|
|||
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -802,7 +813,9 @@ static int i915_drm_resume_early(struct drm_device *dev)
|
|||
|
||||
pci_set_master(dev->pdev);
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv))
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
ret = vlv_resume_prepare(dev_priv, false);
|
||||
if (ret)
|
||||
DRM_ERROR("Resume prepare failed: %d, continuing anyway\n",
|
||||
|
@ -823,6 +836,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
|
|||
out:
|
||||
dev_priv->suspended_to_idle = false;
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1455,6 +1470,9 @@ static int intel_runtime_suspend(struct device *device)
|
|||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
/*
|
||||
* We are safe here against re-faults, since the fault handler takes
|
||||
* an RPM reference.
|
||||
|
@ -1462,6 +1480,8 @@ static int intel_runtime_suspend(struct device *device)
|
|||
i915_gem_release_all_mmaps(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
|
||||
|
||||
intel_guc_suspend(dev);
|
||||
|
||||
intel_suspend_gt_powersave(dev);
|
||||
|
@ -1472,11 +1492,15 @@ static int intel_runtime_suspend(struct device *device)
|
|||
DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
|
||||
intel_runtime_pm_enable_interrupts(dev_priv);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
|
||||
intel_uncore_forcewake_reset(dev, false);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
|
||||
dev_priv->pm.suspended = true;
|
||||
|
||||
/*
|
||||
|
@ -1520,6 +1544,9 @@ static int intel_runtime_resume(struct device *device)
|
|||
|
||||
DRM_DEBUG_KMS("Resuming device\n");
|
||||
|
||||
WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
intel_opregion_notify_adapter(dev, PCI_D0);
|
||||
dev_priv->pm.suspended = false;
|
||||
|
||||
|
@ -1532,7 +1559,7 @@ static int intel_runtime_resume(struct device *device)
|
|||
ret = bxt_resume_prepare(dev_priv);
|
||||
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
hsw_disable_pc8(dev_priv);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
ret = vlv_resume_prepare(dev_priv, true);
|
||||
|
||||
/*
|
||||
|
@ -1549,11 +1576,13 @@ static int intel_runtime_resume(struct device *device)
|
|||
* power well, so hpd is reinitialized from there. For
|
||||
* everyone else do it here.
|
||||
*/
|
||||
if (!IS_VALLEYVIEW(dev_priv))
|
||||
if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
|
||||
intel_hpd_init(dev_priv);
|
||||
|
||||
intel_enable_gt_powersave(dev);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
|
||||
else
|
||||
|
@ -1574,7 +1603,7 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
|
|||
ret = bxt_suspend_complete(dev_priv);
|
||||
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
ret = hsw_suspend_complete(dev_priv);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
ret = vlv_suspend_complete(dev_priv);
|
||||
else
|
||||
ret = 0;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <uapi/drm/i915_drm.h>
|
||||
#include <uapi/drm/drm_fourcc.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include "i915_reg.h"
|
||||
#include "intel_bios.h"
|
||||
#include "intel_ringbuffer.h"
|
||||
|
@ -57,7 +58,7 @@
|
|||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20151204"
|
||||
#define DRIVER_DATE "20151218"
|
||||
|
||||
#undef WARN_ON
|
||||
/* Many gcc seem to no see through this and fall over :( */
|
||||
|
@ -457,7 +458,9 @@ struct intel_opregion {
|
|||
u32 swsci_gbda_sub_functions;
|
||||
u32 swsci_sbcb_sub_functions;
|
||||
struct opregion_asle *asle;
|
||||
void *vbt;
|
||||
void *rvda;
|
||||
const void *vbt;
|
||||
u32 vbt_size;
|
||||
u32 *lid_state;
|
||||
struct work_struct asle_work;
|
||||
};
|
||||
|
@ -763,6 +766,7 @@ struct intel_csr {
|
|||
func(is_crestline) sep \
|
||||
func(is_ivybridge) sep \
|
||||
func(is_valleyview) sep \
|
||||
func(is_cherryview) sep \
|
||||
func(is_haswell) sep \
|
||||
func(is_skylake) sep \
|
||||
func(is_broxton) sep \
|
||||
|
@ -1601,6 +1605,8 @@ struct skl_wm_level {
|
|||
* For more, read the Documentation/power/runtime_pm.txt.
|
||||
*/
|
||||
struct i915_runtime_pm {
|
||||
atomic_t wakeref_count;
|
||||
atomic_t atomic_seq;
|
||||
bool suspended;
|
||||
bool irqs_enabled;
|
||||
};
|
||||
|
@ -1944,6 +1950,8 @@ struct drm_i915_private {
|
|||
/* perform PHY state sanity checks? */
|
||||
bool chv_phy_assert[2];
|
||||
|
||||
struct intel_encoder *dig_port_map[I915_MAX_PORTS];
|
||||
|
||||
/*
|
||||
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
|
||||
* will be rejected. Instead look for a better place.
|
||||
|
@ -2181,8 +2189,17 @@ struct drm_i915_gem_request {
|
|||
struct drm_i915_private *i915;
|
||||
struct intel_engine_cs *ring;
|
||||
|
||||
/** GEM sequence number associated with this request. */
|
||||
uint32_t seqno;
|
||||
/** GEM sequence number associated with the previous request,
|
||||
* when the HWS breadcrumb is equal to this the GPU is processing
|
||||
* this request.
|
||||
*/
|
||||
u32 previous_seqno;
|
||||
|
||||
/** GEM sequence number associated with this request,
|
||||
* when the HWS breadcrumb is equal or greater than this the GPU
|
||||
* has finished processing this request.
|
||||
*/
|
||||
u32 seqno;
|
||||
|
||||
/** Position in the ringbuffer of the start of the request */
|
||||
u32 head;
|
||||
|
@ -2455,9 +2472,9 @@ struct drm_i915_cmd_table {
|
|||
INTEL_DEVID(dev) == 0x0152 || \
|
||||
INTEL_DEVID(dev) == 0x015a)
|
||||
#define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview)
|
||||
#define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
|
||||
#define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview)
|
||||
#define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell)
|
||||
#define IS_BROADWELL(dev) (!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
|
||||
#define IS_BROADWELL(dev) (!INTEL_INFO(dev)->is_cherryview && IS_GEN8(dev))
|
||||
#define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake)
|
||||
#define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton)
|
||||
#define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake)
|
||||
|
@ -2488,6 +2505,14 @@ struct drm_i915_cmd_table {
|
|||
#define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \
|
||||
INTEL_DEVID(dev) == 0x1915 || \
|
||||
INTEL_DEVID(dev) == 0x191E)
|
||||
#define IS_KBL_ULT(dev) (INTEL_DEVID(dev) == 0x5906 || \
|
||||
INTEL_DEVID(dev) == 0x5913 || \
|
||||
INTEL_DEVID(dev) == 0x5916 || \
|
||||
INTEL_DEVID(dev) == 0x5921 || \
|
||||
INTEL_DEVID(dev) == 0x5926)
|
||||
#define IS_KBL_ULX(dev) (INTEL_DEVID(dev) == 0x590E || \
|
||||
INTEL_DEVID(dev) == 0x5915 || \
|
||||
INTEL_DEVID(dev) == 0x591E)
|
||||
#define IS_SKL_GT3(dev) (IS_SKYLAKE(dev) && \
|
||||
(INTEL_DEVID(dev) & 0x00F0) == 0x0020)
|
||||
#define IS_SKL_GT4(dev) (IS_SKYLAKE(dev) && \
|
||||
|
@ -2584,20 +2609,22 @@ struct drm_i915_cmd_table {
|
|||
IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
||||
#define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \
|
||||
IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \
|
||||
IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
||||
IS_CHERRYVIEW(dev) || IS_SKYLAKE(dev) || \
|
||||
IS_KABYLAKE(dev))
|
||||
#define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6)
|
||||
#define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
|
||||
|
||||
#define HAS_CSR(dev) (IS_GEN9(dev))
|
||||
|
||||
#define HAS_GUC_UCODE(dev) (IS_GEN9(dev))
|
||||
#define HAS_GUC_SCHED(dev) (IS_GEN9(dev))
|
||||
#define HAS_GUC_UCODE(dev) (IS_GEN9(dev) && !IS_KABYLAKE(dev))
|
||||
#define HAS_GUC_SCHED(dev) (IS_GEN9(dev) && !IS_KABYLAKE(dev))
|
||||
|
||||
#define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
|
||||
INTEL_INFO(dev)->gen >= 8)
|
||||
|
||||
#define HAS_CORE_RING_FREQ(dev) (INTEL_INFO(dev)->gen >= 6 && \
|
||||
!IS_VALLEYVIEW(dev) && !IS_BROXTON(dev))
|
||||
!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && \
|
||||
!IS_BROXTON(dev))
|
||||
|
||||
#define INTEL_PCH_DEVICE_ID_MASK 0xff00
|
||||
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
|
||||
|
@ -2620,7 +2647,8 @@ struct drm_i915_cmd_table {
|
|||
#define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP)
|
||||
#define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE)
|
||||
|
||||
#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev))
|
||||
#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || \
|
||||
IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
|
||||
/* DPF == dynamic parity feature */
|
||||
#define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
|
||||
|
@ -2860,6 +2888,7 @@ void i915_gem_vma_destroy(struct i915_vma *vma);
|
|||
#define PIN_UPDATE (1<<5)
|
||||
#define PIN_ZONE_4G (1<<6)
|
||||
#define PIN_HIGH (1<<7)
|
||||
#define PIN_OFFSET_FIXED (1<<8)
|
||||
#define PIN_OFFSET_MASK (~4095)
|
||||
int __must_check
|
||||
i915_gem_object_pin(struct drm_i915_gem_object *obj,
|
||||
|
@ -2874,6 +2903,7 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
|
|||
|
||||
int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
|
||||
u32 flags);
|
||||
void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
|
||||
int __must_check i915_vma_unbind(struct i915_vma *vma);
|
||||
/*
|
||||
* BEWARE: Do not use the function below unless you can _absolutely_
|
||||
|
@ -2894,6 +2924,9 @@ static inline int __sg_page_count(struct scatterlist *sg)
|
|||
return sg->length >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
struct page *
|
||||
i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n);
|
||||
|
||||
static inline struct page *
|
||||
i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
|
||||
{
|
||||
|
@ -2945,15 +2978,17 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
|
|||
return (int32_t)(seq1 - seq2) >= 0;
|
||||
}
|
||||
|
||||
static inline bool i915_gem_request_started(struct drm_i915_gem_request *req,
|
||||
bool lazy_coherency)
|
||||
{
|
||||
u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
|
||||
return i915_seqno_passed(seqno, req->previous_seqno);
|
||||
}
|
||||
|
||||
static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
|
||||
bool lazy_coherency)
|
||||
{
|
||||
u32 seqno;
|
||||
|
||||
BUG_ON(req == NULL);
|
||||
|
||||
seqno = req->ring->get_seqno(req->ring, lazy_coherency);
|
||||
|
||||
u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
|
||||
return i915_seqno_passed(seqno, req->seqno);
|
||||
}
|
||||
|
||||
|
@ -3205,6 +3240,7 @@ int __must_check i915_gem_evict_something(struct drm_device *dev,
|
|||
unsigned long start,
|
||||
unsigned long end,
|
||||
unsigned flags);
|
||||
int __must_check i915_gem_evict_for_vma(struct i915_vma *target);
|
||||
int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
|
||||
|
||||
/* belongs in i915_gem_gtt.h */
|
||||
|
@ -3333,6 +3369,10 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
|
|||
}
|
||||
extern void intel_i2c_reset(struct drm_device *dev);
|
||||
|
||||
/* intel_bios.c */
|
||||
int intel_bios_init(struct drm_i915_private *dev_priv);
|
||||
bool intel_bios_is_valid_vbt(const void *buf, size_t size);
|
||||
|
||||
/* intel_opregion.c */
|
||||
#ifdef CONFIG_ACPI
|
||||
extern int intel_opregion_setup(struct drm_device *dev);
|
||||
|
@ -3511,7 +3551,7 @@ __raw_write(64, q)
|
|||
|
||||
static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev)
|
||||
{
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
return VLV_VGACNTRL;
|
||||
else if (INTEL_INFO(dev)->gen >= 5)
|
||||
return CPU_VGACNTRL;
|
||||
|
|
|
@ -1146,23 +1146,74 @@ static bool missed_irq(struct drm_i915_private *dev_priv,
|
|||
return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
|
||||
}
|
||||
|
||||
static int __i915_spin_request(struct drm_i915_gem_request *req)
|
||||
static unsigned long local_clock_us(unsigned *cpu)
|
||||
{
|
||||
unsigned long t;
|
||||
|
||||
/* Cheaply and approximately convert from nanoseconds to microseconds.
|
||||
* The result and subsequent calculations are also defined in the same
|
||||
* approximate microseconds units. The principal source of timing
|
||||
* error here is from the simple truncation.
|
||||
*
|
||||
* Note that local_clock() is only defined wrt to the current CPU;
|
||||
* the comparisons are no longer valid if we switch CPUs. Instead of
|
||||
* blocking preemption for the entire busywait, we can detect the CPU
|
||||
* switch and use that as indicator of system load and a reason to
|
||||
* stop busywaiting, see busywait_stop().
|
||||
*/
|
||||
*cpu = get_cpu();
|
||||
t = local_clock() >> 10;
|
||||
put_cpu();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static bool busywait_stop(unsigned long timeout, unsigned cpu)
|
||||
{
|
||||
unsigned this_cpu;
|
||||
|
||||
if (time_after(local_clock_us(&this_cpu), timeout))
|
||||
return true;
|
||||
|
||||
return this_cpu != cpu;
|
||||
}
|
||||
|
||||
static int __i915_spin_request(struct drm_i915_gem_request *req, int state)
|
||||
{
|
||||
unsigned long timeout;
|
||||
unsigned cpu;
|
||||
|
||||
if (i915_gem_request_get_ring(req)->irq_refcount)
|
||||
/* When waiting for high frequency requests, e.g. during synchronous
|
||||
* rendering split between the CPU and GPU, the finite amount of time
|
||||
* required to set up the irq and wait upon it limits the response
|
||||
* rate. By busywaiting on the request completion for a short while we
|
||||
* can service the high frequency waits as quick as possible. However,
|
||||
* if it is a slow request, we want to sleep as quickly as possible.
|
||||
* The tradeoff between waiting and sleeping is roughly the time it
|
||||
* takes to sleep on a request, on the order of a microsecond.
|
||||
*/
|
||||
|
||||
if (req->ring->irq_refcount)
|
||||
return -EBUSY;
|
||||
|
||||
timeout = jiffies + 1;
|
||||
/* Only spin if we know the GPU is processing this request */
|
||||
if (!i915_gem_request_started(req, true))
|
||||
return -EAGAIN;
|
||||
|
||||
timeout = local_clock_us(&cpu) + 5;
|
||||
while (!need_resched()) {
|
||||
if (i915_gem_request_completed(req, true))
|
||||
return 0;
|
||||
|
||||
if (time_after_eq(jiffies, timeout))
|
||||
if (signal_pending_state(state, current))
|
||||
break;
|
||||
|
||||
if (busywait_stop(timeout, cpu))
|
||||
break;
|
||||
|
||||
cpu_relax_lowlatency();
|
||||
}
|
||||
|
||||
if (i915_gem_request_completed(req, false))
|
||||
return 0;
|
||||
|
||||
|
@ -1197,6 +1248,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
const bool irq_test_in_progress =
|
||||
ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
|
||||
int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
|
||||
DEFINE_WAIT(wait);
|
||||
unsigned long timeout_expire;
|
||||
s64 before, now;
|
||||
|
@ -1229,7 +1281,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
|||
before = ktime_get_raw_ns();
|
||||
|
||||
/* Optimistic spin for the next jiffie before touching IRQs */
|
||||
ret = __i915_spin_request(req);
|
||||
ret = __i915_spin_request(req, state);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
|
@ -1241,8 +1293,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
|||
for (;;) {
|
||||
struct timer_list timer;
|
||||
|
||||
prepare_to_wait(&ring->irq_queue, &wait,
|
||||
interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
|
||||
prepare_to_wait(&ring->irq_queue, &wait, state);
|
||||
|
||||
/* We need to check whether any gpu reset happened in between
|
||||
* the caller grabbing the seqno and now ... */
|
||||
|
@ -1260,7 +1311,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
|||
break;
|
||||
}
|
||||
|
||||
if (interruptible && signal_pending(current)) {
|
||||
if (signal_pending_state(state, current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
@ -2554,6 +2605,7 @@ void __i915_add_request(struct drm_i915_gem_request *request,
|
|||
request->batch_obj = obj;
|
||||
|
||||
request->emitted_jiffies = jiffies;
|
||||
request->previous_seqno = ring->last_submitted_seqno;
|
||||
ring->last_submitted_seqno = request->seqno;
|
||||
list_add_tail(&request->list, &ring->request_list);
|
||||
|
||||
|
@ -2765,20 +2817,13 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
|
|||
|
||||
if (i915.enable_execlists) {
|
||||
spin_lock_irq(&ring->execlist_lock);
|
||||
while (!list_empty(&ring->execlist_queue)) {
|
||||
struct drm_i915_gem_request *submit_req;
|
||||
|
||||
submit_req = list_first_entry(&ring->execlist_queue,
|
||||
struct drm_i915_gem_request,
|
||||
execlist_link);
|
||||
list_del(&submit_req->execlist_link);
|
||||
/* list_splice_tail_init checks for empty lists */
|
||||
list_splice_tail_init(&ring->execlist_queue,
|
||||
&ring->execlist_retired_req_list);
|
||||
|
||||
if (submit_req->ctx != ring->default_context)
|
||||
intel_lr_context_unpin(submit_req);
|
||||
|
||||
i915_gem_request_unreference(submit_req);
|
||||
}
|
||||
spin_unlock_irq(&ring->execlist_lock);
|
||||
intel_execlists_retire_requests(ring);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3480,30 +3525,50 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
|
|||
if (IS_ERR(vma))
|
||||
goto err_unpin;
|
||||
|
||||
if (flags & PIN_HIGH) {
|
||||
search_flag = DRM_MM_SEARCH_BELOW;
|
||||
alloc_flag = DRM_MM_CREATE_TOP;
|
||||
if (flags & PIN_OFFSET_FIXED) {
|
||||
uint64_t offset = flags & PIN_OFFSET_MASK;
|
||||
|
||||
if (offset & (alignment - 1) || offset + size > end) {
|
||||
ret = -EINVAL;
|
||||
goto err_free_vma;
|
||||
}
|
||||
vma->node.start = offset;
|
||||
vma->node.size = size;
|
||||
vma->node.color = obj->cache_level;
|
||||
ret = drm_mm_reserve_node(&vm->mm, &vma->node);
|
||||
if (ret) {
|
||||
ret = i915_gem_evict_for_vma(vma);
|
||||
if (ret == 0)
|
||||
ret = drm_mm_reserve_node(&vm->mm, &vma->node);
|
||||
}
|
||||
if (ret)
|
||||
goto err_free_vma;
|
||||
} else {
|
||||
search_flag = DRM_MM_SEARCH_DEFAULT;
|
||||
alloc_flag = DRM_MM_CREATE_DEFAULT;
|
||||
}
|
||||
if (flags & PIN_HIGH) {
|
||||
search_flag = DRM_MM_SEARCH_BELOW;
|
||||
alloc_flag = DRM_MM_CREATE_TOP;
|
||||
} else {
|
||||
search_flag = DRM_MM_SEARCH_DEFAULT;
|
||||
alloc_flag = DRM_MM_CREATE_DEFAULT;
|
||||
}
|
||||
|
||||
search_free:
|
||||
ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
|
||||
size, alignment,
|
||||
obj->cache_level,
|
||||
start, end,
|
||||
search_flag,
|
||||
alloc_flag);
|
||||
if (ret) {
|
||||
ret = i915_gem_evict_something(dev, vm, size, alignment,
|
||||
obj->cache_level,
|
||||
start, end,
|
||||
flags);
|
||||
if (ret == 0)
|
||||
goto search_free;
|
||||
ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
|
||||
size, alignment,
|
||||
obj->cache_level,
|
||||
start, end,
|
||||
search_flag,
|
||||
alloc_flag);
|
||||
if (ret) {
|
||||
ret = i915_gem_evict_something(dev, vm, size, alignment,
|
||||
obj->cache_level,
|
||||
start, end,
|
||||
flags);
|
||||
if (ret == 0)
|
||||
goto search_free;
|
||||
|
||||
goto err_free_vma;
|
||||
goto err_free_vma;
|
||||
}
|
||||
}
|
||||
if (WARN_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level))) {
|
||||
ret = -EINVAL;
|
||||
|
@ -4094,9 +4159,36 @@ i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags)
|
|||
vma->node.start < (flags & PIN_OFFSET_MASK))
|
||||
return true;
|
||||
|
||||
if (flags & PIN_OFFSET_FIXED &&
|
||||
vma->node.start != (flags & PIN_OFFSET_MASK))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
|
||||
{
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
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 + fence_size <=
|
||||
to_i915(obj->base.dev)->gtt.mappable_end);
|
||||
|
||||
obj->map_and_fenceable = mappable && fenceable;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
|
||||
struct i915_address_space *vm,
|
||||
|
@ -4164,25 +4256,7 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
|
|||
|
||||
if (ggtt_view && ggtt_view->type == I915_GGTT_VIEW_NORMAL &&
|
||||
(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 + fence_size <=
|
||||
dev_priv->gtt.mappable_end);
|
||||
|
||||
obj->map_and_fenceable = mappable && fenceable;
|
||||
|
||||
__i915_vma_set_map_and_fenceable(vma);
|
||||
WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable);
|
||||
}
|
||||
|
||||
|
@ -4842,14 +4916,6 @@ int i915_gem_init(struct drm_device *dev)
|
|||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
/* VLVA0 (potential hack), BIOS isn't actually waking us */
|
||||
I915_WRITE(VLV_GTLC_WAKE_CTRL, VLV_GTLC_ALLOWWAKEREQ);
|
||||
if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) &
|
||||
VLV_GTLC_ALLOWWAKEACK), 10))
|
||||
DRM_DEBUG_DRIVER("allow wake ack timed out\n");
|
||||
}
|
||||
|
||||
if (!i915.enable_execlists) {
|
||||
dev_priv->gt.execbuf_submit = i915_gem_ringbuffer_submission;
|
||||
dev_priv->gt.init_rings = i915_gem_init_rings;
|
||||
|
@ -4967,7 +5033,7 @@ i915_gem_load(struct drm_device *dev)
|
|||
|
||||
dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))
|
||||
dev_priv->num_fence_regs = 32;
|
||||
else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
|
||||
dev_priv->num_fence_regs = 16;
|
||||
|
@ -5188,6 +5254,21 @@ bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Like i915_gem_object_get_page(), but mark the returned page dirty */
|
||||
struct page *
|
||||
i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
/* Only default objects have per-page dirty tracking */
|
||||
if (WARN_ON(obj->ops != &i915_gem_object_ops))
|
||||
return NULL;
|
||||
|
||||
page = i915_gem_object_get_page(obj, n);
|
||||
set_page_dirty(page);
|
||||
return page;
|
||||
}
|
||||
|
||||
/* Allocate a new GEM object and fill it with the supplied data */
|
||||
struct drm_i915_gem_object *
|
||||
i915_gem_object_create_from_data(struct drm_device *dev,
|
||||
|
@ -5213,6 +5294,7 @@ i915_gem_object_create_from_data(struct drm_device *dev,
|
|||
i915_gem_object_pin_pages(obj);
|
||||
sg = obj->pages;
|
||||
bytes = sg_copy_from_buffer(sg->sgl, sg->nents, (void *)data, size);
|
||||
obj->dirty = 1; /* Backing store is now out of date */
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
|
||||
if (WARN_ON(bytes != size)) {
|
||||
|
|
|
@ -189,8 +189,15 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
|
|||
* shouldn't touch the cache level, especially as that
|
||||
* would make the object snooped which might have a
|
||||
* negative performance impact.
|
||||
*
|
||||
* Snooping is required on non-llc platforms in execlist
|
||||
* mode, but since all GGTT accesses use PAT entry 0 we
|
||||
* get snooping anyway regardless of cache_level.
|
||||
*
|
||||
* This is only applicable for Ivy Bridge devices since
|
||||
* later platforms don't have L3 control bits in the PTE.
|
||||
*/
|
||||
if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) {
|
||||
if (IS_IVYBRIDGE(dev)) {
|
||||
ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC);
|
||||
/* Failure shouldn't ever happen this early */
|
||||
if (WARN_ON(ret)) {
|
||||
|
|
|
@ -199,6 +199,45 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
i915_gem_evict_for_vma(struct i915_vma *target)
|
||||
{
|
||||
struct drm_mm_node *node, *next;
|
||||
|
||||
list_for_each_entry_safe(node, next,
|
||||
&target->vm->mm.head_node.node_list,
|
||||
node_list) {
|
||||
struct i915_vma *vma;
|
||||
int ret;
|
||||
|
||||
if (node->start + node->size <= target->node.start)
|
||||
continue;
|
||||
if (node->start >= target->node.start + target->node.size)
|
||||
break;
|
||||
|
||||
vma = container_of(node, typeof(*vma), node);
|
||||
|
||||
if (vma->pin_count) {
|
||||
if (!vma->exec_entry || (vma->pin_count > 1))
|
||||
/* Object is pinned for some other use */
|
||||
return -EBUSY;
|
||||
|
||||
/* We need to evict a buffer in the same batch */
|
||||
if (vma->exec_entry->flags & EXEC_OBJECT_PINNED)
|
||||
/* Overlapping fixed objects in the same batch */
|
||||
return -EINVAL;
|
||||
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
ret = i915_vma_unbind(vma);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_gem_evict_vm - Evict all idle vmas from a vm
|
||||
* @vm: Address space to cleanse
|
||||
|
|
|
@ -264,7 +264,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
vaddr = kmap_atomic(i915_gem_object_get_page(obj,
|
||||
vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
|
||||
reloc->offset >> PAGE_SHIFT));
|
||||
*(uint32_t *)(vaddr + page_offset) = lower_32_bits(delta);
|
||||
|
||||
|
@ -273,7 +273,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj,
|
|||
|
||||
if (page_offset == 0) {
|
||||
kunmap_atomic(vaddr);
|
||||
vaddr = kmap_atomic(i915_gem_object_get_page(obj,
|
||||
vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
|
||||
(reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT));
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
vaddr = kmap_atomic(i915_gem_object_get_page(obj,
|
||||
vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
|
||||
reloc->offset >> PAGE_SHIFT));
|
||||
clflush_write32(vaddr + page_offset, lower_32_bits(delta));
|
||||
|
||||
|
@ -364,7 +364,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj,
|
|||
|
||||
if (page_offset == 0) {
|
||||
kunmap_atomic(vaddr);
|
||||
vaddr = kmap_atomic(i915_gem_object_get_page(obj,
|
||||
vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
|
||||
(reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT));
|
||||
}
|
||||
|
||||
|
@ -599,6 +599,8 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
|
|||
flags |= PIN_GLOBAL | PIN_MAPPABLE;
|
||||
if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS)
|
||||
flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS;
|
||||
if (entry->flags & EXEC_OBJECT_PINNED)
|
||||
flags |= entry->offset | PIN_OFFSET_FIXED;
|
||||
if ((flags & PIN_MAPPABLE) == 0)
|
||||
flags |= PIN_HIGH;
|
||||
}
|
||||
|
@ -670,6 +672,10 @@ eb_vma_misplaced(struct i915_vma *vma)
|
|||
vma->node.start & (entry->alignment - 1))
|
||||
return true;
|
||||
|
||||
if (entry->flags & EXEC_OBJECT_PINNED &&
|
||||
vma->node.start != entry->offset)
|
||||
return true;
|
||||
|
||||
if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS &&
|
||||
vma->node.start < BATCH_OFFSET_BIAS)
|
||||
return true;
|
||||
|
@ -695,6 +701,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
|
|||
struct i915_vma *vma;
|
||||
struct i915_address_space *vm;
|
||||
struct list_head ordered_vmas;
|
||||
struct list_head pinned_vmas;
|
||||
bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
|
||||
int retry;
|
||||
|
||||
|
@ -703,6 +710,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
|
|||
vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm;
|
||||
|
||||
INIT_LIST_HEAD(&ordered_vmas);
|
||||
INIT_LIST_HEAD(&pinned_vmas);
|
||||
while (!list_empty(vmas)) {
|
||||
struct drm_i915_gem_exec_object2 *entry;
|
||||
bool need_fence, need_mappable;
|
||||
|
@ -721,7 +729,9 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
|
|||
obj->tiling_mode != I915_TILING_NONE;
|
||||
need_mappable = need_fence || need_reloc_mappable(vma);
|
||||
|
||||
if (need_mappable) {
|
||||
if (entry->flags & EXEC_OBJECT_PINNED)
|
||||
list_move_tail(&vma->exec_list, &pinned_vmas);
|
||||
else if (need_mappable) {
|
||||
entry->flags |= __EXEC_OBJECT_NEEDS_MAP;
|
||||
list_move(&vma->exec_list, &ordered_vmas);
|
||||
} else
|
||||
|
@ -731,6 +741,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
|
|||
obj->base.pending_write_domain = 0;
|
||||
}
|
||||
list_splice(&ordered_vmas, vmas);
|
||||
list_splice(&pinned_vmas, vmas);
|
||||
|
||||
/* Attempt to pin all of the buffers into the GTT.
|
||||
* This is done in 3 phases:
|
||||
|
@ -1317,7 +1328,8 @@ eb_get_batch(struct eb_vmas *eb)
|
|||
* Note that actual hangs have only been observed on gen7, but for
|
||||
* paranoia do it everywhere.
|
||||
*/
|
||||
vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS;
|
||||
if ((vma->exec_entry->flags & EXEC_OBJECT_PINNED) == 0)
|
||||
vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS;
|
||||
|
||||
return vma->obj;
|
||||
}
|
||||
|
|
|
@ -140,8 +140,7 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
|
|||
#endif
|
||||
|
||||
/* Early VLV doesn't have this */
|
||||
if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
|
||||
dev->pdev->revision < 0xb) {
|
||||
if (IS_VALLEYVIEW(dev) && dev->pdev->revision < 0xb) {
|
||||
DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -770,10 +769,10 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
|
|||
gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
|
||||
scratch_pte);
|
||||
} else {
|
||||
uint64_t templ4, pml4e;
|
||||
uint64_t pml4e;
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
|
||||
gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
|
||||
gen8_ppgtt_clear_pte_range(vm, pdp, start, length,
|
||||
scratch_pte);
|
||||
}
|
||||
|
@ -839,10 +838,10 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
|
|||
cache_level);
|
||||
} else {
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
uint64_t templ4, pml4e;
|
||||
uint64_t pml4e;
|
||||
uint64_t length = (uint64_t)pages->orig_nents << PAGE_SHIFT;
|
||||
|
||||
gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
|
||||
gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter,
|
||||
start, cache_level);
|
||||
}
|
||||
|
@ -1020,10 +1019,9 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm,
|
|||
{
|
||||
struct drm_device *dev = vm->dev;
|
||||
struct i915_page_table *pt;
|
||||
uint64_t temp;
|
||||
uint32_t pde;
|
||||
|
||||
gen8_for_each_pde(pt, pd, start, length, temp, pde) {
|
||||
gen8_for_each_pde(pt, pd, start, length, pde) {
|
||||
/* Don't reallocate page tables */
|
||||
if (test_bit(pde, pd->used_pdes)) {
|
||||
/* Scratch is never allocated this way */
|
||||
|
@ -1082,13 +1080,12 @@ gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm,
|
|||
{
|
||||
struct drm_device *dev = vm->dev;
|
||||
struct i915_page_directory *pd;
|
||||
uint64_t temp;
|
||||
uint32_t pdpe;
|
||||
uint32_t pdpes = I915_PDPES_PER_PDP(dev);
|
||||
|
||||
WARN_ON(!bitmap_empty(new_pds, pdpes));
|
||||
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
||||
if (test_bit(pdpe, pdp->used_pdpes))
|
||||
continue;
|
||||
|
||||
|
@ -1136,12 +1133,11 @@ gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm,
|
|||
{
|
||||
struct drm_device *dev = vm->dev;
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
uint64_t temp;
|
||||
uint32_t pml4e;
|
||||
|
||||
WARN_ON(!bitmap_empty(new_pdps, GEN8_PML4ES_PER_PML4));
|
||||
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
||||
if (!test_bit(pml4e, pml4->used_pml4es)) {
|
||||
pdp = alloc_pdp(dev);
|
||||
if (IS_ERR(pdp))
|
||||
|
@ -1225,7 +1221,6 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
|||
struct i915_page_directory *pd;
|
||||
const uint64_t orig_start = start;
|
||||
const uint64_t orig_length = length;
|
||||
uint64_t temp;
|
||||
uint32_t pdpe;
|
||||
uint32_t pdpes = I915_PDPES_PER_PDP(dev);
|
||||
int ret;
|
||||
|
@ -1252,7 +1247,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
|||
}
|
||||
|
||||
/* For every page directory referenced, allocate page tables */
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
||||
ret = gen8_ppgtt_alloc_pagetabs(vm, pd, start, length,
|
||||
new_page_tables + pdpe * BITS_TO_LONGS(I915_PDES));
|
||||
if (ret)
|
||||
|
@ -1264,7 +1259,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
|||
|
||||
/* Allocations have completed successfully, so set the bitmaps, and do
|
||||
* the mappings. */
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
||||
gen8_pde_t *const page_directory = kmap_px(pd);
|
||||
struct i915_page_table *pt;
|
||||
uint64_t pd_len = length;
|
||||
|
@ -1274,7 +1269,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
|||
/* Every pd should be allocated, we just did that above. */
|
||||
WARN_ON(!pd);
|
||||
|
||||
gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) {
|
||||
gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
|
||||
/* Same reasoning as pd */
|
||||
WARN_ON(!pt);
|
||||
WARN_ON(!pd_len);
|
||||
|
@ -1311,6 +1306,8 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
|||
|
||||
err_out:
|
||||
while (pdpe--) {
|
||||
unsigned long temp;
|
||||
|
||||
for_each_set_bit(temp, new_page_tables + pdpe *
|
||||
BITS_TO_LONGS(I915_PDES), I915_PDES)
|
||||
free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]);
|
||||
|
@ -1333,7 +1330,7 @@ static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
|
|||
struct i915_hw_ppgtt *ppgtt =
|
||||
container_of(vm, struct i915_hw_ppgtt, base);
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
uint64_t temp, pml4e;
|
||||
uint64_t pml4e;
|
||||
int ret = 0;
|
||||
|
||||
/* Do the pml4 allocations first, so we don't need to track the newly
|
||||
|
@ -1352,7 +1349,7 @@ static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
|
|||
"The allocation has spanned more than 512GB. "
|
||||
"It is highly likely this is incorrect.");
|
||||
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
||||
WARN_ON(!pdp);
|
||||
|
||||
ret = gen8_alloc_va_range_3lvl(vm, pdp, start, length);
|
||||
|
@ -1392,10 +1389,9 @@ static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp,
|
|||
struct seq_file *m)
|
||||
{
|
||||
struct i915_page_directory *pd;
|
||||
uint64_t temp;
|
||||
uint32_t pdpe;
|
||||
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
||||
struct i915_page_table *pt;
|
||||
uint64_t pd_len = length;
|
||||
uint64_t pd_start = start;
|
||||
|
@ -1405,7 +1401,7 @@ static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp,
|
|||
continue;
|
||||
|
||||
seq_printf(m, "\tPDPE #%d\n", pdpe);
|
||||
gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) {
|
||||
gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
|
||||
uint32_t pte;
|
||||
gen8_pte_t *pt_vaddr;
|
||||
|
||||
|
@ -1455,11 +1451,11 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
|
|||
if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
|
||||
gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
|
||||
} else {
|
||||
uint64_t templ4, pml4e;
|
||||
uint64_t pml4e;
|
||||
struct i915_pml4 *pml4 = &ppgtt->pml4;
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, templ4, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
||||
if (!test_bit(pml4e, pml4->used_pml4es))
|
||||
continue;
|
||||
|
||||
|
@ -2355,6 +2351,9 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
|
|||
int i = 0;
|
||||
struct sg_page_iter sg_iter;
|
||||
dma_addr_t addr = 0; /* shut up gcc */
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
|
||||
addr = sg_dma_address(sg_iter.sg) +
|
||||
|
@ -2381,6 +2380,8 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
|
|||
*/
|
||||
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
|
||||
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2401,6 +2402,9 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
|
|||
int i = 0;
|
||||
struct sg_page_iter sg_iter;
|
||||
dma_addr_t addr = 0;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
|
||||
addr = sg_page_iter_dma_address(&sg_iter);
|
||||
|
@ -2425,6 +2429,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
|
|||
*/
|
||||
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
|
||||
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
||||
|
@ -2439,6 +2445,9 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
|||
(gen8_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
|
||||
const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
|
||||
int i;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
if (WARN(num_entries > max_entries,
|
||||
"First entry = %d; Num entries = %d (max=%d)\n",
|
||||
|
@ -2451,6 +2460,8 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
|||
for (i = 0; i < num_entries; i++)
|
||||
gen8_set_pte(>t_base[i], scratch_pte);
|
||||
readl(gtt_base);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
static void gen6_ggtt_clear_range(struct i915_address_space *vm,
|
||||
|
@ -2465,6 +2476,9 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
|
|||
(gen6_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
|
||||
const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
|
||||
int i;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
if (WARN(num_entries > max_entries,
|
||||
"First entry = %d; Num entries = %d (max=%d)\n",
|
||||
|
@ -2477,6 +2491,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
|
|||
for (i = 0; i < num_entries; i++)
|
||||
iowrite32(scratch_pte, >t_base[i]);
|
||||
readl(gtt_base);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
static void i915_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
|
@ -2484,11 +2500,17 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm,
|
|||
uint64_t start,
|
||||
enum i915_cache_level cache_level, u32 unused)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = vm->dev->dev_private;
|
||||
unsigned int flags = (cache_level == I915_CACHE_NONE) ?
|
||||
AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
|
||||
}
|
||||
|
||||
static void i915_ggtt_clear_range(struct i915_address_space *vm,
|
||||
|
@ -2496,9 +2518,16 @@ static void i915_ggtt_clear_range(struct i915_address_space *vm,
|
|||
uint64_t length,
|
||||
bool unused)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = vm->dev->dev_private;
|
||||
unsigned first_entry = start >> PAGE_SHIFT;
|
||||
unsigned num_entries = length >> PAGE_SHIFT;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
intel_gtt_clear_range(first_entry, num_entries);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
static int ggtt_bind_vma(struct i915_vma *vma,
|
||||
|
@ -2699,6 +2728,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
|
|||
return ret;
|
||||
}
|
||||
vma->bound |= GLOBAL_BIND;
|
||||
__i915_vma_set_map_and_fenceable(vma);
|
||||
list_add_tail(&vma->mm_list, &ggtt_vm->inactive_list);
|
||||
}
|
||||
|
||||
|
|
|
@ -455,32 +455,29 @@ static inline uint32_t gen6_pde_index(uint32_t addr)
|
|||
* between from start until start + length. On gen8+ it simply iterates
|
||||
* over every page directory entry in a page directory.
|
||||
*/
|
||||
#define gen8_for_each_pde(pt, pd, start, length, temp, iter) \
|
||||
for (iter = gen8_pde_index(start); \
|
||||
length > 0 && iter < I915_PDES ? \
|
||||
(pt = (pd)->page_table[iter]), 1 : 0; \
|
||||
iter++, \
|
||||
temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT) - start, \
|
||||
temp = min(temp, length), \
|
||||
start += temp, length -= temp)
|
||||
#define gen8_for_each_pde(pt, pd, start, length, iter) \
|
||||
for (iter = gen8_pde_index(start); \
|
||||
length > 0 && iter < I915_PDES && \
|
||||
(pt = (pd)->page_table[iter], true); \
|
||||
({ u64 temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT); \
|
||||
temp = min(temp - start, length); \
|
||||
start += temp, length -= temp; }), ++iter)
|
||||
|
||||
#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter) \
|
||||
for (iter = gen8_pdpe_index(start); \
|
||||
length > 0 && (iter < I915_PDPES_PER_PDP(dev)) ? \
|
||||
(pd = (pdp)->page_directory[iter]), 1 : 0; \
|
||||
iter++, \
|
||||
temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT) - start, \
|
||||
temp = min(temp, length), \
|
||||
start += temp, length -= temp)
|
||||
#define gen8_for_each_pdpe(pd, pdp, start, length, iter) \
|
||||
for (iter = gen8_pdpe_index(start); \
|
||||
length > 0 && iter < I915_PDPES_PER_PDP(dev) && \
|
||||
(pd = (pdp)->page_directory[iter], true); \
|
||||
({ u64 temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT); \
|
||||
temp = min(temp - start, length); \
|
||||
start += temp, length -= temp; }), ++iter)
|
||||
|
||||
#define gen8_for_each_pml4e(pdp, pml4, start, length, temp, iter) \
|
||||
for (iter = gen8_pml4e_index(start); \
|
||||
length > 0 && iter < GEN8_PML4ES_PER_PML4 ? \
|
||||
(pdp = (pml4)->pdps[iter]), 1 : 0; \
|
||||
iter++, \
|
||||
temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT) - start, \
|
||||
temp = min(temp, length), \
|
||||
start += temp, length -= temp)
|
||||
#define gen8_for_each_pml4e(pdp, pml4, start, length, iter) \
|
||||
for (iter = gen8_pml4e_index(start); \
|
||||
length > 0 && iter < GEN8_PML4ES_PER_PML4 && \
|
||||
(pdp = (pml4)->pdps[iter], true); \
|
||||
({ u64 temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT); \
|
||||
temp = min(temp - start, length); \
|
||||
start += temp, length -= temp; }), ++iter)
|
||||
|
||||
static inline uint32_t gen8_pte_index(uint64_t address)
|
||||
{
|
||||
|
|
|
@ -103,7 +103,7 @@ static int render_state_setup(struct render_state *so)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
page = sg_page(so->obj->pages->sgl);
|
||||
page = i915_gem_object_get_dirty_page(so->obj, 0);
|
||||
d = kmap(page);
|
||||
|
||||
while (i < rodata->batch_items) {
|
||||
|
|
|
@ -688,6 +688,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
|
|||
}
|
||||
|
||||
vma->bound |= GLOBAL_BIND;
|
||||
__i915_vma_set_map_and_fenceable(vma);
|
||||
list_add_tail(&vma->mm_list, &ggtt->inactive_list);
|
||||
}
|
||||
|
||||
|
|
|
@ -568,7 +568,7 @@ static void lr_context_update(struct drm_i915_gem_request *rq)
|
|||
WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
|
||||
WARN_ON(!i915_gem_obj_is_pinned(rb_obj));
|
||||
|
||||
page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
|
||||
page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
|
||||
reg_state = kmap_atomic(page);
|
||||
|
||||
reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj);
|
||||
|
|
|
@ -581,7 +581,7 @@ i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
|
|||
{
|
||||
u32 enable_mask;
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
|
||||
status_mask);
|
||||
else
|
||||
|
@ -595,7 +595,7 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
|
|||
{
|
||||
u32 enable_mask;
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev,
|
||||
status_mask);
|
||||
else
|
||||
|
@ -1103,6 +1103,14 @@ static void gen6_pm_rps_work(struct work_struct *work)
|
|||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The RPS work is synced during runtime suspend, we don't require a
|
||||
* wakeref. TODO: instead of disabling the asserts make sure that we
|
||||
* always hold an RPM reference while the work is running.
|
||||
*/
|
||||
DISABLE_RPM_WAKEREF_ASSERTS(dev_priv);
|
||||
|
||||
pm_iir = dev_priv->rps.pm_iir;
|
||||
dev_priv->rps.pm_iir = 0;
|
||||
/* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */
|
||||
|
@ -1115,7 +1123,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
|
|||
WARN_ON(pm_iir & ~dev_priv->pm_rps_events);
|
||||
|
||||
if ((pm_iir & dev_priv->pm_rps_events) == 0 && !client_boost)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
|
||||
|
@ -1170,6 +1178,8 @@ static void gen6_pm_rps_work(struct work_struct *work)
|
|||
intel_set_rps(dev_priv->dev, new_delay);
|
||||
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
out:
|
||||
ENABLE_RPM_WAKEREF_ASSERTS(dev_priv);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1723,7 +1733,7 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev)
|
|||
*/
|
||||
POSTING_READ(PORT_HOTPLUG_STAT);
|
||||
|
||||
if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
|
||||
if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
|
||||
|
||||
if (hotplug_trigger) {
|
||||
|
@ -1758,6 +1768,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
|
|||
if (!intel_irqs_enabled(dev_priv))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
while (true) {
|
||||
/* Find, clear, then process each source of interrupt */
|
||||
|
||||
|
@ -1792,6 +1805,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
|
|||
}
|
||||
|
||||
out:
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1805,6 +1820,9 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
|
|||
if (!intel_irqs_enabled(dev_priv))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
for (;;) {
|
||||
master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
|
||||
iir = I915_READ(VLV_IIR);
|
||||
|
@ -1835,6 +1853,8 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
|
|||
POSTING_READ(GEN8_MASTER_IRQ);
|
||||
}
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2165,6 +2185,9 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
|
|||
if (!intel_irqs_enabled(dev_priv))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
/* We get interrupts on unclaimed registers, so check for this before we
|
||||
* do any I915_{READ,WRITE}. */
|
||||
intel_uncore_check_errors(dev);
|
||||
|
@ -2223,6 +2246,9 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
|
|||
POSTING_READ(SDEIER);
|
||||
}
|
||||
|
||||
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2255,6 +2281,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
|
|||
if (!intel_irqs_enabled(dev_priv))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
if (INTEL_INFO(dev_priv)->gen >= 9)
|
||||
aux_mask |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
|
||||
GEN9_AUX_CHANNEL_D;
|
||||
|
@ -2262,7 +2291,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
|
|||
master_ctl = I915_READ_FW(GEN8_MASTER_IRQ);
|
||||
master_ctl &= ~GEN8_MASTER_IRQ_CONTROL;
|
||||
if (!master_ctl)
|
||||
return IRQ_NONE;
|
||||
goto out;
|
||||
|
||||
I915_WRITE_FW(GEN8_MASTER_IRQ, 0);
|
||||
|
||||
|
@ -2393,6 +2422,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
|
|||
I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
|
||||
POSTING_READ_FW(GEN8_MASTER_IRQ);
|
||||
|
||||
out:
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2989,6 +3021,13 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
|
|||
if (!i915.enable_hangcheck)
|
||||
return;
|
||||
|
||||
/*
|
||||
* The hangcheck work is synced during runtime suspend, we don't
|
||||
* require a wakeref. TODO: instead of disabling the asserts make
|
||||
* sure that we hold a reference when this work is running.
|
||||
*/
|
||||
DISABLE_RPM_WAKEREF_ASSERTS(dev_priv);
|
||||
|
||||
for_each_ring(ring, dev_priv, i) {
|
||||
u64 acthd;
|
||||
u32 seqno;
|
||||
|
@ -3080,13 +3119,18 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
if (rings_hung)
|
||||
return i915_handle_error(dev, true, "Ring hung");
|
||||
if (rings_hung) {
|
||||
i915_handle_error(dev, true, "Ring hung");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (busy_count)
|
||||
/* Reset timer case chip hangs without another request
|
||||
* being added */
|
||||
i915_queue_hangcheck(dev);
|
||||
|
||||
out:
|
||||
ENABLE_RPM_WAKEREF_ASSERTS(dev_priv);
|
||||
}
|
||||
|
||||
void i915_queue_hangcheck(struct drm_device *dev)
|
||||
|
@ -3878,13 +3922,18 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
|
|||
u16 flip_mask =
|
||||
I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
|
||||
I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
|
||||
irqreturn_t ret;
|
||||
|
||||
if (!intel_irqs_enabled(dev_priv))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
ret = IRQ_NONE;
|
||||
iir = I915_READ16(IIR);
|
||||
if (iir == 0)
|
||||
return IRQ_NONE;
|
||||
goto out;
|
||||
|
||||
while (iir & ~flip_mask) {
|
||||
/* Can't rely on pipestat interrupt bit in iir as it might
|
||||
|
@ -3933,8 +3982,12 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
|
|||
|
||||
iir = new_iir;
|
||||
}
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
out:
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void i8xx_irq_uninstall(struct drm_device * dev)
|
||||
|
@ -4063,6 +4116,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
|
|||
if (!intel_irqs_enabled(dev_priv))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
iir = I915_READ(IIR);
|
||||
do {
|
||||
bool irq_received = (iir & ~flip_mask) != 0;
|
||||
|
@ -4145,6 +4201,8 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
|
|||
iir = new_iir;
|
||||
} while (iir & ~flip_mask);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -4284,6 +4342,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
|
|||
if (!intel_irqs_enabled(dev_priv))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
iir = I915_READ(IIR);
|
||||
|
||||
for (;;) {
|
||||
|
@ -4369,6 +4430,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
|
|||
iir = new_iir;
|
||||
}
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -4412,7 +4475,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
|
|||
INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
|
||||
|
||||
/* Let's track the enabled rps events */
|
||||
if (IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
|
||||
if (IS_VALLEYVIEW(dev_priv))
|
||||
/* WaGsvRC0ResidencyMethod:vlv */
|
||||
dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED;
|
||||
else
|
||||
|
|
|
@ -7327,6 +7327,7 @@ enum skl_disp_power_wells {
|
|||
#define SBI_READY (0x0<<0)
|
||||
|
||||
/* SBI offsets */
|
||||
#define SBI_SSCDIVINTPHASE 0x0200
|
||||
#define SBI_SSCDIVINTPHASE6 0x0600
|
||||
#define SBI_SSCDIVINTPHASE_DIVSEL_MASK ((0x7f)<<1)
|
||||
#define SBI_SSCDIVINTPHASE_DIVSEL(x) ((x)<<1)
|
||||
|
@ -7334,6 +7335,7 @@ enum skl_disp_power_wells {
|
|||
#define SBI_SSCDIVINTPHASE_INCVAL(x) ((x)<<8)
|
||||
#define SBI_SSCDIVINTPHASE_DIR(x) ((x)<<15)
|
||||
#define SBI_SSCDIVINTPHASE_PROPAGATE (1<<0)
|
||||
#define SBI_SSCDITHPHASE 0x0204
|
||||
#define SBI_SSCCTL 0x020c
|
||||
#define SBI_SSCCTL6 0x060C
|
||||
#define SBI_SSCCTL_PATHALT (1<<3)
|
||||
|
@ -8100,9 +8102,7 @@ enum skl_disp_power_wells {
|
|||
#define RGB_FLIP_TO_BGR (1 << 2)
|
||||
|
||||
#define BXT_PIPE_SELECT_MASK (7 << 7)
|
||||
#define BXT_PIPE_SELECT_C (2 << 7)
|
||||
#define BXT_PIPE_SELECT_B (1 << 7)
|
||||
#define BXT_PIPE_SELECT_A (0 << 7)
|
||||
#define BXT_PIPE_SELECT(pipe) ((pipe) << 7)
|
||||
|
||||
#define _MIPIA_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb108)
|
||||
#define _MIPIC_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb908)
|
||||
|
|
|
@ -49,7 +49,7 @@ static void i915_save_display(struct drm_device *dev)
|
|||
dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
|
||||
dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
|
||||
dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
|
||||
} else if (!IS_VALLEYVIEW(dev)) {
|
||||
} else if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
|
||||
dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
|
||||
dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
|
||||
dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
|
||||
|
@ -84,7 +84,7 @@ static void i915_restore_display(struct drm_device *dev)
|
|||
I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
|
||||
I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
|
||||
I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
|
||||
} else if (!IS_VALLEYVIEW(dev)) {
|
||||
} else if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
|
||||
I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
|
||||
I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
|
||||
I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
|
||||
|
|
|
@ -49,7 +49,7 @@ static u32 calc_residency(struct drm_device *dev,
|
|||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
/* On VLV and CHV, residency time is in CZ units rather than 1.28us */
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
units = 1;
|
||||
div = dev_priv->czclk_freq;
|
||||
|
||||
|
@ -284,7 +284,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev,
|
|||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
if (IS_VALLEYVIEW(dev_priv->dev)) {
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
u32 freq;
|
||||
freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
|
||||
ret = intel_gpu_freq(dev_priv, (freq >> 8) & 0xff);
|
||||
|
@ -598,7 +598,7 @@ void i915_setup_sysfs(struct drm_device *dev)
|
|||
if (ret)
|
||||
DRM_ERROR("RC6p residency sysfs setup failed\n");
|
||||
}
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
ret = sysfs_merge_group(&dev->primary->kdev->kobj,
|
||||
&media_rc6_attr_group);
|
||||
if (ret)
|
||||
|
@ -619,7 +619,7 @@ void i915_setup_sysfs(struct drm_device *dev)
|
|||
}
|
||||
|
||||
ret = 0;
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
ret = sysfs_create_files(&dev->primary->kdev->kobj, vlv_attrs);
|
||||
else if (INTEL_INFO(dev)->gen >= 6)
|
||||
ret = sysfs_create_files(&dev->primary->kdev->kobj, gen6_attrs);
|
||||
|
@ -635,7 +635,7 @@ void i915_setup_sysfs(struct drm_device *dev)
|
|||
void i915_teardown_sysfs(struct drm_device *dev)
|
||||
{
|
||||
sysfs_remove_bin_file(&dev->primary->kdev->kobj, &error_state_attr);
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
sysfs_remove_files(&dev->primary->kdev->kobj, vlv_attrs);
|
||||
else
|
||||
sysfs_remove_files(&dev->primary->kdev->kobj, gen6_attrs);
|
||||
|
|
|
@ -95,6 +95,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
|
|||
|
||||
crtc_state->update_pipe = false;
|
||||
crtc_state->disable_lp_wm = false;
|
||||
crtc_state->disable_cxsr = false;
|
||||
crtc_state->wm_changed = false;
|
||||
|
||||
return &crtc_state->base;
|
||||
}
|
||||
|
|
|
@ -262,7 +262,8 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder)
|
|||
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))
|
||||
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) ||
|
||||
intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
|
||||
tmp |= AUD_CONFIG_N_VALUE_INDEX;
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
|
||||
|
@ -375,7 +376,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder)
|
|||
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)) {
|
||||
} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
aud_config = VLV_AUD_CFG(pipe);
|
||||
aud_cntrl_st2 = VLV_AUD_CNTL_ST2;
|
||||
} else {
|
||||
|
@ -435,7 +436,8 @@ static void ilk_audio_codec_enable(struct drm_connector *connector,
|
|||
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)) {
|
||||
} else if (IS_VALLEYVIEW(connector->dev) ||
|
||||
IS_CHERRYVIEW(connector->dev)) {
|
||||
hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe);
|
||||
aud_config = VLV_AUD_CFG(pipe);
|
||||
aud_cntl_st = VLV_AUD_CNTL_ST(pipe);
|
||||
|
@ -474,7 +476,8 @@ static void ilk_audio_codec_enable(struct drm_connector *connector,
|
|||
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))
|
||||
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) ||
|
||||
intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST))
|
||||
tmp |= AUD_CONFIG_N_VALUE_INDEX;
|
||||
else
|
||||
tmp |= audio_config_hdmi_pixel_clock(adjusted_mode);
|
||||
|
@ -512,7 +515,8 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
|
|||
|
||||
/* ELD Conn_Type */
|
||||
connector->eld[5] &= ~(3 << 2);
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
|
||||
intel_pipe_has_type(crtc, INTEL_OUTPUT_DP_MST))
|
||||
connector->eld[5] |= (1 << 2);
|
||||
|
||||
connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
|
||||
|
@ -521,6 +525,10 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
|
|||
dev_priv->display.audio_codec_enable(connector, intel_encoder,
|
||||
adjusted_mode);
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
intel_dig_port->audio_connector = connector;
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
|
||||
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
|
||||
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
|
||||
}
|
||||
|
@ -544,6 +552,10 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
|
|||
if (dev_priv->display.audio_codec_disable)
|
||||
dev_priv->display.audio_codec_disable(intel_encoder);
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
intel_dig_port->audio_connector = NULL;
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
|
||||
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
|
||||
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
|
||||
}
|
||||
|
@ -559,7 +571,7 @@ void intel_init_audio(struct drm_device *dev)
|
|||
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)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(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) {
|
||||
|
@ -628,15 +640,14 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
|
|||
int port, int rate)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev_to_i915(dev);
|
||||
struct drm_device *drm_dev = dev_priv->dev;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_digital_port *intel_dig_port;
|
||||
struct intel_crtc *crtc;
|
||||
struct drm_display_mode *mode;
|
||||
struct i915_audio_component *acomp = dev_priv->audio_component;
|
||||
enum pipe pipe = -1;
|
||||
enum pipe pipe = INVALID_PIPE;
|
||||
u32 tmp;
|
||||
int n;
|
||||
int err = 0;
|
||||
|
||||
/* HSW, BDW, SKL, KBL need this fix */
|
||||
if (!IS_SKYLAKE(dev_priv) &&
|
||||
|
@ -647,26 +658,22 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
|
|||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
/* 1. get the pipe */
|
||||
for_each_intel_encoder(drm_dev, intel_encoder) {
|
||||
if (intel_encoder->type != INTEL_OUTPUT_HDMI)
|
||||
continue;
|
||||
intel_dig_port = enc_to_dig_port(&intel_encoder->base);
|
||||
if (port == intel_dig_port->port) {
|
||||
crtc = to_intel_crtc(intel_encoder->base.crtc);
|
||||
if (!crtc) {
|
||||
DRM_DEBUG_KMS("%s: crtc is NULL\n", __func__);
|
||||
continue;
|
||||
}
|
||||
pipe = crtc->pipe;
|
||||
break;
|
||||
}
|
||||
intel_encoder = dev_priv->dig_port_map[port];
|
||||
/* intel_encoder might be NULL for DP MST */
|
||||
if (!intel_encoder || !intel_encoder->base.crtc ||
|
||||
intel_encoder->type != INTEL_OUTPUT_HDMI) {
|
||||
DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
|
||||
err = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
crtc = to_intel_crtc(intel_encoder->base.crtc);
|
||||
pipe = crtc->pipe;
|
||||
if (pipe == INVALID_PIPE) {
|
||||
DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port));
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return -ENODEV;
|
||||
err = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("pipe %c connects port %c\n",
|
||||
pipe_name(pipe), port_name(port));
|
||||
mode = &crtc->config->base.adjusted_mode;
|
||||
|
@ -679,8 +686,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
|
|||
tmp = I915_READ(HSW_AUD_CFG(pipe));
|
||||
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
n = audio_config_get_n(mode, rate);
|
||||
|
@ -690,8 +696,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
|
|||
tmp = I915_READ(HSW_AUD_CFG(pipe));
|
||||
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* 3. set the N/CTS/M */
|
||||
|
@ -699,8 +704,37 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
|
|||
tmp = audio_config_setup_n_reg(n, tmp);
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int i915_audio_component_get_eld(struct device *dev, int port,
|
||||
bool *enabled,
|
||||
unsigned char *buf, int max_bytes)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev_to_i915(dev);
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_digital_port *intel_dig_port;
|
||||
const u8 *eld;
|
||||
int ret = -EINVAL;
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
intel_encoder = dev_priv->dig_port_map[port];
|
||||
/* intel_encoder might be NULL for DP MST */
|
||||
if (intel_encoder) {
|
||||
ret = 0;
|
||||
intel_dig_port = enc_to_dig_port(&intel_encoder->base);
|
||||
*enabled = intel_dig_port->audio_connector != NULL;
|
||||
if (*enabled) {
|
||||
eld = intel_dig_port->audio_connector->eld;
|
||||
ret = drm_eld_size(eld);
|
||||
memcpy(buf, eld, min(max_bytes, ret));
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct i915_audio_component_ops i915_audio_component_ops = {
|
||||
|
@ -710,6 +744,7 @@ static const struct i915_audio_component_ops i915_audio_component_ops = {
|
|||
.codec_wake_override = i915_audio_component_codec_wake_override,
|
||||
.get_cdclk_freq = i915_audio_component_get_cdclk_freq,
|
||||
.sync_audio_rate = i915_audio_component_sync_audio_rate,
|
||||
.get_eld = i915_audio_component_get_eld,
|
||||
};
|
||||
|
||||
static int i915_audio_component_bind(struct device *i915_dev,
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
@ -332,10 +332,10 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
|
|||
drm_mode_debug_printmodeline(panel_fixed_mode);
|
||||
}
|
||||
|
||||
static int intel_bios_ssc_frequency(struct drm_device *dev,
|
||||
static int intel_bios_ssc_frequency(struct drm_i915_private *dev_priv,
|
||||
bool alternate)
|
||||
{
|
||||
switch (INTEL_INFO(dev)->gen) {
|
||||
switch (INTEL_INFO(dev_priv)->gen) {
|
||||
case 2:
|
||||
return alternate ? 66667 : 48000;
|
||||
case 3:
|
||||
|
@ -350,29 +350,29 @@ static void
|
|||
parse_general_features(struct drm_i915_private *dev_priv,
|
||||
const struct bdb_header *bdb)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
const struct bdb_general_features *general;
|
||||
|
||||
general = find_section(bdb, BDB_GENERAL_FEATURES);
|
||||
if (general) {
|
||||
dev_priv->vbt.int_tv_support = general->int_tv_support;
|
||||
/* int_crt_support can't be trusted on earlier platforms */
|
||||
if (bdb->version >= 155 &&
|
||||
(HAS_DDI(dev_priv) || IS_VALLEYVIEW(dev_priv)))
|
||||
dev_priv->vbt.int_crt_support = general->int_crt_support;
|
||||
dev_priv->vbt.lvds_use_ssc = general->enable_ssc;
|
||||
dev_priv->vbt.lvds_ssc_freq =
|
||||
intel_bios_ssc_frequency(dev, general->ssc_freq);
|
||||
dev_priv->vbt.display_clock_mode = general->display_clock_mode;
|
||||
dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
|
||||
DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
|
||||
dev_priv->vbt.int_tv_support,
|
||||
dev_priv->vbt.int_crt_support,
|
||||
dev_priv->vbt.lvds_use_ssc,
|
||||
dev_priv->vbt.lvds_ssc_freq,
|
||||
dev_priv->vbt.display_clock_mode,
|
||||
dev_priv->vbt.fdi_rx_polarity_inverted);
|
||||
}
|
||||
if (!general)
|
||||
return;
|
||||
|
||||
dev_priv->vbt.int_tv_support = general->int_tv_support;
|
||||
/* int_crt_support can't be trusted on earlier platforms */
|
||||
if (bdb->version >= 155 &&
|
||||
(HAS_DDI(dev_priv) || IS_VALLEYVIEW(dev_priv)))
|
||||
dev_priv->vbt.int_crt_support = general->int_crt_support;
|
||||
dev_priv->vbt.lvds_use_ssc = general->enable_ssc;
|
||||
dev_priv->vbt.lvds_ssc_freq =
|
||||
intel_bios_ssc_frequency(dev_priv, general->ssc_freq);
|
||||
dev_priv->vbt.display_clock_mode = general->display_clock_mode;
|
||||
dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
|
||||
DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
|
||||
dev_priv->vbt.int_tv_support,
|
||||
dev_priv->vbt.int_crt_support,
|
||||
dev_priv->vbt.lvds_use_ssc,
|
||||
dev_priv->vbt.lvds_ssc_freq,
|
||||
dev_priv->vbt.display_clock_mode,
|
||||
dev_priv->vbt.fdi_rx_polarity_inverted);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1057,10 +1057,9 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
|
|||
static void parse_ddi_ports(struct drm_i915_private *dev_priv,
|
||||
const struct bdb_header *bdb)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
enum port port;
|
||||
|
||||
if (!HAS_DDI(dev))
|
||||
if (!HAS_DDI(dev_priv))
|
||||
return;
|
||||
|
||||
if (!dev_priv->vbt.child_dev_num)
|
||||
|
@ -1173,7 +1172,6 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
|
|||
static void
|
||||
init_vbt_defaults(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
enum port port;
|
||||
|
||||
dev_priv->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC;
|
||||
|
@ -1198,8 +1196,8 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
|
|||
* Core/SandyBridge/IvyBridge use alternative (120MHz) reference
|
||||
* clock for LVDS.
|
||||
*/
|
||||
dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev,
|
||||
!HAS_PCH_SPLIT(dev));
|
||||
dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev_priv,
|
||||
!HAS_PCH_SPLIT(dev_priv));
|
||||
DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq);
|
||||
|
||||
for (port = PORT_A; port < I915_MAX_PORTS; port++) {
|
||||
|
@ -1214,88 +1212,79 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
|
|||
}
|
||||
}
|
||||
|
||||
static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
|
||||
static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt)
|
||||
{
|
||||
DRM_DEBUG_KMS("Falling back to manually reading VBT from "
|
||||
"VBIOS ROM for %s\n",
|
||||
id->ident);
|
||||
return 1;
|
||||
const void *_vbt = vbt;
|
||||
|
||||
return _vbt + vbt->bdb_offset;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id intel_no_opregion_vbt[] = {
|
||||
{
|
||||
.callback = intel_no_opregion_vbt_callback,
|
||||
.ident = "ThinkCentre A57",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct bdb_header *validate_vbt(const void *base,
|
||||
size_t size,
|
||||
const void *_vbt,
|
||||
const char *source)
|
||||
/**
|
||||
* intel_bios_is_valid_vbt - does the given buffer contain a valid VBT
|
||||
* @buf: pointer to a buffer to validate
|
||||
* @size: size of the buffer
|
||||
*
|
||||
* Returns true on valid VBT.
|
||||
*/
|
||||
bool intel_bios_is_valid_vbt(const void *buf, size_t size)
|
||||
{
|
||||
size_t offset = _vbt - base;
|
||||
const struct vbt_header *vbt = _vbt;
|
||||
const struct vbt_header *vbt = buf;
|
||||
const struct bdb_header *bdb;
|
||||
|
||||
if (offset + sizeof(struct vbt_header) > size) {
|
||||
if (!vbt)
|
||||
return false;
|
||||
|
||||
if (sizeof(struct vbt_header) > size) {
|
||||
DRM_DEBUG_DRIVER("VBT header incomplete\n");
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(vbt->signature, "$VBT", 4)) {
|
||||
DRM_DEBUG_DRIVER("VBT invalid signature\n");
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
offset += vbt->bdb_offset;
|
||||
if (offset + sizeof(struct bdb_header) > size) {
|
||||
if (vbt->bdb_offset + sizeof(struct bdb_header) > size) {
|
||||
DRM_DEBUG_DRIVER("BDB header incomplete\n");
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
bdb = base + offset;
|
||||
if (offset + bdb->bdb_size > size) {
|
||||
bdb = get_bdb_header(vbt);
|
||||
if (vbt->bdb_offset + bdb->bdb_size > size) {
|
||||
DRM_DEBUG_DRIVER("BDB incomplete\n");
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("Using VBT from %s: %20s\n",
|
||||
source, vbt->signature);
|
||||
return bdb;
|
||||
return vbt;
|
||||
}
|
||||
|
||||
static const struct bdb_header *find_vbt(void __iomem *bios, size_t size)
|
||||
static const struct vbt_header *find_vbt(void __iomem *bios, size_t size)
|
||||
{
|
||||
const struct bdb_header *bdb = NULL;
|
||||
size_t i;
|
||||
|
||||
/* Scour memory looking for the VBT signature. */
|
||||
for (i = 0; i + 4 < size; i++) {
|
||||
if (ioread32(bios + i) == *((const u32 *) "$VBT")) {
|
||||
/*
|
||||
* This is the one place where we explicitly discard the
|
||||
* address space (__iomem) of the BIOS/VBT. From now on
|
||||
* everything is based on 'base', and treated as regular
|
||||
* memory.
|
||||
*/
|
||||
void *_bios = (void __force *) bios;
|
||||
void *vbt;
|
||||
|
||||
bdb = validate_vbt(_bios, size, _bios + i, "PCI ROM");
|
||||
break;
|
||||
}
|
||||
if (ioread32(bios + i) != *((const u32 *) "$VBT"))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* This is the one place where we explicitly discard the address
|
||||
* space (__iomem) of the BIOS/VBT.
|
||||
*/
|
||||
vbt = (void __force *) bios + i;
|
||||
if (intel_bios_is_valid_vbt(vbt, size - i))
|
||||
return vbt;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return bdb;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_parse_bios - find VBT and initialize settings from the BIOS
|
||||
* intel_bios_init - find VBT and initialize settings from the BIOS
|
||||
* @dev: DRM device
|
||||
*
|
||||
* Loads the Video BIOS and checks that the VBT exists. Sets scratch registers
|
||||
|
@ -1304,37 +1293,39 @@ static const struct bdb_header *find_vbt(void __iomem *bios, size_t size)
|
|||
* Returns 0 on success, nonzero on failure.
|
||||
*/
|
||||
int
|
||||
intel_parse_bios(struct drm_device *dev)
|
||||
intel_bios_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
const struct bdb_header *bdb = NULL;
|
||||
struct pci_dev *pdev = dev_priv->dev->pdev;
|
||||
const struct vbt_header *vbt = dev_priv->opregion.vbt;
|
||||
const struct bdb_header *bdb;
|
||||
u8 __iomem *bios = NULL;
|
||||
|
||||
if (HAS_PCH_NOP(dev))
|
||||
if (HAS_PCH_NOP(dev_priv))
|
||||
return -ENODEV;
|
||||
|
||||
init_vbt_defaults(dev_priv);
|
||||
|
||||
/* XXX Should this validation be moved to intel_opregion.c? */
|
||||
if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt)
|
||||
bdb = validate_vbt(dev_priv->opregion.header, OPREGION_SIZE,
|
||||
dev_priv->opregion.vbt, "OpRegion");
|
||||
|
||||
if (bdb == NULL) {
|
||||
if (!vbt) {
|
||||
size_t size;
|
||||
|
||||
bios = pci_map_rom(pdev, &size);
|
||||
if (!bios)
|
||||
return -1;
|
||||
|
||||
bdb = find_vbt(bios, size);
|
||||
if (!bdb) {
|
||||
vbt = find_vbt(bios, size);
|
||||
if (!vbt) {
|
||||
pci_unmap_rom(pdev, bios);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n");
|
||||
}
|
||||
|
||||
bdb = get_bdb_header(vbt);
|
||||
|
||||
DRM_DEBUG_KMS("VBT signature \"%.*s\", BDB version %d\n",
|
||||
(int)sizeof(vbt->signature), vbt->signature, bdb->version);
|
||||
|
||||
/* Grab useful general definitions */
|
||||
parse_general_features(dev_priv, bdb);
|
||||
parse_general_definitions(dev_priv, bdb);
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#ifndef _I830_BIOS_H_
|
||||
#define _I830_BIOS_H_
|
||||
|
||||
#include <drm/drmP.h>
|
||||
|
||||
struct vbt_header {
|
||||
u8 signature[20]; /**< Always starts with 'VBT$' */
|
||||
u16 version; /**< decimal */
|
||||
|
@ -588,8 +586,6 @@ struct bdb_psr {
|
|||
struct psr_table psr_table[16];
|
||||
} __packed;
|
||||
|
||||
int intel_parse_bios(struct drm_device *dev);
|
||||
|
||||
/*
|
||||
* Driver<->VBIOS interaction occurs through scratch bits in
|
||||
* GR18 & SWF*.
|
||||
|
|
|
@ -844,7 +844,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||
crt->adpa_reg = adpa_reg;
|
||||
|
||||
crt->base.compute_config = intel_crt_compute_config;
|
||||
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
crt->base.disable = pch_disable_crt;
|
||||
crt->base.post_disable = pch_post_disable_crt;
|
||||
} else {
|
||||
|
|
|
@ -166,6 +166,14 @@ struct stepping_info {
|
|||
char substepping;
|
||||
};
|
||||
|
||||
/*
|
||||
* Kabylake derivated from Skylake H0, so SKL H0
|
||||
* is the right firmware for KBL A0 (revid 0).
|
||||
*/
|
||||
static const struct stepping_info kbl_stepping_info[] = {
|
||||
{'H', '0'}, {'I', '0'}
|
||||
};
|
||||
|
||||
static const struct stepping_info skl_stepping_info[] = {
|
||||
{'A', '0'}, {'B', '0'}, {'C', '0'},
|
||||
{'D', '0'}, {'E', '0'}, {'F', '0'},
|
||||
|
@ -182,7 +190,10 @@ static const struct stepping_info *intel_get_stepping_info(struct drm_device *de
|
|||
const struct stepping_info *si;
|
||||
unsigned int size;
|
||||
|
||||
if (IS_SKYLAKE(dev)) {
|
||||
if (IS_KABYLAKE(dev)) {
|
||||
size = ARRAY_SIZE(kbl_stepping_info);
|
||||
si = kbl_stepping_info;
|
||||
} else if (IS_SKYLAKE(dev)) {
|
||||
size = ARRAY_SIZE(skl_stepping_info);
|
||||
si = skl_stepping_info;
|
||||
} else if (IS_BROXTON(dev)) {
|
||||
|
|
|
@ -353,10 +353,10 @@ static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev,
|
|||
{
|
||||
const struct ddi_buf_trans *ddi_translations;
|
||||
|
||||
if (IS_SKL_ULX(dev)) {
|
||||
if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) {
|
||||
ddi_translations = skl_y_ddi_translations_dp;
|
||||
*n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
|
||||
} else if (IS_SKL_ULT(dev)) {
|
||||
} else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) {
|
||||
ddi_translations = skl_u_ddi_translations_dp;
|
||||
*n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp);
|
||||
} else {
|
||||
|
@ -373,7 +373,7 @@ static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev,
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
const struct ddi_buf_trans *ddi_translations;
|
||||
|
||||
if (IS_SKL_ULX(dev)) {
|
||||
if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) {
|
||||
if (dev_priv->edp_low_vswing) {
|
||||
ddi_translations = skl_y_ddi_translations_edp;
|
||||
*n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp);
|
||||
|
@ -381,7 +381,7 @@ static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev,
|
|||
ddi_translations = skl_y_ddi_translations_dp;
|
||||
*n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
|
||||
}
|
||||
} else if (IS_SKL_ULT(dev)) {
|
||||
} else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) {
|
||||
if (dev_priv->edp_low_vswing) {
|
||||
ddi_translations = skl_u_ddi_translations_edp;
|
||||
*n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp);
|
||||
|
@ -408,7 +408,7 @@ skl_get_buf_trans_hdmi(struct drm_device *dev,
|
|||
{
|
||||
const struct ddi_buf_trans *ddi_translations;
|
||||
|
||||
if (IS_SKL_ULX(dev)) {
|
||||
if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) {
|
||||
ddi_translations = skl_y_ddi_translations_hdmi;
|
||||
*n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi);
|
||||
} else {
|
||||
|
@ -675,15 +675,16 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
|
|||
temp = I915_READ(DP_TP_STATUS(PORT_E));
|
||||
if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {
|
||||
DRM_DEBUG_KMS("FDI link training done on step %d\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable normal pixel sending for FDI */
|
||||
I915_WRITE(DP_TP_CTL(PORT_E),
|
||||
DP_TP_CTL_FDI_AUTOTRAIN |
|
||||
DP_TP_CTL_LINK_TRAIN_NORMAL |
|
||||
DP_TP_CTL_ENHANCED_FRAME_ENABLE |
|
||||
DP_TP_CTL_ENABLE);
|
||||
|
||||
return;
|
||||
/*
|
||||
* Leave things enabled even if we failed to train FDI.
|
||||
* Results in less fireworks from the state checker.
|
||||
*/
|
||||
if (i == ARRAY_SIZE(hsw_ddi_translations_fdi) * 2 - 1) {
|
||||
DRM_ERROR("FDI link training failed!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
temp = I915_READ(DDI_BUF_CTL(PORT_E));
|
||||
|
@ -712,7 +713,12 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
|
|||
POSTING_READ(FDI_RX_MISC(PIPE_A));
|
||||
}
|
||||
|
||||
DRM_ERROR("FDI link training failed!\n");
|
||||
/* Enable normal pixel sending for FDI */
|
||||
I915_WRITE(DP_TP_CTL(PORT_E),
|
||||
DP_TP_CTL_FDI_AUTOTRAIN |
|
||||
DP_TP_CTL_LINK_TRAIN_NORMAL |
|
||||
DP_TP_CTL_ENHANCED_FRAME_ENABLE |
|
||||
DP_TP_CTL_ENABLE);
|
||||
}
|
||||
|
||||
void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder)
|
||||
|
@ -3108,6 +3114,19 @@ void intel_ddi_fdi_disable(struct drm_crtc *crtc)
|
|||
I915_WRITE(FDI_RX_CTL(PIPE_A), val);
|
||||
}
|
||||
|
||||
bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
|
||||
struct intel_crtc *intel_crtc)
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
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(intel_crtc->pipe))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void intel_ddi_get_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
|
@ -3168,11 +3187,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
|
|||
break;
|
||||
}
|
||||
|
||||
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(intel_crtc->pipe))
|
||||
pipe_config->has_audio = true;
|
||||
}
|
||||
pipe_config->has_audio =
|
||||
intel_ddi_is_audio_enabled(dev_priv, intel_crtc);
|
||||
|
||||
if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp &&
|
||||
pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
|
||||
|
@ -3295,6 +3311,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
|
|||
intel_encoder->get_config = intel_ddi_get_config;
|
||||
|
||||
intel_dig_port->port = port;
|
||||
dev_priv->dig_port_map[port] = intel_encoder;
|
||||
intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
|
||||
(DDI_BUF_PORT_REVERSAL |
|
||||
DDI_A_4_LANES);
|
||||
|
|
|
@ -118,6 +118,7 @@ static void skylake_pfit_enable(struct intel_crtc *crtc);
|
|||
static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
|
||||
static void ironlake_pfit_enable(struct intel_crtc *crtc);
|
||||
static void intel_modeset_setup_hw_state(struct drm_device *dev);
|
||||
static void intel_pre_disable_primary(struct drm_crtc *crtc);
|
||||
|
||||
typedef struct {
|
||||
int min, max;
|
||||
|
@ -187,7 +188,7 @@ int intel_hrawclk(struct drm_device *dev)
|
|||
uint32_t clkcfg;
|
||||
|
||||
/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
return 200;
|
||||
|
||||
clkcfg = I915_READ(CLKCFG);
|
||||
|
@ -215,7 +216,7 @@ int intel_hrawclk(struct drm_device *dev)
|
|||
|
||||
static void intel_update_czclk(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (!IS_VALLEYVIEW(dev_priv))
|
||||
if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
|
||||
return;
|
||||
|
||||
dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk",
|
||||
|
@ -716,11 +717,12 @@ static bool intel_PLL_is_valid(struct drm_device *dev,
|
|||
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
|
||||
INTELPllInvalid("m1 out of range\n");
|
||||
|
||||
if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) && !IS_BROXTON(dev))
|
||||
if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) &&
|
||||
!IS_CHERRYVIEW(dev) && !IS_BROXTON(dev))
|
||||
if (clock->m1 <= clock->m2)
|
||||
INTELPllInvalid("m1 <= m2\n");
|
||||
|
||||
if (!IS_VALLEYVIEW(dev) && !IS_BROXTON(dev)) {
|
||||
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) {
|
||||
if (clock->p < limit->p.min || limit->p.max < clock->p)
|
||||
INTELPllInvalid("p out of range\n");
|
||||
if (clock->m < limit->m.min || limit->m.max < clock->m)
|
||||
|
@ -1305,7 +1307,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
|
|||
I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
|
||||
panel_pipe = PIPE_B;
|
||||
/* XXX: else fix for eDP */
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
/* presumably write lock depends on pipe, not port select */
|
||||
pp_reg = VLV_PIPE_PP_CONTROL(pipe);
|
||||
panel_pipe = pipe;
|
||||
|
@ -1423,7 +1425,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
|
|||
"plane %d assertion failure, should be off on pipe %c but is still active\n",
|
||||
sprite, pipe_name(pipe));
|
||||
}
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
for_each_sprite(dev_priv, pipe, sprite) {
|
||||
u32 val = I915_READ(SPCNTR(pipe, sprite));
|
||||
I915_STATE_WARN(val & SP_ENABLE,
|
||||
|
@ -1606,9 +1608,6 @@ static void vlv_enable_pll(struct intel_crtc *crtc,
|
|||
|
||||
assert_pipe_disabled(dev_priv, crtc->pipe);
|
||||
|
||||
/* No really, not for ILK+ */
|
||||
BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
|
||||
|
||||
/* PLL is protected by panel, make sure we can write it */
|
||||
if (IS_MOBILE(dev_priv->dev))
|
||||
assert_panel_unlocked(dev_priv, crtc->pipe);
|
||||
|
@ -1646,8 +1645,6 @@ static void chv_enable_pll(struct intel_crtc *crtc,
|
|||
|
||||
assert_pipe_disabled(dev_priv, crtc->pipe);
|
||||
|
||||
BUG_ON(!IS_CHERRYVIEW(dev_priv->dev));
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
|
||||
/* Enable back the 10bit clock to display controller */
|
||||
|
@ -2319,7 +2316,7 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
|
|||
if (INTEL_INFO(dev_priv)->gen >= 9)
|
||||
return 256 * 1024;
|
||||
else if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv) ||
|
||||
IS_VALLEYVIEW(dev_priv))
|
||||
IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
return 128 * 1024;
|
||||
else if (INTEL_INFO(dev_priv)->gen >= 4)
|
||||
return 4 * 1024;
|
||||
|
@ -2599,6 +2596,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
|||
struct drm_i915_gem_object *obj;
|
||||
struct drm_plane *primary = intel_crtc->base.primary;
|
||||
struct drm_plane_state *plane_state = primary->state;
|
||||
struct drm_crtc_state *crtc_state = intel_crtc->base.state;
|
||||
struct intel_plane *intel_plane = to_intel_plane(primary);
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
if (!plane_config->fb)
|
||||
|
@ -2635,6 +2634,18 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We've failed to reconstruct the BIOS FB. Current display state
|
||||
* indicates that the primary plane is visible, but has a NULL FB,
|
||||
* which will lead to problems later if we don't fix it up. The
|
||||
* simplest solution is to just disable the primary plane now and
|
||||
* pretend the BIOS never had it enabled.
|
||||
*/
|
||||
to_intel_plane_state(plane_state)->visible = false;
|
||||
crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
|
||||
intel_pre_disable_primary(&intel_crtc->base);
|
||||
intel_plane->disable_plane(primary, &intel_crtc->base);
|
||||
|
||||
return;
|
||||
|
||||
valid_fb:
|
||||
|
@ -3940,6 +3951,21 @@ static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
|
||||
temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
|
||||
temp |= SBI_SSCCTL_DISABLE;
|
||||
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
}
|
||||
|
||||
/* Program iCLKIP clock to the desired frequency */
|
||||
static void lpt_program_iclkip(struct drm_crtc *crtc)
|
||||
{
|
||||
|
@ -3949,18 +3975,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
|
|||
u32 divsel, phaseinc, auxdiv, phasedir = 0;
|
||||
u32 temp;
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
|
||||
/* It is necessary to ungate the pixclk gate prior to programming
|
||||
* the divisors, and gate it back when it is done.
|
||||
*/
|
||||
I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
|
||||
|
||||
/* Disable SSCCTL */
|
||||
intel_sbi_write(dev_priv, SBI_SSCCTL6,
|
||||
intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK) |
|
||||
SBI_SSCCTL_DISABLE,
|
||||
SBI_ICLK);
|
||||
lpt_disable_iclkip(dev_priv);
|
||||
|
||||
/* 20MHz is a corner case which is out of range for the 7-bit divisor */
|
||||
if (clock == 20000) {
|
||||
|
@ -3978,7 +3993,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
|
|||
u32 iclk_pi_range = 64;
|
||||
u32 desired_divisor, msb_divisor_value, pi_value;
|
||||
|
||||
desired_divisor = (iclk_virtual_root_freq / clock);
|
||||
desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock);
|
||||
msb_divisor_value = desired_divisor / iclk_pi_range;
|
||||
pi_value = desired_divisor % iclk_pi_range;
|
||||
|
||||
|
@ -4000,6 +4015,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
|
|||
phasedir,
|
||||
phaseinc);
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
|
||||
/* Program SSCDIVINTPHASE6 */
|
||||
temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
|
||||
temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
|
||||
|
@ -4021,12 +4038,12 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
|
|||
temp &= ~SBI_SSCCTL_DISABLE;
|
||||
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
|
||||
/* Wait for initialization time */
|
||||
udelay(24);
|
||||
|
||||
I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
}
|
||||
|
||||
static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
|
||||
|
@ -4708,14 +4725,6 @@ intel_post_enable_primary(struct drm_crtc *crtc)
|
|||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
|
||||
/*
|
||||
* BDW signals flip done immediately if the plane
|
||||
* is disabled, even if the plane enable is already
|
||||
* armed to occur at the next vblank :(
|
||||
*/
|
||||
if (IS_BROADWELL(dev))
|
||||
intel_wait_for_vblank(dev, pipe);
|
||||
|
||||
/*
|
||||
* FIXME IPS should be fine as long as one plane is
|
||||
* enabled, but in practice it seems to have problems
|
||||
|
@ -4793,6 +4802,8 @@ intel_pre_disable_primary(struct drm_crtc *crtc)
|
|||
static void intel_post_plane_update(struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
|
||||
struct intel_crtc_state *pipe_config =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
|
||||
if (atomic->wait_vblank)
|
||||
|
@ -4800,10 +4811,9 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
|
|||
|
||||
intel_frontbuffer_flip(dev, atomic->fb_bits);
|
||||
|
||||
if (atomic->disable_cxsr)
|
||||
crtc->wm.cxsr_allowed = true;
|
||||
crtc->wm.cxsr_allowed = true;
|
||||
|
||||
if (crtc->atomic.update_wm_post)
|
||||
if (pipe_config->wm_changed && pipe_config->base.active)
|
||||
intel_update_watermarks(&crtc->base);
|
||||
|
||||
if (atomic->update_fbc)
|
||||
|
@ -4820,6 +4830,8 @@ static void intel_pre_plane_update(struct intel_crtc *crtc)
|
|||
struct drm_device *dev = crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
|
||||
struct intel_crtc_state *pipe_config =
|
||||
to_intel_crtc_state(crtc->base.state);
|
||||
|
||||
if (atomic->disable_fbc)
|
||||
intel_fbc_deactivate(crtc);
|
||||
|
@ -4830,10 +4842,13 @@ static void intel_pre_plane_update(struct intel_crtc *crtc)
|
|||
if (atomic->pre_disable_primary)
|
||||
intel_pre_disable_primary(&crtc->base);
|
||||
|
||||
if (atomic->disable_cxsr) {
|
||||
if (pipe_config->disable_cxsr) {
|
||||
crtc->wm.cxsr_allowed = false;
|
||||
intel_set_memory_cxsr(dev_priv, false);
|
||||
}
|
||||
|
||||
if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed)
|
||||
intel_update_watermarks(&crtc->base);
|
||||
}
|
||||
|
||||
static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
|
||||
|
@ -5166,18 +5181,18 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
|
|||
if (!intel_crtc->config->has_dsi_encoder)
|
||||
intel_ddi_disable_pipe_clock(intel_crtc);
|
||||
|
||||
if (intel_crtc->config->has_pch_encoder) {
|
||||
lpt_disable_pch_transcoder(dev_priv);
|
||||
intel_ddi_fdi_disable(crtc);
|
||||
}
|
||||
|
||||
for_each_encoder_on_crtc(dev, crtc, encoder)
|
||||
if (encoder->post_disable)
|
||||
encoder->post_disable(encoder);
|
||||
|
||||
if (intel_crtc->config->has_pch_encoder)
|
||||
if (intel_crtc->config->has_pch_encoder) {
|
||||
lpt_disable_pch_transcoder(dev_priv);
|
||||
lpt_disable_iclkip(dev_priv);
|
||||
intel_ddi_fdi_disable(crtc);
|
||||
|
||||
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
|
||||
true);
|
||||
}
|
||||
|
||||
intel_fbc_disable_crtc(intel_crtc);
|
||||
}
|
||||
|
@ -5457,7 +5472,7 @@ static void intel_update_cdclk(struct drm_device *dev)
|
|||
* BSpec erroneously claims we should aim for 4MHz, but
|
||||
* in fact 1MHz is the correct frequency.
|
||||
*/
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
/*
|
||||
* Program the gmbus_freq based on the cdclk frequency.
|
||||
* BSpec erroneously claims we should aim for 4MHz, but
|
||||
|
@ -6354,9 +6369,11 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
|
|||
WARN_ON(intel_crtc->unpin_work);
|
||||
|
||||
intel_pre_disable_primary(crtc);
|
||||
|
||||
intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
|
||||
to_intel_plane_state(crtc->primary->state)->visible = false;
|
||||
}
|
||||
|
||||
intel_crtc_disable_planes(crtc, crtc->state->plane_mask);
|
||||
dev_priv->display.crtc_disable(crtc);
|
||||
intel_crtc->active = false;
|
||||
intel_update_watermarks(crtc);
|
||||
|
@ -7182,7 +7199,7 @@ static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
|
|||
|
||||
WARN_ON(!crtc_state->base.state);
|
||||
|
||||
if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) {
|
||||
refclk = 100000;
|
||||
} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
|
||||
intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
|
||||
|
@ -7881,7 +7898,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
|
|||
pipeconf |= PIPECONF_DOUBLE_WIDE;
|
||||
|
||||
/* only g4x and later have fancy bpc/dither controls */
|
||||
if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
|
||||
if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
/* Bspec claims that we can't use dithering for 30bpp pipes. */
|
||||
if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30)
|
||||
pipeconf |= PIPECONF_DITHER_EN |
|
||||
|
@ -7921,7 +7938,8 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
|
|||
} else
|
||||
pipeconf |= PIPECONF_PROGRESSIVE;
|
||||
|
||||
if (IS_VALLEYVIEW(dev) && intel_crtc->config->limited_color_range)
|
||||
if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
|
||||
intel_crtc->config->limited_color_range)
|
||||
pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
|
||||
|
||||
I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
|
||||
|
@ -8168,7 +8186,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
|
|||
if (!(tmp & PIPECONF_ENABLE))
|
||||
return false;
|
||||
|
||||
if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
|
||||
if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
switch (tmp & PIPECONF_BPC_MASK) {
|
||||
case PIPECONF_6BPC:
|
||||
pipe_config->pipe_bpp = 18;
|
||||
|
@ -8184,7 +8202,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
|
|||
}
|
||||
}
|
||||
|
||||
if (IS_VALLEYVIEW(dev) && (tmp & PIPECONF_COLOR_RANGE_SELECT))
|
||||
if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
|
||||
(tmp & PIPECONF_COLOR_RANGE_SELECT))
|
||||
pipe_config->limited_color_range = true;
|
||||
|
||||
if (INTEL_INFO(dev)->gen < 4)
|
||||
|
@ -8212,7 +8231,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
|
|||
pipe_config->pixel_multiplier = 1;
|
||||
}
|
||||
pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
|
||||
if (!IS_VALLEYVIEW(dev)) {
|
||||
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
|
||||
/*
|
||||
* DPLL_DVO_2X_MODE must be enabled for both DPLLs
|
||||
* on 830. Filter it out here so that we don't
|
||||
|
@ -8564,6 +8583,67 @@ static void lpt_disable_clkout_dp(struct drm_device *dev)
|
|||
mutex_unlock(&dev_priv->sb_lock);
|
||||
}
|
||||
|
||||
#define BEND_IDX(steps) ((50 + (steps)) / 5)
|
||||
|
||||
static const uint16_t sscdivintphase[] = {
|
||||
[BEND_IDX( 50)] = 0x3B23,
|
||||
[BEND_IDX( 45)] = 0x3B23,
|
||||
[BEND_IDX( 40)] = 0x3C23,
|
||||
[BEND_IDX( 35)] = 0x3C23,
|
||||
[BEND_IDX( 30)] = 0x3D23,
|
||||
[BEND_IDX( 25)] = 0x3D23,
|
||||
[BEND_IDX( 20)] = 0x3E23,
|
||||
[BEND_IDX( 15)] = 0x3E23,
|
||||
[BEND_IDX( 10)] = 0x3F23,
|
||||
[BEND_IDX( 5)] = 0x3F23,
|
||||
[BEND_IDX( 0)] = 0x0025,
|
||||
[BEND_IDX( -5)] = 0x0025,
|
||||
[BEND_IDX(-10)] = 0x0125,
|
||||
[BEND_IDX(-15)] = 0x0125,
|
||||
[BEND_IDX(-20)] = 0x0225,
|
||||
[BEND_IDX(-25)] = 0x0225,
|
||||
[BEND_IDX(-30)] = 0x0325,
|
||||
[BEND_IDX(-35)] = 0x0325,
|
||||
[BEND_IDX(-40)] = 0x0425,
|
||||
[BEND_IDX(-45)] = 0x0425,
|
||||
[BEND_IDX(-50)] = 0x0525,
|
||||
};
|
||||
|
||||
/*
|
||||
* Bend CLKOUT_DP
|
||||
* steps -50 to 50 inclusive, in steps of 5
|
||||
* < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz)
|
||||
* change in clock period = -(steps / 10) * 5.787 ps
|
||||
*/
|
||||
static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
|
||||
{
|
||||
uint32_t tmp;
|
||||
int idx = BEND_IDX(steps);
|
||||
|
||||
if (WARN_ON(steps % 5 != 0))
|
||||
return;
|
||||
|
||||
if (WARN_ON(idx >= ARRAY_SIZE(sscdivintphase)))
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
|
||||
if (steps % 10 != 0)
|
||||
tmp = 0xAAAAAAAB;
|
||||
else
|
||||
tmp = 0x00000000;
|
||||
intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK);
|
||||
|
||||
tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK);
|
||||
tmp &= 0xffff0000;
|
||||
tmp |= sscdivintphase[idx];
|
||||
intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
}
|
||||
|
||||
#undef BEND_IDX
|
||||
|
||||
static void lpt_init_pch_refclk(struct drm_device *dev)
|
||||
{
|
||||
struct intel_encoder *encoder;
|
||||
|
@ -8579,10 +8659,12 @@ static void lpt_init_pch_refclk(struct drm_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (has_vga)
|
||||
if (has_vga) {
|
||||
lpt_bend_clkout_dp(to_i915(dev), 0);
|
||||
lpt_enable_clkout_dp(dev, true, true);
|
||||
else
|
||||
} else {
|
||||
lpt_disable_clkout_dp(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -9946,14 +10028,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
|
||||
static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
uint32_t cntl = 0, size = 0;
|
||||
|
||||
if (base) {
|
||||
if (on) {
|
||||
unsigned int width = intel_crtc->base.cursor->state->crtc_w;
|
||||
unsigned int height = intel_crtc->base.cursor->state->crtc_h;
|
||||
unsigned int stride = roundup_pow_of_two(width) * 4;
|
||||
|
@ -10008,16 +10090,15 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
|
|||
}
|
||||
}
|
||||
|
||||
static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
|
||||
static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
uint32_t cntl;
|
||||
uint32_t cntl = 0;
|
||||
|
||||
cntl = 0;
|
||||
if (base) {
|
||||
if (on) {
|
||||
cntl = MCURSOR_GAMMA_ENABLE;
|
||||
switch (intel_crtc->base.cursor->state->crtc_w) {
|
||||
case 64:
|
||||
|
@ -10068,18 +10149,17 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
|
|||
int y = cursor_state->crtc_y;
|
||||
u32 base = 0, pos = 0;
|
||||
|
||||
if (on)
|
||||
base = intel_crtc->cursor_addr;
|
||||
base = intel_crtc->cursor_addr;
|
||||
|
||||
if (x >= intel_crtc->config->pipe_src_w)
|
||||
base = 0;
|
||||
on = false;
|
||||
|
||||
if (y >= intel_crtc->config->pipe_src_h)
|
||||
base = 0;
|
||||
on = false;
|
||||
|
||||
if (x < 0) {
|
||||
if (x + cursor_state->crtc_w <= 0)
|
||||
base = 0;
|
||||
on = false;
|
||||
|
||||
pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
|
||||
x = -x;
|
||||
|
@ -10088,16 +10168,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
|
|||
|
||||
if (y < 0) {
|
||||
if (y + cursor_state->crtc_h <= 0)
|
||||
base = 0;
|
||||
on = false;
|
||||
|
||||
pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
|
||||
y = -y;
|
||||
}
|
||||
pos |= y << CURSOR_Y_SHIFT;
|
||||
|
||||
if (base == 0 && intel_crtc->cursor_base == 0)
|
||||
return;
|
||||
|
||||
I915_WRITE(CURPOS(pipe), pos);
|
||||
|
||||
/* ILK+ do this automagically */
|
||||
|
@ -10108,9 +10185,9 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
if (IS_845G(dev) || IS_I865G(dev))
|
||||
i845_update_cursor(crtc, base);
|
||||
i845_update_cursor(crtc, base, on);
|
||||
else
|
||||
i9xx_update_cursor(crtc, base);
|
||||
i9xx_update_cursor(crtc, base, on);
|
||||
}
|
||||
|
||||
static bool cursor_size_ok(struct drm_device *dev,
|
||||
|
@ -11539,7 +11616,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|||
if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
|
||||
work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
ring = &dev_priv->ring[BCS];
|
||||
if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode)
|
||||
/* vlv: DISPLAY_FLIP fails to change tiling */
|
||||
|
@ -11695,9 +11772,14 @@ static bool intel_wm_need_update(struct drm_plane *plane,
|
|||
struct intel_plane_state *cur = to_intel_plane_state(plane->state);
|
||||
|
||||
/* Update watermarks on tiling or size changes. */
|
||||
if (!plane->state->fb || !state->fb ||
|
||||
plane->state->fb->modifier[0] != state->fb->modifier[0] ||
|
||||
plane->state->rotation != state->rotation ||
|
||||
if (new->visible != cur->visible)
|
||||
return true;
|
||||
|
||||
if (!cur->base.fb || !new->base.fb)
|
||||
return false;
|
||||
|
||||
if (cur->base.fb->modifier[0] != new->base.fb->modifier[0] ||
|
||||
cur->base.rotation != new->base.rotation ||
|
||||
drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
|
||||
drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
|
||||
drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
|
||||
|
@ -11720,6 +11802,7 @@ static bool needs_scaling(struct intel_plane_state *state)
|
|||
int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
||||
struct drm_plane_state *plane_state)
|
||||
{
|
||||
struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
|
||||
struct drm_crtc *crtc = crtc_state->crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct drm_plane *plane = plane_state->plane;
|
||||
|
@ -11766,25 +11849,17 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
|
|||
plane->base.id, was_visible, visible,
|
||||
turn_off, turn_on, mode_changed);
|
||||
|
||||
if (turn_on) {
|
||||
intel_crtc->atomic.update_wm_pre = true;
|
||||
/* must disable cxsr around plane enable/disable */
|
||||
if (plane->type != DRM_PLANE_TYPE_CURSOR) {
|
||||
intel_crtc->atomic.disable_cxsr = true;
|
||||
/* to potentially re-enable cxsr */
|
||||
intel_crtc->atomic.wait_vblank = true;
|
||||
intel_crtc->atomic.update_wm_post = true;
|
||||
}
|
||||
} else if (turn_off) {
|
||||
intel_crtc->atomic.update_wm_post = true;
|
||||
if (turn_on || turn_off) {
|
||||
pipe_config->wm_changed = true;
|
||||
|
||||
/* must disable cxsr around plane enable/disable */
|
||||
if (plane->type != DRM_PLANE_TYPE_CURSOR) {
|
||||
if (is_crtc_enabled)
|
||||
intel_crtc->atomic.wait_vblank = true;
|
||||
intel_crtc->atomic.disable_cxsr = true;
|
||||
pipe_config->disable_cxsr = true;
|
||||
}
|
||||
} else if (intel_wm_need_update(plane, plane_state)) {
|
||||
intel_crtc->atomic.update_wm_pre = true;
|
||||
pipe_config->wm_changed = true;
|
||||
}
|
||||
|
||||
if (visible || was_visible)
|
||||
|
@ -11929,7 +12004,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
if (mode_changed && !crtc_state->active)
|
||||
intel_crtc->atomic.update_wm_post = true;
|
||||
pipe_config->wm_changed = true;
|
||||
|
||||
if (mode_changed && crtc_state->enable &&
|
||||
dev_priv->display.crtc_compute_clock &&
|
||||
|
@ -12020,7 +12095,7 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,
|
|||
struct drm_connector_state *connector_state;
|
||||
int bpp, i;
|
||||
|
||||
if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)))
|
||||
if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)))
|
||||
bpp = 10*3;
|
||||
else if (INTEL_INFO(dev)->gen >= 5)
|
||||
bpp = 12*3;
|
||||
|
@ -12630,7 +12705,7 @@ intel_pipe_config_compare(struct drm_device *dev,
|
|||
PIPE_CONF_CHECK_I(pixel_multiplier);
|
||||
PIPE_CONF_CHECK_I(has_hdmi_sink);
|
||||
if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) ||
|
||||
IS_VALLEYVIEW(dev))
|
||||
IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
PIPE_CONF_CHECK_I(limited_color_range);
|
||||
PIPE_CONF_CHECK_I(has_infoframe);
|
||||
|
||||
|
@ -13416,6 +13491,9 @@ static int intel_atomic_commit(struct drm_device *dev,
|
|||
*/
|
||||
intel_check_cpu_fifo_underruns(dev_priv);
|
||||
intel_check_pch_fifo_underruns(dev_priv);
|
||||
|
||||
if (!crtc->state->active)
|
||||
intel_update_watermarks(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13851,9 +13929,6 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
|
|||
to_intel_crtc_state(old_crtc_state);
|
||||
bool modeset = needs_modeset(crtc->state);
|
||||
|
||||
if (intel_crtc->atomic.update_wm_pre)
|
||||
intel_update_watermarks(crtc);
|
||||
|
||||
/* Perform vblank evasion around commit operation */
|
||||
intel_pipe_update_start(intel_crtc);
|
||||
|
||||
|
@ -14040,9 +14115,6 @@ intel_commit_cursor_plane(struct drm_plane *plane,
|
|||
crtc = crtc ? crtc : plane->crtc;
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
if (intel_crtc->cursor_bo == obj)
|
||||
goto update;
|
||||
|
||||
if (!obj)
|
||||
addr = 0;
|
||||
else if (!INTEL_INFO(dev)->cursor_needs_physical)
|
||||
|
@ -14051,9 +14123,7 @@ intel_commit_cursor_plane(struct drm_plane *plane,
|
|||
addr = obj->phys_handle->busaddr;
|
||||
|
||||
intel_crtc->cursor_addr = addr;
|
||||
intel_crtc->cursor_bo = obj;
|
||||
|
||||
update:
|
||||
intel_crtc_update_cursor(crtc, state->visible);
|
||||
}
|
||||
|
||||
|
@ -14382,7 +14452,7 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|||
|
||||
if (I915_READ(PCH_DP_D) & DP_DETECTED)
|
||||
intel_dp_init(dev, PCH_DP_D, PORT_D);
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
/*
|
||||
* The DP_DETECTED bit is the latched state of the DDC
|
||||
* SDA pin at boot. However since eDP doesn't require DDC
|
||||
|
@ -14531,7 +14601,7 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
|
|||
* pixels and 32K bytes."
|
||||
*/
|
||||
return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768);
|
||||
} else if (gen >= 5 && !IS_VALLEYVIEW(dev)) {
|
||||
} else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
|
||||
return 32*1024;
|
||||
} else if (gen >= 4) {
|
||||
if (fb_modifier == I915_FORMAT_MOD_X_TILED)
|
||||
|
@ -14635,7 +14705,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|||
}
|
||||
break;
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
if (!IS_VALLEYVIEW(dev) && INTEL_INFO(dev)->gen < 9) {
|
||||
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
|
||||
INTEL_INFO(dev)->gen < 9) {
|
||||
DRM_DEBUG("unsupported pixel format: %s\n",
|
||||
drm_get_format_name(mode_cmd->pixel_format));
|
||||
return -EINVAL;
|
||||
|
@ -14651,7 +14722,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|||
}
|
||||
break;
|
||||
case DRM_FORMAT_ABGR2101010:
|
||||
if (!IS_VALLEYVIEW(dev)) {
|
||||
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
|
||||
DRM_DEBUG("unsupported pixel format: %s\n",
|
||||
drm_get_format_name(mode_cmd->pixel_format));
|
||||
return -EINVAL;
|
||||
|
@ -14779,7 +14850,7 @@ static void intel_init_display(struct drm_device *dev)
|
|||
dev_priv->display.crtc_disable = ironlake_crtc_disable;
|
||||
dev_priv->display.update_primary_plane =
|
||||
ironlake_update_primary_plane;
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
|
||||
dev_priv->display.get_initial_plane_config =
|
||||
i9xx_get_initial_plane_config;
|
||||
|
@ -14812,7 +14883,7 @@ static void intel_init_display(struct drm_device *dev)
|
|||
else if (IS_HASWELL(dev))
|
||||
dev_priv->display.get_display_clock_speed =
|
||||
haswell_get_display_clock_speed;
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
dev_priv->display.get_display_clock_speed =
|
||||
valleyview_get_display_clock_speed;
|
||||
else if (IS_GEN5(dev))
|
||||
|
@ -14870,7 +14941,7 @@ static void intel_init_display(struct drm_device *dev)
|
|||
dev_priv->display.modeset_calc_cdclk =
|
||||
broadwell_modeset_calc_cdclk;
|
||||
}
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
dev_priv->display.modeset_commit_cdclk =
|
||||
valleyview_modeset_commit_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk =
|
||||
|
@ -15644,7 +15715,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
|
|||
pll->on = false;
|
||||
}
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_wm_get_hw_state(dev);
|
||||
else if (IS_GEN9(dev))
|
||||
skl_wm_get_hw_state(dev);
|
||||
|
@ -15767,7 +15838,7 @@ void intel_connector_unregister(struct intel_connector *intel_connector)
|
|||
void intel_modeset_cleanup(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct intel_connector *connector;
|
||||
|
||||
intel_disable_gt_powersave(dev);
|
||||
|
||||
|
@ -15794,12 +15865,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
|
|||
flush_scheduled_work();
|
||||
|
||||
/* destroy the backlight and sysfs files before encoders/connectors */
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct intel_connector *intel_connector;
|
||||
|
||||
intel_connector = to_intel_connector(connector);
|
||||
intel_connector->unregister(intel_connector);
|
||||
}
|
||||
for_each_intel_connector(dev, connector)
|
||||
connector->unregister(connector);
|
||||
|
||||
drm_mode_config_cleanup(dev);
|
||||
|
||||
|
|
|
@ -389,8 +389,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
|
|||
* We don't have power sequencer currently.
|
||||
* Pick one that's not used by other ports.
|
||||
*/
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
||||
base.head) {
|
||||
for_each_intel_encoder(dev, encoder) {
|
||||
struct intel_dp *tmp;
|
||||
|
||||
if (encoder->type != INTEL_OUTPUT_EDP)
|
||||
|
@ -517,7 +516,7 @@ void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
if (WARN_ON(!IS_VALLEYVIEW(dev)))
|
||||
if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -530,7 +529,7 @@ void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
|
|||
* should use them always.
|
||||
*/
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
|
||||
for_each_intel_encoder(dev, encoder) {
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
if (encoder->type != INTEL_OUTPUT_EDP)
|
||||
|
@ -582,7 +581,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
|
|||
|
||||
pps_lock(intel_dp);
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
|
||||
i915_reg_t pp_ctrl_reg, pp_div_reg;
|
||||
u32 pp_div;
|
||||
|
@ -610,7 +609,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
|
|||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (IS_VALLEYVIEW(dev) &&
|
||||
if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
|
||||
intel_dp->pps_pipe == INVALID_PIPE)
|
||||
return false;
|
||||
|
||||
|
@ -624,7 +623,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
|
|||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (IS_VALLEYVIEW(dev) &&
|
||||
if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
|
||||
intel_dp->pps_pipe == INVALID_PIPE)
|
||||
return false;
|
||||
|
||||
|
@ -915,6 +914,27 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
|
|||
/* Unload any bytes sent back from the other side */
|
||||
recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
|
||||
DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
|
||||
|
||||
/*
|
||||
* By BSpec: "Message sizes of 0 or >20 are not allowed."
|
||||
* We have no idea of what happened so we return -EBUSY so
|
||||
* drm layer takes care for the necessary retries.
|
||||
*/
|
||||
if (recv_bytes == 0 || recv_bytes > 20) {
|
||||
DRM_DEBUG_KMS("Forbidden recv_bytes = %d on aux transaction\n",
|
||||
recv_bytes);
|
||||
/*
|
||||
* FIXME: This patch was created on top of a series that
|
||||
* organize the retries at drm level. There EBUSY should
|
||||
* also take care for 1ms wait before retrying.
|
||||
* That aux retries re-org is still needed and after that is
|
||||
* merged we remove this sleep from here.
|
||||
*/
|
||||
usleep_range(1000, 1500);
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (recv_bytes > recv_size)
|
||||
recv_bytes = recv_size;
|
||||
|
||||
|
@ -1723,7 +1743,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
|
|||
I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp);
|
||||
} else {
|
||||
if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) &&
|
||||
crtc->config->limited_color_range)
|
||||
!IS_CHERRYVIEW(dev) && crtc->config->limited_color_range)
|
||||
intel_dp->DP |= DP_COLOR_RANGE_16_235;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
|
@ -2418,7 +2438,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
|
|||
pipe_config->base.adjusted_mode.flags |= flags;
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) &&
|
||||
tmp & DP_COLOR_RANGE_16_235)
|
||||
!IS_CHERRYVIEW(dev) && tmp & DP_COLOR_RANGE_16_235)
|
||||
pipe_config->limited_color_range = true;
|
||||
|
||||
pipe_config->has_dp_encoder = true;
|
||||
|
@ -2694,7 +2714,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
|
|||
|
||||
pps_lock(intel_dp);
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_init_panel_power_sequencer(intel_dp);
|
||||
|
||||
/*
|
||||
|
@ -2728,7 +2748,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
|
|||
|
||||
pps_unlock(intel_dp);
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
unsigned int lane_mask = 0x0;
|
||||
|
||||
if (IS_CHERRYVIEW(dev))
|
||||
|
@ -2829,8 +2849,7 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
|
|||
if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
|
||||
return;
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
||||
base.head) {
|
||||
for_each_intel_encoder(dev, encoder) {
|
||||
struct intel_dp *intel_dp;
|
||||
enum port port;
|
||||
|
||||
|
@ -3218,7 +3237,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
|
|||
if (dev_priv->edp_low_vswing && port == PORT_A)
|
||||
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
|
||||
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
|
||||
} else if (IS_VALLEYVIEW(dev))
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
|
||||
else if (IS_GEN7(dev) && port == PORT_A)
|
||||
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
|
||||
|
@ -3259,7 +3278,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
|
|||
default:
|
||||
return DP_TRAIN_PRE_EMPH_LEVEL_0;
|
||||
}
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
|
||||
return DP_TRAIN_PRE_EMPH_LEVEL_3;
|
||||
|
@ -4539,7 +4558,7 @@ bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
|
|||
return cpt_digital_port_connected(dev_priv, port);
|
||||
else if (IS_BROXTON(dev_priv))
|
||||
return bxt_digital_port_connected(dev_priv, port);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
return vlv_digital_port_connected(dev_priv, port);
|
||||
else
|
||||
return g4x_digital_port_connected(dev_priv, port);
|
||||
|
@ -4933,7 +4952,7 @@ static void intel_dp_encoder_reset(struct drm_encoder *encoder)
|
|||
* Read out the current power sequencer assignment,
|
||||
* in case the BIOS did something with it.
|
||||
*/
|
||||
if (IS_VALLEYVIEW(encoder->dev))
|
||||
if (IS_VALLEYVIEW(encoder->dev) || IS_CHERRYVIEW(encoder->dev))
|
||||
vlv_initial_power_sequencer_setup(intel_dp);
|
||||
|
||||
intel_edp_panel_vdd_sanitize(intel_dp);
|
||||
|
@ -5293,7 +5312,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
|
|||
|
||||
/* Haswell doesn't have any port selection bits for the panel
|
||||
* power sequencer any more. */
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
port_sel = PANEL_PORT_SELECT_VLV(port);
|
||||
} else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
|
||||
if (port == PORT_A)
|
||||
|
@ -5405,12 +5424,12 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
|
|||
|
||||
val = I915_READ(reg);
|
||||
if (index > DRRS_HIGH_RR) {
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
|
||||
else
|
||||
val |= PIPECONF_EDP_RR_MODE_SWITCH;
|
||||
} else {
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
|
||||
else
|
||||
val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
|
||||
|
@ -5777,7 +5796,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
|||
}
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
intel_dp->edp_notifier.notifier_call = edp_notify_handler;
|
||||
register_reboot_notifier(&intel_dp->edp_notifier);
|
||||
|
||||
|
@ -5825,7 +5844,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
/* intel_dp vfuncs */
|
||||
if (INTEL_INFO(dev)->gen >= 9)
|
||||
intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
|
||||
else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
|
||||
intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
|
||||
|
@ -5860,8 +5879,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
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))
|
||||
if (WARN_ON((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
|
||||
is_edp(intel_dp) && port != PORT_B && port != PORT_C))
|
||||
return false;
|
||||
|
||||
DRM_DEBUG_KMS("Adding %s connector on port %c\n",
|
||||
|
@ -5912,7 +5931,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
if (is_edp(intel_dp)) {
|
||||
pps_lock(intel_dp);
|
||||
intel_dp_init_panel_power_timestamps(intel_dp);
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_initial_power_sequencer_setup(intel_dp);
|
||||
else
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp);
|
||||
|
@ -5988,8 +6007,9 @@ intel_dp_init(struct drm_device *dev,
|
|||
intel_encoder = &intel_dig_port->base;
|
||||
encoder = &intel_encoder->base;
|
||||
|
||||
drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
if (drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL))
|
||||
goto err_encoder_init;
|
||||
|
||||
intel_encoder->compute_config = intel_dp_compute_config;
|
||||
intel_encoder->disable = intel_disable_dp;
|
||||
|
@ -6015,6 +6035,7 @@ intel_dp_init(struct drm_device *dev,
|
|||
}
|
||||
|
||||
intel_dig_port->port = port;
|
||||
dev_priv->dig_port_map[port] = intel_encoder;
|
||||
intel_dig_port->dp.output_reg = output_reg;
|
||||
|
||||
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
|
||||
|
@ -6038,6 +6059,7 @@ intel_dp_init(struct drm_device *dev,
|
|||
|
||||
err_init_connector:
|
||||
drm_encoder_cleanup(encoder);
|
||||
err_encoder_init:
|
||||
kfree(intel_connector);
|
||||
err_connector_alloc:
|
||||
kfree(intel_dig_port);
|
||||
|
|
|
@ -78,6 +78,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, found->port))
|
||||
pipe_config->has_audio = true;
|
||||
mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp);
|
||||
|
||||
pipe_config->pbn = mst_pbn;
|
||||
|
@ -102,6 +104,11 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
|
|||
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
|
||||
struct intel_digital_port *intel_dig_port = intel_mst->primary;
|
||||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_crtc *crtc = encoder->base.crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
|
||||
|
@ -112,6 +119,10 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
|
|||
if (ret) {
|
||||
DRM_ERROR("failed to update payload %d\n", ret);
|
||||
}
|
||||
if (intel_crtc->config->has_audio) {
|
||||
intel_audio_codec_disable(encoder);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
|
||||
|
@ -208,6 +219,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
|
|||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||
struct drm_device *dev = intel_dig_port->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
|
||||
enum port port = intel_dig_port->port;
|
||||
int ret;
|
||||
|
||||
|
@ -220,6 +232,13 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder)
|
|||
ret = drm_dp_check_act_status(&intel_dp->mst_mgr);
|
||||
|
||||
ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr);
|
||||
|
||||
if (crtc->config->has_audio) {
|
||||
DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
|
||||
pipe_name(crtc->pipe));
|
||||
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
|
||||
intel_audio_codec_enable(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
|
||||
|
@ -245,6 +264,9 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder,
|
|||
|
||||
pipe_config->has_dp_encoder = true;
|
||||
|
||||
pipe_config->has_audio =
|
||||
intel_ddi_is_audio_enabled(dev_priv, crtc);
|
||||
|
||||
temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
|
||||
if (temp & TRANS_DDI_PHSYNC)
|
||||
flags |= DRM_MODE_FLAG_PHSYNC;
|
||||
|
|
|
@ -365,7 +365,9 @@ struct intel_crtc_state {
|
|||
#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */
|
||||
unsigned long quirks;
|
||||
|
||||
bool update_pipe;
|
||||
bool update_pipe; /* can a fast modeset be performed? */
|
||||
bool disable_cxsr;
|
||||
bool wm_changed; /* watermarks are updated */
|
||||
|
||||
/* Pipe source size (ie. panel fitter input size)
|
||||
* All planes will be positioned inside this space,
|
||||
|
@ -531,9 +533,7 @@ struct intel_crtc_atomic_commit {
|
|||
/* Sleepable operations to perform before commit */
|
||||
bool disable_fbc;
|
||||
bool disable_ips;
|
||||
bool disable_cxsr;
|
||||
bool pre_disable_primary;
|
||||
bool update_wm_pre, update_wm_post;
|
||||
|
||||
/* Sleepable operations to perform after commit */
|
||||
unsigned fb_bits;
|
||||
|
@ -568,7 +568,6 @@ struct intel_crtc {
|
|||
int adjusted_x;
|
||||
int adjusted_y;
|
||||
|
||||
struct drm_i915_gem_object *cursor_bo;
|
||||
uint32_t cursor_addr;
|
||||
uint32_t cursor_cntl;
|
||||
uint32_t cursor_size;
|
||||
|
@ -818,6 +817,8 @@ struct intel_digital_port {
|
|||
struct intel_hdmi hdmi;
|
||||
enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
|
||||
bool release_cl2_override;
|
||||
/* for communication with audio component; protected by av_mutex */
|
||||
const struct drm_connector *audio_connector;
|
||||
};
|
||||
|
||||
struct intel_dp_mst_encoder {
|
||||
|
@ -1012,6 +1013,8 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
|
|||
void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp);
|
||||
bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
|
||||
void intel_ddi_fdi_disable(struct drm_crtc *crtc);
|
||||
bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
|
||||
struct intel_crtc *intel_crtc);
|
||||
void intel_ddi_get_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config);
|
||||
struct intel_encoder *
|
||||
|
@ -1427,6 +1430,87 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
|
|||
enum intel_display_power_domain domain);
|
||||
void intel_display_power_put(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain);
|
||||
|
||||
static inline void
|
||||
assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
WARN_ONCE(dev_priv->pm.suspended,
|
||||
"Device suspended during HW access\n");
|
||||
}
|
||||
|
||||
static inline void
|
||||
assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
assert_rpm_device_not_suspended(dev_priv);
|
||||
WARN_ONCE(!atomic_read(&dev_priv->pm.wakeref_count),
|
||||
"RPM wakelock ref not held during HW access");
|
||||
}
|
||||
|
||||
static inline int
|
||||
assert_rpm_atomic_begin(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
int seq = atomic_read(&dev_priv->pm.atomic_seq);
|
||||
|
||||
assert_rpm_wakelock_held(dev_priv);
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
static inline void
|
||||
assert_rpm_atomic_end(struct drm_i915_private *dev_priv, int begin_seq)
|
||||
{
|
||||
WARN_ONCE(atomic_read(&dev_priv->pm.atomic_seq) != begin_seq,
|
||||
"HW access outside of RPM atomic section\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* disable_rpm_wakeref_asserts - disable the RPM assert checks
|
||||
* @dev_priv: i915 device instance
|
||||
*
|
||||
* This function disable asserts that check if we hold an RPM wakelock
|
||||
* reference, while keeping the device-not-suspended checks still enabled.
|
||||
* It's meant to be used only in special circumstances where our rule about
|
||||
* the wakelock refcount wrt. the device power state doesn't hold. According
|
||||
* to this rule at any point where we access the HW or want to keep the HW in
|
||||
* an active state we must hold an RPM wakelock reference acquired via one of
|
||||
* the intel_runtime_pm_get() helpers. Currently there are a few special spots
|
||||
* where this rule doesn't hold: the IRQ and suspend/resume handlers, the
|
||||
* forcewake release timer, and the GPU RPS and hangcheck works. All other
|
||||
* users should avoid using this function.
|
||||
*
|
||||
* Any calls to this function must have a symmetric call to
|
||||
* enable_rpm_wakeref_asserts().
|
||||
*/
|
||||
static inline void
|
||||
disable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
atomic_inc(&dev_priv->pm.wakeref_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* enable_rpm_wakeref_asserts - re-enable the RPM assert checks
|
||||
* @dev_priv: i915 device instance
|
||||
*
|
||||
* This function re-enables the RPM assert checks after disabling them with
|
||||
* disable_rpm_wakeref_asserts. It's meant to be used only in special
|
||||
* circumstances otherwise its use should be avoided.
|
||||
*
|
||||
* Any calls to this function must have a symmetric call to
|
||||
* disable_rpm_wakeref_asserts().
|
||||
*/
|
||||
static inline void
|
||||
enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
atomic_dec(&dev_priv->pm.wakeref_count);
|
||||
}
|
||||
|
||||
/* TODO: convert users of these to rely instead on proper RPM refcounting */
|
||||
#define DISABLE_RPM_WAKEREF_ASSERTS(dev_priv) \
|
||||
disable_rpm_wakeref_asserts(dev_priv)
|
||||
|
||||
#define ENABLE_RPM_WAKEREF_ASSERTS(dev_priv) \
|
||||
enable_rpm_wakeref_asserts(dev_priv)
|
||||
|
||||
void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
|
||||
void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
|
||||
void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
|
||||
|
|
|
@ -369,7 +369,7 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder)
|
|||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_dsi_device_ready(encoder);
|
||||
else if (IS_BROXTON(dev))
|
||||
bxt_dsi_device_ready(encoder);
|
||||
|
@ -487,7 +487,7 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder)
|
|||
|
||||
msleep(intel_dsi->panel_on_delay);
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
/*
|
||||
* Disable DPOunit clock gating, can stall pipe
|
||||
* and we need DPLL REFA always enabled
|
||||
|
@ -684,8 +684,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
|
|||
* Enable bit does not get set. To check whether DSI Port C
|
||||
* was enabled in BIOS, check the Pipe B enable bit
|
||||
*/
|
||||
if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
|
||||
(port == PORT_C))
|
||||
if (IS_VALLEYVIEW(dev) && port == PORT_C)
|
||||
dpi_enabled = I915_READ(PIPECONF(PIPE_B)) &
|
||||
PIPECONF_ENABLE;
|
||||
|
||||
|
@ -716,7 +715,8 @@ static void intel_dsi_get_config(struct intel_encoder *encoder,
|
|||
|
||||
if (IS_BROXTON(encoder->base.dev))
|
||||
pclk = bxt_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
|
||||
else if (IS_VALLEYVIEW(encoder->base.dev))
|
||||
else if (IS_VALLEYVIEW(encoder->base.dev) ||
|
||||
IS_CHERRYVIEW(encoder->base.dev))
|
||||
pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
|
||||
|
||||
if (!pclk)
|
||||
|
@ -869,7 +869,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
|
|||
}
|
||||
|
||||
for_each_dsi_port(port, intel_dsi->ports) {
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
/*
|
||||
* escape clock divider, 20MHz, shared for A and C.
|
||||
* device ready must be off when doing this! txclkesc?
|
||||
|
@ -885,21 +885,12 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
|
|||
I915_WRITE(MIPI_CTRL(port), tmp |
|
||||
READ_REQUEST_PRIORITY_HIGH);
|
||||
} else if (IS_BROXTON(dev)) {
|
||||
/*
|
||||
* FIXME:
|
||||
* BXT can connect any PIPE to any MIPI port.
|
||||
* Select the pipe based on the MIPI port read from
|
||||
* VBT for now. Pick PIPE A for MIPI port A and C
|
||||
* for port C.
|
||||
*/
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
|
||||
tmp = I915_READ(MIPI_CTRL(port));
|
||||
tmp &= ~BXT_PIPE_SELECT_MASK;
|
||||
|
||||
if (port == PORT_A)
|
||||
tmp |= BXT_PIPE_SELECT_A;
|
||||
else if (port == PORT_C)
|
||||
tmp |= BXT_PIPE_SELECT_C;
|
||||
|
||||
tmp |= BXT_PIPE_SELECT(pipe);
|
||||
I915_WRITE(MIPI_CTRL(port), tmp);
|
||||
}
|
||||
|
||||
|
@ -1129,7 +1120,7 @@ void intel_dsi_init(struct drm_device *dev)
|
|||
if (!dev_priv->vbt.has_mipi)
|
||||
return;
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
|
||||
} else {
|
||||
DRM_ERROR("Unsupported Mipi device to reg base");
|
||||
|
|
|
@ -561,7 +561,7 @@ void intel_enable_dsi_pll(struct intel_encoder *encoder)
|
|||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_enable_dsi_pll(encoder);
|
||||
else if (IS_BROXTON(dev))
|
||||
bxt_enable_dsi_pll(encoder);
|
||||
|
@ -571,7 +571,7 @@ void intel_disable_dsi_pll(struct intel_encoder *encoder)
|
|||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_disable_dsi_pll(encoder);
|
||||
else if (IS_BROXTON(dev))
|
||||
bxt_disable_dsi_pll(encoder);
|
||||
|
@ -599,6 +599,6 @@ void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
|
|||
|
||||
if (IS_BROXTON(dev))
|
||||
bxt_dsi_reset_clocks(encoder, port);
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_dsi_reset_clocks(encoder, port);
|
||||
}
|
||||
|
|
|
@ -163,13 +163,6 @@ 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(NULL, fb, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to pin obj: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
ifbdev->fb = to_intel_framebuffer(fb);
|
||||
|
@ -225,6 +218,14 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
|||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
/* Pin the GGTT vma for our access via info->screen_base.
|
||||
* This also validates that any existing fb inherited from the
|
||||
* BIOS is suitable for own access.
|
||||
*/
|
||||
ret = intel_pin_and_fence_fb_obj(NULL, &ifbdev->fb->base, NULL);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
DRM_ERROR("Failed to allocate fb_info\n");
|
||||
|
@ -287,6 +288,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
|||
drm_fb_helper_release_fbi(helper);
|
||||
out_unpin:
|
||||
i915_gem_object_ggtt_unpin(obj);
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
@ -524,6 +526,10 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
|
|||
static void intel_fbdev_destroy(struct drm_device *dev,
|
||||
struct intel_fbdev *ifbdev)
|
||||
{
|
||||
/* We rely on the object-free to release the VMA pinning for
|
||||
* the info->screen_base mmaping. Leaking the VMA is simpler than
|
||||
* trying to rectify all the possible error paths leading here.
|
||||
*/
|
||||
|
||||
drm_fb_helper_unregister_fbi(&ifbdev->helper);
|
||||
drm_fb_helper_release_fbi(&ifbdev->helper);
|
||||
|
|
|
@ -78,7 +78,7 @@ static u32 g4x_infoframe_index(enum hdmi_infoframe_type type)
|
|||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
return VIDEO_DIP_SELECT_VENDOR;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
|
||||
MISSING_CASE(type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type)
|
|||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
return VIDEO_DIP_ENABLE_VENDOR;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
|
||||
MISSING_CASE(type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
|
|||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
return VIDEO_DIP_ENABLE_VS_HSW;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
|
||||
MISSING_CASE(type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ hsw_dip_data_reg(struct drm_i915_private *dev_priv,
|
|||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i);
|
||||
default:
|
||||
DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
|
||||
MISSING_CASE(type);
|
||||
return INVALID_MMIO_REG;
|
||||
}
|
||||
}
|
||||
|
@ -375,8 +375,6 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
|
|||
u32 val = I915_READ(ctl_reg);
|
||||
|
||||
data_reg = hsw_dip_data_reg(dev_priv, cpu_transcoder, type, 0);
|
||||
if (i915_mmio_reg_valid(data_reg))
|
||||
return;
|
||||
|
||||
val &= ~hsw_infoframe_enable(type);
|
||||
I915_WRITE(ctl_reg, val);
|
||||
|
@ -638,7 +636,7 @@ static bool intel_hdmi_set_gcp_infoframe(struct drm_encoder *encoder)
|
|||
|
||||
if (HAS_DDI(dev_priv))
|
||||
reg = HSW_TVIDEO_DIP_GCP(crtc->config->cpu_transcoder);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
reg = VLV_TVIDEO_DIP_GCP(crtc->pipe);
|
||||
else if (HAS_PCH_SPLIT(dev_priv->dev))
|
||||
reg = TVIDEO_DIP_GCP(crtc->pipe);
|
||||
|
@ -1397,7 +1395,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
|
|||
while (!live_status && --retry) {
|
||||
live_status = intel_digital_port_connected(dev_priv,
|
||||
hdmi_to_dig_port(intel_hdmi));
|
||||
mdelay(10);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
if (!live_status)
|
||||
|
@ -2100,7 +2098,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
BUG();
|
||||
}
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
intel_hdmi->write_infoframe = vlv_write_infoframe;
|
||||
intel_hdmi->set_infoframes = vlv_set_infoframes;
|
||||
intel_hdmi->infoframe_enabled = vlv_infoframe_enabled;
|
||||
|
@ -2147,6 +2145,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
void intel_hdmi_init(struct drm_device *dev,
|
||||
i915_reg_t hdmi_reg, enum port port)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_digital_port *intel_dig_port;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_connector *intel_connector;
|
||||
|
@ -2215,6 +2214,7 @@ void intel_hdmi_init(struct drm_device *dev,
|
|||
intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
|
||||
|
||||
intel_dig_port->port = port;
|
||||
dev_priv->dig_port_map[port] = intel_encoder;
|
||||
intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
|
||||
intel_dig_port->dp.output_reg = INVALID_MMIO_REG;
|
||||
|
||||
|
|
|
@ -407,7 +407,7 @@ void intel_hpd_irq_handler(struct drm_device *dev,
|
|||
* hotplug bits itself. So only WARN about unexpected
|
||||
* interrupts on saner platforms.
|
||||
*/
|
||||
WARN_ONCE(INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev),
|
||||
WARN_ONCE(!HAS_GMCH_DISPLAY(dev),
|
||||
"Received HPD interrupt on pin %d although disabled\n", i);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -636,7 +636,7 @@ int intel_setup_gmbus(struct drm_device *dev)
|
|||
if (HAS_PCH_NOP(dev))
|
||||
return 0;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE;
|
||||
else if (!HAS_GMCH_DISPLAY(dev_priv))
|
||||
dev_priv->gpio_mmio_base =
|
||||
|
|
|
@ -372,7 +372,7 @@ static int execlists_update_context(struct drm_i915_gem_request *rq)
|
|||
WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
|
||||
WARN_ON(!i915_gem_obj_is_pinned(rb_obj));
|
||||
|
||||
page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
|
||||
page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
|
||||
reg_state = kmap_atomic(page);
|
||||
|
||||
reg_state[CTX_RING_TAIL+1] = rq->tail;
|
||||
|
@ -1425,7 +1425,7 @@ static int intel_init_workaround_bb(struct intel_engine_cs *ring)
|
|||
return ret;
|
||||
}
|
||||
|
||||
page = i915_gem_object_get_page(wa_ctx->obj, 0);
|
||||
page = i915_gem_object_get_dirty_page(wa_ctx->obj, 0);
|
||||
batch = kmap_atomic(page);
|
||||
offset = 0;
|
||||
|
||||
|
@ -1894,8 +1894,10 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring)
|
|||
|
||||
dev_priv = ring->dev->dev_private;
|
||||
|
||||
intel_logical_ring_stop(ring);
|
||||
WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
|
||||
if (ring->buffer) {
|
||||
intel_logical_ring_stop(ring);
|
||||
WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
|
||||
}
|
||||
|
||||
if (ring->cleanup)
|
||||
ring->cleanup(ring);
|
||||
|
@ -1909,6 +1911,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring)
|
|||
}
|
||||
|
||||
lrc_destroy_wa_ctx_obj(ring);
|
||||
ring->dev = NULL;
|
||||
}
|
||||
|
||||
static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring)
|
||||
|
@ -1931,11 +1934,11 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin
|
|||
|
||||
ret = i915_cmd_parser_init_ring(ring);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto error;
|
||||
|
||||
ret = intel_lr_context_deferred_alloc(ring->default_context, ring);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto error;
|
||||
|
||||
/* As this is the default context, always pin it */
|
||||
ret = intel_lr_context_do_pin(
|
||||
|
@ -1946,9 +1949,13 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin
|
|||
DRM_ERROR(
|
||||
"Failed to pin and map ringbuffer %s: %d\n",
|
||||
ring->name, ret);
|
||||
return ret;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
intel_logical_ring_cleanup(ring);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2257,7 +2264,7 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
|
|||
|
||||
/* The second page of the context object contains some fields which must
|
||||
* be set up prior to the first execution. */
|
||||
page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
|
||||
page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
|
||||
reg_state = kmap_atomic(page);
|
||||
|
||||
/* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM
|
||||
|
@ -2343,9 +2350,6 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
|
|||
}
|
||||
|
||||
kunmap_atomic(reg_state);
|
||||
|
||||
ctx_obj->dirty = 1;
|
||||
set_page_dirty(page);
|
||||
i915_gem_object_unpin_pages(ctx_obj);
|
||||
|
||||
return 0;
|
||||
|
@ -2529,7 +2533,7 @@ void intel_lr_context_reset(struct drm_device *dev,
|
|||
WARN(1, "Failed get_pages for context obj\n");
|
||||
continue;
|
||||
}
|
||||
page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
|
||||
page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
|
||||
reg_state = kmap_atomic(page);
|
||||
|
||||
reg_state[CTX_RING_HEAD+1] = 0;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
|
@ -46,6 +47,7 @@
|
|||
#define OPREGION_SWSCI_OFFSET 0x200
|
||||
#define OPREGION_ASLE_OFFSET 0x300
|
||||
#define OPREGION_VBT_OFFSET 0x400
|
||||
#define OPREGION_ASLE_EXT_OFFSET 0x1C00
|
||||
|
||||
#define OPREGION_SIGNATURE "IntelGraphicsMem"
|
||||
#define MBOX_ACPI (1<<0)
|
||||
|
@ -120,7 +122,16 @@ struct opregion_asle {
|
|||
u64 fdss;
|
||||
u32 fdsp;
|
||||
u32 stat;
|
||||
u8 rsvd[70];
|
||||
u64 rvda; /* Physical address of raw vbt data */
|
||||
u32 rvds; /* Size of raw vbt data */
|
||||
u8 rsvd[58];
|
||||
} __packed;
|
||||
|
||||
/* OpRegion mailbox #5: ASLE ext */
|
||||
struct opregion_asle_ext {
|
||||
u32 phed; /* Panel Header */
|
||||
u8 bddc[256]; /* Panel EDID */
|
||||
u8 rsvd[764];
|
||||
} __packed;
|
||||
|
||||
/* Driver readiness indicator */
|
||||
|
@ -411,7 +422,7 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
|
|||
static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_connector *intel_connector;
|
||||
struct intel_connector *connector;
|
||||
struct opregion_asle *asle = dev_priv->opregion.asle;
|
||||
|
||||
DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
|
||||
|
@ -435,8 +446,8 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
|
|||
* only one).
|
||||
*/
|
||||
DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
|
||||
list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
|
||||
intel_panel_set_backlight_acpi(intel_connector, bclp, 255);
|
||||
for_each_intel_connector(dev, connector)
|
||||
intel_panel_set_backlight_acpi(connector, bclp, 255);
|
||||
asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID;
|
||||
|
||||
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
||||
|
@ -826,6 +837,10 @@ void intel_opregion_fini(struct drm_device *dev)
|
|||
|
||||
/* just clear all opregion memory pointers now */
|
||||
memunmap(opregion->header);
|
||||
if (opregion->rvda) {
|
||||
memunmap(opregion->rvda);
|
||||
opregion->rvda = NULL;
|
||||
}
|
||||
opregion->header = NULL;
|
||||
opregion->acpi = NULL;
|
||||
opregion->swsci = NULL;
|
||||
|
@ -894,6 +909,25 @@ static void swsci_setup(struct drm_device *dev)
|
|||
static inline void swsci_setup(struct drm_device *dev) {}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
DRM_DEBUG_KMS("Falling back to manually reading VBT from "
|
||||
"VBIOS ROM for %s\n", id->ident);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id intel_no_opregion_vbt[] = {
|
||||
{
|
||||
.callback = intel_no_opregion_vbt_callback,
|
||||
.ident = "ThinkCentre A57",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
int intel_opregion_setup(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
@ -907,6 +941,7 @@ int intel_opregion_setup(struct drm_device *dev)
|
|||
BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100);
|
||||
BUILD_BUG_ON(sizeof(struct opregion_swsci) != 0x100);
|
||||
BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100);
|
||||
BUILD_BUG_ON(sizeof(struct opregion_asle_ext) != 0x400);
|
||||
|
||||
pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
|
||||
DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
|
||||
|
@ -931,8 +966,6 @@ int intel_opregion_setup(struct drm_device *dev)
|
|||
goto err_out;
|
||||
}
|
||||
opregion->header = base;
|
||||
opregion->vbt = base + OPREGION_VBT_OFFSET;
|
||||
|
||||
opregion->lid_state = base + ACPI_CLID;
|
||||
|
||||
mboxes = opregion->header->mboxes;
|
||||
|
@ -946,6 +979,7 @@ int intel_opregion_setup(struct drm_device *dev)
|
|||
opregion->swsci = base + OPREGION_SWSCI_OFFSET;
|
||||
swsci_setup(dev);
|
||||
}
|
||||
|
||||
if (mboxes & MBOX_ASLE) {
|
||||
DRM_DEBUG_DRIVER("ASLE supported\n");
|
||||
opregion->asle = base + OPREGION_ASLE_OFFSET;
|
||||
|
@ -953,6 +987,37 @@ int intel_opregion_setup(struct drm_device *dev)
|
|||
opregion->asle->ardy = ASLE_ARDY_NOT_READY;
|
||||
}
|
||||
|
||||
if (mboxes & MBOX_ASLE_EXT)
|
||||
DRM_DEBUG_DRIVER("ASLE extension supported\n");
|
||||
|
||||
if (!dmi_check_system(intel_no_opregion_vbt)) {
|
||||
const void *vbt = NULL;
|
||||
u32 vbt_size = 0;
|
||||
|
||||
if (opregion->header->opregion_ver >= 2 && opregion->asle &&
|
||||
opregion->asle->rvda && opregion->asle->rvds) {
|
||||
opregion->rvda = memremap(opregion->asle->rvda,
|
||||
opregion->asle->rvds,
|
||||
MEMREMAP_WB);
|
||||
vbt = opregion->rvda;
|
||||
vbt_size = opregion->asle->rvds;
|
||||
}
|
||||
|
||||
if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
|
||||
DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (RVDA)\n");
|
||||
opregion->vbt = vbt;
|
||||
opregion->vbt_size = vbt_size;
|
||||
} else {
|
||||
vbt = base + OPREGION_VBT_OFFSET;
|
||||
vbt_size = OPREGION_ASLE_EXT_OFFSET - OPREGION_VBT_OFFSET;
|
||||
if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
|
||||
DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (Mailbox #4)\n");
|
||||
opregion->vbt = vbt;
|
||||
opregion->vbt_size = vbt_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
|
|
|
@ -461,8 +461,7 @@ static inline u32 scale_hw_to_user(struct intel_connector *connector,
|
|||
static u32 intel_panel_compute_brightness(struct intel_connector *connector,
|
||||
u32 val)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
|
||||
WARN_ON(panel->backlight.max == 0);
|
||||
|
@ -480,45 +479,40 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector,
|
|||
|
||||
static u32 lpt_get_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
|
||||
return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
}
|
||||
|
||||
static u32 pch_get_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
|
||||
return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
}
|
||||
|
||||
static u32 i9xx_get_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 val;
|
||||
|
||||
val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
if (INTEL_INFO(dev)->gen < 4)
|
||||
if (INTEL_INFO(dev_priv)->gen < 4)
|
||||
val >>= 1;
|
||||
|
||||
if (panel->backlight.combination_mode) {
|
||||
u8 lbpc;
|
||||
|
||||
pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
|
||||
pci_read_config_byte(dev_priv->dev->pdev, PCI_LBPC, &lbpc);
|
||||
val *= lbpc;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
|
||||
static u32 _vlv_get_backlight(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
|
||||
return 0;
|
||||
|
||||
|
@ -527,17 +521,16 @@ static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
|
|||
|
||||
static u32 vlv_get_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
enum pipe pipe = intel_get_pipe_from_connector(connector);
|
||||
|
||||
return _vlv_get_backlight(dev, pipe);
|
||||
return _vlv_get_backlight(dev_priv, pipe);
|
||||
}
|
||||
|
||||
static u32 bxt_get_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
return I915_READ(BXT_BLC_PWM_DUTY(panel->backlight.controller));
|
||||
}
|
||||
|
@ -553,8 +546,7 @@ static u32 pwm_get_backlight(struct intel_connector *connector)
|
|||
|
||||
static u32 intel_panel_get_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 val = 0;
|
||||
|
||||
|
@ -573,16 +565,14 @@ static u32 intel_panel_get_backlight(struct intel_connector *connector)
|
|||
|
||||
static void lpt_set_backlight(struct intel_connector *connector, u32 level)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
|
||||
}
|
||||
|
||||
static void pch_set_backlight(struct intel_connector *connector, u32 level)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
u32 tmp;
|
||||
|
||||
tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
|
@ -591,8 +581,7 @@ static void pch_set_backlight(struct intel_connector *connector, u32 level)
|
|||
|
||||
static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 tmp, mask;
|
||||
|
||||
|
@ -603,10 +592,10 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
|
|||
|
||||
lbpc = level * 0xfe / panel->backlight.max + 1;
|
||||
level /= lbpc;
|
||||
pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
|
||||
pci_write_config_byte(dev_priv->dev->pdev, PCI_LBPC, lbpc);
|
||||
}
|
||||
|
||||
if (IS_GEN4(dev)) {
|
||||
if (IS_GEN4(dev_priv)) {
|
||||
mask = BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
} else {
|
||||
level <<= 1;
|
||||
|
@ -619,8 +608,7 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
|
|||
|
||||
static void vlv_set_backlight(struct intel_connector *connector, u32 level)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
enum pipe pipe = intel_get_pipe_from_connector(connector);
|
||||
u32 tmp;
|
||||
|
||||
|
@ -633,8 +621,7 @@ static void vlv_set_backlight(struct intel_connector *connector, u32 level)
|
|||
|
||||
static void bxt_set_backlight(struct intel_connector *connector, u32 level)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
|
||||
I915_WRITE(BXT_BLC_PWM_DUTY(panel->backlight.controller), level);
|
||||
|
@ -663,8 +650,7 @@ intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
|
|||
static void intel_panel_set_backlight(struct intel_connector *connector,
|
||||
u32 user_level, u32 user_max)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 hw_level;
|
||||
|
||||
|
@ -690,8 +676,7 @@ static void intel_panel_set_backlight(struct intel_connector *connector,
|
|||
void intel_panel_set_backlight_acpi(struct intel_connector *connector,
|
||||
u32 user_level, u32 user_max)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
enum pipe pipe = intel_get_pipe_from_connector(connector);
|
||||
u32 hw_level;
|
||||
|
@ -726,8 +711,7 @@ void intel_panel_set_backlight_acpi(struct intel_connector *connector,
|
|||
|
||||
static void lpt_disable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
u32 tmp;
|
||||
|
||||
intel_panel_actually_set_backlight(connector, 0);
|
||||
|
@ -752,8 +736,7 @@ static void lpt_disable_backlight(struct intel_connector *connector)
|
|||
|
||||
static void pch_disable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
u32 tmp;
|
||||
|
||||
intel_panel_actually_set_backlight(connector, 0);
|
||||
|
@ -772,8 +755,7 @@ static void i9xx_disable_backlight(struct intel_connector *connector)
|
|||
|
||||
static void i965_disable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
u32 tmp;
|
||||
|
||||
intel_panel_actually_set_backlight(connector, 0);
|
||||
|
@ -784,8 +766,7 @@ static void i965_disable_backlight(struct intel_connector *connector)
|
|||
|
||||
static void vlv_disable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
enum pipe pipe = intel_get_pipe_from_connector(connector);
|
||||
u32 tmp;
|
||||
|
||||
|
@ -800,8 +781,7 @@ static void vlv_disable_backlight(struct intel_connector *connector)
|
|||
|
||||
static void bxt_disable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 tmp, val;
|
||||
|
||||
|
@ -830,8 +810,7 @@ static void pwm_disable_backlight(struct intel_connector *connector)
|
|||
|
||||
void intel_panel_disable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
|
||||
if (!panel->backlight.present)
|
||||
|
@ -843,7 +822,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
|
|||
* backlight. This will leave the backlight on unnecessarily when
|
||||
* another client is not activated.
|
||||
*/
|
||||
if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
|
||||
if (dev_priv->dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
|
||||
DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
|
||||
return;
|
||||
}
|
||||
|
@ -860,8 +839,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
|
|||
|
||||
static void lpt_enable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 pch_ctl1, pch_ctl2;
|
||||
|
||||
|
@ -893,8 +871,7 @@ static void lpt_enable_backlight(struct intel_connector *connector)
|
|||
|
||||
static void pch_enable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
enum pipe pipe = intel_get_pipe_from_connector(connector);
|
||||
enum transcoder cpu_transcoder =
|
||||
|
@ -940,8 +917,7 @@ static void pch_enable_backlight(struct intel_connector *connector)
|
|||
|
||||
static void i9xx_enable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 ctl, freq;
|
||||
|
||||
|
@ -958,7 +934,7 @@ static void i9xx_enable_backlight(struct intel_connector *connector)
|
|||
ctl = freq << 17;
|
||||
if (panel->backlight.combination_mode)
|
||||
ctl |= BLM_LEGACY_MODE;
|
||||
if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
|
||||
if (IS_PINEVIEW(dev_priv) && panel->backlight.active_low_pwm)
|
||||
ctl |= BLM_POLARITY_PNV;
|
||||
|
||||
I915_WRITE(BLC_PWM_CTL, ctl);
|
||||
|
@ -972,14 +948,13 @@ static void i9xx_enable_backlight(struct intel_connector *connector)
|
|||
* 855gm only, but checking for gen2 is safe, as 855gm is the only gen2
|
||||
* that has backlight.
|
||||
*/
|
||||
if (IS_GEN2(dev))
|
||||
if (IS_GEN2(dev_priv))
|
||||
I915_WRITE(BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE);
|
||||
}
|
||||
|
||||
static void i965_enable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
enum pipe pipe = intel_get_pipe_from_connector(connector);
|
||||
u32 ctl, ctl2, freq;
|
||||
|
@ -1012,8 +987,7 @@ static void i965_enable_backlight(struct intel_connector *connector)
|
|||
|
||||
static void vlv_enable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
enum pipe pipe = intel_get_pipe_from_connector(connector);
|
||||
u32 ctl, ctl2;
|
||||
|
@ -1044,8 +1018,7 @@ static void vlv_enable_backlight(struct intel_connector *connector)
|
|||
|
||||
static void bxt_enable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
enum pipe pipe = intel_get_pipe_from_connector(connector);
|
||||
u32 pwm_ctl, val;
|
||||
|
@ -1102,8 +1075,7 @@ static void pwm_enable_backlight(struct intel_connector *connector)
|
|||
|
||||
void intel_panel_enable_backlight(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
enum pipe pipe = intel_get_pipe_from_connector(connector);
|
||||
|
||||
|
@ -1278,8 +1250,7 @@ static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
|
|||
*/
|
||||
static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
u32 mul, clock;
|
||||
|
||||
if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY)
|
||||
|
@ -1299,8 +1270,7 @@ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
|
|||
*/
|
||||
static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
u32 mul, clock;
|
||||
|
||||
if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY)
|
||||
|
@ -1393,8 +1363,7 @@ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
|
|||
|
||||
static u32 get_backlight_max_vbt(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz;
|
||||
u32 pwm;
|
||||
|
@ -1427,8 +1396,7 @@ static u32 get_backlight_max_vbt(struct intel_connector *connector)
|
|||
*/
|
||||
static u32 get_backlight_min_vbt(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
int min;
|
||||
|
||||
|
@ -1453,8 +1421,7 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector)
|
|||
|
||||
static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 pch_ctl1, pch_ctl2, val;
|
||||
|
||||
|
@ -1483,8 +1450,7 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus
|
|||
|
||||
static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
|
||||
|
||||
|
@ -1514,17 +1480,16 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus
|
|||
|
||||
static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 ctl, val;
|
||||
|
||||
ctl = I915_READ(BLC_PWM_CTL);
|
||||
|
||||
if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev))
|
||||
if (IS_GEN2(dev_priv) || IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
|
||||
panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
|
||||
|
||||
if (IS_PINEVIEW(dev))
|
||||
if (IS_PINEVIEW(dev_priv))
|
||||
panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
|
||||
|
||||
panel->backlight.max = ctl >> 17;
|
||||
|
@ -1552,8 +1517,7 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu
|
|||
|
||||
static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 ctl, ctl2, val;
|
||||
|
||||
|
@ -1586,8 +1550,7 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu
|
|||
|
||||
static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 ctl, ctl2, val;
|
||||
|
||||
|
@ -1608,7 +1571,7 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe
|
|||
|
||||
panel->backlight.min = get_backlight_min_vbt(connector);
|
||||
|
||||
val = _vlv_get_backlight(dev, pipe);
|
||||
val = _vlv_get_backlight(dev_priv, pipe);
|
||||
panel->backlight.level = intel_panel_compute_brightness(connector, val);
|
||||
|
||||
panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
|
||||
|
@ -1620,8 +1583,7 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe
|
|||
static int
|
||||
bxt_setup_backlight(struct intel_connector *connector, enum pipe unused)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_panel *panel = &connector->panel;
|
||||
u32 pwm_ctl, val;
|
||||
|
||||
|
@ -1699,8 +1661,7 @@ static int pwm_setup_backlight(struct intel_connector *connector,
|
|||
|
||||
int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_connector *intel_connector = to_intel_connector(connector);
|
||||
struct intel_panel *panel = &intel_connector->panel;
|
||||
int ret;
|
||||
|
@ -1755,36 +1716,35 @@ void intel_panel_destroy_backlight(struct drm_connector *connector)
|
|||
static void
|
||||
intel_panel_init_backlight_funcs(struct intel_panel *panel)
|
||||
{
|
||||
struct intel_connector *intel_connector =
|
||||
struct intel_connector *connector =
|
||||
container_of(panel, struct intel_connector, panel);
|
||||
struct drm_device *dev = intel_connector->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
|
||||
if (IS_BROXTON(dev)) {
|
||||
if (IS_BROXTON(dev_priv)) {
|
||||
panel->backlight.setup = bxt_setup_backlight;
|
||||
panel->backlight.enable = bxt_enable_backlight;
|
||||
panel->backlight.disable = bxt_disable_backlight;
|
||||
panel->backlight.set = bxt_set_backlight;
|
||||
panel->backlight.get = bxt_get_backlight;
|
||||
panel->backlight.hz_to_pwm = bxt_hz_to_pwm;
|
||||
} else if (HAS_PCH_LPT(dev) || HAS_PCH_SPT(dev)) {
|
||||
} else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_SPT(dev_priv)) {
|
||||
panel->backlight.setup = lpt_setup_backlight;
|
||||
panel->backlight.enable = lpt_enable_backlight;
|
||||
panel->backlight.disable = lpt_disable_backlight;
|
||||
panel->backlight.set = lpt_set_backlight;
|
||||
panel->backlight.get = lpt_get_backlight;
|
||||
if (HAS_PCH_LPT(dev))
|
||||
if (HAS_PCH_LPT(dev_priv))
|
||||
panel->backlight.hz_to_pwm = lpt_hz_to_pwm;
|
||||
else
|
||||
panel->backlight.hz_to_pwm = spt_hz_to_pwm;
|
||||
} else if (HAS_PCH_SPLIT(dev)) {
|
||||
} else if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
panel->backlight.setup = pch_setup_backlight;
|
||||
panel->backlight.enable = pch_enable_backlight;
|
||||
panel->backlight.disable = pch_disable_backlight;
|
||||
panel->backlight.set = pch_set_backlight;
|
||||
panel->backlight.get = pch_get_backlight;
|
||||
panel->backlight.hz_to_pwm = pch_hz_to_pwm;
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
if (dev_priv->vbt.has_mipi) {
|
||||
panel->backlight.setup = pwm_setup_backlight;
|
||||
panel->backlight.enable = pwm_enable_backlight;
|
||||
|
@ -1799,7 +1759,7 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
|
|||
panel->backlight.get = vlv_get_backlight;
|
||||
panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
|
||||
}
|
||||
} else if (IS_GEN4(dev)) {
|
||||
} else if (IS_GEN4(dev_priv)) {
|
||||
panel->backlight.setup = i965_setup_backlight;
|
||||
panel->backlight.enable = i965_enable_backlight;
|
||||
panel->backlight.disable = i965_disable_backlight;
|
||||
|
@ -1845,7 +1805,7 @@ void intel_backlight_register(struct drm_device *dev)
|
|||
{
|
||||
struct intel_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, base.head)
|
||||
for_each_intel_connector(dev, connector)
|
||||
intel_backlight_device_register(connector);
|
||||
}
|
||||
|
||||
|
@ -1853,6 +1813,6 @@ void intel_backlight_unregister(struct drm_device *dev)
|
|||
{
|
||||
struct intel_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, base.head)
|
||||
for_each_intel_connector(dev, connector)
|
||||
intel_backlight_device_unregister(connector);
|
||||
}
|
||||
|
|
|
@ -291,7 +291,7 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
u32 val;
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0);
|
||||
POSTING_READ(FW_BLC_SELF_VLV);
|
||||
dev_priv->wm.vlv.cxsr = enable;
|
||||
|
@ -3314,7 +3314,7 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv,
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
|
||||
for_each_intel_crtc(dev, crtc) {
|
||||
int i, level, max_level = ilk_wm_max_level(dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
|
@ -3523,8 +3523,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
|
|||
* Otherwise, because of this_crtc being freshly enabled/disabled, the
|
||||
* other active pipes need new DDB allocation and WM values.
|
||||
*/
|
||||
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
|
||||
base.head) {
|
||||
for_each_intel_crtc(dev, intel_crtc) {
|
||||
struct skl_pipe_wm pipe_wm = {};
|
||||
bool wm_changed;
|
||||
|
||||
|
@ -4405,7 +4404,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
|
|||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
if (dev_priv->rps.enabled) {
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_set_rps_idle(dev_priv);
|
||||
else
|
||||
gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
|
||||
|
@ -4458,7 +4457,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv,
|
|||
|
||||
void intel_set_rps(struct drm_device *dev, u8 val)
|
||||
{
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
valleyview_set_rps(dev, val);
|
||||
else
|
||||
gen6_set_rps(dev, val);
|
||||
|
@ -4502,7 +4501,7 @@ static void valleyview_disable_rps(struct drm_device *dev)
|
|||
|
||||
static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
|
||||
{
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
if (mode & (GEN7_RC_CTL_TO_MODE | GEN6_RC_CTL_EI_MODE(1)))
|
||||
mode = GEN6_RC_CTL_RC6_ENABLE;
|
||||
else
|
||||
|
@ -4673,8 +4672,7 @@ static void gen9_enable_rc6(struct drm_device *dev)
|
|||
/* 2b: Program RC6 thresholds.*/
|
||||
|
||||
/* WaRsDoubleRc6WrlWithCoarsePowerGating: Doubling WRL only when CPG is enabled */
|
||||
if (IS_SKYLAKE(dev) && !((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) &&
|
||||
IS_SKL_REVID(dev, 0, SKL_REVID_E0)))
|
||||
if (IS_SKYLAKE(dev))
|
||||
I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 108 << 16);
|
||||
else
|
||||
I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
|
||||
|
@ -4717,7 +4715,7 @@ static void gen9_enable_rc6(struct drm_device *dev)
|
|||
*/
|
||||
if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) ||
|
||||
((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) &&
|
||||
IS_SKL_REVID(dev, 0, SKL_REVID_E0)))
|
||||
IS_SKL_REVID(dev, 0, SKL_REVID_F0)))
|
||||
I915_WRITE(GEN9_PG_ENABLE, 0);
|
||||
else
|
||||
I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
|
||||
|
@ -5101,7 +5099,17 @@ static int valleyview_rps_rpe_freq(struct drm_i915_private *dev_priv)
|
|||
|
||||
static int valleyview_rps_min_freq(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff;
|
||||
u32 val;
|
||||
|
||||
val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff;
|
||||
/*
|
||||
* According to the BYT Punit GPU turbo HAS 1.1.6.3 the minimum value
|
||||
* for the minimum frequency in GPLL mode is 0xc1. Contrary to this on
|
||||
* a BYT-M B0 the above register contains 0xbf. Moreover when setting
|
||||
* a frequency Punit will not allow values below 0xc0. Clamp it 0xc0
|
||||
* to make sure it matches what Punit accepts.
|
||||
*/
|
||||
return max_t(u32, val, 0xc0);
|
||||
}
|
||||
|
||||
/* Check that the pctx buffer wasn't move under us. */
|
||||
|
@ -6006,7 +6014,17 @@ static void intel_init_emon(struct drm_device *dev)
|
|||
|
||||
void intel_init_gt_powersave(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
|
||||
/*
|
||||
* RPM depends on RC6 to save restore the GT HW context, so make RC6 a
|
||||
* requirement.
|
||||
*/
|
||||
if (!i915.enable_rc6) {
|
||||
DRM_INFO("RC6 disabled, disabling runtime PM support\n");
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
}
|
||||
|
||||
if (IS_CHERRYVIEW(dev))
|
||||
cherryview_init_gt_powersave(dev);
|
||||
|
@ -6016,10 +6034,15 @@ void intel_init_gt_powersave(struct drm_device *dev)
|
|||
|
||||
void intel_cleanup_gt_powersave(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_CHERRYVIEW(dev))
|
||||
return;
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
valleyview_cleanup_gt_powersave(dev);
|
||||
|
||||
if (!i915.enable_rc6)
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
}
|
||||
|
||||
static void gen6_suspend_rps(struct drm_device *dev)
|
||||
|
@ -7223,4 +7246,6 @@ void intel_pm_setup(struct drm_device *dev)
|
|||
INIT_LIST_HEAD(&dev_priv->rps.mmioflips.link);
|
||||
|
||||
dev_priv->pm.suspended = false;
|
||||
atomic_set(&dev_priv->pm.wakeref_count, 0);
|
||||
atomic_set(&dev_priv->pm.atomic_seq, 0);
|
||||
}
|
||||
|
|
|
@ -267,25 +267,20 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
uint32_t max_sleep_time = 0x1f;
|
||||
/* Lately it was identified that depending on panel idle frame count
|
||||
* calculated at HW can be off by 1. So let's use what came
|
||||
* from VBT + 1.
|
||||
* There are also other cases where panel demands at least 4
|
||||
* but VBT is not being set. To cover these 2 cases lets use
|
||||
* at least 5 when VBT isn't set to be on the safest side.
|
||||
/*
|
||||
* Let's respect VBT in case VBT asks a higher idle_frame value.
|
||||
* Let's use 6 as the minimum to cover all known cases including
|
||||
* the off-by-one issue that HW has in some cases. Also there are
|
||||
* cases where sink should be able to train
|
||||
* with the 5 or 6 idle patterns.
|
||||
*/
|
||||
uint32_t idle_frames = dev_priv->vbt.psr.idle_frames ?
|
||||
dev_priv->vbt.psr.idle_frames + 1 : 5;
|
||||
uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
|
||||
uint32_t val = 0x0;
|
||||
const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
|
||||
|
||||
if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) {
|
||||
/* Sink should be able to train with the 5 or 6 idle patterns */
|
||||
idle_frames += 4;
|
||||
}
|
||||
if (IS_HASWELL(dev))
|
||||
val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
|
||||
|
||||
I915_WRITE(EDP_PSR_CTL, val |
|
||||
(IS_BROADWELL(dev) ? 0 : link_entry_time) |
|
||||
max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
|
||||
idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
|
||||
EDP_PSR_ENABLE);
|
||||
|
@ -332,8 +327,8 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!IS_VALLEYVIEW(dev) && ((dev_priv->vbt.psr.full_link) ||
|
||||
(dig_port->port != PORT_A))) {
|
||||
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
|
||||
((dev_priv->vbt.psr.full_link) || (dig_port->port != PORT_A))) {
|
||||
DRM_DEBUG_KMS("PSR condition failed: Link Standby requested/needed but not supported on this platform\n");
|
||||
return false;
|
||||
}
|
||||
|
@ -650,7 +645,7 @@ void intel_psr_single_frame_update(struct drm_device *dev,
|
|||
* Single frame update is already supported on BDW+ but it requires
|
||||
* many W/A and it isn't really needed.
|
||||
*/
|
||||
if (!IS_VALLEYVIEW(dev))
|
||||
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->psr.lock);
|
||||
|
|
|
@ -27,29 +27,13 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/log2.h>
|
||||
#include <drm/drmP.h>
|
||||
#include "i915_drv.h"
|
||||
#include <drm/i915_drm.h>
|
||||
#include "i915_trace.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
bool
|
||||
intel_ring_initialized(struct intel_engine_cs *ring)
|
||||
{
|
||||
struct drm_device *dev = ring->dev;
|
||||
|
||||
if (!dev)
|
||||
return false;
|
||||
|
||||
if (i915.enable_execlists) {
|
||||
struct intel_context *dctx = ring->default_context;
|
||||
struct intel_ringbuffer *ringbuf = dctx->engine[ring->id].ringbuf;
|
||||
|
||||
return ringbuf->obj;
|
||||
} else
|
||||
return ring->buffer && ring->buffer->obj;
|
||||
}
|
||||
|
||||
int __intel_ring_space(int head, int tail, int size)
|
||||
{
|
||||
int space = head - tail;
|
||||
|
@ -995,7 +979,7 @@ static int skl_tune_iz_hashing(struct intel_engine_cs *ring)
|
|||
* Only consider slices where one, and only one, subslice has 7
|
||||
* EUs
|
||||
*/
|
||||
if (hweight8(dev_priv->info.subslice_7eu[i]) != 1)
|
||||
if (!is_power_of_2(dev_priv->info.subslice_7eu[i]))
|
||||
continue;
|
||||
|
||||
/*
|
||||
|
@ -1034,10 +1018,6 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
|
|||
return ret;
|
||||
|
||||
if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) {
|
||||
/* WaDisableHDCInvalidation:skl */
|
||||
I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
|
||||
BDW_DISABLE_HDC_INVALIDATION);
|
||||
|
||||
/* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
|
||||
I915_WRITE(FF_SLICE_CS_CHICKEN2,
|
||||
_MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
|
||||
|
@ -1062,7 +1042,7 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
|
|||
WA_SET_BIT_MASKED(HIZ_CHICKEN,
|
||||
BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
|
||||
|
||||
if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) {
|
||||
if (IS_SKL_REVID(dev, 0, SKL_REVID_F0)) {
|
||||
/*
|
||||
*Use Force Non-Coherent whenever executing a 3D context. This
|
||||
* is a workaround for a possible hang in the unlikely event
|
||||
|
@ -1071,6 +1051,10 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
|
|||
/* WaForceEnableNonCoherent:skl */
|
||||
WA_SET_BIT_MASKED(HDC_CHICKEN0,
|
||||
HDC_FORCE_NON_COHERENT);
|
||||
|
||||
/* WaDisableHDCInvalidation:skl */
|
||||
I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
|
||||
BDW_DISABLE_HDC_INVALIDATION);
|
||||
}
|
||||
|
||||
/* WaBarrierPerformanceFixDisable:skl */
|
||||
|
@ -2167,8 +2151,10 @@ static int intel_init_ring_buffer(struct drm_device *dev,
|
|||
init_waitqueue_head(&ring->irq_queue);
|
||||
|
||||
ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE);
|
||||
if (IS_ERR(ringbuf))
|
||||
return PTR_ERR(ringbuf);
|
||||
if (IS_ERR(ringbuf)) {
|
||||
ret = PTR_ERR(ringbuf);
|
||||
goto error;
|
||||
}
|
||||
ring->buffer = ringbuf;
|
||||
|
||||
if (I915_NEED_GFX_HWS(dev)) {
|
||||
|
@ -2197,8 +2183,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
|
|||
return 0;
|
||||
|
||||
error:
|
||||
intel_ringbuffer_free(ringbuf);
|
||||
ring->buffer = NULL;
|
||||
intel_cleanup_ring_buffer(ring);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2211,12 +2196,14 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
|
|||
|
||||
dev_priv = to_i915(ring->dev);
|
||||
|
||||
intel_stop_ring_buffer(ring);
|
||||
WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
|
||||
if (ring->buffer) {
|
||||
intel_stop_ring_buffer(ring);
|
||||
WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
|
||||
|
||||
intel_unpin_ringbuffer_obj(ring->buffer);
|
||||
intel_ringbuffer_free(ring->buffer);
|
||||
ring->buffer = NULL;
|
||||
intel_unpin_ringbuffer_obj(ring->buffer);
|
||||
intel_ringbuffer_free(ring->buffer);
|
||||
ring->buffer = NULL;
|
||||
}
|
||||
|
||||
if (ring->cleanup)
|
||||
ring->cleanup(ring);
|
||||
|
@ -2225,6 +2212,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
|
|||
|
||||
i915_cmd_parser_fini_ring(ring);
|
||||
i915_gem_batch_pool_fini(&ring->batch_pool);
|
||||
ring->dev = NULL;
|
||||
}
|
||||
|
||||
static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
|
||||
|
|
|
@ -350,7 +350,11 @@ struct intel_engine_cs {
|
|||
u32 (*get_cmd_length_mask)(u32 cmd_header);
|
||||
};
|
||||
|
||||
bool intel_ring_initialized(struct intel_engine_cs *ring);
|
||||
static inline bool
|
||||
intel_ring_initialized(struct intel_engine_cs *ring)
|
||||
{
|
||||
return ring->dev != NULL;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
intel_ring_flag(struct intel_engine_cs *ring)
|
||||
|
|
|
@ -538,8 +538,7 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
|
|||
|
||||
WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5),
|
||||
"DC5 already programmed to be enabled.\n");
|
||||
WARN_ONCE(dev_priv->pm.suspended,
|
||||
"DC5 cannot be enabled, if platform is runtime-suspended.\n");
|
||||
assert_rpm_wakelock_held(dev_priv);
|
||||
|
||||
assert_csr_loaded(dev_priv);
|
||||
}
|
||||
|
@ -553,8 +552,7 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
|
|||
if (dev_priv->power_domains.initializing)
|
||||
return;
|
||||
|
||||
WARN_ONCE(dev_priv->pm.suspended,
|
||||
"Disabling of DC5 while platform is runtime-suspended should never happen.\n");
|
||||
assert_rpm_wakelock_held(dev_priv);
|
||||
}
|
||||
|
||||
static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
|
||||
|
@ -1975,14 +1973,29 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
|
|||
*/
|
||||
void intel_power_domains_fini(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
/* The i915.ko module is still not prepared to be loaded when
|
||||
struct device *device = &dev_priv->dev->pdev->dev;
|
||||
|
||||
/*
|
||||
* The i915.ko module is still not prepared to be loaded when
|
||||
* the power well is not enabled, so just enable it in case
|
||||
* we're going to unload/reload. */
|
||||
* we're going to unload/reload.
|
||||
* The following also reacquires the RPM reference the core passed
|
||||
* to the driver during loading, which is dropped in
|
||||
* intel_runtime_pm_enable(). We have to hand back the control of the
|
||||
* device to the core with this reference held.
|
||||
*/
|
||||
intel_display_set_init_power(dev_priv, true);
|
||||
|
||||
/* Remove the refcount we took to keep power well support disabled. */
|
||||
if (!i915.disable_power_well)
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
||||
|
||||
/*
|
||||
* Remove the refcount we took in intel_runtime_pm_enable() in case
|
||||
* the platform doesn't support runtime PM.
|
||||
*/
|
||||
if (!HAS_RUNTIME_PM(dev_priv))
|
||||
pm_runtime_put(device);
|
||||
}
|
||||
|
||||
static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
|
||||
|
@ -2226,11 +2239,10 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
|
||||
if (!HAS_RUNTIME_PM(dev))
|
||||
return;
|
||||
|
||||
pm_runtime_get_sync(device);
|
||||
WARN(dev_priv->pm.suspended, "Device still suspended.\n");
|
||||
|
||||
atomic_inc(&dev_priv->pm.wakeref_count);
|
||||
assert_rpm_wakelock_held(dev_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2255,11 +2267,10 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
|
||||
if (!HAS_RUNTIME_PM(dev))
|
||||
return;
|
||||
|
||||
WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n");
|
||||
assert_rpm_wakelock_held(dev_priv);
|
||||
pm_runtime_get_noresume(device);
|
||||
|
||||
atomic_inc(&dev_priv->pm.wakeref_count);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2275,8 +2286,9 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
|
||||
if (!HAS_RUNTIME_PM(dev))
|
||||
return;
|
||||
assert_rpm_wakelock_held(dev_priv);
|
||||
if (atomic_dec_and_test(&dev_priv->pm.wakeref_count))
|
||||
atomic_inc(&dev_priv->pm.atomic_seq);
|
||||
|
||||
pm_runtime_mark_last_busy(device);
|
||||
pm_runtime_put_autosuspend(device);
|
||||
|
@ -2297,22 +2309,27 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
|
|||
struct drm_device *dev = dev_priv->dev;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
|
||||
if (!HAS_RUNTIME_PM(dev))
|
||||
return;
|
||||
|
||||
/*
|
||||
* RPM depends on RC6 to save restore the GT HW context, so make RC6 a
|
||||
* requirement.
|
||||
*/
|
||||
if (!intel_enable_rc6(dev)) {
|
||||
DRM_INFO("RC6 disabled, disabling runtime PM support\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
|
||||
pm_runtime_mark_last_busy(device);
|
||||
pm_runtime_use_autosuspend(device);
|
||||
|
||||
/*
|
||||
* Take a permanent reference to disable the RPM functionality and drop
|
||||
* it only when unloading the driver. Use the low level get/put helpers,
|
||||
* so the driver's own RPM reference tracking asserts also work on
|
||||
* platforms without RPM support.
|
||||
*/
|
||||
if (!HAS_RUNTIME_PM(dev)) {
|
||||
pm_runtime_dont_use_autosuspend(device);
|
||||
pm_runtime_get_sync(device);
|
||||
} else {
|
||||
pm_runtime_use_autosuspend(device);
|
||||
}
|
||||
|
||||
/*
|
||||
* The core calls the driver load handler with an RPM reference held.
|
||||
* We drop that here and will reacquire it during unloading in
|
||||
* intel_power_domains_fini().
|
||||
*/
|
||||
pm_runtime_put_autosuspend(device);
|
||||
}
|
||||
|
||||
|
|
|
@ -951,7 +951,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
|
|||
if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
|
||||
return -EINVAL;
|
||||
|
||||
if (IS_VALLEYVIEW(dev) &&
|
||||
if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
|
||||
set->flags & I915_SET_COLORKEY_DESTINATION)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1086,7 +1086,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
|
|||
intel_plane->max_downscale = 1;
|
||||
}
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
intel_plane->update_plane = vlv_update_plane;
|
||||
intel_plane->disable_plane = vlv_disable_plane;
|
||||
|
||||
|
|
|
@ -50,13 +50,6 @@ intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id)
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
static void
|
||||
assert_device_not_suspended(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
WARN_ONCE(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
|
||||
"Device suspended\n");
|
||||
}
|
||||
|
||||
static inline void
|
||||
fw_domain_reset(const struct intel_uncore_forcewake_domain *d)
|
||||
{
|
||||
|
@ -236,7 +229,7 @@ static void intel_uncore_fw_release_timer(unsigned long arg)
|
|||
struct intel_uncore_forcewake_domain *domain = (void *)arg;
|
||||
unsigned long irqflags;
|
||||
|
||||
assert_device_not_suspended(domain->i915);
|
||||
assert_rpm_device_not_suspended(domain->i915);
|
||||
|
||||
spin_lock_irqsave(&domain->i915->uncore.lock, irqflags);
|
||||
if (WARN_ON(domain->wake_count == 0))
|
||||
|
@ -411,7 +404,7 @@ void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,
|
|||
if (!dev_priv->uncore.funcs.force_wake_get)
|
||||
return;
|
||||
|
||||
WARN_ON(dev_priv->pm.suspended);
|
||||
assert_rpm_wakelock_held(dev_priv);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
__intel_uncore_forcewake_get(dev_priv, fw_domains);
|
||||
|
@ -628,7 +621,7 @@ hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv)
|
|||
|
||||
#define GEN2_READ_HEADER(x) \
|
||||
u##x val = 0; \
|
||||
assert_device_not_suspended(dev_priv);
|
||||
assert_rpm_wakelock_held(dev_priv);
|
||||
|
||||
#define GEN2_READ_FOOTER \
|
||||
trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \
|
||||
|
@ -670,7 +663,7 @@ __gen2_read(64)
|
|||
u32 offset = i915_mmio_reg_offset(reg); \
|
||||
unsigned long irqflags; \
|
||||
u##x val = 0; \
|
||||
assert_device_not_suspended(dev_priv); \
|
||||
assert_rpm_wakelock_held(dev_priv); \
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
|
||||
|
||||
#define GEN6_READ_FOOTER \
|
||||
|
@ -803,7 +796,7 @@ __gen6_read(64)
|
|||
#define VGPU_READ_HEADER(x) \
|
||||
unsigned long irqflags; \
|
||||
u##x val = 0; \
|
||||
assert_device_not_suspended(dev_priv); \
|
||||
assert_rpm_device_not_suspended(dev_priv); \
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
|
||||
|
||||
#define VGPU_READ_FOOTER \
|
||||
|
@ -830,7 +823,7 @@ __vgpu_read(64)
|
|||
|
||||
#define GEN2_WRITE_HEADER \
|
||||
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
|
||||
assert_device_not_suspended(dev_priv); \
|
||||
assert_rpm_wakelock_held(dev_priv); \
|
||||
|
||||
#define GEN2_WRITE_FOOTER
|
||||
|
||||
|
@ -870,7 +863,7 @@ __gen2_write(64)
|
|||
u32 offset = i915_mmio_reg_offset(reg); \
|
||||
unsigned long irqflags; \
|
||||
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
|
||||
assert_device_not_suspended(dev_priv); \
|
||||
assert_rpm_wakelock_held(dev_priv); \
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
|
||||
|
||||
#define GEN6_WRITE_FOOTER \
|
||||
|
@ -1046,7 +1039,7 @@ __gen6_write(64)
|
|||
#define VGPU_WRITE_HEADER \
|
||||
unsigned long irqflags; \
|
||||
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
|
||||
assert_device_not_suspended(dev_priv); \
|
||||
assert_rpm_device_not_suspended(dev_priv); \
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
|
||||
|
||||
#define VGPU_WRITE_FOOTER \
|
||||
|
@ -1115,7 +1108,7 @@ static void fw_domain_init(struct drm_i915_private *dev_priv,
|
|||
d->val_clear = _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL);
|
||||
}
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv))
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
d->reg_post = FORCEWAKE_ACK_VLV;
|
||||
else if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv) || IS_GEN8(dev_priv))
|
||||
d->reg_post = ECOBUS;
|
||||
|
@ -1148,7 +1141,7 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev)
|
|||
FORCEWAKE_ACK_BLITTER_GEN9);
|
||||
fw_domain_init(dev_priv, FW_DOMAIN_ID_MEDIA,
|
||||
FORCEWAKE_MEDIA_GEN9, FORCEWAKE_ACK_MEDIA_GEN9);
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
dev_priv->uncore.funcs.force_wake_get = fw_domains_get;
|
||||
if (!IS_CHERRYVIEW(dev))
|
||||
dev_priv->uncore.funcs.force_wake_put =
|
||||
|
|
|
@ -94,6 +94,7 @@ struct drm_dp_mst_port {
|
|||
struct drm_dp_mst_topology_mgr *mgr;
|
||||
|
||||
struct edid *cached_edid; /* for DP logical ports - make tiling work */
|
||||
bool has_audio;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -215,13 +216,13 @@ struct drm_dp_sideband_msg_rx {
|
|||
struct drm_dp_sideband_msg_hdr initial_hdr;
|
||||
};
|
||||
|
||||
|
||||
#define DRM_DP_MAX_SDP_STREAMS 16
|
||||
struct drm_dp_allocate_payload {
|
||||
u8 port_number;
|
||||
u8 number_sdp_streams;
|
||||
u8 vcpi;
|
||||
u16 pbn;
|
||||
u8 sdp_stream_sink[8];
|
||||
u8 sdp_stream_sink[DRM_DP_MAX_SDP_STREAMS];
|
||||
};
|
||||
|
||||
struct drm_dp_allocate_payload_ack_reply {
|
||||
|
@ -484,6 +485,8 @@ int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handl
|
|||
|
||||
enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
|
||||
|
||||
bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_port *port);
|
||||
struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
|
||||
|
||||
|
||||
|
|
|
@ -65,6 +65,20 @@ struct i915_audio_component_ops {
|
|||
* sample rate, it will call this function to set n/cts
|
||||
*/
|
||||
int (*sync_audio_rate)(struct device *, int port, int rate);
|
||||
/**
|
||||
* @get_eld: fill the audio state and ELD bytes for the given port
|
||||
*
|
||||
* Called from audio driver to get the HDMI/DP audio state of the given
|
||||
* digital port, and also fetch ELD bytes to the given pointer.
|
||||
*
|
||||
* It returns the byte size of the original ELD (not the actually
|
||||
* copied size), zero for an invalid ELD, or a negative error code.
|
||||
*
|
||||
* Note that the returned size may be over @max_bytes. Then it
|
||||
* implies that only a part of ELD has been copied to the buffer.
|
||||
*/
|
||||
int (*get_eld)(struct device *, int port, bool *enabled,
|
||||
unsigned char *buf, int max_bytes);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -356,6 +356,7 @@ typedef struct drm_i915_irq_wait {
|
|||
#define I915_PARAM_EU_TOTAL 34
|
||||
#define I915_PARAM_HAS_GPU_RESET 35
|
||||
#define I915_PARAM_HAS_RESOURCE_STREAMER 36
|
||||
#define I915_PARAM_HAS_EXEC_SOFTPIN 37
|
||||
|
||||
typedef struct drm_i915_getparam {
|
||||
__s32 param;
|
||||
|
@ -682,8 +683,12 @@ struct drm_i915_gem_exec_object2 {
|
|||
__u64 alignment;
|
||||
|
||||
/**
|
||||
* Returned value of the updated offset of the object, for future
|
||||
* presumed_offset writes.
|
||||
* When the EXEC_OBJECT_PINNED flag is specified this is populated by
|
||||
* the user with the GTT offset at which this object will be pinned.
|
||||
* When the I915_EXEC_NO_RELOC flag is specified this must contain the
|
||||
* presumed_offset of the object.
|
||||
* During execbuffer2 the kernel populates it with the value of the
|
||||
* current GTT offset of the object, for future presumed_offset writes.
|
||||
*/
|
||||
__u64 offset;
|
||||
|
||||
|
@ -691,7 +696,8 @@ struct drm_i915_gem_exec_object2 {
|
|||
#define EXEC_OBJECT_NEEDS_GTT (1<<1)
|
||||
#define EXEC_OBJECT_WRITE (1<<2)
|
||||
#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3)
|
||||
#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_SUPPORTS_48B_ADDRESS<<1)
|
||||
#define EXEC_OBJECT_PINNED (1<<4)
|
||||
#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_PINNED<<1)
|
||||
__u64 flags;
|
||||
|
||||
__u64 rsvd1;
|
||||
|
|
Loading…
Reference in a new issue