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

mdp4_plane.c (11702B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2013 Red Hat
      4 * Author: Rob Clark <robdclark@gmail.com>
      5 */
      6
      7#include <drm/drm_atomic.h>
      8#include <drm/drm_damage_helper.h>
      9#include <drm/drm_fourcc.h>
     10#include <drm/drm_gem_atomic_helper.h>
     11
     12#include "mdp4_kms.h"
     13
     14#define DOWN_SCALE_MAX	8
     15#define UP_SCALE_MAX	8
     16
     17struct mdp4_plane {
     18	struct drm_plane base;
     19	const char *name;
     20
     21	enum mdp4_pipe pipe;
     22
     23	uint32_t caps;
     24	uint32_t nformats;
     25	uint32_t formats[32];
     26
     27	bool enabled;
     28};
     29#define to_mdp4_plane(x) container_of(x, struct mdp4_plane, base)
     30
     31/* MDP format helper functions */
     32static inline
     33enum mdp4_frame_format mdp4_get_frame_format(struct drm_framebuffer *fb)
     34{
     35	bool is_tile = false;
     36
     37	if (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
     38		is_tile = true;
     39
     40	if (fb->format->format == DRM_FORMAT_NV12 && is_tile)
     41		return FRAME_TILE_YCBCR_420;
     42
     43	return FRAME_LINEAR;
     44}
     45
     46static void mdp4_plane_set_scanout(struct drm_plane *plane,
     47		struct drm_framebuffer *fb);
     48static int mdp4_plane_mode_set(struct drm_plane *plane,
     49		struct drm_crtc *crtc, struct drm_framebuffer *fb,
     50		int crtc_x, int crtc_y,
     51		unsigned int crtc_w, unsigned int crtc_h,
     52		uint32_t src_x, uint32_t src_y,
     53		uint32_t src_w, uint32_t src_h);
     54
     55static struct mdp4_kms *get_kms(struct drm_plane *plane)
     56{
     57	struct msm_drm_private *priv = plane->dev->dev_private;
     58	return to_mdp4_kms(to_mdp_kms(priv->kms));
     59}
     60
     61static void mdp4_plane_destroy(struct drm_plane *plane)
     62{
     63	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
     64
     65	drm_plane_cleanup(plane);
     66
     67	kfree(mdp4_plane);
     68}
     69
     70/* helper to install properties which are common to planes and crtcs */
     71static void mdp4_plane_install_properties(struct drm_plane *plane,
     72		struct drm_mode_object *obj)
     73{
     74	// XXX
     75}
     76
     77static int mdp4_plane_set_property(struct drm_plane *plane,
     78		struct drm_property *property, uint64_t val)
     79{
     80	// XXX
     81	return -EINVAL;
     82}
     83
     84static const struct drm_plane_funcs mdp4_plane_funcs = {
     85		.update_plane = drm_atomic_helper_update_plane,
     86		.disable_plane = drm_atomic_helper_disable_plane,
     87		.destroy = mdp4_plane_destroy,
     88		.set_property = mdp4_plane_set_property,
     89		.reset = drm_atomic_helper_plane_reset,
     90		.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
     91		.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
     92};
     93
     94static int mdp4_plane_prepare_fb(struct drm_plane *plane,
     95				 struct drm_plane_state *new_state)
     96{
     97	struct msm_drm_private *priv = plane->dev->dev_private;
     98	struct msm_kms *kms = priv->kms;
     99
    100	if (!new_state->fb)
    101		return 0;
    102
    103	drm_gem_plane_helper_prepare_fb(plane, new_state);
    104
    105	return msm_framebuffer_prepare(new_state->fb, kms->aspace, false);
    106}
    107
    108static void mdp4_plane_cleanup_fb(struct drm_plane *plane,
    109				  struct drm_plane_state *old_state)
    110{
    111	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
    112	struct mdp4_kms *mdp4_kms = get_kms(plane);
    113	struct msm_kms *kms = &mdp4_kms->base.base;
    114	struct drm_framebuffer *fb = old_state->fb;
    115
    116	if (!fb)
    117		return;
    118
    119	DBG("%s: cleanup: FB[%u]", mdp4_plane->name, fb->base.id);
    120	msm_framebuffer_cleanup(fb, kms->aspace, false);
    121}
    122
    123
    124static int mdp4_plane_atomic_check(struct drm_plane *plane,
    125		struct drm_atomic_state *state)
    126{
    127	return 0;
    128}
    129
    130static void mdp4_plane_atomic_update(struct drm_plane *plane,
    131				     struct drm_atomic_state *state)
    132{
    133	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
    134									   plane);
    135	int ret;
    136
    137	ret = mdp4_plane_mode_set(plane,
    138			new_state->crtc, new_state->fb,
    139			new_state->crtc_x, new_state->crtc_y,
    140			new_state->crtc_w, new_state->crtc_h,
    141			new_state->src_x,  new_state->src_y,
    142			new_state->src_w, new_state->src_h);
    143	/* atomic_check should have ensured that this doesn't fail */
    144	WARN_ON(ret < 0);
    145}
    146
    147static const struct drm_plane_helper_funcs mdp4_plane_helper_funcs = {
    148		.prepare_fb = mdp4_plane_prepare_fb,
    149		.cleanup_fb = mdp4_plane_cleanup_fb,
    150		.atomic_check = mdp4_plane_atomic_check,
    151		.atomic_update = mdp4_plane_atomic_update,
    152};
    153
    154static void mdp4_plane_set_scanout(struct drm_plane *plane,
    155		struct drm_framebuffer *fb)
    156{
    157	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
    158	struct mdp4_kms *mdp4_kms = get_kms(plane);
    159	struct msm_kms *kms = &mdp4_kms->base.base;
    160	enum mdp4_pipe pipe = mdp4_plane->pipe;
    161
    162	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe),
    163			MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
    164			MDP4_PIPE_SRC_STRIDE_A_P1(fb->pitches[1]));
    165
    166	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_B(pipe),
    167			MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) |
    168			MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3]));
    169
    170	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe),
    171			msm_framebuffer_iova(fb, kms->aspace, 0));
    172	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP1_BASE(pipe),
    173			msm_framebuffer_iova(fb, kms->aspace, 1));
    174	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP2_BASE(pipe),
    175			msm_framebuffer_iova(fb, kms->aspace, 2));
    176	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe),
    177			msm_framebuffer_iova(fb, kms->aspace, 3));
    178}
    179
    180static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms,
    181		enum mdp4_pipe pipe, struct csc_cfg *csc)
    182{
    183	int i;
    184
    185	for (i = 0; i < ARRAY_SIZE(csc->matrix); i++) {
    186		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_MV(pipe, i),
    187				csc->matrix[i]);
    188	}
    189
    190	for (i = 0; i < ARRAY_SIZE(csc->post_bias) ; i++) {
    191		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_BV(pipe, i),
    192				csc->pre_bias[i]);
    193
    194		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_BV(pipe, i),
    195				csc->post_bias[i]);
    196	}
    197
    198	for (i = 0; i < ARRAY_SIZE(csc->post_clamp) ; i++) {
    199		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_LV(pipe, i),
    200				csc->pre_clamp[i]);
    201
    202		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_LV(pipe, i),
    203				csc->post_clamp[i]);
    204	}
    205}
    206
    207#define MDP4_VG_PHASE_STEP_DEFAULT	0x20000000
    208
    209static int mdp4_plane_mode_set(struct drm_plane *plane,
    210		struct drm_crtc *crtc, struct drm_framebuffer *fb,
    211		int crtc_x, int crtc_y,
    212		unsigned int crtc_w, unsigned int crtc_h,
    213		uint32_t src_x, uint32_t src_y,
    214		uint32_t src_w, uint32_t src_h)
    215{
    216	struct drm_device *dev = plane->dev;
    217	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
    218	struct mdp4_kms *mdp4_kms = get_kms(plane);
    219	enum mdp4_pipe pipe = mdp4_plane->pipe;
    220	const struct mdp_format *format;
    221	uint32_t op_mode = 0;
    222	uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
    223	uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
    224	enum mdp4_frame_format frame_type;
    225
    226	if (!(crtc && fb)) {
    227		DBG("%s: disabled!", mdp4_plane->name);
    228		return 0;
    229	}
    230
    231	frame_type = mdp4_get_frame_format(fb);
    232
    233	/* src values are in Q16 fixed point, convert to integer: */
    234	src_x = src_x >> 16;
    235	src_y = src_y >> 16;
    236	src_w = src_w >> 16;
    237	src_h = src_h >> 16;
    238
    239	DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp4_plane->name,
    240			fb->base.id, src_x, src_y, src_w, src_h,
    241			crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
    242
    243	format = to_mdp_format(msm_framebuffer_format(fb));
    244
    245	if (src_w > (crtc_w * DOWN_SCALE_MAX)) {
    246		DRM_DEV_ERROR(dev->dev, "Width down scaling exceeds limits!\n");
    247		return -ERANGE;
    248	}
    249
    250	if (src_h > (crtc_h * DOWN_SCALE_MAX)) {
    251		DRM_DEV_ERROR(dev->dev, "Height down scaling exceeds limits!\n");
    252		return -ERANGE;
    253	}
    254
    255	if (crtc_w > (src_w * UP_SCALE_MAX)) {
    256		DRM_DEV_ERROR(dev->dev, "Width up scaling exceeds limits!\n");
    257		return -ERANGE;
    258	}
    259
    260	if (crtc_h > (src_h * UP_SCALE_MAX)) {
    261		DRM_DEV_ERROR(dev->dev, "Height up scaling exceeds limits!\n");
    262		return -ERANGE;
    263	}
    264
    265	if (src_w != crtc_w) {
    266		uint32_t sel_unit = SCALE_FIR;
    267		op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN;
    268
    269		if (MDP_FORMAT_IS_YUV(format)) {
    270			if (crtc_w > src_w)
    271				sel_unit = SCALE_PIXEL_RPT;
    272			else if (crtc_w <= (src_w / 4))
    273				sel_unit = SCALE_MN_PHASE;
    274
    275			op_mode |= MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL(sel_unit);
    276			phasex_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,
    277					src_w, crtc_w);
    278		}
    279	}
    280
    281	if (src_h != crtc_h) {
    282		uint32_t sel_unit = SCALE_FIR;
    283		op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN;
    284
    285		if (MDP_FORMAT_IS_YUV(format)) {
    286
    287			if (crtc_h > src_h)
    288				sel_unit = SCALE_PIXEL_RPT;
    289			else if (crtc_h <= (src_h / 4))
    290				sel_unit = SCALE_MN_PHASE;
    291
    292			op_mode |= MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL(sel_unit);
    293			phasey_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,
    294					src_h, crtc_h);
    295		}
    296	}
    297
    298	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe),
    299			MDP4_PIPE_SRC_SIZE_WIDTH(src_w) |
    300			MDP4_PIPE_SRC_SIZE_HEIGHT(src_h));
    301
    302	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_XY(pipe),
    303			MDP4_PIPE_SRC_XY_X(src_x) |
    304			MDP4_PIPE_SRC_XY_Y(src_y));
    305
    306	mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_SIZE(pipe),
    307			MDP4_PIPE_DST_SIZE_WIDTH(crtc_w) |
    308			MDP4_PIPE_DST_SIZE_HEIGHT(crtc_h));
    309
    310	mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_XY(pipe),
    311			MDP4_PIPE_DST_XY_X(crtc_x) |
    312			MDP4_PIPE_DST_XY_Y(crtc_y));
    313
    314	mdp4_plane_set_scanout(plane, fb);
    315
    316	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe),
    317			MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
    318			MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
    319			MDP4_PIPE_SRC_FORMAT_G_BPC(format->bpc_g) |
    320			MDP4_PIPE_SRC_FORMAT_B_BPC(format->bpc_b) |
    321			COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) |
    322			MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
    323			MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
    324			MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) |
    325			MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) |
    326			MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT(frame_type) |
    327			COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));
    328
    329	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe),
    330			MDP4_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) |
    331			MDP4_PIPE_SRC_UNPACK_ELEM1(format->unpack[1]) |
    332			MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) |
    333			MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3]));
    334
    335	if (MDP_FORMAT_IS_YUV(format)) {
    336		struct csc_cfg *csc = mdp_get_default_csc_cfg(CSC_YUV2RGB);
    337
    338		op_mode |= MDP4_PIPE_OP_MODE_SRC_YCBCR;
    339		op_mode |= MDP4_PIPE_OP_MODE_CSC_EN;
    340		mdp4_write_csc_config(mdp4_kms, pipe, csc);
    341	}
    342
    343	mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode);
    344	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);
    345	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step);
    346
    347	if (frame_type != FRAME_LINEAR)
    348		mdp4_write(mdp4_kms, REG_MDP4_PIPE_SSTILE_FRAME_SIZE(pipe),
    349				MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH(src_w) |
    350				MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT(src_h));
    351
    352	return 0;
    353}
    354
    355static const char *pipe_names[] = {
    356		"VG1", "VG2",
    357		"RGB1", "RGB2", "RGB3",
    358		"VG3", "VG4",
    359};
    360
    361enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane)
    362{
    363	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
    364	return mdp4_plane->pipe;
    365}
    366
    367static const uint64_t supported_format_modifiers[] = {
    368	DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
    369	DRM_FORMAT_MOD_LINEAR,
    370	DRM_FORMAT_MOD_INVALID
    371};
    372
    373/* initialize plane */
    374struct drm_plane *mdp4_plane_init(struct drm_device *dev,
    375		enum mdp4_pipe pipe_id, bool private_plane)
    376{
    377	struct drm_plane *plane = NULL;
    378	struct mdp4_plane *mdp4_plane;
    379	int ret;
    380	enum drm_plane_type type;
    381
    382	mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL);
    383	if (!mdp4_plane) {
    384		ret = -ENOMEM;
    385		goto fail;
    386	}
    387
    388	plane = &mdp4_plane->base;
    389
    390	mdp4_plane->pipe = pipe_id;
    391	mdp4_plane->name = pipe_names[pipe_id];
    392	mdp4_plane->caps = mdp4_pipe_caps(pipe_id);
    393
    394	mdp4_plane->nformats = mdp_get_formats(mdp4_plane->formats,
    395			ARRAY_SIZE(mdp4_plane->formats),
    396			!pipe_supports_yuv(mdp4_plane->caps));
    397
    398	type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
    399	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
    400				 mdp4_plane->formats, mdp4_plane->nformats,
    401				 supported_format_modifiers, type, NULL);
    402	if (ret)
    403		goto fail;
    404
    405	drm_plane_helper_add(plane, &mdp4_plane_helper_funcs);
    406
    407	mdp4_plane_install_properties(plane, &plane->base);
    408
    409	drm_plane_enable_fb_damage_clips(plane);
    410
    411	return plane;
    412
    413fail:
    414	if (plane)
    415		mdp4_plane_destroy(plane);
    416
    417	return ERR_PTR(ret);
    418}