.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * 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. |
---|
8 | 4 | */ |
---|
9 | 5 | |
---|
10 | 6 | #include <drm/drm_atomic.h> |
---|
11 | 7 | #include <drm/drm_atomic_helper.h> |
---|
12 | 8 | #include <drm/drm_crtc.h> |
---|
13 | | -#include <drm/drm_crtc_helper.h> |
---|
14 | 9 | #include <drm/drm_fb_cma_helper.h> |
---|
15 | 10 | #include <drm/drm_gem_cma_helper.h> |
---|
| 11 | +#include <drm/drm_gem_framebuffer_helper.h> |
---|
16 | 12 | #include <drm/drm_plane_helper.h> |
---|
17 | | -#include <drm/drmP.h> |
---|
| 13 | +#include <drm/drm_probe_helper.h> |
---|
18 | 14 | |
---|
19 | | -#include "sun8i_vi_layer.h" |
---|
| 15 | +#include "sun8i_csc.h" |
---|
20 | 16 | #include "sun8i_mixer.h" |
---|
| 17 | +#include "sun8i_vi_layer.h" |
---|
21 | 18 | #include "sun8i_vi_scaler.h" |
---|
22 | 19 | |
---|
23 | 20 | static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, |
---|
24 | 21 | int overlay, bool enable, unsigned int zpos, |
---|
25 | 22 | unsigned int old_zpos) |
---|
26 | 23 | { |
---|
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); |
---|
28 | 28 | |
---|
29 | 29 | DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n", |
---|
30 | 30 | enable ? "En" : "Dis", channel, overlay); |
---|
.. | .. |
---|
35 | 35 | val = 0; |
---|
36 | 36 | |
---|
37 | 37 | 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), |
---|
39 | 39 | SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val); |
---|
40 | 40 | |
---|
41 | 41 | if (!enable || zpos != old_zpos) { |
---|
42 | 42 | regmap_update_bits(mixer->engine.regs, |
---|
43 | | - SUN8I_MIXER_BLEND_PIPE_CTL, |
---|
| 43 | + SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), |
---|
44 | 44 | SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos), |
---|
45 | 45 | 0); |
---|
46 | 46 | |
---|
47 | 47 | regmap_update_bits(mixer->engine.regs, |
---|
48 | | - SUN8I_MIXER_BLEND_ROUTE, |
---|
| 48 | + SUN8I_MIXER_BLEND_ROUTE(bld_base), |
---|
49 | 49 | SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos), |
---|
50 | 50 | 0); |
---|
51 | 51 | } |
---|
.. | .. |
---|
54 | 54 | val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos); |
---|
55 | 55 | |
---|
56 | 56 | 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); |
---|
58 | 59 | |
---|
59 | 60 | val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos); |
---|
60 | 61 | |
---|
61 | 62 | regmap_update_bits(mixer->engine.regs, |
---|
62 | | - SUN8I_MIXER_BLEND_ROUTE, |
---|
| 63 | + SUN8I_MIXER_BLEND_ROUTE(bld_base), |
---|
63 | 64 | SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos), |
---|
64 | 65 | val); |
---|
65 | 66 | } |
---|
.. | .. |
---|
72 | 73 | struct drm_plane_state *state = plane->state; |
---|
73 | 74 | const struct drm_format_info *format = state->fb->format; |
---|
74 | 75 | u32 src_w, src_h, dst_w, dst_h; |
---|
| 76 | + u32 bld_base, ch_base; |
---|
75 | 77 | u32 outsize, insize; |
---|
76 | 78 | u32 hphase, vphase; |
---|
| 79 | + u32 hn = 0, hm = 0; |
---|
| 80 | + u32 vn = 0, vm = 0; |
---|
77 | 81 | bool subsampled; |
---|
78 | 82 | |
---|
79 | 83 | DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n", |
---|
80 | 84 | channel, overlay); |
---|
| 85 | + |
---|
| 86 | + bld_base = sun8i_blender_base(mixer); |
---|
| 87 | + ch_base = sun8i_channel_base(mixer, channel); |
---|
81 | 88 | |
---|
82 | 89 | src_w = drm_rect_width(&state->src) >> 16; |
---|
83 | 90 | src_h = drm_rect_height(&state->src) >> 16; |
---|
.. | .. |
---|
115 | 122 | (state->src.y1 >> 16) & ~(format->vsub - 1)); |
---|
116 | 123 | DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h); |
---|
117 | 124 | regmap_write(mixer->engine.regs, |
---|
118 | | - SUN8I_MIXER_CHAN_VI_LAYER_SIZE(channel, overlay), |
---|
| 125 | + SUN8I_MIXER_CHAN_VI_LAYER_SIZE(ch_base, overlay), |
---|
119 | 126 | insize); |
---|
120 | 127 | regmap_write(mixer->engine.regs, |
---|
121 | | - SUN8I_MIXER_CHAN_VI_OVL_SIZE(channel), |
---|
| 128 | + SUN8I_MIXER_CHAN_VI_OVL_SIZE(ch_base), |
---|
122 | 129 | insize); |
---|
123 | 130 | |
---|
124 | 131 | /* |
---|
.. | .. |
---|
128 | 135 | subsampled = format->hsub > 1 || format->vsub > 1; |
---|
129 | 136 | |
---|
130 | 137 | 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; |
---|
132 | 142 | |
---|
133 | 143 | DRM_DEBUG_DRIVER("HW scaling is enabled\n"); |
---|
134 | 144 | |
---|
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; |
---|
137 | 173 | |
---|
138 | 174 | sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w, |
---|
139 | 175 | dst_h, hscale, vscale, hphase, vphase, |
---|
.. | .. |
---|
144 | 180 | sun8i_vi_scaler_enable(mixer, channel, false); |
---|
145 | 181 | } |
---|
146 | 182 | |
---|
| 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 | + |
---|
147 | 200 | /* Set base coordinates */ |
---|
148 | 201 | DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n", |
---|
149 | 202 | state->dst.x1, state->dst.y1); |
---|
150 | 203 | DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h); |
---|
151 | 204 | regmap_write(mixer->engine.regs, |
---|
152 | | - SUN8I_MIXER_BLEND_ATTR_COORD(zpos), |
---|
| 205 | + SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos), |
---|
153 | 206 | SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1)); |
---|
154 | 207 | regmap_write(mixer->engine.regs, |
---|
155 | | - SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos), |
---|
| 208 | + SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos), |
---|
156 | 209 | outsize); |
---|
157 | 210 | |
---|
158 | 211 | 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 | + } |
---|
159 | 228 | } |
---|
160 | 229 | |
---|
161 | 230 | static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, |
---|
162 | 231 | int overlay, struct drm_plane *plane) |
---|
163 | 232 | { |
---|
164 | 233 | 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; |
---|
167 | 237 | |
---|
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) { |
---|
170 | 243 | DRM_DEBUG_DRIVER("Invalid format\n"); |
---|
171 | | - return -EINVAL; |
---|
| 244 | + return ret; |
---|
172 | 245 | } |
---|
173 | 246 | |
---|
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; |
---|
175 | 248 | 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), |
---|
177 | 250 | SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val); |
---|
178 | 251 | |
---|
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); |
---|
181 | 257 | sun8i_csc_enable_ccsc(mixer, channel, true); |
---|
182 | 258 | } else { |
---|
183 | 259 | sun8i_csc_enable_ccsc(mixer, channel, false); |
---|
184 | 260 | } |
---|
185 | 261 | |
---|
186 | | - if (fmt_info->rgb) |
---|
| 262 | + if (!fmt->is_yuv) |
---|
187 | 263 | val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE; |
---|
188 | 264 | else |
---|
189 | 265 | val = 0; |
---|
190 | 266 | |
---|
191 | 267 | 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), |
---|
193 | 269 | 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)); |
---|
194 | 278 | |
---|
195 | 279 | return 0; |
---|
196 | 280 | } |
---|
.. | .. |
---|
204 | 288 | struct drm_gem_cma_object *gem; |
---|
205 | 289 | u32 dx, dy, src_x, src_y; |
---|
206 | 290 | dma_addr_t paddr; |
---|
| 291 | + u32 ch_base; |
---|
207 | 292 | int i; |
---|
| 293 | + |
---|
| 294 | + ch_base = sun8i_channel_base(mixer, channel); |
---|
208 | 295 | |
---|
209 | 296 | /* Adjust x and y to be dividable by subsampling factor */ |
---|
210 | 297 | src_x = (state->src.x1 >> 16) & ~(format->hsub - 1); |
---|
.. | .. |
---|
235 | 322 | DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n", |
---|
236 | 323 | i + 1, fb->pitches[i]); |
---|
237 | 324 | regmap_write(mixer->engine.regs, |
---|
238 | | - SUN8I_MIXER_CHAN_VI_LAYER_PITCH(channel, |
---|
| 325 | + SUN8I_MIXER_CHAN_VI_LAYER_PITCH(ch_base, |
---|
239 | 326 | overlay, i), |
---|
240 | | - fb->pitches[i]); |
---|
| 327 | + fb->pitches[i]); |
---|
241 | 328 | |
---|
242 | 329 | DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n", |
---|
243 | 330 | i + 1, &paddr); |
---|
244 | 331 | |
---|
245 | 332 | regmap_write(mixer->engine.regs, |
---|
246 | | - SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(channel, |
---|
| 333 | + SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch_base, |
---|
247 | 334 | overlay, i), |
---|
248 | | - lower_32_bits(paddr)); |
---|
| 335 | + lower_32_bits(paddr)); |
---|
249 | 336 | } |
---|
250 | 337 | |
---|
251 | 338 | return 0; |
---|
.. | .. |
---|
314 | 401 | true, zpos, old_zpos); |
---|
315 | 402 | } |
---|
316 | 403 | |
---|
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, |
---|
318 | 406 | .atomic_check = sun8i_vi_layer_atomic_check, |
---|
319 | 407 | .atomic_disable = sun8i_vi_layer_atomic_disable, |
---|
320 | 408 | .atomic_update = sun8i_vi_layer_atomic_update, |
---|
.. | .. |
---|
368 | 456 | DRM_FORMAT_YVU422, |
---|
369 | 457 | }; |
---|
370 | 458 | |
---|
| 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 | + |
---|
371 | 503 | struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, |
---|
372 | 504 | struct sun8i_mixer *mixer, |
---|
373 | 505 | int index) |
---|
374 | 506 | { |
---|
| 507 | + u32 supported_encodings, supported_ranges; |
---|
| 508 | + unsigned int plane_cnt, format_count; |
---|
375 | 509 | struct sun8i_vi_layer *layer; |
---|
376 | | - unsigned int plane_cnt; |
---|
| 510 | + const u32 *formats; |
---|
377 | 511 | int ret; |
---|
378 | 512 | |
---|
379 | 513 | layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL); |
---|
380 | 514 | if (!layer) |
---|
381 | 515 | return ERR_PTR(-ENOMEM); |
---|
382 | 516 | |
---|
| 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 | + |
---|
383 | 525 | /* possible crtcs are set later */ |
---|
384 | 526 | ret = drm_universal_plane_init(drm, &layer->plane, 0, |
---|
385 | 527 | &sun8i_vi_layer_funcs, |
---|
386 | | - sun8i_vi_layer_formats, |
---|
387 | | - ARRAY_SIZE(sun8i_vi_layer_formats), |
---|
| 528 | + formats, format_count, |
---|
388 | 529 | NULL, DRM_PLANE_TYPE_OVERLAY, NULL); |
---|
389 | 530 | if (ret) { |
---|
390 | 531 | dev_err(drm->dev, "Couldn't initialize layer\n"); |
---|
.. | .. |
---|
400 | 541 | return ERR_PTR(ret); |
---|
401 | 542 | } |
---|
402 | 543 | |
---|
| 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 | + |
---|
403 | 560 | drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs); |
---|
404 | 561 | layer->mixer = mixer; |
---|
405 | 562 | layer->channel = index; |
---|