| .. | .. |
|---|
| 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; |
|---|