hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/drivers/gpu/drm/sun4i/sun4i_frontend.c
....@@ -3,17 +3,22 @@
33 * Copyright (C) 2017 Free Electrons
44 * Maxime Ripard <maxime.ripard@free-electrons.com>
55 */
6
-#include <drm/drmP.h>
7
-#include <drm/drm_gem_cma_helper.h>
8
-#include <drm/drm_fb_cma_helper.h>
96
107 #include <linux/clk.h>
118 #include <linux/component.h>
129 #include <linux/module.h>
10
+#include <linux/of_device.h>
1311 #include <linux/platform_device.h>
1412 #include <linux/pm_runtime.h>
1513 #include <linux/regmap.h>
1614 #include <linux/reset.h>
15
+
16
+#include <drm/drm_device.h>
17
+#include <drm/drm_fb_cma_helper.h>
18
+#include <drm/drm_fourcc.h>
19
+#include <drm/drm_framebuffer.h>
20
+#include <drm/drm_gem_cma_helper.h>
21
+#include <drm/drm_plane.h>
1722
1823 #include "sun4i_drv.h"
1924 #include "sun4i_frontend.h"
....@@ -48,9 +53,37 @@
4853 0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
4954 };
5055
56
+/*
57
+ * These coefficients are taken from the A33 BSP from Allwinner.
58
+ *
59
+ * The first three values of each row are coded as 13-bit signed fixed-point
60
+ * numbers, with 10 bits for the fractional part. The fourth value is a
61
+ * constant coded as a 14-bit signed fixed-point number with 4 bits for the
62
+ * fractional part.
63
+ *
64
+ * The values in table order give the following colorspace translation:
65
+ * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
66
+ * R = 1.164 * Y + 1.596 * V - 222
67
+ * B = 1.164 * Y + 2.018 * U + 276
68
+ *
69
+ * This seems to be a conversion from Y[16:235] UV[16:240] to RGB[0:255],
70
+ * following the BT601 spec.
71
+ */
72
+const u32 sunxi_bt601_yuv2rgb_coef[12] = {
73
+ 0x000004a7, 0x00001e6f, 0x00001cbf, 0x00000877,
74
+ 0x000004a7, 0x00000000, 0x00000662, 0x00003211,
75
+ 0x000004a7, 0x00000812, 0x00000000, 0x00002eb1,
76
+};
77
+EXPORT_SYMBOL(sunxi_bt601_yuv2rgb_coef);
78
+
5179 static void sun4i_frontend_scaler_init(struct sun4i_frontend *frontend)
5280 {
5381 int i;
82
+
83
+ if (frontend->data->has_coef_access_ctrl)
84
+ regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
85
+ SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL,
86
+ SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL);
5487
5588 for (i = 0; i < 32; i++) {
5689 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZCOEF0_REG(i),
....@@ -67,9 +100,11 @@
67100 sun4i_frontend_vert_coef[i]);
68101 }
69102
70
- regmap_update_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
71
- SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL,
72
- SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL);
103
+ if (frontend->data->has_coef_rdy)
104
+ regmap_write_bits(frontend->regs,
105
+ SUN4I_FRONTEND_FRM_CTRL_REG,
106
+ SUN4I_FRONTEND_FRM_CTRL_COEF_RDY,
107
+ SUN4I_FRONTEND_FRM_CTRL_COEF_RDY);
73108 }
74109
75110 int sun4i_frontend_init(struct sun4i_frontend *frontend)
....@@ -84,31 +119,226 @@
84119 }
85120 EXPORT_SYMBOL(sun4i_frontend_exit);
86121
122
+static bool sun4i_frontend_format_chroma_requires_swap(uint32_t fmt)
123
+{
124
+ switch (fmt) {
125
+ case DRM_FORMAT_YVU411:
126
+ case DRM_FORMAT_YVU420:
127
+ case DRM_FORMAT_YVU422:
128
+ case DRM_FORMAT_YVU444:
129
+ return true;
130
+
131
+ default:
132
+ return false;
133
+ }
134
+}
135
+
136
+static bool sun4i_frontend_format_supports_tiling(uint32_t fmt)
137
+{
138
+ switch (fmt) {
139
+ case DRM_FORMAT_NV12:
140
+ case DRM_FORMAT_NV16:
141
+ case DRM_FORMAT_NV21:
142
+ case DRM_FORMAT_NV61:
143
+ case DRM_FORMAT_YUV411:
144
+ case DRM_FORMAT_YUV420:
145
+ case DRM_FORMAT_YUV422:
146
+ case DRM_FORMAT_YVU420:
147
+ case DRM_FORMAT_YVU422:
148
+ case DRM_FORMAT_YVU411:
149
+ return true;
150
+
151
+ default:
152
+ return false;
153
+ }
154
+}
155
+
87156 void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
88157 struct drm_plane *plane)
89158 {
90159 struct drm_plane_state *state = plane->state;
91160 struct drm_framebuffer *fb = state->fb;
161
+ unsigned int strides[3] = {};
162
+
92163 dma_addr_t paddr;
164
+ bool swap;
165
+
166
+ if (fb->modifier == DRM_FORMAT_MOD_ALLWINNER_TILED) {
167
+ unsigned int width = state->src_w >> 16;
168
+ unsigned int offset;
169
+
170
+ strides[0] = SUN4I_FRONTEND_LINESTRD_TILED(fb->pitches[0]);
171
+
172
+ /*
173
+ * The X1 offset is the offset to the bottom-right point in the
174
+ * end tile, which is the final pixel (at offset width - 1)
175
+ * within the end tile (with a 32-byte mask).
176
+ */
177
+ offset = (width - 1) & (32 - 1);
178
+
179
+ regmap_write(frontend->regs, SUN4I_FRONTEND_TB_OFF0_REG,
180
+ SUN4I_FRONTEND_TB_OFF_X1(offset));
181
+
182
+ if (fb->format->num_planes > 1) {
183
+ strides[1] =
184
+ SUN4I_FRONTEND_LINESTRD_TILED(fb->pitches[1]);
185
+
186
+ regmap_write(frontend->regs, SUN4I_FRONTEND_TB_OFF1_REG,
187
+ SUN4I_FRONTEND_TB_OFF_X1(offset));
188
+ }
189
+
190
+ if (fb->format->num_planes > 2) {
191
+ strides[2] =
192
+ SUN4I_FRONTEND_LINESTRD_TILED(fb->pitches[2]);
193
+
194
+ regmap_write(frontend->regs, SUN4I_FRONTEND_TB_OFF2_REG,
195
+ SUN4I_FRONTEND_TB_OFF_X1(offset));
196
+ }
197
+ } else {
198
+ strides[0] = fb->pitches[0];
199
+
200
+ if (fb->format->num_planes > 1)
201
+ strides[1] = fb->pitches[1];
202
+
203
+ if (fb->format->num_planes > 2)
204
+ strides[2] = fb->pitches[2];
205
+ }
93206
94207 /* Set the line width */
95208 DRM_DEBUG_DRIVER("Frontend stride: %d bytes\n", fb->pitches[0]);
96209 regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD0_REG,
97
- fb->pitches[0]);
210
+ strides[0]);
211
+
212
+ if (fb->format->num_planes > 1)
213
+ regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD1_REG,
214
+ strides[1]);
215
+
216
+ if (fb->format->num_planes > 2)
217
+ regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD2_REG,
218
+ strides[2]);
219
+
220
+ /* Some planar formats require chroma channel swapping by hand. */
221
+ swap = sun4i_frontend_format_chroma_requires_swap(fb->format->format);
98222
99223 /* Set the physical address of the buffer in memory */
100224 paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
101225 paddr -= PHYS_OFFSET;
102
- DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
226
+ DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr);
103227 regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr);
228
+
229
+ if (fb->format->num_planes > 1) {
230
+ paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1);
231
+ paddr -= PHYS_OFFSET;
232
+ DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr);
233
+ regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG,
234
+ paddr);
235
+ }
236
+
237
+ if (fb->format->num_planes > 2) {
238
+ paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2);
239
+ paddr -= PHYS_OFFSET;
240
+ DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr);
241
+ regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG,
242
+ paddr);
243
+ }
104244 }
105245 EXPORT_SYMBOL(sun4i_frontend_update_buffer);
106246
107
-static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
247
+static int
248
+sun4i_frontend_drm_format_to_input_fmt(const struct drm_format_info *format,
249
+ u32 *val)
108250 {
109
- switch (fmt) {
110
- case DRM_FORMAT_ARGB8888:
111
- *val = 5;
251
+ if (!format->is_yuv)
252
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB;
253
+ else if (drm_format_info_is_yuv_sampling_411(format))
254
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV411;
255
+ else if (drm_format_info_is_yuv_sampling_420(format))
256
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV420;
257
+ else if (drm_format_info_is_yuv_sampling_422(format))
258
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV422;
259
+ else if (drm_format_info_is_yuv_sampling_444(format))
260
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV444;
261
+ else
262
+ return -EINVAL;
263
+
264
+ return 0;
265
+}
266
+
267
+static int
268
+sun4i_frontend_drm_format_to_input_mode(const struct drm_format_info *format,
269
+ uint64_t modifier, u32 *val)
270
+{
271
+ bool tiled = (modifier == DRM_FORMAT_MOD_ALLWINNER_TILED);
272
+
273
+ switch (format->num_planes) {
274
+ case 1:
275
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED;
276
+ return 0;
277
+
278
+ case 2:
279
+ *val = tiled ? SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_MB32_SEMIPLANAR
280
+ : SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_SEMIPLANAR;
281
+ return 0;
282
+
283
+ case 3:
284
+ *val = tiled ? SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_MB32_PLANAR
285
+ : SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PLANAR;
286
+ return 0;
287
+
288
+ default:
289
+ return -EINVAL;
290
+ }
291
+}
292
+
293
+static int
294
+sun4i_frontend_drm_format_to_input_sequence(const struct drm_format_info *format,
295
+ u32 *val)
296
+{
297
+ /* Planar formats have an explicit input sequence. */
298
+ if (drm_format_info_is_yuv_planar(format)) {
299
+ *val = 0;
300
+ return 0;
301
+ }
302
+
303
+ switch (format->format) {
304
+ case DRM_FORMAT_BGRX8888:
305
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX;
306
+ return 0;
307
+
308
+ case DRM_FORMAT_NV12:
309
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UV;
310
+ return 0;
311
+
312
+ case DRM_FORMAT_NV16:
313
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UV;
314
+ return 0;
315
+
316
+ case DRM_FORMAT_NV21:
317
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VU;
318
+ return 0;
319
+
320
+ case DRM_FORMAT_NV61:
321
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VU;
322
+ return 0;
323
+
324
+ case DRM_FORMAT_UYVY:
325
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UYVY;
326
+ return 0;
327
+
328
+ case DRM_FORMAT_VYUY:
329
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VYUY;
330
+ return 0;
331
+
332
+ case DRM_FORMAT_XRGB8888:
333
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB;
334
+ return 0;
335
+
336
+ case DRM_FORMAT_YUYV:
337
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_YUYV;
338
+ return 0;
339
+
340
+ case DRM_FORMAT_YVYU:
341
+ *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_YVYU;
112342 return 0;
113343
114344 default:
....@@ -119,9 +349,12 @@
119349 static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
120350 {
121351 switch (fmt) {
352
+ case DRM_FORMAT_BGRX8888:
353
+ *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888;
354
+ return 0;
355
+
122356 case DRM_FORMAT_XRGB8888:
123
- case DRM_FORMAT_ARGB8888:
124
- *val = 2;
357
+ *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888;
125358 return 0;
126359
127360 default:
....@@ -129,19 +362,74 @@
129362 }
130363 }
131364
365
+static const uint32_t sun4i_frontend_formats[] = {
366
+ DRM_FORMAT_BGRX8888,
367
+ DRM_FORMAT_NV12,
368
+ DRM_FORMAT_NV16,
369
+ DRM_FORMAT_NV21,
370
+ DRM_FORMAT_NV61,
371
+ DRM_FORMAT_UYVY,
372
+ DRM_FORMAT_VYUY,
373
+ DRM_FORMAT_XRGB8888,
374
+ DRM_FORMAT_YUV411,
375
+ DRM_FORMAT_YUV420,
376
+ DRM_FORMAT_YUV422,
377
+ DRM_FORMAT_YUV444,
378
+ DRM_FORMAT_YUYV,
379
+ DRM_FORMAT_YVU411,
380
+ DRM_FORMAT_YVU420,
381
+ DRM_FORMAT_YVU422,
382
+ DRM_FORMAT_YVU444,
383
+ DRM_FORMAT_YVYU,
384
+};
385
+
386
+bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier)
387
+{
388
+ unsigned int i;
389
+
390
+ if (modifier == DRM_FORMAT_MOD_ALLWINNER_TILED)
391
+ return sun4i_frontend_format_supports_tiling(fmt);
392
+ else if (modifier != DRM_FORMAT_MOD_LINEAR)
393
+ return false;
394
+
395
+ for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++)
396
+ if (sun4i_frontend_formats[i] == fmt)
397
+ return true;
398
+
399
+ return false;
400
+}
401
+EXPORT_SYMBOL(sun4i_frontend_format_is_supported);
402
+
132403 int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
133404 struct drm_plane *plane, uint32_t out_fmt)
134405 {
135406 struct drm_plane_state *state = plane->state;
136407 struct drm_framebuffer *fb = state->fb;
408
+ const struct drm_format_info *format = fb->format;
409
+ uint64_t modifier = fb->modifier;
410
+ unsigned int ch1_phase_idx;
137411 u32 out_fmt_val;
138
- u32 in_fmt_val;
412
+ u32 in_fmt_val, in_mod_val, in_ps_val;
413
+ unsigned int i;
414
+ u32 bypass;
139415 int ret;
140416
141
- ret = sun4i_frontend_drm_format_to_input_fmt(fb->format->format,
142
- &in_fmt_val);
417
+ ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val);
143418 if (ret) {
144419 DRM_DEBUG_DRIVER("Invalid input format\n");
420
+ return ret;
421
+ }
422
+
423
+ ret = sun4i_frontend_drm_format_to_input_mode(format, modifier,
424
+ &in_mod_val);
425
+ if (ret) {
426
+ DRM_DEBUG_DRIVER("Invalid input mode\n");
427
+ return ret;
428
+ }
429
+
430
+ ret = sun4i_frontend_drm_format_to_input_sequence(format, &in_ps_val);
431
+ if (ret) {
432
+ DRM_DEBUG_DRIVER("Invalid pixel sequence\n");
145433 return ret;
146434 }
147435
....@@ -155,17 +443,43 @@
155443 * I have no idea what this does exactly, but it seems to be
156444 * related to the scaler FIR filter phase parameters.
157445 */
158
- regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG, 0x400);
159
- regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG, 0x400);
160
- regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG, 0x400);
161
- regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG, 0x400);
162
- regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400);
163
- regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400);
446
+ ch1_phase_idx = (format->num_planes > 1) ? 1 : 0;
447
+ regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG,
448
+ frontend->data->ch_phase[0]);
449
+ regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG,
450
+ frontend->data->ch_phase[ch1_phase_idx]);
451
+ regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG,
452
+ frontend->data->ch_phase[0]);
453
+ regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG,
454
+ frontend->data->ch_phase[ch1_phase_idx]);
455
+ regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG,
456
+ frontend->data->ch_phase[0]);
457
+ regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG,
458
+ frontend->data->ch_phase[ch1_phase_idx]);
459
+
460
+ /*
461
+ * Checking the input format is sufficient since we currently only
462
+ * support RGB output formats to the backend. If YUV output formats
463
+ * ever get supported, an YUV input and output would require bypassing
464
+ * the CSC engine too.
465
+ */
466
+ if (format->is_yuv) {
467
+ /* Setup the CSC engine for YUV to RGB conversion. */
468
+ bypass = 0;
469
+
470
+ for (i = 0; i < ARRAY_SIZE(sunxi_bt601_yuv2rgb_coef); i++)
471
+ regmap_write(frontend->regs,
472
+ SUN4I_FRONTEND_CSC_COEF_REG(i),
473
+ sunxi_bt601_yuv2rgb_coef[i]);
474
+ } else {
475
+ bypass = SUN4I_FRONTEND_BYPASS_CSC_EN;
476
+ }
477
+
478
+ regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
479
+ SUN4I_FRONTEND_BYPASS_CSC_EN, bypass);
164480
165481 regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG,
166
- SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) |
167
- SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) |
168
- SUN4I_FRONTEND_INPUT_FMT_PS(1));
482
+ in_mod_val | in_fmt_val | in_ps_val);
169483
170484 /*
171485 * TODO: It look like the A31 and A80 at least will need the
....@@ -173,7 +487,7 @@
173487 * ARGB8888).
174488 */
175489 regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG,
176
- SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(out_fmt_val));
490
+ out_fmt_val);
177491
178492 return 0;
179493 }
....@@ -183,16 +497,24 @@
183497 struct drm_plane *plane)
184498 {
185499 struct drm_plane_state *state = plane->state;
500
+ struct drm_framebuffer *fb = state->fb;
501
+ uint32_t luma_width, luma_height;
502
+ uint32_t chroma_width, chroma_height;
186503
187504 /* Set height and width */
188505 DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n",
189506 state->crtc_w, state->crtc_h);
507
+
508
+ luma_width = state->src_w >> 16;
509
+ luma_height = state->src_h >> 16;
510
+
511
+ chroma_width = DIV_ROUND_UP(luma_width, fb->format->hsub);
512
+ chroma_height = DIV_ROUND_UP(luma_height, fb->format->vsub);
513
+
190514 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG,
191
- SUN4I_FRONTEND_INSIZE(state->src_h >> 16,
192
- state->src_w >> 16));
515
+ SUN4I_FRONTEND_INSIZE(luma_height, luma_width));
193516 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG,
194
- SUN4I_FRONTEND_INSIZE(state->src_h >> 16,
195
- state->src_w >> 16));
517
+ SUN4I_FRONTEND_INSIZE(chroma_height, chroma_width));
196518
197519 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG,
198520 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
....@@ -200,14 +522,14 @@
200522 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
201523
202524 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG,
203
- state->src_w / state->crtc_w);
525
+ (luma_width << 16) / state->crtc_w);
204526 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG,
205
- state->src_w / state->crtc_w);
527
+ (chroma_width << 16) / state->crtc_w);
206528
207529 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG,
208
- state->src_h / state->crtc_h);
530
+ (luma_height << 16) / state->crtc_h);
209531 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG,
210
- state->src_h / state->crtc_h);
532
+ (chroma_height << 16) / state->crtc_h);
211533
212534 regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
213535 SUN4I_FRONTEND_FRM_CTRL_REG_RDY,
....@@ -225,7 +547,7 @@
225547 }
226548 EXPORT_SYMBOL(sun4i_frontend_enable);
227549
228
-static struct regmap_config sun4i_frontend_regmap_config = {
550
+static const struct regmap_config sun4i_frontend_regmap_config = {
229551 .reg_bits = 32,
230552 .val_bits = 32,
231553 .reg_stride = 4,
....@@ -249,6 +571,10 @@
249571 dev_set_drvdata(dev, frontend);
250572 frontend->dev = dev;
251573 frontend->node = dev->of_node;
574
+
575
+ frontend->data = of_device_get_match_data(dev);
576
+ if (!frontend->data)
577
+ return -ENODEV;
252578
253579 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
254580 regs = devm_ioremap_resource(dev, res);
....@@ -339,10 +665,6 @@
339665 SUN4I_FRONTEND_EN_EN,
340666 SUN4I_FRONTEND_EN_EN);
341667
342
- regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
343
- SUN4I_FRONTEND_BYPASS_CSC_EN,
344
- SUN4I_FRONTEND_BYPASS_CSC_EN);
345
-
346668 sun4i_frontend_scaler_init(frontend);
347669
348670 return 0;
....@@ -366,8 +688,33 @@
366688 .runtime_suspend = sun4i_frontend_runtime_suspend,
367689 };
368690
691
+static const struct sun4i_frontend_data sun4i_a10_frontend = {
692
+ .ch_phase = { 0x000, 0xfc000 },
693
+ .has_coef_rdy = true,
694
+};
695
+
696
+static const struct sun4i_frontend_data sun8i_a33_frontend = {
697
+ .ch_phase = { 0x400, 0xfc400 },
698
+ .has_coef_access_ctrl = true,
699
+};
700
+
369701 const struct of_device_id sun4i_frontend_of_table[] = {
370
- { .compatible = "allwinner,sun8i-a33-display-frontend" },
702
+ {
703
+ .compatible = "allwinner,sun4i-a10-display-frontend",
704
+ .data = &sun4i_a10_frontend
705
+ },
706
+ {
707
+ .compatible = "allwinner,sun7i-a20-display-frontend",
708
+ .data = &sun4i_a10_frontend
709
+ },
710
+ {
711
+ .compatible = "allwinner,sun8i-a23-display-frontend",
712
+ .data = &sun8i_a33_frontend
713
+ },
714
+ {
715
+ .compatible = "allwinner,sun8i-a33-display-frontend",
716
+ .data = &sun8i_a33_frontend
717
+ },
371718 { }
372719 };
373720 EXPORT_SYMBOL(sun4i_frontend_of_table);