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

komeda_plane.c (8434B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
      4 * Author: James.Qian.Wang <james.qian.wang@arm.com>
      5 *
      6 */
      7#include <drm/drm_atomic.h>
      8#include <drm/drm_atomic_helper.h>
      9#include <drm/drm_plane_helper.h>
     10#include <drm/drm_print.h>
     11#include "komeda_dev.h"
     12#include "komeda_kms.h"
     13#include "komeda_framebuffer.h"
     14
     15static int
     16komeda_plane_init_data_flow(struct drm_plane_state *st,
     17			    struct komeda_crtc_state *kcrtc_st,
     18			    struct komeda_data_flow_cfg *dflow)
     19{
     20	struct komeda_plane *kplane = to_kplane(st->plane);
     21	struct drm_framebuffer *fb = st->fb;
     22	const struct komeda_format_caps *caps = to_kfb(fb)->format_caps;
     23	struct komeda_pipeline *pipe = kplane->layer->base.pipeline;
     24
     25	memset(dflow, 0, sizeof(*dflow));
     26
     27	dflow->blending_zorder = st->normalized_zpos;
     28	if (pipe == to_kcrtc(st->crtc)->master)
     29		dflow->blending_zorder -= kcrtc_st->max_slave_zorder;
     30	if (dflow->blending_zorder < 0) {
     31		DRM_DEBUG_ATOMIC("%s zorder:%d < max_slave_zorder: %d.\n",
     32				 st->plane->name, st->normalized_zpos,
     33				 kcrtc_st->max_slave_zorder);
     34		return -EINVAL;
     35	}
     36
     37	dflow->pixel_blend_mode = st->pixel_blend_mode;
     38	dflow->layer_alpha = st->alpha >> 8;
     39
     40	dflow->out_x = st->crtc_x;
     41	dflow->out_y = st->crtc_y;
     42	dflow->out_w = st->crtc_w;
     43	dflow->out_h = st->crtc_h;
     44
     45	dflow->in_x = st->src_x >> 16;
     46	dflow->in_y = st->src_y >> 16;
     47	dflow->in_w = st->src_w >> 16;
     48	dflow->in_h = st->src_h >> 16;
     49
     50	dflow->rot = drm_rotation_simplify(st->rotation, caps->supported_rots);
     51	if (!has_bits(dflow->rot, caps->supported_rots)) {
     52		DRM_DEBUG_ATOMIC("rotation(0x%x) isn't supported by %p4cc with modifier: 0x%llx.\n",
     53				 dflow->rot, &caps->fourcc, fb->modifier);
     54		return -EINVAL;
     55	}
     56
     57	komeda_complete_data_flow_cfg(kplane->layer, dflow, fb);
     58
     59	return 0;
     60}
     61
     62/**
     63 * komeda_plane_atomic_check - build input data flow
     64 * @plane: DRM plane
     65 * @state: the plane state object
     66 *
     67 * RETURNS:
     68 * Zero for success or -errno
     69 */
     70static int
     71komeda_plane_atomic_check(struct drm_plane *plane,
     72			  struct drm_atomic_state *state)
     73{
     74	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
     75										 plane);
     76	struct komeda_plane *kplane = to_kplane(plane);
     77	struct komeda_plane_state *kplane_st = to_kplane_st(new_plane_state);
     78	struct komeda_layer *layer = kplane->layer;
     79	struct drm_crtc_state *crtc_st;
     80	struct komeda_crtc_state *kcrtc_st;
     81	struct komeda_data_flow_cfg dflow;
     82	int err;
     83
     84	if (!new_plane_state->crtc || !new_plane_state->fb)
     85		return 0;
     86
     87	crtc_st = drm_atomic_get_crtc_state(state,
     88					    new_plane_state->crtc);
     89	if (IS_ERR(crtc_st) || !crtc_st->enable) {
     90		DRM_DEBUG_ATOMIC("Cannot update plane on a disabled CRTC.\n");
     91		return -EINVAL;
     92	}
     93
     94	/* crtc is inactive, skip the resource assignment */
     95	if (!crtc_st->active)
     96		return 0;
     97
     98	kcrtc_st = to_kcrtc_st(crtc_st);
     99
    100	err = komeda_plane_init_data_flow(new_plane_state, kcrtc_st, &dflow);
    101	if (err)
    102		return err;
    103
    104	if (dflow.en_split)
    105		err = komeda_build_layer_split_data_flow(layer,
    106				kplane_st, kcrtc_st, &dflow);
    107	else
    108		err = komeda_build_layer_data_flow(layer,
    109				kplane_st, kcrtc_st, &dflow);
    110
    111	return err;
    112}
    113
    114/* plane doesn't represent a real HW, so there is no HW update for plane.
    115 * komeda handles all the HW update in crtc->atomic_flush
    116 */
    117static void
    118komeda_plane_atomic_update(struct drm_plane *plane,
    119			   struct drm_atomic_state *state)
    120{
    121}
    122
    123static const struct drm_plane_helper_funcs komeda_plane_helper_funcs = {
    124	.atomic_check	= komeda_plane_atomic_check,
    125	.atomic_update	= komeda_plane_atomic_update,
    126};
    127
    128static void komeda_plane_destroy(struct drm_plane *plane)
    129{
    130	drm_plane_cleanup(plane);
    131
    132	kfree(to_kplane(plane));
    133}
    134
    135static void komeda_plane_reset(struct drm_plane *plane)
    136{
    137	struct komeda_plane_state *state;
    138
    139	if (plane->state)
    140		__drm_atomic_helper_plane_destroy_state(plane->state);
    141
    142	kfree(plane->state);
    143	plane->state = NULL;
    144
    145	state = kzalloc(sizeof(*state), GFP_KERNEL);
    146	if (state)
    147		__drm_atomic_helper_plane_reset(plane, &state->base);
    148}
    149
    150static struct drm_plane_state *
    151komeda_plane_atomic_duplicate_state(struct drm_plane *plane)
    152{
    153	struct komeda_plane_state *new;
    154
    155	if (WARN_ON(!plane->state))
    156		return NULL;
    157
    158	new = kzalloc(sizeof(*new), GFP_KERNEL);
    159	if (!new)
    160		return NULL;
    161
    162	__drm_atomic_helper_plane_duplicate_state(plane, &new->base);
    163
    164	return &new->base;
    165}
    166
    167static void
    168komeda_plane_atomic_destroy_state(struct drm_plane *plane,
    169				  struct drm_plane_state *state)
    170{
    171	__drm_atomic_helper_plane_destroy_state(state);
    172	kfree(to_kplane_st(state));
    173}
    174
    175static bool
    176komeda_plane_format_mod_supported(struct drm_plane *plane,
    177				  u32 format, u64 modifier)
    178{
    179	struct komeda_dev *mdev = plane->dev->dev_private;
    180	struct komeda_plane *kplane = to_kplane(plane);
    181	u32 layer_type = kplane->layer->layer_type;
    182
    183	return komeda_format_mod_supported(&mdev->fmt_tbl, layer_type,
    184					   format, modifier, 0);
    185}
    186
    187static const struct drm_plane_funcs komeda_plane_funcs = {
    188	.update_plane		= drm_atomic_helper_update_plane,
    189	.disable_plane		= drm_atomic_helper_disable_plane,
    190	.destroy		= komeda_plane_destroy,
    191	.reset			= komeda_plane_reset,
    192	.atomic_duplicate_state	= komeda_plane_atomic_duplicate_state,
    193	.atomic_destroy_state	= komeda_plane_atomic_destroy_state,
    194	.format_mod_supported	= komeda_plane_format_mod_supported,
    195};
    196
    197/* for komeda, which is pipeline can be share between crtcs */
    198static u32 get_possible_crtcs(struct komeda_kms_dev *kms,
    199			      struct komeda_pipeline *pipe)
    200{
    201	struct komeda_crtc *crtc;
    202	u32 possible_crtcs = 0;
    203	int i;
    204
    205	for (i = 0; i < kms->n_crtcs; i++) {
    206		crtc = &kms->crtcs[i];
    207
    208		if ((pipe == crtc->master) || (pipe == crtc->slave))
    209			possible_crtcs |= BIT(i);
    210	}
    211
    212	return possible_crtcs;
    213}
    214
    215static void
    216komeda_set_crtc_plane_mask(struct komeda_kms_dev *kms,
    217			   struct komeda_pipeline *pipe,
    218			   struct drm_plane *plane)
    219{
    220	struct komeda_crtc *kcrtc;
    221	int i;
    222
    223	for (i = 0; i < kms->n_crtcs; i++) {
    224		kcrtc = &kms->crtcs[i];
    225
    226		if (pipe == kcrtc->slave)
    227			kcrtc->slave_planes |= BIT(drm_plane_index(plane));
    228	}
    229}
    230
    231/* use Layer0 as primary */
    232static u32 get_plane_type(struct komeda_kms_dev *kms,
    233			  struct komeda_component *c)
    234{
    235	bool is_primary = (c->id == KOMEDA_COMPONENT_LAYER0);
    236
    237	return is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
    238}
    239
    240static int komeda_plane_add(struct komeda_kms_dev *kms,
    241			    struct komeda_layer *layer)
    242{
    243	struct komeda_dev *mdev = kms->base.dev_private;
    244	struct komeda_component *c = &layer->base;
    245	struct komeda_plane *kplane;
    246	struct drm_plane *plane;
    247	u32 *formats, n_formats = 0;
    248	int err;
    249
    250	kplane = kzalloc(sizeof(*kplane), GFP_KERNEL);
    251	if (!kplane)
    252		return -ENOMEM;
    253
    254	plane = &kplane->base;
    255	kplane->layer = layer;
    256
    257	formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,
    258					       layer->layer_type, &n_formats);
    259	if (!formats) {
    260		kfree(kplane);
    261		return -ENOMEM;
    262	}
    263
    264	err = drm_universal_plane_init(&kms->base, plane,
    265			get_possible_crtcs(kms, c->pipeline),
    266			&komeda_plane_funcs,
    267			formats, n_formats, komeda_supported_modifiers,
    268			get_plane_type(kms, c),
    269			"%s", c->name);
    270
    271	komeda_put_fourcc_list(formats);
    272
    273	if (err) {
    274		kfree(kplane);
    275		return err;
    276	}
    277
    278	drm_plane_helper_add(plane, &komeda_plane_helper_funcs);
    279
    280	err = drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
    281						 layer->supported_rots);
    282	if (err)
    283		goto cleanup;
    284
    285	err = drm_plane_create_alpha_property(plane);
    286	if (err)
    287		goto cleanup;
    288
    289	err = drm_plane_create_blend_mode_property(plane,
    290			BIT(DRM_MODE_BLEND_PIXEL_NONE) |
    291			BIT(DRM_MODE_BLEND_PREMULTI)   |
    292			BIT(DRM_MODE_BLEND_COVERAGE));
    293	if (err)
    294		goto cleanup;
    295
    296	err = drm_plane_create_color_properties(plane,
    297			BIT(DRM_COLOR_YCBCR_BT601) |
    298			BIT(DRM_COLOR_YCBCR_BT709) |
    299			BIT(DRM_COLOR_YCBCR_BT2020),
    300			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
    301			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
    302			DRM_COLOR_YCBCR_BT601,
    303			DRM_COLOR_YCBCR_LIMITED_RANGE);
    304	if (err)
    305		goto cleanup;
    306
    307	err = drm_plane_create_zpos_property(plane, layer->base.id, 0, 8);
    308	if (err)
    309		goto cleanup;
    310
    311	komeda_set_crtc_plane_mask(kms, c->pipeline, plane);
    312
    313	return 0;
    314cleanup:
    315	komeda_plane_destroy(plane);
    316	return err;
    317}
    318
    319int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
    320{
    321	struct komeda_pipeline *pipe;
    322	int i, j, err;
    323
    324	for (i = 0; i < mdev->n_pipelines; i++) {
    325		pipe = mdev->pipelines[i];
    326
    327		for (j = 0; j < pipe->n_layers; j++) {
    328			err = komeda_plane_add(kms, pipe->layers[j]);
    329			if (err)
    330				return err;
    331		}
    332	}
    333
    334	return 0;
    335}