1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ 7 8 #include <linux/debugfs.h> 9 10 #include <drm/drm_framebuffer.h> 11 12 #include "dpu_encoder_phys.h" 13 #include "dpu_formats.h" 14 #include "dpu_hw_top.h" 15 #include "dpu_hw_wb.h" 16 #include "dpu_hw_lm.h" 17 #include "dpu_hw_merge3d.h" 18 #include "dpu_hw_interrupts.h" 19 #include "dpu_core_irq.h" 20 #include "dpu_vbif.h" 21 #include "dpu_crtc.h" 22 #include "disp/msm_disp_snapshot.h" 23 24 #define to_dpu_encoder_phys_wb(x) \ 25 container_of(x, struct dpu_encoder_phys_wb, base) 26 27 /** 28 * dpu_encoder_phys_wb_is_master - report wb always as master encoder 29 * @phys_enc: Pointer to physical encoder 30 */ 31 static bool dpu_encoder_phys_wb_is_master(struct dpu_encoder_phys *phys_enc) 32 { 33 /* there is only one physical enc for dpu_writeback */ 34 return true; 35 } 36 37 static bool _dpu_encoder_phys_wb_clk_force_ctrl(struct dpu_hw_wb *wb, 38 struct dpu_hw_mdp *mdp, 39 bool enable, bool *forced_on) 40 { 41 if (wb->ops.setup_clk_force_ctrl) { 42 *forced_on = wb->ops.setup_clk_force_ctrl(wb, enable); 43 return true; 44 } 45 46 if (mdp->ops.setup_clk_force_ctrl) { 47 *forced_on = mdp->ops.setup_clk_force_ctrl(mdp, wb->caps->clk_ctrl, enable); 48 return true; 49 } 50 51 return false; 52 } 53 54 /** 55 * dpu_encoder_phys_wb_set_ot_limit - set OT limit for writeback interface 56 * @phys_enc: Pointer to physical encoder 57 */ 58 static void dpu_encoder_phys_wb_set_ot_limit( 59 struct dpu_encoder_phys *phys_enc) 60 { 61 struct dpu_hw_wb *hw_wb = phys_enc->hw_wb; 62 struct dpu_vbif_set_ot_params ot_params; 63 bool forced_on = false; 64 65 memset(&ot_params, 0, sizeof(ot_params)); 66 ot_params.xin_id = hw_wb->caps->xin_id; 67 ot_params.num = hw_wb->idx - WB_0; 68 ot_params.width = phys_enc->cached_mode.hdisplay; 69 ot_params.height = phys_enc->cached_mode.vdisplay; 70 ot_params.is_wfd = true; 71 ot_params.frame_rate = drm_mode_vrefresh(&phys_enc->cached_mode); 72 ot_params.vbif_idx = hw_wb->caps->vbif_idx; 73 ot_params.rd = false; 74 75 if (!_dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp, 76 true, &forced_on)) 77 return; 78 79 dpu_vbif_set_ot_limit(phys_enc->dpu_kms, &ot_params); 80 81 if (forced_on) 82 _dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp, 83 false, &forced_on); 84 } 85 86 /** 87 * dpu_encoder_phys_wb_set_qos_remap - set QoS remapper for writeback 88 * @phys_enc: Pointer to physical encoder 89 */ 90 static void dpu_encoder_phys_wb_set_qos_remap( 91 struct dpu_encoder_phys *phys_enc) 92 { 93 struct dpu_hw_wb *hw_wb; 94 struct dpu_vbif_set_qos_params qos_params; 95 bool forced_on = false; 96 97 if (!phys_enc || !phys_enc->parent || !phys_enc->parent->crtc) { 98 DPU_ERROR("invalid arguments\n"); 99 return; 100 } 101 102 if (!phys_enc->hw_wb || !phys_enc->hw_wb->caps) { 103 DPU_ERROR("invalid writeback hardware\n"); 104 return; 105 } 106 107 hw_wb = phys_enc->hw_wb; 108 109 memset(&qos_params, 0, sizeof(qos_params)); 110 qos_params.vbif_idx = hw_wb->caps->vbif_idx; 111 qos_params.xin_id = hw_wb->caps->xin_id; 112 qos_params.num = hw_wb->idx - WB_0; 113 qos_params.is_rt = false; 114 115 DPU_DEBUG("[qos_remap] wb:%d vbif:%d xin:%d is_rt:%d\n", 116 qos_params.num, 117 qos_params.vbif_idx, 118 qos_params.xin_id, qos_params.is_rt); 119 120 if (!_dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp, 121 true, &forced_on)) 122 return; 123 124 dpu_vbif_set_qos_remap(phys_enc->dpu_kms, &qos_params); 125 126 if (forced_on) 127 _dpu_encoder_phys_wb_clk_force_ctrl(hw_wb, phys_enc->dpu_kms->hw_mdp, 128 false, &forced_on); 129 } 130 131 /** 132 * dpu_encoder_phys_wb_set_qos - set QoS/danger/safe LUTs for writeback 133 * @phys_enc: Pointer to physical encoder 134 */ 135 static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc) 136 { 137 struct dpu_hw_wb *hw_wb; 138 struct dpu_hw_qos_cfg qos_cfg; 139 const struct dpu_mdss_cfg *catalog; 140 const struct dpu_qos_lut_tbl *qos_lut_tb; 141 142 if (!phys_enc || !phys_enc->dpu_kms || !phys_enc->dpu_kms->catalog) { 143 DPU_ERROR("invalid parameter(s)\n"); 144 return; 145 } 146 147 catalog = phys_enc->dpu_kms->catalog; 148 149 hw_wb = phys_enc->hw_wb; 150 151 memset(&qos_cfg, 0, sizeof(struct dpu_hw_qos_cfg)); 152 qos_cfg.danger_safe_en = true; 153 qos_cfg.danger_lut = 154 catalog->perf->danger_lut_tbl[DPU_QOS_LUT_USAGE_NRT]; 155 156 qos_cfg.safe_lut = catalog->perf->safe_lut_tbl[DPU_QOS_LUT_USAGE_NRT]; 157 158 qos_lut_tb = &catalog->perf->qos_lut_tbl[DPU_QOS_LUT_USAGE_NRT]; 159 qos_cfg.creq_lut = _dpu_hw_get_qos_lut(qos_lut_tb, 0); 160 161 if (hw_wb->ops.setup_qos_lut) 162 hw_wb->ops.setup_qos_lut(hw_wb, &qos_cfg); 163 } 164 165 /** 166 * dpu_encoder_phys_wb_setup_fb - setup output framebuffer 167 * @phys_enc: Pointer to physical encoder 168 * @fb: Pointer to output framebuffer 169 */ 170 static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc, 171 struct drm_framebuffer *fb) 172 { 173 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 174 struct dpu_hw_wb *hw_wb; 175 struct dpu_hw_wb_cfg *wb_cfg; 176 177 if (!phys_enc || !phys_enc->dpu_kms || !phys_enc->dpu_kms->catalog) { 178 DPU_ERROR("invalid encoder\n"); 179 return; 180 } 181 182 hw_wb = phys_enc->hw_wb; 183 wb_cfg = &wb_enc->wb_cfg; 184 185 wb_cfg->intf_mode = phys_enc->intf_mode; 186 wb_cfg->roi.x1 = 0; 187 wb_cfg->roi.x2 = phys_enc->cached_mode.hdisplay; 188 wb_cfg->roi.y1 = 0; 189 wb_cfg->roi.y2 = phys_enc->cached_mode.vdisplay; 190 191 if (hw_wb->ops.setup_roi) 192 hw_wb->ops.setup_roi(hw_wb, wb_cfg); 193 194 if (hw_wb->ops.setup_outformat) 195 hw_wb->ops.setup_outformat(hw_wb, wb_cfg); 196 197 if (hw_wb->ops.setup_cdp) { 198 const struct dpu_perf_cfg *perf = phys_enc->dpu_kms->catalog->perf; 199 200 hw_wb->ops.setup_cdp(hw_wb, wb_cfg->dest.format, 201 perf->cdp_cfg[DPU_PERF_CDP_USAGE_NRT].wr_enable); 202 } 203 204 if (hw_wb->ops.setup_outaddress) 205 hw_wb->ops.setup_outaddress(hw_wb, wb_cfg); 206 } 207 208 /** 209 * dpu_encoder_phys_wb_setup_cdp - setup chroma down prefetch block 210 * @phys_enc:Pointer to physical encoder 211 */ 212 static void dpu_encoder_phys_wb_setup_cdp(struct dpu_encoder_phys *phys_enc) 213 { 214 struct dpu_hw_wb *hw_wb; 215 struct dpu_hw_ctl *ctl; 216 217 if (!phys_enc) { 218 DPU_ERROR("invalid encoder\n"); 219 return; 220 } 221 222 hw_wb = phys_enc->hw_wb; 223 ctl = phys_enc->hw_ctl; 224 225 if (test_bit(DPU_CTL_ACTIVE_CFG, &ctl->caps->features) && 226 (phys_enc->hw_ctl && 227 phys_enc->hw_ctl->ops.setup_intf_cfg)) { 228 struct dpu_hw_intf_cfg intf_cfg = {0}; 229 struct dpu_hw_pingpong *hw_pp = phys_enc->hw_pp; 230 enum dpu_3d_blend_mode mode_3d; 231 232 mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); 233 234 intf_cfg.intf = DPU_NONE; 235 intf_cfg.wb = hw_wb->idx; 236 237 if (mode_3d && hw_pp && hw_pp->merge_3d) 238 intf_cfg.merge_3d = hw_pp->merge_3d->idx; 239 240 if (phys_enc->hw_pp->merge_3d && phys_enc->hw_pp->merge_3d->ops.setup_3d_mode) 241 phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d, 242 mode_3d); 243 244 /* setup which pp blk will connect to this wb */ 245 if (hw_pp && phys_enc->hw_wb->ops.bind_pingpong_blk) 246 phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb, 247 phys_enc->hw_pp->idx); 248 249 phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg); 250 } else if (phys_enc->hw_ctl && phys_enc->hw_ctl->ops.setup_intf_cfg) { 251 struct dpu_hw_intf_cfg intf_cfg = {0}; 252 253 intf_cfg.intf = DPU_NONE; 254 intf_cfg.wb = hw_wb->idx; 255 intf_cfg.mode_3d = 256 dpu_encoder_helper_get_3d_blend_mode(phys_enc); 257 phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg); 258 } 259 } 260 261 /** 262 * dpu_encoder_phys_wb_atomic_check - verify and fixup given atomic states 263 * @phys_enc: Pointer to physical encoder 264 * @crtc_state: Pointer to CRTC atomic state 265 * @conn_state: Pointer to connector atomic state 266 */ 267 static int dpu_encoder_phys_wb_atomic_check( 268 struct dpu_encoder_phys *phys_enc, 269 struct drm_crtc_state *crtc_state, 270 struct drm_connector_state *conn_state) 271 { 272 struct drm_framebuffer *fb; 273 const struct drm_display_mode *mode = &crtc_state->mode; 274 275 DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n", 276 phys_enc->hw_wb->idx, mode->name, mode->hdisplay, mode->vdisplay); 277 278 if (!conn_state || !conn_state->connector) { 279 DPU_ERROR("invalid connector state\n"); 280 return -EINVAL; 281 } else if (conn_state->connector->status != 282 connector_status_connected) { 283 DPU_ERROR("connector not connected %d\n", 284 conn_state->connector->status); 285 return -EINVAL; 286 } 287 288 if (!conn_state->writeback_job || !conn_state->writeback_job->fb) 289 return 0; 290 291 fb = conn_state->writeback_job->fb; 292 293 DPU_DEBUG("[fb_id:%u][fb:%u,%u]\n", fb->base.id, 294 fb->width, fb->height); 295 296 if (fb->width != mode->hdisplay) { 297 DPU_ERROR("invalid fb w=%d, mode w=%d\n", fb->width, 298 mode->hdisplay); 299 return -EINVAL; 300 } else if (fb->height != mode->vdisplay) { 301 DPU_ERROR("invalid fb h=%d, mode h=%d\n", fb->height, 302 mode->vdisplay); 303 return -EINVAL; 304 } else if (fb->width > phys_enc->hw_wb->caps->maxlinewidth) { 305 DPU_ERROR("invalid fb w=%d, maxlinewidth=%u\n", 306 fb->width, phys_enc->hw_wb->caps->maxlinewidth); 307 return -EINVAL; 308 } 309 310 return 0; 311 } 312 313 314 /** 315 * _dpu_encoder_phys_wb_update_flush - flush hardware update 316 * @phys_enc: Pointer to physical encoder 317 */ 318 static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc) 319 { 320 struct dpu_hw_wb *hw_wb; 321 struct dpu_hw_ctl *hw_ctl; 322 struct dpu_hw_pingpong *hw_pp; 323 u32 pending_flush = 0; 324 325 if (!phys_enc) 326 return; 327 328 hw_wb = phys_enc->hw_wb; 329 hw_pp = phys_enc->hw_pp; 330 hw_ctl = phys_enc->hw_ctl; 331 332 DPU_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0); 333 334 if (!hw_ctl) { 335 DPU_DEBUG("[wb:%d] no ctl assigned\n", hw_wb->idx - WB_0); 336 return; 337 } 338 339 if (hw_ctl->ops.update_pending_flush_wb) 340 hw_ctl->ops.update_pending_flush_wb(hw_ctl, hw_wb->idx); 341 342 if (hw_ctl->ops.update_pending_flush_merge_3d && hw_pp && hw_pp->merge_3d) 343 hw_ctl->ops.update_pending_flush_merge_3d(hw_ctl, 344 hw_pp->merge_3d->idx); 345 346 if (hw_ctl->ops.get_pending_flush) 347 pending_flush = hw_ctl->ops.get_pending_flush(hw_ctl); 348 349 DPU_DEBUG("Pending flush mask for CTL_%d is 0x%x, WB %d\n", 350 hw_ctl->idx - CTL_0, pending_flush, 351 hw_wb->idx - WB_0); 352 } 353 354 /** 355 * dpu_encoder_phys_wb_setup - setup writeback encoder 356 * @phys_enc: Pointer to physical encoder 357 */ 358 static void dpu_encoder_phys_wb_setup( 359 struct dpu_encoder_phys *phys_enc) 360 { 361 struct dpu_hw_wb *hw_wb = phys_enc->hw_wb; 362 struct drm_display_mode mode = phys_enc->cached_mode; 363 struct drm_framebuffer *fb = NULL; 364 365 DPU_DEBUG("[mode_set:%d, \"%s\",%d,%d]\n", 366 hw_wb->idx - WB_0, mode.name, 367 mode.hdisplay, mode.vdisplay); 368 369 dpu_encoder_phys_wb_set_ot_limit(phys_enc); 370 371 dpu_encoder_phys_wb_set_qos_remap(phys_enc); 372 373 dpu_encoder_phys_wb_set_qos(phys_enc); 374 375 dpu_encoder_phys_wb_setup_fb(phys_enc, fb); 376 377 dpu_encoder_phys_wb_setup_cdp(phys_enc); 378 379 } 380 381 /** 382 * dpu_encoder_phys_wb_done_irq - writeback interrupt handler 383 * @arg: Pointer to writeback encoder 384 */ 385 static void dpu_encoder_phys_wb_done_irq(void *arg) 386 { 387 struct dpu_encoder_phys *phys_enc = arg; 388 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 389 390 struct dpu_hw_wb *hw_wb = phys_enc->hw_wb; 391 unsigned long lock_flags; 392 u32 event = DPU_ENCODER_FRAME_EVENT_DONE; 393 394 DPU_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0); 395 396 dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, event); 397 398 dpu_encoder_vblank_callback(phys_enc->parent, phys_enc); 399 400 spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); 401 atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); 402 spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); 403 404 if (wb_enc->wb_conn) 405 drm_writeback_signal_completion(wb_enc->wb_conn, 0); 406 407 /* Signal any waiting atomic commit thread */ 408 wake_up_all(&phys_enc->pending_kickoff_wq); 409 } 410 411 /** 412 * dpu_encoder_phys_wb_irq_ctrl - irq control of WB 413 * @phys: Pointer to physical encoder 414 * @enable: indicates enable or disable interrupts 415 */ 416 static void dpu_encoder_phys_wb_irq_ctrl( 417 struct dpu_encoder_phys *phys, bool enable) 418 { 419 420 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys); 421 422 if (enable && atomic_inc_return(&wb_enc->wbirq_refcount) == 1) 423 dpu_core_irq_register_callback(phys->dpu_kms, 424 phys->irq[INTR_IDX_WB_DONE], dpu_encoder_phys_wb_done_irq, phys); 425 else if (!enable && 426 atomic_dec_return(&wb_enc->wbirq_refcount) == 0) 427 dpu_core_irq_unregister_callback(phys->dpu_kms, phys->irq[INTR_IDX_WB_DONE]); 428 } 429 430 static void dpu_encoder_phys_wb_atomic_mode_set( 431 struct dpu_encoder_phys *phys_enc, 432 struct drm_crtc_state *crtc_state, 433 struct drm_connector_state *conn_state) 434 { 435 436 phys_enc->irq[INTR_IDX_WB_DONE] = phys_enc->hw_wb->caps->intr_wb_done; 437 } 438 439 static void _dpu_encoder_phys_wb_handle_wbdone_timeout( 440 struct dpu_encoder_phys *phys_enc) 441 { 442 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 443 u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR; 444 445 wb_enc->wb_done_timeout_cnt++; 446 447 if (wb_enc->wb_done_timeout_cnt == 1) 448 msm_disp_snapshot_state(phys_enc->parent->dev); 449 450 atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); 451 452 /* request a ctl reset before the next kickoff */ 453 phys_enc->enable_state = DPU_ENC_ERR_NEEDS_HW_RESET; 454 455 if (wb_enc->wb_conn) 456 drm_writeback_signal_completion(wb_enc->wb_conn, 0); 457 458 dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, frame_event); 459 } 460 461 /** 462 * dpu_encoder_phys_wb_wait_for_commit_done - wait until request is committed 463 * @phys_enc: Pointer to physical encoder 464 */ 465 static int dpu_encoder_phys_wb_wait_for_commit_done( 466 struct dpu_encoder_phys *phys_enc) 467 { 468 unsigned long ret; 469 struct dpu_encoder_wait_info wait_info; 470 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 471 472 wait_info.wq = &phys_enc->pending_kickoff_wq; 473 wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; 474 wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; 475 476 ret = dpu_encoder_helper_wait_for_irq(phys_enc, 477 phys_enc->irq[INTR_IDX_WB_DONE], 478 dpu_encoder_phys_wb_done_irq, &wait_info); 479 if (ret == -ETIMEDOUT) 480 _dpu_encoder_phys_wb_handle_wbdone_timeout(phys_enc); 481 else if (!ret) 482 wb_enc->wb_done_timeout_cnt = 0; 483 484 return ret; 485 } 486 487 /** 488 * dpu_encoder_phys_wb_prepare_for_kickoff - pre-kickoff processing 489 * @phys_enc: Pointer to physical encoder 490 * Returns: Zero on success 491 */ 492 static void dpu_encoder_phys_wb_prepare_for_kickoff( 493 struct dpu_encoder_phys *phys_enc) 494 { 495 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 496 struct drm_connector *drm_conn; 497 struct drm_connector_state *state; 498 499 DPU_DEBUG("[wb:%d]\n", phys_enc->hw_wb->idx - WB_0); 500 501 if (!wb_enc->wb_conn || !wb_enc->wb_job) { 502 DPU_ERROR("invalid wb_conn or wb_job\n"); 503 return; 504 } 505 506 drm_conn = &wb_enc->wb_conn->base; 507 state = drm_conn->state; 508 509 if (wb_enc->wb_conn && wb_enc->wb_job) 510 drm_writeback_queue_job(wb_enc->wb_conn, state); 511 512 dpu_encoder_phys_wb_setup(phys_enc); 513 514 _dpu_encoder_phys_wb_update_flush(phys_enc); 515 } 516 517 /** 518 * dpu_encoder_phys_wb_needs_single_flush - trigger flush processing 519 * @phys_enc: Pointer to physical encoder 520 */ 521 static bool dpu_encoder_phys_wb_needs_single_flush(struct dpu_encoder_phys *phys_enc) 522 { 523 DPU_DEBUG("[wb:%d]\n", phys_enc->hw_wb->idx - WB_0); 524 return false; 525 } 526 527 /** 528 * dpu_encoder_phys_wb_handle_post_kickoff - post-kickoff processing 529 * @phys_enc: Pointer to physical encoder 530 */ 531 static void dpu_encoder_phys_wb_handle_post_kickoff( 532 struct dpu_encoder_phys *phys_enc) 533 { 534 DPU_DEBUG("[wb:%d]\n", phys_enc->hw_wb->idx - WB_0); 535 536 } 537 538 /** 539 * dpu_encoder_phys_wb_enable - enable writeback encoder 540 * @phys_enc: Pointer to physical encoder 541 */ 542 static void dpu_encoder_phys_wb_enable(struct dpu_encoder_phys *phys_enc) 543 { 544 DPU_DEBUG("[wb:%d]\n", phys_enc->hw_wb->idx - WB_0); 545 phys_enc->enable_state = DPU_ENC_ENABLED; 546 } 547 /** 548 * dpu_encoder_phys_wb_disable - disable writeback encoder 549 * @phys_enc: Pointer to physical encoder 550 */ 551 static void dpu_encoder_phys_wb_disable(struct dpu_encoder_phys *phys_enc) 552 { 553 struct dpu_hw_wb *hw_wb = phys_enc->hw_wb; 554 struct dpu_hw_ctl *hw_ctl = phys_enc->hw_ctl; 555 556 DPU_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0); 557 558 if (phys_enc->enable_state == DPU_ENC_DISABLED) { 559 DPU_ERROR("encoder is already disabled\n"); 560 return; 561 } 562 563 /* reset h/w before final flush */ 564 if (phys_enc->hw_ctl->ops.clear_pending_flush) 565 phys_enc->hw_ctl->ops.clear_pending_flush(phys_enc->hw_ctl); 566 567 /* 568 * New CTL reset sequence from 5.0 MDP onwards. 569 * If has_3d_merge_reset is not set, legacy reset 570 * sequence is executed. 571 * 572 * Legacy reset sequence has not been implemented yet. 573 * Any target earlier than SM8150 will need it and when 574 * WB support is added to those targets will need to add 575 * the legacy teardown sequence as well. 576 */ 577 if (hw_ctl->caps->features & BIT(DPU_CTL_ACTIVE_CFG)) 578 dpu_encoder_helper_phys_cleanup(phys_enc); 579 580 phys_enc->enable_state = DPU_ENC_DISABLED; 581 } 582 583 /** 584 * dpu_encoder_phys_wb_destroy - destroy writeback encoder 585 * @phys_enc: Pointer to physical encoder 586 */ 587 static void dpu_encoder_phys_wb_destroy(struct dpu_encoder_phys *phys_enc) 588 { 589 if (!phys_enc) 590 return; 591 592 DPU_DEBUG("[wb:%d]\n", phys_enc->hw_wb->idx - WB_0); 593 594 kfree(phys_enc); 595 } 596 597 static void dpu_encoder_phys_wb_prepare_wb_job(struct dpu_encoder_phys *phys_enc, 598 struct drm_writeback_job *job) 599 { 600 const struct msm_format *format; 601 struct msm_gem_address_space *aspace; 602 struct dpu_hw_wb_cfg *wb_cfg; 603 int ret; 604 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 605 606 if (!job->fb) 607 return; 608 609 wb_enc->wb_job = job; 610 wb_enc->wb_conn = job->connector; 611 aspace = phys_enc->dpu_kms->base.aspace; 612 613 wb_cfg = &wb_enc->wb_cfg; 614 615 memset(wb_cfg, 0, sizeof(struct dpu_hw_wb_cfg)); 616 617 ret = msm_framebuffer_prepare(job->fb, aspace, false); 618 if (ret) { 619 DPU_ERROR("prep fb failed, %d\n", ret); 620 return; 621 } 622 623 format = msm_framebuffer_format(job->fb); 624 625 wb_cfg->dest.format = dpu_get_dpu_format_ext( 626 format->pixel_format, job->fb->modifier); 627 if (!wb_cfg->dest.format) { 628 /* this error should be detected during atomic_check */ 629 DPU_ERROR("failed to get format %x\n", format->pixel_format); 630 return; 631 } 632 633 ret = dpu_format_populate_layout(aspace, job->fb, &wb_cfg->dest); 634 if (ret) { 635 DPU_DEBUG("failed to populate layout %d\n", ret); 636 return; 637 } 638 639 wb_cfg->dest.width = job->fb->width; 640 wb_cfg->dest.height = job->fb->height; 641 wb_cfg->dest.num_planes = wb_cfg->dest.format->num_planes; 642 643 if ((wb_cfg->dest.format->fetch_planes == DPU_PLANE_PLANAR) && 644 (wb_cfg->dest.format->element[0] == C1_B_Cb)) 645 swap(wb_cfg->dest.plane_addr[1], wb_cfg->dest.plane_addr[2]); 646 647 DPU_DEBUG("[fb_offset:%8.8x,%8.8x,%8.8x,%8.8x]\n", 648 wb_cfg->dest.plane_addr[0], wb_cfg->dest.plane_addr[1], 649 wb_cfg->dest.plane_addr[2], wb_cfg->dest.plane_addr[3]); 650 651 DPU_DEBUG("[fb_stride:%8.8x,%8.8x,%8.8x,%8.8x]\n", 652 wb_cfg->dest.plane_pitch[0], wb_cfg->dest.plane_pitch[1], 653 wb_cfg->dest.plane_pitch[2], wb_cfg->dest.plane_pitch[3]); 654 } 655 656 static void dpu_encoder_phys_wb_cleanup_wb_job(struct dpu_encoder_phys *phys_enc, 657 struct drm_writeback_job *job) 658 { 659 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 660 struct msm_gem_address_space *aspace; 661 662 if (!job->fb) 663 return; 664 665 aspace = phys_enc->dpu_kms->base.aspace; 666 667 msm_framebuffer_cleanup(job->fb, aspace, false); 668 wb_enc->wb_job = NULL; 669 wb_enc->wb_conn = NULL; 670 } 671 672 static bool dpu_encoder_phys_wb_is_valid_for_commit(struct dpu_encoder_phys *phys_enc) 673 { 674 struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc); 675 676 if (wb_enc->wb_job) 677 return true; 678 else 679 return false; 680 } 681 682 /** 683 * dpu_encoder_phys_wb_init_ops - initialize writeback operations 684 * @ops: Pointer to encoder operation table 685 */ 686 static void dpu_encoder_phys_wb_init_ops(struct dpu_encoder_phys_ops *ops) 687 { 688 ops->is_master = dpu_encoder_phys_wb_is_master; 689 ops->atomic_mode_set = dpu_encoder_phys_wb_atomic_mode_set; 690 ops->enable = dpu_encoder_phys_wb_enable; 691 ops->disable = dpu_encoder_phys_wb_disable; 692 ops->destroy = dpu_encoder_phys_wb_destroy; 693 ops->atomic_check = dpu_encoder_phys_wb_atomic_check; 694 ops->wait_for_commit_done = dpu_encoder_phys_wb_wait_for_commit_done; 695 ops->prepare_for_kickoff = dpu_encoder_phys_wb_prepare_for_kickoff; 696 ops->handle_post_kickoff = dpu_encoder_phys_wb_handle_post_kickoff; 697 ops->needs_single_flush = dpu_encoder_phys_wb_needs_single_flush; 698 ops->trigger_start = dpu_encoder_helper_trigger_start; 699 ops->prepare_wb_job = dpu_encoder_phys_wb_prepare_wb_job; 700 ops->cleanup_wb_job = dpu_encoder_phys_wb_cleanup_wb_job; 701 ops->irq_control = dpu_encoder_phys_wb_irq_ctrl; 702 ops->is_valid_for_commit = dpu_encoder_phys_wb_is_valid_for_commit; 703 704 } 705 706 /** 707 * dpu_encoder_phys_wb_init - initialize writeback encoder 708 * @p: Pointer to init info structure with initialization params 709 */ 710 struct dpu_encoder_phys *dpu_encoder_phys_wb_init( 711 struct dpu_enc_phys_init_params *p) 712 { 713 struct dpu_encoder_phys *phys_enc = NULL; 714 struct dpu_encoder_phys_wb *wb_enc = NULL; 715 716 DPU_DEBUG("\n"); 717 718 if (!p || !p->parent) { 719 DPU_ERROR("invalid params\n"); 720 return ERR_PTR(-EINVAL); 721 } 722 723 wb_enc = kzalloc(sizeof(*wb_enc), GFP_KERNEL); 724 if (!wb_enc) { 725 DPU_ERROR("failed to allocate wb phys_enc enc\n"); 726 return ERR_PTR(-ENOMEM); 727 } 728 729 phys_enc = &wb_enc->base; 730 731 dpu_encoder_phys_init(phys_enc, p); 732 733 dpu_encoder_phys_wb_init_ops(&phys_enc->ops); 734 phys_enc->intf_mode = INTF_MODE_WB_LINE; 735 736 atomic_set(&wb_enc->wbirq_refcount, 0); 737 738 wb_enc->wb_done_timeout_cnt = 0; 739 740 DPU_DEBUG("Created dpu_encoder_phys for wb %d\n", phys_enc->hw_wb->idx); 741 742 return phys_enc; 743 } 744