Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 * Copyright (c) 2015 MediaTek Inc.
  3 * Author: CK Hu <ck.hu@mediatek.com>
  4 *
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License version 2 as
  7 * published by the Free Software Foundation.
  8 *
  9 * This program is distributed in the hope that it will be useful,
 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 * GNU General Public License for more details.
 13 */
 14
 15#include <drm/drmP.h>
 16#include <drm/drm_atomic.h>
 17#include <drm/drm_atomic_helper.h>
 18#include <drm/drm_plane_helper.h>
 19
 20#include "mtk_drm_crtc.h"
 21#include "mtk_drm_ddp_comp.h"
 22#include "mtk_drm_drv.h"
 23#include "mtk_drm_fb.h"
 24#include "mtk_drm_gem.h"
 25#include "mtk_drm_plane.h"
 26
 27static const u32 formats[] = {
 28	DRM_FORMAT_XRGB8888,
 29	DRM_FORMAT_ARGB8888,
 30	DRM_FORMAT_RGB565,
 31};
 32
 33static void mtk_plane_reset(struct drm_plane *plane)
 34{
 35	struct mtk_plane_state *state;
 36
 37	if (plane->state) {
 38		__drm_atomic_helper_plane_destroy_state(plane->state);
 39
 40		state = to_mtk_plane_state(plane->state);
 41		memset(state, 0, sizeof(*state));
 42	} else {
 43		state = kzalloc(sizeof(*state), GFP_KERNEL);
 44		if (!state)
 45			return;
 46		plane->state = &state->base;
 47	}
 48
 49	state->base.plane = plane;
 50	state->pending.format = DRM_FORMAT_RGB565;
 51}
 52
 53static struct drm_plane_state *mtk_plane_duplicate_state(struct drm_plane *plane)
 54{
 55	struct mtk_plane_state *old_state = to_mtk_plane_state(plane->state);
 56	struct mtk_plane_state *state;
 57
 58	state = kzalloc(sizeof(*state), GFP_KERNEL);
 59	if (!state)
 60		return NULL;
 61
 62	__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
 63
 64	WARN_ON(state->base.plane != plane);
 65
 66	state->pending = old_state->pending;
 67
 68	return &state->base;
 69}
 70
 71static void mtk_drm_plane_destroy_state(struct drm_plane *plane,
 72					struct drm_plane_state *state)
 73{
 74	__drm_atomic_helper_plane_destroy_state(state);
 75	kfree(to_mtk_plane_state(state));
 76}
 77
 78static const struct drm_plane_funcs mtk_plane_funcs = {
 79	.update_plane = drm_atomic_helper_update_plane,
 80	.disable_plane = drm_atomic_helper_disable_plane,
 81	.destroy = drm_plane_cleanup,
 82	.reset = mtk_plane_reset,
 83	.atomic_duplicate_state = mtk_plane_duplicate_state,
 84	.atomic_destroy_state = mtk_drm_plane_destroy_state,
 85};
 86
 87static int mtk_plane_atomic_check(struct drm_plane *plane,
 88				  struct drm_plane_state *state)
 89{
 90	struct drm_framebuffer *fb = state->fb;
 91	struct drm_crtc_state *crtc_state;
 92	struct drm_rect clip = { 0, };
 93
 94	if (!fb)
 95		return 0;
 96
 97	if (!mtk_fb_get_gem_obj(fb)) {
 98		DRM_DEBUG_KMS("buffer is null\n");
 99		return -EFAULT;
100	}
101
102	if (!state->crtc)
103		return 0;
104
105	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
106	if (IS_ERR(crtc_state))
107		return PTR_ERR(crtc_state);
108
109	clip.x2 = crtc_state->mode.hdisplay;
110	clip.y2 = crtc_state->mode.vdisplay;
111
112	return drm_plane_helper_check_state(state, &clip,
113					    DRM_PLANE_HELPER_NO_SCALING,
114					    DRM_PLANE_HELPER_NO_SCALING,
115					    true, true);
116}
117
118static void mtk_plane_atomic_update(struct drm_plane *plane,
119				    struct drm_plane_state *old_state)
120{
121	struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
122	struct drm_crtc *crtc = plane->state->crtc;
123	struct drm_framebuffer *fb = plane->state->fb;
124	struct drm_gem_object *gem;
125	struct mtk_drm_gem_obj *mtk_gem;
126	unsigned int pitch, format;
127	dma_addr_t addr;
128
129	if (!crtc || WARN_ON(!fb))
130		return;
131
132	gem = mtk_fb_get_gem_obj(fb);
133	mtk_gem = to_mtk_gem_obj(gem);
134	addr = mtk_gem->dma_addr;
135	pitch = fb->pitches[0];
136	format = fb->pixel_format;
137
138	addr += (plane->state->src.x1 >> 16) * drm_format_plane_cpp(format, 0);
139	addr += (plane->state->src.y1 >> 16) * pitch;
140
141	state->pending.enable = true;
142	state->pending.pitch = pitch;
143	state->pending.format = format;
144	state->pending.addr = addr;
145	state->pending.x = plane->state->dst.x1;
146	state->pending.y = plane->state->dst.y1;
147	state->pending.width = drm_rect_width(&plane->state->dst);
148	state->pending.height = drm_rect_height(&plane->state->dst);
149	wmb(); /* Make sure the above parameters are set before update */
150	state->pending.dirty = true;
151}
152
153static void mtk_plane_atomic_disable(struct drm_plane *plane,
154				     struct drm_plane_state *old_state)
155{
156	struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
157
158	state->pending.enable = false;
159	wmb(); /* Make sure the above parameter is set before update */
160	state->pending.dirty = true;
161}
162
163static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
164	.atomic_check = mtk_plane_atomic_check,
165	.atomic_update = mtk_plane_atomic_update,
166	.atomic_disable = mtk_plane_atomic_disable,
167};
168
169int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
170		   unsigned long possible_crtcs, enum drm_plane_type type)
171{
172	int err;
173
174	err = drm_universal_plane_init(dev, plane, possible_crtcs,
175				       &mtk_plane_funcs, formats,
176				       ARRAY_SIZE(formats), type, NULL);
177	if (err) {
178		DRM_ERROR("failed to initialize plane\n");
179		return err;
180	}
181
182	drm_plane_helper_add(plane, &mtk_plane_helper_funcs);
183
184	return 0;
185}