Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2018 Linus Walleij <linus.walleij@linaro.org>
0004  * Parts of this file were based on the MCDE driver by Marcus Lorentzon
0005  * (C) ST-Ericsson SA 2013
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     /* TODO: implement FIFO C0 and FIFO C1 */
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     /* Handle display IRQs */
0080     mispp = readl(mcde->regs + MCDE_MISPP);
0081     misovl = readl(mcde->regs + MCDE_MISOVL);
0082     mischnl = readl(mcde->regs + MCDE_MISCHNL);
0083 
0084     /*
0085      * Handle IRQs from the DSI link. All IRQs from the DSI links
0086      * are just latched onto the MCDE IRQ line, so we need to traverse
0087      * any active DSI masters and check if an IRQ is originating from
0088      * them.
0089      *
0090      * TODO: Currently only one DSI link is supported.
0091      */
0092     if (!mcde->dpi_output && mcde_dsi_irq(mcde->mdsi)) {
0093         u32 val;
0094 
0095         /*
0096          * In oneshot mode we do not send continuous updates
0097          * to the display, instead we only push out updates when
0098          * the update function is called, then we disable the
0099          * flow on the channel once we get the TE IRQ.
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                 /* Disable FIFO A flow */
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     /* Vblank from one of the channels */
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     /* Disable all IRQs */
0149     writel(0, mcde->regs + MCDE_IMSCPP);
0150     writel(0, mcde->regs + MCDE_IMSCOVL);
0151     writel(0, mcde->regs + MCDE_IMSCCHNL);
0152 
0153     /* Clear any pending IRQs */
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         /* FB base address must be dword aligned. */
0171         if (offset & 3) {
0172             DRM_DEBUG_KMS("FB not 32-bit aligned\n");
0173             return -EINVAL;
0174         }
0175 
0176         /*
0177          * There's no pitch register, the mode's hdisplay
0178          * controls this.
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          * We can't change the FB format in a flicker-free
0187          * manner (and only update it during CRTC enable).
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      * Configure external source 0 one buffer (buffer 0)
0248      * primary overlay ID 0.
0249      * From mcde_hw.c ovly_update_registers() in the vendor tree
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     /* Software select, primary */
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     /* Use external source 0 that we just configured */
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     /* OPQ: overlay is opaque */
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         /* No OPQ */
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      * Pixel fetch watermark level is max 0x1FFF pixels.
0439      * Two basic rules should be followed:
0440      * 1. The value should be at least 256 bits.
0441      * 2. The sum of all active overlays pixelfetch watermark level
0442      *    multiplied with bits per pixel, should be lower than the
0443      *    size of input_fifo_size in bits.
0444      * 3. The value should be a multiple of a line (256 bits).
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     /* Number of bytes to fetch per line */
0466     writel(mcde->stride, mcde->regs + ljinc);
0467     /* No cropping */
0468     writel(0, mcde->regs + crop);
0469 
0470     /* Set up overlay control register */
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     /* Not using rotation but set it up anyways */
0478     val |= MCDE_OVLXCR_ROTBURSTSIZE_8W <<
0479         MCDE_OVLXCR_ROTBURSTSIZE_SHIFT;
0480     writel(val, mcde->regs + cr);
0481 
0482     /*
0483      * Set up the overlay compositor to route the overlay out to
0484      * the desired channel
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     /* Set up channel 0 sync (based on chnl_update_registers()) */
0533     switch (mcde->flow_mode) {
0534     case MCDE_COMMAND_ONESHOT_FLOW:
0535         /* Oneshot is achieved with software sync */
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          * TODO:
0550          * The vendor driver uses the formatter as sync source
0551          * for BTA TE mode. Test to use TE if you have a panel
0552          * that uses this mode.
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     /* Set up pixels per line and lines per frame */
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      * Normalize color conversion:
0585      * black background, OLED conversion disable on channel
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     /* Set up muxing: connect the channel to the desired FIFO */
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      * If using DPI configure the sync event.
0606      * TODO: this is for LCD only, it does not cover TV out.
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      * Select the formatter to use for this FIFO
0655      *
0656      * The register definitions imply that different IDs should be used
0657      * by the DSI formatters depending on if they are in VID or CMD
0658      * mode, and the manual says they are dedicated but identical.
0659      * The vendor code uses them as it seems fit.
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     /* Blend source with Alpha 0xff on FIFO */
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      * Set-up from mcde_fmtr_dsi.c, fmtr_dsi_enable_video()
0706      * FIXME: a different clock needs to be selected for TV out.
0707      */
0708     if (mcde->dpi_output) {
0709         struct drm_connector *connector = drm_panel_bridge_connector(mcde->bridge);
0710         u32 bus_format;
0711 
0712         /* Assume RGB888 24 bit if we have no further info */
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          * Set up the CDWIN and OUTBPP for the LCD
0722          *
0723          * FIXME: fill this in if you know the correspondance between the MIPI
0724          * DPI specification and the media bus formats.
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         /* Use the MCDE clock for DSI */
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      * Enable formatter
0796      * 8 bit commands and DCS commands (notgen = not generic)
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     /* Define the MIPI command: we want to write into display memory */
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      * FIXME: the vendor driver has some hack around this value in
0838      * CMD mode with autotrig.
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     /* Check that we really drained and stopped the flow */
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  * This drains a pipe i.e. a FIFO connected to a certain channel
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         /* Attempt to clear the FIFO */
0950         mcde_enable_fifo(mcde, fifo);
0951         /* Trigger a software sync out on respective channel (0-3) */
0952         writel(MCDE_CHNLXSYNCHSW_SW_TRIG, mcde->regs + synsw);
0953         /* Disable FIFO A flow again */
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      * DSI command mode line packets should be split into an even number of
0962      * packets smaller than or equal to the fifo size.
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     /* FIXME: we only support LCD, implement TV out */
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     /* Display actual values */
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      * The pixel fetcher is 128 64-bit words deep = 1024 bytes.
0996      * One overlay of 32bpp (4 cpp) assumed, fetch 160 pixels.
0997      * 160 * 4 = 640 bytes.
0998      */
0999     *fifo_wtrmrk_lvl = 640;
1000 
1001     /* Set up the main control, watermark level at 7 */
1002     val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT;
1003 
1004     /*
1005      * This sets up the internal silicon muxing of the DPI
1006      * lines. This is how the silicon connects out to the
1007      * external pins, then the pins need to be further
1008      * configured into "alternate functions" using pin control
1009      * to actually get the signals out.
1010      *
1011      * FIXME: this is hardcoded to the only setting found in
1012      * the wild. If we need to use different settings for
1013      * different DPI displays, make this parameterizable from
1014      * the device tree.
1015      */
1016     /* 24 bits DPI: connect Ch A LSB to D[0:7] */
1017     val |= 0 << MCDE_CONF0_OUTMUX0_SHIFT;
1018     /* 24 bits DPI: connect Ch A MID to D[8:15] */
1019     val |= 1 << MCDE_CONF0_OUTMUX1_SHIFT;
1020     /* Don't care about this muxing */
1021     val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT;
1022     /* Don't care about this muxing */
1023     val |= 0 << MCDE_CONF0_OUTMUX3_SHIFT;
1024     /* 24 bits DPI: connect Ch A MSB to D[32:39] */
1025     val |= 2 << MCDE_CONF0_OUTMUX4_SHIFT;
1026     /* Syncmux bits zero: DPI channel A */
1027     writel(val, mcde->regs + MCDE_CONF0);
1028 
1029     /* This hammers us into LCD mode */
1030     writel(0, mcde->regs + MCDE_TVCRA);
1031 
1032     /* Front porch and sync width */
1033     val = (vsw << MCDE_TVBL1_BEL1_SHIFT);
1034     val |= (vfp << MCDE_TVBL1_BSL1_SHIFT);
1035     writel(val, mcde->regs + MCDE_TVBL1A);
1036     /* The vendor driver sets the same value into TVBL2A */
1037     writel(val, mcde->regs + MCDE_TVBL2A);
1038 
1039     /* Vertical back porch */
1040     val = (vbp << MCDE_TVDVO_DVO1_SHIFT);
1041     /* The vendor drivers sets the same value into TVDVOA */
1042     val |= (vbp << MCDE_TVDVO_DVO2_SHIFT);
1043     writel(val, mcde->regs + MCDE_TVDVOA);
1044 
1045     /* Horizontal back porch, as 0 = 1 cycle we need to subtract 1 */
1046     writel((hbp - 1), mcde->regs + MCDE_TVTIM1A);
1047 
1048     /* Horizongal sync width and horizonal front porch, 0 = 1 cycle */
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     /* Blank some TV registers we don't use */
1054     writel(0, mcde->regs + MCDE_TVISLA);
1055     writel(0, mcde->regs + MCDE_TVBLUA);
1056 
1057     /* Set up sync inversion etc */
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; /* pixels per line */
1075     u32 formatter_lpf = mode->vdisplay; /* lines per frame */
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     /* Set up the main control, watermark level at 7 */
1093     val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT;
1094 
1095     /*
1096      * This is the internal silicon muxing of the DPI
1097      * (parallell display) lines. Since we are not using
1098      * this at all (we are using DSI) these are just
1099      * dummy values from the vendor tree.
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     /* Calculations from mcde_fmtr_dsi.c, fmtr_dsi_enable_video() */
1109 
1110     /*
1111      * Set up FIFO A watermark level:
1112      * 128 for LCD 32bpp video mode
1113      * 48  for LCD 32bpp command mode
1114      * 128 for LCD 16bpp video mode
1115      * 64  for LCD 16bpp command mode
1116      * 128 for HDMI 32bpp
1117      * 192 for HDMI 16bpp
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         /* The FIFO is 640 entries deep on this v3 hardware */
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     /* NOTE: pkt_div is 1 for video mode */
1133     pkt_size = (formatter_ppl * formatter_cpp) / pkt_div;
1134     /* Commands CMD8 need one extra byte */
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     /* NOTE: pkt_div is 1 for video mode */
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     /* This powers up the entire MCDE block and the DSI hardware */
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     /* Clear any pending interrupts */
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     /* Drain the FIFO A + channel 0 pipe so we have a clean slate */
1196     mcde_drain_pipe(mcde, MCDE_FIFO_A, MCDE_CHANNEL_0);
1197 
1198     /*
1199      * We set up our display pipeline:
1200      * EXTSRC 0 -> OVERLAY 0 -> CHANNEL 0 -> FIFO A -> DSI FORMATTER 0
1201      *
1202      * First configure the external source (memory) on external source 0
1203      * using the desired bitstream/bitmap format
1204      */
1205     mcde_configure_extsrc(mcde, MCDE_EXTSRC_0, format);
1206 
1207     /*
1208      * Configure overlay 0 according to format and mode and take input
1209      * from external source 0 and route the output of this overlay to
1210      * channel 0
1211      */
1212     mcde_configure_overlay(mcde, MCDE_OVERLAY_0, MCDE_EXTSRC_0,
1213                    MCDE_CHANNEL_0, mode, format, cpp);
1214 
1215     /*
1216      * Configure pixel-per-line and line-per-frame for channel 0 and then
1217      * route channel 0 to FIFO A
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         /* Configure FIFO A to use DPI formatter 0 */
1225         mcde_configure_fifo(mcde, MCDE_FIFO_A, MCDE_DPI_FORMATTER_0,
1226                     fifo_wtrmrk);
1227 
1228         /* Set up and enable the LCD clock */
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         /* Configure FIFO A to use DSI formatter 0 */
1243         mcde_configure_fifo(mcde, MCDE_FIFO_A, MCDE_DSI_FORMATTER_0,
1244                     fifo_wtrmrk);
1245 
1246         /*
1247          * This brings up the DSI bridge which is tightly connected
1248          * to the MCDE DSI formatter.
1249          */
1250         mcde_dsi_enable(mcde->bridge);
1251 
1252         /* Configure the DSI formatter 0 for the DSI panel output */
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         /* We are using TE in some combination */
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         /* Enable VSYNC capture on TE0 */
1268         val = readl(mcde->regs + MCDE_CRC);
1269         val |= MCDE_CRC_SYCEN0;
1270         writel(val, mcde->regs + MCDE_CRC);
1271         break;
1272     default:
1273         /* No TE capture */
1274         break;
1275     }
1276 
1277     drm_crtc_vblank_on(crtc);
1278 
1279     /*
1280      * If we're using oneshot mode we don't start the flow
1281      * until each time the display is given an update, and
1282      * then we disable it immediately after. For all other
1283      * modes (command or video) we start the FIFO flow
1284      * right here. This is necessary for the hardware to
1285      * behave right.
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     /* Enable MCDE with automatic clock gating */
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     /* Disable FIFO A flow */
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         /* This disables the DSI bridge */
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     /* Make sure we are powered down (before we may power up again) */
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     /* Request a TE ACK only in TE+BTA mode */
1341     if (mcde->flow_mode == MCDE_COMMAND_BTA_TE_FLOW)
1342         mcde_dsi_te_request(mcde->mdsi);
1343 
1344     /* Enable FIFO A flow */
1345     mcde_enable_fifo(mcde, MCDE_FIFO_A);
1346 
1347     /*
1348      * If oneshot mode is enabled, the flow will be disabled
1349      * when the TE0 IRQ arrives in the interrupt handler. Otherwise
1350      * updates are continuously streamed to the display after this
1351      * point.
1352      */
1353 
1354     if (mcde->flow_mode == MCDE_COMMAND_ONESHOT_FLOW) {
1355         /* Trigger a software sync out on channel 0 */
1356         writel(MCDE_CHNLXSYNCHSW_SW_TRIG,
1357                mcde->regs + MCDE_CHNL0SYNCHSW);
1358 
1359         /*
1360          * Disable FIFO A flow again: since we are using TE sync we
1361          * need to wait for the FIFO to drain before we continue
1362          * so repeated calls to this function will not cause a mess
1363          * in the hardware by pushing updates will updates are going
1364          * on already.
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     /* Write bitmap base address to register */
1375     writel(buffer_address, mcde->regs + MCDE_EXTSRCXA0);
1376     /*
1377      * Base address for next line this is probably only used
1378      * in interlace modes.
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      * Handle any pending event first, we need to arm the vblank
1396      * interrupt before sending any update to the display so we don't
1397      * miss the interrupt.
1398      */
1399     if (event) {
1400         crtc->state->event = NULL;
1401 
1402         spin_lock_irq(&crtc->dev->event_lock);
1403         /*
1404          * Hardware must be on before we can arm any vblank event,
1405          * this is not a scanout controller where there is always
1406          * some periodic update going on, it is completely frozen
1407          * until we get an update. If MCDE output isn't yet enabled,
1408          * we just send a vblank dummy event back.
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      * We do not start sending framebuffer updates before the
1423      * display is enabled. Update events will however be dispatched
1424      * from the DRM core before the display is enabled.
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          * Usually the flow is already active, unless we are in
1431          * oneshot mode, then we need to kick the flow right here.
1432          */
1433         if (mcde->flow_active == 0)
1434             mcde_start_flow(mcde);
1435     } else {
1436         /*
1437          * If an update is receieved before the MCDE is enabled
1438          * (before mcde_display_enable() is called) we can't really
1439          * do much with that buffer.
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     /* Enable all VBLANK IRQs */
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     /* Disable all VBLANK IRQs */
1471     writel(0, mcde->regs + MCDE_IMSCPP);
1472     /* Clear any pending IRQs */
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         /* These are actually IRGB1555 so intensity bit is lost */
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);