Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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_fourcc.h>
 10#include <drm/drm_plane_helper.h>
 11#include <drm/drm_gem_framebuffer_helper.h>
 12
 13#include "mtk_drm_crtc.h"
 14#include "mtk_drm_ddp_comp.h"
 15#include "mtk_drm_drv.h"
 16#include "mtk_drm_fb.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_RGB565,
 24	DRM_FORMAT_UYVY,
 25	DRM_FORMAT_YUYV,
 26};
 27
 28static void mtk_plane_reset(struct drm_plane *plane)
 29{
 30	struct mtk_plane_state *state;
 31
 32	if (plane->state) {
 33		__drm_atomic_helper_plane_destroy_state(plane->state);
 34
 35		state = to_mtk_plane_state(plane->state);
 36		memset(state, 0, sizeof(*state));
 37	} else {
 38		state = kzalloc(sizeof(*state), GFP_KERNEL);
 39		if (!state)
 40			return;
 41		plane->state = &state->base;
 42	}
 43
 44	state->base.plane = plane;
 45	state->pending.format = DRM_FORMAT_RGB565;
 46}
 47
 48static struct drm_plane_state *mtk_plane_duplicate_state(struct drm_plane *plane)
 49{
 50	struct mtk_plane_state *old_state = to_mtk_plane_state(plane->state);
 51	struct mtk_plane_state *state;
 52
 53	state = kzalloc(sizeof(*state), GFP_KERNEL);
 54	if (!state)
 55		return NULL;
 56
 57	__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
 58
 59	WARN_ON(state->base.plane != plane);
 60
 61	state->pending = old_state->pending;
 62
 63	return &state->base;
 64}
 65
 66static void mtk_drm_plane_destroy_state(struct drm_plane *plane,
 67					struct drm_plane_state *state)
 68{
 69	__drm_atomic_helper_plane_destroy_state(state);
 70	kfree(to_mtk_plane_state(state));
 71}
 72
 73static const struct drm_plane_funcs mtk_plane_funcs = {
 74	.update_plane = drm_atomic_helper_update_plane,
 75	.disable_plane = drm_atomic_helper_disable_plane,
 76	.destroy = drm_plane_cleanup,
 77	.reset = mtk_plane_reset,
 78	.atomic_duplicate_state = mtk_plane_duplicate_state,
 79	.atomic_destroy_state = mtk_drm_plane_destroy_state,
 80};
 81
 82static int mtk_plane_atomic_check(struct drm_plane *plane,
 83				  struct drm_plane_state *state)
 84{
 85	struct drm_framebuffer *fb = state->fb;
 86	struct drm_crtc_state *crtc_state;
 87
 88	if (!fb)
 89		return 0;
 90
 91	if (!state->crtc)
 92		return 0;
 93
 94	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
 95	if (IS_ERR(crtc_state))
 96		return PTR_ERR(crtc_state);
 97
 98	return drm_atomic_helper_check_plane_state(state, crtc_state,
 99						   DRM_PLANE_HELPER_NO_SCALING,
100						   DRM_PLANE_HELPER_NO_SCALING,
101						   true, true);
102}
103
104static void mtk_plane_atomic_update(struct drm_plane *plane,
105				    struct drm_plane_state *old_state)
106{
107	struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
108	struct drm_crtc *crtc = plane->state->crtc;
109	struct drm_framebuffer *fb = plane->state->fb;
110	struct drm_gem_object *gem;
111	struct mtk_drm_gem_obj *mtk_gem;
112	unsigned int pitch, format;
113	dma_addr_t addr;
114
115	if (!crtc || WARN_ON(!fb))
116		return;
117
118	gem = fb->obj[0];
119	mtk_gem = to_mtk_gem_obj(gem);
120	addr = mtk_gem->dma_addr;
121	pitch = fb->pitches[0];
122	format = fb->format->format;
123
124	addr += (plane->state->src.x1 >> 16) * fb->format->cpp[0];
125	addr += (plane->state->src.y1 >> 16) * pitch;
126
127	state->pending.enable = true;
128	state->pending.pitch = pitch;
129	state->pending.format = format;
130	state->pending.addr = addr;
131	state->pending.x = plane->state->dst.x1;
132	state->pending.y = plane->state->dst.y1;
133	state->pending.width = drm_rect_width(&plane->state->dst);
134	state->pending.height = drm_rect_height(&plane->state->dst);
135	wmb(); /* Make sure the above parameters are set before update */
136	state->pending.dirty = true;
137}
138
139static void mtk_plane_atomic_disable(struct drm_plane *plane,
140				     struct drm_plane_state *old_state)
141{
142	struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
143
144	state->pending.enable = false;
145	wmb(); /* Make sure the above parameter is set before update */
146	state->pending.dirty = true;
147}
148
149static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
150	.prepare_fb = drm_gem_fb_prepare_fb,
151	.atomic_check = mtk_plane_atomic_check,
152	.atomic_update = mtk_plane_atomic_update,
153	.atomic_disable = mtk_plane_atomic_disable,
154};
155
156int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
157		   unsigned long possible_crtcs, enum drm_plane_type type)
158{
159	int err;
160
161	err = drm_universal_plane_init(dev, plane, possible_crtcs,
162				       &mtk_plane_funcs, formats,
163				       ARRAY_SIZE(formats), NULL, type, NULL);
164	if (err) {
165		DRM_ERROR("failed to initialize plane\n");
166		return err;
167	}
168
169	drm_plane_helper_add(plane, &mtk_plane_helper_funcs);
170
171	return 0;
172}