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