Skip to content

Commit a6d2984

Browse files
TIDY UP (TO SQUASH)
After further testing I'm happy this seems stable and doesn't need to be conditionally enabled. Remove the #ifdef and tidy up. Signed-off-by: Nick Hollinghurst <[email protected]>
1 parent 1d7086c commit a6d2984

File tree

2 files changed

+34
-73
lines changed

2 files changed

+34
-73
lines changed

drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct rp1_vec {
5454
spinlock_t hw_lock; /* the following are used in line-match ISR */
5555
dma_addr_t last_dma_addr;
5656
u32 last_stride;
57-
bool interlaced;
57+
bool field_flip;
5858
bool lower_field_flag;
5959
};
6060

drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c

Lines changed: 33 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
#define VEC_WRITE(reg, val) writel((val), vec->hw_base[RP1VEC_HW_BLOCK_VEC] + (reg ## _OFFSET))
2323
#define VEC_READ(reg) readl(vec->hw_base[RP1VEC_HW_BLOCK_VEC] + (reg ## _OFFSET))
2424

25-
/* Experimental mode for interlace with 60fps buffer flips */
26-
#define FIELD_WOBBLE
27-
2825
static void rp1vec_write_regs(struct rp1_vec *vec, u32 offset, u32 const *vals, u32 num)
2926
{
3027
while (num--) {
@@ -105,13 +102,18 @@ static const struct rp1vec_ipixfmt my_formats[] = {
105102
* See "vec_regs.h" for further descriptions of these registers and fields.
106103
* Driver should adjust some values for other TV standards and for pixel rate,
107104
* 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).
108110
*/
109111

110112
struct rp1vec_hwmode {
111113
u16 max_rows_per_field; /* active lines per field (including partial ones) */
112114
u16 ref_vfp; /* nominal (vsync_start - vdisplay) when max height */
113115
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 */
115117
s16 scale_v; /* V scale in 2.8 format (for power-of-2 CIC rates) */
116118
s16 scale_u; /* U scale in 2.8 format (for power-of-2 CIC rates) */
117119
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] = {
169171
.scale_luma = 0x8c9a,
170172
.scale_sync = 0x3851,
171173
.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 */
173175
.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-
*/
183176
.timing_regs = {
184177
0x03e10cc6, 0x0d6801fb, 0x023d034c, 0x00f80b6d,
185178
0x0207020c, 0x00000005, 0x0006000b, 0x00070104,
186179
0x010e020a, 0x00000000, 0x00000000, 0x0119020a,
187180
0x00120103, 0x01040118,
188181
},
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
197182
},
198183
}, {
199184
/* PAL */
@@ -235,7 +220,7 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2] = {
235220
.scale_luma = 0x89d8,
236221
.scale_sync = 0x3c00,
237222
.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 */
239224
.nco_freq = 0x0a8262b2cc48c1d1,
240225
.timing_regs = {
241226
0x04660cee, 0x0d8001fb, 0x025c034f, 0x00fd0b84,
@@ -261,7 +246,7 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2] = {
261246
.scale_luma = 0x89d8,
262247
.scale_sync = 0x3851,
263248
.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 */
265250
.nco_freq = 0x0879bbf8d6d33ea8,
266251
.timing_regs = {
267252
0x03e10cc6, 0x0d6801fb, 0x023c034c, 0x00f80b6e,
@@ -284,7 +269,7 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2] = {
284269
.scale_luma = 0x89d8,
285270
.scale_sync = 0x3851,
286271
.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 */
288273
.nco_freq = 0x0879bbf8d6d33ea8,
289274
.timing_regs = {
290275
0x03e10cc6, 0x0d6801fb, 0x023c034c, 0x00f80b6e,
@@ -313,28 +298,14 @@ static const struct rp1vec_hwmode rp1vec_vintage_modes[2] = {
313298
.scale_luma = 0x89d8,
314299
.scale_sync = 0x3c00,
315300
.scale_burst_chroma = 0,
316-
.misc = 0x00084002, /* 5-tap FIR, 2 fields, interlace */
301+
.misc = 0x00084000, /* 5-tap FIR, 2 fields */
317302
.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-
*/
324303
.timing_regs = {
325304
0x06f01430, 0x14d503cc, 0x00000000, 0x000010de,
326305
0x03000300, 0x018d0194, 0x03000300, 0x00000000,
327306
0x00000000, 0x00000000, 0x00000000, 0x00d50191,
328307
0x000a00c6, 0x00c700d4,
329308
},
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
338309
}, {
339310
.max_rows_per_field = 369,
340311
.ref_vfp = 6,
@@ -350,7 +321,7 @@ static const struct rp1vec_hwmode rp1vec_vintage_modes[2] = {
350321
.scale_luma = 0x89d8,
351322
.scale_sync = 0x3b13,
352323
.scale_burst_chroma = 0,
353-
.misc = 0x00084002, /* 5-tap FIR, 2 fields, interlace */
324+
.misc = 0x00084000, /* 5-tap FIR, 2 fields */
354325
.nco_freq = 0,
355326
.timing_regs = {
356327
0x03c10a08, 0x0a4d0114, 0x00000000, 0x000008a6,
@@ -463,7 +434,12 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
463434
vpad_b = ((mode->vsync_start - hwm->ref_vfp) >> (hwm->interlaced || vec->fake_31khz)) - h;
464435
vpad_b = min(max(0, vpad_b), hwm->max_rows_per_field - h);
465436

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+
*/
467443
VEC_WRITE(VEC_APB_TIMEOUT, 0x38);
468444
VEC_WRITE(VEC_QOS,
469445
BITS(VEC_QOS_DQOS, 0x0) |
@@ -493,12 +469,7 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
493469
BITS(VEC_MODE_VFP_EN, (vpad_b > 0)) |
494470
BITS(VEC_MODE_VBP_EN, (hwm->max_rows_per_field > h + vpad_b)) |
495471
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)));
502473

503474
/* Configure the hardware "back end" (in the VDAC clock domain) */
504475
VEC_WRITE(VEC_DAC_80,
@@ -529,9 +500,6 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
529500
VEC_WRITE(VEC_DAC_CC, (tvstd >= DRM_MODE_TV_MODE_SECAM) ? 0 : hwm->scale_burst_chroma);
530501
VEC_WRITE(VEC_DAC_D0, 0x02000000); /* ADC offsets -- not needed in RP1? */
531502
misc = hwm->misc;
532-
#ifdef FIELD_WOBBLE
533-
misc &= ~2; /* For field-wobble: Clear the "fields_per_frame_minus1" flag! */
534-
#endif
535503
if ((tvstd == DRM_MODE_TV_MODE_NTSC_443 || tvstd == DRM_MODE_TV_MODE_PAL) &&
536504
mode_family != 1) {
537505
/* Change colour carrier frequency to 4433618.75 Hz; disable hard sync */
@@ -549,13 +517,9 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
549517
VEC_WRITE(VEC_DAC_EC, misc | rp1vec_rate_shift_table[rate - 4]);
550518
rp1vec_write_regs(vec, 0xDC, rp1vec_fir_regs, ARRAY_SIZE(rp1vec_fir_regs));
551519

552-
#ifdef FIELD_WOBBLE
553-
vec->interlaced = hwm->interlaced;
520+
/* State for software-based field flipping */
521+
vec->field_flip = hwm->interlaced;
554522
vec->lower_field_flag = hwm->first_field_odd;
555-
#else
556-
vec->interlaced = false;
557-
vec->lower_field_flag = false;
558-
#endif
559523
vec->last_dma_addr = 0;
560524

561525
/* 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
576540
{
577541
unsigned long flags;
578542

579-
spin_lock_irqsave(&vec->hw_lock, flags);
543+
addr += offset;
580544

581545
/*
582546
* Update STRIDE, DMAH and DMAL only. When called after rp1vec_hw_setup(),
583547
* 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).
587551
*/
588-
addr += offset;
552+
spin_lock_irqsave(&vec->hw_lock, flags);
553+
589554
vec->last_dma_addr = addr;
590555
vec->last_stride = stride;
591-
if (vec->fake_31khz || vec->interlaced) {
556+
if (vec->field_flip || vec->fake_31khz) {
592557
if (vec->fake_31khz || vec->lower_field_flag)
593558
addr += stride;
594559
stride *= 2;
@@ -624,11 +589,9 @@ void rp1vec_hw_stop(struct rp1_vec *vec)
624589
void rp1vec_hw_vblank_ctrl(struct rp1_vec *vec, int enable)
625590
{
626591
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) |
632595
BITS(VEC_IRQ_ENABLES_MATCH_ROW, 32));
633596
}
634597

@@ -644,14 +607,13 @@ irqreturn_t rp1vec_hw_isr(int irq, void *dev)
644607
if (u & VEC_IRQ_FLAGS_DONE_BITS)
645608
complete(&vec->finished);
646609

647-
#ifdef FIELD_WOBBLE
648610
/*
649611
* VEC has native support for interlaced modes, but that only
650612
* supports buffer-flips per frame (30fps), not field (60fps).
651613
* 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).
653615
*/
654-
if ((u & VEC_IRQ_FLAGS_MATCH_BITS) && vec->interlaced) {
616+
if ((u & VEC_IRQ_FLAGS_MATCH_BITS) && vec->field_flip) {
655617
unsigned long flags;
656618
dma_addr_t a;
657619

@@ -666,7 +628,6 @@ irqreturn_t rp1vec_hw_isr(int irq, void *dev)
666628
}
667629
spin_unlock_irqrestore(&vec->hw_lock, flags);
668630
}
669-
#endif
670631
}
671632

672633
return u ? IRQ_HANDLED : IRQ_NONE;

0 commit comments

Comments
 (0)