| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Hisilicon Hi6220 SoC ADE(Advanced Display Engine)'s crtc&plane driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 8 | 9 | * Xinliang Liu <z.liuxinliang@hisilicon.com> |
|---|
| 9 | 10 | * Xinliang Liu <xinliang.liu@linaro.org> |
|---|
| 10 | 11 | * Xinwei Kong <kong.kongxinwei@hisilicon.com> |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 13 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 14 | | - * published by the Free Software Foundation. |
|---|
| 15 | | - * |
|---|
| 16 | 12 | */ |
|---|
| 17 | 13 | |
|---|
| 18 | 14 | #include <linux/bitops.h> |
|---|
| 19 | 15 | #include <linux/clk.h> |
|---|
| 20 | | -#include <video/display_timing.h> |
|---|
| 21 | 16 | #include <linux/mfd/syscon.h> |
|---|
| 17 | +#include <linux/platform_device.h> |
|---|
| 22 | 18 | #include <linux/regmap.h> |
|---|
| 23 | 19 | #include <linux/reset.h> |
|---|
| 24 | 20 | |
|---|
| 25 | | -#include <drm/drmP.h> |
|---|
| 26 | | -#include <drm/drm_crtc.h> |
|---|
| 27 | | -#include <drm/drm_crtc_helper.h> |
|---|
| 21 | +#include <video/display_timing.h> |
|---|
| 22 | + |
|---|
| 28 | 23 | #include <drm/drm_atomic.h> |
|---|
| 29 | 24 | #include <drm/drm_atomic_helper.h> |
|---|
| 30 | | -#include <drm/drm_plane_helper.h> |
|---|
| 31 | | -#include <drm/drm_gem_cma_helper.h> |
|---|
| 25 | +#include <drm/drm_crtc.h> |
|---|
| 26 | +#include <drm/drm_drv.h> |
|---|
| 32 | 27 | #include <drm/drm_fb_cma_helper.h> |
|---|
| 28 | +#include <drm/drm_fourcc.h> |
|---|
| 29 | +#include <drm/drm_gem_cma_helper.h> |
|---|
| 30 | +#include <drm/drm_plane_helper.h> |
|---|
| 31 | +#include <drm/drm_probe_helper.h> |
|---|
| 32 | +#include <drm/drm_vblank.h> |
|---|
| 33 | +#include <drm/drm_gem_framebuffer_helper.h> |
|---|
| 33 | 34 | |
|---|
| 34 | 35 | #include "kirin_drm_drv.h" |
|---|
| 35 | 36 | #include "kirin_ade_reg.h" |
|---|
| 36 | 37 | |
|---|
| 37 | | -#define PRIMARY_CH ADE_CH1 /* primary plane */ |
|---|
| 38 | 38 | #define OUT_OVLY ADE_OVLY2 /* output overlay compositor */ |
|---|
| 39 | 39 | #define ADE_DEBUG 1 |
|---|
| 40 | 40 | |
|---|
| 41 | | -#define to_ade_crtc(crtc) \ |
|---|
| 42 | | - container_of(crtc, struct ade_crtc, base) |
|---|
| 43 | | - |
|---|
| 44 | | -#define to_ade_plane(plane) \ |
|---|
| 45 | | - container_of(plane, struct ade_plane, base) |
|---|
| 46 | 41 | |
|---|
| 47 | 42 | struct ade_hw_ctx { |
|---|
| 48 | 43 | void __iomem *base; |
|---|
| .. | .. |
|---|
| 53 | 48 | struct reset_control *reset; |
|---|
| 54 | 49 | bool power_on; |
|---|
| 55 | 50 | int irq; |
|---|
| 51 | + |
|---|
| 52 | + struct drm_crtc *crtc; |
|---|
| 56 | 53 | }; |
|---|
| 57 | 54 | |
|---|
| 58 | | -struct ade_crtc { |
|---|
| 59 | | - struct drm_crtc base; |
|---|
| 60 | | - struct ade_hw_ctx *ctx; |
|---|
| 61 | | - bool enable; |
|---|
| 62 | | - u32 out_format; |
|---|
| 63 | | -}; |
|---|
| 64 | | - |
|---|
| 65 | | -struct ade_plane { |
|---|
| 66 | | - struct drm_plane base; |
|---|
| 67 | | - void *ctx; |
|---|
| 68 | | - u8 ch; /* channel */ |
|---|
| 69 | | -}; |
|---|
| 70 | | - |
|---|
| 71 | | -struct ade_data { |
|---|
| 72 | | - struct ade_crtc acrtc; |
|---|
| 73 | | - struct ade_plane aplane[ADE_CH_NUM]; |
|---|
| 74 | | - struct ade_hw_ctx ctx; |
|---|
| 75 | | -}; |
|---|
| 76 | | - |
|---|
| 77 | | -/* ade-format info: */ |
|---|
| 78 | | -struct ade_format { |
|---|
| 79 | | - u32 pixel_format; |
|---|
| 80 | | - enum ade_fb_format ade_format; |
|---|
| 81 | | -}; |
|---|
| 82 | | - |
|---|
| 83 | | -static const struct ade_format ade_formats[] = { |
|---|
| 55 | +static const struct kirin_format ade_formats[] = { |
|---|
| 84 | 56 | /* 16bpp RGB: */ |
|---|
| 85 | 57 | { DRM_FORMAT_RGB565, ADE_RGB_565 }, |
|---|
| 86 | 58 | { DRM_FORMAT_BGR565, ADE_BGR_565 }, |
|---|
| .. | .. |
|---|
| 96 | 68 | { DRM_FORMAT_ABGR8888, ADE_ABGR_8888 }, |
|---|
| 97 | 69 | }; |
|---|
| 98 | 70 | |
|---|
| 99 | | -static const u32 channel_formats1[] = { |
|---|
| 71 | +static const u32 channel_formats[] = { |
|---|
| 100 | 72 | /* channel 1,2,3,4 */ |
|---|
| 101 | 73 | DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888, |
|---|
| 102 | 74 | DRM_FORMAT_BGR888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, |
|---|
| 103 | 75 | DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_ARGB8888, |
|---|
| 104 | 76 | DRM_FORMAT_ABGR8888 |
|---|
| 105 | 77 | }; |
|---|
| 106 | | - |
|---|
| 107 | | -u32 ade_get_channel_formats(u8 ch, const u32 **formats) |
|---|
| 108 | | -{ |
|---|
| 109 | | - switch (ch) { |
|---|
| 110 | | - case ADE_CH1: |
|---|
| 111 | | - *formats = channel_formats1; |
|---|
| 112 | | - return ARRAY_SIZE(channel_formats1); |
|---|
| 113 | | - default: |
|---|
| 114 | | - DRM_ERROR("no this channel %d\n", ch); |
|---|
| 115 | | - *formats = NULL; |
|---|
| 116 | | - return 0; |
|---|
| 117 | | - } |
|---|
| 118 | | -} |
|---|
| 119 | 78 | |
|---|
| 120 | 79 | /* convert from fourcc format to ade format */ |
|---|
| 121 | 80 | static u32 ade_get_format(u32 pixel_format) |
|---|
| .. | .. |
|---|
| 124 | 83 | |
|---|
| 125 | 84 | for (i = 0; i < ARRAY_SIZE(ade_formats); i++) |
|---|
| 126 | 85 | if (ade_formats[i].pixel_format == pixel_format) |
|---|
| 127 | | - return ade_formats[i].ade_format; |
|---|
| 86 | + return ade_formats[i].hw_format; |
|---|
| 128 | 87 | |
|---|
| 129 | 88 | /* not found */ |
|---|
| 130 | 89 | DRM_ERROR("Not found pixel format!!fourcc_format= %d\n", |
|---|
| .. | .. |
|---|
| 182 | 141 | const struct drm_display_mode *mode, |
|---|
| 183 | 142 | struct drm_display_mode *adjusted_mode) |
|---|
| 184 | 143 | { |
|---|
| 185 | | - struct ade_crtc *acrtc = to_ade_crtc(crtc); |
|---|
| 186 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 144 | + struct kirin_crtc *kcrtc = to_kirin_crtc(crtc); |
|---|
| 145 | + struct ade_hw_ctx *ctx = kcrtc->hw_ctx; |
|---|
| 187 | 146 | |
|---|
| 188 | 147 | adjusted_mode->clock = |
|---|
| 189 | 148 | clk_round_rate(ctx->ade_pix_clk, mode->clock * 1000) / 1000; |
|---|
| .. | .. |
|---|
| 208 | 167 | adj_mode->clock = clk_get_rate(ctx->ade_pix_clk) / 1000; |
|---|
| 209 | 168 | } |
|---|
| 210 | 169 | |
|---|
| 211 | | -static void ade_ldi_set_mode(struct ade_crtc *acrtc, |
|---|
| 170 | +static void ade_ldi_set_mode(struct ade_hw_ctx *ctx, |
|---|
| 212 | 171 | struct drm_display_mode *mode, |
|---|
| 213 | 172 | struct drm_display_mode *adj_mode) |
|---|
| 214 | 173 | { |
|---|
| 215 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 216 | 174 | void __iomem *base = ctx->base; |
|---|
| 217 | 175 | u32 width = mode->hdisplay; |
|---|
| 218 | 176 | u32 height = mode->vdisplay; |
|---|
| .. | .. |
|---|
| 299 | 257 | ctx->power_on = false; |
|---|
| 300 | 258 | } |
|---|
| 301 | 259 | |
|---|
| 302 | | -static void ade_set_medianoc_qos(struct ade_crtc *acrtc) |
|---|
| 260 | +static void ade_set_medianoc_qos(struct ade_hw_ctx *ctx) |
|---|
| 303 | 261 | { |
|---|
| 304 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 305 | 262 | struct regmap *map = ctx->noc_regmap; |
|---|
| 306 | 263 | |
|---|
| 307 | 264 | regmap_update_bits(map, ADE0_QOSGENERATOR_MODE, |
|---|
| .. | .. |
|---|
| 317 | 274 | |
|---|
| 318 | 275 | static int ade_crtc_enable_vblank(struct drm_crtc *crtc) |
|---|
| 319 | 276 | { |
|---|
| 320 | | - struct ade_crtc *acrtc = to_ade_crtc(crtc); |
|---|
| 321 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 277 | + struct kirin_crtc *kcrtc = to_kirin_crtc(crtc); |
|---|
| 278 | + struct ade_hw_ctx *ctx = kcrtc->hw_ctx; |
|---|
| 322 | 279 | void __iomem *base = ctx->base; |
|---|
| 323 | 280 | |
|---|
| 324 | 281 | if (!ctx->power_on) |
|---|
| .. | .. |
|---|
| 332 | 289 | |
|---|
| 333 | 290 | static void ade_crtc_disable_vblank(struct drm_crtc *crtc) |
|---|
| 334 | 291 | { |
|---|
| 335 | | - struct ade_crtc *acrtc = to_ade_crtc(crtc); |
|---|
| 336 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 292 | + struct kirin_crtc *kcrtc = to_kirin_crtc(crtc); |
|---|
| 293 | + struct ade_hw_ctx *ctx = kcrtc->hw_ctx; |
|---|
| 337 | 294 | void __iomem *base = ctx->base; |
|---|
| 338 | 295 | |
|---|
| 339 | 296 | if (!ctx->power_on) { |
|---|
| .. | .. |
|---|
| 347 | 304 | |
|---|
| 348 | 305 | static irqreturn_t ade_irq_handler(int irq, void *data) |
|---|
| 349 | 306 | { |
|---|
| 350 | | - struct ade_crtc *acrtc = data; |
|---|
| 351 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 352 | | - struct drm_crtc *crtc = &acrtc->base; |
|---|
| 307 | + struct ade_hw_ctx *ctx = data; |
|---|
| 308 | + struct drm_crtc *crtc = ctx->crtc; |
|---|
| 353 | 309 | void __iomem *base = ctx->base; |
|---|
| 354 | 310 | u32 status; |
|---|
| 355 | 311 | |
|---|
| .. | .. |
|---|
| 366 | 322 | return IRQ_HANDLED; |
|---|
| 367 | 323 | } |
|---|
| 368 | 324 | |
|---|
| 369 | | -static void ade_display_enable(struct ade_crtc *acrtc) |
|---|
| 325 | +static void ade_display_enable(struct ade_hw_ctx *ctx) |
|---|
| 370 | 326 | { |
|---|
| 371 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 372 | 327 | void __iomem *base = ctx->base; |
|---|
| 373 | | - u32 out_fmt = acrtc->out_format; |
|---|
| 328 | + u32 out_fmt = LDI_OUT_RGB_888; |
|---|
| 374 | 329 | |
|---|
| 375 | 330 | /* enable output overlay compositor */ |
|---|
| 376 | 331 | writel(ADE_ENABLE, base + ADE_OVLYX_CTL(OUT_OVLY)); |
|---|
| .. | .. |
|---|
| 483 | 438 | static void ade_crtc_atomic_enable(struct drm_crtc *crtc, |
|---|
| 484 | 439 | struct drm_crtc_state *old_state) |
|---|
| 485 | 440 | { |
|---|
| 486 | | - struct ade_crtc *acrtc = to_ade_crtc(crtc); |
|---|
| 487 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 441 | + struct kirin_crtc *kcrtc = to_kirin_crtc(crtc); |
|---|
| 442 | + struct ade_hw_ctx *ctx = kcrtc->hw_ctx; |
|---|
| 488 | 443 | int ret; |
|---|
| 489 | 444 | |
|---|
| 490 | | - if (acrtc->enable) |
|---|
| 445 | + if (kcrtc->enable) |
|---|
| 491 | 446 | return; |
|---|
| 492 | 447 | |
|---|
| 493 | 448 | if (!ctx->power_on) { |
|---|
| .. | .. |
|---|
| 496 | 451 | return; |
|---|
| 497 | 452 | } |
|---|
| 498 | 453 | |
|---|
| 499 | | - ade_set_medianoc_qos(acrtc); |
|---|
| 500 | | - ade_display_enable(acrtc); |
|---|
| 454 | + ade_set_medianoc_qos(ctx); |
|---|
| 455 | + ade_display_enable(ctx); |
|---|
| 501 | 456 | ade_dump_regs(ctx->base); |
|---|
| 502 | 457 | drm_crtc_vblank_on(crtc); |
|---|
| 503 | | - acrtc->enable = true; |
|---|
| 458 | + kcrtc->enable = true; |
|---|
| 504 | 459 | } |
|---|
| 505 | 460 | |
|---|
| 506 | 461 | static void ade_crtc_atomic_disable(struct drm_crtc *crtc, |
|---|
| 507 | 462 | struct drm_crtc_state *old_state) |
|---|
| 508 | 463 | { |
|---|
| 509 | | - struct ade_crtc *acrtc = to_ade_crtc(crtc); |
|---|
| 510 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 464 | + struct kirin_crtc *kcrtc = to_kirin_crtc(crtc); |
|---|
| 465 | + struct ade_hw_ctx *ctx = kcrtc->hw_ctx; |
|---|
| 511 | 466 | |
|---|
| 512 | | - if (!acrtc->enable) |
|---|
| 467 | + if (!kcrtc->enable) |
|---|
| 513 | 468 | return; |
|---|
| 514 | 469 | |
|---|
| 515 | 470 | drm_crtc_vblank_off(crtc); |
|---|
| 516 | 471 | ade_power_down(ctx); |
|---|
| 517 | | - acrtc->enable = false; |
|---|
| 472 | + kcrtc->enable = false; |
|---|
| 518 | 473 | } |
|---|
| 519 | 474 | |
|---|
| 520 | 475 | static void ade_crtc_mode_set_nofb(struct drm_crtc *crtc) |
|---|
| 521 | 476 | { |
|---|
| 522 | | - struct ade_crtc *acrtc = to_ade_crtc(crtc); |
|---|
| 523 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 477 | + struct kirin_crtc *kcrtc = to_kirin_crtc(crtc); |
|---|
| 478 | + struct ade_hw_ctx *ctx = kcrtc->hw_ctx; |
|---|
| 524 | 479 | struct drm_display_mode *mode = &crtc->state->mode; |
|---|
| 525 | 480 | struct drm_display_mode *adj_mode = &crtc->state->adjusted_mode; |
|---|
| 526 | 481 | |
|---|
| 527 | 482 | if (!ctx->power_on) |
|---|
| 528 | 483 | (void)ade_power_up(ctx); |
|---|
| 529 | | - ade_ldi_set_mode(acrtc, mode, adj_mode); |
|---|
| 484 | + ade_ldi_set_mode(ctx, mode, adj_mode); |
|---|
| 530 | 485 | } |
|---|
| 531 | 486 | |
|---|
| 532 | 487 | static void ade_crtc_atomic_begin(struct drm_crtc *crtc, |
|---|
| 533 | 488 | struct drm_crtc_state *old_state) |
|---|
| 534 | 489 | { |
|---|
| 535 | | - struct ade_crtc *acrtc = to_ade_crtc(crtc); |
|---|
| 536 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 490 | + struct kirin_crtc *kcrtc = to_kirin_crtc(crtc); |
|---|
| 491 | + struct ade_hw_ctx *ctx = kcrtc->hw_ctx; |
|---|
| 537 | 492 | struct drm_display_mode *mode = &crtc->state->mode; |
|---|
| 538 | 493 | struct drm_display_mode *adj_mode = &crtc->state->adjusted_mode; |
|---|
| 539 | 494 | |
|---|
| 540 | 495 | if (!ctx->power_on) |
|---|
| 541 | 496 | (void)ade_power_up(ctx); |
|---|
| 542 | | - ade_ldi_set_mode(acrtc, mode, adj_mode); |
|---|
| 497 | + ade_ldi_set_mode(ctx, mode, adj_mode); |
|---|
| 543 | 498 | } |
|---|
| 544 | 499 | |
|---|
| 545 | 500 | static void ade_crtc_atomic_flush(struct drm_crtc *crtc, |
|---|
| 546 | 501 | struct drm_crtc_state *old_state) |
|---|
| 547 | 502 | |
|---|
| 548 | 503 | { |
|---|
| 549 | | - struct ade_crtc *acrtc = to_ade_crtc(crtc); |
|---|
| 550 | | - struct ade_hw_ctx *ctx = acrtc->ctx; |
|---|
| 504 | + struct kirin_crtc *kcrtc = to_kirin_crtc(crtc); |
|---|
| 505 | + struct ade_hw_ctx *ctx = kcrtc->hw_ctx; |
|---|
| 551 | 506 | struct drm_pending_vblank_event *event = crtc->state->event; |
|---|
| 552 | 507 | void __iomem *base = ctx->base; |
|---|
| 553 | 508 | |
|---|
| 554 | 509 | /* only crtc is enabled regs take effect */ |
|---|
| 555 | | - if (acrtc->enable) { |
|---|
| 510 | + if (kcrtc->enable) { |
|---|
| 556 | 511 | ade_dump_regs(base); |
|---|
| 557 | 512 | /* flush ade registers */ |
|---|
| 558 | 513 | writel(ADE_ENABLE, base + ADE_EN); |
|---|
| .. | .. |
|---|
| 589 | 544 | .enable_vblank = ade_crtc_enable_vblank, |
|---|
| 590 | 545 | .disable_vblank = ade_crtc_disable_vblank, |
|---|
| 591 | 546 | }; |
|---|
| 592 | | - |
|---|
| 593 | | -static int ade_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, |
|---|
| 594 | | - struct drm_plane *plane) |
|---|
| 595 | | -{ |
|---|
| 596 | | - struct device_node *port; |
|---|
| 597 | | - int ret; |
|---|
| 598 | | - |
|---|
| 599 | | - /* set crtc port so that |
|---|
| 600 | | - * drm_of_find_possible_crtcs call works |
|---|
| 601 | | - */ |
|---|
| 602 | | - port = of_get_child_by_name(dev->dev->of_node, "port"); |
|---|
| 603 | | - if (!port) { |
|---|
| 604 | | - DRM_ERROR("no port node found in %pOF\n", dev->dev->of_node); |
|---|
| 605 | | - return -EINVAL; |
|---|
| 606 | | - } |
|---|
| 607 | | - of_node_put(port); |
|---|
| 608 | | - crtc->port = port; |
|---|
| 609 | | - |
|---|
| 610 | | - ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, |
|---|
| 611 | | - &ade_crtc_funcs, NULL); |
|---|
| 612 | | - if (ret) { |
|---|
| 613 | | - DRM_ERROR("failed to init crtc.\n"); |
|---|
| 614 | | - return ret; |
|---|
| 615 | | - } |
|---|
| 616 | | - |
|---|
| 617 | | - drm_crtc_helper_add(crtc, &ade_crtc_helper_funcs); |
|---|
| 618 | | - |
|---|
| 619 | | - return 0; |
|---|
| 620 | | -} |
|---|
| 621 | 547 | |
|---|
| 622 | 548 | static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb, |
|---|
| 623 | 549 | u32 ch, u32 y, u32 in_h, u32 fmt) |
|---|
| .. | .. |
|---|
| 780 | 706 | /* |
|---|
| 781 | 707 | * Typicaly, a channel looks like: DMA-->clip-->scale-->ctrans-->compositor |
|---|
| 782 | 708 | */ |
|---|
| 783 | | -static void ade_update_channel(struct ade_plane *aplane, |
|---|
| 709 | +static void ade_update_channel(struct kirin_plane *kplane, |
|---|
| 784 | 710 | struct drm_framebuffer *fb, int crtc_x, |
|---|
| 785 | 711 | int crtc_y, unsigned int crtc_w, |
|---|
| 786 | 712 | unsigned int crtc_h, u32 src_x, |
|---|
| 787 | 713 | u32 src_y, u32 src_w, u32 src_h) |
|---|
| 788 | 714 | { |
|---|
| 789 | | - struct ade_hw_ctx *ctx = aplane->ctx; |
|---|
| 715 | + struct ade_hw_ctx *ctx = kplane->hw_ctx; |
|---|
| 790 | 716 | void __iomem *base = ctx->base; |
|---|
| 791 | 717 | u32 fmt = ade_get_format(fb->format->format); |
|---|
| 792 | | - u32 ch = aplane->ch; |
|---|
| 718 | + u32 ch = kplane->ch; |
|---|
| 793 | 719 | u32 in_w; |
|---|
| 794 | 720 | u32 in_h; |
|---|
| 795 | 721 | |
|---|
| .. | .. |
|---|
| 813 | 739 | ade_compositor_routing_set(base, ch, crtc_x, crtc_y, in_w, in_h, fmt); |
|---|
| 814 | 740 | } |
|---|
| 815 | 741 | |
|---|
| 816 | | -static void ade_disable_channel(struct ade_plane *aplane) |
|---|
| 742 | +static void ade_disable_channel(struct kirin_plane *kplane) |
|---|
| 817 | 743 | { |
|---|
| 818 | | - struct ade_hw_ctx *ctx = aplane->ctx; |
|---|
| 744 | + struct ade_hw_ctx *ctx = kplane->hw_ctx; |
|---|
| 819 | 745 | void __iomem *base = ctx->base; |
|---|
| 820 | | - u32 ch = aplane->ch; |
|---|
| 746 | + u32 ch = kplane->ch; |
|---|
| 821 | 747 | |
|---|
| 822 | 748 | DRM_DEBUG_DRIVER("disable channel%d\n", ch + 1); |
|---|
| 823 | 749 | |
|---|
| .. | .. |
|---|
| 879 | 805 | static void ade_plane_atomic_update(struct drm_plane *plane, |
|---|
| 880 | 806 | struct drm_plane_state *old_state) |
|---|
| 881 | 807 | { |
|---|
| 882 | | - struct drm_plane_state *state = plane->state; |
|---|
| 883 | | - struct ade_plane *aplane = to_ade_plane(plane); |
|---|
| 808 | + struct drm_plane_state *state = plane->state; |
|---|
| 809 | + struct kirin_plane *kplane = to_kirin_plane(plane); |
|---|
| 884 | 810 | |
|---|
| 885 | | - ade_update_channel(aplane, state->fb, state->crtc_x, state->crtc_y, |
|---|
| 811 | + ade_update_channel(kplane, state->fb, state->crtc_x, state->crtc_y, |
|---|
| 886 | 812 | state->crtc_w, state->crtc_h, |
|---|
| 887 | 813 | state->src_x >> 16, state->src_y >> 16, |
|---|
| 888 | 814 | state->src_w >> 16, state->src_h >> 16); |
|---|
| .. | .. |
|---|
| 891 | 817 | static void ade_plane_atomic_disable(struct drm_plane *plane, |
|---|
| 892 | 818 | struct drm_plane_state *old_state) |
|---|
| 893 | 819 | { |
|---|
| 894 | | - struct ade_plane *aplane = to_ade_plane(plane); |
|---|
| 820 | + struct kirin_plane *kplane = to_kirin_plane(plane); |
|---|
| 895 | 821 | |
|---|
| 896 | | - ade_disable_channel(aplane); |
|---|
| 822 | + ade_disable_channel(kplane); |
|---|
| 897 | 823 | } |
|---|
| 898 | 824 | |
|---|
| 899 | 825 | static const struct drm_plane_helper_funcs ade_plane_helper_funcs = { |
|---|
| .. | .. |
|---|
| 911 | 837 | .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, |
|---|
| 912 | 838 | }; |
|---|
| 913 | 839 | |
|---|
| 914 | | -static int ade_plane_init(struct drm_device *dev, struct ade_plane *aplane, |
|---|
| 915 | | - enum drm_plane_type type) |
|---|
| 916 | | -{ |
|---|
| 917 | | - const u32 *fmts; |
|---|
| 918 | | - u32 fmts_cnt; |
|---|
| 919 | | - int ret = 0; |
|---|
| 920 | | - |
|---|
| 921 | | - /* get properties */ |
|---|
| 922 | | - fmts_cnt = ade_get_channel_formats(aplane->ch, &fmts); |
|---|
| 923 | | - if (ret) |
|---|
| 924 | | - return ret; |
|---|
| 925 | | - |
|---|
| 926 | | - ret = drm_universal_plane_init(dev, &aplane->base, 1, &ade_plane_funcs, |
|---|
| 927 | | - fmts, fmts_cnt, NULL, type, NULL); |
|---|
| 928 | | - if (ret) { |
|---|
| 929 | | - DRM_ERROR("fail to init plane, ch=%d\n", aplane->ch); |
|---|
| 930 | | - return ret; |
|---|
| 931 | | - } |
|---|
| 932 | | - |
|---|
| 933 | | - drm_plane_helper_add(&aplane->base, &ade_plane_helper_funcs); |
|---|
| 934 | | - |
|---|
| 935 | | - return 0; |
|---|
| 936 | | -} |
|---|
| 937 | | - |
|---|
| 938 | | -static int ade_dts_parse(struct platform_device *pdev, struct ade_hw_ctx *ctx) |
|---|
| 840 | +static void *ade_hw_ctx_alloc(struct platform_device *pdev, |
|---|
| 841 | + struct drm_crtc *crtc) |
|---|
| 939 | 842 | { |
|---|
| 940 | 843 | struct resource *res; |
|---|
| 941 | 844 | struct device *dev = &pdev->dev; |
|---|
| 942 | 845 | struct device_node *np = pdev->dev.of_node; |
|---|
| 846 | + struct ade_hw_ctx *ctx = NULL; |
|---|
| 847 | + int ret; |
|---|
| 848 | + |
|---|
| 849 | + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); |
|---|
| 850 | + if (!ctx) { |
|---|
| 851 | + DRM_ERROR("failed to alloc ade_hw_ctx\n"); |
|---|
| 852 | + return ERR_PTR(-ENOMEM); |
|---|
| 853 | + } |
|---|
| 943 | 854 | |
|---|
| 944 | 855 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 945 | 856 | ctx->base = devm_ioremap_resource(dev, res); |
|---|
| 946 | 857 | if (IS_ERR(ctx->base)) { |
|---|
| 947 | 858 | DRM_ERROR("failed to remap ade io base\n"); |
|---|
| 948 | | - return PTR_ERR(ctx->base); |
|---|
| 859 | + return ERR_PTR(-EIO); |
|---|
| 949 | 860 | } |
|---|
| 950 | 861 | |
|---|
| 951 | 862 | ctx->reset = devm_reset_control_get(dev, NULL); |
|---|
| 952 | 863 | if (IS_ERR(ctx->reset)) |
|---|
| 953 | | - return PTR_ERR(ctx->reset); |
|---|
| 864 | + return ERR_PTR(-ENODEV); |
|---|
| 954 | 865 | |
|---|
| 955 | 866 | ctx->noc_regmap = |
|---|
| 956 | 867 | syscon_regmap_lookup_by_phandle(np, "hisilicon,noc-syscon"); |
|---|
| 957 | 868 | if (IS_ERR(ctx->noc_regmap)) { |
|---|
| 958 | 869 | DRM_ERROR("failed to get noc regmap\n"); |
|---|
| 959 | | - return PTR_ERR(ctx->noc_regmap); |
|---|
| 870 | + return ERR_PTR(-ENODEV); |
|---|
| 960 | 871 | } |
|---|
| 961 | 872 | |
|---|
| 962 | 873 | ctx->irq = platform_get_irq(pdev, 0); |
|---|
| 963 | 874 | if (ctx->irq < 0) { |
|---|
| 964 | 875 | DRM_ERROR("failed to get irq\n"); |
|---|
| 965 | | - return -ENODEV; |
|---|
| 876 | + return ERR_PTR(-ENODEV); |
|---|
| 966 | 877 | } |
|---|
| 967 | 878 | |
|---|
| 968 | 879 | ctx->ade_core_clk = devm_clk_get(dev, "clk_ade_core"); |
|---|
| 969 | 880 | if (IS_ERR(ctx->ade_core_clk)) { |
|---|
| 970 | 881 | DRM_ERROR("failed to parse clk ADE_CORE\n"); |
|---|
| 971 | | - return PTR_ERR(ctx->ade_core_clk); |
|---|
| 882 | + return ERR_PTR(-ENODEV); |
|---|
| 972 | 883 | } |
|---|
| 973 | 884 | |
|---|
| 974 | 885 | ctx->media_noc_clk = devm_clk_get(dev, "clk_codec_jpeg"); |
|---|
| 975 | 886 | if (IS_ERR(ctx->media_noc_clk)) { |
|---|
| 976 | 887 | DRM_ERROR("failed to parse clk CODEC_JPEG\n"); |
|---|
| 977 | | - return PTR_ERR(ctx->media_noc_clk); |
|---|
| 888 | + return ERR_PTR(-ENODEV); |
|---|
| 978 | 889 | } |
|---|
| 979 | 890 | |
|---|
| 980 | 891 | ctx->ade_pix_clk = devm_clk_get(dev, "clk_ade_pix"); |
|---|
| 981 | 892 | if (IS_ERR(ctx->ade_pix_clk)) { |
|---|
| 982 | 893 | DRM_ERROR("failed to parse clk ADE_PIX\n"); |
|---|
| 983 | | - return PTR_ERR(ctx->ade_pix_clk); |
|---|
| 894 | + return ERR_PTR(-ENODEV); |
|---|
| 984 | 895 | } |
|---|
| 985 | | - |
|---|
| 986 | | - return 0; |
|---|
| 987 | | -} |
|---|
| 988 | | - |
|---|
| 989 | | -static int ade_drm_init(struct platform_device *pdev) |
|---|
| 990 | | -{ |
|---|
| 991 | | - struct drm_device *dev = platform_get_drvdata(pdev); |
|---|
| 992 | | - struct ade_data *ade; |
|---|
| 993 | | - struct ade_hw_ctx *ctx; |
|---|
| 994 | | - struct ade_crtc *acrtc; |
|---|
| 995 | | - struct ade_plane *aplane; |
|---|
| 996 | | - enum drm_plane_type type; |
|---|
| 997 | | - int ret; |
|---|
| 998 | | - int i; |
|---|
| 999 | | - |
|---|
| 1000 | | - ade = devm_kzalloc(dev->dev, sizeof(*ade), GFP_KERNEL); |
|---|
| 1001 | | - if (!ade) { |
|---|
| 1002 | | - DRM_ERROR("failed to alloc ade_data\n"); |
|---|
| 1003 | | - return -ENOMEM; |
|---|
| 1004 | | - } |
|---|
| 1005 | | - platform_set_drvdata(pdev, ade); |
|---|
| 1006 | | - |
|---|
| 1007 | | - ctx = &ade->ctx; |
|---|
| 1008 | | - acrtc = &ade->acrtc; |
|---|
| 1009 | | - acrtc->ctx = ctx; |
|---|
| 1010 | | - acrtc->out_format = LDI_OUT_RGB_888; |
|---|
| 1011 | | - |
|---|
| 1012 | | - ret = ade_dts_parse(pdev, ctx); |
|---|
| 1013 | | - if (ret) |
|---|
| 1014 | | - return ret; |
|---|
| 1015 | | - |
|---|
| 1016 | | - /* |
|---|
| 1017 | | - * plane init |
|---|
| 1018 | | - * TODO: Now only support primary plane, overlay planes |
|---|
| 1019 | | - * need to do. |
|---|
| 1020 | | - */ |
|---|
| 1021 | | - for (i = 0; i < ADE_CH_NUM; i++) { |
|---|
| 1022 | | - aplane = &ade->aplane[i]; |
|---|
| 1023 | | - aplane->ch = i; |
|---|
| 1024 | | - aplane->ctx = ctx; |
|---|
| 1025 | | - type = i == PRIMARY_CH ? DRM_PLANE_TYPE_PRIMARY : |
|---|
| 1026 | | - DRM_PLANE_TYPE_OVERLAY; |
|---|
| 1027 | | - |
|---|
| 1028 | | - ret = ade_plane_init(dev, aplane, type); |
|---|
| 1029 | | - if (ret) |
|---|
| 1030 | | - return ret; |
|---|
| 1031 | | - } |
|---|
| 1032 | | - |
|---|
| 1033 | | - /* crtc init */ |
|---|
| 1034 | | - ret = ade_crtc_init(dev, &acrtc->base, &ade->aplane[PRIMARY_CH].base); |
|---|
| 1035 | | - if (ret) |
|---|
| 1036 | | - return ret; |
|---|
| 1037 | 896 | |
|---|
| 1038 | 897 | /* vblank irq init */ |
|---|
| 1039 | | - ret = devm_request_irq(dev->dev, ctx->irq, ade_irq_handler, |
|---|
| 1040 | | - IRQF_SHARED, dev->driver->name, acrtc); |
|---|
| 898 | + ret = devm_request_irq(dev, ctx->irq, ade_irq_handler, |
|---|
| 899 | + IRQF_SHARED, dev->driver->name, ctx); |
|---|
| 1041 | 900 | if (ret) |
|---|
| 1042 | | - return ret; |
|---|
| 901 | + return ERR_PTR(-EIO); |
|---|
| 1043 | 902 | |
|---|
| 1044 | | - return 0; |
|---|
| 903 | + ctx->crtc = crtc; |
|---|
| 904 | + |
|---|
| 905 | + return ctx; |
|---|
| 1045 | 906 | } |
|---|
| 1046 | 907 | |
|---|
| 1047 | | -static void ade_drm_cleanup(struct platform_device *pdev) |
|---|
| 908 | +static void ade_hw_ctx_cleanup(void *hw_ctx) |
|---|
| 1048 | 909 | { |
|---|
| 1049 | 910 | } |
|---|
| 1050 | 911 | |
|---|
| 1051 | | -const struct kirin_dc_ops ade_dc_ops = { |
|---|
| 1052 | | - .init = ade_drm_init, |
|---|
| 1053 | | - .cleanup = ade_drm_cleanup |
|---|
| 912 | +static const struct drm_mode_config_funcs ade_mode_config_funcs = { |
|---|
| 913 | + .fb_create = drm_gem_fb_create, |
|---|
| 914 | + .atomic_check = drm_atomic_helper_check, |
|---|
| 915 | + .atomic_commit = drm_atomic_helper_commit, |
|---|
| 916 | + |
|---|
| 917 | +}; |
|---|
| 918 | + |
|---|
| 919 | +DEFINE_DRM_GEM_CMA_FOPS(ade_fops); |
|---|
| 920 | + |
|---|
| 921 | +static struct drm_driver ade_driver = { |
|---|
| 922 | + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, |
|---|
| 923 | + .fops = &ade_fops, |
|---|
| 924 | + DRM_GEM_CMA_DRIVER_OPS, |
|---|
| 925 | + .name = "kirin", |
|---|
| 926 | + .desc = "Hisilicon Kirin620 SoC DRM Driver", |
|---|
| 927 | + .date = "20150718", |
|---|
| 928 | + .major = 1, |
|---|
| 929 | + .minor = 0, |
|---|
| 930 | +}; |
|---|
| 931 | + |
|---|
| 932 | +struct kirin_drm_data ade_driver_data = { |
|---|
| 933 | + .num_planes = ADE_CH_NUM, |
|---|
| 934 | + .prim_plane = ADE_CH1, |
|---|
| 935 | + .channel_formats = channel_formats, |
|---|
| 936 | + .channel_formats_cnt = ARRAY_SIZE(channel_formats), |
|---|
| 937 | + .config_max_width = 2048, |
|---|
| 938 | + .config_max_height = 2048, |
|---|
| 939 | + .driver = &ade_driver, |
|---|
| 940 | + .crtc_helper_funcs = &ade_crtc_helper_funcs, |
|---|
| 941 | + .crtc_funcs = &ade_crtc_funcs, |
|---|
| 942 | + .plane_helper_funcs = &ade_plane_helper_funcs, |
|---|
| 943 | + .plane_funcs = &ade_plane_funcs, |
|---|
| 944 | + .mode_config_funcs = &ade_mode_config_funcs, |
|---|
| 945 | + |
|---|
| 946 | + .alloc_hw_ctx = ade_hw_ctx_alloc, |
|---|
| 947 | + .cleanup_hw_ctx = ade_hw_ctx_cleanup, |
|---|
| 1054 | 948 | }; |
|---|