Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2016 BayLibre, SAS
0004  * Author: Neil Armstrong <narmstrong@baylibre.com>
0005  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
0006  * Copyright (C) 2014 Endless Mobile
0007  *
0008  * Written by:
0009  *     Jasper St. Pierre <jstpierre@mecheye.net>
0010  */
0011 
0012 #include <linux/bitfield.h>
0013 #include <linux/soc/amlogic/meson-canvas.h>
0014 
0015 #include <drm/drm_atomic_helper.h>
0016 #include <drm/drm_device.h>
0017 #include <drm/drm_print.h>
0018 #include <drm/drm_probe_helper.h>
0019 #include <drm/drm_vblank.h>
0020 
0021 #include "meson_crtc.h"
0022 #include "meson_plane.h"
0023 #include "meson_registers.h"
0024 #include "meson_venc.h"
0025 #include "meson_viu.h"
0026 #include "meson_rdma.h"
0027 #include "meson_vpp.h"
0028 #include "meson_osd_afbcd.h"
0029 
0030 #define MESON_G12A_VIU_OFFSET   0x5ec0
0031 
0032 /* CRTC definition */
0033 
0034 struct meson_crtc {
0035     struct drm_crtc base;
0036     struct drm_pending_vblank_event *event;
0037     struct meson_drm *priv;
0038     void (*enable_osd1)(struct meson_drm *priv);
0039     void (*enable_vd1)(struct meson_drm *priv);
0040     void (*enable_osd1_afbc)(struct meson_drm *priv);
0041     void (*disable_osd1_afbc)(struct meson_drm *priv);
0042     unsigned int viu_offset;
0043     bool vsync_forced;
0044     bool vsync_disabled;
0045 };
0046 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
0047 
0048 /* CRTC */
0049 
0050 static int meson_crtc_enable_vblank(struct drm_crtc *crtc)
0051 {
0052     struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
0053     struct meson_drm *priv = meson_crtc->priv;
0054 
0055     meson_crtc->vsync_disabled = false;
0056     meson_venc_enable_vsync(priv);
0057 
0058     return 0;
0059 }
0060 
0061 static void meson_crtc_disable_vblank(struct drm_crtc *crtc)
0062 {
0063     struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
0064     struct meson_drm *priv = meson_crtc->priv;
0065 
0066     if (!meson_crtc->vsync_forced) {
0067         meson_crtc->vsync_disabled = true;
0068         meson_venc_disable_vsync(priv);
0069     }
0070 }
0071 
0072 static const struct drm_crtc_funcs meson_crtc_funcs = {
0073     .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
0074     .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
0075     .destroy        = drm_crtc_cleanup,
0076     .page_flip      = drm_atomic_helper_page_flip,
0077     .reset          = drm_atomic_helper_crtc_reset,
0078     .set_config             = drm_atomic_helper_set_config,
0079     .enable_vblank      = meson_crtc_enable_vblank,
0080     .disable_vblank     = meson_crtc_disable_vblank,
0081 
0082 };
0083 
0084 static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
0085                       struct drm_atomic_state *state)
0086 {
0087     struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
0088     struct drm_crtc_state *crtc_state = crtc->state;
0089     struct meson_drm *priv = meson_crtc->priv;
0090 
0091     DRM_DEBUG_DRIVER("\n");
0092 
0093     if (!crtc_state) {
0094         DRM_ERROR("Invalid crtc_state\n");
0095         return;
0096     }
0097 
0098     /* VD1 Preblend vertical start/end */
0099     writel(FIELD_PREP(GENMASK(11, 0), 2303),
0100            priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
0101 
0102     /* Setup Blender */
0103     writel(crtc_state->mode.hdisplay |
0104            crtc_state->mode.vdisplay << 16,
0105            priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
0106 
0107     writel_relaxed(0 << 16 |
0108             (crtc_state->mode.hdisplay - 1),
0109             priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE));
0110     writel_relaxed(0 << 16 |
0111             (crtc_state->mode.vdisplay - 1),
0112             priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
0113     writel_relaxed(crtc_state->mode.hdisplay << 16 |
0114             crtc_state->mode.vdisplay,
0115             priv->io_base + _REG(VPP_OUT_H_V_SIZE));
0116 
0117     drm_crtc_vblank_on(crtc);
0118 }
0119 
0120 static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
0121                      struct drm_atomic_state *state)
0122 {
0123     struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
0124     struct drm_crtc_state *crtc_state = crtc->state;
0125     struct meson_drm *priv = meson_crtc->priv;
0126 
0127     DRM_DEBUG_DRIVER("\n");
0128 
0129     if (!crtc_state) {
0130         DRM_ERROR("Invalid crtc_state\n");
0131         return;
0132     }
0133 
0134     /* Enable VPP Postblend */
0135     writel(crtc_state->mode.hdisplay,
0136            priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
0137 
0138     /* VD1 Preblend vertical start/end */
0139     writel(FIELD_PREP(GENMASK(11, 0), 2303),
0140             priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
0141 
0142     writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
0143                 priv->io_base + _REG(VPP_MISC));
0144 
0145     drm_crtc_vblank_on(crtc);
0146 }
0147 
0148 static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
0149                        struct drm_atomic_state *state)
0150 {
0151     struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
0152     struct meson_drm *priv = meson_crtc->priv;
0153 
0154     DRM_DEBUG_DRIVER("\n");
0155 
0156     drm_crtc_vblank_off(crtc);
0157 
0158     priv->viu.osd1_enabled = false;
0159     priv->viu.osd1_commit = false;
0160 
0161     priv->viu.vd1_enabled = false;
0162     priv->viu.vd1_commit = false;
0163 
0164     if (crtc->state->event && !crtc->state->active) {
0165         spin_lock_irq(&crtc->dev->event_lock);
0166         drm_crtc_send_vblank_event(crtc, crtc->state->event);
0167         spin_unlock_irq(&crtc->dev->event_lock);
0168 
0169         crtc->state->event = NULL;
0170     }
0171 }
0172 
0173 static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
0174                       struct drm_atomic_state *state)
0175 {
0176     struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
0177     struct meson_drm *priv = meson_crtc->priv;
0178 
0179     DRM_DEBUG_DRIVER("\n");
0180 
0181     drm_crtc_vblank_off(crtc);
0182 
0183     priv->viu.osd1_enabled = false;
0184     priv->viu.osd1_commit = false;
0185 
0186     priv->viu.vd1_enabled = false;
0187     priv->viu.vd1_commit = false;
0188 
0189     /* Disable VPP Postblend */
0190     writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_VD1_POSTBLEND |
0191                 VPP_VD1_PREBLEND | VPP_POSTBLEND_ENABLE, 0,
0192                 priv->io_base + _REG(VPP_MISC));
0193 
0194     if (crtc->state->event && !crtc->state->active) {
0195         spin_lock_irq(&crtc->dev->event_lock);
0196         drm_crtc_send_vblank_event(crtc, crtc->state->event);
0197         spin_unlock_irq(&crtc->dev->event_lock);
0198 
0199         crtc->state->event = NULL;
0200     }
0201 }
0202 
0203 static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
0204                     struct drm_atomic_state *state)
0205 {
0206     struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
0207     unsigned long flags;
0208 
0209     if (crtc->state->event) {
0210         WARN_ON(drm_crtc_vblank_get(crtc) != 0);
0211 
0212         spin_lock_irqsave(&crtc->dev->event_lock, flags);
0213         meson_crtc->event = crtc->state->event;
0214         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
0215         crtc->state->event = NULL;
0216     }
0217 }
0218 
0219 static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
0220                     struct drm_atomic_state *state)
0221 {
0222     struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
0223     struct meson_drm *priv = meson_crtc->priv;
0224 
0225     priv->viu.osd1_commit = true;
0226     priv->viu.vd1_commit = true;
0227 }
0228 
0229 static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
0230     .atomic_begin   = meson_crtc_atomic_begin,
0231     .atomic_flush   = meson_crtc_atomic_flush,
0232     .atomic_enable  = meson_crtc_atomic_enable,
0233     .atomic_disable = meson_crtc_atomic_disable,
0234 };
0235 
0236 static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = {
0237     .atomic_begin   = meson_crtc_atomic_begin,
0238     .atomic_flush   = meson_crtc_atomic_flush,
0239     .atomic_enable  = meson_g12a_crtc_atomic_enable,
0240     .atomic_disable = meson_g12a_crtc_atomic_disable,
0241 };
0242 
0243 static void meson_crtc_enable_osd1(struct meson_drm *priv)
0244 {
0245     writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
0246                 priv->io_base + _REG(VPP_MISC));
0247 }
0248 
0249 static void meson_crtc_g12a_enable_osd1_afbc(struct meson_drm *priv)
0250 {
0251     writel_relaxed(priv->viu.osd1_blk2_cfg4,
0252                priv->io_base + _REG(VIU_OSD1_BLK2_CFG_W4));
0253 
0254     writel_bits_relaxed(OSD_MEM_LINEAR_ADDR, OSD_MEM_LINEAR_ADDR,
0255                 priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
0256 
0257     writel_relaxed(priv->viu.osd1_blk1_cfg4,
0258                priv->io_base + _REG(VIU_OSD1_BLK1_CFG_W4));
0259 
0260     meson_viu_g12a_enable_osd1_afbc(priv);
0261 
0262     writel_bits_relaxed(OSD_MEM_LINEAR_ADDR, OSD_MEM_LINEAR_ADDR,
0263                 priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
0264 
0265     writel_bits_relaxed(OSD_MALI_SRC_EN, OSD_MALI_SRC_EN,
0266                 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
0267 }
0268 
0269 static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
0270 {
0271     writel_relaxed(priv->viu.osd_blend_din0_scope_h,
0272                priv->io_base +
0273                _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
0274     writel_relaxed(priv->viu.osd_blend_din0_scope_v,
0275                priv->io_base +
0276                _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
0277     writel_relaxed(priv->viu.osb_blend0_size,
0278                priv->io_base +
0279                _REG(VIU_OSD_BLEND_BLEND0_SIZE));
0280     writel_relaxed(priv->viu.osb_blend1_size,
0281                priv->io_base +
0282                _REG(VIU_OSD_BLEND_BLEND1_SIZE));
0283     writel_bits_relaxed(3 << 8, 3 << 8,
0284                 priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
0285 }
0286 
0287 static void meson_crtc_enable_vd1(struct meson_drm *priv)
0288 {
0289     writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
0290                 VPP_COLOR_MNG_ENABLE,
0291                 VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
0292                 VPP_COLOR_MNG_ENABLE,
0293                 priv->io_base + _REG(VPP_MISC));
0294 
0295     writel_bits_relaxed(VIU_CTRL0_AFBC_TO_VD1,
0296                 priv->viu.vd1_afbc ? VIU_CTRL0_AFBC_TO_VD1 : 0,
0297                 priv->io_base + _REG(VIU_MISC_CTRL0));
0298 }
0299 
0300 static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
0301 {
0302     writel_relaxed(VD_BLEND_PREBLD_SRC_VD1 |
0303                VD_BLEND_PREBLD_PREMULT_EN |
0304                VD_BLEND_POSTBLD_SRC_VD1 |
0305                VD_BLEND_POSTBLD_PREMULT_EN,
0306                priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
0307 
0308     writel_relaxed(priv->viu.vd1_afbc ?
0309                (VD1_AXI_SEL_AFBC | AFBC_VD1_SEL) : 0,
0310                priv->io_base + _REG(VD1_AFBCD0_MISC_CTRL));
0311 }
0312 
0313 void meson_crtc_irq(struct meson_drm *priv)
0314 {
0315     struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
0316     unsigned long flags;
0317 
0318     /* Update the OSD registers */
0319     if (priv->viu.osd1_enabled && priv->viu.osd1_commit) {
0320         writel_relaxed(priv->viu.osd1_ctrl_stat,
0321                 priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
0322         writel_relaxed(priv->viu.osd1_ctrl_stat2,
0323                 priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
0324         writel_relaxed(priv->viu.osd1_blk0_cfg[0],
0325                 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
0326         writel_relaxed(priv->viu.osd1_blk0_cfg[1],
0327                 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1));
0328         writel_relaxed(priv->viu.osd1_blk0_cfg[2],
0329                 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2));
0330         writel_relaxed(priv->viu.osd1_blk0_cfg[3],
0331                 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
0332         writel_relaxed(priv->viu.osd1_blk0_cfg[4],
0333                 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
0334 
0335         if (priv->viu.osd1_afbcd) {
0336             if (meson_crtc->enable_osd1_afbc)
0337                 meson_crtc->enable_osd1_afbc(priv);
0338         } else {
0339             if (meson_crtc->disable_osd1_afbc)
0340                 meson_crtc->disable_osd1_afbc(priv);
0341             if (priv->afbcd.ops) {
0342                 priv->afbcd.ops->reset(priv);
0343                 priv->afbcd.ops->disable(priv);
0344             }
0345             meson_crtc->vsync_forced = false;
0346         }
0347 
0348         writel_relaxed(priv->viu.osd_sc_ctrl0,
0349                 priv->io_base + _REG(VPP_OSD_SC_CTRL0));
0350         writel_relaxed(priv->viu.osd_sc_i_wh_m1,
0351                 priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
0352         writel_relaxed(priv->viu.osd_sc_o_h_start_end,
0353                 priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
0354         writel_relaxed(priv->viu.osd_sc_o_v_start_end,
0355                 priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
0356         writel_relaxed(priv->viu.osd_sc_v_ini_phase,
0357                 priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
0358         writel_relaxed(priv->viu.osd_sc_v_phase_step,
0359                 priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
0360         writel_relaxed(priv->viu.osd_sc_h_ini_phase,
0361                 priv->io_base + _REG(VPP_OSD_HSC_INI_PHASE));
0362         writel_relaxed(priv->viu.osd_sc_h_phase_step,
0363                 priv->io_base + _REG(VPP_OSD_HSC_PHASE_STEP));
0364         writel_relaxed(priv->viu.osd_sc_h_ctrl0,
0365                 priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
0366         writel_relaxed(priv->viu.osd_sc_v_ctrl0,
0367                 priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
0368 
0369         if (!priv->viu.osd1_afbcd)
0370             meson_canvas_config(priv->canvas, priv->canvas_id_osd1,
0371                         priv->viu.osd1_addr,
0372                         priv->viu.osd1_stride,
0373                         priv->viu.osd1_height,
0374                         MESON_CANVAS_WRAP_NONE,
0375                         MESON_CANVAS_BLKMODE_LINEAR, 0);
0376 
0377         /* Enable OSD1 */
0378         if (meson_crtc->enable_osd1)
0379             meson_crtc->enable_osd1(priv);
0380 
0381         if (priv->viu.osd1_afbcd) {
0382             priv->afbcd.ops->reset(priv);
0383             priv->afbcd.ops->setup(priv);
0384             priv->afbcd.ops->enable(priv);
0385             meson_crtc->vsync_forced = true;
0386         }
0387 
0388         priv->viu.osd1_commit = false;
0389     }
0390 
0391     /* Update the VD1 registers */
0392     if (priv->viu.vd1_enabled && priv->viu.vd1_commit) {
0393 
0394         if (priv->viu.vd1_afbc) {
0395             writel_relaxed(priv->viu.vd1_afbc_head_addr,
0396                        priv->io_base +
0397                        _REG(AFBC_HEAD_BADDR));
0398             writel_relaxed(priv->viu.vd1_afbc_body_addr,
0399                        priv->io_base +
0400                        _REG(AFBC_BODY_BADDR));
0401             writel_relaxed(priv->viu.vd1_afbc_en,
0402                        priv->io_base +
0403                        _REG(AFBC_ENABLE));
0404             writel_relaxed(priv->viu.vd1_afbc_mode,
0405                        priv->io_base +
0406                        _REG(AFBC_MODE));
0407             writel_relaxed(priv->viu.vd1_afbc_size_in,
0408                        priv->io_base +
0409                        _REG(AFBC_SIZE_IN));
0410             writel_relaxed(priv->viu.vd1_afbc_dec_def_color,
0411                        priv->io_base +
0412                        _REG(AFBC_DEC_DEF_COLOR));
0413             writel_relaxed(priv->viu.vd1_afbc_conv_ctrl,
0414                        priv->io_base +
0415                        _REG(AFBC_CONV_CTRL));
0416             writel_relaxed(priv->viu.vd1_afbc_size_out,
0417                        priv->io_base +
0418                        _REG(AFBC_SIZE_OUT));
0419             writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_ctrl,
0420                        priv->io_base +
0421                        _REG(AFBC_VD_CFMT_CTRL));
0422             writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_w,
0423                        priv->io_base +
0424                        _REG(AFBC_VD_CFMT_W));
0425             writel_relaxed(priv->viu.vd1_afbc_mif_hor_scope,
0426                        priv->io_base +
0427                        _REG(AFBC_MIF_HOR_SCOPE));
0428             writel_relaxed(priv->viu.vd1_afbc_mif_ver_scope,
0429                        priv->io_base +
0430                        _REG(AFBC_MIF_VER_SCOPE));
0431             writel_relaxed(priv->viu.vd1_afbc_pixel_hor_scope,
0432                        priv->io_base+
0433                        _REG(AFBC_PIXEL_HOR_SCOPE));
0434             writel_relaxed(priv->viu.vd1_afbc_pixel_ver_scope,
0435                        priv->io_base +
0436                        _REG(AFBC_PIXEL_VER_SCOPE));
0437             writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_h,
0438                        priv->io_base +
0439                        _REG(AFBC_VD_CFMT_H));
0440         } else {
0441             switch (priv->viu.vd1_planes) {
0442             case 3:
0443                 meson_canvas_config(priv->canvas,
0444                             priv->canvas_id_vd1_2,
0445                             priv->viu.vd1_addr2,
0446                             priv->viu.vd1_stride2,
0447                             priv->viu.vd1_height2,
0448                             MESON_CANVAS_WRAP_NONE,
0449                             MESON_CANVAS_BLKMODE_LINEAR,
0450                             MESON_CANVAS_ENDIAN_SWAP64);
0451                 fallthrough;
0452             case 2:
0453                 meson_canvas_config(priv->canvas,
0454                             priv->canvas_id_vd1_1,
0455                             priv->viu.vd1_addr1,
0456                             priv->viu.vd1_stride1,
0457                             priv->viu.vd1_height1,
0458                             MESON_CANVAS_WRAP_NONE,
0459                             MESON_CANVAS_BLKMODE_LINEAR,
0460                             MESON_CANVAS_ENDIAN_SWAP64);
0461                 fallthrough;
0462             case 1:
0463                 meson_canvas_config(priv->canvas,
0464                             priv->canvas_id_vd1_0,
0465                             priv->viu.vd1_addr0,
0466                             priv->viu.vd1_stride0,
0467                             priv->viu.vd1_height0,
0468                             MESON_CANVAS_WRAP_NONE,
0469                             MESON_CANVAS_BLKMODE_LINEAR,
0470                             MESON_CANVAS_ENDIAN_SWAP64);
0471             }
0472 
0473             writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
0474         }
0475 
0476         writel_relaxed(priv->viu.vd1_if0_gen_reg,
0477                 priv->io_base + meson_crtc->viu_offset +
0478                 _REG(VD1_IF0_GEN_REG));
0479         writel_relaxed(priv->viu.vd1_if0_gen_reg,
0480                 priv->io_base + meson_crtc->viu_offset +
0481                 _REG(VD2_IF0_GEN_REG));
0482         writel_relaxed(priv->viu.vd1_if0_gen_reg2,
0483                 priv->io_base + meson_crtc->viu_offset +
0484                 _REG(VD1_IF0_GEN_REG2));
0485         writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
0486                 priv->io_base + meson_crtc->viu_offset +
0487                 _REG(VIU_VD1_FMT_CTRL));
0488         writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
0489                 priv->io_base + meson_crtc->viu_offset +
0490                 _REG(VIU_VD2_FMT_CTRL));
0491         writel_relaxed(priv->viu.viu_vd1_fmt_w,
0492                 priv->io_base + meson_crtc->viu_offset +
0493                 _REG(VIU_VD1_FMT_W));
0494         writel_relaxed(priv->viu.viu_vd1_fmt_w,
0495                 priv->io_base + meson_crtc->viu_offset +
0496                 _REG(VIU_VD2_FMT_W));
0497         writel_relaxed(priv->viu.vd1_if0_canvas0,
0498                 priv->io_base + meson_crtc->viu_offset +
0499                 _REG(VD1_IF0_CANVAS0));
0500         writel_relaxed(priv->viu.vd1_if0_canvas0,
0501                 priv->io_base + meson_crtc->viu_offset +
0502                 _REG(VD1_IF0_CANVAS1));
0503         writel_relaxed(priv->viu.vd1_if0_canvas0,
0504                 priv->io_base + meson_crtc->viu_offset +
0505                 _REG(VD2_IF0_CANVAS0));
0506         writel_relaxed(priv->viu.vd1_if0_canvas0,
0507                 priv->io_base + meson_crtc->viu_offset +
0508                 _REG(VD2_IF0_CANVAS1));
0509         writel_relaxed(priv->viu.vd1_if0_luma_x0,
0510                 priv->io_base + meson_crtc->viu_offset +
0511                 _REG(VD1_IF0_LUMA_X0));
0512         writel_relaxed(priv->viu.vd1_if0_luma_x0,
0513                 priv->io_base + meson_crtc->viu_offset +
0514                 _REG(VD1_IF0_LUMA_X1));
0515         writel_relaxed(priv->viu.vd1_if0_luma_x0,
0516                 priv->io_base + meson_crtc->viu_offset +
0517                 _REG(VD2_IF0_LUMA_X0));
0518         writel_relaxed(priv->viu.vd1_if0_luma_x0,
0519                 priv->io_base + meson_crtc->viu_offset +
0520                 _REG(VD2_IF0_LUMA_X1));
0521         writel_relaxed(priv->viu.vd1_if0_luma_y0,
0522                 priv->io_base + meson_crtc->viu_offset +
0523                 _REG(VD1_IF0_LUMA_Y0));
0524         writel_relaxed(priv->viu.vd1_if0_luma_y0,
0525                 priv->io_base + meson_crtc->viu_offset +
0526                 _REG(VD1_IF0_LUMA_Y1));
0527         writel_relaxed(priv->viu.vd1_if0_luma_y0,
0528                 priv->io_base + meson_crtc->viu_offset +
0529                 _REG(VD2_IF0_LUMA_Y0));
0530         writel_relaxed(priv->viu.vd1_if0_luma_y0,
0531                 priv->io_base + meson_crtc->viu_offset +
0532                 _REG(VD2_IF0_LUMA_Y1));
0533         writel_relaxed(priv->viu.vd1_if0_chroma_x0,
0534                 priv->io_base + meson_crtc->viu_offset +
0535                 _REG(VD1_IF0_CHROMA_X0));
0536         writel_relaxed(priv->viu.vd1_if0_chroma_x0,
0537                 priv->io_base + meson_crtc->viu_offset +
0538                 _REG(VD1_IF0_CHROMA_X1));
0539         writel_relaxed(priv->viu.vd1_if0_chroma_x0,
0540                 priv->io_base + meson_crtc->viu_offset +
0541                 _REG(VD2_IF0_CHROMA_X0));
0542         writel_relaxed(priv->viu.vd1_if0_chroma_x0,
0543                 priv->io_base + meson_crtc->viu_offset +
0544                 _REG(VD2_IF0_CHROMA_X1));
0545         writel_relaxed(priv->viu.vd1_if0_chroma_y0,
0546                 priv->io_base + meson_crtc->viu_offset +
0547                 _REG(VD1_IF0_CHROMA_Y0));
0548         writel_relaxed(priv->viu.vd1_if0_chroma_y0,
0549                 priv->io_base + meson_crtc->viu_offset +
0550                 _REG(VD1_IF0_CHROMA_Y1));
0551         writel_relaxed(priv->viu.vd1_if0_chroma_y0,
0552                 priv->io_base + meson_crtc->viu_offset +
0553                 _REG(VD2_IF0_CHROMA_Y0));
0554         writel_relaxed(priv->viu.vd1_if0_chroma_y0,
0555                 priv->io_base + meson_crtc->viu_offset +
0556                 _REG(VD2_IF0_CHROMA_Y1));
0557         writel_relaxed(priv->viu.vd1_if0_repeat_loop,
0558                 priv->io_base + meson_crtc->viu_offset +
0559                 _REG(VD1_IF0_RPT_LOOP));
0560         writel_relaxed(priv->viu.vd1_if0_repeat_loop,
0561                 priv->io_base + meson_crtc->viu_offset +
0562                 _REG(VD2_IF0_RPT_LOOP));
0563         writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
0564                 priv->io_base + meson_crtc->viu_offset +
0565                 _REG(VD1_IF0_LUMA0_RPT_PAT));
0566         writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
0567                 priv->io_base + meson_crtc->viu_offset +
0568                 _REG(VD2_IF0_LUMA0_RPT_PAT));
0569         writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
0570                 priv->io_base + meson_crtc->viu_offset +
0571                 _REG(VD1_IF0_LUMA1_RPT_PAT));
0572         writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
0573                 priv->io_base + meson_crtc->viu_offset +
0574                 _REG(VD2_IF0_LUMA1_RPT_PAT));
0575         writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
0576                 priv->io_base + meson_crtc->viu_offset +
0577                 _REG(VD1_IF0_CHROMA0_RPT_PAT));
0578         writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
0579                 priv->io_base + meson_crtc->viu_offset +
0580                 _REG(VD2_IF0_CHROMA0_RPT_PAT));
0581         writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
0582                 priv->io_base + meson_crtc->viu_offset +
0583                 _REG(VD1_IF0_CHROMA1_RPT_PAT));
0584         writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
0585                 priv->io_base + meson_crtc->viu_offset +
0586                 _REG(VD2_IF0_CHROMA1_RPT_PAT));
0587         writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
0588                 _REG(VD1_IF0_LUMA_PSEL));
0589         writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
0590                 _REG(VD1_IF0_CHROMA_PSEL));
0591         writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
0592                 _REG(VD2_IF0_LUMA_PSEL));
0593         writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
0594                 _REG(VD2_IF0_CHROMA_PSEL));
0595         writel_relaxed(priv->viu.vd1_range_map_y,
0596                 priv->io_base + meson_crtc->viu_offset +
0597                 _REG(VD1_IF0_RANGE_MAP_Y));
0598         writel_relaxed(priv->viu.vd1_range_map_cb,
0599                 priv->io_base + meson_crtc->viu_offset +
0600                 _REG(VD1_IF0_RANGE_MAP_CB));
0601         writel_relaxed(priv->viu.vd1_range_map_cr,
0602                 priv->io_base + meson_crtc->viu_offset +
0603                 _REG(VD1_IF0_RANGE_MAP_CR));
0604         writel_relaxed(VPP_VSC_BANK_LENGTH(4) |
0605                    VPP_HSC_BANK_LENGTH(4) |
0606                    VPP_SC_VD_EN_ENABLE |
0607                    VPP_SC_TOP_EN_ENABLE |
0608                    VPP_SC_HSC_EN_ENABLE |
0609                    VPP_SC_VSC_EN_ENABLE,
0610                 priv->io_base + _REG(VPP_SC_MISC));
0611         writel_relaxed(priv->viu.vpp_pic_in_height,
0612                 priv->io_base + _REG(VPP_PIC_IN_HEIGHT));
0613         writel_relaxed(priv->viu.vpp_postblend_vd1_h_start_end,
0614             priv->io_base + _REG(VPP_POSTBLEND_VD1_H_START_END));
0615         writel_relaxed(priv->viu.vpp_blend_vd2_h_start_end,
0616             priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
0617         writel_relaxed(priv->viu.vpp_postblend_vd1_v_start_end,
0618             priv->io_base + _REG(VPP_POSTBLEND_VD1_V_START_END));
0619         writel_relaxed(priv->viu.vpp_blend_vd2_v_start_end,
0620             priv->io_base + _REG(VPP_BLEND_VD2_V_START_END));
0621         writel_relaxed(priv->viu.vpp_hsc_region12_startp,
0622                 priv->io_base + _REG(VPP_HSC_REGION12_STARTP));
0623         writel_relaxed(priv->viu.vpp_hsc_region34_startp,
0624                 priv->io_base + _REG(VPP_HSC_REGION34_STARTP));
0625         writel_relaxed(priv->viu.vpp_hsc_region4_endp,
0626                 priv->io_base + _REG(VPP_HSC_REGION4_ENDP));
0627         writel_relaxed(priv->viu.vpp_hsc_start_phase_step,
0628                 priv->io_base + _REG(VPP_HSC_START_PHASE_STEP));
0629         writel_relaxed(priv->viu.vpp_hsc_region1_phase_slope,
0630             priv->io_base + _REG(VPP_HSC_REGION1_PHASE_SLOPE));
0631         writel_relaxed(priv->viu.vpp_hsc_region3_phase_slope,
0632             priv->io_base + _REG(VPP_HSC_REGION3_PHASE_SLOPE));
0633         writel_relaxed(priv->viu.vpp_line_in_length,
0634                 priv->io_base + _REG(VPP_LINE_IN_LENGTH));
0635         writel_relaxed(priv->viu.vpp_preblend_h_size,
0636                 priv->io_base + _REG(VPP_PREBLEND_H_SIZE));
0637         writel_relaxed(priv->viu.vpp_vsc_region12_startp,
0638                 priv->io_base + _REG(VPP_VSC_REGION12_STARTP));
0639         writel_relaxed(priv->viu.vpp_vsc_region34_startp,
0640                 priv->io_base + _REG(VPP_VSC_REGION34_STARTP));
0641         writel_relaxed(priv->viu.vpp_vsc_region4_endp,
0642                 priv->io_base + _REG(VPP_VSC_REGION4_ENDP));
0643         writel_relaxed(priv->viu.vpp_vsc_start_phase_step,
0644                 priv->io_base + _REG(VPP_VSC_START_PHASE_STEP));
0645         writel_relaxed(priv->viu.vpp_vsc_ini_phase,
0646                 priv->io_base + _REG(VPP_VSC_INI_PHASE));
0647         writel_relaxed(priv->viu.vpp_vsc_phase_ctrl,
0648                 priv->io_base + _REG(VPP_VSC_PHASE_CTRL));
0649         writel_relaxed(priv->viu.vpp_hsc_phase_ctrl,
0650                 priv->io_base + _REG(VPP_HSC_PHASE_CTRL));
0651         writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX));
0652 
0653         /* Enable VD1 */
0654         if (meson_crtc->enable_vd1)
0655             meson_crtc->enable_vd1(priv);
0656 
0657         priv->viu.vd1_commit = false;
0658     }
0659 
0660     if (meson_crtc->vsync_disabled)
0661         return;
0662 
0663     drm_crtc_handle_vblank(priv->crtc);
0664 
0665     spin_lock_irqsave(&priv->drm->event_lock, flags);
0666     if (meson_crtc->event) {
0667         drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event);
0668         drm_crtc_vblank_put(priv->crtc);
0669         meson_crtc->event = NULL;
0670     }
0671     spin_unlock_irqrestore(&priv->drm->event_lock, flags);
0672 }
0673 
0674 int meson_crtc_create(struct meson_drm *priv)
0675 {
0676     struct meson_crtc *meson_crtc;
0677     struct drm_crtc *crtc;
0678     int ret;
0679 
0680     meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
0681                   GFP_KERNEL);
0682     if (!meson_crtc)
0683         return -ENOMEM;
0684 
0685     meson_crtc->priv = priv;
0686     crtc = &meson_crtc->base;
0687     ret = drm_crtc_init_with_planes(priv->drm, crtc,
0688                     priv->primary_plane, NULL,
0689                     &meson_crtc_funcs, "meson_crtc");
0690     if (ret) {
0691         dev_err(priv->drm->dev, "Failed to init CRTC\n");
0692         return ret;
0693     }
0694 
0695     if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
0696         meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
0697         meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
0698         meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
0699         meson_crtc->enable_osd1_afbc =
0700                     meson_crtc_g12a_enable_osd1_afbc;
0701         meson_crtc->disable_osd1_afbc =
0702                     meson_viu_g12a_disable_osd1_afbc;
0703         drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
0704     } else {
0705         meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
0706         meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
0707         if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
0708             meson_crtc->enable_osd1_afbc =
0709                     meson_viu_gxm_enable_osd1_afbc;
0710             meson_crtc->disable_osd1_afbc =
0711                     meson_viu_gxm_disable_osd1_afbc;
0712         }
0713         drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
0714     }
0715 
0716     priv->crtc = crtc;
0717 
0718     return 0;
0719 }