1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2019-2022 Bootlin 4 * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com> 5 */ 6 7 #include <linux/of.h> 8 #include <linux/types.h> 9 10 #include <drm/drm_atomic.h> 11 #include <drm/drm_atomic_helper.h> 12 #include <drm/drm_blend.h> 13 #include <drm/drm_fb_cma_helper.h> 14 #include <drm/drm_fourcc.h> 15 #include <drm/drm_framebuffer.h> 16 #include <drm/drm_plane.h> 17 #include <drm/drm_plane_helper.h> 18 #include <drm/drm_print.h> 19 20 #include "logicvc_crtc.h" 21 #include "logicvc_drm.h" 22 #include "logicvc_layer.h" 23 #include "logicvc_of.h" 24 #include "logicvc_regs.h" 25 26 #define logicvc_layer(p) \ 27 container_of(p, struct logicvc_layer, drm_plane) 28 29 static uint32_t logicvc_layer_formats_rgb16[] = { 30 DRM_FORMAT_RGB565, 31 DRM_FORMAT_BGR565, 32 DRM_FORMAT_INVALID, 33 }; 34 35 static uint32_t logicvc_layer_formats_rgb24[] = { 36 DRM_FORMAT_XRGB8888, 37 DRM_FORMAT_XBGR8888, 38 DRM_FORMAT_INVALID, 39 }; 40 41 /* 42 * What we call depth in this driver only counts color components, not alpha. 43 * This allows us to stay compatible with the LogiCVC bistream definitions. 44 */ 45 static uint32_t logicvc_layer_formats_rgb24_alpha[] = { 46 DRM_FORMAT_ARGB8888, 47 DRM_FORMAT_ABGR8888, 48 DRM_FORMAT_INVALID, 49 }; 50 51 static struct logicvc_layer_formats logicvc_layer_formats[] = { 52 { 53 .colorspace = LOGICVC_LAYER_COLORSPACE_RGB, 54 .depth = 16, 55 .formats = logicvc_layer_formats_rgb16, 56 }, 57 { 58 .colorspace = LOGICVC_LAYER_COLORSPACE_RGB, 59 .depth = 24, 60 .formats = logicvc_layer_formats_rgb24, 61 }, 62 { 63 .colorspace = LOGICVC_LAYER_COLORSPACE_RGB, 64 .depth = 24, 65 .alpha = true, 66 .formats = logicvc_layer_formats_rgb24_alpha, 67 }, 68 { } 69 }; 70 71 static bool logicvc_layer_format_inverted(uint32_t format) 72 { 73 switch (format) { 74 case DRM_FORMAT_BGR565: 75 case DRM_FORMAT_BGR888: 76 case DRM_FORMAT_XBGR8888: 77 case DRM_FORMAT_ABGR8888: 78 return true; 79 default: 80 return false; 81 } 82 } 83 84 static int logicvc_plane_atomic_check(struct drm_plane *drm_plane, 85 struct drm_atomic_state *state) 86 { 87 struct drm_device *drm_dev = drm_plane->dev; 88 struct logicvc_layer *layer = logicvc_layer(drm_plane); 89 struct logicvc_drm *logicvc = logicvc_drm(drm_dev); 90 struct drm_plane_state *new_state = 91 drm_atomic_get_new_plane_state(state, drm_plane); 92 struct drm_crtc_state *crtc_state; 93 int min_scale, max_scale; 94 bool can_position; 95 int ret; 96 97 if (!new_state->crtc) 98 return 0; 99 100 crtc_state = drm_atomic_get_existing_crtc_state(new_state->state, 101 new_state->crtc); 102 if (WARN_ON(!crtc_state)) 103 return -EINVAL; 104 105 if (new_state->crtc_x < 0 || new_state->crtc_y < 0) { 106 drm_err(drm_dev, 107 "Negative on-CRTC positions are not supported.\n"); 108 return -EINVAL; 109 } 110 111 if (!logicvc->caps->layer_address) { 112 ret = logicvc_layer_buffer_find_setup(logicvc, layer, new_state, 113 NULL); 114 if (ret) { 115 drm_err(drm_dev, "No viable setup for buffer found.\n"); 116 return ret; 117 } 118 } 119 120 min_scale = DRM_PLANE_HELPER_NO_SCALING; 121 max_scale = DRM_PLANE_HELPER_NO_SCALING; 122 123 can_position = (drm_plane->type == DRM_PLANE_TYPE_OVERLAY && 124 layer->index != (logicvc->config.layers_count - 1) && 125 logicvc->config.layers_configurable); 126 127 ret = drm_atomic_helper_check_plane_state(new_state, crtc_state, 128 min_scale, max_scale, 129 can_position, true); 130 if (ret) { 131 drm_err(drm_dev, "Invalid plane state\n\n"); 132 return ret; 133 } 134 135 return 0; 136 } 137 138 static void logicvc_plane_atomic_update(struct drm_plane *drm_plane, 139 struct drm_atomic_state *state) 140 { 141 struct logicvc_layer *layer = logicvc_layer(drm_plane); 142 struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev); 143 struct drm_device *drm_dev = &logicvc->drm_dev; 144 struct drm_plane_state *new_state = 145 drm_atomic_get_new_plane_state(state, drm_plane); 146 struct drm_crtc *drm_crtc = &logicvc->crtc->drm_crtc; 147 struct drm_display_mode *mode = &drm_crtc->state->adjusted_mode; 148 struct drm_framebuffer *fb = new_state->fb; 149 struct logicvc_layer_buffer_setup setup = {}; 150 u32 index = layer->index; 151 u32 reg; 152 153 /* Layer dimensions */ 154 155 regmap_write(logicvc->regmap, LOGICVC_LAYER_WIDTH_REG(index), 156 new_state->crtc_w - 1); 157 regmap_write(logicvc->regmap, LOGICVC_LAYER_HEIGHT_REG(index), 158 new_state->crtc_h - 1); 159 160 if (logicvc->caps->layer_address) { 161 phys_addr_t fb_addr = drm_fb_cma_get_gem_addr(fb, new_state, 0); 162 163 regmap_write(logicvc->regmap, LOGICVC_LAYER_ADDRESS_REG(index), 164 fb_addr); 165 } else { 166 /* Rely on offsets to configure the address. */ 167 168 logicvc_layer_buffer_find_setup(logicvc, layer, new_state, 169 &setup); 170 171 /* Layer memory offsets */ 172 173 regmap_write(logicvc->regmap, LOGICVC_BUFFER_SEL_REG, 174 LOGICVC_BUFFER_SEL_VALUE(index, setup.buffer_sel)); 175 regmap_write(logicvc->regmap, LOGICVC_LAYER_HOFFSET_REG(index), 176 setup.hoffset); 177 regmap_write(logicvc->regmap, LOGICVC_LAYER_VOFFSET_REG(index), 178 setup.voffset); 179 } 180 181 /* Layer position */ 182 183 regmap_write(logicvc->regmap, LOGICVC_LAYER_HPOSITION_REG(index), 184 mode->hdisplay - 1 - new_state->crtc_x); 185 186 /* Vertical position must be set last to sync layer register changes. */ 187 regmap_write(logicvc->regmap, LOGICVC_LAYER_VPOSITION_REG(index), 188 mode->vdisplay - 1 - new_state->crtc_y); 189 190 /* Layer alpha */ 191 192 if (layer->config.alpha_mode == LOGICVC_LAYER_ALPHA_LAYER) { 193 u32 alpha_bits; 194 u32 alpha_max; 195 u32 alpha; 196 197 switch (layer->config.depth) { 198 case 8: 199 alpha_bits = 3; 200 break; 201 case 16: 202 if (layer->config.colorspace == 203 LOGICVC_LAYER_COLORSPACE_YUV) 204 alpha_bits = 8; 205 else 206 alpha_bits = 6; 207 break; 208 default: 209 alpha_bits = 8; 210 break; 211 } 212 213 alpha_max = BIT(alpha_bits) - 1; 214 alpha = new_state->alpha * alpha_max / DRM_BLEND_ALPHA_OPAQUE; 215 216 drm_dbg_kms(drm_dev, "Setting layer %d alpha to %d/%d\n", index, 217 alpha, alpha_max); 218 219 regmap_write(logicvc->regmap, LOGICVC_LAYER_ALPHA_REG(index), 220 alpha); 221 } 222 223 /* Layer control */ 224 225 reg = LOGICVC_LAYER_CTRL_ENABLE; 226 227 if (logicvc_layer_format_inverted(fb->format->format)) 228 reg |= LOGICVC_LAYER_CTRL_PIXEL_FORMAT_INVERT; 229 230 reg |= LOGICVC_LAYER_CTRL_COLOR_KEY_DISABLE; 231 232 regmap_write(logicvc->regmap, LOGICVC_LAYER_CTRL_REG(index), reg); 233 } 234 235 static void logicvc_plane_atomic_disable(struct drm_plane *drm_plane, 236 struct drm_atomic_state *state) 237 { 238 struct logicvc_layer *layer = logicvc_layer(drm_plane); 239 struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev); 240 u32 index = layer->index; 241 242 regmap_write(logicvc->regmap, LOGICVC_LAYER_CTRL_REG(index), 0); 243 } 244 245 static struct drm_plane_helper_funcs logicvc_plane_helper_funcs = { 246 .atomic_check = logicvc_plane_atomic_check, 247 .atomic_update = logicvc_plane_atomic_update, 248 .atomic_disable = logicvc_plane_atomic_disable, 249 }; 250 251 static const struct drm_plane_funcs logicvc_plane_funcs = { 252 .update_plane = drm_atomic_helper_update_plane, 253 .disable_plane = drm_atomic_helper_disable_plane, 254 .destroy = drm_plane_cleanup, 255 .reset = drm_atomic_helper_plane_reset, 256 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 257 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 258 }; 259 260 int logicvc_layer_buffer_find_setup(struct logicvc_drm *logicvc, 261 struct logicvc_layer *layer, 262 struct drm_plane_state *state, 263 struct logicvc_layer_buffer_setup *setup) 264 { 265 struct drm_device *drm_dev = &logicvc->drm_dev; 266 struct drm_framebuffer *fb = state->fb; 267 /* All the supported formats have a single data plane. */ 268 u32 layer_bytespp = fb->format->cpp[0]; 269 u32 layer_stride = layer_bytespp * logicvc->config.row_stride; 270 u32 base_offset = layer->config.base_offset * layer_stride; 271 u32 buffer_offset = layer->config.buffer_offset * layer_stride; 272 u8 buffer_sel = 0; 273 u16 voffset = 0; 274 u16 hoffset = 0; 275 phys_addr_t fb_addr; 276 u32 fb_offset; 277 u32 gap; 278 279 if (!logicvc->reserved_mem_base) { 280 drm_err(drm_dev, "No reserved memory base was registered!\n"); 281 return -ENOMEM; 282 } 283 284 fb_addr = drm_fb_cma_get_gem_addr(fb, state, 0); 285 if (fb_addr < logicvc->reserved_mem_base) { 286 drm_err(drm_dev, 287 "Framebuffer memory below reserved memory base!\n"); 288 return -EINVAL; 289 } 290 291 fb_offset = (u32) (fb_addr - logicvc->reserved_mem_base); 292 293 if (fb_offset < base_offset) { 294 drm_err(drm_dev, 295 "Framebuffer offset below layer base offset!\n"); 296 return -EINVAL; 297 } 298 299 gap = fb_offset - base_offset; 300 301 /* Use the possible video buffers selection. */ 302 if (gap && buffer_offset) { 303 buffer_sel = gap / buffer_offset; 304 if (buffer_sel > LOGICVC_BUFFER_SEL_MAX) 305 buffer_sel = LOGICVC_BUFFER_SEL_MAX; 306 307 gap -= buffer_sel * buffer_offset; 308 } 309 310 /* Use the vertical offset. */ 311 if (gap && layer_stride && logicvc->config.layers_configurable) { 312 voffset = gap / layer_stride; 313 if (voffset > LOGICVC_LAYER_VOFFSET_MAX) 314 voffset = LOGICVC_LAYER_VOFFSET_MAX; 315 316 gap -= voffset * layer_stride; 317 } 318 319 /* Use the horizontal offset. */ 320 if (gap && layer_bytespp && logicvc->config.layers_configurable) { 321 hoffset = gap / layer_bytespp; 322 if (hoffset > LOGICVC_DIMENSIONS_MAX) 323 hoffset = LOGICVC_DIMENSIONS_MAX; 324 325 gap -= hoffset * layer_bytespp; 326 } 327 328 if (gap) { 329 drm_err(drm_dev, 330 "Unable to find layer %d buffer setup for 0x%x byte gap\n", 331 layer->index, fb_offset - base_offset); 332 return -EINVAL; 333 } 334 335 drm_dbg_kms(drm_dev, "Found layer %d buffer setup for 0x%x byte gap:\n", 336 layer->index, fb_offset - base_offset); 337 338 drm_dbg_kms(drm_dev, "- buffer_sel = 0x%x chunks of 0x%x bytes\n", 339 buffer_sel, buffer_offset); 340 drm_dbg_kms(drm_dev, "- voffset = 0x%x chunks of 0x%x bytes\n", voffset, 341 layer_stride); 342 drm_dbg_kms(drm_dev, "- hoffset = 0x%x chunks of 0x%x bytes\n", hoffset, 343 layer_bytespp); 344 345 if (setup) { 346 setup->buffer_sel = buffer_sel; 347 setup->voffset = voffset; 348 setup->hoffset = hoffset; 349 } 350 351 return 0; 352 } 353 354 static struct logicvc_layer_formats *logicvc_layer_formats_lookup(struct logicvc_layer *layer) 355 { 356 bool alpha; 357 unsigned int i = 0; 358 359 alpha = (layer->config.alpha_mode == LOGICVC_LAYER_ALPHA_PIXEL); 360 361 while (logicvc_layer_formats[i].formats) { 362 if (logicvc_layer_formats[i].colorspace == layer->config.colorspace && 363 logicvc_layer_formats[i].depth == layer->config.depth && 364 logicvc_layer_formats[i].alpha == alpha) 365 return &logicvc_layer_formats[i]; 366 367 i++; 368 } 369 370 return NULL; 371 } 372 373 static unsigned int logicvc_layer_formats_count(struct logicvc_layer_formats *formats) 374 { 375 unsigned int count = 0; 376 377 while (formats->formats[count] != DRM_FORMAT_INVALID) 378 count++; 379 380 return count; 381 } 382 383 static int logicvc_layer_config_parse(struct logicvc_drm *logicvc, 384 struct logicvc_layer *layer) 385 { 386 struct device_node *of_node = layer->of_node; 387 struct logicvc_layer_config *config = &layer->config; 388 int ret; 389 390 logicvc_of_property_parse_bool(of_node, 391 LOGICVC_OF_PROPERTY_LAYER_PRIMARY, 392 &config->primary); 393 394 ret = logicvc_of_property_parse_u32(of_node, 395 LOGICVC_OF_PROPERTY_LAYER_COLORSPACE, 396 &config->colorspace); 397 if (ret) 398 return ret; 399 400 ret = logicvc_of_property_parse_u32(of_node, 401 LOGICVC_OF_PROPERTY_LAYER_DEPTH, 402 &config->depth); 403 if (ret) 404 return ret; 405 406 ret = logicvc_of_property_parse_u32(of_node, 407 LOGICVC_OF_PROPERTY_LAYER_ALPHA_MODE, 408 &config->alpha_mode); 409 if (ret) 410 return ret; 411 412 /* 413 * Memory offset is only relevant without layer address configuration. 414 */ 415 if (logicvc->caps->layer_address) 416 return 0; 417 418 ret = logicvc_of_property_parse_u32(of_node, 419 LOGICVC_OF_PROPERTY_LAYER_BASE_OFFSET, 420 &config->base_offset); 421 if (ret) 422 return ret; 423 424 ret = logicvc_of_property_parse_u32(of_node, 425 LOGICVC_OF_PROPERTY_LAYER_BUFFER_OFFSET, 426 &config->buffer_offset); 427 if (ret) 428 return ret; 429 430 return 0; 431 } 432 433 struct logicvc_layer *logicvc_layer_get_from_index(struct logicvc_drm *logicvc, 434 u32 index) 435 { 436 struct logicvc_layer *layer; 437 438 list_for_each_entry(layer, &logicvc->layers_list, list) 439 if (layer->index == index) 440 return layer; 441 442 return NULL; 443 } 444 445 struct logicvc_layer *logicvc_layer_get_from_type(struct logicvc_drm *logicvc, 446 enum drm_plane_type type) 447 { 448 struct logicvc_layer *layer; 449 450 list_for_each_entry(layer, &logicvc->layers_list, list) 451 if (layer->drm_plane.type == type) 452 return layer; 453 454 return NULL; 455 } 456 457 struct logicvc_layer *logicvc_layer_get_primary(struct logicvc_drm *logicvc) 458 { 459 return logicvc_layer_get_from_type(logicvc, DRM_PLANE_TYPE_PRIMARY); 460 } 461 462 static int logicvc_layer_init(struct logicvc_drm *logicvc, 463 struct device_node *of_node, u32 index) 464 { 465 struct drm_device *drm_dev = &logicvc->drm_dev; 466 struct device *dev = drm_dev->dev; 467 struct logicvc_layer *layer = NULL; 468 struct logicvc_layer_formats *formats; 469 unsigned int formats_count; 470 enum drm_plane_type type; 471 unsigned int zpos; 472 int ret; 473 474 layer = devm_kzalloc(dev, sizeof(*layer), GFP_KERNEL); 475 if (!layer) { 476 ret = -ENOMEM; 477 goto error; 478 } 479 480 layer->of_node = of_node; 481 layer->index = index; 482 483 ret = logicvc_layer_config_parse(logicvc, layer); 484 if (ret) { 485 drm_err(drm_dev, "Failed to parse config for layer #%d\n", 486 index); 487 goto error; 488 } 489 490 formats = logicvc_layer_formats_lookup(layer); 491 if (!formats) { 492 drm_err(drm_dev, "Failed to lookup formats for layer #%d\n", 493 index); 494 ret = -EINVAL; 495 goto error; 496 } 497 498 formats_count = logicvc_layer_formats_count(formats); 499 500 /* The final layer can be configured as a background layer. */ 501 if (logicvc->config.background_layer && 502 index == (logicvc->config.layers_count - 1)) { 503 /* 504 * A zero value for black is only valid for RGB, not for YUV, 505 * so this will need to take the format in account for YUV. 506 */ 507 u32 background = 0; 508 509 drm_dbg_kms(drm_dev, "Using layer #%d as background layer\n", 510 index); 511 512 regmap_write(logicvc->regmap, LOGICVC_BACKGROUND_COLOR_REG, 513 background); 514 515 devm_kfree(dev, layer); 516 517 return 0; 518 } 519 520 if (layer->config.primary) 521 type = DRM_PLANE_TYPE_PRIMARY; 522 else 523 type = DRM_PLANE_TYPE_OVERLAY; 524 525 ret = drm_universal_plane_init(drm_dev, &layer->drm_plane, 0, 526 &logicvc_plane_funcs, formats->formats, 527 formats_count, NULL, type, NULL); 528 if (ret) { 529 drm_err(drm_dev, "Failed to initialize layer plane\n"); 530 return ret; 531 } 532 533 drm_plane_helper_add(&layer->drm_plane, &logicvc_plane_helper_funcs); 534 535 zpos = logicvc->config.layers_count - index - 1; 536 drm_dbg_kms(drm_dev, "Giving layer #%d zpos %d\n", index, zpos); 537 538 if (layer->config.alpha_mode == LOGICVC_LAYER_ALPHA_LAYER) 539 drm_plane_create_alpha_property(&layer->drm_plane); 540 541 drm_plane_create_zpos_immutable_property(&layer->drm_plane, zpos); 542 543 drm_dbg_kms(drm_dev, "Registering layer #%d\n", index); 544 545 layer->formats = formats; 546 547 list_add_tail(&layer->list, &logicvc->layers_list); 548 549 return 0; 550 551 error: 552 if (layer) 553 devm_kfree(dev, layer); 554 555 return ret; 556 } 557 558 static void logicvc_layer_fini(struct logicvc_drm *logicvc, 559 struct logicvc_layer *layer) 560 { 561 struct device *dev = logicvc->drm_dev.dev; 562 563 list_del(&layer->list); 564 devm_kfree(dev, layer); 565 } 566 567 void logicvc_layers_attach_crtc(struct logicvc_drm *logicvc) 568 { 569 uint32_t possible_crtcs = drm_crtc_mask(&logicvc->crtc->drm_crtc); 570 struct logicvc_layer *layer; 571 572 list_for_each_entry(layer, &logicvc->layers_list, list) { 573 if (layer->drm_plane.type != DRM_PLANE_TYPE_OVERLAY) 574 continue; 575 576 layer->drm_plane.possible_crtcs = possible_crtcs; 577 } 578 } 579 580 int logicvc_layers_init(struct logicvc_drm *logicvc) 581 { 582 struct drm_device *drm_dev = &logicvc->drm_dev; 583 struct device *dev = drm_dev->dev; 584 struct device_node *of_node = dev->of_node; 585 struct device_node *layer_node = NULL; 586 struct device_node *layers_node; 587 struct logicvc_layer *layer; 588 struct logicvc_layer *next; 589 int ret = 0; 590 591 layers_node = of_get_child_by_name(of_node, "layers"); 592 if (!layers_node) { 593 drm_err(drm_dev, "No layers node found in the description\n"); 594 ret = -ENODEV; 595 goto error; 596 } 597 598 for_each_child_of_node(layers_node, layer_node) { 599 u32 index = 0; 600 601 if (!logicvc_of_node_is_layer(layer_node)) 602 continue; 603 604 ret = of_property_read_u32(layer_node, "reg", &index); 605 if (ret) 606 continue; 607 608 layer = logicvc_layer_get_from_index(logicvc, index); 609 if (layer) { 610 drm_err(drm_dev, "Duplicated entry for layer #%d\n", 611 index); 612 continue; 613 } 614 615 ret = logicvc_layer_init(logicvc, layer_node, index); 616 if (ret) { 617 of_node_put(layers_node); 618 goto error; 619 } 620 } 621 622 of_node_put(layers_node); 623 624 return 0; 625 626 error: 627 list_for_each_entry_safe(layer, next, &logicvc->layers_list, list) 628 logicvc_layer_fini(logicvc, layer); 629 630 return ret; 631 } 632