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 int d71_layer_validate(struct komeda_component *c, 353 struct komeda_component_state *state) 354 { 355 struct komeda_layer_state *st = to_layer_st(state); 356 struct komeda_layer *layer = to_layer(c); 357 struct drm_plane_state *plane_st; 358 struct drm_framebuffer *fb; 359 u32 fourcc, line_sz, max_line_sz; 360 361 plane_st = drm_atomic_get_new_plane_state(state->obj.state, 362 state->plane); 363 fb = plane_st->fb; 364 fourcc = fb->format->format; 365 366 if (drm_rotation_90_or_270(st->rot)) 367 line_sz = st->vsize - st->afbc_crop_t - st->afbc_crop_b; 368 else 369 line_sz = st->hsize - st->afbc_crop_l - st->afbc_crop_r; 370 371 if (fb->modifier) { 372 if ((fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) == 373 AFBC_FORMAT_MOD_BLOCK_SIZE_32x8) 374 max_line_sz = layer->line_sz; 375 else 376 max_line_sz = layer->line_sz / 2; 377 378 if (line_sz > max_line_sz) { 379 DRM_DEBUG_ATOMIC("afbc request line_sz: %d exceed the max afbc line_sz: %d.\n", 380 line_sz, max_line_sz); 381 return -EINVAL; 382 } 383 } 384 385 if (fourcc == DRM_FORMAT_YUV420_10BIT && line_sz > 2046 && (st->afbc_crop_l % 4)) { 386 DRM_DEBUG_ATOMIC("YUV420_10BIT input_hsize: %d exceed the max size 2046.\n", 387 line_sz); 388 return -EINVAL; 389 } 390 391 if (fourcc == DRM_FORMAT_X0L2 && line_sz > 2046 && (st->addr[0] % 16)) { 392 DRM_DEBUG_ATOMIC("X0L2 input_hsize: %d exceed the max size 2046.\n", 393 line_sz); 394 return -EINVAL; 395 } 396 397 return 0; 398 } 399 400 static const struct komeda_component_funcs d71_layer_funcs = { 401 .validate = d71_layer_validate, 402 .update = d71_layer_update, 403 .disable = d71_layer_disable, 404 .dump_register = d71_layer_dump, 405 }; 406 407 static int d71_layer_init(struct d71_dev *d71, 408 struct block_header *blk, u32 __iomem *reg) 409 { 410 struct komeda_component *c; 411 struct komeda_layer *layer; 412 u32 pipe_id, layer_id, layer_info; 413 414 get_resources_id(blk->block_info, &pipe_id, &layer_id); 415 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer), 416 layer_id, 417 BLOCK_INFO_INPUT_ID(blk->block_info), 418 &d71_layer_funcs, 0, 419 get_valid_inputs(blk), 420 1, reg, "LPU%d_LAYER%d", pipe_id, layer_id); 421 if (IS_ERR(c)) { 422 DRM_ERROR("Failed to add layer component\n"); 423 return PTR_ERR(c); 424 } 425 426 layer = to_layer(c); 427 layer_info = malidp_read32(reg, LAYER_INFO); 428 429 if (layer_info & L_INFO_RF) 430 layer->layer_type = KOMEDA_FMT_RICH_LAYER; 431 else 432 layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER; 433 434 if (!d71->periph_addr) { 435 /* D32 or newer product */ 436 layer->line_sz = malidp_read32(reg, BLK_MAX_LINE_SIZE); 437 layer->yuv_line_sz = L_INFO_YUV_MAX_LINESZ(layer_info); 438 } else if (d71->max_line_size > 2048) { 439 /* D71 4K */ 440 layer->line_sz = d71->max_line_size; 441 layer->yuv_line_sz = layer->line_sz / 2; 442 } else { 443 /* D71 2K */ 444 if (layer->layer_type == KOMEDA_FMT_RICH_LAYER) { 445 /* rich layer is 4K configuration */ 446 layer->line_sz = d71->max_line_size * 2; 447 layer->yuv_line_sz = layer->line_sz / 2; 448 } else { 449 layer->line_sz = d71->max_line_size; 450 layer->yuv_line_sz = 0; 451 } 452 } 453 454 set_range(&layer->hsize_in, 4, layer->line_sz); 455 456 set_range(&layer->vsize_in, 4, d71->max_vsize); 457 458 malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP); 459 460 layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK; 461 462 return 0; 463 } 464 465 static void d71_wb_layer_update(struct komeda_component *c, 466 struct komeda_component_state *state) 467 { 468 struct komeda_layer_state *st = to_layer_st(state); 469 struct drm_connector_state *conn_st = state->wb_conn->state; 470 struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb); 471 u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN; 472 u32 __iomem *reg = c->reg; 473 474 d71_layer_update_fb(c, kfb, st->addr); 475 476 if (kfb->is_va) 477 ctrl |= LW_TBU_EN; 478 479 malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize)); 480 malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0)); 481 malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl); 482 } 483 484 static void d71_wb_layer_dump(struct komeda_component *c, struct seq_file *sf) 485 { 486 u32 v[12], i; 487 488 dump_block_header(sf, c->reg); 489 490 get_values_from_reg(c->reg, 0x80, 1, v); 491 seq_printf(sf, "LW_INPUT_ID0:\t\t0x%X\n", v[0]); 492 493 get_values_from_reg(c->reg, 0xD0, 3, v); 494 seq_printf(sf, "LW_CONTROL:\t\t0x%X\n", v[0]); 495 seq_printf(sf, "LW_PROG_LINE:\t\t0x%X\n", v[1]); 496 seq_printf(sf, "LW_FORMAT:\t\t0x%X\n", v[2]); 497 498 get_values_from_reg(c->reg, 0xE0, 1, v); 499 seq_printf(sf, "LW_IN_SIZE:\t\t0x%X\n", v[0]); 500 501 for (i = 0; i < 2; i++) { 502 get_values_from_reg(c->reg, 0x100 + i * 0x10, 3, v); 503 seq_printf(sf, "LW_P%u_PTR_LOW:\t\t0x%X\n", i, v[0]); 504 seq_printf(sf, "LW_P%u_PTR_HIGH:\t\t0x%X\n", i, v[1]); 505 seq_printf(sf, "LW_P%u_STRIDE:\t\t0x%X\n", i, v[2]); 506 } 507 508 get_values_from_reg(c->reg, 0x130, 12, v); 509 for (i = 0; i < 12; i++) 510 seq_printf(sf, "LW_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]); 511 } 512 513 static void d71_wb_layer_disable(struct komeda_component *c) 514 { 515 malidp_write32(c->reg, BLK_INPUT_ID0, 0); 516 malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0); 517 } 518 519 static const struct komeda_component_funcs d71_wb_layer_funcs = { 520 .update = d71_wb_layer_update, 521 .disable = d71_wb_layer_disable, 522 .dump_register = d71_wb_layer_dump, 523 }; 524 525 static int d71_wb_layer_init(struct d71_dev *d71, 526 struct block_header *blk, u32 __iomem *reg) 527 { 528 struct komeda_component *c; 529 struct komeda_layer *wb_layer; 530 u32 pipe_id, layer_id; 531 532 get_resources_id(blk->block_info, &pipe_id, &layer_id); 533 534 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*wb_layer), 535 layer_id, BLOCK_INFO_INPUT_ID(blk->block_info), 536 &d71_wb_layer_funcs, 537 1, get_valid_inputs(blk), 0, reg, 538 "LPU%d_LAYER_WR", pipe_id); 539 if (IS_ERR(c)) { 540 DRM_ERROR("Failed to add wb_layer component\n"); 541 return PTR_ERR(c); 542 } 543 544 wb_layer = to_layer(c); 545 wb_layer->layer_type = KOMEDA_FMT_WB_LAYER; 546 wb_layer->line_sz = get_blk_line_size(d71, reg); 547 wb_layer->yuv_line_sz = wb_layer->line_sz; 548 549 set_range(&wb_layer->hsize_in, 64, wb_layer->line_sz); 550 set_range(&wb_layer->vsize_in, 64, d71->max_vsize); 551 552 return 0; 553 } 554 555 static void d71_component_disable(struct komeda_component *c) 556 { 557 u32 __iomem *reg = c->reg; 558 u32 i; 559 560 malidp_write32(reg, BLK_CONTROL, 0); 561 562 for (i = 0; i < c->max_active_inputs; i++) { 563 malidp_write32(reg, BLK_INPUT_ID0 + (i << 2), 0); 564 565 /* Besides clearing the input ID to zero, D71 compiz also has 566 * input enable bit in CU_INPUTx_CONTROL which need to be 567 * cleared. 568 */ 569 if (has_bit(c->id, KOMEDA_PIPELINE_COMPIZS)) 570 malidp_write32(reg, CU_INPUT0_CONTROL + 571 i * CU_PER_INPUT_REGS * 4, 572 CU_INPUT_CTRL_ALPHA(0xFF)); 573 } 574 } 575 576 static void compiz_enable_input(u32 __iomem *id_reg, 577 u32 __iomem *cfg_reg, 578 u32 input_hw_id, 579 struct komeda_compiz_input_cfg *cin) 580 { 581 u32 ctrl = CU_INPUT_CTRL_EN; 582 u8 blend = cin->pixel_blend_mode; 583 584 if (blend == DRM_MODE_BLEND_PIXEL_NONE) 585 ctrl |= CU_INPUT_CTRL_PAD; 586 else if (blend == DRM_MODE_BLEND_PREMULTI) 587 ctrl |= CU_INPUT_CTRL_PMUL; 588 589 ctrl |= CU_INPUT_CTRL_ALPHA(cin->layer_alpha); 590 591 malidp_write32(id_reg, BLK_INPUT_ID0, input_hw_id); 592 593 malidp_write32(cfg_reg, CU_INPUT0_SIZE, 594 HV_SIZE(cin->hsize, cin->vsize)); 595 malidp_write32(cfg_reg, CU_INPUT0_OFFSET, 596 HV_OFFSET(cin->hoffset, cin->voffset)); 597 malidp_write32(cfg_reg, CU_INPUT0_CONTROL, ctrl); 598 } 599 600 static void d71_compiz_update(struct komeda_component *c, 601 struct komeda_component_state *state) 602 { 603 struct komeda_compiz_state *st = to_compiz_st(state); 604 u32 __iomem *reg = c->reg; 605 u32 __iomem *id_reg, *cfg_reg; 606 u32 index; 607 608 for_each_changed_input(state, index) { 609 id_reg = reg + index; 610 cfg_reg = reg + index * CU_PER_INPUT_REGS; 611 if (state->active_inputs & BIT(index)) { 612 compiz_enable_input(id_reg, cfg_reg, 613 to_d71_input_id(state, index), 614 &st->cins[index]); 615 } else { 616 malidp_write32(id_reg, BLK_INPUT_ID0, 0); 617 malidp_write32(cfg_reg, CU_INPUT0_CONTROL, 0); 618 } 619 } 620 621 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize)); 622 } 623 624 static void d71_compiz_dump(struct komeda_component *c, struct seq_file *sf) 625 { 626 u32 v[8], i; 627 628 dump_block_header(sf, c->reg); 629 630 get_values_from_reg(c->reg, 0x80, 5, v); 631 for (i = 0; i < 5; i++) 632 seq_printf(sf, "CU_INPUT_ID%u:\t\t0x%X\n", i, v[i]); 633 634 get_values_from_reg(c->reg, 0xA0, 5, v); 635 seq_printf(sf, "CU_IRQ_RAW_STATUS:\t0x%X\n", v[0]); 636 seq_printf(sf, "CU_IRQ_CLEAR:\t\t0x%X\n", v[1]); 637 seq_printf(sf, "CU_IRQ_MASK:\t\t0x%X\n", v[2]); 638 seq_printf(sf, "CU_IRQ_STATUS:\t\t0x%X\n", v[3]); 639 seq_printf(sf, "CU_STATUS:\t\t0x%X\n", v[4]); 640 641 get_values_from_reg(c->reg, 0xD0, 2, v); 642 seq_printf(sf, "CU_CONTROL:\t\t0x%X\n", v[0]); 643 seq_printf(sf, "CU_SIZE:\t\t0x%X\n", v[1]); 644 645 get_values_from_reg(c->reg, 0xDC, 1, v); 646 seq_printf(sf, "CU_BG_COLOR:\t\t0x%X\n", v[0]); 647 648 for (i = 0, v[4] = 0xE0; i < 5; i++, v[4] += 0x10) { 649 get_values_from_reg(c->reg, v[4], 3, v); 650 seq_printf(sf, "CU_INPUT%u_SIZE:\t\t0x%X\n", i, v[0]); 651 seq_printf(sf, "CU_INPUT%u_OFFSET:\t0x%X\n", i, v[1]); 652 seq_printf(sf, "CU_INPUT%u_CONTROL:\t0x%X\n", i, v[2]); 653 } 654 655 get_values_from_reg(c->reg, 0x130, 2, v); 656 seq_printf(sf, "CU_USER_LOW:\t\t0x%X\n", v[0]); 657 seq_printf(sf, "CU_USER_HIGH:\t\t0x%X\n", v[1]); 658 } 659 660 static const struct komeda_component_funcs d71_compiz_funcs = { 661 .update = d71_compiz_update, 662 .disable = d71_component_disable, 663 .dump_register = d71_compiz_dump, 664 }; 665 666 static int d71_compiz_init(struct d71_dev *d71, 667 struct block_header *blk, u32 __iomem *reg) 668 { 669 struct komeda_component *c; 670 struct komeda_compiz *compiz; 671 u32 pipe_id, comp_id; 672 673 get_resources_id(blk->block_info, &pipe_id, &comp_id); 674 675 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*compiz), 676 comp_id, 677 BLOCK_INFO_INPUT_ID(blk->block_info), 678 &d71_compiz_funcs, 679 CU_NUM_INPUT_IDS, get_valid_inputs(blk), 680 CU_NUM_OUTPUT_IDS, reg, 681 "CU%d", pipe_id); 682 if (IS_ERR(c)) 683 return PTR_ERR(c); 684 685 compiz = to_compiz(c); 686 687 set_range(&compiz->hsize, 64, get_blk_line_size(d71, reg)); 688 set_range(&compiz->vsize, 64, d71->max_vsize); 689 690 return 0; 691 } 692 693 static void d71_scaler_update_filter_lut(u32 __iomem *reg, u32 hsize_in, 694 u32 vsize_in, u32 hsize_out, 695 u32 vsize_out) 696 { 697 u32 val = 0; 698 699 if (hsize_in <= hsize_out) 700 val |= 0x62; 701 else if (hsize_in <= (hsize_out + hsize_out / 2)) 702 val |= 0x63; 703 else if (hsize_in <= hsize_out * 2) 704 val |= 0x64; 705 else if (hsize_in <= hsize_out * 2 + (hsize_out * 3) / 4) 706 val |= 0x65; 707 else 708 val |= 0x66; 709 710 if (vsize_in <= vsize_out) 711 val |= SC_VTSEL(0x6A); 712 else if (vsize_in <= (vsize_out + vsize_out / 2)) 713 val |= SC_VTSEL(0x6B); 714 else if (vsize_in <= vsize_out * 2) 715 val |= SC_VTSEL(0x6C); 716 else if (vsize_in <= vsize_out * 2 + vsize_out * 3 / 4) 717 val |= SC_VTSEL(0x6D); 718 else 719 val |= SC_VTSEL(0x6E); 720 721 malidp_write32(reg, SC_COEFFTAB, val); 722 } 723 724 static void d71_scaler_update(struct komeda_component *c, 725 struct komeda_component_state *state) 726 { 727 struct komeda_scaler_state *st = to_scaler_st(state); 728 u32 __iomem *reg = c->reg; 729 u32 init_ph, delta_ph, ctrl; 730 731 d71_scaler_update_filter_lut(reg, st->hsize_in, st->vsize_in, 732 st->hsize_out, st->vsize_out); 733 734 malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize_in, st->vsize_in)); 735 malidp_write32(reg, SC_OUT_SIZE, HV_SIZE(st->hsize_out, st->vsize_out)); 736 malidp_write32(reg, SC_H_CROP, HV_CROP(st->left_crop, st->right_crop)); 737 738 /* for right part, HW only sample the valid pixel which means the pixels 739 * in left_crop will be jumpped, and the first sample pixel is: 740 * 741 * dst_a = st->total_hsize_out - st->hsize_out + st->left_crop + 0.5; 742 * 743 * Then the corresponding texel in src is: 744 * 745 * h_delta_phase = st->total_hsize_in / st->total_hsize_out; 746 * src_a = dst_A * h_delta_phase; 747 * 748 * and h_init_phase is src_a deduct the real source start src_S; 749 * 750 * src_S = st->total_hsize_in - st->hsize_in; 751 * h_init_phase = src_a - src_S; 752 * 753 * And HW precision for the initial/delta_phase is 16:16 fixed point, 754 * the following is the simplified formula 755 */ 756 if (st->right_part) { 757 u32 dst_a = st->total_hsize_out - st->hsize_out + st->left_crop; 758 759 if (st->en_img_enhancement) 760 dst_a -= 1; 761 762 init_ph = ((st->total_hsize_in * (2 * dst_a + 1) - 763 2 * st->total_hsize_out * (st->total_hsize_in - 764 st->hsize_in)) << 15) / st->total_hsize_out; 765 } else { 766 init_ph = (st->total_hsize_in << 15) / st->total_hsize_out; 767 } 768 769 malidp_write32(reg, SC_H_INIT_PH, init_ph); 770 771 delta_ph = (st->total_hsize_in << 16) / st->total_hsize_out; 772 malidp_write32(reg, SC_H_DELTA_PH, delta_ph); 773 774 init_ph = (st->total_vsize_in << 15) / st->vsize_out; 775 malidp_write32(reg, SC_V_INIT_PH, init_ph); 776 777 delta_ph = (st->total_vsize_in << 16) / st->vsize_out; 778 malidp_write32(reg, SC_V_DELTA_PH, delta_ph); 779 780 ctrl = 0; 781 ctrl |= st->en_scaling ? SC_CTRL_SCL : 0; 782 ctrl |= st->en_alpha ? SC_CTRL_AP : 0; 783 ctrl |= st->en_img_enhancement ? SC_CTRL_IENH : 0; 784 /* If we use the hardware splitter we shouldn't set SC_CTRL_LS */ 785 if (st->en_split && 786 state->inputs[0].component->id != KOMEDA_COMPONENT_SPLITTER) 787 ctrl |= SC_CTRL_LS; 788 789 malidp_write32(reg, BLK_CONTROL, ctrl); 790 malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0)); 791 } 792 793 static void d71_scaler_dump(struct komeda_component *c, struct seq_file *sf) 794 { 795 u32 v[9]; 796 797 dump_block_header(sf, c->reg); 798 799 get_values_from_reg(c->reg, 0x80, 1, v); 800 seq_printf(sf, "SC_INPUT_ID0:\t\t0x%X\n", v[0]); 801 802 get_values_from_reg(c->reg, 0xD0, 1, v); 803 seq_printf(sf, "SC_CONTROL:\t\t0x%X\n", v[0]); 804 805 get_values_from_reg(c->reg, 0xDC, 9, v); 806 seq_printf(sf, "SC_COEFFTAB:\t\t0x%X\n", v[0]); 807 seq_printf(sf, "SC_IN_SIZE:\t\t0x%X\n", v[1]); 808 seq_printf(sf, "SC_OUT_SIZE:\t\t0x%X\n", v[2]); 809 seq_printf(sf, "SC_H_CROP:\t\t0x%X\n", v[3]); 810 seq_printf(sf, "SC_V_CROP:\t\t0x%X\n", v[4]); 811 seq_printf(sf, "SC_H_INIT_PH:\t\t0x%X\n", v[5]); 812 seq_printf(sf, "SC_H_DELTA_PH:\t\t0x%X\n", v[6]); 813 seq_printf(sf, "SC_V_INIT_PH:\t\t0x%X\n", v[7]); 814 seq_printf(sf, "SC_V_DELTA_PH:\t\t0x%X\n", v[8]); 815 } 816 817 static const struct komeda_component_funcs d71_scaler_funcs = { 818 .update = d71_scaler_update, 819 .disable = d71_component_disable, 820 .dump_register = d71_scaler_dump, 821 }; 822 823 static int d71_scaler_init(struct d71_dev *d71, 824 struct block_header *blk, u32 __iomem *reg) 825 { 826 struct komeda_component *c; 827 struct komeda_scaler *scaler; 828 u32 pipe_id, comp_id; 829 830 get_resources_id(blk->block_info, &pipe_id, &comp_id); 831 832 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*scaler), 833 comp_id, BLOCK_INFO_INPUT_ID(blk->block_info), 834 &d71_scaler_funcs, 835 1, get_valid_inputs(blk), 1, reg, 836 "CU%d_SCALER%d", 837 pipe_id, BLOCK_INFO_BLK_ID(blk->block_info)); 838 839 if (IS_ERR(c)) { 840 DRM_ERROR("Failed to initialize scaler"); 841 return PTR_ERR(c); 842 } 843 844 scaler = to_scaler(c); 845 set_range(&scaler->hsize, 4, __get_blk_line_size(d71, reg, 2048)); 846 set_range(&scaler->vsize, 4, 4096); 847 scaler->max_downscaling = 6; 848 scaler->max_upscaling = 64; 849 scaler->scaling_split_overlap = 8; 850 scaler->enh_split_overlap = 1; 851 852 malidp_write32(c->reg, BLK_CONTROL, 0); 853 854 return 0; 855 } 856 857 static int d71_downscaling_clk_check(struct komeda_pipeline *pipe, 858 struct drm_display_mode *mode, 859 unsigned long aclk_rate, 860 struct komeda_data_flow_cfg *dflow) 861 { 862 u32 h_in = dflow->in_w; 863 u32 v_in = dflow->in_h; 864 u32 v_out = dflow->out_h; 865 u64 fraction, denominator; 866 867 /* D71 downscaling must satisfy the following equation 868 * 869 * ACLK h_in * v_in 870 * ------- >= --------------------------------------------- 871 * PXLCLK (h_total - (1 + 2 * v_in / v_out)) * v_out 872 * 873 * In only horizontal downscaling situation, the right side should be 874 * multiplied by (h_total - 3) / (h_active - 3), then equation becomes 875 * 876 * ACLK h_in 877 * ------- >= ---------------- 878 * PXLCLK (h_active - 3) 879 * 880 * To avoid precision lost the equation 1 will be convert to: 881 * 882 * ACLK h_in * v_in 883 * ------- >= ----------------------------------- 884 * PXLCLK (h_total -1 ) * v_out - 2 * v_in 885 */ 886 if (v_in == v_out) { 887 fraction = h_in; 888 denominator = mode->hdisplay - 3; 889 } else { 890 fraction = h_in * v_in; 891 denominator = (mode->htotal - 1) * v_out - 2 * v_in; 892 } 893 894 return aclk_rate * denominator >= mode->crtc_clock * 1000 * fraction ? 895 0 : -EINVAL; 896 } 897 898 static void d71_splitter_update(struct komeda_component *c, 899 struct komeda_component_state *state) 900 { 901 struct komeda_splitter_state *st = to_splitter_st(state); 902 u32 __iomem *reg = c->reg; 903 904 malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0)); 905 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize)); 906 malidp_write32(reg, SP_OVERLAP_SIZE, st->overlap & 0x1FFF); 907 malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN); 908 } 909 910 static void d71_splitter_dump(struct komeda_component *c, struct seq_file *sf) 911 { 912 u32 v[3]; 913 914 dump_block_header(sf, c->reg); 915 916 get_values_from_reg(c->reg, BLK_INPUT_ID0, 1, v); 917 seq_printf(sf, "SP_INPUT_ID0:\t\t0x%X\n", v[0]); 918 919 get_values_from_reg(c->reg, BLK_CONTROL, 3, v); 920 seq_printf(sf, "SP_CONTROL:\t\t0x%X\n", v[0]); 921 seq_printf(sf, "SP_SIZE:\t\t0x%X\n", v[1]); 922 seq_printf(sf, "SP_OVERLAP_SIZE:\t0x%X\n", v[2]); 923 } 924 925 static const struct komeda_component_funcs d71_splitter_funcs = { 926 .update = d71_splitter_update, 927 .disable = d71_component_disable, 928 .dump_register = d71_splitter_dump, 929 }; 930 931 static int d71_splitter_init(struct d71_dev *d71, 932 struct block_header *blk, u32 __iomem *reg) 933 { 934 struct komeda_component *c; 935 struct komeda_splitter *splitter; 936 u32 pipe_id, comp_id; 937 938 get_resources_id(blk->block_info, &pipe_id, &comp_id); 939 940 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*splitter), 941 comp_id, 942 BLOCK_INFO_INPUT_ID(blk->block_info), 943 &d71_splitter_funcs, 944 1, get_valid_inputs(blk), 2, reg, 945 "CU%d_SPLITTER", pipe_id); 946 947 if (IS_ERR(c)) { 948 DRM_ERROR("Failed to initialize splitter"); 949 return -1; 950 } 951 952 splitter = to_splitter(c); 953 954 set_range(&splitter->hsize, 4, get_blk_line_size(d71, reg)); 955 set_range(&splitter->vsize, 4, d71->max_vsize); 956 957 return 0; 958 } 959 960 static void d71_merger_update(struct komeda_component *c, 961 struct komeda_component_state *state) 962 { 963 struct komeda_merger_state *st = to_merger_st(state); 964 u32 __iomem *reg = c->reg; 965 u32 index; 966 967 for_each_changed_input(state, index) 968 malidp_write32(reg, MG_INPUT_ID0 + index * 4, 969 to_d71_input_id(state, index)); 970 971 malidp_write32(reg, MG_SIZE, HV_SIZE(st->hsize_merged, 972 st->vsize_merged)); 973 malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN); 974 } 975 976 static void d71_merger_dump(struct komeda_component *c, struct seq_file *sf) 977 { 978 u32 v; 979 980 dump_block_header(sf, c->reg); 981 982 get_values_from_reg(c->reg, MG_INPUT_ID0, 1, &v); 983 seq_printf(sf, "MG_INPUT_ID0:\t\t0x%X\n", v); 984 985 get_values_from_reg(c->reg, MG_INPUT_ID1, 1, &v); 986 seq_printf(sf, "MG_INPUT_ID1:\t\t0x%X\n", v); 987 988 get_values_from_reg(c->reg, BLK_CONTROL, 1, &v); 989 seq_printf(sf, "MG_CONTROL:\t\t0x%X\n", v); 990 991 get_values_from_reg(c->reg, MG_SIZE, 1, &v); 992 seq_printf(sf, "MG_SIZE:\t\t0x%X\n", v); 993 } 994 995 static const struct komeda_component_funcs d71_merger_funcs = { 996 .update = d71_merger_update, 997 .disable = d71_component_disable, 998 .dump_register = d71_merger_dump, 999 }; 1000 1001 static int d71_merger_init(struct d71_dev *d71, 1002 struct block_header *blk, u32 __iomem *reg) 1003 { 1004 struct komeda_component *c; 1005 struct komeda_merger *merger; 1006 u32 pipe_id, comp_id; 1007 1008 get_resources_id(blk->block_info, &pipe_id, &comp_id); 1009 1010 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*merger), 1011 comp_id, 1012 BLOCK_INFO_INPUT_ID(blk->block_info), 1013 &d71_merger_funcs, 1014 MG_NUM_INPUTS_IDS, get_valid_inputs(blk), 1015 MG_NUM_OUTPUTS_IDS, reg, 1016 "CU%d_MERGER", pipe_id); 1017 1018 if (IS_ERR(c)) { 1019 DRM_ERROR("Failed to initialize merger.\n"); 1020 return PTR_ERR(c); 1021 } 1022 1023 merger = to_merger(c); 1024 1025 set_range(&merger->hsize_merged, 4, 1026 __get_blk_line_size(d71, reg, 4032)); 1027 set_range(&merger->vsize_merged, 4, 4096); 1028 1029 return 0; 1030 } 1031 1032 static void d71_improc_update(struct komeda_component *c, 1033 struct komeda_component_state *state) 1034 { 1035 struct komeda_improc_state *st = to_improc_st(state); 1036 u32 __iomem *reg = c->reg; 1037 u32 index; 1038 1039 for_each_changed_input(state, index) 1040 malidp_write32(reg, BLK_INPUT_ID0 + index * 4, 1041 to_d71_input_id(state, index)); 1042 1043 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize)); 1044 malidp_write32(reg, IPS_DEPTH, st->color_depth); 1045 } 1046 1047 static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf) 1048 { 1049 u32 v[12], i; 1050 1051 dump_block_header(sf, c->reg); 1052 1053 get_values_from_reg(c->reg, 0x80, 2, v); 1054 seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]); 1055 seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]); 1056 1057 get_values_from_reg(c->reg, 0xC0, 1, v); 1058 seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]); 1059 1060 get_values_from_reg(c->reg, 0xD0, 3, v); 1061 seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]); 1062 seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]); 1063 seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]); 1064 1065 get_values_from_reg(c->reg, 0x130, 12, v); 1066 for (i = 0; i < 12; i++) 1067 seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]); 1068 1069 get_values_from_reg(c->reg, 0x170, 12, v); 1070 for (i = 0; i < 12; i++) 1071 seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]); 1072 } 1073 1074 static const struct komeda_component_funcs d71_improc_funcs = { 1075 .update = d71_improc_update, 1076 .disable = d71_component_disable, 1077 .dump_register = d71_improc_dump, 1078 }; 1079 1080 static int d71_improc_init(struct d71_dev *d71, 1081 struct block_header *blk, u32 __iomem *reg) 1082 { 1083 struct komeda_component *c; 1084 struct komeda_improc *improc; 1085 u32 pipe_id, comp_id, value; 1086 1087 get_resources_id(blk->block_info, &pipe_id, &comp_id); 1088 1089 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*improc), 1090 comp_id, 1091 BLOCK_INFO_INPUT_ID(blk->block_info), 1092 &d71_improc_funcs, IPS_NUM_INPUT_IDS, 1093 get_valid_inputs(blk), 1094 IPS_NUM_OUTPUT_IDS, reg, "DOU%d_IPS", pipe_id); 1095 if (IS_ERR(c)) { 1096 DRM_ERROR("Failed to add improc component\n"); 1097 return PTR_ERR(c); 1098 } 1099 1100 improc = to_improc(c); 1101 improc->supported_color_depths = BIT(8) | BIT(10); 1102 improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 | 1103 DRM_COLOR_FORMAT_YCRCB444 | 1104 DRM_COLOR_FORMAT_YCRCB422; 1105 value = malidp_read32(reg, BLK_INFO); 1106 if (value & IPS_INFO_CHD420) 1107 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCRCB420; 1108 1109 improc->supports_csc = true; 1110 improc->supports_gamma = true; 1111 1112 return 0; 1113 } 1114 1115 static void d71_timing_ctrlr_disable(struct komeda_component *c) 1116 { 1117 malidp_write32_mask(c->reg, BLK_CONTROL, BS_CTRL_EN, 0); 1118 } 1119 1120 static void d71_timing_ctrlr_update(struct komeda_component *c, 1121 struct komeda_component_state *state) 1122 { 1123 struct drm_crtc_state *crtc_st = state->crtc->state; 1124 struct drm_display_mode *mode = &crtc_st->adjusted_mode; 1125 u32 __iomem *reg = c->reg; 1126 u32 hactive, hfront_porch, hback_porch, hsync_len; 1127 u32 vactive, vfront_porch, vback_porch, vsync_len; 1128 u32 value; 1129 1130 hactive = mode->crtc_hdisplay; 1131 hfront_porch = mode->crtc_hsync_start - mode->crtc_hdisplay; 1132 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1133 hback_porch = mode->crtc_htotal - mode->crtc_hsync_end; 1134 1135 vactive = mode->crtc_vdisplay; 1136 vfront_porch = mode->crtc_vsync_start - mode->crtc_vdisplay; 1137 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 1138 vback_porch = mode->crtc_vtotal - mode->crtc_vsync_end; 1139 1140 malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(hactive, vactive)); 1141 malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(hfront_porch, 1142 hback_porch)); 1143 malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vfront_porch, 1144 vback_porch)); 1145 1146 value = BS_SYNC_VSW(vsync_len) | BS_SYNC_HSW(hsync_len); 1147 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BS_SYNC_VSP : 0; 1148 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BS_SYNC_HSP : 0; 1149 malidp_write32(reg, BS_SYNC, value); 1150 1151 malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1); 1152 malidp_write32(reg, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE); 1153 1154 /* configure bs control register */ 1155 value = BS_CTRL_EN | BS_CTRL_VM; 1156 if (c->pipeline->dual_link) { 1157 malidp_write32(reg, BS_DRIFT_TO, hfront_porch + 16); 1158 value |= BS_CTRL_DL; 1159 } 1160 1161 malidp_write32(reg, BLK_CONTROL, value); 1162 } 1163 1164 static void d71_timing_ctrlr_dump(struct komeda_component *c, 1165 struct seq_file *sf) 1166 { 1167 u32 v[8], i; 1168 1169 dump_block_header(sf, c->reg); 1170 1171 get_values_from_reg(c->reg, 0xC0, 1, v); 1172 seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]); 1173 1174 get_values_from_reg(c->reg, 0xD0, 8, v); 1175 seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]); 1176 seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]); 1177 seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]); 1178 seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]); 1179 seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]); 1180 seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]); 1181 seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]); 1182 seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]); 1183 1184 get_values_from_reg(c->reg, 0x100, 3, v); 1185 seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]); 1186 seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]); 1187 seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]); 1188 1189 get_values_from_reg(c->reg, 0x110, 3, v); 1190 for (i = 0; i < 3; i++) 1191 seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]); 1192 1193 get_values_from_reg(c->reg, 0x120, 5, v); 1194 for (i = 0; i < 2; i++) { 1195 seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]); 1196 seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]); 1197 } 1198 seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]); 1199 } 1200 1201 static const struct komeda_component_funcs d71_timing_ctrlr_funcs = { 1202 .update = d71_timing_ctrlr_update, 1203 .disable = d71_timing_ctrlr_disable, 1204 .dump_register = d71_timing_ctrlr_dump, 1205 }; 1206 1207 static int d71_timing_ctrlr_init(struct d71_dev *d71, 1208 struct block_header *blk, u32 __iomem *reg) 1209 { 1210 struct komeda_component *c; 1211 struct komeda_timing_ctrlr *ctrlr; 1212 u32 pipe_id, comp_id; 1213 1214 get_resources_id(blk->block_info, &pipe_id, &comp_id); 1215 1216 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*ctrlr), 1217 KOMEDA_COMPONENT_TIMING_CTRLR, 1218 BLOCK_INFO_INPUT_ID(blk->block_info), 1219 &d71_timing_ctrlr_funcs, 1220 1, BIT(KOMEDA_COMPONENT_IPS0 + pipe_id), 1221 BS_NUM_OUTPUT_IDS, reg, "DOU%d_BS", pipe_id); 1222 if (IS_ERR(c)) { 1223 DRM_ERROR("Failed to add display_ctrl component\n"); 1224 return PTR_ERR(c); 1225 } 1226 1227 ctrlr = to_ctrlr(c); 1228 1229 ctrlr->supports_dual_link = true; 1230 1231 return 0; 1232 } 1233 1234 int d71_probe_block(struct d71_dev *d71, 1235 struct block_header *blk, u32 __iomem *reg) 1236 { 1237 struct d71_pipeline *pipe; 1238 int blk_id = BLOCK_INFO_BLK_ID(blk->block_info); 1239 1240 int err = 0; 1241 1242 switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) { 1243 case D71_BLK_TYPE_GCU: 1244 break; 1245 1246 case D71_BLK_TYPE_LPU: 1247 pipe = d71->pipes[blk_id]; 1248 pipe->lpu_addr = reg; 1249 break; 1250 1251 case D71_BLK_TYPE_LPU_LAYER: 1252 err = d71_layer_init(d71, blk, reg); 1253 break; 1254 1255 case D71_BLK_TYPE_LPU_WB_LAYER: 1256 err = d71_wb_layer_init(d71, blk, reg); 1257 break; 1258 1259 case D71_BLK_TYPE_CU: 1260 pipe = d71->pipes[blk_id]; 1261 pipe->cu_addr = reg; 1262 err = d71_compiz_init(d71, blk, reg); 1263 break; 1264 1265 case D71_BLK_TYPE_CU_SCALER: 1266 err = d71_scaler_init(d71, blk, reg); 1267 break; 1268 1269 case D71_BLK_TYPE_CU_SPLITTER: 1270 err = d71_splitter_init(d71, blk, reg); 1271 break; 1272 1273 case D71_BLK_TYPE_CU_MERGER: 1274 err = d71_merger_init(d71, blk, reg); 1275 break; 1276 1277 case D71_BLK_TYPE_DOU: 1278 pipe = d71->pipes[blk_id]; 1279 pipe->dou_addr = reg; 1280 break; 1281 1282 case D71_BLK_TYPE_DOU_IPS: 1283 err = d71_improc_init(d71, blk, reg); 1284 break; 1285 1286 case D71_BLK_TYPE_DOU_FT_COEFF: 1287 pipe = d71->pipes[blk_id]; 1288 pipe->dou_ft_coeff_addr = reg; 1289 break; 1290 1291 case D71_BLK_TYPE_DOU_BS: 1292 err = d71_timing_ctrlr_init(d71, blk, reg); 1293 break; 1294 1295 case D71_BLK_TYPE_GLB_LT_COEFF: 1296 break; 1297 1298 case D71_BLK_TYPE_GLB_SCL_COEFF: 1299 d71->glb_scl_coeff_addr[blk_id] = reg; 1300 break; 1301 1302 default: 1303 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n", 1304 blk->block_info); 1305 err = -EINVAL; 1306 break; 1307 } 1308 1309 return err; 1310 } 1311 1312 static void d71_gcu_dump(struct d71_dev *d71, struct seq_file *sf) 1313 { 1314 u32 v[5]; 1315 1316 seq_puts(sf, "\n------ GCU ------\n"); 1317 1318 get_values_from_reg(d71->gcu_addr, 0, 3, v); 1319 seq_printf(sf, "GLB_ARCH_ID:\t\t0x%X\n", v[0]); 1320 seq_printf(sf, "GLB_CORE_ID:\t\t0x%X\n", v[1]); 1321 seq_printf(sf, "GLB_CORE_INFO:\t\t0x%X\n", v[2]); 1322 1323 get_values_from_reg(d71->gcu_addr, 0x10, 1, v); 1324 seq_printf(sf, "GLB_IRQ_STATUS:\t\t0x%X\n", v[0]); 1325 1326 get_values_from_reg(d71->gcu_addr, 0xA0, 5, v); 1327 seq_printf(sf, "GCU_IRQ_RAW_STATUS:\t0x%X\n", v[0]); 1328 seq_printf(sf, "GCU_IRQ_CLEAR:\t\t0x%X\n", v[1]); 1329 seq_printf(sf, "GCU_IRQ_MASK:\t\t0x%X\n", v[2]); 1330 seq_printf(sf, "GCU_IRQ_STATUS:\t\t0x%X\n", v[3]); 1331 seq_printf(sf, "GCU_STATUS:\t\t0x%X\n", v[4]); 1332 1333 get_values_from_reg(d71->gcu_addr, 0xD0, 3, v); 1334 seq_printf(sf, "GCU_CONTROL:\t\t0x%X\n", v[0]); 1335 seq_printf(sf, "GCU_CONFIG_VALID0:\t0x%X\n", v[1]); 1336 seq_printf(sf, "GCU_CONFIG_VALID1:\t0x%X\n", v[2]); 1337 } 1338 1339 static void d71_lpu_dump(struct d71_pipeline *pipe, struct seq_file *sf) 1340 { 1341 u32 v[6]; 1342 1343 seq_printf(sf, "\n------ LPU%d ------\n", pipe->base.id); 1344 1345 dump_block_header(sf, pipe->lpu_addr); 1346 1347 get_values_from_reg(pipe->lpu_addr, 0xA0, 6, v); 1348 seq_printf(sf, "LPU_IRQ_RAW_STATUS:\t0x%X\n", v[0]); 1349 seq_printf(sf, "LPU_IRQ_CLEAR:\t\t0x%X\n", v[1]); 1350 seq_printf(sf, "LPU_IRQ_MASK:\t\t0x%X\n", v[2]); 1351 seq_printf(sf, "LPU_IRQ_STATUS:\t\t0x%X\n", v[3]); 1352 seq_printf(sf, "LPU_STATUS:\t\t0x%X\n", v[4]); 1353 seq_printf(sf, "LPU_TBU_STATUS:\t\t0x%X\n", v[5]); 1354 1355 get_values_from_reg(pipe->lpu_addr, 0xC0, 1, v); 1356 seq_printf(sf, "LPU_INFO:\t\t0x%X\n", v[0]); 1357 1358 get_values_from_reg(pipe->lpu_addr, 0xD0, 3, v); 1359 seq_printf(sf, "LPU_RAXI_CONTROL:\t0x%X\n", v[0]); 1360 seq_printf(sf, "LPU_WAXI_CONTROL:\t0x%X\n", v[1]); 1361 seq_printf(sf, "LPU_TBU_CONTROL:\t0x%X\n", v[2]); 1362 } 1363 1364 static void d71_dou_dump(struct d71_pipeline *pipe, struct seq_file *sf) 1365 { 1366 u32 v[5]; 1367 1368 seq_printf(sf, "\n------ DOU%d ------\n", pipe->base.id); 1369 1370 dump_block_header(sf, pipe->dou_addr); 1371 1372 get_values_from_reg(pipe->dou_addr, 0xA0, 5, v); 1373 seq_printf(sf, "DOU_IRQ_RAW_STATUS:\t0x%X\n", v[0]); 1374 seq_printf(sf, "DOU_IRQ_CLEAR:\t\t0x%X\n", v[1]); 1375 seq_printf(sf, "DOU_IRQ_MASK:\t\t0x%X\n", v[2]); 1376 seq_printf(sf, "DOU_IRQ_STATUS:\t\t0x%X\n", v[3]); 1377 seq_printf(sf, "DOU_STATUS:\t\t0x%X\n", v[4]); 1378 } 1379 1380 static void d71_pipeline_dump(struct komeda_pipeline *pipe, struct seq_file *sf) 1381 { 1382 struct d71_pipeline *d71_pipe = to_d71_pipeline(pipe); 1383 1384 d71_lpu_dump(d71_pipe, sf); 1385 d71_dou_dump(d71_pipe, sf); 1386 } 1387 1388 const struct komeda_pipeline_funcs d71_pipeline_funcs = { 1389 .downscaling_clk_check = d71_downscaling_clk_check, 1390 .dump_register = d71_pipeline_dump, 1391 }; 1392 1393 void d71_dump(struct komeda_dev *mdev, struct seq_file *sf) 1394 { 1395 struct d71_dev *d71 = mdev->chip_data; 1396 1397 d71_gcu_dump(d71, sf); 1398 } 1399