197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
225fdd593SJeykumar Sankaran /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
325fdd593SJeykumar Sankaran  */
425fdd593SJeykumar Sankaran 
525fdd593SJeykumar Sankaran #include <linux/iopoll.h>
625fdd593SJeykumar Sankaran 
725fdd593SJeykumar Sankaran #include "dpu_hw_mdss.h"
825fdd593SJeykumar Sankaran #include "dpu_hwio.h"
925fdd593SJeykumar Sankaran #include "dpu_hw_catalog.h"
1025fdd593SJeykumar Sankaran #include "dpu_hw_pingpong.h"
1125fdd593SJeykumar Sankaran #include "dpu_kms.h"
1225fdd593SJeykumar Sankaran #include "dpu_trace.h"
1325fdd593SJeykumar Sankaran 
1425fdd593SJeykumar Sankaran #define PP_TEAR_CHECK_EN                0x000
1525fdd593SJeykumar Sankaran #define PP_SYNC_CONFIG_VSYNC            0x004
1625fdd593SJeykumar Sankaran #define PP_SYNC_CONFIG_HEIGHT           0x008
1725fdd593SJeykumar Sankaran #define PP_SYNC_WRCOUNT                 0x00C
1825fdd593SJeykumar Sankaran #define PP_VSYNC_INIT_VAL               0x010
1925fdd593SJeykumar Sankaran #define PP_INT_COUNT_VAL                0x014
2025fdd593SJeykumar Sankaran #define PP_SYNC_THRESH                  0x018
2125fdd593SJeykumar Sankaran #define PP_START_POS                    0x01C
2225fdd593SJeykumar Sankaran #define PP_RD_PTR_IRQ                   0x020
2325fdd593SJeykumar Sankaran #define PP_WR_PTR_IRQ                   0x024
2425fdd593SJeykumar Sankaran #define PP_OUT_LINE_COUNT               0x028
2525fdd593SJeykumar Sankaran #define PP_LINE_COUNT                   0x02C
26aa9223a6SAngeloGioacchino Del Regno #define PP_AUTOREFRESH_CONFIG           0x030
2725fdd593SJeykumar Sankaran 
2825fdd593SJeykumar Sankaran #define PP_FBC_MODE                     0x034
2925fdd593SJeykumar Sankaran #define PP_FBC_BUDGET_CTL               0x038
3025fdd593SJeykumar Sankaran #define PP_FBC_LOSSY_MODE               0x03C
31893d6982SVinod Koul #define PP_DSC_MODE                     0x0a0
32893d6982SVinod Koul #define PP_DCE_DATA_IN_SWAP             0x0ac
33893d6982SVinod Koul #define PP_DCE_DATA_OUT_SWAP            0x0c8
3425fdd593SJeykumar Sankaran 
353c128638SKalyan Thota #define PP_DITHER_EN			0x000
363c128638SKalyan Thota #define PP_DITHER_BITDEPTH		0x004
373c128638SKalyan Thota #define PP_DITHER_MATRIX		0x008
383c128638SKalyan Thota 
393c128638SKalyan Thota #define DITHER_DEPTH_MAP_INDEX 9
403c128638SKalyan Thota 
413c128638SKalyan Thota static u32 dither_depth_map[DITHER_DEPTH_MAP_INDEX] = {
423c128638SKalyan Thota 	0, 0, 0, 0, 0, 0, 0, 1, 2
433c128638SKalyan Thota };
443c128638SKalyan Thota 
dpu_hw_pp_setup_dither(struct dpu_hw_pingpong * pp,struct dpu_hw_dither_cfg * cfg)453c128638SKalyan Thota static void dpu_hw_pp_setup_dither(struct dpu_hw_pingpong *pp,
463c128638SKalyan Thota 				    struct dpu_hw_dither_cfg *cfg)
473c128638SKalyan Thota {
483c128638SKalyan Thota 	struct dpu_hw_blk_reg_map *c;
493c128638SKalyan Thota 	u32 i, base, data = 0;
503c128638SKalyan Thota 
513c128638SKalyan Thota 	c = &pp->hw;
523c128638SKalyan Thota 	base = pp->caps->sblk->dither.base;
533c128638SKalyan Thota 	if (!cfg) {
543c128638SKalyan Thota 		DPU_REG_WRITE(c, base + PP_DITHER_EN, 0);
553c128638SKalyan Thota 		return;
563c128638SKalyan Thota 	}
573c128638SKalyan Thota 
583c128638SKalyan Thota 	data = dither_depth_map[cfg->c0_bitdepth] & REG_MASK(2);
593c128638SKalyan Thota 	data |= (dither_depth_map[cfg->c1_bitdepth] & REG_MASK(2)) << 2;
603c128638SKalyan Thota 	data |= (dither_depth_map[cfg->c2_bitdepth] & REG_MASK(2)) << 4;
613c128638SKalyan Thota 	data |= (dither_depth_map[cfg->c3_bitdepth] & REG_MASK(2)) << 6;
623c128638SKalyan Thota 	data |= (cfg->temporal_en) ? (1 << 8) : 0;
633c128638SKalyan Thota 
643c128638SKalyan Thota 	DPU_REG_WRITE(c, base + PP_DITHER_BITDEPTH, data);
653c128638SKalyan Thota 
663c128638SKalyan Thota 	for (i = 0; i < DITHER_MATRIX_SZ - 3; i += 4) {
673c128638SKalyan Thota 		data = (cfg->matrix[i] & REG_MASK(4)) |
683c128638SKalyan Thota 			((cfg->matrix[i + 1] & REG_MASK(4)) << 4) |
693c128638SKalyan Thota 			((cfg->matrix[i + 2] & REG_MASK(4)) << 8) |
703c128638SKalyan Thota 			((cfg->matrix[i + 3] & REG_MASK(4)) << 12);
713c128638SKalyan Thota 		DPU_REG_WRITE(c, base + PP_DITHER_MATRIX + i, data);
723c128638SKalyan Thota 	}
733c128638SKalyan Thota 	DPU_REG_WRITE(c, base + PP_DITHER_EN, 1);
743c128638SKalyan Thota }
753c128638SKalyan Thota 
dpu_hw_pp_enable_te(struct dpu_hw_pingpong * pp,struct dpu_hw_tear_check * te)76bb9f1880SMarijn Suijten static int dpu_hw_pp_enable_te(struct dpu_hw_pingpong *pp,
7725fdd593SJeykumar Sankaran 		struct dpu_hw_tear_check *te)
7825fdd593SJeykumar Sankaran {
7925fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c;
8025fdd593SJeykumar Sankaran 	int cfg;
8125fdd593SJeykumar Sankaran 
8225fdd593SJeykumar Sankaran 	if (!pp || !te)
8325fdd593SJeykumar Sankaran 		return -EINVAL;
8425fdd593SJeykumar Sankaran 	c = &pp->hw;
8525fdd593SJeykumar Sankaran 
8625fdd593SJeykumar Sankaran 	cfg = BIT(19); /*VSYNC_COUNTER_EN */
8725fdd593SJeykumar Sankaran 	if (te->hw_vsync_mode)
8825fdd593SJeykumar Sankaran 		cfg |= BIT(20);
8925fdd593SJeykumar Sankaran 
9025fdd593SJeykumar Sankaran 	cfg |= te->vsync_count;
9125fdd593SJeykumar Sankaran 
9225fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, PP_SYNC_CONFIG_VSYNC, cfg);
9325fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, PP_SYNC_CONFIG_HEIGHT, te->sync_cfg_height);
9425fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, PP_VSYNC_INIT_VAL, te->vsync_init_val);
9525fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, PP_RD_PTR_IRQ, te->rd_ptr_irq);
9625fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, PP_START_POS, te->start_pos);
9725fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, PP_SYNC_THRESH,
9825fdd593SJeykumar Sankaran 			((te->sync_threshold_continue << 16) |
9925fdd593SJeykumar Sankaran 			 te->sync_threshold_start));
10025fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, PP_SYNC_WRCOUNT,
10125fdd593SJeykumar Sankaran 			(te->start_pos + te->sync_threshold_start + 1));
10225fdd593SJeykumar Sankaran 
103bb9f1880SMarijn Suijten 	DPU_REG_WRITE(c, PP_TEAR_CHECK_EN, 1);
104bb9f1880SMarijn Suijten 
10525fdd593SJeykumar Sankaran 	return 0;
10625fdd593SJeykumar Sankaran }
10725fdd593SJeykumar Sankaran 
dpu_hw_pp_setup_autorefresh_config(struct dpu_hw_pingpong * pp,u32 frame_count,bool enable)108aa9223a6SAngeloGioacchino Del Regno static void dpu_hw_pp_setup_autorefresh_config(struct dpu_hw_pingpong *pp,
109aa9223a6SAngeloGioacchino Del Regno 					       u32 frame_count, bool enable)
110aa9223a6SAngeloGioacchino Del Regno {
111aa9223a6SAngeloGioacchino Del Regno 	DPU_REG_WRITE(&pp->hw, PP_AUTOREFRESH_CONFIG,
112aa9223a6SAngeloGioacchino Del Regno 		      enable ? (BIT(31) | frame_count) : 0);
113aa9223a6SAngeloGioacchino Del Regno }
114aa9223a6SAngeloGioacchino Del Regno 
115aa9223a6SAngeloGioacchino Del Regno /*
116aa9223a6SAngeloGioacchino Del Regno  * dpu_hw_pp_get_autorefresh_config - Get autorefresh config from HW
117aa9223a6SAngeloGioacchino Del Regno  * @pp:          DPU pingpong structure
118aa9223a6SAngeloGioacchino Del Regno  * @frame_count: Used to return the current frame count from hw
119aa9223a6SAngeloGioacchino Del Regno  *
120aa9223a6SAngeloGioacchino Del Regno  * Returns: True if autorefresh enabled, false if disabled.
121aa9223a6SAngeloGioacchino Del Regno  */
dpu_hw_pp_get_autorefresh_config(struct dpu_hw_pingpong * pp,u32 * frame_count)122aa9223a6SAngeloGioacchino Del Regno static bool dpu_hw_pp_get_autorefresh_config(struct dpu_hw_pingpong *pp,
123aa9223a6SAngeloGioacchino Del Regno 					     u32 *frame_count)
124aa9223a6SAngeloGioacchino Del Regno {
125aa9223a6SAngeloGioacchino Del Regno 	u32 val = DPU_REG_READ(&pp->hw, PP_AUTOREFRESH_CONFIG);
126aa9223a6SAngeloGioacchino Del Regno 	if (frame_count != NULL)
127aa9223a6SAngeloGioacchino Del Regno 		*frame_count = val & 0xffff;
128aa9223a6SAngeloGioacchino Del Regno 	return !!((val & BIT(31)) >> 31);
129aa9223a6SAngeloGioacchino Del Regno }
130aa9223a6SAngeloGioacchino Del Regno 
dpu_hw_pp_disable_te(struct dpu_hw_pingpong * pp)131bb9f1880SMarijn Suijten static int dpu_hw_pp_disable_te(struct dpu_hw_pingpong *pp)
13225fdd593SJeykumar Sankaran {
13325fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c;
13425fdd593SJeykumar Sankaran 
13525fdd593SJeykumar Sankaran 	if (!pp)
13625fdd593SJeykumar Sankaran 		return -EINVAL;
13725fdd593SJeykumar Sankaran 	c = &pp->hw;
13825fdd593SJeykumar Sankaran 
139bb9f1880SMarijn Suijten 	DPU_REG_WRITE(c, PP_TEAR_CHECK_EN, 0);
14025fdd593SJeykumar Sankaran 	return 0;
14125fdd593SJeykumar Sankaran }
14225fdd593SJeykumar Sankaran 
dpu_hw_pp_connect_external_te(struct dpu_hw_pingpong * pp,bool enable_external_te)14325fdd593SJeykumar Sankaran static int dpu_hw_pp_connect_external_te(struct dpu_hw_pingpong *pp,
14425fdd593SJeykumar Sankaran 		bool enable_external_te)
14525fdd593SJeykumar Sankaran {
14625fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &pp->hw;
14725fdd593SJeykumar Sankaran 	u32 cfg;
14825fdd593SJeykumar Sankaran 	int orig;
14925fdd593SJeykumar Sankaran 
15025fdd593SJeykumar Sankaran 	if (!pp)
15125fdd593SJeykumar Sankaran 		return -EINVAL;
15225fdd593SJeykumar Sankaran 
15325fdd593SJeykumar Sankaran 	c = &pp->hw;
15425fdd593SJeykumar Sankaran 	cfg = DPU_REG_READ(c, PP_SYNC_CONFIG_VSYNC);
15525fdd593SJeykumar Sankaran 	orig = (bool)(cfg & BIT(20));
15625fdd593SJeykumar Sankaran 	if (enable_external_te)
15725fdd593SJeykumar Sankaran 		cfg |= BIT(20);
15825fdd593SJeykumar Sankaran 	else
15925fdd593SJeykumar Sankaran 		cfg &= ~BIT(20);
16025fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, PP_SYNC_CONFIG_VSYNC, cfg);
16125fdd593SJeykumar Sankaran 	trace_dpu_pp_connect_ext_te(pp->idx - PINGPONG_0, cfg);
16225fdd593SJeykumar Sankaran 
16325fdd593SJeykumar Sankaran 	return orig;
16425fdd593SJeykumar Sankaran }
16525fdd593SJeykumar Sankaran 
dpu_hw_pp_get_vsync_info(struct dpu_hw_pingpong * pp,struct dpu_hw_pp_vsync_info * info)16625fdd593SJeykumar Sankaran static int dpu_hw_pp_get_vsync_info(struct dpu_hw_pingpong *pp,
16725fdd593SJeykumar Sankaran 		struct dpu_hw_pp_vsync_info *info)
16825fdd593SJeykumar Sankaran {
16925fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c;
17025fdd593SJeykumar Sankaran 	u32 val;
17125fdd593SJeykumar Sankaran 
17225fdd593SJeykumar Sankaran 	if (!pp || !info)
17325fdd593SJeykumar Sankaran 		return -EINVAL;
17425fdd593SJeykumar Sankaran 	c = &pp->hw;
17525fdd593SJeykumar Sankaran 
17625fdd593SJeykumar Sankaran 	val = DPU_REG_READ(c, PP_VSYNC_INIT_VAL);
17725fdd593SJeykumar Sankaran 	info->rd_ptr_init_val = val & 0xffff;
17825fdd593SJeykumar Sankaran 
17925fdd593SJeykumar Sankaran 	val = DPU_REG_READ(c, PP_INT_COUNT_VAL);
18025fdd593SJeykumar Sankaran 	info->rd_ptr_frame_count = (val & 0xffff0000) >> 16;
18125fdd593SJeykumar Sankaran 	info->rd_ptr_line_count = val & 0xffff;
18225fdd593SJeykumar Sankaran 
18325fdd593SJeykumar Sankaran 	val = DPU_REG_READ(c, PP_LINE_COUNT);
18425fdd593SJeykumar Sankaran 	info->wr_ptr_line_count = val & 0xffff;
18525fdd593SJeykumar Sankaran 
18625fdd593SJeykumar Sankaran 	return 0;
18725fdd593SJeykumar Sankaran }
18825fdd593SJeykumar Sankaran 
dpu_hw_pp_get_line_count(struct dpu_hw_pingpong * pp)18925fdd593SJeykumar Sankaran static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong *pp)
19025fdd593SJeykumar Sankaran {
19125fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &pp->hw;
19225fdd593SJeykumar Sankaran 	u32 height, init;
19325fdd593SJeykumar Sankaran 	u32 line = 0xFFFF;
19425fdd593SJeykumar Sankaran 
19525fdd593SJeykumar Sankaran 	if (!pp)
19625fdd593SJeykumar Sankaran 		return 0;
19725fdd593SJeykumar Sankaran 	c = &pp->hw;
19825fdd593SJeykumar Sankaran 
19925fdd593SJeykumar Sankaran 	init = DPU_REG_READ(c, PP_VSYNC_INIT_VAL) & 0xFFFF;
20025fdd593SJeykumar Sankaran 	height = DPU_REG_READ(c, PP_SYNC_CONFIG_HEIGHT) & 0xFFFF;
20125fdd593SJeykumar Sankaran 
20225fdd593SJeykumar Sankaran 	if (height < init)
2030841851fSSean Paul 		return line;
20425fdd593SJeykumar Sankaran 
20525fdd593SJeykumar Sankaran 	line = DPU_REG_READ(c, PP_INT_COUNT_VAL) & 0xFFFF;
20625fdd593SJeykumar Sankaran 
20725fdd593SJeykumar Sankaran 	if (line < init)
20825fdd593SJeykumar Sankaran 		line += (0xFFFF - init);
20925fdd593SJeykumar Sankaran 	else
21025fdd593SJeykumar Sankaran 		line -= init;
21125fdd593SJeykumar Sankaran 
21225fdd593SJeykumar Sankaran 	return line;
21325fdd593SJeykumar Sankaran }
21425fdd593SJeykumar Sankaran 
dpu_hw_pp_disable_autorefresh(struct dpu_hw_pingpong * pp,uint32_t encoder_id,u16 vdisplay)2154a7c38ecSMarijn Suijten static void dpu_hw_pp_disable_autorefresh(struct dpu_hw_pingpong *pp,
2164a7c38ecSMarijn Suijten 					  uint32_t encoder_id, u16 vdisplay)
2174a7c38ecSMarijn Suijten {
2184a7c38ecSMarijn Suijten 	struct dpu_hw_pp_vsync_info info;
2194a7c38ecSMarijn Suijten 	int trial = 0;
2204a7c38ecSMarijn Suijten 
2214a7c38ecSMarijn Suijten 	/* If autorefresh is already disabled, we have nothing to do */
2224a7c38ecSMarijn Suijten 	if (!dpu_hw_pp_get_autorefresh_config(pp, NULL))
2234a7c38ecSMarijn Suijten 		return;
2244a7c38ecSMarijn Suijten 
2254a7c38ecSMarijn Suijten 	/*
2264a7c38ecSMarijn Suijten 	 * If autorefresh is enabled, disable it and make sure it is safe to
2274a7c38ecSMarijn Suijten 	 * proceed with current frame commit/push. Sequence followed is,
2284a7c38ecSMarijn Suijten 	 * 1. Disable TE
2294a7c38ecSMarijn Suijten 	 * 2. Disable autorefresh config
2304a7c38ecSMarijn Suijten 	 * 4. Poll for frame transfer ongoing to be false
2314a7c38ecSMarijn Suijten 	 * 5. Enable TE back
2324a7c38ecSMarijn Suijten 	 */
2334a7c38ecSMarijn Suijten 
2344a7c38ecSMarijn Suijten 	dpu_hw_pp_connect_external_te(pp, false);
2354a7c38ecSMarijn Suijten 	dpu_hw_pp_setup_autorefresh_config(pp, 0, false);
2364a7c38ecSMarijn Suijten 
2374a7c38ecSMarijn Suijten 	do {
2384a7c38ecSMarijn Suijten 		udelay(DPU_ENC_MAX_POLL_TIMEOUT_US);
2394a7c38ecSMarijn Suijten 		if ((trial * DPU_ENC_MAX_POLL_TIMEOUT_US)
2404a7c38ecSMarijn Suijten 				> (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) {
2414a7c38ecSMarijn Suijten 			DPU_ERROR("enc%d pp%d disable autorefresh failed\n",
2424a7c38ecSMarijn Suijten 				  encoder_id, pp->idx - PINGPONG_0);
2434a7c38ecSMarijn Suijten 			break;
2444a7c38ecSMarijn Suijten 		}
2454a7c38ecSMarijn Suijten 
2464a7c38ecSMarijn Suijten 		trial++;
2474a7c38ecSMarijn Suijten 
2484a7c38ecSMarijn Suijten 		dpu_hw_pp_get_vsync_info(pp, &info);
2494a7c38ecSMarijn Suijten 	} while (info.wr_ptr_line_count > 0 &&
2504a7c38ecSMarijn Suijten 		 info.wr_ptr_line_count < vdisplay);
2514a7c38ecSMarijn Suijten 
2524a7c38ecSMarijn Suijten 	dpu_hw_pp_connect_external_te(pp, true);
2534a7c38ecSMarijn Suijten 
2544a7c38ecSMarijn Suijten 	DPU_DEBUG("enc%d pp%d disabled autorefresh\n",
2554a7c38ecSMarijn Suijten 		  encoder_id, pp->idx - PINGPONG_0);
2564a7c38ecSMarijn Suijten }
2574a7c38ecSMarijn Suijten 
dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong * pp)258893d6982SVinod Koul static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
259893d6982SVinod Koul {
260893d6982SVinod Koul 	struct dpu_hw_blk_reg_map *c = &pp->hw;
261893d6982SVinod Koul 
262893d6982SVinod Koul 	DPU_REG_WRITE(c, PP_DSC_MODE, 1);
263893d6982SVinod Koul 	return 0;
264893d6982SVinod Koul }
265893d6982SVinod Koul 
dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong * pp)266893d6982SVinod Koul static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
267893d6982SVinod Koul {
268893d6982SVinod Koul 	struct dpu_hw_blk_reg_map *c = &pp->hw;
269893d6982SVinod Koul 
270893d6982SVinod Koul 	DPU_REG_WRITE(c, PP_DSC_MODE, 0);
271893d6982SVinod Koul }
272893d6982SVinod Koul 
dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong * pp)273893d6982SVinod Koul static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
274893d6982SVinod Koul {
275893d6982SVinod Koul 	struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
276893d6982SVinod Koul 	int data;
277893d6982SVinod Koul 
278893d6982SVinod Koul 	data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
279893d6982SVinod Koul 	data |= BIT(18); /* endian flip */
280893d6982SVinod Koul 	DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
281893d6982SVinod Koul 	return 0;
282893d6982SVinod Koul }
283893d6982SVinod Koul 
_setup_pingpong_ops(struct dpu_hw_pingpong * c,unsigned long features)2843c128638SKalyan Thota static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
2853c128638SKalyan Thota 				unsigned long features)
28625fdd593SJeykumar Sankaran {
287fe9d66cfSMarijn Suijten 	if (test_bit(DPU_PINGPONG_TE, &features)) {
2883c128638SKalyan Thota 		c->ops.enable_tearcheck = dpu_hw_pp_enable_te;
289bb9f1880SMarijn Suijten 		c->ops.disable_tearcheck = dpu_hw_pp_disable_te;
2903c128638SKalyan Thota 		c->ops.connect_external_te = dpu_hw_pp_connect_external_te;
2913c128638SKalyan Thota 		c->ops.get_line_count = dpu_hw_pp_get_line_count;
2924a7c38ecSMarijn Suijten 		c->ops.disable_autorefresh = dpu_hw_pp_disable_autorefresh;
293fe9d66cfSMarijn Suijten 	}
294*108ff141SKuogee Hsieh 
295*108ff141SKuogee Hsieh 	if (test_bit(DPU_PINGPONG_DSC, &features)) {
296893d6982SVinod Koul 		c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
297893d6982SVinod Koul 		c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
298893d6982SVinod Koul 		c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
299*108ff141SKuogee Hsieh 	}
3003c128638SKalyan Thota 
301b8afe9f8SRob Clark 	if (test_bit(DPU_PINGPONG_DITHER, &features))
3023c128638SKalyan Thota 		c->ops.setup_dither = dpu_hw_pp_setup_dither;
30325fdd593SJeykumar Sankaran };
30425fdd593SJeykumar Sankaran 
dpu_hw_pingpong_init(const struct dpu_pingpong_cfg * cfg,void __iomem * addr)305babdb815SMarijn Suijten struct dpu_hw_pingpong *dpu_hw_pingpong_init(const struct dpu_pingpong_cfg *cfg,
306babdb815SMarijn Suijten 		void __iomem *addr)
30725fdd593SJeykumar Sankaran {
30825fdd593SJeykumar Sankaran 	struct dpu_hw_pingpong *c;
30925fdd593SJeykumar Sankaran 
31025fdd593SJeykumar Sankaran 	c = kzalloc(sizeof(*c), GFP_KERNEL);
31125fdd593SJeykumar Sankaran 	if (!c)
31225fdd593SJeykumar Sankaran 		return ERR_PTR(-ENOMEM);
31325fdd593SJeykumar Sankaran 
314babdb815SMarijn Suijten 	c->hw.blk_addr = addr + cfg->base;
315babdb815SMarijn Suijten 	c->hw.log_mask = DPU_DBG_MASK_PINGPONG;
31625fdd593SJeykumar Sankaran 
317babdb815SMarijn Suijten 	c->idx = cfg->id;
31825fdd593SJeykumar Sankaran 	c->caps = cfg;
3193c128638SKalyan Thota 	_setup_pingpong_ops(c, c->caps->features);
32025fdd593SJeykumar Sankaran 
32125fdd593SJeykumar Sankaran 	return c;
32225fdd593SJeykumar Sankaran }
32325fdd593SJeykumar Sankaran 
dpu_hw_pingpong_destroy(struct dpu_hw_pingpong * pp)32425fdd593SJeykumar Sankaran void dpu_hw_pingpong_destroy(struct dpu_hw_pingpong *pp)
32525fdd593SJeykumar Sankaran {
32625fdd593SJeykumar Sankaran 	kfree(pp);
32725fdd593SJeykumar Sankaran }
328