root/drivers/gpu/drm/imx/ipuv3-crtc.c

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

DEFINITIONS

This source file includes following definitions.
  1. to_ipu_crtc
  2. ipu_crtc_atomic_enable
  3. ipu_crtc_disable_planes
  4. ipu_crtc_atomic_disable
  5. imx_drm_crtc_reset
  6. imx_drm_crtc_duplicate_state
  7. imx_drm_crtc_destroy_state
  8. ipu_enable_vblank
  9. ipu_disable_vblank
  10. ipu_irq_handler
  11. ipu_crtc_mode_fixup
  12. ipu_crtc_atomic_check
  13. ipu_crtc_atomic_begin
  14. ipu_crtc_atomic_flush
  15. ipu_crtc_mode_set_nofb
  16. ipu_put_resources
  17. ipu_get_resources
  18. ipu_crtc_init
  19. ipu_drm_bind
  20. ipu_drm_unbind
  21. ipu_drm_probe
  22. ipu_drm_remove

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * i.MX IPUv3 Graphics driver
   4  *
   5  * Copyright (C) 2011 Sascha Hauer, Pengutronix
   6  */
   7 
   8 #include <linux/clk.h>
   9 #include <linux/component.h>
  10 #include <linux/device.h>
  11 #include <linux/dma-mapping.h>
  12 #include <linux/errno.h>
  13 #include <linux/export.h>
  14 #include <linux/module.h>
  15 #include <linux/platform_device.h>
  16 
  17 #include <video/imx-ipu-v3.h>
  18 
  19 #include <drm/drm_atomic.h>
  20 #include <drm/drm_atomic_helper.h>
  21 #include <drm/drm_fb_cma_helper.h>
  22 #include <drm/drm_gem_cma_helper.h>
  23 #include <drm/drm_probe_helper.h>
  24 #include <drm/drm_vblank.h>
  25 
  26 #include "imx-drm.h"
  27 #include "ipuv3-plane.h"
  28 
  29 #define DRIVER_DESC             "i.MX IPUv3 Graphics"
  30 
  31 struct ipu_crtc {
  32         struct device           *dev;
  33         struct drm_crtc         base;
  34 
  35         /* plane[0] is the full plane, plane[1] is the partial plane */
  36         struct ipu_plane        *plane[2];
  37 
  38         struct ipu_dc           *dc;
  39         struct ipu_di           *di;
  40         int                     irq;
  41         struct drm_pending_vblank_event *event;
  42 };
  43 
  44 static inline struct ipu_crtc *to_ipu_crtc(struct drm_crtc *crtc)
  45 {
  46         return container_of(crtc, struct ipu_crtc, base);
  47 }
  48 
  49 static void ipu_crtc_atomic_enable(struct drm_crtc *crtc,
  50                                    struct drm_crtc_state *old_state)
  51 {
  52         struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
  53         struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
  54 
  55         ipu_prg_enable(ipu);
  56         ipu_dc_enable(ipu);
  57         ipu_dc_enable_channel(ipu_crtc->dc);
  58         ipu_di_enable(ipu_crtc->di);
  59 }
  60 
  61 static void ipu_crtc_disable_planes(struct ipu_crtc *ipu_crtc,
  62                                     struct drm_crtc_state *old_crtc_state)
  63 {
  64         bool disable_partial = false;
  65         bool disable_full = false;
  66         struct drm_plane *plane;
  67 
  68         drm_atomic_crtc_state_for_each_plane(plane, old_crtc_state) {
  69                 if (plane == &ipu_crtc->plane[0]->base)
  70                         disable_full = true;
  71                 if (&ipu_crtc->plane[1] && plane == &ipu_crtc->plane[1]->base)
  72                         disable_partial = true;
  73         }
  74 
  75         if (disable_partial)
  76                 ipu_plane_disable(ipu_crtc->plane[1], true);
  77         if (disable_full)
  78                 ipu_plane_disable(ipu_crtc->plane[0], true);
  79 }
  80 
  81 static void ipu_crtc_atomic_disable(struct drm_crtc *crtc,
  82                                     struct drm_crtc_state *old_crtc_state)
  83 {
  84         struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
  85         struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
  86 
  87         ipu_dc_disable_channel(ipu_crtc->dc);
  88         ipu_di_disable(ipu_crtc->di);
  89         /*
  90          * Planes must be disabled before DC clock is removed, as otherwise the
  91          * attached IDMACs will be left in undefined state, possibly hanging
  92          * the IPU or even system.
  93          */
  94         ipu_crtc_disable_planes(ipu_crtc, old_crtc_state);
  95         ipu_dc_disable(ipu);
  96         ipu_prg_disable(ipu);
  97 
  98         drm_crtc_vblank_off(crtc);
  99 
 100         spin_lock_irq(&crtc->dev->event_lock);
 101         if (crtc->state->event && !crtc->state->active) {
 102                 drm_crtc_send_vblank_event(crtc, crtc->state->event);
 103                 crtc->state->event = NULL;
 104         }
 105         spin_unlock_irq(&crtc->dev->event_lock);
 106 }
 107 
 108 static void imx_drm_crtc_reset(struct drm_crtc *crtc)
 109 {
 110         struct imx_crtc_state *state;
 111 
 112         if (crtc->state) {
 113                 if (crtc->state->mode_blob)
 114                         drm_property_blob_put(crtc->state->mode_blob);
 115 
 116                 state = to_imx_crtc_state(crtc->state);
 117                 memset(state, 0, sizeof(*state));
 118         } else {
 119                 state = kzalloc(sizeof(*state), GFP_KERNEL);
 120                 if (!state)
 121                         return;
 122                 crtc->state = &state->base;
 123         }
 124 
 125         state->base.crtc = crtc;
 126 }
 127 
 128 static struct drm_crtc_state *imx_drm_crtc_duplicate_state(struct drm_crtc *crtc)
 129 {
 130         struct imx_crtc_state *state;
 131 
 132         state = kzalloc(sizeof(*state), GFP_KERNEL);
 133         if (!state)
 134                 return NULL;
 135 
 136         __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
 137 
 138         WARN_ON(state->base.crtc != crtc);
 139         state->base.crtc = crtc;
 140 
 141         return &state->base;
 142 }
 143 
 144 static void imx_drm_crtc_destroy_state(struct drm_crtc *crtc,
 145                                        struct drm_crtc_state *state)
 146 {
 147         __drm_atomic_helper_crtc_destroy_state(state);
 148         kfree(to_imx_crtc_state(state));
 149 }
 150 
 151 static int ipu_enable_vblank(struct drm_crtc *crtc)
 152 {
 153         struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 154 
 155         enable_irq(ipu_crtc->irq);
 156 
 157         return 0;
 158 }
 159 
 160 static void ipu_disable_vblank(struct drm_crtc *crtc)
 161 {
 162         struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 163 
 164         disable_irq_nosync(ipu_crtc->irq);
 165 }
 166 
 167 static const struct drm_crtc_funcs ipu_crtc_funcs = {
 168         .set_config = drm_atomic_helper_set_config,
 169         .destroy = drm_crtc_cleanup,
 170         .page_flip = drm_atomic_helper_page_flip,
 171         .reset = imx_drm_crtc_reset,
 172         .atomic_duplicate_state = imx_drm_crtc_duplicate_state,
 173         .atomic_destroy_state = imx_drm_crtc_destroy_state,
 174         .enable_vblank = ipu_enable_vblank,
 175         .disable_vblank = ipu_disable_vblank,
 176 };
 177 
 178 static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
 179 {
 180         struct ipu_crtc *ipu_crtc = dev_id;
 181         struct drm_crtc *crtc = &ipu_crtc->base;
 182         unsigned long flags;
 183         int i;
 184 
 185         drm_crtc_handle_vblank(crtc);
 186 
 187         if (ipu_crtc->event) {
 188                 for (i = 0; i < ARRAY_SIZE(ipu_crtc->plane); i++) {
 189                         struct ipu_plane *plane = ipu_crtc->plane[i];
 190 
 191                         if (!plane)
 192                                 continue;
 193 
 194                         if (ipu_plane_atomic_update_pending(&plane->base))
 195                                 break;
 196                 }
 197 
 198                 if (i == ARRAY_SIZE(ipu_crtc->plane)) {
 199                         spin_lock_irqsave(&crtc->dev->event_lock, flags);
 200                         drm_crtc_send_vblank_event(crtc, ipu_crtc->event);
 201                         ipu_crtc->event = NULL;
 202                         drm_crtc_vblank_put(crtc);
 203                         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 204                 }
 205         }
 206 
 207         return IRQ_HANDLED;
 208 }
 209 
 210 static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc,
 211                                   const struct drm_display_mode *mode,
 212                                   struct drm_display_mode *adjusted_mode)
 213 {
 214         struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 215         struct videomode vm;
 216         int ret;
 217 
 218         drm_display_mode_to_videomode(adjusted_mode, &vm);
 219 
 220         ret = ipu_di_adjust_videomode(ipu_crtc->di, &vm);
 221         if (ret)
 222                 return false;
 223 
 224         if ((vm.vsync_len == 0) || (vm.hsync_len == 0))
 225                 return false;
 226 
 227         drm_display_mode_from_videomode(&vm, adjusted_mode);
 228 
 229         return true;
 230 }
 231 
 232 static int ipu_crtc_atomic_check(struct drm_crtc *crtc,
 233                                  struct drm_crtc_state *state)
 234 {
 235         u32 primary_plane_mask = drm_plane_mask(crtc->primary);
 236 
 237         if (state->active && (primary_plane_mask & state->plane_mask) == 0)
 238                 return -EINVAL;
 239 
 240         return 0;
 241 }
 242 
 243 static void ipu_crtc_atomic_begin(struct drm_crtc *crtc,
 244                                   struct drm_crtc_state *old_crtc_state)
 245 {
 246         drm_crtc_vblank_on(crtc);
 247 }
 248 
 249 static void ipu_crtc_atomic_flush(struct drm_crtc *crtc,
 250                                   struct drm_crtc_state *old_crtc_state)
 251 {
 252         spin_lock_irq(&crtc->dev->event_lock);
 253         if (crtc->state->event) {
 254                 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 255 
 256                 WARN_ON(drm_crtc_vblank_get(crtc));
 257                 ipu_crtc->event = crtc->state->event;
 258                 crtc->state->event = NULL;
 259         }
 260         spin_unlock_irq(&crtc->dev->event_lock);
 261 }
 262 
 263 static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc)
 264 {
 265         struct drm_device *dev = crtc->dev;
 266         struct drm_encoder *encoder;
 267         struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 268         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 269         struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc->state);
 270         struct ipu_di_signal_cfg sig_cfg = {};
 271         unsigned long encoder_types = 0;
 272 
 273         dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
 274                         mode->hdisplay);
 275         dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
 276                         mode->vdisplay);
 277 
 278         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 279                 if (encoder->crtc == crtc)
 280                         encoder_types |= BIT(encoder->encoder_type);
 281         }
 282 
 283         dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n",
 284                 __func__, encoder_types);
 285 
 286         /*
 287          * If we have DAC or LDB, then we need the IPU DI clock to be
 288          * the same as the LDB DI clock. For TVDAC, derive the IPU DI
 289          * clock from 27 MHz TVE_DI clock, but allow to divide it.
 290          */
 291         if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) |
 292                              BIT(DRM_MODE_ENCODER_LVDS)))
 293                 sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT;
 294         else if (encoder_types & BIT(DRM_MODE_ENCODER_TVDAC))
 295                 sig_cfg.clkflags = IPU_DI_CLKMODE_EXT;
 296         else
 297                 sig_cfg.clkflags = 0;
 298 
 299         sig_cfg.enable_pol = !(imx_crtc_state->bus_flags & DRM_BUS_FLAG_DE_LOW);
 300         /* Default to driving pixel data on negative clock edges */
 301         sig_cfg.clk_pol = !!(imx_crtc_state->bus_flags &
 302                              DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE);
 303         sig_cfg.bus_format = imx_crtc_state->bus_format;
 304         sig_cfg.v_to_h_sync = 0;
 305         sig_cfg.hsync_pin = imx_crtc_state->di_hsync_pin;
 306         sig_cfg.vsync_pin = imx_crtc_state->di_vsync_pin;
 307 
 308         drm_display_mode_to_videomode(mode, &sig_cfg.mode);
 309 
 310         ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di,
 311                          mode->flags & DRM_MODE_FLAG_INTERLACE,
 312                          imx_crtc_state->bus_format, mode->hdisplay);
 313         ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg);
 314 }
 315 
 316 static const struct drm_crtc_helper_funcs ipu_helper_funcs = {
 317         .mode_fixup = ipu_crtc_mode_fixup,
 318         .mode_set_nofb = ipu_crtc_mode_set_nofb,
 319         .atomic_check = ipu_crtc_atomic_check,
 320         .atomic_begin = ipu_crtc_atomic_begin,
 321         .atomic_flush = ipu_crtc_atomic_flush,
 322         .atomic_disable = ipu_crtc_atomic_disable,
 323         .atomic_enable = ipu_crtc_atomic_enable,
 324 };
 325 
 326 static void ipu_put_resources(struct ipu_crtc *ipu_crtc)
 327 {
 328         if (!IS_ERR_OR_NULL(ipu_crtc->dc))
 329                 ipu_dc_put(ipu_crtc->dc);
 330         if (!IS_ERR_OR_NULL(ipu_crtc->di))
 331                 ipu_di_put(ipu_crtc->di);
 332 }
 333 
 334 static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
 335                 struct ipu_client_platformdata *pdata)
 336 {
 337         struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
 338         int ret;
 339 
 340         ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc);
 341         if (IS_ERR(ipu_crtc->dc)) {
 342                 ret = PTR_ERR(ipu_crtc->dc);
 343                 goto err_out;
 344         }
 345 
 346         ipu_crtc->di = ipu_di_get(ipu, pdata->di);
 347         if (IS_ERR(ipu_crtc->di)) {
 348                 ret = PTR_ERR(ipu_crtc->di);
 349                 goto err_out;
 350         }
 351 
 352         return 0;
 353 err_out:
 354         ipu_put_resources(ipu_crtc);
 355 
 356         return ret;
 357 }
 358 
 359 static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
 360         struct ipu_client_platformdata *pdata, struct drm_device *drm)
 361 {
 362         struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
 363         struct drm_crtc *crtc = &ipu_crtc->base;
 364         int dp = -EINVAL;
 365         int ret;
 366 
 367         ret = ipu_get_resources(ipu_crtc, pdata);
 368         if (ret) {
 369                 dev_err(ipu_crtc->dev, "getting resources failed with %d.\n",
 370                                 ret);
 371                 return ret;
 372         }
 373 
 374         if (pdata->dp >= 0)
 375                 dp = IPU_DP_FLOW_SYNC_BG;
 376         ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
 377                                             DRM_PLANE_TYPE_PRIMARY);
 378         if (IS_ERR(ipu_crtc->plane[0])) {
 379                 ret = PTR_ERR(ipu_crtc->plane[0]);
 380                 goto err_put_resources;
 381         }
 382 
 383         crtc->port = pdata->of_node;
 384         drm_crtc_helper_add(crtc, &ipu_helper_funcs);
 385         drm_crtc_init_with_planes(drm, crtc, &ipu_crtc->plane[0]->base, NULL,
 386                                   &ipu_crtc_funcs, NULL);
 387 
 388         ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
 389         if (ret) {
 390                 dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
 391                         ret);
 392                 goto err_put_resources;
 393         }
 394 
 395         /* If this crtc is using the DP, add an overlay plane */
 396         if (pdata->dp >= 0 && pdata->dma[1] > 0) {
 397                 ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1],
 398                                                 IPU_DP_FLOW_SYNC_FG,
 399                                                 drm_crtc_mask(&ipu_crtc->base),
 400                                                 DRM_PLANE_TYPE_OVERLAY);
 401                 if (IS_ERR(ipu_crtc->plane[1])) {
 402                         ipu_crtc->plane[1] = NULL;
 403                 } else {
 404                         ret = ipu_plane_get_resources(ipu_crtc->plane[1]);
 405                         if (ret) {
 406                                 dev_err(ipu_crtc->dev, "getting plane 1 "
 407                                         "resources failed with %d.\n", ret);
 408                                 goto err_put_plane0_res;
 409                         }
 410                 }
 411         }
 412 
 413         ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
 414         ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
 415                         "imx_drm", ipu_crtc);
 416         if (ret < 0) {
 417                 dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
 418                 goto err_put_plane1_res;
 419         }
 420         /* Only enable IRQ when we actually need it to trigger work. */
 421         disable_irq(ipu_crtc->irq);
 422 
 423         return 0;
 424 
 425 err_put_plane1_res:
 426         if (ipu_crtc->plane[1])
 427                 ipu_plane_put_resources(ipu_crtc->plane[1]);
 428 err_put_plane0_res:
 429         ipu_plane_put_resources(ipu_crtc->plane[0]);
 430 err_put_resources:
 431         ipu_put_resources(ipu_crtc);
 432 
 433         return ret;
 434 }
 435 
 436 static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
 437 {
 438         struct ipu_client_platformdata *pdata = dev->platform_data;
 439         struct drm_device *drm = data;
 440         struct ipu_crtc *ipu_crtc;
 441         int ret;
 442 
 443         ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
 444         if (!ipu_crtc)
 445                 return -ENOMEM;
 446 
 447         ipu_crtc->dev = dev;
 448 
 449         ret = ipu_crtc_init(ipu_crtc, pdata, drm);
 450         if (ret)
 451                 return ret;
 452 
 453         dev_set_drvdata(dev, ipu_crtc);
 454 
 455         return 0;
 456 }
 457 
 458 static void ipu_drm_unbind(struct device *dev, struct device *master,
 459         void *data)
 460 {
 461         struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
 462 
 463         ipu_put_resources(ipu_crtc);
 464         if (ipu_crtc->plane[1])
 465                 ipu_plane_put_resources(ipu_crtc->plane[1]);
 466         ipu_plane_put_resources(ipu_crtc->plane[0]);
 467 }
 468 
 469 static const struct component_ops ipu_crtc_ops = {
 470         .bind = ipu_drm_bind,
 471         .unbind = ipu_drm_unbind,
 472 };
 473 
 474 static int ipu_drm_probe(struct platform_device *pdev)
 475 {
 476         struct device *dev = &pdev->dev;
 477         int ret;
 478 
 479         if (!dev->platform_data)
 480                 return -EINVAL;
 481 
 482         ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
 483         if (ret)
 484                 return ret;
 485 
 486         return component_add(dev, &ipu_crtc_ops);
 487 }
 488 
 489 static int ipu_drm_remove(struct platform_device *pdev)
 490 {
 491         component_del(&pdev->dev, &ipu_crtc_ops);
 492         return 0;
 493 }
 494 
 495 struct platform_driver ipu_drm_driver = {
 496         .driver = {
 497                 .name = "imx-ipuv3-crtc",
 498         },
 499         .probe = ipu_drm_probe,
 500         .remove = ipu_drm_remove,
 501 };

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