linux/drivers/gpu/drm/meson/meson_crtc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2016 BayLibre, SAS
   4 * Author: Neil Armstrong <narmstrong@baylibre.com>
   5 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
   6 * Copyright (C) 2014 Endless Mobile
   7 *
   8 * Written by:
   9 *     Jasper St. Pierre <jstpierre@mecheye.net>
  10 */
  11
  12#include <linux/bitfield.h>
  13#include <linux/soc/amlogic/meson-canvas.h>
  14
  15#include <drm/drm_atomic_helper.h>
  16#include <drm/drm_device.h>
  17#include <drm/drm_print.h>
  18#include <drm/drm_probe_helper.h>
  19#include <drm/drm_vblank.h>
  20
  21#include "meson_crtc.h"
  22#include "meson_plane.h"
  23#include "meson_registers.h"
  24#include "meson_venc.h"
  25#include "meson_viu.h"
  26#include "meson_rdma.h"
  27#include "meson_vpp.h"
  28#include "meson_osd_afbcd.h"
  29
  30#define MESON_G12A_VIU_OFFSET   0x5ec0
  31
  32/* CRTC definition */
  33
  34struct meson_crtc {
  35        struct drm_crtc base;
  36        struct drm_pending_vblank_event *event;
  37        struct meson_drm *priv;
  38        void (*enable_osd1)(struct meson_drm *priv);
  39        void (*enable_vd1)(struct meson_drm *priv);
  40        void (*enable_osd1_afbc)(struct meson_drm *priv);
  41        void (*disable_osd1_afbc)(struct meson_drm *priv);
  42        unsigned int viu_offset;
  43        bool vsync_forced;
  44        bool vsync_disabled;
  45};
  46#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
  47
  48/* CRTC */
  49
  50static int meson_crtc_enable_vblank(struct drm_crtc *crtc)
  51{
  52        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
  53        struct meson_drm *priv = meson_crtc->priv;
  54
  55        meson_crtc->vsync_disabled = false;
  56        meson_venc_enable_vsync(priv);
  57
  58        return 0;
  59}
  60
  61static void meson_crtc_disable_vblank(struct drm_crtc *crtc)
  62{
  63        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
  64        struct meson_drm *priv = meson_crtc->priv;
  65
  66        if (!meson_crtc->vsync_forced) {
  67                meson_crtc->vsync_disabled = true;
  68                meson_venc_disable_vsync(priv);
  69        }
  70}
  71
  72static const struct drm_crtc_funcs meson_crtc_funcs = {
  73        .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
  74        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
  75        .destroy                = drm_crtc_cleanup,
  76        .page_flip              = drm_atomic_helper_page_flip,
  77        .reset                  = drm_atomic_helper_crtc_reset,
  78        .set_config             = drm_atomic_helper_set_config,
  79        .enable_vblank          = meson_crtc_enable_vblank,
  80        .disable_vblank         = meson_crtc_disable_vblank,
  81
  82};
  83
  84static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
  85                                          struct drm_atomic_state *state)
  86{
  87        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
  88        struct drm_crtc_state *crtc_state = crtc->state;
  89        struct meson_drm *priv = meson_crtc->priv;
  90
  91        DRM_DEBUG_DRIVER("\n");
  92
  93        if (!crtc_state) {
  94                DRM_ERROR("Invalid crtc_state\n");
  95                return;
  96        }
  97
  98        /* VD1 Preblend vertical start/end */
  99        writel(FIELD_PREP(GENMASK(11, 0), 2303),
 100               priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
 101
 102        /* Setup Blender */
 103        writel(crtc_state->mode.hdisplay |
 104               crtc_state->mode.vdisplay << 16,
 105               priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
 106
 107        writel_relaxed(0 << 16 |
 108                        (crtc_state->mode.hdisplay - 1),
 109                        priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE));
 110        writel_relaxed(0 << 16 |
 111                        (crtc_state->mode.vdisplay - 1),
 112                        priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
 113        writel_relaxed(crtc_state->mode.hdisplay << 16 |
 114                        crtc_state->mode.vdisplay,
 115                        priv->io_base + _REG(VPP_OUT_H_V_SIZE));
 116
 117        drm_crtc_vblank_on(crtc);
 118}
 119
 120static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
 121                                     struct drm_atomic_state *state)
 122{
 123        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 124        struct drm_crtc_state *crtc_state = crtc->state;
 125        struct meson_drm *priv = meson_crtc->priv;
 126
 127        DRM_DEBUG_DRIVER("\n");
 128
 129        if (!crtc_state) {
 130                DRM_ERROR("Invalid crtc_state\n");
 131                return;
 132        }
 133
 134        /* Enable VPP Postblend */
 135        writel(crtc_state->mode.hdisplay,
 136               priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
 137
 138        /* VD1 Preblend vertical start/end */
 139        writel(FIELD_PREP(GENMASK(11, 0), 2303),
 140                        priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
 141
 142        writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
 143                            priv->io_base + _REG(VPP_MISC));
 144
 145        drm_crtc_vblank_on(crtc);
 146}
 147
 148static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
 149                                           struct drm_atomic_state *state)
 150{
 151        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 152        struct meson_drm *priv = meson_crtc->priv;
 153
 154        DRM_DEBUG_DRIVER("\n");
 155
 156        drm_crtc_vblank_off(crtc);
 157
 158        priv->viu.osd1_enabled = false;
 159        priv->viu.osd1_commit = false;
 160
 161        priv->viu.vd1_enabled = false;
 162        priv->viu.vd1_commit = false;
 163
 164        if (crtc->state->event && !crtc->state->active) {
 165                spin_lock_irq(&crtc->dev->event_lock);
 166                drm_crtc_send_vblank_event(crtc, crtc->state->event);
 167                spin_unlock_irq(&crtc->dev->event_lock);
 168
 169                crtc->state->event = NULL;
 170        }
 171}
 172
 173static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
 174                                      struct drm_atomic_state *state)
 175{
 176        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 177        struct meson_drm *priv = meson_crtc->priv;
 178
 179        DRM_DEBUG_DRIVER("\n");
 180
 181        drm_crtc_vblank_off(crtc);
 182
 183        priv->viu.osd1_enabled = false;
 184        priv->viu.osd1_commit = false;
 185
 186        priv->viu.vd1_enabled = false;
 187        priv->viu.vd1_commit = false;
 188
 189        /* Disable VPP Postblend */
 190        writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_VD1_POSTBLEND |
 191                            VPP_VD1_PREBLEND | VPP_POSTBLEND_ENABLE, 0,
 192                            priv->io_base + _REG(VPP_MISC));
 193
 194        if (crtc->state->event && !crtc->state->active) {
 195                spin_lock_irq(&crtc->dev->event_lock);
 196                drm_crtc_send_vblank_event(crtc, crtc->state->event);
 197                spin_unlock_irq(&crtc->dev->event_lock);
 198
 199                crtc->state->event = NULL;
 200        }
 201}
 202
 203static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
 204                                    struct drm_atomic_state *state)
 205{
 206        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 207        unsigned long flags;
 208
 209        if (crtc->state->event) {
 210                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 211
 212                spin_lock_irqsave(&crtc->dev->event_lock, flags);
 213                meson_crtc->event = crtc->state->event;
 214                spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 215                crtc->state->event = NULL;
 216        }
 217}
 218
 219static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
 220                                    struct drm_atomic_state *state)
 221{
 222        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 223        struct meson_drm *priv = meson_crtc->priv;
 224
 225        priv->viu.osd1_commit = true;
 226        priv->viu.vd1_commit = true;
 227}
 228
 229static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
 230        .atomic_begin   = meson_crtc_atomic_begin,
 231        .atomic_flush   = meson_crtc_atomic_flush,
 232        .atomic_enable  = meson_crtc_atomic_enable,
 233        .atomic_disable = meson_crtc_atomic_disable,
 234};
 235
 236static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = {
 237        .atomic_begin   = meson_crtc_atomic_begin,
 238        .atomic_flush   = meson_crtc_atomic_flush,
 239        .atomic_enable  = meson_g12a_crtc_atomic_enable,
 240        .atomic_disable = meson_g12a_crtc_atomic_disable,
 241};
 242
 243static void meson_crtc_enable_osd1(struct meson_drm *priv)
 244{
 245        writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
 246                            priv->io_base + _REG(VPP_MISC));
 247}
 248
 249static void meson_crtc_g12a_enable_osd1_afbc(struct meson_drm *priv)
 250{
 251        writel_relaxed(priv->viu.osd1_blk2_cfg4,
 252                       priv->io_base + _REG(VIU_OSD1_BLK2_CFG_W4));
 253
 254        writel_bits_relaxed(OSD_MEM_LINEAR_ADDR, OSD_MEM_LINEAR_ADDR,
 255                            priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
 256
 257        writel_relaxed(priv->viu.osd1_blk1_cfg4,
 258                       priv->io_base + _REG(VIU_OSD1_BLK1_CFG_W4));
 259
 260        meson_viu_g12a_enable_osd1_afbc(priv);
 261
 262        writel_bits_relaxed(OSD_MEM_LINEAR_ADDR, OSD_MEM_LINEAR_ADDR,
 263                            priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
 264
 265        writel_bits_relaxed(OSD_MALI_SRC_EN, OSD_MALI_SRC_EN,
 266                            priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
 267}
 268
 269static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
 270{
 271        writel_relaxed(priv->viu.osd_blend_din0_scope_h,
 272                       priv->io_base +
 273                       _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
 274        writel_relaxed(priv->viu.osd_blend_din0_scope_v,
 275                       priv->io_base +
 276                       _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
 277        writel_relaxed(priv->viu.osb_blend0_size,
 278                       priv->io_base +
 279                       _REG(VIU_OSD_BLEND_BLEND0_SIZE));
 280        writel_relaxed(priv->viu.osb_blend1_size,
 281                       priv->io_base +
 282                       _REG(VIU_OSD_BLEND_BLEND1_SIZE));
 283        writel_bits_relaxed(3 << 8, 3 << 8,
 284                            priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
 285}
 286
 287static void meson_crtc_enable_vd1(struct meson_drm *priv)
 288{
 289        writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
 290                            VPP_COLOR_MNG_ENABLE,
 291                            VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
 292                            VPP_COLOR_MNG_ENABLE,
 293                            priv->io_base + _REG(VPP_MISC));
 294
 295        writel_bits_relaxed(VIU_CTRL0_AFBC_TO_VD1,
 296                            priv->viu.vd1_afbc ? VIU_CTRL0_AFBC_TO_VD1 : 0,
 297                            priv->io_base + _REG(VIU_MISC_CTRL0));
 298}
 299
 300static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
 301{
 302        writel_relaxed(VD_BLEND_PREBLD_SRC_VD1 |
 303                       VD_BLEND_PREBLD_PREMULT_EN |
 304                       VD_BLEND_POSTBLD_SRC_VD1 |
 305                       VD_BLEND_POSTBLD_PREMULT_EN,
 306                       priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
 307
 308        writel_relaxed(priv->viu.vd1_afbc ?
 309                       (VD1_AXI_SEL_AFBC | AFBC_VD1_SEL) : 0,
 310                       priv->io_base + _REG(VD1_AFBCD0_MISC_CTRL));
 311}
 312
 313void meson_crtc_irq(struct meson_drm *priv)
 314{
 315        struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
 316        unsigned long flags;
 317
 318        /* Update the OSD registers */
 319        if (priv->viu.osd1_enabled && priv->viu.osd1_commit) {
 320                writel_relaxed(priv->viu.osd1_ctrl_stat,
 321                                priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
 322                writel_relaxed(priv->viu.osd1_ctrl_stat2,
 323                                priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
 324                writel_relaxed(priv->viu.osd1_blk0_cfg[0],
 325                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
 326                writel_relaxed(priv->viu.osd1_blk0_cfg[1],
 327                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1));
 328                writel_relaxed(priv->viu.osd1_blk0_cfg[2],
 329                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2));
 330                writel_relaxed(priv->viu.osd1_blk0_cfg[3],
 331                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
 332                writel_relaxed(priv->viu.osd1_blk0_cfg[4],
 333                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
 334
 335                if (priv->viu.osd1_afbcd) {
 336                        if (meson_crtc->enable_osd1_afbc)
 337                                meson_crtc->enable_osd1_afbc(priv);
 338                } else {
 339                        if (meson_crtc->disable_osd1_afbc)
 340                                meson_crtc->disable_osd1_afbc(priv);
 341                        if (priv->afbcd.ops) {
 342                                priv->afbcd.ops->reset(priv);
 343                                priv->afbcd.ops->disable(priv);
 344                        }
 345                        meson_crtc->vsync_forced = false;
 346                }
 347
 348                writel_relaxed(priv->viu.osd_sc_ctrl0,
 349                                priv->io_base + _REG(VPP_OSD_SC_CTRL0));
 350                writel_relaxed(priv->viu.osd_sc_i_wh_m1,
 351                                priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
 352                writel_relaxed(priv->viu.osd_sc_o_h_start_end,
 353                                priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
 354                writel_relaxed(priv->viu.osd_sc_o_v_start_end,
 355                                priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
 356                writel_relaxed(priv->viu.osd_sc_v_ini_phase,
 357                                priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
 358                writel_relaxed(priv->viu.osd_sc_v_phase_step,
 359                                priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
 360                writel_relaxed(priv->viu.osd_sc_h_ini_phase,
 361                                priv->io_base + _REG(VPP_OSD_HSC_INI_PHASE));
 362                writel_relaxed(priv->viu.osd_sc_h_phase_step,
 363                                priv->io_base + _REG(VPP_OSD_HSC_PHASE_STEP));
 364                writel_relaxed(priv->viu.osd_sc_h_ctrl0,
 365                                priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
 366                writel_relaxed(priv->viu.osd_sc_v_ctrl0,
 367                                priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
 368
 369                if (!priv->viu.osd1_afbcd)
 370                        meson_canvas_config(priv->canvas, priv->canvas_id_osd1,
 371                                            priv->viu.osd1_addr,
 372                                            priv->viu.osd1_stride,
 373                                            priv->viu.osd1_height,
 374                                            MESON_CANVAS_WRAP_NONE,
 375                                            MESON_CANVAS_BLKMODE_LINEAR, 0);
 376
 377                /* Enable OSD1 */
 378                if (meson_crtc->enable_osd1)
 379                        meson_crtc->enable_osd1(priv);
 380
 381                if (priv->viu.osd1_afbcd) {
 382                        priv->afbcd.ops->reset(priv);
 383                        priv->afbcd.ops->setup(priv);
 384                        priv->afbcd.ops->enable(priv);
 385                        meson_crtc->vsync_forced = true;
 386                }
 387
 388                priv->viu.osd1_commit = false;
 389        }
 390
 391        /* Update the VD1 registers */
 392        if (priv->viu.vd1_enabled && priv->viu.vd1_commit) {
 393
 394                if (priv->viu.vd1_afbc) {
 395                        writel_relaxed(priv->viu.vd1_afbc_head_addr,
 396                                       priv->io_base +
 397                                       _REG(AFBC_HEAD_BADDR));
 398                        writel_relaxed(priv->viu.vd1_afbc_body_addr,
 399                                       priv->io_base +
 400                                       _REG(AFBC_BODY_BADDR));
 401                        writel_relaxed(priv->viu.vd1_afbc_en,
 402                                       priv->io_base +
 403                                       _REG(AFBC_ENABLE));
 404                        writel_relaxed(priv->viu.vd1_afbc_mode,
 405                                       priv->io_base +
 406                                       _REG(AFBC_MODE));
 407                        writel_relaxed(priv->viu.vd1_afbc_size_in,
 408                                       priv->io_base +
 409                                       _REG(AFBC_SIZE_IN));
 410                        writel_relaxed(priv->viu.vd1_afbc_dec_def_color,
 411                                       priv->io_base +
 412                                       _REG(AFBC_DEC_DEF_COLOR));
 413                        writel_relaxed(priv->viu.vd1_afbc_conv_ctrl,
 414                                       priv->io_base +
 415                                       _REG(AFBC_CONV_CTRL));
 416                        writel_relaxed(priv->viu.vd1_afbc_size_out,
 417                                       priv->io_base +
 418                                       _REG(AFBC_SIZE_OUT));
 419                        writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_ctrl,
 420                                       priv->io_base +
 421                                       _REG(AFBC_VD_CFMT_CTRL));
 422                        writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_w,
 423                                       priv->io_base +
 424                                       _REG(AFBC_VD_CFMT_W));
 425                        writel_relaxed(priv->viu.vd1_afbc_mif_hor_scope,
 426                                       priv->io_base +
 427                                       _REG(AFBC_MIF_HOR_SCOPE));
 428                        writel_relaxed(priv->viu.vd1_afbc_mif_ver_scope,
 429                                       priv->io_base +
 430                                       _REG(AFBC_MIF_VER_SCOPE));
 431                        writel_relaxed(priv->viu.vd1_afbc_pixel_hor_scope,
 432                                       priv->io_base+
 433                                       _REG(AFBC_PIXEL_HOR_SCOPE));
 434                        writel_relaxed(priv->viu.vd1_afbc_pixel_ver_scope,
 435                                       priv->io_base +
 436                                       _REG(AFBC_PIXEL_VER_SCOPE));
 437                        writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_h,
 438                                       priv->io_base +
 439                                       _REG(AFBC_VD_CFMT_H));
 440                } else {
 441                        switch (priv->viu.vd1_planes) {
 442                        case 3:
 443                                meson_canvas_config(priv->canvas,
 444                                                    priv->canvas_id_vd1_2,
 445                                                    priv->viu.vd1_addr2,
 446                                                    priv->viu.vd1_stride2,
 447                                                    priv->viu.vd1_height2,
 448                                                    MESON_CANVAS_WRAP_NONE,
 449                                                    MESON_CANVAS_BLKMODE_LINEAR,
 450                                                    MESON_CANVAS_ENDIAN_SWAP64);
 451                                fallthrough;
 452                        case 2:
 453                                meson_canvas_config(priv->canvas,
 454                                                    priv->canvas_id_vd1_1,
 455                                                    priv->viu.vd1_addr1,
 456                                                    priv->viu.vd1_stride1,
 457                                                    priv->viu.vd1_height1,
 458                                                    MESON_CANVAS_WRAP_NONE,
 459                                                    MESON_CANVAS_BLKMODE_LINEAR,
 460                                                    MESON_CANVAS_ENDIAN_SWAP64);
 461                                fallthrough;
 462                        case 1:
 463                                meson_canvas_config(priv->canvas,
 464                                                    priv->canvas_id_vd1_0,
 465                                                    priv->viu.vd1_addr0,
 466                                                    priv->viu.vd1_stride0,
 467                                                    priv->viu.vd1_height0,
 468                                                    MESON_CANVAS_WRAP_NONE,
 469                                                    MESON_CANVAS_BLKMODE_LINEAR,
 470                                                    MESON_CANVAS_ENDIAN_SWAP64);
 471                        }
 472
 473                        writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
 474                }
 475
 476                writel_relaxed(priv->viu.vd1_if0_gen_reg,
 477                                priv->io_base + meson_crtc->viu_offset +
 478                                _REG(VD1_IF0_GEN_REG));
 479                writel_relaxed(priv->viu.vd1_if0_gen_reg,
 480                                priv->io_base + meson_crtc->viu_offset +
 481                                _REG(VD2_IF0_GEN_REG));
 482                writel_relaxed(priv->viu.vd1_if0_gen_reg2,
 483                                priv->io_base + meson_crtc->viu_offset +
 484                                _REG(VD1_IF0_GEN_REG2));
 485                writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
 486                                priv->io_base + meson_crtc->viu_offset +
 487                                _REG(VIU_VD1_FMT_CTRL));
 488                writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
 489                                priv->io_base + meson_crtc->viu_offset +
 490                                _REG(VIU_VD2_FMT_CTRL));
 491                writel_relaxed(priv->viu.viu_vd1_fmt_w,
 492                                priv->io_base + meson_crtc->viu_offset +
 493                                _REG(VIU_VD1_FMT_W));
 494                writel_relaxed(priv->viu.viu_vd1_fmt_w,
 495                                priv->io_base + meson_crtc->viu_offset +
 496                                _REG(VIU_VD2_FMT_W));
 497                writel_relaxed(priv->viu.vd1_if0_canvas0,
 498                                priv->io_base + meson_crtc->viu_offset +
 499                                _REG(VD1_IF0_CANVAS0));
 500                writel_relaxed(priv->viu.vd1_if0_canvas0,
 501                                priv->io_base + meson_crtc->viu_offset +
 502                                _REG(VD1_IF0_CANVAS1));
 503                writel_relaxed(priv->viu.vd1_if0_canvas0,
 504                                priv->io_base + meson_crtc->viu_offset +
 505                                _REG(VD2_IF0_CANVAS0));
 506                writel_relaxed(priv->viu.vd1_if0_canvas0,
 507                                priv->io_base + meson_crtc->viu_offset +
 508                                _REG(VD2_IF0_CANVAS1));
 509                writel_relaxed(priv->viu.vd1_if0_luma_x0,
 510                                priv->io_base + meson_crtc->viu_offset +
 511                                _REG(VD1_IF0_LUMA_X0));
 512                writel_relaxed(priv->viu.vd1_if0_luma_x0,
 513                                priv->io_base + meson_crtc->viu_offset +
 514                                _REG(VD1_IF0_LUMA_X1));
 515                writel_relaxed(priv->viu.vd1_if0_luma_x0,
 516                                priv->io_base + meson_crtc->viu_offset +
 517                                _REG(VD2_IF0_LUMA_X0));
 518                writel_relaxed(priv->viu.vd1_if0_luma_x0,
 519                                priv->io_base + meson_crtc->viu_offset +
 520                                _REG(VD2_IF0_LUMA_X1));
 521                writel_relaxed(priv->viu.vd1_if0_luma_y0,
 522                                priv->io_base + meson_crtc->viu_offset +
 523                                _REG(VD1_IF0_LUMA_Y0));
 524                writel_relaxed(priv->viu.vd1_if0_luma_y0,
 525                                priv->io_base + meson_crtc->viu_offset +
 526                                _REG(VD1_IF0_LUMA_Y1));
 527                writel_relaxed(priv->viu.vd1_if0_luma_y0,
 528                                priv->io_base + meson_crtc->viu_offset +
 529                                _REG(VD2_IF0_LUMA_Y0));
 530                writel_relaxed(priv->viu.vd1_if0_luma_y0,
 531                                priv->io_base + meson_crtc->viu_offset +
 532                                _REG(VD2_IF0_LUMA_Y1));
 533                writel_relaxed(priv->viu.vd1_if0_chroma_x0,
 534                                priv->io_base + meson_crtc->viu_offset +
 535                                _REG(VD1_IF0_CHROMA_X0));
 536                writel_relaxed(priv->viu.vd1_if0_chroma_x0,
 537                                priv->io_base + meson_crtc->viu_offset +
 538                                _REG(VD1_IF0_CHROMA_X1));
 539                writel_relaxed(priv->viu.vd1_if0_chroma_x0,
 540                                priv->io_base + meson_crtc->viu_offset +
 541                                _REG(VD2_IF0_CHROMA_X0));
 542                writel_relaxed(priv->viu.vd1_if0_chroma_x0,
 543                                priv->io_base + meson_crtc->viu_offset +
 544                                _REG(VD2_IF0_CHROMA_X1));
 545                writel_relaxed(priv->viu.vd1_if0_chroma_y0,
 546                                priv->io_base + meson_crtc->viu_offset +
 547                                _REG(VD1_IF0_CHROMA_Y0));
 548                writel_relaxed(priv->viu.vd1_if0_chroma_y0,
 549                                priv->io_base + meson_crtc->viu_offset +
 550                                _REG(VD1_IF0_CHROMA_Y1));
 551                writel_relaxed(priv->viu.vd1_if0_chroma_y0,
 552                                priv->io_base + meson_crtc->viu_offset +
 553                                _REG(VD2_IF0_CHROMA_Y0));
 554                writel_relaxed(priv->viu.vd1_if0_chroma_y0,
 555                                priv->io_base + meson_crtc->viu_offset +
 556                                _REG(VD2_IF0_CHROMA_Y1));
 557                writel_relaxed(priv->viu.vd1_if0_repeat_loop,
 558                                priv->io_base + meson_crtc->viu_offset +
 559                                _REG(VD1_IF0_RPT_LOOP));
 560                writel_relaxed(priv->viu.vd1_if0_repeat_loop,
 561                                priv->io_base + meson_crtc->viu_offset +
 562                                _REG(VD2_IF0_RPT_LOOP));
 563                writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
 564                                priv->io_base + meson_crtc->viu_offset +
 565                                _REG(VD1_IF0_LUMA0_RPT_PAT));
 566                writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
 567                                priv->io_base + meson_crtc->viu_offset +
 568                                _REG(VD2_IF0_LUMA0_RPT_PAT));
 569                writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
 570                                priv->io_base + meson_crtc->viu_offset +
 571                                _REG(VD1_IF0_LUMA1_RPT_PAT));
 572                writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
 573                                priv->io_base + meson_crtc->viu_offset +
 574                                _REG(VD2_IF0_LUMA1_RPT_PAT));
 575                writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
 576                                priv->io_base + meson_crtc->viu_offset +
 577                                _REG(VD1_IF0_CHROMA0_RPT_PAT));
 578                writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
 579                                priv->io_base + meson_crtc->viu_offset +
 580                                _REG(VD2_IF0_CHROMA0_RPT_PAT));
 581                writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
 582                                priv->io_base + meson_crtc->viu_offset +
 583                                _REG(VD1_IF0_CHROMA1_RPT_PAT));
 584                writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
 585                                priv->io_base + meson_crtc->viu_offset +
 586                                _REG(VD2_IF0_CHROMA1_RPT_PAT));
 587                writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
 588                                _REG(VD1_IF0_LUMA_PSEL));
 589                writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
 590                                _REG(VD1_IF0_CHROMA_PSEL));
 591                writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
 592                                _REG(VD2_IF0_LUMA_PSEL));
 593                writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
 594                                _REG(VD2_IF0_CHROMA_PSEL));
 595                writel_relaxed(priv->viu.vd1_range_map_y,
 596                                priv->io_base + meson_crtc->viu_offset +
 597                                _REG(VD1_IF0_RANGE_MAP_Y));
 598                writel_relaxed(priv->viu.vd1_range_map_cb,
 599                                priv->io_base + meson_crtc->viu_offset +
 600                                _REG(VD1_IF0_RANGE_MAP_CB));
 601                writel_relaxed(priv->viu.vd1_range_map_cr,
 602                                priv->io_base + meson_crtc->viu_offset +
 603                                _REG(VD1_IF0_RANGE_MAP_CR));
 604                writel_relaxed(VPP_VSC_BANK_LENGTH(4) |
 605                               VPP_HSC_BANK_LENGTH(4) |
 606                               VPP_SC_VD_EN_ENABLE |
 607                               VPP_SC_TOP_EN_ENABLE |
 608                               VPP_SC_HSC_EN_ENABLE |
 609                               VPP_SC_VSC_EN_ENABLE,
 610                                priv->io_base + _REG(VPP_SC_MISC));
 611                writel_relaxed(priv->viu.vpp_pic_in_height,
 612                                priv->io_base + _REG(VPP_PIC_IN_HEIGHT));
 613                writel_relaxed(priv->viu.vpp_postblend_vd1_h_start_end,
 614                        priv->io_base + _REG(VPP_POSTBLEND_VD1_H_START_END));
 615                writel_relaxed(priv->viu.vpp_blend_vd2_h_start_end,
 616                        priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
 617                writel_relaxed(priv->viu.vpp_postblend_vd1_v_start_end,
 618                        priv->io_base + _REG(VPP_POSTBLEND_VD1_V_START_END));
 619                writel_relaxed(priv->viu.vpp_blend_vd2_v_start_end,
 620                        priv->io_base + _REG(VPP_BLEND_VD2_V_START_END));
 621                writel_relaxed(priv->viu.vpp_hsc_region12_startp,
 622                                priv->io_base + _REG(VPP_HSC_REGION12_STARTP));
 623                writel_relaxed(priv->viu.vpp_hsc_region34_startp,
 624                                priv->io_base + _REG(VPP_HSC_REGION34_STARTP));
 625                writel_relaxed(priv->viu.vpp_hsc_region4_endp,
 626                                priv->io_base + _REG(VPP_HSC_REGION4_ENDP));
 627                writel_relaxed(priv->viu.vpp_hsc_start_phase_step,
 628                                priv->io_base + _REG(VPP_HSC_START_PHASE_STEP));
 629                writel_relaxed(priv->viu.vpp_hsc_region1_phase_slope,
 630                        priv->io_base + _REG(VPP_HSC_REGION1_PHASE_SLOPE));
 631                writel_relaxed(priv->viu.vpp_hsc_region3_phase_slope,
 632                        priv->io_base + _REG(VPP_HSC_REGION3_PHASE_SLOPE));
 633                writel_relaxed(priv->viu.vpp_line_in_length,
 634                                priv->io_base + _REG(VPP_LINE_IN_LENGTH));
 635                writel_relaxed(priv->viu.vpp_preblend_h_size,
 636                                priv->io_base + _REG(VPP_PREBLEND_H_SIZE));
 637                writel_relaxed(priv->viu.vpp_vsc_region12_startp,
 638                                priv->io_base + _REG(VPP_VSC_REGION12_STARTP));
 639                writel_relaxed(priv->viu.vpp_vsc_region34_startp,
 640                                priv->io_base + _REG(VPP_VSC_REGION34_STARTP));
 641                writel_relaxed(priv->viu.vpp_vsc_region4_endp,
 642                                priv->io_base + _REG(VPP_VSC_REGION4_ENDP));
 643                writel_relaxed(priv->viu.vpp_vsc_start_phase_step,
 644                                priv->io_base + _REG(VPP_VSC_START_PHASE_STEP));
 645                writel_relaxed(priv->viu.vpp_vsc_ini_phase,
 646                                priv->io_base + _REG(VPP_VSC_INI_PHASE));
 647                writel_relaxed(priv->viu.vpp_vsc_phase_ctrl,
 648                                priv->io_base + _REG(VPP_VSC_PHASE_CTRL));
 649                writel_relaxed(priv->viu.vpp_hsc_phase_ctrl,
 650                                priv->io_base + _REG(VPP_HSC_PHASE_CTRL));
 651                writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX));
 652
 653                /* Enable VD1 */
 654                if (meson_crtc->enable_vd1)
 655                        meson_crtc->enable_vd1(priv);
 656
 657                priv->viu.vd1_commit = false;
 658        }
 659
 660        if (meson_crtc->vsync_disabled)
 661                return;
 662
 663        drm_crtc_handle_vblank(priv->crtc);
 664
 665        spin_lock_irqsave(&priv->drm->event_lock, flags);
 666        if (meson_crtc->event) {
 667                drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event);
 668                drm_crtc_vblank_put(priv->crtc);
 669                meson_crtc->event = NULL;
 670        }
 671        spin_unlock_irqrestore(&priv->drm->event_lock, flags);
 672}
 673
 674int meson_crtc_create(struct meson_drm *priv)
 675{
 676        struct meson_crtc *meson_crtc;
 677        struct drm_crtc *crtc;
 678        int ret;
 679
 680        meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
 681                                  GFP_KERNEL);
 682        if (!meson_crtc)
 683                return -ENOMEM;
 684
 685        meson_crtc->priv = priv;
 686        crtc = &meson_crtc->base;
 687        ret = drm_crtc_init_with_planes(priv->drm, crtc,
 688                                        priv->primary_plane, NULL,
 689                                        &meson_crtc_funcs, "meson_crtc");
 690        if (ret) {
 691                dev_err(priv->drm->dev, "Failed to init CRTC\n");
 692                return ret;
 693        }
 694
 695        if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
 696                meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
 697                meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
 698                meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
 699                meson_crtc->enable_osd1_afbc =
 700                                        meson_crtc_g12a_enable_osd1_afbc;
 701                meson_crtc->disable_osd1_afbc =
 702                                        meson_viu_g12a_disable_osd1_afbc;
 703                drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
 704        } else {
 705                meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
 706                meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
 707                if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
 708                        meson_crtc->enable_osd1_afbc =
 709                                        meson_viu_gxm_enable_osd1_afbc;
 710                        meson_crtc->disable_osd1_afbc =
 711                                        meson_viu_gxm_disable_osd1_afbc;
 712                }
 713                drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
 714        }
 715
 716        priv->crtc = crtc;
 717
 718        return 0;
 719}
 720