brintos

brintos / linux-shallow public Read only

0
0
Text · 40.1 KiB · 67e5d3b Raw
1445 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.4 * Author: James.Qian.Wang <james.qian.wang@arm.com>5 *6 */7 8#include <linux/seq_file.h>9#include "d71_dev.h"10#include "komeda_kms.h"11#include "malidp_io.h"12#include "komeda_framebuffer.h"13#include "komeda_color_mgmt.h"14 15static void get_resources_id(u32 hw_id, u32 *pipe_id, u32 *comp_id)16{17	u32 id = BLOCK_INFO_BLK_ID(hw_id);18	u32 pipe = id;19 20	switch (BLOCK_INFO_BLK_TYPE(hw_id)) {21	case D71_BLK_TYPE_LPU_WB_LAYER:22		id = KOMEDA_COMPONENT_WB_LAYER;23		break;24	case D71_BLK_TYPE_CU_SPLITTER:25		id = KOMEDA_COMPONENT_SPLITTER;26		break;27	case D71_BLK_TYPE_CU_SCALER:28		pipe = id / D71_PIPELINE_MAX_SCALERS;29		id %= D71_PIPELINE_MAX_SCALERS;30		id += KOMEDA_COMPONENT_SCALER0;31		break;32	case D71_BLK_TYPE_CU:33		id += KOMEDA_COMPONENT_COMPIZ0;34		break;35	case D71_BLK_TYPE_LPU_LAYER:36		pipe = id / D71_PIPELINE_MAX_LAYERS;37		id %= D71_PIPELINE_MAX_LAYERS;38		id += KOMEDA_COMPONENT_LAYER0;39		break;40	case D71_BLK_TYPE_DOU_IPS:41		id += KOMEDA_COMPONENT_IPS0;42		break;43	case D71_BLK_TYPE_CU_MERGER:44		id = KOMEDA_COMPONENT_MERGER;45		break;46	case D71_BLK_TYPE_DOU:47		id = KOMEDA_COMPONENT_TIMING_CTRLR;48		break;49	default:50		id = 0xFFFFFFFF;51	}52 53	if (comp_id)54		*comp_id = id;55 56	if (pipe_id)57		*pipe_id = pipe;58}59 60static u32 get_valid_inputs(struct block_header *blk)61{62	u32 valid_inputs = 0, comp_id;63	int i;64 65	for (i = 0; i < PIPELINE_INFO_N_VALID_INPUTS(blk->pipeline_info); i++) {66		get_resources_id(blk->input_ids[i], NULL, &comp_id);67		if (comp_id == 0xFFFFFFFF)68			continue;69		valid_inputs |= BIT(comp_id);70	}71 72	return valid_inputs;73}74 75static void get_values_from_reg(void __iomem *reg, u32 offset,76				u32 count, u32 *val)77{78	u32 i, addr;79 80	for (i = 0; i < count; i++) {81		addr = offset + (i << 2);82		/* 0xA4 is WO register */83		if (addr != 0xA4)84			val[i] = malidp_read32(reg, addr);85		else86			val[i] = 0xDEADDEAD;87	}88}89 90static void dump_block_header(struct seq_file *sf, void __iomem *reg)91{92	struct block_header hdr;93	u32 i, n_input, n_output;94 95	d71_read_block_header(reg, &hdr);96	seq_printf(sf, "BLOCK_INFO:\t\t0x%X\n", hdr.block_info);97	seq_printf(sf, "PIPELINE_INFO:\t\t0x%X\n", hdr.pipeline_info);98 99	n_output = PIPELINE_INFO_N_OUTPUTS(hdr.pipeline_info);100	n_input  = PIPELINE_INFO_N_VALID_INPUTS(hdr.pipeline_info);101 102	for (i = 0; i < n_input; i++)103		seq_printf(sf, "VALID_INPUT_ID%u:\t0x%X\n",104			   i, hdr.input_ids[i]);105 106	for (i = 0; i < n_output; i++)107		seq_printf(sf, "OUTPUT_ID%u:\t\t0x%X\n",108			   i, hdr.output_ids[i]);109}110 111/* On D71, we are using the global line size. From D32, every component have112 * a line size register to indicate the fifo size.113 */114static u32 __get_blk_line_size(struct d71_dev *d71, u32 __iomem *reg,115			       u32 max_default)116{117	if (!d71->periph_addr)118		max_default = malidp_read32(reg, BLK_MAX_LINE_SIZE);119 120	return max_default;121}122 123static u32 get_blk_line_size(struct d71_dev *d71, u32 __iomem *reg)124{125	return __get_blk_line_size(d71, reg, d71->max_line_size);126}127 128static u32 to_rot_ctrl(u32 rot)129{130	u32 lr_ctrl = 0;131 132	switch (rot & DRM_MODE_ROTATE_MASK) {133	case DRM_MODE_ROTATE_0:134		lr_ctrl |= L_ROT(L_ROT_R0);135		break;136	case DRM_MODE_ROTATE_90:137		lr_ctrl |= L_ROT(L_ROT_R90);138		break;139	case DRM_MODE_ROTATE_180:140		lr_ctrl |= L_ROT(L_ROT_R180);141		break;142	case DRM_MODE_ROTATE_270:143		lr_ctrl |= L_ROT(L_ROT_R270);144		break;145	}146 147	if (rot & DRM_MODE_REFLECT_X)148		lr_ctrl |= L_HFLIP;149	if (rot & DRM_MODE_REFLECT_Y)150		lr_ctrl |= L_VFLIP;151 152	return lr_ctrl;153}154 155static u32 to_ad_ctrl(u64 modifier)156{157	u32 afbc_ctrl = AD_AEN;158 159	if (!modifier)160		return 0;161 162	if ((modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) ==163	    AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)164		afbc_ctrl |= AD_WB;165 166	if (modifier & AFBC_FORMAT_MOD_YTR)167		afbc_ctrl |= AD_YT;168	if (modifier & AFBC_FORMAT_MOD_SPLIT)169		afbc_ctrl |= AD_BS;170	if (modifier & AFBC_FORMAT_MOD_TILED)171		afbc_ctrl |= AD_TH;172 173	return afbc_ctrl;174}175 176static inline u32 to_d71_input_id(struct komeda_component_state *st, int idx)177{178	struct komeda_component_output *input = &st->inputs[idx];179 180	/* if input is not active, set hw input_id(0) to disable it */181	if (has_bit(idx, st->active_inputs))182		return input->component->hw_id + input->output_port;183	else184		return 0;185}186 187static void d71_layer_update_fb(struct komeda_component *c,188				struct komeda_fb *kfb,189				dma_addr_t *addr)190{191	struct drm_framebuffer *fb = &kfb->base;192	const struct drm_format_info *info = fb->format;193	u32 __iomem *reg = c->reg;194	int block_h;195 196	if (info->num_planes > 2)197		malidp_write64(reg, BLK_P2_PTR_LOW, addr[2]);198 199	if (info->num_planes > 1) {200		block_h = drm_format_info_block_height(info, 1);201		malidp_write32(reg, BLK_P1_STRIDE, fb->pitches[1] * block_h);202		malidp_write64(reg, BLK_P1_PTR_LOW, addr[1]);203	}204 205	block_h = drm_format_info_block_height(info, 0);206	malidp_write32(reg, BLK_P0_STRIDE, fb->pitches[0] * block_h);207	malidp_write64(reg, BLK_P0_PTR_LOW, addr[0]);208	malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);209}210 211static void d71_layer_disable(struct komeda_component *c)212{213	malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);214}215 216static void d71_layer_update(struct komeda_component *c,217			     struct komeda_component_state *state)218{219	struct komeda_layer_state *st = to_layer_st(state);220	struct drm_plane_state *plane_st = state->plane->state;221	struct drm_framebuffer *fb = plane_st->fb;222	struct komeda_fb *kfb = to_kfb(fb);223	u32 __iomem *reg = c->reg;224	u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN;225	u32 ctrl = L_EN | to_rot_ctrl(st->rot);226 227	d71_layer_update_fb(c, kfb, st->addr);228 229	malidp_write32(reg, AD_CONTROL, to_ad_ctrl(fb->modifier));230	if (fb->modifier) {231		u64 addr;232 233		malidp_write32(reg, LAYER_AD_H_CROP, HV_CROP(st->afbc_crop_l,234							     st->afbc_crop_r));235		malidp_write32(reg, LAYER_AD_V_CROP, HV_CROP(st->afbc_crop_t,236							     st->afbc_crop_b));237		/* afbc 1.2 wants payload, afbc 1.0/1.1 wants end_addr */238		if (fb->modifier & AFBC_FORMAT_MOD_TILED)239			addr = st->addr[0] + kfb->offset_payload;240		else241			addr = st->addr[0] + kfb->afbc_size - 1;242 243		malidp_write32(reg, BLK_P1_PTR_LOW, lower_32_bits(addr));244		malidp_write32(reg, BLK_P1_PTR_HIGH, upper_32_bits(addr));245	}246 247	if (fb->format->is_yuv) {248		u32 upsampling = 0;249 250		switch (kfb->format_caps->fourcc) {251		case DRM_FORMAT_YUYV:252			upsampling = fb->modifier ? LR_CHI422_BILINEAR :253				     LR_CHI422_REPLICATION;254			break;255		case DRM_FORMAT_UYVY:256			upsampling = LR_CHI422_REPLICATION;257			break;258		case DRM_FORMAT_NV12:259		case DRM_FORMAT_YUV420_8BIT:260		case DRM_FORMAT_YUV420_10BIT:261		case DRM_FORMAT_YUV420:262		case DRM_FORMAT_P010:263		/* these fmt support MPGE/JPEG both, here perfer JPEG*/264			upsampling = LR_CHI420_JPEG;265			break;266		case DRM_FORMAT_X0L2:267			upsampling = LR_CHI420_JPEG;268			break;269		default:270			break;271		}272 273		malidp_write32(reg, LAYER_R_CONTROL, upsampling);274		malidp_write_group(reg, LAYER_YUV_RGB_COEFF0,275				   KOMEDA_N_YUV2RGB_COEFFS,276				   komeda_select_yuv2rgb_coeffs(277					plane_st->color_encoding,278					plane_st->color_range));279	}280 281	malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));282 283	if (kfb->is_va)284		ctrl |= L_TBU_EN;285	malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);286}287 288static void d71_layer_dump(struct komeda_component *c, struct seq_file *sf)289{290	u32 v[15], i;291	bool rich, rgb2rgb;292	char *prefix;293 294	get_values_from_reg(c->reg, LAYER_INFO, 1, &v[14]);295	if (v[14] & 0x1) {296		rich = true;297		prefix = "LR_";298	} else {299		rich = false;300		prefix = "LS_";301	}302 303	rgb2rgb = !!(v[14] & L_INFO_CM);304 305	dump_block_header(sf, c->reg);306 307	seq_printf(sf, "%sLAYER_INFO:\t\t0x%X\n", prefix, v[14]);308 309	get_values_from_reg(c->reg, 0xD0, 1, v);310	seq_printf(sf, "%sCONTROL:\t\t0x%X\n", prefix, v[0]);311	if (rich) {312		get_values_from_reg(c->reg, 0xD4, 1, v);313		seq_printf(sf, "LR_RICH_CONTROL:\t0x%X\n", v[0]);314	}315	get_values_from_reg(c->reg, 0xD8, 4, v);316	seq_printf(sf, "%sFORMAT:\t\t0x%X\n", prefix, v[0]);317	seq_printf(sf, "%sIT_COEFFTAB:\t\t0x%X\n", prefix, v[1]);318	seq_printf(sf, "%sIN_SIZE:\t\t0x%X\n", prefix, v[2]);319	seq_printf(sf, "%sPALPHA:\t\t0x%X\n", prefix, v[3]);320 321	get_values_from_reg(c->reg, 0x100, 3, v);322	seq_printf(sf, "%sP0_PTR_LOW:\t\t0x%X\n", prefix, v[0]);323	seq_printf(sf, "%sP0_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);324	seq_printf(sf, "%sP0_STRIDE:\t\t0x%X\n", prefix, v[2]);325 326	get_values_from_reg(c->reg, 0x110, 2, v);327	seq_printf(sf, "%sP1_PTR_LOW:\t\t0x%X\n", prefix, v[0]);328	seq_printf(sf, "%sP1_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);329	if (rich) {330		get_values_from_reg(c->reg, 0x118, 1, v);331		seq_printf(sf, "LR_P1_STRIDE:\t\t0x%X\n", v[0]);332 333		get_values_from_reg(c->reg, 0x120, 2, v);334		seq_printf(sf, "LR_P2_PTR_LOW:\t\t0x%X\n", v[0]);335		seq_printf(sf, "LR_P2_PTR_HIGH:\t\t0x%X\n", v[1]);336 337		get_values_from_reg(c->reg, 0x130, 12, v);338		for (i = 0; i < 12; i++)339			seq_printf(sf, "LR_YUV_RGB_COEFF%u:\t0x%X\n", i, v[i]);340	}341 342	if (rgb2rgb) {343		get_values_from_reg(c->reg, LAYER_RGB_RGB_COEFF0, 12, v);344		for (i = 0; i < 12; i++)345			seq_printf(sf, "LS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);346	}347 348	get_values_from_reg(c->reg, 0x160, 3, v);349	seq_printf(sf, "%sAD_CONTROL:\t\t0x%X\n", prefix, v[0]);350	seq_printf(sf, "%sAD_H_CROP:\t\t0x%X\n", prefix, v[1]);351	seq_printf(sf, "%sAD_V_CROP:\t\t0x%X\n", prefix, v[2]);352}353 354static int d71_layer_validate(struct komeda_component *c,355			      struct komeda_component_state *state)356{357	struct komeda_layer_state *st = to_layer_st(state);358	struct komeda_layer *layer = to_layer(c);359	struct drm_plane_state *plane_st;360	struct drm_framebuffer *fb;361	u32 fourcc, line_sz, max_line_sz;362 363	plane_st = drm_atomic_get_new_plane_state(state->obj.state,364						  state->plane);365	fb = plane_st->fb;366	fourcc = fb->format->format;367 368	if (drm_rotation_90_or_270(st->rot))369		line_sz = st->vsize - st->afbc_crop_t - st->afbc_crop_b;370	else371		line_sz = st->hsize - st->afbc_crop_l - st->afbc_crop_r;372 373	if (fb->modifier) {374		if ((fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) ==375			AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)376			max_line_sz = layer->line_sz;377		else378			max_line_sz = layer->line_sz / 2;379 380		if (line_sz > max_line_sz) {381			DRM_DEBUG_ATOMIC("afbc request line_sz: %d exceed the max afbc line_sz: %d.\n",382					 line_sz, max_line_sz);383			return -EINVAL;384		}385	}386 387	if (fourcc == DRM_FORMAT_YUV420_10BIT && line_sz > 2046 && (st->afbc_crop_l % 4)) {388		DRM_DEBUG_ATOMIC("YUV420_10BIT input_hsize: %d exceed the max size 2046.\n",389				 line_sz);390		return -EINVAL;391	}392 393	if (fourcc == DRM_FORMAT_X0L2 && line_sz > 2046 && (st->addr[0] % 16)) {394		DRM_DEBUG_ATOMIC("X0L2 input_hsize: %d exceed the max size 2046.\n",395				 line_sz);396		return -EINVAL;397	}398 399	return 0;400}401 402static const struct komeda_component_funcs d71_layer_funcs = {403	.validate	= d71_layer_validate,404	.update		= d71_layer_update,405	.disable	= d71_layer_disable,406	.dump_register	= d71_layer_dump,407};408 409static int d71_layer_init(struct d71_dev *d71,410			  struct block_header *blk, u32 __iomem *reg)411{412	struct komeda_component *c;413	struct komeda_layer *layer;414	u32 pipe_id, layer_id, layer_info;415 416	get_resources_id(blk->block_info, &pipe_id, &layer_id);417	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer),418				 layer_id,419				 BLOCK_INFO_INPUT_ID(blk->block_info),420				 &d71_layer_funcs, 0,421				 get_valid_inputs(blk),422				 1, reg, "LPU%d_LAYER%d", pipe_id, layer_id);423	if (IS_ERR(c)) {424		DRM_ERROR("Failed to add layer component\n");425		return PTR_ERR(c);426	}427 428	layer = to_layer(c);429	layer_info = malidp_read32(reg, LAYER_INFO);430 431	if (layer_info & L_INFO_RF)432		layer->layer_type = KOMEDA_FMT_RICH_LAYER;433	else434		layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER;435 436	if (!d71->periph_addr) {437		/* D32 or newer product */438		layer->line_sz = malidp_read32(reg, BLK_MAX_LINE_SIZE);439		layer->yuv_line_sz = L_INFO_YUV_MAX_LINESZ(layer_info);440	} else if (d71->max_line_size > 2048) {441		/* D71 4K */442		layer->line_sz = d71->max_line_size;443		layer->yuv_line_sz = layer->line_sz / 2;444	} else	{445		/* D71 2K */446		if (layer->layer_type == KOMEDA_FMT_RICH_LAYER) {447			/* rich layer is 4K configuration */448			layer->line_sz = d71->max_line_size * 2;449			layer->yuv_line_sz = layer->line_sz / 2;450		} else {451			layer->line_sz = d71->max_line_size;452			layer->yuv_line_sz = 0;453		}454	}455 456	set_range(&layer->hsize_in, 4, layer->line_sz);457 458	set_range(&layer->vsize_in, 4, d71->max_vsize);459 460	malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP);461 462	layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK;463 464	return 0;465}466 467static void d71_wb_layer_update(struct komeda_component *c,468				struct komeda_component_state *state)469{470	struct komeda_layer_state *st = to_layer_st(state);471	struct drm_connector_state *conn_st = state->wb_conn->state;472	struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb);473	u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN;474	u32 __iomem *reg = c->reg;475 476	d71_layer_update_fb(c, kfb, st->addr);477 478	if (kfb->is_va)479		ctrl |= LW_TBU_EN;480 481	malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));482	malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0));483	malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);484}485 486static void d71_wb_layer_dump(struct komeda_component *c, struct seq_file *sf)487{488	u32 v[12], i;489 490	dump_block_header(sf, c->reg);491 492	get_values_from_reg(c->reg, 0x80, 1, v);493	seq_printf(sf, "LW_INPUT_ID0:\t\t0x%X\n", v[0]);494 495	get_values_from_reg(c->reg, 0xD0, 3, v);496	seq_printf(sf, "LW_CONTROL:\t\t0x%X\n", v[0]);497	seq_printf(sf, "LW_PROG_LINE:\t\t0x%X\n", v[1]);498	seq_printf(sf, "LW_FORMAT:\t\t0x%X\n", v[2]);499 500	get_values_from_reg(c->reg, 0xE0, 1, v);501	seq_printf(sf, "LW_IN_SIZE:\t\t0x%X\n", v[0]);502 503	for (i = 0; i < 2; i++) {504		get_values_from_reg(c->reg, 0x100 + i * 0x10, 3, v);505		seq_printf(sf, "LW_P%u_PTR_LOW:\t\t0x%X\n", i, v[0]);506		seq_printf(sf, "LW_P%u_PTR_HIGH:\t\t0x%X\n", i, v[1]);507		seq_printf(sf, "LW_P%u_STRIDE:\t\t0x%X\n", i, v[2]);508	}509 510	get_values_from_reg(c->reg, 0x130, 12, v);511	for (i = 0; i < 12; i++)512		seq_printf(sf, "LW_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);513}514 515static void d71_wb_layer_disable(struct komeda_component *c)516{517	malidp_write32(c->reg, BLK_INPUT_ID0, 0);518	malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);519}520 521static const struct komeda_component_funcs d71_wb_layer_funcs = {522	.update		= d71_wb_layer_update,523	.disable	= d71_wb_layer_disable,524	.dump_register	= d71_wb_layer_dump,525};526 527static int d71_wb_layer_init(struct d71_dev *d71,528			     struct block_header *blk, u32 __iomem *reg)529{530	struct komeda_component *c;531	struct komeda_layer *wb_layer;532	u32 pipe_id, layer_id;533 534	get_resources_id(blk->block_info, &pipe_id, &layer_id);535 536	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*wb_layer),537				 layer_id, BLOCK_INFO_INPUT_ID(blk->block_info),538				 &d71_wb_layer_funcs,539				 1, get_valid_inputs(blk), 0, reg,540				 "LPU%d_LAYER_WR", pipe_id);541	if (IS_ERR(c)) {542		DRM_ERROR("Failed to add wb_layer component\n");543		return PTR_ERR(c);544	}545 546	wb_layer = to_layer(c);547	wb_layer->layer_type = KOMEDA_FMT_WB_LAYER;548	wb_layer->line_sz = get_blk_line_size(d71, reg);549	wb_layer->yuv_line_sz = wb_layer->line_sz;550 551	set_range(&wb_layer->hsize_in, 64, wb_layer->line_sz);552	set_range(&wb_layer->vsize_in, 64, d71->max_vsize);553 554	return 0;555}556 557static void d71_component_disable(struct komeda_component *c)558{559	u32 __iomem *reg = c->reg;560	u32 i;561 562	malidp_write32(reg, BLK_CONTROL, 0);563 564	for (i = 0; i < c->max_active_inputs; i++) {565		malidp_write32(reg, BLK_INPUT_ID0 + (i << 2), 0);566 567		/* Besides clearing the input ID to zero, D71 compiz also has568		 * input enable bit in CU_INPUTx_CONTROL which need to be569		 * cleared.570		 */571		if (has_bit(c->id, KOMEDA_PIPELINE_COMPIZS))572			malidp_write32(reg, CU_INPUT0_CONTROL +573				       i * CU_PER_INPUT_REGS * 4,574				       CU_INPUT_CTRL_ALPHA(0xFF));575	}576}577 578static void compiz_enable_input(u32 __iomem *id_reg,579				u32 __iomem *cfg_reg,580				u32 input_hw_id,581				struct komeda_compiz_input_cfg *cin)582{583	u32 ctrl = CU_INPUT_CTRL_EN;584	u8 blend = cin->pixel_blend_mode;585 586	if (blend == DRM_MODE_BLEND_PIXEL_NONE)587		ctrl |= CU_INPUT_CTRL_PAD;588	else if (blend == DRM_MODE_BLEND_PREMULTI)589		ctrl |= CU_INPUT_CTRL_PMUL;590 591	ctrl |= CU_INPUT_CTRL_ALPHA(cin->layer_alpha);592 593	malidp_write32(id_reg, BLK_INPUT_ID0, input_hw_id);594 595	malidp_write32(cfg_reg, CU_INPUT0_SIZE,596		       HV_SIZE(cin->hsize, cin->vsize));597	malidp_write32(cfg_reg, CU_INPUT0_OFFSET,598		       HV_OFFSET(cin->hoffset, cin->voffset));599	malidp_write32(cfg_reg, CU_INPUT0_CONTROL, ctrl);600}601 602static void d71_compiz_update(struct komeda_component *c,603			      struct komeda_component_state *state)604{605	struct komeda_compiz_state *st = to_compiz_st(state);606	u32 __iomem *reg = c->reg;607	u32 __iomem *id_reg, *cfg_reg;608	u32 index;609 610	for_each_changed_input(state, index) {611		id_reg = reg + index;612		cfg_reg = reg + index * CU_PER_INPUT_REGS;613		if (state->active_inputs & BIT(index)) {614			compiz_enable_input(id_reg, cfg_reg,615					    to_d71_input_id(state, index),616					    &st->cins[index]);617		} else {618			malidp_write32(id_reg, BLK_INPUT_ID0, 0);619			malidp_write32(cfg_reg, CU_INPUT0_CONTROL, 0);620		}621	}622 623	malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));624}625 626static void d71_compiz_dump(struct komeda_component *c, struct seq_file *sf)627{628	u32 v[8], i;629 630	dump_block_header(sf, c->reg);631 632	get_values_from_reg(c->reg, 0x80, 5, v);633	for (i = 0; i < 5; i++)634		seq_printf(sf, "CU_INPUT_ID%u:\t\t0x%X\n", i, v[i]);635 636	get_values_from_reg(c->reg, 0xA0, 5, v);637	seq_printf(sf, "CU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);638	seq_printf(sf, "CU_IRQ_CLEAR:\t\t0x%X\n", v[1]);639	seq_printf(sf, "CU_IRQ_MASK:\t\t0x%X\n", v[2]);640	seq_printf(sf, "CU_IRQ_STATUS:\t\t0x%X\n", v[3]);641	seq_printf(sf, "CU_STATUS:\t\t0x%X\n", v[4]);642 643	get_values_from_reg(c->reg, 0xD0, 2, v);644	seq_printf(sf, "CU_CONTROL:\t\t0x%X\n", v[0]);645	seq_printf(sf, "CU_SIZE:\t\t0x%X\n", v[1]);646 647	get_values_from_reg(c->reg, 0xDC, 1, v);648	seq_printf(sf, "CU_BG_COLOR:\t\t0x%X\n", v[0]);649 650	for (i = 0, v[4] = 0xE0; i < 5; i++, v[4] += 0x10) {651		get_values_from_reg(c->reg, v[4], 3, v);652		seq_printf(sf, "CU_INPUT%u_SIZE:\t\t0x%X\n", i, v[0]);653		seq_printf(sf, "CU_INPUT%u_OFFSET:\t0x%X\n", i, v[1]);654		seq_printf(sf, "CU_INPUT%u_CONTROL:\t0x%X\n", i, v[2]);655	}656 657	get_values_from_reg(c->reg, 0x130, 2, v);658	seq_printf(sf, "CU_USER_LOW:\t\t0x%X\n", v[0]);659	seq_printf(sf, "CU_USER_HIGH:\t\t0x%X\n", v[1]);660}661 662static const struct komeda_component_funcs d71_compiz_funcs = {663	.update		= d71_compiz_update,664	.disable	= d71_component_disable,665	.dump_register	= d71_compiz_dump,666};667 668static int d71_compiz_init(struct d71_dev *d71,669			   struct block_header *blk, u32 __iomem *reg)670{671	struct komeda_component *c;672	struct komeda_compiz *compiz;673	u32 pipe_id, comp_id;674 675	get_resources_id(blk->block_info, &pipe_id, &comp_id);676 677	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*compiz),678				 comp_id,679				 BLOCK_INFO_INPUT_ID(blk->block_info),680				 &d71_compiz_funcs,681				 CU_NUM_INPUT_IDS, get_valid_inputs(blk),682				 CU_NUM_OUTPUT_IDS, reg,683				 "CU%d", pipe_id);684	if (IS_ERR(c))685		return PTR_ERR(c);686 687	compiz = to_compiz(c);688 689	set_range(&compiz->hsize, 64, get_blk_line_size(d71, reg));690	set_range(&compiz->vsize, 64, d71->max_vsize);691 692	return 0;693}694 695static void d71_scaler_update_filter_lut(u32 __iomem *reg, u32 hsize_in,696					 u32 vsize_in, u32 hsize_out,697					 u32 vsize_out)698{699	u32 val = 0;700 701	if (hsize_in <= hsize_out)702		val  |= 0x62;703	else if (hsize_in <= (hsize_out + hsize_out / 2))704		val |= 0x63;705	else if (hsize_in <= hsize_out * 2)706		val |= 0x64;707	else if (hsize_in <= hsize_out * 2 + (hsize_out * 3) / 4)708		val |= 0x65;709	else710		val |= 0x66;711 712	if (vsize_in <= vsize_out)713		val  |= SC_VTSEL(0x6A);714	else if (vsize_in <= (vsize_out + vsize_out / 2))715		val |= SC_VTSEL(0x6B);716	else if (vsize_in <= vsize_out * 2)717		val |= SC_VTSEL(0x6C);718	else if (vsize_in <= vsize_out * 2 + vsize_out * 3 / 4)719		val |= SC_VTSEL(0x6D);720	else721		val |= SC_VTSEL(0x6E);722 723	malidp_write32(reg, SC_COEFFTAB, val);724}725 726static void d71_scaler_update(struct komeda_component *c,727			      struct komeda_component_state *state)728{729	struct komeda_scaler_state *st = to_scaler_st(state);730	u32 __iomem *reg = c->reg;731	u32 init_ph, delta_ph, ctrl;732 733	d71_scaler_update_filter_lut(reg, st->hsize_in, st->vsize_in,734				     st->hsize_out, st->vsize_out);735 736	malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize_in, st->vsize_in));737	malidp_write32(reg, SC_OUT_SIZE, HV_SIZE(st->hsize_out, st->vsize_out));738	malidp_write32(reg, SC_H_CROP, HV_CROP(st->left_crop, st->right_crop));739 740	/* for right part, HW only sample the valid pixel which means the pixels741	 * in left_crop will be jumpped, and the first sample pixel is:742	 *743	 * dst_a = st->total_hsize_out - st->hsize_out + st->left_crop + 0.5;744	 *745	 * Then the corresponding texel in src is:746	 *747	 * h_delta_phase = st->total_hsize_in / st->total_hsize_out;748	 * src_a = dst_A * h_delta_phase;749	 *750	 * and h_init_phase is src_a deduct the real source start src_S;751	 *752	 * src_S = st->total_hsize_in - st->hsize_in;753	 * h_init_phase = src_a - src_S;754	 *755	 * And HW precision for the initial/delta_phase is 16:16 fixed point,756	 * the following is the simplified formula757	 */758	if (st->right_part) {759		u32 dst_a = st->total_hsize_out - st->hsize_out + st->left_crop;760 761		if (st->en_img_enhancement)762			dst_a -= 1;763 764		init_ph = ((st->total_hsize_in * (2 * dst_a + 1) -765			    2 * st->total_hsize_out * (st->total_hsize_in -766			    st->hsize_in)) << 15) / st->total_hsize_out;767	} else {768		init_ph = (st->total_hsize_in << 15) / st->total_hsize_out;769	}770 771	malidp_write32(reg, SC_H_INIT_PH, init_ph);772 773	delta_ph = (st->total_hsize_in << 16) / st->total_hsize_out;774	malidp_write32(reg, SC_H_DELTA_PH, delta_ph);775 776	init_ph = (st->total_vsize_in << 15) / st->vsize_out;777	malidp_write32(reg, SC_V_INIT_PH, init_ph);778 779	delta_ph = (st->total_vsize_in << 16) / st->vsize_out;780	malidp_write32(reg, SC_V_DELTA_PH, delta_ph);781 782	ctrl = 0;783	ctrl |= st->en_scaling ? SC_CTRL_SCL : 0;784	ctrl |= st->en_alpha ? SC_CTRL_AP : 0;785	ctrl |= st->en_img_enhancement ? SC_CTRL_IENH : 0;786	/* If we use the hardware splitter we shouldn't set SC_CTRL_LS */787	if (st->en_split &&788	    state->inputs[0].component->id != KOMEDA_COMPONENT_SPLITTER)789		ctrl |= SC_CTRL_LS;790 791	malidp_write32(reg, BLK_CONTROL, ctrl);792	malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0));793}794 795static void d71_scaler_dump(struct komeda_component *c, struct seq_file *sf)796{797	u32 v[10];798 799	dump_block_header(sf, c->reg);800 801	get_values_from_reg(c->reg, 0x80, 1, v);802	seq_printf(sf, "SC_INPUT_ID0:\t\t0x%X\n", v[0]);803 804	get_values_from_reg(c->reg, 0xD0, 1, v);805	seq_printf(sf, "SC_CONTROL:\t\t0x%X\n", v[0]);806 807	get_values_from_reg(c->reg, 0xDC, 9, v);808	seq_printf(sf, "SC_COEFFTAB:\t\t0x%X\n", v[0]);809	seq_printf(sf, "SC_IN_SIZE:\t\t0x%X\n", v[1]);810	seq_printf(sf, "SC_OUT_SIZE:\t\t0x%X\n", v[2]);811	seq_printf(sf, "SC_H_CROP:\t\t0x%X\n", v[3]);812	seq_printf(sf, "SC_V_CROP:\t\t0x%X\n", v[4]);813	seq_printf(sf, "SC_H_INIT_PH:\t\t0x%X\n", v[5]);814	seq_printf(sf, "SC_H_DELTA_PH:\t\t0x%X\n", v[6]);815	seq_printf(sf, "SC_V_INIT_PH:\t\t0x%X\n", v[7]);816	seq_printf(sf, "SC_V_DELTA_PH:\t\t0x%X\n", v[8]);817 818	get_values_from_reg(c->reg, 0x130, 10, v);819	seq_printf(sf, "SC_ENH_LIMITS:\t\t0x%X\n", v[0]);820	seq_printf(sf, "SC_ENH_COEFF0:\t\t0x%X\n", v[1]);821	seq_printf(sf, "SC_ENH_COEFF1:\t\t0x%X\n", v[2]);822	seq_printf(sf, "SC_ENH_COEFF2:\t\t0x%X\n", v[3]);823	seq_printf(sf, "SC_ENH_COEFF3:\t\t0x%X\n", v[4]);824	seq_printf(sf, "SC_ENH_COEFF4:\t\t0x%X\n", v[5]);825	seq_printf(sf, "SC_ENH_COEFF5:\t\t0x%X\n", v[6]);826	seq_printf(sf, "SC_ENH_COEFF6:\t\t0x%X\n", v[7]);827	seq_printf(sf, "SC_ENH_COEFF7:\t\t0x%X\n", v[8]);828	seq_printf(sf, "SC_ENH_COEFF8:\t\t0x%X\n", v[9]);829}830 831static const struct komeda_component_funcs d71_scaler_funcs = {832	.update		= d71_scaler_update,833	.disable	= d71_component_disable,834	.dump_register	= d71_scaler_dump,835};836 837static int d71_scaler_init(struct d71_dev *d71,838			   struct block_header *blk, u32 __iomem *reg)839{840	struct komeda_component *c;841	struct komeda_scaler *scaler;842	u32 pipe_id, comp_id;843 844	get_resources_id(blk->block_info, &pipe_id, &comp_id);845 846	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*scaler),847				 comp_id, BLOCK_INFO_INPUT_ID(blk->block_info),848				 &d71_scaler_funcs,849				 1, get_valid_inputs(blk), 1, reg,850				 "CU%d_SCALER%d",851				 pipe_id, BLOCK_INFO_BLK_ID(blk->block_info));852 853	if (IS_ERR(c)) {854		DRM_ERROR("Failed to initialize scaler");855		return PTR_ERR(c);856	}857 858	scaler = to_scaler(c);859	set_range(&scaler->hsize, 4, __get_blk_line_size(d71, reg, 2048));860	set_range(&scaler->vsize, 4, 4096);861	scaler->max_downscaling = 6;862	scaler->max_upscaling = 64;863	scaler->scaling_split_overlap = 8;864	scaler->enh_split_overlap = 1;865 866	malidp_write32(c->reg, BLK_CONTROL, 0);867 868	return 0;869}870 871static int d71_downscaling_clk_check(struct komeda_pipeline *pipe,872				     struct drm_display_mode *mode,873				     unsigned long aclk_rate,874				     struct komeda_data_flow_cfg *dflow)875{876	u32 h_in = dflow->in_w;877	u32 v_in = dflow->in_h;878	u32 v_out = dflow->out_h;879	u64 fraction, denominator;880 881	/* D71 downscaling must satisfy the following equation882	 *883	 *   ACLK                   h_in * v_in884	 * ------- >= ---------------------------------------------885	 *  PXLCLK     (h_total - (1 + 2 * v_in / v_out)) * v_out886	 *887	 * In only horizontal downscaling situation, the right side should be888	 * multiplied by (h_total - 3) / (h_active - 3), then equation becomes889	 *890	 *   ACLK          h_in891	 * ------- >= ----------------892	 *  PXLCLK     (h_active - 3)893	 *894	 * To avoid precision lost the equation 1 will be convert to:895	 *896	 *   ACLK             h_in * v_in897	 * ------- >= -----------------------------------898	 *  PXLCLK     (h_total -1 ) * v_out -  2 * v_in899	 */900	if (v_in == v_out) {901		fraction = h_in;902		denominator = mode->hdisplay - 3;903	} else {904		fraction = h_in * v_in;905		denominator = (mode->htotal - 1) * v_out -  2 * v_in;906	}907 908	return aclk_rate * denominator >= mode->crtc_clock * 1000 * fraction ?909	       0 : -EINVAL;910}911 912static void d71_splitter_update(struct komeda_component *c,913				struct komeda_component_state *state)914{915	struct komeda_splitter_state *st = to_splitter_st(state);916	u32 __iomem *reg = c->reg;917 918	malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0));919	malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));920	malidp_write32(reg, SP_OVERLAP_SIZE, st->overlap & 0x1FFF);921	malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN);922}923 924static void d71_splitter_dump(struct komeda_component *c, struct seq_file *sf)925{926	u32 v[3];927 928	dump_block_header(sf, c->reg);929 930	get_values_from_reg(c->reg, BLK_INPUT_ID0, 1, v);931	seq_printf(sf, "SP_INPUT_ID0:\t\t0x%X\n", v[0]);932 933	get_values_from_reg(c->reg, BLK_CONTROL, 3, v);934	seq_printf(sf, "SP_CONTROL:\t\t0x%X\n", v[0]);935	seq_printf(sf, "SP_SIZE:\t\t0x%X\n", v[1]);936	seq_printf(sf, "SP_OVERLAP_SIZE:\t0x%X\n", v[2]);937}938 939static const struct komeda_component_funcs d71_splitter_funcs = {940	.update		= d71_splitter_update,941	.disable	= d71_component_disable,942	.dump_register	= d71_splitter_dump,943};944 945static int d71_splitter_init(struct d71_dev *d71,946			     struct block_header *blk, u32 __iomem *reg)947{948	struct komeda_component *c;949	struct komeda_splitter *splitter;950	u32 pipe_id, comp_id;951 952	get_resources_id(blk->block_info, &pipe_id, &comp_id);953 954	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*splitter),955				 comp_id,956				 BLOCK_INFO_INPUT_ID(blk->block_info),957				 &d71_splitter_funcs,958				 1, get_valid_inputs(blk), 2, reg,959				 "CU%d_SPLITTER", pipe_id);960 961	if (IS_ERR(c)) {962		DRM_ERROR("Failed to initialize splitter");963		return -1;964	}965 966	splitter = to_splitter(c);967 968	set_range(&splitter->hsize, 4, get_blk_line_size(d71, reg));969	set_range(&splitter->vsize, 4, d71->max_vsize);970 971	return 0;972}973 974static void d71_merger_update(struct komeda_component *c,975			      struct komeda_component_state *state)976{977	struct komeda_merger_state *st = to_merger_st(state);978	u32 __iomem *reg = c->reg;979	u32 index;980 981	for_each_changed_input(state, index)982		malidp_write32(reg, MG_INPUT_ID0 + index * 4,983			       to_d71_input_id(state, index));984 985	malidp_write32(reg, MG_SIZE, HV_SIZE(st->hsize_merged,986					     st->vsize_merged));987	malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN);988}989 990static void d71_merger_dump(struct komeda_component *c, struct seq_file *sf)991{992	u32 v;993 994	dump_block_header(sf, c->reg);995 996	get_values_from_reg(c->reg, MG_INPUT_ID0, 1, &v);997	seq_printf(sf, "MG_INPUT_ID0:\t\t0x%X\n", v);998 999	get_values_from_reg(c->reg, MG_INPUT_ID1, 1, &v);1000	seq_printf(sf, "MG_INPUT_ID1:\t\t0x%X\n", v);1001 1002	get_values_from_reg(c->reg, BLK_CONTROL, 1, &v);1003	seq_printf(sf, "MG_CONTROL:\t\t0x%X\n", v);1004 1005	get_values_from_reg(c->reg, MG_SIZE, 1, &v);1006	seq_printf(sf, "MG_SIZE:\t\t0x%X\n", v);1007}1008 1009static const struct komeda_component_funcs d71_merger_funcs = {1010	.update		= d71_merger_update,1011	.disable	= d71_component_disable,1012	.dump_register	= d71_merger_dump,1013};1014 1015static int d71_merger_init(struct d71_dev *d71,1016			   struct block_header *blk, u32 __iomem *reg)1017{1018	struct komeda_component *c;1019	struct komeda_merger *merger;1020	u32 pipe_id, comp_id;1021 1022	get_resources_id(blk->block_info, &pipe_id, &comp_id);1023 1024	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*merger),1025				 comp_id,1026				 BLOCK_INFO_INPUT_ID(blk->block_info),1027				 &d71_merger_funcs,1028				 MG_NUM_INPUTS_IDS, get_valid_inputs(blk),1029				 MG_NUM_OUTPUTS_IDS, reg,1030				 "CU%d_MERGER", pipe_id);1031 1032	if (IS_ERR(c)) {1033		DRM_ERROR("Failed to initialize merger.\n");1034		return PTR_ERR(c);1035	}1036 1037	merger = to_merger(c);1038 1039	set_range(&merger->hsize_merged, 4,1040		  __get_blk_line_size(d71, reg, 4032));1041	set_range(&merger->vsize_merged, 4, 4096);1042 1043	return 0;1044}1045 1046static void d71_improc_update(struct komeda_component *c,1047			      struct komeda_component_state *state)1048{1049	struct drm_crtc_state *crtc_st = state->crtc->state;1050	struct komeda_improc_state *st = to_improc_st(state);1051	struct d71_pipeline *pipe = to_d71_pipeline(c->pipeline);1052	u32 __iomem *reg = c->reg;1053	u32 index, mask = 0, ctrl = 0;1054 1055	for_each_changed_input(state, index)1056		malidp_write32(reg, BLK_INPUT_ID0 + index * 4,1057			       to_d71_input_id(state, index));1058 1059	malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));1060	malidp_write32(reg, IPS_DEPTH, st->color_depth);1061 1062	if (crtc_st->color_mgmt_changed) {1063		mask |= IPS_CTRL_FT | IPS_CTRL_RGB;1064 1065		if (crtc_st->gamma_lut) {1066			malidp_write_group(pipe->dou_ft_coeff_addr, FT_COEFF0,1067					   KOMEDA_N_GAMMA_COEFFS,1068					   st->fgamma_coeffs);1069			ctrl |= IPS_CTRL_FT; /* enable gamma */1070		}1071 1072		if (crtc_st->ctm) {1073			malidp_write_group(reg, IPS_RGB_RGB_COEFF0,1074					   KOMEDA_N_CTM_COEFFS,1075					   st->ctm_coeffs);1076			ctrl |= IPS_CTRL_RGB; /* enable gamut */1077		}1078	}1079 1080	mask |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;1081 1082	/* config color format */1083	if (st->color_format == DRM_COLOR_FORMAT_YCBCR420)1084		ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;1085	else if (st->color_format == DRM_COLOR_FORMAT_YCBCR422)1086		ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422;1087	else if (st->color_format == DRM_COLOR_FORMAT_YCBCR444)1088		ctrl |= IPS_CTRL_YUV;1089 1090	malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);1091}1092 1093static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf)1094{1095	u32 v[12], i;1096 1097	dump_block_header(sf, c->reg);1098 1099	get_values_from_reg(c->reg, 0x80, 2, v);1100	seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]);1101	seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]);1102 1103	get_values_from_reg(c->reg, 0xC0, 1, v);1104	seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]);1105 1106	get_values_from_reg(c->reg, 0xD0, 3, v);1107	seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]);1108	seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]);1109	seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]);1110 1111	get_values_from_reg(c->reg, 0x130, 12, v);1112	for (i = 0; i < 12; i++)1113		seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);1114 1115	get_values_from_reg(c->reg, 0x170, 12, v);1116	for (i = 0; i < 12; i++)1117		seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);1118}1119 1120static const struct komeda_component_funcs d71_improc_funcs = {1121	.update		= d71_improc_update,1122	.disable	= d71_component_disable,1123	.dump_register	= d71_improc_dump,1124};1125 1126static int d71_improc_init(struct d71_dev *d71,1127			   struct block_header *blk, u32 __iomem *reg)1128{1129	struct komeda_component *c;1130	struct komeda_improc *improc;1131	u32 pipe_id, comp_id, value;1132 1133	get_resources_id(blk->block_info, &pipe_id, &comp_id);1134 1135	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*improc),1136				 comp_id,1137				 BLOCK_INFO_INPUT_ID(blk->block_info),1138				 &d71_improc_funcs, IPS_NUM_INPUT_IDS,1139				 get_valid_inputs(blk),1140				 IPS_NUM_OUTPUT_IDS, reg, "DOU%d_IPS", pipe_id);1141	if (IS_ERR(c)) {1142		DRM_ERROR("Failed to add improc component\n");1143		return PTR_ERR(c);1144	}1145 1146	improc = to_improc(c);1147	improc->supported_color_depths = BIT(8) | BIT(10);1148	improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |1149					  DRM_COLOR_FORMAT_YCBCR444 |1150					  DRM_COLOR_FORMAT_YCBCR422;1151	value = malidp_read32(reg, BLK_INFO);1152	if (value & IPS_INFO_CHD420)1153		improc->supported_color_formats |= DRM_COLOR_FORMAT_YCBCR420;1154 1155	improc->supports_csc = true;1156	improc->supports_gamma = true;1157 1158	return 0;1159}1160 1161static void d71_timing_ctrlr_disable(struct komeda_component *c)1162{1163	malidp_write32_mask(c->reg, BLK_CONTROL, BS_CTRL_EN, 0);1164}1165 1166static void d71_timing_ctrlr_update(struct komeda_component *c,1167				    struct komeda_component_state *state)1168{1169	struct drm_crtc_state *crtc_st = state->crtc->state;1170	struct drm_display_mode *mode = &crtc_st->adjusted_mode;1171	u32 __iomem *reg = c->reg;1172	u32 hactive, hfront_porch, hback_porch, hsync_len;1173	u32 vactive, vfront_porch, vback_porch, vsync_len;1174	u32 value;1175 1176	hactive = mode->crtc_hdisplay;1177	hfront_porch = mode->crtc_hsync_start - mode->crtc_hdisplay;1178	hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;1179	hback_porch = mode->crtc_htotal - mode->crtc_hsync_end;1180 1181	vactive = mode->crtc_vdisplay;1182	vfront_porch = mode->crtc_vsync_start - mode->crtc_vdisplay;1183	vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;1184	vback_porch = mode->crtc_vtotal - mode->crtc_vsync_end;1185 1186	malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(hactive, vactive));1187	malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(hfront_porch,1188							hback_porch));1189	malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vfront_porch,1190							vback_porch));1191 1192	value = BS_SYNC_VSW(vsync_len) | BS_SYNC_HSW(hsync_len);1193	value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BS_SYNC_VSP : 0;1194	value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BS_SYNC_HSP : 0;1195	malidp_write32(reg, BS_SYNC, value);1196 1197	malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1);1198	malidp_write32(reg, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE);1199 1200	/* configure bs control register */1201	value = BS_CTRL_EN | BS_CTRL_VM;1202	if (c->pipeline->dual_link) {1203		malidp_write32(reg, BS_DRIFT_TO, hfront_porch + 16);1204		value |= BS_CTRL_DL;1205	}1206 1207	malidp_write32(reg, BLK_CONTROL, value);1208}1209 1210static void d71_timing_ctrlr_dump(struct komeda_component *c,1211				  struct seq_file *sf)1212{1213	u32 v[8], i;1214 1215	dump_block_header(sf, c->reg);1216 1217	get_values_from_reg(c->reg, 0xC0, 1, v);1218	seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]);1219 1220	get_values_from_reg(c->reg, 0xD0, 8, v);1221	seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]);1222	seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]);1223	seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]);1224	seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]);1225	seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]);1226	seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]);1227	seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]);1228	seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]);1229 1230	get_values_from_reg(c->reg, 0x100, 3, v);1231	seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]);1232	seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]);1233	seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]);1234 1235	get_values_from_reg(c->reg, 0x110, 3, v);1236	for (i = 0; i < 3; i++)1237		seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]);1238 1239	get_values_from_reg(c->reg, 0x120, 5, v);1240	for (i = 0; i < 2; i++) {1241		seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]);1242		seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]);1243	}1244	seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]);1245}1246 1247static const struct komeda_component_funcs d71_timing_ctrlr_funcs = {1248	.update		= d71_timing_ctrlr_update,1249	.disable	= d71_timing_ctrlr_disable,1250	.dump_register	= d71_timing_ctrlr_dump,1251};1252 1253static int d71_timing_ctrlr_init(struct d71_dev *d71,1254				 struct block_header *blk, u32 __iomem *reg)1255{1256	struct komeda_component *c;1257	struct komeda_timing_ctrlr *ctrlr;1258	u32 pipe_id, comp_id;1259 1260	get_resources_id(blk->block_info, &pipe_id, &comp_id);1261 1262	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*ctrlr),1263				 KOMEDA_COMPONENT_TIMING_CTRLR,1264				 BLOCK_INFO_INPUT_ID(blk->block_info),1265				 &d71_timing_ctrlr_funcs,1266				 1, BIT(KOMEDA_COMPONENT_IPS0 + pipe_id),1267				 BS_NUM_OUTPUT_IDS, reg, "DOU%d_BS", pipe_id);1268	if (IS_ERR(c)) {1269		DRM_ERROR("Failed to add display_ctrl component\n");1270		return PTR_ERR(c);1271	}1272 1273	ctrlr = to_ctrlr(c);1274 1275	ctrlr->supports_dual_link = d71->supports_dual_link;1276 1277	return 0;1278}1279 1280int d71_probe_block(struct d71_dev *d71,1281		    struct block_header *blk, u32 __iomem *reg)1282{1283	struct d71_pipeline *pipe;1284	int blk_id = BLOCK_INFO_BLK_ID(blk->block_info);1285 1286	int err = 0;1287 1288	switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) {1289	case D71_BLK_TYPE_GCU:1290		break;1291 1292	case D71_BLK_TYPE_LPU:1293		pipe = d71->pipes[blk_id];1294		pipe->lpu_addr = reg;1295		break;1296 1297	case D71_BLK_TYPE_LPU_LAYER:1298		err = d71_layer_init(d71, blk, reg);1299		break;1300 1301	case D71_BLK_TYPE_LPU_WB_LAYER:1302		err = d71_wb_layer_init(d71, blk, reg);1303		break;1304 1305	case D71_BLK_TYPE_CU:1306		pipe = d71->pipes[blk_id];1307		pipe->cu_addr = reg;1308		err = d71_compiz_init(d71, blk, reg);1309		break;1310 1311	case D71_BLK_TYPE_CU_SCALER:1312		err = d71_scaler_init(d71, blk, reg);1313		break;1314 1315	case D71_BLK_TYPE_CU_SPLITTER:1316		err = d71_splitter_init(d71, blk, reg);1317		break;1318 1319	case D71_BLK_TYPE_CU_MERGER:1320		err = d71_merger_init(d71, blk, reg);1321		break;1322 1323	case D71_BLK_TYPE_DOU:1324		pipe = d71->pipes[blk_id];1325		pipe->dou_addr = reg;1326		break;1327 1328	case D71_BLK_TYPE_DOU_IPS:1329		err = d71_improc_init(d71, blk, reg);1330		break;1331 1332	case D71_BLK_TYPE_DOU_FT_COEFF:1333		pipe = d71->pipes[blk_id];1334		pipe->dou_ft_coeff_addr = reg;1335		break;1336 1337	case D71_BLK_TYPE_DOU_BS:1338		err = d71_timing_ctrlr_init(d71, blk, reg);1339		break;1340 1341	case D71_BLK_TYPE_GLB_LT_COEFF:1342		break;1343 1344	case D71_BLK_TYPE_GLB_SCL_COEFF:1345		d71->glb_scl_coeff_addr[blk_id] = reg;1346		break;1347 1348	default:1349		DRM_ERROR("Unknown block (block_info: 0x%x) is found\n",1350			  blk->block_info);1351		err = -EINVAL;1352		break;1353	}1354 1355	return err;1356}1357 1358static void d71_gcu_dump(struct d71_dev *d71, struct seq_file *sf)1359{1360	u32 v[5];1361 1362	seq_puts(sf, "\n------ GCU ------\n");1363 1364	get_values_from_reg(d71->gcu_addr, 0, 3, v);1365	seq_printf(sf, "GLB_ARCH_ID:\t\t0x%X\n", v[0]);1366	seq_printf(sf, "GLB_CORE_ID:\t\t0x%X\n", v[1]);1367	seq_printf(sf, "GLB_CORE_INFO:\t\t0x%X\n", v[2]);1368 1369	get_values_from_reg(d71->gcu_addr, 0x10, 1, v);1370	seq_printf(sf, "GLB_IRQ_STATUS:\t\t0x%X\n", v[0]);1371 1372	get_values_from_reg(d71->gcu_addr, 0xA0, 5, v);1373	seq_printf(sf, "GCU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);1374	seq_printf(sf, "GCU_IRQ_CLEAR:\t\t0x%X\n", v[1]);1375	seq_printf(sf, "GCU_IRQ_MASK:\t\t0x%X\n", v[2]);1376	seq_printf(sf, "GCU_IRQ_STATUS:\t\t0x%X\n", v[3]);1377	seq_printf(sf, "GCU_STATUS:\t\t0x%X\n", v[4]);1378 1379	get_values_from_reg(d71->gcu_addr, 0xD0, 3, v);1380	seq_printf(sf, "GCU_CONTROL:\t\t0x%X\n", v[0]);1381	seq_printf(sf, "GCU_CONFIG_VALID0:\t0x%X\n", v[1]);1382	seq_printf(sf, "GCU_CONFIG_VALID1:\t0x%X\n", v[2]);1383}1384 1385static void d71_lpu_dump(struct d71_pipeline *pipe, struct seq_file *sf)1386{1387	u32 v[6];1388 1389	seq_printf(sf, "\n------ LPU%d ------\n", pipe->base.id);1390 1391	dump_block_header(sf, pipe->lpu_addr);1392 1393	get_values_from_reg(pipe->lpu_addr, 0xA0, 6, v);1394	seq_printf(sf, "LPU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);1395	seq_printf(sf, "LPU_IRQ_CLEAR:\t\t0x%X\n", v[1]);1396	seq_printf(sf, "LPU_IRQ_MASK:\t\t0x%X\n", v[2]);1397	seq_printf(sf, "LPU_IRQ_STATUS:\t\t0x%X\n", v[3]);1398	seq_printf(sf, "LPU_STATUS:\t\t0x%X\n", v[4]);1399	seq_printf(sf, "LPU_TBU_STATUS:\t\t0x%X\n", v[5]);1400 1401	get_values_from_reg(pipe->lpu_addr, 0xC0, 1, v);1402	seq_printf(sf, "LPU_INFO:\t\t0x%X\n", v[0]);1403 1404	get_values_from_reg(pipe->lpu_addr, 0xD0, 3, v);1405	seq_printf(sf, "LPU_RAXI_CONTROL:\t0x%X\n", v[0]);1406	seq_printf(sf, "LPU_WAXI_CONTROL:\t0x%X\n", v[1]);1407	seq_printf(sf, "LPU_TBU_CONTROL:\t0x%X\n", v[2]);1408}1409 1410static void d71_dou_dump(struct d71_pipeline *pipe, struct seq_file *sf)1411{1412	u32 v[5];1413 1414	seq_printf(sf, "\n------ DOU%d ------\n", pipe->base.id);1415 1416	dump_block_header(sf, pipe->dou_addr);1417 1418	get_values_from_reg(pipe->dou_addr, 0xA0, 5, v);1419	seq_printf(sf, "DOU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);1420	seq_printf(sf, "DOU_IRQ_CLEAR:\t\t0x%X\n", v[1]);1421	seq_printf(sf, "DOU_IRQ_MASK:\t\t0x%X\n", v[2]);1422	seq_printf(sf, "DOU_IRQ_STATUS:\t\t0x%X\n", v[3]);1423	seq_printf(sf, "DOU_STATUS:\t\t0x%X\n", v[4]);1424}1425 1426static void d71_pipeline_dump(struct komeda_pipeline *pipe, struct seq_file *sf)1427{1428	struct d71_pipeline *d71_pipe = to_d71_pipeline(pipe);1429 1430	d71_lpu_dump(d71_pipe, sf);1431	d71_dou_dump(d71_pipe, sf);1432}1433 1434const struct komeda_pipeline_funcs d71_pipeline_funcs = {1435	.downscaling_clk_check	= d71_downscaling_clk_check,1436	.dump_register		= d71_pipeline_dump,1437};1438 1439void d71_dump(struct komeda_dev *mdev, struct seq_file *sf)1440{1441	struct d71_dev *d71 = mdev->chip_data;1442 1443	d71_gcu_dump(d71, sf);1444}1445