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/kernel.h>
  13#include <linux/module.h>
  14#include <linux/mutex.h>
  15#include <linux/platform_device.h>
  16#include <linux/bitfield.h>
  17#include <drm/drmP.h>
  18#include <drm/drm_atomic.h>
  19#include <drm/drm_atomic_helper.h>
  20#include <drm/drm_flip_work.h>
  21#include <drm/drm_probe_helper.h>
  22
  23#include "meson_crtc.h"
  24#include "meson_plane.h"
  25#include "meson_venc.h"
  26#include "meson_vpp.h"
  27#include "meson_viu.h"
  28#include "meson_registers.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        unsigned int viu_offset;
  41};
  42#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
  43
  44/* CRTC */
  45
  46static int meson_crtc_enable_vblank(struct drm_crtc *crtc)
  47{
  48        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
  49        struct meson_drm *priv = meson_crtc->priv;
  50
  51        meson_venc_enable_vsync(priv);
  52
  53        return 0;
  54}
  55
  56static void meson_crtc_disable_vblank(struct drm_crtc *crtc)
  57{
  58        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
  59        struct meson_drm *priv = meson_crtc->priv;
  60
  61        meson_venc_disable_vsync(priv);
  62}
  63
  64static const struct drm_crtc_funcs meson_crtc_funcs = {
  65        .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
  66        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
  67        .destroy                = drm_crtc_cleanup,
  68        .page_flip              = drm_atomic_helper_page_flip,
  69        .reset                  = drm_atomic_helper_crtc_reset,
  70        .set_config             = drm_atomic_helper_set_config,
  71        .enable_vblank          = meson_crtc_enable_vblank,
  72        .disable_vblank         = meson_crtc_disable_vblank,
  73
  74};
  75
  76static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
  77                                          struct drm_crtc_state *old_state)
  78{
  79        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
  80        struct drm_crtc_state *crtc_state = crtc->state;
  81        struct meson_drm *priv = meson_crtc->priv;
  82
  83        DRM_DEBUG_DRIVER("\n");
  84
  85        if (!crtc_state) {
  86                DRM_ERROR("Invalid crtc_state\n");
  87                return;
  88        }
  89
  90        /* VD1 Preblend vertical start/end */
  91        writel(FIELD_PREP(GENMASK(11, 0), 2303),
  92               priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
  93
  94        /* Setup Blender */
  95        writel(crtc_state->mode.hdisplay |
  96               crtc_state->mode.vdisplay << 16,
  97               priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
  98
  99        writel_relaxed(0 << 16 |
 100                        (crtc_state->mode.hdisplay - 1),
 101                        priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE));
 102        writel_relaxed(0 << 16 |
 103                        (crtc_state->mode.vdisplay - 1),
 104                        priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
 105        writel_relaxed(crtc_state->mode.hdisplay << 16 |
 106                        crtc_state->mode.vdisplay,
 107                        priv->io_base + _REG(VPP_OUT_H_V_SIZE));
 108
 109        drm_crtc_vblank_on(crtc);
 110}
 111
 112static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
 113                                     struct drm_crtc_state *old_state)
 114{
 115        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 116        struct drm_crtc_state *crtc_state = crtc->state;
 117        struct meson_drm *priv = meson_crtc->priv;
 118
 119        DRM_DEBUG_DRIVER("\n");
 120
 121        if (!crtc_state) {
 122                DRM_ERROR("Invalid crtc_state\n");
 123                return;
 124        }
 125
 126        /* Enable VPP Postblend */
 127        writel(crtc_state->mode.hdisplay,
 128               priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
 129
 130        /* VD1 Preblend vertical start/end */
 131        writel(FIELD_PREP(GENMASK(11, 0), 2303),
 132                        priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
 133
 134        writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
 135                            priv->io_base + _REG(VPP_MISC));
 136
 137        drm_crtc_vblank_on(crtc);
 138}
 139
 140static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
 141                                           struct drm_crtc_state *old_state)
 142{
 143        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 144        struct meson_drm *priv = meson_crtc->priv;
 145
 146        DRM_DEBUG_DRIVER("\n");
 147
 148        drm_crtc_vblank_off(crtc);
 149
 150        priv->viu.osd1_enabled = false;
 151        priv->viu.osd1_commit = false;
 152
 153        priv->viu.vd1_enabled = false;
 154        priv->viu.vd1_commit = false;
 155
 156        if (crtc->state->event && !crtc->state->active) {
 157                spin_lock_irq(&crtc->dev->event_lock);
 158                drm_crtc_send_vblank_event(crtc, crtc->state->event);
 159                spin_unlock_irq(&crtc->dev->event_lock);
 160
 161                crtc->state->event = NULL;
 162        }
 163}
 164
 165static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
 166                                      struct drm_crtc_state *old_state)
 167{
 168        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 169        struct meson_drm *priv = meson_crtc->priv;
 170
 171        DRM_DEBUG_DRIVER("\n");
 172
 173        drm_crtc_vblank_off(crtc);
 174
 175        priv->viu.osd1_enabled = false;
 176        priv->viu.osd1_commit = false;
 177
 178        priv->viu.vd1_enabled = false;
 179        priv->viu.vd1_commit = false;
 180
 181        /* Disable VPP Postblend */
 182        writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_VD1_POSTBLEND |
 183                            VPP_VD1_PREBLEND | VPP_POSTBLEND_ENABLE, 0,
 184                            priv->io_base + _REG(VPP_MISC));
 185
 186        if (crtc->state->event && !crtc->state->active) {
 187                spin_lock_irq(&crtc->dev->event_lock);
 188                drm_crtc_send_vblank_event(crtc, crtc->state->event);
 189                spin_unlock_irq(&crtc->dev->event_lock);
 190
 191                crtc->state->event = NULL;
 192        }
 193}
 194
 195static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
 196                                    struct drm_crtc_state *state)
 197{
 198        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 199        unsigned long flags;
 200
 201        if (crtc->state->event) {
 202                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 203
 204                spin_lock_irqsave(&crtc->dev->event_lock, flags);
 205                meson_crtc->event = crtc->state->event;
 206                spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 207                crtc->state->event = NULL;
 208        }
 209}
 210
 211static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
 212                                    struct drm_crtc_state *old_crtc_state)
 213{
 214        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
 215        struct meson_drm *priv = meson_crtc->priv;
 216
 217        priv->viu.osd1_commit = true;
 218        priv->viu.vd1_commit = true;
 219}
 220
 221static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
 222        .atomic_begin   = meson_crtc_atomic_begin,
 223        .atomic_flush   = meson_crtc_atomic_flush,
 224        .atomic_enable  = meson_crtc_atomic_enable,
 225        .atomic_disable = meson_crtc_atomic_disable,
 226};
 227
 228static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = {
 229        .atomic_begin   = meson_crtc_atomic_begin,
 230        .atomic_flush   = meson_crtc_atomic_flush,
 231        .atomic_enable  = meson_g12a_crtc_atomic_enable,
 232        .atomic_disable = meson_g12a_crtc_atomic_disable,
 233};
 234
 235static void meson_crtc_enable_osd1(struct meson_drm *priv)
 236{
 237        writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
 238                            priv->io_base + _REG(VPP_MISC));
 239}
 240
 241static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
 242{
 243        writel_relaxed(priv->viu.osd_blend_din0_scope_h,
 244                       priv->io_base +
 245                       _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
 246        writel_relaxed(priv->viu.osd_blend_din0_scope_v,
 247                       priv->io_base +
 248                       _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
 249        writel_relaxed(priv->viu.osb_blend0_size,
 250                       priv->io_base +
 251                       _REG(VIU_OSD_BLEND_BLEND0_SIZE));
 252        writel_relaxed(priv->viu.osb_blend1_size,
 253                       priv->io_base +
 254                       _REG(VIU_OSD_BLEND_BLEND1_SIZE));
 255        writel_bits_relaxed(3 << 8, 3 << 8,
 256                            priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
 257}
 258
 259static void meson_crtc_enable_vd1(struct meson_drm *priv)
 260{
 261        writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
 262                            VPP_COLOR_MNG_ENABLE,
 263                            VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
 264                            VPP_COLOR_MNG_ENABLE,
 265                            priv->io_base + _REG(VPP_MISC));
 266}
 267
 268static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
 269{
 270        writel_relaxed(((1 << 16) | /* post bld premult*/
 271                        (1 << 8) | /* post src */
 272                        (1 << 4) | /* pre bld premult*/
 273                        (1 << 0)),
 274                        priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
 275}
 276
 277void meson_crtc_irq(struct meson_drm *priv)
 278{
 279        struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
 280        unsigned long flags;
 281
 282        /* Update the OSD registers */
 283        if (priv->viu.osd1_enabled && priv->viu.osd1_commit) {
 284                writel_relaxed(priv->viu.osd1_ctrl_stat,
 285                                priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
 286                writel_relaxed(priv->viu.osd1_blk0_cfg[0],
 287                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
 288                writel_relaxed(priv->viu.osd1_blk0_cfg[1],
 289                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1));
 290                writel_relaxed(priv->viu.osd1_blk0_cfg[2],
 291                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2));
 292                writel_relaxed(priv->viu.osd1_blk0_cfg[3],
 293                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
 294                writel_relaxed(priv->viu.osd1_blk0_cfg[4],
 295                                priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
 296                writel_relaxed(priv->viu.osd_sc_ctrl0,
 297                                priv->io_base + _REG(VPP_OSD_SC_CTRL0));
 298                writel_relaxed(priv->viu.osd_sc_i_wh_m1,
 299                                priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
 300                writel_relaxed(priv->viu.osd_sc_o_h_start_end,
 301                                priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
 302                writel_relaxed(priv->viu.osd_sc_o_v_start_end,
 303                                priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
 304                writel_relaxed(priv->viu.osd_sc_v_ini_phase,
 305                                priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
 306                writel_relaxed(priv->viu.osd_sc_v_phase_step,
 307                                priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
 308                writel_relaxed(priv->viu.osd_sc_h_ini_phase,
 309                                priv->io_base + _REG(VPP_OSD_HSC_INI_PHASE));
 310                writel_relaxed(priv->viu.osd_sc_h_phase_step,
 311                                priv->io_base + _REG(VPP_OSD_HSC_PHASE_STEP));
 312                writel_relaxed(priv->viu.osd_sc_h_ctrl0,
 313                                priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
 314                writel_relaxed(priv->viu.osd_sc_v_ctrl0,
 315                                priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
 316
 317                meson_canvas_config(priv->canvas, priv->canvas_id_osd1,
 318                                priv->viu.osd1_addr, priv->viu.osd1_stride,
 319                                priv->viu.osd1_height, MESON_CANVAS_WRAP_NONE,
 320                                MESON_CANVAS_BLKMODE_LINEAR, 0);
 321
 322                /* Enable OSD1 */
 323                if (meson_crtc->enable_osd1)
 324                        meson_crtc->enable_osd1(priv);
 325
 326                priv->viu.osd1_commit = false;
 327        }
 328
 329        /* Update the VD1 registers */
 330        if (priv->viu.vd1_enabled && priv->viu.vd1_commit) {
 331
 332                switch (priv->viu.vd1_planes) {
 333                case 3:
 334                        meson_canvas_config(priv->canvas,
 335                                            priv->canvas_id_vd1_2,
 336                                            priv->viu.vd1_addr2,
 337                                            priv->viu.vd1_stride2,
 338                                            priv->viu.vd1_height2,
 339                                            MESON_CANVAS_WRAP_NONE,
 340                                            MESON_CANVAS_BLKMODE_LINEAR,
 341                                            MESON_CANVAS_ENDIAN_SWAP64);
 342                /* fallthrough */
 343                case 2:
 344                        meson_canvas_config(priv->canvas,
 345                                            priv->canvas_id_vd1_1,
 346                                            priv->viu.vd1_addr1,
 347                                            priv->viu.vd1_stride1,
 348                                            priv->viu.vd1_height1,
 349                                            MESON_CANVAS_WRAP_NONE,
 350                                            MESON_CANVAS_BLKMODE_LINEAR,
 351                                            MESON_CANVAS_ENDIAN_SWAP64);
 352                /* fallthrough */
 353                case 1:
 354                        meson_canvas_config(priv->canvas,
 355                                            priv->canvas_id_vd1_0,
 356                                            priv->viu.vd1_addr0,
 357                                            priv->viu.vd1_stride0,
 358                                            priv->viu.vd1_height0,
 359                                            MESON_CANVAS_WRAP_NONE,
 360                                            MESON_CANVAS_BLKMODE_LINEAR,
 361                                            MESON_CANVAS_ENDIAN_SWAP64);
 362                };
 363
 364                writel_relaxed(priv->viu.vd1_if0_gen_reg,
 365                                priv->io_base + meson_crtc->viu_offset +
 366                                _REG(VD1_IF0_GEN_REG));
 367                writel_relaxed(priv->viu.vd1_if0_gen_reg,
 368                                priv->io_base + meson_crtc->viu_offset +
 369                                _REG(VD2_IF0_GEN_REG));
 370                writel_relaxed(priv->viu.vd1_if0_gen_reg2,
 371                                priv->io_base + meson_crtc->viu_offset +
 372                                _REG(VD1_IF0_GEN_REG2));
 373                writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
 374                                priv->io_base + meson_crtc->viu_offset +
 375                                _REG(VIU_VD1_FMT_CTRL));
 376                writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
 377                                priv->io_base + meson_crtc->viu_offset +
 378                                _REG(VIU_VD2_FMT_CTRL));
 379                writel_relaxed(priv->viu.viu_vd1_fmt_w,
 380                                priv->io_base + meson_crtc->viu_offset +
 381                                _REG(VIU_VD1_FMT_W));
 382                writel_relaxed(priv->viu.viu_vd1_fmt_w,
 383                                priv->io_base + meson_crtc->viu_offset +
 384                                _REG(VIU_VD2_FMT_W));
 385                writel_relaxed(priv->viu.vd1_if0_canvas0,
 386                                priv->io_base + meson_crtc->viu_offset +
 387                                _REG(VD1_IF0_CANVAS0));
 388                writel_relaxed(priv->viu.vd1_if0_canvas0,
 389                                priv->io_base + meson_crtc->viu_offset +
 390                                _REG(VD1_IF0_CANVAS1));
 391                writel_relaxed(priv->viu.vd1_if0_canvas0,
 392                                priv->io_base + meson_crtc->viu_offset +
 393                                _REG(VD2_IF0_CANVAS0));
 394                writel_relaxed(priv->viu.vd1_if0_canvas0,
 395                                priv->io_base + meson_crtc->viu_offset +
 396                                _REG(VD2_IF0_CANVAS1));
 397                writel_relaxed(priv->viu.vd1_if0_luma_x0,
 398                                priv->io_base + meson_crtc->viu_offset +
 399                                _REG(VD1_IF0_LUMA_X0));
 400                writel_relaxed(priv->viu.vd1_if0_luma_x0,
 401                                priv->io_base + meson_crtc->viu_offset +
 402                                _REG(VD1_IF0_LUMA_X1));
 403                writel_relaxed(priv->viu.vd1_if0_luma_x0,
 404                                priv->io_base + meson_crtc->viu_offset +
 405                                _REG(VD2_IF0_LUMA_X0));
 406                writel_relaxed(priv->viu.vd1_if0_luma_x0,
 407                                priv->io_base + meson_crtc->viu_offset +
 408                                _REG(VD2_IF0_LUMA_X1));
 409                writel_relaxed(priv->viu.vd1_if0_luma_y0,
 410                                priv->io_base + meson_crtc->viu_offset +
 411                                _REG(VD1_IF0_LUMA_Y0));
 412                writel_relaxed(priv->viu.vd1_if0_luma_y0,
 413                                priv->io_base + meson_crtc->viu_offset +
 414                                _REG(VD1_IF0_LUMA_Y1));
 415                writel_relaxed(priv->viu.vd1_if0_luma_y0,
 416                                priv->io_base + meson_crtc->viu_offset +
 417                                _REG(VD2_IF0_LUMA_Y0));
 418                writel_relaxed(priv->viu.vd1_if0_luma_y0,
 419                                priv->io_base + meson_crtc->viu_offset +
 420                                _REG(VD2_IF0_LUMA_Y1));
 421                writel_relaxed(priv->viu.vd1_if0_chroma_x0,
 422                                priv->io_base + meson_crtc->viu_offset +
 423                                _REG(VD1_IF0_CHROMA_X0));
 424                writel_relaxed(priv->viu.vd1_if0_chroma_x0,
 425                                priv->io_base + meson_crtc->viu_offset +
 426                                _REG(VD1_IF0_CHROMA_X1));
 427                writel_relaxed(priv->viu.vd1_if0_chroma_x0,
 428                                priv->io_base + meson_crtc->viu_offset +
 429                                _REG(VD2_IF0_CHROMA_X0));
 430                writel_relaxed(priv->viu.vd1_if0_chroma_x0,
 431                                priv->io_base + meson_crtc->viu_offset +
 432                                _REG(VD2_IF0_CHROMA_X1));
 433                writel_relaxed(priv->viu.vd1_if0_chroma_y0,
 434                                priv->io_base + meson_crtc->viu_offset +
 435                                _REG(VD1_IF0_CHROMA_Y0));
 436                writel_relaxed(priv->viu.vd1_if0_chroma_y0,
 437                                priv->io_base + meson_crtc->viu_offset +
 438                                _REG(VD1_IF0_CHROMA_Y1));
 439                writel_relaxed(priv->viu.vd1_if0_chroma_y0,
 440                                priv->io_base + meson_crtc->viu_offset +
 441                                _REG(VD2_IF0_CHROMA_Y0));
 442                writel_relaxed(priv->viu.vd1_if0_chroma_y0,
 443                                priv->io_base + meson_crtc->viu_offset +
 444                                _REG(VD2_IF0_CHROMA_Y1));
 445                writel_relaxed(priv->viu.vd1_if0_repeat_loop,
 446                                priv->io_base + meson_crtc->viu_offset +
 447                                _REG(VD1_IF0_RPT_LOOP));
 448                writel_relaxed(priv->viu.vd1_if0_repeat_loop,
 449                                priv->io_base + meson_crtc->viu_offset +
 450                                _REG(VD2_IF0_RPT_LOOP));
 451                writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
 452                                priv->io_base + meson_crtc->viu_offset +
 453                                _REG(VD1_IF0_LUMA0_RPT_PAT));
 454                writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
 455                                priv->io_base + meson_crtc->viu_offset +
 456                                _REG(VD2_IF0_LUMA0_RPT_PAT));
 457                writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
 458                                priv->io_base + meson_crtc->viu_offset +
 459                                _REG(VD1_IF0_LUMA1_RPT_PAT));
 460                writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
 461                                priv->io_base + meson_crtc->viu_offset +
 462                                _REG(VD2_IF0_LUMA1_RPT_PAT));
 463                writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
 464                                priv->io_base + meson_crtc->viu_offset +
 465                                _REG(VD1_IF0_CHROMA0_RPT_PAT));
 466                writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
 467                                priv->io_base + meson_crtc->viu_offset +
 468                                _REG(VD2_IF0_CHROMA0_RPT_PAT));
 469                writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
 470                                priv->io_base + meson_crtc->viu_offset +
 471                                _REG(VD1_IF0_CHROMA1_RPT_PAT));
 472                writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
 473                                priv->io_base + meson_crtc->viu_offset +
 474                                _REG(VD2_IF0_CHROMA1_RPT_PAT));
 475                writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
 476                                _REG(VD1_IF0_LUMA_PSEL));
 477                writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
 478                                _REG(VD1_IF0_CHROMA_PSEL));
 479                writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
 480                                _REG(VD2_IF0_LUMA_PSEL));
 481                writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
 482                                _REG(VD2_IF0_CHROMA_PSEL));
 483                writel_relaxed(priv->viu.vd1_range_map_y,
 484                                priv->io_base + meson_crtc->viu_offset +
 485                                _REG(VD1_IF0_RANGE_MAP_Y));
 486                writel_relaxed(priv->viu.vd1_range_map_cb,
 487                                priv->io_base + meson_crtc->viu_offset +
 488                                _REG(VD1_IF0_RANGE_MAP_CB));
 489                writel_relaxed(priv->viu.vd1_range_map_cr,
 490                                priv->io_base + meson_crtc->viu_offset +
 491                                _REG(VD1_IF0_RANGE_MAP_CR));
 492                writel_relaxed(0x78404,
 493                                priv->io_base + _REG(VPP_SC_MISC));
 494                writel_relaxed(priv->viu.vpp_pic_in_height,
 495                                priv->io_base + _REG(VPP_PIC_IN_HEIGHT));
 496                writel_relaxed(priv->viu.vpp_postblend_vd1_h_start_end,
 497                        priv->io_base + _REG(VPP_POSTBLEND_VD1_H_START_END));
 498                writel_relaxed(priv->viu.vpp_blend_vd2_h_start_end,
 499                        priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
 500                writel_relaxed(priv->viu.vpp_postblend_vd1_v_start_end,
 501                        priv->io_base + _REG(VPP_POSTBLEND_VD1_V_START_END));
 502                writel_relaxed(priv->viu.vpp_blend_vd2_v_start_end,
 503                        priv->io_base + _REG(VPP_BLEND_VD2_V_START_END));
 504                writel_relaxed(priv->viu.vpp_hsc_region12_startp,
 505                                priv->io_base + _REG(VPP_HSC_REGION12_STARTP));
 506                writel_relaxed(priv->viu.vpp_hsc_region34_startp,
 507                                priv->io_base + _REG(VPP_HSC_REGION34_STARTP));
 508                writel_relaxed(priv->viu.vpp_hsc_region4_endp,
 509                                priv->io_base + _REG(VPP_HSC_REGION4_ENDP));
 510                writel_relaxed(priv->viu.vpp_hsc_start_phase_step,
 511                                priv->io_base + _REG(VPP_HSC_START_PHASE_STEP));
 512                writel_relaxed(priv->viu.vpp_hsc_region1_phase_slope,
 513                        priv->io_base + _REG(VPP_HSC_REGION1_PHASE_SLOPE));
 514                writel_relaxed(priv->viu.vpp_hsc_region3_phase_slope,
 515                        priv->io_base + _REG(VPP_HSC_REGION3_PHASE_SLOPE));
 516                writel_relaxed(priv->viu.vpp_line_in_length,
 517                                priv->io_base + _REG(VPP_LINE_IN_LENGTH));
 518                writel_relaxed(priv->viu.vpp_preblend_h_size,
 519                                priv->io_base + _REG(VPP_PREBLEND_H_SIZE));
 520                writel_relaxed(priv->viu.vpp_vsc_region12_startp,
 521                                priv->io_base + _REG(VPP_VSC_REGION12_STARTP));
 522                writel_relaxed(priv->viu.vpp_vsc_region34_startp,
 523                                priv->io_base + _REG(VPP_VSC_REGION34_STARTP));
 524                writel_relaxed(priv->viu.vpp_vsc_region4_endp,
 525                                priv->io_base + _REG(VPP_VSC_REGION4_ENDP));
 526                writel_relaxed(priv->viu.vpp_vsc_start_phase_step,
 527                                priv->io_base + _REG(VPP_VSC_START_PHASE_STEP));
 528                writel_relaxed(priv->viu.vpp_vsc_ini_phase,
 529                                priv->io_base + _REG(VPP_VSC_INI_PHASE));
 530                writel_relaxed(priv->viu.vpp_vsc_phase_ctrl,
 531                                priv->io_base + _REG(VPP_VSC_PHASE_CTRL));
 532                writel_relaxed(priv->viu.vpp_hsc_phase_ctrl,
 533                                priv->io_base + _REG(VPP_HSC_PHASE_CTRL));
 534                writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX));
 535
 536                /* Enable VD1 */
 537                if (meson_crtc->enable_vd1)
 538                        meson_crtc->enable_vd1(priv);
 539
 540                priv->viu.vd1_commit = false;
 541        }
 542
 543        drm_crtc_handle_vblank(priv->crtc);
 544
 545        spin_lock_irqsave(&priv->drm->event_lock, flags);
 546        if (meson_crtc->event) {
 547                drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event);
 548                drm_crtc_vblank_put(priv->crtc);
 549                meson_crtc->event = NULL;
 550        }
 551        spin_unlock_irqrestore(&priv->drm->event_lock, flags);
 552}
 553
 554int meson_crtc_create(struct meson_drm *priv)
 555{
 556        struct meson_crtc *meson_crtc;
 557        struct drm_crtc *crtc;
 558        int ret;
 559
 560        meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
 561                                  GFP_KERNEL);
 562        if (!meson_crtc)
 563                return -ENOMEM;
 564
 565        meson_crtc->priv = priv;
 566        crtc = &meson_crtc->base;
 567        ret = drm_crtc_init_with_planes(priv->drm, crtc,
 568                                        priv->primary_plane, NULL,
 569                                        &meson_crtc_funcs, "meson_crtc");
 570        if (ret) {
 571                dev_err(priv->drm->dev, "Failed to init CRTC\n");
 572                return ret;
 573        }
 574
 575        if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
 576                meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
 577                meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
 578                meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
 579                drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
 580        } else {
 581                meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
 582                meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
 583                drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
 584        }
 585
 586        priv->crtc = crtc;
 587
 588        return 0;
 589}
 590