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