1 // SPDX-License-Identifier: GPL-2.0
3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4 * Author: James.Qian.Wang <james.qian.wang@arm.com>
8 #include <drm/drm_print.h>
10 #include "komeda_kms.h"
11 #include "malidp_io.h"
12 #include "komeda_framebuffer.h"
14 static void get_resources_id(u32 hw_id, u32 *pipe_id, u32 *comp_id)
16 u32 id = BLOCK_INFO_BLK_ID(hw_id);
19 switch (BLOCK_INFO_BLK_TYPE(hw_id)) {
20 case D71_BLK_TYPE_LPU_WB_LAYER:
21 id = KOMEDA_COMPONENT_WB_LAYER;
23 case D71_BLK_TYPE_CU_SPLITTER:
24 id = KOMEDA_COMPONENT_SPLITTER;
26 case D71_BLK_TYPE_CU_SCALER:
27 pipe = id / D71_PIPELINE_MAX_SCALERS;
28 id %= D71_PIPELINE_MAX_SCALERS;
29 id += KOMEDA_COMPONENT_SCALER0;
32 id += KOMEDA_COMPONENT_COMPIZ0;
34 case D71_BLK_TYPE_LPU_LAYER:
35 pipe = id / D71_PIPELINE_MAX_LAYERS;
36 id %= D71_PIPELINE_MAX_LAYERS;
37 id += KOMEDA_COMPONENT_LAYER0;
39 case D71_BLK_TYPE_DOU_IPS:
40 id += KOMEDA_COMPONENT_IPS0;
42 case D71_BLK_TYPE_CU_MERGER:
43 id = KOMEDA_COMPONENT_MERGER;
45 case D71_BLK_TYPE_DOU:
46 id = KOMEDA_COMPONENT_TIMING_CTRLR;
59 static u32 get_valid_inputs(struct block_header *blk)
61 u32 valid_inputs = 0, comp_id;
64 for (i = 0; i < PIPELINE_INFO_N_VALID_INPUTS(blk->pipeline_info); i++) {
65 get_resources_id(blk->input_ids[i], NULL, &comp_id);
66 if (comp_id == 0xFFFFFFFF)
68 valid_inputs |= BIT(comp_id);
74 static void get_values_from_reg(void __iomem *reg, u32 offset,
79 for (i = 0; i < count; i++) {
80 addr = offset + (i << 2);
81 /* 0xA4 is WO register */
83 val[i] = malidp_read32(reg, addr);
89 static void dump_block_header(struct seq_file *sf, void __iomem *reg)
91 struct block_header hdr;
92 u32 i, n_input, n_output;
94 d71_read_block_header(reg, &hdr);
95 seq_printf(sf, "BLOCK_INFO:\t\t0x%X\n", hdr.block_info);
96 seq_printf(sf, "PIPELINE_INFO:\t\t0x%X\n", hdr.pipeline_info);
98 n_output = PIPELINE_INFO_N_OUTPUTS(hdr.pipeline_info);
99 n_input = PIPELINE_INFO_N_VALID_INPUTS(hdr.pipeline_info);
101 for (i = 0; i < n_input; i++)
102 seq_printf(sf, "VALID_INPUT_ID%u:\t0x%X\n",
103 i, hdr.input_ids[i]);
105 for (i = 0; i < n_output; i++)
106 seq_printf(sf, "OUTPUT_ID%u:\t\t0x%X\n",
107 i, hdr.output_ids[i]);
110 static u32 to_rot_ctrl(u32 rot)
114 switch (rot & DRM_MODE_ROTATE_MASK) {
115 case DRM_MODE_ROTATE_0:
116 lr_ctrl |= L_ROT(L_ROT_R0);
118 case DRM_MODE_ROTATE_90:
119 lr_ctrl |= L_ROT(L_ROT_R90);
121 case DRM_MODE_ROTATE_180:
122 lr_ctrl |= L_ROT(L_ROT_R180);
124 case DRM_MODE_ROTATE_270:
125 lr_ctrl |= L_ROT(L_ROT_R270);
129 if (rot & DRM_MODE_REFLECT_X)
131 if (rot & DRM_MODE_REFLECT_Y)
137 static u32 to_ad_ctrl(u64 modifier)
139 u32 afbc_ctrl = AD_AEN;
144 if ((modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) ==
145 AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)
148 if (modifier & AFBC_FORMAT_MOD_YTR)
150 if (modifier & AFBC_FORMAT_MOD_SPLIT)
152 if (modifier & AFBC_FORMAT_MOD_TILED)
158 static inline u32 to_d71_input_id(struct komeda_component_output *output)
160 struct komeda_component *comp = output->component;
162 return comp ? (comp->hw_id + output->output_port) : 0;
165 static void d71_layer_disable(struct komeda_component *c)
167 malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
170 static void d71_layer_update(struct komeda_component *c,
171 struct komeda_component_state *state)
173 struct komeda_layer_state *st = to_layer_st(state);
174 struct drm_plane_state *plane_st = state->plane->state;
175 struct drm_framebuffer *fb = plane_st->fb;
176 struct komeda_fb *kfb = to_kfb(fb);
177 u32 __iomem *reg = c->reg;
178 u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN;
179 u32 ctrl = L_EN | to_rot_ctrl(st->rot);
182 for (i = 0; i < fb->format->num_planes; i++) {
184 BLK_P0_PTR_LOW + i * LAYER_PER_PLANE_REGS * 4,
185 lower_32_bits(st->addr[i]));
187 BLK_P0_PTR_HIGH + i * LAYER_PER_PLANE_REGS * 4,
188 upper_32_bits(st->addr[i]));
193 BLK_P0_STRIDE + i * LAYER_PER_PLANE_REGS * 4,
194 fb->pitches[i] & 0xFFFF);
197 malidp_write32(reg, AD_CONTROL, to_ad_ctrl(fb->modifier));
201 malidp_write32(reg, LAYER_AD_H_CROP, HV_CROP(st->afbc_crop_l,
203 malidp_write32(reg, LAYER_AD_V_CROP, HV_CROP(st->afbc_crop_t,
205 /* afbc 1.2 wants payload, afbc 1.0/1.1 wants end_addr */
206 if (fb->modifier & AFBC_FORMAT_MOD_TILED)
207 addr = st->addr[0] + kfb->offset_payload;
209 addr = st->addr[0] + kfb->afbc_size - 1;
211 malidp_write32(reg, BLK_P1_PTR_LOW, lower_32_bits(addr));
212 malidp_write32(reg, BLK_P1_PTR_HIGH, upper_32_bits(addr));
215 malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
216 malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
218 malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
221 static void d71_layer_dump(struct komeda_component *c, struct seq_file *sf)
227 get_values_from_reg(c->reg, LAYER_INFO, 1, &v[14]);
236 rgb2rgb = !!(v[14] & L_INFO_CM);
238 dump_block_header(sf, c->reg);
240 seq_printf(sf, "%sLAYER_INFO:\t\t0x%X\n", prefix, v[14]);
242 get_values_from_reg(c->reg, 0xD0, 1, v);
243 seq_printf(sf, "%sCONTROL:\t\t0x%X\n", prefix, v[0]);
245 get_values_from_reg(c->reg, 0xD4, 1, v);
246 seq_printf(sf, "LR_RICH_CONTROL:\t0x%X\n", v[0]);
248 get_values_from_reg(c->reg, 0xD8, 4, v);
249 seq_printf(sf, "%sFORMAT:\t\t0x%X\n", prefix, v[0]);
250 seq_printf(sf, "%sIT_COEFFTAB:\t\t0x%X\n", prefix, v[1]);
251 seq_printf(sf, "%sIN_SIZE:\t\t0x%X\n", prefix, v[2]);
252 seq_printf(sf, "%sPALPHA:\t\t0x%X\n", prefix, v[3]);
254 get_values_from_reg(c->reg, 0x100, 3, v);
255 seq_printf(sf, "%sP0_PTR_LOW:\t\t0x%X\n", prefix, v[0]);
256 seq_printf(sf, "%sP0_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);
257 seq_printf(sf, "%sP0_STRIDE:\t\t0x%X\n", prefix, v[2]);
259 get_values_from_reg(c->reg, 0x110, 2, v);
260 seq_printf(sf, "%sP1_PTR_LOW:\t\t0x%X\n", prefix, v[0]);
261 seq_printf(sf, "%sP1_PTR_HIGH:\t\t0x%X\n", prefix, v[1]);
263 get_values_from_reg(c->reg, 0x118, 1, v);
264 seq_printf(sf, "LR_P1_STRIDE:\t\t0x%X\n", v[0]);
266 get_values_from_reg(c->reg, 0x120, 2, v);
267 seq_printf(sf, "LR_P2_PTR_LOW:\t\t0x%X\n", v[0]);
268 seq_printf(sf, "LR_P2_PTR_HIGH:\t\t0x%X\n", v[1]);
270 get_values_from_reg(c->reg, 0x130, 12, v);
271 for (i = 0; i < 12; i++)
272 seq_printf(sf, "LR_YUV_RGB_COEFF%u:\t0x%X\n", i, v[i]);
276 get_values_from_reg(c->reg, LAYER_RGB_RGB_COEFF0, 12, v);
277 for (i = 0; i < 12; i++)
278 seq_printf(sf, "LS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);
281 get_values_from_reg(c->reg, 0x160, 3, v);
282 seq_printf(sf, "%sAD_CONTROL:\t\t0x%X\n", prefix, v[0]);
283 seq_printf(sf, "%sAD_H_CROP:\t\t0x%X\n", prefix, v[1]);
284 seq_printf(sf, "%sAD_V_CROP:\t\t0x%X\n", prefix, v[2]);
287 static const struct komeda_component_funcs d71_layer_funcs = {
288 .update = d71_layer_update,
289 .disable = d71_layer_disable,
290 .dump_register = d71_layer_dump,
293 static int d71_layer_init(struct d71_dev *d71,
294 struct block_header *blk, u32 __iomem *reg)
296 struct komeda_component *c;
297 struct komeda_layer *layer;
298 u32 pipe_id, layer_id, layer_info;
300 get_resources_id(blk->block_info, &pipe_id, &layer_id);
301 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer),
303 BLOCK_INFO_INPUT_ID(blk->block_info),
305 get_valid_inputs(blk),
306 1, reg, "LPU%d_LAYER%d", pipe_id, layer_id);
308 DRM_ERROR("Failed to add layer component\n");
313 layer_info = malidp_read32(reg, LAYER_INFO);
315 if (layer_info & L_INFO_RF)
316 layer->layer_type = KOMEDA_FMT_RICH_LAYER;
318 layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER;
320 set_range(&layer->hsize_in, 4, d71->max_line_size);
321 set_range(&layer->vsize_in, 4, d71->max_vsize);
323 malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP);
325 layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK;
330 static void d71_wb_layer_update(struct komeda_component *c,
331 struct komeda_component_state *state)
333 struct komeda_layer_state *st = to_layer_st(state);
334 struct drm_connector_state *conn_st = state->wb_conn->state;
335 struct drm_framebuffer *fb = conn_st->writeback_job->fb;
336 struct komeda_fb *kfb = to_kfb(fb);
337 u32 __iomem *reg = c->reg;
338 u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN;
341 for (i = 0; i < fb->format->num_planes; i++) {
342 malidp_write32(reg + i * LAYER_PER_PLANE_REGS, BLK_P0_PTR_LOW,
343 lower_32_bits(st->addr[i]));
344 malidp_write32(reg + i * LAYER_PER_PLANE_REGS, BLK_P0_PTR_HIGH,
345 upper_32_bits(st->addr[i]));
347 malidp_write32(reg + i * LAYER_PER_PLANE_REGS, BLK_P0_STRIDE,
348 fb->pitches[i] & 0xFFFF);
351 malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
352 malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
353 malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(&state->inputs[0]));
354 malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);
357 static void d71_wb_layer_dump(struct komeda_component *c, struct seq_file *sf)
361 dump_block_header(sf, c->reg);
363 get_values_from_reg(c->reg, 0x80, 1, v);
364 seq_printf(sf, "LW_INPUT_ID0:\t\t0x%X\n", v[0]);
366 get_values_from_reg(c->reg, 0xD0, 3, v);
367 seq_printf(sf, "LW_CONTROL:\t\t0x%X\n", v[0]);
368 seq_printf(sf, "LW_PROG_LINE:\t\t0x%X\n", v[1]);
369 seq_printf(sf, "LW_FORMAT:\t\t0x%X\n", v[2]);
371 get_values_from_reg(c->reg, 0xE0, 1, v);
372 seq_printf(sf, "LW_IN_SIZE:\t\t0x%X\n", v[0]);
374 for (i = 0; i < 2; i++) {
375 get_values_from_reg(c->reg, 0x100 + i * 0x10, 3, v);
376 seq_printf(sf, "LW_P%u_PTR_LOW:\t\t0x%X\n", i, v[0]);
377 seq_printf(sf, "LW_P%u_PTR_HIGH:\t\t0x%X\n", i, v[1]);
378 seq_printf(sf, "LW_P%u_STRIDE:\t\t0x%X\n", i, v[2]);
381 get_values_from_reg(c->reg, 0x130, 12, v);
382 for (i = 0; i < 12; i++)
383 seq_printf(sf, "LW_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);
386 static void d71_wb_layer_disable(struct komeda_component *c)
388 malidp_write32(c->reg, BLK_INPUT_ID0, 0);
389 malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
392 static const struct komeda_component_funcs d71_wb_layer_funcs = {
393 .update = d71_wb_layer_update,
394 .disable = d71_wb_layer_disable,
395 .dump_register = d71_wb_layer_dump,
398 static int d71_wb_layer_init(struct d71_dev *d71,
399 struct block_header *blk, u32 __iomem *reg)
401 struct komeda_component *c;
402 struct komeda_layer *wb_layer;
403 u32 pipe_id, layer_id;
405 get_resources_id(blk->block_info, &pipe_id, &layer_id);
407 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*wb_layer),
408 layer_id, BLOCK_INFO_INPUT_ID(blk->block_info),
410 1, get_valid_inputs(blk), 0, reg,
411 "LPU%d_LAYER_WR", pipe_id);
413 DRM_ERROR("Failed to add wb_layer component\n");
417 wb_layer = to_layer(c);
418 wb_layer->layer_type = KOMEDA_FMT_WB_LAYER;
420 set_range(&wb_layer->hsize_in, D71_MIN_LINE_SIZE, d71->max_line_size);
421 set_range(&wb_layer->vsize_in, D71_MIN_VERTICAL_SIZE, d71->max_vsize);
426 static void d71_component_disable(struct komeda_component *c)
428 u32 __iomem *reg = c->reg;
431 malidp_write32(reg, BLK_CONTROL, 0);
433 for (i = 0; i < c->max_active_inputs; i++)
434 malidp_write32(reg, BLK_INPUT_ID0 + (i << 2), 0);
437 static void compiz_enable_input(u32 __iomem *id_reg,
438 u32 __iomem *cfg_reg,
440 struct komeda_compiz_input_cfg *cin)
442 u32 ctrl = CU_INPUT_CTRL_EN;
443 u8 blend = cin->pixel_blend_mode;
445 if (blend == DRM_MODE_BLEND_PIXEL_NONE)
446 ctrl |= CU_INPUT_CTRL_PAD;
447 else if (blend == DRM_MODE_BLEND_PREMULTI)
448 ctrl |= CU_INPUT_CTRL_PMUL;
450 ctrl |= CU_INPUT_CTRL_ALPHA(cin->layer_alpha);
452 malidp_write32(id_reg, BLK_INPUT_ID0, input_hw_id);
454 malidp_write32(cfg_reg, CU_INPUT0_SIZE,
455 HV_SIZE(cin->hsize, cin->vsize));
456 malidp_write32(cfg_reg, CU_INPUT0_OFFSET,
457 HV_OFFSET(cin->hoffset, cin->voffset));
458 malidp_write32(cfg_reg, CU_INPUT0_CONTROL, ctrl);
461 static void d71_compiz_update(struct komeda_component *c,
462 struct komeda_component_state *state)
464 struct komeda_compiz_state *st = to_compiz_st(state);
465 u32 __iomem *reg = c->reg;
466 u32 __iomem *id_reg, *cfg_reg;
467 u32 index, input_hw_id;
469 for_each_changed_input(state, index) {
470 id_reg = reg + index;
471 cfg_reg = reg + index * CU_PER_INPUT_REGS;
472 input_hw_id = to_d71_input_id(&state->inputs[index]);
473 if (state->active_inputs & BIT(index)) {
474 compiz_enable_input(id_reg, cfg_reg,
475 input_hw_id, &st->cins[index]);
477 malidp_write32(id_reg, BLK_INPUT_ID0, 0);
478 malidp_write32(cfg_reg, CU_INPUT0_CONTROL, 0);
482 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
485 static void d71_compiz_dump(struct komeda_component *c, struct seq_file *sf)
489 dump_block_header(sf, c->reg);
491 get_values_from_reg(c->reg, 0x80, 5, v);
492 for (i = 0; i < 5; i++)
493 seq_printf(sf, "CU_INPUT_ID%u:\t\t0x%X\n", i, v[i]);
495 get_values_from_reg(c->reg, 0xA0, 5, v);
496 seq_printf(sf, "CU_IRQ_RAW_STATUS:\t0x%X\n", v[0]);
497 seq_printf(sf, "CU_IRQ_CLEAR:\t\t0x%X\n", v[1]);
498 seq_printf(sf, "CU_IRQ_MASK:\t\t0x%X\n", v[2]);
499 seq_printf(sf, "CU_IRQ_STATUS:\t\t0x%X\n", v[3]);
500 seq_printf(sf, "CU_STATUS:\t\t0x%X\n", v[4]);
502 get_values_from_reg(c->reg, 0xD0, 2, v);
503 seq_printf(sf, "CU_CONTROL:\t\t0x%X\n", v[0]);
504 seq_printf(sf, "CU_SIZE:\t\t0x%X\n", v[1]);
506 get_values_from_reg(c->reg, 0xDC, 1, v);
507 seq_printf(sf, "CU_BG_COLOR:\t\t0x%X\n", v[0]);
509 for (i = 0, v[4] = 0xE0; i < 5; i++, v[4] += 0x10) {
510 get_values_from_reg(c->reg, v[4], 3, v);
511 seq_printf(sf, "CU_INPUT%u_SIZE:\t\t0x%X\n", i, v[0]);
512 seq_printf(sf, "CU_INPUT%u_OFFSET:\t0x%X\n", i, v[1]);
513 seq_printf(sf, "CU_INPUT%u_CONTROL:\t0x%X\n", i, v[2]);
516 get_values_from_reg(c->reg, 0x130, 2, v);
517 seq_printf(sf, "CU_USER_LOW:\t\t0x%X\n", v[0]);
518 seq_printf(sf, "CU_USER_HIGH:\t\t0x%X\n", v[1]);
521 static const struct komeda_component_funcs d71_compiz_funcs = {
522 .update = d71_compiz_update,
523 .disable = d71_component_disable,
524 .dump_register = d71_compiz_dump,
527 static int d71_compiz_init(struct d71_dev *d71,
528 struct block_header *blk, u32 __iomem *reg)
530 struct komeda_component *c;
531 struct komeda_compiz *compiz;
532 u32 pipe_id, comp_id;
534 get_resources_id(blk->block_info, &pipe_id, &comp_id);
536 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*compiz),
538 BLOCK_INFO_INPUT_ID(blk->block_info),
540 CU_NUM_INPUT_IDS, get_valid_inputs(blk),
541 CU_NUM_OUTPUT_IDS, reg,
546 compiz = to_compiz(c);
548 set_range(&compiz->hsize, D71_MIN_LINE_SIZE, d71->max_line_size);
549 set_range(&compiz->vsize, D71_MIN_VERTICAL_SIZE, d71->max_vsize);
554 static void d71_improc_update(struct komeda_component *c,
555 struct komeda_component_state *state)
557 struct komeda_improc_state *st = to_improc_st(state);
558 u32 __iomem *reg = c->reg;
559 u32 index, input_hw_id;
561 for_each_changed_input(state, index) {
562 input_hw_id = state->active_inputs & BIT(index) ?
563 to_d71_input_id(&state->inputs[index]) : 0;
564 malidp_write32(reg, BLK_INPUT_ID0 + index * 4, input_hw_id);
567 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
570 static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf)
574 dump_block_header(sf, c->reg);
576 get_values_from_reg(c->reg, 0x80, 2, v);
577 seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]);
578 seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]);
580 get_values_from_reg(c->reg, 0xC0, 1, v);
581 seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]);
583 get_values_from_reg(c->reg, 0xD0, 3, v);
584 seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]);
585 seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]);
586 seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]);
588 get_values_from_reg(c->reg, 0x130, 12, v);
589 for (i = 0; i < 12; i++)
590 seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]);
592 get_values_from_reg(c->reg, 0x170, 12, v);
593 for (i = 0; i < 12; i++)
594 seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);
597 static const struct komeda_component_funcs d71_improc_funcs = {
598 .update = d71_improc_update,
599 .disable = d71_component_disable,
600 .dump_register = d71_improc_dump,
603 static int d71_improc_init(struct d71_dev *d71,
604 struct block_header *blk, u32 __iomem *reg)
606 struct komeda_component *c;
607 struct komeda_improc *improc;
608 u32 pipe_id, comp_id, value;
610 get_resources_id(blk->block_info, &pipe_id, &comp_id);
612 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*improc),
614 BLOCK_INFO_INPUT_ID(blk->block_info),
615 &d71_improc_funcs, IPS_NUM_INPUT_IDS,
616 get_valid_inputs(blk),
617 IPS_NUM_OUTPUT_IDS, reg, "DOU%d_IPS", pipe_id);
619 DRM_ERROR("Failed to add improc component\n");
623 improc = to_improc(c);
624 improc->supported_color_depths = BIT(8) | BIT(10);
625 improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
626 DRM_COLOR_FORMAT_YCRCB444 |
627 DRM_COLOR_FORMAT_YCRCB422;
628 value = malidp_read32(reg, BLK_INFO);
629 if (value & IPS_INFO_CHD420)
630 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCRCB420;
632 improc->supports_csc = true;
633 improc->supports_gamma = true;
638 static void d71_timing_ctrlr_disable(struct komeda_component *c)
640 malidp_write32_mask(c->reg, BLK_CONTROL, BS_CTRL_EN, 0);
643 static void d71_timing_ctrlr_update(struct komeda_component *c,
644 struct komeda_component_state *state)
646 struct drm_crtc_state *crtc_st = state->crtc->state;
647 u32 __iomem *reg = c->reg;
651 drm_display_mode_to_videomode(&crtc_st->adjusted_mode, &vm);
653 malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(vm.hactive, vm.vactive));
654 malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(vm.hfront_porch,
656 malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vm.vfront_porch,
659 value = BS_SYNC_VSW(vm.vsync_len) | BS_SYNC_HSW(vm.hsync_len);
660 value |= vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? BS_SYNC_VSP : 0;
661 value |= vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? BS_SYNC_HSP : 0;
662 malidp_write32(reg, BS_SYNC, value);
664 malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1);
665 malidp_write32(reg, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE);
667 /* configure bs control register */
668 value = BS_CTRL_EN | BS_CTRL_VM;
670 malidp_write32(reg, BLK_CONTROL, value);
673 static void d71_timing_ctrlr_dump(struct komeda_component *c,
678 dump_block_header(sf, c->reg);
680 get_values_from_reg(c->reg, 0xC0, 1, v);
681 seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]);
683 get_values_from_reg(c->reg, 0xD0, 8, v);
684 seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]);
685 seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]);
686 seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]);
687 seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]);
688 seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]);
689 seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]);
690 seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]);
691 seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]);
693 get_values_from_reg(c->reg, 0x100, 3, v);
694 seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]);
695 seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]);
696 seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]);
698 get_values_from_reg(c->reg, 0x110, 3, v);
699 for (i = 0; i < 3; i++)
700 seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]);
702 get_values_from_reg(c->reg, 0x120, 5, v);
703 for (i = 0; i < 2; i++) {
704 seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]);
705 seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]);
707 seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]);
710 static const struct komeda_component_funcs d71_timing_ctrlr_funcs = {
711 .update = d71_timing_ctrlr_update,
712 .disable = d71_timing_ctrlr_disable,
713 .dump_register = d71_timing_ctrlr_dump,
716 static int d71_timing_ctrlr_init(struct d71_dev *d71,
717 struct block_header *blk, u32 __iomem *reg)
719 struct komeda_component *c;
720 struct komeda_timing_ctrlr *ctrlr;
721 u32 pipe_id, comp_id;
723 get_resources_id(blk->block_info, &pipe_id, &comp_id);
725 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*ctrlr),
726 KOMEDA_COMPONENT_TIMING_CTRLR,
727 BLOCK_INFO_INPUT_ID(blk->block_info),
728 &d71_timing_ctrlr_funcs,
729 1, BIT(KOMEDA_COMPONENT_IPS0 + pipe_id),
730 BS_NUM_OUTPUT_IDS, reg, "DOU%d_BS", pipe_id);
732 DRM_ERROR("Failed to add display_ctrl component\n");
738 ctrlr->supports_dual_link = true;
743 int d71_probe_block(struct d71_dev *d71,
744 struct block_header *blk, u32 __iomem *reg)
746 struct d71_pipeline *pipe;
747 int blk_id = BLOCK_INFO_BLK_ID(blk->block_info);
751 switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) {
752 case D71_BLK_TYPE_GCU:
755 case D71_BLK_TYPE_LPU:
756 pipe = d71->pipes[blk_id];
757 pipe->lpu_addr = reg;
760 case D71_BLK_TYPE_LPU_LAYER:
761 err = d71_layer_init(d71, blk, reg);
764 case D71_BLK_TYPE_LPU_WB_LAYER:
765 err = d71_wb_layer_init(d71, blk, reg);
768 case D71_BLK_TYPE_CU:
769 pipe = d71->pipes[blk_id];
771 err = d71_compiz_init(d71, blk, reg);
774 case D71_BLK_TYPE_CU_SPLITTER:
775 case D71_BLK_TYPE_CU_SCALER:
776 case D71_BLK_TYPE_CU_MERGER:
779 case D71_BLK_TYPE_DOU:
780 pipe = d71->pipes[blk_id];
781 pipe->dou_addr = reg;
784 case D71_BLK_TYPE_DOU_IPS:
785 err = d71_improc_init(d71, blk, reg);
788 case D71_BLK_TYPE_DOU_FT_COEFF:
789 pipe = d71->pipes[blk_id];
790 pipe->dou_ft_coeff_addr = reg;
793 case D71_BLK_TYPE_DOU_BS:
794 err = d71_timing_ctrlr_init(d71, blk, reg);
797 case D71_BLK_TYPE_GLB_LT_COEFF:
800 case D71_BLK_TYPE_GLB_SCL_COEFF:
801 d71->glb_scl_coeff_addr[blk_id] = reg;
805 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n",