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