22
22
#define VEC_WRITE (reg , val ) writel((val), vec->hw_base[RP1VEC_HW_BLOCK_VEC] + (reg ## _OFFSET))
23
23
#define VEC_READ (reg ) readl(vec->hw_base[RP1VEC_HW_BLOCK_VEC] + (reg ## _OFFSET))
24
24
25
- /* Experimental mode for interlace with 60fps buffer flips */
26
- #define FIELD_WOBBLE
27
-
28
25
static void rp1vec_write_regs (struct rp1_vec * vec , u32 offset , u32 const * vals , u32 num )
29
26
{
30
27
while (num -- ) {
@@ -105,13 +102,18 @@ static const struct rp1vec_ipixfmt my_formats[] = {
105
102
* See "vec_regs.h" for further descriptions of these registers and fields.
106
103
* Driver should adjust some values for other TV standards and for pixel rate,
107
104
* and must ensure that ((de_end - de_bgn) % rate) == 0.
105
+ *
106
+ * To support 60fps update in interlaced modes, we now do ISR-based field-flip.
107
+ * The FIELDS_PER_FRAME_MINUS1 flag in "misc" is no longer set. Some vertical
108
+ * timings have been rotated wrt conventional line-numbering (to ensure a gap
109
+ * between the last active line and nominal end-of-field).
108
110
*/
109
111
110
112
struct rp1vec_hwmode {
111
113
u16 max_rows_per_field ; /* active lines per field (including partial ones) */
112
114
u16 ref_vfp ; /* nominal (vsync_start - vdisplay) when max height */
113
115
bool interlaced ; /* set for interlaced */
114
- bool first_field_odd ; /* depends confusingly on line numbering convention */
116
+ bool first_field_odd ; /* true if odd-indexed scanlines go to first field */
115
117
s16 scale_v ; /* V scale in 2.8 format (for power-of-2 CIC rates) */
116
118
s16 scale_u ; /* U scale in 2.8 format (for power-of-2 CIC rates) */
117
119
u16 scale_y ; /* Y scale in 2.8 format (for power-of-2 CIC rates) */
@@ -169,31 +171,14 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2] = {
169
171
.scale_luma = 0x8c9a ,
170
172
.scale_sync = 0x3851 ,
171
173
.scale_burst_chroma = 0x11195561 ,
172
- .misc = 0x00094c02 , /* 5-tap FIR, SEQ_EN, 2 flds, 4 fld sync, ilace */
174
+ .misc = 0x00094c00 , /* 5-tap FIR, SEQ_EN, 2 flds, 4 fld sync */
173
175
.nco_freq = 0x087c1f07c1f07c1f ,
174
- #ifdef FIELD_WOBBLE
175
- /*
176
- * NOTE: For the "field-wobble" interlace technique
177
- * (used to achieve 60fps buffer-flip rate) to work,
178
- * we had to offset the vertical timings so that VSYNC
179
- * starts at half-line 0; all image line numbers are
180
- * reduced by 3 compared to NTSC standard numbering.
181
- * This should have no effect on the actual frame.
182
- */
183
176
.timing_regs = {
184
177
0x03e10cc6 , 0x0d6801fb , 0x023d034c , 0x00f80b6d ,
185
178
0x0207020c , 0x00000005 , 0x0006000b , 0x00070104 ,
186
179
0x010e020a , 0x00000000 , 0x00000000 , 0x0119020a ,
187
180
0x00120103 , 0x01040118 ,
188
181
},
189
- #else
190
- .timing_regs = {
191
- 0x03e10cc6 , 0x0d6801fb , 0x023d034c , 0x00f80b6d ,
192
- 0x00000005 , 0x0006000b , 0x000c0011 , 0x000a0107 ,
193
- 0x0111020d , 0x00000000 , 0x00000000 , 0x011c020d ,
194
- 0x00150106 , 0x0107011b ,
195
- },
196
- #endif
197
182
},
198
183
}, {
199
184
/* PAL */
@@ -235,7 +220,7 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2] = {
235
220
.scale_luma = 0x89d8 ,
236
221
.scale_sync = 0x3c00 ,
237
222
.scale_burst_chroma = 0x0caf53b5 ,
238
- .misc = 0x0009dc03 , /* 5-tap FIR, SEQ_EN, 4 flds, 8 fld sync, ilace , PAL */
223
+ .misc = 0x0009dc01 , /* 5-tap FIR, SEQ_EN, 4 flds, 8 fld sync, PAL */
239
224
.nco_freq = 0x0a8262b2cc48c1d1 ,
240
225
.timing_regs = {
241
226
0x04660cee , 0x0d8001fb , 0x025c034f , 0x00fd0b84 ,
@@ -261,7 +246,7 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2] = {
261
246
.scale_luma = 0x89d8 ,
262
247
.scale_sync = 0x3851 ,
263
248
.scale_burst_chroma = 0x0d5c53b5 ,
264
- .misc = 0x00091c01 , /* 5-tap FIR, SEQ_EN, 8 fld sync PAL */
249
+ .misc = 0x00091c01 , /* 5-tap FIR, SEQ_EN, 8 fld sync, PAL */
265
250
.nco_freq = 0x0879bbf8d6d33ea8 ,
266
251
.timing_regs = {
267
252
0x03e10cc6 , 0x0d6801fb , 0x023c034c , 0x00f80b6e ,
@@ -284,7 +269,7 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2] = {
284
269
.scale_luma = 0x89d8 ,
285
270
.scale_sync = 0x3851 ,
286
271
.scale_burst_chroma = 0x0d5c53b5 ,
287
- .misc = 0x0009dc03 , /* 5-tap FIR, SEQ_EN, 4 flds, 8 fld sync, ilace , PAL */
272
+ .misc = 0x0009dc01 , /* 5-tap FIR, SEQ_EN, 4 flds, 8 fld sync, PAL */
288
273
.nco_freq = 0x0879bbf8d6d33ea8 ,
289
274
.timing_regs = {
290
275
0x03e10cc6 , 0x0d6801fb , 0x023c034c , 0x00f80b6e ,
@@ -313,28 +298,14 @@ static const struct rp1vec_hwmode rp1vec_vintage_modes[2] = {
313
298
.scale_luma = 0x89d8 ,
314
299
.scale_sync = 0x3c00 ,
315
300
.scale_burst_chroma = 0 ,
316
- .misc = 0x00084002 , /* 5-tap FIR, 2 fields, interlace */
301
+ .misc = 0x00084000 , /* 5-tap FIR, 2 fields */
317
302
.nco_freq = 0 ,
318
- #ifdef FIELD_WOBBLE
319
- /*
320
- * Again we must offset the vertical timings to leave a gap
321
- * between the last active line and the field/frame datum.
322
- * This means the VSync sequence is banished to field end!
323
- */
324
303
.timing_regs = {
325
304
0x06f01430 , 0x14d503cc , 0x00000000 , 0x000010de ,
326
305
0x03000300 , 0x018d0194 , 0x03000300 , 0x00000000 ,
327
306
0x00000000 , 0x00000000 , 0x00000000 , 0x00d50191 ,
328
307
0x000a00c6 , 0x00c700d4 ,
329
308
},
330
- #else
331
- .timing_regs = {
332
- 0x06f01430 , 0x14d503cc , 0x00000000 , 0x000010de ,
333
- 0x00000000 , 0x00000007 , 0x00000000 , 0x00000000 ,
334
- 0x00000000 , 0x00000000 , 0x00000000 , 0x00d90195 ,
335
- 0x000e00ca , 0x00cb00d8 ,
336
- },
337
- #endif
338
309
}, {
339
310
.max_rows_per_field = 369 ,
340
311
.ref_vfp = 6 ,
@@ -350,7 +321,7 @@ static const struct rp1vec_hwmode rp1vec_vintage_modes[2] = {
350
321
.scale_luma = 0x89d8 ,
351
322
.scale_sync = 0x3b13 ,
352
323
.scale_burst_chroma = 0 ,
353
- .misc = 0x00084002 , /* 5-tap FIR, 2 fields, interlace */
324
+ .misc = 0x00084000 , /* 5-tap FIR, 2 fields */
354
325
.nco_freq = 0 ,
355
326
.timing_regs = {
356
327
0x03c10a08 , 0x0a4d0114 , 0x00000000 , 0x000008a6 ,
@@ -463,7 +434,12 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
463
434
vpad_b = ((mode -> vsync_start - hwm -> ref_vfp ) >> (hwm -> interlaced || vec -> fake_31khz )) - h ;
464
435
vpad_b = min (max (0 , vpad_b ), hwm -> max_rows_per_field - h );
465
436
466
- /* Configure the hardware "front end" (in the sysclock domain) */
437
+ /*
438
+ * Configure the hardware "front end" (in the sysclock domain).
439
+ * Note: To support 60fps update (per-field buffer flips), we no longer
440
+ * enable VEC's native interlaced mode (which can't flip in mid-frame).
441
+ * Instead, send individual fields, using software to flip between them.
442
+ */
467
443
VEC_WRITE (VEC_APB_TIMEOUT , 0x38 );
468
444
VEC_WRITE (VEC_QOS ,
469
445
BITS (VEC_QOS_DQOS , 0x0 ) |
@@ -493,12 +469,7 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
493
469
BITS (VEC_MODE_VFP_EN , (vpad_b > 0 )) |
494
470
BITS (VEC_MODE_VBP_EN , (hwm -> max_rows_per_field > h + vpad_b )) |
495
471
BITS (VEC_MODE_HFP_EN , (hpad_r > 0 )) |
496
- BITS (VEC_MODE_HBP_EN , (wmax > w + hpad_r )) |
497
- #ifndef FIELD_WOBBLE /* Clear these for field-wobble! */
498
- BITS (VEC_MODE_FIELDS_PER_FRAME_MINUS1 , hwm -> interlaced ) |
499
- BITS (VEC_MODE_FIRST_FIELD_ODD , hwm -> first_field_odd ) |
500
- #endif
501
- 0 );
472
+ BITS (VEC_MODE_HBP_EN , (wmax > w + hpad_r )));
502
473
503
474
/* Configure the hardware "back end" (in the VDAC clock domain) */
504
475
VEC_WRITE (VEC_DAC_80 ,
@@ -529,9 +500,6 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
529
500
VEC_WRITE (VEC_DAC_CC , (tvstd >= DRM_MODE_TV_MODE_SECAM ) ? 0 : hwm -> scale_burst_chroma );
530
501
VEC_WRITE (VEC_DAC_D0 , 0x02000000 ); /* ADC offsets -- not needed in RP1? */
531
502
misc = hwm -> misc ;
532
- #ifdef FIELD_WOBBLE
533
- misc &= ~2 ; /* For field-wobble: Clear the "fields_per_frame_minus1" flag! */
534
- #endif
535
503
if ((tvstd == DRM_MODE_TV_MODE_NTSC_443 || tvstd == DRM_MODE_TV_MODE_PAL ) &&
536
504
mode_family != 1 ) {
537
505
/* Change colour carrier frequency to 4433618.75 Hz; disable hard sync */
@@ -549,13 +517,9 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
549
517
VEC_WRITE (VEC_DAC_EC , misc | rp1vec_rate_shift_table [rate - 4 ]);
550
518
rp1vec_write_regs (vec , 0xDC , rp1vec_fir_regs , ARRAY_SIZE (rp1vec_fir_regs ));
551
519
552
- #ifdef FIELD_WOBBLE
553
- vec -> interlaced = hwm -> interlaced ;
520
+ /* State for software-based field flipping */
521
+ vec -> field_flip = hwm -> interlaced ;
554
522
vec -> lower_field_flag = hwm -> first_field_odd ;
555
- #else
556
- vec -> interlaced = false;
557
- vec -> lower_field_flag = false;
558
- #endif
559
523
vec -> last_dma_addr = 0 ;
560
524
561
525
/* Set up interrupts and initialise VEC. It will start on the next rp1vec_hw_update() */
@@ -576,19 +540,20 @@ void rp1vec_hw_update(struct rp1_vec *vec, dma_addr_t addr, u32 offset, u32 stri
576
540
{
577
541
unsigned long flags ;
578
542
579
- spin_lock_irqsave ( & vec -> hw_lock , flags ) ;
543
+ addr += offset ;
580
544
581
545
/*
582
546
* Update STRIDE, DMAH and DMAL only. When called after rp1vec_hw_setup(),
583
547
* DMA starts immediately; if already running, the buffer will flip at
584
- * the next vertical sync event. In interlaced mode, we need to adjust
585
- * the address and stride to display only the current field, saving
586
- * the original address (so it can be flipped for subsequent fields).
548
+ * the next vertical sync event. For field-rate update in interlaced modes,
549
+ * we need to adjust the address and stride to display the current field,
550
+ * saving the original address (so it can be flipped for subsequent fields).
587
551
*/
588
- addr += offset ;
552
+ spin_lock_irqsave (& vec -> hw_lock , flags );
553
+
589
554
vec -> last_dma_addr = addr ;
590
555
vec -> last_stride = stride ;
591
- if (vec -> fake_31khz || vec -> interlaced ) {
556
+ if (vec -> field_flip || vec -> fake_31khz ) {
592
557
if (vec -> fake_31khz || vec -> lower_field_flag )
593
558
addr += stride ;
594
559
stride *= 2 ;
@@ -624,11 +589,9 @@ void rp1vec_hw_stop(struct rp1_vec *vec)
624
589
void rp1vec_hw_vblank_ctrl (struct rp1_vec * vec , int enable )
625
590
{
626
591
VEC_WRITE (VEC_IRQ_ENABLES ,
627
- BITS (VEC_IRQ_ENABLES_DONE , 1 ) |
628
- BITS (VEC_IRQ_ENABLES_DMA , (enable ? 1 : 0 )) |
629
- #ifdef FIELD_WOBBLE
630
- BITS (VEC_IRQ_ENABLES_MATCH , vec -> interlaced ) |
631
- #endif
592
+ BITS (VEC_IRQ_ENABLES_DONE , 1 ) |
593
+ BITS (VEC_IRQ_ENABLES_DMA , (enable ? 1 : 0 )) |
594
+ BITS (VEC_IRQ_ENABLES_MATCH , vec -> field_flip ) |
632
595
BITS (VEC_IRQ_ENABLES_MATCH_ROW , 32 ));
633
596
}
634
597
@@ -644,14 +607,13 @@ irqreturn_t rp1vec_hw_isr(int irq, void *dev)
644
607
if (u & VEC_IRQ_FLAGS_DONE_BITS )
645
608
complete (& vec -> finished );
646
609
647
- #ifdef FIELD_WOBBLE
648
610
/*
649
611
* VEC has native support for interlaced modes, but that only
650
612
* supports buffer-flips per frame (30fps), not field (60fps).
651
613
* Instead, we always run the VEC front end in a "progressive"
652
- * mode and use the "field-wobble " trick (see RP1 DPI driver).
614
+ * mode and use the "field-flip " trick (see RP1 DPI driver).
653
615
*/
654
- if ((u & VEC_IRQ_FLAGS_MATCH_BITS ) && vec -> interlaced ) {
616
+ if ((u & VEC_IRQ_FLAGS_MATCH_BITS ) && vec -> field_flip ) {
655
617
unsigned long flags ;
656
618
dma_addr_t a ;
657
619
@@ -666,7 +628,6 @@ irqreturn_t rp1vec_hw_isr(int irq, void *dev)
666
628
}
667
629
spin_unlock_irqrestore (& vec -> hw_lock , flags );
668
630
}
669
- #endif
670
631
}
671
632
672
633
return u ? IRQ_HANDLED : IRQ_NONE ;
0 commit comments