- implemented video mode setting with the property tags, and once again it only
[rpikern] / src / video.c
index 33b740f..cd3533a 100644 (file)
 #include "config.h"
+#include <stdio.h>
 #include <string.h>
 #include <stdint.h>
+#include "rpi.h"
 #include "video.h"
-#include "serial.h"
 #include "mem.h"
+#include "debug.h"
 
-#define MBOX_READ_REG  (*(volatile uint32_t*)(IO_BASE | 0xb880))
-#define MBOX_POLL_REG  (*(volatile uint32_t*)(IO_BASE | 0xb890))
-#define MBOX_SENDER_REG        (*(volatile uint32_t*)(IO_BASE | 0xb894))
-#define MBOX_STATUS_REG        (*(volatile uint32_t*)(IO_BASE | 0xb898))
-#define MBOX_CFG_REG   (*(volatile uint32_t*)(IO_BASE | 0xb89c))
-#define MBOX_WRITE_REG (*(volatile uint32_t*)(IO_BASE | 0xb8a0))
+/* 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)));
 
-#define MBOX_STAT_WRBUSY       0x80000000
-#define MBOX_STAT_RDBUSY       0x40000000
+static void *fb_pixels;
+static int fb_width, fb_height, fb_depth, fb_size;
 
-struct vc_fbinfo {
-       uint32_t phys_width, phys_height;
-       uint32_t virt_width, virt_height;
-       uint32_t pitch;                 /* filled by videocore */
-       uint32_t depth;
-       uint32_t x, y;
-       void *addr;             /* filled by videocore */
-       uint32_t size;  /* filled by videocore */
-};
+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);
 
-void mbox_write(int mbox, uint32_t msg);
-uint32_t mbox_read(int mbox);
+       hdr->size = sizeof propbuf;
+       hdr->res = 0;
 
-static struct vc_fbinfo fbinf __attribute__((aligned(16)));
+       fb_width = 1024;
+       fb_height = 600;
+       fb_depth = 32;
 
-int video_init(void)
-{
-       memset(&fbinf, 0, sizeof fbinf);
-       fbinf.phys_width = fbinf.virt_width = 1024;
-       fbinf.phys_height = fbinf.virt_height = 600;
-       fbinf.depth = 32;
-       fbinf.x = fbinf.y = 0;
-
-       mbox_write(1, MEM_BUS_COHERENT(&fbinf));
-       if(mbox_read(1) != 0) {
-               ser_printstr("Failed to initialize display\n");
+       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;
        }
 
-       ser_printstr("Video init successful\n");
-       memset(fbinf.addr, 0, fbinf.size);
-       return 0;
-}
+       prop = (struct rpi_prop*)(hdr + 1);
+       while(prop->id) {
+               prop->size = prop->res & 0x7fffffff;
 
-void mbox_write(int mbox, uint32_t msg)
-{
-       while(MBOX_STATUS_REG & MBOX_STAT_WRBUSY);
-       MBOX_WRITE_REG = (msg & 0xfffffff0) | mbox;
-}
+               switch(prop->id) {
+               case RPI_TAG_SETFBPHYS:
+                       printf("setfbphys");
+                       break;
 
-uint32_t mbox_read(int mbox)
-{
-       uint32_t msg;
+               case RPI_TAG_SETFBVIRT:
+                       printf("setfbvirt");
+                       fb_width = prop->data[0];
+                       fb_height = prop->data[1];
+                       break;
+
+               case RPI_TAG_SETFBDEPTH:
+                       printf("setfbdepth");
+                       fb_depth = prop->data[0];
+                       break;
 
-       do {
-               while(MBOX_STATUS_REG & MBOX_STAT_RDBUSY);
-               msg = MBOX_READ_REG;
-       } while((msg & 0xf) != mbox);
+               case RPI_TAG_ALLOCFB:
+                       printf("allocfb");
+                       fb_pixels = (void*)prop->data[0];
+                       fb_size = prop->data[1];
+                       break;
 
-       return msg & 0xfffffff0;
+               default:
+                       printf("tag %x", prop->id);
+                       break;
+               }
+
+               printf(" %08x (%u bytes):", prop->res, prop->size);
+               for(i=0; i<prop->size / 4; i++) {
+                       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);
+
+       memset(fb_pixels, 0, fb_size);
+       return 0;
 }