brintos

brintos / linux-shallow public Read only

0
0
Text · 20.1 KiB · 2e50049 Raw
762 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.4 */5 6#include <linux/delay.h>7 8#include <drm/drm_managed.h>9 10#include "dpu_hwio.h"11#include "dpu_hw_ctl.h"12#include "dpu_kms.h"13#include "dpu_trace.h"14 15#define   CTL_LAYER(lm)                 \16	(((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004))17#define   CTL_LAYER_EXT(lm)             \18	(0x40 + (((lm) - LM_0) * 0x004))19#define   CTL_LAYER_EXT2(lm)             \20	(0x70 + (((lm) - LM_0) * 0x004))21#define   CTL_LAYER_EXT3(lm)             \22	(0xA0 + (((lm) - LM_0) * 0x004))23#define CTL_LAYER_EXT4(lm)             \24	(0xB8 + (((lm) - LM_0) * 0x004))25#define   CTL_TOP                       0x01426#define   CTL_FLUSH                     0x01827#define   CTL_START                     0x01C28#define   CTL_PREPARE                   0x0d029#define   CTL_SW_RESET                  0x03030#define   CTL_LAYER_EXTN_OFFSET         0x4031#define   CTL_MERGE_3D_ACTIVE           0x0E432#define   CTL_DSC_ACTIVE                0x0E833#define   CTL_WB_ACTIVE                 0x0EC34#define   CTL_INTF_ACTIVE               0x0F435#define   CTL_CDM_ACTIVE                0x0F836#define   CTL_FETCH_PIPE_ACTIVE         0x0FC37#define   CTL_MERGE_3D_FLUSH            0x10038#define   CTL_DSC_FLUSH                0x10439#define   CTL_WB_FLUSH                  0x10840#define   CTL_INTF_FLUSH                0x11041#define   CTL_CDM_FLUSH                0x11442#define   CTL_PERIPH_FLUSH              0x12843#define   CTL_INTF_MASTER               0x13444#define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))45 46#define CTL_MIXER_BORDER_OUT            BIT(24)47#define CTL_FLUSH_MASK_CTL              BIT(17)48 49#define DPU_REG_RESET_TIMEOUT_US        200050#define  MERGE_3D_IDX   2351#define  DSC_IDX        2252#define CDM_IDX         2653#define  PERIPH_IDX     3054#define  INTF_IDX       3155#define WB_IDX          1656#define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */57#define CTL_INVALID_BIT                 0xffff58#define CTL_DEFAULT_GROUP_ID		0xf59 60static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19,61	CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0,62	1, 2, 3, 4, 5};63 64static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count,65		enum dpu_lm lm)66{67	int i;68	int stages = -EINVAL;69 70	for (i = 0; i < count; i++) {71		if (lm == mixer[i].id) {72			stages = mixer[i].sblk->maxblendstages;73			break;74		}75	}76 77	return stages;78}79 80static inline u32 dpu_hw_ctl_get_flush_register(struct dpu_hw_ctl *ctx)81{82	struct dpu_hw_blk_reg_map *c = &ctx->hw;83 84	return DPU_REG_READ(c, CTL_FLUSH);85}86 87static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx)88{89	trace_dpu_hw_ctl_trigger_start(ctx->pending_flush_mask,90				       dpu_hw_ctl_get_flush_register(ctx));91	DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1);92}93 94static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx)95{96	return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0));97}98 99static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx)100{101	trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask,102					 dpu_hw_ctl_get_flush_register(ctx));103	DPU_REG_WRITE(&ctx->hw, CTL_PREPARE, 0x1);104}105 106static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)107{108	trace_dpu_hw_ctl_clear_pending_flush(ctx->pending_flush_mask,109				     dpu_hw_ctl_get_flush_register(ctx));110	ctx->pending_flush_mask = 0x0;111	ctx->pending_intf_flush_mask = 0;112	ctx->pending_wb_flush_mask = 0;113	ctx->pending_merge_3d_flush_mask = 0;114	ctx->pending_dsc_flush_mask = 0;115	ctx->pending_cdm_flush_mask = 0;116 117	memset(ctx->pending_dspp_flush_mask, 0,118		sizeof(ctx->pending_dspp_flush_mask));119}120 121static inline void dpu_hw_ctl_update_pending_flush(struct dpu_hw_ctl *ctx,122		u32 flushbits)123{124	trace_dpu_hw_ctl_update_pending_flush(flushbits,125					      ctx->pending_flush_mask);126	ctx->pending_flush_mask |= flushbits;127}128 129static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)130{131	return ctx->pending_flush_mask;132}133 134static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)135{136	int dspp;137 138	if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))139		DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,140				ctx->pending_merge_3d_flush_mask);141	if (ctx->pending_flush_mask & BIT(INTF_IDX))142		DPU_REG_WRITE(&ctx->hw, CTL_INTF_FLUSH,143				ctx->pending_intf_flush_mask);144	if (ctx->pending_flush_mask & BIT(WB_IDX))145		DPU_REG_WRITE(&ctx->hw, CTL_WB_FLUSH,146				ctx->pending_wb_flush_mask);147 148	if (ctx->pending_flush_mask & BIT(DSPP_IDX))149		for (dspp = DSPP_0; dspp < DSPP_MAX; dspp++) {150			if (ctx->pending_dspp_flush_mask[dspp - DSPP_0])151				DPU_REG_WRITE(&ctx->hw,152				CTL_DSPP_n_FLUSH(dspp - DSPP_0),153				ctx->pending_dspp_flush_mask[dspp - DSPP_0]);154		}155 156	if (ctx->pending_flush_mask & BIT(PERIPH_IDX))157		DPU_REG_WRITE(&ctx->hw, CTL_PERIPH_FLUSH,158			      ctx->pending_periph_flush_mask);159 160	if (ctx->pending_flush_mask & BIT(DSC_IDX))161		DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,162			      ctx->pending_dsc_flush_mask);163 164	if (ctx->pending_flush_mask & BIT(CDM_IDX))165		DPU_REG_WRITE(&ctx->hw, CTL_CDM_FLUSH,166			      ctx->pending_cdm_flush_mask);167 168	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);169}170 171static inline void dpu_hw_ctl_trigger_flush(struct dpu_hw_ctl *ctx)172{173	trace_dpu_hw_ctl_trigger_pending_flush(ctx->pending_flush_mask,174				     dpu_hw_ctl_get_flush_register(ctx));175	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);176}177 178static void dpu_hw_ctl_update_pending_flush_sspp(struct dpu_hw_ctl *ctx,179	enum dpu_sspp sspp)180{181	switch (sspp) {182	case SSPP_VIG0:183		ctx->pending_flush_mask |=  BIT(0);184		break;185	case SSPP_VIG1:186		ctx->pending_flush_mask |= BIT(1);187		break;188	case SSPP_VIG2:189		ctx->pending_flush_mask |= BIT(2);190		break;191	case SSPP_VIG3:192		ctx->pending_flush_mask |= BIT(18);193		break;194	case SSPP_RGB0:195		ctx->pending_flush_mask |= BIT(3);196		break;197	case SSPP_RGB1:198		ctx->pending_flush_mask |= BIT(4);199		break;200	case SSPP_RGB2:201		ctx->pending_flush_mask |= BIT(5);202		break;203	case SSPP_RGB3:204		ctx->pending_flush_mask |= BIT(19);205		break;206	case SSPP_DMA0:207		ctx->pending_flush_mask |= BIT(11);208		break;209	case SSPP_DMA1:210		ctx->pending_flush_mask |= BIT(12);211		break;212	case SSPP_DMA2:213		ctx->pending_flush_mask |= BIT(24);214		break;215	case SSPP_DMA3:216		ctx->pending_flush_mask |= BIT(25);217		break;218	case SSPP_DMA4:219		ctx->pending_flush_mask |= BIT(13);220		break;221	case SSPP_DMA5:222		ctx->pending_flush_mask |= BIT(14);223		break;224	case SSPP_CURSOR0:225		ctx->pending_flush_mask |= BIT(22);226		break;227	case SSPP_CURSOR1:228		ctx->pending_flush_mask |= BIT(23);229		break;230	default:231		break;232	}233}234 235static void dpu_hw_ctl_update_pending_flush_mixer(struct dpu_hw_ctl *ctx,236	enum dpu_lm lm)237{238	switch (lm) {239	case LM_0:240		ctx->pending_flush_mask |= BIT(6);241		break;242	case LM_1:243		ctx->pending_flush_mask |= BIT(7);244		break;245	case LM_2:246		ctx->pending_flush_mask |= BIT(8);247		break;248	case LM_3:249		ctx->pending_flush_mask |= BIT(9);250		break;251	case LM_4:252		ctx->pending_flush_mask |= BIT(10);253		break;254	case LM_5:255		ctx->pending_flush_mask |= BIT(20);256		break;257	default:258		break;259	}260 261	ctx->pending_flush_mask |= CTL_FLUSH_MASK_CTL;262}263 264static void dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,265		enum dpu_intf intf)266{267	switch (intf) {268	case INTF_0:269		ctx->pending_flush_mask |= BIT(31);270		break;271	case INTF_1:272		ctx->pending_flush_mask |= BIT(30);273		break;274	case INTF_2:275		ctx->pending_flush_mask |= BIT(29);276		break;277	case INTF_3:278		ctx->pending_flush_mask |= BIT(28);279		break;280	default:281		break;282	}283}284 285static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,286		enum dpu_wb wb)287{288	switch (wb) {289	case WB_0:290	case WB_1:291	case WB_2:292		ctx->pending_flush_mask |= BIT(WB_IDX);293		break;294	default:295		break;296	}297}298 299static void dpu_hw_ctl_update_pending_flush_cdm(struct dpu_hw_ctl *ctx, enum dpu_cdm cdm_num)300{301	/* update pending flush only if CDM_0 is flushed */302	if (cdm_num == CDM_0)303		ctx->pending_flush_mask |= BIT(CDM_IDX);304}305 306static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,307		enum dpu_wb wb)308{309	ctx->pending_wb_flush_mask |= BIT(wb - WB_0);310	ctx->pending_flush_mask |= BIT(WB_IDX);311}312 313static void dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,314		enum dpu_intf intf)315{316	ctx->pending_intf_flush_mask |= BIT(intf - INTF_0);317	ctx->pending_flush_mask |= BIT(INTF_IDX);318}319 320static void dpu_hw_ctl_update_pending_flush_periph_v1(struct dpu_hw_ctl *ctx,321						      enum dpu_intf intf)322{323	ctx->pending_periph_flush_mask |= BIT(intf - INTF_0);324	ctx->pending_flush_mask |= BIT(PERIPH_IDX);325}326 327static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,328		enum dpu_merge_3d merge_3d)329{330	ctx->pending_merge_3d_flush_mask |= BIT(merge_3d - MERGE_3D_0);331	ctx->pending_flush_mask |= BIT(MERGE_3D_IDX);332}333 334static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,335						   enum dpu_dsc dsc_num)336{337	ctx->pending_dsc_flush_mask |= BIT(dsc_num - DSC_0);338	ctx->pending_flush_mask |= BIT(DSC_IDX);339}340 341static void dpu_hw_ctl_update_pending_flush_cdm_v1(struct dpu_hw_ctl *ctx, enum dpu_cdm cdm_num)342{343	ctx->pending_cdm_flush_mask |= BIT(cdm_num - CDM_0);344	ctx->pending_flush_mask |= BIT(CDM_IDX);345}346 347static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,348	enum dpu_dspp dspp, u32 dspp_sub_blk)349{350	switch (dspp) {351	case DSPP_0:352		ctx->pending_flush_mask |= BIT(13);353		break;354	case DSPP_1:355		ctx->pending_flush_mask |= BIT(14);356		break;357	case DSPP_2:358		ctx->pending_flush_mask |= BIT(15);359		break;360	case DSPP_3:361		ctx->pending_flush_mask |= BIT(21);362		break;363	default:364		break;365	}366}367 368static void dpu_hw_ctl_update_pending_flush_dspp_sub_blocks(369	struct dpu_hw_ctl *ctx,	enum dpu_dspp dspp, u32 dspp_sub_blk)370{371	if (dspp >= DSPP_MAX)372		return;373 374	switch (dspp_sub_blk) {375	case DPU_DSPP_PCC:376		ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(4);377		break;378	default:379		return;380	}381 382	ctx->pending_flush_mask |= BIT(DSPP_IDX);383}384 385static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)386{387	struct dpu_hw_blk_reg_map *c = &ctx->hw;388	ktime_t timeout;389	u32 status;390 391	timeout = ktime_add_us(ktime_get(), timeout_us);392 393	/*394	 * it takes around 30us to have mdp finish resetting its ctl path395	 * poll every 50us so that reset should be completed at 1st poll396	 */397	do {398		status = DPU_REG_READ(c, CTL_SW_RESET);399		status &= 0x1;400		if (status)401			usleep_range(20, 50);402	} while (status && ktime_compare_safe(ktime_get(), timeout) < 0);403 404	return status;405}406 407static int dpu_hw_ctl_reset_control(struct dpu_hw_ctl *ctx)408{409	struct dpu_hw_blk_reg_map *c = &ctx->hw;410 411	pr_debug("issuing hw ctl reset for ctl:%d\n", ctx->idx);412	DPU_REG_WRITE(c, CTL_SW_RESET, 0x1);413	if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US))414		return -EINVAL;415 416	return 0;417}418 419static int dpu_hw_ctl_wait_reset_status(struct dpu_hw_ctl *ctx)420{421	struct dpu_hw_blk_reg_map *c = &ctx->hw;422	u32 status;423 424	status = DPU_REG_READ(c, CTL_SW_RESET);425	status &= 0x01;426	if (!status)427		return 0;428 429	pr_debug("hw ctl reset is set for ctl:%d\n", ctx->idx);430	if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US)) {431		pr_err("hw recovery is not complete for ctl:%d\n", ctx->idx);432		return -EINVAL;433	}434 435	return 0;436}437 438static void dpu_hw_ctl_clear_all_blendstages(struct dpu_hw_ctl *ctx)439{440	struct dpu_hw_blk_reg_map *c = &ctx->hw;441	int i;442 443	for (i = 0; i < ctx->mixer_count; i++) {444		enum dpu_lm mixer_id = ctx->mixer_hw_caps[i].id;445 446		DPU_REG_WRITE(c, CTL_LAYER(mixer_id), 0);447		DPU_REG_WRITE(c, CTL_LAYER_EXT(mixer_id), 0);448		DPU_REG_WRITE(c, CTL_LAYER_EXT2(mixer_id), 0);449		DPU_REG_WRITE(c, CTL_LAYER_EXT3(mixer_id), 0);450	}451 452	DPU_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0);453}454 455struct ctl_blend_config {456	int idx, shift, ext_shift;457};458 459static const struct ctl_blend_config ctl_blend_config[][2] = {460	[SSPP_NONE] = { { -1 }, { -1 } },461	[SSPP_MAX] =  { { -1 }, { -1 } },462	[SSPP_VIG0] = { { 0, 0,  0  }, { 3, 0 } },463	[SSPP_VIG1] = { { 0, 3,  2  }, { 3, 4 } },464	[SSPP_VIG2] = { { 0, 6,  4  }, { 3, 8 } },465	[SSPP_VIG3] = { { 0, 26, 6  }, { 3, 12 } },466	[SSPP_RGB0] = { { 0, 9,  8  }, { -1 } },467	[SSPP_RGB1] = { { 0, 12, 10 }, { -1 } },468	[SSPP_RGB2] = { { 0, 15, 12 }, { -1 } },469	[SSPP_RGB3] = { { 0, 29, 14 }, { -1 } },470	[SSPP_DMA0] = { { 0, 18, 16 }, { 2, 8 } },471	[SSPP_DMA1] = { { 0, 21, 18 }, { 2, 12 } },472	[SSPP_DMA2] = { { 2, 0      }, { 2, 16 } },473	[SSPP_DMA3] = { { 2, 4      }, { 2, 20 } },474	[SSPP_DMA4] = { { 4, 0      }, { 4, 8 } },475	[SSPP_DMA5] = { { 4, 4      }, { 4, 12 } },476	[SSPP_CURSOR0] =  { { 1, 20 }, { -1 } },477	[SSPP_CURSOR1] =  { { 1, 26 }, { -1 } },478};479 480static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,481	enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg)482{483	struct dpu_hw_blk_reg_map *c = &ctx->hw;484	u32 mix, ext, mix_ext;485	u32 mixercfg[5] = { 0 };486	int i, j;487	int stages;488	int pipes_per_stage;489 490	stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);491	if (stages < 0)492		return;493 494	if (test_bit(DPU_MIXER_SOURCESPLIT,495		&ctx->mixer_hw_caps->features))496		pipes_per_stage = PIPES_PER_STAGE;497	else498		pipes_per_stage = 1;499 500	mixercfg[0] = CTL_MIXER_BORDER_OUT; /* always set BORDER_OUT */501 502	if (!stage_cfg)503		goto exit;504 505	for (i = 0; i <= stages; i++) {506		/* overflow to ext register if 'i + 1 > 7' */507		mix = (i + 1) & 0x7;508		ext = i >= 7;509		mix_ext = (i + 1) & 0xf;510 511		for (j = 0 ; j < pipes_per_stage; j++) {512			enum dpu_sspp_multirect_index rect_index =513				stage_cfg->multirect_index[i][j];514			enum dpu_sspp pipe = stage_cfg->stage[i][j];515			const struct ctl_blend_config *cfg =516				&ctl_blend_config[pipe][rect_index == DPU_SSPP_RECT_1];517 518			/*519			 * CTL_LAYER has 3-bit field (and extra bits in EXT register),520			 * all EXT registers has 4-bit fields.521			 */522			if (cfg->idx == -1) {523				continue;524			} else if (cfg->idx == 0) {525				mixercfg[0] |= mix << cfg->shift;526				mixercfg[1] |= ext << cfg->ext_shift;527			} else {528				mixercfg[cfg->idx] |= mix_ext << cfg->shift;529			}530		}531	}532 533exit:534	DPU_REG_WRITE(c, CTL_LAYER(lm), mixercfg[0]);535	DPU_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg[1]);536	DPU_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg[2]);537	DPU_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg[3]);538	if ((test_bit(DPU_CTL_HAS_LAYER_EXT4, &ctx->caps->features)))539		DPU_REG_WRITE(c, CTL_LAYER_EXT4(lm), mixercfg[4]);540}541 542 543static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,544		struct dpu_hw_intf_cfg *cfg)545{546	struct dpu_hw_blk_reg_map *c = &ctx->hw;547	u32 intf_active = 0;548	u32 dsc_active = 0;549	u32 wb_active = 0;550	u32 mode_sel = 0;551 552	/* CTL_TOP[31:28] carries group_id to collate CTL paths553	 * per VM. Explicitly disable it until VM support is554	 * added in SW. Power on reset value is not disable.555	 */556	if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features)))557		mode_sel = CTL_DEFAULT_GROUP_ID  << 28;558 559	if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)560		mode_sel |= BIT(17);561 562	intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);563	wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);564	dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE);565 566	if (cfg->intf)567		intf_active |= BIT(cfg->intf - INTF_0);568 569	if (cfg->wb)570		wb_active |= BIT(cfg->wb - WB_0);571 572	if (cfg->dsc)573		dsc_active |= cfg->dsc;574 575	DPU_REG_WRITE(c, CTL_TOP, mode_sel);576	DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);577	DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);578	DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);579 580	if (cfg->merge_3d)581		DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,582			      BIT(cfg->merge_3d - MERGE_3D_0));583 584	if (cfg->cdm)585		DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm);586}587 588static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,589		struct dpu_hw_intf_cfg *cfg)590{591	struct dpu_hw_blk_reg_map *c = &ctx->hw;592	u32 intf_cfg = 0;593 594	intf_cfg |= (cfg->intf & 0xF) << 4;595 596	if (cfg->mode_3d) {597		intf_cfg |= BIT(19);598		intf_cfg |= (cfg->mode_3d - 0x1) << 20;599	}600 601	if (cfg->wb)602		intf_cfg |= (cfg->wb & 0x3) + 2;603 604	switch (cfg->intf_mode_sel) {605	case DPU_CTL_MODE_SEL_VID:606		intf_cfg &= ~BIT(17);607		intf_cfg &= ~(0x3 << 15);608		break;609	case DPU_CTL_MODE_SEL_CMD:610		intf_cfg |= BIT(17);611		intf_cfg |= ((cfg->stream_sel & 0x3) << 15);612		break;613	default:614		pr_err("unknown interface type %d\n", cfg->intf_mode_sel);615		return;616	}617 618	DPU_REG_WRITE(c, CTL_TOP, intf_cfg);619}620 621static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,622		struct dpu_hw_intf_cfg *cfg)623{624	struct dpu_hw_blk_reg_map *c = &ctx->hw;625	u32 intf_active = 0;626	u32 wb_active = 0;627	u32 merge3d_active = 0;628	u32 dsc_active;629	u32 cdm_active;630 631	/*632	 * This API resets each portion of the CTL path namely,633	 * clearing the sspps staged on the lm, merge_3d block,634	 * interfaces , writeback etc to ensure clean teardown of the pipeline.635	 * This will be used for writeback to begin with to have a636	 * proper teardown of the writeback session but upon further637	 * validation, this can be extended to all interfaces.638	 */639	if (cfg->merge_3d) {640		merge3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE);641		merge3d_active &= ~BIT(cfg->merge_3d - MERGE_3D_0);642		DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,643				merge3d_active);644	}645 646	dpu_hw_ctl_clear_all_blendstages(ctx);647 648	if (cfg->intf) {649		intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);650		intf_active &= ~BIT(cfg->intf - INTF_0);651		DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);652	}653 654	if (cfg->wb) {655		wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);656		wb_active &= ~BIT(cfg->wb - WB_0);657		DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);658	}659 660	if (cfg->dsc) {661		dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE);662		dsc_active &= ~cfg->dsc;663		DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);664	}665 666	if (cfg->cdm) {667		cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);668		cdm_active &= ~cfg->cdm;669		DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cdm_active);670	}671}672 673static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,674	unsigned long *fetch_active)675{676	int i;677	u32 val = 0;678 679	if (fetch_active) {680		for (i = 0; i < SSPP_MAX; i++) {681			if (test_bit(i, fetch_active) &&682				fetch_tbl[i] != CTL_INVALID_BIT)683				val |= BIT(fetch_tbl[i]);684		}685	}686 687	DPU_REG_WRITE(&ctx->hw, CTL_FETCH_PIPE_ACTIVE, val);688}689 690static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,691		unsigned long cap)692{693	if (cap & BIT(DPU_CTL_ACTIVE_CFG)) {694		ops->trigger_flush = dpu_hw_ctl_trigger_flush_v1;695		ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg_v1;696		ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;697		ops->update_pending_flush_intf =698			dpu_hw_ctl_update_pending_flush_intf_v1;699 700		ops->update_pending_flush_periph =701			dpu_hw_ctl_update_pending_flush_periph_v1;702 703		ops->update_pending_flush_merge_3d =704			dpu_hw_ctl_update_pending_flush_merge_3d_v1;705		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;706		ops->update_pending_flush_dsc =707			dpu_hw_ctl_update_pending_flush_dsc_v1;708		ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;709	} else {710		ops->trigger_flush = dpu_hw_ctl_trigger_flush;711		ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;712		ops->update_pending_flush_intf =713			dpu_hw_ctl_update_pending_flush_intf;714		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;715		ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm;716	}717	ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush;718	ops->update_pending_flush = dpu_hw_ctl_update_pending_flush;719	ops->get_pending_flush = dpu_hw_ctl_get_pending_flush;720	ops->get_flush_register = dpu_hw_ctl_get_flush_register;721	ops->trigger_start = dpu_hw_ctl_trigger_start;722	ops->is_started = dpu_hw_ctl_is_started;723	ops->trigger_pending = dpu_hw_ctl_trigger_pending;724	ops->reset = dpu_hw_ctl_reset_control;725	ops->wait_reset_status = dpu_hw_ctl_wait_reset_status;726	ops->clear_all_blendstages = dpu_hw_ctl_clear_all_blendstages;727	ops->setup_blendstage = dpu_hw_ctl_setup_blendstage;728	ops->update_pending_flush_sspp = dpu_hw_ctl_update_pending_flush_sspp;729	ops->update_pending_flush_mixer = dpu_hw_ctl_update_pending_flush_mixer;730	if (cap & BIT(DPU_CTL_DSPP_SUB_BLOCK_FLUSH))731		ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp_sub_blocks;732	else733		ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp;734 735	if (cap & BIT(DPU_CTL_FETCH_ACTIVE))736		ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;737};738 739struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev,740				   const struct dpu_ctl_cfg *cfg,741				   void __iomem *addr,742				   u32 mixer_count,743				   const struct dpu_lm_cfg *mixer)744{745	struct dpu_hw_ctl *c;746 747	c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);748	if (!c)749		return ERR_PTR(-ENOMEM);750 751	c->hw.blk_addr = addr + cfg->base;752	c->hw.log_mask = DPU_DBG_MASK_CTL;753 754	c->caps = cfg;755	_setup_ctl_ops(&c->ops, c->caps->features);756	c->idx = cfg->id;757	c->mixer_count = mixer_count;758	c->mixer_hw_caps = mixer;759 760	return c;761}762