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