Commit c6797654 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:
 "Back from holidays, found these in the cracks: one nouveau revert, one
  vmwgfx locking fix and a bunch of exynos fixes"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  Revert "drm/nouveau/fifo/gk104: kick channels when deactivating them"
  drm/vmwgfx: Fix execbuf locking issues
  drm/exynos/fimc: fix runtime pm support
  drm/exynos/mixer: always update INT_EN cache
  drm/exynos/mixer: correct vsync configuration sequence
  drm/exynos/mixer: fix interrupt clearing
  drm/exynos/hdmi: fix edid memory leak
  drm/exynos: gsc: fix wrong bitwise operation for swap detection
parents 7ddab733 d211d87e
...@@ -1745,7 +1745,6 @@ static int fimc_probe(struct platform_device *pdev) ...@@ -1745,7 +1745,6 @@ static int fimc_probe(struct platform_device *pdev)
spin_lock_init(&ctx->lock); spin_lock_init(&ctx->lock);
platform_set_drvdata(pdev, ctx); platform_set_drvdata(pdev, ctx);
pm_runtime_set_active(dev);
pm_runtime_enable(dev); pm_runtime_enable(dev);
ret = exynos_drm_ippdrv_register(ippdrv); ret = exynos_drm_ippdrv_register(ippdrv);
......
...@@ -593,8 +593,7 @@ static int gsc_src_set_transf(struct device *dev, ...@@ -593,8 +593,7 @@ static int gsc_src_set_transf(struct device *dev,
gsc_write(cfg, GSC_IN_CON); gsc_write(cfg, GSC_IN_CON);
ctx->rotation = cfg & ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0;
(GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
*swap = ctx->rotation; *swap = ctx->rotation;
return 0; return 0;
...@@ -857,8 +856,7 @@ static int gsc_dst_set_transf(struct device *dev, ...@@ -857,8 +856,7 @@ static int gsc_dst_set_transf(struct device *dev,
gsc_write(cfg, GSC_IN_CON); gsc_write(cfg, GSC_IN_CON);
ctx->rotation = cfg & ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0;
(GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
*swap = ctx->rotation; *swap = ctx->rotation;
return 0; return 0;
......
...@@ -1064,6 +1064,7 @@ static int hdmi_get_modes(struct drm_connector *connector) ...@@ -1064,6 +1064,7 @@ static int hdmi_get_modes(struct drm_connector *connector)
{ {
struct hdmi_context *hdata = ctx_from_connector(connector); struct hdmi_context *hdata = ctx_from_connector(connector);
struct edid *edid; struct edid *edid;
int ret;
if (!hdata->ddc_adpt) if (!hdata->ddc_adpt)
return -ENODEV; return -ENODEV;
...@@ -1079,7 +1080,11 @@ static int hdmi_get_modes(struct drm_connector *connector) ...@@ -1079,7 +1080,11 @@ static int hdmi_get_modes(struct drm_connector *connector)
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
return drm_add_edid_modes(connector, edid); ret = drm_add_edid_modes(connector, edid);
kfree(edid);
return ret;
} }
static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
......
...@@ -718,6 +718,10 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) ...@@ -718,6 +718,10 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
/* handling VSYNC */ /* handling VSYNC */
if (val & MXR_INT_STATUS_VSYNC) { if (val & MXR_INT_STATUS_VSYNC) {
/* vsync interrupt use different bit for read and clear */
val |= MXR_INT_CLEAR_VSYNC;
val &= ~MXR_INT_STATUS_VSYNC;
/* interlace scan need to check shadow register */ /* interlace scan need to check shadow register */
if (ctx->interlace) { if (ctx->interlace) {
base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0)); base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
...@@ -743,11 +747,6 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) ...@@ -743,11 +747,6 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
out: out:
/* clear interrupts */ /* clear interrupts */
if (~val & MXR_INT_EN_VSYNC) {
/* vsync interrupt use different bit for read and clear */
val &= ~MXR_INT_EN_VSYNC;
val |= MXR_INT_CLEAR_VSYNC;
}
mixer_reg_write(res, MXR_INT_STATUS, val); mixer_reg_write(res, MXR_INT_STATUS, val);
spin_unlock(&res->reg_slock); spin_unlock(&res->reg_slock);
...@@ -907,8 +906,8 @@ static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) ...@@ -907,8 +906,8 @@ static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
} }
/* enable vsync interrupt */ /* enable vsync interrupt */
mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC, mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
MXR_INT_EN_VSYNC); mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
return 0; return 0;
} }
...@@ -918,7 +917,13 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) ...@@ -918,7 +917,13 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
struct mixer_context *mixer_ctx = crtc->ctx; struct mixer_context *mixer_ctx = crtc->ctx;
struct mixer_resources *res = &mixer_ctx->mixer_res; struct mixer_resources *res = &mixer_ctx->mixer_res;
if (!mixer_ctx->powered) {
mixer_ctx->int_en &= MXR_INT_EN_VSYNC;
return;
}
/* disable vsync interrupt */ /* disable vsync interrupt */
mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
} }
...@@ -1047,6 +1052,8 @@ static void mixer_enable(struct exynos_drm_crtc *crtc) ...@@ -1047,6 +1052,8 @@ static void mixer_enable(struct exynos_drm_crtc *crtc)
mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
if (ctx->int_en & MXR_INT_EN_VSYNC)
mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
mixer_reg_write(res, MXR_INT_EN, ctx->int_en); mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
mixer_win_reset(ctx); mixer_win_reset(ctx);
} }
......
...@@ -165,31 +165,15 @@ gk104_fifo_context_attach(struct nvkm_object *parent, ...@@ -165,31 +165,15 @@ gk104_fifo_context_attach(struct nvkm_object *parent,
return 0; return 0;
} }
static int
gk104_fifo_chan_kick(struct gk104_fifo_chan *chan)
{
struct nvkm_object *obj = (void *)chan;
struct gk104_fifo_priv *priv = (void *)obj->engine;
nv_wr32(priv, 0x002634, chan->base.chid);
if (!nv_wait(priv, 0x002634, 0x100000, 0x000000)) {
nv_error(priv, "channel %d [%s] kick timeout\n",
chan->base.chid, nvkm_client_name(chan));
return -EBUSY;
}
return 0;
}
static int static int
gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
struct nvkm_object *object) struct nvkm_object *object)
{ {
struct nvkm_bar *bar = nvkm_bar(parent); struct nvkm_bar *bar = nvkm_bar(parent);
struct gk104_fifo_priv *priv = (void *)parent->engine;
struct gk104_fifo_base *base = (void *)parent->parent; struct gk104_fifo_base *base = (void *)parent->parent;
struct gk104_fifo_chan *chan = (void *)parent; struct gk104_fifo_chan *chan = (void *)parent;
u32 addr; u32 addr;
int ret;
switch (nv_engidx(object->engine)) { switch (nv_engidx(object->engine)) {
case NVDEV_ENGINE_SW : return 0; case NVDEV_ENGINE_SW : return 0;
...@@ -204,9 +188,13 @@ gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, ...@@ -204,9 +188,13 @@ gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
return -EINVAL; return -EINVAL;
} }
ret = gk104_fifo_chan_kick(chan); nv_wr32(priv, 0x002634, chan->base.chid);
if (ret && suspend) if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) {
return ret; nv_error(priv, "channel %d [%s] kick timeout\n",
chan->base.chid, nvkm_client_name(chan));
if (suspend)
return -EBUSY;
}
if (addr) { if (addr) {
nv_wo32(base, addr + 0x00, 0x00000000); nv_wo32(base, addr + 0x00, 0x00000000);
...@@ -331,7 +319,6 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend) ...@@ -331,7 +319,6 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend)
gk104_fifo_runlist_update(priv, chan->engine); gk104_fifo_runlist_update(priv, chan->engine);
} }
gk104_fifo_chan_kick(chan);
nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
return nvkm_fifo_channel_fini(&chan->base, suspend); return nvkm_fifo_channel_fini(&chan->base, suspend);
} }
......
...@@ -2492,7 +2492,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, ...@@ -2492,7 +2492,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes, ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes,
true, NULL); true, NULL);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto out_err; goto out_err_nores;
ret = vmw_validate_buffers(dev_priv, sw_context); ret = vmw_validate_buffers(dev_priv, sw_context);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
...@@ -2536,6 +2536,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, ...@@ -2536,6 +2536,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
vmw_resource_relocations_free(&sw_context->res_relocations); vmw_resource_relocations_free(&sw_context->res_relocations);
vmw_fifo_commit(dev_priv, command_size); vmw_fifo_commit(dev_priv, command_size);
mutex_unlock(&dev_priv->binding_mutex);
vmw_query_bo_switch_commit(dev_priv, sw_context); vmw_query_bo_switch_commit(dev_priv, sw_context);
ret = vmw_execbuf_fence_commands(file_priv, dev_priv, ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
...@@ -2551,7 +2552,6 @@ int vmw_execbuf_process(struct drm_file *file_priv, ...@@ -2551,7 +2552,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
DRM_ERROR("Fence submission error. Syncing.\n"); DRM_ERROR("Fence submission error. Syncing.\n");
vmw_resource_list_unreserve(&sw_context->resource_list, false); vmw_resource_list_unreserve(&sw_context->resource_list, false);
mutex_unlock(&dev_priv->binding_mutex);
ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes, ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes,
(void *) fence); (void *) fence);
......
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