Linux Audio

Check our new training course

Loading...
v6.13.7
 1// SPDX-License-Identifier: GPL-2.0-only
 2/*
 3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
 4 * Author:Mark Yao <mark.yao@rock-chips.com>
 
 
 
 
 
 
 
 
 
 5 */
 6
 7#include <linux/kernel.h>
 8
 9#include <drm/drm.h>
 
10#include <drm/drm_atomic.h>
11#include <drm/drm_damage_helper.h>
12#include <drm/drm_fourcc.h>
13#include <drm/drm_framebuffer.h>
14#include <drm/drm_gem_framebuffer_helper.h>
15#include <drm/drm_probe_helper.h>
16
17#include "rockchip_drm_drv.h"
18#include "rockchip_drm_fb.h"
19#include "rockchip_drm_gem.h"
 
20
21static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
22	.destroy       = drm_gem_fb_destroy,
23	.create_handle = drm_gem_fb_create_handle,
24	.dirty	       = drm_atomic_helper_dirtyfb,
 
25};
26
27static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
28	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29};
30
31static struct drm_framebuffer *
32rockchip_fb_create(struct drm_device *dev, struct drm_file *file,
33		   const struct drm_mode_fb_cmd2 *mode_cmd)
34{
35	struct drm_afbc_framebuffer *afbc_fb;
36	const struct drm_format_info *info;
37	int ret;
 
38
39	info = drm_get_format_info(dev, mode_cmd);
40	if (!info)
41		return ERR_PTR(-ENOMEM);
42
43	afbc_fb = kzalloc(sizeof(*afbc_fb), GFP_KERNEL);
44	if (!afbc_fb)
45		return ERR_PTR(-ENOMEM);
 
46
47	ret = drm_gem_fb_init_with_funcs(dev, &afbc_fb->base, file, mode_cmd,
48					 &rockchip_drm_fb_funcs);
49	if (ret) {
50		kfree(afbc_fb);
 
 
51		return ERR_PTR(ret);
52	}
53
54	if (drm_is_afbc(mode_cmd->modifier[0])) {
55		int ret, i;
56
57		ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb);
58		if (ret) {
59			struct drm_gem_object **obj = afbc_fb->base.obj;
 
 
 
 
 
 
 
 
 
60
61			for (i = 0; i < info->num_planes; ++i)
62				drm_gem_object_put(obj[i]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
64			kfree(afbc_fb);
65			return ERR_PTR(ret);
 
 
 
 
 
 
66		}
 
 
 
 
 
 
 
67	}
68
69	return &afbc_fb->base;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70}
71
 
 
 
 
72static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
73	.fb_create = rockchip_fb_create,
 
74	.atomic_check = drm_atomic_helper_check,
75	.atomic_commit = drm_atomic_helper_commit,
76};
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78void rockchip_drm_mode_config_init(struct drm_device *dev)
79{
80	dev->mode_config.min_width = 0;
81	dev->mode_config.min_height = 0;
82
83	/*
84	 * set max width and height as default value(4096x4096).
85	 * this value would be used to check framebuffer size limitation
86	 * at drm_mode_addfb().
87	 */
88	dev->mode_config.max_width = 4096;
89	dev->mode_config.max_height = 4096;
90
91	dev->mode_config.funcs = &rockchip_drm_mode_config_funcs;
92	dev->mode_config.helper_private = &rockchip_mode_config_helpers;
93
94	dev->mode_config.normalize_zpos = true;
95}
v4.10.11
 
  1/*
  2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  3 * Author:Mark Yao <mark.yao@rock-chips.com>
  4 *
  5 * This software is licensed under the terms of the GNU General Public
  6 * License version 2, as published by the Free Software Foundation, and
  7 * may be copied, distributed, and modified under those terms.
  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 <linux/kernel.h>
 
 16#include <drm/drm.h>
 17#include <drm/drmP.h>
 18#include <drm/drm_atomic.h>
 19#include <drm/drm_fb_helper.h>
 20#include <drm/drm_crtc_helper.h>
 
 
 
 21
 22#include "rockchip_drm_drv.h"
 23#include "rockchip_drm_fb.h"
 24#include "rockchip_drm_gem.h"
 25#include "rockchip_drm_psr.h"
 26
 27#define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
 28
 29struct rockchip_drm_fb {
 30	struct drm_framebuffer fb;
 31	struct drm_gem_object *obj[ROCKCHIP_MAX_FB_BUFFER];
 32};
 33
 34struct drm_gem_object *rockchip_fb_get_gem_obj(struct drm_framebuffer *fb,
 35					       unsigned int plane)
 36{
 37	struct rockchip_drm_fb *rk_fb = to_rockchip_fb(fb);
 38
 39	if (plane >= ROCKCHIP_MAX_FB_BUFFER)
 40		return NULL;
 41
 42	return rk_fb->obj[plane];
 43}
 44
 45static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb)
 46{
 47	struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
 48	int i;
 49
 50	for (i = 0; i < ROCKCHIP_MAX_FB_BUFFER; i++)
 51		drm_gem_object_unreference_unlocked(rockchip_fb->obj[i]);
 52
 53	drm_framebuffer_cleanup(fb);
 54	kfree(rockchip_fb);
 55}
 56
 57static int rockchip_drm_fb_create_handle(struct drm_framebuffer *fb,
 58					 struct drm_file *file_priv,
 59					 unsigned int *handle)
 60{
 61	struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
 62
 63	return drm_gem_handle_create(file_priv,
 64				     rockchip_fb->obj[0], handle);
 65}
 66
 67static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
 68				 struct drm_file *file,
 69				 unsigned int flags, unsigned int color,
 70				 struct drm_clip_rect *clips,
 71				 unsigned int num_clips)
 72{
 73	rockchip_drm_psr_flush_all(fb->dev);
 74	return 0;
 75}
 76
 77static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
 78	.destroy	= rockchip_drm_fb_destroy,
 79	.create_handle	= rockchip_drm_fb_create_handle,
 80	.dirty		= rockchip_drm_fb_dirty,
 81};
 82
 83static struct rockchip_drm_fb *
 84rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
 85		  struct drm_gem_object **obj, unsigned int num_planes)
 86{
 87	struct rockchip_drm_fb *rockchip_fb;
 
 88	int ret;
 89	int i;
 90
 91	rockchip_fb = kzalloc(sizeof(*rockchip_fb), GFP_KERNEL);
 92	if (!rockchip_fb)
 93		return ERR_PTR(-ENOMEM);
 94
 95	drm_helper_mode_fill_fb_struct(&rockchip_fb->fb, mode_cmd);
 96
 97	for (i = 0; i < num_planes; i++)
 98		rockchip_fb->obj[i] = obj[i];
 99
100	ret = drm_framebuffer_init(dev, &rockchip_fb->fb,
101				   &rockchip_drm_fb_funcs);
102	if (ret) {
103		dev_err(dev->dev, "Failed to initialize framebuffer: %d\n",
104			ret);
105		kfree(rockchip_fb);
106		return ERR_PTR(ret);
107	}
108
109	return rockchip_fb;
110}
111
112static struct drm_framebuffer *
113rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
114			const struct drm_mode_fb_cmd2 *mode_cmd)
115{
116	struct rockchip_drm_fb *rockchip_fb;
117	struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];
118	struct drm_gem_object *obj;
119	unsigned int hsub;
120	unsigned int vsub;
121	int num_planes;
122	int ret;
123	int i;
124
125	hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
126	vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
127	num_planes = min(drm_format_num_planes(mode_cmd->pixel_format),
128			 ROCKCHIP_MAX_FB_BUFFER);
129
130	for (i = 0; i < num_planes; i++) {
131		unsigned int width = mode_cmd->width / (i ? hsub : 1);
132		unsigned int height = mode_cmd->height / (i ? vsub : 1);
133		unsigned int min_size;
134
135		obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
136		if (!obj) {
137			dev_err(dev->dev, "Failed to lookup GEM object\n");
138			ret = -ENXIO;
139			goto err_gem_object_unreference;
140		}
141
142		min_size = (height - 1) * mode_cmd->pitches[i] +
143			mode_cmd->offsets[i] +
144			width * drm_format_plane_cpp(mode_cmd->pixel_format, i);
145
146		if (obj->size < min_size) {
147			drm_gem_object_unreference_unlocked(obj);
148			ret = -EINVAL;
149			goto err_gem_object_unreference;
150		}
151		objs[i] = obj;
152	}
153
154	rockchip_fb = rockchip_fb_alloc(dev, mode_cmd, objs, i);
155	if (IS_ERR(rockchip_fb)) {
156		ret = PTR_ERR(rockchip_fb);
157		goto err_gem_object_unreference;
158	}
159
160	return &rockchip_fb->fb;
161
162err_gem_object_unreference:
163	for (i--; i >= 0; i--)
164		drm_gem_object_unreference_unlocked(objs[i]);
165	return ERR_PTR(ret);
166}
167
168static void rockchip_drm_output_poll_changed(struct drm_device *dev)
169{
170	struct rockchip_drm_private *private = dev->dev_private;
171	struct drm_fb_helper *fb_helper = &private->fbdev_helper;
172
173	if (fb_helper)
174		drm_fb_helper_hotplug_event(fb_helper);
175}
176
177static void
178rockchip_atomic_commit_tail(struct drm_atomic_state *state)
179{
180	struct drm_device *dev = state->dev;
181
182	drm_atomic_helper_commit_modeset_disables(dev, state);
183
184	drm_atomic_helper_commit_modeset_enables(dev, state);
185
186	drm_atomic_helper_commit_planes(dev, state,
187					DRM_PLANE_COMMIT_ACTIVE_ONLY);
188
189	drm_atomic_helper_commit_hw_done(state);
190
191	drm_atomic_helper_wait_for_vblanks(dev, state);
192
193	drm_atomic_helper_cleanup_planes(dev, state);
194}
195
196static struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
197	.atomic_commit_tail = rockchip_atomic_commit_tail,
198};
199
200static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
201	.fb_create = rockchip_user_fb_create,
202	.output_poll_changed = rockchip_drm_output_poll_changed,
203	.atomic_check = drm_atomic_helper_check,
204	.atomic_commit = drm_atomic_helper_commit,
205};
206
207struct drm_framebuffer *
208rockchip_drm_framebuffer_init(struct drm_device *dev,
209			      const struct drm_mode_fb_cmd2 *mode_cmd,
210			      struct drm_gem_object *obj)
211{
212	struct rockchip_drm_fb *rockchip_fb;
213
214	rockchip_fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1);
215	if (IS_ERR(rockchip_fb))
216		return NULL;
217
218	return &rockchip_fb->fb;
219}
220
221void rockchip_drm_mode_config_init(struct drm_device *dev)
222{
223	dev->mode_config.min_width = 0;
224	dev->mode_config.min_height = 0;
225
226	/*
227	 * set max width and height as default value(4096x4096).
228	 * this value would be used to check framebuffer size limitation
229	 * at drm_mode_addfb().
230	 */
231	dev->mode_config.max_width = 4096;
232	dev->mode_config.max_height = 4096;
233
234	dev->mode_config.funcs = &rockchip_drm_mode_config_funcs;
235	dev->mode_config.helper_private = &rockchip_mode_config_helpers;
 
 
236}