Commit 35683dd3 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:
 "This has two main sets of fixes:

   - A bunch of Exynos fixes, mainly for their MIC component.

   - vblank regression fixes from Mario, apparantly some changes in 4.4
     caused some vblank breakage on radeon/nouveau, this set fixes all
     the issues seen.

  There is also a revert of one of the MST changse, that I was
  overzealous in including, that broke 30" MST monitors, and two qxl
  fixes"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/qxl: fix erroneous return value
  drm/nouveau/display: Enable vblank irqs after display engine is on again.
  drm/radeon/pm: Handle failure of drm_vblank_get.
  drm: Fix treatment of drm_vblank_offdelay in drm_vblank_on() (v2)
  drm: Fix drm_vblank_pre/post_modeset regression from Linux 4.4
  drm: Prevent vblank counter bumps > 1 with active vblank clients. (v2)
  drm: No-Op redundant calls to drm_vblank_off() (v2)
  drm/qxl: use kmalloc_array to alloc reloc_info in qxl_process_single_command
  Revert "drm/dp/mst: change MST detection scheme"
  drm/exynos/decon: fix disable clocks order
  drm/exynos: fix incorrect cpu address for dma_mmap_attrs()
  drm/exynos: exynos5433_decon: fix wrong state in decon_vblank_enable
  drm/exynos: exynos5433_decon: fix wrong state assignment in decon_enable
  drm/exynos: dsi: restore support for drm bridge
  drm/exynos: mic: make all functions static
  drm/exynos: mic: convert to component framework
  drm/exynos: mic: use devm_clk interface
  drm/exynos: fix types for compilation on 64bit architectures
  drm/exynos: ipp: fix incorrect format specifiers in debug messages
  drm/exynos: depend on ARCH_EXYNOS for DRM_EXYNOS
parents a9f70bd4 dada168b
...@@ -1159,11 +1159,13 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, ...@@ -1159,11 +1159,13 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
drm_dp_put_port(port); drm_dp_put_port(port);
goto out; goto out;
} }
if (port->port_num >= DP_MST_LOGICAL_PORT_0) {
port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
drm_mode_connector_set_tile_property(port->connector); drm_mode_connector_set_tile_property(port->connector);
}
(*mstb->mgr->cbs->register_connector)(port->connector); (*mstb->mgr->cbs->register_connector)(port->connector);
} }
out: out:
/* put reference to this port */ /* put reference to this port */
drm_dp_put_port(port); drm_dp_put_port(port);
...@@ -1188,8 +1190,8 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb, ...@@ -1188,8 +1190,8 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
port->ddps = conn_stat->displayport_device_plug_status; port->ddps = conn_stat->displayport_device_plug_status;
if (old_ddps != port->ddps) { if (old_ddps != port->ddps) {
dowork = true;
if (port->ddps) { if (port->ddps) {
dowork = true;
} else { } else {
port->available_pbn = 0; port->available_pbn = 0;
} }
...@@ -1294,13 +1296,8 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m ...@@ -1294,13 +1296,8 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
if (port->input) if (port->input)
continue; continue;
if (!port->ddps) { if (!port->ddps)
if (port->cached_edid) {
kfree(port->cached_edid);
port->cached_edid = NULL;
}
continue; continue;
}
if (!port->available_pbn) if (!port->available_pbn)
drm_dp_send_enum_path_resources(mgr, mstb, port); drm_dp_send_enum_path_resources(mgr, mstb, port);
...@@ -1311,12 +1308,6 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m ...@@ -1311,12 +1308,6 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
drm_dp_check_and_send_link_address(mgr, mstb_child); drm_dp_check_and_send_link_address(mgr, mstb_child);
drm_dp_put_mst_branch_device(mstb_child); drm_dp_put_mst_branch_device(mstb_child);
} }
} else if (port->pdt == DP_PEER_DEVICE_SST_SINK ||
port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV) {
if (!port->cached_edid) {
port->cached_edid =
drm_get_edid(port->connector, &port->aux.ddc);
}
} }
} }
} }
...@@ -1336,8 +1327,6 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work) ...@@ -1336,8 +1327,6 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work)
drm_dp_check_and_send_link_address(mgr, mstb); drm_dp_check_and_send_link_address(mgr, mstb);
drm_dp_put_mst_branch_device(mstb); drm_dp_put_mst_branch_device(mstb);
} }
(*mgr->cbs->hotplug)(mgr);
} }
static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr, static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
...@@ -1597,6 +1586,7 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr, ...@@ -1597,6 +1586,7 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) { for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
} }
(*mgr->cbs->hotplug)(mgr);
} }
} else { } else {
mstb->link_address_sent = false; mstb->link_address_sent = false;
...@@ -2293,6 +2283,8 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) ...@@ -2293,6 +2283,8 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
drm_dp_update_port(mstb, &msg.u.conn_stat); drm_dp_update_port(mstb, &msg.u.conn_stat);
DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
(*mgr->cbs->hotplug)(mgr);
} else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
if (!mstb) if (!mstb)
...@@ -2379,6 +2371,10 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector ...@@ -2379,6 +2371,10 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector
case DP_PEER_DEVICE_SST_SINK: case DP_PEER_DEVICE_SST_SINK:
status = connector_status_connected; status = connector_status_connected;
/* for logical ports - cache the EDID */
if (port->port_num >= 8 && !port->cached_edid) {
port->cached_edid = drm_get_edid(connector, &port->aux.ddc);
}
break; break;
case DP_PEER_DEVICE_DP_LEGACY_CONV: case DP_PEER_DEVICE_DP_LEGACY_CONV:
if (port->ldps) if (port->ldps)
...@@ -2433,7 +2429,10 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_ ...@@ -2433,7 +2429,10 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
if (port->cached_edid) if (port->cached_edid)
edid = drm_edid_duplicate(port->cached_edid); edid = drm_edid_duplicate(port->cached_edid);
else {
edid = drm_get_edid(connector, &port->aux.ddc);
drm_mode_connector_set_tile_property(connector);
}
port->has_audio = drm_detect_monitor_audio(edid); port->has_audio = drm_detect_monitor_audio(edid);
drm_dp_put_port(port); drm_dp_put_port(port);
return edid; return edid;
......
...@@ -224,6 +224,64 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, ...@@ -224,6 +224,64 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0; diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0;
} }
/*
* Within a drm_vblank_pre_modeset - drm_vblank_post_modeset
* interval? If so then vblank irqs keep running and it will likely
* happen that the hardware vblank counter is not trustworthy as it
* might reset at some point in that interval and vblank timestamps
* are not trustworthy either in that interval. Iow. this can result
* in a bogus diff >> 1 which must be avoided as it would cause
* random large forward jumps of the software vblank counter.
*/
if (diff > 1 && (vblank->inmodeset & 0x2)) {
DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u"
" due to pre-modeset.\n", pipe, diff);
diff = 1;
}
/*
* FIMXE: Need to replace this hack with proper seqlocks.
*
* Restrict the bump of the software vblank counter to a safe maximum
* value of +1 whenever there is the possibility that concurrent readers
* of vblank timestamps could be active at the moment, as the current
* implementation of the timestamp caching and updating is not safe
* against concurrent readers for calls to store_vblank() with a bump
* of anything but +1. A bump != 1 would very likely return corrupted
* timestamps to userspace, because the same slot in the cache could
* be concurrently written by store_vblank() and read by one of those
* readers without the read-retry logic detecting the collision.
*
* Concurrent readers can exist when we are called from the
* drm_vblank_off() or drm_vblank_on() functions and other non-vblank-
* irq callers. However, all those calls to us are happening with the
* vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount
* can't increase while we are executing. Therefore a zero refcount at
* this point is safe for arbitrary counter bumps if we are called
* outside vblank irq, a non-zero count is not 100% safe. Unfortunately
* we must also accept a refcount of 1, as whenever we are called from
* drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and
* we must let that one pass through in order to not lose vblank counts
* during vblank irq off - which would completely defeat the whole
* point of this routine.
*
* Whenever we are called from vblank irq, we have to assume concurrent
* readers exist or can show up any time during our execution, even if
* the refcount is currently zero, as vblank irqs are usually only
* enabled due to the presence of readers, and because when we are called
* from vblank irq we can't hold the vbl_lock to protect us from sudden
* bumps in vblank refcount. Therefore also restrict bumps to +1 when
* called from vblank irq.
*/
if ((diff > 1) && (atomic_read(&vblank->refcount) > 1 ||
(flags & DRM_CALLED_FROM_VBLIRQ))) {
DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u "
"refcount %u, vblirq %u\n", pipe, diff,
atomic_read(&vblank->refcount),
(flags & DRM_CALLED_FROM_VBLIRQ) != 0);
diff = 1;
}
DRM_DEBUG_VBL("updating vblank count on crtc %u:" DRM_DEBUG_VBL("updating vblank count on crtc %u:"
" current=%u, diff=%u, hw=%u hw_last=%u\n", " current=%u, diff=%u, hw=%u hw_last=%u\n",
pipe, vblank->count, diff, cur_vblank, vblank->last); pipe, vblank->count, diff, cur_vblank, vblank->last);
...@@ -1316,7 +1374,13 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe) ...@@ -1316,7 +1374,13 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
spin_lock_irqsave(&dev->event_lock, irqflags); spin_lock_irqsave(&dev->event_lock, irqflags);
spin_lock(&dev->vbl_lock); spin_lock(&dev->vbl_lock);
DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
pipe, vblank->enabled, vblank->inmodeset);
/* Avoid redundant vblank disables without previous drm_vblank_on(). */
if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
vblank_disable_and_save(dev, pipe); vblank_disable_and_save(dev, pipe);
wake_up(&vblank->queue); wake_up(&vblank->queue);
/* /*
...@@ -1418,6 +1482,9 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe) ...@@ -1418,6 +1482,9 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
return; return;
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
pipe, vblank->enabled, vblank->inmodeset);
/* Drop our private "prevent drm_vblank_get" refcount */ /* Drop our private "prevent drm_vblank_get" refcount */
if (vblank->inmodeset) { if (vblank->inmodeset) {
atomic_dec(&vblank->refcount); atomic_dec(&vblank->refcount);
...@@ -1430,8 +1497,7 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe) ...@@ -1430,8 +1497,7 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
* re-enable interrupts if there are users left, or the * re-enable interrupts if there are users left, or the
* user wishes vblank interrupts to be enabled all the time. * user wishes vblank interrupts to be enabled all the time.
*/ */
if (atomic_read(&vblank->refcount) != 0 || if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0)
(!dev->vblank_disable_immediate && drm_vblank_offdelay == 0))
WARN_ON(drm_vblank_enable(dev, pipe)); WARN_ON(drm_vblank_enable(dev, pipe));
spin_unlock_irqrestore(&dev->vbl_lock, irqflags); spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
} }
...@@ -1526,6 +1592,7 @@ void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe) ...@@ -1526,6 +1592,7 @@ void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)
if (vblank->inmodeset) { if (vblank->inmodeset) {
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
dev->vblank_disable_allowed = true; dev->vblank_disable_allowed = true;
drm_reset_vblank_timestamp(dev, pipe);
spin_unlock_irqrestore(&dev->vbl_lock, irqflags); spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
if (vblank->inmodeset & 0x2) if (vblank->inmodeset & 0x2)
......
config DRM_EXYNOS config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series" tristate "DRM Support for Samsung SoC EXYNOS Series"
depends on OF && DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM) depends on OF && DRM && (ARCH_S3C64XX || ARCH_EXYNOS || ARCH_MULTIPLATFORM)
select DRM_KMS_HELPER select DRM_KMS_HELPER
select DRM_KMS_FB_HELPER select DRM_KMS_FB_HELPER
select FB_CFB_FILLRECT select FB_CFB_FILLRECT
......
...@@ -93,7 +93,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc) ...@@ -93,7 +93,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
if (test_bit(BIT_SUSPENDED, &ctx->flags)) if (test_bit(BIT_SUSPENDED, &ctx->flags))
return -EPERM; return -EPERM;
if (test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) { if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) {
val = VIDINTCON0_INTEN; val = VIDINTCON0_INTEN;
if (ctx->out_type == IFTYPE_I80) if (ctx->out_type == IFTYPE_I80)
val |= VIDINTCON0_FRAMEDONE; val |= VIDINTCON0_FRAMEDONE;
...@@ -402,8 +402,6 @@ static void decon_enable(struct exynos_drm_crtc *crtc) ...@@ -402,8 +402,6 @@ static void decon_enable(struct exynos_drm_crtc *crtc)
decon_enable_vblank(ctx->crtc); decon_enable_vblank(ctx->crtc);
decon_commit(ctx->crtc); decon_commit(ctx->crtc);
set_bit(BIT_SUSPENDED, &ctx->flags);
} }
static void decon_disable(struct exynos_drm_crtc *crtc) static void decon_disable(struct exynos_drm_crtc *crtc)
...@@ -582,9 +580,9 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id) ...@@ -582,9 +580,9 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
static int exynos5433_decon_suspend(struct device *dev) static int exynos5433_decon_suspend(struct device *dev)
{ {
struct decon_context *ctx = dev_get_drvdata(dev); struct decon_context *ctx = dev_get_drvdata(dev);
int i; int i = ARRAY_SIZE(decon_clks_name);
for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) while (--i >= 0)
clk_disable_unprepare(ctx->clks[i]); clk_disable_unprepare(ctx->clks[i]);
return 0; return 0;
......
...@@ -1782,6 +1782,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, ...@@ -1782,6 +1782,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
bridge = of_drm_find_bridge(dsi->bridge_node); bridge = of_drm_find_bridge(dsi->bridge_node);
if (bridge) { if (bridge) {
encoder->bridge = bridge;
drm_bridge_attach(drm_dev, bridge); drm_bridge_attach(drm_dev, bridge);
} }
......
...@@ -50,7 +50,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info, ...@@ -50,7 +50,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
if (vm_size > exynos_gem->size) if (vm_size > exynos_gem->size)
return -EINVAL; return -EINVAL;
ret = dma_mmap_attrs(helper->dev->dev, vma, exynos_gem->pages, ret = dma_mmap_attrs(helper->dev->dev, vma, exynos_gem->cookie,
exynos_gem->dma_addr, exynos_gem->size, exynos_gem->dma_addr, exynos_gem->size,
&exynos_gem->dma_attrs); &exynos_gem->dma_attrs);
if (ret < 0) { if (ret < 0) {
......
...@@ -1723,7 +1723,7 @@ static int fimc_probe(struct platform_device *pdev) ...@@ -1723,7 +1723,7 @@ static int fimc_probe(struct platform_device *pdev)
goto err_put_clk; goto err_put_clk;
} }
DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv); DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv);
spin_lock_init(&ctx->lock); spin_lock_init(&ctx->lock);
platform_set_drvdata(pdev, ctx); platform_set_drvdata(pdev, ctx);
......
...@@ -1166,7 +1166,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, ...@@ -1166,7 +1166,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
goto err_free_event; goto err_free_event;
} }
cmd = (struct drm_exynos_g2d_cmd *)(uint32_t)req->cmd; cmd = (struct drm_exynos_g2d_cmd *)(unsigned long)req->cmd;
if (copy_from_user(cmdlist->data + cmdlist->last, if (copy_from_user(cmdlist->data + cmdlist->last,
(void __user *)cmd, (void __user *)cmd,
...@@ -1184,7 +1184,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, ...@@ -1184,7 +1184,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
if (req->cmd_buf_nr) { if (req->cmd_buf_nr) {
struct drm_exynos_g2d_cmd *cmd_buf; struct drm_exynos_g2d_cmd *cmd_buf;
cmd_buf = (struct drm_exynos_g2d_cmd *)(uint32_t)req->cmd_buf; cmd_buf = (struct drm_exynos_g2d_cmd *)
(unsigned long)req->cmd_buf;
if (copy_from_user(cmdlist->data + cmdlist->last, if (copy_from_user(cmdlist->data + cmdlist->last,
(void __user *)cmd_buf, (void __user *)cmd_buf,
......
...@@ -218,7 +218,7 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev, ...@@ -218,7 +218,7 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); DRM_DEBUG_KMS("created file object = %p\n", obj->filp);
return exynos_gem; return exynos_gem;
} }
...@@ -335,7 +335,7 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem, ...@@ -335,7 +335,7 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
if (vm_size > exynos_gem->size) if (vm_size > exynos_gem->size)
return -EINVAL; return -EINVAL;
ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->pages, ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->cookie,
exynos_gem->dma_addr, exynos_gem->size, exynos_gem->dma_addr, exynos_gem->size,
&exynos_gem->dma_attrs); &exynos_gem->dma_attrs);
if (ret < 0) { if (ret < 0) {
......
...@@ -1723,7 +1723,7 @@ static int gsc_probe(struct platform_device *pdev) ...@@ -1723,7 +1723,7 @@ static int gsc_probe(struct platform_device *pdev)
return ret; return ret;
} }
DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv); DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv);
mutex_init(&ctx->lock); mutex_init(&ctx->lock);
platform_set_drvdata(pdev, ctx); platform_set_drvdata(pdev, ctx);
......
...@@ -208,7 +208,7 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id) ...@@ -208,7 +208,7 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)
* e.g PAUSE state, queue buf, command control. * e.g PAUSE state, queue buf, command control.
*/ */
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n", count++, (int)ippdrv); DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n", count++, ippdrv);
mutex_lock(&ippdrv->cmd_lock); mutex_lock(&ippdrv->cmd_lock);
list_for_each_entry(c_node, &ippdrv->cmd_list, list) { list_for_each_entry(c_node, &ippdrv->cmd_list, list) {
...@@ -388,8 +388,8 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, ...@@ -388,8 +388,8 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
} }
property->prop_id = ret; property->prop_id = ret;
DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[0x%x]\n", DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[%p]\n",
property->prop_id, property->cmd, (int)ippdrv); property->prop_id, property->cmd, ippdrv);
/* stored property information and ippdrv in private data */ /* stored property information and ippdrv in private data */
c_node->property = *property; c_node->property = *property;
...@@ -518,7 +518,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev, ...@@ -518,7 +518,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev,
{ {
int i; int i;
DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node); DRM_DEBUG_KMS("node[%p]\n", m_node);
if (!m_node) { if (!m_node) {
DRM_ERROR("invalid dequeue node.\n"); DRM_ERROR("invalid dequeue node.\n");
...@@ -562,7 +562,7 @@ static struct drm_exynos_ipp_mem_node ...@@ -562,7 +562,7 @@ static struct drm_exynos_ipp_mem_node
m_node->buf_id = qbuf->buf_id; m_node->buf_id = qbuf->buf_id;
INIT_LIST_HEAD(&m_node->list); INIT_LIST_HEAD(&m_node->list);
DRM_DEBUG_KMS("m_node[0x%x]ops_id[%d]\n", (int)m_node, qbuf->ops_id); DRM_DEBUG_KMS("m_node[%p]ops_id[%d]\n", m_node, qbuf->ops_id);
DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id); DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id);
for_each_ipp_planar(i) { for_each_ipp_planar(i) {
...@@ -582,8 +582,8 @@ static struct drm_exynos_ipp_mem_node ...@@ -582,8 +582,8 @@ static struct drm_exynos_ipp_mem_node
buf_info->handles[i] = qbuf->handle[i]; buf_info->handles[i] = qbuf->handle[i];
buf_info->base[i] = *addr; buf_info->base[i] = *addr;
DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%lx]\n", i, DRM_DEBUG_KMS("i[%d]base[%pad]hd[0x%lx]\n", i,
buf_info->base[i], buf_info->handles[i]); &buf_info->base[i], buf_info->handles[i]);
} }
} }
...@@ -664,7 +664,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node, ...@@ -664,7 +664,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
mutex_lock(&c_node->event_lock); mutex_lock(&c_node->event_lock);
list_for_each_entry_safe(e, te, &c_node->event_list, base.link) { list_for_each_entry_safe(e, te, &c_node->event_list, base.link) {
DRM_DEBUG_KMS("count[%d]e[0x%x]\n", count++, (int)e); DRM_DEBUG_KMS("count[%d]e[%p]\n", count++, e);
/* /*
* qbuf == NULL condition means all event deletion. * qbuf == NULL condition means all event deletion.
...@@ -755,7 +755,7 @@ static struct drm_exynos_ipp_mem_node ...@@ -755,7 +755,7 @@ static struct drm_exynos_ipp_mem_node
/* find memory node from memory list */ /* find memory node from memory list */
list_for_each_entry(m_node, head, list) { list_for_each_entry(m_node, head, list) {
DRM_DEBUG_KMS("count[%d]m_node[0x%x]\n", count++, (int)m_node); DRM_DEBUG_KMS("count[%d]m_node[%p]\n", count++, m_node);
/* compare buffer id */ /* compare buffer id */
if (m_node->buf_id == qbuf->buf_id) if (m_node->buf_id == qbuf->buf_id)
...@@ -772,7 +772,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv, ...@@ -772,7 +772,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
struct exynos_drm_ipp_ops *ops = NULL; struct exynos_drm_ipp_ops *ops = NULL;
int ret = 0; int ret = 0;
DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node); DRM_DEBUG_KMS("node[%p]\n", m_node);
if (!m_node) { if (!m_node) {
DRM_ERROR("invalid queue node.\n"); DRM_ERROR("invalid queue node.\n");
...@@ -1237,7 +1237,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv, ...@@ -1237,7 +1237,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
m_node = list_first_entry(head, m_node = list_first_entry(head,
struct drm_exynos_ipp_mem_node, list); struct drm_exynos_ipp_mem_node, list);
DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node); DRM_DEBUG_KMS("m_node[%p]\n", m_node);
ret = ipp_set_mem_node(ippdrv, c_node, m_node); ret = ipp_set_mem_node(ippdrv, c_node, m_node);
if (ret) { if (ret) {
...@@ -1610,8 +1610,8 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev) ...@@ -1610,8 +1610,8 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
} }
ippdrv->prop_list.ipp_id = ret; ippdrv->prop_list.ipp_id = ret;
DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n", DRM_DEBUG_KMS("count[%d]ippdrv[%p]ipp_id[%d]\n",
count++, (int)ippdrv, ret); count++, ippdrv, ret);
/* store parent device for node */ /* store parent device for node */
ippdrv->parent_dev = dev; ippdrv->parent_dev = dev;
...@@ -1668,7 +1668,7 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev, ...@@ -1668,7 +1668,7 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
file_priv->ipp_dev = dev; file_priv->ipp_dev = dev;
DRM_DEBUG_KMS("done priv[0x%x]\n", (int)dev); DRM_DEBUG_KMS("done priv[%p]\n", dev);
return 0; return 0;
} }
...@@ -1685,8 +1685,8 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev, ...@@ -1685,8 +1685,8 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
mutex_lock(&ippdrv->cmd_lock); mutex_lock(&ippdrv->cmd_lock);
list_for_each_entry_safe(c_node, tc_node, list_for_each_entry_safe(c_node, tc_node,
&ippdrv->cmd_list, list) { &ippdrv->cmd_list, list) {
DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n", DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n",
count++, (int)ippdrv); count++, ippdrv);
if (c_node->filp == file) { if (c_node->filp == file) {
/* /*
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/component.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -306,9 +307,9 @@ static int parse_dt(struct exynos_mic *mic) ...@@ -306,9 +307,9 @@ static int parse_dt(struct exynos_mic *mic)
return ret; return ret;
} }
void mic_disable(struct drm_bridge *bridge) { } static void mic_disable(struct drm_bridge *bridge) { }
void mic_post_disable(struct drm_bridge *bridge) static void mic_post_disable(struct drm_bridge *bridge)
{ {
struct exynos_mic *mic = bridge->driver_private; struct exynos_mic *mic = bridge->driver_private;
int i; int i;
...@@ -328,7 +329,7 @@ void mic_post_disable(struct drm_bridge *bridge) ...@@ -328,7 +329,7 @@ void mic_post_disable(struct drm_bridge *bridge)
mutex_unlock(&mic_mutex); mutex_unlock(&mic_mutex);
} }
void mic_pre_enable(struct drm_bridge *bridge) static void mic_pre_enable(struct drm_bridge *bridge)
{ {
struct exynos_mic *mic = bridge->driver_private; struct exynos_mic *mic = bridge->driver_private;
int ret, i; int ret, i;
...@@ -371,11 +372,35 @@ void mic_pre_enable(struct drm_bridge *bridge) ...@@ -371,11 +372,35 @@ void mic_pre_enable(struct drm_bridge *bridge)
mutex_unlock(&mic_mutex); mutex_unlock(&mic_mutex);
} }
void mic_enable(struct drm_bridge *bridge) { } static void mic_enable(struct drm_bridge *bridge) { }
void mic_destroy(struct drm_bridge *bridge) static const struct drm_bridge_funcs mic_bridge_funcs = {
.disable = mic_disable,
.post_disable = mic_post_disable,
.pre_enable = mic_pre_enable,
.enable = mic_enable,
};
static int exynos_mic_bind(struct device *dev, struct device *master,
void *data)
{ {
struct exynos_mic *mic = bridge->driver_private; struct exynos_mic *mic = dev_get_drvdata(dev);
int ret;
mic->bridge.funcs = &mic_bridge_funcs;
mic->bridge.of_node = dev->of_node;
mic->bridge.driver_private = mic;
ret = drm_bridge_add(&mic->bridge);
if (ret)
DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
return ret;
}
static void exynos_mic_unbind(struct device *dev, struct device *master,
void *data)
{
struct exynos_mic *mic = dev_get_drvdata(dev);
int i; int i;
mutex_lock(&mic_mutex); mutex_lock(&mic_mutex);
...@@ -387,16 +412,16 @@ void mic_destroy(struct drm_bridge *bridge) ...@@ -387,16 +412,16 @@ void mic_destroy(struct drm_bridge *bridge)
already_disabled: already_disabled:
mutex_unlock(&mic_mutex); mutex_unlock(&mic_mutex);
drm_bridge_remove(&mic->bridge);
} }
static const struct drm_bridge_funcs mic_bridge_funcs = { static const struct component_ops exynos_mic_component_ops = {
.disable = mic_disable, .bind = exynos_mic_bind,
.post_disable = mic_post_disable, .unbind = exynos_mic_unbind,
.pre_enable = mic_pre_enable,
.enable = mic_enable,
}; };
int exynos_mic_probe(struct platform_device *pdev) static int exynos_mic_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct exynos_mic *mic; struct exynos_mic *mic;
...@@ -435,17 +460,8 @@ int exynos_mic_probe(struct platform_device *pdev) ...@@ -435,17 +460,8 @@ int exynos_mic_probe(struct platform_device *pdev)
goto err; goto err;
} }
mic->bridge.funcs = &mic_bridge_funcs;
mic->bridge.of_node = dev->of_node;
mic->bridge.driver_private = mic;
ret = drm_bridge_add(&mic->bridge);
if (ret) {
DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
goto err;
}
for (i = 0; i < NUM_CLKS; i++) { for (i = 0; i < NUM_CLKS; i++) {
mic->clks[i] = of_clk_get_by_name(dev->of_node, clk_names[i]); mic->clks[i] = devm_clk_get(dev, clk_names[i]);
if (IS_ERR(mic->clks[i])) { if (IS_ERR(mic->clks[i])) {
DRM_ERROR("mic: Failed to get clock (%s)\n", DRM_ERROR("mic: Failed to get clock (%s)\n",
clk_names[i]); clk_names[i]);
...@@ -454,7 +470,10 @@ int exynos_mic_probe(struct platform_device *pdev) ...@@ -454,7 +470,10 @@ int exynos_mic_probe(struct platform_device *pdev)
} }
} }
platform_set_drvdata(pdev, mic);
DRM_DEBUG_KMS("MIC has been probed\n"); DRM_DEBUG_KMS("MIC has been probed\n");
return component_add(dev, &exynos_mic_component_ops);
err: err:
return ret; return ret;
...@@ -462,14 +481,7 @@ int exynos_mic_probe(struct platform_device *pdev) ...@@ -462,14 +481,7 @@ int exynos_mic_probe(struct platform_device *pdev)
static int exynos_mic_remove(struct platform_device *pdev) static int exynos_mic_remove(struct platform_device *pdev)
{ {
struct exynos_mic *mic = platform_get_drvdata(pdev); component_del(&pdev->dev, &exynos_mic_component_ops);
int i;
drm_bridge_remove(&mic->bridge);
for (i = NUM_CLKS - 1; i > -1; i--)
clk_put(mic->clks[i]);
return 0; return 0;
} }
......
...@@ -754,7 +754,7 @@ static int rotator_probe(struct platform_device *pdev) ...@@ -754,7 +754,7 @@ static int rotator_probe(struct platform_device *pdev)
goto err_ippdrv_register; goto err_ippdrv_register;
} }
DRM_DEBUG_KMS("ippdrv[0x%x]\n", (int)ippdrv); DRM_DEBUG_KMS("ippdrv[%p]\n", ippdrv);
platform_set_drvdata(pdev, rot); platform_set_drvdata(pdev, rot);
......
...@@ -223,7 +223,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work) ...@@ -223,7 +223,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
} }
} }
static int vidi_show_connection(struct device *dev, static ssize_t vidi_show_connection(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct vidi_context *ctx = dev_get_drvdata(dev); struct vidi_context *ctx = dev_get_drvdata(dev);
...@@ -238,7 +238,7 @@ static int vidi_show_connection(struct device *dev, ...@@ -238,7 +238,7 @@ static int vidi_show_connection(struct device *dev,
return rc; return rc;
} }
static int vidi_store_connection(struct device *dev, static ssize_t vidi_store_connection(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t len) const char *buf, size_t len)
{ {
...@@ -294,7 +294,9 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, ...@@ -294,7 +294,9 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
} }
if (vidi->connection) { if (vidi->connection) {
struct edid *raw_edid = (struct edid *)(uint32_t)vidi->edid; struct edid *raw_edid;
raw_edid = (struct edid *)(unsigned long)vidi->edid;
if (!drm_edid_is_valid(raw_edid)) { if (!drm_edid_is_valid(raw_edid)) {
DRM_DEBUG_KMS("edid data is invalid.\n"); DRM_DEBUG_KMS("edid data is invalid.\n");
return -EINVAL; return -EINVAL;
......
...@@ -635,10 +635,6 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) ...@@ -635,10 +635,6 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
nv_crtc->lut.depth = 0; nv_crtc->lut.depth = 0;
} }
/* Make sure that drm and hw vblank irqs get resumed if needed. */
for (head = 0; head < dev->mode_config.num_crtc; head++)
drm_vblank_on(dev, head);
/* This should ensure we don't hit a locking problem when someone /* This should ensure we don't hit a locking problem when someone
* wakes us up via a connector. We should never go into suspend * wakes us up via a connector. We should never go into suspend
* while the display is on anyways. * while the display is on anyways.
...@@ -648,6 +644,10 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) ...@@ -648,6 +644,10 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
drm_helper_resume_force_mode(dev); drm_helper_resume_force_mode(dev);
/* Make sure that drm and hw vblank irqs get resumed if needed. */
for (head = 0; head < dev->mode_config.num_crtc; head++)
drm_vblank_on(dev, head);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
......
...@@ -168,7 +168,8 @@ static int qxl_process_single_command(struct qxl_device *qdev, ...@@ -168,7 +168,8 @@ static int qxl_process_single_command(struct qxl_device *qdev,
cmd->command_size)) cmd->command_size))
return -EFAULT; return -EFAULT;
reloc_info = kmalloc(sizeof(struct qxl_reloc_info) * cmd->relocs_num, GFP_KERNEL); reloc_info = kmalloc_array(cmd->relocs_num,
sizeof(struct qxl_reloc_info), GFP_KERNEL);
if (!reloc_info) if (!reloc_info)
return -ENOMEM; return -ENOMEM;
......
...@@ -68,5 +68,5 @@ int qxl_gem_prime_mmap(struct drm_gem_object *obj, ...@@ -68,5 +68,5 @@ int qxl_gem_prime_mmap(struct drm_gem_object *obj,
struct vm_area_struct *area) struct vm_area_struct *area)
{ {
WARN_ONCE(1, "not implemented"); WARN_ONCE(1, "not implemented");
return ENOSYS; return -ENOSYS;
} }
...@@ -276,8 +276,12 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) ...@@ -276,8 +276,12 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
if (rdev->irq.installed) { if (rdev->irq.installed) {
for (i = 0; i < rdev->num_crtc; i++) { for (i = 0; i < rdev->num_crtc; i++) {
if (rdev->pm.active_crtcs & (1 << i)) { if (rdev->pm.active_crtcs & (1 << i)) {
/* This can fail if a modeset is in progress */
if (drm_vblank_get(rdev->ddev, i) == 0)
rdev->pm.req_vblank |= (1 << i); rdev->pm.req_vblank |= (1 << i);
drm_vblank_get(rdev->ddev, i); else
DRM_DEBUG_DRIVER("crtc %d no vblank, can glitch\n",
i);
} }
} }
} }
......
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