aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_crtc.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2015-01-17 18:12:59 -0500
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2015-03-20 08:30:22 -0400
commit971fb3e55feeafe5182c283a39f1f39d0d705b99 (patch)
tree5f061d2faa352982d38f6499a2b6957fd8df11e7 /drivers/gpu/drm/omapdrm/omap_crtc.c
parent87bb2ef15b0fbb91e9ea2d56ef5100e47439e11d (diff)
drm: omapdrm: Reorder CRTC functions
The next commit will need functions to be reordered. Do it separately to help review. This only moves functions without any change to the code. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c396
1 files changed, 206 insertions, 190 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 105eab7cb830..5cd10cf57985 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -74,6 +74,10 @@ struct omap_crtc {
74 struct work_struct page_flip_work; 74 struct work_struct page_flip_work;
75}; 75};
76 76
77/* -----------------------------------------------------------------------------
78 * Helper Functions
79 */
80
77uint32_t pipe2vbl(struct drm_crtc *crtc) 81uint32_t pipe2vbl(struct drm_crtc *crtc)
78{ 82{
79 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 83 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
@@ -81,6 +85,22 @@ uint32_t pipe2vbl(struct drm_crtc *crtc)
81 return dispc_mgr_get_vsync_irq(omap_crtc->channel); 85 return dispc_mgr_get_vsync_irq(omap_crtc->channel);
82} 86}
83 87
88const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc)
89{
90 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
91 return &omap_crtc->timings;
92}
93
94enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
95{
96 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
97 return omap_crtc->channel;
98}
99
100/* -----------------------------------------------------------------------------
101 * DSS Manager Functions
102 */
103
84/* 104/*
85 * Manager-ops, callbacks from output when they need to configure 105 * Manager-ops, callbacks from output when they need to configure
86 * the upstream part of the video pipe. 106 * the upstream part of the video pipe.
@@ -232,8 +252,189 @@ static const struct dss_mgr_ops mgr_ops = {
232 .unregister_framedone_handler = omap_crtc_unregister_framedone_handler, 252 .unregister_framedone_handler = omap_crtc_unregister_framedone_handler,
233}; 253};
234 254
235/* 255/* -----------------------------------------------------------------------------
236 * CRTC funcs: 256 * Apply Logic
257 */
258
259static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
260{
261 struct omap_crtc *omap_crtc =
262 container_of(irq, struct omap_crtc, error_irq);
263 struct drm_crtc *crtc = &omap_crtc->base;
264 DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
265 /* avoid getting in a flood, unregister the irq until next vblank */
266 __omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
267}
268
269static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
270{
271 struct omap_crtc *omap_crtc =
272 container_of(irq, struct omap_crtc, apply_irq);
273 struct drm_crtc *crtc = &omap_crtc->base;
274
275 if (!omap_crtc->error_irq.registered)
276 __omap_irq_register(crtc->dev, &omap_crtc->error_irq);
277
278 if (!dispc_mgr_go_busy(omap_crtc->channel)) {
279 struct omap_drm_private *priv =
280 crtc->dev->dev_private;
281 DBG("%s: apply done", omap_crtc->name);
282 __omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
283 queue_work(priv->wq, &omap_crtc->apply_work);
284 }
285}
286
287static void apply_worker(struct work_struct *work)
288{
289 struct omap_crtc *omap_crtc =
290 container_of(work, struct omap_crtc, apply_work);
291 struct drm_crtc *crtc = &omap_crtc->base;
292 struct drm_device *dev = crtc->dev;
293 struct omap_drm_apply *apply, *n;
294 bool need_apply;
295
296 /*
297 * Synchronize everything on mode_config.mutex, to keep
298 * the callbacks and list modification all serialized
299 * with respect to modesetting ioctls from userspace.
300 */
301 drm_modeset_lock(&crtc->mutex, NULL);
302 dispc_runtime_get();
303
304 /*
305 * If we are still pending a previous update, wait.. when the
306 * pending update completes, we get kicked again.
307 */
308 if (omap_crtc->apply_irq.registered)
309 goto out;
310
311 /* finish up previous apply's: */
312 list_for_each_entry_safe(apply, n,
313 &omap_crtc->pending_applies, pending_node) {
314 apply->post_apply(apply);
315 list_del(&apply->pending_node);
316 }
317
318 need_apply = !list_empty(&omap_crtc->queued_applies);
319
320 /* then handle the next round of of queued apply's: */
321 list_for_each_entry_safe(apply, n,
322 &omap_crtc->queued_applies, queued_node) {
323 apply->pre_apply(apply);
324 list_del(&apply->queued_node);
325 apply->queued = false;
326 list_add_tail(&apply->pending_node,
327 &omap_crtc->pending_applies);
328 }
329
330 if (need_apply) {
331 enum omap_channel channel = omap_crtc->channel;
332
333 DBG("%s: GO", omap_crtc->name);
334
335 if (dispc_mgr_is_enabled(channel)) {
336 dispc_mgr_go(channel);
337 omap_irq_register(dev, &omap_crtc->apply_irq);
338 } else {
339 struct omap_drm_private *priv = dev->dev_private;
340 queue_work(priv->wq, &omap_crtc->apply_work);
341 }
342 }
343
344out:
345 dispc_runtime_put();
346 drm_modeset_unlock(&crtc->mutex);
347}
348
349int omap_crtc_apply(struct drm_crtc *crtc,
350 struct omap_drm_apply *apply)
351{
352 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
353
354 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
355
356 /* no need to queue it again if it is already queued: */
357 if (apply->queued)
358 return 0;
359
360 apply->queued = true;
361 list_add_tail(&apply->queued_node, &omap_crtc->queued_applies);
362
363 /*
364 * If there are no currently pending updates, then go ahead and
365 * kick the worker immediately, otherwise it will run again when
366 * the current update finishes.
367 */
368 if (list_empty(&omap_crtc->pending_applies)) {
369 struct omap_drm_private *priv = crtc->dev->dev_private;
370 queue_work(priv->wq, &omap_crtc->apply_work);
371 }
372
373 return 0;
374}
375
376static void omap_crtc_pre_apply(struct omap_drm_apply *apply)
377{
378 struct omap_crtc *omap_crtc =
379 container_of(apply, struct omap_crtc, apply);
380 struct drm_crtc *crtc = &omap_crtc->base;
381 struct omap_drm_private *priv = crtc->dev->dev_private;
382 struct drm_encoder *encoder = NULL;
383 unsigned int i;
384
385 DBG("%s: enabled=%d", omap_crtc->name, omap_crtc->enabled);
386
387 for (i = 0; i < priv->num_encoders; i++) {
388 if (priv->encoders[i]->crtc == crtc) {
389 encoder = priv->encoders[i];
390 break;
391 }
392 }
393
394 if (omap_crtc->current_encoder && encoder != omap_crtc->current_encoder)
395 omap_encoder_set_enabled(omap_crtc->current_encoder, false);
396
397 omap_crtc->current_encoder = encoder;
398
399 if (!omap_crtc->enabled) {
400 if (encoder)
401 omap_encoder_set_enabled(encoder, false);
402 } else {
403 if (encoder) {
404 omap_encoder_set_enabled(encoder, false);
405 omap_encoder_update(encoder, omap_crtc->mgr,
406 &omap_crtc->timings);
407 omap_encoder_set_enabled(encoder, true);
408 }
409 }
410}
411
412static void omap_crtc_post_apply(struct omap_drm_apply *apply)
413{
414 /* nothing needed for post-apply */
415}
416
417void omap_crtc_flush(struct drm_crtc *crtc)
418{
419 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
420 int loops = 0;
421
422 while (!list_empty(&omap_crtc->pending_applies) ||
423 !list_empty(&omap_crtc->queued_applies) ||
424 omap_crtc->event || omap_crtc->old_fb) {
425
426 if (++loops > 10) {
427 dev_err(crtc->dev->dev,
428 "omap_crtc_flush() timeout\n");
429 break;
430 }
431
432 schedule_timeout_uninterruptible(msecs_to_jiffies(20));
433 }
434}
435
436/* -----------------------------------------------------------------------------
437 * CRTC Functions
237 */ 438 */
238 439
239static void omap_crtc_destroy(struct drm_crtc *crtc) 440static void omap_crtc_destroy(struct drm_crtc *crtc)
@@ -455,194 +656,9 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
455 .mode_set_base = omap_crtc_mode_set_base, 656 .mode_set_base = omap_crtc_mode_set_base,
456}; 657};
457 658
458const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc) 659/* -----------------------------------------------------------------------------
459{ 660 * Init and Cleanup
460 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 661 */
461 return &omap_crtc->timings;
462}
463
464enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
465{
466 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
467 return omap_crtc->channel;
468}
469
470static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
471{
472 struct omap_crtc *omap_crtc =
473 container_of(irq, struct omap_crtc, error_irq);
474 struct drm_crtc *crtc = &omap_crtc->base;
475 DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
476 /* avoid getting in a flood, unregister the irq until next vblank */
477 __omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
478}
479
480static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
481{
482 struct omap_crtc *omap_crtc =
483 container_of(irq, struct omap_crtc, apply_irq);
484 struct drm_crtc *crtc = &omap_crtc->base;
485
486 if (!omap_crtc->error_irq.registered)
487 __omap_irq_register(crtc->dev, &omap_crtc->error_irq);
488
489 if (!dispc_mgr_go_busy(omap_crtc->channel)) {
490 struct omap_drm_private *priv =
491 crtc->dev->dev_private;
492 DBG("%s: apply done", omap_crtc->name);
493 __omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
494 queue_work(priv->wq, &omap_crtc->apply_work);
495 }
496}
497
498static void apply_worker(struct work_struct *work)
499{
500 struct omap_crtc *omap_crtc =
501 container_of(work, struct omap_crtc, apply_work);
502 struct drm_crtc *crtc = &omap_crtc->base;
503 struct drm_device *dev = crtc->dev;
504 struct omap_drm_apply *apply, *n;
505 bool need_apply;
506
507 /*
508 * Synchronize everything on mode_config.mutex, to keep
509 * the callbacks and list modification all serialized
510 * with respect to modesetting ioctls from userspace.
511 */
512 drm_modeset_lock(&crtc->mutex, NULL);
513 dispc_runtime_get();
514
515 /*
516 * If we are still pending a previous update, wait.. when the
517 * pending update completes, we get kicked again.
518 */
519 if (omap_crtc->apply_irq.registered)
520 goto out;
521
522 /* finish up previous apply's: */
523 list_for_each_entry_safe(apply, n,
524 &omap_crtc->pending_applies, pending_node) {
525 apply->post_apply(apply);
526 list_del(&apply->pending_node);
527 }
528
529 need_apply = !list_empty(&omap_crtc->queued_applies);
530
531 /* then handle the next round of of queued apply's: */
532 list_for_each_entry_safe(apply, n,
533 &omap_crtc->queued_applies, queued_node) {
534 apply->pre_apply(apply);
535 list_del(&apply->queued_node);
536 apply->queued = false;
537 list_add_tail(&apply->pending_node,
538 &omap_crtc->pending_applies);
539 }
540
541 if (need_apply) {
542 enum omap_channel channel = omap_crtc->channel;
543
544 DBG("%s: GO", omap_crtc->name);
545
546 if (dispc_mgr_is_enabled(channel)) {
547 dispc_mgr_go(channel);
548 omap_irq_register(dev, &omap_crtc->apply_irq);
549 } else {
550 struct omap_drm_private *priv = dev->dev_private;
551 queue_work(priv->wq, &omap_crtc->apply_work);
552 }
553 }
554
555out:
556 dispc_runtime_put();
557 drm_modeset_unlock(&crtc->mutex);
558}
559
560int omap_crtc_apply(struct drm_crtc *crtc,
561 struct omap_drm_apply *apply)
562{
563 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
564
565 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
566
567 /* no need to queue it again if it is already queued: */
568 if (apply->queued)
569 return 0;
570
571 apply->queued = true;
572 list_add_tail(&apply->queued_node, &omap_crtc->queued_applies);
573
574 /*
575 * If there are no currently pending updates, then go ahead and
576 * kick the worker immediately, otherwise it will run again when
577 * the current update finishes.
578 */
579 if (list_empty(&omap_crtc->pending_applies)) {
580 struct omap_drm_private *priv = crtc->dev->dev_private;
581 queue_work(priv->wq, &omap_crtc->apply_work);
582 }
583
584 return 0;
585}
586
587static void omap_crtc_pre_apply(struct omap_drm_apply *apply)
588{
589 struct omap_crtc *omap_crtc =
590 container_of(apply, struct omap_crtc, apply);
591 struct drm_crtc *crtc = &omap_crtc->base;
592 struct omap_drm_private *priv = crtc->dev->dev_private;
593 struct drm_encoder *encoder = NULL;
594 unsigned int i;
595
596 DBG("%s: enabled=%d", omap_crtc->name, omap_crtc->enabled);
597
598 for (i = 0; i < priv->num_encoders; i++) {
599 if (priv->encoders[i]->crtc == crtc) {
600 encoder = priv->encoders[i];
601 break;
602 }
603 }
604
605 if (omap_crtc->current_encoder && encoder != omap_crtc->current_encoder)
606 omap_encoder_set_enabled(omap_crtc->current_encoder, false);
607
608 omap_crtc->current_encoder = encoder;
609
610 if (!omap_crtc->enabled) {
611 if (encoder)
612 omap_encoder_set_enabled(encoder, false);
613 } else {
614 if (encoder) {
615 omap_encoder_set_enabled(encoder, false);
616 omap_encoder_update(encoder, omap_crtc->mgr,
617 &omap_crtc->timings);
618 omap_encoder_set_enabled(encoder, true);
619 }
620 }
621}
622
623static void omap_crtc_post_apply(struct omap_drm_apply *apply)
624{
625 /* nothing needed for post-apply */
626}
627
628void omap_crtc_flush(struct drm_crtc *crtc)
629{
630 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
631 int loops = 0;
632
633 while (!list_empty(&omap_crtc->pending_applies) ||
634 !list_empty(&omap_crtc->queued_applies) ||
635 omap_crtc->event || omap_crtc->old_fb) {
636
637 if (++loops > 10) {
638 dev_err(crtc->dev->dev,
639 "omap_crtc_flush() timeout\n");
640 break;
641 }
642
643 schedule_timeout_uninterruptible(msecs_to_jiffies(20));
644 }
645}
646 662
647static const char *channel_names[] = { 663static const char *channel_names[] = {
648 [OMAP_DSS_CHANNEL_LCD] = "lcd", 664 [OMAP_DSS_CHANNEL_LCD] = "lcd",