2 * Copyright (C) 2014-2018 The Linux Foundation. All rights reserved.
3 * Copyright (C) 2013 Red Hat
4 * Author: Rob Clark <robdclark@gmail.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
19 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
21 #include <linux/debugfs.h>
22 #include <linux/dma-buf.h>
24 #include <drm/drm_atomic_uapi.h>
28 #include "dpu_formats.h"
29 #include "dpu_hw_sspp.h"
30 #include "dpu_hw_catalog_format.h"
31 #include "dpu_trace.h"
34 #include "dpu_plane.h"
36 #define DPU_DEBUG_PLANE(pl, fmt, ...) DPU_DEBUG("plane%d " fmt,\
37 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
39 #define DPU_ERROR_PLANE(pl, fmt, ...) DPU_ERROR("plane%d " fmt,\
40 (pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
42 #define DECIMATED_DIMENSION(dim, deci) (((dim) + ((1 << (deci)) - 1)) >> (deci))
43 #define PHASE_STEP_SHIFT 21
44 #define PHASE_STEP_UNIT_SCALE ((int) (1 << PHASE_STEP_SHIFT))
45 #define PHASE_RESIDUAL 15
47 #define SHARP_STRENGTH_DEFAULT 32
48 #define SHARP_EDGE_THR_DEFAULT 112
49 #define SHARP_SMOOTH_THR_DEFAULT 8
50 #define SHARP_NOISE_THR_DEFAULT 2
52 #define DPU_NAME_SIZE 12
54 #define DPU_PLANE_COLOR_FILL_FLAG BIT(31)
55 #define DPU_ZPOS_MAX 255
57 /* multirect rect index */
64 #define DPU_QSEED3_DEFAULT_PRELOAD_H 0x4
65 #define DPU_QSEED3_DEFAULT_PRELOAD_V 0x3
67 #define DEFAULT_REFRESH_RATE 60
70 * enum dpu_plane_qos - Different qos configurations for each pipe
72 * @DPU_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
73 * @DPU_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
74 * this configuration is mutually exclusive from VBLANK_CTRL.
75 * @DPU_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
78 DPU_PLANE_QOS_VBLANK_CTRL
= BIT(0),
79 DPU_PLANE_QOS_VBLANK_AMORTIZE
= BIT(1),
80 DPU_PLANE_QOS_PANIC_CTRL
= BIT(2),
84 * struct dpu_plane - local dpu plane structure
85 * @aspace: address space pointer
86 * @csc_ptr: Points to dpu_csc_cfg structure to use for current
87 * @mplane_list: List of multirect planes of the same pipe
88 * @catalog: Points to dpu catalog structure
89 * @revalidate: force revalidation of all the plane properties
92 struct drm_plane base
;
97 uint32_t features
; /* capabilities from catalog */
101 struct dpu_hw_pipe
*pipe_hw
;
102 struct dpu_hw_pipe_cfg pipe_cfg
;
103 struct dpu_hw_pipe_qos_cfg pipe_qos_cfg
;
108 struct list_head mplane_list
;
109 struct dpu_mdss_cfg
*catalog
;
111 struct dpu_csc_cfg
*csc_ptr
;
113 const struct dpu_sspp_sub_blks
*pipe_sblk
;
114 char pipe_name
[DPU_NAME_SIZE
];
116 /* debugfs related stuff */
117 struct dentry
*debugfs_root
;
118 struct dpu_debugfs_regset32 debugfs_src
;
119 struct dpu_debugfs_regset32 debugfs_scaler
;
120 struct dpu_debugfs_regset32 debugfs_csc
;
121 bool debugfs_default_scale
;
124 #define to_dpu_plane(x) container_of(x, struct dpu_plane, base)
126 static struct dpu_kms
*_dpu_plane_get_kms(struct drm_plane
*plane
)
128 struct msm_drm_private
*priv
= plane
->dev
->dev_private
;
130 return to_dpu_kms(priv
->kms
);
134 * _dpu_plane_calc_fill_level - calculate fill level of the given source format
135 * @plane: Pointer to drm plane
136 * @fmt: Pointer to source buffer format
137 * @src_wdith: width of source buffer
138 * Return: fill level corresponding to the source buffer/format or 0 if error
140 static int _dpu_plane_calc_fill_level(struct drm_plane
*plane
,
141 const struct dpu_format
*fmt
, u32 src_width
)
143 struct dpu_plane
*pdpu
, *tmp
;
144 struct dpu_plane_state
*pstate
;
148 if (!fmt
|| !plane
->state
|| !src_width
|| !fmt
->bpp
) {
149 DPU_ERROR("invalid arguments\n");
153 pdpu
= to_dpu_plane(plane
);
154 pstate
= to_dpu_plane_state(plane
->state
);
155 fixed_buff_size
= pdpu
->pipe_sblk
->common
->pixel_ram_size
;
157 list_for_each_entry(tmp
, &pdpu
->mplane_list
, mplane_list
) {
158 if (!tmp
->base
.state
->visible
)
160 DPU_DEBUG("plane%d/%d src_width:%d/%d\n",
161 pdpu
->base
.base
.id
, tmp
->base
.base
.id
,
163 drm_rect_width(&tmp
->pipe_cfg
.src_rect
));
164 src_width
= max_t(u32
, src_width
,
165 drm_rect_width(&tmp
->pipe_cfg
.src_rect
));
168 if (fmt
->fetch_planes
== DPU_PLANE_PSEUDO_PLANAR
) {
169 if (fmt
->chroma_sample
== DPU_CHROMA_420
) {
171 total_fl
= (fixed_buff_size
/ 2) /
172 ((src_width
+ 32) * fmt
->bpp
);
175 total_fl
= (fixed_buff_size
/ 2) * 2 /
176 ((src_width
+ 32) * fmt
->bpp
);
179 if (pstate
->multirect_mode
== DPU_SSPP_MULTIRECT_PARALLEL
) {
180 total_fl
= (fixed_buff_size
/ 2) * 2 /
181 ((src_width
+ 32) * fmt
->bpp
);
183 total_fl
= (fixed_buff_size
) * 2 /
184 ((src_width
+ 32) * fmt
->bpp
);
188 DPU_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u fl:%u\n",
189 plane
->base
.id
, pdpu
->pipe
- SSPP_VIG0
,
190 (char *)&fmt
->base
.pixel_format
,
191 src_width
, total_fl
);
197 * _dpu_plane_get_qos_lut - get LUT mapping based on fill level
198 * @tbl: Pointer to LUT table
199 * @total_fl: fill level
200 * Return: LUT setting corresponding to the fill level
202 static u64
_dpu_plane_get_qos_lut(const struct dpu_qos_lut_tbl
*tbl
,
207 if (!tbl
|| !tbl
->nentry
|| !tbl
->entries
)
210 for (i
= 0; i
< tbl
->nentry
; i
++)
211 if (total_fl
<= tbl
->entries
[i
].fl
)
212 return tbl
->entries
[i
].lut
;
214 /* if last fl is zero, use as default */
215 if (!tbl
->entries
[i
-1].fl
)
216 return tbl
->entries
[i
-1].lut
;
222 * _dpu_plane_set_qos_lut - set QoS LUT of the given plane
223 * @plane: Pointer to drm plane
224 * @fb: Pointer to framebuffer associated with the given plane
226 static void _dpu_plane_set_qos_lut(struct drm_plane
*plane
,
227 struct drm_framebuffer
*fb
)
229 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
230 const struct dpu_format
*fmt
= NULL
;
232 u32 total_fl
= 0, lut_usage
;
234 if (!pdpu
->is_rt_pipe
) {
235 lut_usage
= DPU_QOS_LUT_USAGE_NRT
;
237 fmt
= dpu_get_dpu_format_ext(
240 total_fl
= _dpu_plane_calc_fill_level(plane
, fmt
,
241 drm_rect_width(&pdpu
->pipe_cfg
.src_rect
));
243 if (fmt
&& DPU_FORMAT_IS_LINEAR(fmt
))
244 lut_usage
= DPU_QOS_LUT_USAGE_LINEAR
;
246 lut_usage
= DPU_QOS_LUT_USAGE_MACROTILE
;
249 qos_lut
= _dpu_plane_get_qos_lut(
250 &pdpu
->catalog
->perf
.qos_lut_tbl
[lut_usage
], total_fl
);
252 pdpu
->pipe_qos_cfg
.creq_lut
= qos_lut
;
254 trace_dpu_perf_set_qos_luts(pdpu
->pipe
- SSPP_VIG0
,
255 (fmt
) ? fmt
->base
.pixel_format
: 0,
256 pdpu
->is_rt_pipe
, total_fl
, qos_lut
, lut_usage
);
258 DPU_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
260 pdpu
->pipe
- SSPP_VIG0
,
261 fmt
? (char *)&fmt
->base
.pixel_format
: NULL
,
262 pdpu
->is_rt_pipe
, total_fl
, qos_lut
);
264 pdpu
->pipe_hw
->ops
.setup_creq_lut(pdpu
->pipe_hw
, &pdpu
->pipe_qos_cfg
);
268 * _dpu_plane_set_panic_lut - set danger/safe LUT of the given plane
269 * @plane: Pointer to drm plane
270 * @fb: Pointer to framebuffer associated with the given plane
272 static void _dpu_plane_set_danger_lut(struct drm_plane
*plane
,
273 struct drm_framebuffer
*fb
)
275 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
276 const struct dpu_format
*fmt
= NULL
;
277 u32 danger_lut
, safe_lut
;
279 if (!pdpu
->is_rt_pipe
) {
280 danger_lut
= pdpu
->catalog
->perf
.danger_lut_tbl
281 [DPU_QOS_LUT_USAGE_NRT
];
282 safe_lut
= pdpu
->catalog
->perf
.safe_lut_tbl
283 [DPU_QOS_LUT_USAGE_NRT
];
285 fmt
= dpu_get_dpu_format_ext(
289 if (fmt
&& DPU_FORMAT_IS_LINEAR(fmt
)) {
290 danger_lut
= pdpu
->catalog
->perf
.danger_lut_tbl
291 [DPU_QOS_LUT_USAGE_LINEAR
];
292 safe_lut
= pdpu
->catalog
->perf
.safe_lut_tbl
293 [DPU_QOS_LUT_USAGE_LINEAR
];
295 danger_lut
= pdpu
->catalog
->perf
.danger_lut_tbl
296 [DPU_QOS_LUT_USAGE_MACROTILE
];
297 safe_lut
= pdpu
->catalog
->perf
.safe_lut_tbl
298 [DPU_QOS_LUT_USAGE_MACROTILE
];
302 pdpu
->pipe_qos_cfg
.danger_lut
= danger_lut
;
303 pdpu
->pipe_qos_cfg
.safe_lut
= safe_lut
;
305 trace_dpu_perf_set_danger_luts(pdpu
->pipe
- SSPP_VIG0
,
306 (fmt
) ? fmt
->base
.pixel_format
: 0,
307 (fmt
) ? fmt
->fetch_mode
: 0,
308 pdpu
->pipe_qos_cfg
.danger_lut
,
309 pdpu
->pipe_qos_cfg
.safe_lut
);
311 DPU_DEBUG("plane%u: pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
313 pdpu
->pipe
- SSPP_VIG0
,
314 fmt
? (char *)&fmt
->base
.pixel_format
: NULL
,
315 fmt
? fmt
->fetch_mode
: -1,
316 pdpu
->pipe_qos_cfg
.danger_lut
,
317 pdpu
->pipe_qos_cfg
.safe_lut
);
319 pdpu
->pipe_hw
->ops
.setup_danger_safe_lut(pdpu
->pipe_hw
,
320 &pdpu
->pipe_qos_cfg
);
324 * _dpu_plane_set_qos_ctrl - set QoS control of the given plane
325 * @plane: Pointer to drm plane
326 * @enable: true to enable QoS control
327 * @flags: QoS control mode (enum dpu_plane_qos)
329 static void _dpu_plane_set_qos_ctrl(struct drm_plane
*plane
,
330 bool enable
, u32 flags
)
332 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
334 if (flags
& DPU_PLANE_QOS_VBLANK_CTRL
) {
335 pdpu
->pipe_qos_cfg
.creq_vblank
= pdpu
->pipe_sblk
->creq_vblank
;
336 pdpu
->pipe_qos_cfg
.danger_vblank
=
337 pdpu
->pipe_sblk
->danger_vblank
;
338 pdpu
->pipe_qos_cfg
.vblank_en
= enable
;
341 if (flags
& DPU_PLANE_QOS_VBLANK_AMORTIZE
) {
342 /* this feature overrules previous VBLANK_CTRL */
343 pdpu
->pipe_qos_cfg
.vblank_en
= false;
344 pdpu
->pipe_qos_cfg
.creq_vblank
= 0; /* clear vblank bits */
347 if (flags
& DPU_PLANE_QOS_PANIC_CTRL
)
348 pdpu
->pipe_qos_cfg
.danger_safe_en
= enable
;
350 if (!pdpu
->is_rt_pipe
) {
351 pdpu
->pipe_qos_cfg
.vblank_en
= false;
352 pdpu
->pipe_qos_cfg
.danger_safe_en
= false;
355 DPU_DEBUG("plane%u: pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n",
357 pdpu
->pipe
- SSPP_VIG0
,
358 pdpu
->pipe_qos_cfg
.danger_safe_en
,
359 pdpu
->pipe_qos_cfg
.vblank_en
,
360 pdpu
->pipe_qos_cfg
.creq_vblank
,
361 pdpu
->pipe_qos_cfg
.danger_vblank
,
364 pdpu
->pipe_hw
->ops
.setup_qos_ctrl(pdpu
->pipe_hw
,
365 &pdpu
->pipe_qos_cfg
);
368 static void dpu_plane_danger_signal_ctrl(struct drm_plane
*plane
, bool enable
)
370 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
371 struct dpu_kms
*dpu_kms
= _dpu_plane_get_kms(plane
);
373 if (!pdpu
->is_rt_pipe
)
376 pm_runtime_get_sync(&dpu_kms
->pdev
->dev
);
377 _dpu_plane_set_qos_ctrl(plane
, enable
, DPU_PLANE_QOS_PANIC_CTRL
);
378 pm_runtime_put_sync(&dpu_kms
->pdev
->dev
);
382 * _dpu_plane_set_ot_limit - set OT limit for the given plane
383 * @plane: Pointer to drm plane
384 * @crtc: Pointer to drm crtc
386 static void _dpu_plane_set_ot_limit(struct drm_plane
*plane
,
387 struct drm_crtc
*crtc
)
389 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
390 struct dpu_vbif_set_ot_params ot_params
;
391 struct dpu_kms
*dpu_kms
= _dpu_plane_get_kms(plane
);
393 memset(&ot_params
, 0, sizeof(ot_params
));
394 ot_params
.xin_id
= pdpu
->pipe_hw
->cap
->xin_id
;
395 ot_params
.num
= pdpu
->pipe_hw
->idx
- SSPP_NONE
;
396 ot_params
.width
= drm_rect_width(&pdpu
->pipe_cfg
.src_rect
);
397 ot_params
.height
= drm_rect_height(&pdpu
->pipe_cfg
.src_rect
);
398 ot_params
.is_wfd
= !pdpu
->is_rt_pipe
;
399 ot_params
.frame_rate
= crtc
->mode
.vrefresh
;
400 ot_params
.vbif_idx
= VBIF_RT
;
401 ot_params
.clk_ctrl
= pdpu
->pipe_hw
->cap
->clk_ctrl
;
404 dpu_vbif_set_ot_limit(dpu_kms
, &ot_params
);
408 * _dpu_plane_set_vbif_qos - set vbif QoS for the given plane
409 * @plane: Pointer to drm plane
411 static void _dpu_plane_set_qos_remap(struct drm_plane
*plane
)
413 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
414 struct dpu_vbif_set_qos_params qos_params
;
415 struct dpu_kms
*dpu_kms
= _dpu_plane_get_kms(plane
);
417 memset(&qos_params
, 0, sizeof(qos_params
));
418 qos_params
.vbif_idx
= VBIF_RT
;
419 qos_params
.clk_ctrl
= pdpu
->pipe_hw
->cap
->clk_ctrl
;
420 qos_params
.xin_id
= pdpu
->pipe_hw
->cap
->xin_id
;
421 qos_params
.num
= pdpu
->pipe_hw
->idx
- SSPP_VIG0
;
422 qos_params
.is_rt
= pdpu
->is_rt_pipe
;
424 DPU_DEBUG("plane%d pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n",
425 plane
->base
.id
, qos_params
.num
,
427 qos_params
.xin_id
, qos_params
.is_rt
,
428 qos_params
.clk_ctrl
);
430 dpu_vbif_set_qos_remap(dpu_kms
, &qos_params
);
433 static void _dpu_plane_set_scanout(struct drm_plane
*plane
,
434 struct dpu_plane_state
*pstate
,
435 struct dpu_hw_pipe_cfg
*pipe_cfg
,
436 struct drm_framebuffer
*fb
)
438 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
439 struct dpu_kms
*kms
= _dpu_plane_get_kms(&pdpu
->base
);
440 struct msm_gem_address_space
*aspace
= kms
->base
.aspace
;
443 ret
= dpu_format_populate_layout(aspace
, fb
, &pipe_cfg
->layout
);
445 DPU_DEBUG_PLANE(pdpu
, "not updating same src addrs\n");
447 DPU_ERROR_PLANE(pdpu
, "failed to get format layout, %d\n", ret
);
448 else if (pdpu
->pipe_hw
->ops
.setup_sourceaddress
) {
449 trace_dpu_plane_set_scanout(pdpu
->pipe_hw
->idx
,
451 pstate
->multirect_index
);
452 pdpu
->pipe_hw
->ops
.setup_sourceaddress(pdpu
->pipe_hw
, pipe_cfg
,
453 pstate
->multirect_index
);
457 static void _dpu_plane_setup_scaler3(struct dpu_plane
*pdpu
,
458 struct dpu_plane_state
*pstate
,
459 uint32_t src_w
, uint32_t src_h
, uint32_t dst_w
, uint32_t dst_h
,
460 struct dpu_hw_scaler3_cfg
*scale_cfg
,
461 const struct dpu_format
*fmt
,
462 uint32_t chroma_subsmpl_h
, uint32_t chroma_subsmpl_v
)
466 memset(scale_cfg
, 0, sizeof(*scale_cfg
));
467 memset(&pstate
->pixel_ext
, 0, sizeof(struct dpu_hw_pixel_ext
));
469 scale_cfg
->phase_step_x
[DPU_SSPP_COMP_0
] =
470 mult_frac((1 << PHASE_STEP_SHIFT
), src_w
, dst_w
);
471 scale_cfg
->phase_step_y
[DPU_SSPP_COMP_0
] =
472 mult_frac((1 << PHASE_STEP_SHIFT
), src_h
, dst_h
);
475 scale_cfg
->phase_step_y
[DPU_SSPP_COMP_1_2
] =
476 scale_cfg
->phase_step_y
[DPU_SSPP_COMP_0
] / chroma_subsmpl_v
;
477 scale_cfg
->phase_step_x
[DPU_SSPP_COMP_1_2
] =
478 scale_cfg
->phase_step_x
[DPU_SSPP_COMP_0
] / chroma_subsmpl_h
;
480 scale_cfg
->phase_step_x
[DPU_SSPP_COMP_2
] =
481 scale_cfg
->phase_step_x
[DPU_SSPP_COMP_1_2
];
482 scale_cfg
->phase_step_y
[DPU_SSPP_COMP_2
] =
483 scale_cfg
->phase_step_y
[DPU_SSPP_COMP_1_2
];
485 scale_cfg
->phase_step_x
[DPU_SSPP_COMP_3
] =
486 scale_cfg
->phase_step_x
[DPU_SSPP_COMP_0
];
487 scale_cfg
->phase_step_y
[DPU_SSPP_COMP_3
] =
488 scale_cfg
->phase_step_y
[DPU_SSPP_COMP_0
];
490 for (i
= 0; i
< DPU_MAX_PLANES
; i
++) {
491 scale_cfg
->src_width
[i
] = src_w
;
492 scale_cfg
->src_height
[i
] = src_h
;
493 if (i
== DPU_SSPP_COMP_1_2
|| i
== DPU_SSPP_COMP_2
) {
494 scale_cfg
->src_width
[i
] /= chroma_subsmpl_h
;
495 scale_cfg
->src_height
[i
] /= chroma_subsmpl_v
;
497 scale_cfg
->preload_x
[i
] = DPU_QSEED3_DEFAULT_PRELOAD_H
;
498 scale_cfg
->preload_y
[i
] = DPU_QSEED3_DEFAULT_PRELOAD_V
;
499 pstate
->pixel_ext
.num_ext_pxls_top
[i
] =
500 scale_cfg
->src_height
[i
];
501 pstate
->pixel_ext
.num_ext_pxls_left
[i
] =
502 scale_cfg
->src_width
[i
];
504 if (!(DPU_FORMAT_IS_YUV(fmt
)) && (src_h
== dst_h
)
508 scale_cfg
->dst_width
= dst_w
;
509 scale_cfg
->dst_height
= dst_h
;
510 scale_cfg
->y_rgb_filter_cfg
= DPU_SCALE_BIL
;
511 scale_cfg
->uv_filter_cfg
= DPU_SCALE_BIL
;
512 scale_cfg
->alpha_filter_cfg
= DPU_SCALE_ALPHA_BIL
;
513 scale_cfg
->lut_flag
= 0;
514 scale_cfg
->blend_cfg
= 1;
515 scale_cfg
->enable
= 1;
518 static void _dpu_plane_setup_csc(struct dpu_plane
*pdpu
)
520 static const struct dpu_csc_cfg dpu_csc_YUV2RGB_601L
= {
523 0x00012A00, 0x00000000, 0x00019880,
524 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
525 0x00012A00, 0x00020480, 0x00000000,
528 { 0xfff0, 0xff80, 0xff80,},
531 { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
532 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
534 static const struct dpu_csc_cfg dpu_csc10_YUV2RGB_601L
= {
537 0x00012A00, 0x00000000, 0x00019880,
538 0x00012A00, 0xFFFF9B80, 0xFFFF3000,
539 0x00012A00, 0x00020480, 0x00000000,
542 { 0xffc0, 0xfe00, 0xfe00,},
545 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
546 { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,},
550 DPU_ERROR("invalid plane\n");
554 if (BIT(DPU_SSPP_CSC_10BIT
) & pdpu
->features
)
555 pdpu
->csc_ptr
= (struct dpu_csc_cfg
*)&dpu_csc10_YUV2RGB_601L
;
557 pdpu
->csc_ptr
= (struct dpu_csc_cfg
*)&dpu_csc_YUV2RGB_601L
;
559 DPU_DEBUG_PLANE(pdpu
, "using 0x%X 0x%X 0x%X...\n",
560 pdpu
->csc_ptr
->csc_mv
[0],
561 pdpu
->csc_ptr
->csc_mv
[1],
562 pdpu
->csc_ptr
->csc_mv
[2]);
565 static void _dpu_plane_setup_scaler(struct dpu_plane
*pdpu
,
566 struct dpu_plane_state
*pstate
,
567 const struct dpu_format
*fmt
, bool color_fill
)
569 uint32_t chroma_subsmpl_h
, chroma_subsmpl_v
;
571 /* don't chroma subsample if decimating */
573 drm_format_horz_chroma_subsampling(fmt
->base
.pixel_format
);
575 drm_format_vert_chroma_subsampling(fmt
->base
.pixel_format
);
577 /* update scaler. calculate default config for QSEED3 */
578 _dpu_plane_setup_scaler3(pdpu
, pstate
,
579 drm_rect_width(&pdpu
->pipe_cfg
.src_rect
),
580 drm_rect_height(&pdpu
->pipe_cfg
.src_rect
),
581 drm_rect_width(&pdpu
->pipe_cfg
.dst_rect
),
582 drm_rect_height(&pdpu
->pipe_cfg
.dst_rect
),
583 &pstate
->scaler3_cfg
, fmt
,
584 chroma_subsmpl_h
, chroma_subsmpl_v
);
588 * _dpu_plane_color_fill - enables color fill on plane
589 * @pdpu: Pointer to DPU plane object
590 * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
591 * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
592 * Returns: 0 on success
594 static int _dpu_plane_color_fill(struct dpu_plane
*pdpu
,
595 uint32_t color
, uint32_t alpha
)
597 const struct dpu_format
*fmt
;
598 const struct drm_plane
*plane
= &pdpu
->base
;
599 struct dpu_plane_state
*pstate
= to_dpu_plane_state(plane
->state
);
601 DPU_DEBUG_PLANE(pdpu
, "\n");
604 * select fill format to match user property expectation,
605 * h/w only supports RGB variants
607 fmt
= dpu_get_dpu_format(DRM_FORMAT_ABGR8888
);
610 if (fmt
&& pdpu
->pipe_hw
->ops
.setup_solidfill
) {
611 pdpu
->pipe_hw
->ops
.setup_solidfill(pdpu
->pipe_hw
,
612 (color
& 0xFFFFFF) | ((alpha
& 0xFF) << 24),
613 pstate
->multirect_index
);
615 /* override scaler/decimation if solid fill */
616 pdpu
->pipe_cfg
.src_rect
.x1
= 0;
617 pdpu
->pipe_cfg
.src_rect
.y1
= 0;
618 pdpu
->pipe_cfg
.src_rect
.x2
=
619 drm_rect_width(&pdpu
->pipe_cfg
.dst_rect
);
620 pdpu
->pipe_cfg
.src_rect
.y2
=
621 drm_rect_height(&pdpu
->pipe_cfg
.dst_rect
);
622 _dpu_plane_setup_scaler(pdpu
, pstate
, fmt
, true);
624 if (pdpu
->pipe_hw
->ops
.setup_format
)
625 pdpu
->pipe_hw
->ops
.setup_format(pdpu
->pipe_hw
,
626 fmt
, DPU_SSPP_SOLID_FILL
,
627 pstate
->multirect_index
);
629 if (pdpu
->pipe_hw
->ops
.setup_rects
)
630 pdpu
->pipe_hw
->ops
.setup_rects(pdpu
->pipe_hw
,
632 pstate
->multirect_index
);
634 if (pdpu
->pipe_hw
->ops
.setup_pe
)
635 pdpu
->pipe_hw
->ops
.setup_pe(pdpu
->pipe_hw
,
638 if (pdpu
->pipe_hw
->ops
.setup_scaler
&&
639 pstate
->multirect_index
!= DPU_SSPP_RECT_1
)
640 pdpu
->pipe_hw
->ops
.setup_scaler(pdpu
->pipe_hw
,
641 &pdpu
->pipe_cfg
, &pstate
->pixel_ext
,
642 &pstate
->scaler3_cfg
);
648 void dpu_plane_clear_multirect(const struct drm_plane_state
*drm_state
)
650 struct dpu_plane_state
*pstate
= to_dpu_plane_state(drm_state
);
652 pstate
->multirect_index
= DPU_SSPP_RECT_SOLO
;
653 pstate
->multirect_mode
= DPU_SSPP_MULTIRECT_NONE
;
656 int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states
*plane
)
658 struct dpu_plane_state
*pstate
[R_MAX
];
659 const struct drm_plane_state
*drm_state
[R_MAX
];
660 struct drm_rect src
[R_MAX
], dst
[R_MAX
];
661 struct dpu_plane
*dpu_plane
[R_MAX
];
662 const struct dpu_format
*fmt
[R_MAX
];
664 unsigned int max_tile_height
= 1;
665 bool parallel_fetch_qualified
= true;
666 bool has_tiled_rect
= false;
668 for (i
= 0; i
< R_MAX
; i
++) {
669 const struct msm_format
*msm_fmt
;
671 drm_state
[i
] = i
? plane
->r1
: plane
->r0
;
672 msm_fmt
= msm_framebuffer_format(drm_state
[i
]->fb
);
673 fmt
[i
] = to_dpu_format(msm_fmt
);
675 if (DPU_FORMAT_IS_UBWC(fmt
[i
])) {
676 has_tiled_rect
= true;
677 if (fmt
[i
]->tile_height
> max_tile_height
)
678 max_tile_height
= fmt
[i
]->tile_height
;
682 for (i
= 0; i
< R_MAX
; i
++) {
685 pstate
[i
] = to_dpu_plane_state(drm_state
[i
]);
686 dpu_plane
[i
] = to_dpu_plane(drm_state
[i
]->plane
);
688 if (pstate
[i
] == NULL
) {
689 DPU_ERROR("DPU plane state of plane id %d is NULL\n",
690 drm_state
[i
]->plane
->base
.id
);
694 src
[i
].x1
= drm_state
[i
]->src_x
>> 16;
695 src
[i
].y1
= drm_state
[i
]->src_y
>> 16;
696 src
[i
].x2
= src
[i
].x1
+ (drm_state
[i
]->src_w
>> 16);
697 src
[i
].y2
= src
[i
].y1
+ (drm_state
[i
]->src_h
>> 16);
699 dst
[i
] = drm_plane_state_dest(drm_state
[i
]);
701 if (drm_rect_calc_hscale(&src
[i
], &dst
[i
], 1, 1) != 1 ||
702 drm_rect_calc_vscale(&src
[i
], &dst
[i
], 1, 1) != 1) {
703 DPU_ERROR_PLANE(dpu_plane
[i
],
704 "scaling is not supported in multirect mode\n");
708 if (DPU_FORMAT_IS_YUV(fmt
[i
])) {
709 DPU_ERROR_PLANE(dpu_plane
[i
],
710 "Unsupported format for multirect mode\n");
715 * SSPP PD_MEM is split half - one for each RECT.
716 * Tiled formats need 5 lines of buffering while fetching
717 * whereas linear formats need only 2 lines.
718 * So we cannot support more than half of the supported SSPP
719 * width for tiled formats.
721 width_threshold
= dpu_plane
[i
]->pipe_sblk
->common
->maxlinewidth
;
723 width_threshold
/= 2;
725 if (parallel_fetch_qualified
&&
726 drm_rect_width(&src
[i
]) > width_threshold
)
727 parallel_fetch_qualified
= false;
731 /* Validate RECT's and set the mode */
733 /* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
734 if (parallel_fetch_qualified
) {
735 pstate
[R0
]->multirect_mode
= DPU_SSPP_MULTIRECT_PARALLEL
;
736 pstate
[R1
]->multirect_mode
= DPU_SSPP_MULTIRECT_PARALLEL
;
742 buffer_lines
= 2 * max_tile_height
;
744 if (dst
[R1
].y1
>= dst
[R0
].y2
+ buffer_lines
||
745 dst
[R0
].y1
>= dst
[R1
].y2
+ buffer_lines
) {
746 pstate
[R0
]->multirect_mode
= DPU_SSPP_MULTIRECT_TIME_MX
;
747 pstate
[R1
]->multirect_mode
= DPU_SSPP_MULTIRECT_TIME_MX
;
750 "No multirect mode possible for the planes (%d - %d)\n",
751 drm_state
[R0
]->plane
->base
.id
,
752 drm_state
[R1
]->plane
->base
.id
);
757 if (dpu_plane
[R0
]->is_virtual
) {
758 pstate
[R0
]->multirect_index
= DPU_SSPP_RECT_1
;
759 pstate
[R1
]->multirect_index
= DPU_SSPP_RECT_0
;
761 pstate
[R0
]->multirect_index
= DPU_SSPP_RECT_0
;
762 pstate
[R1
]->multirect_index
= DPU_SSPP_RECT_1
;
765 DPU_DEBUG_PLANE(dpu_plane
[R0
], "R0: %d - %d\n",
766 pstate
[R0
]->multirect_mode
, pstate
[R0
]->multirect_index
);
767 DPU_DEBUG_PLANE(dpu_plane
[R1
], "R1: %d - %d\n",
768 pstate
[R1
]->multirect_mode
, pstate
[R1
]->multirect_index
);
773 * dpu_plane_get_ctl_flush - get control flush for the given plane
774 * @plane: Pointer to drm plane structure
775 * @ctl: Pointer to hardware control driver
776 * @flush_sspp: Pointer to sspp flush control word
778 void dpu_plane_get_ctl_flush(struct drm_plane
*plane
, struct dpu_hw_ctl
*ctl
,
781 *flush_sspp
= ctl
->ops
.get_bitmask_sspp(ctl
, dpu_plane_pipe(plane
));
784 static int dpu_plane_prepare_fb(struct drm_plane
*plane
,
785 struct drm_plane_state
*new_state
)
787 struct drm_framebuffer
*fb
= new_state
->fb
;
788 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
789 struct dpu_plane_state
*pstate
= to_dpu_plane_state(new_state
);
790 struct dpu_hw_fmt_layout layout
;
791 struct drm_gem_object
*obj
;
792 struct msm_gem_object
*msm_obj
;
793 struct dma_fence
*fence
;
794 struct dpu_kms
*kms
= _dpu_plane_get_kms(&pdpu
->base
);
800 DPU_DEBUG_PLANE(pdpu
, "FB[%u]\n", fb
->base
.id
);
803 pstate
->aspace
= kms
->base
.aspace
;
806 * TODO: Need to sort out the msm_framebuffer_prepare() call below so
807 * we can use msm_atomic_prepare_fb() instead of doing the
808 * implicit fence and fb prepare by hand here.
810 obj
= msm_framebuffer_bo(new_state
->fb
, 0);
811 msm_obj
= to_msm_bo(obj
);
812 fence
= reservation_object_get_excl_rcu(msm_obj
->resv
);
814 drm_atomic_set_fence_for_plane(new_state
, fence
);
816 if (pstate
->aspace
) {
817 ret
= msm_framebuffer_prepare(new_state
->fb
,
820 DPU_ERROR("failed to prepare framebuffer\n");
825 /* validate framebuffer layout before commit */
826 ret
= dpu_format_populate_layout(pstate
->aspace
,
827 new_state
->fb
, &layout
);
829 DPU_ERROR_PLANE(pdpu
, "failed to get format layout, %d\n", ret
);
836 static void dpu_plane_cleanup_fb(struct drm_plane
*plane
,
837 struct drm_plane_state
*old_state
)
839 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
840 struct dpu_plane_state
*old_pstate
;
842 if (!old_state
|| !old_state
->fb
)
845 old_pstate
= to_dpu_plane_state(old_state
);
847 DPU_DEBUG_PLANE(pdpu
, "FB[%u]\n", old_state
->fb
->base
.id
);
849 msm_framebuffer_cleanup(old_state
->fb
, old_pstate
->aspace
);
852 static bool dpu_plane_validate_src(struct drm_rect
*src
,
853 struct drm_rect
*fb_rect
,
854 uint32_t min_src_size
)
856 /* Ensure fb size is supported */
857 if (drm_rect_width(fb_rect
) > MAX_IMG_WIDTH
||
858 drm_rect_height(fb_rect
) > MAX_IMG_HEIGHT
)
861 /* Ensure src rect is above the minimum size */
862 if (drm_rect_width(src
) < min_src_size
||
863 drm_rect_height(src
) < min_src_size
)
866 /* Ensure src is fully encapsulated in fb */
867 return drm_rect_intersect(fb_rect
, src
) &&
868 drm_rect_equals(fb_rect
, src
);
871 static int dpu_plane_atomic_check(struct drm_plane
*plane
,
872 struct drm_plane_state
*state
)
874 int ret
= 0, min_scale
;
875 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
876 const struct drm_crtc_state
*crtc_state
= NULL
;
877 const struct dpu_format
*fmt
;
878 struct drm_rect src
, dst
, fb_rect
= { 0 };
879 uint32_t min_src_size
, max_linewidth
;
882 crtc_state
= drm_atomic_get_new_crtc_state(state
->state
,
885 min_scale
= FRAC_16_16(1, pdpu
->pipe_sblk
->maxdwnscale
);
886 ret
= drm_atomic_helper_check_plane_state(state
, crtc_state
, min_scale
,
887 pdpu
->pipe_sblk
->maxupscale
<< 16,
890 DPU_ERROR_PLANE(pdpu
, "Check plane state failed (%d)\n", ret
);
896 src
.x1
= state
->src_x
>> 16;
897 src
.y1
= state
->src_y
>> 16;
898 src
.x2
= src
.x1
+ (state
->src_w
>> 16);
899 src
.y2
= src
.y1
+ (state
->src_h
>> 16);
901 dst
= drm_plane_state_dest(state
);
903 fb_rect
.x2
= state
->fb
->width
;
904 fb_rect
.y2
= state
->fb
->height
;
906 max_linewidth
= pdpu
->pipe_sblk
->common
->maxlinewidth
;
908 fmt
= to_dpu_format(msm_framebuffer_format(state
->fb
));
910 min_src_size
= DPU_FORMAT_IS_YUV(fmt
) ? 2 : 1;
912 if (DPU_FORMAT_IS_YUV(fmt
) &&
913 (!(pdpu
->features
& DPU_SSPP_SCALER
) ||
914 !(pdpu
->features
& (BIT(DPU_SSPP_CSC
)
915 | BIT(DPU_SSPP_CSC_10BIT
))))) {
916 DPU_ERROR_PLANE(pdpu
,
917 "plane doesn't have scaler/csc for yuv\n");
920 /* check src bounds */
921 } else if (!dpu_plane_validate_src(&src
, &fb_rect
, min_src_size
)) {
922 DPU_ERROR_PLANE(pdpu
, "invalid source " DRM_RECT_FMT
"\n",
926 /* valid yuv image */
927 } else if (DPU_FORMAT_IS_YUV(fmt
) &&
928 (src
.x1
& 0x1 || src
.y1
& 0x1 ||
929 drm_rect_width(&src
) & 0x1 ||
930 drm_rect_height(&src
) & 0x1)) {
931 DPU_ERROR_PLANE(pdpu
, "invalid yuv source " DRM_RECT_FMT
"\n",
935 /* min dst support */
936 } else if (drm_rect_width(&dst
) < 0x1 || drm_rect_height(&dst
) < 0x1) {
937 DPU_ERROR_PLANE(pdpu
, "invalid dest rect " DRM_RECT_FMT
"\n",
941 /* check decimated source width */
942 } else if (drm_rect_width(&src
) > max_linewidth
) {
943 DPU_ERROR_PLANE(pdpu
, "invalid src " DRM_RECT_FMT
" line:%u\n",
944 DRM_RECT_ARG(&src
), max_linewidth
);
951 void dpu_plane_flush(struct drm_plane
*plane
)
953 struct dpu_plane
*pdpu
;
954 struct dpu_plane_state
*pstate
;
956 if (!plane
|| !plane
->state
) {
957 DPU_ERROR("invalid plane\n");
961 pdpu
= to_dpu_plane(plane
);
962 pstate
= to_dpu_plane_state(plane
->state
);
965 * These updates have to be done immediately before the plane flush
966 * timing, and may not be moved to the atomic_update/mode_set functions.
969 /* force white frame with 100% alpha pipe output on error */
970 _dpu_plane_color_fill(pdpu
, 0xFFFFFF, 0xFF);
971 else if (pdpu
->color_fill
& DPU_PLANE_COLOR_FILL_FLAG
)
972 /* force 100% alpha */
973 _dpu_plane_color_fill(pdpu
, pdpu
->color_fill
, 0xFF);
974 else if (pdpu
->pipe_hw
&& pdpu
->csc_ptr
&& pdpu
->pipe_hw
->ops
.setup_csc
)
975 pdpu
->pipe_hw
->ops
.setup_csc(pdpu
->pipe_hw
, pdpu
->csc_ptr
);
977 /* flag h/w flush complete */
979 pstate
->pending
= false;
983 * dpu_plane_set_error: enable/disable error condition
984 * @plane: pointer to drm_plane structure
986 void dpu_plane_set_error(struct drm_plane
*plane
, bool error
)
988 struct dpu_plane
*pdpu
;
993 pdpu
= to_dpu_plane(plane
);
994 pdpu
->is_error
= error
;
997 static void dpu_plane_sspp_atomic_update(struct drm_plane
*plane
)
1000 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
1001 struct drm_plane_state
*state
= plane
->state
;
1002 struct dpu_plane_state
*pstate
= to_dpu_plane_state(state
);
1003 struct drm_crtc
*crtc
= state
->crtc
;
1004 struct drm_framebuffer
*fb
= state
->fb
;
1005 const struct dpu_format
*fmt
=
1006 to_dpu_format(msm_framebuffer_format(fb
));
1008 memset(&(pdpu
->pipe_cfg
), 0, sizeof(struct dpu_hw_pipe_cfg
));
1010 _dpu_plane_set_scanout(plane
, pstate
, &pdpu
->pipe_cfg
, fb
);
1012 pstate
->pending
= true;
1014 pdpu
->is_rt_pipe
= (dpu_crtc_get_client_type(crtc
) != NRT_CLIENT
);
1015 _dpu_plane_set_qos_ctrl(plane
, false, DPU_PLANE_QOS_PANIC_CTRL
);
1017 DPU_DEBUG_PLANE(pdpu
, "FB[%u] " DRM_RECT_FP_FMT
"->crtc%u " DRM_RECT_FMT
1018 ", %4.4s ubwc %d\n", fb
->base
.id
, DRM_RECT_FP_ARG(&state
->src
),
1019 crtc
->base
.id
, DRM_RECT_ARG(&state
->dst
),
1020 (char *)&fmt
->base
.pixel_format
, DPU_FORMAT_IS_UBWC(fmt
));
1022 pdpu
->pipe_cfg
.src_rect
= state
->src
;
1024 /* state->src is 16.16, src_rect is not */
1025 pdpu
->pipe_cfg
.src_rect
.x1
>>= 16;
1026 pdpu
->pipe_cfg
.src_rect
.x2
>>= 16;
1027 pdpu
->pipe_cfg
.src_rect
.y1
>>= 16;
1028 pdpu
->pipe_cfg
.src_rect
.y2
>>= 16;
1030 pdpu
->pipe_cfg
.dst_rect
= state
->dst
;
1032 _dpu_plane_setup_scaler(pdpu
, pstate
, fmt
, false);
1034 /* override for color fill */
1035 if (pdpu
->color_fill
& DPU_PLANE_COLOR_FILL_FLAG
) {
1036 /* skip remaining processing on color fill */
1040 if (pdpu
->pipe_hw
->ops
.setup_rects
) {
1041 pdpu
->pipe_hw
->ops
.setup_rects(pdpu
->pipe_hw
,
1043 pstate
->multirect_index
);
1046 if (pdpu
->pipe_hw
->ops
.setup_pe
&&
1047 (pstate
->multirect_index
!= DPU_SSPP_RECT_1
))
1048 pdpu
->pipe_hw
->ops
.setup_pe(pdpu
->pipe_hw
,
1049 &pstate
->pixel_ext
);
1052 * when programmed in multirect mode, scalar block will be
1053 * bypassed. Still we need to update alpha and bitwidth
1056 if (pdpu
->pipe_hw
->ops
.setup_scaler
&&
1057 pstate
->multirect_index
!= DPU_SSPP_RECT_1
)
1058 pdpu
->pipe_hw
->ops
.setup_scaler(pdpu
->pipe_hw
,
1059 &pdpu
->pipe_cfg
, &pstate
->pixel_ext
,
1060 &pstate
->scaler3_cfg
);
1062 if (pdpu
->pipe_hw
->ops
.setup_multirect
)
1063 pdpu
->pipe_hw
->ops
.setup_multirect(
1065 pstate
->multirect_index
,
1066 pstate
->multirect_mode
);
1068 if (pdpu
->pipe_hw
->ops
.setup_format
) {
1072 pdpu
->pipe_hw
->ops
.setup_format(pdpu
->pipe_hw
, fmt
, src_flags
,
1073 pstate
->multirect_index
);
1075 if (pdpu
->pipe_hw
->ops
.setup_cdp
) {
1076 struct dpu_hw_pipe_cdp_cfg
*cdp_cfg
= &pstate
->cdp_cfg
;
1078 memset(cdp_cfg
, 0, sizeof(struct dpu_hw_pipe_cdp_cfg
));
1080 cdp_cfg
->enable
= pdpu
->catalog
->perf
.cdp_cfg
1081 [DPU_PERF_CDP_USAGE_RT
].rd_enable
;
1082 cdp_cfg
->ubwc_meta_enable
=
1083 DPU_FORMAT_IS_UBWC(fmt
);
1084 cdp_cfg
->tile_amortize_enable
=
1085 DPU_FORMAT_IS_UBWC(fmt
) ||
1086 DPU_FORMAT_IS_TILE(fmt
);
1087 cdp_cfg
->preload_ahead
= DPU_SSPP_CDP_PRELOAD_AHEAD_64
;
1089 pdpu
->pipe_hw
->ops
.setup_cdp(pdpu
->pipe_hw
, cdp_cfg
);
1093 if (DPU_FORMAT_IS_YUV(fmt
))
1094 _dpu_plane_setup_csc(pdpu
);
1099 _dpu_plane_set_qos_lut(plane
, fb
);
1100 _dpu_plane_set_danger_lut(plane
, fb
);
1102 if (plane
->type
!= DRM_PLANE_TYPE_CURSOR
) {
1103 _dpu_plane_set_qos_ctrl(plane
, true, DPU_PLANE_QOS_PANIC_CTRL
);
1104 _dpu_plane_set_ot_limit(plane
, crtc
);
1107 _dpu_plane_set_qos_remap(plane
);
1110 static void _dpu_plane_atomic_disable(struct drm_plane
*plane
)
1112 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
1113 struct drm_plane_state
*state
= plane
->state
;
1114 struct dpu_plane_state
*pstate
= to_dpu_plane_state(state
);
1116 trace_dpu_plane_disable(DRMID(plane
), is_dpu_plane_virtual(plane
),
1117 pstate
->multirect_mode
);
1119 pstate
->pending
= true;
1121 if (is_dpu_plane_virtual(plane
) &&
1122 pdpu
->pipe_hw
&& pdpu
->pipe_hw
->ops
.setup_multirect
)
1123 pdpu
->pipe_hw
->ops
.setup_multirect(pdpu
->pipe_hw
,
1124 DPU_SSPP_RECT_SOLO
, DPU_SSPP_MULTIRECT_NONE
);
1127 static void dpu_plane_atomic_update(struct drm_plane
*plane
,
1128 struct drm_plane_state
*old_state
)
1130 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
1131 struct drm_plane_state
*state
= plane
->state
;
1133 pdpu
->is_error
= false;
1135 DPU_DEBUG_PLANE(pdpu
, "\n");
1137 if (!state
->visible
) {
1138 _dpu_plane_atomic_disable(plane
);
1140 dpu_plane_sspp_atomic_update(plane
);
1144 void dpu_plane_restore(struct drm_plane
*plane
)
1146 struct dpu_plane
*pdpu
;
1148 if (!plane
|| !plane
->state
) {
1149 DPU_ERROR("invalid plane\n");
1153 pdpu
= to_dpu_plane(plane
);
1155 DPU_DEBUG_PLANE(pdpu
, "\n");
1157 /* last plane state is same as current state */
1158 dpu_plane_atomic_update(plane
, plane
->state
);
1161 static void dpu_plane_destroy(struct drm_plane
*plane
)
1163 struct dpu_plane
*pdpu
= plane
? to_dpu_plane(plane
) : NULL
;
1165 DPU_DEBUG_PLANE(pdpu
, "\n");
1168 _dpu_plane_set_qos_ctrl(plane
, false, DPU_PLANE_QOS_PANIC_CTRL
);
1170 mutex_destroy(&pdpu
->lock
);
1172 /* this will destroy the states as well */
1173 drm_plane_cleanup(plane
);
1175 dpu_hw_sspp_destroy(pdpu
->pipe_hw
);
1181 static void dpu_plane_destroy_state(struct drm_plane
*plane
,
1182 struct drm_plane_state
*state
)
1184 __drm_atomic_helper_plane_destroy_state(state
);
1185 kfree(to_dpu_plane_state(state
));
1188 static struct drm_plane_state
*
1189 dpu_plane_duplicate_state(struct drm_plane
*plane
)
1191 struct dpu_plane
*pdpu
;
1192 struct dpu_plane_state
*pstate
;
1193 struct dpu_plane_state
*old_state
;
1196 DPU_ERROR("invalid plane\n");
1198 } else if (!plane
->state
) {
1199 DPU_ERROR("invalid plane state\n");
1203 old_state
= to_dpu_plane_state(plane
->state
);
1204 pdpu
= to_dpu_plane(plane
);
1205 pstate
= kmemdup(old_state
, sizeof(*old_state
), GFP_KERNEL
);
1207 DPU_ERROR_PLANE(pdpu
, "failed to allocate state\n");
1211 DPU_DEBUG_PLANE(pdpu
, "\n");
1213 pstate
->pending
= false;
1215 __drm_atomic_helper_plane_duplicate_state(plane
, &pstate
->base
);
1217 return &pstate
->base
;
1220 static void dpu_plane_reset(struct drm_plane
*plane
)
1222 struct dpu_plane
*pdpu
;
1223 struct dpu_plane_state
*pstate
;
1226 DPU_ERROR("invalid plane\n");
1230 pdpu
= to_dpu_plane(plane
);
1231 DPU_DEBUG_PLANE(pdpu
, "\n");
1233 /* remove previous state, if present */
1235 dpu_plane_destroy_state(plane
, plane
->state
);
1239 pstate
= kzalloc(sizeof(*pstate
), GFP_KERNEL
);
1241 DPU_ERROR_PLANE(pdpu
, "failed to allocate state\n");
1245 pstate
->base
.plane
= plane
;
1247 plane
->state
= &pstate
->base
;
1250 #ifdef CONFIG_DEBUG_FS
1251 static ssize_t
_dpu_plane_danger_read(struct file
*file
,
1252 char __user
*buff
, size_t count
, loff_t
*ppos
)
1254 struct dpu_kms
*kms
= file
->private_data
;
1258 len
= scnprintf(buf
, sizeof(buf
), "%d\n", !kms
->has_danger_ctrl
);
1260 return simple_read_from_buffer(buff
, count
, ppos
, buf
, len
);
1263 static void _dpu_plane_set_danger_state(struct dpu_kms
*kms
, bool enable
)
1265 struct drm_plane
*plane
;
1267 drm_for_each_plane(plane
, kms
->dev
) {
1268 if (plane
->fb
&& plane
->state
) {
1269 dpu_plane_danger_signal_ctrl(plane
, enable
);
1270 DPU_DEBUG("plane:%d img:%dx%d ",
1271 plane
->base
.id
, plane
->fb
->width
,
1273 DPU_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n",
1274 plane
->state
->src_x
>> 16,
1275 plane
->state
->src_y
>> 16,
1276 plane
->state
->src_w
>> 16,
1277 plane
->state
->src_h
>> 16,
1278 plane
->state
->crtc_x
, plane
->state
->crtc_y
,
1279 plane
->state
->crtc_w
, plane
->state
->crtc_h
);
1281 DPU_DEBUG("Inactive plane:%d\n", plane
->base
.id
);
1286 static ssize_t
_dpu_plane_danger_write(struct file
*file
,
1287 const char __user
*user_buf
, size_t count
, loff_t
*ppos
)
1289 struct dpu_kms
*kms
= file
->private_data
;
1293 ret
= kstrtouint_from_user(user_buf
, count
, 0, &disable_panic
);
1297 if (disable_panic
) {
1298 /* Disable panic signal for all active pipes */
1299 DPU_DEBUG("Disabling danger:\n");
1300 _dpu_plane_set_danger_state(kms
, false);
1301 kms
->has_danger_ctrl
= false;
1303 /* Enable panic signal for all active pipes */
1304 DPU_DEBUG("Enabling danger:\n");
1305 kms
->has_danger_ctrl
= true;
1306 _dpu_plane_set_danger_state(kms
, true);
1312 static const struct file_operations dpu_plane_danger_enable
= {
1313 .open
= simple_open
,
1314 .read
= _dpu_plane_danger_read
,
1315 .write
= _dpu_plane_danger_write
,
1318 static int _dpu_plane_init_debugfs(struct drm_plane
*plane
)
1320 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
1321 struct dpu_kms
*kms
= _dpu_plane_get_kms(plane
);
1322 const struct dpu_sspp_cfg
*cfg
= pdpu
->pipe_hw
->cap
;
1323 const struct dpu_sspp_sub_blks
*sblk
= cfg
->sblk
;
1325 /* create overall sub-directory for the pipe */
1326 pdpu
->debugfs_root
=
1327 debugfs_create_dir(pdpu
->pipe_name
,
1328 plane
->dev
->primary
->debugfs_root
);
1330 if (!pdpu
->debugfs_root
)
1333 /* don't error check these */
1334 debugfs_create_x32("features", 0600,
1335 pdpu
->debugfs_root
, &pdpu
->features
);
1337 /* add register dump support */
1338 dpu_debugfs_setup_regset32(&pdpu
->debugfs_src
,
1339 sblk
->src_blk
.base
+ cfg
->base
,
1342 dpu_debugfs_create_regset32("src_blk", 0400,
1343 pdpu
->debugfs_root
, &pdpu
->debugfs_src
);
1345 if (cfg
->features
& BIT(DPU_SSPP_SCALER_QSEED3
) ||
1346 cfg
->features
& BIT(DPU_SSPP_SCALER_QSEED2
)) {
1347 dpu_debugfs_setup_regset32(&pdpu
->debugfs_scaler
,
1348 sblk
->scaler_blk
.base
+ cfg
->base
,
1349 sblk
->scaler_blk
.len
,
1351 dpu_debugfs_create_regset32("scaler_blk", 0400,
1353 &pdpu
->debugfs_scaler
);
1354 debugfs_create_bool("default_scaling",
1357 &pdpu
->debugfs_default_scale
);
1360 if (cfg
->features
& BIT(DPU_SSPP_CSC
) ||
1361 cfg
->features
& BIT(DPU_SSPP_CSC_10BIT
)) {
1362 dpu_debugfs_setup_regset32(&pdpu
->debugfs_csc
,
1363 sblk
->csc_blk
.base
+ cfg
->base
,
1366 dpu_debugfs_create_regset32("csc_blk", 0400,
1367 pdpu
->debugfs_root
, &pdpu
->debugfs_csc
);
1370 debugfs_create_u32("xin_id",
1373 (u32
*) &cfg
->xin_id
);
1374 debugfs_create_u32("clk_ctrl",
1377 (u32
*) &cfg
->clk_ctrl
);
1378 debugfs_create_x32("creq_vblank",
1381 (u32
*) &sblk
->creq_vblank
);
1382 debugfs_create_x32("danger_vblank",
1385 (u32
*) &sblk
->danger_vblank
);
1387 debugfs_create_file("disable_danger",
1390 kms
, &dpu_plane_danger_enable
);
1395 static int _dpu_plane_init_debugfs(struct drm_plane
*plane
)
1401 static int dpu_plane_late_register(struct drm_plane
*plane
)
1403 return _dpu_plane_init_debugfs(plane
);
1406 static void dpu_plane_early_unregister(struct drm_plane
*plane
)
1408 struct dpu_plane
*pdpu
= to_dpu_plane(plane
);
1410 debugfs_remove_recursive(pdpu
->debugfs_root
);
1413 static const struct drm_plane_funcs dpu_plane_funcs
= {
1414 .update_plane
= drm_atomic_helper_update_plane
,
1415 .disable_plane
= drm_atomic_helper_disable_plane
,
1416 .destroy
= dpu_plane_destroy
,
1417 .reset
= dpu_plane_reset
,
1418 .atomic_duplicate_state
= dpu_plane_duplicate_state
,
1419 .atomic_destroy_state
= dpu_plane_destroy_state
,
1420 .late_register
= dpu_plane_late_register
,
1421 .early_unregister
= dpu_plane_early_unregister
,
1424 static const struct drm_plane_helper_funcs dpu_plane_helper_funcs
= {
1425 .prepare_fb
= dpu_plane_prepare_fb
,
1426 .cleanup_fb
= dpu_plane_cleanup_fb
,
1427 .atomic_check
= dpu_plane_atomic_check
,
1428 .atomic_update
= dpu_plane_atomic_update
,
1431 enum dpu_sspp
dpu_plane_pipe(struct drm_plane
*plane
)
1433 return plane
? to_dpu_plane(plane
)->pipe
: SSPP_NONE
;
1436 bool is_dpu_plane_virtual(struct drm_plane
*plane
)
1438 return plane
? to_dpu_plane(plane
)->is_virtual
: false;
1441 /* initialize plane */
1442 struct drm_plane
*dpu_plane_init(struct drm_device
*dev
,
1443 uint32_t pipe
, enum drm_plane_type type
,
1444 unsigned long possible_crtcs
, u32 master_plane_id
)
1446 struct drm_plane
*plane
= NULL
, *master_plane
= NULL
;
1447 const struct dpu_format_extended
*format_list
;
1448 struct dpu_plane
*pdpu
;
1449 struct msm_drm_private
*priv
= dev
->dev_private
;
1450 struct dpu_kms
*kms
= to_dpu_kms(priv
->kms
);
1451 int zpos_max
= DPU_ZPOS_MAX
;
1454 /* create and zero local structure */
1455 pdpu
= kzalloc(sizeof(*pdpu
), GFP_KERNEL
);
1457 DPU_ERROR("[%u]failed to allocate local plane struct\n", pipe
);
1459 return ERR_PTR(ret
);
1462 /* cache local stuff for later */
1463 plane
= &pdpu
->base
;
1465 pdpu
->is_virtual
= (master_plane_id
!= 0);
1466 INIT_LIST_HEAD(&pdpu
->mplane_list
);
1467 master_plane
= drm_plane_find(dev
, NULL
, master_plane_id
);
1469 struct dpu_plane
*mpdpu
= to_dpu_plane(master_plane
);
1471 list_add_tail(&pdpu
->mplane_list
, &mpdpu
->mplane_list
);
1474 /* initialize underlying h/w driver */
1475 pdpu
->pipe_hw
= dpu_hw_sspp_init(pipe
, kms
->mmio
, kms
->catalog
,
1476 master_plane_id
!= 0);
1477 if (IS_ERR(pdpu
->pipe_hw
)) {
1478 DPU_ERROR("[%u]SSPP init failed\n", pipe
);
1479 ret
= PTR_ERR(pdpu
->pipe_hw
);
1481 } else if (!pdpu
->pipe_hw
->cap
|| !pdpu
->pipe_hw
->cap
->sblk
) {
1482 DPU_ERROR("[%u]SSPP init returned invalid cfg\n", pipe
);
1486 /* cache features mask for later */
1487 pdpu
->features
= pdpu
->pipe_hw
->cap
->features
;
1488 pdpu
->pipe_sblk
= pdpu
->pipe_hw
->cap
->sblk
;
1489 if (!pdpu
->pipe_sblk
) {
1490 DPU_ERROR("[%u]invalid sblk\n", pipe
);
1494 if (!master_plane_id
)
1495 format_list
= pdpu
->pipe_sblk
->format_list
;
1497 format_list
= pdpu
->pipe_sblk
->virt_format_list
;
1499 pdpu
->nformats
= dpu_populate_formats(format_list
,
1502 ARRAY_SIZE(pdpu
->formats
));
1504 if (!pdpu
->nformats
) {
1505 DPU_ERROR("[%u]no valid formats for plane\n", pipe
);
1509 ret
= drm_universal_plane_init(dev
, plane
, 0xff, &dpu_plane_funcs
,
1510 pdpu
->formats
, pdpu
->nformats
,
1515 pdpu
->catalog
= kms
->catalog
;
1517 if (kms
->catalog
->mixer_count
&&
1518 kms
->catalog
->mixer
[0].sblk
->maxblendstages
) {
1519 zpos_max
= kms
->catalog
->mixer
[0].sblk
->maxblendstages
- 1;
1520 if (zpos_max
> DPU_STAGE_MAX
- DPU_STAGE_0
- 1)
1521 zpos_max
= DPU_STAGE_MAX
- DPU_STAGE_0
- 1;
1524 ret
= drm_plane_create_zpos_property(plane
, 0, 0, zpos_max
);
1526 DPU_ERROR("failed to install zpos property, rc = %d\n", ret
);
1528 /* success! finalize initialization */
1529 drm_plane_helper_add(plane
, &dpu_plane_helper_funcs
);
1531 /* save user friendly pipe name for later */
1532 snprintf(pdpu
->pipe_name
, DPU_NAME_SIZE
, "plane%u", plane
->base
.id
);
1534 mutex_init(&pdpu
->lock
);
1536 DPU_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", pdpu
->pipe_name
,
1537 pipe
, plane
->base
.id
, master_plane_id
);
1541 if (pdpu
&& pdpu
->pipe_hw
)
1542 dpu_hw_sspp_destroy(pdpu
->pipe_hw
);
1545 return ERR_PTR(ret
);