1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2014-2018 The Linux Foundation. All rights reserved. 4 * Copyright (C) 2013 Red Hat 5 * Author: Rob Clark <robdclark@gmail.com> 6 */ 7 8 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ 9 10 #include <linux/debugfs.h> 11 #include <linux/dma-buf.h> 12 13 #include <drm/drm_atomic.h> 14 #include <drm/drm_atomic_uapi.h> 15 #include <drm/drm_blend.h> 16 #include <drm/drm_damage_helper.h> 17 #include <drm/drm_framebuffer.h> 18 #include <drm/drm_gem_atomic_helper.h> 19 20 #include "msm_drv.h" 21 #include "dpu_kms.h" 22 #include "dpu_formats.h" 23 #include "dpu_hw_sspp.h" 24 #include "dpu_trace.h" 25 #include "dpu_crtc.h" 26 #include "dpu_vbif.h" 27 #include "dpu_plane.h" 28 29 #define DPU_DEBUG_PLANE(pl, fmt, ...) DRM_DEBUG_ATOMIC("plane%d " fmt,\ 30 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__) 31 32 #define DPU_ERROR_PLANE(pl, fmt, ...) DPU_ERROR("plane%d " fmt,\ 33 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__) 34 35 #define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci)) 36 #define PHASE_STEP_SHIFT 21 37 #define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT)) 38 #define PHASE_RESIDUAL 15 39 40 #define SHARP_STRENGTH_DEFAULT 32 41 #define SHARP_EDGE_THR_DEFAULT 112 42 #define SHARP_SMOOTH_THR_DEFAULT 8 43 #define SHARP_NOISE_THR_DEFAULT 2 44 45 #define DPU_PLANE_COLOR_FILL_FLAG BIT(31) 46 #define DPU_ZPOS_MAX 255 47 48 /* 49 * Default Preload Values 50 */ 51 #define DPU_QSEED3_DEFAULT_PRELOAD_H 0x4 52 #define DPU_QSEED3_DEFAULT_PRELOAD_V 0x3 53 #define DPU_QSEED4_DEFAULT_PRELOAD_V 0x2 54 #define DPU_QSEED4_DEFAULT_PRELOAD_H 0x4 55 56 #define DEFAULT_REFRESH_RATE 60 57 58 static const uint32_t qcom_compressed_supported_formats[] = { 59 DRM_FORMAT_ABGR8888, 60 DRM_FORMAT_ARGB8888, 61 DRM_FORMAT_XBGR8888, 62 DRM_FORMAT_XRGB8888, 63 DRM_FORMAT_ARGB2101010, 64 DRM_FORMAT_XRGB2101010, 65 DRM_FORMAT_BGR565, 66 67 DRM_FORMAT_NV12, 68 DRM_FORMAT_P010, 69 }; 70 71 /* 72 * struct dpu_plane - local dpu plane structure 73 * @aspace: address space pointer 74 * @csc_ptr: Points to dpu_csc_cfg structure to use for current 75 * @catalog: Points to dpu catalog structure 76 * @revalidate: force revalidation of all the plane properties 77 */ 78 struct dpu_plane { 79 struct drm_plane base; 80 81 struct mutex lock; 82 83 enum dpu_sspp pipe; 84 85 uint32_t color_fill; 86 bool is_error; 87 bool is_rt_pipe; 88 const struct dpu_mdss_cfg *catalog; 89 }; 90 91 static const uint64_t supported_format_modifiers[] = { 92 DRM_FORMAT_MOD_QCOM_COMPRESSED, 93 DRM_FORMAT_MOD_LINEAR, 94 DRM_FORMAT_MOD_INVALID 95 }; 96 97 #define to_dpu_plane(x) container_of(x, struct dpu_plane, base) 98 99 static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane) 100 { 101 struct msm_drm_private *priv = plane->dev->dev_private; 102 103 return to_dpu_kms(priv->kms); 104 } 105 106 /** 107 * _dpu_plane_calc_bw - calculate bandwidth required for a plane 108 * @catalog: Points to dpu catalog structure 109 * @fmt: Pointer to source buffer format 110 * @mode: Pointer to drm display mode 111 * @pipe_cfg: Pointer to pipe configuration 112 * Result: Updates calculated bandwidth in the plane state. 113 * BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest) 114 * Prefill BW Equation: line src bytes * line_time 115 */ 116 static u64 _dpu_plane_calc_bw(const struct dpu_mdss_cfg *catalog, 117 const struct dpu_format *fmt, 118 const struct drm_display_mode *mode, 119 struct dpu_sw_pipe_cfg *pipe_cfg) 120 { 121 int src_width, src_height, dst_height, fps; 122 u64 plane_pixel_rate, plane_bit_rate; 123 u64 plane_prefill_bw; 124 u64 plane_bw; 125 u32 hw_latency_lines; 126 u64 scale_factor; 127 int vbp, vpw, vfp; 128 129 src_width = drm_rect_width(&pipe_cfg->src_rect); 130 src_height = drm_rect_height(&pipe_cfg->src_rect); 131 dst_height = drm_rect_height(&pipe_cfg->dst_rect); 132 fps = drm_mode_vrefresh(mode); 133 vbp = mode->vtotal - mode->vsync_end; 134 vpw = mode->vsync_end - mode->vsync_start; 135 vfp = mode->vsync_start - mode->vdisplay; 136 hw_latency_lines = catalog->perf->min_prefill_lines; 137 scale_factor = src_height > dst_height ? 138 mult_frac(src_height, 1, dst_height) : 1; 139 140 plane_pixel_rate = src_width * mode->vtotal * fps; 141 plane_bit_rate = plane_pixel_rate * fmt->bpp; 142 143 plane_bw = plane_bit_rate * scale_factor; 144 145 plane_prefill_bw = plane_bw * hw_latency_lines; 146 147 if ((vbp+vpw) > hw_latency_lines) 148 do_div(plane_prefill_bw, (vbp+vpw)); 149 else if ((vbp+vpw+vfp) < hw_latency_lines) 150 do_div(plane_prefill_bw, (vbp+vpw+vfp)); 151 else 152 do_div(plane_prefill_bw, hw_latency_lines); 153 154 155 return max(plane_bw, plane_prefill_bw); 156 } 157 158 /** 159 * _dpu_plane_calc_clk - calculate clock required for a plane 160 * @mode: Pointer to drm display mode 161 * @pipe_cfg: Pointer to pipe configuration 162 * Result: Updates calculated clock in the plane state. 163 * Clock equation: dst_w * v_total * fps * (src_h / dst_h) 164 */ 165 static u64 _dpu_plane_calc_clk(const struct drm_display_mode *mode, 166 struct dpu_sw_pipe_cfg *pipe_cfg) 167 { 168 int dst_width, src_height, dst_height, fps; 169 u64 plane_clk; 170 171 src_height = drm_rect_height(&pipe_cfg->src_rect); 172 dst_width = drm_rect_width(&pipe_cfg->dst_rect); 173 dst_height = drm_rect_height(&pipe_cfg->dst_rect); 174 fps = drm_mode_vrefresh(mode); 175 176 plane_clk = 177 dst_width * mode->vtotal * fps; 178 179 if (src_height > dst_height) { 180 plane_clk *= src_height; 181 do_div(plane_clk, dst_height); 182 } 183 184 return plane_clk; 185 } 186 187 /** 188 * _dpu_plane_calc_fill_level - calculate fill level of the given source format 189 * @plane: Pointer to drm plane 190 * @pipe: Pointer to software pipe 191 * @lut_usage: LUT usecase 192 * @fmt: Pointer to source buffer format 193 * @src_width: width of source buffer 194 * Return: fill level corresponding to the source buffer/format or 0 if error 195 */ 196 static int _dpu_plane_calc_fill_level(struct drm_plane *plane, 197 struct dpu_sw_pipe *pipe, 198 enum dpu_qos_lut_usage lut_usage, 199 const struct dpu_format *fmt, u32 src_width) 200 { 201 struct dpu_plane *pdpu; 202 u32 fixed_buff_size; 203 u32 total_fl; 204 205 if (!fmt || !pipe || !src_width || !fmt->bpp) { 206 DPU_ERROR("invalid arguments\n"); 207 return 0; 208 } 209 210 if (lut_usage == DPU_QOS_LUT_USAGE_NRT) 211 return 0; 212 213 pdpu = to_dpu_plane(plane); 214 fixed_buff_size = pdpu->catalog->caps->pixel_ram_size; 215 216 /* FIXME: in multirect case account for the src_width of all the planes */ 217 218 if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) { 219 if (fmt->chroma_sample == DPU_CHROMA_420) { 220 /* NV12 */ 221 total_fl = (fixed_buff_size / 2) / 222 ((src_width + 32) * fmt->bpp); 223 } else { 224 /* non NV12 */ 225 total_fl = (fixed_buff_size / 2) * 2 / 226 ((src_width + 32) * fmt->bpp); 227 } 228 } else { 229 if (pipe->multirect_mode == DPU_SSPP_MULTIRECT_PARALLEL) { 230 total_fl = (fixed_buff_size / 2) * 2 / 231 ((src_width + 32) * fmt->bpp); 232 } else { 233 total_fl = (fixed_buff_size) * 2 / 234 ((src_width + 32) * fmt->bpp); 235 } 236 } 237 238 DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s w:%u fl:%u\n", 239 pipe->sspp->idx - SSPP_VIG0, 240 (char *)&fmt->base.pixel_format, 241 src_width, total_fl); 242 243 return total_fl; 244 } 245 246 /** 247 * _dpu_plane_set_qos_lut - set QoS LUT of the given plane 248 * @plane: Pointer to drm plane 249 * @pipe: Pointer to software pipe 250 * @fmt: Pointer to source buffer format 251 * @pipe_cfg: Pointer to pipe configuration 252 */ 253 static void _dpu_plane_set_qos_lut(struct drm_plane *plane, 254 struct dpu_sw_pipe *pipe, 255 const struct dpu_format *fmt, struct dpu_sw_pipe_cfg *pipe_cfg) 256 { 257 struct dpu_plane *pdpu = to_dpu_plane(plane); 258 struct dpu_hw_qos_cfg cfg; 259 u32 total_fl, lut_usage; 260 261 if (!pdpu->is_rt_pipe) { 262 lut_usage = DPU_QOS_LUT_USAGE_NRT; 263 } else { 264 if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) 265 lut_usage = DPU_QOS_LUT_USAGE_LINEAR; 266 else 267 lut_usage = DPU_QOS_LUT_USAGE_MACROTILE; 268 } 269 270 total_fl = _dpu_plane_calc_fill_level(plane, pipe, lut_usage, fmt, 271 drm_rect_width(&pipe_cfg->src_rect)); 272 273 cfg.creq_lut = _dpu_hw_get_qos_lut(&pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl); 274 cfg.danger_lut = pdpu->catalog->perf->danger_lut_tbl[lut_usage]; 275 cfg.safe_lut = pdpu->catalog->perf->safe_lut_tbl[lut_usage]; 276 277 if (pipe->sspp->idx != SSPP_CURSOR0 && 278 pipe->sspp->idx != SSPP_CURSOR1 && 279 pdpu->is_rt_pipe) 280 cfg.danger_safe_en = true; 281 282 DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d is_rt:%d\n", 283 pdpu->pipe - SSPP_VIG0, 284 cfg.danger_safe_en, 285 pdpu->is_rt_pipe); 286 287 trace_dpu_perf_set_qos_luts(pipe->sspp->idx - SSPP_VIG0, 288 (fmt) ? fmt->base.pixel_format : 0, 289 pdpu->is_rt_pipe, total_fl, cfg.creq_lut, lut_usage); 290 291 DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n", 292 pdpu->pipe - SSPP_VIG0, 293 fmt ? (char *)&fmt->base.pixel_format : NULL, 294 pdpu->is_rt_pipe, total_fl, cfg.creq_lut); 295 296 trace_dpu_perf_set_danger_luts(pdpu->pipe - SSPP_VIG0, 297 (fmt) ? fmt->base.pixel_format : 0, 298 (fmt) ? fmt->fetch_mode : 0, 299 cfg.danger_lut, 300 cfg.safe_lut); 301 302 DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n", 303 pdpu->pipe - SSPP_VIG0, 304 fmt ? (char *)&fmt->base.pixel_format : NULL, 305 fmt ? fmt->fetch_mode : -1, 306 cfg.danger_lut, 307 cfg.safe_lut); 308 309 pipe->sspp->ops.setup_qos_lut(pipe->sspp, &cfg); 310 } 311 312 /** 313 * _dpu_plane_set_qos_ctrl - set QoS control of the given plane 314 * @plane: Pointer to drm plane 315 * @pipe: Pointer to software pipe 316 * @enable: true to enable QoS control 317 */ 318 static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, 319 struct dpu_sw_pipe *pipe, 320 bool enable) 321 { 322 struct dpu_plane *pdpu = to_dpu_plane(plane); 323 324 if (!pdpu->is_rt_pipe) 325 enable = false; 326 327 DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d is_rt:%d\n", 328 pdpu->pipe - SSPP_VIG0, 329 enable, 330 pdpu->is_rt_pipe); 331 332 pipe->sspp->ops.setup_qos_ctrl(pipe->sspp, 333 enable); 334 } 335 336 static bool _dpu_plane_sspp_clk_force_ctrl(struct dpu_hw_sspp *sspp, 337 struct dpu_hw_mdp *mdp, 338 bool enable, bool *forced_on) 339 { 340 if (sspp->ops.setup_clk_force_ctrl) { 341 *forced_on = sspp->ops.setup_clk_force_ctrl(sspp, enable); 342 return true; 343 } 344 345 if (mdp->ops.setup_clk_force_ctrl) { 346 *forced_on = mdp->ops.setup_clk_force_ctrl(mdp, sspp->cap->clk_ctrl, enable); 347 return true; 348 } 349 350 return false; 351 } 352 353 /** 354 * _dpu_plane_set_ot_limit - set OT limit for the given plane 355 * @plane: Pointer to drm plane 356 * @pipe: Pointer to software pipe 357 * @pipe_cfg: Pointer to pipe configuration 358 * @frame_rate: CRTC's frame rate 359 */ 360 static void _dpu_plane_set_ot_limit(struct drm_plane *plane, 361 struct dpu_sw_pipe *pipe, 362 struct dpu_sw_pipe_cfg *pipe_cfg, 363 int frame_rate) 364 { 365 struct dpu_plane *pdpu = to_dpu_plane(plane); 366 struct dpu_vbif_set_ot_params ot_params; 367 struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); 368 bool forced_on = false; 369 370 memset(&ot_params, 0, sizeof(ot_params)); 371 ot_params.xin_id = pipe->sspp->cap->xin_id; 372 ot_params.num = pipe->sspp->idx - SSPP_NONE; 373 ot_params.width = drm_rect_width(&pipe_cfg->src_rect); 374 ot_params.height = drm_rect_height(&pipe_cfg->src_rect); 375 ot_params.is_wfd = !pdpu->is_rt_pipe; 376 ot_params.frame_rate = frame_rate; 377 ot_params.vbif_idx = VBIF_RT; 378 ot_params.rd = true; 379 380 if (!_dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp, 381 true, &forced_on)) 382 return; 383 384 dpu_vbif_set_ot_limit(dpu_kms, &ot_params); 385 386 if (forced_on) 387 _dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp, 388 false, &forced_on); 389 } 390 391 /** 392 * _dpu_plane_set_qos_remap - set vbif QoS for the given plane 393 * @plane: Pointer to drm plane 394 * @pipe: Pointer to software pipe 395 */ 396 static void _dpu_plane_set_qos_remap(struct drm_plane *plane, 397 struct dpu_sw_pipe *pipe) 398 { 399 struct dpu_plane *pdpu = to_dpu_plane(plane); 400 struct dpu_vbif_set_qos_params qos_params; 401 struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); 402 bool forced_on = false; 403 404 memset(&qos_params, 0, sizeof(qos_params)); 405 qos_params.vbif_idx = VBIF_RT; 406 qos_params.xin_id = pipe->sspp->cap->xin_id; 407 qos_params.num = pipe->sspp->idx - SSPP_VIG0; 408 qos_params.is_rt = pdpu->is_rt_pipe; 409 410 DPU_DEBUG_PLANE(pdpu, "pipe:%d vbif:%d xin:%d rt:%d\n", 411 qos_params.num, 412 qos_params.vbif_idx, 413 qos_params.xin_id, qos_params.is_rt); 414 415 if (!_dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp, 416 true, &forced_on)) 417 return; 418 419 dpu_vbif_set_qos_remap(dpu_kms, &qos_params); 420 421 if (forced_on) 422 _dpu_plane_sspp_clk_force_ctrl(pipe->sspp, dpu_kms->hw_mdp, 423 false, &forced_on); 424 } 425 426 static void _dpu_plane_setup_scaler3(struct dpu_hw_sspp *pipe_hw, 427 uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h, 428 struct dpu_hw_scaler3_cfg *scale_cfg, 429 const struct dpu_format *fmt, 430 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v, 431 unsigned int rotation) 432 { 433 uint32_t i; 434 bool inline_rotation = rotation & DRM_MODE_ROTATE_90; 435 436 /* 437 * For inline rotation cases, scaler config is post-rotation, 438 * so swap the dimensions here. However, pixel extension will 439 * need pre-rotation settings. 440 */ 441 if (inline_rotation) 442 swap(src_w, src_h); 443 444 scale_cfg->phase_step_x[DPU_SSPP_COMP_0] = 445 mult_frac((1 << PHASE_STEP_SHIFT), src_w, dst_w); 446 scale_cfg->phase_step_y[DPU_SSPP_COMP_0] = 447 mult_frac((1 << PHASE_STEP_SHIFT), src_h, dst_h); 448 449 450 scale_cfg->phase_step_y[DPU_SSPP_COMP_1_2] = 451 scale_cfg->phase_step_y[DPU_SSPP_COMP_0] / chroma_subsmpl_v; 452 scale_cfg->phase_step_x[DPU_SSPP_COMP_1_2] = 453 scale_cfg->phase_step_x[DPU_SSPP_COMP_0] / chroma_subsmpl_h; 454 455 scale_cfg->phase_step_x[DPU_SSPP_COMP_2] = 456 scale_cfg->phase_step_x[DPU_SSPP_COMP_1_2]; 457 scale_cfg->phase_step_y[DPU_SSPP_COMP_2] = 458 scale_cfg->phase_step_y[DPU_SSPP_COMP_1_2]; 459 460 scale_cfg->phase_step_x[DPU_SSPP_COMP_3] = 461 scale_cfg->phase_step_x[DPU_SSPP_COMP_0]; 462 scale_cfg->phase_step_y[DPU_SSPP_COMP_3] = 463 scale_cfg->phase_step_y[DPU_SSPP_COMP_0]; 464 465 for (i = 0; i < DPU_MAX_PLANES; i++) { 466 scale_cfg->src_width[i] = src_w; 467 scale_cfg->src_height[i] = src_h; 468 if (i == DPU_SSPP_COMP_1_2 || i == DPU_SSPP_COMP_2) { 469 scale_cfg->src_width[i] /= chroma_subsmpl_h; 470 scale_cfg->src_height[i] /= chroma_subsmpl_v; 471 } 472 473 if (pipe_hw->cap->features & 474 BIT(DPU_SSPP_SCALER_QSEED4)) { 475 scale_cfg->preload_x[i] = DPU_QSEED4_DEFAULT_PRELOAD_H; 476 scale_cfg->preload_y[i] = DPU_QSEED4_DEFAULT_PRELOAD_V; 477 } else { 478 scale_cfg->preload_x[i] = DPU_QSEED3_DEFAULT_PRELOAD_H; 479 scale_cfg->preload_y[i] = DPU_QSEED3_DEFAULT_PRELOAD_V; 480 } 481 } 482 if (!(DPU_FORMAT_IS_YUV(fmt)) && (src_h == dst_h) 483 && (src_w == dst_w)) 484 return; 485 486 scale_cfg->dst_width = dst_w; 487 scale_cfg->dst_height = dst_h; 488 scale_cfg->y_rgb_filter_cfg = DPU_SCALE_BIL; 489 scale_cfg->uv_filter_cfg = DPU_SCALE_BIL; 490 scale_cfg->alpha_filter_cfg = DPU_SCALE_ALPHA_BIL; 491 scale_cfg->lut_flag = 0; 492 scale_cfg->blend_cfg = 1; 493 scale_cfg->enable = 1; 494 } 495 496 static void _dpu_plane_setup_pixel_ext(struct dpu_hw_scaler3_cfg *scale_cfg, 497 struct dpu_hw_pixel_ext *pixel_ext, 498 uint32_t src_w, uint32_t src_h, 499 uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v) 500 { 501 int i; 502 503 for (i = 0; i < DPU_MAX_PLANES; i++) { 504 if (i == DPU_SSPP_COMP_1_2 || i == DPU_SSPP_COMP_2) { 505 src_w /= chroma_subsmpl_h; 506 src_h /= chroma_subsmpl_v; 507 } 508 509 pixel_ext->num_ext_pxls_top[i] = src_h; 510 pixel_ext->num_ext_pxls_left[i] = src_w; 511 } 512 } 513 514 static const struct dpu_csc_cfg dpu_csc_YUV2RGB_601L = { 515 { 516 /* S15.16 format */ 517 0x00012A00, 0x00000000, 0x00019880, 518 0x00012A00, 0xFFFF9B80, 0xFFFF3000, 519 0x00012A00, 0x00020480, 0x00000000, 520 }, 521 /* signed bias */ 522 { 0xfff0, 0xff80, 0xff80,}, 523 { 0x0, 0x0, 0x0,}, 524 /* unsigned clamp */ 525 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,}, 526 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,}, 527 }; 528 529 static const struct dpu_csc_cfg dpu_csc10_YUV2RGB_601L = { 530 { 531 /* S15.16 format */ 532 0x00012A00, 0x00000000, 0x00019880, 533 0x00012A00, 0xFFFF9B80, 0xFFFF3000, 534 0x00012A00, 0x00020480, 0x00000000, 535 }, 536 /* signed bias */ 537 { 0xffc0, 0xfe00, 0xfe00,}, 538 { 0x0, 0x0, 0x0,}, 539 /* unsigned clamp */ 540 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,}, 541 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,}, 542 }; 543 544 static const struct dpu_csc_cfg *_dpu_plane_get_csc(struct dpu_sw_pipe *pipe, 545 const struct dpu_format *fmt) 546 { 547 const struct dpu_csc_cfg *csc_ptr; 548 549 if (!DPU_FORMAT_IS_YUV(fmt)) 550 return NULL; 551 552 if (BIT(DPU_SSPP_CSC_10BIT) & pipe->sspp->cap->features) 553 csc_ptr = &dpu_csc10_YUV2RGB_601L; 554 else 555 csc_ptr = &dpu_csc_YUV2RGB_601L; 556 557 return csc_ptr; 558 } 559 560 static void _dpu_plane_setup_scaler(struct dpu_sw_pipe *pipe, 561 const struct dpu_format *fmt, bool color_fill, 562 struct dpu_sw_pipe_cfg *pipe_cfg, 563 unsigned int rotation) 564 { 565 struct dpu_hw_sspp *pipe_hw = pipe->sspp; 566 const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format); 567 struct dpu_hw_scaler3_cfg scaler3_cfg; 568 struct dpu_hw_pixel_ext pixel_ext; 569 u32 src_width = drm_rect_width(&pipe_cfg->src_rect); 570 u32 src_height = drm_rect_height(&pipe_cfg->src_rect); 571 u32 dst_width = drm_rect_width(&pipe_cfg->dst_rect); 572 u32 dst_height = drm_rect_height(&pipe_cfg->dst_rect); 573 574 memset(&scaler3_cfg, 0, sizeof(scaler3_cfg)); 575 memset(&pixel_ext, 0, sizeof(pixel_ext)); 576 577 /* don't chroma subsample if decimating */ 578 /* update scaler. calculate default config for QSEED3 */ 579 _dpu_plane_setup_scaler3(pipe_hw, 580 src_width, 581 src_height, 582 dst_width, 583 dst_height, 584 &scaler3_cfg, fmt, 585 info->hsub, info->vsub, 586 rotation); 587 588 /* configure pixel extension based on scalar config */ 589 _dpu_plane_setup_pixel_ext(&scaler3_cfg, &pixel_ext, 590 src_width, src_height, info->hsub, info->vsub); 591 592 if (pipe_hw->ops.setup_pe) 593 pipe_hw->ops.setup_pe(pipe_hw, 594 &pixel_ext); 595 596 /** 597 * when programmed in multirect mode, scalar block will be 598 * bypassed. Still we need to update alpha and bitwidth 599 * ONLY for RECT0 600 */ 601 if (pipe_hw->ops.setup_scaler && 602 pipe->multirect_index != DPU_SSPP_RECT_1) 603 pipe_hw->ops.setup_scaler(pipe_hw, 604 &scaler3_cfg, 605 fmt); 606 } 607 608 static void _dpu_plane_color_fill_pipe(struct dpu_plane_state *pstate, 609 struct dpu_sw_pipe *pipe, 610 struct drm_rect *dst_rect, 611 u32 fill_color, 612 const struct dpu_format *fmt) 613 { 614 struct dpu_sw_pipe_cfg pipe_cfg; 615 616 /* update sspp */ 617 if (!pipe->sspp->ops.setup_solidfill) 618 return; 619 620 pipe->sspp->ops.setup_solidfill(pipe, fill_color); 621 622 /* override scaler/decimation if solid fill */ 623 pipe_cfg.dst_rect = *dst_rect; 624 625 pipe_cfg.src_rect.x1 = 0; 626 pipe_cfg.src_rect.y1 = 0; 627 pipe_cfg.src_rect.x2 = 628 drm_rect_width(&pipe_cfg.dst_rect); 629 pipe_cfg.src_rect.y2 = 630 drm_rect_height(&pipe_cfg.dst_rect); 631 632 if (pipe->sspp->ops.setup_format) 633 pipe->sspp->ops.setup_format(pipe, fmt, DPU_SSPP_SOLID_FILL); 634 635 if (pipe->sspp->ops.setup_rects) 636 pipe->sspp->ops.setup_rects(pipe, &pipe_cfg); 637 638 _dpu_plane_setup_scaler(pipe, fmt, true, &pipe_cfg, pstate->rotation); 639 } 640 641 /** 642 * _dpu_plane_color_fill - enables color fill on plane 643 * @pdpu: Pointer to DPU plane object 644 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red 645 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha 646 */ 647 static void _dpu_plane_color_fill(struct dpu_plane *pdpu, 648 uint32_t color, uint32_t alpha) 649 { 650 const struct dpu_format *fmt; 651 const struct drm_plane *plane = &pdpu->base; 652 struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state); 653 u32 fill_color = (color & 0xFFFFFF) | ((alpha & 0xFF) << 24); 654 655 DPU_DEBUG_PLANE(pdpu, "\n"); 656 657 /* 658 * select fill format to match user property expectation, 659 * h/w only supports RGB variants 660 */ 661 fmt = dpu_get_dpu_format(DRM_FORMAT_ABGR8888); 662 /* should not happen ever */ 663 if (!fmt) 664 return; 665 666 /* update sspp */ 667 _dpu_plane_color_fill_pipe(pstate, &pstate->pipe, &pstate->pipe_cfg.dst_rect, 668 fill_color, fmt); 669 670 if (pstate->r_pipe.sspp) 671 _dpu_plane_color_fill_pipe(pstate, &pstate->r_pipe, &pstate->r_pipe_cfg.dst_rect, 672 fill_color, fmt); 673 } 674 675 static int dpu_plane_prepare_fb(struct drm_plane *plane, 676 struct drm_plane_state *new_state) 677 { 678 struct drm_framebuffer *fb = new_state->fb; 679 struct dpu_plane *pdpu = to_dpu_plane(plane); 680 struct dpu_plane_state *pstate = to_dpu_plane_state(new_state); 681 struct dpu_hw_fmt_layout layout; 682 struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); 683 int ret; 684 685 if (!new_state->fb) 686 return 0; 687 688 DPU_DEBUG_PLANE(pdpu, "FB[%u]\n", fb->base.id); 689 690 /* cache aspace */ 691 pstate->aspace = kms->base.aspace; 692 693 /* 694 * TODO: Need to sort out the msm_framebuffer_prepare() call below so 695 * we can use msm_atomic_prepare_fb() instead of doing the 696 * implicit fence and fb prepare by hand here. 697 */ 698 drm_gem_plane_helper_prepare_fb(plane, new_state); 699 700 if (pstate->aspace) { 701 ret = msm_framebuffer_prepare(new_state->fb, 702 pstate->aspace, pstate->needs_dirtyfb); 703 if (ret) { 704 DPU_ERROR("failed to prepare framebuffer\n"); 705 return ret; 706 } 707 } 708 709 /* validate framebuffer layout before commit */ 710 ret = dpu_format_populate_layout(pstate->aspace, 711 new_state->fb, &layout); 712 if (ret) { 713 DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret); 714 return ret; 715 } 716 717 return 0; 718 } 719 720 static void dpu_plane_cleanup_fb(struct drm_plane *plane, 721 struct drm_plane_state *old_state) 722 { 723 struct dpu_plane *pdpu = to_dpu_plane(plane); 724 struct dpu_plane_state *old_pstate; 725 726 if (!old_state || !old_state->fb) 727 return; 728 729 old_pstate = to_dpu_plane_state(old_state); 730 731 DPU_DEBUG_PLANE(pdpu, "FB[%u]\n", old_state->fb->base.id); 732 733 msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace, 734 old_pstate->needs_dirtyfb); 735 } 736 737 static int dpu_plane_check_inline_rotation(struct dpu_plane *pdpu, 738 const struct dpu_sspp_sub_blks *sblk, 739 struct drm_rect src, const struct dpu_format *fmt) 740 { 741 size_t num_formats; 742 const u32 *supported_formats; 743 744 if (!sblk->rotation_cfg) { 745 DPU_ERROR("invalid rotation cfg\n"); 746 return -EINVAL; 747 } 748 749 if (drm_rect_width(&src) > sblk->rotation_cfg->rot_maxheight) { 750 DPU_DEBUG_PLANE(pdpu, "invalid height for inline rot:%d max:%d\n", 751 src.y2, sblk->rotation_cfg->rot_maxheight); 752 return -EINVAL; 753 } 754 755 supported_formats = sblk->rotation_cfg->rot_format_list; 756 num_formats = sblk->rotation_cfg->rot_num_formats; 757 758 if (!DPU_FORMAT_IS_UBWC(fmt) || 759 !dpu_find_format(fmt->base.pixel_format, supported_formats, num_formats)) 760 return -EINVAL; 761 762 return 0; 763 } 764 765 static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu, 766 struct dpu_sw_pipe *pipe, 767 struct dpu_sw_pipe_cfg *pipe_cfg, 768 const struct dpu_format *fmt, 769 const struct drm_display_mode *mode) 770 { 771 uint32_t min_src_size; 772 struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); 773 774 min_src_size = DPU_FORMAT_IS_YUV(fmt) ? 2 : 1; 775 776 if (DPU_FORMAT_IS_YUV(fmt) && 777 (!(pipe->sspp->cap->features & DPU_SSPP_SCALER) || 778 !(pipe->sspp->cap->features & DPU_SSPP_CSC_ANY))) { 779 DPU_DEBUG_PLANE(pdpu, 780 "plane doesn't have scaler/csc for yuv\n"); 781 return -EINVAL; 782 } 783 784 /* check src bounds */ 785 if (drm_rect_width(&pipe_cfg->src_rect) < min_src_size || 786 drm_rect_height(&pipe_cfg->src_rect) < min_src_size) { 787 DPU_DEBUG_PLANE(pdpu, "invalid source " DRM_RECT_FMT "\n", 788 DRM_RECT_ARG(&pipe_cfg->src_rect)); 789 return -E2BIG; 790 } 791 792 /* valid yuv image */ 793 if (DPU_FORMAT_IS_YUV(fmt) && 794 (pipe_cfg->src_rect.x1 & 0x1 || 795 pipe_cfg->src_rect.y1 & 0x1 || 796 drm_rect_width(&pipe_cfg->src_rect) & 0x1 || 797 drm_rect_height(&pipe_cfg->src_rect) & 0x1)) { 798 DPU_DEBUG_PLANE(pdpu, "invalid yuv source " DRM_RECT_FMT "\n", 799 DRM_RECT_ARG(&pipe_cfg->src_rect)); 800 return -EINVAL; 801 } 802 803 /* min dst support */ 804 if (drm_rect_width(&pipe_cfg->dst_rect) < 0x1 || 805 drm_rect_height(&pipe_cfg->dst_rect) < 0x1) { 806 DPU_DEBUG_PLANE(pdpu, "invalid dest rect " DRM_RECT_FMT "\n", 807 DRM_RECT_ARG(&pipe_cfg->dst_rect)); 808 return -EINVAL; 809 } 810 811 /* max clk check */ 812 if (_dpu_plane_calc_clk(mode, pipe_cfg) > kms->perf.max_core_clk_rate) { 813 DPU_DEBUG_PLANE(pdpu, "plane exceeds max mdp core clk limits\n"); 814 return -E2BIG; 815 } 816 817 return 0; 818 } 819 820 static int dpu_plane_atomic_check(struct drm_plane *plane, 821 struct drm_atomic_state *state) 822 { 823 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 824 plane); 825 int ret = 0, min_scale; 826 struct dpu_plane *pdpu = to_dpu_plane(plane); 827 struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state); 828 struct dpu_sw_pipe *pipe = &pstate->pipe; 829 struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; 830 const struct drm_crtc_state *crtc_state = NULL; 831 const struct dpu_format *fmt; 832 struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; 833 struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; 834 struct drm_rect fb_rect = { 0 }; 835 uint32_t max_linewidth; 836 unsigned int rotation; 837 uint32_t supported_rotations; 838 const struct dpu_sspp_cfg *pipe_hw_caps = pstate->pipe.sspp->cap; 839 const struct dpu_sspp_sub_blks *sblk = pstate->pipe.sspp->cap->sblk; 840 841 if (new_plane_state->crtc) 842 crtc_state = drm_atomic_get_new_crtc_state(state, 843 new_plane_state->crtc); 844 845 min_scale = FRAC_16_16(1, sblk->maxupscale); 846 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 847 min_scale, 848 sblk->maxdwnscale << 16, 849 true, true); 850 if (ret) { 851 DPU_DEBUG_PLANE(pdpu, "Check plane state failed (%d)\n", ret); 852 return ret; 853 } 854 if (!new_plane_state->visible) 855 return 0; 856 857 pipe->multirect_index = DPU_SSPP_RECT_SOLO; 858 pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; 859 r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; 860 r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; 861 r_pipe->sspp = NULL; 862 863 pstate->stage = DPU_STAGE_0 + pstate->base.normalized_zpos; 864 if (pstate->stage >= pdpu->catalog->caps->max_mixer_blendstages) { 865 DPU_ERROR("> %d plane stages assigned\n", 866 pdpu->catalog->caps->max_mixer_blendstages - DPU_STAGE_0); 867 return -EINVAL; 868 } 869 870 pipe_cfg->src_rect = new_plane_state->src; 871 872 /* state->src is 16.16, src_rect is not */ 873 pipe_cfg->src_rect.x1 >>= 16; 874 pipe_cfg->src_rect.x2 >>= 16; 875 pipe_cfg->src_rect.y1 >>= 16; 876 pipe_cfg->src_rect.y2 >>= 16; 877 878 pipe_cfg->dst_rect = new_plane_state->dst; 879 880 fb_rect.x2 = new_plane_state->fb->width; 881 fb_rect.y2 = new_plane_state->fb->height; 882 883 /* Ensure fb size is supported */ 884 if (drm_rect_width(&fb_rect) > MAX_IMG_WIDTH || 885 drm_rect_height(&fb_rect) > MAX_IMG_HEIGHT) { 886 DPU_DEBUG_PLANE(pdpu, "invalid framebuffer " DRM_RECT_FMT "\n", 887 DRM_RECT_ARG(&fb_rect)); 888 return -E2BIG; 889 } 890 891 fmt = to_dpu_format(msm_framebuffer_format(new_plane_state->fb)); 892 893 max_linewidth = pdpu->catalog->caps->max_linewidth; 894 895 if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) { 896 /* 897 * In parallel multirect case only the half of the usual width 898 * is supported for tiled formats. If we are here, we know that 899 * full width is more than max_linewidth, thus each rect is 900 * wider than allowed. 901 */ 902 if (DPU_FORMAT_IS_UBWC(fmt)) { 903 DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u, tiled format\n", 904 DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); 905 return -E2BIG; 906 } 907 908 if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) { 909 DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n", 910 DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); 911 return -E2BIG; 912 } 913 914 if (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect) || 915 drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect) || 916 (!test_bit(DPU_SSPP_SMART_DMA_V1, &pipe->sspp->cap->features) && 917 !test_bit(DPU_SSPP_SMART_DMA_V2, &pipe->sspp->cap->features)) || 918 DPU_FORMAT_IS_YUV(fmt)) { 919 DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u, can't use split source\n", 920 DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); 921 return -E2BIG; 922 } 923 924 /* 925 * Use multirect for wide plane. We do not support dynamic 926 * assignment of SSPPs, so we know the configuration. 927 */ 928 pipe->multirect_index = DPU_SSPP_RECT_0; 929 pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; 930 931 r_pipe->sspp = pipe->sspp; 932 r_pipe->multirect_index = DPU_SSPP_RECT_1; 933 r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL; 934 935 *r_pipe_cfg = *pipe_cfg; 936 pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1; 937 pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1; 938 r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2; 939 r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2; 940 } 941 942 ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt, &crtc_state->adjusted_mode); 943 if (ret) 944 return ret; 945 946 if (r_pipe->sspp) { 947 ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, fmt, 948 &crtc_state->adjusted_mode); 949 if (ret) 950 return ret; 951 } 952 953 supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0; 954 955 if (pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION)) 956 supported_rotations |= DRM_MODE_ROTATE_90; 957 958 rotation = drm_rotation_simplify(new_plane_state->rotation, 959 supported_rotations); 960 961 if ((pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION)) && 962 (rotation & DRM_MODE_ROTATE_90)) { 963 ret = dpu_plane_check_inline_rotation(pdpu, sblk, pipe_cfg->src_rect, fmt); 964 if (ret) 965 return ret; 966 } 967 968 pstate->rotation = rotation; 969 pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state); 970 971 return 0; 972 } 973 974 static void dpu_plane_flush_csc(struct dpu_plane *pdpu, struct dpu_sw_pipe *pipe) 975 { 976 const struct dpu_format *format = 977 to_dpu_format(msm_framebuffer_format(pdpu->base.state->fb)); 978 const struct dpu_csc_cfg *csc_ptr; 979 980 if (!pipe->sspp || !pipe->sspp->ops.setup_csc) 981 return; 982 983 csc_ptr = _dpu_plane_get_csc(pipe, format); 984 if (!csc_ptr) 985 return; 986 987 DPU_DEBUG_PLANE(pdpu, "using 0x%X 0x%X 0x%X...\n", 988 csc_ptr->csc_mv[0], 989 csc_ptr->csc_mv[1], 990 csc_ptr->csc_mv[2]); 991 992 pipe->sspp->ops.setup_csc(pipe->sspp, csc_ptr); 993 994 } 995 996 void dpu_plane_flush(struct drm_plane *plane) 997 { 998 struct dpu_plane *pdpu; 999 struct dpu_plane_state *pstate; 1000 1001 if (!plane || !plane->state) { 1002 DPU_ERROR("invalid plane\n"); 1003 return; 1004 } 1005 1006 pdpu = to_dpu_plane(plane); 1007 pstate = to_dpu_plane_state(plane->state); 1008 1009 /* 1010 * These updates have to be done immediately before the plane flush 1011 * timing, and may not be moved to the atomic_update/mode_set functions. 1012 */ 1013 if (pdpu->is_error) 1014 /* force white frame with 100% alpha pipe output on error */ 1015 _dpu_plane_color_fill(pdpu, 0xFFFFFF, 0xFF); 1016 else if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) 1017 /* force 100% alpha */ 1018 _dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF); 1019 else { 1020 dpu_plane_flush_csc(pdpu, &pstate->pipe); 1021 dpu_plane_flush_csc(pdpu, &pstate->r_pipe); 1022 } 1023 1024 /* flag h/w flush complete */ 1025 if (plane->state) 1026 pstate->pending = false; 1027 } 1028 1029 /** 1030 * dpu_plane_set_error: enable/disable error condition 1031 * @plane: pointer to drm_plane structure 1032 * @error: error value to set 1033 */ 1034 void dpu_plane_set_error(struct drm_plane *plane, bool error) 1035 { 1036 struct dpu_plane *pdpu; 1037 1038 if (!plane) 1039 return; 1040 1041 pdpu = to_dpu_plane(plane); 1042 pdpu->is_error = error; 1043 } 1044 1045 static void dpu_plane_sspp_update_pipe(struct drm_plane *plane, 1046 struct dpu_sw_pipe *pipe, 1047 struct dpu_sw_pipe_cfg *pipe_cfg, 1048 const struct dpu_format *fmt, 1049 int frame_rate, 1050 struct dpu_hw_fmt_layout *layout) 1051 { 1052 uint32_t src_flags; 1053 struct dpu_plane *pdpu = to_dpu_plane(plane); 1054 struct drm_plane_state *state = plane->state; 1055 struct dpu_plane_state *pstate = to_dpu_plane_state(state); 1056 1057 if (layout && pipe->sspp->ops.setup_sourceaddress) { 1058 trace_dpu_plane_set_scanout(pipe, layout); 1059 pipe->sspp->ops.setup_sourceaddress(pipe, layout); 1060 } 1061 1062 /* override for color fill */ 1063 if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) { 1064 _dpu_plane_set_qos_ctrl(plane, pipe, false); 1065 1066 /* skip remaining processing on color fill */ 1067 return; 1068 } 1069 1070 if (pipe->sspp->ops.setup_rects) { 1071 pipe->sspp->ops.setup_rects(pipe, 1072 pipe_cfg); 1073 } 1074 1075 _dpu_plane_setup_scaler(pipe, fmt, false, pipe_cfg, pstate->rotation); 1076 1077 if (pipe->sspp->ops.setup_multirect) 1078 pipe->sspp->ops.setup_multirect( 1079 pipe); 1080 1081 if (pipe->sspp->ops.setup_format) { 1082 unsigned int rotation = pstate->rotation; 1083 1084 src_flags = 0x0; 1085 1086 if (rotation & DRM_MODE_REFLECT_X) 1087 src_flags |= DPU_SSPP_FLIP_LR; 1088 1089 if (rotation & DRM_MODE_REFLECT_Y) 1090 src_flags |= DPU_SSPP_FLIP_UD; 1091 1092 if (rotation & DRM_MODE_ROTATE_90) 1093 src_flags |= DPU_SSPP_ROT_90; 1094 1095 /* update format */ 1096 pipe->sspp->ops.setup_format(pipe, fmt, src_flags); 1097 1098 if (pipe->sspp->ops.setup_cdp) { 1099 const struct dpu_perf_cfg *perf = pdpu->catalog->perf; 1100 1101 pipe->sspp->ops.setup_cdp(pipe, fmt, 1102 perf->cdp_cfg[DPU_PERF_CDP_USAGE_RT].rd_enable); 1103 } 1104 } 1105 1106 _dpu_plane_set_qos_lut(plane, pipe, fmt, pipe_cfg); 1107 1108 if (pipe->sspp->idx != SSPP_CURSOR0 && 1109 pipe->sspp->idx != SSPP_CURSOR1) 1110 _dpu_plane_set_ot_limit(plane, pipe, pipe_cfg, frame_rate); 1111 1112 if (pstate->needs_qos_remap) 1113 _dpu_plane_set_qos_remap(plane, pipe); 1114 } 1115 1116 static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) 1117 { 1118 struct dpu_plane *pdpu = to_dpu_plane(plane); 1119 struct drm_plane_state *state = plane->state; 1120 struct dpu_plane_state *pstate = to_dpu_plane_state(state); 1121 struct dpu_sw_pipe *pipe = &pstate->pipe; 1122 struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; 1123 struct drm_crtc *crtc = state->crtc; 1124 struct drm_framebuffer *fb = state->fb; 1125 bool is_rt_pipe; 1126 const struct dpu_format *fmt = 1127 to_dpu_format(msm_framebuffer_format(fb)); 1128 struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; 1129 struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; 1130 struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); 1131 struct msm_gem_address_space *aspace = kms->base.aspace; 1132 struct dpu_hw_fmt_layout layout; 1133 bool layout_valid = false; 1134 int ret; 1135 1136 ret = dpu_format_populate_layout(aspace, fb, &layout); 1137 if (ret) 1138 DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret); 1139 else 1140 layout_valid = true; 1141 1142 pstate->pending = true; 1143 1144 is_rt_pipe = (dpu_crtc_get_client_type(crtc) != NRT_CLIENT); 1145 pstate->needs_qos_remap |= (is_rt_pipe != pdpu->is_rt_pipe); 1146 pdpu->is_rt_pipe = is_rt_pipe; 1147 1148 DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FP_FMT "->crtc%u " DRM_RECT_FMT 1149 ", %4.4s ubwc %d\n", fb->base.id, DRM_RECT_FP_ARG(&state->src), 1150 crtc->base.id, DRM_RECT_ARG(&state->dst), 1151 (char *)&fmt->base.pixel_format, DPU_FORMAT_IS_UBWC(fmt)); 1152 1153 dpu_plane_sspp_update_pipe(plane, pipe, pipe_cfg, fmt, 1154 drm_mode_vrefresh(&crtc->mode), 1155 layout_valid ? &layout : NULL); 1156 1157 if (r_pipe->sspp) { 1158 dpu_plane_sspp_update_pipe(plane, r_pipe, r_pipe_cfg, fmt, 1159 drm_mode_vrefresh(&crtc->mode), 1160 layout_valid ? &layout : NULL); 1161 } 1162 1163 if (pstate->needs_qos_remap) 1164 pstate->needs_qos_remap = false; 1165 1166 pstate->plane_fetch_bw = _dpu_plane_calc_bw(pdpu->catalog, fmt, 1167 &crtc->mode, pipe_cfg); 1168 1169 pstate->plane_clk = _dpu_plane_calc_clk(&crtc->mode, pipe_cfg); 1170 1171 if (r_pipe->sspp) { 1172 pstate->plane_fetch_bw += _dpu_plane_calc_bw(pdpu->catalog, fmt, &crtc->mode, r_pipe_cfg); 1173 1174 pstate->plane_clk = max(pstate->plane_clk, _dpu_plane_calc_clk(&crtc->mode, r_pipe_cfg)); 1175 } 1176 } 1177 1178 static void _dpu_plane_atomic_disable(struct drm_plane *plane) 1179 { 1180 struct drm_plane_state *state = plane->state; 1181 struct dpu_plane_state *pstate = to_dpu_plane_state(state); 1182 struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; 1183 1184 trace_dpu_plane_disable(DRMID(plane), false, 1185 pstate->pipe.multirect_mode); 1186 1187 if (r_pipe->sspp) { 1188 r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; 1189 r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; 1190 1191 if (r_pipe->sspp->ops.setup_multirect) 1192 r_pipe->sspp->ops.setup_multirect(r_pipe); 1193 } 1194 1195 pstate->pending = true; 1196 } 1197 1198 static void dpu_plane_atomic_update(struct drm_plane *plane, 1199 struct drm_atomic_state *state) 1200 { 1201 struct dpu_plane *pdpu = to_dpu_plane(plane); 1202 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 1203 plane); 1204 1205 pdpu->is_error = false; 1206 1207 DPU_DEBUG_PLANE(pdpu, "\n"); 1208 1209 if (!new_state->visible) { 1210 _dpu_plane_atomic_disable(plane); 1211 } else { 1212 dpu_plane_sspp_atomic_update(plane); 1213 } 1214 } 1215 1216 static void dpu_plane_destroy(struct drm_plane *plane) 1217 { 1218 struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL; 1219 struct dpu_plane_state *pstate; 1220 1221 DPU_DEBUG_PLANE(pdpu, "\n"); 1222 1223 if (pdpu) { 1224 pstate = to_dpu_plane_state(plane->state); 1225 _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, false); 1226 1227 if (pstate->r_pipe.sspp) 1228 _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, false); 1229 1230 mutex_destroy(&pdpu->lock); 1231 1232 /* this will destroy the states as well */ 1233 drm_plane_cleanup(plane); 1234 1235 kfree(pdpu); 1236 } 1237 } 1238 1239 static void dpu_plane_destroy_state(struct drm_plane *plane, 1240 struct drm_plane_state *state) 1241 { 1242 __drm_atomic_helper_plane_destroy_state(state); 1243 kfree(to_dpu_plane_state(state)); 1244 } 1245 1246 static struct drm_plane_state * 1247 dpu_plane_duplicate_state(struct drm_plane *plane) 1248 { 1249 struct dpu_plane *pdpu; 1250 struct dpu_plane_state *pstate; 1251 struct dpu_plane_state *old_state; 1252 1253 if (!plane) { 1254 DPU_ERROR("invalid plane\n"); 1255 return NULL; 1256 } else if (!plane->state) { 1257 DPU_ERROR("invalid plane state\n"); 1258 return NULL; 1259 } 1260 1261 old_state = to_dpu_plane_state(plane->state); 1262 pdpu = to_dpu_plane(plane); 1263 pstate = kmemdup(old_state, sizeof(*old_state), GFP_KERNEL); 1264 if (!pstate) { 1265 DPU_ERROR_PLANE(pdpu, "failed to allocate state\n"); 1266 return NULL; 1267 } 1268 1269 DPU_DEBUG_PLANE(pdpu, "\n"); 1270 1271 pstate->pending = false; 1272 1273 __drm_atomic_helper_plane_duplicate_state(plane, &pstate->base); 1274 1275 return &pstate->base; 1276 } 1277 1278 static const char * const multirect_mode_name[] = { 1279 [DPU_SSPP_MULTIRECT_NONE] = "none", 1280 [DPU_SSPP_MULTIRECT_PARALLEL] = "parallel", 1281 [DPU_SSPP_MULTIRECT_TIME_MX] = "time_mx", 1282 }; 1283 1284 static const char * const multirect_index_name[] = { 1285 [DPU_SSPP_RECT_SOLO] = "solo", 1286 [DPU_SSPP_RECT_0] = "rect_0", 1287 [DPU_SSPP_RECT_1] = "rect_1", 1288 }; 1289 1290 static const char *dpu_get_multirect_mode(enum dpu_sspp_multirect_mode mode) 1291 { 1292 if (WARN_ON(mode >= ARRAY_SIZE(multirect_mode_name))) 1293 return "unknown"; 1294 1295 return multirect_mode_name[mode]; 1296 } 1297 1298 static const char *dpu_get_multirect_index(enum dpu_sspp_multirect_index index) 1299 { 1300 if (WARN_ON(index >= ARRAY_SIZE(multirect_index_name))) 1301 return "unknown"; 1302 1303 return multirect_index_name[index]; 1304 } 1305 1306 static void dpu_plane_atomic_print_state(struct drm_printer *p, 1307 const struct drm_plane_state *state) 1308 { 1309 const struct dpu_plane_state *pstate = to_dpu_plane_state(state); 1310 const struct dpu_sw_pipe *pipe = &pstate->pipe; 1311 const struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg; 1312 const struct dpu_sw_pipe *r_pipe = &pstate->r_pipe; 1313 const struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg; 1314 1315 drm_printf(p, "\tstage=%d\n", pstate->stage); 1316 1317 drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name); 1318 drm_printf(p, "\tmultirect_mode[0]=%s\n", dpu_get_multirect_mode(pipe->multirect_mode)); 1319 drm_printf(p, "\tmultirect_index[0]=%s\n", 1320 dpu_get_multirect_index(pipe->multirect_index)); 1321 drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect)); 1322 drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect)); 1323 1324 if (r_pipe->sspp) { 1325 drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name); 1326 drm_printf(p, "\tmultirect_mode[1]=%s\n", 1327 dpu_get_multirect_mode(r_pipe->multirect_mode)); 1328 drm_printf(p, "\tmultirect_index[1]=%s\n", 1329 dpu_get_multirect_index(r_pipe->multirect_index)); 1330 drm_printf(p, "\tsrc[1]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&r_pipe_cfg->src_rect)); 1331 drm_printf(p, "\tdst[1]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&r_pipe_cfg->dst_rect)); 1332 } 1333 } 1334 1335 static void dpu_plane_reset(struct drm_plane *plane) 1336 { 1337 struct dpu_plane *pdpu; 1338 struct dpu_plane_state *pstate; 1339 struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); 1340 1341 if (!plane) { 1342 DPU_ERROR("invalid plane\n"); 1343 return; 1344 } 1345 1346 pdpu = to_dpu_plane(plane); 1347 DPU_DEBUG_PLANE(pdpu, "\n"); 1348 1349 /* remove previous state, if present */ 1350 if (plane->state) { 1351 dpu_plane_destroy_state(plane, plane->state); 1352 plane->state = NULL; 1353 } 1354 1355 pstate = kzalloc(sizeof(*pstate), GFP_KERNEL); 1356 if (!pstate) { 1357 DPU_ERROR_PLANE(pdpu, "failed to allocate state\n"); 1358 return; 1359 } 1360 1361 /* 1362 * Set the SSPP here until we have proper virtualized DPU planes. 1363 * This is the place where the state is allocated, so fill it fully. 1364 */ 1365 pstate->pipe.sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe); 1366 pstate->pipe.multirect_index = DPU_SSPP_RECT_SOLO; 1367 pstate->pipe.multirect_mode = DPU_SSPP_MULTIRECT_NONE; 1368 1369 pstate->r_pipe.sspp = NULL; 1370 1371 __drm_atomic_helper_plane_reset(plane, &pstate->base); 1372 } 1373 1374 #ifdef CONFIG_DEBUG_FS 1375 void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) 1376 { 1377 struct dpu_plane *pdpu = to_dpu_plane(plane); 1378 struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state); 1379 struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); 1380 1381 if (!pdpu->is_rt_pipe) 1382 return; 1383 1384 pm_runtime_get_sync(&dpu_kms->pdev->dev); 1385 _dpu_plane_set_qos_ctrl(plane, &pstate->pipe, enable); 1386 if (pstate->r_pipe.sspp) 1387 _dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, enable); 1388 pm_runtime_put_sync(&dpu_kms->pdev->dev); 1389 } 1390 #endif 1391 1392 static bool dpu_plane_format_mod_supported(struct drm_plane *plane, 1393 uint32_t format, uint64_t modifier) 1394 { 1395 if (modifier == DRM_FORMAT_MOD_LINEAR) 1396 return true; 1397 1398 if (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) 1399 return dpu_find_format(format, qcom_compressed_supported_formats, 1400 ARRAY_SIZE(qcom_compressed_supported_formats)); 1401 1402 return false; 1403 } 1404 1405 static const struct drm_plane_funcs dpu_plane_funcs = { 1406 .update_plane = drm_atomic_helper_update_plane, 1407 .disable_plane = drm_atomic_helper_disable_plane, 1408 .destroy = dpu_plane_destroy, 1409 .reset = dpu_plane_reset, 1410 .atomic_duplicate_state = dpu_plane_duplicate_state, 1411 .atomic_destroy_state = dpu_plane_destroy_state, 1412 .atomic_print_state = dpu_plane_atomic_print_state, 1413 .format_mod_supported = dpu_plane_format_mod_supported, 1414 }; 1415 1416 static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = { 1417 .prepare_fb = dpu_plane_prepare_fb, 1418 .cleanup_fb = dpu_plane_cleanup_fb, 1419 .atomic_check = dpu_plane_atomic_check, 1420 .atomic_update = dpu_plane_atomic_update, 1421 }; 1422 1423 /* initialize plane */ 1424 struct drm_plane *dpu_plane_init(struct drm_device *dev, 1425 uint32_t pipe, enum drm_plane_type type, 1426 unsigned long possible_crtcs) 1427 { 1428 struct drm_plane *plane = NULL; 1429 const uint32_t *format_list; 1430 struct dpu_plane *pdpu; 1431 struct msm_drm_private *priv = dev->dev_private; 1432 struct dpu_kms *kms = to_dpu_kms(priv->kms); 1433 struct dpu_hw_sspp *pipe_hw; 1434 uint32_t num_formats; 1435 uint32_t supported_rotations; 1436 int ret = -EINVAL; 1437 1438 /* create and zero local structure */ 1439 pdpu = kzalloc(sizeof(*pdpu), GFP_KERNEL); 1440 if (!pdpu) { 1441 DPU_ERROR("[%u]failed to allocate local plane struct\n", pipe); 1442 ret = -ENOMEM; 1443 return ERR_PTR(ret); 1444 } 1445 1446 /* cache local stuff for later */ 1447 plane = &pdpu->base; 1448 pdpu->pipe = pipe; 1449 1450 /* initialize underlying h/w driver */ 1451 pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe); 1452 if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) { 1453 DPU_ERROR("[%u]SSPP is invalid\n", pipe); 1454 goto clean_plane; 1455 } 1456 1457 format_list = pipe_hw->cap->sblk->format_list; 1458 num_formats = pipe_hw->cap->sblk->num_formats; 1459 1460 ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs, 1461 format_list, num_formats, 1462 supported_format_modifiers, type, NULL); 1463 if (ret) 1464 goto clean_plane; 1465 1466 pdpu->catalog = kms->catalog; 1467 1468 ret = drm_plane_create_zpos_property(plane, 0, 0, DPU_ZPOS_MAX); 1469 if (ret) 1470 DPU_ERROR("failed to install zpos property, rc = %d\n", ret); 1471 1472 drm_plane_create_alpha_property(plane); 1473 drm_plane_create_blend_mode_property(plane, 1474 BIT(DRM_MODE_BLEND_PIXEL_NONE) | 1475 BIT(DRM_MODE_BLEND_PREMULTI) | 1476 BIT(DRM_MODE_BLEND_COVERAGE)); 1477 1478 supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; 1479 1480 if (pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION)) 1481 supported_rotations |= DRM_MODE_ROTATE_MASK; 1482 1483 drm_plane_create_rotation_property(plane, 1484 DRM_MODE_ROTATE_0, supported_rotations); 1485 1486 drm_plane_enable_fb_damage_clips(plane); 1487 1488 /* success! finalize initialization */ 1489 drm_plane_helper_add(plane, &dpu_plane_helper_funcs); 1490 1491 mutex_init(&pdpu->lock); 1492 1493 DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name, 1494 pipe, plane->base.id); 1495 return plane; 1496 1497 clean_plane: 1498 kfree(pdpu); 1499 return ERR_PTR(ret); 1500 } 1501