cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mtk_drm_plane.c (7752B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2015 MediaTek Inc.
      4 * Author: CK Hu <ck.hu@mediatek.com>
      5 */
      6
      7#include <drm/drm_atomic.h>
      8#include <drm/drm_atomic_helper.h>
      9#include <drm/drm_atomic_uapi.h>
     10#include <drm/drm_fourcc.h>
     11#include <drm/drm_gem_atomic_helper.h>
     12#include <drm/drm_plane_helper.h>
     13
     14#include "mtk_drm_crtc.h"
     15#include "mtk_drm_ddp_comp.h"
     16#include "mtk_drm_drv.h"
     17#include "mtk_drm_gem.h"
     18#include "mtk_drm_plane.h"
     19
     20static const u32 formats[] = {
     21	DRM_FORMAT_XRGB8888,
     22	DRM_FORMAT_ARGB8888,
     23	DRM_FORMAT_BGRX8888,
     24	DRM_FORMAT_BGRA8888,
     25	DRM_FORMAT_ABGR8888,
     26	DRM_FORMAT_XBGR8888,
     27	DRM_FORMAT_RGB888,
     28	DRM_FORMAT_BGR888,
     29	DRM_FORMAT_RGB565,
     30	DRM_FORMAT_UYVY,
     31	DRM_FORMAT_YUYV,
     32};
     33
     34static void mtk_plane_reset(struct drm_plane *plane)
     35{
     36	struct mtk_plane_state *state;
     37
     38	if (plane->state) {
     39		__drm_atomic_helper_plane_destroy_state(plane->state);
     40
     41		state = to_mtk_plane_state(plane->state);
     42		memset(state, 0, sizeof(*state));
     43	} else {
     44		state = kzalloc(sizeof(*state), GFP_KERNEL);
     45		if (!state)
     46			return;
     47	}
     48
     49	__drm_atomic_helper_plane_reset(plane, &state->base);
     50
     51	state->base.plane = plane;
     52	state->pending.format = DRM_FORMAT_RGB565;
     53}
     54
     55static struct drm_plane_state *mtk_plane_duplicate_state(struct drm_plane *plane)
     56{
     57	struct mtk_plane_state *old_state = to_mtk_plane_state(plane->state);
     58	struct mtk_plane_state *state;
     59
     60	state = kmalloc(sizeof(*state), GFP_KERNEL);
     61	if (!state)
     62		return NULL;
     63
     64	__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
     65
     66	WARN_ON(state->base.plane != plane);
     67
     68	state->pending = old_state->pending;
     69
     70	return &state->base;
     71}
     72
     73static void mtk_drm_plane_destroy_state(struct drm_plane *plane,
     74					struct drm_plane_state *state)
     75{
     76	__drm_atomic_helper_plane_destroy_state(state);
     77	kfree(to_mtk_plane_state(state));
     78}
     79
     80static int mtk_plane_atomic_async_check(struct drm_plane *plane,
     81					struct drm_atomic_state *state)
     82{
     83	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
     84										 plane);
     85	struct drm_crtc_state *crtc_state;
     86	int ret;
     87
     88	if (plane != new_plane_state->crtc->cursor)
     89		return -EINVAL;
     90
     91	if (!plane->state)
     92		return -EINVAL;
     93
     94	if (!plane->state->fb)
     95		return -EINVAL;
     96
     97	ret = mtk_drm_crtc_plane_check(new_plane_state->crtc, plane,
     98				       to_mtk_plane_state(new_plane_state));
     99	if (ret)
    100		return ret;
    101
    102	if (state)
    103		crtc_state = drm_atomic_get_existing_crtc_state(state,
    104								new_plane_state->crtc);
    105	else /* Special case for asynchronous cursor updates. */
    106		crtc_state = new_plane_state->crtc->state;
    107
    108	return drm_atomic_helper_check_plane_state(plane->state, crtc_state,
    109						   DRM_PLANE_HELPER_NO_SCALING,
    110						   DRM_PLANE_HELPER_NO_SCALING,
    111						   true, true);
    112}
    113
    114static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
    115				       struct mtk_plane_state *mtk_plane_state)
    116{
    117	struct drm_framebuffer *fb = new_state->fb;
    118	struct drm_gem_object *gem;
    119	struct mtk_drm_gem_obj *mtk_gem;
    120	unsigned int pitch, format;
    121	dma_addr_t addr;
    122
    123	gem = fb->obj[0];
    124	mtk_gem = to_mtk_gem_obj(gem);
    125	addr = mtk_gem->dma_addr;
    126	pitch = fb->pitches[0];
    127	format = fb->format->format;
    128
    129	addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
    130	addr += (new_state->src.y1 >> 16) * pitch;
    131
    132	mtk_plane_state->pending.enable = true;
    133	mtk_plane_state->pending.pitch = pitch;
    134	mtk_plane_state->pending.format = format;
    135	mtk_plane_state->pending.addr = addr;
    136	mtk_plane_state->pending.x = new_state->dst.x1;
    137	mtk_plane_state->pending.y = new_state->dst.y1;
    138	mtk_plane_state->pending.width = drm_rect_width(&new_state->dst);
    139	mtk_plane_state->pending.height = drm_rect_height(&new_state->dst);
    140	mtk_plane_state->pending.rotation = new_state->rotation;
    141}
    142
    143static void mtk_plane_atomic_async_update(struct drm_plane *plane,
    144					  struct drm_atomic_state *state)
    145{
    146	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
    147									   plane);
    148	struct mtk_plane_state *new_plane_state = to_mtk_plane_state(plane->state);
    149
    150	plane->state->crtc_x = new_state->crtc_x;
    151	plane->state->crtc_y = new_state->crtc_y;
    152	plane->state->crtc_h = new_state->crtc_h;
    153	plane->state->crtc_w = new_state->crtc_w;
    154	plane->state->src_x = new_state->src_x;
    155	plane->state->src_y = new_state->src_y;
    156	plane->state->src_h = new_state->src_h;
    157	plane->state->src_w = new_state->src_w;
    158	swap(plane->state->fb, new_state->fb);
    159
    160	mtk_plane_update_new_state(new_state, new_plane_state);
    161	wmb(); /* Make sure the above parameters are set before update */
    162	new_plane_state->pending.async_dirty = true;
    163	mtk_drm_crtc_async_update(new_state->crtc, plane, state);
    164}
    165
    166static const struct drm_plane_funcs mtk_plane_funcs = {
    167	.update_plane = drm_atomic_helper_update_plane,
    168	.disable_plane = drm_atomic_helper_disable_plane,
    169	.destroy = drm_plane_cleanup,
    170	.reset = mtk_plane_reset,
    171	.atomic_duplicate_state = mtk_plane_duplicate_state,
    172	.atomic_destroy_state = mtk_drm_plane_destroy_state,
    173};
    174
    175static int mtk_plane_atomic_check(struct drm_plane *plane,
    176				  struct drm_atomic_state *state)
    177{
    178	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
    179										 plane);
    180	struct drm_framebuffer *fb = new_plane_state->fb;
    181	struct drm_crtc_state *crtc_state;
    182	int ret;
    183
    184	if (!fb)
    185		return 0;
    186
    187	if (WARN_ON(!new_plane_state->crtc))
    188		return 0;
    189
    190	ret = mtk_drm_crtc_plane_check(new_plane_state->crtc, plane,
    191				       to_mtk_plane_state(new_plane_state));
    192	if (ret)
    193		return ret;
    194
    195	crtc_state = drm_atomic_get_crtc_state(state,
    196					       new_plane_state->crtc);
    197	if (IS_ERR(crtc_state))
    198		return PTR_ERR(crtc_state);
    199
    200	return drm_atomic_helper_check_plane_state(new_plane_state,
    201						   crtc_state,
    202						   DRM_PLANE_HELPER_NO_SCALING,
    203						   DRM_PLANE_HELPER_NO_SCALING,
    204						   true, true);
    205}
    206
    207static void mtk_plane_atomic_disable(struct drm_plane *plane,
    208				     struct drm_atomic_state *state)
    209{
    210	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
    211									   plane);
    212	struct mtk_plane_state *mtk_plane_state = to_mtk_plane_state(new_state);
    213	mtk_plane_state->pending.enable = false;
    214	wmb(); /* Make sure the above parameter is set before update */
    215	mtk_plane_state->pending.dirty = true;
    216}
    217
    218static void mtk_plane_atomic_update(struct drm_plane *plane,
    219				    struct drm_atomic_state *state)
    220{
    221	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
    222									   plane);
    223	struct mtk_plane_state *mtk_plane_state = to_mtk_plane_state(new_state);
    224
    225	if (!new_state->crtc || WARN_ON(!new_state->fb))
    226		return;
    227
    228	if (!new_state->visible) {
    229		mtk_plane_atomic_disable(plane, state);
    230		return;
    231	}
    232
    233	mtk_plane_update_new_state(new_state, mtk_plane_state);
    234	wmb(); /* Make sure the above parameters are set before update */
    235	mtk_plane_state->pending.dirty = true;
    236}
    237
    238static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
    239	.atomic_check = mtk_plane_atomic_check,
    240	.atomic_update = mtk_plane_atomic_update,
    241	.atomic_disable = mtk_plane_atomic_disable,
    242	.atomic_async_update = mtk_plane_atomic_async_update,
    243	.atomic_async_check = mtk_plane_atomic_async_check,
    244};
    245
    246int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
    247		   unsigned long possible_crtcs, enum drm_plane_type type,
    248		   unsigned int supported_rotations)
    249{
    250	int err;
    251
    252	err = drm_universal_plane_init(dev, plane, possible_crtcs,
    253				       &mtk_plane_funcs, formats,
    254				       ARRAY_SIZE(formats), NULL, type, NULL);
    255	if (err) {
    256		DRM_ERROR("failed to initialize plane\n");
    257		return err;
    258	}
    259
    260	if (supported_rotations & ~DRM_MODE_ROTATE_0) {
    261		err = drm_plane_create_rotation_property(plane,
    262							 DRM_MODE_ROTATE_0,
    263							 supported_rotations);
    264		if (err)
    265			DRM_INFO("Create rotation property failed\n");
    266	}
    267
    268	drm_plane_helper_add(plane, &mtk_plane_helper_funcs);
    269
    270	return 0;
    271}