hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
....@@ -1,364 +1,178 @@
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
+ vop_bw_info->plane_num_4k = 0;
167
+
168
+ for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
255169 funcs = priv->crtc_funcs[drm_crtc_index(crtc)];
256170
257171 if (funcs && funcs->bandwidth)
258
- *line_bw_mbyte += funcs->bandwidth(crtc, crtc_state,
259
- frame_bw_mbyte,
260
- plane_num);
172
+ funcs->bandwidth(crtc, old_crtc_state, vop_bw_info);
261173 }
262174
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
- }
175
+ return 0;
362176 }
363177
364178 static void drm_atomic_helper_connector_commit(struct drm_device *dev,
....@@ -379,181 +193,110 @@
379193 }
380194 }
381195
382
-static void
383
-rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
196
+/**
197
+ * rockchip_drm_atomic_helper_commit_tail_rpm - commit atomic update to hardware
198
+ * @old_state: new modeset state to be committed
199
+ *
200
+ * This is an alternative implementation for the
201
+ * &drm_mode_config_helper_funcs.atomic_commit_tail hook, for drivers
202
+ * that support runtime_pm or need the CRTC to be enabled to perform a
203
+ * commit. Otherwise, one should use the default implementation
204
+ * drm_atomic_helper_commit_tail().
205
+ */
206
+static void rockchip_drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
384207 {
385208 struct drm_device *dev = old_state->dev;
386
-
387
- rockchip_drm_psr_inhibit_get_state(old_state);
209
+ struct rockchip_drm_private *prv = dev->dev_private;
210
+ struct dmcfreq_vop_info vop_bw_info;
388211
389212 drm_atomic_helper_commit_modeset_disables(dev, old_state);
390213
391214 drm_atomic_helper_commit_modeset_enables(dev, old_state);
392215
393
- drm_atomic_helper_commit_planes(dev, old_state,
394
- DRM_PLANE_COMMIT_ACTIVE_ONLY);
216
+ rockchip_drm_bandwidth_atomic_check(dev, old_state, &vop_bw_info);
395217
396
- rockchip_drm_psr_inhibit_put_state(old_state);
218
+ rockchip_dmcfreq_vop_bandwidth_update(&vop_bw_info);
219
+
220
+ mutex_lock(&prv->ovl_lock);
221
+ drm_atomic_helper_commit_planes(dev, old_state, DRM_PLANE_COMMIT_ACTIVE_ONLY);
222
+ mutex_unlock(&prv->ovl_lock);
223
+
224
+ drm_atomic_helper_fake_vblank(old_state);
397225
398226 drm_atomic_helper_connector_commit(dev, old_state);
399227
400228 drm_atomic_helper_commit_hw_done(old_state);
401229
402
- rockchip_drm_atomic_helper_wait_for_vblanks(dev, old_state);
230
+ drm_atomic_helper_wait_for_vblanks(dev, old_state);
403231
404232 drm_atomic_helper_cleanup_planes(dev, old_state);
405233 }
406234
407235 static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
408
- .atomic_commit_tail = rockchip_atomic_helper_commit_tail_rpm,
236
+ .atomic_commit_tail = rockchip_drm_atomic_helper_commit_tail_rpm,
409237 };
410238
411
-static void
412
-rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit)
239
+static struct drm_framebuffer *
240
+rockchip_fb_create(struct drm_device *dev, struct drm_file *file,
241
+ const struct drm_mode_fb_cmd2 *mode_cmd)
413242 {
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;
243
+ struct drm_afbc_framebuffer *afbc_fb;
244
+ const struct drm_format_info *info;
245
+ int ret, i;
420246
421
- /*
422
- * TODO: do fence wait here.
423
- */
247
+ info = drm_get_format_info(dev, mode_cmd);
248
+ if (!info)
249
+ return ERR_PTR(-ENOMEM);
424250
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;
251
+ for (i = 0; i < info->num_planes; ++i) {
252
+ if (mode_cmd->pitches[i] % 4) {
253
+ DRM_DEV_ERROR_RATELIMITED(dev->dev,
254
+ "fb pitch[%d] must be 4 byte aligned: %d\n", i, mode_cmd->pitches[i]);
255
+ return ERR_PTR(-EINVAL);
256
+ }
452257 }
453
- if (prv->devfreq)
454
- rockchip_dmcfreq_vop_bandwidth_update(prv->devfreq, line_bw_mbyte, frame_bw_mbyte,
455
- plane_num);
456258
457
- mutex_lock(&prv->ovl_lock);
458
- drm_atomic_helper_commit_planes(dev, state, true);
459
- mutex_unlock(&prv->ovl_lock);
259
+ afbc_fb = kzalloc(sizeof(*afbc_fb), GFP_KERNEL);
260
+ if (!afbc_fb)
261
+ return ERR_PTR(-ENOMEM);
460262
461
- rockchip_drm_psr_inhibit_put_state(state);
263
+ ret = drm_gem_fb_init_with_funcs(dev, &afbc_fb->base, file, mode_cmd,
264
+ &rockchip_drm_fb_funcs);
265
+ if (ret) {
266
+ kfree(afbc_fb);
267
+ return ERR_PTR(ret);
268
+ }
462269
463
- drm_atomic_helper_connector_commit(dev, state);
270
+ if (drm_is_afbc(mode_cmd->modifier[0])) {
271
+ ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb);
272
+ if (ret) {
273
+ struct drm_gem_object **obj = afbc_fb->base.obj;
464274
465
- drm_atomic_helper_commit_hw_done(state);
275
+ for (i = 0; i < info->num_planes; ++i)
276
+ drm_gem_object_put(obj[i]);
466277
467
- rockchip_drm_atomic_helper_wait_for_vblanks(dev, state);
278
+ kfree(afbc_fb);
279
+ return ERR_PTR(ret);
280
+ }
281
+ }
468282
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);
283
+ return &afbc_fb->base;
476284 }
477285
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)
286
+static void rockchip_drm_output_poll_changed(struct drm_device *dev)
490287 {
491288 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;
289
+ struct drm_fb_helper *fb_helper = private->fbdev_helper;
497290
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;
291
+ if (fb_helper && dev->mode_config.poll_enabled && !private->loader_protect)
292
+ drm_fb_helper_hotplug_event(fb_helper);
550293 }
551294
552295 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
553
- .fb_create = rockchip_user_fb_create,
296
+ .fb_create = rockchip_fb_create,
554297 .output_poll_changed = rockchip_drm_output_poll_changed,
555298 .atomic_check = drm_atomic_helper_check,
556
- .atomic_commit = rockchip_drm_atomic_commit,
299
+ .atomic_commit = drm_atomic_helper_commit,
557300 };
558301
559302 struct drm_framebuffer *
....@@ -563,7 +306,7 @@
563306 {
564307 struct drm_framebuffer *fb;
565308
566
- fb = rockchip_fb_alloc(dev, mode_cmd, &obj, NULL, 1);
309
+ fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1);
567310 if (IS_ERR(fb))
568311 return ERR_CAST(fb);
569312
....@@ -576,12 +319,12 @@
576319 dev->mode_config.min_height = 0;
577320
578321 /*
579
- * set max width and height as default value(4096x4096).
322
+ * set max width and height as default value(16384x16384).
580323 * this value would be used to check framebuffer size limitation
581324 * at drm_mode_addfb().
582325 */
583
- dev->mode_config.max_width = 8192;
584
- dev->mode_config.max_height = 8192;
326
+ dev->mode_config.max_width = 16384;
327
+ dev->mode_config.max_height = 16384;
585328 dev->mode_config.async_page_flip = true;
586329
587330 dev->mode_config.funcs = &rockchip_drm_mode_config_funcs;