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

omap_overlay.c (5646B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2018 Texas Instruments Incorporated -  http://www.ti.com/
      4 * Author: Benoit Parrot <bparrot@ti.com>
      5 */
      6
      7#include <drm/drm_atomic.h>
      8#include <drm/drm_atomic_helper.h>
      9#include <drm/drm_plane_helper.h>
     10
     11#include "omap_dmm_tiler.h"
     12#include "omap_drv.h"
     13
     14/*
     15 * overlay funcs
     16 */
     17static const char * const overlay_id_to_name[] = {
     18	[OMAP_DSS_GFX] = "gfx",
     19	[OMAP_DSS_VIDEO1] = "vid1",
     20	[OMAP_DSS_VIDEO2] = "vid2",
     21	[OMAP_DSS_VIDEO3] = "vid3",
     22};
     23
     24/*
     25 * Find a free overlay with the required caps and supported fourcc
     26 */
     27static struct omap_hw_overlay *
     28omap_plane_find_free_overlay(struct drm_device *dev, struct drm_plane *hwoverlay_to_plane[],
     29			     u32 caps, u32 fourcc)
     30{
     31	struct omap_drm_private *priv = dev->dev_private;
     32	int i;
     33
     34	DBG("caps: %x fourcc: %x", caps, fourcc);
     35
     36	for (i = 0; i < priv->num_ovls; i++) {
     37		struct omap_hw_overlay *cur = priv->overlays[i];
     38
     39		DBG("%d: id: %d cur->caps: %x",
     40		    cur->idx, cur->id, cur->caps);
     41
     42		/* skip if already in-use */
     43		if (hwoverlay_to_plane[cur->idx])
     44			continue;
     45
     46		/* skip if doesn't support some required caps: */
     47		if (caps & ~cur->caps)
     48			continue;
     49
     50		/* check supported format */
     51		if (!dispc_ovl_color_mode_supported(priv->dispc,
     52						    cur->id, fourcc))
     53			continue;
     54
     55		return cur;
     56	}
     57
     58	DBG("no match");
     59	return NULL;
     60}
     61
     62/*
     63 * Assign a new overlay to a plane with the required caps and supported fourcc
     64 * If a plane need a new overlay, the previous one should have been released
     65 * with omap_overlay_release()
     66 * This should be called from the plane atomic_check() in order to prepare the
     67 * next global overlay_map to be enabled when atomic transaction is valid.
     68 */
     69int omap_overlay_assign(struct drm_atomic_state *s, struct drm_plane *plane,
     70			u32 caps, u32 fourcc, struct omap_hw_overlay **overlay,
     71			struct omap_hw_overlay **r_overlay)
     72{
     73	/* Get the global state of the current atomic transaction */
     74	struct omap_global_state *state = omap_get_global_state(s);
     75	struct drm_plane **overlay_map = state->hwoverlay_to_plane;
     76	struct omap_hw_overlay *ovl, *r_ovl;
     77
     78	ovl = omap_plane_find_free_overlay(s->dev, overlay_map, caps, fourcc);
     79	if (!ovl)
     80		return -ENOMEM;
     81
     82	overlay_map[ovl->idx] = plane;
     83	*overlay = ovl;
     84
     85	if (r_overlay) {
     86		r_ovl = omap_plane_find_free_overlay(s->dev, overlay_map,
     87						     caps, fourcc);
     88		if (!r_ovl) {
     89			overlay_map[ovl->idx] = NULL;
     90			*overlay = NULL;
     91			return -ENOMEM;
     92		}
     93
     94		overlay_map[r_ovl->idx] = plane;
     95		*r_overlay = r_ovl;
     96	}
     97
     98	DBG("%s: assign to plane %s caps %x", ovl->name, plane->name, caps);
     99
    100	if (r_overlay) {
    101		DBG("%s: assign to right of plane %s caps %x",
    102		    r_ovl->name, plane->name, caps);
    103	}
    104
    105	return 0;
    106}
    107
    108/*
    109 * Release an overlay from a plane if the plane gets not visible or the plane
    110 * need a new overlay if overlay caps changes.
    111 * This should be called from the plane atomic_check() in order to prepare the
    112 * next global overlay_map to be enabled when atomic transaction is valid.
    113 */
    114void omap_overlay_release(struct drm_atomic_state *s, struct omap_hw_overlay *overlay)
    115{
    116	/* Get the global state of the current atomic transaction */
    117	struct omap_global_state *state = omap_get_global_state(s);
    118	struct drm_plane **overlay_map = state->hwoverlay_to_plane;
    119
    120	if (!overlay)
    121		return;
    122
    123	if (WARN_ON(!overlay_map[overlay->idx]))
    124		return;
    125
    126	DBG("%s: release from plane %s", overlay->name, overlay_map[overlay->idx]->name);
    127
    128	overlay_map[overlay->idx] = NULL;
    129}
    130
    131/*
    132 * Update an overlay state that was attached to a plane before the current atomic state.
    133 * This should be called from the plane atomic_update() or atomic_disable(),
    134 * where an overlay association to a plane could have changed between the old and current
    135 * atomic state.
    136 */
    137void omap_overlay_update_state(struct omap_drm_private *priv,
    138			       struct omap_hw_overlay *overlay)
    139{
    140	struct omap_global_state *state = omap_get_existing_global_state(priv);
    141	struct drm_plane **overlay_map = state->hwoverlay_to_plane;
    142
    143	/* Check if this overlay is not used anymore, then disable it */
    144	if (!overlay_map[overlay->idx]) {
    145		DBG("%s: disabled", overlay->name);
    146
    147		/* disable the overlay */
    148		dispc_ovl_enable(priv->dispc, overlay->id, false);
    149	}
    150}
    151
    152static void omap_overlay_destroy(struct omap_hw_overlay *overlay)
    153{
    154	kfree(overlay);
    155}
    156
    157static struct omap_hw_overlay *omap_overlay_init(enum omap_plane_id overlay_id,
    158						 enum omap_overlay_caps caps)
    159{
    160	struct omap_hw_overlay *overlay;
    161
    162	overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
    163	if (!overlay)
    164		return ERR_PTR(-ENOMEM);
    165
    166	overlay->name = overlay_id_to_name[overlay_id];
    167	overlay->id = overlay_id;
    168	overlay->caps = caps;
    169
    170	return overlay;
    171}
    172
    173int omap_hwoverlays_init(struct omap_drm_private *priv)
    174{
    175	static const enum omap_plane_id hw_plane_ids[] = {
    176			OMAP_DSS_GFX, OMAP_DSS_VIDEO1,
    177			OMAP_DSS_VIDEO2, OMAP_DSS_VIDEO3,
    178	};
    179	u32 num_overlays = dispc_get_num_ovls(priv->dispc);
    180	enum omap_overlay_caps caps;
    181	int i, ret;
    182
    183	for (i = 0; i < num_overlays; i++) {
    184		struct omap_hw_overlay *overlay;
    185
    186		caps = dispc_ovl_get_caps(priv->dispc, hw_plane_ids[i]);
    187		overlay = omap_overlay_init(hw_plane_ids[i], caps);
    188		if (IS_ERR(overlay)) {
    189			ret = PTR_ERR(overlay);
    190			dev_err(priv->dev, "failed to construct overlay for %s (%d)\n",
    191				overlay_id_to_name[i], ret);
    192			omap_hwoverlays_destroy(priv);
    193			return ret;
    194		}
    195		overlay->idx = priv->num_ovls;
    196		priv->overlays[priv->num_ovls++] = overlay;
    197	}
    198
    199	return 0;
    200}
    201
    202void omap_hwoverlays_destroy(struct omap_drm_private *priv)
    203{
    204	int i;
    205
    206	for (i = 0; i < priv->num_ovls; i++) {
    207		omap_overlay_destroy(priv->overlays[i]);
    208		priv->overlays[i] = NULL;
    209	}
    210
    211	priv->num_ovls = 0;
    212}