brintos

brintos / linux-shallow public Read only

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