videomixer: add PLL control code
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 18 Nov 2013 19:37:10 +0000 (20:37 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 18 Nov 2013 19:37:10 +0000 (20:37 +0100)
software/videomixer/Makefile
software/videomixer/pll.c [new file with mode: 0644]
software/videomixer/pll.h [new file with mode: 0644]

index 58e3aec7722abcacd2c09f1e36ab8e0c35d7a9d2..6111c9da62e41bbc608956df7d0ee2ce15ec6865 100644 (file)
@@ -1,7 +1,7 @@
 MSCDIR=../..
 include $(MSCDIR)/software/common.mak
 
-OBJECTS=isr.o processor.o dvisampler0.o dvisampler1.o edid.o ci.o main.o
+OBJECTS=isr.o processor.o dvisampler0.o dvisampler1.o edid.o pll.o ci.o main.o
 
 all: videomixer.bin videomixer.fbi
 
diff --git a/software/videomixer/pll.c b/software/videomixer/pll.c
new file mode 100644 (file)
index 0000000..fd49393
--- /dev/null
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <hw/csr.h>
+
+#include "pll.h"
+
+/*
+ * Despite varying pixel clocks, we must keep the PLL VCO operating
+ * in the specified range of 400MHz - 1000MHz.
+ * This code can program two sets of DRP data:
+ * 1. with VCO operating at 20x the pixel clock (for 20MHz - 50MHz pixel clock)
+ * 2. with VCO operating at 10x the pixel clock (for 40MHz - 100MHz pixel clock)
+ */
+
+static const unsigned short int pll_config_20x[32] = {
+       0x0006, 0x0008, 0x0000, 0x4400, 0x1708, 0x0097, 0x0501, 0x8288,
+       0x4201, 0x0d90, 0x00a1, 0x0111, 0x1004, 0x2028, 0x0802, 0x2800,
+       0x0288, 0x8058, 0x020c, 0x0200, 0x1210, 0x400b, 0xfc21, 0x0b21,
+       0x7f5f, 0xc0eb, 0x472a, 0xc02a, 0x20b6, 0x0e96, 0x1002, 0xd6ce
+};
+
+static const unsigned short int pll_config_10x[32] = {
+       0x0006, 0x0008, 0x0000, 0x4400, 0x1708, 0x0097, 0x0901, 0x8118,
+       0x4181, 0x0d60, 0x00a1, 0x0111, 0x1004, 0x2028, 0x0802, 0x0608,
+       0x0148, 0x8018, 0x020c, 0x0200, 0x1210, 0x400b, 0xfc21, 0x0b22,
+       0x5fdf, 0x40eb, 0x472b, 0xc02a, 0x20b6, 0x0e96, 0x1002, 0xd6ce
+};
+
+static void program_data(const unsigned short *data)
+{
+       int i;
+
+       /*
+        * Some bits of words 4 and 5 appear to depend on PLL location,
+        * so we start at word 6.
+        * PLLs also seem to dislike any write to the last words.
+        */
+       for(i=6;i<32-5;i++) {
+               fb_driver_clocking_pll_adr_write(i);
+               fb_driver_clocking_pll_dat_w_write(data[i]);
+               fb_driver_clocking_pll_write_write(1);
+               while(!fb_driver_clocking_pll_drdy_read());
+       }
+       for(i=6;i<32-5;i++) {
+               dvisampler0_clocking_pll_adr_write(i);
+               dvisampler0_clocking_pll_dat_w_write(data[i]);
+               dvisampler0_clocking_pll_write_write(1);
+               while(!dvisampler0_clocking_pll_drdy_read());
+       }
+       for(i=6;i<32-5;i++) {
+               dvisampler1_clocking_pll_adr_write(i);
+               dvisampler1_clocking_pll_dat_w_write(data[i]);
+               dvisampler1_clocking_pll_write_write(1);
+               while(!dvisampler1_clocking_pll_drdy_read());
+       }
+}
+
+void pll_config_for_clock(int freq)
+{
+       if(freq < 2000)
+               printf("Frequency too low for PLLs\n");
+       else if(freq < 4500)
+               program_data(pll_config_20x);
+       else if(freq < 10000)
+               program_data(pll_config_10x);
+       else
+               printf("Frequency too high for PLLs\n");
+}
+
+void pll_dump(void)
+{
+       int i;
+
+       printf("framebuffer PLL:\n");
+       for(i=0;i<32;i++) {
+               fb_driver_clocking_pll_adr_write(i);
+               fb_driver_clocking_pll_read_write(1);
+               while(!fb_driver_clocking_pll_drdy_read());
+               printf("%04x ", fb_driver_clocking_pll_dat_r_read());
+       }
+       printf("\n");
+       printf("dvisampler0 PLL:\n");
+       for(i=0;i<32;i++) {
+               dvisampler0_clocking_pll_adr_write(i);
+               dvisampler0_clocking_pll_read_write(1);
+               while(!dvisampler0_clocking_pll_drdy_read());
+               printf("%04x ", dvisampler0_clocking_pll_dat_r_read());
+       }
+       printf("\n");
+       printf("dvisampler1 PLL:\n");
+       for(i=0;i<32;i++) {
+               dvisampler1_clocking_pll_adr_write(i);
+               dvisampler1_clocking_pll_read_write(1);
+               while(!dvisampler1_clocking_pll_drdy_read());
+               printf("%04x ", dvisampler1_clocking_pll_dat_r_read());
+       }
+       printf("\n");
+}
diff --git a/software/videomixer/pll.h b/software/videomixer/pll.h
new file mode 100644 (file)
index 0000000..3c4a626
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __PLL_H
+#define __PLL_H
+
+void pll_config_for_clock(int freq);
+void pll_dump(void);
+
+#endif