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