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