brintos

brintos / linux-shallow public Read only

0
0
Text · 20.4 KiB · 2c720f1 Raw
701 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.3 */4 5#include <linux/debugfs.h>6 7#include "dpu_hwio.h"8#include "dpu_hw_catalog.h"9#include "dpu_hw_lm.h"10#include "dpu_hw_sspp.h"11#include "dpu_kms.h"12 13#include "msm_mdss.h"14 15#include <drm/drm_file.h>16#include <drm/drm_managed.h>17 18#define DPU_FETCH_CONFIG_RESET_VALUE   0x0000008719 20/* SSPP registers */21#define SSPP_SRC_SIZE                      0x0022#define SSPP_SRC_XY                        0x0823#define SSPP_OUT_SIZE                      0x0c24#define SSPP_OUT_XY                        0x1025#define SSPP_SRC0_ADDR                     0x1426#define SSPP_SRC1_ADDR                     0x1827#define SSPP_SRC2_ADDR                     0x1C28#define SSPP_SRC3_ADDR                     0x2029#define SSPP_SRC_YSTRIDE0                  0x2430#define SSPP_SRC_YSTRIDE1                  0x2831#define SSPP_SRC_FORMAT                    0x3032#define SSPP_SRC_UNPACK_PATTERN            0x3433#define SSPP_SRC_OP_MODE                   0x3834#define SSPP_SRC_CONSTANT_COLOR            0x3c35#define SSPP_EXCL_REC_CTL                  0x4036#define SSPP_UBWC_STATIC_CTRL              0x4437#define SSPP_FETCH_CONFIG                  0x4838#define SSPP_DANGER_LUT                    0x6039#define SSPP_SAFE_LUT                      0x6440#define SSPP_CREQ_LUT                      0x6841#define SSPP_QOS_CTRL                      0x6C42#define SSPP_SRC_ADDR_SW_STATUS            0x7043#define SSPP_CREQ_LUT_0                    0x7444#define SSPP_CREQ_LUT_1                    0x7845#define SSPP_DECIMATION_CONFIG             0xB446#define SSPP_SW_PIX_EXT_C0_LR              0x10047#define SSPP_SW_PIX_EXT_C0_TB              0x10448#define SSPP_SW_PIX_EXT_C0_REQ_PIXELS      0x10849#define SSPP_SW_PIX_EXT_C1C2_LR            0x11050#define SSPP_SW_PIX_EXT_C1C2_TB            0x11451#define SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS    0x11852#define SSPP_SW_PIX_EXT_C3_LR              0x12053#define SSPP_SW_PIX_EXT_C3_TB              0x12454#define SSPP_SW_PIX_EXT_C3_REQ_PIXELS      0x12855#define SSPP_TRAFFIC_SHAPER                0x13056#define SSPP_CDP_CNTL                      0x13457#define SSPP_UBWC_ERROR_STATUS             0x13858#define SSPP_CDP_CNTL_REC1                 0x13c59#define SSPP_TRAFFIC_SHAPER_PREFILL        0x15060#define SSPP_TRAFFIC_SHAPER_REC1_PREFILL   0x15461#define SSPP_TRAFFIC_SHAPER_REC1           0x15862#define SSPP_OUT_SIZE_REC1                 0x16063#define SSPP_OUT_XY_REC1                   0x16464#define SSPP_SRC_XY_REC1                   0x16865#define SSPP_SRC_SIZE_REC1                 0x16C66#define SSPP_MULTIRECT_OPMODE              0x17067#define SSPP_SRC_FORMAT_REC1               0x17468#define SSPP_SRC_UNPACK_PATTERN_REC1       0x17869#define SSPP_SRC_OP_MODE_REC1              0x17C70#define SSPP_SRC_CONSTANT_COLOR_REC1       0x18071#define SSPP_EXCL_REC_SIZE_REC1            0x18472#define SSPP_EXCL_REC_XY_REC1              0x18873#define SSPP_EXCL_REC_SIZE                 0x1B474#define SSPP_EXCL_REC_XY                   0x1B875#define SSPP_CLK_CTRL                      0x33076 77/* SSPP_SRC_OP_MODE & OP_MODE_REC1 */78#define MDSS_MDP_OP_DEINTERLACE            BIT(22)79#define MDSS_MDP_OP_DEINTERLACE_ODD        BIT(23)80#define MDSS_MDP_OP_IGC_ROM_1              BIT(18)81#define MDSS_MDP_OP_IGC_ROM_0              BIT(17)82#define MDSS_MDP_OP_IGC_EN                 BIT(16)83#define MDSS_MDP_OP_FLIP_UD                BIT(14)84#define MDSS_MDP_OP_FLIP_LR                BIT(13)85#define MDSS_MDP_OP_BWC_EN                 BIT(0)86#define MDSS_MDP_OP_PE_OVERRIDE            BIT(31)87#define MDSS_MDP_OP_BWC_LOSSLESS           (0 << 1)88#define MDSS_MDP_OP_BWC_Q_HIGH             (1 << 1)89#define MDSS_MDP_OP_BWC_Q_MED              (2 << 1)90 91/* SSPP_QOS_CTRL */92#define SSPP_QOS_CTRL_VBLANK_EN            BIT(16)93#define SSPP_QOS_CTRL_DANGER_SAFE_EN       BIT(0)94#define SSPP_QOS_CTRL_DANGER_VBLANK_MASK   0x395#define SSPP_QOS_CTRL_DANGER_VBLANK_OFF    496#define SSPP_QOS_CTRL_CREQ_VBLANK_MASK     0x397#define SSPP_QOS_CTRL_CREQ_VBLANK_OFF      2098 99/* DPU_SSPP_SCALER_QSEED2 */100#define SSPP_VIG_OP_MODE                   0x0101#define SCALE_CONFIG                       0x04102#define COMP0_3_PHASE_STEP_X               0x10103#define COMP0_3_PHASE_STEP_Y               0x14104#define COMP1_2_PHASE_STEP_X               0x18105#define COMP1_2_PHASE_STEP_Y               0x1c106#define COMP0_3_INIT_PHASE_X               0x20107#define COMP0_3_INIT_PHASE_Y               0x24108#define COMP1_2_INIT_PHASE_X               0x28109#define COMP1_2_INIT_PHASE_Y               0x2C110#define VIG_0_QSEED2_SHARP                 0x30111 112/* SSPP_TRAFFIC_SHAPER and _REC1 */113#define SSPP_TRAFFIC_SHAPER_BPC_MAX        0xFF114 115/*116 * Definitions for ViG op modes117 */118#define VIG_OP_CSC_DST_DATAFMT BIT(19)119#define VIG_OP_CSC_SRC_DATAFMT BIT(18)120#define VIG_OP_CSC_EN          BIT(17)121#define VIG_OP_MEM_PROT_CONT   BIT(15)122#define VIG_OP_MEM_PROT_VAL    BIT(14)123#define VIG_OP_MEM_PROT_SAT    BIT(13)124#define VIG_OP_MEM_PROT_HUE    BIT(12)125#define VIG_OP_HIST            BIT(8)126#define VIG_OP_SKY_COL         BIT(7)127#define VIG_OP_FOIL            BIT(6)128#define VIG_OP_SKIN_COL        BIT(5)129#define VIG_OP_PA_EN           BIT(4)130#define VIG_OP_PA_SAT_ZERO_EXP BIT(2)131#define VIG_OP_MEM_PROT_BLEND  BIT(1)132 133/*134 * Definitions for CSC 10 op modes135 */136#define SSPP_VIG_CSC_10_OP_MODE            0x0137#define VIG_CSC_10_SRC_DATAFMT BIT(1)138#define VIG_CSC_10_EN          BIT(0)139#define CSC_10BIT_OFFSET       4140 141/* traffic shaper clock in Hz */142#define TS_CLK			19200000143 144 145static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe *pipe)146{147	struct dpu_hw_sspp *ctx = pipe->sspp;148	u32 mode_mask;149 150	if (!ctx)151		return;152 153	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {154		/**155		 * if rect index is RECT_SOLO, we cannot expect a156		 * virtual plane sharing the same SSPP id. So we go157		 * and disable multirect158		 */159		mode_mask = 0;160	} else {161		mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE);162		mode_mask |= pipe->multirect_index;163		if (pipe->multirect_mode == DPU_SSPP_MULTIRECT_TIME_MX)164			mode_mask |= BIT(2);165		else166			mode_mask &= ~BIT(2);167	}168 169	DPU_REG_WRITE(&ctx->hw, SSPP_MULTIRECT_OPMODE, mode_mask);170}171 172static void _sspp_setup_opmode(struct dpu_hw_sspp *ctx,173		u32 mask, u8 en)174{175	const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;176	u32 opmode;177 178	if (!test_bit(DPU_SSPP_SCALER_QSEED2, &ctx->cap->features) ||179		!test_bit(DPU_SSPP_CSC, &ctx->cap->features))180		return;181 182	opmode = DPU_REG_READ(&ctx->hw, sblk->scaler_blk.base + SSPP_VIG_OP_MODE);183 184	if (en)185		opmode |= mask;186	else187		opmode &= ~mask;188 189	DPU_REG_WRITE(&ctx->hw, sblk->scaler_blk.base + SSPP_VIG_OP_MODE, opmode);190}191 192static void _sspp_setup_csc10_opmode(struct dpu_hw_sspp *ctx,193		u32 mask, u8 en)194{195	const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;196	u32 opmode;197 198	opmode = DPU_REG_READ(&ctx->hw, sblk->csc_blk.base + SSPP_VIG_CSC_10_OP_MODE);199	if (en)200		opmode |= mask;201	else202		opmode &= ~mask;203 204	DPU_REG_WRITE(&ctx->hw, sblk->csc_blk.base + SSPP_VIG_CSC_10_OP_MODE, opmode);205}206 207/*208 * Setup source pixel format, flip,209 */210static void dpu_hw_sspp_setup_format(struct dpu_sw_pipe *pipe,211		const struct msm_format *fmt, u32 flags)212{213	struct dpu_hw_sspp *ctx = pipe->sspp;214	struct dpu_hw_blk_reg_map *c;215	u32 chroma_samp, unpack, src_format;216	u32 opmode = 0;217	u32 fast_clear = 0;218	u32 op_mode_off, unpack_pat_off, format_off;219 220	if (!ctx || !fmt)221		return;222 223	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||224	    pipe->multirect_index == DPU_SSPP_RECT_0) {225		op_mode_off = SSPP_SRC_OP_MODE;226		unpack_pat_off = SSPP_SRC_UNPACK_PATTERN;227		format_off = SSPP_SRC_FORMAT;228	} else {229		op_mode_off = SSPP_SRC_OP_MODE_REC1;230		unpack_pat_off = SSPP_SRC_UNPACK_PATTERN_REC1;231		format_off = SSPP_SRC_FORMAT_REC1;232	}233 234	c = &ctx->hw;235	opmode = DPU_REG_READ(c, op_mode_off);236	opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD |237			MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE);238 239	if (flags & DPU_SSPP_FLIP_LR)240		opmode |= MDSS_MDP_OP_FLIP_LR;241	if (flags & DPU_SSPP_FLIP_UD)242		opmode |= MDSS_MDP_OP_FLIP_UD;243 244	chroma_samp = fmt->chroma_sample;245	if (flags & DPU_SSPP_SOURCE_ROTATED_90) {246		if (chroma_samp == CHROMA_H2V1)247			chroma_samp = CHROMA_H1V2;248		else if (chroma_samp == CHROMA_H1V2)249			chroma_samp = CHROMA_H2V1;250	}251 252	src_format = (chroma_samp << 23) | (fmt->fetch_type << 19) |253		(fmt->bpc_a << 6) | (fmt->bpc_r_cr << 4) |254		(fmt->bpc_b_cb << 2) | (fmt->bpc_g_y << 0);255 256	if (flags & DPU_SSPP_ROT_90)257		src_format |= BIT(11); /* ROT90 */258 259	if (fmt->alpha_enable && fmt->fetch_type == MDP_PLANE_INTERLEAVED)260		src_format |= BIT(8); /* SRCC3_EN */261 262	if (flags & DPU_SSPP_SOLID_FILL)263		src_format |= BIT(22);264 265	unpack = (fmt->element[3] << 24) | (fmt->element[2] << 16) |266		(fmt->element[1] << 8) | (fmt->element[0] << 0);267	src_format |= ((fmt->unpack_count - 1) << 12) |268		((fmt->flags & MSM_FORMAT_FLAG_UNPACK_TIGHT ? 1 : 0) << 17) |269		((fmt->flags & MSM_FORMAT_FLAG_UNPACK_ALIGN_MSB ? 1 : 0) << 18) |270		((fmt->bpp - 1) << 9);271 272	if (fmt->fetch_mode != MDP_FETCH_LINEAR) {273		if (MSM_FORMAT_IS_UBWC(fmt))274			opmode |= MDSS_MDP_OP_BWC_EN;275		src_format |= (fmt->fetch_mode & 3) << 30; /*FRAME_FORMAT */276		DPU_REG_WRITE(c, SSPP_FETCH_CONFIG,277			DPU_FETCH_CONFIG_RESET_VALUE |278			ctx->ubwc->highest_bank_bit << 18);279		switch (ctx->ubwc->ubwc_enc_version) {280		case UBWC_1_0:281			fast_clear = fmt->alpha_enable ? BIT(31) : 0;282			DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,283					fast_clear | (ctx->ubwc->ubwc_swizzle & 0x1) |284					BIT(8) |285					(ctx->ubwc->highest_bank_bit << 4));286			break;287		case UBWC_2_0:288			fast_clear = fmt->alpha_enable ? BIT(31) : 0;289			DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,290					fast_clear | (ctx->ubwc->ubwc_swizzle) |291					(ctx->ubwc->highest_bank_bit << 4));292			break;293		case UBWC_3_0:294			DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,295					BIT(30) | (ctx->ubwc->ubwc_swizzle) |296					(ctx->ubwc->highest_bank_bit << 4));297			break;298		case UBWC_4_0:299			DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,300					MSM_FORMAT_IS_YUV(fmt) ? 0 : BIT(30));301			break;302		}303	}304 305	opmode |= MDSS_MDP_OP_PE_OVERRIDE;306 307	/* if this is YUV pixel format, enable CSC */308	if (MSM_FORMAT_IS_YUV(fmt))309		src_format |= BIT(15);310 311	if (MSM_FORMAT_IS_DX(fmt))312		src_format |= BIT(14);313 314	/* update scaler opmode, if appropriate */315	if (test_bit(DPU_SSPP_CSC, &ctx->cap->features))316		_sspp_setup_opmode(ctx, VIG_OP_CSC_EN | VIG_OP_CSC_SRC_DATAFMT,317			MSM_FORMAT_IS_YUV(fmt));318	else if (test_bit(DPU_SSPP_CSC_10BIT, &ctx->cap->features))319		_sspp_setup_csc10_opmode(ctx,320			VIG_CSC_10_EN | VIG_CSC_10_SRC_DATAFMT,321			MSM_FORMAT_IS_YUV(fmt));322 323	DPU_REG_WRITE(c, format_off, src_format);324	DPU_REG_WRITE(c, unpack_pat_off, unpack);325	DPU_REG_WRITE(c, op_mode_off, opmode);326 327	/* clear previous UBWC error */328	DPU_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31));329}330 331static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_sspp *ctx,332		struct dpu_hw_pixel_ext *pe_ext)333{334	struct dpu_hw_blk_reg_map *c;335	u8 color;336	u32 lr_pe[4], tb_pe[4], tot_req_pixels[4];337	const u32 bytemask = 0xff;338	const u32 shortmask = 0xffff;339 340	if (!ctx || !pe_ext)341		return;342 343	c = &ctx->hw;344 345	/* program SW pixel extension override for all pipes*/346	for (color = 0; color < DPU_MAX_PLANES; color++) {347		/* color 2 has the same set of registers as color 1 */348		if (color == 2)349			continue;350 351		lr_pe[color] = ((pe_ext->right_ftch[color] & bytemask) << 24)|352			((pe_ext->right_rpt[color] & bytemask) << 16)|353			((pe_ext->left_ftch[color] & bytemask) << 8)|354			(pe_ext->left_rpt[color] & bytemask);355 356		tb_pe[color] = ((pe_ext->btm_ftch[color] & bytemask) << 24)|357			((pe_ext->btm_rpt[color] & bytemask) << 16)|358			((pe_ext->top_ftch[color] & bytemask) << 8)|359			(pe_ext->top_rpt[color] & bytemask);360 361		tot_req_pixels[color] = (((pe_ext->roi_h[color] +362			pe_ext->num_ext_pxls_top[color] +363			pe_ext->num_ext_pxls_btm[color]) & shortmask) << 16) |364			((pe_ext->roi_w[color] +365			pe_ext->num_ext_pxls_left[color] +366			pe_ext->num_ext_pxls_right[color]) & shortmask);367	}368 369	/* color 0 */370	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_LR, lr_pe[0]);371	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_TB, tb_pe[0]);372	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_REQ_PIXELS,373			tot_req_pixels[0]);374 375	/* color 1 and color 2 */376	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_LR, lr_pe[1]);377	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_TB, tb_pe[1]);378	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS,379			tot_req_pixels[1]);380 381	/* color 3 */382	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_LR, lr_pe[3]);383	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_TB, lr_pe[3]);384	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_REQ_PIXELS,385			tot_req_pixels[3]);386}387 388static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_sspp *ctx,389		struct dpu_hw_scaler3_cfg *scaler3_cfg,390		const struct msm_format *format)391{392	if (!ctx || !scaler3_cfg)393		return;394 395	dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg,396			ctx->cap->sblk->scaler_blk.base,397			ctx->cap->sblk->scaler_blk.version,398			format);399}400 401/*402 * dpu_hw_sspp_setup_rects()403 */404static void dpu_hw_sspp_setup_rects(struct dpu_sw_pipe *pipe,405		struct dpu_sw_pipe_cfg *cfg)406{407	struct dpu_hw_sspp *ctx = pipe->sspp;408	struct dpu_hw_blk_reg_map *c;409	u32 src_size, src_xy, dst_size, dst_xy;410	u32 src_size_off, src_xy_off, out_size_off, out_xy_off;411 412	if (!ctx || !cfg)413		return;414 415	c = &ctx->hw;416 417	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||418	    pipe->multirect_index == DPU_SSPP_RECT_0) {419		src_size_off = SSPP_SRC_SIZE;420		src_xy_off = SSPP_SRC_XY;421		out_size_off = SSPP_OUT_SIZE;422		out_xy_off = SSPP_OUT_XY;423	} else {424		src_size_off = SSPP_SRC_SIZE_REC1;425		src_xy_off = SSPP_SRC_XY_REC1;426		out_size_off = SSPP_OUT_SIZE_REC1;427		out_xy_off = SSPP_OUT_XY_REC1;428	}429 430 431	/* src and dest rect programming */432	src_xy = (cfg->src_rect.y1 << 16) | cfg->src_rect.x1;433	src_size = (drm_rect_height(&cfg->src_rect) << 16) |434		   drm_rect_width(&cfg->src_rect);435	dst_xy = (cfg->dst_rect.y1 << 16) | cfg->dst_rect.x1;436	dst_size = (drm_rect_height(&cfg->dst_rect) << 16) |437		drm_rect_width(&cfg->dst_rect);438 439	/* rectangle register programming */440	DPU_REG_WRITE(c, src_size_off, src_size);441	DPU_REG_WRITE(c, src_xy_off, src_xy);442	DPU_REG_WRITE(c, out_size_off, dst_size);443	DPU_REG_WRITE(c, out_xy_off, dst_xy);444}445 446static void dpu_hw_sspp_setup_sourceaddress(struct dpu_sw_pipe *pipe,447		struct dpu_hw_fmt_layout *layout)448{449	struct dpu_hw_sspp *ctx = pipe->sspp;450	u32 ystride0, ystride1;451	int i;452 453	if (!ctx)454		return;455 456	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {457		for (i = 0; i < ARRAY_SIZE(layout->plane_addr); i++)458			DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + i * 0x4,459					layout->plane_addr[i]);460	} else if (pipe->multirect_index == DPU_SSPP_RECT_0) {461		DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR,462				layout->plane_addr[0]);463		DPU_REG_WRITE(&ctx->hw, SSPP_SRC2_ADDR,464				layout->plane_addr[2]);465	} else {466		DPU_REG_WRITE(&ctx->hw, SSPP_SRC1_ADDR,467				layout->plane_addr[0]);468		DPU_REG_WRITE(&ctx->hw, SSPP_SRC3_ADDR,469				layout->plane_addr[2]);470	}471 472	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {473		ystride0 = (layout->plane_pitch[0]) |474			(layout->plane_pitch[1] << 16);475		ystride1 = (layout->plane_pitch[2]) |476			(layout->plane_pitch[3] << 16);477	} else {478		ystride0 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE0);479		ystride1 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE1);480 481		if (pipe->multirect_index == DPU_SSPP_RECT_0) {482			ystride0 = (ystride0 & 0xFFFF0000) |483				(layout->plane_pitch[0] & 0x0000FFFF);484			ystride1 = (ystride1 & 0xFFFF0000)|485				(layout->plane_pitch[2] & 0x0000FFFF);486		} else {487			ystride0 = (ystride0 & 0x0000FFFF) |488				((layout->plane_pitch[0] << 16) &489				 0xFFFF0000);490			ystride1 = (ystride1 & 0x0000FFFF) |491				((layout->plane_pitch[2] << 16) &492				 0xFFFF0000);493		}494	}495 496	DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE0, ystride0);497	DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE1, ystride1);498}499 500static void dpu_hw_sspp_setup_csc(struct dpu_hw_sspp *ctx,501		const struct dpu_csc_cfg *data)502{503	u32 offset;504	bool csc10 = false;505 506	if (!ctx || !data)507		return;508 509	offset = ctx->cap->sblk->csc_blk.base;510 511	if (test_bit(DPU_SSPP_CSC_10BIT, &ctx->cap->features)) {512		offset += CSC_10BIT_OFFSET;513		csc10 = true;514	}515 516	dpu_hw_csc_setup(&ctx->hw, offset, data, csc10);517}518 519static void dpu_hw_sspp_setup_solidfill(struct dpu_sw_pipe *pipe, u32 color)520{521	struct dpu_hw_sspp *ctx = pipe->sspp;522	struct dpu_hw_fmt_layout cfg;523 524	if (!ctx)525		return;526 527	/* cleanup source addresses */528	memset(&cfg, 0, sizeof(cfg));529	ctx->ops.setup_sourceaddress(pipe, &cfg);530 531	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||532	    pipe->multirect_index == DPU_SSPP_RECT_0)533		DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR, color);534	else535		DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1,536				color);537}538 539static void dpu_hw_sspp_setup_qos_lut(struct dpu_hw_sspp *ctx,540				      struct dpu_hw_qos_cfg *cfg)541{542	if (!ctx || !cfg)543		return;544 545	_dpu_hw_setup_qos_lut(&ctx->hw, SSPP_DANGER_LUT,546			      test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features),547			      cfg);548}549 550static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp *ctx,551				       bool danger_safe_en)552{553	if (!ctx)554		return;555 556	DPU_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL,557		      danger_safe_en ? SSPP_QOS_CTRL_DANGER_SAFE_EN : 0);558}559 560static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe,561				  const struct msm_format *fmt,562				  bool enable)563{564	struct dpu_hw_sspp *ctx = pipe->sspp;565	u32 cdp_cntl_offset = 0;566 567	if (!ctx)568		return;569 570	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||571	    pipe->multirect_index == DPU_SSPP_RECT_0)572		cdp_cntl_offset = SSPP_CDP_CNTL;573	else574		cdp_cntl_offset = SSPP_CDP_CNTL_REC1;575 576	dpu_setup_cdp(&ctx->hw, cdp_cntl_offset, fmt, enable);577}578 579static bool dpu_hw_sspp_setup_clk_force_ctrl(struct dpu_hw_sspp *ctx, bool enable)580{581	static const struct dpu_clk_ctrl_reg sspp_clk_ctrl = {582		.reg_off = SSPP_CLK_CTRL,583		.bit_off = 0584	};585 586	return dpu_hw_clk_force_ctrl(&ctx->hw, &sspp_clk_ctrl, enable);587}588 589static void _setup_layer_ops(struct dpu_hw_sspp *c,590		unsigned long features, const struct dpu_mdss_version *mdss_rev)591{592	c->ops.setup_format = dpu_hw_sspp_setup_format;593	c->ops.setup_rects = dpu_hw_sspp_setup_rects;594	c->ops.setup_sourceaddress = dpu_hw_sspp_setup_sourceaddress;595	c->ops.setup_solidfill = dpu_hw_sspp_setup_solidfill;596	c->ops.setup_pe = dpu_hw_sspp_setup_pe_config;597 598	if (test_bit(DPU_SSPP_QOS, &features)) {599		c->ops.setup_qos_lut = dpu_hw_sspp_setup_qos_lut;600		c->ops.setup_qos_ctrl = dpu_hw_sspp_setup_qos_ctrl;601	}602 603	if (test_bit(DPU_SSPP_CSC, &features) ||604		test_bit(DPU_SSPP_CSC_10BIT, &features))605		c->ops.setup_csc = dpu_hw_sspp_setup_csc;606 607	if (test_bit(DPU_SSPP_SMART_DMA_V1, &c->cap->features) ||608		test_bit(DPU_SSPP_SMART_DMA_V2, &c->cap->features))609		c->ops.setup_multirect = dpu_hw_sspp_setup_multirect;610 611	if (test_bit(DPU_SSPP_SCALER_QSEED3_COMPATIBLE, &features))612		c->ops.setup_scaler = _dpu_hw_sspp_setup_scaler3;613 614	if (test_bit(DPU_SSPP_CDP, &features))615		c->ops.setup_cdp = dpu_hw_sspp_setup_cdp;616 617	if (mdss_rev->core_major_ver >= 9)618		c->ops.setup_clk_force_ctrl = dpu_hw_sspp_setup_clk_force_ctrl;619}620 621#ifdef CONFIG_DEBUG_FS622int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms,623			      struct dentry *entry)624{625	const struct dpu_sspp_cfg *cfg = hw_pipe->cap;626	const struct dpu_sspp_sub_blks *sblk = cfg->sblk;627	struct dentry *debugfs_root;628	char sspp_name[32];629 630	snprintf(sspp_name, sizeof(sspp_name), "%d", hw_pipe->idx);631 632	/* create overall sub-directory for the pipe */633	debugfs_root =634		debugfs_create_dir(sspp_name, entry);635 636	/* don't error check these */637	debugfs_create_xul("features", 0600,638			debugfs_root, (unsigned long *)&hw_pipe->cap->features);639 640	/* add register dump support */641	dpu_debugfs_create_regset32("src_blk", 0400,642			debugfs_root,643			cfg->base,644			cfg->len,645			kms);646 647	if (sblk->scaler_blk.len)648		dpu_debugfs_create_regset32("scaler_blk", 0400,649				debugfs_root,650				sblk->scaler_blk.base + cfg->base,651				sblk->scaler_blk.len,652				kms);653 654	if (cfg->features & BIT(DPU_SSPP_CSC) ||655			cfg->features & BIT(DPU_SSPP_CSC_10BIT))656		dpu_debugfs_create_regset32("csc_blk", 0400,657				debugfs_root,658				sblk->csc_blk.base + cfg->base,659				sblk->csc_blk.len,660				kms);661 662	debugfs_create_u32("xin_id",663			0400,664			debugfs_root,665			(u32 *) &cfg->xin_id);666	debugfs_create_u32("clk_ctrl",667			0400,668			debugfs_root,669			(u32 *) &cfg->clk_ctrl);670 671	return 0;672}673#endif674 675struct dpu_hw_sspp *dpu_hw_sspp_init(struct drm_device *dev,676				     const struct dpu_sspp_cfg *cfg,677				     void __iomem *addr,678				     const struct msm_mdss_data *mdss_data,679				     const struct dpu_mdss_version *mdss_rev)680{681	struct dpu_hw_sspp *hw_pipe;682 683	if (!addr)684		return ERR_PTR(-EINVAL);685 686	hw_pipe = drmm_kzalloc(dev, sizeof(*hw_pipe), GFP_KERNEL);687	if (!hw_pipe)688		return ERR_PTR(-ENOMEM);689 690	hw_pipe->hw.blk_addr = addr + cfg->base;691	hw_pipe->hw.log_mask = DPU_DBG_MASK_SSPP;692 693	/* Assign ops */694	hw_pipe->ubwc = mdss_data;695	hw_pipe->idx = cfg->id;696	hw_pipe->cap = cfg;697	_setup_layer_ops(hw_pipe, hw_pipe->cap->features, mdss_rev);698 699	return hw_pipe;700}701