0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/delay.h>
0009 #include <linux/dma-buf.h>
0010 #include <linux/regulator/consumer.h>
0011 #include <linux/media-bus-format.h>
0012
0013 #include <drm/drm_device.h>
0014 #include <drm/drm_fb_cma_helper.h>
0015 #include <drm/drm_fourcc.h>
0016 #include <drm/drm_framebuffer.h>
0017 #include <drm/drm_gem_atomic_helper.h>
0018 #include <drm/drm_gem_cma_helper.h>
0019 #include <drm/drm_mipi_dsi.h>
0020 #include <drm/drm_simple_kms_helper.h>
0021 #include <drm/drm_bridge.h>
0022 #include <drm/drm_vblank.h>
0023 #include <video/mipi_display.h>
0024
0025 #include "mcde_drm.h"
0026 #include "mcde_display_regs.h"
0027
0028 enum mcde_fifo {
0029 MCDE_FIFO_A,
0030 MCDE_FIFO_B,
0031
0032 };
0033
0034 enum mcde_channel {
0035 MCDE_CHANNEL_0 = 0,
0036 MCDE_CHANNEL_1,
0037 MCDE_CHANNEL_2,
0038 MCDE_CHANNEL_3,
0039 };
0040
0041 enum mcde_extsrc {
0042 MCDE_EXTSRC_0 = 0,
0043 MCDE_EXTSRC_1,
0044 MCDE_EXTSRC_2,
0045 MCDE_EXTSRC_3,
0046 MCDE_EXTSRC_4,
0047 MCDE_EXTSRC_5,
0048 MCDE_EXTSRC_6,
0049 MCDE_EXTSRC_7,
0050 MCDE_EXTSRC_8,
0051 MCDE_EXTSRC_9,
0052 };
0053
0054 enum mcde_overlay {
0055 MCDE_OVERLAY_0 = 0,
0056 MCDE_OVERLAY_1,
0057 MCDE_OVERLAY_2,
0058 MCDE_OVERLAY_3,
0059 MCDE_OVERLAY_4,
0060 MCDE_OVERLAY_5,
0061 };
0062
0063 enum mcde_formatter {
0064 MCDE_DSI_FORMATTER_0 = 0,
0065 MCDE_DSI_FORMATTER_1,
0066 MCDE_DSI_FORMATTER_2,
0067 MCDE_DSI_FORMATTER_3,
0068 MCDE_DSI_FORMATTER_4,
0069 MCDE_DSI_FORMATTER_5,
0070 MCDE_DPI_FORMATTER_0,
0071 MCDE_DPI_FORMATTER_1,
0072 };
0073
0074 void mcde_display_irq(struct mcde *mcde)
0075 {
0076 u32 mispp, misovl, mischnl;
0077 bool vblank = false;
0078
0079
0080 mispp = readl(mcde->regs + MCDE_MISPP);
0081 misovl = readl(mcde->regs + MCDE_MISOVL);
0082 mischnl = readl(mcde->regs + MCDE_MISCHNL);
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 if (!mcde->dpi_output && mcde_dsi_irq(mcde->mdsi)) {
0093 u32 val;
0094
0095
0096
0097
0098
0099
0100
0101 if (mcde->flow_mode == MCDE_COMMAND_ONESHOT_FLOW) {
0102 spin_lock(&mcde->flow_lock);
0103 if (--mcde->flow_active == 0) {
0104 dev_dbg(mcde->dev, "TE0 IRQ\n");
0105
0106 val = readl(mcde->regs + MCDE_CRA0);
0107 val &= ~MCDE_CRX0_FLOEN;
0108 writel(val, mcde->regs + MCDE_CRA0);
0109 }
0110 spin_unlock(&mcde->flow_lock);
0111 }
0112 }
0113
0114
0115 if (mispp & MCDE_PP_VCMPA) {
0116 dev_dbg(mcde->dev, "chnl A vblank IRQ\n");
0117 vblank = true;
0118 }
0119 if (mispp & MCDE_PP_VCMPB) {
0120 dev_dbg(mcde->dev, "chnl B vblank IRQ\n");
0121 vblank = true;
0122 }
0123 if (mispp & MCDE_PP_VCMPC0)
0124 dev_dbg(mcde->dev, "chnl C0 vblank IRQ\n");
0125 if (mispp & MCDE_PP_VCMPC1)
0126 dev_dbg(mcde->dev, "chnl C1 vblank IRQ\n");
0127 if (mispp & MCDE_PP_VSCC0)
0128 dev_dbg(mcde->dev, "chnl C0 TE IRQ\n");
0129 if (mispp & MCDE_PP_VSCC1)
0130 dev_dbg(mcde->dev, "chnl C1 TE IRQ\n");
0131 writel(mispp, mcde->regs + MCDE_RISPP);
0132
0133 if (vblank)
0134 drm_crtc_handle_vblank(&mcde->pipe.crtc);
0135
0136 if (misovl)
0137 dev_info(mcde->dev, "some stray overlay IRQ %08x\n", misovl);
0138 writel(misovl, mcde->regs + MCDE_RISOVL);
0139
0140 if (mischnl)
0141 dev_info(mcde->dev, "some stray channel error IRQ %08x\n",
0142 mischnl);
0143 writel(mischnl, mcde->regs + MCDE_RISCHNL);
0144 }
0145
0146 void mcde_display_disable_irqs(struct mcde *mcde)
0147 {
0148
0149 writel(0, mcde->regs + MCDE_IMSCPP);
0150 writel(0, mcde->regs + MCDE_IMSCOVL);
0151 writel(0, mcde->regs + MCDE_IMSCCHNL);
0152
0153
0154 writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP);
0155 writel(0xFFFFFFFF, mcde->regs + MCDE_RISOVL);
0156 writel(0xFFFFFFFF, mcde->regs + MCDE_RISCHNL);
0157 }
0158
0159 static int mcde_display_check(struct drm_simple_display_pipe *pipe,
0160 struct drm_plane_state *pstate,
0161 struct drm_crtc_state *cstate)
0162 {
0163 const struct drm_display_mode *mode = &cstate->mode;
0164 struct drm_framebuffer *old_fb = pipe->plane.state->fb;
0165 struct drm_framebuffer *fb = pstate->fb;
0166
0167 if (fb) {
0168 u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
0169
0170
0171 if (offset & 3) {
0172 DRM_DEBUG_KMS("FB not 32-bit aligned\n");
0173 return -EINVAL;
0174 }
0175
0176
0177
0178
0179
0180 if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) {
0181 DRM_DEBUG_KMS("can't handle pitches\n");
0182 return -EINVAL;
0183 }
0184
0185
0186
0187
0188
0189 if (old_fb && old_fb->format != fb->format)
0190 cstate->mode_changed = true;
0191 }
0192
0193 return 0;
0194 }
0195
0196 static int mcde_configure_extsrc(struct mcde *mcde, enum mcde_extsrc src,
0197 u32 format)
0198 {
0199 u32 val;
0200 u32 conf;
0201 u32 cr;
0202
0203 switch (src) {
0204 case MCDE_EXTSRC_0:
0205 conf = MCDE_EXTSRC0CONF;
0206 cr = MCDE_EXTSRC0CR;
0207 break;
0208 case MCDE_EXTSRC_1:
0209 conf = MCDE_EXTSRC1CONF;
0210 cr = MCDE_EXTSRC1CR;
0211 break;
0212 case MCDE_EXTSRC_2:
0213 conf = MCDE_EXTSRC2CONF;
0214 cr = MCDE_EXTSRC2CR;
0215 break;
0216 case MCDE_EXTSRC_3:
0217 conf = MCDE_EXTSRC3CONF;
0218 cr = MCDE_EXTSRC3CR;
0219 break;
0220 case MCDE_EXTSRC_4:
0221 conf = MCDE_EXTSRC4CONF;
0222 cr = MCDE_EXTSRC4CR;
0223 break;
0224 case MCDE_EXTSRC_5:
0225 conf = MCDE_EXTSRC5CONF;
0226 cr = MCDE_EXTSRC5CR;
0227 break;
0228 case MCDE_EXTSRC_6:
0229 conf = MCDE_EXTSRC6CONF;
0230 cr = MCDE_EXTSRC6CR;
0231 break;
0232 case MCDE_EXTSRC_7:
0233 conf = MCDE_EXTSRC7CONF;
0234 cr = MCDE_EXTSRC7CR;
0235 break;
0236 case MCDE_EXTSRC_8:
0237 conf = MCDE_EXTSRC8CONF;
0238 cr = MCDE_EXTSRC8CR;
0239 break;
0240 case MCDE_EXTSRC_9:
0241 conf = MCDE_EXTSRC9CONF;
0242 cr = MCDE_EXTSRC9CR;
0243 break;
0244 }
0245
0246
0247
0248
0249
0250
0251 val = 0 << MCDE_EXTSRCXCONF_BUF_ID_SHIFT;
0252 val |= 1 << MCDE_EXTSRCXCONF_BUF_NB_SHIFT;
0253 val |= 0 << MCDE_EXTSRCXCONF_PRI_OVLID_SHIFT;
0254
0255 switch (format) {
0256 case DRM_FORMAT_ARGB8888:
0257 val |= MCDE_EXTSRCXCONF_BPP_ARGB8888 <<
0258 MCDE_EXTSRCXCONF_BPP_SHIFT;
0259 break;
0260 case DRM_FORMAT_ABGR8888:
0261 val |= MCDE_EXTSRCXCONF_BPP_ARGB8888 <<
0262 MCDE_EXTSRCXCONF_BPP_SHIFT;
0263 val |= MCDE_EXTSRCXCONF_BGR;
0264 break;
0265 case DRM_FORMAT_XRGB8888:
0266 val |= MCDE_EXTSRCXCONF_BPP_XRGB8888 <<
0267 MCDE_EXTSRCXCONF_BPP_SHIFT;
0268 break;
0269 case DRM_FORMAT_XBGR8888:
0270 val |= MCDE_EXTSRCXCONF_BPP_XRGB8888 <<
0271 MCDE_EXTSRCXCONF_BPP_SHIFT;
0272 val |= MCDE_EXTSRCXCONF_BGR;
0273 break;
0274 case DRM_FORMAT_RGB888:
0275 val |= MCDE_EXTSRCXCONF_BPP_RGB888 <<
0276 MCDE_EXTSRCXCONF_BPP_SHIFT;
0277 break;
0278 case DRM_FORMAT_BGR888:
0279 val |= MCDE_EXTSRCXCONF_BPP_RGB888 <<
0280 MCDE_EXTSRCXCONF_BPP_SHIFT;
0281 val |= MCDE_EXTSRCXCONF_BGR;
0282 break;
0283 case DRM_FORMAT_ARGB4444:
0284 val |= MCDE_EXTSRCXCONF_BPP_ARGB4444 <<
0285 MCDE_EXTSRCXCONF_BPP_SHIFT;
0286 break;
0287 case DRM_FORMAT_ABGR4444:
0288 val |= MCDE_EXTSRCXCONF_BPP_ARGB4444 <<
0289 MCDE_EXTSRCXCONF_BPP_SHIFT;
0290 val |= MCDE_EXTSRCXCONF_BGR;
0291 break;
0292 case DRM_FORMAT_XRGB4444:
0293 val |= MCDE_EXTSRCXCONF_BPP_RGB444 <<
0294 MCDE_EXTSRCXCONF_BPP_SHIFT;
0295 break;
0296 case DRM_FORMAT_XBGR4444:
0297 val |= MCDE_EXTSRCXCONF_BPP_RGB444 <<
0298 MCDE_EXTSRCXCONF_BPP_SHIFT;
0299 val |= MCDE_EXTSRCXCONF_BGR;
0300 break;
0301 case DRM_FORMAT_XRGB1555:
0302 val |= MCDE_EXTSRCXCONF_BPP_IRGB1555 <<
0303 MCDE_EXTSRCXCONF_BPP_SHIFT;
0304 break;
0305 case DRM_FORMAT_XBGR1555:
0306 val |= MCDE_EXTSRCXCONF_BPP_IRGB1555 <<
0307 MCDE_EXTSRCXCONF_BPP_SHIFT;
0308 val |= MCDE_EXTSRCXCONF_BGR;
0309 break;
0310 case DRM_FORMAT_RGB565:
0311 val |= MCDE_EXTSRCXCONF_BPP_RGB565 <<
0312 MCDE_EXTSRCXCONF_BPP_SHIFT;
0313 break;
0314 case DRM_FORMAT_BGR565:
0315 val |= MCDE_EXTSRCXCONF_BPP_RGB565 <<
0316 MCDE_EXTSRCXCONF_BPP_SHIFT;
0317 val |= MCDE_EXTSRCXCONF_BGR;
0318 break;
0319 case DRM_FORMAT_YUV422:
0320 val |= MCDE_EXTSRCXCONF_BPP_YCBCR422 <<
0321 MCDE_EXTSRCXCONF_BPP_SHIFT;
0322 break;
0323 default:
0324 dev_err(mcde->dev, "Unknown pixel format 0x%08x\n",
0325 format);
0326 return -EINVAL;
0327 }
0328 writel(val, mcde->regs + conf);
0329
0330
0331 val = MCDE_EXTSRCXCR_SEL_MOD_SOFTWARE_SEL;
0332 val |= MCDE_EXTSRCXCR_MULTIOVL_CTRL_PRIMARY;
0333 writel(val, mcde->regs + cr);
0334
0335 return 0;
0336 }
0337
0338 static void mcde_configure_overlay(struct mcde *mcde, enum mcde_overlay ovl,
0339 enum mcde_extsrc src,
0340 enum mcde_channel ch,
0341 const struct drm_display_mode *mode,
0342 u32 format, int cpp)
0343 {
0344 u32 val;
0345 u32 conf1;
0346 u32 conf2;
0347 u32 crop;
0348 u32 ljinc;
0349 u32 cr;
0350 u32 comp;
0351 u32 pixel_fetcher_watermark;
0352
0353 switch (ovl) {
0354 case MCDE_OVERLAY_0:
0355 conf1 = MCDE_OVL0CONF;
0356 conf2 = MCDE_OVL0CONF2;
0357 crop = MCDE_OVL0CROP;
0358 ljinc = MCDE_OVL0LJINC;
0359 cr = MCDE_OVL0CR;
0360 comp = MCDE_OVL0COMP;
0361 break;
0362 case MCDE_OVERLAY_1:
0363 conf1 = MCDE_OVL1CONF;
0364 conf2 = MCDE_OVL1CONF2;
0365 crop = MCDE_OVL1CROP;
0366 ljinc = MCDE_OVL1LJINC;
0367 cr = MCDE_OVL1CR;
0368 comp = MCDE_OVL1COMP;
0369 break;
0370 case MCDE_OVERLAY_2:
0371 conf1 = MCDE_OVL2CONF;
0372 conf2 = MCDE_OVL2CONF2;
0373 crop = MCDE_OVL2CROP;
0374 ljinc = MCDE_OVL2LJINC;
0375 cr = MCDE_OVL2CR;
0376 comp = MCDE_OVL2COMP;
0377 break;
0378 case MCDE_OVERLAY_3:
0379 conf1 = MCDE_OVL3CONF;
0380 conf2 = MCDE_OVL3CONF2;
0381 crop = MCDE_OVL3CROP;
0382 ljinc = MCDE_OVL3LJINC;
0383 cr = MCDE_OVL3CR;
0384 comp = MCDE_OVL3COMP;
0385 break;
0386 case MCDE_OVERLAY_4:
0387 conf1 = MCDE_OVL4CONF;
0388 conf2 = MCDE_OVL4CONF2;
0389 crop = MCDE_OVL4CROP;
0390 ljinc = MCDE_OVL4LJINC;
0391 cr = MCDE_OVL4CR;
0392 comp = MCDE_OVL4COMP;
0393 break;
0394 case MCDE_OVERLAY_5:
0395 conf1 = MCDE_OVL5CONF;
0396 conf2 = MCDE_OVL5CONF2;
0397 crop = MCDE_OVL5CROP;
0398 ljinc = MCDE_OVL5LJINC;
0399 cr = MCDE_OVL5CR;
0400 comp = MCDE_OVL5COMP;
0401 break;
0402 }
0403
0404 val = mode->hdisplay << MCDE_OVLXCONF_PPL_SHIFT;
0405 val |= mode->vdisplay << MCDE_OVLXCONF_LPF_SHIFT;
0406
0407 val |= src << MCDE_OVLXCONF_EXTSRC_ID_SHIFT;
0408 writel(val, mcde->regs + conf1);
0409
0410 val = MCDE_OVLXCONF2_BP_PER_PIXEL_ALPHA;
0411 val |= 0xff << MCDE_OVLXCONF2_ALPHAVALUE_SHIFT;
0412
0413 switch (format) {
0414 case DRM_FORMAT_ARGB8888:
0415 case DRM_FORMAT_ABGR8888:
0416 case DRM_FORMAT_ARGB4444:
0417 case DRM_FORMAT_ABGR4444:
0418 case DRM_FORMAT_XRGB1555:
0419 case DRM_FORMAT_XBGR1555:
0420
0421 break;
0422 case DRM_FORMAT_XRGB8888:
0423 case DRM_FORMAT_XBGR8888:
0424 case DRM_FORMAT_RGB888:
0425 case DRM_FORMAT_BGR888:
0426 case DRM_FORMAT_RGB565:
0427 case DRM_FORMAT_BGR565:
0428 case DRM_FORMAT_YUV422:
0429 val |= MCDE_OVLXCONF2_OPQ;
0430 break;
0431 default:
0432 dev_err(mcde->dev, "Unknown pixel format 0x%08x\n",
0433 format);
0434 break;
0435 }
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446 switch (cpp) {
0447 case 2:
0448 pixel_fetcher_watermark = 128;
0449 break;
0450 case 3:
0451 pixel_fetcher_watermark = 96;
0452 break;
0453 case 4:
0454 pixel_fetcher_watermark = 48;
0455 break;
0456 default:
0457 pixel_fetcher_watermark = 48;
0458 break;
0459 }
0460 dev_dbg(mcde->dev, "pixel fetcher watermark level %d pixels\n",
0461 pixel_fetcher_watermark);
0462 val |= pixel_fetcher_watermark << MCDE_OVLXCONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT;
0463 writel(val, mcde->regs + conf2);
0464
0465
0466 writel(mcde->stride, mcde->regs + ljinc);
0467
0468 writel(0, mcde->regs + crop);
0469
0470
0471 val = MCDE_OVLXCR_OVLEN;
0472 val |= MCDE_OVLXCR_COLCCTRL_DISABLED;
0473 val |= MCDE_OVLXCR_BURSTSIZE_8W <<
0474 MCDE_OVLXCR_BURSTSIZE_SHIFT;
0475 val |= MCDE_OVLXCR_MAXOUTSTANDING_8_REQ <<
0476 MCDE_OVLXCR_MAXOUTSTANDING_SHIFT;
0477
0478 val |= MCDE_OVLXCR_ROTBURSTSIZE_8W <<
0479 MCDE_OVLXCR_ROTBURSTSIZE_SHIFT;
0480 writel(val, mcde->regs + cr);
0481
0482
0483
0484
0485
0486 val = ch << MCDE_OVLXCOMP_CH_ID_SHIFT;
0487 writel(val, mcde->regs + comp);
0488 }
0489
0490 static void mcde_configure_channel(struct mcde *mcde, enum mcde_channel ch,
0491 enum mcde_fifo fifo,
0492 const struct drm_display_mode *mode)
0493 {
0494 u32 val;
0495 u32 conf;
0496 u32 sync;
0497 u32 stat;
0498 u32 bgcol;
0499 u32 mux;
0500
0501 switch (ch) {
0502 case MCDE_CHANNEL_0:
0503 conf = MCDE_CHNL0CONF;
0504 sync = MCDE_CHNL0SYNCHMOD;
0505 stat = MCDE_CHNL0STAT;
0506 bgcol = MCDE_CHNL0BCKGNDCOL;
0507 mux = MCDE_CHNL0MUXING;
0508 break;
0509 case MCDE_CHANNEL_1:
0510 conf = MCDE_CHNL1CONF;
0511 sync = MCDE_CHNL1SYNCHMOD;
0512 stat = MCDE_CHNL1STAT;
0513 bgcol = MCDE_CHNL1BCKGNDCOL;
0514 mux = MCDE_CHNL1MUXING;
0515 break;
0516 case MCDE_CHANNEL_2:
0517 conf = MCDE_CHNL2CONF;
0518 sync = MCDE_CHNL2SYNCHMOD;
0519 stat = MCDE_CHNL2STAT;
0520 bgcol = MCDE_CHNL2BCKGNDCOL;
0521 mux = MCDE_CHNL2MUXING;
0522 break;
0523 case MCDE_CHANNEL_3:
0524 conf = MCDE_CHNL3CONF;
0525 sync = MCDE_CHNL3SYNCHMOD;
0526 stat = MCDE_CHNL3STAT;
0527 bgcol = MCDE_CHNL3BCKGNDCOL;
0528 mux = MCDE_CHNL3MUXING;
0529 return;
0530 }
0531
0532
0533 switch (mcde->flow_mode) {
0534 case MCDE_COMMAND_ONESHOT_FLOW:
0535
0536 val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SOFTWARE
0537 << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
0538 break;
0539 case MCDE_COMMAND_TE_FLOW:
0540 val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE
0541 << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
0542 val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0
0543 << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
0544 break;
0545 case MCDE_COMMAND_BTA_TE_FLOW:
0546 val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE
0547 << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
0548
0549
0550
0551
0552
0553
0554 val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER
0555 << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
0556 break;
0557 case MCDE_VIDEO_TE_FLOW:
0558 val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE
0559 << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
0560 val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0
0561 << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
0562 break;
0563 case MCDE_VIDEO_FORMATTER_FLOW:
0564 case MCDE_DPI_FORMATTER_FLOW:
0565 val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE
0566 << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
0567 val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER
0568 << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
0569 break;
0570 default:
0571 dev_err(mcde->dev, "unknown flow mode %d\n",
0572 mcde->flow_mode);
0573 return;
0574 }
0575
0576 writel(val, mcde->regs + sync);
0577
0578
0579 val = (mode->hdisplay - 1) << MCDE_CHNLXCONF_PPL_SHIFT;
0580 val |= (mode->vdisplay - 1) << MCDE_CHNLXCONF_LPF_SHIFT;
0581 writel(val, mcde->regs + conf);
0582
0583
0584
0585
0586
0587 val = MCDE_CHNLXSTAT_CHNLBLBCKGND_EN |
0588 MCDE_CHNLXSTAT_CHNLRD;
0589 writel(val, mcde->regs + stat);
0590 writel(0, mcde->regs + bgcol);
0591
0592
0593 switch (fifo) {
0594 case MCDE_FIFO_A:
0595 writel(MCDE_CHNLXMUXING_FIFO_ID_FIFO_A,
0596 mcde->regs + mux);
0597 break;
0598 case MCDE_FIFO_B:
0599 writel(MCDE_CHNLXMUXING_FIFO_ID_FIFO_B,
0600 mcde->regs + mux);
0601 break;
0602 }
0603
0604
0605
0606
0607
0608 if (mcde->dpi_output) {
0609 u32 stripwidth;
0610
0611 stripwidth = 0xF000 / (mode->vdisplay * 4);
0612 dev_info(mcde->dev, "stripwidth: %d\n", stripwidth);
0613
0614 val = MCDE_SYNCHCONF_HWREQVEVENT_ACTIVE_VIDEO |
0615 (mode->hdisplay - 1 - stripwidth) << MCDE_SYNCHCONF_HWREQVCNT_SHIFT |
0616 MCDE_SYNCHCONF_SWINTVEVENT_ACTIVE_VIDEO |
0617 (mode->hdisplay - 1 - stripwidth) << MCDE_SYNCHCONF_SWINTVCNT_SHIFT;
0618
0619 switch (fifo) {
0620 case MCDE_FIFO_A:
0621 writel(val, mcde->regs + MCDE_SYNCHCONFA);
0622 break;
0623 case MCDE_FIFO_B:
0624 writel(val, mcde->regs + MCDE_SYNCHCONFB);
0625 break;
0626 }
0627 }
0628 }
0629
0630 static void mcde_configure_fifo(struct mcde *mcde, enum mcde_fifo fifo,
0631 enum mcde_formatter fmt,
0632 int fifo_wtrmrk)
0633 {
0634 u32 val;
0635 u32 ctrl;
0636 u32 cr0, cr1;
0637
0638 switch (fifo) {
0639 case MCDE_FIFO_A:
0640 ctrl = MCDE_CTRLA;
0641 cr0 = MCDE_CRA0;
0642 cr1 = MCDE_CRA1;
0643 break;
0644 case MCDE_FIFO_B:
0645 ctrl = MCDE_CTRLB;
0646 cr0 = MCDE_CRB0;
0647 cr1 = MCDE_CRB1;
0648 break;
0649 }
0650
0651 val = fifo_wtrmrk << MCDE_CTRLX_FIFOWTRMRK_SHIFT;
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661 switch (fmt) {
0662 case MCDE_DSI_FORMATTER_0:
0663 val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
0664 val |= MCDE_CTRLX_FORMID_DSI0VID << MCDE_CTRLX_FORMID_SHIFT;
0665 break;
0666 case MCDE_DSI_FORMATTER_1:
0667 val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
0668 val |= MCDE_CTRLX_FORMID_DSI0CMD << MCDE_CTRLX_FORMID_SHIFT;
0669 break;
0670 case MCDE_DSI_FORMATTER_2:
0671 val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
0672 val |= MCDE_CTRLX_FORMID_DSI1VID << MCDE_CTRLX_FORMID_SHIFT;
0673 break;
0674 case MCDE_DSI_FORMATTER_3:
0675 val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
0676 val |= MCDE_CTRLX_FORMID_DSI1CMD << MCDE_CTRLX_FORMID_SHIFT;
0677 break;
0678 case MCDE_DSI_FORMATTER_4:
0679 val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
0680 val |= MCDE_CTRLX_FORMID_DSI2VID << MCDE_CTRLX_FORMID_SHIFT;
0681 break;
0682 case MCDE_DSI_FORMATTER_5:
0683 val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
0684 val |= MCDE_CTRLX_FORMID_DSI2CMD << MCDE_CTRLX_FORMID_SHIFT;
0685 break;
0686 case MCDE_DPI_FORMATTER_0:
0687 val |= MCDE_CTRLX_FORMTYPE_DPITV << MCDE_CTRLX_FORMTYPE_SHIFT;
0688 val |= MCDE_CTRLX_FORMID_DPIA << MCDE_CTRLX_FORMID_SHIFT;
0689 break;
0690 case MCDE_DPI_FORMATTER_1:
0691 val |= MCDE_CTRLX_FORMTYPE_DPITV << MCDE_CTRLX_FORMTYPE_SHIFT;
0692 val |= MCDE_CTRLX_FORMID_DPIB << MCDE_CTRLX_FORMID_SHIFT;
0693 break;
0694 }
0695 writel(val, mcde->regs + ctrl);
0696
0697
0698 val = MCDE_CRX0_BLENDEN |
0699 0xff << MCDE_CRX0_ALPHABLEND_SHIFT;
0700 writel(val, mcde->regs + cr0);
0701
0702 spin_lock(&mcde->fifo_crx1_lock);
0703 val = readl(mcde->regs + cr1);
0704
0705
0706
0707
0708 if (mcde->dpi_output) {
0709 struct drm_connector *connector = drm_panel_bridge_connector(mcde->bridge);
0710 u32 bus_format;
0711
0712
0713 if (!connector->display_info.num_bus_formats) {
0714 dev_info(mcde->dev, "panel does not specify bus format, assume RGB888\n");
0715 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
0716 } else {
0717 bus_format = connector->display_info.bus_formats[0];
0718 }
0719
0720
0721
0722
0723
0724
0725
0726 val &= ~MCDE_CRX1_CDWIN_MASK;
0727 val &= ~MCDE_CRX1_OUTBPP_MASK;
0728 switch (bus_format) {
0729 case MEDIA_BUS_FMT_RGB888_1X24:
0730 val |= MCDE_CRX1_CDWIN_24BPP << MCDE_CRX1_CDWIN_SHIFT;
0731 val |= MCDE_CRX1_OUTBPP_24BPP << MCDE_CRX1_OUTBPP_SHIFT;
0732 break;
0733 default:
0734 dev_err(mcde->dev, "unknown bus format, assume RGB888\n");
0735 val |= MCDE_CRX1_CDWIN_24BPP << MCDE_CRX1_CDWIN_SHIFT;
0736 val |= MCDE_CRX1_OUTBPP_24BPP << MCDE_CRX1_OUTBPP_SHIFT;
0737 break;
0738 }
0739 } else {
0740
0741 val &= ~MCDE_CRX1_CLKSEL_MASK;
0742 val |= MCDE_CRX1_CLKSEL_MCDECLK << MCDE_CRX1_CLKSEL_SHIFT;
0743 }
0744 writel(val, mcde->regs + cr1);
0745 spin_unlock(&mcde->fifo_crx1_lock);
0746 };
0747
0748 static void mcde_configure_dsi_formatter(struct mcde *mcde,
0749 enum mcde_formatter fmt,
0750 u32 formatter_frame,
0751 int pkt_size)
0752 {
0753 u32 val;
0754 u32 conf0;
0755 u32 frame;
0756 u32 pkt;
0757 u32 sync;
0758 u32 cmdw;
0759 u32 delay0, delay1;
0760
0761 switch (fmt) {
0762 case MCDE_DSI_FORMATTER_0:
0763 conf0 = MCDE_DSIVID0CONF0;
0764 frame = MCDE_DSIVID0FRAME;
0765 pkt = MCDE_DSIVID0PKT;
0766 sync = MCDE_DSIVID0SYNC;
0767 cmdw = MCDE_DSIVID0CMDW;
0768 delay0 = MCDE_DSIVID0DELAY0;
0769 delay1 = MCDE_DSIVID0DELAY1;
0770 break;
0771 case MCDE_DSI_FORMATTER_1:
0772 conf0 = MCDE_DSIVID1CONF0;
0773 frame = MCDE_DSIVID1FRAME;
0774 pkt = MCDE_DSIVID1PKT;
0775 sync = MCDE_DSIVID1SYNC;
0776 cmdw = MCDE_DSIVID1CMDW;
0777 delay0 = MCDE_DSIVID1DELAY0;
0778 delay1 = MCDE_DSIVID1DELAY1;
0779 break;
0780 case MCDE_DSI_FORMATTER_2:
0781 conf0 = MCDE_DSIVID2CONF0;
0782 frame = MCDE_DSIVID2FRAME;
0783 pkt = MCDE_DSIVID2PKT;
0784 sync = MCDE_DSIVID2SYNC;
0785 cmdw = MCDE_DSIVID2CMDW;
0786 delay0 = MCDE_DSIVID2DELAY0;
0787 delay1 = MCDE_DSIVID2DELAY1;
0788 break;
0789 default:
0790 dev_err(mcde->dev, "tried to configure a non-DSI formatter as DSI\n");
0791 return;
0792 }
0793
0794
0795
0796
0797
0798 val = MCDE_DSICONF0_CMD8 | MCDE_DSICONF0_DCSVID_NOTGEN;
0799 if (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO)
0800 val |= MCDE_DSICONF0_VID_MODE_VID;
0801 switch (mcde->mdsi->format) {
0802 case MIPI_DSI_FMT_RGB888:
0803 val |= MCDE_DSICONF0_PACKING_RGB888 <<
0804 MCDE_DSICONF0_PACKING_SHIFT;
0805 break;
0806 case MIPI_DSI_FMT_RGB666:
0807 val |= MCDE_DSICONF0_PACKING_RGB666 <<
0808 MCDE_DSICONF0_PACKING_SHIFT;
0809 break;
0810 case MIPI_DSI_FMT_RGB666_PACKED:
0811 dev_err(mcde->dev,
0812 "we cannot handle the packed RGB666 format\n");
0813 val |= MCDE_DSICONF0_PACKING_RGB666 <<
0814 MCDE_DSICONF0_PACKING_SHIFT;
0815 break;
0816 case MIPI_DSI_FMT_RGB565:
0817 val |= MCDE_DSICONF0_PACKING_RGB565 <<
0818 MCDE_DSICONF0_PACKING_SHIFT;
0819 break;
0820 default:
0821 dev_err(mcde->dev, "unknown DSI format\n");
0822 return;
0823 }
0824 writel(val, mcde->regs + conf0);
0825
0826 writel(formatter_frame, mcde->regs + frame);
0827 writel(pkt_size, mcde->regs + pkt);
0828 writel(0, mcde->regs + sync);
0829
0830 val = MIPI_DCS_WRITE_MEMORY_CONTINUE <<
0831 MCDE_DSIVIDXCMDW_CMDW_CONTINUE_SHIFT;
0832 val |= MIPI_DCS_WRITE_MEMORY_START <<
0833 MCDE_DSIVIDXCMDW_CMDW_START_SHIFT;
0834 writel(val, mcde->regs + cmdw);
0835
0836
0837
0838
0839
0840 writel(0, mcde->regs + delay0);
0841 writel(0, mcde->regs + delay1);
0842 }
0843
0844 static void mcde_enable_fifo(struct mcde *mcde, enum mcde_fifo fifo)
0845 {
0846 u32 val;
0847 u32 cr;
0848
0849 switch (fifo) {
0850 case MCDE_FIFO_A:
0851 cr = MCDE_CRA0;
0852 break;
0853 case MCDE_FIFO_B:
0854 cr = MCDE_CRB0;
0855 break;
0856 default:
0857 dev_err(mcde->dev, "cannot enable FIFO %c\n",
0858 'A' + fifo);
0859 return;
0860 }
0861
0862 spin_lock(&mcde->flow_lock);
0863 val = readl(mcde->regs + cr);
0864 val |= MCDE_CRX0_FLOEN;
0865 writel(val, mcde->regs + cr);
0866 mcde->flow_active++;
0867 spin_unlock(&mcde->flow_lock);
0868 }
0869
0870 static void mcde_disable_fifo(struct mcde *mcde, enum mcde_fifo fifo,
0871 bool wait_for_drain)
0872 {
0873 int timeout = 100;
0874 u32 val;
0875 u32 cr;
0876
0877 switch (fifo) {
0878 case MCDE_FIFO_A:
0879 cr = MCDE_CRA0;
0880 break;
0881 case MCDE_FIFO_B:
0882 cr = MCDE_CRB0;
0883 break;
0884 default:
0885 dev_err(mcde->dev, "cannot disable FIFO %c\n",
0886 'A' + fifo);
0887 return;
0888 }
0889
0890 spin_lock(&mcde->flow_lock);
0891 val = readl(mcde->regs + cr);
0892 val &= ~MCDE_CRX0_FLOEN;
0893 writel(val, mcde->regs + cr);
0894 mcde->flow_active = 0;
0895 spin_unlock(&mcde->flow_lock);
0896
0897 if (!wait_for_drain)
0898 return;
0899
0900
0901 while (readl(mcde->regs + cr) & MCDE_CRX0_FLOEN) {
0902 usleep_range(1000, 1500);
0903 if (!--timeout) {
0904 dev_err(mcde->dev,
0905 "FIFO timeout while clearing FIFO %c\n",
0906 'A' + fifo);
0907 return;
0908 }
0909 }
0910 }
0911
0912
0913
0914
0915 static void mcde_drain_pipe(struct mcde *mcde, enum mcde_fifo fifo,
0916 enum mcde_channel ch)
0917 {
0918 u32 val;
0919 u32 ctrl;
0920 u32 synsw;
0921
0922 switch (fifo) {
0923 case MCDE_FIFO_A:
0924 ctrl = MCDE_CTRLA;
0925 break;
0926 case MCDE_FIFO_B:
0927 ctrl = MCDE_CTRLB;
0928 break;
0929 }
0930
0931 switch (ch) {
0932 case MCDE_CHANNEL_0:
0933 synsw = MCDE_CHNL0SYNCHSW;
0934 break;
0935 case MCDE_CHANNEL_1:
0936 synsw = MCDE_CHNL1SYNCHSW;
0937 break;
0938 case MCDE_CHANNEL_2:
0939 synsw = MCDE_CHNL2SYNCHSW;
0940 break;
0941 case MCDE_CHANNEL_3:
0942 synsw = MCDE_CHNL3SYNCHSW;
0943 return;
0944 }
0945
0946 val = readl(mcde->regs + ctrl);
0947 if (!(val & MCDE_CTRLX_FIFOEMPTY)) {
0948 dev_err(mcde->dev, "Channel A FIFO not empty (handover)\n");
0949
0950 mcde_enable_fifo(mcde, fifo);
0951
0952 writel(MCDE_CHNLXSYNCHSW_SW_TRIG, mcde->regs + synsw);
0953
0954 mcde_disable_fifo(mcde, fifo, true);
0955 }
0956 }
0957
0958 static int mcde_dsi_get_pkt_div(int ppl, int fifo_size)
0959 {
0960
0961
0962
0963
0964 int div;
0965 const int max_div = DIV_ROUND_UP(MCDE_MAX_WIDTH, fifo_size);
0966
0967 for (div = 1; div < max_div; div++)
0968 if (ppl % div == 0 && ppl / div <= fifo_size)
0969 return div;
0970 return 1;
0971 }
0972
0973 static void mcde_setup_dpi(struct mcde *mcde, const struct drm_display_mode *mode,
0974 int *fifo_wtrmrk_lvl)
0975 {
0976 struct drm_connector *connector = drm_panel_bridge_connector(mcde->bridge);
0977 u32 hsw, hfp, hbp;
0978 u32 vsw, vfp, vbp;
0979 u32 val;
0980
0981
0982 hsw = mode->hsync_end - mode->hsync_start;
0983 hfp = mode->hsync_start - mode->hdisplay;
0984 hbp = mode->htotal - mode->hsync_end;
0985 vsw = mode->vsync_end - mode->vsync_start;
0986 vfp = mode->vsync_start - mode->vdisplay;
0987 vbp = mode->vtotal - mode->vsync_end;
0988
0989 dev_info(mcde->dev, "output on DPI LCD from channel A\n");
0990
0991 dev_info(mcde->dev, "HSW: %d, HFP: %d, HBP: %d, VSW: %d, VFP: %d, VBP: %d\n",
0992 hsw, hfp, hbp, vsw, vfp, vbp);
0993
0994
0995
0996
0997
0998
0999 *fifo_wtrmrk_lvl = 640;
1000
1001
1002 val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT;
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017 val |= 0 << MCDE_CONF0_OUTMUX0_SHIFT;
1018
1019 val |= 1 << MCDE_CONF0_OUTMUX1_SHIFT;
1020
1021 val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT;
1022
1023 val |= 0 << MCDE_CONF0_OUTMUX3_SHIFT;
1024
1025 val |= 2 << MCDE_CONF0_OUTMUX4_SHIFT;
1026
1027 writel(val, mcde->regs + MCDE_CONF0);
1028
1029
1030 writel(0, mcde->regs + MCDE_TVCRA);
1031
1032
1033 val = (vsw << MCDE_TVBL1_BEL1_SHIFT);
1034 val |= (vfp << MCDE_TVBL1_BSL1_SHIFT);
1035 writel(val, mcde->regs + MCDE_TVBL1A);
1036
1037 writel(val, mcde->regs + MCDE_TVBL2A);
1038
1039
1040 val = (vbp << MCDE_TVDVO_DVO1_SHIFT);
1041
1042 val |= (vbp << MCDE_TVDVO_DVO2_SHIFT);
1043 writel(val, mcde->regs + MCDE_TVDVOA);
1044
1045
1046 writel((hbp - 1), mcde->regs + MCDE_TVTIM1A);
1047
1048
1049 val = ((hsw - 1) << MCDE_TVLBALW_LBW_SHIFT);
1050 val |= ((hfp - 1) << MCDE_TVLBALW_ALW_SHIFT);
1051 writel(val, mcde->regs + MCDE_TVLBALWA);
1052
1053
1054 writel(0, mcde->regs + MCDE_TVISLA);
1055 writel(0, mcde->regs + MCDE_TVBLUA);
1056
1057
1058 val = 0;
1059 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1060 val |= MCDE_LCDTIM1B_IHS;
1061 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1062 val |= MCDE_LCDTIM1B_IVS;
1063 if (connector->display_info.bus_flags & DRM_BUS_FLAG_DE_LOW)
1064 val |= MCDE_LCDTIM1B_IOE;
1065 if (connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
1066 val |= MCDE_LCDTIM1B_IPC;
1067 writel(val, mcde->regs + MCDE_LCDTIM1A);
1068 }
1069
1070 static void mcde_setup_dsi(struct mcde *mcde, const struct drm_display_mode *mode,
1071 int cpp, int *fifo_wtrmrk_lvl, int *dsi_formatter_frame,
1072 int *dsi_pkt_size)
1073 {
1074 u32 formatter_ppl = mode->hdisplay;
1075 u32 formatter_lpf = mode->vdisplay;
1076 int formatter_frame;
1077 int formatter_cpp;
1078 int fifo_wtrmrk;
1079 u32 pkt_div;
1080 int pkt_size;
1081 u32 val;
1082
1083 dev_info(mcde->dev, "output in %s mode, format %dbpp\n",
1084 (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ?
1085 "VIDEO" : "CMD",
1086 mipi_dsi_pixel_format_to_bpp(mcde->mdsi->format));
1087 formatter_cpp =
1088 mipi_dsi_pixel_format_to_bpp(mcde->mdsi->format) / 8;
1089 dev_info(mcde->dev, "Overlay CPP: %d bytes, DSI formatter CPP %d bytes\n",
1090 cpp, formatter_cpp);
1091
1092
1093 val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT;
1094
1095
1096
1097
1098
1099
1100
1101 val |= 3 << MCDE_CONF0_OUTMUX0_SHIFT;
1102 val |= 3 << MCDE_CONF0_OUTMUX1_SHIFT;
1103 val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT;
1104 val |= 4 << MCDE_CONF0_OUTMUX3_SHIFT;
1105 val |= 5 << MCDE_CONF0_OUTMUX4_SHIFT;
1106 writel(val, mcde->regs + MCDE_CONF0);
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119 fifo_wtrmrk = mode->hdisplay;
1120 if (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
1121 fifo_wtrmrk = min(fifo_wtrmrk, 128);
1122 pkt_div = 1;
1123 } else {
1124 fifo_wtrmrk = min(fifo_wtrmrk, 48);
1125
1126 pkt_div = mcde_dsi_get_pkt_div(mode->hdisplay, 640);
1127 }
1128 dev_dbg(mcde->dev, "FIFO watermark after flooring: %d bytes\n",
1129 fifo_wtrmrk);
1130 dev_dbg(mcde->dev, "Packet divisor: %d bytes\n", pkt_div);
1131
1132
1133 pkt_size = (formatter_ppl * formatter_cpp) / pkt_div;
1134
1135 if (!(mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO))
1136 pkt_size++;
1137
1138 dev_dbg(mcde->dev, "DSI packet size: %d * %d bytes per line\n",
1139 pkt_size, pkt_div);
1140 dev_dbg(mcde->dev, "Overlay frame size: %u bytes\n",
1141 mode->hdisplay * mode->vdisplay * cpp);
1142
1143 formatter_frame = pkt_size * pkt_div * formatter_lpf;
1144 dev_dbg(mcde->dev, "Formatter frame size: %u bytes\n", formatter_frame);
1145
1146 *fifo_wtrmrk_lvl = fifo_wtrmrk;
1147 *dsi_pkt_size = pkt_size;
1148 *dsi_formatter_frame = formatter_frame;
1149 }
1150
1151 static void mcde_display_enable(struct drm_simple_display_pipe *pipe,
1152 struct drm_crtc_state *cstate,
1153 struct drm_plane_state *plane_state)
1154 {
1155 struct drm_crtc *crtc = &pipe->crtc;
1156 struct drm_plane *plane = &pipe->plane;
1157 struct drm_device *drm = crtc->dev;
1158 struct mcde *mcde = to_mcde(drm);
1159 const struct drm_display_mode *mode = &cstate->mode;
1160 struct drm_framebuffer *fb = plane->state->fb;
1161 u32 format = fb->format->format;
1162 int dsi_pkt_size;
1163 int fifo_wtrmrk;
1164 int cpp = fb->format->cpp[0];
1165 u32 dsi_formatter_frame;
1166 u32 val;
1167 int ret;
1168
1169
1170 ret = regulator_enable(mcde->epod);
1171 if (ret) {
1172 dev_err(drm->dev, "can't re-enable EPOD regulator\n");
1173 return;
1174 }
1175
1176 dev_info(drm->dev, "enable MCDE, %d x %d format %p4cc\n",
1177 mode->hdisplay, mode->vdisplay, &format);
1178
1179
1180
1181 mcde_display_disable_irqs(mcde);
1182 writel(0, mcde->regs + MCDE_IMSCERR);
1183 writel(0xFFFFFFFF, mcde->regs + MCDE_RISERR);
1184
1185 if (mcde->dpi_output)
1186 mcde_setup_dpi(mcde, mode, &fifo_wtrmrk);
1187 else
1188 mcde_setup_dsi(mcde, mode, cpp, &fifo_wtrmrk,
1189 &dsi_formatter_frame, &dsi_pkt_size);
1190
1191 mcde->stride = mode->hdisplay * cpp;
1192 dev_dbg(drm->dev, "Overlay line stride: %u bytes\n",
1193 mcde->stride);
1194
1195
1196 mcde_drain_pipe(mcde, MCDE_FIFO_A, MCDE_CHANNEL_0);
1197
1198
1199
1200
1201
1202
1203
1204
1205 mcde_configure_extsrc(mcde, MCDE_EXTSRC_0, format);
1206
1207
1208
1209
1210
1211
1212 mcde_configure_overlay(mcde, MCDE_OVERLAY_0, MCDE_EXTSRC_0,
1213 MCDE_CHANNEL_0, mode, format, cpp);
1214
1215
1216
1217
1218
1219 mcde_configure_channel(mcde, MCDE_CHANNEL_0, MCDE_FIFO_A, mode);
1220
1221 if (mcde->dpi_output) {
1222 unsigned long lcd_freq;
1223
1224
1225 mcde_configure_fifo(mcde, MCDE_FIFO_A, MCDE_DPI_FORMATTER_0,
1226 fifo_wtrmrk);
1227
1228
1229 lcd_freq = clk_round_rate(mcde->fifoa_clk, mode->clock * 1000);
1230 ret = clk_set_rate(mcde->fifoa_clk, lcd_freq);
1231 if (ret)
1232 dev_err(mcde->dev, "failed to set LCD clock rate %lu Hz\n",
1233 lcd_freq);
1234 ret = clk_prepare_enable(mcde->fifoa_clk);
1235 if (ret) {
1236 dev_err(mcde->dev, "failed to enable FIFO A DPI clock\n");
1237 return;
1238 }
1239 dev_info(mcde->dev, "LCD FIFO A clk rate %lu Hz\n",
1240 clk_get_rate(mcde->fifoa_clk));
1241 } else {
1242
1243 mcde_configure_fifo(mcde, MCDE_FIFO_A, MCDE_DSI_FORMATTER_0,
1244 fifo_wtrmrk);
1245
1246
1247
1248
1249
1250 mcde_dsi_enable(mcde->bridge);
1251
1252
1253 mcde_configure_dsi_formatter(mcde, MCDE_DSI_FORMATTER_0,
1254 dsi_formatter_frame, dsi_pkt_size);
1255 }
1256
1257 switch (mcde->flow_mode) {
1258 case MCDE_COMMAND_TE_FLOW:
1259 case MCDE_COMMAND_BTA_TE_FLOW:
1260 case MCDE_VIDEO_TE_FLOW:
1261
1262 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1263 val = MCDE_VSCRC_VSPOL;
1264 else
1265 val = 0;
1266 writel(val, mcde->regs + MCDE_VSCRC0);
1267
1268 val = readl(mcde->regs + MCDE_CRC);
1269 val |= MCDE_CRC_SYCEN0;
1270 writel(val, mcde->regs + MCDE_CRC);
1271 break;
1272 default:
1273
1274 break;
1275 }
1276
1277 drm_crtc_vblank_on(crtc);
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287 if (mcde->flow_mode != MCDE_COMMAND_ONESHOT_FLOW) {
1288 mcde_enable_fifo(mcde, MCDE_FIFO_A);
1289 dev_dbg(mcde->dev, "started MCDE video FIFO flow\n");
1290 }
1291
1292
1293 val = readl(mcde->regs + MCDE_CR);
1294 val |= MCDE_CR_MCDEEN | MCDE_CR_AUTOCLKG_EN;
1295 writel(val, mcde->regs + MCDE_CR);
1296
1297 dev_info(drm->dev, "MCDE display is enabled\n");
1298 }
1299
1300 static void mcde_display_disable(struct drm_simple_display_pipe *pipe)
1301 {
1302 struct drm_crtc *crtc = &pipe->crtc;
1303 struct drm_device *drm = crtc->dev;
1304 struct mcde *mcde = to_mcde(drm);
1305 struct drm_pending_vblank_event *event;
1306 int ret;
1307
1308 drm_crtc_vblank_off(crtc);
1309
1310
1311 mcde_disable_fifo(mcde, MCDE_FIFO_A, true);
1312
1313 if (mcde->dpi_output) {
1314 clk_disable_unprepare(mcde->fifoa_clk);
1315 } else {
1316
1317 mcde_dsi_disable(mcde->bridge);
1318 }
1319
1320 event = crtc->state->event;
1321 if (event) {
1322 crtc->state->event = NULL;
1323
1324 spin_lock_irq(&crtc->dev->event_lock);
1325 drm_crtc_send_vblank_event(crtc, event);
1326 spin_unlock_irq(&crtc->dev->event_lock);
1327 }
1328
1329 ret = regulator_disable(mcde->epod);
1330 if (ret)
1331 dev_err(drm->dev, "can't disable EPOD regulator\n");
1332
1333 usleep_range(50000, 70000);
1334
1335 dev_info(drm->dev, "MCDE display is disabled\n");
1336 }
1337
1338 static void mcde_start_flow(struct mcde *mcde)
1339 {
1340
1341 if (mcde->flow_mode == MCDE_COMMAND_BTA_TE_FLOW)
1342 mcde_dsi_te_request(mcde->mdsi);
1343
1344
1345 mcde_enable_fifo(mcde, MCDE_FIFO_A);
1346
1347
1348
1349
1350
1351
1352
1353
1354 if (mcde->flow_mode == MCDE_COMMAND_ONESHOT_FLOW) {
1355
1356 writel(MCDE_CHNLXSYNCHSW_SW_TRIG,
1357 mcde->regs + MCDE_CHNL0SYNCHSW);
1358
1359
1360
1361
1362
1363
1364
1365
1366 mcde_disable_fifo(mcde, MCDE_FIFO_A, true);
1367 }
1368
1369 dev_dbg(mcde->dev, "started MCDE FIFO flow\n");
1370 }
1371
1372 static void mcde_set_extsrc(struct mcde *mcde, u32 buffer_address)
1373 {
1374
1375 writel(buffer_address, mcde->regs + MCDE_EXTSRCXA0);
1376
1377
1378
1379
1380 writel(buffer_address + mcde->stride, mcde->regs + MCDE_EXTSRCXA1);
1381 }
1382
1383 static void mcde_display_update(struct drm_simple_display_pipe *pipe,
1384 struct drm_plane_state *old_pstate)
1385 {
1386 struct drm_crtc *crtc = &pipe->crtc;
1387 struct drm_device *drm = crtc->dev;
1388 struct mcde *mcde = to_mcde(drm);
1389 struct drm_pending_vblank_event *event = crtc->state->event;
1390 struct drm_plane *plane = &pipe->plane;
1391 struct drm_plane_state *pstate = plane->state;
1392 struct drm_framebuffer *fb = pstate->fb;
1393
1394
1395
1396
1397
1398
1399 if (event) {
1400 crtc->state->event = NULL;
1401
1402 spin_lock_irq(&crtc->dev->event_lock);
1403
1404
1405
1406
1407
1408
1409
1410 if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) {
1411 dev_dbg(mcde->dev, "arm vblank event\n");
1412 drm_crtc_arm_vblank_event(crtc, event);
1413 } else {
1414 dev_dbg(mcde->dev, "insert fake vblank event\n");
1415 drm_crtc_send_vblank_event(crtc, event);
1416 }
1417
1418 spin_unlock_irq(&crtc->dev->event_lock);
1419 }
1420
1421
1422
1423
1424
1425
1426 if (fb) {
1427 mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0));
1428 dev_info_once(mcde->dev, "first update of display contents\n");
1429
1430
1431
1432
1433 if (mcde->flow_active == 0)
1434 mcde_start_flow(mcde);
1435 } else {
1436
1437
1438
1439
1440
1441 dev_info(mcde->dev, "ignored a display update\n");
1442 }
1443 }
1444
1445 static int mcde_display_enable_vblank(struct drm_simple_display_pipe *pipe)
1446 {
1447 struct drm_crtc *crtc = &pipe->crtc;
1448 struct drm_device *drm = crtc->dev;
1449 struct mcde *mcde = to_mcde(drm);
1450 u32 val;
1451
1452
1453 val = MCDE_PP_VCMPA |
1454 MCDE_PP_VCMPB |
1455 MCDE_PP_VSCC0 |
1456 MCDE_PP_VSCC1 |
1457 MCDE_PP_VCMPC0 |
1458 MCDE_PP_VCMPC1;
1459 writel(val, mcde->regs + MCDE_IMSCPP);
1460
1461 return 0;
1462 }
1463
1464 static void mcde_display_disable_vblank(struct drm_simple_display_pipe *pipe)
1465 {
1466 struct drm_crtc *crtc = &pipe->crtc;
1467 struct drm_device *drm = crtc->dev;
1468 struct mcde *mcde = to_mcde(drm);
1469
1470
1471 writel(0, mcde->regs + MCDE_IMSCPP);
1472
1473 writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP);
1474 }
1475
1476 static struct drm_simple_display_pipe_funcs mcde_display_funcs = {
1477 .check = mcde_display_check,
1478 .enable = mcde_display_enable,
1479 .disable = mcde_display_disable,
1480 .update = mcde_display_update,
1481 .enable_vblank = mcde_display_enable_vblank,
1482 .disable_vblank = mcde_display_disable_vblank,
1483 };
1484
1485 int mcde_display_init(struct drm_device *drm)
1486 {
1487 struct mcde *mcde = to_mcde(drm);
1488 int ret;
1489 static const u32 formats[] = {
1490 DRM_FORMAT_ARGB8888,
1491 DRM_FORMAT_ABGR8888,
1492 DRM_FORMAT_XRGB8888,
1493 DRM_FORMAT_XBGR8888,
1494 DRM_FORMAT_RGB888,
1495 DRM_FORMAT_BGR888,
1496 DRM_FORMAT_ARGB4444,
1497 DRM_FORMAT_ABGR4444,
1498 DRM_FORMAT_XRGB4444,
1499 DRM_FORMAT_XBGR4444,
1500
1501 DRM_FORMAT_XRGB1555,
1502 DRM_FORMAT_XBGR1555,
1503 DRM_FORMAT_RGB565,
1504 DRM_FORMAT_BGR565,
1505 DRM_FORMAT_YUV422,
1506 };
1507
1508 ret = mcde_init_clock_divider(mcde);
1509 if (ret)
1510 return ret;
1511
1512 ret = drm_simple_display_pipe_init(drm, &mcde->pipe,
1513 &mcde_display_funcs,
1514 formats, ARRAY_SIZE(formats),
1515 NULL,
1516 mcde->connector);
1517 if (ret)
1518 return ret;
1519
1520 return 0;
1521 }
1522 EXPORT_SYMBOL_GPL(mcde_display_init);