aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2011-11-14 17:51:27 -0500
committerDave Airlie <airlied@redhat.com>2011-11-15 14:53:10 -0500
commit8cf5c9177151537e73ff1816540e4ba24b174391 (patch)
tree0b805659ef5b68550b37166c5d98319c4fde5639 /drivers/gpu
parente08e96de986ceb2c6b683df0bd0c4ddd4f91dcfd (diff)
drm: add plane support v3
Planes are a bit like half-CRTCs. They have a location and fb, but don't drive outputs directly. Add support for handling them to the core KMS code. v2: fix ABI of get_plane - move format_type_ptr to the end v3: add 'flags' field for interlaced support (from Ville) Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Reviewed-by: Rob Clark <rob.clark@linaro.org> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/drm_crtc.c257
-rw-r--r--drivers/gpu/drm/drm_drv.c3
2 files changed, 258 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9a2e2a14b3bb..5e1df76c8f72 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -324,6 +324,7 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
324{ 324{
325 struct drm_device *dev = fb->dev; 325 struct drm_device *dev = fb->dev;
326 struct drm_crtc *crtc; 326 struct drm_crtc *crtc;
327 struct drm_plane *plane;
327 struct drm_mode_set set; 328 struct drm_mode_set set;
328 int ret; 329 int ret;
329 330
@@ -340,6 +341,15 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
340 } 341 }
341 } 342 }
342 343
344 list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
345 if (plane->fb == fb) {
346 /* should turn off the crtc */
347 ret = plane->funcs->disable_plane(plane);
348 if (ret)
349 DRM_ERROR("failed to disable plane with busy fb\n");
350 }
351 }
352
343 drm_mode_object_put(dev, &fb->base); 353 drm_mode_object_put(dev, &fb->base);
344 list_del(&fb->head); 354 list_del(&fb->head);
345 dev->mode_config.num_fb--; 355 dev->mode_config.num_fb--;
@@ -540,6 +550,50 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
540} 550}
541EXPORT_SYMBOL(drm_encoder_cleanup); 551EXPORT_SYMBOL(drm_encoder_cleanup);
542 552
553int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
554 unsigned long possible_crtcs,
555 const struct drm_plane_funcs *funcs,
556 uint32_t *formats, uint32_t format_count)
557{
558 mutex_lock(&dev->mode_config.mutex);
559
560 plane->dev = dev;
561 drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
562 plane->funcs = funcs;
563 plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
564 GFP_KERNEL);
565 if (!plane->format_types) {
566 DRM_DEBUG_KMS("out of memory when allocating plane\n");
567 drm_mode_object_put(dev, &plane->base);
568 return -ENOMEM;
569 }
570
571 memcpy(plane->format_types, formats, format_count);
572 plane->format_count = format_count;
573 plane->possible_crtcs = possible_crtcs;
574
575 list_add_tail(&plane->head, &dev->mode_config.plane_list);
576 dev->mode_config.num_plane++;
577
578 mutex_unlock(&dev->mode_config.mutex);
579
580 return 0;
581}
582EXPORT_SYMBOL(drm_plane_init);
583
584void drm_plane_cleanup(struct drm_plane *plane)
585{
586 struct drm_device *dev = plane->dev;
587
588 mutex_lock(&dev->mode_config.mutex);
589 kfree(plane->format_types);
590 drm_mode_object_put(dev, &plane->base);
591 list_del(&plane->head);
592 dev->mode_config.num_plane--;
593 mutex_unlock(&dev->mode_config.mutex);
594}
595EXPORT_SYMBOL(drm_plane_cleanup);
596
543/** 597/**
544 * drm_mode_create - create a new display mode 598 * drm_mode_create - create a new display mode
545 * @dev: DRM device 599 * @dev: DRM device
@@ -871,6 +925,7 @@ void drm_mode_config_init(struct drm_device *dev)
871 INIT_LIST_HEAD(&dev->mode_config.encoder_list); 925 INIT_LIST_HEAD(&dev->mode_config.encoder_list);
872 INIT_LIST_HEAD(&dev->mode_config.property_list); 926 INIT_LIST_HEAD(&dev->mode_config.property_list);
873 INIT_LIST_HEAD(&dev->mode_config.property_blob_list); 927 INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
928 INIT_LIST_HEAD(&dev->mode_config.plane_list);
874 idr_init(&dev->mode_config.crtc_idr); 929 idr_init(&dev->mode_config.crtc_idr);
875 930
876 mutex_lock(&dev->mode_config.mutex); 931 mutex_lock(&dev->mode_config.mutex);
@@ -947,6 +1002,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
947 struct drm_encoder *encoder, *enct; 1002 struct drm_encoder *encoder, *enct;
948 struct drm_framebuffer *fb, *fbt; 1003 struct drm_framebuffer *fb, *fbt;
949 struct drm_property *property, *pt; 1004 struct drm_property *property, *pt;
1005 struct drm_plane *plane, *plt;
950 1006
951 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, 1007 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
952 head) { 1008 head) {
@@ -971,6 +1027,10 @@ void drm_mode_config_cleanup(struct drm_device *dev)
971 crtc->funcs->destroy(crtc); 1027 crtc->funcs->destroy(crtc);
972 } 1028 }
973 1029
1030 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
1031 head) {
1032 plane->funcs->destroy(plane);
1033 }
974} 1034}
975EXPORT_SYMBOL(drm_mode_config_cleanup); 1035EXPORT_SYMBOL(drm_mode_config_cleanup);
976 1036
@@ -1471,6 +1531,197 @@ out:
1471} 1531}
1472 1532
1473/** 1533/**
1534 * drm_mode_getplane_res - get plane info
1535 * @dev: DRM device
1536 * @data: ioctl data
1537 * @file_priv: DRM file info
1538 *
1539 * Return an plane count and set of IDs.
1540 */
1541int drm_mode_getplane_res(struct drm_device *dev, void *data,
1542 struct drm_file *file_priv)
1543{
1544 struct drm_mode_get_plane_res *plane_resp = data;
1545 struct drm_mode_config *config;
1546 struct drm_plane *plane;
1547 uint32_t __user *plane_ptr;
1548 int copied = 0, ret = 0;
1549
1550 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1551 return -EINVAL;
1552
1553 mutex_lock(&dev->mode_config.mutex);
1554 config = &dev->mode_config;
1555
1556 /*
1557 * This ioctl is called twice, once to determine how much space is
1558 * needed, and the 2nd time to fill it.
1559 */
1560 if (config->num_plane &&
1561 (plane_resp->count_planes >= config->num_plane)) {
1562 plane_ptr = (uint32_t *)(unsigned long)plane_resp->plane_id_ptr;
1563
1564 list_for_each_entry(plane, &config->plane_list, head) {
1565 if (put_user(plane->base.id, plane_ptr + copied)) {
1566 ret = -EFAULT;
1567 goto out;
1568 }
1569 copied++;
1570 }
1571 }
1572 plane_resp->count_planes = config->num_plane;
1573
1574out:
1575 mutex_unlock(&dev->mode_config.mutex);
1576 return ret;
1577}
1578
1579/**
1580 * drm_mode_getplane - get plane info
1581 * @dev: DRM device
1582 * @data: ioctl data
1583 * @file_priv: DRM file info
1584 *
1585 * Return plane info, including formats supported, gamma size, any
1586 * current fb, etc.
1587 */
1588int drm_mode_getplane(struct drm_device *dev, void *data,
1589 struct drm_file *file_priv)
1590{
1591 struct drm_mode_get_plane *plane_resp = data;
1592 struct drm_mode_object *obj;
1593 struct drm_plane *plane;
1594 uint32_t __user *format_ptr;
1595 int ret = 0;
1596
1597 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1598 return -EINVAL;
1599
1600 mutex_lock(&dev->mode_config.mutex);
1601 obj = drm_mode_object_find(dev, plane_resp->plane_id,
1602 DRM_MODE_OBJECT_PLANE);
1603 if (!obj) {
1604 ret = -ENOENT;
1605 goto out;
1606 }
1607 plane = obj_to_plane(obj);
1608
1609 if (plane->crtc)
1610 plane_resp->crtc_id = plane->crtc->base.id;
1611 else
1612 plane_resp->crtc_id = 0;
1613
1614 if (plane->fb)
1615 plane_resp->fb_id = plane->fb->base.id;
1616 else
1617 plane_resp->fb_id = 0;
1618
1619 plane_resp->plane_id = plane->base.id;
1620 plane_resp->possible_crtcs = plane->possible_crtcs;
1621 plane_resp->gamma_size = plane->gamma_size;
1622
1623 /*
1624 * This ioctl is called twice, once to determine how much space is
1625 * needed, and the 2nd time to fill it.
1626 */
1627 if (plane->format_count &&
1628 (plane_resp->count_format_types >= plane->format_count)) {
1629 format_ptr = (uint32_t *)(unsigned long)plane_resp->format_type_ptr;
1630 if (copy_to_user(format_ptr,
1631 plane->format_types,
1632 sizeof(uint32_t) * plane->format_count)) {
1633 ret = -EFAULT;
1634 goto out;
1635 }
1636 }
1637 plane_resp->count_format_types = plane->format_count;
1638
1639out:
1640 mutex_unlock(&dev->mode_config.mutex);
1641 return ret;
1642}
1643
1644/**
1645 * drm_mode_setplane - set up or tear down an plane
1646 * @dev: DRM device
1647 * @data: ioctl data*
1648 * @file_prive: DRM file info
1649 *
1650 * Set plane info, including placement, fb, scaling, and other factors.
1651 * Or pass a NULL fb to disable.
1652 */
1653int drm_mode_setplane(struct drm_device *dev, void *data,
1654 struct drm_file *file_priv)
1655{
1656 struct drm_mode_set_plane *plane_req = data;
1657 struct drm_mode_object *obj;
1658 struct drm_plane *plane;
1659 struct drm_crtc *crtc;
1660 struct drm_framebuffer *fb;
1661 int ret = 0;
1662
1663 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1664 return -EINVAL;
1665
1666 mutex_lock(&dev->mode_config.mutex);
1667
1668 /*
1669 * First, find the plane, crtc, and fb objects. If not available,
1670 * we don't bother to call the driver.
1671 */
1672 obj = drm_mode_object_find(dev, plane_req->plane_id,
1673 DRM_MODE_OBJECT_PLANE);
1674 if (!obj) {
1675 DRM_DEBUG_KMS("Unknown plane ID %d\n",
1676 plane_req->plane_id);
1677 ret = -ENOENT;
1678 goto out;
1679 }
1680 plane = obj_to_plane(obj);
1681
1682 /* No fb means shut it down */
1683 if (!plane_req->fb_id) {
1684 plane->funcs->disable_plane(plane);
1685 goto out;
1686 }
1687
1688 obj = drm_mode_object_find(dev, plane_req->crtc_id,
1689 DRM_MODE_OBJECT_CRTC);
1690 if (!obj) {
1691 DRM_DEBUG_KMS("Unknown crtc ID %d\n",
1692 plane_req->crtc_id);
1693 ret = -ENOENT;
1694 goto out;
1695 }
1696 crtc = obj_to_crtc(obj);
1697
1698 obj = drm_mode_object_find(dev, plane_req->fb_id,
1699 DRM_MODE_OBJECT_FB);
1700 if (!obj) {
1701 DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
1702 plane_req->fb_id);
1703 ret = -ENOENT;
1704 goto out;
1705 }
1706 fb = obj_to_fb(obj);
1707
1708 ret = plane->funcs->update_plane(plane, crtc, fb,
1709 plane_req->crtc_x, plane_req->crtc_y,
1710 plane_req->crtc_w, plane_req->crtc_h,
1711 plane_req->src_x, plane_req->src_y,
1712 plane_req->src_w, plane_req->src_h);
1713 if (!ret) {
1714 plane->crtc = crtc;
1715 plane->fb = fb;
1716 }
1717
1718out:
1719 mutex_unlock(&dev->mode_config.mutex);
1720
1721 return ret;
1722}
1723
1724/**
1474 * drm_mode_setcrtc - set CRTC configuration 1725 * drm_mode_setcrtc - set CRTC configuration
1475 * @inode: inode from the ioctl 1726 * @inode: inode from the ioctl
1476 * @filp: file * from the ioctl 1727 * @filp: file * from the ioctl
@@ -1693,11 +1944,13 @@ int drm_mode_addfb(struct drm_device *dev,
1693 return -EINVAL; 1944 return -EINVAL;
1694 1945
1695 if ((config->min_width > r->width) || (r->width > config->max_width)) { 1946 if ((config->min_width > r->width) || (r->width > config->max_width)) {
1696 DRM_ERROR("mode new framebuffer width not within limits\n"); 1947 DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n",
1948 r->width, config->min_width, config->max_width);
1697 return -EINVAL; 1949 return -EINVAL;
1698 } 1950 }
1699 if ((config->min_height > r->height) || (r->height > config->max_height)) { 1951 if ((config->min_height > r->height) || (r->height > config->max_height)) {
1700 DRM_ERROR("mode new framebuffer height not within limits\n"); 1952 DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n",
1953 r->height, config->min_height, config->max_height);
1701 return -EINVAL; 1954 return -EINVAL;
1702 } 1955 }
1703 1956
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index fc81af9dbf42..4f25989b0d4a 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -136,8 +136,11 @@ static struct drm_ioctl_desc drm_ioctls[] = {
136 DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), 136 DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
137 137
138 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 138 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
139 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
139 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 140 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
140 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 141 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
142 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
143 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
141 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), 144 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
142 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED), 145 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
143 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED), 146 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),