Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/gpu/drm/drm_crtc_helper.c
15111 views
1
/*
2
* Copyright (c) 2006-2008 Intel Corporation
3
* Copyright (c) 2007 Dave Airlie <[email protected]>
4
*
5
* DRM core CRTC related functions
6
*
7
* Permission to use, copy, modify, distribute, and sell this software and its
8
* documentation for any purpose is hereby granted without fee, provided that
9
* the above copyright notice appear in all copies and that both that copyright
10
* notice and this permission notice appear in supporting documentation, and
11
* that the name of the copyright holders not be used in advertising or
12
* publicity pertaining to distribution of the software without specific,
13
* written prior permission. The copyright holders make no representations
14
* about the suitability of this software for any purpose. It is provided "as
15
* is" without express or implied warranty.
16
*
17
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23
* OF THIS SOFTWARE.
24
*
25
* Authors:
26
* Keith Packard
27
* Eric Anholt <[email protected]>
28
* Dave Airlie <[email protected]>
29
* Jesse Barnes <[email protected]>
30
*/
31
32
#include "drmP.h"
33
#include "drm_crtc.h"
34
#include "drm_crtc_helper.h"
35
#include "drm_fb_helper.h"
36
37
static bool drm_kms_helper_poll = true;
38
module_param_named(poll, drm_kms_helper_poll, bool, 0600);
39
40
static void drm_mode_validate_flag(struct drm_connector *connector,
41
int flags)
42
{
43
struct drm_display_mode *mode, *t;
44
45
if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE))
46
return;
47
48
list_for_each_entry_safe(mode, t, &connector->modes, head) {
49
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
50
!(flags & DRM_MODE_FLAG_INTERLACE))
51
mode->status = MODE_NO_INTERLACE;
52
if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
53
!(flags & DRM_MODE_FLAG_DBLSCAN))
54
mode->status = MODE_NO_DBLESCAN;
55
}
56
57
return;
58
}
59
60
/**
61
* drm_helper_probe_single_connector_modes - get complete set of display modes
62
* @dev: DRM device
63
* @maxX: max width for modes
64
* @maxY: max height for modes
65
*
66
* LOCKING:
67
* Caller must hold mode config lock.
68
*
69
* Based on @dev's mode_config layout, scan all the connectors and try to detect
70
* modes on them. Modes will first be added to the connector's probed_modes
71
* list, then culled (based on validity and the @maxX, @maxY parameters) and
72
* put into the normal modes list.
73
*
74
* Intended to be used either at bootup time or when major configuration
75
* changes have occurred.
76
*
77
* FIXME: take into account monitor limits
78
*
79
* RETURNS:
80
* Number of modes found on @connector.
81
*/
82
int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
83
uint32_t maxX, uint32_t maxY)
84
{
85
struct drm_device *dev = connector->dev;
86
struct drm_display_mode *mode, *t;
87
struct drm_connector_helper_funcs *connector_funcs =
88
connector->helper_private;
89
int count = 0;
90
int mode_flags = 0;
91
92
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
93
drm_get_connector_name(connector));
94
/* set all modes to the unverified state */
95
list_for_each_entry_safe(mode, t, &connector->modes, head)
96
mode->status = MODE_UNVERIFIED;
97
98
if (connector->force) {
99
if (connector->force == DRM_FORCE_ON)
100
connector->status = connector_status_connected;
101
else
102
connector->status = connector_status_disconnected;
103
if (connector->funcs->force)
104
connector->funcs->force(connector);
105
} else {
106
connector->status = connector->funcs->detect(connector, true);
107
drm_kms_helper_poll_enable(dev);
108
}
109
110
if (connector->status == connector_status_disconnected) {
111
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
112
connector->base.id, drm_get_connector_name(connector));
113
drm_mode_connector_update_edid_property(connector, NULL);
114
goto prune;
115
}
116
117
count = (*connector_funcs->get_modes)(connector);
118
if (count == 0 && connector->status == connector_status_connected)
119
count = drm_add_modes_noedid(connector, 1024, 768);
120
if (count == 0)
121
goto prune;
122
123
drm_mode_connector_list_update(connector);
124
125
if (maxX && maxY)
126
drm_mode_validate_size(dev, &connector->modes, maxX,
127
maxY, 0);
128
129
if (connector->interlace_allowed)
130
mode_flags |= DRM_MODE_FLAG_INTERLACE;
131
if (connector->doublescan_allowed)
132
mode_flags |= DRM_MODE_FLAG_DBLSCAN;
133
drm_mode_validate_flag(connector, mode_flags);
134
135
list_for_each_entry_safe(mode, t, &connector->modes, head) {
136
if (mode->status == MODE_OK)
137
mode->status = connector_funcs->mode_valid(connector,
138
mode);
139
}
140
141
prune:
142
drm_mode_prune_invalid(dev, &connector->modes, true);
143
144
if (list_empty(&connector->modes))
145
return 0;
146
147
drm_mode_sort(&connector->modes);
148
149
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
150
drm_get_connector_name(connector));
151
list_for_each_entry_safe(mode, t, &connector->modes, head) {
152
mode->vrefresh = drm_mode_vrefresh(mode);
153
154
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
155
drm_mode_debug_printmodeline(mode);
156
}
157
158
return count;
159
}
160
EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
161
162
/**
163
* drm_helper_encoder_in_use - check if a given encoder is in use
164
* @encoder: encoder to check
165
*
166
* LOCKING:
167
* Caller must hold mode config lock.
168
*
169
* Walk @encoders's DRM device's mode_config and see if it's in use.
170
*
171
* RETURNS:
172
* True if @encoder is part of the mode_config, false otherwise.
173
*/
174
bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
175
{
176
struct drm_connector *connector;
177
struct drm_device *dev = encoder->dev;
178
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
179
if (connector->encoder == encoder)
180
return true;
181
return false;
182
}
183
EXPORT_SYMBOL(drm_helper_encoder_in_use);
184
185
/**
186
* drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
187
* @crtc: CRTC to check
188
*
189
* LOCKING:
190
* Caller must hold mode config lock.
191
*
192
* Walk @crtc's DRM device's mode_config and see if it's in use.
193
*
194
* RETURNS:
195
* True if @crtc is part of the mode_config, false otherwise.
196
*/
197
bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
198
{
199
struct drm_encoder *encoder;
200
struct drm_device *dev = crtc->dev;
201
/* FIXME: Locking around list access? */
202
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
203
if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
204
return true;
205
return false;
206
}
207
EXPORT_SYMBOL(drm_helper_crtc_in_use);
208
209
static void
210
drm_encoder_disable(struct drm_encoder *encoder)
211
{
212
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
213
214
if (encoder_funcs->disable)
215
(*encoder_funcs->disable)(encoder);
216
else
217
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
218
}
219
220
/**
221
* drm_helper_disable_unused_functions - disable unused objects
222
* @dev: DRM device
223
*
224
* LOCKING:
225
* Caller must hold mode config lock.
226
*
227
* If an connector or CRTC isn't part of @dev's mode_config, it can be disabled
228
* by calling its dpms function, which should power it off.
229
*/
230
void drm_helper_disable_unused_functions(struct drm_device *dev)
231
{
232
struct drm_encoder *encoder;
233
struct drm_connector *connector;
234
struct drm_crtc *crtc;
235
236
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
237
if (!connector->encoder)
238
continue;
239
if (connector->status == connector_status_disconnected)
240
connector->encoder = NULL;
241
}
242
243
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
244
if (!drm_helper_encoder_in_use(encoder)) {
245
drm_encoder_disable(encoder);
246
/* disconnector encoder from any connector */
247
encoder->crtc = NULL;
248
}
249
}
250
251
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
252
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
253
crtc->enabled = drm_helper_crtc_in_use(crtc);
254
if (!crtc->enabled) {
255
if (crtc_funcs->disable)
256
(*crtc_funcs->disable)(crtc);
257
else
258
(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
259
crtc->fb = NULL;
260
}
261
}
262
}
263
EXPORT_SYMBOL(drm_helper_disable_unused_functions);
264
265
/**
266
* drm_encoder_crtc_ok - can a given crtc drive a given encoder?
267
* @encoder: encoder to test
268
* @crtc: crtc to test
269
*
270
* Return false if @encoder can't be driven by @crtc, true otherwise.
271
*/
272
static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
273
struct drm_crtc *crtc)
274
{
275
struct drm_device *dev;
276
struct drm_crtc *tmp;
277
int crtc_mask = 1;
278
279
WARN(!crtc, "checking null crtc?\n");
280
281
dev = crtc->dev;
282
283
list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
284
if (tmp == crtc)
285
break;
286
crtc_mask <<= 1;
287
}
288
289
if (encoder->possible_crtcs & crtc_mask)
290
return true;
291
return false;
292
}
293
294
/*
295
* Check the CRTC we're going to map each output to vs. its current
296
* CRTC. If they don't match, we have to disable the output and the CRTC
297
* since the driver will have to re-route things.
298
*/
299
static void
300
drm_crtc_prepare_encoders(struct drm_device *dev)
301
{
302
struct drm_encoder_helper_funcs *encoder_funcs;
303
struct drm_encoder *encoder;
304
305
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
306
encoder_funcs = encoder->helper_private;
307
/* Disable unused encoders */
308
if (encoder->crtc == NULL)
309
drm_encoder_disable(encoder);
310
/* Disable encoders whose CRTC is about to change */
311
if (encoder_funcs->get_crtc &&
312
encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
313
drm_encoder_disable(encoder);
314
}
315
}
316
317
/**
318
* drm_crtc_set_mode - set a mode
319
* @crtc: CRTC to program
320
* @mode: mode to use
321
* @x: width of mode
322
* @y: height of mode
323
*
324
* LOCKING:
325
* Caller must hold mode config lock.
326
*
327
* Try to set @mode on @crtc. Give @crtc and its associated connectors a chance
328
* to fixup or reject the mode prior to trying to set it.
329
*
330
* RETURNS:
331
* True if the mode was set successfully, or false otherwise.
332
*/
333
bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
334
struct drm_display_mode *mode,
335
int x, int y,
336
struct drm_framebuffer *old_fb)
337
{
338
struct drm_device *dev = crtc->dev;
339
struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
340
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
341
struct drm_encoder_helper_funcs *encoder_funcs;
342
int saved_x, saved_y;
343
struct drm_encoder *encoder;
344
bool ret = true;
345
346
crtc->enabled = drm_helper_crtc_in_use(crtc);
347
if (!crtc->enabled)
348
return true;
349
350
adjusted_mode = drm_mode_duplicate(dev, mode);
351
352
saved_hwmode = crtc->hwmode;
353
saved_mode = crtc->mode;
354
saved_x = crtc->x;
355
saved_y = crtc->y;
356
357
/* Update crtc values up front so the driver can rely on them for mode
358
* setting.
359
*/
360
crtc->mode = *mode;
361
crtc->x = x;
362
crtc->y = y;
363
364
/* Pass our mode to the connectors and the CRTC to give them a chance to
365
* adjust it according to limitations or connector properties, and also
366
* a chance to reject the mode entirely.
367
*/
368
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
369
370
if (encoder->crtc != crtc)
371
continue;
372
encoder_funcs = encoder->helper_private;
373
if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
374
adjusted_mode))) {
375
goto done;
376
}
377
}
378
379
if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
380
goto done;
381
}
382
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
383
384
/* Prepare the encoders and CRTCs before setting the mode. */
385
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
386
387
if (encoder->crtc != crtc)
388
continue;
389
encoder_funcs = encoder->helper_private;
390
/* Disable the encoders as the first thing we do. */
391
encoder_funcs->prepare(encoder);
392
}
393
394
drm_crtc_prepare_encoders(dev);
395
396
crtc_funcs->prepare(crtc);
397
398
/* Set up the DPLL and any encoders state that needs to adjust or depend
399
* on the DPLL.
400
*/
401
ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
402
if (!ret)
403
goto done;
404
405
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
406
407
if (encoder->crtc != crtc)
408
continue;
409
410
DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
411
encoder->base.id, drm_get_encoder_name(encoder),
412
mode->base.id, mode->name);
413
encoder_funcs = encoder->helper_private;
414
encoder_funcs->mode_set(encoder, mode, adjusted_mode);
415
}
416
417
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
418
crtc_funcs->commit(crtc);
419
420
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
421
422
if (encoder->crtc != crtc)
423
continue;
424
425
encoder_funcs = encoder->helper_private;
426
encoder_funcs->commit(encoder);
427
428
}
429
430
/* Store real post-adjustment hardware mode. */
431
crtc->hwmode = *adjusted_mode;
432
433
/* Calculate and store various constants which
434
* are later needed by vblank and swap-completion
435
* timestamping. They are derived from true hwmode.
436
*/
437
drm_calc_timestamping_constants(crtc);
438
439
/* FIXME: add subpixel order */
440
done:
441
drm_mode_destroy(dev, adjusted_mode);
442
if (!ret) {
443
crtc->hwmode = saved_hwmode;
444
crtc->mode = saved_mode;
445
crtc->x = saved_x;
446
crtc->y = saved_y;
447
}
448
449
return ret;
450
}
451
EXPORT_SYMBOL(drm_crtc_helper_set_mode);
452
453
454
/**
455
* drm_crtc_helper_set_config - set a new config from userspace
456
* @crtc: CRTC to setup
457
* @crtc_info: user provided configuration
458
* @new_mode: new mode to set
459
* @connector_set: set of connectors for the new config
460
* @fb: new framebuffer
461
*
462
* LOCKING:
463
* Caller must hold mode config lock.
464
*
465
* Setup a new configuration, provided by the user in @crtc_info, and enable
466
* it.
467
*
468
* RETURNS:
469
* Zero. (FIXME)
470
*/
471
int drm_crtc_helper_set_config(struct drm_mode_set *set)
472
{
473
struct drm_device *dev;
474
struct drm_crtc *save_crtcs, *new_crtc, *crtc;
475
struct drm_encoder *save_encoders, *new_encoder, *encoder;
476
struct drm_framebuffer *old_fb = NULL;
477
bool mode_changed = false; /* if true do a full mode set */
478
bool fb_changed = false; /* if true and !mode_changed just do a flip */
479
struct drm_connector *save_connectors, *connector;
480
int count = 0, ro, fail = 0;
481
struct drm_crtc_helper_funcs *crtc_funcs;
482
int ret = 0;
483
int i;
484
485
DRM_DEBUG_KMS("\n");
486
487
if (!set)
488
return -EINVAL;
489
490
if (!set->crtc)
491
return -EINVAL;
492
493
if (!set->crtc->helper_private)
494
return -EINVAL;
495
496
crtc_funcs = set->crtc->helper_private;
497
498
if (!set->mode)
499
set->fb = NULL;
500
501
if (set->fb) {
502
DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
503
set->crtc->base.id, set->fb->base.id,
504
(int)set->num_connectors, set->x, set->y);
505
} else {
506
DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
507
set->mode = NULL;
508
set->num_connectors = 0;
509
}
510
511
dev = set->crtc->dev;
512
513
/* Allocate space for the backup of all (non-pointer) crtc, encoder and
514
* connector data. */
515
save_crtcs = kzalloc(dev->mode_config.num_crtc *
516
sizeof(struct drm_crtc), GFP_KERNEL);
517
if (!save_crtcs)
518
return -ENOMEM;
519
520
save_encoders = kzalloc(dev->mode_config.num_encoder *
521
sizeof(struct drm_encoder), GFP_KERNEL);
522
if (!save_encoders) {
523
kfree(save_crtcs);
524
return -ENOMEM;
525
}
526
527
save_connectors = kzalloc(dev->mode_config.num_connector *
528
sizeof(struct drm_connector), GFP_KERNEL);
529
if (!save_connectors) {
530
kfree(save_crtcs);
531
kfree(save_encoders);
532
return -ENOMEM;
533
}
534
535
/* Copy data. Note that driver private data is not affected.
536
* Should anything bad happen only the expected state is
537
* restored, not the drivers personal bookkeeping.
538
*/
539
count = 0;
540
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
541
save_crtcs[count++] = *crtc;
542
}
543
544
count = 0;
545
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
546
save_encoders[count++] = *encoder;
547
}
548
549
count = 0;
550
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
551
save_connectors[count++] = *connector;
552
}
553
554
/* We should be able to check here if the fb has the same properties
555
* and then just flip_or_move it */
556
if (set->crtc->fb != set->fb) {
557
/* If we have no fb then treat it as a full mode set */
558
if (set->crtc->fb == NULL) {
559
DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
560
mode_changed = true;
561
} else if (set->fb == NULL) {
562
mode_changed = true;
563
} else
564
fb_changed = true;
565
}
566
567
if (set->x != set->crtc->x || set->y != set->crtc->y)
568
fb_changed = true;
569
570
if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
571
DRM_DEBUG_KMS("modes are different, full mode set\n");
572
drm_mode_debug_printmodeline(&set->crtc->mode);
573
drm_mode_debug_printmodeline(set->mode);
574
mode_changed = true;
575
}
576
577
/* a) traverse passed in connector list and get encoders for them */
578
count = 0;
579
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
580
struct drm_connector_helper_funcs *connector_funcs =
581
connector->helper_private;
582
new_encoder = connector->encoder;
583
for (ro = 0; ro < set->num_connectors; ro++) {
584
if (set->connectors[ro] == connector) {
585
new_encoder = connector_funcs->best_encoder(connector);
586
/* if we can't get an encoder for a connector
587
we are setting now - then fail */
588
if (new_encoder == NULL)
589
/* don't break so fail path works correct */
590
fail = 1;
591
break;
592
}
593
}
594
595
if (new_encoder != connector->encoder) {
596
DRM_DEBUG_KMS("encoder changed, full mode switch\n");
597
mode_changed = true;
598
/* If the encoder is reused for another connector, then
599
* the appropriate crtc will be set later.
600
*/
601
if (connector->encoder)
602
connector->encoder->crtc = NULL;
603
connector->encoder = new_encoder;
604
}
605
}
606
607
if (fail) {
608
ret = -EINVAL;
609
goto fail;
610
}
611
612
count = 0;
613
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
614
if (!connector->encoder)
615
continue;
616
617
if (connector->encoder->crtc == set->crtc)
618
new_crtc = NULL;
619
else
620
new_crtc = connector->encoder->crtc;
621
622
for (ro = 0; ro < set->num_connectors; ro++) {
623
if (set->connectors[ro] == connector)
624
new_crtc = set->crtc;
625
}
626
627
/* Make sure the new CRTC will work with the encoder */
628
if (new_crtc &&
629
!drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
630
ret = -EINVAL;
631
goto fail;
632
}
633
if (new_crtc != connector->encoder->crtc) {
634
DRM_DEBUG_KMS("crtc changed, full mode switch\n");
635
mode_changed = true;
636
connector->encoder->crtc = new_crtc;
637
}
638
if (new_crtc) {
639
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
640
connector->base.id, drm_get_connector_name(connector),
641
new_crtc->base.id);
642
} else {
643
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
644
connector->base.id, drm_get_connector_name(connector));
645
}
646
}
647
648
/* mode_set_base is not a required function */
649
if (fb_changed && !crtc_funcs->mode_set_base)
650
mode_changed = true;
651
652
if (mode_changed) {
653
set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
654
if (set->crtc->enabled) {
655
DRM_DEBUG_KMS("attempting to set mode from"
656
" userspace\n");
657
drm_mode_debug_printmodeline(set->mode);
658
old_fb = set->crtc->fb;
659
set->crtc->fb = set->fb;
660
if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
661
set->x, set->y,
662
old_fb)) {
663
DRM_ERROR("failed to set mode on [CRTC:%d]\n",
664
set->crtc->base.id);
665
set->crtc->fb = old_fb;
666
ret = -EINVAL;
667
goto fail;
668
}
669
DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
670
for (i = 0; i < set->num_connectors; i++) {
671
DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
672
drm_get_connector_name(set->connectors[i]));
673
set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
674
}
675
}
676
drm_helper_disable_unused_functions(dev);
677
} else if (fb_changed) {
678
set->crtc->x = set->x;
679
set->crtc->y = set->y;
680
681
old_fb = set->crtc->fb;
682
if (set->crtc->fb != set->fb)
683
set->crtc->fb = set->fb;
684
ret = crtc_funcs->mode_set_base(set->crtc,
685
set->x, set->y, old_fb);
686
if (ret != 0) {
687
set->crtc->fb = old_fb;
688
goto fail;
689
}
690
}
691
692
kfree(save_connectors);
693
kfree(save_encoders);
694
kfree(save_crtcs);
695
return 0;
696
697
fail:
698
/* Restore all previous data. */
699
count = 0;
700
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
701
*crtc = save_crtcs[count++];
702
}
703
704
count = 0;
705
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
706
*encoder = save_encoders[count++];
707
}
708
709
count = 0;
710
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
711
*connector = save_connectors[count++];
712
}
713
714
kfree(save_connectors);
715
kfree(save_encoders);
716
kfree(save_crtcs);
717
return ret;
718
}
719
EXPORT_SYMBOL(drm_crtc_helper_set_config);
720
721
static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
722
{
723
int dpms = DRM_MODE_DPMS_OFF;
724
struct drm_connector *connector;
725
struct drm_device *dev = encoder->dev;
726
727
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
728
if (connector->encoder == encoder)
729
if (connector->dpms < dpms)
730
dpms = connector->dpms;
731
return dpms;
732
}
733
734
static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
735
{
736
int dpms = DRM_MODE_DPMS_OFF;
737
struct drm_connector *connector;
738
struct drm_device *dev = crtc->dev;
739
740
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
741
if (connector->encoder && connector->encoder->crtc == crtc)
742
if (connector->dpms < dpms)
743
dpms = connector->dpms;
744
return dpms;
745
}
746
747
/**
748
* drm_helper_connector_dpms
749
* @connector affected connector
750
* @mode DPMS mode
751
*
752
* Calls the low-level connector DPMS function, then
753
* calls appropriate encoder and crtc DPMS functions as well
754
*/
755
void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
756
{
757
struct drm_encoder *encoder = connector->encoder;
758
struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
759
int old_dpms;
760
761
if (mode == connector->dpms)
762
return;
763
764
old_dpms = connector->dpms;
765
connector->dpms = mode;
766
767
/* from off to on, do crtc then encoder */
768
if (mode < old_dpms) {
769
if (crtc) {
770
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
771
if (crtc_funcs->dpms)
772
(*crtc_funcs->dpms) (crtc,
773
drm_helper_choose_crtc_dpms(crtc));
774
}
775
if (encoder) {
776
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
777
if (encoder_funcs->dpms)
778
(*encoder_funcs->dpms) (encoder,
779
drm_helper_choose_encoder_dpms(encoder));
780
}
781
}
782
783
/* from on to off, do encoder then crtc */
784
if (mode > old_dpms) {
785
if (encoder) {
786
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
787
if (encoder_funcs->dpms)
788
(*encoder_funcs->dpms) (encoder,
789
drm_helper_choose_encoder_dpms(encoder));
790
}
791
if (crtc) {
792
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
793
if (crtc_funcs->dpms)
794
(*crtc_funcs->dpms) (crtc,
795
drm_helper_choose_crtc_dpms(crtc));
796
}
797
}
798
799
return;
800
}
801
EXPORT_SYMBOL(drm_helper_connector_dpms);
802
803
int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
804
struct drm_mode_fb_cmd *mode_cmd)
805
{
806
fb->width = mode_cmd->width;
807
fb->height = mode_cmd->height;
808
fb->pitch = mode_cmd->pitch;
809
fb->bits_per_pixel = mode_cmd->bpp;
810
fb->depth = mode_cmd->depth;
811
812
return 0;
813
}
814
EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
815
816
int drm_helper_resume_force_mode(struct drm_device *dev)
817
{
818
struct drm_crtc *crtc;
819
struct drm_encoder *encoder;
820
struct drm_encoder_helper_funcs *encoder_funcs;
821
struct drm_crtc_helper_funcs *crtc_funcs;
822
int ret;
823
824
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
825
826
if (!crtc->enabled)
827
continue;
828
829
ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
830
crtc->x, crtc->y, crtc->fb);
831
832
if (ret == false)
833
DRM_ERROR("failed to set mode on crtc %p\n", crtc);
834
835
/* Turn off outputs that were already powered off */
836
if (drm_helper_choose_crtc_dpms(crtc)) {
837
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
838
839
if(encoder->crtc != crtc)
840
continue;
841
842
encoder_funcs = encoder->helper_private;
843
if (encoder_funcs->dpms)
844
(*encoder_funcs->dpms) (encoder,
845
drm_helper_choose_encoder_dpms(encoder));
846
}
847
848
crtc_funcs = crtc->helper_private;
849
if (crtc_funcs->dpms)
850
(*crtc_funcs->dpms) (crtc,
851
drm_helper_choose_crtc_dpms(crtc));
852
}
853
}
854
/* disable the unused connectors while restoring the modesetting */
855
drm_helper_disable_unused_functions(dev);
856
return 0;
857
}
858
EXPORT_SYMBOL(drm_helper_resume_force_mode);
859
860
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
861
static void output_poll_execute(struct work_struct *work)
862
{
863
struct delayed_work *delayed_work = to_delayed_work(work);
864
struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
865
struct drm_connector *connector;
866
enum drm_connector_status old_status;
867
bool repoll = false, changed = false;
868
869
if (!drm_kms_helper_poll)
870
return;
871
872
mutex_lock(&dev->mode_config.mutex);
873
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
874
875
/* if this is HPD or polled don't check it -
876
TV out for instance */
877
if (!connector->polled)
878
continue;
879
880
else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT))
881
repoll = true;
882
883
old_status = connector->status;
884
/* if we are connected and don't want to poll for disconnect
885
skip it */
886
if (old_status == connector_status_connected &&
887
!(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) &&
888
!(connector->polled & DRM_CONNECTOR_POLL_HPD))
889
continue;
890
891
connector->status = connector->funcs->detect(connector, false);
892
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
893
connector->base.id,
894
drm_get_connector_name(connector),
895
old_status, connector->status);
896
if (old_status != connector->status)
897
changed = true;
898
}
899
900
mutex_unlock(&dev->mode_config.mutex);
901
902
if (changed) {
903
/* send a uevent + call fbdev */
904
drm_sysfs_hotplug_event(dev);
905
if (dev->mode_config.funcs->output_poll_changed)
906
dev->mode_config.funcs->output_poll_changed(dev);
907
}
908
909
if (repoll)
910
queue_delayed_work(system_nrt_wq, delayed_work, DRM_OUTPUT_POLL_PERIOD);
911
}
912
913
void drm_kms_helper_poll_disable(struct drm_device *dev)
914
{
915
if (!dev->mode_config.poll_enabled)
916
return;
917
cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
918
}
919
EXPORT_SYMBOL(drm_kms_helper_poll_disable);
920
921
void drm_kms_helper_poll_enable(struct drm_device *dev)
922
{
923
bool poll = false;
924
struct drm_connector *connector;
925
926
if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
927
return;
928
929
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
930
if (connector->polled)
931
poll = true;
932
}
933
934
if (poll)
935
queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
936
}
937
EXPORT_SYMBOL(drm_kms_helper_poll_enable);
938
939
void drm_kms_helper_poll_init(struct drm_device *dev)
940
{
941
INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute);
942
dev->mode_config.poll_enabled = true;
943
944
drm_kms_helper_poll_enable(dev);
945
}
946
EXPORT_SYMBOL(drm_kms_helper_poll_init);
947
948
void drm_kms_helper_poll_fini(struct drm_device *dev)
949
{
950
drm_kms_helper_poll_disable(dev);
951
}
952
EXPORT_SYMBOL(drm_kms_helper_poll_fini);
953
954
void drm_helper_hpd_irq_event(struct drm_device *dev)
955
{
956
if (!dev->mode_config.poll_enabled)
957
return;
958
959
/* kill timer and schedule immediate execution, this doesn't block */
960
cancel_delayed_work(&dev->mode_config.output_poll_work);
961
if (drm_kms_helper_poll)
962
queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0);
963
}
964
EXPORT_SYMBOL(drm_helper_hpd_irq_event);
965
966