880 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2020 Unisoc Inc.4 */5 6#include <linux/component.h>7#include <linux/delay.h>8#include <linux/dma-buf.h>9#include <linux/io.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/of_graph.h>13#include <linux/platform_device.h>14#include <linux/wait.h>15#include <linux/workqueue.h>16 17#include <drm/drm_atomic_helper.h>18#include <drm/drm_blend.h>19#include <drm/drm_fb_dma_helper.h>20#include <drm/drm_framebuffer.h>21#include <drm/drm_gem_dma_helper.h>22#include <drm/drm_gem_framebuffer_helper.h>23 24#include "sprd_drm.h"25#include "sprd_dpu.h"26#include "sprd_dsi.h"27 28/* Global control registers */29#define REG_DPU_CTRL 0x0430#define REG_DPU_CFG0 0x0831#define REG_PANEL_SIZE 0x2032#define REG_BLEND_SIZE 0x2433#define REG_BG_COLOR 0x2C34 35/* Layer0 control registers */36#define REG_LAY_BASE_ADDR0 0x3037#define REG_LAY_BASE_ADDR1 0x3438#define REG_LAY_BASE_ADDR2 0x3839#define REG_LAY_CTRL 0x4040#define REG_LAY_SIZE 0x4441#define REG_LAY_PITCH 0x4842#define REG_LAY_POS 0x4C43#define REG_LAY_ALPHA 0x5044#define REG_LAY_CROP_START 0x5C45 46/* Interrupt control registers */47#define REG_DPU_INT_EN 0x1E048#define REG_DPU_INT_CLR 0x1E449#define REG_DPU_INT_STS 0x1E850 51/* DPI control registers */52#define REG_DPI_CTRL 0x1F053#define REG_DPI_H_TIMING 0x1F454#define REG_DPI_V_TIMING 0x1F855 56/* MMU control registers */57#define REG_MMU_EN 0x80058#define REG_MMU_VPN_RANGE 0x80C59#define REG_MMU_PPN1 0x83C60#define REG_MMU_RANGE1 0x84061#define REG_MMU_PPN2 0x84462#define REG_MMU_RANGE2 0x84863 64/* Global control bits */65#define BIT_DPU_RUN BIT(0)66#define BIT_DPU_STOP BIT(1)67#define BIT_DPU_REG_UPDATE BIT(2)68#define BIT_DPU_IF_EDPI BIT(0)69 70/* Layer control bits */71#define BIT_DPU_LAY_EN BIT(0)72#define BIT_DPU_LAY_LAYER_ALPHA (0x01 << 2)73#define BIT_DPU_LAY_COMBO_ALPHA (0x02 << 2)74#define BIT_DPU_LAY_FORMAT_YUV422_2PLANE (0x00 << 4)75#define BIT_DPU_LAY_FORMAT_YUV420_2PLANE (0x01 << 4)76#define BIT_DPU_LAY_FORMAT_YUV420_3PLANE (0x02 << 4)77#define BIT_DPU_LAY_FORMAT_ARGB8888 (0x03 << 4)78#define BIT_DPU_LAY_FORMAT_RGB565 (0x04 << 4)79#define BIT_DPU_LAY_DATA_ENDIAN_B0B1B2B3 (0x00 << 8)80#define BIT_DPU_LAY_DATA_ENDIAN_B3B2B1B0 (0x01 << 8)81#define BIT_DPU_LAY_NO_SWITCH (0x00 << 10)82#define BIT_DPU_LAY_RB_OR_UV_SWITCH (0x01 << 10)83#define BIT_DPU_LAY_MODE_BLEND_NORMAL (0x00 << 16)84#define BIT_DPU_LAY_MODE_BLEND_PREMULT (0x01 << 16)85#define BIT_DPU_LAY_ROTATION_0 (0x00 << 20)86#define BIT_DPU_LAY_ROTATION_90 (0x01 << 20)87#define BIT_DPU_LAY_ROTATION_180 (0x02 << 20)88#define BIT_DPU_LAY_ROTATION_270 (0x03 << 20)89#define BIT_DPU_LAY_ROTATION_0_M (0x04 << 20)90#define BIT_DPU_LAY_ROTATION_90_M (0x05 << 20)91#define BIT_DPU_LAY_ROTATION_180_M (0x06 << 20)92#define BIT_DPU_LAY_ROTATION_270_M (0x07 << 20)93 94/* Interrupt control & status bits */95#define BIT_DPU_INT_DONE BIT(0)96#define BIT_DPU_INT_TE BIT(1)97#define BIT_DPU_INT_ERR BIT(2)98#define BIT_DPU_INT_UPDATE_DONE BIT(4)99#define BIT_DPU_INT_VSYNC BIT(5)100 101/* DPI control bits */102#define BIT_DPU_EDPI_TE_EN BIT(8)103#define BIT_DPU_EDPI_FROM_EXTERNAL_PAD BIT(10)104#define BIT_DPU_DPI_HALT_EN BIT(16)105 106static const u32 layer_fmts[] = {107 DRM_FORMAT_XRGB8888,108 DRM_FORMAT_XBGR8888,109 DRM_FORMAT_ARGB8888,110 DRM_FORMAT_ABGR8888,111 DRM_FORMAT_RGBA8888,112 DRM_FORMAT_BGRA8888,113 DRM_FORMAT_RGBX8888,114 DRM_FORMAT_RGB565,115 DRM_FORMAT_BGR565,116 DRM_FORMAT_NV12,117 DRM_FORMAT_NV21,118 DRM_FORMAT_NV16,119 DRM_FORMAT_NV61,120 DRM_FORMAT_YUV420,121 DRM_FORMAT_YVU420,122};123 124struct sprd_plane {125 struct drm_plane base;126};127 128static int dpu_wait_stop_done(struct sprd_dpu *dpu)129{130 struct dpu_context *ctx = &dpu->ctx;131 int rc;132 133 if (ctx->stopped)134 return 0;135 136 rc = wait_event_interruptible_timeout(ctx->wait_queue, ctx->evt_stop,137 msecs_to_jiffies(500));138 ctx->evt_stop = false;139 140 ctx->stopped = true;141 142 if (!rc) {143 drm_err(dpu->drm, "dpu wait for stop done time out!\n");144 return -ETIMEDOUT;145 }146 147 return 0;148}149 150static int dpu_wait_update_done(struct sprd_dpu *dpu)151{152 struct dpu_context *ctx = &dpu->ctx;153 int rc;154 155 ctx->evt_update = false;156 157 rc = wait_event_interruptible_timeout(ctx->wait_queue, ctx->evt_update,158 msecs_to_jiffies(500));159 160 if (!rc) {161 drm_err(dpu->drm, "dpu wait for reg update done time out!\n");162 return -ETIMEDOUT;163 }164 165 return 0;166}167 168static u32 drm_format_to_dpu(struct drm_framebuffer *fb)169{170 u32 format = 0;171 172 switch (fb->format->format) {173 case DRM_FORMAT_BGRA8888:174 /* BGRA8888 -> ARGB8888 */175 format |= BIT_DPU_LAY_DATA_ENDIAN_B3B2B1B0;176 format |= BIT_DPU_LAY_FORMAT_ARGB8888;177 break;178 case DRM_FORMAT_RGBX8888:179 case DRM_FORMAT_RGBA8888:180 /* RGBA8888 -> ABGR8888 */181 format |= BIT_DPU_LAY_DATA_ENDIAN_B3B2B1B0;182 fallthrough;183 case DRM_FORMAT_ABGR8888:184 /* RB switch */185 format |= BIT_DPU_LAY_RB_OR_UV_SWITCH;186 fallthrough;187 case DRM_FORMAT_ARGB8888:188 format |= BIT_DPU_LAY_FORMAT_ARGB8888;189 break;190 case DRM_FORMAT_XBGR8888:191 /* RB switch */192 format |= BIT_DPU_LAY_RB_OR_UV_SWITCH;193 fallthrough;194 case DRM_FORMAT_XRGB8888:195 format |= BIT_DPU_LAY_FORMAT_ARGB8888;196 break;197 case DRM_FORMAT_BGR565:198 /* RB switch */199 format |= BIT_DPU_LAY_RB_OR_UV_SWITCH;200 fallthrough;201 case DRM_FORMAT_RGB565:202 format |= BIT_DPU_LAY_FORMAT_RGB565;203 break;204 case DRM_FORMAT_NV12:205 /* 2-Lane: Yuv420 */206 format |= BIT_DPU_LAY_FORMAT_YUV420_2PLANE;207 /* Y endian */208 format |= BIT_DPU_LAY_DATA_ENDIAN_B0B1B2B3;209 /* UV endian */210 format |= BIT_DPU_LAY_NO_SWITCH;211 break;212 case DRM_FORMAT_NV21:213 /* 2-Lane: Yuv420 */214 format |= BIT_DPU_LAY_FORMAT_YUV420_2PLANE;215 /* Y endian */216 format |= BIT_DPU_LAY_DATA_ENDIAN_B0B1B2B3;217 /* UV endian */218 format |= BIT_DPU_LAY_RB_OR_UV_SWITCH;219 break;220 case DRM_FORMAT_NV16:221 /* 2-Lane: Yuv422 */222 format |= BIT_DPU_LAY_FORMAT_YUV422_2PLANE;223 /* Y endian */224 format |= BIT_DPU_LAY_DATA_ENDIAN_B3B2B1B0;225 /* UV endian */226 format |= BIT_DPU_LAY_RB_OR_UV_SWITCH;227 break;228 case DRM_FORMAT_NV61:229 /* 2-Lane: Yuv422 */230 format |= BIT_DPU_LAY_FORMAT_YUV422_2PLANE;231 /* Y endian */232 format |= BIT_DPU_LAY_DATA_ENDIAN_B0B1B2B3;233 /* UV endian */234 format |= BIT_DPU_LAY_NO_SWITCH;235 break;236 case DRM_FORMAT_YUV420:237 format |= BIT_DPU_LAY_FORMAT_YUV420_3PLANE;238 /* Y endian */239 format |= BIT_DPU_LAY_DATA_ENDIAN_B0B1B2B3;240 /* UV endian */241 format |= BIT_DPU_LAY_NO_SWITCH;242 break;243 case DRM_FORMAT_YVU420:244 format |= BIT_DPU_LAY_FORMAT_YUV420_3PLANE;245 /* Y endian */246 format |= BIT_DPU_LAY_DATA_ENDIAN_B0B1B2B3;247 /* UV endian */248 format |= BIT_DPU_LAY_RB_OR_UV_SWITCH;249 break;250 default:251 break;252 }253 254 return format;255}256 257static u32 drm_rotation_to_dpu(struct drm_plane_state *state)258{259 u32 rotation = 0;260 261 switch (state->rotation) {262 default:263 case DRM_MODE_ROTATE_0:264 rotation = BIT_DPU_LAY_ROTATION_0;265 break;266 case DRM_MODE_ROTATE_90:267 rotation = BIT_DPU_LAY_ROTATION_90;268 break;269 case DRM_MODE_ROTATE_180:270 rotation = BIT_DPU_LAY_ROTATION_180;271 break;272 case DRM_MODE_ROTATE_270:273 rotation = BIT_DPU_LAY_ROTATION_270;274 break;275 case DRM_MODE_REFLECT_Y:276 rotation = BIT_DPU_LAY_ROTATION_180_M;277 break;278 case (DRM_MODE_REFLECT_Y | DRM_MODE_ROTATE_90):279 rotation = BIT_DPU_LAY_ROTATION_90_M;280 break;281 case DRM_MODE_REFLECT_X:282 rotation = BIT_DPU_LAY_ROTATION_0_M;283 break;284 case (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90):285 rotation = BIT_DPU_LAY_ROTATION_270_M;286 break;287 }288 289 return rotation;290}291 292static u32 drm_blend_to_dpu(struct drm_plane_state *state)293{294 u32 blend = 0;295 296 switch (state->pixel_blend_mode) {297 case DRM_MODE_BLEND_COVERAGE:298 /* alpha mode select - combo alpha */299 blend |= BIT_DPU_LAY_COMBO_ALPHA;300 /* Normal mode */301 blend |= BIT_DPU_LAY_MODE_BLEND_NORMAL;302 break;303 case DRM_MODE_BLEND_PREMULTI:304 /* alpha mode select - combo alpha */305 blend |= BIT_DPU_LAY_COMBO_ALPHA;306 /* Pre-mult mode */307 blend |= BIT_DPU_LAY_MODE_BLEND_PREMULT;308 break;309 case DRM_MODE_BLEND_PIXEL_NONE:310 default:311 /* don't do blending, maybe RGBX */312 /* alpha mode select - layer alpha */313 blend |= BIT_DPU_LAY_LAYER_ALPHA;314 break;315 }316 317 return blend;318}319 320static void sprd_dpu_layer(struct sprd_dpu *dpu, struct drm_plane_state *state)321{322 struct dpu_context *ctx = &dpu->ctx;323 struct drm_gem_dma_object *dma_obj;324 struct drm_framebuffer *fb = state->fb;325 u32 addr, size, offset, pitch, blend, format, rotation;326 u32 src_x = state->src_x >> 16;327 u32 src_y = state->src_y >> 16;328 u32 src_w = state->src_w >> 16;329 u32 src_h = state->src_h >> 16;330 u32 dst_x = state->crtc_x;331 u32 dst_y = state->crtc_y;332 u32 alpha = state->alpha;333 u32 index = state->zpos;334 int i;335 336 offset = (dst_x & 0xffff) | (dst_y << 16);337 size = (src_w & 0xffff) | (src_h << 16);338 339 for (i = 0; i < fb->format->num_planes; i++) {340 dma_obj = drm_fb_dma_get_gem_obj(fb, i);341 addr = dma_obj->dma_addr + fb->offsets[i];342 343 if (i == 0)344 layer_reg_wr(ctx, REG_LAY_BASE_ADDR0, addr, index);345 else if (i == 1)346 layer_reg_wr(ctx, REG_LAY_BASE_ADDR1, addr, index);347 else348 layer_reg_wr(ctx, REG_LAY_BASE_ADDR2, addr, index);349 }350 351 if (fb->format->num_planes == 3) {352 /* UV pitch is 1/2 of Y pitch */353 pitch = (fb->pitches[0] / fb->format->cpp[0]) |354 (fb->pitches[0] / fb->format->cpp[0] << 15);355 } else {356 pitch = fb->pitches[0] / fb->format->cpp[0];357 }358 359 layer_reg_wr(ctx, REG_LAY_POS, offset, index);360 layer_reg_wr(ctx, REG_LAY_SIZE, size, index);361 layer_reg_wr(ctx, REG_LAY_CROP_START,362 src_y << 16 | src_x, index);363 layer_reg_wr(ctx, REG_LAY_ALPHA, alpha, index);364 layer_reg_wr(ctx, REG_LAY_PITCH, pitch, index);365 366 format = drm_format_to_dpu(fb);367 blend = drm_blend_to_dpu(state);368 rotation = drm_rotation_to_dpu(state);369 370 layer_reg_wr(ctx, REG_LAY_CTRL, BIT_DPU_LAY_EN |371 format |372 blend |373 rotation,374 index);375}376 377static void sprd_dpu_flip(struct sprd_dpu *dpu)378{379 struct dpu_context *ctx = &dpu->ctx;380 381 /*382 * Make sure the dpu is in stop status. DPU has no shadow383 * registers in EDPI mode. So the config registers can only be384 * updated in the rising edge of DPU_RUN bit.385 */386 if (ctx->if_type == SPRD_DPU_IF_EDPI)387 dpu_wait_stop_done(dpu);388 389 /* update trigger and wait */390 if (ctx->if_type == SPRD_DPU_IF_DPI) {391 if (!ctx->stopped) {392 dpu_reg_set(ctx, REG_DPU_CTRL, BIT_DPU_REG_UPDATE);393 dpu_wait_update_done(dpu);394 }395 396 dpu_reg_set(ctx, REG_DPU_INT_EN, BIT_DPU_INT_ERR);397 } else if (ctx->if_type == SPRD_DPU_IF_EDPI) {398 dpu_reg_set(ctx, REG_DPU_CTRL, BIT_DPU_RUN);399 400 ctx->stopped = false;401 }402}403 404static void sprd_dpu_init(struct sprd_dpu *dpu)405{406 struct dpu_context *ctx = &dpu->ctx;407 u32 int_mask = 0;408 409 writel(0x00, ctx->base + REG_BG_COLOR);410 writel(0x00, ctx->base + REG_MMU_EN);411 writel(0x00, ctx->base + REG_MMU_PPN1);412 writel(0xffff, ctx->base + REG_MMU_RANGE1);413 writel(0x00, ctx->base + REG_MMU_PPN2);414 writel(0xffff, ctx->base + REG_MMU_RANGE2);415 writel(0x1ffff, ctx->base + REG_MMU_VPN_RANGE);416 417 if (ctx->if_type == SPRD_DPU_IF_DPI) {418 /* use dpi as interface */419 dpu_reg_clr(ctx, REG_DPU_CFG0, BIT_DPU_IF_EDPI);420 /* disable Halt function for SPRD DSI */421 dpu_reg_clr(ctx, REG_DPI_CTRL, BIT_DPU_DPI_HALT_EN);422 /* select te from external pad */423 dpu_reg_set(ctx, REG_DPI_CTRL, BIT_DPU_EDPI_FROM_EXTERNAL_PAD);424 425 /* enable dpu update done INT */426 int_mask |= BIT_DPU_INT_UPDATE_DONE;427 /* enable dpu done INT */428 int_mask |= BIT_DPU_INT_DONE;429 /* enable dpu dpi vsync */430 int_mask |= BIT_DPU_INT_VSYNC;431 /* enable dpu TE INT */432 int_mask |= BIT_DPU_INT_TE;433 /* enable underflow err INT */434 int_mask |= BIT_DPU_INT_ERR;435 } else if (ctx->if_type == SPRD_DPU_IF_EDPI) {436 /* use edpi as interface */437 dpu_reg_set(ctx, REG_DPU_CFG0, BIT_DPU_IF_EDPI);438 /* use external te */439 dpu_reg_set(ctx, REG_DPI_CTRL, BIT_DPU_EDPI_FROM_EXTERNAL_PAD);440 /* enable te */441 dpu_reg_set(ctx, REG_DPI_CTRL, BIT_DPU_EDPI_TE_EN);442 443 /* enable stop done INT */444 int_mask |= BIT_DPU_INT_DONE;445 /* enable TE INT */446 int_mask |= BIT_DPU_INT_TE;447 }448 449 writel(int_mask, ctx->base + REG_DPU_INT_EN);450}451 452static void sprd_dpu_fini(struct sprd_dpu *dpu)453{454 struct dpu_context *ctx = &dpu->ctx;455 456 writel(0x00, ctx->base + REG_DPU_INT_EN);457 writel(0xff, ctx->base + REG_DPU_INT_CLR);458}459 460static void sprd_dpi_init(struct sprd_dpu *dpu)461{462 struct dpu_context *ctx = &dpu->ctx;463 u32 reg_val;464 u32 size;465 466 size = (ctx->vm.vactive << 16) | ctx->vm.hactive;467 writel(size, ctx->base + REG_PANEL_SIZE);468 writel(size, ctx->base + REG_BLEND_SIZE);469 470 if (ctx->if_type == SPRD_DPU_IF_DPI) {471 /* set dpi timing */472 reg_val = ctx->vm.hsync_len << 0 |473 ctx->vm.hback_porch << 8 |474 ctx->vm.hfront_porch << 20;475 writel(reg_val, ctx->base + REG_DPI_H_TIMING);476 477 reg_val = ctx->vm.vsync_len << 0 |478 ctx->vm.vback_porch << 8 |479 ctx->vm.vfront_porch << 20;480 writel(reg_val, ctx->base + REG_DPI_V_TIMING);481 }482}483 484void sprd_dpu_run(struct sprd_dpu *dpu)485{486 struct dpu_context *ctx = &dpu->ctx;487 488 dpu_reg_set(ctx, REG_DPU_CTRL, BIT_DPU_RUN);489 490 ctx->stopped = false;491}492 493void sprd_dpu_stop(struct sprd_dpu *dpu)494{495 struct dpu_context *ctx = &dpu->ctx;496 497 if (ctx->if_type == SPRD_DPU_IF_DPI)498 dpu_reg_set(ctx, REG_DPU_CTRL, BIT_DPU_STOP);499 500 dpu_wait_stop_done(dpu);501}502 503static int sprd_plane_atomic_check(struct drm_plane *plane,504 struct drm_atomic_state *state)505{506 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state,507 plane);508 struct drm_crtc_state *crtc_state;509 u32 fmt;510 511 if (!plane_state->fb || !plane_state->crtc)512 return 0;513 514 fmt = drm_format_to_dpu(plane_state->fb);515 if (!fmt)516 return -EINVAL;517 518 crtc_state = drm_atomic_get_crtc_state(plane_state->state, plane_state->crtc);519 if (IS_ERR(crtc_state))520 return PTR_ERR(crtc_state);521 522 return drm_atomic_helper_check_plane_state(plane_state, crtc_state,523 DRM_PLANE_NO_SCALING,524 DRM_PLANE_NO_SCALING,525 true, true);526}527 528static void sprd_plane_atomic_update(struct drm_plane *drm_plane,529 struct drm_atomic_state *state)530{531 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,532 drm_plane);533 struct sprd_dpu *dpu = to_sprd_crtc(new_state->crtc);534 535 /* start configure dpu layers */536 sprd_dpu_layer(dpu, new_state);537}538 539static void sprd_plane_atomic_disable(struct drm_plane *drm_plane,540 struct drm_atomic_state *state)541{542 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,543 drm_plane);544 struct sprd_dpu *dpu = to_sprd_crtc(old_state->crtc);545 546 layer_reg_wr(&dpu->ctx, REG_LAY_CTRL, 0x00, old_state->zpos);547}548 549static void sprd_plane_create_properties(struct sprd_plane *plane, int index)550{551 unsigned int supported_modes = BIT(DRM_MODE_BLEND_PIXEL_NONE) |552 BIT(DRM_MODE_BLEND_PREMULTI) |553 BIT(DRM_MODE_BLEND_COVERAGE);554 555 /* create rotation property */556 drm_plane_create_rotation_property(&plane->base,557 DRM_MODE_ROTATE_0,558 DRM_MODE_ROTATE_MASK |559 DRM_MODE_REFLECT_MASK);560 561 /* create alpha property */562 drm_plane_create_alpha_property(&plane->base);563 564 /* create blend mode property */565 drm_plane_create_blend_mode_property(&plane->base, supported_modes);566 567 /* create zpos property */568 drm_plane_create_zpos_immutable_property(&plane->base, index);569}570 571static const struct drm_plane_helper_funcs sprd_plane_helper_funcs = {572 .atomic_check = sprd_plane_atomic_check,573 .atomic_update = sprd_plane_atomic_update,574 .atomic_disable = sprd_plane_atomic_disable,575};576 577static const struct drm_plane_funcs sprd_plane_funcs = {578 .update_plane = drm_atomic_helper_update_plane,579 .disable_plane = drm_atomic_helper_disable_plane,580 .destroy = drm_plane_cleanup,581 .reset = drm_atomic_helper_plane_reset,582 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,583 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,584};585 586static struct sprd_plane *sprd_planes_init(struct drm_device *drm)587{588 struct sprd_plane *plane, *primary;589 enum drm_plane_type plane_type;590 int i;591 592 for (i = 0; i < 6; i++) {593 plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :594 DRM_PLANE_TYPE_OVERLAY;595 596 plane = drmm_universal_plane_alloc(drm, struct sprd_plane, base,597 1, &sprd_plane_funcs,598 layer_fmts, ARRAY_SIZE(layer_fmts),599 NULL, plane_type, NULL);600 if (IS_ERR(plane)) {601 drm_err(drm, "failed to init drm plane: %d\n", i);602 return plane;603 }604 605 drm_plane_helper_add(&plane->base, &sprd_plane_helper_funcs);606 607 sprd_plane_create_properties(plane, i);608 609 if (i == 0)610 primary = plane;611 }612 613 return primary;614}615 616static void sprd_crtc_mode_set_nofb(struct drm_crtc *crtc)617{618 struct sprd_dpu *dpu = to_sprd_crtc(crtc);619 struct drm_display_mode *mode = &crtc->state->adjusted_mode;620 struct drm_encoder *encoder;621 struct sprd_dsi *dsi;622 623 drm_display_mode_to_videomode(mode, &dpu->ctx.vm);624 625 drm_for_each_encoder_mask(encoder, crtc->dev,626 crtc->state->encoder_mask) {627 dsi = encoder_to_dsi(encoder);628 629 if (dsi->slave->mode_flags & MIPI_DSI_MODE_VIDEO)630 dpu->ctx.if_type = SPRD_DPU_IF_DPI;631 else632 dpu->ctx.if_type = SPRD_DPU_IF_EDPI;633 }634 635 sprd_dpi_init(dpu);636}637 638static void sprd_crtc_atomic_enable(struct drm_crtc *crtc,639 struct drm_atomic_state *state)640{641 struct sprd_dpu *dpu = to_sprd_crtc(crtc);642 643 sprd_dpu_init(dpu);644 645 drm_crtc_vblank_on(&dpu->base);646}647 648static void sprd_crtc_atomic_disable(struct drm_crtc *crtc,649 struct drm_atomic_state *state)650{651 struct sprd_dpu *dpu = to_sprd_crtc(crtc);652 struct drm_device *drm = dpu->base.dev;653 654 drm_crtc_vblank_off(&dpu->base);655 656 sprd_dpu_fini(dpu);657 658 spin_lock_irq(&drm->event_lock);659 if (crtc->state->event) {660 drm_crtc_send_vblank_event(crtc, crtc->state->event);661 crtc->state->event = NULL;662 }663 spin_unlock_irq(&drm->event_lock);664}665 666static void sprd_crtc_atomic_flush(struct drm_crtc *crtc,667 struct drm_atomic_state *state)668 669{670 struct sprd_dpu *dpu = to_sprd_crtc(crtc);671 struct drm_device *drm = dpu->base.dev;672 673 sprd_dpu_flip(dpu);674 675 spin_lock_irq(&drm->event_lock);676 if (crtc->state->event) {677 drm_crtc_send_vblank_event(crtc, crtc->state->event);678 crtc->state->event = NULL;679 }680 spin_unlock_irq(&drm->event_lock);681}682 683static int sprd_crtc_enable_vblank(struct drm_crtc *crtc)684{685 struct sprd_dpu *dpu = to_sprd_crtc(crtc);686 687 dpu_reg_set(&dpu->ctx, REG_DPU_INT_EN, BIT_DPU_INT_VSYNC);688 689 return 0;690}691 692static void sprd_crtc_disable_vblank(struct drm_crtc *crtc)693{694 struct sprd_dpu *dpu = to_sprd_crtc(crtc);695 696 dpu_reg_clr(&dpu->ctx, REG_DPU_INT_EN, BIT_DPU_INT_VSYNC);697}698 699static const struct drm_crtc_helper_funcs sprd_crtc_helper_funcs = {700 .mode_set_nofb = sprd_crtc_mode_set_nofb,701 .atomic_flush = sprd_crtc_atomic_flush,702 .atomic_enable = sprd_crtc_atomic_enable,703 .atomic_disable = sprd_crtc_atomic_disable,704};705 706static const struct drm_crtc_funcs sprd_crtc_funcs = {707 .destroy = drm_crtc_cleanup,708 .set_config = drm_atomic_helper_set_config,709 .page_flip = drm_atomic_helper_page_flip,710 .reset = drm_atomic_helper_crtc_reset,711 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,712 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,713 .enable_vblank = sprd_crtc_enable_vblank,714 .disable_vblank = sprd_crtc_disable_vblank,715};716 717static struct sprd_dpu *sprd_crtc_init(struct drm_device *drm,718 struct drm_plane *primary, struct device *dev)719{720 struct device_node *port;721 struct sprd_dpu *dpu;722 723 dpu = drmm_crtc_alloc_with_planes(drm, struct sprd_dpu, base,724 primary, NULL,725 &sprd_crtc_funcs, NULL);726 if (IS_ERR(dpu)) {727 drm_err(drm, "failed to init crtc\n");728 return dpu;729 }730 drm_crtc_helper_add(&dpu->base, &sprd_crtc_helper_funcs);731 732 /*733 * set crtc port so that drm_of_find_possible_crtcs call works734 */735 port = of_graph_get_port_by_id(dev->of_node, 0);736 if (!port) {737 drm_err(drm, "failed to found crtc output port for %s\n",738 dev->of_node->full_name);739 return ERR_PTR(-EINVAL);740 }741 dpu->base.port = port;742 of_node_put(port);743 744 return dpu;745}746 747static irqreturn_t sprd_dpu_isr(int irq, void *data)748{749 struct sprd_dpu *dpu = data;750 struct dpu_context *ctx = &dpu->ctx;751 u32 reg_val, int_mask = 0;752 753 reg_val = readl(ctx->base + REG_DPU_INT_STS);754 755 /* disable err interrupt */756 if (reg_val & BIT_DPU_INT_ERR) {757 int_mask |= BIT_DPU_INT_ERR;758 drm_warn(dpu->drm, "Warning: dpu underflow!\n");759 }760 761 /* dpu update done isr */762 if (reg_val & BIT_DPU_INT_UPDATE_DONE) {763 ctx->evt_update = true;764 wake_up_interruptible_all(&ctx->wait_queue);765 }766 767 /* dpu stop done isr */768 if (reg_val & BIT_DPU_INT_DONE) {769 ctx->evt_stop = true;770 wake_up_interruptible_all(&ctx->wait_queue);771 }772 773 if (reg_val & BIT_DPU_INT_VSYNC)774 drm_crtc_handle_vblank(&dpu->base);775 776 writel(reg_val, ctx->base + REG_DPU_INT_CLR);777 dpu_reg_clr(ctx, REG_DPU_INT_EN, int_mask);778 779 return IRQ_HANDLED;780}781 782static int sprd_dpu_context_init(struct sprd_dpu *dpu,783 struct device *dev)784{785 struct platform_device *pdev = to_platform_device(dev);786 struct dpu_context *ctx = &dpu->ctx;787 struct resource *res;788 int ret;789 790 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);791 if (!res) {792 dev_err(dev, "failed to get I/O resource\n");793 return -EINVAL;794 }795 796 ctx->base = devm_ioremap(dev, res->start, resource_size(res));797 if (!ctx->base) {798 dev_err(dev, "failed to map dpu registers\n");799 return -EFAULT;800 }801 802 ctx->irq = platform_get_irq(pdev, 0);803 if (ctx->irq < 0)804 return ctx->irq;805 806 /* disable and clear interrupts before register dpu IRQ. */807 writel(0x00, ctx->base + REG_DPU_INT_EN);808 writel(0xff, ctx->base + REG_DPU_INT_CLR);809 810 ret = devm_request_irq(dev, ctx->irq, sprd_dpu_isr,811 IRQF_TRIGGER_NONE, "DPU", dpu);812 if (ret) {813 dev_err(dev, "failed to register dpu irq handler\n");814 return ret;815 }816 817 init_waitqueue_head(&ctx->wait_queue);818 819 return 0;820}821 822static int sprd_dpu_bind(struct device *dev, struct device *master, void *data)823{824 struct drm_device *drm = data;825 struct sprd_dpu *dpu;826 struct sprd_plane *plane;827 int ret;828 829 plane = sprd_planes_init(drm);830 if (IS_ERR(plane))831 return PTR_ERR(plane);832 833 dpu = sprd_crtc_init(drm, &plane->base, dev);834 if (IS_ERR(dpu))835 return PTR_ERR(dpu);836 837 dpu->drm = drm;838 dev_set_drvdata(dev, dpu);839 840 ret = sprd_dpu_context_init(dpu, dev);841 if (ret)842 return ret;843 844 return 0;845}846 847static const struct component_ops dpu_component_ops = {848 .bind = sprd_dpu_bind,849};850 851static const struct of_device_id dpu_match_table[] = {852 { .compatible = "sprd,sharkl3-dpu" },853 { /* sentinel */ },854};855MODULE_DEVICE_TABLE(of, dpu_match_table);856 857static int sprd_dpu_probe(struct platform_device *pdev)858{859 return component_add(&pdev->dev, &dpu_component_ops);860}861 862static void sprd_dpu_remove(struct platform_device *pdev)863{864 component_del(&pdev->dev, &dpu_component_ops);865}866 867struct platform_driver sprd_dpu_driver = {868 .probe = sprd_dpu_probe,869 .remove_new = sprd_dpu_remove,870 .driver = {871 .name = "sprd-dpu-drv",872 .of_match_table = dpu_match_table,873 },874};875 876MODULE_AUTHOR("Leon He <leon.he@unisoc.com>");877MODULE_AUTHOR("Kevin Tang <kevin.tang@unisoc.com>");878MODULE_DESCRIPTION("Unisoc Display Controller Driver");879MODULE_LICENSE("GPL v2");880