1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved. 4 * Author: James.Qian.Wang <james.qian.wang@arm.com> 5 * 6 */ 7 8 #include <drm/drm_print.h> 9 #include "d71_dev.h" 10 #include "komeda_kms.h" 11 #include "malidp_io.h" 12 #include "komeda_framebuffer.h" 13 14 static void get_resources_id(u32 hw_id, u32 *pipe_id, u32 *comp_id) 15 { 16 u32 id = BLOCK_INFO_BLK_ID(hw_id); 17 u32 pipe = id; 18 19 switch (BLOCK_INFO_BLK_TYPE(hw_id)) { 20 case D71_BLK_TYPE_LPU_WB_LAYER: 21 id = KOMEDA_COMPONENT_WB_LAYER; 22 break; 23 case D71_BLK_TYPE_CU_SPLITTER: 24 id = KOMEDA_COMPONENT_SPLITTER; 25 break; 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; 30 break; 31 case D71_BLK_TYPE_CU: 32 id += KOMEDA_COMPONENT_COMPIZ0; 33 break; 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; 38 break; 39 case D71_BLK_TYPE_DOU_IPS: 40 id += KOMEDA_COMPONENT_IPS0; 41 break; 42 case D71_BLK_TYPE_CU_MERGER: 43 id = KOMEDA_COMPONENT_MERGER; 44 break; 45 case D71_BLK_TYPE_DOU: 46 id = KOMEDA_COMPONENT_TIMING_CTRLR; 47 break; 48 default: 49 id = 0xFFFFFFFF; 50 } 51 52 if (comp_id) 53 *comp_id = id; 54 55 if (pipe_id) 56 *pipe_id = pipe; 57 } 58 59 static u32 get_valid_inputs(struct block_header *blk) 60 { 61 u32 valid_inputs = 0, comp_id; 62 int i; 63 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) 67 continue; 68 valid_inputs |= BIT(comp_id); 69 } 70 71 return valid_inputs; 72 } 73 74 static void get_values_from_reg(void __iomem *reg, u32 offset, 75 u32 count, u32 *val) 76 { 77 u32 i, addr; 78 79 for (i = 0; i < count; i++) { 80 addr = offset + (i << 2); 81 /* 0xA4 is WO register */ 82 if (addr != 0xA4) 83 val[i] = malidp_read32(reg, addr); 84 else 85 val[i] = 0xDEADDEAD; 86 } 87 } 88 89 static void dump_block_header(struct seq_file *sf, void __iomem *reg) 90 { 91 struct block_header hdr; 92 u32 i, n_input, n_output; 93 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); 97 98 n_output = PIPELINE_INFO_N_OUTPUTS(hdr.pipeline_info); 99 n_input = PIPELINE_INFO_N_VALID_INPUTS(hdr.pipeline_info); 100 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]); 104 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]); 108 } 109 110 static u32 to_rot_ctrl(u32 rot) 111 { 112 u32 lr_ctrl = 0; 113 114 switch (rot & DRM_MODE_ROTATE_MASK) { 115 case DRM_MODE_ROTATE_0: 116 lr_ctrl |= L_ROT(L_ROT_R0); 117 break; 118 case DRM_MODE_ROTATE_90: 119 lr_ctrl |= L_ROT(L_ROT_R90); 120 break; 121 case DRM_MODE_ROTATE_180: 122 lr_ctrl |= L_ROT(L_ROT_R180); 123 break; 124 case DRM_MODE_ROTATE_270: 125 lr_ctrl |= L_ROT(L_ROT_R270); 126 break; 127 } 128 129 if (rot & DRM_MODE_REFLECT_X) 130 lr_ctrl |= L_HFLIP; 131 if (rot & DRM_MODE_REFLECT_Y) 132 lr_ctrl |= L_VFLIP; 133 134 return lr_ctrl; 135 } 136 137 static inline u32 to_d71_input_id(struct komeda_component_output *output) 138 { 139 struct komeda_component *comp = output->component; 140 141 return comp ? (comp->hw_id + output->output_port) : 0; 142 } 143 144 static void d71_layer_disable(struct komeda_component *c) 145 { 146 malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0); 147 } 148 149 static void d71_layer_update(struct komeda_component *c, 150 struct komeda_component_state *state) 151 { 152 struct komeda_layer_state *st = to_layer_st(state); 153 struct drm_plane_state *plane_st = state->plane->state; 154 struct drm_framebuffer *fb = plane_st->fb; 155 struct komeda_fb *kfb = to_kfb(fb); 156 u32 __iomem *reg = c->reg; 157 u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN; 158 u32 ctrl = L_EN | to_rot_ctrl(st->rot); 159 int i; 160 161 for (i = 0; i < fb->format->num_planes; i++) { 162 malidp_write32(reg, 163 BLK_P0_PTR_LOW + i * LAYER_PER_PLANE_REGS * 4, 164 lower_32_bits(st->addr[i])); 165 malidp_write32(reg, 166 BLK_P0_PTR_HIGH + i * LAYER_PER_PLANE_REGS * 4, 167 upper_32_bits(st->addr[i])); 168 if (i >= 2) 169 break; 170 171 malidp_write32(reg, 172 BLK_P0_STRIDE + i * LAYER_PER_PLANE_REGS * 4, 173 fb->pitches[i] & 0xFFFF); 174 } 175 176 malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id); 177 malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize)); 178 179 malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl); 180 } 181 182 static void d71_layer_dump(struct komeda_component *c, struct seq_file *sf) 183 { 184 u32 v[15], i; 185 bool rich, rgb2rgb; 186 char *prefix; 187 188 get_values_from_reg(c->reg, LAYER_INFO, 1, &v[14]); 189 if (v[14] & 0x1) { 190 rich = true; 191 prefix = "LR_"; 192 } else { 193 rich = false; 194 prefix = "LS_"; 195 } 196 197 rgb2rgb = !!(v[14] & L_INFO_CM); 198 199 dump_block_header(sf, c->reg); 200 201 seq_printf(sf, "%sLAYER_INFO:\t\t0x%X\n", prefix, v[14]); 202 203 get_values_from_reg(c->reg, 0xD0, 1, v); 204 seq_printf(sf, "%sCONTROL:\t\t0x%X\n", prefix, v[0]); 205 if (rich) { 206 get_values_from_reg(c->reg, 0xD4, 1, v); 207 seq_printf(sf, "LR_RICH_CONTROL:\t0x%X\n", v[0]); 208 } 209 get_values_from_reg(c->reg, 0xD8, 4, v); 210 seq_printf(sf, "%sFORMAT:\t\t0x%X\n", prefix, v[0]); 211 seq_printf(sf, "%sIT_COEFFTAB:\t\t0x%X\n", prefix, v[1]); 212 seq_printf(sf, "%sIN_SIZE:\t\t0x%X\n", prefix, v[2]); 213 seq_printf(sf, "%sPALPHA:\t\t0x%X\n", prefix, v[3]); 214 215 get_values_from_reg(c->reg, 0x100, 3, v); 216 seq_printf(sf, "%sP0_PTR_LOW:\t\t0x%X\n", prefix, v[0]); 217 seq_printf(sf, "%sP0_PTR_HIGH:\t\t0x%X\n", prefix, v[1]); 218 seq_printf(sf, "%sP0_STRIDE:\t\t0x%X\n", prefix, v[2]); 219 220 get_values_from_reg(c->reg, 0x110, 2, v); 221 seq_printf(sf, "%sP1_PTR_LOW:\t\t0x%X\n", prefix, v[0]); 222 seq_printf(sf, "%sP1_PTR_HIGH:\t\t0x%X\n", prefix, v[1]); 223 if (rich) { 224 get_values_from_reg(c->reg, 0x118, 1, v); 225 seq_printf(sf, "LR_P1_STRIDE:\t\t0x%X\n", v[0]); 226 227 get_values_from_reg(c->reg, 0x120, 2, v); 228 seq_printf(sf, "LR_P2_PTR_LOW:\t\t0x%X\n", v[0]); 229 seq_printf(sf, "LR_P2_PTR_HIGH:\t\t0x%X\n", v[1]); 230 231 get_values_from_reg(c->reg, 0x130, 12, v); 232 for (i = 0; i < 12; i++) 233 seq_printf(sf, "LR_YUV_RGB_COEFF%u:\t0x%X\n", i, v[i]); 234 } 235 236 if (rgb2rgb) { 237 get_values_from_reg(c->reg, LAYER_RGB_RGB_COEFF0, 12, v); 238 for (i = 0; i < 12; i++) 239 seq_printf(sf, "LS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]); 240 } 241 242 get_values_from_reg(c->reg, 0x160, 3, v); 243 seq_printf(sf, "%sAD_CONTROL:\t\t0x%X\n", prefix, v[0]); 244 seq_printf(sf, "%sAD_H_CROP:\t\t0x%X\n", prefix, v[1]); 245 seq_printf(sf, "%sAD_V_CROP:\t\t0x%X\n", prefix, v[2]); 246 } 247 248 static struct komeda_component_funcs d71_layer_funcs = { 249 .update = d71_layer_update, 250 .disable = d71_layer_disable, 251 .dump_register = d71_layer_dump, 252 }; 253 254 static int d71_layer_init(struct d71_dev *d71, 255 struct block_header *blk, u32 __iomem *reg) 256 { 257 struct komeda_component *c; 258 struct komeda_layer *layer; 259 u32 pipe_id, layer_id, layer_info; 260 261 get_resources_id(blk->block_info, &pipe_id, &layer_id); 262 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer), 263 layer_id, 264 BLOCK_INFO_INPUT_ID(blk->block_info), 265 &d71_layer_funcs, 0, 266 get_valid_inputs(blk), 267 1, reg, "LPU%d_LAYER%d", pipe_id, layer_id); 268 if (IS_ERR(c)) { 269 DRM_ERROR("Failed to add layer component\n"); 270 return PTR_ERR(c); 271 } 272 273 layer = to_layer(c); 274 layer_info = malidp_read32(reg, LAYER_INFO); 275 276 if (layer_info & L_INFO_RF) 277 layer->layer_type = KOMEDA_FMT_RICH_LAYER; 278 else 279 layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER; 280 281 set_range(&layer->hsize_in, 4, d71->max_line_size); 282 set_range(&layer->vsize_in, 4, d71->max_vsize); 283 284 malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP); 285 286 layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK; 287 288 return 0; 289 } 290 291 static int d71_wb_layer_init(struct d71_dev *d71, 292 struct block_header *blk, u32 __iomem *reg) 293 { 294 DRM_DEBUG("Detect D71_Wb_Layer.\n"); 295 296 return 0; 297 } 298 299 static void d71_component_disable(struct komeda_component *c) 300 { 301 u32 __iomem *reg = c->reg; 302 u32 i; 303 304 malidp_write32(reg, BLK_CONTROL, 0); 305 306 for (i = 0; i < c->max_active_inputs; i++) 307 malidp_write32(reg, BLK_INPUT_ID0 + (i << 2), 0); 308 } 309 310 static void compiz_enable_input(u32 __iomem *id_reg, 311 u32 __iomem *cfg_reg, 312 u32 input_hw_id, 313 struct komeda_compiz_input_cfg *cin) 314 { 315 u32 ctrl = CU_INPUT_CTRL_EN; 316 u8 blend = cin->pixel_blend_mode; 317 318 if (blend == DRM_MODE_BLEND_PIXEL_NONE) 319 ctrl |= CU_INPUT_CTRL_PAD; 320 else if (blend == DRM_MODE_BLEND_PREMULTI) 321 ctrl |= CU_INPUT_CTRL_PMUL; 322 323 ctrl |= CU_INPUT_CTRL_ALPHA(cin->layer_alpha); 324 325 malidp_write32(id_reg, BLK_INPUT_ID0, input_hw_id); 326 327 malidp_write32(cfg_reg, CU_INPUT0_SIZE, 328 HV_SIZE(cin->hsize, cin->vsize)); 329 malidp_write32(cfg_reg, CU_INPUT0_OFFSET, 330 HV_OFFSET(cin->hoffset, cin->voffset)); 331 malidp_write32(cfg_reg, CU_INPUT0_CONTROL, ctrl); 332 } 333 334 static void d71_compiz_update(struct komeda_component *c, 335 struct komeda_component_state *state) 336 { 337 struct komeda_compiz_state *st = to_compiz_st(state); 338 u32 __iomem *reg = c->reg; 339 u32 __iomem *id_reg, *cfg_reg; 340 u32 index, input_hw_id; 341 342 for_each_changed_input(state, index) { 343 id_reg = reg + index; 344 cfg_reg = reg + index * CU_PER_INPUT_REGS; 345 input_hw_id = to_d71_input_id(&state->inputs[index]); 346 if (state->active_inputs & BIT(index)) { 347 compiz_enable_input(id_reg, cfg_reg, 348 input_hw_id, &st->cins[index]); 349 } else { 350 malidp_write32(id_reg, BLK_INPUT_ID0, 0); 351 malidp_write32(cfg_reg, CU_INPUT0_CONTROL, 0); 352 } 353 } 354 355 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize)); 356 } 357 358 static void d71_compiz_dump(struct komeda_component *c, struct seq_file *sf) 359 { 360 u32 v[8], i; 361 362 dump_block_header(sf, c->reg); 363 364 get_values_from_reg(c->reg, 0x80, 5, v); 365 for (i = 0; i < 5; i++) 366 seq_printf(sf, "CU_INPUT_ID%u:\t\t0x%X\n", i, v[i]); 367 368 get_values_from_reg(c->reg, 0xA0, 5, v); 369 seq_printf(sf, "CU_IRQ_RAW_STATUS:\t0x%X\n", v[0]); 370 seq_printf(sf, "CU_IRQ_CLEAR:\t\t0x%X\n", v[1]); 371 seq_printf(sf, "CU_IRQ_MASK:\t\t0x%X\n", v[2]); 372 seq_printf(sf, "CU_IRQ_STATUS:\t\t0x%X\n", v[3]); 373 seq_printf(sf, "CU_STATUS:\t\t0x%X\n", v[4]); 374 375 get_values_from_reg(c->reg, 0xD0, 2, v); 376 seq_printf(sf, "CU_CONTROL:\t\t0x%X\n", v[0]); 377 seq_printf(sf, "CU_SIZE:\t\t0x%X\n", v[1]); 378 379 get_values_from_reg(c->reg, 0xDC, 1, v); 380 seq_printf(sf, "CU_BG_COLOR:\t\t0x%X\n", v[0]); 381 382 for (i = 0, v[4] = 0xE0; i < 5; i++, v[4] += 0x10) { 383 get_values_from_reg(c->reg, v[4], 3, v); 384 seq_printf(sf, "CU_INPUT%u_SIZE:\t\t0x%X\n", i, v[0]); 385 seq_printf(sf, "CU_INPUT%u_OFFSET:\t0x%X\n", i, v[1]); 386 seq_printf(sf, "CU_INPUT%u_CONTROL:\t0x%X\n", i, v[2]); 387 } 388 389 get_values_from_reg(c->reg, 0x130, 2, v); 390 seq_printf(sf, "CU_USER_LOW:\t\t0x%X\n", v[0]); 391 seq_printf(sf, "CU_USER_HIGH:\t\t0x%X\n", v[1]); 392 } 393 394 static struct komeda_component_funcs d71_compiz_funcs = { 395 .update = d71_compiz_update, 396 .disable = d71_component_disable, 397 .dump_register = d71_compiz_dump, 398 }; 399 400 static int d71_compiz_init(struct d71_dev *d71, 401 struct block_header *blk, u32 __iomem *reg) 402 { 403 struct komeda_component *c; 404 struct komeda_compiz *compiz; 405 u32 pipe_id, comp_id; 406 407 get_resources_id(blk->block_info, &pipe_id, &comp_id); 408 409 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*compiz), 410 comp_id, 411 BLOCK_INFO_INPUT_ID(blk->block_info), 412 &d71_compiz_funcs, 413 CU_NUM_INPUT_IDS, get_valid_inputs(blk), 414 CU_NUM_OUTPUT_IDS, reg, 415 "CU%d", pipe_id); 416 if (IS_ERR(c)) 417 return PTR_ERR(c); 418 419 compiz = to_compiz(c); 420 421 set_range(&compiz->hsize, D71_MIN_LINE_SIZE, d71->max_line_size); 422 set_range(&compiz->vsize, D71_MIN_VERTICAL_SIZE, d71->max_vsize); 423 424 return 0; 425 } 426 427 static void d71_improc_update(struct komeda_component *c, 428 struct komeda_component_state *state) 429 { 430 struct komeda_improc_state *st = to_improc_st(state); 431 u32 __iomem *reg = c->reg; 432 u32 index, input_hw_id; 433 434 for_each_changed_input(state, index) { 435 input_hw_id = state->active_inputs & BIT(index) ? 436 to_d71_input_id(&state->inputs[index]) : 0; 437 malidp_write32(reg, BLK_INPUT_ID0 + index * 4, input_hw_id); 438 } 439 440 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize)); 441 } 442 443 static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf) 444 { 445 u32 v[12], i; 446 447 dump_block_header(sf, c->reg); 448 449 get_values_from_reg(c->reg, 0x80, 2, v); 450 seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]); 451 seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]); 452 453 get_values_from_reg(c->reg, 0xC0, 1, v); 454 seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]); 455 456 get_values_from_reg(c->reg, 0xD0, 3, v); 457 seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]); 458 seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]); 459 seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]); 460 461 get_values_from_reg(c->reg, 0x130, 12, v); 462 for (i = 0; i < 12; i++) 463 seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]); 464 465 get_values_from_reg(c->reg, 0x170, 12, v); 466 for (i = 0; i < 12; i++) 467 seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]); 468 } 469 470 static struct komeda_component_funcs d71_improc_funcs = { 471 .update = d71_improc_update, 472 .disable = d71_component_disable, 473 .dump_register = d71_improc_dump, 474 }; 475 476 static int d71_improc_init(struct d71_dev *d71, 477 struct block_header *blk, u32 __iomem *reg) 478 { 479 struct komeda_component *c; 480 struct komeda_improc *improc; 481 u32 pipe_id, comp_id, value; 482 483 get_resources_id(blk->block_info, &pipe_id, &comp_id); 484 485 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*improc), 486 comp_id, 487 BLOCK_INFO_INPUT_ID(blk->block_info), 488 &d71_improc_funcs, IPS_NUM_INPUT_IDS, 489 get_valid_inputs(blk), 490 IPS_NUM_OUTPUT_IDS, reg, "DOU%d_IPS", pipe_id); 491 if (IS_ERR(c)) { 492 DRM_ERROR("Failed to add improc component\n"); 493 return PTR_ERR(c); 494 } 495 496 improc = to_improc(c); 497 improc->supported_color_depths = BIT(8) | BIT(10); 498 improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 | 499 DRM_COLOR_FORMAT_YCRCB444 | 500 DRM_COLOR_FORMAT_YCRCB422; 501 value = malidp_read32(reg, BLK_INFO); 502 if (value & IPS_INFO_CHD420) 503 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCRCB420; 504 505 improc->supports_csc = true; 506 improc->supports_gamma = true; 507 508 return 0; 509 } 510 511 static void d71_timing_ctrlr_disable(struct komeda_component *c) 512 { 513 malidp_write32_mask(c->reg, BLK_CONTROL, BS_CTRL_EN, 0); 514 } 515 516 static void d71_timing_ctrlr_update(struct komeda_component *c, 517 struct komeda_component_state *state) 518 { 519 struct drm_crtc_state *crtc_st = state->crtc->state; 520 u32 __iomem *reg = c->reg; 521 struct videomode vm; 522 u32 value; 523 524 drm_display_mode_to_videomode(&crtc_st->adjusted_mode, &vm); 525 526 malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(vm.hactive, vm.vactive)); 527 malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(vm.hfront_porch, 528 vm.hback_porch)); 529 malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vm.vfront_porch, 530 vm.vback_porch)); 531 532 value = BS_SYNC_VSW(vm.vsync_len) | BS_SYNC_HSW(vm.hsync_len); 533 value |= vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? BS_SYNC_VSP : 0; 534 value |= vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? BS_SYNC_HSP : 0; 535 malidp_write32(reg, BS_SYNC, value); 536 537 malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1); 538 malidp_write32(reg, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE); 539 540 /* configure bs control register */ 541 value = BS_CTRL_EN | BS_CTRL_VM; 542 543 malidp_write32(reg, BLK_CONTROL, value); 544 } 545 546 static void d71_timing_ctrlr_dump(struct komeda_component *c, 547 struct seq_file *sf) 548 { 549 u32 v[8], i; 550 551 dump_block_header(sf, c->reg); 552 553 get_values_from_reg(c->reg, 0xC0, 1, v); 554 seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]); 555 556 get_values_from_reg(c->reg, 0xD0, 8, v); 557 seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]); 558 seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]); 559 seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]); 560 seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]); 561 seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]); 562 seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]); 563 seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]); 564 seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]); 565 566 get_values_from_reg(c->reg, 0x100, 3, v); 567 seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]); 568 seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]); 569 seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]); 570 571 get_values_from_reg(c->reg, 0x110, 3, v); 572 for (i = 0; i < 3; i++) 573 seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]); 574 575 get_values_from_reg(c->reg, 0x120, 5, v); 576 for (i = 0; i < 2; i++) { 577 seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]); 578 seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]); 579 } 580 seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]); 581 } 582 583 static struct komeda_component_funcs d71_timing_ctrlr_funcs = { 584 .update = d71_timing_ctrlr_update, 585 .disable = d71_timing_ctrlr_disable, 586 .dump_register = d71_timing_ctrlr_dump, 587 }; 588 589 static int d71_timing_ctrlr_init(struct d71_dev *d71, 590 struct block_header *blk, u32 __iomem *reg) 591 { 592 struct komeda_component *c; 593 struct komeda_timing_ctrlr *ctrlr; 594 u32 pipe_id, comp_id; 595 596 get_resources_id(blk->block_info, &pipe_id, &comp_id); 597 598 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*ctrlr), 599 KOMEDA_COMPONENT_TIMING_CTRLR, 600 BLOCK_INFO_INPUT_ID(blk->block_info), 601 &d71_timing_ctrlr_funcs, 602 1, BIT(KOMEDA_COMPONENT_IPS0 + pipe_id), 603 BS_NUM_OUTPUT_IDS, reg, "DOU%d_BS", pipe_id); 604 if (IS_ERR(c)) { 605 DRM_ERROR("Failed to add display_ctrl component\n"); 606 return PTR_ERR(c); 607 } 608 609 ctrlr = to_ctrlr(c); 610 611 ctrlr->supports_dual_link = true; 612 613 return 0; 614 } 615 616 int d71_probe_block(struct d71_dev *d71, 617 struct block_header *blk, u32 __iomem *reg) 618 { 619 struct d71_pipeline *pipe; 620 int blk_id = BLOCK_INFO_BLK_ID(blk->block_info); 621 622 int err = 0; 623 624 switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) { 625 case D71_BLK_TYPE_GCU: 626 break; 627 628 case D71_BLK_TYPE_LPU: 629 pipe = d71->pipes[blk_id]; 630 pipe->lpu_addr = reg; 631 break; 632 633 case D71_BLK_TYPE_LPU_LAYER: 634 err = d71_layer_init(d71, blk, reg); 635 break; 636 637 case D71_BLK_TYPE_LPU_WB_LAYER: 638 err = d71_wb_layer_init(d71, blk, reg); 639 break; 640 641 case D71_BLK_TYPE_CU: 642 pipe = d71->pipes[blk_id]; 643 pipe->cu_addr = reg; 644 err = d71_compiz_init(d71, blk, reg); 645 break; 646 647 case D71_BLK_TYPE_CU_SPLITTER: 648 case D71_BLK_TYPE_CU_SCALER: 649 case D71_BLK_TYPE_CU_MERGER: 650 break; 651 652 case D71_BLK_TYPE_DOU: 653 pipe = d71->pipes[blk_id]; 654 pipe->dou_addr = reg; 655 break; 656 657 case D71_BLK_TYPE_DOU_IPS: 658 err = d71_improc_init(d71, blk, reg); 659 break; 660 661 case D71_BLK_TYPE_DOU_FT_COEFF: 662 pipe = d71->pipes[blk_id]; 663 pipe->dou_ft_coeff_addr = reg; 664 break; 665 666 case D71_BLK_TYPE_DOU_BS: 667 err = d71_timing_ctrlr_init(d71, blk, reg); 668 break; 669 670 case D71_BLK_TYPE_GLB_LT_COEFF: 671 break; 672 673 case D71_BLK_TYPE_GLB_SCL_COEFF: 674 d71->glb_scl_coeff_addr[blk_id] = reg; 675 break; 676 677 default: 678 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n", 679 blk->block_info); 680 err = -EINVAL; 681 break; 682 } 683 684 return err; 685 } 686