/ src / drivers / dvhstx / dvi.cpp
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  };