dvi.cpp
1 #include <pico/stdlib.h> 2 3 #include "dvi.hpp" 4 5 // VGA -- we do this mode properly, with a pretty comfortable clk_sys (252 MHz) 6 const struct dvi_timing dvi_timing_640x480p_60hz = { 7 .h_sync_polarity = false, 8 .h_front_porch = 16, 9 .h_sync_width = 96, 10 .h_back_porch = 48, 11 .h_active_pixels = 640, 12 13 .v_sync_polarity = false, 14 .v_front_porch = 10, 15 .v_sync_width = 2, 16 .v_back_porch = 33, 17 .v_active_lines = 480, 18 19 .bit_clk_khz = 252000 20 }; 21 22 // SVGA -- completely by-the-book but requires 400 MHz clk_sys 23 const struct dvi_timing dvi_timing_800x600p_60hz = { 24 .h_sync_polarity = false, 25 .h_front_porch = 44, 26 .h_sync_width = 128, 27 .h_back_porch = 88, 28 .h_active_pixels = 800, 29 30 .v_sync_polarity = false, 31 .v_front_porch = 1, 32 .v_sync_width = 4, 33 .v_back_porch = 23, 34 .v_active_lines = 600, 35 36 .bit_clk_khz = 400000 37 }; 38 39 // 720x480 - timings from dumping the EDID of my monitor 40 const struct dvi_timing dvi_timing_720x480p_60hz = { 41 .h_sync_polarity = false, 42 .h_front_porch = 16, 43 .h_sync_width = 62, 44 .h_back_porch = 60, 45 .h_active_pixels = 720, 46 47 .v_sync_polarity = false, 48 .v_front_porch = 9, 49 .v_sync_width = 6, 50 .v_back_porch = 30, 51 .v_active_lines = 480, 52 53 .bit_clk_khz = 270000 54 }; 55 56 // 720x576@50Hz - CEA timing 57 const struct dvi_timing dvi_timing_720x576p_50hz = { 58 .h_sync_polarity = false, 59 .h_front_porch = 12, 60 .h_sync_width = 64, 61 .h_back_porch = 68, 62 .h_active_pixels = 720, 63 64 .v_sync_polarity = false, 65 .v_front_porch = 5, 66 .v_sync_width = 5, 67 .v_back_porch = 39, 68 .v_active_lines = 576, 69 70 .bit_clk_khz = 270000 71 }; 72 73 // 720x400@70Hz - "IBM" timing 74 const struct dvi_timing dvi_timing_720x400p_70hz = { 75 .h_sync_polarity = false, 76 .h_front_porch = 18, 77 .h_sync_width = 108, 78 .h_back_porch = 54, 79 .h_active_pixels = 720, 80 81 .v_sync_polarity = true, 82 .v_front_porch = 13, 83 .v_sync_width = 2, 84 .v_back_porch = 34, 85 .v_active_lines = 400, 86 87 .bit_clk_khz = 283200 88 }; 89 90 // 800x480p 60 Hz (note this doesn't seem to be a CEA mode, I just used the 91 // output of `cvt 800 480 60`), 295 MHz bit clock 92 const struct dvi_timing dvi_timing_800x480p_60hz = { 93 .h_sync_polarity = false, 94 .h_front_porch = 24, 95 .h_sync_width = 72, 96 .h_back_porch = 96, 97 .h_active_pixels = 800, 98 99 .v_sync_polarity = true, 100 .v_front_porch = 3, 101 .v_sync_width = 10, 102 .v_back_porch = 7, 103 .v_active_lines = 480, 104 105 .bit_clk_khz = 295200 106 }; 107 108 // 800x450p 60 Hz Similarly not a CEA mode, but is 16:9 109 const struct dvi_timing dvi_timing_800x450p_60hz = { 110 .h_sync_polarity = false, 111 .h_front_porch = 24, 112 .h_sync_width = 72, 113 .h_back_porch = 96, 114 .h_active_pixels = 800, 115 116 .v_sync_polarity = true, 117 .v_front_porch = 3, 118 .v_sync_width = 5, 119 .v_back_porch = 10, 120 .v_active_lines = 450, 121 122 .bit_clk_khz = 278400 123 }; 124 125 // SVGA reduced blanking (355 MHz bit clock) -- valid CVT mode, less common 126 // than fully-blanked SVGA, but doesn't require such a high system clock 127 const struct dvi_timing dvi_timing_800x600p_reduced_60hz = { 128 .h_sync_polarity = true, 129 .h_front_porch = 48, 130 .h_sync_width = 32, 131 .h_back_porch = 80, 132 .h_active_pixels = 800, 133 134 .v_sync_polarity = false, 135 .v_front_porch = 3, 136 .v_sync_width = 4, 137 .v_back_porch = 11, 138 .v_active_lines = 600, 139 140 .bit_clk_khz = 354000 141 }; 142 143 // Also known as qHD, bit uncommon, but it's a nice modest-resolution 16:9 144 // aspect mode. Pixel clock 40.75 MHz for full CVT mode (no reduced blanking) 145 const struct dvi_timing dvi_timing_960x540p_60hz = { 146 .h_sync_polarity = false, 147 .h_front_porch = 32, 148 .h_sync_width = 96, 149 .h_back_porch = 128, 150 .h_active_pixels = 960, 151 152 .v_sync_polarity = true, 153 .v_front_porch = 3, 154 .v_sync_width = 5, 155 .v_back_porch = 14, 156 .v_active_lines = 540, 157 158 .bit_clk_khz = 408000 159 }; 160 161 // Also known as qHD, bit uncommon, but it's a nice modest-resolution 16:9 162 // aspect mode. Pixel clock 33.5 MHz for 50Hz CVT mode (no reduced blanking) 163 const struct dvi_timing dvi_timing_960x540p_50hz = { 164 .h_sync_polarity = false, 165 .h_front_porch = 24, 166 .h_sync_width = 96, 167 .h_back_porch = 120, 168 .h_active_pixels = 960, 169 170 .v_sync_polarity = true, 171 .v_front_porch = 3, 172 .v_sync_width = 5, 173 .v_back_porch = 11, 174 .v_active_lines = 540, 175 176 .bit_clk_khz = 336000 177 }; 178 179 // 1024x768, CVT-RB 180 const struct dvi_timing dvi_timing_1024x768_rb_60hz = { 181 .h_sync_polarity = true, 182 .h_front_porch = 48, 183 .h_sync_width = 32, 184 .h_back_porch = 80, 185 .h_active_pixels = 1024, 186 187 .v_sync_polarity = false, 188 .v_front_porch = 3, 189 .v_sync_width = 4, 190 .v_back_porch = 15, 191 .v_active_lines = 768, 192 193 .bit_clk_khz = 560000 194 }; 195 196 // 720p50, this is a standard HD mode, the CVT-RB variant 197 // should be widely supported 198 const struct dvi_timing dvi_timing_1280x720p_rb_50hz = { 199 .h_sync_polarity = true, 200 .h_front_porch = 48, 201 .h_sync_width = 32, 202 .h_back_porch = 80, 203 .h_active_pixels = 1280, 204 205 .v_sync_polarity = false, 206 .v_front_porch = 3, 207 .v_sync_width = 5, 208 .v_back_porch = 9, 209 .v_active_lines = 720, 210 211 .bit_clk_khz = 528000 212 }; 213 214 // 720p60, this is the CVT-RB variant, again should be widely supported 215 const struct dvi_timing dvi_timing_1280x720p_rb_60hz = { 216 .h_sync_polarity = true, 217 .h_front_porch = 48, 218 .h_sync_width = 32, 219 .h_back_porch = 80, 220 .h_active_pixels = 1280, 221 222 .v_sync_polarity = false, 223 .v_front_porch = 3, 224 .v_sync_width = 5, 225 .v_back_porch = 13, 226 .v_active_lines = 720, 227 228 .bit_clk_khz = 640000 229 }; 230 231 // 1080p30 - not a normal mode but seems to work on a wide variety of hardware 232 // Strictly speaking RB2 should have a clock speed matching the target frequency more closely 233 // but it seems to work! 234 const struct dvi_timing dvi_timing_1920x1080p_rb2_30hz = { 235 .h_sync_polarity = true, 236 .h_front_porch = 8, 237 .h_sync_width = 32, 238 .h_back_porch = 40, 239 .h_active_pixels = 1920, 240 241 .v_sync_polarity = false, 242 .v_front_porch = 7, 243 .v_sync_width = 8, 244 .v_back_porch = 6, 245 .v_active_lines = 1080, 246 247 .bit_clk_khz = 660000 248 }; 249 250 // 1440p24 YOLO - works on my Dell Ultrasharp, that most forgiving of monitors. May require a little more than 1.3V 251 const struct dvi_timing dvi_timing_2560x1440p_yolo_24hz = { 252 .h_sync_polarity = true, 253 .h_front_porch = 8, 254 .h_sync_width = 32, 255 .h_back_porch = 20, 256 .h_active_pixels = 2560, 257 258 .v_sync_polarity = false, 259 .v_front_porch = 2, 260 .v_sync_width = 6, 261 .v_back_porch = 2, 262 .v_active_lines = 1440, 263 264 .bit_clk_khz = 912000 265 };