]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/omapdrmtest.git/blobdiff - util/display-kms.c
display-kms: Call SetCrtc at init time
[glsdk/omapdrmtest.git] / util / display-kms.c
index ff4ca7d8eb081a01b152624fc10b0088f698aefd..89c480e25e57e7a58464e408084f2b660895d4d4 100644 (file)
@@ -20,7 +20,6 @@
 #endif
 
 #include "util.h"
-#include <libdce.h>
 
 #include <xf86drmMode.h>
 
@@ -56,6 +55,8 @@ struct display_kms {
        drmModeResPtr resources;
        drmModePlaneRes *plane_resources;
        struct buffer *current;
+       bool no_master;
+       int mastership;
 };
 
 #define to_buffer_kms(x) container_of(x, struct buffer_kms, base)
@@ -66,6 +67,7 @@ struct buffer_kms {
 
 static int global_fd = 0;
 static uint32_t used_planes = 0;
+static int ndisplays = 0;
 
 static struct omap_bo *
 alloc_bo(struct display *disp, uint32_t bpp, uint32_t width, uint32_t height,
@@ -194,8 +196,10 @@ free_buffers(struct display *disp, uint32_t n)
        uint32_t i;
        for (i = 0; i < n; i++) {
                 if (disp->buf[i]) {
+                       close(disp->buf[i]->fd[0]);
                        omap_bo_del(disp->buf[i]->bo[0]);
                        if(disp->multiplanar){
+                               close(disp->buf[i]->fd[1]);
                                omap_bo_del(disp->buf[i]->bo[1]);
                        }
                 }
@@ -332,6 +336,29 @@ post_buffer(struct display *disp, struct buffer *buf)
        return last_err;
 }
 
+int
+get_overlay_plane(struct display *disp, struct buffer *buf)
+{
+       struct display_kms *disp_kms = to_display_kms(disp);
+       uint32_t i, ret;
+
+       for (i = 0; i < disp_kms->connectors_count; i++) {
+               struct connector *connector = &disp_kms->connector[i];
+               drmModeModeInfo *mode = connector->mode;
+
+               disp_kms->ovr[i] = drmModeGetPlane(disp->fd,
+                                       disp_kms->plane_resources->planes[1]);
+
+               ret = drmModeObjectSetProperty(disp->fd,
+                       disp_kms->ovr[i]->plane_id, DRM_MODE_OBJECT_PLANE, 7, 3);
+               if (ret < 0) {
+                       MSG("Could not set Z order for plane");
+                       return ret;
+               }
+       }
+       return 0;
+}
+
 static int
 post_vid_buffer(struct display *disp, struct buffer *buf,
                uint32_t x, uint32_t y, uint32_t w, uint32_t h)
@@ -373,24 +400,50 @@ post_vid_buffer(struct display *disp, struct buffer *buf,
                        continue;
                }
 
-               ret = drmModeSetPlane(disp->fd, disp_kms->ovr[i]->plane_id,
+               if(buf->noScale) {
+                       ret = drmModeSetPlane(disp->fd, disp_kms->ovr[i]->plane_id,
+                               connector->crtc, buf_kms->fb_id, 0,
+                               /* Use x and y as co-ordinates of overlay */
+                               x, y, buf->width, buf->height,
+                               /* Consider source x and y is 0 always */
+                               0, 0, w << 16, h << 16);
+               } else {
+                       ret = drmModeSetPlane(disp->fd, disp_kms->ovr[i]->plane_id,
                                connector->crtc, buf_kms->fb_id, 0,
                                /* make video fullscreen: */
                                0, 0, mode->hdisplay, mode->vdisplay,
                                /* source/cropping coordinates are given in Q16 */
                                x << 16, y << 16, w << 16, h << 16);
+               }
                if (ret) {
                        ERROR("failed to enable plane %d: %s",
                                        disp_kms->ovr[i]->plane_id, strerror(errno));
                }
        }
 
+       if (disp_kms->no_master && disp_kms->mastership) {
+               /* Drop mastership after the first buffer on each plane is
+                * displayed. This will lock these planes for us and allow
+                * others to consume remaining
+                */
+               disp_kms->mastership = 0;
+               drmDropMaster(disp->fd);
+       }
+
        return ret;
 }
 
 static void
 close_kms(struct display *disp)
 {
+       omap_device_del(disp->dev);
+       disp->dev = NULL;
+       if (used_planes) {
+               used_planes >>= 1;
+       }
+       if (--ndisplays == 0) {
+               close(global_fd);
+       }
 }
 
 static void
@@ -442,20 +495,45 @@ connector_find_mode(struct display *disp, struct connector *c)
        }
 
        /* Now get the encoder */
-       for (i = 0; i < disp_kms->resources->count_encoders; i++) {
+       for (i = 0; i < connector->count_encoders; i++) {
                c->encoder = drmModeGetEncoder(disp->fd,
-                               disp_kms->resources->encoders[i]);
+                               connector->encoders[i]);
 
                if (!c->encoder) {
                        ERROR("could not get encoder %i: %s",
                                        disp_kms->resources->encoders[i], strerror(errno));
-                       drmModeFreeEncoder(c->encoder);
                        continue;
                }
 
-               if (c->encoder->encoder_id  == connector->encoder_id)
-                       break;
+               /* Take the fisrt one, if none is assigned */
+               if (!connector->encoder_id)
+               {
+                       connector->encoder_id = c->encoder->encoder_id;
+               }
+
+               if (c->encoder->encoder_id  == connector->encoder_id) {
+                       /* find the first valid CRTC if not assigned */
+                       if (!c->encoder->crtc_id)
+                       {
+                               int k;
+                               for (k = 0; k < disp_kms->resources->count_crtcs; ++k) {
+                                       /* check whether this CRTC works with the encoder */
+                                       if (!(c->encoder->possible_crtcs & (1 << k)))
+                                               continue;
+
+                                       c->encoder->crtc_id = disp_kms->resources->crtcs[k];
+                                       break;
+                               }
 
+                               if (!c->encoder->crtc_id)
+                               {
+                                       ERROR("Encoder(%d): no CRTC found!\n", c->encoder->encoder_id);
+                                       drmModeFreeEncoder(c->encoder);
+                                       continue;
+                               }
+                       }
+                       break;
+               }
                drmModeFreeEncoder(c->encoder);
        }
 
@@ -486,6 +564,7 @@ disp_kms_open(int argc, char **argv)
 {
        struct display_kms *disp_kms = NULL;
        struct display *disp;
+       struct buffer **bufs;
        int i;
 
        disp_kms = calloc(1, sizeof(*disp_kms));
@@ -504,6 +583,7 @@ disp_kms_open(int argc, char **argv)
        }
 
        disp->fd = global_fd;
+       ndisplays++;  /* increment the number of displays counter */
 
        disp->dev = omap_device_new(disp->fd);
        if (!disp->dev) {
@@ -581,6 +661,9 @@ disp_kms_open(int argc, char **argv)
                                goto fail;
                        }
                        disp_kms->bo_flags |= OMAP_BO_SCANOUT;
+               } else if (!strcmp("-nm", argv[i])) {
+                       disp_kms->no_master = true;
+                       disp_kms->mastership = 1;
                } else {
                        /* ignore */
                        continue;
@@ -605,6 +688,9 @@ disp_kms_open(int argc, char **argv)
        MSG("using %d connectors, %dx%d display, multiplanar: %d",
                        disp_kms->connectors_count, disp->width, disp->height, disp->multiplanar);
 
+       bufs = disp_get_buffers(disp, 1);
+       disp_post_buffer(disp, bufs[0]);
+
        return disp;
 
 fail: