hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/gpu/drm/drm_fb_helper.c
....@@ -32,18 +32,22 @@
3232 #include <linux/console.h>
3333 #include <linux/dma-buf.h>
3434 #include <linux/kernel.h>
35
-#include <linux/sysrq.h>
36
-#include <linux/slab.h>
3735 #include <linux/module.h>
38
-#include <drm/drmP.h>
39
-#include <drm/drm_crtc.h>
40
-#include <drm/drm_fb_helper.h>
41
-#include <drm/drm_crtc_helper.h>
42
-#include <drm/drm_atomic.h>
43
-#include <drm/drm_atomic_helper.h>
36
+#include <linux/slab.h>
37
+#include <linux/sysrq.h>
38
+#include <linux/vmalloc.h>
4439
45
-#include "drm_crtc_internal.h"
40
+#include <drm/drm_atomic.h>
41
+#include <drm/drm_crtc.h>
42
+#include <drm/drm_crtc_helper.h>
43
+#include <drm/drm_drv.h>
44
+#include <drm/drm_fb_helper.h>
45
+#include <drm/drm_fourcc.h>
46
+#include <drm/drm_print.h>
47
+#include <drm/drm_vblank.h>
48
+
4649 #include "drm_crtc_helper_internal.h"
50
+#include "drm_internal.h"
4751
4852 static bool drm_fbdev_emulation = true;
4953 module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
....@@ -71,7 +75,7 @@
7175 #if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
7276 static bool drm_leak_fbdev_smem = false;
7377 module_param_unsafe(drm_leak_fbdev_smem, bool, 0600);
74
-MODULE_PARM_DESC(fbdev_emulation,
78
+MODULE_PARM_DESC(drm_leak_fbdev_smem,
7579 "Allow unsafe leaking fbdev physical smem address [default=false]");
7680 #endif
7781
....@@ -88,15 +92,8 @@
8892 *
8993 * Drivers that support a dumb buffer with a virtual address and mmap support,
9094 * should try out the generic fbdev emulation using drm_fbdev_generic_setup().
91
- *
92
- * Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it
93
- * down by calling drm_fb_helper_fbdev_teardown().
94
- *
95
- * Drivers that need to handle connector hotplugging (e.g. dp mst) can't use
96
- * the setup helper and will need to do the whole four-step setup process with
97
- * drm_fb_helper_prepare(), drm_fb_helper_init(),
98
- * drm_fb_helper_single_add_all_connectors(), enable hotplugging and
99
- * drm_fb_helper_initial_config() to avoid a possible race window.
95
+ * It will automatically set up deferred I/O if the driver requires a shadow
96
+ * buffer.
10097 *
10198 * At runtime drivers should restore the fbdev console by using
10299 * drm_fb_helper_lastclose() as their &drm_driver.lastclose callback.
....@@ -120,8 +117,7 @@
120117 * encoders and connectors. To finish up the fbdev helper initialization, the
121118 * drm_fb_helper_init() function is called. To probe for all attached displays
122119 * and set up an initial configuration using the detected hardware, drivers
123
- * should call drm_fb_helper_single_add_all_connectors() followed by
124
- * drm_fb_helper_initial_config().
120
+ * should call drm_fb_helper_initial_config().
125121 *
126122 * If &drm_framebuffer_funcs.dirty is set, the
127123 * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will
....@@ -130,168 +126,11 @@
130126 * always run in process context since the fb_*() function could be running in
131127 * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io
132128 * callback it will also schedule dirty_work with the damage collected from the
133
- * mmap page writes. Drivers can use drm_fb_helper_defio_init() to setup
134
- * deferred I/O (coupled with drm_fb_helper_fbdev_teardown()).
135
- */
136
-
137
-#define drm_fb_helper_for_each_connector(fbh, i__) \
138
- for (({ lockdep_assert_held(&(fbh)->lock); }), \
139
- i__ = 0; i__ < (fbh)->connector_count; i__++)
140
-
141
-static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
142
- struct drm_connector *connector)
143
-{
144
- struct drm_fb_helper_connector *fb_conn;
145
- struct drm_fb_helper_connector **temp;
146
- unsigned int count;
147
-
148
- if (!drm_fbdev_emulation)
149
- return 0;
150
-
151
- lockdep_assert_held(&fb_helper->lock);
152
-
153
- count = fb_helper->connector_count + 1;
154
-
155
- if (count > fb_helper->connector_info_alloc_count) {
156
- size_t size = count * sizeof(fb_conn);
157
-
158
- temp = krealloc(fb_helper->connector_info, size, GFP_KERNEL);
159
- if (!temp)
160
- return -ENOMEM;
161
-
162
- fb_helper->connector_info_alloc_count = count;
163
- fb_helper->connector_info = temp;
164
- }
165
-
166
- fb_conn = kzalloc(sizeof(*fb_conn), GFP_KERNEL);
167
- if (!fb_conn)
168
- return -ENOMEM;
169
-
170
- drm_connector_get(connector);
171
- fb_conn->connector = connector;
172
- fb_helper->connector_info[fb_helper->connector_count++] = fb_conn;
173
-
174
- return 0;
175
-}
176
-
177
-int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
178
- struct drm_connector *connector)
179
-{
180
- int err;
181
-
182
- if (!fb_helper)
183
- return 0;
184
-
185
- mutex_lock(&fb_helper->lock);
186
- err = __drm_fb_helper_add_one_connector(fb_helper, connector);
187
- mutex_unlock(&fb_helper->lock);
188
-
189
- return err;
190
-}
191
-EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
192
-
193
-/**
194
- * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
195
- * emulation helper
196
- * @fb_helper: fbdev initialized with drm_fb_helper_init, can be NULL
129
+ * mmap page writes.
197130 *
198
- * This functions adds all the available connectors for use with the given
199
- * fb_helper. This is a separate step to allow drivers to freely assign
200
- * connectors to the fbdev, e.g. if some are reserved for special purposes or
201
- * not adequate to be used for the fbcon.
202
- *
203
- * This function is protected against concurrent connector hotadds/removals
204
- * using drm_fb_helper_add_one_connector() and
205
- * drm_fb_helper_remove_one_connector().
131
+ * Deferred I/O is not compatible with SHMEM. Such drivers should request an
132
+ * fbdev shadow buffer and call drm_fbdev_generic_setup() instead.
206133 */
207
-int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
208
-{
209
- struct drm_device *dev;
210
- struct drm_connector *connector;
211
- struct drm_connector_list_iter conn_iter;
212
- int i, ret = 0;
213
-
214
- if (!drm_fbdev_emulation || !fb_helper)
215
- return 0;
216
-
217
- dev = fb_helper->dev;
218
-
219
- mutex_lock(&fb_helper->lock);
220
- drm_connector_list_iter_begin(dev, &conn_iter);
221
- drm_for_each_connector_iter(connector, &conn_iter) {
222
- if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
223
- continue;
224
-
225
- ret = __drm_fb_helper_add_one_connector(fb_helper, connector);
226
- if (ret)
227
- goto fail;
228
- }
229
- goto out;
230
-
231
-fail:
232
- drm_fb_helper_for_each_connector(fb_helper, i) {
233
- struct drm_fb_helper_connector *fb_helper_connector =
234
- fb_helper->connector_info[i];
235
-
236
- drm_connector_put(fb_helper_connector->connector);
237
-
238
- kfree(fb_helper_connector);
239
- fb_helper->connector_info[i] = NULL;
240
- }
241
- fb_helper->connector_count = 0;
242
-out:
243
- drm_connector_list_iter_end(&conn_iter);
244
- mutex_unlock(&fb_helper->lock);
245
-
246
- return ret;
247
-}
248
-EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
249
-
250
-static int __drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
251
- struct drm_connector *connector)
252
-{
253
- struct drm_fb_helper_connector *fb_helper_connector;
254
- int i, j;
255
-
256
- if (!drm_fbdev_emulation)
257
- return 0;
258
-
259
- lockdep_assert_held(&fb_helper->lock);
260
-
261
- drm_fb_helper_for_each_connector(fb_helper, i) {
262
- if (fb_helper->connector_info[i]->connector == connector)
263
- break;
264
- }
265
-
266
- if (i == fb_helper->connector_count)
267
- return -EINVAL;
268
- fb_helper_connector = fb_helper->connector_info[i];
269
- drm_connector_put(fb_helper_connector->connector);
270
-
271
- for (j = i + 1; j < fb_helper->connector_count; j++)
272
- fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
273
-
274
- fb_helper->connector_count--;
275
- kfree(fb_helper_connector);
276
-
277
- return 0;
278
-}
279
-
280
-int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
281
- struct drm_connector *connector)
282
-{
283
- int err;
284
-
285
- if (!fb_helper)
286
- return 0;
287
-
288
- mutex_lock(&fb_helper->lock);
289
- err = __drm_fb_helper_remove_one_connector(fb_helper, connector);
290
- mutex_unlock(&fb_helper->lock);
291
-
292
- return err;
293
-}
294
-EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
295134
296135 static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
297136 {
....@@ -316,13 +155,11 @@
316155 {
317156 struct drm_fb_helper *helper = info->par;
318157 const struct drm_crtc_helper_funcs *funcs;
319
- int i;
158
+ struct drm_mode_set *mode_set;
320159
321160 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
322
- for (i = 0; i < helper->crtc_count; i++) {
323
- struct drm_mode_set *mode_set =
324
- &helper->crtc_info[i].mode_set;
325
-
161
+ mutex_lock(&helper->client.modeset_mutex);
162
+ drm_client_for_each_modeset(mode_set, &helper->client) {
326163 if (!mode_set->crtc->enabled)
327164 continue;
328165
....@@ -339,6 +176,7 @@
339176 mode_set->y,
340177 ENTER_ATOMIC_MODE_SET);
341178 }
179
+ mutex_unlock(&helper->client.modeset_mutex);
342180 }
343181
344182 return 0;
....@@ -352,14 +190,15 @@
352190 int drm_fb_helper_debug_leave(struct fb_info *info)
353191 {
354192 struct drm_fb_helper *helper = info->par;
193
+ struct drm_client_dev *client = &helper->client;
194
+ struct drm_device *dev = helper->dev;
355195 struct drm_crtc *crtc;
356196 const struct drm_crtc_helper_funcs *funcs;
197
+ struct drm_mode_set *mode_set;
357198 struct drm_framebuffer *fb;
358
- int i;
359199
360
- for (i = 0; i < helper->crtc_count; i++) {
361
- struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
362
-
200
+ mutex_lock(&client->modeset_mutex);
201
+ drm_client_for_each_modeset(mode_set, client) {
363202 crtc = mode_set->crtc;
364203 if (drm_drv_uses_atomic_modeset(crtc->dev))
365204 continue;
....@@ -371,7 +210,7 @@
371210 continue;
372211
373212 if (!fb) {
374
- DRM_ERROR("no fb to restore??\n");
213
+ drm_err(dev, "no fb to restore?\n");
375214 continue;
376215 }
377216
....@@ -382,141 +221,46 @@
382221 funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
383222 crtc->y, LEAVE_ATOMIC_MODE_SET);
384223 }
224
+ mutex_unlock(&client->modeset_mutex);
385225
386226 return 0;
387227 }
388228 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
389229
390
-static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active)
230
+static int
231
+__drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper,
232
+ bool force)
391233 {
392
- struct drm_device *dev = fb_helper->dev;
393
- struct drm_plane_state *plane_state;
394
- struct drm_plane *plane;
395
- struct drm_atomic_state *state;
396
- int i, ret;
397
- struct drm_modeset_acquire_ctx ctx;
234
+ bool do_delayed;
235
+ int ret;
398236
399
- drm_modeset_acquire_init(&ctx, 0);
237
+ if (!drm_fbdev_emulation || !fb_helper)
238
+ return -ENODEV;
400239
401
- state = drm_atomic_state_alloc(dev);
402
- if (!state) {
403
- ret = -ENOMEM;
404
- goto out_ctx;
405
- }
240
+ if (READ_ONCE(fb_helper->deferred_setup))
241
+ return 0;
406242
407
- state->acquire_ctx = &ctx;
408
-retry:
409
- drm_for_each_plane(plane, dev) {
410
- plane_state = drm_atomic_get_plane_state(state, plane);
411
- if (IS_ERR(plane_state)) {
412
- ret = PTR_ERR(plane_state);
413
- goto out_state;
414
- }
415
-
416
- plane_state->rotation = DRM_MODE_ROTATE_0;
417
-
418
- /* disable non-primary: */
419
- if (plane->type == DRM_PLANE_TYPE_PRIMARY)
420
- continue;
421
-
422
- ret = __drm_atomic_helper_disable_plane(plane, plane_state);
423
- if (ret != 0)
424
- goto out_state;
425
- }
426
-
427
- for (i = 0; i < fb_helper->crtc_count; i++) {
428
- struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
429
- struct drm_plane *primary = mode_set->crtc->primary;
430
-
431
- /* Cannot fail as we've already gotten the plane state above */
432
- plane_state = drm_atomic_get_new_plane_state(state, primary);
433
- plane_state->rotation = fb_helper->crtc_info[i].rotation;
434
-
435
- ret = __drm_atomic_helper_set_config(mode_set, state);
436
- if (ret != 0)
437
- goto out_state;
438
-
243
+ mutex_lock(&fb_helper->lock);
244
+ if (force) {
439245 /*
440
- * __drm_atomic_helper_set_config() sets active when a
441
- * mode is set, unconditionally clear it if we force DPMS off
246
+ * Yes this is the _locked version which expects the master lock
247
+ * to be held. But for forced restores we're intentionally
248
+ * racing here, see drm_fb_helper_set_par().
442249 */
443
- if (!active) {
444
- struct drm_crtc *crtc = mode_set->crtc;
445
- struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
446
-
447
- crtc_state->active = false;
448
- }
250
+ ret = drm_client_modeset_commit_locked(&fb_helper->client);
251
+ } else {
252
+ ret = drm_client_modeset_commit(&fb_helper->client);
449253 }
450254
451
- ret = drm_atomic_commit(state);
255
+ do_delayed = fb_helper->delayed_hotplug;
256
+ if (do_delayed)
257
+ fb_helper->delayed_hotplug = false;
258
+ mutex_unlock(&fb_helper->lock);
452259
453
-out_state:
454
- if (ret == -EDEADLK)
455
- goto backoff;
456
-
457
- drm_atomic_state_put(state);
458
-out_ctx:
459
- drm_modeset_drop_locks(&ctx);
460
- drm_modeset_acquire_fini(&ctx);
260
+ if (do_delayed)
261
+ drm_fb_helper_hotplug_event(fb_helper);
461262
462263 return ret;
463
-
464
-backoff:
465
- drm_atomic_state_clear(state);
466
- drm_modeset_backoff(&ctx);
467
-
468
- goto retry;
469
-}
470
-
471
-static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
472
-{
473
- struct drm_device *dev = fb_helper->dev;
474
- struct drm_plane *plane;
475
- int i, ret = 0;
476
-
477
- drm_modeset_lock_all(fb_helper->dev);
478
- drm_for_each_plane(plane, dev) {
479
- if (plane->type != DRM_PLANE_TYPE_PRIMARY)
480
- drm_plane_force_disable(plane);
481
-
482
- if (plane->rotation_property)
483
- drm_mode_plane_set_obj_prop(plane,
484
- plane->rotation_property,
485
- DRM_MODE_ROTATE_0);
486
- }
487
-
488
- for (i = 0; i < fb_helper->crtc_count; i++) {
489
- struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
490
- struct drm_crtc *crtc = mode_set->crtc;
491
-
492
- if (crtc->funcs->cursor_set2) {
493
- ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
494
- if (ret)
495
- goto out;
496
- } else if (crtc->funcs->cursor_set) {
497
- ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
498
- if (ret)
499
- goto out;
500
- }
501
-
502
- ret = drm_mode_set_config_internal(mode_set);
503
- if (ret)
504
- goto out;
505
- }
506
-out:
507
- drm_modeset_unlock_all(fb_helper->dev);
508
-
509
- return ret;
510
-}
511
-
512
-static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
513
-{
514
- struct drm_device *dev = fb_helper->dev;
515
-
516
- if (drm_drv_uses_atomic_modeset(dev))
517
- return restore_fbdev_mode_atomic(fb_helper, true);
518
- else
519
- return restore_fbdev_mode_legacy(fb_helper);
520264 }
521265
522266 /**
....@@ -532,57 +276,9 @@
532276 */
533277 int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
534278 {
535
- bool do_delayed;
536
- int ret;
537
-
538
- if (!drm_fbdev_emulation || !fb_helper)
539
- return -ENODEV;
540
-
541
- if (READ_ONCE(fb_helper->deferred_setup))
542
- return 0;
543
-
544
- mutex_lock(&fb_helper->lock);
545
- ret = restore_fbdev_mode(fb_helper);
546
-
547
- do_delayed = fb_helper->delayed_hotplug;
548
- if (do_delayed)
549
- fb_helper->delayed_hotplug = false;
550
- mutex_unlock(&fb_helper->lock);
551
-
552
- if (do_delayed)
553
- drm_fb_helper_hotplug_event(fb_helper);
554
-
555
- return ret;
279
+ return __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, false);
556280 }
557281 EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
558
-
559
-static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
560
-{
561
- struct drm_device *dev = fb_helper->dev;
562
- struct drm_crtc *crtc;
563
- int bound = 0, crtcs_bound = 0;
564
-
565
- /*
566
- * Sometimes user space wants everything disabled, so don't steal the
567
- * display if there's a master.
568
- */
569
- if (READ_ONCE(dev->master))
570
- return false;
571
-
572
- drm_for_each_crtc(crtc, dev) {
573
- drm_modeset_lock(&crtc->mutex, NULL);
574
- if (crtc->primary->fb)
575
- crtcs_bound++;
576
- if (crtc->primary->fb == fb_helper->fb)
577
- bound++;
578
- drm_modeset_unlock(&crtc->mutex);
579
- }
580
-
581
- if (bound < crtcs_bound)
582
- return false;
583
-
584
- return true;
585
-}
586282
587283 #ifdef CONFIG_MAGIC_SYSRQ
588284 /*
....@@ -604,7 +300,7 @@
604300 continue;
605301
606302 mutex_lock(&helper->lock);
607
- ret = restore_fbdev_mode(helper);
303
+ ret = drm_client_modeset_commit_locked(&helper->client);
608304 if (ret)
609305 error = true;
610306 mutex_unlock(&helper->lock);
....@@ -627,57 +323,21 @@
627323 schedule_work(&drm_fb_helper_restore_work);
628324 }
629325
630
-static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
326
+static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
631327 .handler = drm_fb_helper_sysrq,
632
- .help_msg = "force-fb(V)",
328
+ .help_msg = "force-fb(v)",
633329 .action_msg = "Restore framebuffer console",
634330 };
635331 #else
636
-static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
332
+static const struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
637333 #endif
638
-
639
-static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
640
-{
641
- struct drm_device *dev = fb_helper->dev;
642
- struct drm_crtc *crtc;
643
- struct drm_connector *connector;
644
- int i, j;
645
-
646
- drm_modeset_lock_all(dev);
647
- for (i = 0; i < fb_helper->crtc_count; i++) {
648
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
649
-
650
- if (!crtc->enabled)
651
- continue;
652
-
653
- /* Walk the connectors & encoders on this fb turning them on/off */
654
- drm_fb_helper_for_each_connector(fb_helper, j) {
655
- connector = fb_helper->connector_info[j]->connector;
656
- connector->funcs->dpms(connector, dpms_mode);
657
- drm_object_property_set_value(&connector->base,
658
- dev->mode_config.dpms_property, dpms_mode);
659
- }
660
- }
661
- drm_modeset_unlock_all(dev);
662
-}
663334
664335 static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
665336 {
666337 struct drm_fb_helper *fb_helper = info->par;
667338
668
- /*
669
- * For each CRTC in this fb, turn the connectors on/off.
670
- */
671339 mutex_lock(&fb_helper->lock);
672
- if (!drm_fb_helper_is_bound(fb_helper)) {
673
- mutex_unlock(&fb_helper->lock);
674
- return;
675
- }
676
-
677
- if (drm_drv_uses_atomic_modeset(fb_helper->dev))
678
- restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON);
679
- else
680
- dpms_legacy(fb_helper, dpms_mode);
340
+ drm_client_modeset_dpms(&fb_helper->client, dpms_mode);
681341 mutex_unlock(&fb_helper->lock);
682342 }
683343
....@@ -717,43 +377,6 @@
717377 }
718378 EXPORT_SYMBOL(drm_fb_helper_blank);
719379
720
-static void drm_fb_helper_modeset_release(struct drm_fb_helper *helper,
721
- struct drm_mode_set *modeset)
722
-{
723
- int i;
724
-
725
- for (i = 0; i < modeset->num_connectors; i++) {
726
- drm_connector_put(modeset->connectors[i]);
727
- modeset->connectors[i] = NULL;
728
- }
729
- modeset->num_connectors = 0;
730
-
731
- drm_mode_destroy(helper->dev, modeset->mode);
732
- modeset->mode = NULL;
733
-
734
- /* FIXME should hold a ref? */
735
- modeset->fb = NULL;
736
-}
737
-
738
-static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
739
-{
740
- int i;
741
-
742
- for (i = 0; i < helper->connector_count; i++) {
743
- drm_connector_put(helper->connector_info[i]->connector);
744
- kfree(helper->connector_info[i]);
745
- }
746
- kfree(helper->connector_info);
747
-
748
- for (i = 0; i < helper->crtc_count; i++) {
749
- struct drm_mode_set *modeset = &helper->crtc_info[i].mode_set;
750
-
751
- drm_fb_helper_modeset_release(helper, modeset);
752
- kfree(modeset->connectors);
753
- }
754
- kfree(helper->crtc_info);
755
-}
756
-
757380 static void drm_fb_helper_resume_worker(struct work_struct *work)
758381 {
759382 struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
....@@ -768,7 +391,7 @@
768391 struct drm_clip_rect *clip)
769392 {
770393 struct drm_framebuffer *fb = fb_helper->fb;
771
- unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
394
+ unsigned int cpp = fb->format->cpp[0];
772395 size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
773396 void *src = fb_helper->fbdev->screen_buffer + offset;
774397 void *dst = fb_helper->buffer->vaddr + offset;
....@@ -776,7 +399,11 @@
776399 unsigned int y;
777400
778401 for (y = clip->y1; y < clip->y2; y++) {
779
- memcpy(dst, src, len);
402
+ if (!fb_helper->dev->mode_config.fbdev_use_iomem)
403
+ memcpy(dst, src, len);
404
+ else
405
+ memcpy_toio((void __iomem *)dst, src, len);
406
+
780407 src += fb->pitches[0];
781408 dst += fb->pitches[0];
782409 }
....@@ -789,6 +416,7 @@
789416 struct drm_clip_rect *clip = &helper->dirty_clip;
790417 struct drm_clip_rect clip_copy;
791418 unsigned long flags;
419
+ void *vaddr;
792420
793421 spin_lock_irqsave(&helper->dirty_lock, flags);
794422 clip_copy = *clip;
....@@ -798,10 +426,20 @@
798426
799427 /* call dirty callback only when it has been really touched */
800428 if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2) {
429
+
801430 /* Generic fbdev uses a shadow buffer */
802
- if (helper->buffer)
431
+ if (helper->buffer) {
432
+ vaddr = drm_client_buffer_vmap(helper->buffer);
433
+ if (IS_ERR(vaddr))
434
+ return;
803435 drm_fb_helper_dirty_blit_real(helper, &clip_copy);
804
- helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
436
+ }
437
+ if (helper->fb->funcs->dirty)
438
+ helper->fb->funcs->dirty(helper->fb, NULL, 0, 0,
439
+ &clip_copy, 1);
440
+
441
+ if (helper->buffer)
442
+ drm_client_buffer_vunmap(helper->buffer);
805443 }
806444 }
807445
....@@ -832,7 +470,6 @@
832470 * drm_fb_helper_init - initialize a &struct drm_fb_helper
833471 * @dev: drm device
834472 * @fb_helper: driver-allocated fbdev helper structure to initialize
835
- * @max_conn_count: max connector count
836473 *
837474 * This allocates the structures for the fbdev helper with the given limits.
838475 * Note that this won't yet touch the hardware (through the driver interfaces)
....@@ -845,58 +482,28 @@
845482 * Zero if everything went ok, nonzero otherwise.
846483 */
847484 int drm_fb_helper_init(struct drm_device *dev,
848
- struct drm_fb_helper *fb_helper,
849
- int max_conn_count)
485
+ struct drm_fb_helper *fb_helper)
850486 {
851
- struct drm_crtc *crtc;
852
- struct drm_mode_config *config = &dev->mode_config;
853
- int i;
487
+ int ret;
854488
855489 if (!drm_fbdev_emulation) {
856490 dev->fb_helper = fb_helper;
857491 return 0;
858492 }
859493
860
- if (!max_conn_count)
861
- return -EINVAL;
862
-
863
- fb_helper->crtc_info = kcalloc(config->num_crtc, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
864
- if (!fb_helper->crtc_info)
865
- return -ENOMEM;
866
-
867
- fb_helper->crtc_count = config->num_crtc;
868
- fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
869
- if (!fb_helper->connector_info) {
870
- kfree(fb_helper->crtc_info);
871
- return -ENOMEM;
872
- }
873
- fb_helper->connector_info_alloc_count = dev->mode_config.num_connector;
874
- fb_helper->connector_count = 0;
875
-
876
- for (i = 0; i < fb_helper->crtc_count; i++) {
877
- fb_helper->crtc_info[i].mode_set.connectors =
878
- kcalloc(max_conn_count,
879
- sizeof(struct drm_connector *),
880
- GFP_KERNEL);
881
-
882
- if (!fb_helper->crtc_info[i].mode_set.connectors)
883
- goto out_free;
884
- fb_helper->crtc_info[i].mode_set.num_connectors = 0;
885
- fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0;
886
- }
887
-
888
- i = 0;
889
- drm_for_each_crtc(crtc, dev) {
890
- fb_helper->crtc_info[i].mode_set.crtc = crtc;
891
- i++;
494
+ /*
495
+ * If this is not the generic fbdev client, initialize a drm_client
496
+ * without callbacks so we can use the modesets.
497
+ */
498
+ if (!fb_helper->client.funcs) {
499
+ ret = drm_client_init(dev, &fb_helper->client, "drm_fb_helper", NULL);
500
+ if (ret)
501
+ return ret;
892502 }
893503
894504 dev->fb_helper = fb_helper;
895505
896506 return 0;
897
-out_free:
898
- drm_fb_helper_crtc_free(fb_helper);
899
- return -ENOMEM;
900507 }
901508 EXPORT_SYMBOL(drm_fb_helper_init);
902509
....@@ -927,6 +534,14 @@
927534 if (ret)
928535 goto err_release;
929536
537
+ /*
538
+ * TODO: We really should be smarter here and alloc an apperture
539
+ * for each IORESOURCE_MEM resource helper->dev->dev has and also
540
+ * init the ranges of the appertures based on the resources.
541
+ * Note some drivers currently count on there being only 1 empty
542
+ * aperture and fill this themselves, these will need to be dealt
543
+ * with somehow when fixing this.
544
+ */
930545 info->apertures = alloc_apertures(1);
931546 if (!info->apertures) {
932547 ret = -ENOMEM;
....@@ -934,6 +549,7 @@
934549 }
935550
936551 fb_helper->fbdev = info;
552
+ info->skip_vt_switch = true;
937553
938554 return info;
939555
....@@ -964,8 +580,7 @@
964580 * drm_fb_helper_fini - finialize a &struct drm_fb_helper
965581 * @fb_helper: driver-allocated fbdev helper, can be NULL
966582 *
967
- * This cleans up all remaining resources associated with @fb_helper. Must be
968
- * called after drm_fb_helper_unlink_fbi() was called.
583
+ * This cleans up all remaining resources associated with @fb_helper.
969584 */
970585 void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
971586 {
....@@ -999,23 +614,21 @@
999614 mutex_unlock(&kernel_fb_helper_lock);
1000615
1001616 mutex_destroy(&fb_helper->lock);
1002
- drm_fb_helper_crtc_free(fb_helper);
1003617
618
+ if (!fb_helper->client.funcs)
619
+ drm_client_release(&fb_helper->client);
1004620 }
1005621 EXPORT_SYMBOL(drm_fb_helper_fini);
1006622
1007
-/**
1008
- * drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer
1009
- * @fb_helper: driver-allocated fbdev helper, can be NULL
1010
- *
1011
- * A wrapper around unlink_framebuffer implemented by fbdev core
1012
- */
1013
-void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
623
+static bool drm_fbdev_use_shadow_fb(struct drm_fb_helper *fb_helper)
1014624 {
1015
- if (fb_helper && fb_helper->fbdev)
1016
- unlink_framebuffer(fb_helper->fbdev);
625
+ struct drm_device *dev = fb_helper->dev;
626
+ struct drm_framebuffer *fb = fb_helper->fb;
627
+
628
+ return dev->mode_config.prefer_shadow_fbdev ||
629
+ dev->mode_config.prefer_shadow ||
630
+ fb->funcs->dirty;
1017631 }
1018
-EXPORT_SYMBOL(drm_fb_helper_unlink_fbi);
1019632
1020633 static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y,
1021634 u32 width, u32 height)
....@@ -1024,7 +637,7 @@
1024637 struct drm_clip_rect *clip = &helper->dirty_clip;
1025638 unsigned long flags;
1026639
1027
- if (!helper->fb->funcs->dirty)
640
+ if (!drm_fbdev_use_shadow_fb(helper))
1028641 return;
1029642
1030643 spin_lock_irqsave(&helper->dirty_lock, flags);
....@@ -1069,49 +682,6 @@
1069682 }
1070683 }
1071684 EXPORT_SYMBOL(drm_fb_helper_deferred_io);
1072
-
1073
-/**
1074
- * drm_fb_helper_defio_init - fbdev deferred I/O initialization
1075
- * @fb_helper: driver-allocated fbdev helper
1076
- *
1077
- * This function allocates &fb_deferred_io, sets callback to
1078
- * drm_fb_helper_deferred_io(), delay to 50ms and calls fb_deferred_io_init().
1079
- * It should be called from the &drm_fb_helper_funcs->fb_probe callback.
1080
- * drm_fb_helper_fbdev_teardown() cleans up deferred I/O.
1081
- *
1082
- * NOTE: A copy of &fb_ops is made and assigned to &info->fbops. This is done
1083
- * because fb_deferred_io_cleanup() clears &fbops->fb_mmap and would thereby
1084
- * affect other instances of that &fb_ops.
1085
- *
1086
- * Returns:
1087
- * 0 on success or a negative error code on failure.
1088
- */
1089
-int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
1090
-{
1091
- struct fb_info *info = fb_helper->fbdev;
1092
- struct fb_deferred_io *fbdefio;
1093
- struct fb_ops *fbops;
1094
-
1095
- fbdefio = kzalloc(sizeof(*fbdefio), GFP_KERNEL);
1096
- fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
1097
- if (!fbdefio || !fbops) {
1098
- kfree(fbdefio);
1099
- kfree(fbops);
1100
- return -ENOMEM;
1101
- }
1102
-
1103
- info->fbdefio = fbdefio;
1104
- fbdefio->delay = msecs_to_jiffies(50);
1105
- fbdefio->deferred_io = drm_fb_helper_deferred_io;
1106
-
1107
- *fbops = *info->fbops;
1108
- info->fbops = fbops;
1109
-
1110
- fb_deferred_io_init(info);
1111
-
1112
- return 0;
1113
-}
1114
-EXPORT_SYMBOL(drm_fb_helper_defio_init);
1115685
1116686 /**
1117687 * drm_fb_helper_sys_read - wrapper around fb_sys_read
....@@ -1345,18 +915,23 @@
1345915 static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
1346916 {
1347917 struct drm_fb_helper *fb_helper = info->par;
918
+ struct drm_mode_set *modeset;
1348919 struct drm_crtc *crtc;
1349920 u16 *r, *g, *b;
1350
- int i, ret = 0;
921
+ int ret = 0;
1351922
1352923 drm_modeset_lock_all(fb_helper->dev);
1353
- for (i = 0; i < fb_helper->crtc_count; i++) {
1354
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
1355
- if (!crtc->funcs->gamma_set || !crtc->gamma_size)
1356
- return -EINVAL;
924
+ drm_client_for_each_modeset(modeset, &fb_helper->client) {
925
+ crtc = modeset->crtc;
926
+ if (!crtc->funcs->gamma_set || !crtc->gamma_size) {
927
+ ret = -EINVAL;
928
+ goto out;
929
+ }
1357930
1358
- if (cmap->start + cmap->len > crtc->gamma_size)
1359
- return -EINVAL;
931
+ if (cmap->start + cmap->len > crtc->gamma_size) {
932
+ ret = -EINVAL;
933
+ goto out;
934
+ }
1360935
1361936 r = crtc->gamma_store;
1362937 g = r + crtc->gamma_size;
....@@ -1369,8 +944,9 @@
1369944 ret = crtc->funcs->gamma_set(crtc, r, g, b,
1370945 crtc->gamma_size, NULL);
1371946 if (ret)
1372
- return ret;
947
+ goto out;
1373948 }
949
+out:
1374950 drm_modeset_unlock_all(fb_helper->dev);
1375951
1376952 return ret;
....@@ -1427,10 +1003,11 @@
14271003 struct drm_modeset_acquire_ctx ctx;
14281004 struct drm_crtc_state *crtc_state;
14291005 struct drm_atomic_state *state;
1006
+ struct drm_mode_set *modeset;
14301007 struct drm_crtc *crtc;
14311008 u16 *r, *g, *b;
1432
- int i, ret = 0;
14331009 bool replaced;
1010
+ int ret = 0;
14341011
14351012 drm_modeset_acquire_init(&ctx, 0);
14361013
....@@ -1442,8 +1019,8 @@
14421019
14431020 state->acquire_ctx = &ctx;
14441021 retry:
1445
- for (i = 0; i < fb_helper->crtc_count; i++) {
1446
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
1022
+ drm_client_for_each_modeset(modeset, &fb_helper->client) {
1023
+ crtc = modeset->crtc;
14471024
14481025 if (!gamma_lut)
14491026 gamma_lut = setcmap_new_gamma_lut(crtc, cmap);
....@@ -1471,8 +1048,8 @@
14711048 if (ret)
14721049 goto out_state;
14731050
1474
- for (i = 0; i < fb_helper->crtc_count; i++) {
1475
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
1051
+ drm_client_for_each_modeset(modeset, &fb_helper->client) {
1052
+ crtc = modeset->crtc;
14761053
14771054 r = crtc->gamma_store;
14781055 g = r + crtc->gamma_size;
....@@ -1509,6 +1086,7 @@
15091086 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
15101087 {
15111088 struct drm_fb_helper *fb_helper = info->par;
1089
+ struct drm_device *dev = fb_helper->dev;
15121090 int ret;
15131091
15141092 if (oops_in_progress)
....@@ -1516,19 +1094,22 @@
15161094
15171095 mutex_lock(&fb_helper->lock);
15181096
1519
- if (!drm_fb_helper_is_bound(fb_helper)) {
1097
+ if (!drm_master_internal_acquire(dev)) {
15201098 ret = -EBUSY;
1521
- goto out;
1099
+ goto unlock;
15221100 }
15231101
1102
+ mutex_lock(&fb_helper->client.modeset_mutex);
15241103 if (info->fix.visual == FB_VISUAL_TRUECOLOR)
15251104 ret = setcmap_pseudo_palette(cmap, info);
15261105 else if (drm_drv_uses_atomic_modeset(fb_helper->dev))
15271106 ret = setcmap_atomic(cmap, info);
15281107 else
15291108 ret = setcmap_legacy(cmap, info);
1109
+ mutex_unlock(&fb_helper->client.modeset_mutex);
15301110
1531
-out:
1111
+ drm_master_internal_release(dev);
1112
+unlock:
15321113 mutex_unlock(&fb_helper->lock);
15331114
15341115 return ret;
....@@ -1548,12 +1129,12 @@
15481129 unsigned long arg)
15491130 {
15501131 struct drm_fb_helper *fb_helper = info->par;
1551
- struct drm_mode_set *mode_set;
1132
+ struct drm_device *dev = fb_helper->dev;
15521133 struct drm_crtc *crtc;
15531134 int ret = 0;
15541135
15551136 mutex_lock(&fb_helper->lock);
1556
- if (!drm_fb_helper_is_bound(fb_helper)) {
1137
+ if (!drm_master_internal_acquire(dev)) {
15571138 ret = -EBUSY;
15581139 goto unlock;
15591140 }
....@@ -1576,8 +1157,7 @@
15761157 * make. If we're not smart enough here, one should
15771158 * just consider switch the userspace to KMS.
15781159 */
1579
- mode_set = &fb_helper->crtc_info[0].mode_set;
1580
- crtc = mode_set->crtc;
1160
+ crtc = fb_helper->client.modesets[0].crtc;
15811161
15821162 /*
15831163 * Only wait for a vblank event if the CRTC is
....@@ -1591,11 +1171,12 @@
15911171 }
15921172
15931173 ret = 0;
1594
- goto unlock;
1174
+ break;
15951175 default:
15961176 ret = -ENOTTY;
15971177 }
15981178
1179
+ drm_master_internal_release(dev);
15991180 unlock:
16001181 mutex_unlock(&fb_helper->lock);
16011182 return ret;
....@@ -1689,29 +1270,37 @@
16891270 {
16901271 struct drm_fb_helper *fb_helper = info->par;
16911272 struct drm_framebuffer *fb = fb_helper->fb;
1273
+ struct drm_device *dev = fb_helper->dev;
16921274
16931275 if (in_dbg_master())
16941276 return -EINVAL;
16951277
16961278 if (var->pixclock != 0) {
1697
- DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
1279
+ drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
16981280 var->pixclock = 0;
16991281 }
1282
+
1283
+ if ((drm_format_info_block_width(fb->format, 0) > 1) ||
1284
+ (drm_format_info_block_height(fb->format, 0) > 1))
1285
+ return -EINVAL;
17001286
17011287 /*
17021288 * Changes struct fb_var_screeninfo are currently not pushed back
17031289 * to KMS, hence fail if different settings are requested.
17041290 */
1705
- if (var->bits_per_pixel > fb->format->bpp[0] ||
1291
+ if (var->bits_per_pixel > fb->format->cpp[0] * 8 ||
17061292 var->xres > fb->width || var->yres > fb->height ||
17071293 var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
1708
- DRM_DEBUG("fb requested width/height/bpp can't fit in current fb "
1294
+ drm_dbg_kms(dev, "fb requested width/height/bpp can't fit in current fb "
17091295 "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
17101296 var->xres, var->yres, var->bits_per_pixel,
17111297 var->xres_virtual, var->yres_virtual,
1712
- fb->width, fb->height, fb->format->bpp[0]);
1298
+ fb->width, fb->height, fb->format->cpp[0] * 8);
17131299 return -EINVAL;
17141300 }
1301
+
1302
+ var->xres_virtual = fb->width;
1303
+ var->yres_virtual = fb->height;
17151304
17161305 /*
17171306 * Workaround for SDL 1.2, which is known to be setting all pixel format
....@@ -1730,14 +1319,14 @@
17301319 /*
17311320 * Likewise, bits_per_pixel should be rounded up to a supported value.
17321321 */
1733
- var->bits_per_pixel = fb->format->bpp[0];
1322
+ var->bits_per_pixel = fb->format->cpp[0] * 8;
17341323
17351324 /*
17361325 * drm fbdev emulation doesn't support changing the pixel format at all,
17371326 * so reject all pixel format changing requests.
17381327 */
17391328 if (!drm_fb_pixel_format_equal(var, &info->var)) {
1740
- DRM_DEBUG("fbdev emulation doesn't support changing the pixel format\n");
1329
+ drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel format\n");
17411330 return -EINVAL;
17421331 }
17431332
....@@ -1757,16 +1346,35 @@
17571346 {
17581347 struct drm_fb_helper *fb_helper = info->par;
17591348 struct fb_var_screeninfo *var = &info->var;
1349
+ bool force;
17601350
17611351 if (oops_in_progress)
17621352 return -EBUSY;
17631353
17641354 if (var->pixclock != 0) {
1765
- DRM_ERROR("PIXEL CLOCK SET\n");
1355
+ drm_err(fb_helper->dev, "PIXEL CLOCK SET\n");
17661356 return -EINVAL;
17671357 }
17681358
1769
- drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
1359
+ /*
1360
+ * Normally we want to make sure that a kms master takes precedence over
1361
+ * fbdev, to avoid fbdev flickering and occasionally stealing the
1362
+ * display status. But Xorg first sets the vt back to text mode using
1363
+ * the KDSET IOCTL with KD_TEXT, and only after that drops the master
1364
+ * status when exiting.
1365
+ *
1366
+ * In the past this was caught by drm_fb_helper_lastclose(), but on
1367
+ * modern systems where logind always keeps a drm fd open to orchestrate
1368
+ * the vt switching, this doesn't work.
1369
+ *
1370
+ * To not break the userspace ABI we have this special case here, which
1371
+ * is only used for the above case. Everything else uses the normal
1372
+ * commit function, which ensures that we never steal the display from
1373
+ * an active drm master.
1374
+ */
1375
+ force = var->activate & FB_ACTIVATE_KD_TEXT;
1376
+
1377
+ __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, force);
17701378
17711379 return 0;
17721380 }
....@@ -1774,16 +1382,14 @@
17741382
17751383 static void pan_set(struct drm_fb_helper *fb_helper, int x, int y)
17761384 {
1777
- int i;
1385
+ struct drm_mode_set *mode_set;
17781386
1779
- for (i = 0; i < fb_helper->crtc_count; i++) {
1780
- struct drm_mode_set *mode_set;
1781
-
1782
- mode_set = &fb_helper->crtc_info[i].mode_set;
1783
-
1387
+ mutex_lock(&fb_helper->client.modeset_mutex);
1388
+ drm_client_for_each_modeset(mode_set, &fb_helper->client) {
17841389 mode_set->x = x;
17851390 mode_set->y = y;
17861391 }
1392
+ mutex_unlock(&fb_helper->client.modeset_mutex);
17871393 }
17881394
17891395 static int pan_display_atomic(struct fb_var_screeninfo *var,
....@@ -1794,7 +1400,7 @@
17941400
17951401 pan_set(fb_helper, var->xoffset, var->yoffset);
17961402
1797
- ret = restore_fbdev_mode_atomic(fb_helper, true);
1403
+ ret = drm_client_modeset_commit_locked(&fb_helper->client);
17981404 if (!ret) {
17991405 info->var.xoffset = var->xoffset;
18001406 info->var.yoffset = var->yoffset;
....@@ -1808,14 +1414,13 @@
18081414 struct fb_info *info)
18091415 {
18101416 struct drm_fb_helper *fb_helper = info->par;
1417
+ struct drm_client_dev *client = &fb_helper->client;
18111418 struct drm_mode_set *modeset;
18121419 int ret = 0;
1813
- int i;
18141420
1421
+ mutex_lock(&client->modeset_mutex);
18151422 drm_modeset_lock_all(fb_helper->dev);
1816
- for (i = 0; i < fb_helper->crtc_count; i++) {
1817
- modeset = &fb_helper->crtc_info[i].mode_set;
1818
-
1423
+ drm_client_for_each_modeset(modeset, client) {
18191424 modeset->x = var->xoffset;
18201425 modeset->y = var->yoffset;
18211426
....@@ -1828,6 +1433,7 @@
18281433 }
18291434 }
18301435 drm_modeset_unlock_all(fb_helper->dev);
1436
+ mutex_unlock(&client->modeset_mutex);
18311437
18321438 return ret;
18331439 }
....@@ -1848,15 +1454,18 @@
18481454 return -EBUSY;
18491455
18501456 mutex_lock(&fb_helper->lock);
1851
- if (!drm_fb_helper_is_bound(fb_helper)) {
1852
- mutex_unlock(&fb_helper->lock);
1853
- return -EBUSY;
1457
+ if (!drm_master_internal_acquire(dev)) {
1458
+ ret = -EBUSY;
1459
+ goto unlock;
18541460 }
18551461
18561462 if (drm_drv_uses_atomic_modeset(dev))
18571463 ret = pan_display_atomic(var, info);
18581464 else
18591465 ret = pan_display_legacy(var, info);
1466
+
1467
+ drm_master_internal_release(dev);
1468
+unlock:
18601469 mutex_unlock(&fb_helper->lock);
18611470
18621471 return ret;
....@@ -1870,11 +1479,15 @@
18701479 static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
18711480 int preferred_bpp)
18721481 {
1482
+ struct drm_client_dev *client = &fb_helper->client;
1483
+ struct drm_device *dev = fb_helper->dev;
18731484 int ret = 0;
18741485 int crtc_count = 0;
1875
- int i;
1486
+ struct drm_connector_list_iter conn_iter;
18761487 struct drm_fb_helper_surface_size sizes;
1877
- int gamma_size = 0;
1488
+ struct drm_connector *connector;
1489
+ struct drm_mode_set *mode_set;
1490
+ int best_depth = 0;
18781491
18791492 memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
18801493 sizes.surface_depth = 24;
....@@ -1882,16 +1495,18 @@
18821495 sizes.fb_width = (u32)-1;
18831496 sizes.fb_height = (u32)-1;
18841497
1885
- /* if driver picks 8 or 16 by default use that for both depth/bpp */
1498
+ /*
1499
+ * If driver picks 8 or 16 by default use that for both depth/bpp
1500
+ * to begin with
1501
+ */
18861502 if (preferred_bpp != sizes.surface_bpp)
18871503 sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
18881504
1889
- /* first up get a count of crtcs now in use and new min/maxes width/heights */
1890
- drm_fb_helper_for_each_connector(fb_helper, i) {
1891
- struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
1505
+ drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
1506
+ drm_client_for_each_connector_iter(connector, &conn_iter) {
18921507 struct drm_cmdline_mode *cmdline_mode;
18931508
1894
- cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
1509
+ cmdline_mode = &connector->cmdline_mode;
18951510
18961511 if (cmdline_mode->bpp_specified) {
18971512 switch (cmdline_mode->bpp) {
....@@ -1916,11 +1531,61 @@
19161531 break;
19171532 }
19181533 }
1534
+ drm_connector_list_iter_end(&conn_iter);
19191535
1536
+ /*
1537
+ * If we run into a situation where, for example, the primary plane
1538
+ * supports RGBA5551 (16 bpp, depth 15) but not RGB565 (16 bpp, depth
1539
+ * 16) we need to scale down the depth of the sizes we request.
1540
+ */
1541
+ mutex_lock(&client->modeset_mutex);
1542
+ drm_client_for_each_modeset(mode_set, client) {
1543
+ struct drm_crtc *crtc = mode_set->crtc;
1544
+ struct drm_plane *plane = crtc->primary;
1545
+ int j;
1546
+
1547
+ drm_dbg_kms(dev, "test CRTC %u primary plane\n", drm_crtc_index(crtc));
1548
+
1549
+ for (j = 0; j < plane->format_count; j++) {
1550
+ const struct drm_format_info *fmt;
1551
+
1552
+ fmt = drm_format_info(plane->format_types[j]);
1553
+
1554
+ /*
1555
+ * Do not consider YUV or other complicated formats
1556
+ * for framebuffers. This means only legacy formats
1557
+ * are supported (fmt->depth is a legacy field) but
1558
+ * the framebuffer emulation can only deal with such
1559
+ * formats, specifically RGB/BGA formats.
1560
+ */
1561
+ if (fmt->depth == 0)
1562
+ continue;
1563
+
1564
+ /* We found a perfect fit, great */
1565
+ if (fmt->depth == sizes.surface_depth) {
1566
+ best_depth = fmt->depth;
1567
+ break;
1568
+ }
1569
+
1570
+ /* Skip depths above what we're looking for */
1571
+ if (fmt->depth > sizes.surface_depth)
1572
+ continue;
1573
+
1574
+ /* Best depth found so far */
1575
+ if (fmt->depth > best_depth)
1576
+ best_depth = fmt->depth;
1577
+ }
1578
+ }
1579
+ if (sizes.surface_depth != best_depth && best_depth) {
1580
+ drm_info(dev, "requested bpp %d, scaled depth down to %d",
1581
+ sizes.surface_bpp, best_depth);
1582
+ sizes.surface_depth = best_depth;
1583
+ }
1584
+
1585
+ /* first up get a count of crtcs now in use and new min/maxes width/heights */
19201586 crtc_count = 0;
1921
- for (i = 0; i < fb_helper->crtc_count; i++) {
1587
+ drm_client_for_each_modeset(mode_set, client) {
19221588 struct drm_display_mode *desired_mode;
1923
- struct drm_mode_set *mode_set;
19241589 int x, y, j;
19251590 /* in case of tile group, are we the last tile vert or horiz?
19261591 * If no tile group you are always the last one both vertically
....@@ -1928,19 +1593,15 @@
19281593 */
19291594 bool lastv = true, lasth = true;
19301595
1931
- desired_mode = fb_helper->crtc_info[i].desired_mode;
1932
- mode_set = &fb_helper->crtc_info[i].mode_set;
1596
+ desired_mode = mode_set->mode;
19331597
19341598 if (!desired_mode)
19351599 continue;
19361600
19371601 crtc_count++;
19381602
1939
- x = fb_helper->crtc_info[i].x;
1940
- y = fb_helper->crtc_info[i].y;
1941
-
1942
- if (gamma_size == 0)
1943
- gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
1603
+ x = mode_set->x;
1604
+ y = mode_set->y;
19441605
19451606 sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
19461607 sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
....@@ -1948,7 +1609,9 @@
19481609 for (j = 0; j < mode_set->num_connectors; j++) {
19491610 struct drm_connector *connector = mode_set->connectors[j];
19501611
1951
- if (connector->has_tile) {
1612
+ if (connector->has_tile &&
1613
+ desired_mode->hdisplay == connector->tile_h_size &&
1614
+ desired_mode->vdisplay == connector->tile_v_size) {
19521615 lasth = (connector->tile_h_loc == (connector->num_h_tile - 1));
19531616 lastv = (connector->tile_v_loc == (connector->num_v_tile - 1));
19541617 /* cloning to multiple tiles is just crazy-talk, so: */
....@@ -1961,13 +1624,14 @@
19611624 if (lastv)
19621625 sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
19631626 }
1627
+ mutex_unlock(&client->modeset_mutex);
19641628
19651629 if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
1966
- DRM_INFO("Cannot find any crtc or sizes\n");
1630
+ drm_info(dev, "Cannot find any crtc or sizes\n");
19671631
19681632 /* First time: disable all crtc's.. */
1969
- if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master))
1970
- restore_fbdev_mode(fb_helper);
1633
+ if (!fb_helper->deferred_setup)
1634
+ drm_client_modeset_commit(client);
19711635 return -EAGAIN;
19721636 }
19731637
....@@ -1984,21 +1648,8 @@
19841648 return 0;
19851649 }
19861650
1987
-/**
1988
- * drm_fb_helper_fill_fix - initializes fixed fbdev information
1989
- * @info: fbdev registered by the helper
1990
- * @pitch: desired pitch
1991
- * @depth: desired depth
1992
- *
1993
- * Helper to fill in the fixed fbdev information useful for a non-accelerated
1994
- * fbdev emulations. Drivers which support acceleration methods which impose
1995
- * additional constraints need to set up their own limits.
1996
- *
1997
- * Drivers should call this (or their equivalent setup code) from their
1998
- * &drm_fb_helper_funcs.fb_probe callback.
1999
- */
2000
-void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
2001
- uint32_t depth)
1651
+static void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
1652
+ uint32_t depth)
20021653 {
20031654 info->fix.type = FB_TYPE_PACKED_PIXELS;
20041655 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
....@@ -2013,31 +1664,19 @@
20131664
20141665 info->fix.line_length = pitch;
20151666 }
2016
-EXPORT_SYMBOL(drm_fb_helper_fill_fix);
20171667
2018
-/**
2019
- * drm_fb_helper_fill_var - initalizes variable fbdev information
2020
- * @info: fbdev instance to set up
2021
- * @fb_helper: fb helper instance to use as template
2022
- * @fb_width: desired fb width
2023
- * @fb_height: desired fb height
2024
- *
2025
- * Sets up the variable fbdev metainformation from the given fb helper instance
2026
- * and the drm framebuffer allocated in &drm_fb_helper.fb.
2027
- *
2028
- * Drivers should call this (or their equivalent setup code) from their
2029
- * &drm_fb_helper_funcs.fb_probe callback after having allocated the fbdev
2030
- * backing storage framebuffer.
2031
- */
2032
-void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
2033
- uint32_t fb_width, uint32_t fb_height)
1668
+static void drm_fb_helper_fill_var(struct fb_info *info,
1669
+ struct drm_fb_helper *fb_helper,
1670
+ uint32_t fb_width, uint32_t fb_height)
20341671 {
20351672 struct drm_framebuffer *fb = fb_helper->fb;
20361673
1674
+ WARN_ON((drm_format_info_block_width(fb->format, 0) > 1) ||
1675
+ (drm_format_info_block_height(fb->format, 0) > 1));
20371676 info->pseudo_palette = fb_helper->pseudo_palette;
20381677 info->var.xres_virtual = fb->width;
20391678 info->var.yres_virtual = fb->height;
2040
- info->var.bits_per_pixel = fb->format->bpp[0];
1679
+ info->var.bits_per_pixel = fb->format->cpp[0] * 8;
20411680 info->var.accel_flags = FB_ACCELF_TEXT;
20421681 info->var.xoffset = 0;
20431682 info->var.yoffset = 0;
....@@ -2048,556 +1687,36 @@
20481687 info->var.xres = fb_width;
20491688 info->var.yres = fb_height;
20501689 }
2051
-EXPORT_SYMBOL(drm_fb_helper_fill_var);
20521690
2053
-static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
2054
- uint32_t maxX,
2055
- uint32_t maxY)
2056
-{
2057
- struct drm_connector *connector;
2058
- int i, count = 0;
2059
-
2060
- drm_fb_helper_for_each_connector(fb_helper, i) {
2061
- connector = fb_helper->connector_info[i]->connector;
2062
- count += connector->funcs->fill_modes(connector, maxX, maxY);
2063
- }
2064
-
2065
- return count;
2066
-}
2067
-
2068
-struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
2069
-{
2070
- struct drm_display_mode *mode;
2071
-
2072
- list_for_each_entry(mode, &fb_connector->connector->modes, head) {
2073
- if (mode->hdisplay > width ||
2074
- mode->vdisplay > height)
2075
- continue;
2076
- if (mode->type & DRM_MODE_TYPE_PREFERRED)
2077
- return mode;
2078
- }
2079
- return NULL;
2080
-}
2081
-EXPORT_SYMBOL(drm_has_preferred_mode);
2082
-
2083
-static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
2084
-{
2085
- return fb_connector->connector->cmdline_mode.specified;
2086
-}
2087
-
2088
-struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn)
2089
-{
2090
- struct drm_cmdline_mode *cmdline_mode;
2091
- struct drm_display_mode *mode;
2092
- bool prefer_non_interlace;
2093
-
2094
- cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
2095
- if (cmdline_mode->specified == false)
2096
- return NULL;
2097
-
2098
- /* attempt to find a matching mode in the list of modes
2099
- * we have gotten so far, if not add a CVT mode that conforms
2100
- */
2101
- if (cmdline_mode->rb || cmdline_mode->margins)
2102
- goto create_mode;
2103
-
2104
- prefer_non_interlace = !cmdline_mode->interlace;
2105
-again:
2106
- list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
2107
- /* check width/height */
2108
- if (mode->hdisplay != cmdline_mode->xres ||
2109
- mode->vdisplay != cmdline_mode->yres)
2110
- continue;
2111
-
2112
- if (cmdline_mode->refresh_specified) {
2113
- if (mode->vrefresh != cmdline_mode->refresh)
2114
- continue;
2115
- }
2116
-
2117
- if (cmdline_mode->interlace) {
2118
- if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
2119
- continue;
2120
- } else if (prefer_non_interlace) {
2121
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
2122
- continue;
2123
- }
2124
- return mode;
2125
- }
2126
-
2127
- if (prefer_non_interlace) {
2128
- prefer_non_interlace = false;
2129
- goto again;
2130
- }
2131
-
2132
-create_mode:
2133
- mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
2134
- cmdline_mode);
2135
- list_add(&mode->head, &fb_helper_conn->connector->modes);
2136
- return mode;
2137
-}
2138
-EXPORT_SYMBOL(drm_pick_cmdline_mode);
2139
-
2140
-static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
2141
-{
2142
- bool enable;
2143
-
2144
- if (connector->display_info.non_desktop)
2145
- return false;
2146
-
2147
- if (strict)
2148
- enable = connector->status == connector_status_connected;
2149
- else
2150
- enable = connector->status != connector_status_disconnected;
2151
-
2152
- return enable;
2153
-}
2154
-
2155
-static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
2156
- bool *enabled)
2157
-{
2158
- bool any_enabled = false;
2159
- struct drm_connector *connector;
2160
- int i = 0;
2161
-
2162
- drm_fb_helper_for_each_connector(fb_helper, i) {
2163
- connector = fb_helper->connector_info[i]->connector;
2164
- enabled[i] = drm_connector_enabled(connector, true);
2165
- DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
2166
- connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no");
2167
-
2168
- any_enabled |= enabled[i];
2169
- }
2170
-
2171
- if (any_enabled)
2172
- return;
2173
-
2174
- drm_fb_helper_for_each_connector(fb_helper, i) {
2175
- connector = fb_helper->connector_info[i]->connector;
2176
- enabled[i] = drm_connector_enabled(connector, false);
2177
- }
2178
-}
2179
-
2180
-static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
2181
- struct drm_display_mode **modes,
2182
- struct drm_fb_offset *offsets,
2183
- bool *enabled, int width, int height)
2184
-{
2185
- int count, i, j;
2186
- bool can_clone = false;
2187
- struct drm_fb_helper_connector *fb_helper_conn;
2188
- struct drm_display_mode *dmt_mode, *mode;
2189
-
2190
- /* only contemplate cloning in the single crtc case */
2191
- if (fb_helper->crtc_count > 1)
2192
- return false;
2193
-
2194
- count = 0;
2195
- drm_fb_helper_for_each_connector(fb_helper, i) {
2196
- if (enabled[i])
2197
- count++;
2198
- }
2199
-
2200
- /* only contemplate cloning if more than one connector is enabled */
2201
- if (count <= 1)
2202
- return false;
2203
-
2204
- /* check the command line or if nothing common pick 1024x768 */
2205
- can_clone = true;
2206
- drm_fb_helper_for_each_connector(fb_helper, i) {
2207
- if (!enabled[i])
2208
- continue;
2209
- fb_helper_conn = fb_helper->connector_info[i];
2210
- modes[i] = drm_pick_cmdline_mode(fb_helper_conn);
2211
- if (!modes[i]) {
2212
- can_clone = false;
2213
- break;
2214
- }
2215
- for (j = 0; j < i; j++) {
2216
- if (!enabled[j])
2217
- continue;
2218
- if (!drm_mode_match(modes[j], modes[i],
2219
- DRM_MODE_MATCH_TIMINGS |
2220
- DRM_MODE_MATCH_CLOCK |
2221
- DRM_MODE_MATCH_FLAGS |
2222
- DRM_MODE_MATCH_3D_FLAGS))
2223
- can_clone = false;
2224
- }
2225
- }
2226
-
2227
- if (can_clone) {
2228
- DRM_DEBUG_KMS("can clone using command line\n");
2229
- return true;
2230
- }
2231
-
2232
- /* try and find a 1024x768 mode on each connector */
2233
- can_clone = true;
2234
- dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false);
2235
-
2236
- drm_fb_helper_for_each_connector(fb_helper, i) {
2237
- if (!enabled[i])
2238
- continue;
2239
-
2240
- fb_helper_conn = fb_helper->connector_info[i];
2241
- list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
2242
- if (drm_mode_match(mode, dmt_mode,
2243
- DRM_MODE_MATCH_TIMINGS |
2244
- DRM_MODE_MATCH_CLOCK |
2245
- DRM_MODE_MATCH_FLAGS |
2246
- DRM_MODE_MATCH_3D_FLAGS))
2247
- modes[i] = mode;
2248
- }
2249
- if (!modes[i])
2250
- can_clone = false;
2251
- }
2252
-
2253
- if (can_clone) {
2254
- DRM_DEBUG_KMS("can clone using 1024x768\n");
2255
- return true;
2256
- }
2257
- DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
2258
- return false;
2259
-}
2260
-
2261
-static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper,
2262
- struct drm_display_mode **modes,
2263
- struct drm_fb_offset *offsets,
2264
- int idx,
2265
- int h_idx, int v_idx)
2266
-{
2267
- struct drm_fb_helper_connector *fb_helper_conn;
2268
- int i;
2269
- int hoffset = 0, voffset = 0;
2270
-
2271
- drm_fb_helper_for_each_connector(fb_helper, i) {
2272
- fb_helper_conn = fb_helper->connector_info[i];
2273
- if (!fb_helper_conn->connector->has_tile)
2274
- continue;
2275
-
2276
- if (!modes[i] && (h_idx || v_idx)) {
2277
- DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i,
2278
- fb_helper_conn->connector->base.id);
2279
- continue;
2280
- }
2281
- if (fb_helper_conn->connector->tile_h_loc < h_idx)
2282
- hoffset += modes[i]->hdisplay;
2283
-
2284
- if (fb_helper_conn->connector->tile_v_loc < v_idx)
2285
- voffset += modes[i]->vdisplay;
2286
- }
2287
- offsets[idx].x = hoffset;
2288
- offsets[idx].y = voffset;
2289
- DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx);
2290
- return 0;
2291
-}
2292
-
2293
-static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
2294
- struct drm_display_mode **modes,
2295
- struct drm_fb_offset *offsets,
2296
- bool *enabled, int width, int height)
2297
-{
2298
- struct drm_fb_helper_connector *fb_helper_conn;
2299
- const u64 mask = BIT_ULL(fb_helper->connector_count) - 1;
2300
- u64 conn_configured = 0;
2301
- int tile_pass = 0;
2302
- int i;
2303
-
2304
-retry:
2305
- drm_fb_helper_for_each_connector(fb_helper, i) {
2306
- fb_helper_conn = fb_helper->connector_info[i];
2307
-
2308
- if (conn_configured & BIT_ULL(i))
2309
- continue;
2310
-
2311
- if (enabled[i] == false) {
2312
- conn_configured |= BIT_ULL(i);
2313
- continue;
2314
- }
2315
-
2316
- /* first pass over all the untiled connectors */
2317
- if (tile_pass == 0 && fb_helper_conn->connector->has_tile)
2318
- continue;
2319
-
2320
- if (tile_pass == 1) {
2321
- if (fb_helper_conn->connector->tile_h_loc != 0 ||
2322
- fb_helper_conn->connector->tile_v_loc != 0)
2323
- continue;
2324
-
2325
- } else {
2326
- if (fb_helper_conn->connector->tile_h_loc != tile_pass - 1 &&
2327
- fb_helper_conn->connector->tile_v_loc != tile_pass - 1)
2328
- /* if this tile_pass doesn't cover any of the tiles - keep going */
2329
- continue;
2330
-
2331
- /*
2332
- * find the tile offsets for this pass - need to find
2333
- * all tiles left and above
2334
- */
2335
- drm_get_tile_offsets(fb_helper, modes, offsets,
2336
- i, fb_helper_conn->connector->tile_h_loc, fb_helper_conn->connector->tile_v_loc);
2337
- }
2338
- DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
2339
- fb_helper_conn->connector->base.id);
2340
-
2341
- /* got for command line mode first */
2342
- modes[i] = drm_pick_cmdline_mode(fb_helper_conn);
2343
- if (!modes[i]) {
2344
- DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n",
2345
- fb_helper_conn->connector->base.id, fb_helper_conn->connector->tile_group ? fb_helper_conn->connector->tile_group->id : 0);
2346
- modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height);
2347
- }
2348
- /* No preferred modes, pick one off the list */
2349
- if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) {
2350
- list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head)
2351
- break;
2352
- }
2353
- DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
2354
- "none");
2355
- conn_configured |= BIT_ULL(i);
2356
- }
2357
-
2358
- if ((conn_configured & mask) != mask) {
2359
- tile_pass++;
2360
- goto retry;
2361
- }
2362
- return true;
2363
-}
2364
-
2365
-static bool connector_has_possible_crtc(struct drm_connector *connector,
2366
- struct drm_crtc *crtc)
2367
-{
2368
- struct drm_encoder *encoder;
2369
- int i;
2370
-
2371
- drm_connector_for_each_possible_encoder(connector, encoder, i) {
2372
- if (encoder->possible_crtcs & drm_crtc_mask(crtc))
2373
- return true;
2374
- }
2375
-
2376
- return false;
2377
-}
2378
-
2379
-static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
2380
- struct drm_fb_helper_crtc **best_crtcs,
2381
- struct drm_display_mode **modes,
2382
- int n, int width, int height)
2383
-{
2384
- int c, o;
2385
- struct drm_connector *connector;
2386
- int my_score, best_score, score;
2387
- struct drm_fb_helper_crtc **crtcs, *crtc;
2388
- struct drm_fb_helper_connector *fb_helper_conn;
2389
-
2390
- if (n == fb_helper->connector_count)
2391
- return 0;
2392
-
2393
- fb_helper_conn = fb_helper->connector_info[n];
2394
- connector = fb_helper_conn->connector;
2395
-
2396
- best_crtcs[n] = NULL;
2397
- best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height);
2398
- if (modes[n] == NULL)
2399
- return best_score;
2400
-
2401
- crtcs = kcalloc(fb_helper->connector_count,
2402
- sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
2403
- if (!crtcs)
2404
- return best_score;
2405
-
2406
- my_score = 1;
2407
- if (connector->status == connector_status_connected)
2408
- my_score++;
2409
- if (drm_has_cmdline_mode(fb_helper_conn))
2410
- my_score++;
2411
- if (drm_has_preferred_mode(fb_helper_conn, width, height))
2412
- my_score++;
2413
-
2414
- /*
2415
- * select a crtc for this connector and then attempt to configure
2416
- * remaining connectors
2417
- */
2418
- for (c = 0; c < fb_helper->crtc_count; c++) {
2419
- crtc = &fb_helper->crtc_info[c];
2420
-
2421
- if (!connector_has_possible_crtc(connector,
2422
- crtc->mode_set.crtc))
2423
- continue;
2424
-
2425
- for (o = 0; o < n; o++)
2426
- if (best_crtcs[o] == crtc)
2427
- break;
2428
-
2429
- if (o < n) {
2430
- /* ignore cloning unless only a single crtc */
2431
- if (fb_helper->crtc_count > 1)
2432
- continue;
2433
-
2434
- if (!drm_mode_equal(modes[o], modes[n]))
2435
- continue;
2436
- }
2437
-
2438
- crtcs[n] = crtc;
2439
- memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *));
2440
- score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1,
2441
- width, height);
2442
- if (score > best_score) {
2443
- best_score = score;
2444
- memcpy(best_crtcs, crtcs,
2445
- fb_helper->connector_count *
2446
- sizeof(struct drm_fb_helper_crtc *));
2447
- }
2448
- }
2449
-
2450
- kfree(crtcs);
2451
- return best_score;
2452
-}
2453
-
2454
-/*
2455
- * This function checks if rotation is necessary because of panel orientation
2456
- * and if it is, if it is supported.
2457
- * If rotation is necessary and supported, its gets set in fb_crtc.rotation.
2458
- * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets
2459
- * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only
2460
- * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do
2461
- * the unsupported rotation.
1691
+/**
1692
+ * drm_fb_helper_fill_info - initializes fbdev information
1693
+ * @info: fbdev instance to set up
1694
+ * @fb_helper: fb helper instance to use as template
1695
+ * @sizes: describes fbdev size and scanout surface size
1696
+ *
1697
+ * Sets up the variable and fixed fbdev metainformation from the given fb helper
1698
+ * instance and the drm framebuffer allocated in &drm_fb_helper.fb.
1699
+ *
1700
+ * Drivers should call this (or their equivalent setup code) from their
1701
+ * &drm_fb_helper_funcs.fb_probe callback after having allocated the fbdev
1702
+ * backing storage framebuffer.
24621703 */
2463
-static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper,
2464
- struct drm_fb_helper_crtc *fb_crtc,
2465
- struct drm_connector *connector)
1704
+void drm_fb_helper_fill_info(struct fb_info *info,
1705
+ struct drm_fb_helper *fb_helper,
1706
+ struct drm_fb_helper_surface_size *sizes)
24661707 {
2467
- struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
2468
- uint64_t valid_mask = 0;
2469
- int i, rotation;
1708
+ struct drm_framebuffer *fb = fb_helper->fb;
24701709
2471
- fb_crtc->rotation = DRM_MODE_ROTATE_0;
1710
+ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
1711
+ drm_fb_helper_fill_var(info, fb_helper,
1712
+ sizes->fb_width, sizes->fb_height);
24721713
2473
- switch (connector->display_info.panel_orientation) {
2474
- case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
2475
- rotation = DRM_MODE_ROTATE_180;
2476
- break;
2477
- case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
2478
- rotation = DRM_MODE_ROTATE_90;
2479
- break;
2480
- case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
2481
- rotation = DRM_MODE_ROTATE_270;
2482
- break;
2483
- default:
2484
- rotation = DRM_MODE_ROTATE_0;
2485
- }
1714
+ info->par = fb_helper;
1715
+ snprintf(info->fix.id, sizeof(info->fix.id), "%sdrmfb",
1716
+ fb_helper->dev->driver->name);
24861717
2487
- /*
2488
- * TODO: support 90 / 270 degree hardware rotation,
2489
- * depending on the hardware this may require the framebuffer
2490
- * to be in a specific tiling format.
2491
- */
2492
- if (rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) {
2493
- fb_helper->sw_rotations |= rotation;
2494
- return;
2495
- }
2496
-
2497
- for (i = 0; i < plane->rotation_property->num_values; i++)
2498
- valid_mask |= (1ULL << plane->rotation_property->values[i]);
2499
-
2500
- if (!(rotation & valid_mask)) {
2501
- fb_helper->sw_rotations |= rotation;
2502
- return;
2503
- }
2504
-
2505
- fb_crtc->rotation = rotation;
2506
- /* Rotating in hardware, fbcon should not rotate */
2507
- fb_helper->sw_rotations |= DRM_MODE_ROTATE_0;
25081718 }
2509
-
2510
-static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
2511
- u32 width, u32 height)
2512
-{
2513
- struct drm_device *dev = fb_helper->dev;
2514
- struct drm_fb_helper_crtc **crtcs;
2515
- struct drm_display_mode **modes;
2516
- struct drm_fb_offset *offsets;
2517
- bool *enabled;
2518
- int i;
2519
-
2520
- DRM_DEBUG_KMS("\n");
2521
- /* prevent concurrent modification of connector_count by hotplug */
2522
- lockdep_assert_held(&fb_helper->lock);
2523
-
2524
- crtcs = kcalloc(fb_helper->connector_count,
2525
- sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
2526
- modes = kcalloc(fb_helper->connector_count,
2527
- sizeof(struct drm_display_mode *), GFP_KERNEL);
2528
- offsets = kcalloc(fb_helper->connector_count,
2529
- sizeof(struct drm_fb_offset), GFP_KERNEL);
2530
- enabled = kcalloc(fb_helper->connector_count,
2531
- sizeof(bool), GFP_KERNEL);
2532
- if (!crtcs || !modes || !enabled || !offsets) {
2533
- DRM_ERROR("Memory allocation failed\n");
2534
- goto out;
2535
- }
2536
-
2537
- mutex_lock(&fb_helper->dev->mode_config.mutex);
2538
- if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0)
2539
- DRM_DEBUG_KMS("No connectors reported connected with modes\n");
2540
- drm_enable_connectors(fb_helper, enabled);
2541
-
2542
- if (!(fb_helper->funcs->initial_config &&
2543
- fb_helper->funcs->initial_config(fb_helper, crtcs, modes,
2544
- offsets,
2545
- enabled, width, height))) {
2546
- memset(modes, 0, fb_helper->connector_count*sizeof(modes[0]));
2547
- memset(crtcs, 0, fb_helper->connector_count*sizeof(crtcs[0]));
2548
- memset(offsets, 0, fb_helper->connector_count*sizeof(offsets[0]));
2549
-
2550
- if (!drm_target_cloned(fb_helper, modes, offsets,
2551
- enabled, width, height) &&
2552
- !drm_target_preferred(fb_helper, modes, offsets,
2553
- enabled, width, height))
2554
- DRM_ERROR("Unable to find initial modes\n");
2555
-
2556
- DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n",
2557
- width, height);
2558
-
2559
- drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
2560
- }
2561
- mutex_unlock(&fb_helper->dev->mode_config.mutex);
2562
-
2563
- /* need to set the modesets up here for use later */
2564
- /* fill out the connector<->crtc mappings into the modesets */
2565
- for (i = 0; i < fb_helper->crtc_count; i++)
2566
- drm_fb_helper_modeset_release(fb_helper,
2567
- &fb_helper->crtc_info[i].mode_set);
2568
-
2569
- fb_helper->sw_rotations = 0;
2570
- drm_fb_helper_for_each_connector(fb_helper, i) {
2571
- struct drm_display_mode *mode = modes[i];
2572
- struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
2573
- struct drm_fb_offset *offset = &offsets[i];
2574
-
2575
- if (mode && fb_crtc) {
2576
- struct drm_mode_set *modeset = &fb_crtc->mode_set;
2577
- struct drm_connector *connector =
2578
- fb_helper->connector_info[i]->connector;
2579
-
2580
- DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
2581
- mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
2582
-
2583
- fb_crtc->desired_mode = mode;
2584
- fb_crtc->x = offset->x;
2585
- fb_crtc->y = offset->y;
2586
- modeset->mode = drm_mode_duplicate(dev,
2587
- fb_crtc->desired_mode);
2588
- drm_connector_get(connector);
2589
- drm_setup_crtc_rotation(fb_helper, fb_crtc, connector);
2590
- modeset->connectors[modeset->num_connectors++] = connector;
2591
- modeset->x = offset->x;
2592
- modeset->y = offset->y;
2593
- }
2594
- }
2595
-out:
2596
- kfree(crtcs);
2597
- kfree(modes);
2598
- kfree(offsets);
2599
- kfree(enabled);
2600
-}
1719
+EXPORT_SYMBOL(drm_fb_helper_fill_info);
26011720
26021721 /*
26031722 * This is a continuation of drm_setup_crtcs() that sets up anything related
....@@ -2608,17 +1727,30 @@
26081727 */
26091728 static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
26101729 {
1730
+ struct drm_client_dev *client = &fb_helper->client;
1731
+ struct drm_connector_list_iter conn_iter;
26111732 struct fb_info *info = fb_helper->fbdev;
2612
- int i;
1733
+ unsigned int rotation, sw_rotations = 0;
1734
+ struct drm_connector *connector;
1735
+ struct drm_mode_set *modeset;
26131736
2614
- for (i = 0; i < fb_helper->crtc_count; i++)
2615
- if (fb_helper->crtc_info[i].mode_set.num_connectors)
2616
- fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
1737
+ mutex_lock(&client->modeset_mutex);
1738
+ drm_client_for_each_modeset(modeset, client) {
1739
+ if (!modeset->num_connectors)
1740
+ continue;
26171741
2618
- mutex_lock(&fb_helper->dev->mode_config.mutex);
2619
- drm_fb_helper_for_each_connector(fb_helper, i) {
2620
- struct drm_connector *connector =
2621
- fb_helper->connector_info[i]->connector;
1742
+ modeset->fb = fb_helper->fb;
1743
+
1744
+ if (drm_client_rotation(modeset, &rotation))
1745
+ /* Rotating in hardware, fbcon should not rotate */
1746
+ sw_rotations |= DRM_MODE_ROTATE_0;
1747
+ else
1748
+ sw_rotations |= rotation;
1749
+ }
1750
+ mutex_unlock(&client->modeset_mutex);
1751
+
1752
+ drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
1753
+ drm_client_for_each_connector_iter(connector, &conn_iter) {
26221754
26231755 /* use first connected connector for the physical dimensions */
26241756 if (connector->status == connector_status_connected) {
....@@ -2627,9 +1759,9 @@
26271759 break;
26281760 }
26291761 }
2630
- mutex_unlock(&fb_helper->dev->mode_config.mutex);
1762
+ drm_connector_list_iter_end(&conn_iter);
26311763
2632
- switch (fb_helper->sw_rotations) {
1764
+ switch (sw_rotations) {
26331765 case DRM_MODE_ROTATE_0:
26341766 info->fbcon_rotate_hint = FB_ROTATE_UR;
26351767 break;
....@@ -2665,7 +1797,7 @@
26651797 width = dev->mode_config.max_width;
26661798 height = dev->mode_config.max_height;
26671799
2668
- drm_setup_crtcs(fb_helper, width, height);
1800
+ drm_client_modeset_probe(&fb_helper->client, width, height);
26691801 ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
26701802 if (ret < 0) {
26711803 if (ret == -EAGAIN) {
....@@ -2683,6 +1815,12 @@
26831815
26841816 info = fb_helper->fbdev;
26851817 info->var.pixclock = 0;
1818
+ /* Shamelessly allow physical address leaking to userspace */
1819
+#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
1820
+ if (!drm_leak_fbdev_smem)
1821
+#endif
1822
+ /* don't leak any physical addresses to userspace */
1823
+ info->flags |= FBINFO_HIDE_SMEM_START;
26861824
26871825 /* Need to drop locks to avoid recursive deadlock in
26881826 * register_framebuffer. This is ok because the only thing left to do is
....@@ -2693,7 +1831,7 @@
26931831 if (ret < 0)
26941832 return ret;
26951833
2696
- dev_info(dev->dev, "fb%d: %s frame buffer device\n",
1834
+ drm_info(dev, "fb%d: %s frame buffer device\n",
26971835 info->node, info->fix.id);
26981836
26991837 mutex_lock(&kernel_fb_helper_lock);
....@@ -2720,9 +1858,8 @@
27201858 *
27211859 * This function will call down into the &drm_fb_helper_funcs.fb_probe callback
27221860 * to let the driver allocate and initialize the fbdev info structure and the
2723
- * drm framebuffer used to back the fbdev. drm_fb_helper_fill_var() and
2724
- * drm_fb_helper_fill_fix() are provided as helpers to setup simple default
2725
- * values for the fbdev info structure.
1861
+ * drm framebuffer used to back the fbdev. drm_fb_helper_fill_info() is provided
1862
+ * as a helper to setup simple default values for the fbdev info structure.
27261863 *
27271864 * HANG DEBUGGING:
27281865 *
....@@ -2797,15 +1934,17 @@
27971934 return err;
27981935 }
27991936
2800
- if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
1937
+ if (!fb_helper->fb || !drm_master_internal_acquire(fb_helper->dev)) {
28011938 fb_helper->delayed_hotplug = true;
28021939 mutex_unlock(&fb_helper->lock);
28031940 return err;
28041941 }
28051942
2806
- DRM_DEBUG_KMS("\n");
1943
+ drm_master_internal_release(fb_helper->dev);
28071944
2808
- drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height);
1945
+ drm_dbg_kms(fb_helper->dev, "\n");
1946
+
1947
+ drm_client_modeset_probe(&fb_helper->client, fb_helper->fb->width, fb_helper->fb->height);
28091948 drm_setup_crtcs_fb(fb_helper);
28101949 mutex_unlock(&fb_helper->lock);
28111950
....@@ -2814,120 +1953,6 @@
28141953 return 0;
28151954 }
28161955 EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
2817
-
2818
-/**
2819
- * drm_fb_helper_fbdev_setup() - Setup fbdev emulation
2820
- * @dev: DRM device
2821
- * @fb_helper: fbdev helper structure to set up
2822
- * @funcs: fbdev helper functions
2823
- * @preferred_bpp: Preferred bits per pixel for the device.
2824
- * @dev->mode_config.preferred_depth is used if this is zero.
2825
- * @max_conn_count: Maximum number of connectors.
2826
- * @dev->mode_config.num_connector is used if this is zero.
2827
- *
2828
- * This function sets up fbdev emulation and registers fbdev for access by
2829
- * userspace. If all connectors are disconnected, setup is deferred to the next
2830
- * time drm_fb_helper_hotplug_event() is called.
2831
- * The caller must to provide a &drm_fb_helper_funcs->fb_probe callback
2832
- * function.
2833
- *
2834
- * See also: drm_fb_helper_initial_config()
2835
- *
2836
- * Returns:
2837
- * Zero on success or negative error code on failure.
2838
- */
2839
-int drm_fb_helper_fbdev_setup(struct drm_device *dev,
2840
- struct drm_fb_helper *fb_helper,
2841
- const struct drm_fb_helper_funcs *funcs,
2842
- unsigned int preferred_bpp,
2843
- unsigned int max_conn_count)
2844
-{
2845
- int ret;
2846
-
2847
- if (!preferred_bpp)
2848
- preferred_bpp = dev->mode_config.preferred_depth;
2849
- if (!preferred_bpp)
2850
- preferred_bpp = 32;
2851
-
2852
- if (!max_conn_count)
2853
- max_conn_count = dev->mode_config.num_connector;
2854
- if (!max_conn_count) {
2855
- DRM_DEV_ERROR(dev->dev, "No connectors\n");
2856
- return -EINVAL;
2857
- }
2858
-
2859
- drm_fb_helper_prepare(dev, fb_helper, funcs);
2860
-
2861
- ret = drm_fb_helper_init(dev, fb_helper, max_conn_count);
2862
- if (ret < 0) {
2863
- DRM_DEV_ERROR(dev->dev, "Failed to initialize fbdev helper\n");
2864
- return ret;
2865
- }
2866
-
2867
- ret = drm_fb_helper_single_add_all_connectors(fb_helper);
2868
- if (ret < 0) {
2869
- DRM_DEV_ERROR(dev->dev, "Failed to add connectors\n");
2870
- goto err_drm_fb_helper_fini;
2871
- }
2872
-
2873
- if (!drm_drv_uses_atomic_modeset(dev))
2874
- drm_helper_disable_unused_functions(dev);
2875
-
2876
- ret = drm_fb_helper_initial_config(fb_helper, preferred_bpp);
2877
- if (ret < 0) {
2878
- DRM_DEV_ERROR(dev->dev, "Failed to set fbdev configuration\n");
2879
- goto err_drm_fb_helper_fini;
2880
- }
2881
-
2882
- return 0;
2883
-
2884
-err_drm_fb_helper_fini:
2885
- drm_fb_helper_fbdev_teardown(dev);
2886
-
2887
- return ret;
2888
-}
2889
-EXPORT_SYMBOL(drm_fb_helper_fbdev_setup);
2890
-
2891
-/**
2892
- * drm_fb_helper_fbdev_teardown - Tear down fbdev emulation
2893
- * @dev: DRM device
2894
- *
2895
- * This function unregisters fbdev if not already done and cleans up the
2896
- * associated resources including the &drm_framebuffer.
2897
- * The driver is responsible for freeing the &drm_fb_helper structure which is
2898
- * stored in &drm_device->fb_helper. Do note that this pointer has been cleared
2899
- * when this function returns.
2900
- *
2901
- * In order to support device removal/unplug while file handles are still open,
2902
- * drm_fb_helper_unregister_fbi() should be called on device removal and
2903
- * drm_fb_helper_fbdev_teardown() in the &drm_driver->release callback when
2904
- * file handles are closed.
2905
- */
2906
-void drm_fb_helper_fbdev_teardown(struct drm_device *dev)
2907
-{
2908
- struct drm_fb_helper *fb_helper = dev->fb_helper;
2909
- struct fb_ops *fbops = NULL;
2910
-
2911
- if (!fb_helper)
2912
- return;
2913
-
2914
- /* Unregister if it hasn't been done already */
2915
- if (fb_helper->fbdev && fb_helper->fbdev->dev)
2916
- drm_fb_helper_unregister_fbi(fb_helper);
2917
-
2918
- if (fb_helper->fbdev && fb_helper->fbdev->fbdefio) {
2919
- fb_deferred_io_cleanup(fb_helper->fbdev);
2920
- kfree(fb_helper->fbdev->fbdefio);
2921
- fbops = fb_helper->fbdev->fbops;
2922
- }
2923
-
2924
- drm_fb_helper_fini(fb_helper);
2925
- kfree(fbops);
2926
-
2927
- if (fb_helper->fb)
2928
- drm_framebuffer_remove(fb_helper->fb);
2929
-}
2930
-EXPORT_SYMBOL(drm_fb_helper_fbdev_teardown);
29311956
29321957 /**
29331958 * drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation
....@@ -2982,7 +2007,6 @@
29822007 static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper)
29832008 {
29842009 struct fb_info *fbi = fb_helper->fbdev;
2985
- struct fb_ops *fbops = NULL;
29862010 void *shadow = NULL;
29872011
29882012 if (!fb_helper->dev)
....@@ -2991,15 +2015,11 @@
29912015 if (fbi && fbi->fbdefio) {
29922016 fb_deferred_io_cleanup(fbi);
29932017 shadow = fbi->screen_buffer;
2994
- fbops = fbi->fbops;
29952018 }
29962019
29972020 drm_fb_helper_fini(fb_helper);
29982021
2999
- if (shadow) {
3000
- vfree(shadow);
3001
- kfree(fbops);
3002
- }
2022
+ vfree(shadow);
30032023
30042024 drm_client_framebuffer_delete(fb_helper->buffer);
30052025 }
....@@ -3007,16 +2027,8 @@
30072027 static void drm_fbdev_release(struct drm_fb_helper *fb_helper)
30082028 {
30092029 drm_fbdev_cleanup(fb_helper);
3010
-
3011
- /*
3012
- * FIXME:
3013
- * Remove conditional when all CMA drivers have been moved over to using
3014
- * drm_fbdev_generic_setup().
3015
- */
3016
- if (fb_helper->client.funcs) {
3017
- drm_client_release(&fb_helper->client);
3018
- kfree(fb_helper);
3019
- }
2030
+ drm_client_release(&fb_helper->client);
2031
+ kfree(fb_helper);
30202032 }
30212033
30222034 /*
....@@ -3038,7 +2050,7 @@
30382050 return -ENODEV;
30392051 }
30402052
3041
-static struct fb_ops drm_fbdev_fb_ops = {
2053
+static const struct fb_ops drm_fbdev_fb_ops = {
30422054 .owner = THIS_MODULE,
30432055 DRM_FB_HELPER_DEFAULT_OPS,
30442056 .fb_open = drm_fbdev_fb_open,
....@@ -3057,31 +2069,26 @@
30572069 .deferred_io = drm_fb_helper_deferred_io,
30582070 };
30592071
3060
-/**
3061
- * drm_fb_helper_generic_probe - Generic fbdev emulation probe helper
3062
- * @fb_helper: fbdev helper structure
3063
- * @sizes: describes fbdev size and scanout surface size
3064
- *
3065
- * This function uses the client API to crate a framebuffer backed by a dumb buffer.
2072
+/*
2073
+ * This function uses the client API to create a framebuffer backed by a dumb buffer.
30662074 *
30672075 * The _sys_ versions are used for &fb_ops.fb_read, fb_write, fb_fillrect,
30682076 * fb_copyarea, fb_imageblit.
3069
- *
3070
- * Returns:
3071
- * Zero on success or negative error code on failure.
30722077 */
3073
-int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
3074
- struct drm_fb_helper_surface_size *sizes)
2078
+static int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
2079
+ struct drm_fb_helper_surface_size *sizes)
30752080 {
30762081 struct drm_client_dev *client = &fb_helper->client;
2082
+ struct drm_device *dev = fb_helper->dev;
30772083 struct drm_client_buffer *buffer;
30782084 struct drm_framebuffer *fb;
30792085 struct fb_info *fbi;
30802086 u32 format;
2087
+ void *vaddr;
30812088
3082
- DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
3083
- sizes->surface_width, sizes->surface_height,
3084
- sizes->surface_bpp);
2089
+ drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n",
2090
+ sizes->surface_width, sizes->surface_height,
2091
+ sizes->surface_bpp);
30852092
30862093 format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
30872094 buffer = drm_client_framebuffer_create(client, sizes->surface_width,
....@@ -3097,49 +2104,37 @@
30972104 if (IS_ERR(fbi))
30982105 return PTR_ERR(fbi);
30992106
3100
- fbi->par = fb_helper;
31012107 fbi->fbops = &drm_fbdev_fb_ops;
31022108 fbi->screen_size = fb->height * fb->pitches[0];
31032109 fbi->fix.smem_len = fbi->screen_size;
3104
- fbi->screen_buffer = buffer->vaddr;
3105
- /* Shamelessly leak the physical address to user-space */
3106
-#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
3107
- if (drm_leak_fbdev_smem && fbi->fix.smem_start == 0)
3108
- fbi->fix.smem_start =
3109
- page_to_phys(virt_to_page(fbi->screen_buffer));
3110
-#endif
3111
- strcpy(fbi->fix.id, "DRM emulated");
31122110
3113
- drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth);
3114
- drm_fb_helper_fill_var(fbi, fb_helper, sizes->fb_width, sizes->fb_height);
2111
+ drm_fb_helper_fill_info(fbi, fb_helper, sizes);
31152112
3116
- if (fb->funcs->dirty) {
3117
- struct fb_ops *fbops;
3118
- void *shadow;
3119
-
3120
- /*
3121
- * fb_deferred_io_cleanup() clears &fbops->fb_mmap so a per
3122
- * instance version is necessary.
3123
- */
3124
- fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
3125
- shadow = vzalloc(fbi->screen_size);
3126
- if (!fbops || !shadow) {
3127
- kfree(fbops);
3128
- vfree(shadow);
2113
+ if (drm_fbdev_use_shadow_fb(fb_helper)) {
2114
+ fbi->screen_buffer = vzalloc(fbi->screen_size);
2115
+ if (!fbi->screen_buffer)
31292116 return -ENOMEM;
3130
- }
31312117
3132
- *fbops = *fbi->fbops;
3133
- fbi->fbops = fbops;
3134
- fbi->screen_buffer = shadow;
31352118 fbi->fbdefio = &drm_fbdev_defio;
31362119
31372120 fb_deferred_io_init(fbi);
2121
+ } else {
2122
+ /* buffer is mapped for HW framebuffer */
2123
+ vaddr = drm_client_buffer_vmap(fb_helper->buffer);
2124
+ if (IS_ERR(vaddr))
2125
+ return PTR_ERR(vaddr);
2126
+
2127
+ fbi->screen_buffer = vaddr;
2128
+ /* Shamelessly leak the physical address to user-space */
2129
+#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
2130
+ if (drm_leak_fbdev_smem && fbi->fix.smem_start == 0)
2131
+ fbi->fix.smem_start =
2132
+ page_to_phys(virt_to_page(fbi->screen_buffer));
2133
+#endif
31382134 }
31392135
31402136 return 0;
31412137 }
3142
-EXPORT_SYMBOL(drm_fb_helper_generic_probe);
31432138
31442139 static const struct drm_fb_helper_funcs drm_fb_helper_generic_funcs = {
31452140 .fb_probe = drm_fb_helper_generic_probe,
....@@ -3176,18 +2171,16 @@
31762171 if (dev->fb_helper)
31772172 return drm_fb_helper_hotplug_event(dev->fb_helper);
31782173
3179
- if (!dev->mode_config.num_connector)
2174
+ if (!dev->mode_config.num_connector) {
2175
+ drm_dbg_kms(dev, "No connectors found, will not create framebuffer!\n");
31802176 return 0;
2177
+ }
31812178
31822179 drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs);
31832180
3184
- ret = drm_fb_helper_init(dev, fb_helper, dev->mode_config.num_connector);
2181
+ ret = drm_fb_helper_init(dev, fb_helper);
31852182 if (ret)
31862183 goto err;
3187
-
3188
- ret = drm_fb_helper_single_add_all_connectors(fb_helper);
3189
- if (ret)
3190
- goto err_cleanup;
31912184
31922185 if (!drm_drv_uses_atomic_modeset(dev))
31932186 drm_helper_disable_unused_functions(dev);
....@@ -3204,7 +2197,7 @@
32042197 fb_helper->dev = NULL;
32052198 fb_helper->fbdev = NULL;
32062199
3207
- DRM_DEV_ERROR(dev->dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
2200
+ drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
32082201
32092202 return ret;
32102203 }
....@@ -3217,13 +2210,15 @@
32172210 };
32182211
32192212 /**
3220
- * drm_fb_helper_generic_fbdev_setup() - Setup generic fbdev emulation
2213
+ * drm_fbdev_generic_setup() - Setup generic fbdev emulation
32212214 * @dev: DRM device
32222215 * @preferred_bpp: Preferred bits per pixel for the device.
32232216 * @dev->mode_config.preferred_depth is used if this is zero.
32242217 *
32252218 * This function sets up generic fbdev emulation for drivers that supports
32262219 * dumb buffers with a virtual address and that can be mmap'ed.
2220
+ * drm_fbdev_generic_setup() shall be called after the DRM driver registered
2221
+ * the new DRM device with drm_dev_register().
32272222 *
32282223 * Restore, hotplug events and teardown are all taken care of. Drivers that do
32292224 * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
....@@ -3231,30 +2226,39 @@
32312226 *
32322227 * Drivers that set the dirty callback on their framebuffer will get a shadow
32332228 * fbdev buffer that is blitted onto the real buffer. This is done in order to
3234
- * make deferred I/O work with all kinds of buffers.
2229
+ * make deferred I/O work with all kinds of buffers. A shadow buffer can be
2230
+ * requested explicitly by setting struct drm_mode_config.prefer_shadow or
2231
+ * struct drm_mode_config.prefer_shadow_fbdev to true beforehand. This is
2232
+ * required to use generic fbdev emulation with SHMEM helpers.
32352233 *
32362234 * This function is safe to call even when there are no connectors present.
32372235 * Setup will be retried on the next hotplug event.
32382236 *
3239
- * Returns:
3240
- * Zero on success or negative error code on failure.
2237
+ * The fbdev is destroyed by drm_dev_unregister().
32412238 */
3242
-int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
2239
+void drm_fbdev_generic_setup(struct drm_device *dev,
2240
+ unsigned int preferred_bpp)
32432241 {
32442242 struct drm_fb_helper *fb_helper;
32452243 int ret;
32462244
2245
+ drm_WARN(dev, !dev->registered, "Device has not been registered.\n");
2246
+ drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n");
2247
+
32472248 if (!drm_fbdev_emulation)
3248
- return 0;
2249
+ return;
32492250
32502251 fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
3251
- if (!fb_helper)
3252
- return -ENOMEM;
2252
+ if (!fb_helper) {
2253
+ drm_err(dev, "Failed to allocate fb_helper\n");
2254
+ return;
2255
+ }
32532256
32542257 ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
32552258 if (ret) {
32562259 kfree(fb_helper);
3257
- return ret;
2260
+ drm_err(dev, "Failed to register client: %d\n", ret);
2261
+ return;
32582262 }
32592263
32602264 if (!preferred_bpp)
....@@ -3263,31 +2267,10 @@
32632267 preferred_bpp = 32;
32642268 fb_helper->preferred_bpp = preferred_bpp;
32652269
3266
- drm_fbdev_client_hotplug(&fb_helper->client);
2270
+ ret = drm_fbdev_client_hotplug(&fb_helper->client);
2271
+ if (ret)
2272
+ drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
32672273
3268
- drm_client_add(&fb_helper->client);
3269
-
3270
- return 0;
2274
+ drm_client_register(&fb_helper->client);
32712275 }
32722276 EXPORT_SYMBOL(drm_fbdev_generic_setup);
3273
-
3274
-/* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
3275
- * but the module doesn't depend on any fb console symbols. At least
3276
- * attempt to load fbcon to avoid leaving the system without a usable console.
3277
- */
3278
-int __init drm_fb_helper_modinit(void)
3279
-{
3280
-#if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT)
3281
- const char name[] = "fbcon";
3282
- struct module *fbcon;
3283
-
3284
- mutex_lock(&module_mutex);
3285
- fbcon = find_module(name);
3286
- mutex_unlock(&module_mutex);
3287
-
3288
- if (!fbcon)
3289
- request_module_nowait(name);
3290
-#endif
3291
- return 0;
3292
-}
3293
-EXPORT_SYMBOL(drm_fb_helper_modinit);