/ software / libdvi / dvi_timing.c
dvi_timing.c
  1  #include "dvi.h"
  2  #include "dvi_timing.h"
  3  #include "hardware/dma.h"
  4  
  5  // This file contains:
  6  // - Timing parameters for DVI modes (horizontal + vertical counts, best
  7  //   achievable bit clock from 12 MHz crystal)
  8  // - Helper functions for generating DMA lists based on these timings
  9  
 10  // Pull into RAM but apply unique section suffix to allow linker GC
 11  #define __dvi_func(x) __not_in_flash_func(x)
 12  #define __dvi_const(x) __not_in_flash_func(x)
 13  
 14  // VGA -- we do this mode properly, with a pretty comfortable clk_sys (252 MHz)
 15  const struct dvi_timing __dvi_const(dvi_timing_640x480p_60hz) = {
 16  	.h_sync_polarity   = false,
 17  	.h_front_porch     = 16,
 18  	.h_sync_width      = 96,
 19  	.h_back_porch      = 48,
 20  	.h_active_pixels   = 640,
 21  
 22  	.v_sync_polarity   = false,
 23  	.v_front_porch     = 10,
 24  	.v_sync_width      = 2,
 25  	.v_back_porch      = 33,
 26  	.v_active_lines    = 480,
 27  
 28  	.bit_clk_khz       = 252000
 29  };
 30  
 31  // SVGA -- completely by-the-book but requires 400 MHz clk_sys
 32  const struct dvi_timing __dvi_const(dvi_timing_800x600p_60hz) = {
 33  	.h_sync_polarity   = false,
 34  	.h_front_porch     = 44,
 35  	.h_sync_width      = 128,
 36  	.h_back_porch      = 88,
 37  	.h_active_pixels   = 800,
 38  
 39  	.v_sync_polarity   = false,
 40  	.v_front_porch     = 1,
 41  	.v_sync_width      = 4,
 42  	.v_back_porch      = 23,
 43  	.v_active_lines    = 600,
 44  
 45  	.bit_clk_khz       = 400000
 46  };
 47  
 48  // 800x480p 60 Hz (note this doesn't seem to be a CEA mode, I just used the
 49  // output of `cvt 800 480 60`), 295 MHz bit clock
 50  const struct dvi_timing __dvi_const(dvi_timing_800x480p_60hz) = {
 51  	.h_sync_polarity = false,
 52  	.h_front_porch   = 24,
 53  	.h_sync_width    = 72,
 54  	.h_back_porch    = 96,
 55  	.h_active_pixels = 800,
 56  
 57  	.v_sync_polarity = true,
 58  	.v_front_porch   = 3,
 59  	.v_sync_width    = 10,
 60  	.v_back_porch    = 7,
 61  	.v_active_lines  = 480,
 62  
 63  	.bit_clk_khz     = 295200
 64  };
 65  
 66  // SVGA reduced blanking (355 MHz bit clock) -- valid CVT mode, less common
 67  // than fully-blanked SVGA, but doesn't require such a high system clock
 68  const struct dvi_timing __dvi_const(dvi_timing_800x600p_reduced_60hz) = {
 69  	.h_sync_polarity   = true,
 70  	.h_front_porch     = 48,
 71  	.h_sync_width      = 32,
 72  	.h_back_porch      = 80,
 73  	.h_active_pixels   = 800,
 74  
 75  	.v_sync_polarity   = false,
 76  	.v_front_porch     = 3,
 77  	.v_sync_width      = 4,
 78  	.v_back_porch      = 11,
 79  	.v_active_lines    = 600,
 80  
 81  	.bit_clk_khz       = 354000
 82  };
 83  
 84  // Also known as qHD, bit uncommon, but it's a nice modest-resolution 16:9
 85  // aspect mode. Pixel clock 37.3 MHz
 86  const struct dvi_timing __dvi_const(dvi_timing_960x540p_60hz) = {
 87  	.h_sync_polarity   = true,
 88  	.h_front_porch     = 16,
 89  	.h_sync_width      = 32,
 90  	.h_back_porch      = 96,
 91  	.h_active_pixels   = 960,
 92  
 93  	.v_sync_polarity   = true,
 94  	.v_front_porch     = 2,
 95  	.v_sync_width      = 6,
 96  	.v_back_porch      = 15,
 97  	.v_active_lines    = 540,
 98  
 99  	.bit_clk_khz       = 372000
100  };
101  
102  // Note this is NOT the correct 720p30 CEA mode, but rather 720p60 run at half
103  // pixel clock. Seems to be commonly accepted (and is a valid CVT mode). The
104  // actual CEA mode is the same pixel clock as 720p60 but with >50% blanking,
105  // which would require a clk_sys of 742 MHz!
106  const struct dvi_timing __dvi_const(dvi_timing_1280x720p_30hz) = {
107  	.h_sync_polarity   = true,
108  	.h_front_porch     = 110,
109  	.h_sync_width      = 40,
110  	.h_back_porch      = 220,
111  	.h_active_pixels   = 1280,
112  
113  	.v_sync_polarity   = true,
114  	.v_front_porch     = 5,
115  	.v_sync_width      = 5,
116  	.v_back_porch      = 20,
117  	.v_active_lines    = 720,
118  
119  	.bit_clk_khz       = 372000
120  };
121  
122  // Reduced-blanking (CVT) 720p. You aren't supposed to use reduced blanking
123  // modes below 60 Hz, but I won't tell anyone (and it works on the monitors
124  // I've tried). This nets a lower system clock than regular 720p30 (319 MHz)
125  const struct dvi_timing __dvi_const(dvi_timing_1280x720p_reduced_30hz) = {
126  	.h_sync_polarity   = true,
127  	.h_front_porch     = 48,
128  	.h_sync_width      = 32,
129  	.h_back_porch      = 80,
130  	.h_active_pixels   = 1280,
131  
132  	.v_sync_polarity   = false,
133  	.v_front_porch     = 3,
134  	.v_sync_width      = 5,
135  	.v_back_porch      = 13,
136  	.v_active_lines    = 720,
137  
138  	.bit_clk_khz       = 319200
139  };
140  
141  // This requires a spicy 488 MHz system clock and is illegal in most countries
142  // (you need to have a very lucky piece of silicon to run this at 1.3 V, or
143  // connect an external supply and give it a bit more juice)
144  const struct dvi_timing __dvi_const(dvi_timing_1600x900p_reduced_30hz) = {
145  	.h_sync_polarity   = true,
146  	.h_front_porch     = 48,
147  	.h_sync_width      = 32,
148  	.h_back_porch      = 80,
149  	.h_active_pixels   = 1600,
150  
151  	.v_sync_polarity   = false,
152  	.v_front_porch     = 3,
153  	.v_sync_width      = 5,
154  	.v_back_porch      = 18,
155  	.v_active_lines    = 900,
156  
157  	.bit_clk_khz       = 488000
158  };
159  
160  // ----------------------------------------------------------------------------
161  
162  // The DMA scheme is:
163  //
164  // - One channel transferring data to each of the three PIO state machines
165  //   performing TMDS serialisation
166  //
167  // - One channel programming the registers of each of these data channels,
168  //   triggered (CHAIN_TO) each time the corresponding data channel completes
169  //
170  // - Lanes 1 and 2 have one block for blanking and one for video data
171  //
172  // - Lane 0 has one block for each horizontal region (front porch, hsync, back
173  //   porch, active)
174  //
175  // - The IRQ_QUIET flag is used to select which data block on the sync lane is
176  //   allowed to generate an IRQ upon completion. This is the block immediately
177  //   before the horizontal active region. The IRQ is entered at ~the same time
178  //   as the last data transfer starts
179  //
180  // - The IRQ points the control channels at new blocklists for next scanline.
181  //   The DMA starts the new list automatically at end-of-scanline, via
182  //   CHAIN_TO.
183  //
184  // The horizontal active region is the longest continuous transfer, so this
185  // gives the most time to handle the IRQ and load new blocklists.
186  //
187  // Note a null trigger IRQ is not suitable because we get that *after* the
188  // last data transfer finishes, and the FIFOs bottom out very shortly
189  // afterward. For pure DVI (four blocks per scanline), it works ok to take
190  // four regular IRQs per scanline and return early from 3 of them, but this
191  // breaks down when you have very short scanline sections like guard bands.
192  
193  // Each symbol appears twice, concatenated in one word. Note these must be in
194  // RAM because they see a lot of DMA traffic
195  const uint32_t __dvi_const(dvi_ctrl_syms)[4] = {
196  	0xd5354,
197  	0x2acab,
198  	0x55154,
199  	0xaaeab
200  };
201  
202  // Output solid red scanline if we are given NULL for tmdsbuff
203  #if DVI_SYMBOLS_PER_WORD == 2
204  static uint32_t __dvi_const(empty_scanline_tmds)[3] = {
205  	0x7fd00u, // 0x00, 0x00
206  	0x7fd00u, // 0x00, 0x00
207  	0xbfa01u  // 0xfc, 0xfc
208  };
209  #else
210  static uint32_t __attribute__((aligned(8))) __dvi_const(empty_scanline_tmds)[6] = {
211  	0x100u, 0x1ffu, // 0x00, 0x00
212  	0x100u, 0x1ffu, // 0x00, 0x00
213  	0x201u, 0x2feu  // 0xfc, 0xfc
214  };
215  #endif
216  
217  void dvi_timing_state_init(struct dvi_timing_state *t) {
218  	t->v_ctr = 0;
219  	t->v_state = DVI_STATE_FRONT_PORCH;
220  };
221  
222  void __dvi_func(dvi_timing_state_advance)(const struct dvi_timing *t, struct dvi_timing_state *s) {
223  		s->v_ctr++;
224  		if ((s->v_state == DVI_STATE_FRONT_PORCH && s->v_ctr == t->v_front_porch) || 
225  		    (s->v_state == DVI_STATE_SYNC && s->v_ctr == t->v_sync_width) ||
226  		    (s->v_state == DVI_STATE_BACK_PORCH && s->v_ctr == t->v_back_porch) ||
227  		    (s->v_state == DVI_STATE_ACTIVE && s->v_ctr == t->v_active_lines)) {
228  
229  			s->v_state = (s->v_state + 1) % DVI_STATE_COUNT;
230  			s->v_ctr = 0;
231  		}
232  }
233  
234  void dvi_scanline_dma_list_init(struct dvi_scanline_dma_list *dma_list) {
235  	*dma_list = (struct dvi_scanline_dma_list){};	
236  }
237  
238  static const uint32_t *get_ctrl_sym(bool vsync, bool hsync) {
239  	return &dvi_ctrl_syms[!!vsync << 1 | !!hsync];
240  }
241  
242  // Make a sequence of paced transfers to the relevant FIFO
243  static void _set_data_cb(dma_cb_t *cb, const struct dvi_lane_dma_cfg *dma_cfg,
244  		const void *read_addr, uint transfer_count, uint read_ring, bool irq_on_finish) {
245  	cb->read_addr = read_addr;
246  	cb->write_addr = dma_cfg->tx_fifo;
247  	cb->transfer_count = transfer_count;
248  	cb->c = dma_channel_get_default_config(dma_cfg->chan_data);
249  	channel_config_set_ring(&cb->c, false, read_ring);
250  	channel_config_set_dreq(&cb->c, dma_cfg->dreq);
251  	// Call back to control channel for reconfiguration:
252  	channel_config_set_chain_to(&cb->c, dma_cfg->chan_ctrl);
253  	// Note we never send a null trigger, so IRQ_QUIET is an IRQ suppression flag
254  	channel_config_set_irq_quiet(&cb->c, !irq_on_finish);
255  };
256  
257  void dvi_setup_scanline_for_vblank(const struct dvi_timing *t, const struct dvi_lane_dma_cfg dma_cfg[],
258  		bool vsync_asserted, struct dvi_scanline_dma_list *l) {
259  
260  	bool vsync = t->v_sync_polarity == vsync_asserted;
261  	const uint32_t *sym_hsync_off = get_ctrl_sym(vsync, !t->h_sync_polarity);
262  	const uint32_t *sym_hsync_on  = get_ctrl_sym(vsync,  t->h_sync_polarity);
263  	const uint32_t *sym_no_sync   = get_ctrl_sym(false,  false             );
264  
265  	dma_cb_t *synclist = dvi_lane_from_list(l, TMDS_SYNC_LANE);
266  	// The symbol table contains each control symbol *twice*, concatenated into 20 LSBs of table word, so we can always do word-repeat.
267  	_set_data_cb(&synclist[0], &dma_cfg[TMDS_SYNC_LANE], sym_hsync_off, t->h_front_porch   / DVI_SYMBOLS_PER_WORD, 2, false);
268  	_set_data_cb(&synclist[1], &dma_cfg[TMDS_SYNC_LANE], sym_hsync_on,  t->h_sync_width    / DVI_SYMBOLS_PER_WORD, 2, false);
269  	_set_data_cb(&synclist[2], &dma_cfg[TMDS_SYNC_LANE], sym_hsync_off, t->h_back_porch    / DVI_SYMBOLS_PER_WORD, 2, true);
270  	_set_data_cb(&synclist[3], &dma_cfg[TMDS_SYNC_LANE], sym_hsync_off, t->h_active_pixels / DVI_SYMBOLS_PER_WORD, 2, false);
271  
272  	for (int i = 0; i < N_TMDS_LANES; ++i) {
273  		if (i == TMDS_SYNC_LANE)
274  			continue;
275  		dma_cb_t *cblist = dvi_lane_from_list(l, i);
276  		_set_data_cb(&cblist[0], &dma_cfg[i], sym_no_sync,(t->h_front_porch + t->h_sync_width + t->h_back_porch) / DVI_SYMBOLS_PER_WORD, 2, false);
277  		_set_data_cb(&cblist[1], &dma_cfg[i], sym_no_sync, t->h_active_pixels / DVI_SYMBOLS_PER_WORD, 2, false);
278  	}
279  }
280  
281  void dvi_setup_scanline_for_active(const struct dvi_timing *t, const struct dvi_lane_dma_cfg dma_cfg[],
282  		uint32_t *tmdsbuf, struct dvi_scanline_dma_list *l) {
283  
284  	const uint32_t *sym_hsync_off = get_ctrl_sym(!t->v_sync_polarity, !t->h_sync_polarity);
285  	const uint32_t *sym_hsync_on  = get_ctrl_sym(!t->v_sync_polarity,  t->h_sync_polarity);
286  	const uint32_t *sym_no_sync   = get_ctrl_sym(false,                false             );
287  
288  	dma_cb_t *synclist = dvi_lane_from_list(l, TMDS_SYNC_LANE);
289  	_set_data_cb(&synclist[0], &dma_cfg[TMDS_SYNC_LANE], sym_hsync_off, t->h_front_porch / DVI_SYMBOLS_PER_WORD, 2, false);
290  	_set_data_cb(&synclist[1], &dma_cfg[TMDS_SYNC_LANE], sym_hsync_on,  t->h_sync_width  / DVI_SYMBOLS_PER_WORD, 2, false);
291  	_set_data_cb(&synclist[2], &dma_cfg[TMDS_SYNC_LANE], sym_hsync_off, t->h_back_porch  / DVI_SYMBOLS_PER_WORD, 2, true);
292  
293  	for (int i = 0; i < N_TMDS_LANES; ++i) {
294  		dma_cb_t *cblist = dvi_lane_from_list(l, i);
295  		if (i != TMDS_SYNC_LANE) {
296  			_set_data_cb(&cblist[0], &dma_cfg[i], sym_no_sync,
297  				(t->h_front_porch + t->h_sync_width + t->h_back_porch) / DVI_SYMBOLS_PER_WORD, 2, false);
298  		}
299  		int target_block = i == TMDS_SYNC_LANE ? DVI_SYNC_LANE_CHUNKS - 1 :  DVI_NOSYNC_LANE_CHUNKS - 1;
300  		if (tmdsbuf) {
301  			// Non-repeating DMA for the freshly-encoded TMDS buffer
302  			_set_data_cb(&cblist[target_block], &dma_cfg[i], tmdsbuf + i * (t->h_active_pixels / DVI_SYMBOLS_PER_WORD),
303  				t->h_active_pixels / DVI_SYMBOLS_PER_WORD, 0, false);
304  		}
305  		else {
306  			// Use read ring to repeat the correct DC-balanced symbol pair on blank scanlines (4 or 8 byte period)
307  			_set_data_cb(&cblist[target_block], &dma_cfg[i], &empty_scanline_tmds[2 * i / DVI_SYMBOLS_PER_WORD],
308  				t->h_active_pixels / DVI_SYMBOLS_PER_WORD, DVI_SYMBOLS_PER_WORD == 2 ? 2 : 3, false);
309  		}
310  	}
311  }
312  
313  void __dvi_func(dvi_update_scanline_data_dma)(const struct dvi_timing *t, const uint32_t *tmdsbuf, struct dvi_scanline_dma_list *l) {
314  	for (int i = 0; i < N_TMDS_LANES; ++i) {
315  #if DVI_MONOCHROME_TMDS
316  		const uint32_t *lane_tmdsbuf = tmdsbuf;
317  #else
318  		const uint32_t *lane_tmdsbuf = tmdsbuf + i * t->h_active_pixels / DVI_SYMBOLS_PER_WORD;
319  #endif
320  		if (i == TMDS_SYNC_LANE)
321  			dvi_lane_from_list(l, i)[3].read_addr = lane_tmdsbuf;
322  		else
323  			dvi_lane_from_list(l, i)[1].read_addr = lane_tmdsbuf;
324  	}
325  }
326