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