aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2011-11-14 17:51:28 -0500
committerDave Airlie <airlied@redhat.com>2011-11-15 14:53:23 -0500
commit308e5bcbdb10452e8aba31aa21432fb67ee46d72 (patch)
tree5e4eebef07685c4047f54d1727fc9bcbace8889d /drivers/gpu/drm/drm_crtc.c
parent8cf5c9177151537e73ff1816540e4ba24b174391 (diff)
drm: add an fb creation ioctl that takes a pixel format v5
To properly support the various plane formats supported by different hardware, the kernel must know the pixel format of a framebuffer object. So add a new ioctl taking a format argument corresponding to a fourcc name from the new drm_fourcc.h header file. Implement the fb creation hooks in terms of the new mode_fb_cmd2 using helpers where the old bpp/depth values are needed. v2: create DRM specific fourcc header file for sharing with libdrm etc v3: fix rebase failure and use DRM fourcc codes in intel_display.c and update commit message v4: make fb_cmd2 handle field into an array for multi-object formats pull in Ville's fix for the memcpy in drm_plane_init apply Ville's cleanup to zero out fb_cmd2 arg in drm_mode_addfb v5: add 'flags' field for interlaced support (from Ville) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Reviewed-by: Rob Clark <rob.clark@linaro.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c111
1 files changed, 106 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5e1df76c8f72..e54c0a6a3072 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -36,6 +36,7 @@
36#include "drmP.h" 36#include "drmP.h"
37#include "drm_crtc.h" 37#include "drm_crtc.h"
38#include "drm_edid.h" 38#include "drm_edid.h"
39#include "drm_fourcc.h"
39 40
40struct drm_prop_enum_list { 41struct drm_prop_enum_list {
41 int type; 42 int type;
@@ -568,7 +569,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
568 return -ENOMEM; 569 return -ENOMEM;
569 } 570 }
570 571
571 memcpy(plane->format_types, formats, format_count); 572 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
572 plane->format_count = format_count; 573 plane->format_count = format_count;
573 plane->possible_crtcs = possible_crtcs; 574 plane->possible_crtcs = possible_crtcs;
574 575
@@ -1915,6 +1916,42 @@ out:
1915 return ret; 1916 return ret;
1916} 1917}
1917 1918
1919/* Original addfb only supported RGB formats, so figure out which one */
1920uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
1921{
1922 uint32_t fmt;
1923
1924 switch (bpp) {
1925 case 8:
1926 fmt = DRM_FOURCC_RGB332;
1927 break;
1928 case 16:
1929 if (depth == 15)
1930 fmt = DRM_FOURCC_RGB555;
1931 else
1932 fmt = DRM_FOURCC_RGB565;
1933 break;
1934 case 24:
1935 fmt = DRM_FOURCC_RGB24;
1936 break;
1937 case 32:
1938 if (depth == 24)
1939 fmt = DRM_FOURCC_RGB24;
1940 else if (depth == 30)
1941 fmt = DRM_INTEL_RGB30;
1942 else
1943 fmt = DRM_FOURCC_RGB32;
1944 break;
1945 default:
1946 DRM_ERROR("bad bpp, assuming RGB24 pixel format\n");
1947 fmt = DRM_FOURCC_RGB24;
1948 break;
1949 }
1950
1951 return fmt;
1952}
1953EXPORT_SYMBOL(drm_mode_legacy_fb_format);
1954
1918/** 1955/**
1919 * drm_mode_addfb - add an FB to the graphics configuration 1956 * drm_mode_addfb - add an FB to the graphics configuration
1920 * @inode: inode from the ioctl 1957 * @inode: inode from the ioctl
@@ -1935,7 +1972,74 @@ out:
1935int drm_mode_addfb(struct drm_device *dev, 1972int drm_mode_addfb(struct drm_device *dev,
1936 void *data, struct drm_file *file_priv) 1973 void *data, struct drm_file *file_priv)
1937{ 1974{
1938 struct drm_mode_fb_cmd *r = data; 1975 struct drm_mode_fb_cmd *or = data;
1976 struct drm_mode_fb_cmd2 r = {};
1977 struct drm_mode_config *config = &dev->mode_config;
1978 struct drm_framebuffer *fb;
1979 int ret = 0;
1980
1981 /* Use new struct with format internally */
1982 r.fb_id = or->fb_id;
1983 r.width = or->width;
1984 r.height = or->height;
1985 r.pitches[0] = or->pitch;
1986 r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
1987 r.handles[0] = or->handle;
1988
1989 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1990 return -EINVAL;
1991
1992 if ((config->min_width > r.width) || (r.width > config->max_width)) {
1993 DRM_ERROR("mode new framebuffer width not within limits\n");
1994 return -EINVAL;
1995 }
1996 if ((config->min_height > r.height) || (r.height > config->max_height)) {
1997 DRM_ERROR("mode new framebuffer height not within limits\n");
1998 return -EINVAL;
1999 }
2000
2001 mutex_lock(&dev->mode_config.mutex);
2002
2003 /* TODO check buffer is sufficiently large */
2004 /* TODO setup destructor callback */
2005
2006 fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
2007 if (IS_ERR(fb)) {
2008 DRM_ERROR("could not create framebuffer\n");
2009 ret = PTR_ERR(fb);
2010 goto out;
2011 }
2012
2013 or->fb_id = fb->base.id;
2014 list_add(&fb->filp_head, &file_priv->fbs);
2015 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
2016
2017out:
2018 mutex_unlock(&dev->mode_config.mutex);
2019 return ret;
2020}
2021
2022/**
2023 * drm_mode_addfb2 - add an FB to the graphics configuration
2024 * @inode: inode from the ioctl
2025 * @filp: file * from the ioctl
2026 * @cmd: cmd from ioctl
2027 * @arg: arg from ioctl
2028 *
2029 * LOCKING:
2030 * Takes mode config lock.
2031 *
2032 * Add a new FB to the specified CRTC, given a user request with format.
2033 *
2034 * Called by the user via ioctl.
2035 *
2036 * RETURNS:
2037 * Zero on success, errno on failure.
2038 */
2039int drm_mode_addfb2(struct drm_device *dev,
2040 void *data, struct drm_file *file_priv)
2041{
2042 struct drm_mode_fb_cmd2 *r = data;
1939 struct drm_mode_config *config = &dev->mode_config; 2043 struct drm_mode_config *config = &dev->mode_config;
1940 struct drm_framebuffer *fb; 2044 struct drm_framebuffer *fb;
1941 int ret = 0; 2045 int ret = 0;
@@ -1956,9 +2060,6 @@ int drm_mode_addfb(struct drm_device *dev,
1956 2060
1957 mutex_lock(&dev->mode_config.mutex); 2061 mutex_lock(&dev->mode_config.mutex);
1958 2062
1959 /* TODO check buffer is sufficiently large */
1960 /* TODO setup destructor callback */
1961
1962 fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); 2063 fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
1963 if (IS_ERR(fb)) { 2064 if (IS_ERR(fb)) {
1964 DRM_ERROR("could not create framebuffer\n"); 2065 DRM_ERROR("could not create framebuffer\n");