display works sortof
[rpikern] / src / video.c
index cd3533a..9f56e9c 100644 (file)
 #include "video.h"
 #include "mem.h"
 #include "debug.h"
-
-/* needs to by 16-byte aligned, because the address we send over the mailbox
- * interface, will have its 4 least significant bits masked off and taken over
- * by the mailbox id
- */
-static char propbuf[256] __attribute__((aligned(16)));
+#include "sysctl.h"
 
 static void *fb_pixels;
-static int fb_width, fb_height, fb_depth, fb_size;
+static int scr_width, scr_height;
+static int fb_width, fb_height, fb_depth, fb_size, fb_pitch;
+static int fb_xoffs, fb_yoffs;
 
 int video_init(void)
 {
-       int i;
-       struct rpi_prop_header *hdr = (struct rpi_prop_header*)propbuf;
-       struct rpi_prop *prop = (struct rpi_prop*)(hdr + 1);
-
-       hdr->size = sizeof propbuf;
-       hdr->res = 0;
-
-       fb_width = 1024;
-       fb_height = 600;
+       int i, j;
+       struct rpi_prop *prop;
+       uint32_t *fbptr;
+
+       scr_width = 1024;
+       scr_height = 576;
+       /*fb_width = 1920;
+       fb_height = 1024;*/
+       fb_width = scr_width;
+       fb_height = scr_height;
        fb_depth = 32;
 
-       prop->id = RPI_TAG_SETFBPHYS;
-       prop->size = 8;
-       prop->res = 0;
-       prop->data[0] = fb_width;
-       prop->data[1] = fb_height;
-       prop = RPI_PROP_NEXT(prop);
-
-       prop->id = RPI_TAG_SETFBVIRT;
-       prop->size = 8;
-       prop->res = 0;
-       prop->data[0] = fb_width;
-       prop->data[1] = fb_height;
-       prop = RPI_PROP_NEXT(prop);
-
-       prop->id = RPI_TAG_SETFBDEPTH;
-       prop->size = 4;
-       prop->res = 0;
-       prop->data[0] = fb_depth;
-       prop = RPI_PROP_NEXT(prop);
-
-       prop->id = RPI_TAG_ALLOCFB;
-       prop->size = 4;
-       prop->res = 0;
-       prop->data[0] = 4;      /* alignment */
-       prop = RPI_PROP_NEXT(prop);
-
-       prop->id = 0;
-       prop->size = 0;
-       prop->res = 0;
-       prop = RPI_PROP_NEXT(prop);
-
-       printf("Requesting video mode: %dx%d (%d bpp)\n", fb_width, fb_height, fb_depth);
-
-       rpi_mbox_send(RPI_MBOX_PROP, RPI_MEM_BUS_COHERENT(propbuf));
-       while(rpi_mbox_recv(RPI_MBOX_PROP) != RPI_MEM_BUS_COHERENT(propbuf));
-
-       hexdump(propbuf, sizeof propbuf);
-
-       if(hdr->res != 0x80000000) {
-               printf("Request failed, error: %x\n", hdr->res);
-               return -1;
-       }
+       printf("Requesting video mode: %dx%d %d bpp (fb:%dx%d)\n", scr_width, scr_height,
+                       fb_depth, fb_width, fb_height);
+
+       rpi_prop(RPI_TAG_ALLOCFB, 16);
+       rpi_prop(RPI_TAG_SETFBVIRT, scr_width, scr_height);
+       rpi_prop(RPI_TAG_SETFBPHYS, fb_width, fb_height);
+       rpi_prop(RPI_TAG_SETFBDEPTH, fb_depth);
 
-       prop = (struct rpi_prop*)(hdr + 1);
-       while(prop->id) {
-               prop->size = prop->res & 0x7fffffff;
+       rpi_prop_send();
 
+       while((prop = rpi_prop_next())) {
                switch(prop->id) {
                case RPI_TAG_SETFBPHYS:
-                       printf("setfbphys");
+                       printf(" setfbphys");
+                       fb_width = prop->data[0];
+                       fb_height = prop->data[1];
                        break;
 
                case RPI_TAG_SETFBVIRT:
-                       printf("setfbvirt");
-                       fb_width = prop->data[0];
-                       fb_height = prop->data[1];
+                       printf(" setfbvirt");
+                       scr_width = prop->data[0];
+                       scr_height = prop->data[1];
                        break;
 
                case RPI_TAG_SETFBDEPTH:
-                       printf("setfbdepth");
+                       printf(" setfbdepth");
                        fb_depth = prop->data[0];
                        break;
 
                case RPI_TAG_ALLOCFB:
-                       printf("allocfb");
-                       fb_pixels = (void*)prop->data[0];
+                       printf(" allocfb");
+                       fb_pixels = (void*)(prop->data[0] & 0x3fffffff);
                        fb_size = prop->data[1];
                        break;
 
                default:
-                       printf("tag %x", prop->id);
+                       printf(" tag %x", prop->id);
                        break;
                }
 
@@ -108,12 +72,100 @@ int video_init(void)
                        printf(" %u", prop->data[i]);
                }
                putchar('\n');
-               prop = RPI_PROP_NEXT(prop);
        }
 
-       printf("Got video mode: %dx%d (%d bpp) at %p (%d bytes)\n", fb_width, fb_height,
-                       fb_depth, fb_pixels, fb_size);
+       if(!fb_pixels) {
+               rpi_prop(RPI_TAG_ALLOCFB, 16);
+               if(rpi_prop_send() == -1 || !(prop = rpi_prop_find(RPI_TAG_ALLOCFB))) {
+                       printf("Failed to allocate framebuffer\n");
+                       return -1;
+               }
+               fb_pixels = (void*)(prop->data[0] & 0x3fffffff);
+               fb_size = prop->data[1];
+       }
+
+       rpi_prop(RPI_TAG_GETFBPITCH);
+       rpi_prop(RPI_TAG_GETFBOFFS);
+       rpi_prop_send();
+       /*
+       if(rpi_prop_send() == -1) {
+               printf("Failed to get pitch\n");
+               return -1;
+       }
+       */
+
+       while((prop = rpi_prop_next())) {
+               switch(prop->id) {
+               case RPI_TAG_GETFBPITCH:
+                       fb_pitch = prop->data[0];
+                       break;
+
+               case RPI_TAG_GETFBOFFS:
+                       fb_xoffs = prop->data[0];
+                       fb_yoffs = prop->data[1];
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       printf("Got video mode: %dx%d (%d bpp)\n", scr_width, scr_height, fb_depth);
+       printf("Framebuffer: %dx%d at %p (%d bytes)\n", fb_width, fb_height, fb_pixels, fb_size);
+       printf("  virtual offset: %d, %d\n", fb_xoffs, fb_yoffs);
+       printf("  scanline pitch: %d\n", fb_pitch);
+
+       fbptr = fb_pixels;
+       for(i=0; i<fb_height; i++) {
+               for(j=0; j<fb_width; j++) {
+                       int r = i ^ j;
+                       int g = (i ^ j) >> 1;
+                       int b = (i ^ j) >> 2;
+                       fbptr[j] = b | (g << 8) | (r << 16) | 0xff000000;
+               }
+               fbptr += fb_pitch >> 2;
+       }
 
-       memset(fb_pixels, 0, fb_size);
+       sysctl_dcache_clean_inval((uint32_t)fb_pixels, fb_size);
        return 0;
 }
+
+int video_scroll(int x, int y)
+{
+       struct rpi_prop *prop;
+
+       rpi_prop(RPI_TAG_SETFBOFFS, x, y);
+       if(rpi_prop_send() == -1 || !(prop = rpi_prop_find(RPI_TAG_SETFBOFFS))) {
+               return -1;
+       }
+
+       fb_xoffs = prop->data[0];
+       fb_yoffs = prop->data[1];
+       return 0;
+}
+
+void video_update(int dt)
+{
+       static int dirx = 1, diry = 1;
+       int nx, ny;
+
+       nx = fb_xoffs + dirx * dt;
+       ny = fb_yoffs + diry * dt;
+
+       if(nx < 0) {
+               nx = 0;
+               dirx = -dirx;
+       } else if(nx + scr_width >= fb_width) {
+               nx = fb_width - scr_width;
+               dirx = -dirx;
+       }
+       if(ny < 0) {
+               ny = 0;
+               diry = -diry;
+       } else if(ny + scr_height >= fb_height) {
+               ny = fb_height - scr_height;
+               diry = -diry;
+       }
+
+       video_scroll(nx, ny);
+}