diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2015-01-17 18:12:59 -0500 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2015-03-20 08:30:22 -0400 |
commit | 971fb3e55feeafe5182c283a39f1f39d0d705b99 (patch) | |
tree | 5f061d2faa352982d38f6499a2b6957fd8df11e7 /drivers/gpu/drm/omapdrm/omap_crtc.c | |
parent | 87bb2ef15b0fbb91e9ea2d56ef5100e47439e11d (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.c | 396 |
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 | |||
77 | uint32_t pipe2vbl(struct drm_crtc *crtc) | 81 | uint32_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 | ||
88 | const 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 | |||
94 | enum 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 | |||
259 | static 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 | |||
269 | static 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 | |||
287 | static 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 | |||
344 | out: | ||
345 | dispc_runtime_put(); | ||
346 | drm_modeset_unlock(&crtc->mutex); | ||
347 | } | ||
348 | |||
349 | int 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 | |||
376 | static 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 | |||
412 | static void omap_crtc_post_apply(struct omap_drm_apply *apply) | ||
413 | { | ||
414 | /* nothing needed for post-apply */ | ||
415 | } | ||
416 | |||
417 | void 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 | ||
239 | static void omap_crtc_destroy(struct drm_crtc *crtc) | 440 | static 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 | ||
458 | const 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 | |||
464 | enum 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 | |||
470 | static 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 | |||
480 | static 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 | |||
498 | static 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 | |||
555 | out: | ||
556 | dispc_runtime_put(); | ||
557 | drm_modeset_unlock(&crtc->mutex); | ||
558 | } | ||
559 | |||
560 | int 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 | |||
587 | static 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 | |||
623 | static void omap_crtc_post_apply(struct omap_drm_apply *apply) | ||
624 | { | ||
625 | /* nothing needed for post-apply */ | ||
626 | } | ||
627 | |||
628 | void 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 | ||
647 | static const char *channel_names[] = { | 663 | static const char *channel_names[] = { |
648 | [OMAP_DSS_CHANNEL_LCD] = "lcd", | 664 | [OMAP_DSS_CHANNEL_LCD] = "lcd", |