root/drivers/gpu/drm/sti/sti_crtc.c

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

DEFINITIONS

This source file includes following definitions.
  1. sti_crtc_atomic_enable
  2. sti_crtc_atomic_disable
  3. sti_crtc_mode_set
  4. sti_crtc_disable
  5. sti_crtc_mode_set_nofb
  6. sti_crtc_atomic_flush
  7. sti_crtc_destroy
  8. sti_crtc_set_property
  9. sti_crtc_vblank_cb
  10. sti_crtc_enable_vblank
  11. sti_crtc_disable_vblank
  12. sti_crtc_late_register
  13. sti_crtc_is_main
  14. sti_crtc_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) STMicroelectronics SA 2014
   4  * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
   5  *          Fabien Dessenne <fabien.dessenne@st.com>
   6  *          for STMicroelectronics.
   7  */
   8 
   9 #include <linux/clk.h>
  10 
  11 #include <drm/drm_atomic.h>
  12 #include <drm/drm_atomic_helper.h>
  13 #include <drm/drm_device.h>
  14 #include <drm/drm_plane_helper.h>
  15 #include <drm/drm_print.h>
  16 #include <drm/drm_probe_helper.h>
  17 #include <drm/drm_vblank.h>
  18 
  19 #include "sti_compositor.h"
  20 #include "sti_crtc.h"
  21 #include "sti_drv.h"
  22 #include "sti_vid.h"
  23 #include "sti_vtg.h"
  24 
  25 static void sti_crtc_atomic_enable(struct drm_crtc *crtc,
  26                                    struct drm_crtc_state *old_state)
  27 {
  28         struct sti_mixer *mixer = to_sti_mixer(crtc);
  29 
  30         DRM_DEBUG_DRIVER("\n");
  31 
  32         mixer->status = STI_MIXER_READY;
  33 
  34         drm_crtc_vblank_on(crtc);
  35 }
  36 
  37 static void sti_crtc_atomic_disable(struct drm_crtc *crtc,
  38                                     struct drm_crtc_state *old_state)
  39 {
  40         struct sti_mixer *mixer = to_sti_mixer(crtc);
  41 
  42         DRM_DEBUG_DRIVER("\n");
  43 
  44         mixer->status = STI_MIXER_DISABLING;
  45 
  46         drm_crtc_wait_one_vblank(crtc);
  47 }
  48 
  49 static int
  50 sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
  51 {
  52         struct sti_mixer *mixer = to_sti_mixer(crtc);
  53         struct device *dev = mixer->dev;
  54         struct sti_compositor *compo = dev_get_drvdata(dev);
  55         struct clk *compo_clk, *pix_clk;
  56         int rate = mode->clock * 1000;
  57 
  58         DRM_DEBUG_KMS("CRTC:%d (%s) mode: (%s)\n",
  59                       crtc->base.id, sti_mixer_to_str(mixer), mode->name);
  60 
  61         DRM_DEBUG_KMS(DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
  62 
  63         if (mixer->id == STI_MIXER_MAIN) {
  64                 compo_clk = compo->clk_compo_main;
  65                 pix_clk = compo->clk_pix_main;
  66         } else {
  67                 compo_clk = compo->clk_compo_aux;
  68                 pix_clk = compo->clk_pix_aux;
  69         }
  70 
  71         /* Prepare and enable the compo IP clock */
  72         if (clk_prepare_enable(compo_clk)) {
  73                 DRM_INFO("Failed to prepare/enable compositor clk\n");
  74                 goto compo_error;
  75         }
  76 
  77         /* Set rate and prepare/enable pixel clock */
  78         if (clk_set_rate(pix_clk, rate) < 0) {
  79                 DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate);
  80                 goto pix_error;
  81         }
  82         if (clk_prepare_enable(pix_clk)) {
  83                 DRM_ERROR("Failed to prepare/enable pix clk\n");
  84                 goto pix_error;
  85         }
  86 
  87         sti_vtg_set_config(compo->vtg[mixer->id], &crtc->mode);
  88 
  89         if (sti_mixer_active_video_area(mixer, &crtc->mode)) {
  90                 DRM_ERROR("Can't set active video area\n");
  91                 goto mixer_error;
  92         }
  93 
  94         return 0;
  95 
  96 mixer_error:
  97         clk_disable_unprepare(pix_clk);
  98 pix_error:
  99         clk_disable_unprepare(compo_clk);
 100 compo_error:
 101         return -EINVAL;
 102 }
 103 
 104 static void sti_crtc_disable(struct drm_crtc *crtc)
 105 {
 106         struct sti_mixer *mixer = to_sti_mixer(crtc);
 107         struct device *dev = mixer->dev;
 108         struct sti_compositor *compo = dev_get_drvdata(dev);
 109 
 110         DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
 111 
 112         /* Disable Background */
 113         sti_mixer_set_background_status(mixer, false);
 114 
 115         drm_crtc_vblank_off(crtc);
 116 
 117         /* Disable pixel clock and compo IP clocks */
 118         if (mixer->id == STI_MIXER_MAIN) {
 119                 clk_disable_unprepare(compo->clk_pix_main);
 120                 clk_disable_unprepare(compo->clk_compo_main);
 121         } else {
 122                 clk_disable_unprepare(compo->clk_pix_aux);
 123                 clk_disable_unprepare(compo->clk_compo_aux);
 124         }
 125 
 126         mixer->status = STI_MIXER_DISABLED;
 127 }
 128 
 129 static void
 130 sti_crtc_mode_set_nofb(struct drm_crtc *crtc)
 131 {
 132         sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
 133 }
 134 
 135 static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
 136                                   struct drm_crtc_state *old_crtc_state)
 137 {
 138         struct drm_device *drm_dev = crtc->dev;
 139         struct sti_mixer *mixer = to_sti_mixer(crtc);
 140         struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
 141         struct drm_plane *p;
 142         struct drm_pending_vblank_event *event;
 143         unsigned long flags;
 144 
 145         DRM_DEBUG_DRIVER("\n");
 146 
 147         /* perform plane actions */
 148         list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
 149                 struct sti_plane *plane = to_sti_plane(p);
 150 
 151                 switch (plane->status) {
 152                 case STI_PLANE_UPDATED:
 153                         /* ignore update for other CRTC */
 154                         if (p->state->crtc != crtc)
 155                                 continue;
 156 
 157                         /* update planes tag as updated */
 158                         DRM_DEBUG_DRIVER("update plane %s\n",
 159                                          sti_plane_to_str(plane));
 160 
 161                         if (sti_mixer_set_plane_depth(mixer, plane)) {
 162                                 DRM_ERROR("Cannot set plane %s depth\n",
 163                                           sti_plane_to_str(plane));
 164                                 break;
 165                         }
 166 
 167                         if (sti_mixer_set_plane_status(mixer, plane, true)) {
 168                                 DRM_ERROR("Cannot enable plane %s at mixer\n",
 169                                           sti_plane_to_str(plane));
 170                                 break;
 171                         }
 172 
 173                         /* if plane is HQVDP_0 then commit the vid[0] */
 174                         if (plane->desc == STI_HQVDP_0)
 175                                 sti_vid_commit(compo->vid[0], p->state);
 176 
 177                         plane->status = STI_PLANE_READY;
 178 
 179                         break;
 180                 case STI_PLANE_DISABLING:
 181                         /* disabling sequence for planes tag as disabling */
 182                         DRM_DEBUG_DRIVER("disable plane %s from mixer\n",
 183                                          sti_plane_to_str(plane));
 184 
 185                         if (sti_mixer_set_plane_status(mixer, plane, false)) {
 186                                 DRM_ERROR("Cannot disable plane %s at mixer\n",
 187                                           sti_plane_to_str(plane));
 188                                 continue;
 189                         }
 190 
 191                         if (plane->desc == STI_CURSOR)
 192                                 /* tag plane status for disabled */
 193                                 plane->status = STI_PLANE_DISABLED;
 194                         else
 195                                 /* tag plane status for flushing */
 196                                 plane->status = STI_PLANE_FLUSHING;
 197 
 198                         /* if plane is HQVDP_0 then disable the vid[0] */
 199                         if (plane->desc == STI_HQVDP_0)
 200                                 sti_vid_disable(compo->vid[0]);
 201 
 202                         break;
 203                 default:
 204                         /* Other status case are not handled */
 205                         break;
 206                 }
 207         }
 208 
 209         event = crtc->state->event;
 210         if (event) {
 211                 crtc->state->event = NULL;
 212 
 213                 spin_lock_irqsave(&crtc->dev->event_lock, flags);
 214                 if (drm_crtc_vblank_get(crtc) == 0)
 215                         drm_crtc_arm_vblank_event(crtc, event);
 216                 else
 217                         drm_crtc_send_vblank_event(crtc, event);
 218                 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 219         }
 220 }
 221 
 222 static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
 223         .mode_set_nofb = sti_crtc_mode_set_nofb,
 224         .atomic_flush = sti_crtc_atomic_flush,
 225         .atomic_enable = sti_crtc_atomic_enable,
 226         .atomic_disable = sti_crtc_atomic_disable,
 227 };
 228 
 229 static void sti_crtc_destroy(struct drm_crtc *crtc)
 230 {
 231         DRM_DEBUG_KMS("\n");
 232         drm_crtc_cleanup(crtc);
 233 }
 234 
 235 static int sti_crtc_set_property(struct drm_crtc *crtc,
 236                                  struct drm_property *property,
 237                                  uint64_t val)
 238 {
 239         DRM_DEBUG_KMS("\n");
 240         return 0;
 241 }
 242 
 243 int sti_crtc_vblank_cb(struct notifier_block *nb,
 244                        unsigned long event, void *data)
 245 {
 246         struct sti_compositor *compo;
 247         struct drm_crtc *crtc = data;
 248         struct sti_mixer *mixer;
 249         unsigned int pipe;
 250 
 251         pipe = drm_crtc_index(crtc);
 252         compo = container_of(nb, struct sti_compositor, vtg_vblank_nb[pipe]);
 253         mixer = compo->mixer[pipe];
 254 
 255         if ((event != VTG_TOP_FIELD_EVENT) &&
 256             (event != VTG_BOTTOM_FIELD_EVENT)) {
 257                 DRM_ERROR("unknown event: %lu\n", event);
 258                 return -EINVAL;
 259         }
 260 
 261         drm_crtc_handle_vblank(crtc);
 262 
 263         if (mixer->status == STI_MIXER_DISABLING) {
 264                 struct drm_plane *p;
 265 
 266                 /* Disable mixer only if all overlay planes (GDP and VDP)
 267                  * are disabled */
 268                 list_for_each_entry(p, &crtc->dev->mode_config.plane_list,
 269                                     head) {
 270                         struct sti_plane *plane = to_sti_plane(p);
 271 
 272                         if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
 273                                 if (plane->status != STI_PLANE_DISABLED)
 274                                         return 0;
 275                 }
 276                 sti_crtc_disable(crtc);
 277         }
 278 
 279         return 0;
 280 }
 281 
 282 int sti_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
 283 {
 284         struct sti_private *dev_priv = dev->dev_private;
 285         struct sti_compositor *compo = dev_priv->compo;
 286         struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe];
 287         struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
 288         struct sti_vtg *vtg = compo->vtg[pipe];
 289 
 290         DRM_DEBUG_DRIVER("\n");
 291 
 292         if (sti_vtg_register_client(vtg, vtg_vblank_nb, crtc)) {
 293                 DRM_ERROR("Cannot register VTG notifier\n");
 294                 return -EINVAL;
 295         }
 296 
 297         return 0;
 298 }
 299 
 300 void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
 301 {
 302         struct sti_private *priv = drm_dev->dev_private;
 303         struct sti_compositor *compo = priv->compo;
 304         struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe];
 305         struct sti_vtg *vtg = compo->vtg[pipe];
 306 
 307         DRM_DEBUG_DRIVER("\n");
 308 
 309         if (sti_vtg_unregister_client(vtg, vtg_vblank_nb))
 310                 DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
 311 }
 312 
 313 static int sti_crtc_late_register(struct drm_crtc *crtc)
 314 {
 315         struct sti_mixer *mixer = to_sti_mixer(crtc);
 316         struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
 317 
 318         if (drm_crtc_index(crtc) == 0)
 319                 return sti_compositor_debugfs_init(compo, crtc->dev->primary);
 320 
 321         return 0;
 322 }
 323 
 324 static const struct drm_crtc_funcs sti_crtc_funcs = {
 325         .set_config = drm_atomic_helper_set_config,
 326         .page_flip = drm_atomic_helper_page_flip,
 327         .destroy = sti_crtc_destroy,
 328         .set_property = sti_crtc_set_property,
 329         .reset = drm_atomic_helper_crtc_reset,
 330         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 331         .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 332         .late_register = sti_crtc_late_register,
 333 };
 334 
 335 bool sti_crtc_is_main(struct drm_crtc *crtc)
 336 {
 337         struct sti_mixer *mixer = to_sti_mixer(crtc);
 338 
 339         if (mixer->id == STI_MIXER_MAIN)
 340                 return true;
 341 
 342         return false;
 343 }
 344 
 345 int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
 346                   struct drm_plane *primary, struct drm_plane *cursor)
 347 {
 348         struct drm_crtc *crtc = &mixer->drm_crtc;
 349         int res;
 350 
 351         res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
 352                                         &sti_crtc_funcs, NULL);
 353         if (res) {
 354                 DRM_ERROR("Can't initialize CRTC\n");
 355                 return -EINVAL;
 356         }
 357 
 358         drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs);
 359 
 360         DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n",
 361                          crtc->base.id, sti_mixer_to_str(mixer));
 362 
 363         return 0;
 364 }

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