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 296 static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv) 297 { 298 writel_relaxed(VD_BLEND_PREBLD_SRC_VD1 | 299 VD_BLEND_PREBLD_PREMULT_EN | 300 VD_BLEND_POSTBLD_SRC_VD1 | 301 VD_BLEND_POSTBLD_PREMULT_EN, 302 priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); 303 } 304 305 void meson_crtc_irq(struct meson_drm *priv) 306 { 307 struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc); 308 unsigned long flags; 309 310 /* Update the OSD registers */ 311 if (priv->viu.osd1_enabled && priv->viu.osd1_commit) { 312 writel_relaxed(priv->viu.osd1_ctrl_stat, 313 priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); 314 writel_relaxed(priv->viu.osd1_ctrl_stat2, 315 priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); 316 writel_relaxed(priv->viu.osd1_blk0_cfg[0], 317 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0)); 318 writel_relaxed(priv->viu.osd1_blk0_cfg[1], 319 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1)); 320 writel_relaxed(priv->viu.osd1_blk0_cfg[2], 321 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2)); 322 writel_relaxed(priv->viu.osd1_blk0_cfg[3], 323 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3)); 324 writel_relaxed(priv->viu.osd1_blk0_cfg[4], 325 priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4)); 326 327 if (priv->viu.osd1_afbcd) { 328 if (meson_crtc->enable_osd1_afbc) 329 meson_crtc->enable_osd1_afbc(priv); 330 } else { 331 if (meson_crtc->disable_osd1_afbc) 332 meson_crtc->disable_osd1_afbc(priv); 333 if (priv->afbcd.ops) { 334 priv->afbcd.ops->reset(priv); 335 priv->afbcd.ops->disable(priv); 336 } 337 meson_crtc->vsync_forced = false; 338 } 339 340 writel_relaxed(priv->viu.osd_sc_ctrl0, 341 priv->io_base + _REG(VPP_OSD_SC_CTRL0)); 342 writel_relaxed(priv->viu.osd_sc_i_wh_m1, 343 priv->io_base + _REG(VPP_OSD_SCI_WH_M1)); 344 writel_relaxed(priv->viu.osd_sc_o_h_start_end, 345 priv->io_base + _REG(VPP_OSD_SCO_H_START_END)); 346 writel_relaxed(priv->viu.osd_sc_o_v_start_end, 347 priv->io_base + _REG(VPP_OSD_SCO_V_START_END)); 348 writel_relaxed(priv->viu.osd_sc_v_ini_phase, 349 priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE)); 350 writel_relaxed(priv->viu.osd_sc_v_phase_step, 351 priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP)); 352 writel_relaxed(priv->viu.osd_sc_h_ini_phase, 353 priv->io_base + _REG(VPP_OSD_HSC_INI_PHASE)); 354 writel_relaxed(priv->viu.osd_sc_h_phase_step, 355 priv->io_base + _REG(VPP_OSD_HSC_PHASE_STEP)); 356 writel_relaxed(priv->viu.osd_sc_h_ctrl0, 357 priv->io_base + _REG(VPP_OSD_HSC_CTRL0)); 358 writel_relaxed(priv->viu.osd_sc_v_ctrl0, 359 priv->io_base + _REG(VPP_OSD_VSC_CTRL0)); 360 361 if (!priv->viu.osd1_afbcd) 362 meson_canvas_config(priv->canvas, priv->canvas_id_osd1, 363 priv->viu.osd1_addr, 364 priv->viu.osd1_stride, 365 priv->viu.osd1_height, 366 MESON_CANVAS_WRAP_NONE, 367 MESON_CANVAS_BLKMODE_LINEAR, 0); 368 369 /* Enable OSD1 */ 370 if (meson_crtc->enable_osd1) 371 meson_crtc->enable_osd1(priv); 372 373 if (priv->viu.osd1_afbcd) { 374 priv->afbcd.ops->reset(priv); 375 priv->afbcd.ops->setup(priv); 376 priv->afbcd.ops->enable(priv); 377 meson_crtc->vsync_forced = true; 378 } 379 380 priv->viu.osd1_commit = false; 381 } 382 383 /* Update the VD1 registers */ 384 if (priv->viu.vd1_enabled && priv->viu.vd1_commit) { 385 386 switch (priv->viu.vd1_planes) { 387 case 3: 388 meson_canvas_config(priv->canvas, 389 priv->canvas_id_vd1_2, 390 priv->viu.vd1_addr2, 391 priv->viu.vd1_stride2, 392 priv->viu.vd1_height2, 393 MESON_CANVAS_WRAP_NONE, 394 MESON_CANVAS_BLKMODE_LINEAR, 395 MESON_CANVAS_ENDIAN_SWAP64); 396 /* fallthrough */ 397 case 2: 398 meson_canvas_config(priv->canvas, 399 priv->canvas_id_vd1_1, 400 priv->viu.vd1_addr1, 401 priv->viu.vd1_stride1, 402 priv->viu.vd1_height1, 403 MESON_CANVAS_WRAP_NONE, 404 MESON_CANVAS_BLKMODE_LINEAR, 405 MESON_CANVAS_ENDIAN_SWAP64); 406 /* fallthrough */ 407 case 1: 408 meson_canvas_config(priv->canvas, 409 priv->canvas_id_vd1_0, 410 priv->viu.vd1_addr0, 411 priv->viu.vd1_stride0, 412 priv->viu.vd1_height0, 413 MESON_CANVAS_WRAP_NONE, 414 MESON_CANVAS_BLKMODE_LINEAR, 415 MESON_CANVAS_ENDIAN_SWAP64); 416 } 417 418 writel_relaxed(priv->viu.vd1_if0_gen_reg, 419 priv->io_base + meson_crtc->viu_offset + 420 _REG(VD1_IF0_GEN_REG)); 421 writel_relaxed(priv->viu.vd1_if0_gen_reg, 422 priv->io_base + meson_crtc->viu_offset + 423 _REG(VD2_IF0_GEN_REG)); 424 writel_relaxed(priv->viu.vd1_if0_gen_reg2, 425 priv->io_base + meson_crtc->viu_offset + 426 _REG(VD1_IF0_GEN_REG2)); 427 writel_relaxed(priv->viu.viu_vd1_fmt_ctrl, 428 priv->io_base + meson_crtc->viu_offset + 429 _REG(VIU_VD1_FMT_CTRL)); 430 writel_relaxed(priv->viu.viu_vd1_fmt_ctrl, 431 priv->io_base + meson_crtc->viu_offset + 432 _REG(VIU_VD2_FMT_CTRL)); 433 writel_relaxed(priv->viu.viu_vd1_fmt_w, 434 priv->io_base + meson_crtc->viu_offset + 435 _REG(VIU_VD1_FMT_W)); 436 writel_relaxed(priv->viu.viu_vd1_fmt_w, 437 priv->io_base + meson_crtc->viu_offset + 438 _REG(VIU_VD2_FMT_W)); 439 writel_relaxed(priv->viu.vd1_if0_canvas0, 440 priv->io_base + meson_crtc->viu_offset + 441 _REG(VD1_IF0_CANVAS0)); 442 writel_relaxed(priv->viu.vd1_if0_canvas0, 443 priv->io_base + meson_crtc->viu_offset + 444 _REG(VD1_IF0_CANVAS1)); 445 writel_relaxed(priv->viu.vd1_if0_canvas0, 446 priv->io_base + meson_crtc->viu_offset + 447 _REG(VD2_IF0_CANVAS0)); 448 writel_relaxed(priv->viu.vd1_if0_canvas0, 449 priv->io_base + meson_crtc->viu_offset + 450 _REG(VD2_IF0_CANVAS1)); 451 writel_relaxed(priv->viu.vd1_if0_luma_x0, 452 priv->io_base + meson_crtc->viu_offset + 453 _REG(VD1_IF0_LUMA_X0)); 454 writel_relaxed(priv->viu.vd1_if0_luma_x0, 455 priv->io_base + meson_crtc->viu_offset + 456 _REG(VD1_IF0_LUMA_X1)); 457 writel_relaxed(priv->viu.vd1_if0_luma_x0, 458 priv->io_base + meson_crtc->viu_offset + 459 _REG(VD2_IF0_LUMA_X0)); 460 writel_relaxed(priv->viu.vd1_if0_luma_x0, 461 priv->io_base + meson_crtc->viu_offset + 462 _REG(VD2_IF0_LUMA_X1)); 463 writel_relaxed(priv->viu.vd1_if0_luma_y0, 464 priv->io_base + meson_crtc->viu_offset + 465 _REG(VD1_IF0_LUMA_Y0)); 466 writel_relaxed(priv->viu.vd1_if0_luma_y0, 467 priv->io_base + meson_crtc->viu_offset + 468 _REG(VD1_IF0_LUMA_Y1)); 469 writel_relaxed(priv->viu.vd1_if0_luma_y0, 470 priv->io_base + meson_crtc->viu_offset + 471 _REG(VD2_IF0_LUMA_Y0)); 472 writel_relaxed(priv->viu.vd1_if0_luma_y0, 473 priv->io_base + meson_crtc->viu_offset + 474 _REG(VD2_IF0_LUMA_Y1)); 475 writel_relaxed(priv->viu.vd1_if0_chroma_x0, 476 priv->io_base + meson_crtc->viu_offset + 477 _REG(VD1_IF0_CHROMA_X0)); 478 writel_relaxed(priv->viu.vd1_if0_chroma_x0, 479 priv->io_base + meson_crtc->viu_offset + 480 _REG(VD1_IF0_CHROMA_X1)); 481 writel_relaxed(priv->viu.vd1_if0_chroma_x0, 482 priv->io_base + meson_crtc->viu_offset + 483 _REG(VD2_IF0_CHROMA_X0)); 484 writel_relaxed(priv->viu.vd1_if0_chroma_x0, 485 priv->io_base + meson_crtc->viu_offset + 486 _REG(VD2_IF0_CHROMA_X1)); 487 writel_relaxed(priv->viu.vd1_if0_chroma_y0, 488 priv->io_base + meson_crtc->viu_offset + 489 _REG(VD1_IF0_CHROMA_Y0)); 490 writel_relaxed(priv->viu.vd1_if0_chroma_y0, 491 priv->io_base + meson_crtc->viu_offset + 492 _REG(VD1_IF0_CHROMA_Y1)); 493 writel_relaxed(priv->viu.vd1_if0_chroma_y0, 494 priv->io_base + meson_crtc->viu_offset + 495 _REG(VD2_IF0_CHROMA_Y0)); 496 writel_relaxed(priv->viu.vd1_if0_chroma_y0, 497 priv->io_base + meson_crtc->viu_offset + 498 _REG(VD2_IF0_CHROMA_Y1)); 499 writel_relaxed(priv->viu.vd1_if0_repeat_loop, 500 priv->io_base + meson_crtc->viu_offset + 501 _REG(VD1_IF0_RPT_LOOP)); 502 writel_relaxed(priv->viu.vd1_if0_repeat_loop, 503 priv->io_base + meson_crtc->viu_offset + 504 _REG(VD2_IF0_RPT_LOOP)); 505 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, 506 priv->io_base + meson_crtc->viu_offset + 507 _REG(VD1_IF0_LUMA0_RPT_PAT)); 508 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, 509 priv->io_base + meson_crtc->viu_offset + 510 _REG(VD2_IF0_LUMA0_RPT_PAT)); 511 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, 512 priv->io_base + meson_crtc->viu_offset + 513 _REG(VD1_IF0_LUMA1_RPT_PAT)); 514 writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat, 515 priv->io_base + meson_crtc->viu_offset + 516 _REG(VD2_IF0_LUMA1_RPT_PAT)); 517 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, 518 priv->io_base + meson_crtc->viu_offset + 519 _REG(VD1_IF0_CHROMA0_RPT_PAT)); 520 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, 521 priv->io_base + meson_crtc->viu_offset + 522 _REG(VD2_IF0_CHROMA0_RPT_PAT)); 523 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, 524 priv->io_base + meson_crtc->viu_offset + 525 _REG(VD1_IF0_CHROMA1_RPT_PAT)); 526 writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat, 527 priv->io_base + meson_crtc->viu_offset + 528 _REG(VD2_IF0_CHROMA1_RPT_PAT)); 529 writel_relaxed(0, priv->io_base + meson_crtc->viu_offset + 530 _REG(VD1_IF0_LUMA_PSEL)); 531 writel_relaxed(0, priv->io_base + meson_crtc->viu_offset + 532 _REG(VD1_IF0_CHROMA_PSEL)); 533 writel_relaxed(0, priv->io_base + meson_crtc->viu_offset + 534 _REG(VD2_IF0_LUMA_PSEL)); 535 writel_relaxed(0, priv->io_base + meson_crtc->viu_offset + 536 _REG(VD2_IF0_CHROMA_PSEL)); 537 writel_relaxed(priv->viu.vd1_range_map_y, 538 priv->io_base + meson_crtc->viu_offset + 539 _REG(VD1_IF0_RANGE_MAP_Y)); 540 writel_relaxed(priv->viu.vd1_range_map_cb, 541 priv->io_base + meson_crtc->viu_offset + 542 _REG(VD1_IF0_RANGE_MAP_CB)); 543 writel_relaxed(priv->viu.vd1_range_map_cr, 544 priv->io_base + meson_crtc->viu_offset + 545 _REG(VD1_IF0_RANGE_MAP_CR)); 546 writel_relaxed(VPP_VSC_BANK_LENGTH(4) | 547 VPP_HSC_BANK_LENGTH(4) | 548 VPP_SC_VD_EN_ENABLE | 549 VPP_SC_TOP_EN_ENABLE | 550 VPP_SC_HSC_EN_ENABLE | 551 VPP_SC_VSC_EN_ENABLE, 552 priv->io_base + _REG(VPP_SC_MISC)); 553 writel_relaxed(priv->viu.vpp_pic_in_height, 554 priv->io_base + _REG(VPP_PIC_IN_HEIGHT)); 555 writel_relaxed(priv->viu.vpp_postblend_vd1_h_start_end, 556 priv->io_base + _REG(VPP_POSTBLEND_VD1_H_START_END)); 557 writel_relaxed(priv->viu.vpp_blend_vd2_h_start_end, 558 priv->io_base + _REG(VPP_BLEND_VD2_H_START_END)); 559 writel_relaxed(priv->viu.vpp_postblend_vd1_v_start_end, 560 priv->io_base + _REG(VPP_POSTBLEND_VD1_V_START_END)); 561 writel_relaxed(priv->viu.vpp_blend_vd2_v_start_end, 562 priv->io_base + _REG(VPP_BLEND_VD2_V_START_END)); 563 writel_relaxed(priv->viu.vpp_hsc_region12_startp, 564 priv->io_base + _REG(VPP_HSC_REGION12_STARTP)); 565 writel_relaxed(priv->viu.vpp_hsc_region34_startp, 566 priv->io_base + _REG(VPP_HSC_REGION34_STARTP)); 567 writel_relaxed(priv->viu.vpp_hsc_region4_endp, 568 priv->io_base + _REG(VPP_HSC_REGION4_ENDP)); 569 writel_relaxed(priv->viu.vpp_hsc_start_phase_step, 570 priv->io_base + _REG(VPP_HSC_START_PHASE_STEP)); 571 writel_relaxed(priv->viu.vpp_hsc_region1_phase_slope, 572 priv->io_base + _REG(VPP_HSC_REGION1_PHASE_SLOPE)); 573 writel_relaxed(priv->viu.vpp_hsc_region3_phase_slope, 574 priv->io_base + _REG(VPP_HSC_REGION3_PHASE_SLOPE)); 575 writel_relaxed(priv->viu.vpp_line_in_length, 576 priv->io_base + _REG(VPP_LINE_IN_LENGTH)); 577 writel_relaxed(priv->viu.vpp_preblend_h_size, 578 priv->io_base + _REG(VPP_PREBLEND_H_SIZE)); 579 writel_relaxed(priv->viu.vpp_vsc_region12_startp, 580 priv->io_base + _REG(VPP_VSC_REGION12_STARTP)); 581 writel_relaxed(priv->viu.vpp_vsc_region34_startp, 582 priv->io_base + _REG(VPP_VSC_REGION34_STARTP)); 583 writel_relaxed(priv->viu.vpp_vsc_region4_endp, 584 priv->io_base + _REG(VPP_VSC_REGION4_ENDP)); 585 writel_relaxed(priv->viu.vpp_vsc_start_phase_step, 586 priv->io_base + _REG(VPP_VSC_START_PHASE_STEP)); 587 writel_relaxed(priv->viu.vpp_vsc_ini_phase, 588 priv->io_base + _REG(VPP_VSC_INI_PHASE)); 589 writel_relaxed(priv->viu.vpp_vsc_phase_ctrl, 590 priv->io_base + _REG(VPP_VSC_PHASE_CTRL)); 591 writel_relaxed(priv->viu.vpp_hsc_phase_ctrl, 592 priv->io_base + _REG(VPP_HSC_PHASE_CTRL)); 593 writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX)); 594 595 /* Enable VD1 */ 596 if (meson_crtc->enable_vd1) 597 meson_crtc->enable_vd1(priv); 598 599 priv->viu.vd1_commit = false; 600 } 601 602 if (meson_crtc->vsync_disabled) 603 return; 604 605 drm_crtc_handle_vblank(priv->crtc); 606 607 spin_lock_irqsave(&priv->drm->event_lock, flags); 608 if (meson_crtc->event) { 609 drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event); 610 drm_crtc_vblank_put(priv->crtc); 611 meson_crtc->event = NULL; 612 } 613 spin_unlock_irqrestore(&priv->drm->event_lock, flags); 614 } 615 616 int meson_crtc_create(struct meson_drm *priv) 617 { 618 struct meson_crtc *meson_crtc; 619 struct drm_crtc *crtc; 620 int ret; 621 622 meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc), 623 GFP_KERNEL); 624 if (!meson_crtc) 625 return -ENOMEM; 626 627 meson_crtc->priv = priv; 628 crtc = &meson_crtc->base; 629 ret = drm_crtc_init_with_planes(priv->drm, crtc, 630 priv->primary_plane, NULL, 631 &meson_crtc_funcs, "meson_crtc"); 632 if (ret) { 633 dev_err(priv->drm->dev, "Failed to init CRTC\n"); 634 return ret; 635 } 636 637 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { 638 meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1; 639 meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1; 640 meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET; 641 meson_crtc->enable_osd1_afbc = 642 meson_crtc_g12a_enable_osd1_afbc; 643 meson_crtc->disable_osd1_afbc = 644 meson_viu_g12a_disable_osd1_afbc; 645 drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs); 646 } else { 647 meson_crtc->enable_osd1 = meson_crtc_enable_osd1; 648 meson_crtc->enable_vd1 = meson_crtc_enable_vd1; 649 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) { 650 meson_crtc->enable_osd1_afbc = 651 meson_viu_gxm_enable_osd1_afbc; 652 meson_crtc->disable_osd1_afbc = 653 meson_viu_gxm_disable_osd1_afbc; 654 } 655 drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs); 656 } 657 658 priv->crtc = crtc; 659 660 return 0; 661 } 662