11
11
#include <linux/delay.h>
12
12
#include <linux/interrupt.h>
13
13
#include <linux/platform_device.h>
14
- #include <linux/printk.h>
15
14
#include <drm/drm_fourcc.h>
16
15
#include <drm/drm_print.h>
17
16
#include <drm/drm_vblank.h>
@@ -82,13 +81,13 @@ static const struct rp1vec_ipixfmt my_formats[] = {
82
81
/*
83
82
* Hardware mode descriptions (@ 108 MHz clock rate).
84
83
* These rely largely on "canned" register settings.
85
- * TODO: Port the generating software from FP to integer,
86
- * or better factorize the differences between modes.
87
84
*/
88
85
89
86
struct rp1vec_hwmode {
90
- u16 total_cols ; /* active columns, plus padding for filter context */
87
+ u16 total_cols ; /* max active columns incl. padding and windowing */
91
88
u16 rows_per_field ; /* active lines per field (including partial ones) */
89
+ u16 ref_hfp ; /* nominal (hsync_start - hdisplay) when max width */
90
+ u16 ref_vfp ; /* nominal (vsync_start - vdisplay) when max height */
92
91
bool interlaced ; /* set for interlaced */
93
92
bool first_field_odd ; /* set for interlaced and 30fps */
94
93
u32 yuv_scaling ; /* three 10-bit fields {Y, U, V} in 2.8 format */
@@ -103,6 +102,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
103
102
{
104
103
.total_cols = 724 ,
105
104
.rows_per_field = 240 ,
105
+ .ref_hfp = 12 ,
106
+ .ref_vfp = 2 ,
106
107
.interlaced = false,
107
108
.first_field_odd = false,
108
109
.yuv_scaling = 0x1071d0cf ,
@@ -118,6 +119,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
118
119
}, {
119
120
.total_cols = 815 ,
120
121
.rows_per_field = 240 ,
122
+ .ref_hfp = 16 ,
123
+ .ref_vfp = 2 ,
121
124
.interlaced = false,
122
125
.first_field_odd = false,
123
126
.yuv_scaling = 0x1c131962 ,
@@ -135,6 +138,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
135
138
{
136
139
.total_cols = 724 ,
137
140
.rows_per_field = 243 ,
141
+ .ref_hfp = 12 ,
142
+ .ref_vfp = 3 ,
138
143
.interlaced = true,
139
144
.first_field_odd = true,
140
145
.yuv_scaling = 0x1071d0cf ,
@@ -150,6 +155,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
150
155
}, {
151
156
.total_cols = 815 ,
152
157
.rows_per_field = 243 ,
158
+ .ref_hfp = 16 ,
159
+ .ref_vfp = 3 ,
153
160
.interlaced = true,
154
161
.first_field_odd = true,
155
162
.yuv_scaling = 0x1c131962 ,
@@ -170,6 +177,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
170
177
{
171
178
.total_cols = 724 ,
172
179
.rows_per_field = 288 ,
180
+ .ref_hfp = 16 ,
181
+ .ref_vfp = 2 ,
173
182
.interlaced = false,
174
183
.first_field_odd = false,
175
184
.yuv_scaling = 0x11c1f8e0 ,
@@ -185,6 +194,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
185
194
}, {
186
195
.total_cols = 804 ,
187
196
.rows_per_field = 288 ,
197
+ .ref_hfp = 24 ,
198
+ .ref_vfp = 2 ,
188
199
.interlaced = false,
189
200
.first_field_odd = false,
190
201
.yuv_scaling = 0x1e635d7f ,
@@ -202,6 +213,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
202
213
{
203
214
.total_cols = 724 ,
204
215
.rows_per_field = 288 ,
216
+ .ref_hfp = 16 ,
217
+ .ref_vfp = 5 ,
205
218
.interlaced = true,
206
219
.first_field_odd = false,
207
220
.yuv_scaling = 0x11c1f8e0 ,
@@ -217,6 +230,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
217
230
}, {
218
231
.total_cols = 804 ,
219
232
.rows_per_field = 288 ,
233
+ .ref_hfp = 24 ,
234
+ .ref_vfp = 5 ,
220
235
.interlaced = true,
221
236
.first_field_odd = false,
222
237
.yuv_scaling = 0x1e635d7f ,
@@ -237,6 +252,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
237
252
{
238
253
.total_cols = 724 ,
239
254
.rows_per_field = 240 ,
255
+ .ref_hfp = 12 ,
256
+ .ref_vfp = 2 ,
240
257
.interlaced = false,
241
258
.first_field_odd = false,
242
259
.yuv_scaling = 0x11c1f8e0 ,
@@ -252,6 +269,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
252
269
}, {
253
270
.total_cols = 815 ,
254
271
.rows_per_field = 240 ,
272
+ .ref_hfp = 16 ,
273
+ .ref_vfp = 2 ,
255
274
.interlaced = false,
256
275
.first_field_odd = false,
257
276
.yuv_scaling = 0x1e635d7f ,
@@ -269,6 +288,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
269
288
{
270
289
.total_cols = 724 ,
271
290
.rows_per_field = 243 ,
291
+ .ref_hfp = 12 ,
292
+ .ref_vfp = 3 ,
272
293
.interlaced = true,
273
294
.first_field_odd = true,
274
295
.yuv_scaling = 0x11c1f8e0 ,
@@ -284,6 +305,8 @@ static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = {
284
305
}, {
285
306
.total_cols = 815 ,
286
307
.rows_per_field = 243 ,
308
+ .ref_hfp = 16 ,
309
+ .ref_vfp = 3 ,
287
310
.interlaced = true,
288
311
.first_field_odd = true,
289
312
.yuv_scaling = 0x1e635d7f ,
@@ -308,11 +331,11 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
308
331
{
309
332
unsigned int i , mode_family , mode_ilaced , mode_narrow ;
310
333
const struct rp1vec_hwmode * hwm ;
311
- unsigned int w , h ;
334
+ int w , h , hpad , vpad ;
312
335
313
336
/* Pick the appropriate "base" mode, which we may modify */
314
337
mode_ilaced = !!(mode -> flags & DRM_MODE_FLAG_INTERLACE );
315
- if (mode -> vtotal > 263 * (1 + mode_ilaced ))
338
+ if (mode -> vtotal >= 272 * (1 + mode_ilaced ))
316
339
mode_family = 1 ;
317
340
else
318
341
mode_family = (tvstd == RP1VEC_TVSTD_PAL_M || tvstd == RP1VEC_TVSTD_PAL60 ) ? 2 : 0 ;
@@ -326,13 +349,28 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
326
349
tvstd , rp1vec_tvstd_names [tvstd ]);
327
350
328
351
w = mode -> hdisplay ;
329
- h = mode -> vdisplay ;
330
- if (mode_ilaced )
331
- h >>= 1 ;
352
+ h = mode -> vdisplay >> mode_ilaced ;
332
353
if (w > hwm -> total_cols )
333
354
w = hwm -> total_cols ;
334
355
if (h > hwm -> rows_per_field )
335
- w = hwm -> rows_per_field ;
356
+ h = hwm -> rows_per_field ;
357
+
358
+ /*
359
+ * Add padding so a framebuffer with the given dimensions and
360
+ * [hv]sync_start can be displayed in the chosen hardware mode.
361
+ *
362
+ * |<----- mode->hsync_start ----->|
363
+ * |<------ w ------>| |
364
+ * | | >|--|< ref_hfp
365
+ * |<- hpad ->|
366
+ * |<------------ total_cols ----------->|
367
+ * ________FRAMEBUFFERCONTENTS__________
368
+ * ' `--\____/-<\/\/\>-'
369
+ */
370
+ hpad = max (0 , mode -> hsync_start - hwm -> ref_hfp - w );
371
+ hpad = min (hpad , hwm -> total_cols - w );
372
+ vpad = max (0 , ((mode -> vsync_start - hwm -> ref_vfp ) >> mode_ilaced ) - h );
373
+ vpad = min (vpad , hwm -> rows_per_field - h );
336
374
337
375
/* Configure the hardware */
338
376
VEC_WRITE (VEC_APB_TIMEOUT , 0x38 );
@@ -347,18 +385,18 @@ void rp1vec_hw_setup(struct rp1_vec *vec,
347
385
BITS (VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1 , h - 1 ));
348
386
VEC_WRITE (VEC_YUV_SCALING , hwm -> yuv_scaling );
349
387
VEC_WRITE (VEC_BACK_PORCH ,
350
- BITS (VEC_BACK_PORCH_HBP_MINUS1 , ( hwm -> total_cols - w - 1 ) >> 1 ) |
351
- BITS (VEC_BACK_PORCH_VBP_MINUS1 , ( hwm -> rows_per_field - h - 1 ) >> 1 ));
388
+ BITS (VEC_BACK_PORCH_HBP_MINUS1 , hwm -> total_cols - w - hpad - 1 ) |
389
+ BITS (VEC_BACK_PORCH_VBP_MINUS1 , hwm -> rows_per_field - h - vpad - 1 ));
352
390
VEC_WRITE (VEC_FRONT_PORCH ,
353
- BITS (VEC_FRONT_PORCH_HFP_MINUS1 , ( hwm -> total_cols - w - 2 ) >> 1 ) |
354
- BITS (VEC_FRONT_PORCH_VFP_MINUS1 , ( hwm -> rows_per_field - h - 2 ) >> 1 ));
391
+ BITS (VEC_FRONT_PORCH_HFP_MINUS1 , hpad - 1 ) |
392
+ BITS (VEC_FRONT_PORCH_VFP_MINUS1 , vpad - 1 ));
355
393
VEC_WRITE (VEC_MODE ,
356
394
BITS (VEC_MODE_HIGH_WATER , 0xE0 ) |
357
395
BITS (VEC_MODE_ALIGN16 , !((w | mode -> hdisplay ) & 15 )) |
358
- BITS (VEC_MODE_VFP_EN , (hwm -> rows_per_field > h + 1 )) |
359
- BITS (VEC_MODE_VBP_EN , (hwm -> rows_per_field > h )) |
360
- BITS (VEC_MODE_HFP_EN , (hwm -> total_cols > w + 1 )) |
361
- BITS (VEC_MODE_HBP_EN , (hwm -> total_cols > w )) |
396
+ BITS (VEC_MODE_VFP_EN , (vpad > 0 )) |
397
+ BITS (VEC_MODE_VBP_EN , (hwm -> rows_per_field > h + vpad )) |
398
+ BITS (VEC_MODE_HFP_EN , (hpad > 0 )) |
399
+ BITS (VEC_MODE_HBP_EN , (hwm -> total_cols > w + hpad )) |
362
400
BITS (VEC_MODE_FIELDS_PER_FRAME_MINUS1 , hwm -> interlaced ) |
363
401
BITS (VEC_MODE_FIRST_FIELD_ODD , hwm -> first_field_odd ));
364
402
for (i = 0 ; i < ARRAY_SIZE (hwm -> back_end_regs ); ++ i ) {
0 commit comments