root/drivers/gpu/drm/exynos/exynos_drm_crtc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. exynos_drm_crtc_atomic_enable
  2. exynos_drm_crtc_atomic_disable
  3. exynos_crtc_atomic_check
  4. exynos_crtc_atomic_begin
  5. exynos_crtc_atomic_flush
  6. exynos_crtc_mode_valid
  7. exynos_crtc_mode_fixup
  8. exynos_crtc_handle_event
  9. exynos_drm_crtc_destroy
  10. exynos_drm_crtc_enable_vblank
  11. exynos_drm_crtc_disable_vblank
  12. exynos_drm_crtc_create
  13. exynos_drm_crtc_get_by_type
  14. exynos_drm_set_possible_crtcs
  15. exynos_drm_crtc_te_handler

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* exynos_drm_crtc.c
   3  *
   4  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
   5  * Authors:
   6  *      Inki Dae <inki.dae@samsung.com>
   7  *      Joonyoung Shim <jy0922.shim@samsung.com>
   8  *      Seung-Woo Kim <sw0312.kim@samsung.com>
   9  */
  10 
  11 #include <drm/drm_atomic.h>
  12 #include <drm/drm_atomic_helper.h>
  13 #include <drm/drm_encoder.h>
  14 #include <drm/drm_probe_helper.h>
  15 #include <drm/drm_vblank.h>
  16 
  17 #include "exynos_drm_crtc.h"
  18 #include "exynos_drm_drv.h"
  19 #include "exynos_drm_plane.h"
  20 
  21 static void exynos_drm_crtc_atomic_enable(struct drm_crtc *crtc,
  22                                           struct drm_crtc_state *old_state)
  23 {
  24         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
  25 
  26         if (exynos_crtc->ops->enable)
  27                 exynos_crtc->ops->enable(exynos_crtc);
  28 
  29         drm_crtc_vblank_on(crtc);
  30 }
  31 
  32 static void exynos_drm_crtc_atomic_disable(struct drm_crtc *crtc,
  33                                            struct drm_crtc_state *old_state)
  34 {
  35         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
  36 
  37         drm_crtc_vblank_off(crtc);
  38 
  39         if (exynos_crtc->ops->disable)
  40                 exynos_crtc->ops->disable(exynos_crtc);
  41 
  42         if (crtc->state->event && !crtc->state->active) {
  43                 spin_lock_irq(&crtc->dev->event_lock);
  44                 drm_crtc_send_vblank_event(crtc, crtc->state->event);
  45                 spin_unlock_irq(&crtc->dev->event_lock);
  46 
  47                 crtc->state->event = NULL;
  48         }
  49 }
  50 
  51 static int exynos_crtc_atomic_check(struct drm_crtc *crtc,
  52                                      struct drm_crtc_state *state)
  53 {
  54         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
  55 
  56         if (!state->enable)
  57                 return 0;
  58 
  59         if (exynos_crtc->ops->atomic_check)
  60                 return exynos_crtc->ops->atomic_check(exynos_crtc, state);
  61 
  62         return 0;
  63 }
  64 
  65 static void exynos_crtc_atomic_begin(struct drm_crtc *crtc,
  66                                      struct drm_crtc_state *old_crtc_state)
  67 {
  68         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
  69 
  70         if (exynos_crtc->ops->atomic_begin)
  71                 exynos_crtc->ops->atomic_begin(exynos_crtc);
  72 }
  73 
  74 static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
  75                                      struct drm_crtc_state *old_crtc_state)
  76 {
  77         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
  78 
  79         if (exynos_crtc->ops->atomic_flush)
  80                 exynos_crtc->ops->atomic_flush(exynos_crtc);
  81 }
  82 
  83 static enum drm_mode_status exynos_crtc_mode_valid(struct drm_crtc *crtc,
  84         const struct drm_display_mode *mode)
  85 {
  86         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
  87 
  88         if (exynos_crtc->ops->mode_valid)
  89                 return exynos_crtc->ops->mode_valid(exynos_crtc, mode);
  90 
  91         return MODE_OK;
  92 }
  93 
  94 static bool exynos_crtc_mode_fixup(struct drm_crtc *crtc,
  95                 const struct drm_display_mode *mode,
  96                 struct drm_display_mode *adjusted_mode)
  97 {
  98         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
  99 
 100         if (exynos_crtc->ops->mode_fixup)
 101                 return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
 102                                 adjusted_mode);
 103 
 104         return true;
 105 }
 106 
 107 
 108 static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
 109         .mode_valid     = exynos_crtc_mode_valid,
 110         .mode_fixup     = exynos_crtc_mode_fixup,
 111         .atomic_check   = exynos_crtc_atomic_check,
 112         .atomic_begin   = exynos_crtc_atomic_begin,
 113         .atomic_flush   = exynos_crtc_atomic_flush,
 114         .atomic_enable  = exynos_drm_crtc_atomic_enable,
 115         .atomic_disable = exynos_drm_crtc_atomic_disable,
 116 };
 117 
 118 void exynos_crtc_handle_event(struct exynos_drm_crtc *exynos_crtc)
 119 {
 120         struct drm_crtc *crtc = &exynos_crtc->base;
 121         struct drm_pending_vblank_event *event = crtc->state->event;
 122         unsigned long flags;
 123 
 124         if (!event)
 125                 return;
 126         crtc->state->event = NULL;
 127 
 128         WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 129 
 130         spin_lock_irqsave(&crtc->dev->event_lock, flags);
 131         drm_crtc_arm_vblank_event(crtc, event);
 132         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 133 }
 134 
 135 static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
 136 {
 137         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 138 
 139         drm_crtc_cleanup(crtc);
 140         kfree(exynos_crtc);
 141 }
 142 
 143 static int exynos_drm_crtc_enable_vblank(struct drm_crtc *crtc)
 144 {
 145         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 146 
 147         if (exynos_crtc->ops->enable_vblank)
 148                 return exynos_crtc->ops->enable_vblank(exynos_crtc);
 149 
 150         return 0;
 151 }
 152 
 153 static void exynos_drm_crtc_disable_vblank(struct drm_crtc *crtc)
 154 {
 155         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 156 
 157         if (exynos_crtc->ops->disable_vblank)
 158                 exynos_crtc->ops->disable_vblank(exynos_crtc);
 159 }
 160 
 161 static const struct drm_crtc_funcs exynos_crtc_funcs = {
 162         .set_config     = drm_atomic_helper_set_config,
 163         .page_flip      = drm_atomic_helper_page_flip,
 164         .destroy        = exynos_drm_crtc_destroy,
 165         .reset = drm_atomic_helper_crtc_reset,
 166         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 167         .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 168         .enable_vblank = exynos_drm_crtc_enable_vblank,
 169         .disable_vblank = exynos_drm_crtc_disable_vblank,
 170 };
 171 
 172 struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
 173                                         struct drm_plane *plane,
 174                                         enum exynos_drm_output_type type,
 175                                         const struct exynos_drm_crtc_ops *ops,
 176                                         void *ctx)
 177 {
 178         struct exynos_drm_crtc *exynos_crtc;
 179         struct drm_crtc *crtc;
 180         int ret;
 181 
 182         exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
 183         if (!exynos_crtc)
 184                 return ERR_PTR(-ENOMEM);
 185 
 186         exynos_crtc->type = type;
 187         exynos_crtc->ops = ops;
 188         exynos_crtc->ctx = ctx;
 189 
 190         crtc = &exynos_crtc->base;
 191 
 192         ret = drm_crtc_init_with_planes(drm_dev, crtc, plane, NULL,
 193                                         &exynos_crtc_funcs, NULL);
 194         if (ret < 0)
 195                 goto err_crtc;
 196 
 197         drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
 198 
 199         return exynos_crtc;
 200 
 201 err_crtc:
 202         plane->funcs->destroy(plane);
 203         kfree(exynos_crtc);
 204         return ERR_PTR(ret);
 205 }
 206 
 207 struct exynos_drm_crtc *exynos_drm_crtc_get_by_type(struct drm_device *drm_dev,
 208                                        enum exynos_drm_output_type out_type)
 209 {
 210         struct drm_crtc *crtc;
 211 
 212         drm_for_each_crtc(crtc, drm_dev)
 213                 if (to_exynos_crtc(crtc)->type == out_type)
 214                         return to_exynos_crtc(crtc);
 215 
 216         return ERR_PTR(-ENODEV);
 217 }
 218 
 219 int exynos_drm_set_possible_crtcs(struct drm_encoder *encoder,
 220                 enum exynos_drm_output_type out_type)
 221 {
 222         struct exynos_drm_crtc *crtc = exynos_drm_crtc_get_by_type(encoder->dev,
 223                                                 out_type);
 224 
 225         if (IS_ERR(crtc))
 226                 return PTR_ERR(crtc);
 227 
 228         encoder->possible_crtcs = drm_crtc_mask(&crtc->base);
 229 
 230         return 0;
 231 }
 232 
 233 void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
 234 {
 235         struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 236 
 237         if (exynos_crtc->ops->te_handler)
 238                 exynos_crtc->ops->te_handler(exynos_crtc);
 239 }

/* [<][>][^][v][top][bottom][index][help] */