1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2015-2018, 2020-2021 The Linux Foundation. All rights reserved.
4  */
5 
6 #define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
7 #include <linux/delay.h>
8 #include "dpu_encoder_phys.h"
9 #include "dpu_hw_interrupts.h"
10 #include "dpu_hw_pingpong.h"
11 #include "dpu_core_irq.h"
12 #include "dpu_formats.h"
13 #include "dpu_trace.h"
14 #include "disp/msm_disp_snapshot.h"
15 
16 #include <drm/drm_managed.h>
17 
18 #define DPU_DEBUG_CMDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \
19 		(e) && (e)->base.parent ? \
20 		(e)->base.parent->base.id : -1, \
21 		(e) ? (e)->base.hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)
22 
23 #define DPU_ERROR_CMDENC(e, fmt, ...) DPU_ERROR("enc%d intf%d " fmt, \
24 		(e) && (e)->base.parent ? \
25 		(e)->base.parent->base.id : -1, \
26 		(e) ? (e)->base.hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)
27 
28 #define to_dpu_encoder_phys_cmd(x) \
29 	container_of(x, struct dpu_encoder_phys_cmd, base)
30 
31 #define PP_TIMEOUT_MAX_TRIALS	10
32 
33 /*
34  * Tearcheck sync start and continue thresholds are empirically found
35  * based on common panels In the future, may want to allow panels to override
36  * these default values
37  */
38 #define DEFAULT_TEARCHECK_SYNC_THRESH_START	4
39 #define DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE	4
40 
41 static void dpu_encoder_phys_cmd_enable_te(struct dpu_encoder_phys *phys_enc);
42 
43 static bool dpu_encoder_phys_cmd_is_master(struct dpu_encoder_phys *phys_enc)
44 {
45 	return (phys_enc->split_role != ENC_ROLE_SLAVE);
46 }
47 
48 static void _dpu_encoder_phys_cmd_update_intf_cfg(
49 		struct dpu_encoder_phys *phys_enc)
50 {
51 	struct dpu_encoder_phys_cmd *cmd_enc =
52 			to_dpu_encoder_phys_cmd(phys_enc);
53 	struct dpu_hw_ctl *ctl;
54 	struct dpu_hw_intf_cfg intf_cfg = { 0 };
55 	struct dpu_hw_intf_cmd_mode_cfg cmd_mode_cfg = {};
56 
57 	ctl = phys_enc->hw_ctl;
58 	if (!ctl->ops.setup_intf_cfg)
59 		return;
60 
61 	intf_cfg.intf = phys_enc->hw_intf->idx;
62 	intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
63 	intf_cfg.stream_sel = cmd_enc->stream_sel;
64 	intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
65 	intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc);
66 	ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
67 
68 	/* setup which pp blk will connect to this intf */
69 	if (test_bit(DPU_CTL_ACTIVE_CFG, &ctl->caps->features) && phys_enc->hw_intf->ops.bind_pingpong_blk)
70 		phys_enc->hw_intf->ops.bind_pingpong_blk(
71 				phys_enc->hw_intf,
72 				phys_enc->hw_pp->idx);
73 
74 	if (intf_cfg.dsc != 0)
75 		cmd_mode_cfg.data_compress = true;
76 
77 	cmd_mode_cfg.wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent);
78 
79 	if (phys_enc->hw_intf->ops.program_intf_cmd_cfg)
80 		phys_enc->hw_intf->ops.program_intf_cmd_cfg(phys_enc->hw_intf, &cmd_mode_cfg);
81 }
82 
83 static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg)
84 {
85 	struct dpu_encoder_phys *phys_enc = arg;
86 	unsigned long lock_flags;
87 	int new_cnt;
88 	u32 event = DPU_ENCODER_FRAME_EVENT_DONE;
89 
90 	if (!phys_enc->hw_pp)
91 		return;
92 
93 	DPU_ATRACE_BEGIN("pp_done_irq");
94 	/* notify all synchronous clients first, then asynchronous clients */
95 	dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, event);
96 
97 	spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
98 	new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);
99 	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
100 
101 	trace_dpu_enc_phys_cmd_pp_tx_done(DRMID(phys_enc->parent),
102 					  phys_enc->hw_pp->idx - PINGPONG_0,
103 					  new_cnt, event);
104 
105 	/* Signal any waiting atomic commit thread */
106 	wake_up_all(&phys_enc->pending_kickoff_wq);
107 	DPU_ATRACE_END("pp_done_irq");
108 }
109 
110 static void dpu_encoder_phys_cmd_te_rd_ptr_irq(void *arg)
111 {
112 	struct dpu_encoder_phys *phys_enc = arg;
113 	struct dpu_encoder_phys_cmd *cmd_enc;
114 
115 	DPU_ATRACE_BEGIN("rd_ptr_irq");
116 	cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
117 
118 	dpu_encoder_vblank_callback(phys_enc->parent, phys_enc);
119 
120 	atomic_add_unless(&cmd_enc->pending_vblank_cnt, -1, 0);
121 	wake_up_all(&cmd_enc->pending_vblank_wq);
122 	DPU_ATRACE_END("rd_ptr_irq");
123 }
124 
125 static void dpu_encoder_phys_cmd_ctl_start_irq(void *arg)
126 {
127 	struct dpu_encoder_phys *phys_enc = arg;
128 
129 	DPU_ATRACE_BEGIN("ctl_start_irq");
130 
131 	atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
132 
133 	/* Signal any waiting ctl start interrupt */
134 	wake_up_all(&phys_enc->pending_kickoff_wq);
135 	DPU_ATRACE_END("ctl_start_irq");
136 }
137 
138 static void dpu_encoder_phys_cmd_underrun_irq(void *arg)
139 {
140 	struct dpu_encoder_phys *phys_enc = arg;
141 
142 	dpu_encoder_underrun_callback(phys_enc->parent, phys_enc);
143 }
144 
145 static int _dpu_encoder_phys_cmd_handle_ppdone_timeout(
146 		struct dpu_encoder_phys *phys_enc)
147 {
148 	struct dpu_encoder_phys_cmd *cmd_enc =
149 			to_dpu_encoder_phys_cmd(phys_enc);
150 	u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR;
151 	bool do_log = false;
152 	struct drm_encoder *drm_enc;
153 
154 	if (!phys_enc->hw_pp)
155 		return -EINVAL;
156 
157 	drm_enc = phys_enc->parent;
158 
159 	cmd_enc->pp_timeout_report_cnt++;
160 	if (cmd_enc->pp_timeout_report_cnt == PP_TIMEOUT_MAX_TRIALS) {
161 		frame_event |= DPU_ENCODER_FRAME_EVENT_PANEL_DEAD;
162 		do_log = true;
163 	} else if (cmd_enc->pp_timeout_report_cnt == 1) {
164 		do_log = true;
165 	}
166 
167 	trace_dpu_enc_phys_cmd_pdone_timeout(DRMID(drm_enc),
168 		     phys_enc->hw_pp->idx - PINGPONG_0,
169 		     cmd_enc->pp_timeout_report_cnt,
170 		     atomic_read(&phys_enc->pending_kickoff_cnt),
171 		     frame_event);
172 
173 	/* to avoid flooding, only log first time, and "dead" time */
174 	if (do_log) {
175 		DRM_ERROR("id:%d pp:%d kickoff timeout %d cnt %d koff_cnt %d\n",
176 			  DRMID(drm_enc),
177 			  phys_enc->hw_pp->idx - PINGPONG_0,
178 			  phys_enc->hw_ctl->idx - CTL_0,
179 			  cmd_enc->pp_timeout_report_cnt,
180 			  atomic_read(&phys_enc->pending_kickoff_cnt));
181 		msm_disp_snapshot_state(drm_enc->dev);
182 		dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
183 				phys_enc->irq[INTR_IDX_RDPTR]);
184 	}
185 
186 	atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);
187 
188 	/* request a ctl reset before the next kickoff */
189 	phys_enc->enable_state = DPU_ENC_ERR_NEEDS_HW_RESET;
190 
191 	dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, frame_event);
192 
193 	return -ETIMEDOUT;
194 }
195 
196 static int _dpu_encoder_phys_cmd_wait_for_idle(
197 		struct dpu_encoder_phys *phys_enc)
198 {
199 	struct dpu_encoder_phys_cmd *cmd_enc =
200 			to_dpu_encoder_phys_cmd(phys_enc);
201 	struct dpu_encoder_wait_info wait_info;
202 	int ret;
203 
204 	wait_info.wq = &phys_enc->pending_kickoff_wq;
205 	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
206 	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
207 
208 	ret = dpu_encoder_helper_wait_for_irq(phys_enc,
209 			phys_enc->irq[INTR_IDX_PINGPONG],
210 			dpu_encoder_phys_cmd_pp_tx_done_irq,
211 			&wait_info);
212 	if (ret == -ETIMEDOUT)
213 		_dpu_encoder_phys_cmd_handle_ppdone_timeout(phys_enc);
214 	else if (!ret)
215 		cmd_enc->pp_timeout_report_cnt = 0;
216 
217 	return ret;
218 }
219 
220 static int dpu_encoder_phys_cmd_control_vblank_irq(
221 		struct dpu_encoder_phys *phys_enc,
222 		bool enable)
223 {
224 	int ret = 0;
225 	int refcount;
226 
227 	if (!phys_enc->hw_pp) {
228 		DPU_ERROR("invalid encoder\n");
229 		return -EINVAL;
230 	}
231 
232 	mutex_lock(&phys_enc->vblank_ctl_lock);
233 	refcount = phys_enc->vblank_refcount;
234 
235 	/* Slave encoders don't report vblank */
236 	if (!dpu_encoder_phys_cmd_is_master(phys_enc))
237 		goto end;
238 
239 	/* protect against negative */
240 	if (!enable && refcount == 0) {
241 		ret = -EINVAL;
242 		goto end;
243 	}
244 
245 	DRM_DEBUG_KMS("id:%u pp:%d enable=%s/%d\n", DRMID(phys_enc->parent),
246 		      phys_enc->hw_pp->idx - PINGPONG_0,
247 		      enable ? "true" : "false", refcount);
248 
249 	if (enable) {
250 		if (phys_enc->vblank_refcount == 0)
251 			ret = dpu_core_irq_register_callback(phys_enc->dpu_kms,
252 					phys_enc->irq[INTR_IDX_RDPTR],
253 					dpu_encoder_phys_cmd_te_rd_ptr_irq,
254 					phys_enc);
255 		if (!ret)
256 			phys_enc->vblank_refcount++;
257 	} else if (!enable) {
258 		if (phys_enc->vblank_refcount == 1)
259 			ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
260 					phys_enc->irq[INTR_IDX_RDPTR]);
261 		if (!ret)
262 			phys_enc->vblank_refcount--;
263 	}
264 
265 end:
266 	mutex_unlock(&phys_enc->vblank_ctl_lock);
267 	if (ret) {
268 		DRM_ERROR("vblank irq err id:%u pp:%d ret:%d, enable %s/%d\n",
269 			  DRMID(phys_enc->parent),
270 			  phys_enc->hw_pp->idx - PINGPONG_0, ret,
271 			  enable ? "true" : "false", refcount);
272 	}
273 
274 	return ret;
275 }
276 
277 static void dpu_encoder_phys_cmd_irq_enable(struct dpu_encoder_phys *phys_enc)
278 {
279 	trace_dpu_enc_phys_cmd_irq_enable(DRMID(phys_enc->parent),
280 					  phys_enc->hw_pp->idx - PINGPONG_0,
281 					  phys_enc->vblank_refcount);
282 
283 	phys_enc->irq[INTR_IDX_CTL_START] = phys_enc->hw_ctl->caps->intr_start;
284 	phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done;
285 
286 	if (phys_enc->has_intf_te)
287 		phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr;
288 	else
289 		phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
290 
291 	dpu_core_irq_register_callback(phys_enc->dpu_kms,
292 				       phys_enc->irq[INTR_IDX_PINGPONG],
293 				       dpu_encoder_phys_cmd_pp_tx_done_irq,
294 				       phys_enc);
295 	dpu_core_irq_register_callback(phys_enc->dpu_kms,
296 				       phys_enc->irq[INTR_IDX_UNDERRUN],
297 				       dpu_encoder_phys_cmd_underrun_irq,
298 				       phys_enc);
299 	dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
300 
301 	if (dpu_encoder_phys_cmd_is_master(phys_enc))
302 		dpu_core_irq_register_callback(phys_enc->dpu_kms,
303 					       phys_enc->irq[INTR_IDX_CTL_START],
304 					       dpu_encoder_phys_cmd_ctl_start_irq,
305 					       phys_enc);
306 }
307 
308 static void dpu_encoder_phys_cmd_irq_disable(struct dpu_encoder_phys *phys_enc)
309 {
310 	trace_dpu_enc_phys_cmd_irq_disable(DRMID(phys_enc->parent),
311 					   phys_enc->hw_pp->idx - PINGPONG_0,
312 					   phys_enc->vblank_refcount);
313 
314 	if (dpu_encoder_phys_cmd_is_master(phys_enc))
315 		dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
316 						 phys_enc->irq[INTR_IDX_CTL_START]);
317 
318 	dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_UNDERRUN]);
319 	dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
320 	dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_PINGPONG]);
321 
322 	phys_enc->irq[INTR_IDX_CTL_START] = 0;
323 	phys_enc->irq[INTR_IDX_PINGPONG] = 0;
324 	phys_enc->irq[INTR_IDX_RDPTR] = 0;
325 }
326 
327 static void dpu_encoder_phys_cmd_tearcheck_config(
328 		struct dpu_encoder_phys *phys_enc)
329 {
330 	struct dpu_encoder_phys_cmd *cmd_enc =
331 		to_dpu_encoder_phys_cmd(phys_enc);
332 	struct dpu_hw_tear_check tc_cfg = { 0 };
333 	struct drm_display_mode *mode;
334 	bool tc_enable = true;
335 	unsigned long vsync_hz;
336 	struct dpu_kms *dpu_kms;
337 
338 	/*
339 	 * TODO: if/when resource allocation is refactored, move this to a
340 	 * place where the driver can actually return an error.
341 	 */
342 	if (!phys_enc->has_intf_te &&
343 	    (!phys_enc->hw_pp ||
344 	     !phys_enc->hw_pp->ops.enable_tearcheck)) {
345 		DPU_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
346 		return;
347 	}
348 
349 	DPU_DEBUG_CMDENC(cmd_enc, "intf %d pp %d\n",
350 			 phys_enc->hw_intf ? phys_enc->hw_intf->idx - INTF_0 : -1,
351 			 phys_enc->hw_pp ? phys_enc->hw_pp->idx - PINGPONG_0 : -1);
352 
353 	mode = &phys_enc->cached_mode;
354 
355 	dpu_kms = phys_enc->dpu_kms;
356 
357 	/*
358 	 * TE default: dsi byte clock calculated base on 70 fps;
359 	 * around 14 ms to complete a kickoff cycle if te disabled;
360 	 * vclk_line base on 60 fps; write is faster than read;
361 	 * init == start == rdptr;
362 	 *
363 	 * vsync_count is ratio of MDP VSYNC clock frequency to LCD panel
364 	 * frequency divided by the no. of rows (lines) in the LCDpanel.
365 	 */
366 	vsync_hz = dpu_kms_get_clk_rate(dpu_kms, "vsync");
367 	if (!vsync_hz) {
368 		DPU_DEBUG_CMDENC(cmd_enc, "invalid - no vsync clock\n");
369 		return;
370 	}
371 
372 	tc_cfg.vsync_count = vsync_hz /
373 				(mode->vtotal * drm_mode_vrefresh(mode));
374 
375 	/*
376 	 * Set the sync_cfg_height to twice vtotal so that if we lose a
377 	 * TE event coming from the display TE pin we won't stall immediately
378 	 */
379 	tc_cfg.hw_vsync_mode = 1;
380 	tc_cfg.sync_cfg_height = mode->vtotal * 2;
381 	tc_cfg.vsync_init_val = mode->vdisplay;
382 	tc_cfg.sync_threshold_start = DEFAULT_TEARCHECK_SYNC_THRESH_START;
383 	tc_cfg.sync_threshold_continue = DEFAULT_TEARCHECK_SYNC_THRESH_CONTINUE;
384 	tc_cfg.start_pos = mode->vdisplay;
385 	tc_cfg.rd_ptr_irq = mode->vdisplay + 1;
386 
387 	DPU_DEBUG_CMDENC(cmd_enc,
388 		"tc vsync_clk_speed_hz %lu vtotal %u vrefresh %u\n",
389 		vsync_hz, mode->vtotal, drm_mode_vrefresh(mode));
390 	DPU_DEBUG_CMDENC(cmd_enc,
391 		"tc enable %u start_pos %u rd_ptr_irq %u\n",
392 		tc_enable, tc_cfg.start_pos, tc_cfg.rd_ptr_irq);
393 	DPU_DEBUG_CMDENC(cmd_enc,
394 		"tc hw_vsync_mode %u vsync_count %u vsync_init_val %u\n",
395 		tc_cfg.hw_vsync_mode, tc_cfg.vsync_count,
396 		tc_cfg.vsync_init_val);
397 	DPU_DEBUG_CMDENC(cmd_enc,
398 		"tc cfgheight %u thresh_start %u thresh_cont %u\n",
399 		tc_cfg.sync_cfg_height, tc_cfg.sync_threshold_start,
400 		tc_cfg.sync_threshold_continue);
401 
402 	if (phys_enc->has_intf_te)
403 		phys_enc->hw_intf->ops.enable_tearcheck(phys_enc->hw_intf, &tc_cfg);
404 	else
405 		phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, &tc_cfg);
406 }
407 
408 static void _dpu_encoder_phys_cmd_pingpong_config(
409 		struct dpu_encoder_phys *phys_enc)
410 {
411 	struct dpu_encoder_phys_cmd *cmd_enc =
412 		to_dpu_encoder_phys_cmd(phys_enc);
413 
414 	if (!phys_enc->hw_pp || !phys_enc->hw_ctl->ops.setup_intf_cfg) {
415 		DPU_ERROR("invalid arg(s), enc %d\n", phys_enc != NULL);
416 		return;
417 	}
418 
419 	DPU_DEBUG_CMDENC(cmd_enc, "pp %d, enabling mode:\n",
420 			phys_enc->hw_pp->idx - PINGPONG_0);
421 	drm_mode_debug_printmodeline(&phys_enc->cached_mode);
422 
423 	_dpu_encoder_phys_cmd_update_intf_cfg(phys_enc);
424 	dpu_encoder_phys_cmd_tearcheck_config(phys_enc);
425 }
426 
427 static bool dpu_encoder_phys_cmd_needs_single_flush(
428 		struct dpu_encoder_phys *phys_enc)
429 {
430 	/**
431 	 * we do separate flush for each CTL and let
432 	 * CTL_START synchronize them
433 	 */
434 	return false;
435 }
436 
437 static void dpu_encoder_phys_cmd_enable_helper(
438 		struct dpu_encoder_phys *phys_enc)
439 {
440 	struct dpu_hw_ctl *ctl;
441 
442 	if (!phys_enc->hw_pp) {
443 		DPU_ERROR("invalid arg(s), encoder %d\n", phys_enc != NULL);
444 		return;
445 	}
446 
447 	dpu_encoder_helper_split_config(phys_enc, phys_enc->hw_intf->idx);
448 
449 	_dpu_encoder_phys_cmd_pingpong_config(phys_enc);
450 
451 	if (!dpu_encoder_phys_cmd_is_master(phys_enc))
452 		return;
453 
454 	ctl = phys_enc->hw_ctl;
455 	ctl->ops.update_pending_flush_intf(ctl, phys_enc->hw_intf->idx);
456 }
457 
458 static void dpu_encoder_phys_cmd_enable(struct dpu_encoder_phys *phys_enc)
459 {
460 	struct dpu_encoder_phys_cmd *cmd_enc =
461 		to_dpu_encoder_phys_cmd(phys_enc);
462 
463 	if (!phys_enc->hw_pp) {
464 		DPU_ERROR("invalid phys encoder\n");
465 		return;
466 	}
467 
468 	DPU_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
469 
470 	if (phys_enc->enable_state == DPU_ENC_ENABLED) {
471 		DPU_ERROR("already enabled\n");
472 		return;
473 	}
474 
475 	dpu_encoder_phys_cmd_enable_helper(phys_enc);
476 	phys_enc->enable_state = DPU_ENC_ENABLED;
477 }
478 
479 static void _dpu_encoder_phys_cmd_connect_te(
480 		struct dpu_encoder_phys *phys_enc, bool enable)
481 {
482 	if (phys_enc->has_intf_te) {
483 		if (!phys_enc->hw_intf || !phys_enc->hw_intf->ops.connect_external_te)
484 			return;
485 
486 		trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable);
487 		phys_enc->hw_intf->ops.connect_external_te(phys_enc->hw_intf, enable);
488 	} else {
489 		if (!phys_enc->hw_pp || !phys_enc->hw_pp->ops.connect_external_te)
490 			return;
491 
492 		trace_dpu_enc_phys_cmd_connect_te(DRMID(phys_enc->parent), enable);
493 		phys_enc->hw_pp->ops.connect_external_te(phys_enc->hw_pp, enable);
494 	}
495 }
496 
497 static void dpu_encoder_phys_cmd_prepare_idle_pc(
498 		struct dpu_encoder_phys *phys_enc)
499 {
500 	_dpu_encoder_phys_cmd_connect_te(phys_enc, false);
501 }
502 
503 static int dpu_encoder_phys_cmd_get_line_count(
504 		struct dpu_encoder_phys *phys_enc)
505 {
506 	struct dpu_hw_pingpong *hw_pp;
507 	struct dpu_hw_intf *hw_intf;
508 
509 	if (!dpu_encoder_phys_cmd_is_master(phys_enc))
510 		return -EINVAL;
511 
512 	if (phys_enc->has_intf_te) {
513 		hw_intf = phys_enc->hw_intf;
514 		if (!hw_intf || !hw_intf->ops.get_line_count)
515 			return -EINVAL;
516 		return hw_intf->ops.get_line_count(hw_intf);
517 	}
518 
519 	hw_pp = phys_enc->hw_pp;
520 	if (!hw_pp || !hw_pp->ops.get_line_count)
521 		return -EINVAL;
522 	return hw_pp->ops.get_line_count(hw_pp);
523 }
524 
525 static void dpu_encoder_phys_cmd_disable(struct dpu_encoder_phys *phys_enc)
526 {
527 	struct dpu_encoder_phys_cmd *cmd_enc =
528 		to_dpu_encoder_phys_cmd(phys_enc);
529 	struct dpu_hw_ctl *ctl;
530 
531 	if (phys_enc->enable_state == DPU_ENC_DISABLED) {
532 		DPU_ERROR_CMDENC(cmd_enc, "already disabled\n");
533 		return;
534 	}
535 
536 	if (phys_enc->has_intf_te) {
537 		DRM_DEBUG_KMS("id:%u intf:%d state:%d\n", DRMID(phys_enc->parent),
538 			      phys_enc->hw_intf->idx - INTF_0,
539 			      phys_enc->enable_state);
540 
541 		if (phys_enc->hw_intf->ops.disable_tearcheck)
542 			phys_enc->hw_intf->ops.disable_tearcheck(phys_enc->hw_intf);
543 	} else {
544 		if (!phys_enc->hw_pp) {
545 			DPU_ERROR("invalid encoder\n");
546 			return;
547 		}
548 
549 		DRM_DEBUG_KMS("id:%u pp:%d state:%d\n", DRMID(phys_enc->parent),
550 			      phys_enc->hw_pp->idx - PINGPONG_0,
551 			      phys_enc->enable_state);
552 
553 		if (phys_enc->hw_pp->ops.disable_tearcheck)
554 			phys_enc->hw_pp->ops.disable_tearcheck(phys_enc->hw_pp);
555 	}
556 
557 	if (phys_enc->hw_intf->ops.bind_pingpong_blk) {
558 		phys_enc->hw_intf->ops.bind_pingpong_blk(
559 				phys_enc->hw_intf,
560 				PINGPONG_NONE);
561 
562 		ctl = phys_enc->hw_ctl;
563 		ctl->ops.update_pending_flush_intf(ctl, phys_enc->hw_intf->idx);
564 	}
565 
566 	phys_enc->enable_state = DPU_ENC_DISABLED;
567 }
568 
569 static void dpu_encoder_phys_cmd_prepare_for_kickoff(
570 		struct dpu_encoder_phys *phys_enc)
571 {
572 	struct dpu_encoder_phys_cmd *cmd_enc =
573 			to_dpu_encoder_phys_cmd(phys_enc);
574 	int ret;
575 
576 	if (!phys_enc->hw_pp) {
577 		DPU_ERROR("invalid encoder\n");
578 		return;
579 	}
580 	DRM_DEBUG_KMS("id:%u pp:%d pending_cnt:%d\n", DRMID(phys_enc->parent),
581 		      phys_enc->hw_pp->idx - PINGPONG_0,
582 		      atomic_read(&phys_enc->pending_kickoff_cnt));
583 
584 	/*
585 	 * Mark kickoff request as outstanding. If there are more than one,
586 	 * outstanding, then we have to wait for the previous one to complete
587 	 */
588 	ret = _dpu_encoder_phys_cmd_wait_for_idle(phys_enc);
589 	if (ret) {
590 		/* force pending_kickoff_cnt 0 to discard failed kickoff */
591 		atomic_set(&phys_enc->pending_kickoff_cnt, 0);
592 		DRM_ERROR("failed wait_for_idle: id:%u ret:%d pp:%d\n",
593 			  DRMID(phys_enc->parent), ret,
594 			  phys_enc->hw_pp->idx - PINGPONG_0);
595 	}
596 
597 	dpu_encoder_phys_cmd_enable_te(phys_enc);
598 
599 	DPU_DEBUG_CMDENC(cmd_enc, "pp:%d pending_cnt %d\n",
600 			phys_enc->hw_pp->idx - PINGPONG_0,
601 			atomic_read(&phys_enc->pending_kickoff_cnt));
602 }
603 
604 static void dpu_encoder_phys_cmd_enable_te(struct dpu_encoder_phys *phys_enc)
605 {
606 	if (!phys_enc)
607 		return;
608 	if (!dpu_encoder_phys_cmd_is_master(phys_enc))
609 		return;
610 
611 	if (phys_enc->has_intf_te) {
612 		if (!phys_enc->hw_intf->ops.disable_autorefresh)
613 			return;
614 
615 		phys_enc->hw_intf->ops.disable_autorefresh(
616 				phys_enc->hw_intf,
617 				DRMID(phys_enc->parent),
618 				phys_enc->cached_mode.vdisplay);
619 	} else {
620 		if (!phys_enc->hw_pp ||
621 		    !phys_enc->hw_pp->ops.disable_autorefresh)
622 			return;
623 
624 		phys_enc->hw_pp->ops.disable_autorefresh(
625 				phys_enc->hw_pp,
626 				DRMID(phys_enc->parent),
627 				phys_enc->cached_mode.vdisplay);
628 	}
629 }
630 
631 static int _dpu_encoder_phys_cmd_wait_for_ctl_start(
632 		struct dpu_encoder_phys *phys_enc)
633 {
634 	struct dpu_encoder_phys_cmd *cmd_enc =
635 			to_dpu_encoder_phys_cmd(phys_enc);
636 	struct dpu_encoder_wait_info wait_info;
637 	int ret;
638 
639 	wait_info.wq = &phys_enc->pending_kickoff_wq;
640 	wait_info.atomic_cnt = &phys_enc->pending_ctlstart_cnt;
641 	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
642 
643 	ret = dpu_encoder_helper_wait_for_irq(phys_enc,
644 			phys_enc->irq[INTR_IDX_CTL_START],
645 			dpu_encoder_phys_cmd_ctl_start_irq,
646 			&wait_info);
647 	if (ret == -ETIMEDOUT) {
648 		DPU_ERROR_CMDENC(cmd_enc, "ctl start interrupt wait failed\n");
649 		ret = -EINVAL;
650 	} else if (!ret)
651 		ret = 0;
652 
653 	return ret;
654 }
655 
656 static int dpu_encoder_phys_cmd_wait_for_tx_complete(
657 		struct dpu_encoder_phys *phys_enc)
658 {
659 	int rc;
660 
661 	rc = _dpu_encoder_phys_cmd_wait_for_idle(phys_enc);
662 	if (rc) {
663 		DRM_ERROR("failed wait_for_idle: id:%u ret:%d intf:%d\n",
664 			  DRMID(phys_enc->parent), rc,
665 			  phys_enc->hw_intf->idx - INTF_0);
666 	}
667 
668 	return rc;
669 }
670 
671 static int dpu_encoder_phys_cmd_wait_for_commit_done(
672 		struct dpu_encoder_phys *phys_enc)
673 {
674 	/* only required for master controller */
675 	if (!dpu_encoder_phys_cmd_is_master(phys_enc))
676 		return 0;
677 
678 	if (phys_enc->hw_ctl->ops.is_started(phys_enc->hw_ctl))
679 		return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc);
680 
681 	return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc);
682 }
683 
684 static void dpu_encoder_phys_cmd_handle_post_kickoff(
685 		struct dpu_encoder_phys *phys_enc)
686 {
687 	/**
688 	 * re-enable external TE, either for the first time after enabling
689 	 * or if disabled for Autorefresh
690 	 */
691 	_dpu_encoder_phys_cmd_connect_te(phys_enc, true);
692 }
693 
694 static void dpu_encoder_phys_cmd_trigger_start(
695 		struct dpu_encoder_phys *phys_enc)
696 {
697 	dpu_encoder_helper_trigger_start(phys_enc);
698 }
699 
700 static void dpu_encoder_phys_cmd_init_ops(
701 		struct dpu_encoder_phys_ops *ops)
702 {
703 	ops->is_master = dpu_encoder_phys_cmd_is_master;
704 	ops->enable = dpu_encoder_phys_cmd_enable;
705 	ops->disable = dpu_encoder_phys_cmd_disable;
706 	ops->control_vblank_irq = dpu_encoder_phys_cmd_control_vblank_irq;
707 	ops->wait_for_commit_done = dpu_encoder_phys_cmd_wait_for_commit_done;
708 	ops->prepare_for_kickoff = dpu_encoder_phys_cmd_prepare_for_kickoff;
709 	ops->wait_for_tx_complete = dpu_encoder_phys_cmd_wait_for_tx_complete;
710 	ops->trigger_start = dpu_encoder_phys_cmd_trigger_start;
711 	ops->needs_single_flush = dpu_encoder_phys_cmd_needs_single_flush;
712 	ops->irq_enable = dpu_encoder_phys_cmd_irq_enable;
713 	ops->irq_disable = dpu_encoder_phys_cmd_irq_disable;
714 	ops->restore = dpu_encoder_phys_cmd_enable_helper;
715 	ops->prepare_idle_pc = dpu_encoder_phys_cmd_prepare_idle_pc;
716 	ops->handle_post_kickoff = dpu_encoder_phys_cmd_handle_post_kickoff;
717 	ops->get_line_count = dpu_encoder_phys_cmd_get_line_count;
718 }
719 
720 struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev,
721 		struct dpu_enc_phys_init_params *p)
722 {
723 	struct dpu_encoder_phys *phys_enc = NULL;
724 	struct dpu_encoder_phys_cmd *cmd_enc = NULL;
725 
726 	DPU_DEBUG("intf\n");
727 
728 	cmd_enc = drmm_kzalloc(dev, sizeof(*cmd_enc), GFP_KERNEL);
729 	if (!cmd_enc) {
730 		DPU_ERROR("failed to allocate\n");
731 		return ERR_PTR(-ENOMEM);
732 	}
733 	phys_enc = &cmd_enc->base;
734 
735 	dpu_encoder_phys_init(phys_enc, p);
736 
737 	mutex_init(&phys_enc->vblank_ctl_lock);
738 	phys_enc->vblank_refcount = 0;
739 
740 	dpu_encoder_phys_cmd_init_ops(&phys_enc->ops);
741 	phys_enc->intf_mode = INTF_MODE_CMD;
742 	phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
743 
744 	cmd_enc->stream_sel = 0;
745 
746 	if (!phys_enc->hw_intf) {
747 		DPU_ERROR_CMDENC(cmd_enc, "no INTF provided\n");
748 		return ERR_PTR(-EINVAL);
749 	}
750 
751 	/* DPU before 5.0 use PINGPONG for TE handling */
752 	if (phys_enc->dpu_kms->catalog->mdss_ver->core_major_ver >= 5)
753 		phys_enc->has_intf_te = true;
754 
755 	if (phys_enc->has_intf_te && !phys_enc->hw_intf->ops.enable_tearcheck) {
756 		DPU_ERROR_CMDENC(cmd_enc, "tearcheck not supported\n");
757 		return ERR_PTR(-EINVAL);
758 	}
759 
760 	atomic_set(&cmd_enc->pending_vblank_cnt, 0);
761 	init_waitqueue_head(&cmd_enc->pending_vblank_wq);
762 
763 	DPU_DEBUG_CMDENC(cmd_enc, "created\n");
764 
765 	return phys_enc;
766 }
767