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[10]; 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 get_values_from_reg(c->reg, 0x130, 10, v); 817 seq_printf(sf, "SC_ENH_LIMITS:\t\t0x%X\n", v[0]); 818 seq_printf(sf, "SC_ENH_COEFF0:\t\t0x%X\n", v[1]); 819 seq_printf(sf, "SC_ENH_COEFF1:\t\t0x%X\n", v[2]); 820 seq_printf(sf, "SC_ENH_COEFF2:\t\t0x%X\n", v[3]); 821 seq_printf(sf, "SC_ENH_COEFF3:\t\t0x%X\n", v[4]); 822 seq_printf(sf, "SC_ENH_COEFF4:\t\t0x%X\n", v[5]); 823 seq_printf(sf, "SC_ENH_COEFF5:\t\t0x%X\n", v[6]); 824 seq_printf(sf, "SC_ENH_COEFF6:\t\t0x%X\n", v[7]); 825 seq_printf(sf, "SC_ENH_COEFF7:\t\t0x%X\n", v[8]); 826 seq_printf(sf, "SC_ENH_COEFF8:\t\t0x%X\n", v[9]); 827 } 828 829 static const struct komeda_component_funcs d71_scaler_funcs = { 830 .update = d71_scaler_update, 831 .disable = d71_component_disable, 832 .dump_register = d71_scaler_dump, 833 }; 834 835 static int d71_scaler_init(struct d71_dev *d71, 836 struct block_header *blk, u32 __iomem *reg) 837 { 838 struct komeda_component *c; 839 struct komeda_scaler *scaler; 840 u32 pipe_id, comp_id; 841 842 get_resources_id(blk->block_info, &pipe_id, &comp_id); 843 844 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*scaler), 845 comp_id, BLOCK_INFO_INPUT_ID(blk->block_info), 846 &d71_scaler_funcs, 847 1, get_valid_inputs(blk), 1, reg, 848 "CU%d_SCALER%d", 849 pipe_id, BLOCK_INFO_BLK_ID(blk->block_info)); 850 851 if (IS_ERR(c)) { 852 DRM_ERROR("Failed to initialize scaler"); 853 return PTR_ERR(c); 854 } 855 856 scaler = to_scaler(c); 857 set_range(&scaler->hsize, 4, __get_blk_line_size(d71, reg, 2048)); 858 set_range(&scaler->vsize, 4, 4096); 859 scaler->max_downscaling = 6; 860 scaler->max_upscaling = 64; 861 scaler->scaling_split_overlap = 8; 862 scaler->enh_split_overlap = 1; 863 864 malidp_write32(c->reg, BLK_CONTROL, 0); 865 866 return 0; 867 } 868 869 static int d71_downscaling_clk_check(struct komeda_pipeline *pipe, 870 struct drm_display_mode *mode, 871 unsigned long aclk_rate, 872 struct komeda_data_flow_cfg *dflow) 873 { 874 u32 h_in = dflow->in_w; 875 u32 v_in = dflow->in_h; 876 u32 v_out = dflow->out_h; 877 u64 fraction, denominator; 878 879 /* D71 downscaling must satisfy the following equation 880 * 881 * ACLK h_in * v_in 882 * ------- >= --------------------------------------------- 883 * PXLCLK (h_total - (1 + 2 * v_in / v_out)) * v_out 884 * 885 * In only horizontal downscaling situation, the right side should be 886 * multiplied by (h_total - 3) / (h_active - 3), then equation becomes 887 * 888 * ACLK h_in 889 * ------- >= ---------------- 890 * PXLCLK (h_active - 3) 891 * 892 * To avoid precision lost the equation 1 will be convert to: 893 * 894 * ACLK h_in * v_in 895 * ------- >= ----------------------------------- 896 * PXLCLK (h_total -1 ) * v_out - 2 * v_in 897 */ 898 if (v_in == v_out) { 899 fraction = h_in; 900 denominator = mode->hdisplay - 3; 901 } else { 902 fraction = h_in * v_in; 903 denominator = (mode->htotal - 1) * v_out - 2 * v_in; 904 } 905 906 return aclk_rate * denominator >= mode->crtc_clock * 1000 * fraction ? 907 0 : -EINVAL; 908 } 909 910 static void d71_splitter_update(struct komeda_component *c, 911 struct komeda_component_state *state) 912 { 913 struct komeda_splitter_state *st = to_splitter_st(state); 914 u32 __iomem *reg = c->reg; 915 916 malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0)); 917 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize)); 918 malidp_write32(reg, SP_OVERLAP_SIZE, st->overlap & 0x1FFF); 919 malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN); 920 } 921 922 static void d71_splitter_dump(struct komeda_component *c, struct seq_file *sf) 923 { 924 u32 v[3]; 925 926 dump_block_header(sf, c->reg); 927 928 get_values_from_reg(c->reg, BLK_INPUT_ID0, 1, v); 929 seq_printf(sf, "SP_INPUT_ID0:\t\t0x%X\n", v[0]); 930 931 get_values_from_reg(c->reg, BLK_CONTROL, 3, v); 932 seq_printf(sf, "SP_CONTROL:\t\t0x%X\n", v[0]); 933 seq_printf(sf, "SP_SIZE:\t\t0x%X\n", v[1]); 934 seq_printf(sf, "SP_OVERLAP_SIZE:\t0x%X\n", v[2]); 935 } 936 937 static const struct komeda_component_funcs d71_splitter_funcs = { 938 .update = d71_splitter_update, 939 .disable = d71_component_disable, 940 .dump_register = d71_splitter_dump, 941 }; 942 943 static int d71_splitter_init(struct d71_dev *d71, 944 struct block_header *blk, u32 __iomem *reg) 945 { 946 struct komeda_component *c; 947 struct komeda_splitter *splitter; 948 u32 pipe_id, comp_id; 949 950 get_resources_id(blk->block_info, &pipe_id, &comp_id); 951 952 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*splitter), 953 comp_id, 954 BLOCK_INFO_INPUT_ID(blk->block_info), 955 &d71_splitter_funcs, 956 1, get_valid_inputs(blk), 2, reg, 957 "CU%d_SPLITTER", pipe_id); 958 959 if (IS_ERR(c)) { 960 DRM_ERROR("Failed to initialize splitter"); 961 return -1; 962 } 963 964 splitter = to_splitter(c); 965 966 set_range(&splitter->hsize, 4, get_blk_line_size(d71, reg)); 967 set_range(&splitter->vsize, 4, d71->max_vsize); 968 969 return 0; 970 } 971 972 static void d71_merger_update(struct komeda_component *c, 973 struct komeda_component_state *state) 974 { 975 struct komeda_merger_state *st = to_merger_st(state); 976 u32 __iomem *reg = c->reg; 977 u32 index; 978 979 for_each_changed_input(state, index) 980 malidp_write32(reg, MG_INPUT_ID0 + index * 4, 981 to_d71_input_id(state, index)); 982 983 malidp_write32(reg, MG_SIZE, HV_SIZE(st->hsize_merged, 984 st->vsize_merged)); 985 malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN); 986 } 987 988 static void d71_merger_dump(struct komeda_component *c, struct seq_file *sf) 989 { 990 u32 v; 991 992 dump_block_header(sf, c->reg); 993 994 get_values_from_reg(c->reg, MG_INPUT_ID0, 1, &v); 995 seq_printf(sf, "MG_INPUT_ID0:\t\t0x%X\n", v); 996 997 get_values_from_reg(c->reg, MG_INPUT_ID1, 1, &v); 998 seq_printf(sf, "MG_INPUT_ID1:\t\t0x%X\n", v); 999 1000 get_values_from_reg(c->reg, BLK_CONTROL, 1, &v); 1001 seq_printf(sf, "MG_CONTROL:\t\t0x%X\n", v); 1002 1003 get_values_from_reg(c->reg, MG_SIZE, 1, &v); 1004 seq_printf(sf, "MG_SIZE:\t\t0x%X\n", v); 1005 } 1006 1007 static const struct komeda_component_funcs d71_merger_funcs = { 1008 .update = d71_merger_update, 1009 .disable = d71_component_disable, 1010 .dump_register = d71_merger_dump, 1011 }; 1012 1013 static int d71_merger_init(struct d71_dev *d71, 1014 struct block_header *blk, u32 __iomem *reg) 1015 { 1016 struct komeda_component *c; 1017 struct komeda_merger *merger; 1018 u32 pipe_id, comp_id; 1019 1020 get_resources_id(blk->block_info, &pipe_id, &comp_id); 1021 1022 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*merger), 1023 comp_id, 1024 BLOCK_INFO_INPUT_ID(blk->block_info), 1025 &d71_merger_funcs, 1026 MG_NUM_INPUTS_IDS, get_valid_inputs(blk), 1027 MG_NUM_OUTPUTS_IDS, reg, 1028 "CU%d_MERGER", pipe_id); 1029 1030 if (IS_ERR(c)) { 1031 DRM_ERROR("Failed to initialize merger.\n"); 1032 return PTR_ERR(c); 1033 } 1034 1035 merger = to_merger(c); 1036 1037 set_range(&merger->hsize_merged, 4, 1038 __get_blk_line_size(d71, reg, 4032)); 1039 set_range(&merger->vsize_merged, 4, 4096); 1040 1041 return 0; 1042 } 1043 1044 static void d71_improc_update(struct komeda_component *c, 1045 struct komeda_component_state *state) 1046 { 1047 struct drm_crtc_state *crtc_st = state->crtc->state; 1048 struct komeda_improc_state *st = to_improc_st(state); 1049 struct d71_pipeline *pipe = to_d71_pipeline(c->pipeline); 1050 u32 __iomem *reg = c->reg; 1051 u32 index, mask = 0, ctrl = 0; 1052 1053 for_each_changed_input(state, index) 1054 malidp_write32(reg, BLK_INPUT_ID0 + index * 4, 1055 to_d71_input_id(state, index)); 1056 1057 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize)); 1058 malidp_write32(reg, IPS_DEPTH, st->color_depth); 1059 1060 if (crtc_st->color_mgmt_changed) { 1061 mask |= IPS_CTRL_FT | IPS_CTRL_RGB; 1062 1063 if (crtc_st->gamma_lut) { 1064 malidp_write_group(pipe->dou_ft_coeff_addr, FT_COEFF0, 1065 KOMEDA_N_GAMMA_COEFFS, 1066 st->fgamma_coeffs); 1067 ctrl |= IPS_CTRL_FT; /* enable gamma */ 1068 } 1069 1070 if (crtc_st->ctm) { 1071 malidp_write_group(reg, IPS_RGB_RGB_COEFF0, 1072 KOMEDA_N_CTM_COEFFS, 1073 st->ctm_coeffs); 1074 ctrl |= IPS_CTRL_RGB; /* enable gamut */ 1075 } 1076 } 1077 1078 mask |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420; 1079 1080 /* config color format */ 1081 if (st->color_format == DRM_COLOR_FORMAT_YCBCR420) 1082 ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420; 1083 else if (st->color_format == DRM_COLOR_FORMAT_YCBCR422) 1084 ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422; 1085 else if (st->color_format == DRM_COLOR_FORMAT_YCBCR444) 1086 ctrl |= IPS_CTRL_YUV; 1087 1088 malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl); 1089 } 1090 1091 static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf) 1092 { 1093 u32 v[12], i; 1094 1095 dump_block_header(sf, c->reg); 1096 1097 get_values_from_reg(c->reg, 0x80, 2, v); 1098 seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]); 1099 seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]); 1100 1101 get_values_from_reg(c->reg, 0xC0, 1, v); 1102 seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]); 1103 1104 get_values_from_reg(c->reg, 0xD0, 3, v); 1105 seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]); 1106 seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]); 1107 seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]); 1108 1109 get_values_from_reg(c->reg, 0x130, 12, v); 1110 for (i = 0; i < 12; i++) 1111 seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]); 1112 1113 get_values_from_reg(c->reg, 0x170, 12, v); 1114 for (i = 0; i < 12; i++) 1115 seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]); 1116 } 1117 1118 static const struct komeda_component_funcs d71_improc_funcs = { 1119 .update = d71_improc_update, 1120 .disable = d71_component_disable, 1121 .dump_register = d71_improc_dump, 1122 }; 1123 1124 static int d71_improc_init(struct d71_dev *d71, 1125 struct block_header *blk, u32 __iomem *reg) 1126 { 1127 struct komeda_component *c; 1128 struct komeda_improc *improc; 1129 u32 pipe_id, comp_id, value; 1130 1131 get_resources_id(blk->block_info, &pipe_id, &comp_id); 1132 1133 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*improc), 1134 comp_id, 1135 BLOCK_INFO_INPUT_ID(blk->block_info), 1136 &d71_improc_funcs, IPS_NUM_INPUT_IDS, 1137 get_valid_inputs(blk), 1138 IPS_NUM_OUTPUT_IDS, reg, "DOU%d_IPS", pipe_id); 1139 if (IS_ERR(c)) { 1140 DRM_ERROR("Failed to add improc component\n"); 1141 return PTR_ERR(c); 1142 } 1143 1144 improc = to_improc(c); 1145 improc->supported_color_depths = BIT(8) | BIT(10); 1146 improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 | 1147 DRM_COLOR_FORMAT_YCBCR444 | 1148 DRM_COLOR_FORMAT_YCBCR422; 1149 value = malidp_read32(reg, BLK_INFO); 1150 if (value & IPS_INFO_CHD420) 1151 improc->supported_color_formats |= DRM_COLOR_FORMAT_YCBCR420; 1152 1153 improc->supports_csc = true; 1154 improc->supports_gamma = true; 1155 1156 return 0; 1157 } 1158 1159 static void d71_timing_ctrlr_disable(struct komeda_component *c) 1160 { 1161 malidp_write32_mask(c->reg, BLK_CONTROL, BS_CTRL_EN, 0); 1162 } 1163 1164 static void d71_timing_ctrlr_update(struct komeda_component *c, 1165 struct komeda_component_state *state) 1166 { 1167 struct drm_crtc_state *crtc_st = state->crtc->state; 1168 struct drm_display_mode *mode = &crtc_st->adjusted_mode; 1169 u32 __iomem *reg = c->reg; 1170 u32 hactive, hfront_porch, hback_porch, hsync_len; 1171 u32 vactive, vfront_porch, vback_porch, vsync_len; 1172 u32 value; 1173 1174 hactive = mode->crtc_hdisplay; 1175 hfront_porch = mode->crtc_hsync_start - mode->crtc_hdisplay; 1176 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1177 hback_porch = mode->crtc_htotal - mode->crtc_hsync_end; 1178 1179 vactive = mode->crtc_vdisplay; 1180 vfront_porch = mode->crtc_vsync_start - mode->crtc_vdisplay; 1181 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 1182 vback_porch = mode->crtc_vtotal - mode->crtc_vsync_end; 1183 1184 malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(hactive, vactive)); 1185 malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(hfront_porch, 1186 hback_porch)); 1187 malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vfront_porch, 1188 vback_porch)); 1189 1190 value = BS_SYNC_VSW(vsync_len) | BS_SYNC_HSW(hsync_len); 1191 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BS_SYNC_VSP : 0; 1192 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BS_SYNC_HSP : 0; 1193 malidp_write32(reg, BS_SYNC, value); 1194 1195 malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1); 1196 malidp_write32(reg, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE); 1197 1198 /* configure bs control register */ 1199 value = BS_CTRL_EN | BS_CTRL_VM; 1200 if (c->pipeline->dual_link) { 1201 malidp_write32(reg, BS_DRIFT_TO, hfront_porch + 16); 1202 value |= BS_CTRL_DL; 1203 } 1204 1205 malidp_write32(reg, BLK_CONTROL, value); 1206 } 1207 1208 static void d71_timing_ctrlr_dump(struct komeda_component *c, 1209 struct seq_file *sf) 1210 { 1211 u32 v[8], i; 1212 1213 dump_block_header(sf, c->reg); 1214 1215 get_values_from_reg(c->reg, 0xC0, 1, v); 1216 seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]); 1217 1218 get_values_from_reg(c->reg, 0xD0, 8, v); 1219 seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]); 1220 seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]); 1221 seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]); 1222 seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]); 1223 seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]); 1224 seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]); 1225 seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]); 1226 seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]); 1227 1228 get_values_from_reg(c->reg, 0x100, 3, v); 1229 seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]); 1230 seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]); 1231 seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]); 1232 1233 get_values_from_reg(c->reg, 0x110, 3, v); 1234 for (i = 0; i < 3; i++) 1235 seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]); 1236 1237 get_values_from_reg(c->reg, 0x120, 5, v); 1238 for (i = 0; i < 2; i++) { 1239 seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]); 1240 seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]); 1241 } 1242 seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]); 1243 } 1244 1245 static const struct komeda_component_funcs d71_timing_ctrlr_funcs = { 1246 .update = d71_timing_ctrlr_update, 1247 .disable = d71_timing_ctrlr_disable, 1248 .dump_register = d71_timing_ctrlr_dump, 1249 }; 1250 1251 static int d71_timing_ctrlr_init(struct d71_dev *d71, 1252 struct block_header *blk, u32 __iomem *reg) 1253 { 1254 struct komeda_component *c; 1255 struct komeda_timing_ctrlr *ctrlr; 1256 u32 pipe_id, comp_id; 1257 1258 get_resources_id(blk->block_info, &pipe_id, &comp_id); 1259 1260 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*ctrlr), 1261 KOMEDA_COMPONENT_TIMING_CTRLR, 1262 BLOCK_INFO_INPUT_ID(blk->block_info), 1263 &d71_timing_ctrlr_funcs, 1264 1, BIT(KOMEDA_COMPONENT_IPS0 + pipe_id), 1265 BS_NUM_OUTPUT_IDS, reg, "DOU%d_BS", pipe_id); 1266 if (IS_ERR(c)) { 1267 DRM_ERROR("Failed to add display_ctrl component\n"); 1268 return PTR_ERR(c); 1269 } 1270 1271 ctrlr = to_ctrlr(c); 1272 1273 ctrlr->supports_dual_link = d71->supports_dual_link; 1274 1275 return 0; 1276 } 1277 1278 int d71_probe_block(struct d71_dev *d71, 1279 struct block_header *blk, u32 __iomem *reg) 1280 { 1281 struct d71_pipeline *pipe; 1282 int blk_id = BLOCK_INFO_BLK_ID(blk->block_info); 1283 1284 int err = 0; 1285 1286 switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) { 1287 case D71_BLK_TYPE_GCU: 1288 break; 1289 1290 case D71_BLK_TYPE_LPU: 1291 pipe = d71->pipes[blk_id]; 1292 pipe->lpu_addr = reg; 1293 break; 1294 1295 case D71_BLK_TYPE_LPU_LAYER: 1296 err = d71_layer_init(d71, blk, reg); 1297 break; 1298 1299 case D71_BLK_TYPE_LPU_WB_LAYER: 1300 err = d71_wb_layer_init(d71, blk, reg); 1301 break; 1302 1303 case D71_BLK_TYPE_CU: 1304 pipe = d71->pipes[blk_id]; 1305 pipe->cu_addr = reg; 1306 err = d71_compiz_init(d71, blk, reg); 1307 break; 1308 1309 case D71_BLK_TYPE_CU_SCALER: 1310 err = d71_scaler_init(d71, blk, reg); 1311 break; 1312 1313 case D71_BLK_TYPE_CU_SPLITTER: 1314 err = d71_splitter_init(d71, blk, reg); 1315 break; 1316 1317 case D71_BLK_TYPE_CU_MERGER: 1318 err = d71_merger_init(d71, blk, reg); 1319 break; 1320 1321 case D71_BLK_TYPE_DOU: 1322 pipe = d71->pipes[blk_id]; 1323 pipe->dou_addr = reg; 1324 break; 1325 1326 case D71_BLK_TYPE_DOU_IPS: 1327 err = d71_improc_init(d71, blk, reg); 1328 break; 1329 1330 case D71_BLK_TYPE_DOU_FT_COEFF: 1331 pipe = d71->pipes[blk_id]; 1332 pipe->dou_ft_coeff_addr = reg; 1333 break; 1334 1335 case D71_BLK_TYPE_DOU_BS: 1336 err = d71_timing_ctrlr_init(d71, blk, reg); 1337 break; 1338 1339 case D71_BLK_TYPE_GLB_LT_COEFF: 1340 break; 1341 1342 case D71_BLK_TYPE_GLB_SCL_COEFF: 1343 d71->glb_scl_coeff_addr[blk_id] = reg; 1344 break; 1345 1346 default: 1347 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n", 1348 blk->block_info); 1349 err = -EINVAL; 1350 break; 1351 } 1352 1353 return err; 1354 } 1355 1356 static void d71_gcu_dump(struct d71_dev *d71, struct seq_file *sf) 1357 { 1358 u32 v[5]; 1359 1360 seq_puts(sf, "\n------ GCU ------\n"); 1361 1362 get_values_from_reg(d71->gcu_addr, 0, 3, v); 1363 seq_printf(sf, "GLB_ARCH_ID:\t\t0x%X\n", v[0]); 1364 seq_printf(sf, "GLB_CORE_ID:\t\t0x%X\n", v[1]); 1365 seq_printf(sf, "GLB_CORE_INFO:\t\t0x%X\n", v[2]); 1366 1367 get_values_from_reg(d71->gcu_addr, 0x10, 1, v); 1368 seq_printf(sf, "GLB_IRQ_STATUS:\t\t0x%X\n", v[0]); 1369 1370 get_values_from_reg(d71->gcu_addr, 0xA0, 5, v); 1371 seq_printf(sf, "GCU_IRQ_RAW_STATUS:\t0x%X\n", v[0]); 1372 seq_printf(sf, "GCU_IRQ_CLEAR:\t\t0x%X\n", v[1]); 1373 seq_printf(sf, "GCU_IRQ_MASK:\t\t0x%X\n", v[2]); 1374 seq_printf(sf, "GCU_IRQ_STATUS:\t\t0x%X\n", v[3]); 1375 seq_printf(sf, "GCU_STATUS:\t\t0x%X\n", v[4]); 1376 1377 get_values_from_reg(d71->gcu_addr, 0xD0, 3, v); 1378 seq_printf(sf, "GCU_CONTROL:\t\t0x%X\n", v[0]); 1379 seq_printf(sf, "GCU_CONFIG_VALID0:\t0x%X\n", v[1]); 1380 seq_printf(sf, "GCU_CONFIG_VALID1:\t0x%X\n", v[2]); 1381 } 1382 1383 static void d71_lpu_dump(struct d71_pipeline *pipe, struct seq_file *sf) 1384 { 1385 u32 v[6]; 1386 1387 seq_printf(sf, "\n------ LPU%d ------\n", pipe->base.id); 1388 1389 dump_block_header(sf, pipe->lpu_addr); 1390 1391 get_values_from_reg(pipe->lpu_addr, 0xA0, 6, v); 1392 seq_printf(sf, "LPU_IRQ_RAW_STATUS:\t0x%X\n", v[0]); 1393 seq_printf(sf, "LPU_IRQ_CLEAR:\t\t0x%X\n", v[1]); 1394 seq_printf(sf, "LPU_IRQ_MASK:\t\t0x%X\n", v[2]); 1395 seq_printf(sf, "LPU_IRQ_STATUS:\t\t0x%X\n", v[3]); 1396 seq_printf(sf, "LPU_STATUS:\t\t0x%X\n", v[4]); 1397 seq_printf(sf, "LPU_TBU_STATUS:\t\t0x%X\n", v[5]); 1398 1399 get_values_from_reg(pipe->lpu_addr, 0xC0, 1, v); 1400 seq_printf(sf, "LPU_INFO:\t\t0x%X\n", v[0]); 1401 1402 get_values_from_reg(pipe->lpu_addr, 0xD0, 3, v); 1403 seq_printf(sf, "LPU_RAXI_CONTROL:\t0x%X\n", v[0]); 1404 seq_printf(sf, "LPU_WAXI_CONTROL:\t0x%X\n", v[1]); 1405 seq_printf(sf, "LPU_TBU_CONTROL:\t0x%X\n", v[2]); 1406 } 1407 1408 static void d71_dou_dump(struct d71_pipeline *pipe, struct seq_file *sf) 1409 { 1410 u32 v[5]; 1411 1412 seq_printf(sf, "\n------ DOU%d ------\n", pipe->base.id); 1413 1414 dump_block_header(sf, pipe->dou_addr); 1415 1416 get_values_from_reg(pipe->dou_addr, 0xA0, 5, v); 1417 seq_printf(sf, "DOU_IRQ_RAW_STATUS:\t0x%X\n", v[0]); 1418 seq_printf(sf, "DOU_IRQ_CLEAR:\t\t0x%X\n", v[1]); 1419 seq_printf(sf, "DOU_IRQ_MASK:\t\t0x%X\n", v[2]); 1420 seq_printf(sf, "DOU_IRQ_STATUS:\t\t0x%X\n", v[3]); 1421 seq_printf(sf, "DOU_STATUS:\t\t0x%X\n", v[4]); 1422 } 1423 1424 static void d71_pipeline_dump(struct komeda_pipeline *pipe, struct seq_file *sf) 1425 { 1426 struct d71_pipeline *d71_pipe = to_d71_pipeline(pipe); 1427 1428 d71_lpu_dump(d71_pipe, sf); 1429 d71_dou_dump(d71_pipe, sf); 1430 } 1431 1432 const struct komeda_pipeline_funcs d71_pipeline_funcs = { 1433 .downscaling_clk_check = d71_downscaling_clk_check, 1434 .dump_register = d71_pipeline_dump, 1435 }; 1436 1437 void d71_dump(struct komeda_dev *mdev, struct seq_file *sf) 1438 { 1439 struct d71_dev *d71 = mdev->chip_data; 1440 1441 d71_gcu_dump(d71, sf); 1442 } 1443