videomixer: support different resolutions
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 14 Jun 2013 16:17:04 +0000 (18:17 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 14 Jun 2013 21:39:45 +0000 (23:39 +0200)
software/videomixer/dvisamplerX.c
software/videomixer/fb.c [new file with mode: 0644]
software/videomixer/fb.h [new file with mode: 0644]
software/videomixer/main.c

index 01f7e029c0630d88de1062864259cb871ddbf5af..cf2a50f7b4433a4e0cd92ea399438f5177099e8e 100644 (file)
@@ -7,12 +7,13 @@
 #include <hw/flags.h>
 
 #include "time.h"
+#include "fb.h"
 #include "dvisamplerX.h"
 
 #define FRAMEBUFFER_COUNT 4
 #define FRAMEBUFFER_MASK (FRAMEBUFFER_COUNT - 1)
 
-static unsigned int dvisamplerX_framebuffers[FRAMEBUFFER_COUNT][640*480] __attribute__((aligned(16)));
+static unsigned int dvisamplerX_framebuffers[FRAMEBUFFER_COUNT][800*600] __attribute__((aligned(16)));
 static int dvisamplerX_fb_slot_indexes[2];
 static int dvisamplerX_next_fb_index;
 
@@ -49,7 +50,7 @@ void dvisamplerX_init_video(void)
        mask |= 1 << DVISAMPLERX_INTERRUPT;
        irq_setmask(mask);
 
-       dvisamplerX_dma_frame_size_write(sizeof(dvisamplerX_framebuffers[0]));
+       dvisamplerX_dma_frame_size_write(fb_hres*fb_vres*4);
        dvisamplerX_fb_slot_indexes[0] = 0;
        dvisamplerX_dma_slot0_address_write((unsigned int)dvisamplerX_framebuffers[0]);
        dvisamplerX_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED);
diff --git a/software/videomixer/fb.c b/software/videomixer/fb.c
new file mode 100644 (file)
index 0000000..58b90bc
--- /dev/null
@@ -0,0 +1,103 @@
+#include <stdio.h>
+
+#include <hw/csr.h>
+#include <hw/flags.h>
+
+#include "fb.h"
+
+int fb_hres = 640;
+int fb_vres = 480;
+
+static void fb_clkgen_write(int cmd, int data)
+{
+       int word;
+
+       word = (data << 2) | cmd;
+       crg_cmd_data_write(word);
+       crg_send_cmd_data_write(1);
+       while(crg_status_read() & CLKGEN_STATUS_BUSY);
+}
+
+void fb_set_mode(int mode)
+{
+       int clock_m, clock_d;
+
+       switch(mode) {
+               default:
+               case FB_MODE_640_480: // Pixel clock: 25MHz
+                       fb_hres = 640;
+                       fb_vres = 480;
+                       clock_m = 2;
+                       clock_d = 4;
+                       fb_fi_hres_write(640);
+                       fb_fi_hsync_start_write(656);
+                       fb_fi_hsync_end_write(752);
+                       fb_fi_hscan_write(800);
+                       fb_fi_vres_write(480);
+                       fb_fi_vsync_start_write(492);
+                       fb_fi_vsync_end_write(494);
+                       fb_fi_vscan_write(525);
+                       break;
+               case FB_MODE_800_600: // Pixel clock: 50MHz
+                       fb_hres = 800;
+                       fb_vres = 600;
+                       clock_m = 2;
+                       clock_d = 2;
+                       fb_fi_hres_write(800);
+                       fb_fi_hsync_start_write(848);
+                       fb_fi_hsync_end_write(976);
+                       fb_fi_hscan_write(1040);
+                       fb_fi_vres_write(600);
+                       fb_fi_vsync_start_write(636);
+                       fb_fi_vsync_end_write(642);
+                       fb_fi_vscan_write(665);
+                       break;
+               case FB_MODE_1024_768: // Pixel clock: 65MHz
+                       fb_hres = 1024;
+                       fb_vres = 768;
+                       clock_m = 13;
+                       clock_d = 10;
+                       fb_fi_hres_write(1024);
+                       fb_fi_hsync_start_write(1048);
+                       fb_fi_hsync_end_write(1184);
+                       fb_fi_hscan_write(1344);
+                       fb_fi_vres_write(768);
+                       fb_fi_vsync_start_write(772);
+                       fb_fi_vsync_end_write(778);
+                       fb_fi_vscan_write(807);
+                       break;
+               case FB_MODE_1920_1080: // Pixel clock: 148MHz
+                       fb_hres = 1920;
+                       fb_vres = 1080;
+                       clock_m = 74;
+                       clock_d = 25;
+                       fb_fi_hres_write(1920);
+                       fb_fi_hsync_start_write(2008);
+                       fb_fi_hsync_end_write(2052);
+                       fb_fi_hscan_write(2200);
+                       fb_fi_vres_write(1080);
+                       fb_fi_vsync_start_write(1084);
+                       fb_fi_vsync_end_write(1089);
+                       fb_fi_vscan_write(1125);
+                       break;
+       }
+       fb_dma0_length_write(fb_hres*fb_vres*4);
+       fb_dma1_length_write(fb_hres*fb_vres*4);
+
+       fb_clkgen_write(0x1, clock_d-1);
+       fb_clkgen_write(0x3, clock_m-1);
+       crg_send_go_write(1);
+       printf("waiting for PROGDONE...");
+       while(!(crg_status_read() & CLKGEN_STATUS_PROGDONE));
+       printf("ok\n");
+       printf("waiting for LOCKED...");
+       while(!(crg_status_read() & CLKGEN_STATUS_LOCKED));
+       printf("ok\n");
+
+       printf("VGA: mode set to %dx%d\n", fb_hres, fb_vres);
+}
+
+void fb_enable(int en)
+{
+       fb_enable_write(!!en);
+}
diff --git a/software/videomixer/fb.h b/software/videomixer/fb.h
new file mode 100644 (file)
index 0000000..7b9cc92
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __FB_H
+#define __FB_H
+
+enum {
+    FB_MODE_640_480,
+    FB_MODE_800_600,
+    FB_MODE_1024_768,
+    FB_MODE_1920_1080
+};
+
+extern int fb_hres, fb_vres;
+
+void fb_set_mode(int mode);
+void fb_enable(int en);
+
+#endif /* __FB_H */
index aa92c0f87f283531069bc565eecb378f92214ab5..4a44be7dfdba7c3293624c1bdd6911f0ea62dae6 100644 (file)
@@ -8,6 +8,7 @@
 #include <console.h>
 
 #include "time.h"
+#include "fb.h"
 #include "dvisampler0.h"
 #include "dvisampler1.h"
 
@@ -80,10 +81,10 @@ static void fb_service(void)
        if(readchar_nonblock()) {
                c = readchar();
                if(c == '1') {
-                       fb_enable_write(1);
+                       fb_enable(1);
                        printf("Framebuffer is ON\n");
                } else if(c == '0') {
-                       fb_enable_write(0);
+                       fb_enable(0);
                        printf("Framebuffer is OFF\n");
                }
        }
@@ -98,9 +99,10 @@ int main(void)
        puts("Minimal video mixer software built "__DATE__" "__TIME__"\n");
        
        time_init();
+       fb_set_mode(FB_MODE_640_480);
        dvisampler0_init_video();
        dvisampler1_init_video();
-       fb_enable_write(1);
+       fb_enable(1);
 
        while(1) {
                dvisampler0_service();