forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
....@@ -1,30 +1,30 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License as
6
- * published by the Free Software Foundation; either version 2 of
7
- * the License, or (at your option) any later version.
84 */
95
106 #include <drm/drm_atomic.h>
117 #include <drm/drm_atomic_helper.h>
128 #include <drm/drm_crtc.h>
13
-#include <drm/drm_crtc_helper.h>
149 #include <drm/drm_fb_cma_helper.h>
1510 #include <drm/drm_gem_cma_helper.h>
11
+#include <drm/drm_gem_framebuffer_helper.h>
1612 #include <drm/drm_plane_helper.h>
17
-#include <drm/drmP.h>
13
+#include <drm/drm_probe_helper.h>
1814
19
-#include "sun8i_vi_layer.h"
15
+#include "sun8i_csc.h"
2016 #include "sun8i_mixer.h"
17
+#include "sun8i_vi_layer.h"
2118 #include "sun8i_vi_scaler.h"
2219
2320 static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
2421 int overlay, bool enable, unsigned int zpos,
2522 unsigned int old_zpos)
2623 {
27
- u32 val;
24
+ u32 val, bld_base, ch_base;
25
+
26
+ bld_base = sun8i_blender_base(mixer);
27
+ ch_base = sun8i_channel_base(mixer, channel);
2828
2929 DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n",
3030 enable ? "En" : "Dis", channel, overlay);
....@@ -35,17 +35,17 @@
3535 val = 0;
3636
3737 regmap_update_bits(mixer->engine.regs,
38
- SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
38
+ SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
3939 SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
4040
4141 if (!enable || zpos != old_zpos) {
4242 regmap_update_bits(mixer->engine.regs,
43
- SUN8I_MIXER_BLEND_PIPE_CTL,
43
+ SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
4444 SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
4545 0);
4646
4747 regmap_update_bits(mixer->engine.regs,
48
- SUN8I_MIXER_BLEND_ROUTE,
48
+ SUN8I_MIXER_BLEND_ROUTE(bld_base),
4949 SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
5050 0);
5151 }
....@@ -54,12 +54,13 @@
5454 val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
5555
5656 regmap_update_bits(mixer->engine.regs,
57
- SUN8I_MIXER_BLEND_PIPE_CTL, val, val);
57
+ SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
58
+ val, val);
5859
5960 val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
6061
6162 regmap_update_bits(mixer->engine.regs,
62
- SUN8I_MIXER_BLEND_ROUTE,
63
+ SUN8I_MIXER_BLEND_ROUTE(bld_base),
6364 SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
6465 val);
6566 }
....@@ -72,12 +73,18 @@
7273 struct drm_plane_state *state = plane->state;
7374 const struct drm_format_info *format = state->fb->format;
7475 u32 src_w, src_h, dst_w, dst_h;
76
+ u32 bld_base, ch_base;
7577 u32 outsize, insize;
7678 u32 hphase, vphase;
79
+ u32 hn = 0, hm = 0;
80
+ u32 vn = 0, vm = 0;
7781 bool subsampled;
7882
7983 DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
8084 channel, overlay);
85
+
86
+ bld_base = sun8i_blender_base(mixer);
87
+ ch_base = sun8i_channel_base(mixer, channel);
8188
8289 src_w = drm_rect_width(&state->src) >> 16;
8390 src_h = drm_rect_height(&state->src) >> 16;
....@@ -115,10 +122,10 @@
115122 (state->src.y1 >> 16) & ~(format->vsub - 1));
116123 DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h);
117124 regmap_write(mixer->engine.regs,
118
- SUN8I_MIXER_CHAN_VI_LAYER_SIZE(channel, overlay),
125
+ SUN8I_MIXER_CHAN_VI_LAYER_SIZE(ch_base, overlay),
119126 insize);
120127 regmap_write(mixer->engine.regs,
121
- SUN8I_MIXER_CHAN_VI_OVL_SIZE(channel),
128
+ SUN8I_MIXER_CHAN_VI_OVL_SIZE(ch_base),
122129 insize);
123130
124131 /*
....@@ -128,12 +135,41 @@
128135 subsampled = format->hsub > 1 || format->vsub > 1;
129136
130137 if (insize != outsize || subsampled || hphase || vphase) {
131
- u32 hscale, vscale;
138
+ unsigned int scanline, required;
139
+ struct drm_display_mode *mode;
140
+ u32 hscale, vscale, fps;
141
+ u64 ability;
132142
133143 DRM_DEBUG_DRIVER("HW scaling is enabled\n");
134144
135
- hscale = state->src_w / state->crtc_w;
136
- vscale = state->src_h / state->crtc_h;
145
+ mode = &plane->state->crtc->state->mode;
146
+ fps = (mode->clock * 1000) / (mode->vtotal * mode->htotal);
147
+ ability = clk_get_rate(mixer->mod_clk);
148
+ /* BSP algorithm assumes 80% efficiency of VI scaler unit */
149
+ ability *= 80;
150
+ do_div(ability, mode->vdisplay * fps * max(src_w, dst_w));
151
+
152
+ required = src_h * 100 / dst_h;
153
+
154
+ if (ability < required) {
155
+ DRM_DEBUG_DRIVER("Using vertical coarse scaling\n");
156
+ vm = src_h;
157
+ vn = (u32)ability * dst_h / 100;
158
+ src_h = vn;
159
+ }
160
+
161
+ /* it seems that every RGB scaler has buffer for 2048 pixels */
162
+ scanline = subsampled ? mixer->cfg->scanline_yuv : 2048;
163
+
164
+ if (src_w > scanline) {
165
+ DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n");
166
+ hm = src_w;
167
+ hn = scanline;
168
+ src_w = hn;
169
+ }
170
+
171
+ hscale = (src_w << 16) / dst_w;
172
+ vscale = (src_h << 16) / dst_h;
137173
138174 sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w,
139175 dst_h, hscale, vscale, hphase, vphase,
....@@ -144,53 +180,101 @@
144180 sun8i_vi_scaler_enable(mixer, channel, false);
145181 }
146182
183
+ regmap_write(mixer->engine.regs,
184
+ SUN8I_MIXER_CHAN_VI_HDS_Y(ch_base),
185
+ SUN8I_MIXER_CHAN_VI_DS_N(hn) |
186
+ SUN8I_MIXER_CHAN_VI_DS_M(hm));
187
+ regmap_write(mixer->engine.regs,
188
+ SUN8I_MIXER_CHAN_VI_HDS_UV(ch_base),
189
+ SUN8I_MIXER_CHAN_VI_DS_N(hn) |
190
+ SUN8I_MIXER_CHAN_VI_DS_M(hm));
191
+ regmap_write(mixer->engine.regs,
192
+ SUN8I_MIXER_CHAN_VI_VDS_Y(ch_base),
193
+ SUN8I_MIXER_CHAN_VI_DS_N(vn) |
194
+ SUN8I_MIXER_CHAN_VI_DS_M(vm));
195
+ regmap_write(mixer->engine.regs,
196
+ SUN8I_MIXER_CHAN_VI_VDS_UV(ch_base),
197
+ SUN8I_MIXER_CHAN_VI_DS_N(vn) |
198
+ SUN8I_MIXER_CHAN_VI_DS_M(vm));
199
+
147200 /* Set base coordinates */
148201 DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
149202 state->dst.x1, state->dst.y1);
150203 DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
151204 regmap_write(mixer->engine.regs,
152
- SUN8I_MIXER_BLEND_ATTR_COORD(zpos),
205
+ SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos),
153206 SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
154207 regmap_write(mixer->engine.regs,
155
- SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos),
208
+ SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos),
156209 outsize);
157210
158211 return 0;
212
+}
213
+
214
+static u32 sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format)
215
+{
216
+ if (!format->is_yuv)
217
+ return SUN8I_CSC_MODE_OFF;
218
+
219
+ switch (format->format) {
220
+ case DRM_FORMAT_YVU411:
221
+ case DRM_FORMAT_YVU420:
222
+ case DRM_FORMAT_YVU422:
223
+ case DRM_FORMAT_YVU444:
224
+ return SUN8I_CSC_MODE_YVU2RGB;
225
+ default:
226
+ return SUN8I_CSC_MODE_YUV2RGB;
227
+ }
159228 }
160229
161230 static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
162231 int overlay, struct drm_plane *plane)
163232 {
164233 struct drm_plane_state *state = plane->state;
165
- const struct de2_fmt_info *fmt_info;
166
- u32 val;
234
+ u32 val, ch_base, csc_mode, hw_fmt;
235
+ const struct drm_format_info *fmt;
236
+ int ret;
167237
168
- fmt_info = sun8i_mixer_format_info(state->fb->format->format);
169
- if (!fmt_info) {
238
+ ch_base = sun8i_channel_base(mixer, channel);
239
+
240
+ fmt = state->fb->format;
241
+ ret = sun8i_mixer_drm_format_to_hw(fmt->format, &hw_fmt);
242
+ if (ret) {
170243 DRM_DEBUG_DRIVER("Invalid format\n");
171
- return -EINVAL;
244
+ return ret;
172245 }
173246
174
- val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET;
247
+ val = hw_fmt << SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET;
175248 regmap_update_bits(mixer->engine.regs,
176
- SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
249
+ SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
177250 SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val);
178251
179
- if (fmt_info->csc != SUN8I_CSC_MODE_OFF) {
180
- sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_info->csc);
252
+ csc_mode = sun8i_vi_layer_get_csc_mode(fmt);
253
+ if (csc_mode != SUN8I_CSC_MODE_OFF) {
254
+ sun8i_csc_set_ccsc_coefficients(mixer, channel, csc_mode,
255
+ state->color_encoding,
256
+ state->color_range);
181257 sun8i_csc_enable_ccsc(mixer, channel, true);
182258 } else {
183259 sun8i_csc_enable_ccsc(mixer, channel, false);
184260 }
185261
186
- if (fmt_info->rgb)
262
+ if (!fmt->is_yuv)
187263 val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE;
188264 else
189265 val = 0;
190266
191267 regmap_update_bits(mixer->engine.regs,
192
- SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
268
+ SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
193269 SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE, val);
270
+
271
+ /* It seems that YUV formats use global alpha setting. */
272
+ if (mixer->cfg->is_de3)
273
+ regmap_update_bits(mixer->engine.regs,
274
+ SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base,
275
+ overlay),
276
+ SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK,
277
+ SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA(0xff));
194278
195279 return 0;
196280 }
....@@ -204,7 +288,10 @@
204288 struct drm_gem_cma_object *gem;
205289 u32 dx, dy, src_x, src_y;
206290 dma_addr_t paddr;
291
+ u32 ch_base;
207292 int i;
293
+
294
+ ch_base = sun8i_channel_base(mixer, channel);
208295
209296 /* Adjust x and y to be dividable by subsampling factor */
210297 src_x = (state->src.x1 >> 16) & ~(format->hsub - 1);
....@@ -235,17 +322,17 @@
235322 DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n",
236323 i + 1, fb->pitches[i]);
237324 regmap_write(mixer->engine.regs,
238
- SUN8I_MIXER_CHAN_VI_LAYER_PITCH(channel,
325
+ SUN8I_MIXER_CHAN_VI_LAYER_PITCH(ch_base,
239326 overlay, i),
240
- fb->pitches[i]);
327
+ fb->pitches[i]);
241328
242329 DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n",
243330 i + 1, &paddr);
244331
245332 regmap_write(mixer->engine.regs,
246
- SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(channel,
333
+ SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch_base,
247334 overlay, i),
248
- lower_32_bits(paddr));
335
+ lower_32_bits(paddr));
249336 }
250337
251338 return 0;
....@@ -314,7 +401,8 @@
314401 true, zpos, old_zpos);
315402 }
316403
317
-static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
404
+static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
405
+ .prepare_fb = drm_gem_fb_prepare_fb,
318406 .atomic_check = sun8i_vi_layer_atomic_check,
319407 .atomic_disable = sun8i_vi_layer_atomic_disable,
320408 .atomic_update = sun8i_vi_layer_atomic_update,
....@@ -368,23 +456,76 @@
368456 DRM_FORMAT_YVU422,
369457 };
370458
459
+static const u32 sun8i_vi_layer_de3_formats[] = {
460
+ DRM_FORMAT_ABGR1555,
461
+ DRM_FORMAT_ABGR2101010,
462
+ DRM_FORMAT_ABGR4444,
463
+ DRM_FORMAT_ABGR8888,
464
+ DRM_FORMAT_ARGB1555,
465
+ DRM_FORMAT_ARGB2101010,
466
+ DRM_FORMAT_ARGB4444,
467
+ DRM_FORMAT_ARGB8888,
468
+ DRM_FORMAT_BGR565,
469
+ DRM_FORMAT_BGR888,
470
+ DRM_FORMAT_BGRA1010102,
471
+ DRM_FORMAT_BGRA5551,
472
+ DRM_FORMAT_BGRA4444,
473
+ DRM_FORMAT_BGRA8888,
474
+ DRM_FORMAT_BGRX8888,
475
+ DRM_FORMAT_RGB565,
476
+ DRM_FORMAT_RGB888,
477
+ DRM_FORMAT_RGBA1010102,
478
+ DRM_FORMAT_RGBA4444,
479
+ DRM_FORMAT_RGBA5551,
480
+ DRM_FORMAT_RGBA8888,
481
+ DRM_FORMAT_RGBX8888,
482
+ DRM_FORMAT_XBGR8888,
483
+ DRM_FORMAT_XRGB8888,
484
+
485
+ DRM_FORMAT_NV16,
486
+ DRM_FORMAT_NV12,
487
+ DRM_FORMAT_NV21,
488
+ DRM_FORMAT_NV61,
489
+ DRM_FORMAT_P010,
490
+ DRM_FORMAT_P210,
491
+ DRM_FORMAT_UYVY,
492
+ DRM_FORMAT_VYUY,
493
+ DRM_FORMAT_YUYV,
494
+ DRM_FORMAT_YVYU,
495
+ DRM_FORMAT_YUV411,
496
+ DRM_FORMAT_YUV420,
497
+ DRM_FORMAT_YUV422,
498
+ DRM_FORMAT_YVU411,
499
+ DRM_FORMAT_YVU420,
500
+ DRM_FORMAT_YVU422,
501
+};
502
+
371503 struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
372504 struct sun8i_mixer *mixer,
373505 int index)
374506 {
507
+ u32 supported_encodings, supported_ranges;
508
+ unsigned int plane_cnt, format_count;
375509 struct sun8i_vi_layer *layer;
376
- unsigned int plane_cnt;
510
+ const u32 *formats;
377511 int ret;
378512
379513 layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
380514 if (!layer)
381515 return ERR_PTR(-ENOMEM);
382516
517
+ if (mixer->cfg->is_de3) {
518
+ formats = sun8i_vi_layer_de3_formats;
519
+ format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
520
+ } else {
521
+ formats = sun8i_vi_layer_formats;
522
+ format_count = ARRAY_SIZE(sun8i_vi_layer_formats);
523
+ }
524
+
383525 /* possible crtcs are set later */
384526 ret = drm_universal_plane_init(drm, &layer->plane, 0,
385527 &sun8i_vi_layer_funcs,
386
- sun8i_vi_layer_formats,
387
- ARRAY_SIZE(sun8i_vi_layer_formats),
528
+ formats, format_count,
388529 NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
389530 if (ret) {
390531 dev_err(drm->dev, "Couldn't initialize layer\n");
....@@ -400,6 +541,22 @@
400541 return ERR_PTR(ret);
401542 }
402543
544
+ supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
545
+ BIT(DRM_COLOR_YCBCR_BT709);
546
+
547
+ supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
548
+ BIT(DRM_COLOR_YCBCR_FULL_RANGE);
549
+
550
+ ret = drm_plane_create_color_properties(&layer->plane,
551
+ supported_encodings,
552
+ supported_ranges,
553
+ DRM_COLOR_YCBCR_BT709,
554
+ DRM_COLOR_YCBCR_LIMITED_RANGE);
555
+ if (ret) {
556
+ dev_err(drm->dev, "Couldn't add encoding and range properties!\n");
557
+ return ERR_PTR(ret);
558
+ }
559
+
403560 drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs);
404561 layer->mixer = mixer;
405562 layer->channel = index;