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 34 struct 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 50 static 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 61 static 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 72 static 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 84 static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc, 85 struct drm_crtc_state *old_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 120 static void meson_crtc_atomic_enable(struct drm_crtc *crtc, 121 struct drm_crtc_state *old_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 148 static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc, 149 struct drm_crtc_state *old_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 173 static void meson_crtc_atomic_disable(struct drm_crtc *crtc, 174 struct drm_crtc_state *old_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 203 static void meson_crtc_atomic_begin(struct drm_crtc *crtc, 204 struct drm_crtc_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 219 static void meson_crtc_atomic_flush(struct drm_crtc *crtc, 220 struct drm_crtc_state *old_crtc_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 229 static 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 236 static 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 243 static 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 249 static 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 269 static 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 287 static 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 300 static 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 313 void 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 674 int 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