X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=rpikern;a=blobdiff_plain;f=src%2Fvideo.c;h=9f56e9c67bfe48925d50a0ddeea849881e7ddcb9;hp=33b740f09ce28788a5d86d8968479fa1e4383cca;hb=99bdc8838f189f79ba77bfbbf41d7f1b4839ce0f;hpb=203b43a75a028e9238307bd6e73768eb8e942071 diff --git a/src/video.c b/src/video.c index 33b740f..9f56e9c 100644 --- a/src/video.c +++ b/src/video.c @@ -1,68 +1,171 @@ #include "config.h" +#include #include #include +#include "rpi.h" #include "video.h" -#include "serial.h" #include "mem.h" +#include "debug.h" +#include "sysctl.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)) +static void *fb_pixels; +static int scr_width, scr_height; +static int fb_width, fb_height, fb_depth, fb_size, fb_pitch; +static int fb_xoffs, fb_yoffs; -#define MBOX_STAT_WRBUSY 0x80000000 -#define MBOX_STAT_RDBUSY 0x40000000 +int video_init(void) +{ + int i, j; + struct rpi_prop *prop; + uint32_t *fbptr; -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 */ -}; + scr_width = 1024; + scr_height = 576; + /*fb_width = 1920; + fb_height = 1024;*/ + fb_width = scr_width; + fb_height = scr_height; + fb_depth = 32; -void mbox_write(int mbox, uint32_t msg); -uint32_t mbox_read(int mbox); + printf("Requesting video mode: %dx%d %d bpp (fb:%dx%d)\n", scr_width, scr_height, + fb_depth, fb_width, fb_height); -static struct vc_fbinfo fbinf __attribute__((aligned(16))); + 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); -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"); + rpi_prop_send(); + + while((prop = rpi_prop_next())) { + switch(prop->id) { + case RPI_TAG_SETFBPHYS: + printf(" setfbphys"); + fb_width = prop->data[0]; + fb_height = prop->data[1]; + break; + + case RPI_TAG_SETFBVIRT: + printf(" setfbvirt"); + scr_width = prop->data[0]; + scr_height = prop->data[1]; + break; + + case RPI_TAG_SETFBDEPTH: + printf(" setfbdepth"); + fb_depth = prop->data[0]; + break; + + case RPI_TAG_ALLOCFB: + printf(" allocfb"); + fb_pixels = (void*)(prop->data[0] & 0x3fffffff); + fb_size = prop->data[1]; + break; + + default: + printf(" tag %x", prop->id); + break; + } + + printf(" %08x (%u bytes):", prop->res, prop->size); + for(i=0; isize / 4; i++) { + printf(" %u", prop->data[i]); + } + putchar('\n'); + } + + 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; - ser_printstr("Video init successful\n"); - memset(fbinf.addr, 0, fbinf.size); + 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> 1; + int b = (i ^ j) >> 2; + fbptr[j] = b | (g << 8) | (r << 16) | 0xff000000; + } + fbptr += fb_pitch >> 2; + } + + sysctl_dcache_clean_inval((uint32_t)fb_pixels, fb_size); return 0; } -void mbox_write(int mbox, uint32_t msg) +int video_scroll(int x, int y) { - while(MBOX_STATUS_REG & MBOX_STAT_WRBUSY); - MBOX_WRITE_REG = (msg & 0xfffffff0) | mbox; + 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; } -uint32_t mbox_read(int mbox) +void video_update(int dt) { - uint32_t msg; + static int dirx = 1, diry = 1; + int nx, ny; - do { - while(MBOX_STATUS_REG & MBOX_STAT_RDBUSY); - msg = MBOX_READ_REG; - } while((msg & 0xf) != mbox); + 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; + } - return msg & 0xfffffff0; + video_scroll(nx, ny); }