| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2012 Russell King |
|---|
| 3 | 4 | * Rewritten from the dovefb driver, and Armada510 manuals. |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 7 | | - * published by the Free Software Foundation. |
|---|
| 8 | 5 | */ |
|---|
| 9 | | -#include <drm/drmP.h> |
|---|
| 6 | + |
|---|
| 7 | +#include <linux/bitfield.h> |
|---|
| 8 | + |
|---|
| 9 | +#include <drm/armada_drm.h> |
|---|
| 10 | 10 | #include <drm/drm_atomic.h> |
|---|
| 11 | 11 | #include <drm/drm_atomic_helper.h> |
|---|
| 12 | +#include <drm/drm_atomic_uapi.h> |
|---|
| 13 | +#include <drm/drm_fourcc.h> |
|---|
| 12 | 14 | #include <drm/drm_plane_helper.h> |
|---|
| 13 | | -#include <drm/armada_drm.h> |
|---|
| 15 | + |
|---|
| 14 | 16 | #include "armada_crtc.h" |
|---|
| 15 | 17 | #include "armada_drm.h" |
|---|
| 16 | 18 | #include "armada_fb.h" |
|---|
| .. | .. |
|---|
| 26 | 28 | #define DEFAULT_ENCODING DRM_COLOR_YCBCR_BT601 |
|---|
| 27 | 29 | |
|---|
| 28 | 30 | struct armada_overlay_state { |
|---|
| 29 | | - struct drm_plane_state base; |
|---|
| 31 | + struct armada_plane_state base; |
|---|
| 30 | 32 | u32 colorkey_yr; |
|---|
| 31 | 33 | u32 colorkey_ug; |
|---|
| 32 | 34 | u32 colorkey_vb; |
|---|
| .. | .. |
|---|
| 37 | 39 | u16 saturation; |
|---|
| 38 | 40 | }; |
|---|
| 39 | 41 | #define drm_to_overlay_state(s) \ |
|---|
| 40 | | - container_of(s, struct armada_overlay_state, base) |
|---|
| 42 | + container_of(s, struct armada_overlay_state, base.base) |
|---|
| 41 | 43 | |
|---|
| 42 | 44 | static inline u32 armada_spu_contrast(struct drm_plane_state *state) |
|---|
| 43 | 45 | { |
|---|
| .. | .. |
|---|
| 93 | 95 | armada_reg_queue_mod(regs, idx, |
|---|
| 94 | 96 | 0, CFG_PDWN16x66 | CFG_PDWN32x66, |
|---|
| 95 | 97 | LCD_SPU_SRAM_PARA1); |
|---|
| 96 | | - val = armada_rect_hw_fp(&state->src); |
|---|
| 97 | | - if (armada_rect_hw_fp(&old_state->src) != val) |
|---|
| 98 | + val = armada_src_hw(state); |
|---|
| 99 | + if (armada_src_hw(old_state) != val) |
|---|
| 98 | 100 | armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_HPXL_VLN); |
|---|
| 99 | | - val = armada_rect_yx(&state->dst); |
|---|
| 100 | | - if (armada_rect_yx(&old_state->dst) != val) |
|---|
| 101 | + val = armada_dst_yx(state); |
|---|
| 102 | + if (armada_dst_yx(old_state) != val) |
|---|
| 101 | 103 | armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_OVSA_HPXL_VLN); |
|---|
| 102 | | - val = armada_rect_hw(&state->dst); |
|---|
| 103 | | - if (armada_rect_hw(&old_state->dst) != val) |
|---|
| 104 | + val = armada_dst_hw(state); |
|---|
| 105 | + if (armada_dst_hw(old_state) != val) |
|---|
| 104 | 106 | armada_reg_queue_set(regs, idx, val, LCD_SPU_DZM_HPXL_VLN); |
|---|
| 105 | 107 | /* FIXME: overlay on an interlaced display */ |
|---|
| 106 | 108 | if (old_state->src.x1 != state->src.x1 || |
|---|
| 107 | 109 | old_state->src.y1 != state->src.y1 || |
|---|
| 108 | | - old_state->fb != state->fb) { |
|---|
| 110 | + old_state->fb != state->fb || |
|---|
| 111 | + state->crtc->state->mode_changed) { |
|---|
| 109 | 112 | const struct drm_format_info *format; |
|---|
| 110 | | - u16 src_x, pitches[3]; |
|---|
| 111 | | - u32 addrs[2][3]; |
|---|
| 113 | + u16 src_x; |
|---|
| 112 | 114 | |
|---|
| 113 | | - armada_drm_plane_calc(state, addrs, pitches, false); |
|---|
| 114 | | - |
|---|
| 115 | | - armada_reg_queue_set(regs, idx, addrs[0][0], |
|---|
| 115 | + armada_reg_queue_set(regs, idx, armada_addr(state, 0, 0), |
|---|
| 116 | 116 | LCD_SPU_DMA_START_ADDR_Y0); |
|---|
| 117 | | - armada_reg_queue_set(regs, idx, addrs[0][1], |
|---|
| 117 | + armada_reg_queue_set(regs, idx, armada_addr(state, 0, 1), |
|---|
| 118 | 118 | LCD_SPU_DMA_START_ADDR_U0); |
|---|
| 119 | | - armada_reg_queue_set(regs, idx, addrs[0][2], |
|---|
| 119 | + armada_reg_queue_set(regs, idx, armada_addr(state, 0, 2), |
|---|
| 120 | 120 | LCD_SPU_DMA_START_ADDR_V0); |
|---|
| 121 | | - armada_reg_queue_set(regs, idx, addrs[1][0], |
|---|
| 121 | + armada_reg_queue_set(regs, idx, armada_addr(state, 1, 0), |
|---|
| 122 | 122 | LCD_SPU_DMA_START_ADDR_Y1); |
|---|
| 123 | | - armada_reg_queue_set(regs, idx, addrs[1][1], |
|---|
| 123 | + armada_reg_queue_set(regs, idx, armada_addr(state, 1, 1), |
|---|
| 124 | 124 | LCD_SPU_DMA_START_ADDR_U1); |
|---|
| 125 | | - armada_reg_queue_set(regs, idx, addrs[1][2], |
|---|
| 125 | + armada_reg_queue_set(regs, idx, armada_addr(state, 1, 2), |
|---|
| 126 | 126 | LCD_SPU_DMA_START_ADDR_V1); |
|---|
| 127 | 127 | |
|---|
| 128 | | - val = pitches[0] << 16 | pitches[0]; |
|---|
| 128 | + val = armada_pitch(state, 0) << 16 | armada_pitch(state, 0); |
|---|
| 129 | 129 | armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_YC); |
|---|
| 130 | | - val = pitches[1] << 16 | pitches[2]; |
|---|
| 130 | + val = armada_pitch(state, 1) << 16 | armada_pitch(state, 2); |
|---|
| 131 | 131 | armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_UV); |
|---|
| 132 | 132 | |
|---|
| 133 | 133 | cfg = CFG_DMA_FMT(drm_fb_to_armada_fb(state->fb)->fmt) | |
|---|
| .. | .. |
|---|
| 145 | 145 | src_x = state->src.x1 >> 16; |
|---|
| 146 | 146 | if (format->num_planes == 1 && src_x & (format->hsub - 1)) |
|---|
| 147 | 147 | cfg ^= CFG_DMA_MOD(CFG_SWAPUV); |
|---|
| 148 | + if (to_armada_plane_state(state)->interlace) |
|---|
| 149 | + cfg |= CFG_DMA_FTOGGLE; |
|---|
| 148 | 150 | cfg_mask = CFG_CBSH_ENA | CFG_DMAFORMAT | |
|---|
| 149 | 151 | CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | |
|---|
| 150 | 152 | CFG_SWAPYU | CFG_YUV2RGB) | |
|---|
| .. | .. |
|---|
| 306 | 308 | if (plane->state) |
|---|
| 307 | 309 | __drm_atomic_helper_plane_destroy_state(plane->state); |
|---|
| 308 | 310 | kfree(plane->state); |
|---|
| 311 | + plane->state = NULL; |
|---|
| 309 | 312 | |
|---|
| 310 | 313 | state = kzalloc(sizeof(*state), GFP_KERNEL); |
|---|
| 311 | 314 | if (state) { |
|---|
| 312 | | - state->base.plane = plane; |
|---|
| 313 | | - state->base.color_encoding = DEFAULT_ENCODING; |
|---|
| 314 | | - state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; |
|---|
| 315 | | - state->base.rotation = DRM_MODE_ROTATE_0; |
|---|
| 316 | 315 | state->colorkey_yr = 0xfefefe00; |
|---|
| 317 | 316 | state->colorkey_ug = 0x01010100; |
|---|
| 318 | 317 | state->colorkey_vb = 0x01010100; |
|---|
| .. | .. |
|---|
| 322 | 321 | state->brightness = DEFAULT_BRIGHTNESS; |
|---|
| 323 | 322 | state->contrast = DEFAULT_CONTRAST; |
|---|
| 324 | 323 | state->saturation = DEFAULT_SATURATION; |
|---|
| 324 | + __drm_atomic_helper_plane_reset(plane, &state->base.base); |
|---|
| 325 | + state->base.base.color_encoding = DEFAULT_ENCODING; |
|---|
| 326 | + state->base.base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; |
|---|
| 325 | 327 | } |
|---|
| 326 | | - plane->state = &state->base; |
|---|
| 327 | 328 | } |
|---|
| 328 | 329 | |
|---|
| 329 | 330 | struct drm_plane_state * |
|---|
| .. | .. |
|---|
| 336 | 337 | |
|---|
| 337 | 338 | state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL); |
|---|
| 338 | 339 | if (state) |
|---|
| 339 | | - __drm_atomic_helper_plane_duplicate_state(plane, &state->base); |
|---|
| 340 | | - return &state->base; |
|---|
| 340 | + __drm_atomic_helper_plane_duplicate_state(plane, |
|---|
| 341 | + &state->base.base); |
|---|
| 342 | + return &state->base.base; |
|---|
| 341 | 343 | } |
|---|
| 342 | 344 | |
|---|
| 343 | 345 | static int armada_overlay_set_property(struct drm_plane *plane, |
|---|
| 344 | 346 | struct drm_plane_state *state, struct drm_property *property, |
|---|
| 345 | 347 | uint64_t val) |
|---|
| 346 | 348 | { |
|---|
| 347 | | - struct armada_private *priv = plane->dev->dev_private; |
|---|
| 349 | + struct armada_private *priv = drm_to_armada_dev(plane->dev); |
|---|
| 348 | 350 | |
|---|
| 349 | 351 | #define K2R(val) (((val) >> 0) & 0xff) |
|---|
| 350 | 352 | #define K2G(val) (((val) >> 8) & 0xff) |
|---|
| .. | .. |
|---|
| 412 | 414 | const struct drm_plane_state *state, struct drm_property *property, |
|---|
| 413 | 415 | uint64_t *val) |
|---|
| 414 | 416 | { |
|---|
| 415 | | - struct armada_private *priv = plane->dev->dev_private; |
|---|
| 417 | + struct armada_private *priv = drm_to_armada_dev(plane->dev); |
|---|
| 416 | 418 | |
|---|
| 417 | 419 | #define C2K(c,s) (((c) >> (s)) & 0xff) |
|---|
| 418 | 420 | #define R2BGR(r,g,b,s) (C2K(r,s) << 0 | C2K(g,s) << 8 | C2K(b,s) << 16) |
|---|
| .. | .. |
|---|
| 446 | 448 | drm_to_overlay_state(state)->colorkey_ug, |
|---|
| 447 | 449 | drm_to_overlay_state(state)->colorkey_vb, 0); |
|---|
| 448 | 450 | } else if (property == priv->colorkey_mode_prop) { |
|---|
| 449 | | - *val = (drm_to_overlay_state(state)->colorkey_mode & |
|---|
| 450 | | - CFG_CKMODE_MASK) >> ffs(CFG_CKMODE_MASK); |
|---|
| 451 | + *val = FIELD_GET(CFG_CKMODE_MASK, |
|---|
| 452 | + drm_to_overlay_state(state)->colorkey_mode); |
|---|
| 451 | 453 | } else if (property == priv->brightness_prop) { |
|---|
| 452 | 454 | *val = drm_to_overlay_state(state)->brightness + 256; |
|---|
| 453 | 455 | } else if (property == priv->contrast_prop) { |
|---|
| .. | .. |
|---|
| 505 | 507 | |
|---|
| 506 | 508 | static int armada_overlay_create_properties(struct drm_device *dev) |
|---|
| 507 | 509 | { |
|---|
| 508 | | - struct armada_private *priv = dev->dev_private; |
|---|
| 510 | + struct armada_private *priv = drm_to_armada_dev(dev); |
|---|
| 509 | 511 | |
|---|
| 510 | 512 | if (priv->colorkey_prop) |
|---|
| 511 | 513 | return 0; |
|---|
| .. | .. |
|---|
| 539 | 541 | |
|---|
| 540 | 542 | int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) |
|---|
| 541 | 543 | { |
|---|
| 542 | | - struct armada_private *priv = dev->dev_private; |
|---|
| 544 | + struct armada_private *priv = drm_to_armada_dev(dev); |
|---|
| 543 | 545 | struct drm_mode_object *mobj; |
|---|
| 544 | 546 | struct drm_plane *overlay; |
|---|
| 545 | 547 | int ret; |
|---|