2019-06-01 08:08:57 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2016-03-07 10:00:53 +00:00
|
|
|
/*
|
|
|
|
* (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
|
|
|
|
* Author: Liviu Dudau <Liviu.Dudau@arm.com>
|
|
|
|
*
|
|
|
|
* ARM Mali DP plane manipulation routines.
|
|
|
|
*/
|
|
|
|
|
2018-10-01 13:39:07 +00:00
|
|
|
#include <linux/iommu.h>
|
2019-08-04 09:41:32 +00:00
|
|
|
#include <linux/platform_device.h>
|
2018-10-01 13:39:07 +00:00
|
|
|
|
2016-11-25 14:28:54 +00:00
|
|
|
#include <drm/drm_atomic.h>
|
2016-03-07 10:00:53 +00:00
|
|
|
#include <drm/drm_atomic_helper.h>
|
2022-06-13 20:03:12 +00:00
|
|
|
#include <drm/drm_blend.h>
|
2019-08-04 09:41:32 +00:00
|
|
|
#include <drm/drm_drv.h>
|
2022-08-02 00:04:02 +00:00
|
|
|
#include <drm/drm_fb_dma_helper.h>
|
2019-08-04 09:41:32 +00:00
|
|
|
#include <drm/drm_fourcc.h>
|
2022-06-14 09:54:49 +00:00
|
|
|
#include <drm/drm_framebuffer.h>
|
2022-08-02 00:04:03 +00:00
|
|
|
#include <drm/drm_gem_dma_helper.h>
|
2018-10-01 13:39:07 +00:00
|
|
|
#include <drm/drm_gem_framebuffer_helper.h>
|
2017-01-23 15:12:02 +00:00
|
|
|
#include <drm/drm_print.h>
|
2016-03-07 10:00:53 +00:00
|
|
|
|
|
|
|
#include "malidp_hw.h"
|
|
|
|
#include "malidp_drv.h"
|
|
|
|
|
|
|
|
/* Layer specific register offsets */
|
|
|
|
#define MALIDP_LAYER_FORMAT 0x000
|
2018-04-10 18:25:03 +00:00
|
|
|
#define LAYER_FORMAT_MASK 0x3f
|
2016-03-07 10:00:53 +00:00
|
|
|
#define MALIDP_LAYER_CONTROL 0x004
|
|
|
|
#define LAYER_ENABLE (1 << 0)
|
2017-02-13 15:14:05 +00:00
|
|
|
#define LAYER_FLOWCFG_MASK 7
|
|
|
|
#define LAYER_FLOWCFG(x) (((x) & LAYER_FLOWCFG_MASK) << 1)
|
|
|
|
#define LAYER_FLOWCFG_SCALE_SE 3
|
2016-03-07 10:00:53 +00:00
|
|
|
#define LAYER_ROT_OFFSET 8
|
|
|
|
#define LAYER_H_FLIP (1 << 10)
|
|
|
|
#define LAYER_V_FLIP (1 << 11)
|
|
|
|
#define LAYER_ROT_MASK (0xf << 8)
|
2016-10-11 14:26:08 +00:00
|
|
|
#define LAYER_COMP_MASK (0x3 << 12)
|
|
|
|
#define LAYER_COMP_PIXEL (0x3 << 12)
|
|
|
|
#define LAYER_COMP_PLANE (0x2 << 12)
|
2018-08-31 11:35:30 +00:00
|
|
|
#define LAYER_PMUL_ENABLE (0x1 << 14)
|
2018-01-23 16:49:29 +00:00
|
|
|
#define LAYER_ALPHA_OFFSET (16)
|
|
|
|
#define LAYER_ALPHA_MASK (0xff)
|
|
|
|
#define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET)
|
2016-10-11 14:26:08 +00:00
|
|
|
#define MALIDP_LAYER_COMPOSE 0x008
|
2016-03-07 10:00:53 +00:00
|
|
|
#define MALIDP_LAYER_SIZE 0x00c
|
|
|
|
#define LAYER_H_VAL(x) (((x) & 0x1fff) << 0)
|
|
|
|
#define LAYER_V_VAL(x) (((x) & 0x1fff) << 16)
|
|
|
|
#define MALIDP_LAYER_COMP_SIZE 0x010
|
|
|
|
#define MALIDP_LAYER_OFFSET 0x014
|
2017-02-09 11:32:00 +00:00
|
|
|
#define MALIDP550_LS_ENABLE 0x01c
|
|
|
|
#define MALIDP550_LS_R1_IN_SIZE 0x020
|
2016-03-07 10:00:53 +00:00
|
|
|
|
2018-07-17 11:11:09 +00:00
|
|
|
#define MODIFIERS_COUNT_MAX 15
|
|
|
|
|
2016-10-11 14:26:08 +00:00
|
|
|
/*
|
|
|
|
* This 4-entry look-up-table is used to determine the full 8-bit alpha value
|
|
|
|
* for formats with 1- or 2-bit alpha channels.
|
|
|
|
* We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0%
|
|
|
|
* opacity for 2-bit formats.
|
|
|
|
*/
|
|
|
|
#define MALIDP_ALPHA_LUT 0xffaa5500
|
|
|
|
|
2018-10-01 13:39:07 +00:00
|
|
|
/* page sizes the MMU prefetcher can support */
|
|
|
|
#define MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES (SZ_4K | SZ_64K)
|
|
|
|
#define MALIDP_MMU_PREFETCH_FULL_PGSIZES (SZ_1M | SZ_2M)
|
|
|
|
|
|
|
|
/* readahead for partial-frame prefetch */
|
|
|
|
#define MALIDP_MMU_PREFETCH_READAHEAD 8
|
|
|
|
|
2016-12-01 12:19:58 +00:00
|
|
|
/*
|
|
|
|
* Replicate what the default ->reset hook does: free the state pointer and
|
|
|
|
* allocate a new empty object. We just need enough space to store
|
|
|
|
* a malidp_plane_state instead of a drm_plane_state.
|
|
|
|
*/
|
|
|
|
static void malidp_plane_reset(struct drm_plane *plane)
|
|
|
|
{
|
|
|
|
struct malidp_plane_state *state = to_malidp_plane_state(plane->state);
|
|
|
|
|
|
|
|
if (state)
|
|
|
|
__drm_atomic_helper_plane_destroy_state(&state->base);
|
|
|
|
kfree(state);
|
|
|
|
plane->state = NULL;
|
|
|
|
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
2018-08-04 16:15:23 +00:00
|
|
|
if (state)
|
|
|
|
__drm_atomic_helper_plane_reset(plane, &state->base);
|
2016-12-01 12:19:58 +00:00
|
|
|
}
|
|
|
|
|
2016-10-22 09:13:01 +00:00
|
|
|
static struct
|
|
|
|
drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
|
2016-03-07 10:00:53 +00:00
|
|
|
{
|
|
|
|
struct malidp_plane_state *state, *m_state;
|
|
|
|
|
|
|
|
if (!plane->state)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
state = kmalloc(sizeof(*state), GFP_KERNEL);
|
2016-11-11 13:35:00 +00:00
|
|
|
if (!state)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
m_state = to_malidp_plane_state(plane->state);
|
|
|
|
__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
|
|
|
|
state->rotmem_size = m_state->rotmem_size;
|
|
|
|
state->format = m_state->format;
|
|
|
|
state->n_planes = m_state->n_planes;
|
2016-03-07 10:00:53 +00:00
|
|
|
|
2018-10-01 13:39:07 +00:00
|
|
|
state->mmu_prefetch_mode = m_state->mmu_prefetch_mode;
|
|
|
|
state->mmu_prefetch_pgsize = m_state->mmu_prefetch_pgsize;
|
|
|
|
|
2016-03-07 10:00:53 +00:00
|
|
|
return &state->base;
|
|
|
|
}
|
|
|
|
|
2016-10-22 09:13:01 +00:00
|
|
|
static void malidp_destroy_plane_state(struct drm_plane *plane,
|
|
|
|
struct drm_plane_state *state)
|
2016-03-07 10:00:53 +00:00
|
|
|
{
|
|
|
|
struct malidp_plane_state *m_state = to_malidp_plane_state(state);
|
|
|
|
|
|
|
|
__drm_atomic_helper_plane_destroy_state(state);
|
|
|
|
kfree(m_state);
|
|
|
|
}
|
|
|
|
|
2018-10-01 13:39:07 +00:00
|
|
|
static const char * const prefetch_mode_names[] = {
|
|
|
|
[MALIDP_PREFETCH_MODE_NONE] = "MMU_PREFETCH_NONE",
|
|
|
|
[MALIDP_PREFETCH_MODE_PARTIAL] = "MMU_PREFETCH_PARTIAL",
|
|
|
|
[MALIDP_PREFETCH_MODE_FULL] = "MMU_PREFETCH_FULL",
|
|
|
|
};
|
|
|
|
|
2017-01-23 15:12:02 +00:00
|
|
|
static void malidp_plane_atomic_print_state(struct drm_printer *p,
|
|
|
|
const struct drm_plane_state *state)
|
|
|
|
{
|
|
|
|
struct malidp_plane_state *ms = to_malidp_plane_state(state);
|
|
|
|
|
|
|
|
drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size);
|
|
|
|
drm_printf(p, "\tformat_id=%u\n", ms->format);
|
|
|
|
drm_printf(p, "\tn_planes=%u\n", ms->n_planes);
|
2018-10-01 13:39:07 +00:00
|
|
|
drm_printf(p, "\tmmu_prefetch_mode=%s\n",
|
|
|
|
prefetch_mode_names[ms->mmu_prefetch_mode]);
|
|
|
|
drm_printf(p, "\tmmu_prefetch_pgsize=%d\n", ms->mmu_prefetch_pgsize);
|
2017-01-23 15:12:02 +00:00
|
|
|
}
|
|
|
|
|
2018-07-17 11:11:09 +00:00
|
|
|
bool malidp_format_mod_supported(struct drm_device *drm,
|
|
|
|
u32 format, u64 modifier)
|
|
|
|
{
|
|
|
|
const struct drm_format_info *info;
|
|
|
|
const u64 *modifiers;
|
2022-10-26 15:59:31 +00:00
|
|
|
struct malidp_drm *malidp = drm_to_malidp(drm);
|
2018-07-17 11:11:09 +00:00
|
|
|
const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
|
|
|
|
|
|
|
|
if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* Some pixel formats are supported without any modifier */
|
|
|
|
if (modifier == DRM_FORMAT_MOD_LINEAR) {
|
|
|
|
/*
|
|
|
|
* However these pixel formats need to be supported with
|
|
|
|
* modifiers only
|
|
|
|
*/
|
|
|
|
return !malidp_hw_format_is_afbc_only(format);
|
|
|
|
}
|
|
|
|
|
2021-06-10 11:12:35 +00:00
|
|
|
if (!fourcc_mod_is_vendor(modifier, ARM)) {
|
2018-07-17 11:11:09 +00:00
|
|
|
DRM_ERROR("Unknown modifier (not Arm)\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modifier &
|
|
|
|
~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
|
|
|
|
DRM_DEBUG_KMS("Unsupported modifiers\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
modifiers = malidp_format_modifiers;
|
|
|
|
|
|
|
|
/* SPLIT buffers must use SPARSE layout */
|
|
|
|
if (WARN_ON_ONCE((modifier & AFBC_SPLIT) && !(modifier & AFBC_SPARSE)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* CBR only applies to YUV formats, where YTR should be always 0 */
|
|
|
|
if (WARN_ON_ONCE((modifier & AFBC_CBR) && (modifier & AFBC_YTR)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
while (*modifiers != DRM_FORMAT_MOD_INVALID) {
|
|
|
|
if (*modifiers == modifier)
|
|
|
|
break;
|
|
|
|
|
|
|
|
modifiers++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return false, if the modifier was not found */
|
|
|
|
if (*modifiers == DRM_FORMAT_MOD_INVALID) {
|
|
|
|
DRM_DEBUG_KMS("Unsupported modifier\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
info = drm_format_info(format);
|
|
|
|
|
|
|
|
if (info->num_planes != 1) {
|
|
|
|
DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (malidp_hw_format_is_linear_only(format) == true) {
|
|
|
|
DRM_DEBUG_KMS("Given format (0x%x) is supported is linear mode only\n",
|
|
|
|
format);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* RGB formats need to provide YTR modifier and YUV formats should not
|
|
|
|
* provide YTR modifier.
|
|
|
|
*/
|
|
|
|
if (!(info->is_yuv) != !!(modifier & AFBC_FORMAT_MOD_YTR)) {
|
|
|
|
DRM_DEBUG_KMS("AFBC_FORMAT_MOD_YTR is %s for %s formats\n",
|
|
|
|
info->is_yuv ? "disallowed" : "mandatory",
|
|
|
|
info->is_yuv ? "YUV" : "RGB");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modifier & AFBC_SPLIT) {
|
|
|
|
if (!info->is_yuv) {
|
2019-05-16 10:31:52 +00:00
|
|
|
if (info->cpp[0] <= 2) {
|
2018-07-17 11:11:09 +00:00
|
|
|
DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-16 10:31:48 +00:00
|
|
|
if ((info->hsub != 1) || (info->vsub != 1)) {
|
2018-07-17 11:11:09 +00:00
|
|
|
if (!(format == DRM_FORMAT_YUV420_10BIT &&
|
|
|
|
(map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) {
|
|
|
|
DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modifier & AFBC_CBR) {
|
2019-05-16 10:31:48 +00:00
|
|
|
if ((info->hsub == 1) || (info->vsub == 1)) {
|
2018-07-17 11:11:09 +00:00
|
|
|
DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool malidp_format_mod_supported_per_plane(struct drm_plane *plane,
|
|
|
|
u32 format, u64 modifier)
|
|
|
|
{
|
|
|
|
return malidp_format_mod_supported(plane->dev, format, modifier);
|
|
|
|
}
|
|
|
|
|
2016-03-07 10:00:53 +00:00
|
|
|
static const struct drm_plane_funcs malidp_de_plane_funcs = {
|
|
|
|
.update_plane = drm_atomic_helper_update_plane,
|
|
|
|
.disable_plane = drm_atomic_helper_disable_plane,
|
2016-12-01 12:19:58 +00:00
|
|
|
.reset = malidp_plane_reset,
|
2016-03-07 10:00:53 +00:00
|
|
|
.atomic_duplicate_state = malidp_duplicate_plane_state,
|
|
|
|
.atomic_destroy_state = malidp_destroy_plane_state,
|
2017-01-23 15:12:02 +00:00
|
|
|
.atomic_print_state = malidp_plane_atomic_print_state,
|
2018-07-17 11:11:09 +00:00
|
|
|
.format_mod_supported = malidp_format_mod_supported_per_plane,
|
2016-03-07 10:00:53 +00:00
|
|
|
};
|
|
|
|
|
2017-02-13 15:14:05 +00:00
|
|
|
static int malidp_se_check_scaling(struct malidp_plane *mp,
|
|
|
|
struct drm_plane_state *state)
|
|
|
|
{
|
|
|
|
struct drm_crtc_state *crtc_state =
|
|
|
|
drm_atomic_get_existing_crtc_state(state->state, state->crtc);
|
|
|
|
struct malidp_crtc_state *mc;
|
|
|
|
u32 src_w, src_h;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!crtc_state)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2017-12-09 11:46:13 +00:00
|
|
|
mc = to_malidp_crtc_state(crtc_state);
|
|
|
|
|
2018-01-23 17:08:57 +00:00
|
|
|
ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
2017-11-01 20:16:19 +00:00
|
|
|
0, INT_MAX, true, true);
|
2017-02-13 15:14:05 +00:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2017-12-15 16:42:19 +00:00
|
|
|
if (state->rotation & MALIDP_ROTATED_MASK) {
|
|
|
|
src_w = state->src_h >> 16;
|
|
|
|
src_h = state->src_w >> 16;
|
|
|
|
} else {
|
|
|
|
src_w = state->src_w >> 16;
|
|
|
|
src_h = state->src_h >> 16;
|
|
|
|
}
|
|
|
|
|
2017-02-13 15:14:05 +00:00
|
|
|
if ((state->crtc_w == src_w) && (state->crtc_h == src_h)) {
|
|
|
|
/* Scaling not necessary for this plane. */
|
|
|
|
mc->scaled_planes_mask &= ~(mp->layer->id);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mp->layer->id & (DE_SMART | DE_GRAPHICS2))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
mc->scaled_planes_mask |= mp->layer->id;
|
|
|
|
/* Defer scaling requirements calculation to the crtc check. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-10-01 13:39:07 +00:00
|
|
|
static u32 malidp_get_pgsize_bitmap(struct malidp_plane *mp)
|
|
|
|
{
|
2022-04-05 14:11:18 +00:00
|
|
|
struct iommu_domain *mmu_dom;
|
2018-10-01 13:39:07 +00:00
|
|
|
|
2022-04-05 14:11:18 +00:00
|
|
|
mmu_dom = iommu_get_domain_for_dev(mp->base.dev->dev);
|
|
|
|
if (mmu_dom)
|
|
|
|
return mmu_dom->pgsize_bitmap;
|
2018-10-01 13:39:07 +00:00
|
|
|
|
2022-04-05 14:11:18 +00:00
|
|
|
return 0;
|
2018-10-01 13:39:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if the framebuffer is entirely made up of pages at least pgsize in
|
|
|
|
* size. Only a heuristic: assumes that each scatterlist entry has been aligned
|
|
|
|
* to the largest page size smaller than its length and that the MMU maps to
|
|
|
|
* the largest page size possible.
|
|
|
|
*/
|
|
|
|
static bool malidp_check_pages_threshold(struct malidp_plane_state *ms,
|
|
|
|
u32 pgsize)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ms->n_planes; i++) {
|
|
|
|
struct drm_gem_object *obj;
|
2022-08-02 00:04:03 +00:00
|
|
|
struct drm_gem_dma_object *dma_obj;
|
2018-10-01 13:39:07 +00:00
|
|
|
struct sg_table *sgt;
|
|
|
|
struct scatterlist *sgl;
|
|
|
|
|
|
|
|
obj = drm_gem_fb_get_obj(ms->base.fb, i);
|
2022-08-02 00:04:03 +00:00
|
|
|
dma_obj = to_drm_gem_dma_obj(obj);
|
2018-10-01 13:39:07 +00:00
|
|
|
|
2022-08-02 00:04:03 +00:00
|
|
|
if (dma_obj->sgt)
|
|
|
|
sgt = dma_obj->sgt;
|
2018-10-01 13:39:07 +00:00
|
|
|
else
|
2020-08-07 11:10:22 +00:00
|
|
|
sgt = obj->funcs->get_sg_table(obj);
|
2018-10-01 13:39:07 +00:00
|
|
|
|
2021-12-13 07:21:15 +00:00
|
|
|
if (IS_ERR(sgt))
|
2018-10-01 13:39:07 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
sgl = sgt->sgl;
|
|
|
|
|
|
|
|
while (sgl) {
|
|
|
|
if (sgl->length < pgsize) {
|
2022-08-02 00:04:03 +00:00
|
|
|
if (!dma_obj->sgt)
|
2018-10-01 13:39:07 +00:00
|
|
|
kfree(sgt);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sgl = sg_next(sgl);
|
|
|
|
}
|
2022-08-02 00:04:03 +00:00
|
|
|
if (!dma_obj->sgt)
|
2018-10-01 13:39:07 +00:00
|
|
|
kfree(sgt);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if it is possible to enable partial-frame MMU prefetch given the
|
|
|
|
* current format, AFBC state and rotation.
|
|
|
|
*/
|
|
|
|
static bool malidp_partial_prefetch_supported(u32 format, u64 modifier,
|
|
|
|
unsigned int rotation)
|
|
|
|
{
|
|
|
|
bool afbc, sparse;
|
|
|
|
|
|
|
|
/* rotation and horizontal flip not supported for partial prefetch */
|
|
|
|
if (rotation & (DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
|
|
|
|
DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
afbc = modifier & DRM_FORMAT_MOD_ARM_AFBC(0);
|
|
|
|
sparse = modifier & AFBC_FORMAT_MOD_SPARSE;
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
case DRM_FORMAT_ARGB2101010:
|
|
|
|
case DRM_FORMAT_RGBA1010102:
|
|
|
|
case DRM_FORMAT_BGRA1010102:
|
|
|
|
case DRM_FORMAT_ARGB8888:
|
|
|
|
case DRM_FORMAT_RGBA8888:
|
|
|
|
case DRM_FORMAT_BGRA8888:
|
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
|
case DRM_FORMAT_RGBX8888:
|
|
|
|
case DRM_FORMAT_BGRX8888:
|
|
|
|
case DRM_FORMAT_RGB888:
|
|
|
|
case DRM_FORMAT_RGBA5551:
|
|
|
|
case DRM_FORMAT_RGB565:
|
|
|
|
/* always supported */
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case DRM_FORMAT_ABGR2101010:
|
|
|
|
case DRM_FORMAT_ABGR8888:
|
|
|
|
case DRM_FORMAT_ABGR1555:
|
|
|
|
case DRM_FORMAT_BGR565:
|
|
|
|
/* supported, but if AFBC then must be sparse mode */
|
|
|
|
return (!afbc) || (afbc && sparse);
|
|
|
|
|
|
|
|
case DRM_FORMAT_BGR888:
|
|
|
|
/* supported, but not for AFBC */
|
|
|
|
return !afbc;
|
|
|
|
|
|
|
|
case DRM_FORMAT_YUYV:
|
|
|
|
case DRM_FORMAT_UYVY:
|
|
|
|
case DRM_FORMAT_NV12:
|
|
|
|
case DRM_FORMAT_YUV420:
|
|
|
|
/* not supported */
|
|
|
|
return false;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Select the preferred MMU prefetch mode. Full-frame prefetch is preferred as
|
|
|
|
* long as the framebuffer is all large pages. Otherwise partial-frame prefetch
|
|
|
|
* is selected as long as it is supported for the current format. The selected
|
|
|
|
* page size for prefetch is returned in pgsize_bitmap.
|
|
|
|
*/
|
|
|
|
static enum mmu_prefetch_mode malidp_mmu_prefetch_select_mode
|
|
|
|
(struct malidp_plane_state *ms, u32 *pgsize_bitmap)
|
|
|
|
{
|
|
|
|
u32 pgsizes;
|
|
|
|
|
|
|
|
/* get the full-frame prefetch page size(s) supported by the MMU */
|
|
|
|
pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_FULL_PGSIZES;
|
|
|
|
|
|
|
|
while (pgsizes) {
|
|
|
|
u32 largest_pgsize = 1 << __fls(pgsizes);
|
|
|
|
|
|
|
|
if (malidp_check_pages_threshold(ms, largest_pgsize)) {
|
|
|
|
*pgsize_bitmap = largest_pgsize;
|
|
|
|
return MALIDP_PREFETCH_MODE_FULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pgsizes -= largest_pgsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the partial-frame prefetch page size(s) supported by the MMU */
|
|
|
|
pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES;
|
|
|
|
|
|
|
|
if (malidp_partial_prefetch_supported(ms->base.fb->format->format,
|
|
|
|
ms->base.fb->modifier,
|
|
|
|
ms->base.rotation)) {
|
|
|
|
/* partial prefetch using the smallest page size */
|
|
|
|
*pgsize_bitmap = 1 << __ffs(pgsizes);
|
|
|
|
return MALIDP_PREFETCH_MODE_PARTIAL;
|
|
|
|
}
|
|
|
|
*pgsize_bitmap = 0;
|
|
|
|
return MALIDP_PREFETCH_MODE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u32 malidp_calc_mmu_control_value(enum mmu_prefetch_mode mode,
|
|
|
|
u8 readahead, u8 n_planes, u32 pgsize)
|
|
|
|
{
|
|
|
|
u32 mmu_ctrl = 0;
|
|
|
|
|
|
|
|
if (mode != MALIDP_PREFETCH_MODE_NONE) {
|
|
|
|
mmu_ctrl |= MALIDP_MMU_CTRL_EN;
|
|
|
|
|
|
|
|
if (mode == MALIDP_PREFETCH_MODE_PARTIAL) {
|
|
|
|
mmu_ctrl |= MALIDP_MMU_CTRL_MODE;
|
|
|
|
mmu_ctrl |= MALIDP_MMU_CTRL_PP_NUM_REQ(readahead);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pgsize == SZ_64K || pgsize == SZ_2M) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < n_planes; i++)
|
|
|
|
mmu_ctrl |= MALIDP_MMU_CTRL_PX_PS(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mmu_ctrl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void malidp_de_prefetch_settings(struct malidp_plane *mp,
|
|
|
|
struct malidp_plane_state *ms)
|
|
|
|
{
|
|
|
|
if (!mp->layer->mmu_ctrl_offset)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* get the page sizes supported by the MMU */
|
|
|
|
ms->mmu_prefetch_pgsize = malidp_get_pgsize_bitmap(mp);
|
|
|
|
ms->mmu_prefetch_mode =
|
|
|
|
malidp_mmu_prefetch_select_mode(ms, &ms->mmu_prefetch_pgsize);
|
|
|
|
}
|
|
|
|
|
2016-03-07 10:00:53 +00:00
|
|
|
static int malidp_de_plane_check(struct drm_plane *plane,
|
drm/atomic: Pass the full state to planes atomic_check
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert all the remaining helpers to provide a consistent
interface, starting with the planes atomic_check.
The conversion was done using the coccinelle script below plus some
manual changes for vmwgfx, built tested on all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
int (*atomic_check)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_check = func,
...,
};
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier dev;
identifier plane, plane_state, state;
@@
f(struct drm_device *dev, struct drm_atomic_state *state)
{
<+...
- FUNCS->atomic_check(plane, plane_state)
+ FUNCS->atomic_check(plane, state)
...+>
}
@ ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
... when != new_plane_state
}
@ adds_new_state depends on plane_atomic_func && !ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *new_plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_new_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_new_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-4-maxime@cerno.tech
2021-02-19 12:00:24 +00:00
|
|
|
struct drm_atomic_state *state)
|
2016-03-07 10:00:53 +00:00
|
|
|
{
|
drm/atomic: Pass the full state to planes atomic_check
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert all the remaining helpers to provide a consistent
interface, starting with the planes atomic_check.
The conversion was done using the coccinelle script below plus some
manual changes for vmwgfx, built tested on all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
int (*atomic_check)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_check = func,
...,
};
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier dev;
identifier plane, plane_state, state;
@@
f(struct drm_device *dev, struct drm_atomic_state *state)
{
<+...
- FUNCS->atomic_check(plane, plane_state)
+ FUNCS->atomic_check(plane, state)
...+>
}
@ ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
... when != new_plane_state
}
@ adds_new_state depends on plane_atomic_func && !ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *new_plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_new_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_new_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-4-maxime@cerno.tech
2021-02-19 12:00:24 +00:00
|
|
|
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
|
|
|
|
plane);
|
2016-03-07 10:00:53 +00:00
|
|
|
struct malidp_plane *mp = to_malidp_plane(plane);
|
2021-02-19 12:00:22 +00:00
|
|
|
struct malidp_plane_state *ms = to_malidp_plane_state(new_plane_state);
|
|
|
|
bool rotated = new_plane_state->rotation & MALIDP_ROTATED_MASK;
|
2016-10-11 14:26:05 +00:00
|
|
|
struct drm_framebuffer *fb;
|
2021-02-19 12:00:22 +00:00
|
|
|
u16 pixel_alpha = new_plane_state->pixel_blend_mode;
|
2016-11-25 14:28:54 +00:00
|
|
|
int i, ret;
|
2018-11-01 15:11:31 +00:00
|
|
|
unsigned int block_w, block_h;
|
2016-03-07 10:00:53 +00:00
|
|
|
|
2021-02-19 12:00:22 +00:00
|
|
|
if (!new_plane_state->crtc || WARN_ON(!new_plane_state->fb))
|
2016-03-07 10:00:53 +00:00
|
|
|
return 0;
|
|
|
|
|
2021-02-19 12:00:22 +00:00
|
|
|
fb = new_plane_state->fb;
|
2016-10-11 14:26:05 +00:00
|
|
|
|
2017-08-31 14:48:43 +00:00
|
|
|
ms->format = malidp_hw_get_format_id(&mp->hwdev->hw->map,
|
2018-07-17 11:11:09 +00:00
|
|
|
mp->layer->id, fb->format->format,
|
|
|
|
!!fb->modifier);
|
2016-10-11 14:26:09 +00:00
|
|
|
if (ms->format == MALIDP_INVALID_FORMAT_ID)
|
2016-03-07 10:00:53 +00:00
|
|
|
return -EINVAL;
|
|
|
|
|
2016-12-14 21:30:22 +00:00
|
|
|
ms->n_planes = fb->format->num_planes;
|
2016-10-11 14:26:09 +00:00
|
|
|
for (i = 0; i < ms->n_planes; i++) {
|
2017-12-05 16:51:03 +00:00
|
|
|
u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated);
|
2018-11-01 15:11:31 +00:00
|
|
|
|
2018-11-19 14:41:03 +00:00
|
|
|
if (((fb->pitches[i] * drm_format_info_block_height(fb->format, i))
|
|
|
|
& (alignment - 1)) && !(fb->modifier)) {
|
2016-10-11 14:26:05 +00:00
|
|
|
DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
|
|
|
|
fb->pitches[i], i);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-01 15:11:31 +00:00
|
|
|
block_w = drm_format_info_block_width(fb->format, 0);
|
|
|
|
block_h = drm_format_info_block_height(fb->format, 0);
|
|
|
|
if (fb->width % block_w || fb->height % block_h) {
|
|
|
|
DRM_DEBUG_KMS("Buffer width/height needs to be a multiple of tile sizes");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2021-02-19 12:00:22 +00:00
|
|
|
if ((new_plane_state->src_x >> 16) % block_w || (new_plane_state->src_y >> 16) % block_h) {
|
2018-11-01 15:11:31 +00:00
|
|
|
DRM_DEBUG_KMS("Plane src_x/src_y needs to be a multiple of tile sizes");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2021-02-19 12:00:22 +00:00
|
|
|
if ((new_plane_state->crtc_w > mp->hwdev->max_line_size) ||
|
|
|
|
(new_plane_state->crtc_h > mp->hwdev->max_line_size) ||
|
|
|
|
(new_plane_state->crtc_w < mp->hwdev->min_line_size) ||
|
|
|
|
(new_plane_state->crtc_h < mp->hwdev->min_line_size))
|
2016-03-07 10:00:53 +00:00
|
|
|
return -EINVAL;
|
|
|
|
|
2017-01-23 15:24:35 +00:00
|
|
|
/*
|
|
|
|
* DP550/650 video layers can accept 3 plane formats only if
|
|
|
|
* fb->pitches[1] == fb->pitches[2] since they don't have a
|
|
|
|
* third plane stride register.
|
|
|
|
*/
|
|
|
|
if (ms->n_planes == 3 &&
|
2017-08-31 14:48:43 +00:00
|
|
|
!(mp->hwdev->hw->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) &&
|
2021-02-19 12:00:22 +00:00
|
|
|
(new_plane_state->fb->pitches[1] != new_plane_state->fb->pitches[2]))
|
2017-01-23 15:24:35 +00:00
|
|
|
return -EINVAL;
|
|
|
|
|
2021-02-19 12:00:22 +00:00
|
|
|
ret = malidp_se_check_scaling(mp, new_plane_state);
|
2017-02-13 15:14:05 +00:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2018-10-02 11:11:00 +00:00
|
|
|
/* validate the rotation constraints for each layer */
|
2021-02-19 12:00:22 +00:00
|
|
|
if (new_plane_state->rotation != DRM_MODE_ROTATE_0) {
|
2018-10-02 11:11:00 +00:00
|
|
|
if (mp->layer->rot == ROTATE_NONE)
|
|
|
|
return -EINVAL;
|
|
|
|
if ((mp->layer->rot == ROTATE_COMPRESSED) && !(fb->modifier))
|
|
|
|
return -EINVAL;
|
|
|
|
/*
|
|
|
|
* packed RGB888 / BGR888 can't be rotated or flipped
|
|
|
|
* unless they are stored in a compressed way
|
|
|
|
*/
|
|
|
|
if ((fb->format->format == DRM_FORMAT_RGB888 ||
|
|
|
|
fb->format->format == DRM_FORMAT_BGR888) && !(fb->modifier))
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2016-03-07 10:00:53 +00:00
|
|
|
|
2018-07-17 11:11:09 +00:00
|
|
|
/* SMART layer does not support AFBC */
|
|
|
|
if (mp->layer->id == DE_SMART && fb->modifier) {
|
|
|
|
DRM_ERROR("AFBC framebuffer not supported in SMART layer");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2016-03-07 10:00:53 +00:00
|
|
|
ms->rotmem_size = 0;
|
2021-02-19 12:00:22 +00:00
|
|
|
if (new_plane_state->rotation & MALIDP_ROTATED_MASK) {
|
2016-03-07 10:00:53 +00:00
|
|
|
int val;
|
|
|
|
|
2021-02-19 12:00:22 +00:00
|
|
|
val = mp->hwdev->hw->rotmem_required(mp->hwdev, new_plane_state->crtc_w,
|
|
|
|
new_plane_state->crtc_h,
|
2018-09-17 15:07:41 +00:00
|
|
|
fb->format->format,
|
|
|
|
!!(fb->modifier));
|
2016-03-07 10:00:53 +00:00
|
|
|
if (val < 0)
|
|
|
|
return val;
|
|
|
|
|
|
|
|
ms->rotmem_size = val;
|
|
|
|
}
|
|
|
|
|
2018-08-31 11:35:30 +00:00
|
|
|
/* HW can't support plane + pixel blending */
|
2021-02-19 12:00:22 +00:00
|
|
|
if ((new_plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
|
2018-08-31 11:35:30 +00:00
|
|
|
(pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE) &&
|
|
|
|
fb->format->has_alpha)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2018-10-01 13:39:07 +00:00
|
|
|
malidp_de_prefetch_settings(mp, ms);
|
|
|
|
|
2016-03-07 10:00:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-01-23 15:24:35 +00:00
|
|
|
static void malidp_de_set_plane_pitches(struct malidp_plane *mp,
|
|
|
|
int num_planes, unsigned int pitches[3])
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int num_strides = num_planes;
|
|
|
|
|
|
|
|
if (!mp->layer->stride_offset)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (num_planes == 3)
|
2017-08-31 14:48:43 +00:00
|
|
|
num_strides = (mp->hwdev->hw->features &
|
2017-01-23 15:24:35 +00:00
|
|
|
MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2;
|
|
|
|
|
2018-11-01 15:11:31 +00:00
|
|
|
/*
|
|
|
|
* The drm convention for pitch is that it needs to cover width * cpp,
|
|
|
|
* but our hardware wants the pitch/stride to cover all rows included
|
|
|
|
* in a tile.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < num_strides; ++i) {
|
|
|
|
unsigned int block_h = drm_format_info_block_height(mp->base.state->fb->format, i);
|
|
|
|
|
|
|
|
malidp_hw_write(mp->hwdev, pitches[i] * block_h,
|
2017-01-23 15:24:35 +00:00
|
|
|
mp->layer->base +
|
|
|
|
mp->layer->stride_offset + i * 4);
|
2018-11-01 15:11:31 +00:00
|
|
|
}
|
2017-01-23 15:24:35 +00:00
|
|
|
}
|
|
|
|
|
2017-11-07 15:30:46 +00:00
|
|
|
static const s16
|
|
|
|
malidp_yuv2rgb_coeffs[][DRM_COLOR_RANGE_MAX][MALIDP_COLORADJ_NUM_COEFFS] = {
|
|
|
|
[DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
|
|
|
|
1192, 0, 1634,
|
|
|
|
1192, -401, -832,
|
|
|
|
1192, 2066, 0,
|
|
|
|
64, 512, 512
|
|
|
|
},
|
|
|
|
[DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_FULL_RANGE] = {
|
|
|
|
1024, 0, 1436,
|
|
|
|
1024, -352, -731,
|
|
|
|
1024, 1815, 0,
|
|
|
|
0, 512, 512
|
|
|
|
},
|
|
|
|
[DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
|
|
|
|
1192, 0, 1836,
|
|
|
|
1192, -218, -546,
|
|
|
|
1192, 2163, 0,
|
|
|
|
64, 512, 512
|
|
|
|
},
|
|
|
|
[DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_FULL_RANGE] = {
|
|
|
|
1024, 0, 1613,
|
|
|
|
1024, -192, -479,
|
|
|
|
1024, 1900, 0,
|
|
|
|
0, 512, 512
|
|
|
|
},
|
|
|
|
[DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
|
|
|
|
1024, 0, 1476,
|
|
|
|
1024, -165, -572,
|
|
|
|
1024, 1884, 0,
|
|
|
|
0, 512, 512
|
|
|
|
},
|
|
|
|
[DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_FULL_RANGE] = {
|
|
|
|
1024, 0, 1510,
|
|
|
|
1024, -168, -585,
|
|
|
|
1024, 1927, 0,
|
|
|
|
0, 512, 512
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void malidp_de_set_color_encoding(struct malidp_plane *plane,
|
|
|
|
enum drm_color_encoding enc,
|
|
|
|
enum drm_color_range range)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
|
|
|
|
/* coefficients are signed, two's complement values */
|
|
|
|
malidp_hw_write(plane->hwdev, malidp_yuv2rgb_coeffs[enc][range][i],
|
|
|
|
plane->layer->base + plane->layer->yuv2rgb_offset +
|
|
|
|
i * 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-01 13:39:07 +00:00
|
|
|
static void malidp_de_set_mmu_control(struct malidp_plane *mp,
|
|
|
|
struct malidp_plane_state *ms)
|
|
|
|
{
|
|
|
|
u32 mmu_ctrl;
|
|
|
|
|
|
|
|
/* check hardware supports MMU prefetch */
|
|
|
|
if (!mp->layer->mmu_ctrl_offset)
|
|
|
|
return;
|
|
|
|
|
|
|
|
mmu_ctrl = malidp_calc_mmu_control_value(ms->mmu_prefetch_mode,
|
|
|
|
MALIDP_MMU_PREFETCH_READAHEAD,
|
|
|
|
ms->n_planes,
|
|
|
|
ms->mmu_prefetch_pgsize);
|
|
|
|
|
|
|
|
malidp_hw_write(mp->hwdev, mmu_ctrl,
|
|
|
|
mp->layer->base + mp->layer->mmu_ctrl_offset);
|
|
|
|
}
|
|
|
|
|
2018-05-16 18:23:08 +00:00
|
|
|
static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
|
|
|
|
struct malidp_plane *mp,
|
|
|
|
int plane_index)
|
|
|
|
{
|
2022-08-02 00:04:04 +00:00
|
|
|
dma_addr_t dma_addr;
|
2018-05-16 18:23:08 +00:00
|
|
|
u16 ptr;
|
|
|
|
struct drm_plane *plane = &mp->base;
|
|
|
|
bool afbc = fb->modifier ? true : false;
|
|
|
|
|
|
|
|
ptr = mp->layer->ptr + (plane_index << 4);
|
|
|
|
|
|
|
|
/*
|
2022-08-02 00:04:02 +00:00
|
|
|
* drm_fb_dma_get_gem_addr() alters the physical base address of the
|
2018-05-16 18:23:08 +00:00
|
|
|
* framebuffer as per the plane's src_x, src_y co-ordinates (ie to
|
|
|
|
* take care of source cropping).
|
|
|
|
* For AFBC, this is not needed as the cropping is handled by _AD_CROP_H
|
|
|
|
* and _AD_CROP_V registers.
|
|
|
|
*/
|
|
|
|
if (!afbc) {
|
2022-08-02 00:04:04 +00:00
|
|
|
dma_addr = drm_fb_dma_get_gem_addr(fb, plane->state,
|
|
|
|
plane_index);
|
2018-05-16 18:23:08 +00:00
|
|
|
} else {
|
2022-08-02 00:04:03 +00:00
|
|
|
struct drm_gem_dma_object *obj;
|
2018-05-16 18:23:08 +00:00
|
|
|
|
2022-08-02 00:04:02 +00:00
|
|
|
obj = drm_fb_dma_get_gem_obj(fb, plane_index);
|
2018-05-16 18:23:08 +00:00
|
|
|
|
|
|
|
if (WARN_ON(!obj))
|
|
|
|
return;
|
2022-08-02 00:04:04 +00:00
|
|
|
dma_addr = obj->dma_addr;
|
2018-05-16 18:23:08 +00:00
|
|
|
}
|
|
|
|
|
2022-08-02 00:04:04 +00:00
|
|
|
malidp_hw_write(mp->hwdev, lower_32_bits(dma_addr), ptr);
|
|
|
|
malidp_hw_write(mp->hwdev, upper_32_bits(dma_addr), ptr + 4);
|
2018-05-16 18:23:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void malidp_de_set_plane_afbc(struct drm_plane *plane)
|
|
|
|
{
|
|
|
|
struct malidp_plane *mp;
|
|
|
|
u32 src_w, src_h, val = 0, src_x, src_y;
|
|
|
|
struct drm_framebuffer *fb = plane->state->fb;
|
|
|
|
|
|
|
|
mp = to_malidp_plane(plane);
|
|
|
|
|
|
|
|
/* no afbc_decoder_offset means AFBC is not supported on this plane */
|
|
|
|
if (!mp->layer->afbc_decoder_offset)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!fb->modifier) {
|
|
|
|
malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert src values from Q16 fixed point to integer */
|
|
|
|
src_w = plane->state->src_w >> 16;
|
|
|
|
src_h = plane->state->src_h >> 16;
|
|
|
|
src_x = plane->state->src_x >> 16;
|
|
|
|
src_y = plane->state->src_y >> 16;
|
|
|
|
|
|
|
|
val = ((fb->width - (src_x + src_w)) << MALIDP_AD_CROP_RIGHT_OFFSET) |
|
|
|
|
src_x;
|
|
|
|
malidp_hw_write(mp->hwdev, val,
|
|
|
|
mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_H);
|
|
|
|
|
|
|
|
val = ((fb->height - (src_y + src_h)) << MALIDP_AD_CROP_BOTTOM_OFFSET) |
|
|
|
|
src_y;
|
|
|
|
malidp_hw_write(mp->hwdev, val,
|
|
|
|
mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_V);
|
|
|
|
|
|
|
|
val = MALIDP_AD_EN;
|
|
|
|
if (fb->modifier & AFBC_FORMAT_MOD_SPLIT)
|
|
|
|
val |= MALIDP_AD_BS;
|
|
|
|
if (fb->modifier & AFBC_FORMAT_MOD_YTR)
|
|
|
|
val |= MALIDP_AD_YTR;
|
|
|
|
|
|
|
|
malidp_hw_write(mp->hwdev, val, mp->layer->afbc_decoder_offset);
|
|
|
|
}
|
|
|
|
|
2016-03-07 10:00:53 +00:00
|
|
|
static void malidp_de_plane_update(struct drm_plane *plane,
|
drm/atomic: Pass the full state to planes atomic disable and update
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert the remaining helpers to provide a consistent interface,
this time with the planes atomic_update and atomic_disable.
The conversion was done using the coccinelle script below, built tested on
all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_update)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_disable)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
)
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier crtc_state;
identifier plane, plane_state, state;
expression e;
@@
f(struct drm_crtc_state *crtc_state)
{
...
struct drm_atomic_state *state = e;
<+...
(
- FUNCS->atomic_disable(plane, plane_state)
+ FUNCS->atomic_disable(plane, state)
|
- FUNCS->atomic_update(plane, plane_state)
+ FUNCS->atomic_update(plane, state)
)
...+>
}
@@
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *state)
+ struct drm_plane_state *old_plane_state)
{
<...
- state
+ old_plane_state
...>
}
@ ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
... when != old_state
}
@ adds_old_state depends on plane_atomic_func && !ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
+ struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_old_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_old_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
<+...
- plane_state->state
+ state
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-9-maxime@cerno.tech
2021-02-19 12:00:29 +00:00
|
|
|
struct drm_atomic_state *state)
|
2016-03-07 10:00:53 +00:00
|
|
|
{
|
drm/atomic: Pass the full state to planes atomic disable and update
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert the remaining helpers to provide a consistent interface,
this time with the planes atomic_update and atomic_disable.
The conversion was done using the coccinelle script below, built tested on
all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_update)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_disable)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
)
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier crtc_state;
identifier plane, plane_state, state;
expression e;
@@
f(struct drm_crtc_state *crtc_state)
{
...
struct drm_atomic_state *state = e;
<+...
(
- FUNCS->atomic_disable(plane, plane_state)
+ FUNCS->atomic_disable(plane, state)
|
- FUNCS->atomic_update(plane, plane_state)
+ FUNCS->atomic_update(plane, state)
)
...+>
}
@@
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *state)
+ struct drm_plane_state *old_plane_state)
{
<...
- state
+ old_plane_state
...>
}
@ ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
... when != old_state
}
@ adds_old_state depends on plane_atomic_func && !ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
+ struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_old_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_old_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
<+...
- plane_state->state
+ state
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-9-maxime@cerno.tech
2021-02-19 12:00:29 +00:00
|
|
|
struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
|
|
|
|
plane);
|
2016-03-07 10:00:53 +00:00
|
|
|
struct malidp_plane *mp;
|
2016-10-11 14:26:09 +00:00
|
|
|
struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
|
drm: Use state helper instead of the plane state pointer
Many drivers reference the plane->state pointer in order to get the
current plane state in their atomic_update or atomic_disable hooks,
which would be the new plane state in the global atomic state since
_swap_state happened when those hooks are run.
Use the drm_atomic_get_new_plane_state helper to get that state to make it
more obvious.
This was made using the coccinelle script below:
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ adds_new_state @
identifier plane_atomic_func.func;
identifier plane, state;
identifier new_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state)
{
...
- struct drm_plane_state *new_state = plane->state;
+ struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
...
}
@ include depends on adds_new_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_new_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://lore.kernel.org/r/20210219120032.260676-1-maxime@cerno.tech
2021-02-19 12:00:30 +00:00
|
|
|
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
|
|
|
|
plane);
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
u16 pixel_alpha = new_state->pixel_blend_mode;
|
|
|
|
u8 plane_alpha = new_state->alpha >> 8;
|
2016-10-11 14:26:09 +00:00
|
|
|
u32 src_w, src_h, dest_w, dest_h, val;
|
|
|
|
int i;
|
2018-05-16 18:23:08 +00:00
|
|
|
struct drm_framebuffer *fb = plane->state->fb;
|
2016-03-07 10:00:53 +00:00
|
|
|
|
|
|
|
mp = to_malidp_plane(plane);
|
|
|
|
|
2018-05-16 18:23:08 +00:00
|
|
|
/*
|
|
|
|
* For AFBC framebuffer, use the framebuffer width and height for
|
|
|
|
* configuring layer input size register.
|
|
|
|
*/
|
|
|
|
if (fb->modifier) {
|
|
|
|
src_w = fb->width;
|
|
|
|
src_h = fb->height;
|
|
|
|
} else {
|
|
|
|
/* convert src values from Q16 fixed point to integer */
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
src_w = new_state->src_w >> 16;
|
|
|
|
src_h = new_state->src_h >> 16;
|
2018-05-16 18:23:08 +00:00
|
|
|
}
|
|
|
|
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
dest_w = new_state->crtc_w;
|
|
|
|
dest_h = new_state->crtc_h;
|
2016-03-07 10:00:53 +00:00
|
|
|
|
2018-04-10 18:25:03 +00:00
|
|
|
val = malidp_hw_read(mp->hwdev, mp->layer->base);
|
|
|
|
val = (val & ~LAYER_FORMAT_MASK) | ms->format;
|
|
|
|
malidp_hw_write(mp->hwdev, val, mp->layer->base);
|
2016-03-07 10:00:53 +00:00
|
|
|
|
2018-05-16 18:23:08 +00:00
|
|
|
for (i = 0; i < ms->n_planes; i++)
|
|
|
|
malidp_set_plane_base_addr(fb, mp, i);
|
2018-10-01 13:39:07 +00:00
|
|
|
|
|
|
|
malidp_de_set_mmu_control(mp, ms);
|
|
|
|
|
2017-01-23 15:24:35 +00:00
|
|
|
malidp_de_set_plane_pitches(mp, ms->n_planes,
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
new_state->fb->pitches);
|
2016-03-07 10:00:53 +00:00
|
|
|
|
2017-11-07 15:30:46 +00:00
|
|
|
if ((plane->state->color_encoding != old_state->color_encoding) ||
|
|
|
|
(plane->state->color_range != old_state->color_range))
|
|
|
|
malidp_de_set_color_encoding(mp, plane->state->color_encoding,
|
|
|
|
plane->state->color_range);
|
|
|
|
|
2016-03-07 10:00:53 +00:00
|
|
|
malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
|
|
|
|
mp->layer->base + MALIDP_LAYER_SIZE);
|
|
|
|
|
|
|
|
malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
|
|
|
|
mp->layer->base + MALIDP_LAYER_COMP_SIZE);
|
|
|
|
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
malidp_hw_write(mp->hwdev, LAYER_H_VAL(new_state->crtc_x) |
|
|
|
|
LAYER_V_VAL(new_state->crtc_y),
|
2016-03-07 10:00:53 +00:00
|
|
|
mp->layer->base + MALIDP_LAYER_OFFSET);
|
|
|
|
|
2018-09-21 13:39:44 +00:00
|
|
|
if (mp->layer->id == DE_SMART) {
|
|
|
|
/*
|
|
|
|
* Enable the first rectangle in the SMART layer to be
|
|
|
|
* able to use it as a drm plane.
|
|
|
|
*/
|
|
|
|
malidp_hw_write(mp->hwdev, 1,
|
|
|
|
mp->layer->base + MALIDP550_LS_ENABLE);
|
2017-02-09 11:32:00 +00:00
|
|
|
malidp_hw_write(mp->hwdev,
|
|
|
|
LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
|
|
|
|
mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
|
2018-09-21 13:39:44 +00:00
|
|
|
}
|
2017-02-09 11:32:00 +00:00
|
|
|
|
2018-05-16 18:23:08 +00:00
|
|
|
malidp_de_set_plane_afbc(plane);
|
|
|
|
|
2016-10-11 14:26:08 +00:00
|
|
|
/* first clear the rotation bits */
|
|
|
|
val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
|
|
|
|
val &= ~LAYER_ROT_MASK;
|
2016-03-07 10:00:53 +00:00
|
|
|
|
|
|
|
/* setup the rotation and axis flip bits */
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
if (new_state->rotation & DRM_MODE_ROTATE_MASK)
|
2017-05-19 20:50:17 +00:00
|
|
|
val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) <<
|
2016-12-23 09:57:20 +00:00
|
|
|
LAYER_ROT_OFFSET;
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
if (new_state->rotation & DRM_MODE_REFLECT_X)
|
2016-03-07 10:00:53 +00:00
|
|
|
val |= LAYER_H_FLIP;
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
if (new_state->rotation & DRM_MODE_REFLECT_Y)
|
2016-12-07 13:20:28 +00:00
|
|
|
val |= LAYER_V_FLIP;
|
2016-03-07 10:00:53 +00:00
|
|
|
|
2018-08-31 11:35:30 +00:00
|
|
|
val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE | LAYER_ALPHA(0xff));
|
2018-01-23 16:49:29 +00:00
|
|
|
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
if (new_state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
|
2018-01-23 16:49:29 +00:00
|
|
|
val |= LAYER_COMP_PLANE;
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
} else if (new_state->fb->format->has_alpha) {
|
2018-08-31 11:35:30 +00:00
|
|
|
/* We only care about blend mode if the format has alpha */
|
|
|
|
switch (pixel_alpha) {
|
|
|
|
case DRM_MODE_BLEND_PREMULTI:
|
|
|
|
val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE;
|
|
|
|
break;
|
|
|
|
case DRM_MODE_BLEND_COVERAGE:
|
|
|
|
val |= LAYER_COMP_PIXEL;
|
|
|
|
break;
|
|
|
|
}
|
2018-01-23 16:49:29 +00:00
|
|
|
}
|
2018-08-31 11:35:30 +00:00
|
|
|
val |= LAYER_ALPHA(plane_alpha);
|
2016-10-11 14:26:08 +00:00
|
|
|
|
2017-02-13 15:14:05 +00:00
|
|
|
val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
if (new_state->crtc) {
|
2017-02-13 15:14:05 +00:00
|
|
|
struct malidp_crtc_state *m =
|
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 12:00:28 +00:00
|
|
|
to_malidp_crtc_state(new_state->crtc->state);
|
2017-02-13 15:14:05 +00:00
|
|
|
|
|
|
|
if (m->scaler_config.scale_enable &&
|
|
|
|
m->scaler_config.plane_src_id == mp->layer->id)
|
|
|
|
val |= LAYER_FLOWCFG(LAYER_FLOWCFG_SCALE_SE);
|
|
|
|
}
|
|
|
|
|
2016-03-07 10:00:53 +00:00
|
|
|
/* set the 'enable layer' bit */
|
|
|
|
val |= LAYER_ENABLE;
|
|
|
|
|
2016-10-11 14:26:08 +00:00
|
|
|
malidp_hw_write(mp->hwdev, val,
|
|
|
|
mp->layer->base + MALIDP_LAYER_CONTROL);
|
2016-03-07 10:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void malidp_de_plane_disable(struct drm_plane *plane,
|
drm/atomic: Pass the full state to planes atomic disable and update
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert the remaining helpers to provide a consistent interface,
this time with the planes atomic_update and atomic_disable.
The conversion was done using the coccinelle script below, built tested on
all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_update)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_disable)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
)
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier crtc_state;
identifier plane, plane_state, state;
expression e;
@@
f(struct drm_crtc_state *crtc_state)
{
...
struct drm_atomic_state *state = e;
<+...
(
- FUNCS->atomic_disable(plane, plane_state)
+ FUNCS->atomic_disable(plane, state)
|
- FUNCS->atomic_update(plane, plane_state)
+ FUNCS->atomic_update(plane, state)
)
...+>
}
@@
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *state)
+ struct drm_plane_state *old_plane_state)
{
<...
- state
+ old_plane_state
...>
}
@ ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
... when != old_state
}
@ adds_old_state depends on plane_atomic_func && !ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
+ struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_old_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_old_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
<+...
- plane_state->state
+ state
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-9-maxime@cerno.tech
2021-02-19 12:00:29 +00:00
|
|
|
struct drm_atomic_state *state)
|
2016-03-07 10:00:53 +00:00
|
|
|
{
|
|
|
|
struct malidp_plane *mp = to_malidp_plane(plane);
|
|
|
|
|
2017-02-13 15:14:05 +00:00
|
|
|
malidp_hw_clearbits(mp->hwdev,
|
|
|
|
LAYER_ENABLE | LAYER_FLOWCFG(LAYER_FLOWCFG_MASK),
|
2016-03-07 10:00:53 +00:00
|
|
|
mp->layer->base + MALIDP_LAYER_CONTROL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct drm_plane_helper_funcs malidp_de_plane_helper_funcs = {
|
|
|
|
.atomic_check = malidp_de_plane_check,
|
|
|
|
.atomic_update = malidp_de_plane_update,
|
|
|
|
.atomic_disable = malidp_de_plane_disable,
|
|
|
|
};
|
|
|
|
|
2021-04-27 09:20:12 +00:00
|
|
|
static const uint64_t linear_only_modifiers[] = {
|
|
|
|
DRM_FORMAT_MOD_LINEAR,
|
|
|
|
DRM_FORMAT_MOD_INVALID
|
|
|
|
};
|
|
|
|
|
2016-03-07 10:00:53 +00:00
|
|
|
int malidp_de_planes_init(struct drm_device *drm)
|
|
|
|
{
|
2022-10-26 15:59:31 +00:00
|
|
|
struct malidp_drm *malidp = drm_to_malidp(drm);
|
2017-08-31 14:48:43 +00:00
|
|
|
const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
|
2016-03-07 10:00:53 +00:00
|
|
|
struct malidp_plane *plane = NULL;
|
|
|
|
enum drm_plane_type plane_type;
|
2020-06-18 10:04:00 +00:00
|
|
|
unsigned long crtcs = BIT(drm->mode_config.num_crtc);
|
2017-05-19 20:50:17 +00:00
|
|
|
unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
|
|
|
|
DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
|
2018-08-31 11:35:30 +00:00
|
|
|
unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
|
|
|
|
BIT(DRM_MODE_BLEND_PREMULTI) |
|
|
|
|
BIT(DRM_MODE_BLEND_COVERAGE);
|
2016-03-07 10:00:53 +00:00
|
|
|
u32 *formats;
|
2018-05-15 12:35:57 +00:00
|
|
|
int ret, i = 0, j = 0, n;
|
|
|
|
u64 supported_modifiers[MODIFIERS_COUNT_MAX];
|
|
|
|
const u64 *modifiers;
|
|
|
|
|
|
|
|
modifiers = malidp_format_modifiers;
|
|
|
|
|
|
|
|
if (!(map->features & MALIDP_DEVICE_AFBC_SUPPORT_SPLIT)) {
|
|
|
|
/*
|
|
|
|
* Since our hardware does not support SPLIT, so build the list
|
|
|
|
* of supported modifiers excluding SPLIT ones.
|
|
|
|
*/
|
|
|
|
while (*modifiers != DRM_FORMAT_MOD_INVALID) {
|
|
|
|
if (!(*modifiers & AFBC_SPLIT))
|
|
|
|
supported_modifiers[j++] = *modifiers;
|
|
|
|
|
|
|
|
modifiers++;
|
|
|
|
}
|
|
|
|
supported_modifiers[j++] = DRM_FORMAT_MOD_INVALID;
|
|
|
|
modifiers = supported_modifiers;
|
|
|
|
}
|
2016-03-07 10:00:53 +00:00
|
|
|
|
2016-10-03 14:08:12 +00:00
|
|
|
formats = kcalloc(map->n_pixel_formats, sizeof(*formats), GFP_KERNEL);
|
2016-03-07 10:00:53 +00:00
|
|
|
if (!formats) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < map->n_layers; i++) {
|
|
|
|
u8 id = map->layers[i].id;
|
|
|
|
|
|
|
|
/* build the list of DRM supported formats based on the map */
|
2016-10-03 14:08:12 +00:00
|
|
|
for (n = 0, j = 0; j < map->n_pixel_formats; j++) {
|
|
|
|
if ((map->pixel_formats[j].layer & id) == id)
|
|
|
|
formats[n++] = map->pixel_formats[j].format;
|
2016-03-07 10:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
|
|
|
|
DRM_PLANE_TYPE_OVERLAY;
|
2018-05-15 12:35:57 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* All the layers except smart layer supports AFBC modifiers.
|
|
|
|
*/
|
2022-10-26 15:59:33 +00:00
|
|
|
plane = drmm_universal_plane_alloc(drm, struct malidp_plane, base,
|
|
|
|
crtcs, &malidp_de_plane_funcs, formats, n,
|
|
|
|
(id == DE_SMART) ? linear_only_modifiers :
|
|
|
|
modifiers, plane_type, NULL);
|
|
|
|
if (IS_ERR(plane)) {
|
|
|
|
ret = PTR_ERR(plane);
|
2016-03-07 10:00:53 +00:00
|
|
|
goto cleanup;
|
2022-10-26 15:59:33 +00:00
|
|
|
}
|
2016-03-07 10:00:53 +00:00
|
|
|
|
|
|
|
drm_plane_helper_add(&plane->base,
|
|
|
|
&malidp_de_plane_helper_funcs);
|
|
|
|
plane->hwdev = malidp->dev;
|
|
|
|
plane->layer = &map->layers[i];
|
2016-10-11 14:26:07 +00:00
|
|
|
|
2018-08-31 11:35:30 +00:00
|
|
|
drm_plane_create_alpha_property(&plane->base);
|
|
|
|
drm_plane_create_blend_mode_property(&plane->base, blend_caps);
|
|
|
|
|
2017-02-09 11:32:00 +00:00
|
|
|
if (id == DE_SMART) {
|
|
|
|
/* Skip the features which the SMART layer doesn't have. */
|
2016-10-11 14:26:07 +00:00
|
|
|
continue;
|
2017-02-09 11:32:00 +00:00
|
|
|
}
|
2016-10-11 14:26:07 +00:00
|
|
|
|
2017-05-19 20:50:17 +00:00
|
|
|
drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, flags);
|
2016-10-11 14:26:08 +00:00
|
|
|
malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
|
|
|
|
plane->layer->base + MALIDP_LAYER_COMPOSE);
|
2017-11-07 15:30:46 +00:00
|
|
|
|
|
|
|
/* Attach the YUV->RGB property only to video layers */
|
|
|
|
if (id & (DE_VIDEO1 | DE_VIDEO2)) {
|
|
|
|
/* default encoding for YUV->RGB is BT601 NARROW */
|
|
|
|
enum drm_color_encoding enc = DRM_COLOR_YCBCR_BT601;
|
|
|
|
enum drm_color_range range = DRM_COLOR_YCBCR_LIMITED_RANGE;
|
|
|
|
|
|
|
|
ret = drm_plane_create_color_properties(&plane->base,
|
|
|
|
BIT(DRM_COLOR_YCBCR_BT601) | \
|
|
|
|
BIT(DRM_COLOR_YCBCR_BT709) | \
|
|
|
|
BIT(DRM_COLOR_YCBCR_BT2020),
|
|
|
|
BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \
|
|
|
|
BIT(DRM_COLOR_YCBCR_FULL_RANGE),
|
|
|
|
enc, range);
|
|
|
|
if (!ret)
|
|
|
|
/* program the HW registers */
|
|
|
|
malidp_de_set_color_encoding(plane, enc, range);
|
|
|
|
else
|
|
|
|
DRM_WARN("Failed to create video layer %d color properties\n", id);
|
|
|
|
}
|
2016-03-07 10:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
kfree(formats);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
kfree(formats);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|