Commit ed8c37e1 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "Smattering of fixes, i915, exynos, tegra, msm, vmwgfx.

  A bit of framebuffer reference counting fallout fixes, i915 GM45
  regression fix, DVI regression fix, vmware info leak between processes
  fix"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/exynos: use %pad for dma_addr_t
  drm/exynos: dsi: use IS_ERR() to check devm_ioremap_resource() results
  MAINTAINERS: update maintainer entry for Exynos DP driver
  drm/exynos: balance framebuffer refcount
  drm/i915: Move all ring resets before setting the HWS page
  drm/i915: Don't WARN nor handle unexpected hpd interrupts on gmch platforms
  drm/msm/mdp4: cure for the cursor blues (v2)
  drm/msm: default to XR24 rather than AR24
  drm/msm: fix memory leak
  drm/tegra: restrict plane loops to legacy planes
  drm/i915: Allow full PPGTT with param override
  drm/i915: Discard BIOS framebuffers too small to accommodate chosen mode
  drm/vmwgfx: Make sure user-space can't DMA across buffer object boundaries v2
  drm/i915: get power domain in case the BIOS enabled eDP VDD
  drm/i915: Don't check gmch state on inherited configs
  drm/i915: Allow user modes to exceed DVI 165MHz limit
parents 2aafe1a4 b8eade24
...@@ -3485,6 +3485,12 @@ S: Maintained ...@@ -3485,6 +3485,12 @@ S: Maintained
F: drivers/extcon/ F: drivers/extcon/
F: Documentation/extcon/ F: Documentation/extcon/
EXYNOS DP DRIVER
M: Jingoo Han <jg1.han@samsung.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
F: drivers/gpu/drm/exynos/exynos_dp*
EXYNOS MIPI DISPLAY DRIVERS EXYNOS MIPI DISPLAY DRIVERS
M: Inki Dae <inki.dae@samsung.com> M: Inki Dae <inki.dae@samsung.com>
M: Donghwa Lee <dh09.lee@samsung.com> M: Donghwa Lee <dh09.lee@samsung.com>
......
...@@ -145,6 +145,7 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, ...@@ -145,6 +145,7 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
plane->crtc = crtc; plane->crtc = crtc;
plane->fb = crtc->primary->fb; plane->fb = crtc->primary->fb;
drm_framebuffer_reference(plane->fb);
return 0; return 0;
} }
......
...@@ -263,7 +263,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, ...@@ -263,7 +263,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
buffer->sgt = sgt; buffer->sgt = sgt;
exynos_gem_obj->base.import_attach = attach; exynos_gem_obj->base.import_attach = attach;
DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr, DRM_DEBUG_PRIME("dma_addr = %pad, size = 0x%lx\n", &buffer->dma_addr,
buffer->size); buffer->size);
return &exynos_gem_obj->base; return &exynos_gem_obj->base;
......
...@@ -1426,9 +1426,9 @@ static int exynos_dsi_probe(struct platform_device *pdev) ...@@ -1426,9 +1426,9 @@ static int exynos_dsi_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dsi->reg_base = devm_ioremap_resource(&pdev->dev, res); dsi->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (!dsi->reg_base) { if (IS_ERR(dsi->reg_base)) {
dev_err(&pdev->dev, "failed to remap io region\n"); dev_err(&pdev->dev, "failed to remap io region\n");
return -EADDRNOTAVAIL; return PTR_ERR(dsi->reg_base);
} }
dsi->phy = devm_phy_get(&pdev->dev, "dsim"); dsi->phy = devm_phy_get(&pdev->dev, "dsim");
......
...@@ -220,7 +220,7 @@ static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos) ...@@ -220,7 +220,7 @@ static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
win_data->enabled = true; win_data->enabled = true;
DRM_DEBUG_KMS("dma_addr = 0x%x\n", win_data->dma_addr); DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr);
if (ctx->vblank_on) if (ctx->vblank_on)
schedule_work(&ctx->work); schedule_work(&ctx->work);
......
...@@ -50,7 +50,7 @@ bool intel_enable_ppgtt(struct drm_device *dev, bool full) ...@@ -50,7 +50,7 @@ bool intel_enable_ppgtt(struct drm_device *dev, bool full)
/* Full ppgtt disabled by default for now due to issues. */ /* Full ppgtt disabled by default for now due to issues. */
if (full) if (full)
return false; /* HAS_PPGTT(dev) */ return HAS_PPGTT(dev) && (i915.enable_ppgtt == 2);
else else
return HAS_ALIASING_PPGTT(dev); return HAS_ALIASING_PPGTT(dev);
} }
......
...@@ -1362,10 +1362,20 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev, ...@@ -1362,10 +1362,20 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
spin_lock(&dev_priv->irq_lock); spin_lock(&dev_priv->irq_lock);
for (i = 1; i < HPD_NUM_PINS; i++) { for (i = 1; i < HPD_NUM_PINS; i++) {
WARN_ONCE(hpd[i] & hotplug_trigger && if (hpd[i] & hotplug_trigger &&
dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED, dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED) {
"Received HPD interrupt (0x%08x) on pin %d (0x%08x) although disabled\n", /*
hotplug_trigger, i, hpd[i]); * On GMCH platforms the interrupt mask bits only
* prevent irq generation, not the setting of the
* hotplug bits itself. So only WARN about unexpected
* interrupts on saner platforms.
*/
WARN_ONCE(INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev),
"Received HPD interrupt (0x%08x) on pin %d (0x%08x) although disabled\n",
hotplug_trigger, i, hpd[i]);
continue;
}
if (!(hpd[i] & hotplug_trigger) || if (!(hpd[i] & hotplug_trigger) ||
dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED) dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
......
...@@ -827,6 +827,7 @@ enum punit_power_well { ...@@ -827,6 +827,7 @@ enum punit_power_well {
# define MI_FLUSH_ENABLE (1 << 12) # define MI_FLUSH_ENABLE (1 << 12)
# define ASYNC_FLIP_PERF_DISABLE (1 << 14) # define ASYNC_FLIP_PERF_DISABLE (1 << 14)
# define MODE_IDLE (1 << 9) # define MODE_IDLE (1 << 9)
# define STOP_RING (1 << 8)
#define GEN6_GT_MODE 0x20d0 #define GEN6_GT_MODE 0x20d0
#define GEN7_GT_MODE 0x7008 #define GEN7_GT_MODE 0x7008
......
...@@ -9654,11 +9654,22 @@ intel_pipe_config_compare(struct drm_device *dev, ...@@ -9654,11 +9654,22 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_I(pipe_src_w); PIPE_CONF_CHECK_I(pipe_src_w);
PIPE_CONF_CHECK_I(pipe_src_h); PIPE_CONF_CHECK_I(pipe_src_h);
PIPE_CONF_CHECK_I(gmch_pfit.control); /*
/* pfit ratios are autocomputed by the hw on gen4+ */ * FIXME: BIOS likes to set up a cloned config with lvds+external
if (INTEL_INFO(dev)->gen < 4) * screen. Since we don't yet re-compute the pipe config when moving
PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios); * just the lvds port away to another pipe the sw tracking won't match.
PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits); *
* Proper atomic modesets with recomputed global state will fix this.
* Until then just don't check gmch state for inherited modes.
*/
if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_INHERITED_MODE)) {
PIPE_CONF_CHECK_I(gmch_pfit.control);
/* pfit ratios are autocomputed by the hw on gen4+ */
if (INTEL_INFO(dev)->gen < 4)
PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
}
PIPE_CONF_CHECK_I(pch_pfit.enabled); PIPE_CONF_CHECK_I(pch_pfit.enabled);
if (current_config->pch_pfit.enabled) { if (current_config->pch_pfit.enabled) {
PIPE_CONF_CHECK_I(pch_pfit.pos); PIPE_CONF_CHECK_I(pch_pfit.pos);
...@@ -11616,6 +11627,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) ...@@ -11616,6 +11627,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
base.head) { base.head) {
memset(&crtc->config, 0, sizeof(crtc->config)); memset(&crtc->config, 0, sizeof(crtc->config));
crtc->config.quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE;
crtc->active = dev_priv->display.get_pipe_config(crtc, crtc->active = dev_priv->display.get_pipe_config(crtc,
&crtc->config); &crtc->config);
......
...@@ -3619,7 +3619,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, ...@@ -3619,7 +3619,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
{ {
struct drm_connector *connector = &intel_connector->base; struct drm_connector *connector = &intel_connector->base;
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev; struct intel_encoder *intel_encoder = &intel_dig_port->base;
struct drm_device *dev = intel_encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *fixed_mode = NULL; struct drm_display_mode *fixed_mode = NULL;
bool has_dpcd; bool has_dpcd;
...@@ -3629,6 +3630,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, ...@@ -3629,6 +3630,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
if (!is_edp(intel_dp)) if (!is_edp(intel_dp))
return true; return true;
/* The VDD bit needs a power domain reference, so if the bit is already
* enabled when we boot, grab this reference. */
if (edp_have_panel_vdd(intel_dp)) {
enum intel_display_power_domain power_domain;
power_domain = intel_display_port_power_domain(intel_encoder);
intel_display_power_get(dev_priv, power_domain);
}
/* Cache DPCD and EDID for edp. */ /* Cache DPCD and EDID for edp. */
intel_edp_panel_vdd_on(intel_dp); intel_edp_panel_vdd_on(intel_dp);
has_dpcd = intel_dp_get_dpcd(intel_dp); has_dpcd = intel_dp_get_dpcd(intel_dp);
......
...@@ -236,7 +236,8 @@ struct intel_crtc_config { ...@@ -236,7 +236,8 @@ struct intel_crtc_config {
* tracked with quirk flags so that fastboot and state checker can act * tracked with quirk flags so that fastboot and state checker can act
* accordingly. * accordingly.
*/ */
#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */
#define PIPE_CONFIG_QUIRK_INHERITED_MODE (1<<1) /* mode inherited from firmware */
unsigned long quirks; unsigned long quirks;
/* User requested mode, only valid as a starting point to /* User requested mode, only valid as a starting point to
......
...@@ -132,6 +132,16 @@ static int intelfb_create(struct drm_fb_helper *helper, ...@@ -132,6 +132,16 @@ static int intelfb_create(struct drm_fb_helper *helper,
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
if (intel_fb &&
(sizes->fb_width > intel_fb->base.width ||
sizes->fb_height > intel_fb->base.height)) {
DRM_DEBUG_KMS("BIOS fb too small (%dx%d), we require (%dx%d),"
" releasing it\n",
intel_fb->base.width, intel_fb->base.height,
sizes->fb_width, sizes->fb_height);
drm_framebuffer_unreference(&intel_fb->base);
intel_fb = ifbdev->fb = NULL;
}
if (!intel_fb || WARN_ON(!intel_fb->obj)) { if (!intel_fb || WARN_ON(!intel_fb->obj)) {
DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
ret = intelfb_alloc(helper, sizes); ret = intelfb_alloc(helper, sizes);
......
...@@ -821,11 +821,11 @@ static void intel_disable_hdmi(struct intel_encoder *encoder) ...@@ -821,11 +821,11 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
} }
} }
static int hdmi_portclock_limit(struct intel_hdmi *hdmi) static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit)
{ {
struct drm_device *dev = intel_hdmi_to_dev(hdmi); struct drm_device *dev = intel_hdmi_to_dev(hdmi);
if (!hdmi->has_hdmi_sink || IS_G4X(dev)) if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev))
return 165000; return 165000;
else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8)
return 300000; return 300000;
...@@ -837,7 +837,8 @@ static enum drm_mode_status ...@@ -837,7 +837,8 @@ static enum drm_mode_status
intel_hdmi_mode_valid(struct drm_connector *connector, intel_hdmi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector))) if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector),
true))
return MODE_CLOCK_HIGH; return MODE_CLOCK_HIGH;
if (mode->clock < 20000) if (mode->clock < 20000)
return MODE_CLOCK_LOW; return MODE_CLOCK_LOW;
...@@ -879,7 +880,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, ...@@ -879,7 +880,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2; int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2;
int portclock_limit = hdmi_portclock_limit(intel_hdmi); int portclock_limit = hdmi_portclock_limit(intel_hdmi, false);
int desired_bpp; int desired_bpp;
if (intel_hdmi->color_range_auto) { if (intel_hdmi->color_range_auto) {
......
...@@ -437,32 +437,41 @@ static void ring_setup_phys_status_page(struct intel_ring_buffer *ring) ...@@ -437,32 +437,41 @@ static void ring_setup_phys_status_page(struct intel_ring_buffer *ring)
I915_WRITE(HWS_PGA, addr); I915_WRITE(HWS_PGA, addr);
} }
static int init_ring_common(struct intel_ring_buffer *ring) static bool stop_ring(struct intel_ring_buffer *ring)
{ {
struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = to_i915(ring->dev);
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = ring->obj;
int ret = 0;
u32 head;
gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); if (!IS_GEN2(ring->dev)) {
I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
return false;
}
}
/* Stop the ring if it's running. */
I915_WRITE_CTL(ring, 0); I915_WRITE_CTL(ring, 0);
I915_WRITE_HEAD(ring, 0); I915_WRITE_HEAD(ring, 0);
ring->write_tail(ring, 0); ring->write_tail(ring, 0);
if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000))
DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
if (I915_NEED_GFX_HWS(dev)) if (!IS_GEN2(ring->dev)) {
intel_ring_setup_status_page(ring); (void)I915_READ_CTL(ring);
else I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING));
ring_setup_phys_status_page(ring); }
head = I915_READ_HEAD(ring) & HEAD_ADDR; return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0;
}
/* G45 ring initialization fails to reset head to zero */ static int init_ring_common(struct intel_ring_buffer *ring)
if (head != 0) { {
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = ring->obj;
int ret = 0;
gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
if (!stop_ring(ring)) {
/* G45 ring initialization often fails to reset head to zero */
DRM_DEBUG_KMS("%s head not reset to zero " DRM_DEBUG_KMS("%s head not reset to zero "
"ctl %08x head %08x tail %08x start %08x\n", "ctl %08x head %08x tail %08x start %08x\n",
ring->name, ring->name,
...@@ -471,9 +480,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) ...@@ -471,9 +480,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
I915_READ_TAIL(ring), I915_READ_TAIL(ring),
I915_READ_START(ring)); I915_READ_START(ring));
I915_WRITE_HEAD(ring, 0); if (!stop_ring(ring)) {
if (I915_READ_HEAD(ring) & HEAD_ADDR) {
DRM_ERROR("failed to set %s head to zero " DRM_ERROR("failed to set %s head to zero "
"ctl %08x head %08x tail %08x start %08x\n", "ctl %08x head %08x tail %08x start %08x\n",
ring->name, ring->name,
...@@ -481,9 +488,16 @@ static int init_ring_common(struct intel_ring_buffer *ring) ...@@ -481,9 +488,16 @@ static int init_ring_common(struct intel_ring_buffer *ring)
I915_READ_HEAD(ring), I915_READ_HEAD(ring),
I915_READ_TAIL(ring), I915_READ_TAIL(ring),
I915_READ_START(ring)); I915_READ_START(ring));
ret = -EIO;
goto out;
} }
} }
if (I915_NEED_GFX_HWS(dev))
intel_ring_setup_status_page(ring);
else
ring_setup_phys_status_page(ring);
/* Initialize the ring. This must happen _after_ we've cleared the ring /* Initialize the ring. This must happen _after_ we've cleared the ring
* registers with the above sequence (the readback of the HEAD registers * registers with the above sequence (the readback of the HEAD registers
* also enforces ordering), otherwise the hw might lose the new ring * also enforces ordering), otherwise the hw might lose the new ring
......
...@@ -34,6 +34,7 @@ struct intel_hw_status_page { ...@@ -34,6 +34,7 @@ struct intel_hw_status_page {
#define I915_WRITE_IMR(ring, val) I915_WRITE(RING_IMR((ring)->mmio_base), val) #define I915_WRITE_IMR(ring, val) I915_WRITE(RING_IMR((ring)->mmio_base), val)
#define I915_READ_MODE(ring) I915_READ(RING_MI_MODE((ring)->mmio_base)) #define I915_READ_MODE(ring) I915_READ(RING_MI_MODE((ring)->mmio_base))
#define I915_WRITE_MODE(ring, val) I915_WRITE(RING_MI_MODE((ring)->mmio_base), val)
enum intel_ring_hangcheck_action { enum intel_ring_hangcheck_action {
HANGCHECK_IDLE = 0, HANGCHECK_IDLE = 0,
......
...@@ -510,9 +510,8 @@ static void update_cursor(struct drm_crtc *crtc) ...@@ -510,9 +510,8 @@ static void update_cursor(struct drm_crtc *crtc)
MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN); MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN);
} else { } else {
/* disable cursor: */ /* disable cursor: */
mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma), 0); mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma),
mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma), mdp4_kms->blank_cursor_iova);
MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB));
} }
/* and drop the iova ref + obj rev when done scanning out: */ /* and drop the iova ref + obj rev when done scanning out: */
...@@ -574,11 +573,9 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -574,11 +573,9 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc,
if (old_bo) { if (old_bo) {
/* drop our previous reference: */ /* drop our previous reference: */
msm_gem_put_iova(old_bo, mdp4_kms->id); drm_flip_work_queue(&mdp4_crtc->unref_cursor_work, old_bo);
drm_gem_object_unreference_unlocked(old_bo);
} }
crtc_flush(crtc);
request_pending(crtc, PENDING_CURSOR); request_pending(crtc, PENDING_CURSOR);
return 0; return 0;
......
...@@ -70,12 +70,12 @@ irqreturn_t mdp4_irq(struct msm_kms *kms) ...@@ -70,12 +70,12 @@ irqreturn_t mdp4_irq(struct msm_kms *kms)
VERB("status=%08x", status); VERB("status=%08x", status);
mdp_dispatch_irqs(mdp_kms, status);
for (id = 0; id < priv->num_crtcs; id++) for (id = 0; id < priv->num_crtcs; id++)
if (status & mdp4_crtc_vblank(priv->crtcs[id])) if (status & mdp4_crtc_vblank(priv->crtcs[id]))
drm_handle_vblank(dev, id); drm_handle_vblank(dev, id);
mdp_dispatch_irqs(mdp_kms, status);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -144,6 +144,10 @@ static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file) ...@@ -144,6 +144,10 @@ static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file)
static void mdp4_destroy(struct msm_kms *kms) static void mdp4_destroy(struct msm_kms *kms)
{ {
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
if (mdp4_kms->blank_cursor_iova)
msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id);
if (mdp4_kms->blank_cursor_bo)
drm_gem_object_unreference(mdp4_kms->blank_cursor_bo);
kfree(mdp4_kms); kfree(mdp4_kms);
} }
...@@ -372,6 +376,23 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev) ...@@ -372,6 +376,23 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
goto fail; goto fail;
} }
mutex_lock(&dev->struct_mutex);
mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC);
mutex_unlock(&dev->struct_mutex);
if (IS_ERR(mdp4_kms->blank_cursor_bo)) {
ret = PTR_ERR(mdp4_kms->blank_cursor_bo);
dev_err(dev->dev, "could not allocate blank-cursor bo: %d\n", ret);
mdp4_kms->blank_cursor_bo = NULL;
goto fail;
}
ret = msm_gem_get_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id,
&mdp4_kms->blank_cursor_iova);
if (ret) {
dev_err(dev->dev, "could not pin blank-cursor bo: %d\n", ret);
goto fail;
}
return kms; return kms;
fail: fail:
......
...@@ -44,6 +44,10 @@ struct mdp4_kms { ...@@ -44,6 +44,10 @@ struct mdp4_kms {
struct clk *lut_clk; struct clk *lut_clk;
struct mdp_irq error_handler; struct mdp_irq error_handler;
/* empty/blank cursor bo to use when cursor is "disabled" */
struct drm_gem_object *blank_cursor_bo;
uint32_t blank_cursor_iova;
}; };
#define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base) #define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base)
......
...@@ -71,11 +71,11 @@ static void mdp5_irq_mdp(struct mdp_kms *mdp_kms) ...@@ -71,11 +71,11 @@ static void mdp5_irq_mdp(struct mdp_kms *mdp_kms)
VERB("status=%08x", status); VERB("status=%08x", status);
mdp_dispatch_irqs(mdp_kms, status);
for (id = 0; id < priv->num_crtcs; id++) for (id = 0; id < priv->num_crtcs; id++)
if (status & mdp5_crtc_vblank(priv->crtcs[id])) if (status & mdp5_crtc_vblank(priv->crtcs[id]))
drm_handle_vblank(dev, id); drm_handle_vblank(dev, id);
mdp_dispatch_irqs(mdp_kms, status);
} }
irqreturn_t mdp5_irq(struct msm_kms *kms) irqreturn_t mdp5_irq(struct msm_kms *kms)
......
...@@ -62,11 +62,8 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, ...@@ -62,11 +62,8 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
dma_addr_t paddr; dma_addr_t paddr;
int ret, size; int ret, size;
/* only doing ARGB32 since this is what is needed to alpha-blend
* with video overlays:
*/
sizes->surface_bpp = 32; sizes->surface_bpp = 32;
sizes->surface_depth = 32; sizes->surface_depth = 24;
DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width, DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width,
sizes->surface_height, sizes->surface_bpp, sizes->surface_height, sizes->surface_bpp,
......
...@@ -118,8 +118,10 @@ static void put_pages(struct drm_gem_object *obj) ...@@ -118,8 +118,10 @@ static void put_pages(struct drm_gem_object *obj)
if (iommu_present(&platform_bus_type)) if (iommu_present(&platform_bus_type))
drm_gem_put_pages(obj, msm_obj->pages, true, false); drm_gem_put_pages(obj, msm_obj->pages, true, false);
else else {
drm_mm_remove_node(msm_obj->vram_node); drm_mm_remove_node(msm_obj->vram_node);
drm_free_large(msm_obj->pages);
}
msm_obj->pages = NULL; msm_obj->pages = NULL;
} }
......
...@@ -312,7 +312,7 @@ static void tegra_crtc_disable(struct drm_crtc *crtc) ...@@ -312,7 +312,7 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
struct drm_device *drm = crtc->dev; struct drm_device *drm = crtc->dev;
struct drm_plane *plane; struct drm_plane *plane;
list_for_each_entry(plane, &drm->mode_config.plane_list, head) { drm_for_each_legacy_plane(plane, &drm->mode_config.plane_list) {
if (plane->crtc == crtc) { if (plane->crtc == crtc) {
tegra_plane_disable(plane); tegra_plane_disable(plane);
plane->crtc = NULL; plane->crtc = NULL;
......
...@@ -1214,14 +1214,36 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, ...@@ -1214,14 +1214,36 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
SVGA3dCmdSurfaceDMA dma; SVGA3dCmdSurfaceDMA dma;
} *cmd; } *cmd;
int ret; int ret;
SVGA3dCmdSurfaceDMASuffix *suffix;
uint32_t bo_size;
cmd = container_of(header, struct vmw_dma_cmd, header); cmd = container_of(header, struct vmw_dma_cmd, header);
suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->dma +
header->size - sizeof(*suffix));
/* Make sure device and verifier stays in sync. */
if (unlikely(suffix->suffixSize != sizeof(*suffix))) {
DRM_ERROR("Invalid DMA suffix size.\n");
return -EINVAL;
}
ret = vmw_translate_guest_ptr(dev_priv, sw_context, ret = vmw_translate_guest_ptr(dev_priv, sw_context,
&cmd->dma.guest.ptr, &cmd->dma.guest.ptr,
&vmw_bo); &vmw_bo);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
return ret; return ret;
/* Make sure DMA doesn't cross BO boundaries. */
bo_size = vmw_bo->base.num_pages * PAGE_SIZE;
if (unlikely(cmd->dma.guest.ptr.offset > bo_size)) {
DRM_ERROR("Invalid DMA offset.\n");
return -EINVAL;
}
bo_size -= cmd->dma.guest.ptr.offset;
if (unlikely(suffix->maximumOffset > bo_size))
suffix->maximumOffset = bo_size;
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
user_surface_converter, &cmd->dma.host.sid, user_surface_converter, &cmd->dma.host.sid,
NULL); NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment