720 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2016 BayLibre, SAS4 * Author: Neil Armstrong <narmstrong@baylibre.com>5 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.6 * Copyright (C) 2014 Endless Mobile7 *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 0x5ec031 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