cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mcde_display.c (41166B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2018 Linus Walleij <linus.walleij@linaro.org>
      4 * Parts of this file were based on the MCDE driver by Marcus Lorentzon
      5 * (C) ST-Ericsson SA 2013
      6 */
      7#include <linux/clk.h>
      8#include <linux/delay.h>
      9#include <linux/dma-buf.h>
     10#include <linux/regulator/consumer.h>
     11#include <linux/media-bus-format.h>
     12
     13#include <drm/drm_device.h>
     14#include <drm/drm_fb_cma_helper.h>
     15#include <drm/drm_fourcc.h>
     16#include <drm/drm_gem_atomic_helper.h>
     17#include <drm/drm_gem_cma_helper.h>
     18#include <drm/drm_mipi_dsi.h>
     19#include <drm/drm_simple_kms_helper.h>
     20#include <drm/drm_bridge.h>
     21#include <drm/drm_vblank.h>
     22#include <video/mipi_display.h>
     23
     24#include "mcde_drm.h"
     25#include "mcde_display_regs.h"
     26
     27enum mcde_fifo {
     28	MCDE_FIFO_A,
     29	MCDE_FIFO_B,
     30	/* TODO: implement FIFO C0 and FIFO C1 */
     31};
     32
     33enum mcde_channel {
     34	MCDE_CHANNEL_0 = 0,
     35	MCDE_CHANNEL_1,
     36	MCDE_CHANNEL_2,
     37	MCDE_CHANNEL_3,
     38};
     39
     40enum mcde_extsrc {
     41	MCDE_EXTSRC_0 = 0,
     42	MCDE_EXTSRC_1,
     43	MCDE_EXTSRC_2,
     44	MCDE_EXTSRC_3,
     45	MCDE_EXTSRC_4,
     46	MCDE_EXTSRC_5,
     47	MCDE_EXTSRC_6,
     48	MCDE_EXTSRC_7,
     49	MCDE_EXTSRC_8,
     50	MCDE_EXTSRC_9,
     51};
     52
     53enum mcde_overlay {
     54	MCDE_OVERLAY_0 = 0,
     55	MCDE_OVERLAY_1,
     56	MCDE_OVERLAY_2,
     57	MCDE_OVERLAY_3,
     58	MCDE_OVERLAY_4,
     59	MCDE_OVERLAY_5,
     60};
     61
     62enum mcde_formatter {
     63	MCDE_DSI_FORMATTER_0 = 0,
     64	MCDE_DSI_FORMATTER_1,
     65	MCDE_DSI_FORMATTER_2,
     66	MCDE_DSI_FORMATTER_3,
     67	MCDE_DSI_FORMATTER_4,
     68	MCDE_DSI_FORMATTER_5,
     69	MCDE_DPI_FORMATTER_0,
     70	MCDE_DPI_FORMATTER_1,
     71};
     72
     73void mcde_display_irq(struct mcde *mcde)
     74{
     75	u32 mispp, misovl, mischnl;
     76	bool vblank = false;
     77
     78	/* Handle display IRQs */
     79	mispp = readl(mcde->regs + MCDE_MISPP);
     80	misovl = readl(mcde->regs + MCDE_MISOVL);
     81	mischnl = readl(mcde->regs + MCDE_MISCHNL);
     82
     83	/*
     84	 * Handle IRQs from the DSI link. All IRQs from the DSI links
     85	 * are just latched onto the MCDE IRQ line, so we need to traverse
     86	 * any active DSI masters and check if an IRQ is originating from
     87	 * them.
     88	 *
     89	 * TODO: Currently only one DSI link is supported.
     90	 */
     91	if (!mcde->dpi_output && mcde_dsi_irq(mcde->mdsi)) {
     92		u32 val;
     93
     94		/*
     95		 * In oneshot mode we do not send continuous updates
     96		 * to the display, instead we only push out updates when
     97		 * the update function is called, then we disable the
     98		 * flow on the channel once we get the TE IRQ.
     99		 */
    100		if (mcde->flow_mode == MCDE_COMMAND_ONESHOT_FLOW) {
    101			spin_lock(&mcde->flow_lock);
    102			if (--mcde->flow_active == 0) {
    103				dev_dbg(mcde->dev, "TE0 IRQ\n");
    104				/* Disable FIFO A flow */
    105				val = readl(mcde->regs + MCDE_CRA0);
    106				val &= ~MCDE_CRX0_FLOEN;
    107				writel(val, mcde->regs + MCDE_CRA0);
    108			}
    109			spin_unlock(&mcde->flow_lock);
    110		}
    111	}
    112
    113	/* Vblank from one of the channels */
    114	if (mispp & MCDE_PP_VCMPA) {
    115		dev_dbg(mcde->dev, "chnl A vblank IRQ\n");
    116		vblank = true;
    117	}
    118	if (mispp & MCDE_PP_VCMPB) {
    119		dev_dbg(mcde->dev, "chnl B vblank IRQ\n");
    120		vblank = true;
    121	}
    122	if (mispp & MCDE_PP_VCMPC0)
    123		dev_dbg(mcde->dev, "chnl C0 vblank IRQ\n");
    124	if (mispp & MCDE_PP_VCMPC1)
    125		dev_dbg(mcde->dev, "chnl C1 vblank IRQ\n");
    126	if (mispp & MCDE_PP_VSCC0)
    127		dev_dbg(mcde->dev, "chnl C0 TE IRQ\n");
    128	if (mispp & MCDE_PP_VSCC1)
    129		dev_dbg(mcde->dev, "chnl C1 TE IRQ\n");
    130	writel(mispp, mcde->regs + MCDE_RISPP);
    131
    132	if (vblank)
    133		drm_crtc_handle_vblank(&mcde->pipe.crtc);
    134
    135	if (misovl)
    136		dev_info(mcde->dev, "some stray overlay IRQ %08x\n", misovl);
    137	writel(misovl, mcde->regs + MCDE_RISOVL);
    138
    139	if (mischnl)
    140		dev_info(mcde->dev, "some stray channel error IRQ %08x\n",
    141			 mischnl);
    142	writel(mischnl, mcde->regs + MCDE_RISCHNL);
    143}
    144
    145void mcde_display_disable_irqs(struct mcde *mcde)
    146{
    147	/* Disable all IRQs */
    148	writel(0, mcde->regs + MCDE_IMSCPP);
    149	writel(0, mcde->regs + MCDE_IMSCOVL);
    150	writel(0, mcde->regs + MCDE_IMSCCHNL);
    151
    152	/* Clear any pending IRQs */
    153	writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP);
    154	writel(0xFFFFFFFF, mcde->regs + MCDE_RISOVL);
    155	writel(0xFFFFFFFF, mcde->regs + MCDE_RISCHNL);
    156}
    157
    158static int mcde_display_check(struct drm_simple_display_pipe *pipe,
    159			      struct drm_plane_state *pstate,
    160			      struct drm_crtc_state *cstate)
    161{
    162	const struct drm_display_mode *mode = &cstate->mode;
    163	struct drm_framebuffer *old_fb = pipe->plane.state->fb;
    164	struct drm_framebuffer *fb = pstate->fb;
    165
    166	if (fb) {
    167		u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
    168
    169		/* FB base address must be dword aligned. */
    170		if (offset & 3) {
    171			DRM_DEBUG_KMS("FB not 32-bit aligned\n");
    172			return -EINVAL;
    173		}
    174
    175		/*
    176		 * There's no pitch register, the mode's hdisplay
    177		 * controls this.
    178		 */
    179		if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) {
    180			DRM_DEBUG_KMS("can't handle pitches\n");
    181			return -EINVAL;
    182		}
    183
    184		/*
    185		 * We can't change the FB format in a flicker-free
    186		 * manner (and only update it during CRTC enable).
    187		 */
    188		if (old_fb && old_fb->format != fb->format)
    189			cstate->mode_changed = true;
    190	}
    191
    192	return 0;
    193}
    194
    195static int mcde_configure_extsrc(struct mcde *mcde, enum mcde_extsrc src,
    196				 u32 format)
    197{
    198	u32 val;
    199	u32 conf;
    200	u32 cr;
    201
    202	switch (src) {
    203	case MCDE_EXTSRC_0:
    204		conf = MCDE_EXTSRC0CONF;
    205		cr = MCDE_EXTSRC0CR;
    206		break;
    207	case MCDE_EXTSRC_1:
    208		conf = MCDE_EXTSRC1CONF;
    209		cr = MCDE_EXTSRC1CR;
    210		break;
    211	case MCDE_EXTSRC_2:
    212		conf = MCDE_EXTSRC2CONF;
    213		cr = MCDE_EXTSRC2CR;
    214		break;
    215	case MCDE_EXTSRC_3:
    216		conf = MCDE_EXTSRC3CONF;
    217		cr = MCDE_EXTSRC3CR;
    218		break;
    219	case MCDE_EXTSRC_4:
    220		conf = MCDE_EXTSRC4CONF;
    221		cr = MCDE_EXTSRC4CR;
    222		break;
    223	case MCDE_EXTSRC_5:
    224		conf = MCDE_EXTSRC5CONF;
    225		cr = MCDE_EXTSRC5CR;
    226		break;
    227	case MCDE_EXTSRC_6:
    228		conf = MCDE_EXTSRC6CONF;
    229		cr = MCDE_EXTSRC6CR;
    230		break;
    231	case MCDE_EXTSRC_7:
    232		conf = MCDE_EXTSRC7CONF;
    233		cr = MCDE_EXTSRC7CR;
    234		break;
    235	case MCDE_EXTSRC_8:
    236		conf = MCDE_EXTSRC8CONF;
    237		cr = MCDE_EXTSRC8CR;
    238		break;
    239	case MCDE_EXTSRC_9:
    240		conf = MCDE_EXTSRC9CONF;
    241		cr = MCDE_EXTSRC9CR;
    242		break;
    243	}
    244
    245	/*
    246	 * Configure external source 0 one buffer (buffer 0)
    247	 * primary overlay ID 0.
    248	 * From mcde_hw.c ovly_update_registers() in the vendor tree
    249	 */
    250	val = 0 << MCDE_EXTSRCXCONF_BUF_ID_SHIFT;
    251	val |= 1 << MCDE_EXTSRCXCONF_BUF_NB_SHIFT;
    252	val |= 0 << MCDE_EXTSRCXCONF_PRI_OVLID_SHIFT;
    253
    254	switch (format) {
    255	case DRM_FORMAT_ARGB8888:
    256		val |= MCDE_EXTSRCXCONF_BPP_ARGB8888 <<
    257			MCDE_EXTSRCXCONF_BPP_SHIFT;
    258		break;
    259	case DRM_FORMAT_ABGR8888:
    260		val |= MCDE_EXTSRCXCONF_BPP_ARGB8888 <<
    261			MCDE_EXTSRCXCONF_BPP_SHIFT;
    262		val |= MCDE_EXTSRCXCONF_BGR;
    263		break;
    264	case DRM_FORMAT_XRGB8888:
    265		val |= MCDE_EXTSRCXCONF_BPP_XRGB8888 <<
    266			MCDE_EXTSRCXCONF_BPP_SHIFT;
    267		break;
    268	case DRM_FORMAT_XBGR8888:
    269		val |= MCDE_EXTSRCXCONF_BPP_XRGB8888 <<
    270			MCDE_EXTSRCXCONF_BPP_SHIFT;
    271		val |= MCDE_EXTSRCXCONF_BGR;
    272		break;
    273	case DRM_FORMAT_RGB888:
    274		val |= MCDE_EXTSRCXCONF_BPP_RGB888 <<
    275			MCDE_EXTSRCXCONF_BPP_SHIFT;
    276		break;
    277	case DRM_FORMAT_BGR888:
    278		val |= MCDE_EXTSRCXCONF_BPP_RGB888 <<
    279			MCDE_EXTSRCXCONF_BPP_SHIFT;
    280		val |= MCDE_EXTSRCXCONF_BGR;
    281		break;
    282	case DRM_FORMAT_ARGB4444:
    283		val |= MCDE_EXTSRCXCONF_BPP_ARGB4444 <<
    284			MCDE_EXTSRCXCONF_BPP_SHIFT;
    285		break;
    286	case DRM_FORMAT_ABGR4444:
    287		val |= MCDE_EXTSRCXCONF_BPP_ARGB4444 <<
    288			MCDE_EXTSRCXCONF_BPP_SHIFT;
    289		val |= MCDE_EXTSRCXCONF_BGR;
    290		break;
    291	case DRM_FORMAT_XRGB4444:
    292		val |= MCDE_EXTSRCXCONF_BPP_RGB444 <<
    293			MCDE_EXTSRCXCONF_BPP_SHIFT;
    294		break;
    295	case DRM_FORMAT_XBGR4444:
    296		val |= MCDE_EXTSRCXCONF_BPP_RGB444 <<
    297			MCDE_EXTSRCXCONF_BPP_SHIFT;
    298		val |= MCDE_EXTSRCXCONF_BGR;
    299		break;
    300	case DRM_FORMAT_XRGB1555:
    301		val |= MCDE_EXTSRCXCONF_BPP_IRGB1555 <<
    302			MCDE_EXTSRCXCONF_BPP_SHIFT;
    303		break;
    304	case DRM_FORMAT_XBGR1555:
    305		val |= MCDE_EXTSRCXCONF_BPP_IRGB1555 <<
    306			MCDE_EXTSRCXCONF_BPP_SHIFT;
    307		val |= MCDE_EXTSRCXCONF_BGR;
    308		break;
    309	case DRM_FORMAT_RGB565:
    310		val |= MCDE_EXTSRCXCONF_BPP_RGB565 <<
    311			MCDE_EXTSRCXCONF_BPP_SHIFT;
    312		break;
    313	case DRM_FORMAT_BGR565:
    314		val |= MCDE_EXTSRCXCONF_BPP_RGB565 <<
    315			MCDE_EXTSRCXCONF_BPP_SHIFT;
    316		val |= MCDE_EXTSRCXCONF_BGR;
    317		break;
    318	case DRM_FORMAT_YUV422:
    319		val |= MCDE_EXTSRCXCONF_BPP_YCBCR422 <<
    320			MCDE_EXTSRCXCONF_BPP_SHIFT;
    321		break;
    322	default:
    323		dev_err(mcde->dev, "Unknown pixel format 0x%08x\n",
    324			format);
    325		return -EINVAL;
    326	}
    327	writel(val, mcde->regs + conf);
    328
    329	/* Software select, primary */
    330	val = MCDE_EXTSRCXCR_SEL_MOD_SOFTWARE_SEL;
    331	val |= MCDE_EXTSRCXCR_MULTIOVL_CTRL_PRIMARY;
    332	writel(val, mcde->regs + cr);
    333
    334	return 0;
    335}
    336
    337static void mcde_configure_overlay(struct mcde *mcde, enum mcde_overlay ovl,
    338				   enum mcde_extsrc src,
    339				   enum mcde_channel ch,
    340				   const struct drm_display_mode *mode,
    341				   u32 format, int cpp)
    342{
    343	u32 val;
    344	u32 conf1;
    345	u32 conf2;
    346	u32 crop;
    347	u32 ljinc;
    348	u32 cr;
    349	u32 comp;
    350	u32 pixel_fetcher_watermark;
    351
    352	switch (ovl) {
    353	case MCDE_OVERLAY_0:
    354		conf1 = MCDE_OVL0CONF;
    355		conf2 = MCDE_OVL0CONF2;
    356		crop = MCDE_OVL0CROP;
    357		ljinc = MCDE_OVL0LJINC;
    358		cr = MCDE_OVL0CR;
    359		comp = MCDE_OVL0COMP;
    360		break;
    361	case MCDE_OVERLAY_1:
    362		conf1 = MCDE_OVL1CONF;
    363		conf2 = MCDE_OVL1CONF2;
    364		crop = MCDE_OVL1CROP;
    365		ljinc = MCDE_OVL1LJINC;
    366		cr = MCDE_OVL1CR;
    367		comp = MCDE_OVL1COMP;
    368		break;
    369	case MCDE_OVERLAY_2:
    370		conf1 = MCDE_OVL2CONF;
    371		conf2 = MCDE_OVL2CONF2;
    372		crop = MCDE_OVL2CROP;
    373		ljinc = MCDE_OVL2LJINC;
    374		cr = MCDE_OVL2CR;
    375		comp = MCDE_OVL2COMP;
    376		break;
    377	case MCDE_OVERLAY_3:
    378		conf1 = MCDE_OVL3CONF;
    379		conf2 = MCDE_OVL3CONF2;
    380		crop = MCDE_OVL3CROP;
    381		ljinc = MCDE_OVL3LJINC;
    382		cr = MCDE_OVL3CR;
    383		comp = MCDE_OVL3COMP;
    384		break;
    385	case MCDE_OVERLAY_4:
    386		conf1 = MCDE_OVL4CONF;
    387		conf2 = MCDE_OVL4CONF2;
    388		crop = MCDE_OVL4CROP;
    389		ljinc = MCDE_OVL4LJINC;
    390		cr = MCDE_OVL4CR;
    391		comp = MCDE_OVL4COMP;
    392		break;
    393	case MCDE_OVERLAY_5:
    394		conf1 = MCDE_OVL5CONF;
    395		conf2 = MCDE_OVL5CONF2;
    396		crop = MCDE_OVL5CROP;
    397		ljinc = MCDE_OVL5LJINC;
    398		cr = MCDE_OVL5CR;
    399		comp = MCDE_OVL5COMP;
    400		break;
    401	}
    402
    403	val = mode->hdisplay << MCDE_OVLXCONF_PPL_SHIFT;
    404	val |= mode->vdisplay << MCDE_OVLXCONF_LPF_SHIFT;
    405	/* Use external source 0 that we just configured */
    406	val |= src << MCDE_OVLXCONF_EXTSRC_ID_SHIFT;
    407	writel(val, mcde->regs + conf1);
    408
    409	val = MCDE_OVLXCONF2_BP_PER_PIXEL_ALPHA;
    410	val |= 0xff << MCDE_OVLXCONF2_ALPHAVALUE_SHIFT;
    411	/* OPQ: overlay is opaque */
    412	switch (format) {
    413	case DRM_FORMAT_ARGB8888:
    414	case DRM_FORMAT_ABGR8888:
    415	case DRM_FORMAT_ARGB4444:
    416	case DRM_FORMAT_ABGR4444:
    417	case DRM_FORMAT_XRGB1555:
    418	case DRM_FORMAT_XBGR1555:
    419		/* No OPQ */
    420		break;
    421	case DRM_FORMAT_XRGB8888:
    422	case DRM_FORMAT_XBGR8888:
    423	case DRM_FORMAT_RGB888:
    424	case DRM_FORMAT_BGR888:
    425	case DRM_FORMAT_RGB565:
    426	case DRM_FORMAT_BGR565:
    427	case DRM_FORMAT_YUV422:
    428		val |= MCDE_OVLXCONF2_OPQ;
    429		break;
    430	default:
    431		dev_err(mcde->dev, "Unknown pixel format 0x%08x\n",
    432			format);
    433		break;
    434	}
    435
    436	/*
    437	 * Pixel fetch watermark level is max 0x1FFF pixels.
    438	 * Two basic rules should be followed:
    439	 * 1. The value should be at least 256 bits.
    440	 * 2. The sum of all active overlays pixelfetch watermark level
    441	 *    multiplied with bits per pixel, should be lower than the
    442	 *    size of input_fifo_size in bits.
    443	 * 3. The value should be a multiple of a line (256 bits).
    444	 */
    445	switch (cpp) {
    446	case 2:
    447		pixel_fetcher_watermark = 128;
    448		break;
    449	case 3:
    450		pixel_fetcher_watermark = 96;
    451		break;
    452	case 4:
    453		pixel_fetcher_watermark = 48;
    454		break;
    455	default:
    456		pixel_fetcher_watermark = 48;
    457		break;
    458	}
    459	dev_dbg(mcde->dev, "pixel fetcher watermark level %d pixels\n",
    460		pixel_fetcher_watermark);
    461	val |= pixel_fetcher_watermark << MCDE_OVLXCONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT;
    462	writel(val, mcde->regs + conf2);
    463
    464	/* Number of bytes to fetch per line */
    465	writel(mcde->stride, mcde->regs + ljinc);
    466	/* No cropping */
    467	writel(0, mcde->regs + crop);
    468
    469	/* Set up overlay control register */
    470	val = MCDE_OVLXCR_OVLEN;
    471	val |= MCDE_OVLXCR_COLCCTRL_DISABLED;
    472	val |= MCDE_OVLXCR_BURSTSIZE_8W <<
    473		MCDE_OVLXCR_BURSTSIZE_SHIFT;
    474	val |= MCDE_OVLXCR_MAXOUTSTANDING_8_REQ <<
    475		MCDE_OVLXCR_MAXOUTSTANDING_SHIFT;
    476	/* Not using rotation but set it up anyways */
    477	val |= MCDE_OVLXCR_ROTBURSTSIZE_8W <<
    478		MCDE_OVLXCR_ROTBURSTSIZE_SHIFT;
    479	writel(val, mcde->regs + cr);
    480
    481	/*
    482	 * Set up the overlay compositor to route the overlay out to
    483	 * the desired channel
    484	 */
    485	val = ch << MCDE_OVLXCOMP_CH_ID_SHIFT;
    486	writel(val, mcde->regs + comp);
    487}
    488
    489static void mcde_configure_channel(struct mcde *mcde, enum mcde_channel ch,
    490				   enum mcde_fifo fifo,
    491				   const struct drm_display_mode *mode)
    492{
    493	u32 val;
    494	u32 conf;
    495	u32 sync;
    496	u32 stat;
    497	u32 bgcol;
    498	u32 mux;
    499
    500	switch (ch) {
    501	case MCDE_CHANNEL_0:
    502		conf = MCDE_CHNL0CONF;
    503		sync = MCDE_CHNL0SYNCHMOD;
    504		stat = MCDE_CHNL0STAT;
    505		bgcol = MCDE_CHNL0BCKGNDCOL;
    506		mux = MCDE_CHNL0MUXING;
    507		break;
    508	case MCDE_CHANNEL_1:
    509		conf = MCDE_CHNL1CONF;
    510		sync = MCDE_CHNL1SYNCHMOD;
    511		stat = MCDE_CHNL1STAT;
    512		bgcol = MCDE_CHNL1BCKGNDCOL;
    513		mux = MCDE_CHNL1MUXING;
    514		break;
    515	case MCDE_CHANNEL_2:
    516		conf = MCDE_CHNL2CONF;
    517		sync = MCDE_CHNL2SYNCHMOD;
    518		stat = MCDE_CHNL2STAT;
    519		bgcol = MCDE_CHNL2BCKGNDCOL;
    520		mux = MCDE_CHNL2MUXING;
    521		break;
    522	case MCDE_CHANNEL_3:
    523		conf = MCDE_CHNL3CONF;
    524		sync = MCDE_CHNL3SYNCHMOD;
    525		stat = MCDE_CHNL3STAT;
    526		bgcol = MCDE_CHNL3BCKGNDCOL;
    527		mux = MCDE_CHNL3MUXING;
    528		return;
    529	}
    530
    531	/* Set up channel 0 sync (based on chnl_update_registers()) */
    532	switch (mcde->flow_mode) {
    533	case MCDE_COMMAND_ONESHOT_FLOW:
    534		/* Oneshot is achieved with software sync */
    535		val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SOFTWARE
    536			<< MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
    537		break;
    538	case MCDE_COMMAND_TE_FLOW:
    539		val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE
    540			<< MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
    541		val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0
    542			<< MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
    543		break;
    544	case MCDE_COMMAND_BTA_TE_FLOW:
    545		val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE
    546			<< MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
    547		/*
    548		 * TODO:
    549		 * The vendor driver uses the formatter as sync source
    550		 * for BTA TE mode. Test to use TE if you have a panel
    551		 * that uses this mode.
    552		 */
    553		val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER
    554			<< MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
    555		break;
    556	case MCDE_VIDEO_TE_FLOW:
    557		val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE
    558			<< MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
    559		val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0
    560			<< MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
    561		break;
    562	case MCDE_VIDEO_FORMATTER_FLOW:
    563	case MCDE_DPI_FORMATTER_FLOW:
    564		val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE
    565			<< MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT;
    566		val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER
    567			<< MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT;
    568		break;
    569	default:
    570		dev_err(mcde->dev, "unknown flow mode %d\n",
    571			mcde->flow_mode);
    572		return;
    573	}
    574
    575	writel(val, mcde->regs + sync);
    576
    577	/* Set up pixels per line and lines per frame */
    578	val = (mode->hdisplay - 1) << MCDE_CHNLXCONF_PPL_SHIFT;
    579	val |= (mode->vdisplay - 1) << MCDE_CHNLXCONF_LPF_SHIFT;
    580	writel(val, mcde->regs + conf);
    581
    582	/*
    583	 * Normalize color conversion:
    584	 * black background, OLED conversion disable on channel
    585	 */
    586	val = MCDE_CHNLXSTAT_CHNLBLBCKGND_EN |
    587		MCDE_CHNLXSTAT_CHNLRD;
    588	writel(val, mcde->regs + stat);
    589	writel(0, mcde->regs + bgcol);
    590
    591	/* Set up muxing: connect the channel to the desired FIFO */
    592	switch (fifo) {
    593	case MCDE_FIFO_A:
    594		writel(MCDE_CHNLXMUXING_FIFO_ID_FIFO_A,
    595		       mcde->regs + mux);
    596		break;
    597	case MCDE_FIFO_B:
    598		writel(MCDE_CHNLXMUXING_FIFO_ID_FIFO_B,
    599		       mcde->regs + mux);
    600		break;
    601	}
    602
    603	/*
    604	 * If using DPI configure the sync event.
    605	 * TODO: this is for LCD only, it does not cover TV out.
    606	 */
    607	if (mcde->dpi_output) {
    608		u32 stripwidth;
    609
    610		stripwidth = 0xF000 / (mode->vdisplay * 4);
    611		dev_info(mcde->dev, "stripwidth: %d\n", stripwidth);
    612
    613		val = MCDE_SYNCHCONF_HWREQVEVENT_ACTIVE_VIDEO |
    614			(mode->hdisplay - 1 - stripwidth) << MCDE_SYNCHCONF_HWREQVCNT_SHIFT |
    615			MCDE_SYNCHCONF_SWINTVEVENT_ACTIVE_VIDEO |
    616			(mode->hdisplay - 1 - stripwidth) << MCDE_SYNCHCONF_SWINTVCNT_SHIFT;
    617
    618		switch (fifo) {
    619		case MCDE_FIFO_A:
    620			writel(val, mcde->regs + MCDE_SYNCHCONFA);
    621			break;
    622		case MCDE_FIFO_B:
    623			writel(val, mcde->regs + MCDE_SYNCHCONFB);
    624			break;
    625		}
    626	}
    627}
    628
    629static void mcde_configure_fifo(struct mcde *mcde, enum mcde_fifo fifo,
    630				enum mcde_formatter fmt,
    631				int fifo_wtrmrk)
    632{
    633	u32 val;
    634	u32 ctrl;
    635	u32 cr0, cr1;
    636
    637	switch (fifo) {
    638	case MCDE_FIFO_A:
    639		ctrl = MCDE_CTRLA;
    640		cr0 = MCDE_CRA0;
    641		cr1 = MCDE_CRA1;
    642		break;
    643	case MCDE_FIFO_B:
    644		ctrl = MCDE_CTRLB;
    645		cr0 = MCDE_CRB0;
    646		cr1 = MCDE_CRB1;
    647		break;
    648	}
    649
    650	val = fifo_wtrmrk << MCDE_CTRLX_FIFOWTRMRK_SHIFT;
    651
    652	/*
    653	 * Select the formatter to use for this FIFO
    654	 *
    655	 * The register definitions imply that different IDs should be used
    656	 * by the DSI formatters depending on if they are in VID or CMD
    657	 * mode, and the manual says they are dedicated but identical.
    658	 * The vendor code uses them as it seems fit.
    659	 */
    660	switch (fmt) {
    661	case MCDE_DSI_FORMATTER_0:
    662		val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
    663		val |= MCDE_CTRLX_FORMID_DSI0VID << MCDE_CTRLX_FORMID_SHIFT;
    664		break;
    665	case MCDE_DSI_FORMATTER_1:
    666		val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
    667		val |= MCDE_CTRLX_FORMID_DSI0CMD << MCDE_CTRLX_FORMID_SHIFT;
    668		break;
    669	case MCDE_DSI_FORMATTER_2:
    670		val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
    671		val |= MCDE_CTRLX_FORMID_DSI1VID << MCDE_CTRLX_FORMID_SHIFT;
    672		break;
    673	case MCDE_DSI_FORMATTER_3:
    674		val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
    675		val |= MCDE_CTRLX_FORMID_DSI1CMD << MCDE_CTRLX_FORMID_SHIFT;
    676		break;
    677	case MCDE_DSI_FORMATTER_4:
    678		val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
    679		val |= MCDE_CTRLX_FORMID_DSI2VID << MCDE_CTRLX_FORMID_SHIFT;
    680		break;
    681	case MCDE_DSI_FORMATTER_5:
    682		val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
    683		val |= MCDE_CTRLX_FORMID_DSI2CMD << MCDE_CTRLX_FORMID_SHIFT;
    684		break;
    685	case MCDE_DPI_FORMATTER_0:
    686		val |= MCDE_CTRLX_FORMTYPE_DPITV << MCDE_CTRLX_FORMTYPE_SHIFT;
    687		val |= MCDE_CTRLX_FORMID_DPIA << MCDE_CTRLX_FORMID_SHIFT;
    688		break;
    689	case MCDE_DPI_FORMATTER_1:
    690		val |= MCDE_CTRLX_FORMTYPE_DPITV << MCDE_CTRLX_FORMTYPE_SHIFT;
    691		val |= MCDE_CTRLX_FORMID_DPIB << MCDE_CTRLX_FORMID_SHIFT;
    692		break;
    693	}
    694	writel(val, mcde->regs + ctrl);
    695
    696	/* Blend source with Alpha 0xff on FIFO */
    697	val = MCDE_CRX0_BLENDEN |
    698		0xff << MCDE_CRX0_ALPHABLEND_SHIFT;
    699	writel(val, mcde->regs + cr0);
    700
    701	spin_lock(&mcde->fifo_crx1_lock);
    702	val = readl(mcde->regs + cr1);
    703	/*
    704	 * Set-up from mcde_fmtr_dsi.c, fmtr_dsi_enable_video()
    705	 * FIXME: a different clock needs to be selected for TV out.
    706	 */
    707	if (mcde->dpi_output) {
    708		struct drm_connector *connector = drm_panel_bridge_connector(mcde->bridge);
    709		u32 bus_format;
    710
    711		/* Assume RGB888 24 bit if we have no further info */
    712		if (!connector->display_info.num_bus_formats) {
    713			dev_info(mcde->dev, "panel does not specify bus format, assume RGB888\n");
    714			bus_format = MEDIA_BUS_FMT_RGB888_1X24;
    715		} else {
    716			bus_format = connector->display_info.bus_formats[0];
    717		}
    718
    719		/*
    720		 * Set up the CDWIN and OUTBPP for the LCD
    721		 *
    722		 * FIXME: fill this in if you know the correspondance between the MIPI
    723		 * DPI specification and the media bus formats.
    724		 */
    725		val &= ~MCDE_CRX1_CDWIN_MASK;
    726		val &= ~MCDE_CRX1_OUTBPP_MASK;
    727		switch (bus_format) {
    728		case MEDIA_BUS_FMT_RGB888_1X24:
    729			val |= MCDE_CRX1_CDWIN_24BPP << MCDE_CRX1_CDWIN_SHIFT;
    730			val |= MCDE_CRX1_OUTBPP_24BPP << MCDE_CRX1_OUTBPP_SHIFT;
    731			break;
    732		default:
    733			dev_err(mcde->dev, "unknown bus format, assume RGB888\n");
    734			val |= MCDE_CRX1_CDWIN_24BPP << MCDE_CRX1_CDWIN_SHIFT;
    735			val |= MCDE_CRX1_OUTBPP_24BPP << MCDE_CRX1_OUTBPP_SHIFT;
    736			break;
    737		}
    738	} else {
    739		/* Use the MCDE clock for DSI */
    740		val &= ~MCDE_CRX1_CLKSEL_MASK;
    741		val |= MCDE_CRX1_CLKSEL_MCDECLK << MCDE_CRX1_CLKSEL_SHIFT;
    742	}
    743	writel(val, mcde->regs + cr1);
    744	spin_unlock(&mcde->fifo_crx1_lock);
    745};
    746
    747static void mcde_configure_dsi_formatter(struct mcde *mcde,
    748					 enum mcde_formatter fmt,
    749					 u32 formatter_frame,
    750					 int pkt_size)
    751{
    752	u32 val;
    753	u32 conf0;
    754	u32 frame;
    755	u32 pkt;
    756	u32 sync;
    757	u32 cmdw;
    758	u32 delay0, delay1;
    759
    760	switch (fmt) {
    761	case MCDE_DSI_FORMATTER_0:
    762		conf0 = MCDE_DSIVID0CONF0;
    763		frame = MCDE_DSIVID0FRAME;
    764		pkt = MCDE_DSIVID0PKT;
    765		sync = MCDE_DSIVID0SYNC;
    766		cmdw = MCDE_DSIVID0CMDW;
    767		delay0 = MCDE_DSIVID0DELAY0;
    768		delay1 = MCDE_DSIVID0DELAY1;
    769		break;
    770	case MCDE_DSI_FORMATTER_1:
    771		conf0 = MCDE_DSIVID1CONF0;
    772		frame = MCDE_DSIVID1FRAME;
    773		pkt = MCDE_DSIVID1PKT;
    774		sync = MCDE_DSIVID1SYNC;
    775		cmdw = MCDE_DSIVID1CMDW;
    776		delay0 = MCDE_DSIVID1DELAY0;
    777		delay1 = MCDE_DSIVID1DELAY1;
    778		break;
    779	case MCDE_DSI_FORMATTER_2:
    780		conf0 = MCDE_DSIVID2CONF0;
    781		frame = MCDE_DSIVID2FRAME;
    782		pkt = MCDE_DSIVID2PKT;
    783		sync = MCDE_DSIVID2SYNC;
    784		cmdw = MCDE_DSIVID2CMDW;
    785		delay0 = MCDE_DSIVID2DELAY0;
    786		delay1 = MCDE_DSIVID2DELAY1;
    787		break;
    788	default:
    789		dev_err(mcde->dev, "tried to configure a non-DSI formatter as DSI\n");
    790		return;
    791	}
    792
    793	/*
    794	 * Enable formatter
    795	 * 8 bit commands and DCS commands (notgen = not generic)
    796	 */
    797	val = MCDE_DSICONF0_CMD8 | MCDE_DSICONF0_DCSVID_NOTGEN;
    798	if (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO)
    799		val |= MCDE_DSICONF0_VID_MODE_VID;
    800	switch (mcde->mdsi->format) {
    801	case MIPI_DSI_FMT_RGB888:
    802		val |= MCDE_DSICONF0_PACKING_RGB888 <<
    803			MCDE_DSICONF0_PACKING_SHIFT;
    804		break;
    805	case MIPI_DSI_FMT_RGB666:
    806		val |= MCDE_DSICONF0_PACKING_RGB666 <<
    807			MCDE_DSICONF0_PACKING_SHIFT;
    808		break;
    809	case MIPI_DSI_FMT_RGB666_PACKED:
    810		dev_err(mcde->dev,
    811			"we cannot handle the packed RGB666 format\n");
    812		val |= MCDE_DSICONF0_PACKING_RGB666 <<
    813			MCDE_DSICONF0_PACKING_SHIFT;
    814		break;
    815	case MIPI_DSI_FMT_RGB565:
    816		val |= MCDE_DSICONF0_PACKING_RGB565 <<
    817			MCDE_DSICONF0_PACKING_SHIFT;
    818		break;
    819	default:
    820		dev_err(mcde->dev, "unknown DSI format\n");
    821		return;
    822	}
    823	writel(val, mcde->regs + conf0);
    824
    825	writel(formatter_frame, mcde->regs + frame);
    826	writel(pkt_size, mcde->regs + pkt);
    827	writel(0, mcde->regs + sync);
    828	/* Define the MIPI command: we want to write into display memory */
    829	val = MIPI_DCS_WRITE_MEMORY_CONTINUE <<
    830		MCDE_DSIVIDXCMDW_CMDW_CONTINUE_SHIFT;
    831	val |= MIPI_DCS_WRITE_MEMORY_START <<
    832		MCDE_DSIVIDXCMDW_CMDW_START_SHIFT;
    833	writel(val, mcde->regs + cmdw);
    834
    835	/*
    836	 * FIXME: the vendor driver has some hack around this value in
    837	 * CMD mode with autotrig.
    838	 */
    839	writel(0, mcde->regs + delay0);
    840	writel(0, mcde->regs + delay1);
    841}
    842
    843static void mcde_enable_fifo(struct mcde *mcde, enum mcde_fifo fifo)
    844{
    845	u32 val;
    846	u32 cr;
    847
    848	switch (fifo) {
    849	case MCDE_FIFO_A:
    850		cr = MCDE_CRA0;
    851		break;
    852	case MCDE_FIFO_B:
    853		cr = MCDE_CRB0;
    854		break;
    855	default:
    856		dev_err(mcde->dev, "cannot enable FIFO %c\n",
    857			'A' + fifo);
    858		return;
    859	}
    860
    861	spin_lock(&mcde->flow_lock);
    862	val = readl(mcde->regs + cr);
    863	val |= MCDE_CRX0_FLOEN;
    864	writel(val, mcde->regs + cr);
    865	mcde->flow_active++;
    866	spin_unlock(&mcde->flow_lock);
    867}
    868
    869static void mcde_disable_fifo(struct mcde *mcde, enum mcde_fifo fifo,
    870			      bool wait_for_drain)
    871{
    872	int timeout = 100;
    873	u32 val;
    874	u32 cr;
    875
    876	switch (fifo) {
    877	case MCDE_FIFO_A:
    878		cr = MCDE_CRA0;
    879		break;
    880	case MCDE_FIFO_B:
    881		cr = MCDE_CRB0;
    882		break;
    883	default:
    884		dev_err(mcde->dev, "cannot disable FIFO %c\n",
    885			'A' + fifo);
    886		return;
    887	}
    888
    889	spin_lock(&mcde->flow_lock);
    890	val = readl(mcde->regs + cr);
    891	val &= ~MCDE_CRX0_FLOEN;
    892	writel(val, mcde->regs + cr);
    893	mcde->flow_active = 0;
    894	spin_unlock(&mcde->flow_lock);
    895
    896	if (!wait_for_drain)
    897		return;
    898
    899	/* Check that we really drained and stopped the flow */
    900	while (readl(mcde->regs + cr) & MCDE_CRX0_FLOEN) {
    901		usleep_range(1000, 1500);
    902		if (!--timeout) {
    903			dev_err(mcde->dev,
    904				"FIFO timeout while clearing FIFO %c\n",
    905				'A' + fifo);
    906			return;
    907		}
    908	}
    909}
    910
    911/*
    912 * This drains a pipe i.e. a FIFO connected to a certain channel
    913 */
    914static void mcde_drain_pipe(struct mcde *mcde, enum mcde_fifo fifo,
    915			    enum mcde_channel ch)
    916{
    917	u32 val;
    918	u32 ctrl;
    919	u32 synsw;
    920
    921	switch (fifo) {
    922	case MCDE_FIFO_A:
    923		ctrl = MCDE_CTRLA;
    924		break;
    925	case MCDE_FIFO_B:
    926		ctrl = MCDE_CTRLB;
    927		break;
    928	}
    929
    930	switch (ch) {
    931	case MCDE_CHANNEL_0:
    932		synsw = MCDE_CHNL0SYNCHSW;
    933		break;
    934	case MCDE_CHANNEL_1:
    935		synsw = MCDE_CHNL1SYNCHSW;
    936		break;
    937	case MCDE_CHANNEL_2:
    938		synsw = MCDE_CHNL2SYNCHSW;
    939		break;
    940	case MCDE_CHANNEL_3:
    941		synsw = MCDE_CHNL3SYNCHSW;
    942		return;
    943	}
    944
    945	val = readl(mcde->regs + ctrl);
    946	if (!(val & MCDE_CTRLX_FIFOEMPTY)) {
    947		dev_err(mcde->dev, "Channel A FIFO not empty (handover)\n");
    948		/* Attempt to clear the FIFO */
    949		mcde_enable_fifo(mcde, fifo);
    950		/* Trigger a software sync out on respective channel (0-3) */
    951		writel(MCDE_CHNLXSYNCHSW_SW_TRIG, mcde->regs + synsw);
    952		/* Disable FIFO A flow again */
    953		mcde_disable_fifo(mcde, fifo, true);
    954	}
    955}
    956
    957static int mcde_dsi_get_pkt_div(int ppl, int fifo_size)
    958{
    959	/*
    960	 * DSI command mode line packets should be split into an even number of
    961	 * packets smaller than or equal to the fifo size.
    962	 */
    963	int div;
    964	const int max_div = DIV_ROUND_UP(MCDE_MAX_WIDTH, fifo_size);
    965
    966	for (div = 1; div < max_div; div++)
    967		if (ppl % div == 0 && ppl / div <= fifo_size)
    968			return div;
    969	return 1;
    970}
    971
    972static void mcde_setup_dpi(struct mcde *mcde, const struct drm_display_mode *mode,
    973			   int *fifo_wtrmrk_lvl)
    974{
    975	struct drm_connector *connector = drm_panel_bridge_connector(mcde->bridge);
    976	u32 hsw, hfp, hbp;
    977	u32 vsw, vfp, vbp;
    978	u32 val;
    979
    980	/* FIXME: we only support LCD, implement TV out */
    981	hsw = mode->hsync_end - mode->hsync_start;
    982	hfp = mode->hsync_start - mode->hdisplay;
    983	hbp = mode->htotal - mode->hsync_end;
    984	vsw = mode->vsync_end - mode->vsync_start;
    985	vfp = mode->vsync_start - mode->vdisplay;
    986	vbp = mode->vtotal - mode->vsync_end;
    987
    988	dev_info(mcde->dev, "output on DPI LCD from channel A\n");
    989	/* Display actual values */
    990	dev_info(mcde->dev, "HSW: %d, HFP: %d, HBP: %d, VSW: %d, VFP: %d, VBP: %d\n",
    991		 hsw, hfp, hbp, vsw, vfp, vbp);
    992
    993	/*
    994	 * The pixel fetcher is 128 64-bit words deep = 1024 bytes.
    995	 * One overlay of 32bpp (4 cpp) assumed, fetch 160 pixels.
    996	 * 160 * 4 = 640 bytes.
    997	 */
    998	*fifo_wtrmrk_lvl = 640;
    999
   1000	/* Set up the main control, watermark level at 7 */
   1001	val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT;
   1002
   1003	/*
   1004	 * This sets up the internal silicon muxing of the DPI
   1005	 * lines. This is how the silicon connects out to the
   1006	 * external pins, then the pins need to be further
   1007	 * configured into "alternate functions" using pin control
   1008	 * to actually get the signals out.
   1009	 *
   1010	 * FIXME: this is hardcoded to the only setting found in
   1011	 * the wild. If we need to use different settings for
   1012	 * different DPI displays, make this parameterizable from
   1013	 * the device tree.
   1014	 */
   1015	/* 24 bits DPI: connect Ch A LSB to D[0:7] */
   1016	val |= 0 << MCDE_CONF0_OUTMUX0_SHIFT;
   1017	/* 24 bits DPI: connect Ch A MID to D[8:15] */
   1018	val |= 1 << MCDE_CONF0_OUTMUX1_SHIFT;
   1019	/* Don't care about this muxing */
   1020	val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT;
   1021	/* Don't care about this muxing */
   1022	val |= 0 << MCDE_CONF0_OUTMUX3_SHIFT;
   1023	/* 24 bits DPI: connect Ch A MSB to D[32:39] */
   1024	val |= 2 << MCDE_CONF0_OUTMUX4_SHIFT;
   1025	/* Syncmux bits zero: DPI channel A */
   1026	writel(val, mcde->regs + MCDE_CONF0);
   1027
   1028	/* This hammers us into LCD mode */
   1029	writel(0, mcde->regs + MCDE_TVCRA);
   1030
   1031	/* Front porch and sync width */
   1032	val = (vsw << MCDE_TVBL1_BEL1_SHIFT);
   1033	val |= (vfp << MCDE_TVBL1_BSL1_SHIFT);
   1034	writel(val, mcde->regs + MCDE_TVBL1A);
   1035	/* The vendor driver sets the same value into TVBL2A */
   1036	writel(val, mcde->regs + MCDE_TVBL2A);
   1037
   1038	/* Vertical back porch */
   1039	val = (vbp << MCDE_TVDVO_DVO1_SHIFT);
   1040	/* The vendor drivers sets the same value into TVDVOA */
   1041	val |= (vbp << MCDE_TVDVO_DVO2_SHIFT);
   1042	writel(val, mcde->regs + MCDE_TVDVOA);
   1043
   1044	/* Horizontal back porch, as 0 = 1 cycle we need to subtract 1 */
   1045	writel((hbp - 1), mcde->regs + MCDE_TVTIM1A);
   1046
   1047	/* Horizongal sync width and horizonal front porch, 0 = 1 cycle */
   1048	val = ((hsw - 1) << MCDE_TVLBALW_LBW_SHIFT);
   1049	val |= ((hfp - 1) << MCDE_TVLBALW_ALW_SHIFT);
   1050	writel(val, mcde->regs + MCDE_TVLBALWA);
   1051
   1052	/* Blank some TV registers we don't use */
   1053	writel(0, mcde->regs + MCDE_TVISLA);
   1054	writel(0, mcde->regs + MCDE_TVBLUA);
   1055
   1056	/* Set up sync inversion etc */
   1057	val = 0;
   1058	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
   1059		val |= MCDE_LCDTIM1B_IHS;
   1060	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
   1061		val |= MCDE_LCDTIM1B_IVS;
   1062	if (connector->display_info.bus_flags & DRM_BUS_FLAG_DE_LOW)
   1063		val |= MCDE_LCDTIM1B_IOE;
   1064	if (connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
   1065		val |= MCDE_LCDTIM1B_IPC;
   1066	writel(val, mcde->regs + MCDE_LCDTIM1A);
   1067}
   1068
   1069static void mcde_setup_dsi(struct mcde *mcde, const struct drm_display_mode *mode,
   1070			   int cpp, int *fifo_wtrmrk_lvl, int *dsi_formatter_frame,
   1071			   int *dsi_pkt_size)
   1072{
   1073	u32 formatter_ppl = mode->hdisplay; /* pixels per line */
   1074	u32 formatter_lpf = mode->vdisplay; /* lines per frame */
   1075	int formatter_frame;
   1076	int formatter_cpp;
   1077	int fifo_wtrmrk;
   1078	u32 pkt_div;
   1079	int pkt_size;
   1080	u32 val;
   1081
   1082	dev_info(mcde->dev, "output in %s mode, format %dbpp\n",
   1083		 (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ?
   1084		 "VIDEO" : "CMD",
   1085		 mipi_dsi_pixel_format_to_bpp(mcde->mdsi->format));
   1086	formatter_cpp =
   1087		mipi_dsi_pixel_format_to_bpp(mcde->mdsi->format) / 8;
   1088	dev_info(mcde->dev, "Overlay CPP: %d bytes, DSI formatter CPP %d bytes\n",
   1089		 cpp, formatter_cpp);
   1090
   1091	/* Set up the main control, watermark level at 7 */
   1092	val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT;
   1093
   1094	/*
   1095	 * This is the internal silicon muxing of the DPI
   1096	 * (parallell display) lines. Since we are not using
   1097	 * this at all (we are using DSI) these are just
   1098	 * dummy values from the vendor tree.
   1099	 */
   1100	val |= 3 << MCDE_CONF0_OUTMUX0_SHIFT;
   1101	val |= 3 << MCDE_CONF0_OUTMUX1_SHIFT;
   1102	val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT;
   1103	val |= 4 << MCDE_CONF0_OUTMUX3_SHIFT;
   1104	val |= 5 << MCDE_CONF0_OUTMUX4_SHIFT;
   1105	writel(val, mcde->regs + MCDE_CONF0);
   1106
   1107	/* Calculations from mcde_fmtr_dsi.c, fmtr_dsi_enable_video() */
   1108
   1109	/*
   1110	 * Set up FIFO A watermark level:
   1111	 * 128 for LCD 32bpp video mode
   1112	 * 48  for LCD 32bpp command mode
   1113	 * 128 for LCD 16bpp video mode
   1114	 * 64  for LCD 16bpp command mode
   1115	 * 128 for HDMI 32bpp
   1116	 * 192 for HDMI 16bpp
   1117	 */
   1118	fifo_wtrmrk = mode->hdisplay;
   1119	if (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
   1120		fifo_wtrmrk = min(fifo_wtrmrk, 128);
   1121		pkt_div = 1;
   1122	} else {
   1123		fifo_wtrmrk = min(fifo_wtrmrk, 48);
   1124		/* The FIFO is 640 entries deep on this v3 hardware */
   1125		pkt_div = mcde_dsi_get_pkt_div(mode->hdisplay, 640);
   1126	}
   1127	dev_dbg(mcde->dev, "FIFO watermark after flooring: %d bytes\n",
   1128		fifo_wtrmrk);
   1129	dev_dbg(mcde->dev, "Packet divisor: %d bytes\n", pkt_div);
   1130
   1131	/* NOTE: pkt_div is 1 for video mode */
   1132	pkt_size = (formatter_ppl * formatter_cpp) / pkt_div;
   1133	/* Commands CMD8 need one extra byte */
   1134	if (!(mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO))
   1135		pkt_size++;
   1136
   1137	dev_dbg(mcde->dev, "DSI packet size: %d * %d bytes per line\n",
   1138		pkt_size, pkt_div);
   1139	dev_dbg(mcde->dev, "Overlay frame size: %u bytes\n",
   1140		mode->hdisplay * mode->vdisplay * cpp);
   1141	/* NOTE: pkt_div is 1 for video mode */
   1142	formatter_frame = pkt_size * pkt_div * formatter_lpf;
   1143	dev_dbg(mcde->dev, "Formatter frame size: %u bytes\n", formatter_frame);
   1144
   1145	*fifo_wtrmrk_lvl = fifo_wtrmrk;
   1146	*dsi_pkt_size = pkt_size;
   1147	*dsi_formatter_frame = formatter_frame;
   1148}
   1149
   1150static void mcde_display_enable(struct drm_simple_display_pipe *pipe,
   1151				struct drm_crtc_state *cstate,
   1152				struct drm_plane_state *plane_state)
   1153{
   1154	struct drm_crtc *crtc = &pipe->crtc;
   1155	struct drm_plane *plane = &pipe->plane;
   1156	struct drm_device *drm = crtc->dev;
   1157	struct mcde *mcde = to_mcde(drm);
   1158	const struct drm_display_mode *mode = &cstate->mode;
   1159	struct drm_framebuffer *fb = plane->state->fb;
   1160	u32 format = fb->format->format;
   1161	int dsi_pkt_size;
   1162	int fifo_wtrmrk;
   1163	int cpp = fb->format->cpp[0];
   1164	u32 dsi_formatter_frame;
   1165	u32 val;
   1166	int ret;
   1167
   1168	/* This powers up the entire MCDE block and the DSI hardware */
   1169	ret = regulator_enable(mcde->epod);
   1170	if (ret) {
   1171		dev_err(drm->dev, "can't re-enable EPOD regulator\n");
   1172		return;
   1173	}
   1174
   1175	dev_info(drm->dev, "enable MCDE, %d x %d format %p4cc\n",
   1176		 mode->hdisplay, mode->vdisplay, &format);
   1177
   1178
   1179	/* Clear any pending interrupts */
   1180	mcde_display_disable_irqs(mcde);
   1181	writel(0, mcde->regs + MCDE_IMSCERR);
   1182	writel(0xFFFFFFFF, mcde->regs + MCDE_RISERR);
   1183
   1184	if (mcde->dpi_output)
   1185		mcde_setup_dpi(mcde, mode, &fifo_wtrmrk);
   1186	else
   1187		mcde_setup_dsi(mcde, mode, cpp, &fifo_wtrmrk,
   1188			       &dsi_formatter_frame, &dsi_pkt_size);
   1189
   1190	mcde->stride = mode->hdisplay * cpp;
   1191	dev_dbg(drm->dev, "Overlay line stride: %u bytes\n",
   1192		 mcde->stride);
   1193
   1194	/* Drain the FIFO A + channel 0 pipe so we have a clean slate */
   1195	mcde_drain_pipe(mcde, MCDE_FIFO_A, MCDE_CHANNEL_0);
   1196
   1197	/*
   1198	 * We set up our display pipeline:
   1199	 * EXTSRC 0 -> OVERLAY 0 -> CHANNEL 0 -> FIFO A -> DSI FORMATTER 0
   1200	 *
   1201	 * First configure the external source (memory) on external source 0
   1202	 * using the desired bitstream/bitmap format
   1203	 */
   1204	mcde_configure_extsrc(mcde, MCDE_EXTSRC_0, format);
   1205
   1206	/*
   1207	 * Configure overlay 0 according to format and mode and take input
   1208	 * from external source 0 and route the output of this overlay to
   1209	 * channel 0
   1210	 */
   1211	mcde_configure_overlay(mcde, MCDE_OVERLAY_0, MCDE_EXTSRC_0,
   1212			       MCDE_CHANNEL_0, mode, format, cpp);
   1213
   1214	/*
   1215	 * Configure pixel-per-line and line-per-frame for channel 0 and then
   1216	 * route channel 0 to FIFO A
   1217	 */
   1218	mcde_configure_channel(mcde, MCDE_CHANNEL_0, MCDE_FIFO_A, mode);
   1219
   1220	if (mcde->dpi_output) {
   1221		unsigned long lcd_freq;
   1222
   1223		/* Configure FIFO A to use DPI formatter 0 */
   1224		mcde_configure_fifo(mcde, MCDE_FIFO_A, MCDE_DPI_FORMATTER_0,
   1225				    fifo_wtrmrk);
   1226
   1227		/* Set up and enable the LCD clock */
   1228		lcd_freq = clk_round_rate(mcde->fifoa_clk, mode->clock * 1000);
   1229		ret = clk_set_rate(mcde->fifoa_clk, lcd_freq);
   1230		if (ret)
   1231			dev_err(mcde->dev, "failed to set LCD clock rate %lu Hz\n",
   1232				lcd_freq);
   1233		ret = clk_prepare_enable(mcde->fifoa_clk);
   1234		if (ret) {
   1235			dev_err(mcde->dev, "failed to enable FIFO A DPI clock\n");
   1236			return;
   1237		}
   1238		dev_info(mcde->dev, "LCD FIFO A clk rate %lu Hz\n",
   1239			 clk_get_rate(mcde->fifoa_clk));
   1240	} else {
   1241		/* Configure FIFO A to use DSI formatter 0 */
   1242		mcde_configure_fifo(mcde, MCDE_FIFO_A, MCDE_DSI_FORMATTER_0,
   1243				    fifo_wtrmrk);
   1244
   1245		/*
   1246		 * This brings up the DSI bridge which is tightly connected
   1247		 * to the MCDE DSI formatter.
   1248		 */
   1249		mcde_dsi_enable(mcde->bridge);
   1250
   1251		/* Configure the DSI formatter 0 for the DSI panel output */
   1252		mcde_configure_dsi_formatter(mcde, MCDE_DSI_FORMATTER_0,
   1253					     dsi_formatter_frame, dsi_pkt_size);
   1254	}
   1255
   1256	switch (mcde->flow_mode) {
   1257	case MCDE_COMMAND_TE_FLOW:
   1258	case MCDE_COMMAND_BTA_TE_FLOW:
   1259	case MCDE_VIDEO_TE_FLOW:
   1260		/* We are using TE in some combination */
   1261		if (mode->flags & DRM_MODE_FLAG_NVSYNC)
   1262			val = MCDE_VSCRC_VSPOL;
   1263		else
   1264			val = 0;
   1265		writel(val, mcde->regs + MCDE_VSCRC0);
   1266		/* Enable VSYNC capture on TE0 */
   1267		val = readl(mcde->regs + MCDE_CRC);
   1268		val |= MCDE_CRC_SYCEN0;
   1269		writel(val, mcde->regs + MCDE_CRC);
   1270		break;
   1271	default:
   1272		/* No TE capture */
   1273		break;
   1274	}
   1275
   1276	drm_crtc_vblank_on(crtc);
   1277
   1278	/*
   1279	 * If we're using oneshot mode we don't start the flow
   1280	 * until each time the display is given an update, and
   1281	 * then we disable it immediately after. For all other
   1282	 * modes (command or video) we start the FIFO flow
   1283	 * right here. This is necessary for the hardware to
   1284	 * behave right.
   1285	 */
   1286	if (mcde->flow_mode != MCDE_COMMAND_ONESHOT_FLOW) {
   1287		mcde_enable_fifo(mcde, MCDE_FIFO_A);
   1288		dev_dbg(mcde->dev, "started MCDE video FIFO flow\n");
   1289	}
   1290
   1291	/* Enable MCDE with automatic clock gating */
   1292	val = readl(mcde->regs + MCDE_CR);
   1293	val |= MCDE_CR_MCDEEN | MCDE_CR_AUTOCLKG_EN;
   1294	writel(val, mcde->regs + MCDE_CR);
   1295
   1296	dev_info(drm->dev, "MCDE display is enabled\n");
   1297}
   1298
   1299static void mcde_display_disable(struct drm_simple_display_pipe *pipe)
   1300{
   1301	struct drm_crtc *crtc = &pipe->crtc;
   1302	struct drm_device *drm = crtc->dev;
   1303	struct mcde *mcde = to_mcde(drm);
   1304	struct drm_pending_vblank_event *event;
   1305	int ret;
   1306
   1307	drm_crtc_vblank_off(crtc);
   1308
   1309	/* Disable FIFO A flow */
   1310	mcde_disable_fifo(mcde, MCDE_FIFO_A, true);
   1311
   1312	if (mcde->dpi_output) {
   1313		clk_disable_unprepare(mcde->fifoa_clk);
   1314	} else {
   1315		/* This disables the DSI bridge */
   1316		mcde_dsi_disable(mcde->bridge);
   1317	}
   1318
   1319	event = crtc->state->event;
   1320	if (event) {
   1321		crtc->state->event = NULL;
   1322
   1323		spin_lock_irq(&crtc->dev->event_lock);
   1324		drm_crtc_send_vblank_event(crtc, event);
   1325		spin_unlock_irq(&crtc->dev->event_lock);
   1326	}
   1327
   1328	ret = regulator_disable(mcde->epod);
   1329	if (ret)
   1330		dev_err(drm->dev, "can't disable EPOD regulator\n");
   1331	/* Make sure we are powered down (before we may power up again) */
   1332	usleep_range(50000, 70000);
   1333
   1334	dev_info(drm->dev, "MCDE display is disabled\n");
   1335}
   1336
   1337static void mcde_start_flow(struct mcde *mcde)
   1338{
   1339	/* Request a TE ACK only in TE+BTA mode */
   1340	if (mcde->flow_mode == MCDE_COMMAND_BTA_TE_FLOW)
   1341		mcde_dsi_te_request(mcde->mdsi);
   1342
   1343	/* Enable FIFO A flow */
   1344	mcde_enable_fifo(mcde, MCDE_FIFO_A);
   1345
   1346	/*
   1347	 * If oneshot mode is enabled, the flow will be disabled
   1348	 * when the TE0 IRQ arrives in the interrupt handler. Otherwise
   1349	 * updates are continuously streamed to the display after this
   1350	 * point.
   1351	 */
   1352
   1353	if (mcde->flow_mode == MCDE_COMMAND_ONESHOT_FLOW) {
   1354		/* Trigger a software sync out on channel 0 */
   1355		writel(MCDE_CHNLXSYNCHSW_SW_TRIG,
   1356		       mcde->regs + MCDE_CHNL0SYNCHSW);
   1357
   1358		/*
   1359		 * Disable FIFO A flow again: since we are using TE sync we
   1360		 * need to wait for the FIFO to drain before we continue
   1361		 * so repeated calls to this function will not cause a mess
   1362		 * in the hardware by pushing updates will updates are going
   1363		 * on already.
   1364		 */
   1365		mcde_disable_fifo(mcde, MCDE_FIFO_A, true);
   1366	}
   1367
   1368	dev_dbg(mcde->dev, "started MCDE FIFO flow\n");
   1369}
   1370
   1371static void mcde_set_extsrc(struct mcde *mcde, u32 buffer_address)
   1372{
   1373	/* Write bitmap base address to register */
   1374	writel(buffer_address, mcde->regs + MCDE_EXTSRCXA0);
   1375	/*
   1376	 * Base address for next line this is probably only used
   1377	 * in interlace modes.
   1378	 */
   1379	writel(buffer_address + mcde->stride, mcde->regs + MCDE_EXTSRCXA1);
   1380}
   1381
   1382static void mcde_display_update(struct drm_simple_display_pipe *pipe,
   1383				struct drm_plane_state *old_pstate)
   1384{
   1385	struct drm_crtc *crtc = &pipe->crtc;
   1386	struct drm_device *drm = crtc->dev;
   1387	struct mcde *mcde = to_mcde(drm);
   1388	struct drm_pending_vblank_event *event = crtc->state->event;
   1389	struct drm_plane *plane = &pipe->plane;
   1390	struct drm_plane_state *pstate = plane->state;
   1391	struct drm_framebuffer *fb = pstate->fb;
   1392
   1393	/*
   1394	 * Handle any pending event first, we need to arm the vblank
   1395	 * interrupt before sending any update to the display so we don't
   1396	 * miss the interrupt.
   1397	 */
   1398	if (event) {
   1399		crtc->state->event = NULL;
   1400
   1401		spin_lock_irq(&crtc->dev->event_lock);
   1402		/*
   1403		 * Hardware must be on before we can arm any vblank event,
   1404		 * this is not a scanout controller where there is always
   1405		 * some periodic update going on, it is completely frozen
   1406		 * until we get an update. If MCDE output isn't yet enabled,
   1407		 * we just send a vblank dummy event back.
   1408		 */
   1409		if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) {
   1410			dev_dbg(mcde->dev, "arm vblank event\n");
   1411			drm_crtc_arm_vblank_event(crtc, event);
   1412		} else {
   1413			dev_dbg(mcde->dev, "insert fake vblank event\n");
   1414			drm_crtc_send_vblank_event(crtc, event);
   1415		}
   1416
   1417		spin_unlock_irq(&crtc->dev->event_lock);
   1418	}
   1419
   1420	/*
   1421	 * We do not start sending framebuffer updates before the
   1422	 * display is enabled. Update events will however be dispatched
   1423	 * from the DRM core before the display is enabled.
   1424	 */
   1425	if (fb) {
   1426		mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0));
   1427		dev_info_once(mcde->dev, "first update of display contents\n");
   1428		/*
   1429		 * Usually the flow is already active, unless we are in
   1430		 * oneshot mode, then we need to kick the flow right here.
   1431		 */
   1432		if (mcde->flow_active == 0)
   1433			mcde_start_flow(mcde);
   1434	} else {
   1435		/*
   1436		 * If an update is receieved before the MCDE is enabled
   1437		 * (before mcde_display_enable() is called) we can't really
   1438		 * do much with that buffer.
   1439		 */
   1440		dev_info(mcde->dev, "ignored a display update\n");
   1441	}
   1442}
   1443
   1444static int mcde_display_enable_vblank(struct drm_simple_display_pipe *pipe)
   1445{
   1446	struct drm_crtc *crtc = &pipe->crtc;
   1447	struct drm_device *drm = crtc->dev;
   1448	struct mcde *mcde = to_mcde(drm);
   1449	u32 val;
   1450
   1451	/* Enable all VBLANK IRQs */
   1452	val = MCDE_PP_VCMPA |
   1453		MCDE_PP_VCMPB |
   1454		MCDE_PP_VSCC0 |
   1455		MCDE_PP_VSCC1 |
   1456		MCDE_PP_VCMPC0 |
   1457		MCDE_PP_VCMPC1;
   1458	writel(val, mcde->regs + MCDE_IMSCPP);
   1459
   1460	return 0;
   1461}
   1462
   1463static void mcde_display_disable_vblank(struct drm_simple_display_pipe *pipe)
   1464{
   1465	struct drm_crtc *crtc = &pipe->crtc;
   1466	struct drm_device *drm = crtc->dev;
   1467	struct mcde *mcde = to_mcde(drm);
   1468
   1469	/* Disable all VBLANK IRQs */
   1470	writel(0, mcde->regs + MCDE_IMSCPP);
   1471	/* Clear any pending IRQs */
   1472	writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP);
   1473}
   1474
   1475static struct drm_simple_display_pipe_funcs mcde_display_funcs = {
   1476	.check = mcde_display_check,
   1477	.enable = mcde_display_enable,
   1478	.disable = mcde_display_disable,
   1479	.update = mcde_display_update,
   1480	.enable_vblank = mcde_display_enable_vblank,
   1481	.disable_vblank = mcde_display_disable_vblank,
   1482};
   1483
   1484int mcde_display_init(struct drm_device *drm)
   1485{
   1486	struct mcde *mcde = to_mcde(drm);
   1487	int ret;
   1488	static const u32 formats[] = {
   1489		DRM_FORMAT_ARGB8888,
   1490		DRM_FORMAT_ABGR8888,
   1491		DRM_FORMAT_XRGB8888,
   1492		DRM_FORMAT_XBGR8888,
   1493		DRM_FORMAT_RGB888,
   1494		DRM_FORMAT_BGR888,
   1495		DRM_FORMAT_ARGB4444,
   1496		DRM_FORMAT_ABGR4444,
   1497		DRM_FORMAT_XRGB4444,
   1498		DRM_FORMAT_XBGR4444,
   1499		/* These are actually IRGB1555 so intensity bit is lost */
   1500		DRM_FORMAT_XRGB1555,
   1501		DRM_FORMAT_XBGR1555,
   1502		DRM_FORMAT_RGB565,
   1503		DRM_FORMAT_BGR565,
   1504		DRM_FORMAT_YUV422,
   1505	};
   1506
   1507	ret = mcde_init_clock_divider(mcde);
   1508	if (ret)
   1509		return ret;
   1510
   1511	ret = drm_simple_display_pipe_init(drm, &mcde->pipe,
   1512					   &mcde_display_funcs,
   1513					   formats, ARRAY_SIZE(formats),
   1514					   NULL,
   1515					   mcde->connector);
   1516	if (ret)
   1517		return ret;
   1518
   1519	return 0;
   1520}
   1521EXPORT_SYMBOL_GPL(mcde_display_init);