forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
kernel/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
....@@ -1,364 +1,177 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
34 * 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.
135 */
146
157 #include <linux/kernel.h>
8
+#include <linux/devfreq.h>
9
+
1610 #include <drm/drm.h>
17
-#include <drm/drmP.h>
1811 #include <drm/drm_atomic.h>
12
+#include <drm/drm_damage_helper.h>
1913 #include <drm/drm_fb_helper.h>
20
-#include <drm/drm_crtc_helper.h>
14
+#include <drm/drm_fourcc.h>
2115 #include <drm/drm_gem_framebuffer_helper.h>
22
-#include <linux/memblock.h>
16
+#include <drm/drm_probe_helper.h>
2317 #include <soc/rockchip/rockchip_dmc.h>
2418
2519 #include "rockchip_drm_drv.h"
2620 #include "rockchip_drm_fb.h"
2721 #include "rockchip_drm_gem.h"
28
-#include "rockchip_drm_psr.h"
22
+#include "rockchip_drm_logo.h"
2923
30
-bool rockchip_fb_is_logo(struct drm_framebuffer *fb)
24
+static bool is_rockchip_logo_fb(struct drm_framebuffer *fb)
3125 {
32
- struct rockchip_drm_fb *rk_fb = to_rockchip_fb(fb);
33
-
34
- return rk_fb && rk_fb->logo;
26
+ return fb->flags & ROCKCHIP_DRM_MODE_LOGO_FB ? true : false;
3527 }
3628
37
-dma_addr_t rockchip_fb_get_dma_addr(struct drm_framebuffer *fb,
38
- unsigned int plane)
29
+static void __rockchip_drm_fb_destroy(struct drm_framebuffer *fb)
3930 {
40
- struct rockchip_drm_fb *rk_fb = to_rockchip_fb(fb);
31
+ int i = 0;
4132
42
- if (WARN_ON(plane >= ROCKCHIP_MAX_FB_BUFFER))
43
- return 0;
33
+ drm_framebuffer_cleanup(fb);
4434
45
- return rk_fb->dma_addr[plane];
35
+ if (is_rockchip_logo_fb(fb)) {
36
+ struct rockchip_drm_logo_fb *rockchip_logo_fb = to_rockchip_logo_fb(fb);
37
+
38
+#ifndef MODULE
39
+ rockchip_free_loader_memory(fb->dev);
40
+#endif
41
+ drm_gem_object_release(rockchip_logo_fb->fb.obj[0]);
42
+ kfree(rockchip_logo_fb);
43
+ } else {
44
+ for (i = 0; i < 4; i++) {
45
+ if (fb->obj[i])
46
+ drm_gem_object_put(fb->obj[i]);
47
+ }
48
+
49
+ kfree(fb);
50
+ }
4651 }
4752
48
-void *rockchip_fb_get_kvaddr(struct drm_framebuffer *fb, unsigned int plane)
53
+static void rockchip_drm_fb_destroy_work(struct work_struct *work)
4954 {
50
- struct rockchip_drm_fb *rk_fb = to_rockchip_fb(fb);
55
+ struct rockchip_drm_logo_fb *fb;
5156
52
- if (WARN_ON(plane >= ROCKCHIP_MAX_FB_BUFFER))
53
- return 0;
57
+ fb = container_of(to_delayed_work(work), struct rockchip_drm_logo_fb, destroy_work);
5458
55
- return rk_fb->kvaddr[plane];
59
+ __rockchip_drm_fb_destroy(&fb->fb);
5660 }
5761
5862 static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb)
5963 {
60
- struct drm_gem_object *obj;
61
- int i;
62
- struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
6364
64
- for (i = 0; i < ROCKCHIP_MAX_FB_BUFFER; i++) {
65
- obj = rockchip_fb->obj[i];
66
- if (obj)
67
- drm_gem_object_unreference_unlocked(obj);
65
+ if (is_rockchip_logo_fb(fb)) {
66
+ struct rockchip_drm_logo_fb *rockchip_logo_fb = to_rockchip_logo_fb(fb);
67
+
68
+ schedule_delayed_work(&rockchip_logo_fb->destroy_work, HZ);
69
+ } else {
70
+ __rockchip_drm_fb_destroy(fb);
6871 }
69
-
70
-#ifndef MODULE
71
- if (rockchip_fb->logo)
72
- rockchip_free_loader_memory(fb->dev);
73
-#else
74
- WARN_ON(rockchip_fb->logo);
75
-#endif
76
-
77
- drm_framebuffer_cleanup(fb);
78
- kfree(rockchip_fb);
7972 }
8073
81
-static int rockchip_drm_fb_create_handle(struct drm_framebuffer *fb,
82
- struct drm_file *file_priv,
83
- unsigned int *handle)
74
+static int rockchip_drm_gem_fb_create_handle(struct drm_framebuffer *fb,
75
+ struct drm_file *file,
76
+ unsigned int *handle)
8477 {
85
- struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
86
-
87
- if (rockchip_fb_is_logo(fb))
78
+ if (is_rockchip_logo_fb(fb))
8879 return -EOPNOTSUPP;
8980
90
- return drm_gem_handle_create(file_priv,
91
- rockchip_fb->obj[0], handle);
92
-}
93
-
94
-static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
95
- struct drm_file *file,
96
- unsigned int flags, unsigned int color,
97
- struct drm_clip_rect *clips,
98
- unsigned int num_clips)
99
-{
100
- rockchip_drm_psr_flush_all(fb->dev);
101
- return 0;
81
+ return drm_gem_fb_create_handle(fb, file, handle);
10282 }
10383
10484 static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
10585 .destroy = rockchip_drm_fb_destroy,
106
- .create_handle = rockchip_drm_fb_create_handle,
107
- .dirty = rockchip_drm_fb_dirty,
86
+ .create_handle = rockchip_drm_gem_fb_create_handle,
10887 };
10988
11089 struct drm_framebuffer *
11190 rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
112
- struct drm_gem_object **obj, struct rockchip_logo *logo,
113
- unsigned int num_planes)
114
-{
115
- struct rockchip_drm_fb *rockchip_fb;
116
- struct rockchip_gem_object *rk_obj;
117
- int ret = 0;
118
- int i;
119
-
120
- rockchip_fb = kzalloc(sizeof(*rockchip_fb), GFP_KERNEL);
121
- if (!rockchip_fb)
122
- return ERR_PTR(-ENOMEM);
123
-
124
- drm_helper_mode_fill_fb_struct(dev, &rockchip_fb->fb, mode_cmd);
125
-
126
- ret = drm_framebuffer_init(dev, &rockchip_fb->fb,
127
- &rockchip_drm_fb_funcs);
128
- if (ret) {
129
- dev_err(dev->dev, "Failed to initialize framebuffer: %d\n",
130
- ret);
131
- goto err_free_fb;
132
- }
133
-
134
- if (obj) {
135
- for (i = 0; i < num_planes; i++)
136
- rockchip_fb->obj[i] = obj[i];
137
-
138
- for (i = 0; i < num_planes; i++) {
139
- rk_obj = to_rockchip_obj(obj[i]);
140
- rockchip_fb->dma_addr[i] = rk_obj->dma_addr;
141
- rockchip_fb->kvaddr[i] = rk_obj->kvaddr;
142
- }
143
-#ifndef MODULE
144
- } else if (logo) {
145
- rockchip_fb->dma_addr[0] = logo->dma_addr;
146
- rockchip_fb->kvaddr[0] = logo->kvaddr;
147
- rockchip_fb->logo = logo;
148
- logo->count++;
149
-#endif
150
- } else {
151
- ret = -EINVAL;
152
- dev_err(dev->dev, "Failed to find available buffer\n");
153
- goto err_deinit_drm_fb;
154
- }
155
-
156
- return &rockchip_fb->fb;
157
-
158
-err_deinit_drm_fb:
159
- drm_framebuffer_cleanup(&rockchip_fb->fb);
160
-err_free_fb:
161
- kfree(rockchip_fb);
162
- return ERR_PTR(ret);
163
-}
164
-
165
-static struct drm_framebuffer *
166
-rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
167
- const struct drm_mode_fb_cmd2 *mode_cmd)
91
+ struct drm_gem_object **obj, unsigned int num_planes)
16892 {
16993 struct drm_framebuffer *fb;
170
- struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];
171
- struct drm_gem_object *obj;
172
- unsigned int hsub;
173
- unsigned int vsub;
174
- int num_planes;
17594 int ret;
17695 int i;
17796
178
- hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
179
- vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
180
- num_planes = min(drm_format_num_planes(mode_cmd->pixel_format),
181
- ROCKCHIP_MAX_FB_BUFFER);
97
+ fb = kzalloc(sizeof(*fb), GFP_KERNEL);
98
+ if (!fb)
99
+ return ERR_PTR(-ENOMEM);
182100
183
- for (i = 0; i < num_planes; ++i) {
184
- if (mode_cmd->pitches[i] % 4) {
185
- DRM_DEV_ERROR_RATELIMITED(dev->dev,
186
- "fb pitch[%d] must be 4 byte aligned: %d\n", i, mode_cmd->pitches[i]);
187
- return ERR_PTR(-EINVAL);
188
- }
189
- }
101
+ drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
190102
191
- for (i = 0; i < num_planes; i++) {
192
- unsigned int width = mode_cmd->width / (i ? hsub : 1);
193
- unsigned int height = mode_cmd->height / (i ? vsub : 1);
194
- unsigned int min_size;
103
+ for (i = 0; i < num_planes; i++)
104
+ fb->obj[i] = obj[i];
195105
196
- obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
197
- if (!obj) {
198
- DRM_DEV_ERROR(dev->dev,
199
- "Failed to lookup GEM object\n");
200
- ret = -ENXIO;
201
- goto err_gem_object_unreference;
202
- }
203
-
204
- min_size = (height - 1) * mode_cmd->pitches[i] +
205
- mode_cmd->offsets[i] +
206
- width * drm_format_plane_cpp(mode_cmd->pixel_format, i);
207
-
208
- if (obj->size < min_size) {
209
- drm_gem_object_put_unlocked(obj);
210
- ret = -EINVAL;
211
- goto err_gem_object_unreference;
212
- }
213
- objs[i] = obj;
214
- }
215
-
216
- fb = rockchip_fb_alloc(dev, mode_cmd, objs, NULL, i);
217
- if (IS_ERR(fb)) {
218
- ret = PTR_ERR(fb);
219
- goto err_gem_object_unreference;
106
+ ret = drm_framebuffer_init(dev, fb, &rockchip_drm_fb_funcs);
107
+ if (ret) {
108
+ DRM_DEV_ERROR(dev->dev,
109
+ "Failed to initialize framebuffer: %d\n",
110
+ ret);
111
+ kfree(fb);
112
+ return ERR_PTR(ret);
220113 }
221114
222115 return fb;
223
-
224
-err_gem_object_unreference:
225
- for (i--; i >= 0; i--)
226
- drm_gem_object_put_unlocked(objs[i]);
227
- return ERR_PTR(ret);
228116 }
229117
230
-static void rockchip_drm_output_poll_changed(struct drm_device *dev)
118
+struct drm_framebuffer *
119
+rockchip_drm_logo_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
120
+ struct rockchip_logo *logo)
231121 {
232
- struct rockchip_drm_private *private = dev->dev_private;
233
- struct drm_fb_helper *fb_helper = private->fbdev_helper;
122
+ int ret = 0;
123
+ struct rockchip_drm_logo_fb *rockchip_logo_fb;
124
+ struct drm_framebuffer *fb;
234125
235
- if (fb_helper && dev->mode_config.poll_enabled && !private->loader_protect)
236
- drm_fb_helper_hotplug_event(fb_helper);
126
+ rockchip_logo_fb = kzalloc(sizeof(*rockchip_logo_fb), GFP_KERNEL);
127
+ if (!rockchip_logo_fb)
128
+ return ERR_PTR(-ENOMEM);
129
+ fb = &rockchip_logo_fb->fb;
130
+
131
+ drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
132
+
133
+ ret = drm_framebuffer_init(dev, fb, &rockchip_drm_fb_funcs);
134
+ if (ret) {
135
+ DRM_DEV_ERROR(dev->dev,
136
+ "Failed to initialize rockchip logo fb: %d\n",
137
+ ret);
138
+ kfree(rockchip_logo_fb);
139
+ return ERR_PTR(ret);
140
+ }
141
+
142
+ fb->flags |= ROCKCHIP_DRM_MODE_LOGO_FB;
143
+ rockchip_logo_fb->logo = logo;
144
+ rockchip_logo_fb->fb.obj[0] = &rockchip_logo_fb->rk_obj.base;
145
+ drm_gem_object_init(dev, rockchip_logo_fb->fb.obj[0], PAGE_ALIGN(logo->size));
146
+ rockchip_logo_fb->rk_obj.dma_addr = logo->dma_addr;
147
+ rockchip_logo_fb->rk_obj.kvaddr = logo->kvaddr;
148
+ logo->count++;
149
+ INIT_DELAYED_WORK(&rockchip_logo_fb->destroy_work, rockchip_drm_fb_destroy_work);
150
+ return &rockchip_logo_fb->fb;
237151 }
238152
239153 static int rockchip_drm_bandwidth_atomic_check(struct drm_device *dev,
240154 struct drm_atomic_state *state,
241
- size_t *line_bw_mbyte,
242
- size_t *frame_bw_mbyte,
243
- unsigned int *plane_num)
155
+ struct dmcfreq_vop_info *vop_bw_info)
244156 {
245157 struct rockchip_drm_private *priv = dev->dev_private;
246
- struct drm_crtc_state *crtc_state;
158
+ struct drm_crtc_state *old_crtc_state;
247159 const struct rockchip_crtc_funcs *funcs;
248160 struct drm_crtc *crtc;
249
- int i, ret = 0;
161
+ int i;
250162
251
- *line_bw_mbyte = 0;
252
- *frame_bw_mbyte = 0;
253
- *plane_num = 0;
254
- for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
163
+ vop_bw_info->line_bw_mbyte = 0;
164
+ vop_bw_info->frame_bw_mbyte = 0;
165
+ vop_bw_info->plane_num = 0;
166
+
167
+ for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
255168 funcs = priv->crtc_funcs[drm_crtc_index(crtc)];
256169
257170 if (funcs && funcs->bandwidth)
258
- *line_bw_mbyte += funcs->bandwidth(crtc, crtc_state,
259
- frame_bw_mbyte,
260
- plane_num);
171
+ funcs->bandwidth(crtc, old_crtc_state, vop_bw_info);
261172 }
262173
263
- /*
264
- * Check ddr frequency support here here.
265
- */
266
- if (priv->dmc_support && !priv->devfreq) {
267
- priv->devfreq = devfreq_get_devfreq_by_phandle(dev->dev, 0);
268
- if (IS_ERR(priv->devfreq))
269
- priv->devfreq = NULL;
270
- }
271
-
272
- if (priv->devfreq)
273
- ret = rockchip_dmcfreq_vop_bandwidth_request(priv->devfreq,
274
- *line_bw_mbyte);
275
-
276
- return ret;
277
-}
278
-
279
-static void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state)
280
-{
281
- struct drm_crtc *crtc;
282
- struct drm_crtc_state *crtc_state;
283
- struct drm_encoder *encoder;
284
- u32 encoder_mask = 0;
285
- int i;
286
-
287
- for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
288
- encoder_mask |= crtc_state->encoder_mask;
289
- encoder_mask |= crtc->state->encoder_mask;
290
- }
291
-
292
- drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
293
- rockchip_drm_psr_inhibit_get(encoder);
294
-}
295
-
296
-static void
297
-rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state)
298
-{
299
- struct drm_crtc *crtc;
300
- struct drm_crtc_state *crtc_state;
301
- struct drm_encoder *encoder;
302
- u32 encoder_mask = 0;
303
- int i;
304
-
305
- for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
306
- encoder_mask |= crtc_state->encoder_mask;
307
- encoder_mask |= crtc->state->encoder_mask;
308
- }
309
-
310
- drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
311
- rockchip_drm_psr_inhibit_put(encoder);
312
-}
313
-
314
-static void
315
-rockchip_drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
316
- struct drm_atomic_state *old_state)
317
-{
318
- struct drm_crtc *crtc;
319
- struct drm_crtc_state *old_crtc_state, *new_crtc_state;
320
- int i, ret;
321
- unsigned int crtc_mask = 0;
322
- struct rockchip_crtc_state *s;
323
-
324
- /*
325
- * Legacy cursor ioctls are completely unsynced, and userspace
326
- * relies on that (by doing tons of cursor updates).
327
- */
328
- if (old_state->legacy_cursor_update)
329
- return;
330
-
331
- for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
332
- if (!new_crtc_state->active)
333
- continue;
334
-
335
- ret = drm_crtc_vblank_get(crtc);
336
- if (ret != 0)
337
- continue;
338
-
339
- crtc_mask |= drm_crtc_mask(crtc);
340
- old_state->crtcs[i].last_vblank_count =
341
- drm_crtc_vblank_count(crtc);
342
- }
343
-
344
- for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
345
- if (!(crtc_mask & drm_crtc_mask(crtc)))
346
- continue;
347
-
348
- ret = wait_event_timeout(dev->vblank[i].queue,
349
- old_state->crtcs[i].last_vblank_count !=
350
- drm_crtc_vblank_count(crtc),
351
- msecs_to_jiffies(50));
352
-
353
- s = to_rockchip_crtc_state(crtc->state);
354
-
355
- if (!s->mode_update && !ret)
356
- DRM_WARN("[CRTC:%d:%s] state:%d, vblank wait timed out\n",
357
- crtc->base.id, crtc->name, old_crtc_state->active);
358
-
359
- drm_crtc_vblank_put(crtc);
360
- s->mode_update = false;
361
- }
174
+ return 0;
362175 }
363176
364177 static void drm_atomic_helper_connector_commit(struct drm_device *dev,
....@@ -379,181 +192,110 @@
379192 }
380193 }
381194
382
-static void
383
-rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
195
+/**
196
+ * rockchip_drm_atomic_helper_commit_tail_rpm - commit atomic update to hardware
197
+ * @old_state: new modeset state to be committed
198
+ *
199
+ * This is an alternative implementation for the
200
+ * &drm_mode_config_helper_funcs.atomic_commit_tail hook, for drivers
201
+ * that support runtime_pm or need the CRTC to be enabled to perform a
202
+ * commit. Otherwise, one should use the default implementation
203
+ * drm_atomic_helper_commit_tail().
204
+ */
205
+static void rockchip_drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
384206 {
385207 struct drm_device *dev = old_state->dev;
386
-
387
- rockchip_drm_psr_inhibit_get_state(old_state);
208
+ struct rockchip_drm_private *prv = dev->dev_private;
209
+ struct dmcfreq_vop_info vop_bw_info;
388210
389211 drm_atomic_helper_commit_modeset_disables(dev, old_state);
390212
391213 drm_atomic_helper_commit_modeset_enables(dev, old_state);
392214
393
- drm_atomic_helper_commit_planes(dev, old_state,
394
- DRM_PLANE_COMMIT_ACTIVE_ONLY);
215
+ rockchip_drm_bandwidth_atomic_check(dev, old_state, &vop_bw_info);
395216
396
- rockchip_drm_psr_inhibit_put_state(old_state);
217
+ rockchip_dmcfreq_vop_bandwidth_update(&vop_bw_info);
218
+
219
+ mutex_lock(&prv->ovl_lock);
220
+ drm_atomic_helper_commit_planes(dev, old_state, DRM_PLANE_COMMIT_ACTIVE_ONLY);
221
+ mutex_unlock(&prv->ovl_lock);
222
+
223
+ drm_atomic_helper_fake_vblank(old_state);
397224
398225 drm_atomic_helper_connector_commit(dev, old_state);
399226
400227 drm_atomic_helper_commit_hw_done(old_state);
401228
402
- rockchip_drm_atomic_helper_wait_for_vblanks(dev, old_state);
229
+ drm_atomic_helper_wait_for_vblanks(dev, old_state);
403230
404231 drm_atomic_helper_cleanup_planes(dev, old_state);
405232 }
406233
407234 static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
408
- .atomic_commit_tail = rockchip_atomic_helper_commit_tail_rpm,
235
+ .atomic_commit_tail = rockchip_drm_atomic_helper_commit_tail_rpm,
409236 };
410237
411
-static void
412
-rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit)
238
+static struct drm_framebuffer *
239
+rockchip_fb_create(struct drm_device *dev, struct drm_file *file,
240
+ const struct drm_mode_fb_cmd2 *mode_cmd)
413241 {
414
- struct drm_atomic_state *state = commit->state;
415
- struct drm_device *dev = commit->dev;
416
- struct rockchip_drm_private *prv = dev->dev_private;
417
- size_t line_bw_mbyte = commit->line_bw_mbyte;
418
- size_t frame_bw_mbyte = commit->frame_bw_mbyte;
419
- unsigned int plane_num = commit->plane_num;
242
+ struct drm_afbc_framebuffer *afbc_fb;
243
+ const struct drm_format_info *info;
244
+ int ret, i;
420245
421
- /*
422
- * TODO: do fence wait here.
423
- */
246
+ info = drm_get_format_info(dev, mode_cmd);
247
+ if (!info)
248
+ return ERR_PTR(-ENOMEM);
424249
425
- /*
426
- * Rockchip crtc support runtime PM, can't update display planes
427
- * when crtc is disabled.
428
- *
429
- * drm_atomic_helper_commit comments detail that:
430
- * For drivers supporting runtime PM the recommended sequence is
431
- *
432
- * drm_atomic_helper_commit_modeset_disables(dev, state);
433
- *
434
- * drm_atomic_helper_commit_modeset_enables(dev, state);
435
- *
436
- * drm_atomic_helper_commit_planes(dev, state, true);
437
- *
438
- * See the kerneldoc entries for these three functions for more details.
439
- */
440
- drm_atomic_helper_wait_for_dependencies(state);
441
-
442
- rockchip_drm_psr_inhibit_get_state(state);
443
-
444
- drm_atomic_helper_commit_modeset_disables(dev, state);
445
-
446
- drm_atomic_helper_commit_modeset_enables(dev, state);
447
-
448
- if (prv->dmc_support && !prv->devfreq) {
449
- prv->devfreq = devfreq_get_devfreq_by_phandle(dev->dev, 0);
450
- if (IS_ERR(prv->devfreq))
451
- prv->devfreq = NULL;
250
+ for (i = 0; i < info->num_planes; ++i) {
251
+ if (mode_cmd->pitches[i] % 4) {
252
+ DRM_DEV_ERROR_RATELIMITED(dev->dev,
253
+ "fb pitch[%d] must be 4 byte aligned: %d\n", i, mode_cmd->pitches[i]);
254
+ return ERR_PTR(-EINVAL);
255
+ }
452256 }
453
- if (prv->devfreq)
454
- rockchip_dmcfreq_vop_bandwidth_update(prv->devfreq, line_bw_mbyte, frame_bw_mbyte,
455
- plane_num);
456257
457
- mutex_lock(&prv->ovl_lock);
458
- drm_atomic_helper_commit_planes(dev, state, true);
459
- mutex_unlock(&prv->ovl_lock);
258
+ afbc_fb = kzalloc(sizeof(*afbc_fb), GFP_KERNEL);
259
+ if (!afbc_fb)
260
+ return ERR_PTR(-ENOMEM);
460261
461
- rockchip_drm_psr_inhibit_put_state(state);
262
+ ret = drm_gem_fb_init_with_funcs(dev, &afbc_fb->base, file, mode_cmd,
263
+ &rockchip_drm_fb_funcs);
264
+ if (ret) {
265
+ kfree(afbc_fb);
266
+ return ERR_PTR(ret);
267
+ }
462268
463
- drm_atomic_helper_connector_commit(dev, state);
269
+ if (drm_is_afbc(mode_cmd->modifier[0])) {
270
+ ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb);
271
+ if (ret) {
272
+ struct drm_gem_object **obj = afbc_fb->base.obj;
464273
465
- drm_atomic_helper_commit_hw_done(state);
274
+ for (i = 0; i < info->num_planes; ++i)
275
+ drm_gem_object_put(obj[i]);
466276
467
- rockchip_drm_atomic_helper_wait_for_vblanks(dev, state);
277
+ kfree(afbc_fb);
278
+ return ERR_PTR(ret);
279
+ }
280
+ }
468281
469
- drm_atomic_helper_cleanup_planes(dev, state);
470
-
471
- drm_atomic_helper_commit_cleanup_done(state);
472
-
473
- drm_atomic_state_put(state);
474
-
475
- kfree(commit);
282
+ return &afbc_fb->base;
476283 }
477284
478
-void rockchip_drm_atomic_work(struct work_struct *work)
479
-{
480
- struct rockchip_drm_private *private = container_of(work,
481
- struct rockchip_drm_private, commit_work);
482
-
483
- rockchip_atomic_commit_complete(private->commit);
484
- private->commit = NULL;
485
-}
486
-
487
-static int rockchip_drm_atomic_commit(struct drm_device *dev,
488
- struct drm_atomic_state *state,
489
- bool async)
285
+static void rockchip_drm_output_poll_changed(struct drm_device *dev)
490286 {
491287 struct rockchip_drm_private *private = dev->dev_private;
492
- struct rockchip_atomic_commit *commit;
493
- size_t line_bw_mbyte;
494
- size_t frame_bw_mbyte;
495
- unsigned int plane_num;
496
- int ret;
288
+ struct drm_fb_helper *fb_helper = private->fbdev_helper;
497289
498
- ret = drm_atomic_helper_setup_commit(state, false);
499
- if (ret)
500
- return ret;
501
-
502
- ret = drm_atomic_helper_prepare_planes(dev, state);
503
- if (ret)
504
- return ret;
505
-
506
- ret = rockchip_drm_bandwidth_atomic_check(dev, state,
507
- &line_bw_mbyte,
508
- &frame_bw_mbyte,
509
- &plane_num);
510
- if (ret) {
511
- /*
512
- * TODO:
513
- * Just report bandwidth can't support now.
514
- */
515
- DRM_ERROR("vop bandwidth too large %zd\n", line_bw_mbyte);
516
- }
517
-
518
- ret = drm_atomic_helper_swap_state(state, true);
519
- if (ret < 0) {
520
- DRM_ERROR("swap atomic state for %s failed: %d\n", current->comm, ret);
521
- drm_atomic_helper_cleanup_planes(dev, state);
522
- return ret;
523
- }
524
-
525
- drm_atomic_state_get(state);
526
- commit = kmalloc(sizeof(*commit), GFP_KERNEL);
527
- if (!commit)
528
- return -ENOMEM;
529
-
530
- commit->dev = dev;
531
- commit->state = state;
532
- commit->line_bw_mbyte = line_bw_mbyte;
533
- commit->frame_bw_mbyte = frame_bw_mbyte;
534
- commit->plane_num = plane_num;
535
-
536
- if (async) {
537
- mutex_lock(&private->commit_lock);
538
-
539
- flush_work(&private->commit_work);
540
- WARN_ON(private->commit);
541
- private->commit = commit;
542
- schedule_work(&private->commit_work);
543
-
544
- mutex_unlock(&private->commit_lock);
545
- } else {
546
- rockchip_atomic_commit_complete(commit);
547
- }
548
-
549
- return 0;
290
+ if (fb_helper && dev->mode_config.poll_enabled && !private->loader_protect)
291
+ drm_fb_helper_hotplug_event(fb_helper);
550292 }
551293
552294 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
553
- .fb_create = rockchip_user_fb_create,
295
+ .fb_create = rockchip_fb_create,
554296 .output_poll_changed = rockchip_drm_output_poll_changed,
555297 .atomic_check = drm_atomic_helper_check,
556
- .atomic_commit = rockchip_drm_atomic_commit,
298
+ .atomic_commit = drm_atomic_helper_commit,
557299 };
558300
559301 struct drm_framebuffer *
....@@ -563,7 +305,7 @@
563305 {
564306 struct drm_framebuffer *fb;
565307
566
- fb = rockchip_fb_alloc(dev, mode_cmd, &obj, NULL, 1);
308
+ fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1);
567309 if (IS_ERR(fb))
568310 return ERR_CAST(fb);
569311
....@@ -576,12 +318,12 @@
576318 dev->mode_config.min_height = 0;
577319
578320 /*
579
- * set max width and height as default value(4096x4096).
321
+ * set max width and height as default value(16384x16384).
580322 * this value would be used to check framebuffer size limitation
581323 * at drm_mode_addfb().
582324 */
583
- dev->mode_config.max_width = 8192;
584
- dev->mode_config.max_height = 8192;
325
+ dev->mode_config.max_width = 16384;
326
+ dev->mode_config.max_height = 16384;
585327 dev->mode_config.async_page_flip = true;
586328
587329 dev->mode_config.funcs = &rockchip_drm_mode_config_funcs;