summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Marchenko <r.marchenko@samsung.com>2015-10-21 18:27:38 +0300
committerSangjin Lee <lsj119@samsung.com>2015-11-23 22:23:28 -0800
commit4b59e48cdfbfa1c845be270eb6068123af3a6a4e (patch)
tree36398174798b0992df1cf8b4229e29fe2fd2456a
parent01e5a24518a3fb0f936deeb477a5edef61f60aa7 (diff)
downloadlibdrm-4b59e48cdfbfa1c845be270eb6068123af3a6a4e.tar.gz
libdrm-4b59e48cdfbfa1c845be270eb6068123af3a6a4e.tar.bz2
libdrm-4b59e48cdfbfa1c845be270eb6068123af3a6a4e.zip
[SPRD] Add processing framebuffer
- DRM_IOCTL_MODE_GETFB - DRM_IOCTL_MODE_ADDFB - DRM_IOCTL_MODE_ADDFB2 - DRM_IOCTL_MODE_RMFB Change-Id: I54c6c45cc434d01c57e5d59c6fda3754999a2352 Signed-off-by: Roman Marchenko <r.marchenko@samsung.com>
-rw-r--r--sprd/sprd_drm.c198
1 files changed, 194 insertions, 4 deletions
diff --git a/sprd/sprd_drm.c b/sprd/sprd_drm.c
index fa711270..9d3c86b7 100644
--- a/sprd/sprd_drm.c
+++ b/sprd/sprd_drm.c
@@ -53,6 +53,16 @@
#define U642INTPTR(x) ( (unsigned int*) U642VOID(x) )
#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
+//#define SPRD_DEBUG_MSG 0
+
+#ifdef SPRD_DEBUG_MSG
+ #define SPRD_DRM_DEBUG(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
+ #define SPRD_DRM_ERROR(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
+#else
+ #define SPRD_DRM_DEBUG(fmt, ...)
+ #define SPRD_DRM_ERROR(fmt, ...)
+#endif
+
#define FB_DEV_LCD "/dev/fb0"
//TODO::
@@ -126,6 +136,7 @@ struct sprd_drm_framebuffer {
uint32_t pitches[4];
uint32_t offsets[4];
+ uint32_t handles[4];
uint32_t width;
uint32_t height;
uint32_t depth;
@@ -227,6 +238,113 @@ static void sprd_drm_resource_del(int id)
}
+/*
+ * from kernel
+ * Original addfb only supported RGB formats, so figure out which one
+ */
+uint32_t sprd_drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
+{
+ uint32_t fmt;
+
+ switch (bpp) {
+ case 8:
+ fmt = DRM_FORMAT_C8;
+ break;
+ case 16:
+ if (depth == 15)
+ fmt = DRM_FORMAT_XRGB1555;
+ else
+ fmt = DRM_FORMAT_RGB565;
+ break;
+ case 24:
+ fmt = DRM_FORMAT_RGB888;
+ break;
+ case 32:
+ if (depth == 24)
+ fmt = DRM_FORMAT_XRGB8888;
+ else if (depth == 30)
+ fmt = DRM_FORMAT_XRGB2101010;
+ else
+ fmt = DRM_FORMAT_ARGB8888;
+ break;
+ default:
+ SPRD_DRM_DEBUG("bad bpp, assuming x8r8g8b8 pixel format\n");
+ fmt = DRM_FORMAT_XRGB8888;
+ break;
+ }
+
+ return fmt;
+}
+
+/*
+ * from kernel
+ *
+ * Just need to support RGB formats here for compat with code that doesn't
+ * use pixel formats directly yet.
+ */
+void sprd_drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp)
+{
+ switch (format) {
+ case DRM_FORMAT_C8:
+ case DRM_FORMAT_RGB332:
+ case DRM_FORMAT_BGR233:
+ *depth = 8;
+ *bpp = 8;
+ break;
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_XBGR1555:
+ case DRM_FORMAT_RGBX5551:
+ case DRM_FORMAT_BGRX5551:
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_BGRA5551:
+ *depth = 15;
+ *bpp = 16;
+ break;
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ *depth = 16;
+ *bpp = 16;
+ break;
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_BGR888:
+ *depth = 24;
+ *bpp = 24;
+ break;
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRX8888:
+ *depth = 24;
+ *bpp = 32;
+ break;
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_BGRX1010102:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_BGRA1010102:
+ *depth = 30;
+ *bpp = 32;
+ break;
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_BGRA8888:
+ *depth = 32;
+ *bpp = 32;
+ break;
+ default:
+ SPRD_DRM_DEBUG("unsupported pixel format\n");
+ *depth = 0;
+ *bpp = 0;
+ break;
+ }
+}
+
static inline uint32_t _get_refresh(struct fb_var_screeninfo * timing)
{
uint32_t pixclock, hfreq, htotal, vtotal;
@@ -383,6 +501,42 @@ static int sprd_drm_connector_LCD_create(struct sprd_drm_device * dev, struct sp
return 0;
}
+static int32_t sprd_drm_framebuffer_create(struct sprd_drm_device * dev, struct drm_mode_fb_cmd2 * fb_cmd)
+{
+ struct sprd_drm_framebuffer * fb;
+
+ fb = drmMalloc(sizeof (struct sprd_drm_framebuffer));
+ fb->id = sprd_drm_resource_new_id(fb);
+ fb->refcount = 1;
+ DRMLISTADDTAIL(&fb->link, &dev->crtc_list);
+ dev->num_fb++;
+
+
+ fb->width = fb_cmd->width;
+ fb->height = fb_cmd->height;
+ fb->pixel_format = fb_cmd->pixel_format;
+ fb->flags = fb_cmd->flags;
+
+ sprd_drm_fb_get_bpp_depth(fb_cmd->pixel_format, &fb->depth, &fb->bits_per_pixel);
+
+ memcpy(fb->handles, fb_cmd->handles, 4 * sizeof(fb->handles[0]));
+ memcpy(fb->pitches, fb_cmd->pitches, 4 * sizeof(fb->pitches[0]));
+ memcpy(fb->offsets, fb_cmd->offsets, 4 * sizeof(fb->offsets[0]));
+
+
+ return 0;
+}
+
+static void sprd_drm_framebuffer_remove(struct sprd_drm_device * dev, struct sprd_drm_framebuffer * fb)
+{
+ if (--fb->refcount) {
+ sprd_drm_resource_new_id(fb->id);
+ DRMLISTDEL(&fb->link);
+ dev->num_fb--;
+ drmFree(fb);
+ }
+}
+
static struct sprd_drm_mode_encoder * sprd_drm_encoder_create(struct sprd_drm_device * dev, uint32_t encoder_type)
{
struct sprd_drm_mode_encoder * enc = NULL;
@@ -660,22 +814,58 @@ static int sprd_drm_mode_set_crtc(int fd, void *arg)
static int sprd_drm_mode_add_fb(int fd, void *arg)
{
- return -1;
+ struct drm_mode_fb_cmd *or = (struct drm_mode_fb_cmd *)arg;
+ struct drm_mode_fb_cmd2 r;
+
+ /* Use new struct with format internally */
+ r.fb_id = or->fb_id;
+ r.width = or->width;
+ r.height = or->height;
+ r.pitches[0] = or->pitch;
+ r.pixel_format = sprd_drm_mode_legacy_fb_format(or->bpp, or->depth);
+ r.handles[0] = or->handle;
+
+ return sprd_drm_framebuffer_create(get_sprd_device(fd), &r);
}
static int sprd_drm_mode_add_fb2(int fd, void *arg)
{
- return -1;
+ struct drm_mode_fb_cmd2 *r = (struct drm_mode_fb_cmd *)arg;
+
+ return sprd_drm_framebuffer_create(get_sprd_device(fd), &r);
}
static int sprd_drm_mode_rem_fb(int fd, void *arg)
{
- return -1;
+ struct sprd_drm_framebuffer *fb;
+ uint32_t id = *((uint32_t *)arg);
+
+ fb = (struct sprd_drm_framebuffer *)sprd_drm_resource_get(id);
+
+ if (!fb) return EINVAL;
+
+ sprd_drm_framebuffer_remove(get_sprd_device(fd), fb);
+
+ return 0;
}
static int sprd_drm_mode_get_fb(int fd, void *arg)
{
- return -1;
+ struct drm_mode_fb_cmd *fb_cmd = (struct drm_mode_fb_cmd *)arg;
+ struct sprd_drm_framebuffer *fb = NULL;
+
+ fb = (struct sprd_drm_framebuffer *)sprd_drm_resource_get(fb_cmd->fb_id);
+
+ if (!fb) return EINVAL;
+
+ fb_cmd->width = fb->width;
+ fb_cmd->height = fb->height;
+ fb_cmd->pitch = fb->pitches;
+ fb_cmd->bpp = fb->bits_per_pixel;
+ fb_cmd->depth = fb->depth;
+ fb_cmd->handle = fb->handles[0];
+
+ return 0;
}
static int sprd_drm_mode_page_flip(int fd, void *arg)