linux/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
   4 * Copyright (C) 2013 Red Hat
   5 * Author: Rob Clark <robdclark@gmail.com>
   6 */
   7
   8#include <linux/sort.h>
   9
  10#include <drm/drm_atomic.h>
  11#include <drm/drm_mode.h>
  12#include <drm/drm_crtc.h>
  13#include <drm/drm_flip_work.h>
  14#include <drm/drm_fourcc.h>
  15#include <drm/drm_probe_helper.h>
  16#include <drm/drm_vblank.h>
  17
  18#include "mdp5_kms.h"
  19#include "msm_gem.h"
  20
  21#define CURSOR_WIDTH    64
  22#define CURSOR_HEIGHT   64
  23
  24struct mdp5_crtc {
  25        struct drm_crtc base;
  26        int id;
  27        bool enabled;
  28
  29        spinlock_t lm_lock;     /* protect REG_MDP5_LM_* registers */
  30
  31        /* if there is a pending flip, these will be non-null: */
  32        struct drm_pending_vblank_event *event;
  33
  34        /* Bits have been flushed at the last commit,
  35         * used to decide if a vsync has happened since last commit.
  36         */
  37        u32 flushed_mask;
  38
  39#define PENDING_CURSOR 0x1
  40#define PENDING_FLIP   0x2
  41        atomic_t pending;
  42
  43        /* for unref'ing cursor bo's after scanout completes: */
  44        struct drm_flip_work unref_cursor_work;
  45
  46        struct mdp_irq vblank;
  47        struct mdp_irq err;
  48        struct mdp_irq pp_done;
  49
  50        struct completion pp_completion;
  51
  52        bool lm_cursor_enabled;
  53
  54        struct {
  55                /* protect REG_MDP5_LM_CURSOR* registers and cursor scanout_bo*/
  56                spinlock_t lock;
  57
  58                /* current cursor being scanned out: */
  59                struct drm_gem_object *scanout_bo;
  60                uint64_t iova;
  61                uint32_t width, height;
  62                int x, y;
  63        } cursor;
  64};
  65#define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
  66
  67static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc);
  68
  69static struct mdp5_kms *get_kms(struct drm_crtc *crtc)
  70{
  71        struct msm_drm_private *priv = crtc->dev->dev_private;
  72        return to_mdp5_kms(to_mdp_kms(priv->kms));
  73}
  74
  75static void request_pending(struct drm_crtc *crtc, uint32_t pending)
  76{
  77        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
  78
  79        atomic_or(pending, &mdp5_crtc->pending);
  80        mdp_irq_register(&get_kms(crtc)->base, &mdp5_crtc->vblank);
  81}
  82
  83static void request_pp_done_pending(struct drm_crtc *crtc)
  84{
  85        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
  86        reinit_completion(&mdp5_crtc->pp_completion);
  87}
  88
  89static u32 crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
  90{
  91        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
  92        struct mdp5_ctl *ctl = mdp5_cstate->ctl;
  93        struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
  94        bool start = !mdp5_cstate->defer_start;
  95
  96        mdp5_cstate->defer_start = false;
  97
  98        DBG("%s: flush=%08x", crtc->name, flush_mask);
  99
 100        return mdp5_ctl_commit(ctl, pipeline, flush_mask, start);
 101}
 102
 103/*
 104 * flush updates, to make sure hw is updated to new scanout fb,
 105 * so that we can safely queue unref to current fb (ie. next
 106 * vblank we know hw is done w/ previous scanout_fb).
 107 */
 108static u32 crtc_flush_all(struct drm_crtc *crtc)
 109{
 110        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 111        struct mdp5_hw_mixer *mixer, *r_mixer;
 112        struct drm_plane *plane;
 113        uint32_t flush_mask = 0;
 114
 115        /* this should not happen: */
 116        if (WARN_ON(!mdp5_cstate->ctl))
 117                return 0;
 118
 119        drm_atomic_crtc_for_each_plane(plane, crtc) {
 120                if (!plane->state->visible)
 121                        continue;
 122                flush_mask |= mdp5_plane_get_flush(plane);
 123        }
 124
 125        mixer = mdp5_cstate->pipeline.mixer;
 126        flush_mask |= mdp_ctl_flush_mask_lm(mixer->lm);
 127
 128        r_mixer = mdp5_cstate->pipeline.r_mixer;
 129        if (r_mixer)
 130                flush_mask |= mdp_ctl_flush_mask_lm(r_mixer->lm);
 131
 132        return crtc_flush(crtc, flush_mask);
 133}
 134
 135/* if file!=NULL, this is preclose potential cancel-flip path */
 136static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
 137{
 138        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 139        struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
 140        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 141        struct mdp5_ctl *ctl = mdp5_cstate->ctl;
 142        struct drm_device *dev = crtc->dev;
 143        struct drm_pending_vblank_event *event;
 144        unsigned long flags;
 145
 146        spin_lock_irqsave(&dev->event_lock, flags);
 147        event = mdp5_crtc->event;
 148        if (event) {
 149                mdp5_crtc->event = NULL;
 150                DBG("%s: send event: %p", crtc->name, event);
 151                drm_crtc_send_vblank_event(crtc, event);
 152        }
 153        spin_unlock_irqrestore(&dev->event_lock, flags);
 154
 155        if (ctl && !crtc->state->enable) {
 156                /* set STAGE_UNUSED for all layers */
 157                mdp5_ctl_blend(ctl, pipeline, NULL, NULL, 0, 0);
 158                /* XXX: What to do here? */
 159                /* mdp5_crtc->ctl = NULL; */
 160        }
 161}
 162
 163static void unref_cursor_worker(struct drm_flip_work *work, void *val)
 164{
 165        struct mdp5_crtc *mdp5_crtc =
 166                container_of(work, struct mdp5_crtc, unref_cursor_work);
 167        struct mdp5_kms *mdp5_kms = get_kms(&mdp5_crtc->base);
 168        struct msm_kms *kms = &mdp5_kms->base.base;
 169
 170        msm_gem_unpin_iova(val, kms->aspace);
 171        drm_gem_object_put(val);
 172}
 173
 174static void mdp5_crtc_destroy(struct drm_crtc *crtc)
 175{
 176        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 177
 178        drm_crtc_cleanup(crtc);
 179        drm_flip_work_cleanup(&mdp5_crtc->unref_cursor_work);
 180
 181        kfree(mdp5_crtc);
 182}
 183
 184static inline u32 mdp5_lm_use_fg_alpha_mask(enum mdp_mixer_stage_id stage)
 185{
 186        switch (stage) {
 187        case STAGE0: return MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA;
 188        case STAGE1: return MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA;
 189        case STAGE2: return MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA;
 190        case STAGE3: return MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA;
 191        case STAGE4: return MDP5_LM_BLEND_COLOR_OUT_STAGE4_FG_ALPHA;
 192        case STAGE5: return MDP5_LM_BLEND_COLOR_OUT_STAGE5_FG_ALPHA;
 193        case STAGE6: return MDP5_LM_BLEND_COLOR_OUT_STAGE6_FG_ALPHA;
 194        default:
 195                return 0;
 196        }
 197}
 198
 199/*
 200 * left/right pipe offsets for the stage array used in blend_setup()
 201 */
 202#define PIPE_LEFT       0
 203#define PIPE_RIGHT      1
 204
 205/*
 206 * blend_setup() - blend all the planes of a CRTC
 207 *
 208 * If no base layer is available, border will be enabled as the base layer.
 209 * Otherwise all layers will be blended based on their stage calculated
 210 * in mdp5_crtc_atomic_check.
 211 */
 212static void blend_setup(struct drm_crtc *crtc)
 213{
 214        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 215        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 216        struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
 217        struct mdp5_kms *mdp5_kms = get_kms(crtc);
 218        struct drm_plane *plane;
 219        struct mdp5_plane_state *pstate, *pstates[STAGE_MAX + 1] = {NULL};
 220        const struct mdp_format *format;
 221        struct mdp5_hw_mixer *mixer = pipeline->mixer;
 222        uint32_t lm = mixer->lm;
 223        struct mdp5_hw_mixer *r_mixer = pipeline->r_mixer;
 224        uint32_t r_lm = r_mixer ? r_mixer->lm : 0;
 225        struct mdp5_ctl *ctl = mdp5_cstate->ctl;
 226        uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags = 0;
 227        unsigned long flags;
 228        enum mdp5_pipe stage[STAGE_MAX + 1][MAX_PIPE_STAGE] = { { SSPP_NONE } };
 229        enum mdp5_pipe r_stage[STAGE_MAX + 1][MAX_PIPE_STAGE] = { { SSPP_NONE } };
 230        int i, plane_cnt = 0;
 231        bool bg_alpha_enabled = false;
 232        u32 mixer_op_mode = 0;
 233        u32 val;
 234#define blender(stage)  ((stage) - STAGE0)
 235
 236        spin_lock_irqsave(&mdp5_crtc->lm_lock, flags);
 237
 238        /* ctl could be released already when we are shutting down: */
 239        /* XXX: Can this happen now? */
 240        if (!ctl)
 241                goto out;
 242
 243        /* Collect all plane information */
 244        drm_atomic_crtc_for_each_plane(plane, crtc) {
 245                enum mdp5_pipe right_pipe;
 246
 247                if (!plane->state->visible)
 248                        continue;
 249
 250                pstate = to_mdp5_plane_state(plane->state);
 251                pstates[pstate->stage] = pstate;
 252                stage[pstate->stage][PIPE_LEFT] = mdp5_plane_pipe(plane);
 253                /*
 254                 * if we have a right mixer, stage the same pipe as we
 255                 * have on the left mixer
 256                 */
 257                if (r_mixer)
 258                        r_stage[pstate->stage][PIPE_LEFT] =
 259                                                mdp5_plane_pipe(plane);
 260                /*
 261                 * if we have a right pipe (i.e, the plane comprises of 2
 262                 * hwpipes, then stage the right pipe on the right side of both
 263                 * the layer mixers
 264                 */
 265                right_pipe = mdp5_plane_right_pipe(plane);
 266                if (right_pipe) {
 267                        stage[pstate->stage][PIPE_RIGHT] = right_pipe;
 268                        r_stage[pstate->stage][PIPE_RIGHT] = right_pipe;
 269                }
 270
 271                plane_cnt++;
 272        }
 273
 274        if (!pstates[STAGE_BASE]) {
 275                ctl_blend_flags |= MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT;
 276                DBG("Border Color is enabled");
 277        } else if (plane_cnt) {
 278                format = to_mdp_format(msm_framebuffer_format(pstates[STAGE_BASE]->base.fb));
 279
 280                if (format->alpha_enable)
 281                        bg_alpha_enabled = true;
 282        }
 283
 284        /* The reset for blending */
 285        for (i = STAGE0; i <= STAGE_MAX; i++) {
 286                if (!pstates[i])
 287                        continue;
 288
 289                format = to_mdp_format(
 290                        msm_framebuffer_format(pstates[i]->base.fb));
 291                plane = pstates[i]->base.plane;
 292                blend_op = MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) |
 293                        MDP5_LM_BLEND_OP_MODE_BG_ALPHA(BG_CONST);
 294                fg_alpha = pstates[i]->base.alpha >> 8;
 295                bg_alpha = 0xFF - fg_alpha;
 296
 297                if (!format->alpha_enable && bg_alpha_enabled)
 298                        mixer_op_mode = 0;
 299                else
 300                        mixer_op_mode |= mdp5_lm_use_fg_alpha_mask(i);
 301
 302                DBG("Stage %d fg_alpha %x bg_alpha %x", i, fg_alpha, bg_alpha);
 303
 304                if (format->alpha_enable &&
 305                    pstates[i]->base.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) {
 306                        blend_op = MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) |
 307                                MDP5_LM_BLEND_OP_MODE_BG_ALPHA(FG_PIXEL);
 308                        if (fg_alpha != 0xff) {
 309                                bg_alpha = fg_alpha;
 310                                blend_op |=
 311                                        MDP5_LM_BLEND_OP_MODE_BG_MOD_ALPHA |
 312                                        MDP5_LM_BLEND_OP_MODE_BG_INV_MOD_ALPHA;
 313                        } else {
 314                                blend_op |= MDP5_LM_BLEND_OP_MODE_BG_INV_ALPHA;
 315                        }
 316                } else if (format->alpha_enable &&
 317                           pstates[i]->base.pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
 318                        blend_op = MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_PIXEL) |
 319                                MDP5_LM_BLEND_OP_MODE_BG_ALPHA(FG_PIXEL);
 320                        if (fg_alpha != 0xff) {
 321                                bg_alpha = fg_alpha;
 322                                blend_op |=
 323                                       MDP5_LM_BLEND_OP_MODE_FG_MOD_ALPHA |
 324                                       MDP5_LM_BLEND_OP_MODE_FG_INV_MOD_ALPHA |
 325                                       MDP5_LM_BLEND_OP_MODE_BG_MOD_ALPHA |
 326                                       MDP5_LM_BLEND_OP_MODE_BG_INV_MOD_ALPHA;
 327                        } else {
 328                                blend_op |= MDP5_LM_BLEND_OP_MODE_BG_INV_ALPHA;
 329                        }
 330                }
 331
 332                mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_OP_MODE(lm,
 333                                blender(i)), blend_op);
 334                mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_FG_ALPHA(lm,
 335                                blender(i)), fg_alpha);
 336                mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_BG_ALPHA(lm,
 337                                blender(i)), bg_alpha);
 338                if (r_mixer) {
 339                        mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_OP_MODE(r_lm,
 340                                        blender(i)), blend_op);
 341                        mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_FG_ALPHA(r_lm,
 342                                        blender(i)), fg_alpha);
 343                        mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_BG_ALPHA(r_lm,
 344                                        blender(i)), bg_alpha);
 345                }
 346        }
 347
 348        val = mdp5_read(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(lm));
 349        mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(lm),
 350                   val | mixer_op_mode);
 351        if (r_mixer) {
 352                val = mdp5_read(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(r_lm));
 353                mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(r_lm),
 354                           val | mixer_op_mode);
 355        }
 356
 357        mdp5_ctl_blend(ctl, pipeline, stage, r_stage, plane_cnt,
 358                       ctl_blend_flags);
 359out:
 360        spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags);
 361}
 362
 363static void mdp5_crtc_mode_set_nofb(struct drm_crtc *crtc)
 364{
 365        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 366        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 367        struct mdp5_kms *mdp5_kms = get_kms(crtc);
 368        struct mdp5_hw_mixer *mixer = mdp5_cstate->pipeline.mixer;
 369        struct mdp5_hw_mixer *r_mixer = mdp5_cstate->pipeline.r_mixer;
 370        uint32_t lm = mixer->lm;
 371        u32 mixer_width, val;
 372        unsigned long flags;
 373        struct drm_display_mode *mode;
 374
 375        if (WARN_ON(!crtc->state))
 376                return;
 377
 378        mode = &crtc->state->adjusted_mode;
 379
 380        DBG("%s: set mode: " DRM_MODE_FMT, crtc->name, DRM_MODE_ARG(mode));
 381
 382        mixer_width = mode->hdisplay;
 383        if (r_mixer)
 384                mixer_width /= 2;
 385
 386        spin_lock_irqsave(&mdp5_crtc->lm_lock, flags);
 387        mdp5_write(mdp5_kms, REG_MDP5_LM_OUT_SIZE(lm),
 388                        MDP5_LM_OUT_SIZE_WIDTH(mixer_width) |
 389                        MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
 390
 391        /* Assign mixer to LEFT side in source split mode */
 392        val = mdp5_read(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(lm));
 393        val &= ~MDP5_LM_BLEND_COLOR_OUT_SPLIT_LEFT_RIGHT;
 394        mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(lm), val);
 395
 396        if (r_mixer) {
 397                u32 r_lm = r_mixer->lm;
 398
 399                mdp5_write(mdp5_kms, REG_MDP5_LM_OUT_SIZE(r_lm),
 400                           MDP5_LM_OUT_SIZE_WIDTH(mixer_width) |
 401                           MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
 402
 403                /* Assign mixer to RIGHT side in source split mode */
 404                val = mdp5_read(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(r_lm));
 405                val |= MDP5_LM_BLEND_COLOR_OUT_SPLIT_LEFT_RIGHT;
 406                mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(r_lm), val);
 407        }
 408
 409        spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags);
 410}
 411
 412static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc)
 413{
 414        struct drm_device *dev = crtc->dev;
 415        struct drm_encoder *encoder;
 416
 417        drm_for_each_encoder(encoder, dev)
 418                if (encoder->crtc == crtc)
 419                        return encoder;
 420
 421        return NULL;
 422}
 423
 424static bool mdp5_crtc_get_scanout_position(struct drm_crtc *crtc,
 425                                           bool in_vblank_irq,
 426                                           int *vpos, int *hpos,
 427                                           ktime_t *stime, ktime_t *etime,
 428                                           const struct drm_display_mode *mode)
 429{
 430        unsigned int pipe = crtc->index;
 431        struct drm_encoder *encoder;
 432        int line, vsw, vbp, vactive_start, vactive_end, vfp_end;
 433
 434
 435        encoder = get_encoder_from_crtc(crtc);
 436        if (!encoder) {
 437                DRM_ERROR("no encoder found for crtc %d\n", pipe);
 438                return false;
 439        }
 440
 441        vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
 442        vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
 443
 444        /*
 445         * the line counter is 1 at the start of the VSYNC pulse and VTOTAL at
 446         * the end of VFP. Translate the porch values relative to the line
 447         * counter positions.
 448         */
 449
 450        vactive_start = vsw + vbp + 1;
 451
 452        vactive_end = vactive_start + mode->crtc_vdisplay;
 453
 454        /* last scan line before VSYNC */
 455        vfp_end = mode->crtc_vtotal;
 456
 457        if (stime)
 458                *stime = ktime_get();
 459
 460        line = mdp5_encoder_get_linecount(encoder);
 461
 462        if (line < vactive_start)
 463                line -= vactive_start;
 464        else if (line > vactive_end)
 465                line = line - vfp_end - vactive_start;
 466        else
 467                line -= vactive_start;
 468
 469        *vpos = line;
 470        *hpos = 0;
 471
 472        if (etime)
 473                *etime = ktime_get();
 474
 475        return true;
 476}
 477
 478static u32 mdp5_crtc_get_vblank_counter(struct drm_crtc *crtc)
 479{
 480        struct drm_encoder *encoder;
 481
 482        encoder = get_encoder_from_crtc(crtc);
 483        if (!encoder)
 484                return 0;
 485
 486        return mdp5_encoder_get_framecount(encoder);
 487}
 488
 489static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
 490                                     struct drm_atomic_state *state)
 491{
 492        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 493        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 494        struct mdp5_kms *mdp5_kms = get_kms(crtc);
 495        struct device *dev = &mdp5_kms->pdev->dev;
 496        unsigned long flags;
 497
 498        DBG("%s", crtc->name);
 499
 500        if (WARN_ON(!mdp5_crtc->enabled))
 501                return;
 502
 503        /* Disable/save vblank irq handling before power is disabled */
 504        drm_crtc_vblank_off(crtc);
 505
 506        if (mdp5_cstate->cmd_mode)
 507                mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->pp_done);
 508
 509        mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
 510        pm_runtime_put_sync(dev);
 511
 512        if (crtc->state->event && !crtc->state->active) {
 513                WARN_ON(mdp5_crtc->event);
 514                spin_lock_irqsave(&mdp5_kms->dev->event_lock, flags);
 515                drm_crtc_send_vblank_event(crtc, crtc->state->event);
 516                crtc->state->event = NULL;
 517                spin_unlock_irqrestore(&mdp5_kms->dev->event_lock, flags);
 518        }
 519
 520        mdp5_crtc->enabled = false;
 521}
 522
 523static void mdp5_crtc_vblank_on(struct drm_crtc *crtc)
 524{
 525        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 526        struct mdp5_interface *intf = mdp5_cstate->pipeline.intf;
 527        u32 count;
 528
 529        count = intf->mode == MDP5_INTF_DSI_MODE_COMMAND ? 0 : 0xffffffff;
 530        drm_crtc_set_max_vblank_count(crtc, count);
 531
 532        drm_crtc_vblank_on(crtc);
 533}
 534
 535static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
 536                                    struct drm_atomic_state *state)
 537{
 538        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 539        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 540        struct mdp5_kms *mdp5_kms = get_kms(crtc);
 541        struct device *dev = &mdp5_kms->pdev->dev;
 542
 543        DBG("%s", crtc->name);
 544
 545        if (WARN_ON(mdp5_crtc->enabled))
 546                return;
 547
 548        pm_runtime_get_sync(dev);
 549
 550        if (mdp5_crtc->lm_cursor_enabled) {
 551                /*
 552                 * Restore LM cursor state, as it might have been lost
 553                 * with suspend:
 554                 */
 555                if (mdp5_crtc->cursor.iova) {
 556                        unsigned long flags;
 557
 558                        spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
 559                        mdp5_crtc_restore_cursor(crtc);
 560                        spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
 561
 562                        mdp5_ctl_set_cursor(mdp5_cstate->ctl,
 563                                            &mdp5_cstate->pipeline, 0, true);
 564                } else {
 565                        mdp5_ctl_set_cursor(mdp5_cstate->ctl,
 566                                            &mdp5_cstate->pipeline, 0, false);
 567                }
 568        }
 569
 570        /* Restore vblank irq handling after power is enabled */
 571        mdp5_crtc_vblank_on(crtc);
 572
 573        mdp5_crtc_mode_set_nofb(crtc);
 574
 575        mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
 576
 577        if (mdp5_cstate->cmd_mode)
 578                mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->pp_done);
 579
 580        mdp5_crtc->enabled = true;
 581}
 582
 583static int mdp5_crtc_setup_pipeline(struct drm_crtc *crtc,
 584                                    struct drm_crtc_state *new_crtc_state,
 585                                    bool need_right_mixer)
 586{
 587        struct mdp5_crtc_state *mdp5_cstate =
 588                        to_mdp5_crtc_state(new_crtc_state);
 589        struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
 590        struct mdp5_interface *intf;
 591        bool new_mixer = false;
 592
 593        new_mixer = !pipeline->mixer;
 594
 595        if ((need_right_mixer && !pipeline->r_mixer) ||
 596            (!need_right_mixer && pipeline->r_mixer))
 597                new_mixer = true;
 598
 599        if (new_mixer) {
 600                struct mdp5_hw_mixer *old_mixer = pipeline->mixer;
 601                struct mdp5_hw_mixer *old_r_mixer = pipeline->r_mixer;
 602                u32 caps;
 603                int ret;
 604
 605                caps = MDP_LM_CAP_DISPLAY;
 606                if (need_right_mixer)
 607                        caps |= MDP_LM_CAP_PAIR;
 608
 609                ret = mdp5_mixer_assign(new_crtc_state->state, crtc, caps,
 610                                        &pipeline->mixer, need_right_mixer ?
 611                                        &pipeline->r_mixer : NULL);
 612                if (ret)
 613                        return ret;
 614
 615                mdp5_mixer_release(new_crtc_state->state, old_mixer);
 616                if (old_r_mixer) {
 617                        mdp5_mixer_release(new_crtc_state->state, old_r_mixer);
 618                        if (!need_right_mixer)
 619                                pipeline->r_mixer = NULL;
 620                }
 621        }
 622
 623        /*
 624         * these should have been already set up in the encoder's atomic
 625         * check (called by drm_atomic_helper_check_modeset)
 626         */
 627        intf = pipeline->intf;
 628
 629        mdp5_cstate->err_irqmask = intf2err(intf->num);
 630        mdp5_cstate->vblank_irqmask = intf2vblank(pipeline->mixer, intf);
 631
 632        if ((intf->type == INTF_DSI) &&
 633            (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)) {
 634                mdp5_cstate->pp_done_irqmask = lm2ppdone(pipeline->mixer);
 635                mdp5_cstate->cmd_mode = true;
 636        } else {
 637                mdp5_cstate->pp_done_irqmask = 0;
 638                mdp5_cstate->cmd_mode = false;
 639        }
 640
 641        return 0;
 642}
 643
 644struct plane_state {
 645        struct drm_plane *plane;
 646        struct mdp5_plane_state *state;
 647};
 648
 649static int pstate_cmp(const void *a, const void *b)
 650{
 651        struct plane_state *pa = (struct plane_state *)a;
 652        struct plane_state *pb = (struct plane_state *)b;
 653        return pa->state->base.normalized_zpos - pb->state->base.normalized_zpos;
 654}
 655
 656/* is there a helper for this? */
 657static bool is_fullscreen(struct drm_crtc_state *cstate,
 658                struct drm_plane_state *pstate)
 659{
 660        return (pstate->crtc_x <= 0) && (pstate->crtc_y <= 0) &&
 661                ((pstate->crtc_x + pstate->crtc_w) >= cstate->mode.hdisplay) &&
 662                ((pstate->crtc_y + pstate->crtc_h) >= cstate->mode.vdisplay);
 663}
 664
 665static enum mdp_mixer_stage_id get_start_stage(struct drm_crtc *crtc,
 666                                        struct drm_crtc_state *new_crtc_state,
 667                                        struct drm_plane_state *bpstate)
 668{
 669        struct mdp5_crtc_state *mdp5_cstate =
 670                        to_mdp5_crtc_state(new_crtc_state);
 671
 672        /*
 673         * if we're in source split mode, it's mandatory to have
 674         * border out on the base stage
 675         */
 676        if (mdp5_cstate->pipeline.r_mixer)
 677                return STAGE0;
 678
 679        /* if the bottom-most layer is not fullscreen, we need to use
 680         * it for solid-color:
 681         */
 682        if (!is_fullscreen(new_crtc_state, bpstate))
 683                return STAGE0;
 684
 685        return STAGE_BASE;
 686}
 687
 688static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 689                struct drm_atomic_state *state)
 690{
 691        struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
 692                                                                          crtc);
 693        struct mdp5_kms *mdp5_kms = get_kms(crtc);
 694        struct drm_plane *plane;
 695        struct drm_device *dev = crtc->dev;
 696        struct plane_state pstates[STAGE_MAX + 1];
 697        const struct mdp5_cfg_hw *hw_cfg;
 698        const struct drm_plane_state *pstate;
 699        const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
 700        bool cursor_plane = false;
 701        bool need_right_mixer = false;
 702        int cnt = 0, i;
 703        int ret;
 704        enum mdp_mixer_stage_id start;
 705
 706        DBG("%s: check", crtc->name);
 707
 708        drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {
 709                if (!pstate->visible)
 710                        continue;
 711
 712                pstates[cnt].plane = plane;
 713                pstates[cnt].state = to_mdp5_plane_state(pstate);
 714
 715                /*
 716                 * if any plane on this crtc uses 2 hwpipes, then we need
 717                 * the crtc to have a right hwmixer.
 718                 */
 719                if (pstates[cnt].state->r_hwpipe)
 720                        need_right_mixer = true;
 721                cnt++;
 722
 723                if (plane->type == DRM_PLANE_TYPE_CURSOR)
 724                        cursor_plane = true;
 725        }
 726
 727        /* bail out early if there aren't any planes */
 728        if (!cnt)
 729                return 0;
 730
 731        hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
 732
 733        /*
 734         * we need a right hwmixer if the mode's width is greater than a single
 735         * LM's max width
 736         */
 737        if (mode->hdisplay > hw_cfg->lm.max_width)
 738                need_right_mixer = true;
 739
 740        ret = mdp5_crtc_setup_pipeline(crtc, crtc_state, need_right_mixer);
 741        if (ret) {
 742                DRM_DEV_ERROR(dev->dev, "couldn't assign mixers %d\n", ret);
 743                return ret;
 744        }
 745
 746        /* assign a stage based on sorted zpos property */
 747        sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
 748
 749        /* trigger a warning if cursor isn't the highest zorder */
 750        WARN_ON(cursor_plane &&
 751                (pstates[cnt - 1].plane->type != DRM_PLANE_TYPE_CURSOR));
 752
 753        start = get_start_stage(crtc, crtc_state, &pstates[0].state->base);
 754
 755        /* verify that there are not too many planes attached to crtc
 756         * and that we don't have conflicting mixer stages:
 757         */
 758        if ((cnt + start - 1) >= hw_cfg->lm.nb_stages) {
 759                DRM_DEV_ERROR(dev->dev, "too many planes! cnt=%d, start stage=%d\n",
 760                        cnt, start);
 761                return -EINVAL;
 762        }
 763
 764        for (i = 0; i < cnt; i++) {
 765                if (cursor_plane && (i == (cnt - 1)))
 766                        pstates[i].state->stage = hw_cfg->lm.nb_stages;
 767                else
 768                        pstates[i].state->stage = start + i;
 769                DBG("%s: assign pipe %s on stage=%d", crtc->name,
 770                                pstates[i].plane->name,
 771                                pstates[i].state->stage);
 772        }
 773
 774        return 0;
 775}
 776
 777static void mdp5_crtc_atomic_begin(struct drm_crtc *crtc,
 778                                   struct drm_atomic_state *state)
 779{
 780        DBG("%s: begin", crtc->name);
 781}
 782
 783static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc,
 784                                   struct drm_atomic_state *state)
 785{
 786        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 787        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 788        struct drm_device *dev = crtc->dev;
 789        unsigned long flags;
 790
 791        DBG("%s: event: %p", crtc->name, crtc->state->event);
 792
 793        WARN_ON(mdp5_crtc->event);
 794
 795        spin_lock_irqsave(&dev->event_lock, flags);
 796        mdp5_crtc->event = crtc->state->event;
 797        crtc->state->event = NULL;
 798        spin_unlock_irqrestore(&dev->event_lock, flags);
 799
 800        /*
 801         * If no CTL has been allocated in mdp5_crtc_atomic_check(),
 802         * it means we are trying to flush a CRTC whose state is disabled:
 803         * nothing else needs to be done.
 804         */
 805        /* XXX: Can this happen now ? */
 806        if (unlikely(!mdp5_cstate->ctl))
 807                return;
 808
 809        blend_setup(crtc);
 810
 811        /* PP_DONE irq is only used by command mode for now.
 812         * It is better to request pending before FLUSH and START trigger
 813         * to make sure no pp_done irq missed.
 814         * This is safe because no pp_done will happen before SW trigger
 815         * in command mode.
 816         */
 817        if (mdp5_cstate->cmd_mode)
 818                request_pp_done_pending(crtc);
 819
 820        mdp5_crtc->flushed_mask = crtc_flush_all(crtc);
 821
 822        /* XXX are we leaking out state here? */
 823        mdp5_crtc->vblank.irqmask = mdp5_cstate->vblank_irqmask;
 824        mdp5_crtc->err.irqmask = mdp5_cstate->err_irqmask;
 825        mdp5_crtc->pp_done.irqmask = mdp5_cstate->pp_done_irqmask;
 826
 827        request_pending(crtc, PENDING_FLIP);
 828}
 829
 830static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h)
 831{
 832        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 833        uint32_t xres = crtc->mode.hdisplay;
 834        uint32_t yres = crtc->mode.vdisplay;
 835
 836        /*
 837         * Cursor Region Of Interest (ROI) is a plane read from cursor
 838         * buffer to render. The ROI region is determined by the visibility of
 839         * the cursor point. In the default Cursor image the cursor point will
 840         * be at the top left of the cursor image.
 841         *
 842         * Without rotation:
 843         * If the cursor point reaches the right (xres - x < cursor.width) or
 844         * bottom (yres - y < cursor.height) boundary of the screen, then ROI
 845         * width and ROI height need to be evaluated to crop the cursor image
 846         * accordingly.
 847         * (xres-x) will be new cursor width when x > (xres - cursor.width)
 848         * (yres-y) will be new cursor height when y > (yres - cursor.height)
 849         *
 850         * With rotation:
 851         * We get negative x and/or y coordinates.
 852         * (cursor.width - abs(x)) will be new cursor width when x < 0
 853         * (cursor.height - abs(y)) will be new cursor width when y < 0
 854         */
 855        if (mdp5_crtc->cursor.x >= 0)
 856                *roi_w = min(mdp5_crtc->cursor.width, xres -
 857                        mdp5_crtc->cursor.x);
 858        else
 859                *roi_w = mdp5_crtc->cursor.width - abs(mdp5_crtc->cursor.x);
 860        if (mdp5_crtc->cursor.y >= 0)
 861                *roi_h = min(mdp5_crtc->cursor.height, yres -
 862                        mdp5_crtc->cursor.y);
 863        else
 864                *roi_h = mdp5_crtc->cursor.height - abs(mdp5_crtc->cursor.y);
 865}
 866
 867static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc)
 868{
 869        const struct drm_format_info *info = drm_format_info(DRM_FORMAT_ARGB8888);
 870        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 871        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 872        struct mdp5_kms *mdp5_kms = get_kms(crtc);
 873        const enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
 874        uint32_t blendcfg, stride;
 875        uint32_t x, y, src_x, src_y, width, height;
 876        uint32_t roi_w, roi_h;
 877        int lm;
 878
 879        assert_spin_locked(&mdp5_crtc->cursor.lock);
 880
 881        lm = mdp5_cstate->pipeline.mixer->lm;
 882
 883        x = mdp5_crtc->cursor.x;
 884        y = mdp5_crtc->cursor.y;
 885        width = mdp5_crtc->cursor.width;
 886        height = mdp5_crtc->cursor.height;
 887
 888        stride = width * info->cpp[0];
 889
 890        get_roi(crtc, &roi_w, &roi_h);
 891
 892        /* If cusror buffer overlaps due to rotation on the
 893         * upper or left screen border the pixel offset inside
 894         * the cursor buffer of the ROI is the positive overlap
 895         * distance.
 896         */
 897        if (mdp5_crtc->cursor.x < 0) {
 898                src_x = abs(mdp5_crtc->cursor.x);
 899                x = 0;
 900        } else {
 901                src_x = 0;
 902        }
 903        if (mdp5_crtc->cursor.y < 0) {
 904                src_y = abs(mdp5_crtc->cursor.y);
 905                y = 0;
 906        } else {
 907                src_y = 0;
 908        }
 909        DBG("%s: x=%d, y=%d roi_w=%d roi_h=%d src_x=%d src_y=%d",
 910                crtc->name, x, y, roi_w, roi_h, src_x, src_y);
 911
 912        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
 913        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
 914                        MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
 915        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_IMG_SIZE(lm),
 916                        MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) |
 917                        MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width));
 918        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
 919                        MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) |
 920                        MDP5_LM_CURSOR_SIZE_ROI_W(roi_w));
 921        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_START_XY(lm),
 922                        MDP5_LM_CURSOR_START_XY_Y_START(y) |
 923                        MDP5_LM_CURSOR_START_XY_X_START(x));
 924        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_XY(lm),
 925                        MDP5_LM_CURSOR_XY_SRC_Y(src_y) |
 926                        MDP5_LM_CURSOR_XY_SRC_X(src_x));
 927        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm),
 928                        mdp5_crtc->cursor.iova);
 929
 930        blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN;
 931        blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha);
 932        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg);
 933}
 934
 935static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
 936                struct drm_file *file, uint32_t handle,
 937                uint32_t width, uint32_t height)
 938{
 939        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 940        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 941        struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
 942        struct drm_device *dev = crtc->dev;
 943        struct mdp5_kms *mdp5_kms = get_kms(crtc);
 944        struct platform_device *pdev = mdp5_kms->pdev;
 945        struct msm_kms *kms = &mdp5_kms->base.base;
 946        struct drm_gem_object *cursor_bo, *old_bo = NULL;
 947        struct mdp5_ctl *ctl;
 948        int ret;
 949        uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
 950        bool cursor_enable = true;
 951        unsigned long flags;
 952
 953        if (!mdp5_crtc->lm_cursor_enabled) {
 954                dev_warn(dev->dev,
 955                         "cursor_set is deprecated with cursor planes\n");
 956                return -EINVAL;
 957        }
 958
 959        if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
 960                DRM_DEV_ERROR(dev->dev, "bad cursor size: %dx%d\n", width, height);
 961                return -EINVAL;
 962        }
 963
 964        ctl = mdp5_cstate->ctl;
 965        if (!ctl)
 966                return -EINVAL;
 967
 968        /* don't support LM cursors when we have source split enabled */
 969        if (mdp5_cstate->pipeline.r_mixer)
 970                return -EINVAL;
 971
 972        if (!handle) {
 973                DBG("Cursor off");
 974                cursor_enable = false;
 975                mdp5_crtc->cursor.iova = 0;
 976                pm_runtime_get_sync(&pdev->dev);
 977                goto set_cursor;
 978        }
 979
 980        cursor_bo = drm_gem_object_lookup(file, handle);
 981        if (!cursor_bo)
 982                return -ENOENT;
 983
 984        ret = msm_gem_get_and_pin_iova(cursor_bo, kms->aspace,
 985                        &mdp5_crtc->cursor.iova);
 986        if (ret)
 987                return -EINVAL;
 988
 989        pm_runtime_get_sync(&pdev->dev);
 990
 991        spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
 992        old_bo = mdp5_crtc->cursor.scanout_bo;
 993
 994        mdp5_crtc->cursor.scanout_bo = cursor_bo;
 995        mdp5_crtc->cursor.width = width;
 996        mdp5_crtc->cursor.height = height;
 997
 998        mdp5_crtc_restore_cursor(crtc);
 999
1000        spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
1001
1002set_cursor:
1003        ret = mdp5_ctl_set_cursor(ctl, pipeline, 0, cursor_enable);
1004        if (ret) {
1005                DRM_DEV_ERROR(dev->dev, "failed to %sable cursor: %d\n",
1006                                cursor_enable ? "en" : "dis", ret);
1007                goto end;
1008        }
1009
1010        crtc_flush(crtc, flush_mask);
1011
1012end:
1013        pm_runtime_put_sync(&pdev->dev);
1014        if (old_bo) {
1015                drm_flip_work_queue(&mdp5_crtc->unref_cursor_work, old_bo);
1016                /* enable vblank to complete cursor work: */
1017                request_pending(crtc, PENDING_CURSOR);
1018        }
1019        return ret;
1020}
1021
1022static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
1023{
1024        struct mdp5_kms *mdp5_kms = get_kms(crtc);
1025        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
1026        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
1027        uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
1028        struct drm_device *dev = crtc->dev;
1029        uint32_t roi_w;
1030        uint32_t roi_h;
1031        unsigned long flags;
1032
1033        if (!mdp5_crtc->lm_cursor_enabled) {
1034                dev_warn(dev->dev,
1035                         "cursor_move is deprecated with cursor planes\n");
1036                return -EINVAL;
1037        }
1038
1039        /* don't support LM cursors when we have source split enabled */
1040        if (mdp5_cstate->pipeline.r_mixer)
1041                return -EINVAL;
1042
1043        /* In case the CRTC is disabled, just drop the cursor update */
1044        if (unlikely(!crtc->state->enable))
1045                return 0;
1046
1047        /* accept negative x/y coordinates up to maximum cursor overlap */
1048        mdp5_crtc->cursor.x = x = max(x, -(int)mdp5_crtc->cursor.width);
1049        mdp5_crtc->cursor.y = y = max(y, -(int)mdp5_crtc->cursor.height);
1050
1051        get_roi(crtc, &roi_w, &roi_h);
1052
1053        pm_runtime_get_sync(&mdp5_kms->pdev->dev);
1054
1055        spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
1056        mdp5_crtc_restore_cursor(crtc);
1057        spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
1058
1059        crtc_flush(crtc, flush_mask);
1060
1061        pm_runtime_put_sync(&mdp5_kms->pdev->dev);
1062
1063        return 0;
1064}
1065
1066static void
1067mdp5_crtc_atomic_print_state(struct drm_printer *p,
1068                             const struct drm_crtc_state *state)
1069{
1070        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(state);
1071        struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
1072        struct mdp5_kms *mdp5_kms = get_kms(state->crtc);
1073
1074        if (WARN_ON(!pipeline))
1075                return;
1076
1077        if (mdp5_cstate->ctl)
1078                drm_printf(p, "\tctl=%d\n", mdp5_ctl_get_ctl_id(mdp5_cstate->ctl));
1079
1080        drm_printf(p, "\thwmixer=%s\n", pipeline->mixer ?
1081                        pipeline->mixer->name : "(null)");
1082
1083        if (mdp5_kms->caps & MDP_CAP_SRC_SPLIT)
1084                drm_printf(p, "\tright hwmixer=%s\n", pipeline->r_mixer ?
1085                           pipeline->r_mixer->name : "(null)");
1086
1087        drm_printf(p, "\tcmd_mode=%d\n", mdp5_cstate->cmd_mode);
1088}
1089
1090static struct drm_crtc_state *
1091mdp5_crtc_duplicate_state(struct drm_crtc *crtc)
1092{
1093        struct mdp5_crtc_state *mdp5_cstate;
1094
1095        if (WARN_ON(!crtc->state))
1096                return NULL;
1097
1098        mdp5_cstate = kmemdup(to_mdp5_crtc_state(crtc->state),
1099                              sizeof(*mdp5_cstate), GFP_KERNEL);
1100        if (!mdp5_cstate)
1101                return NULL;
1102
1103        __drm_atomic_helper_crtc_duplicate_state(crtc, &mdp5_cstate->base);
1104
1105        return &mdp5_cstate->base;
1106}
1107
1108static void mdp5_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state)
1109{
1110        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(state);
1111
1112        __drm_atomic_helper_crtc_destroy_state(state);
1113
1114        kfree(mdp5_cstate);
1115}
1116
1117static void mdp5_crtc_reset(struct drm_crtc *crtc)
1118{
1119        struct mdp5_crtc_state *mdp5_cstate =
1120                kzalloc(sizeof(*mdp5_cstate), GFP_KERNEL);
1121
1122        if (crtc->state)
1123                mdp5_crtc_destroy_state(crtc, crtc->state);
1124
1125        __drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base);
1126}
1127
1128static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = {
1129        .set_config = drm_atomic_helper_set_config,
1130        .destroy = mdp5_crtc_destroy,
1131        .page_flip = drm_atomic_helper_page_flip,
1132        .reset = mdp5_crtc_reset,
1133        .atomic_duplicate_state = mdp5_crtc_duplicate_state,
1134        .atomic_destroy_state = mdp5_crtc_destroy_state,
1135        .atomic_print_state = mdp5_crtc_atomic_print_state,
1136        .get_vblank_counter = mdp5_crtc_get_vblank_counter,
1137        .enable_vblank  = msm_crtc_enable_vblank,
1138        .disable_vblank = msm_crtc_disable_vblank,
1139        .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
1140};
1141
1142static const struct drm_crtc_funcs mdp5_crtc_funcs = {
1143        .set_config = drm_atomic_helper_set_config,
1144        .destroy = mdp5_crtc_destroy,
1145        .page_flip = drm_atomic_helper_page_flip,
1146        .reset = mdp5_crtc_reset,
1147        .atomic_duplicate_state = mdp5_crtc_duplicate_state,
1148        .atomic_destroy_state = mdp5_crtc_destroy_state,
1149        .cursor_set = mdp5_crtc_cursor_set,
1150        .cursor_move = mdp5_crtc_cursor_move,
1151        .atomic_print_state = mdp5_crtc_atomic_print_state,
1152        .get_vblank_counter = mdp5_crtc_get_vblank_counter,
1153        .enable_vblank  = msm_crtc_enable_vblank,
1154        .disable_vblank = msm_crtc_disable_vblank,
1155        .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
1156};
1157
1158static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
1159        .mode_set_nofb = mdp5_crtc_mode_set_nofb,
1160        .atomic_check = mdp5_crtc_atomic_check,
1161        .atomic_begin = mdp5_crtc_atomic_begin,
1162        .atomic_flush = mdp5_crtc_atomic_flush,
1163        .atomic_enable = mdp5_crtc_atomic_enable,
1164        .atomic_disable = mdp5_crtc_atomic_disable,
1165        .get_scanout_position = mdp5_crtc_get_scanout_position,
1166};
1167
1168static void mdp5_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus)
1169{
1170        struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, vblank);
1171        struct drm_crtc *crtc = &mdp5_crtc->base;
1172        struct msm_drm_private *priv = crtc->dev->dev_private;
1173        unsigned pending;
1174
1175        mdp_irq_unregister(&get_kms(crtc)->base, &mdp5_crtc->vblank);
1176
1177        pending = atomic_xchg(&mdp5_crtc->pending, 0);
1178
1179        if (pending & PENDING_FLIP) {
1180                complete_flip(crtc, NULL);
1181        }
1182
1183        if (pending & PENDING_CURSOR)
1184                drm_flip_work_commit(&mdp5_crtc->unref_cursor_work, priv->wq);
1185}
1186
1187static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
1188{
1189        struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, err);
1190
1191        DBG("%s: error: %08x", mdp5_crtc->base.name, irqstatus);
1192}
1193
1194static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus)
1195{
1196        struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc,
1197                                                                pp_done);
1198
1199        complete_all(&mdp5_crtc->pp_completion);
1200}
1201
1202static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
1203{
1204        struct drm_device *dev = crtc->dev;
1205        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
1206        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
1207        int ret;
1208
1209        ret = wait_for_completion_timeout(&mdp5_crtc->pp_completion,
1210                                                msecs_to_jiffies(50));
1211        if (ret == 0)
1212                dev_warn_ratelimited(dev->dev, "pp done time out, lm=%d\n",
1213                                     mdp5_cstate->pipeline.mixer->lm);
1214}
1215
1216static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc)
1217{
1218        struct drm_device *dev = crtc->dev;
1219        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
1220        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
1221        struct mdp5_ctl *ctl = mdp5_cstate->ctl;
1222        int ret;
1223
1224        /* Should not call this function if crtc is disabled. */
1225        if (!ctl)
1226                return;
1227
1228        ret = drm_crtc_vblank_get(crtc);
1229        if (ret)
1230                return;
1231
1232        ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
1233                ((mdp5_ctl_get_commit_status(ctl) &
1234                mdp5_crtc->flushed_mask) == 0),
1235                msecs_to_jiffies(50));
1236        if (ret <= 0)
1237                dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp5_crtc->id);
1238
1239        mdp5_crtc->flushed_mask = 0;
1240
1241        drm_crtc_vblank_put(crtc);
1242}
1243
1244uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc)
1245{
1246        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
1247        return mdp5_crtc->vblank.irqmask;
1248}
1249
1250void mdp5_crtc_set_pipeline(struct drm_crtc *crtc)
1251{
1252        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
1253        struct mdp5_kms *mdp5_kms = get_kms(crtc);
1254
1255        /* should this be done elsewhere ? */
1256        mdp_irq_update(&mdp5_kms->base);
1257
1258        mdp5_ctl_set_pipeline(mdp5_cstate->ctl, &mdp5_cstate->pipeline);
1259}
1260
1261struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)
1262{
1263        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
1264
1265        return mdp5_cstate->ctl;
1266}
1267
1268struct mdp5_hw_mixer *mdp5_crtc_get_mixer(struct drm_crtc *crtc)
1269{
1270        struct mdp5_crtc_state *mdp5_cstate;
1271
1272        if (WARN_ON(!crtc))
1273                return ERR_PTR(-EINVAL);
1274
1275        mdp5_cstate = to_mdp5_crtc_state(crtc->state);
1276
1277        return WARN_ON(!mdp5_cstate->pipeline.mixer) ?
1278                ERR_PTR(-EINVAL) : mdp5_cstate->pipeline.mixer;
1279}
1280
1281struct mdp5_pipeline *mdp5_crtc_get_pipeline(struct drm_crtc *crtc)
1282{
1283        struct mdp5_crtc_state *mdp5_cstate;
1284
1285        if (WARN_ON(!crtc))
1286                return ERR_PTR(-EINVAL);
1287
1288        mdp5_cstate = to_mdp5_crtc_state(crtc->state);
1289
1290        return &mdp5_cstate->pipeline;
1291}
1292
1293void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)
1294{
1295        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
1296
1297        if (mdp5_cstate->cmd_mode)
1298                mdp5_crtc_wait_for_pp_done(crtc);
1299        else
1300                mdp5_crtc_wait_for_flush_done(crtc);
1301}
1302
1303/* initialize crtc */
1304struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
1305                                struct drm_plane *plane,
1306                                struct drm_plane *cursor_plane, int id)
1307{
1308        struct drm_crtc *crtc = NULL;
1309        struct mdp5_crtc *mdp5_crtc;
1310
1311        mdp5_crtc = kzalloc(sizeof(*mdp5_crtc), GFP_KERNEL);
1312        if (!mdp5_crtc)
1313                return ERR_PTR(-ENOMEM);
1314
1315        crtc = &mdp5_crtc->base;
1316
1317        mdp5_crtc->id = id;
1318
1319        spin_lock_init(&mdp5_crtc->lm_lock);
1320        spin_lock_init(&mdp5_crtc->cursor.lock);
1321        init_completion(&mdp5_crtc->pp_completion);
1322
1323        mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
1324        mdp5_crtc->err.irq = mdp5_crtc_err_irq;
1325        mdp5_crtc->pp_done.irq = mdp5_crtc_pp_done_irq;
1326
1327        mdp5_crtc->lm_cursor_enabled = cursor_plane ? false : true;
1328
1329        drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane,
1330                                  cursor_plane ?
1331                                  &mdp5_crtc_no_lm_cursor_funcs :
1332                                  &mdp5_crtc_funcs, NULL);
1333
1334        drm_flip_work_init(&mdp5_crtc->unref_cursor_work,
1335                        "unref cursor", unref_cursor_worker);
1336
1337        drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs);
1338
1339        return crtc;
1340}
1341