Lines Matching +full:fifo +full:- +full:watermark +full:- +full:aligned

1 // SPDX-License-Identifier: GPL-2.0
5 * (C) ST-Ericsson SA 2013
9 #include <linux/dma-buf.h>
28 /* TODO: implement FIFO C0 and FIFO C1 */
72 mispp = readl(mcde->regs + MCDE_MISPP); in mcde_display_irq()
73 misovl = readl(mcde->regs + MCDE_MISOVL); in mcde_display_irq()
74 mischnl = readl(mcde->regs + MCDE_MISCHNL); in mcde_display_irq()
84 if (mcde_dsi_irq(mcde->mdsi)) { in mcde_display_irq()
93 if (mcde->flow_mode == MCDE_COMMAND_ONESHOT_FLOW) { in mcde_display_irq()
94 spin_lock(&mcde->flow_lock); in mcde_display_irq()
95 if (--mcde->flow_active == 0) { in mcde_display_irq()
96 dev_dbg(mcde->dev, "TE0 IRQ\n"); in mcde_display_irq()
97 /* Disable FIFO A flow */ in mcde_display_irq()
98 val = readl(mcde->regs + MCDE_CRA0); in mcde_display_irq()
100 writel(val, mcde->regs + MCDE_CRA0); in mcde_display_irq()
102 spin_unlock(&mcde->flow_lock); in mcde_display_irq()
108 dev_dbg(mcde->dev, "chnl A vblank IRQ\n"); in mcde_display_irq()
112 dev_dbg(mcde->dev, "chnl B vblank IRQ\n"); in mcde_display_irq()
116 dev_dbg(mcde->dev, "chnl C0 vblank IRQ\n"); in mcde_display_irq()
118 dev_dbg(mcde->dev, "chnl C1 vblank IRQ\n"); in mcde_display_irq()
120 dev_dbg(mcde->dev, "chnl C0 TE IRQ\n"); in mcde_display_irq()
122 dev_dbg(mcde->dev, "chnl C1 TE IRQ\n"); in mcde_display_irq()
123 writel(mispp, mcde->regs + MCDE_RISPP); in mcde_display_irq()
126 drm_crtc_handle_vblank(&mcde->pipe.crtc); in mcde_display_irq()
129 dev_info(mcde->dev, "some stray overlay IRQ %08x\n", misovl); in mcde_display_irq()
130 writel(misovl, mcde->regs + MCDE_RISOVL); in mcde_display_irq()
133 dev_info(mcde->dev, "some stray channel error IRQ %08x\n", in mcde_display_irq()
135 writel(mischnl, mcde->regs + MCDE_RISCHNL); in mcde_display_irq()
141 writel(0, mcde->regs + MCDE_IMSCPP); in mcde_display_disable_irqs()
142 writel(0, mcde->regs + MCDE_IMSCOVL); in mcde_display_disable_irqs()
143 writel(0, mcde->regs + MCDE_IMSCCHNL); in mcde_display_disable_irqs()
146 writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP); in mcde_display_disable_irqs()
147 writel(0xFFFFFFFF, mcde->regs + MCDE_RISOVL); in mcde_display_disable_irqs()
148 writel(0xFFFFFFFF, mcde->regs + MCDE_RISCHNL); in mcde_display_disable_irqs()
155 const struct drm_display_mode *mode = &cstate->mode; in mcde_display_check()
156 struct drm_framebuffer *old_fb = pipe->plane.state->fb; in mcde_display_check()
157 struct drm_framebuffer *fb = pstate->fb; in mcde_display_check()
162 /* FB base address must be dword aligned. */ in mcde_display_check()
164 DRM_DEBUG_KMS("FB not 32-bit aligned\n"); in mcde_display_check()
165 return -EINVAL; in mcde_display_check()
172 if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) { in mcde_display_check()
174 return -EINVAL; in mcde_display_check()
178 * We can't change the FB format in a flicker-free in mcde_display_check()
181 if (old_fb && old_fb->format != fb->format) in mcde_display_check()
182 cstate->mode_changed = true; in mcde_display_check()
319 dev_err(mcde->dev, "Unknown pixel format 0x%08x\n", in mcde_configure_extsrc()
321 return -EINVAL; in mcde_configure_extsrc()
323 writel(val, mcde->regs + conf); in mcde_configure_extsrc()
328 writel(val, mcde->regs + cr); in mcde_configure_extsrc()
399 val = mode->hdisplay << MCDE_OVLXCONF_PPL_SHIFT; in mcde_configure_overlay()
400 val |= mode->vdisplay << MCDE_OVLXCONF_LPF_SHIFT; in mcde_configure_overlay()
403 writel(val, mcde->regs + conf1); in mcde_configure_overlay()
427 dev_err(mcde->dev, "Unknown pixel format 0x%08x\n", in mcde_configure_overlay()
433 * Pixel fetch watermark level is max 0x1FFF pixels. in mcde_configure_overlay()
436 * 2. The sum of all active overlays pixelfetch watermark level in mcde_configure_overlay()
455 dev_dbg(mcde->dev, "pixel fetcher watermark level %d pixels\n", in mcde_configure_overlay()
458 writel(val, mcde->regs + conf2); in mcde_configure_overlay()
461 writel(mcde->stride, mcde->regs + ljinc); in mcde_configure_overlay()
463 writel(0, mcde->regs + crop); in mcde_configure_overlay()
475 writel(val, mcde->regs + cr); in mcde_configure_overlay()
482 writel(val, mcde->regs + comp); in mcde_configure_overlay()
486 enum mcde_fifo fifo, in mcde_configure_channel() argument
528 switch (mcde->flow_mode) { in mcde_configure_channel()
565 dev_err(mcde->dev, "unknown flow mode %d\n", in mcde_configure_channel()
566 mcde->flow_mode); in mcde_configure_channel()
570 writel(val, mcde->regs + sync); in mcde_configure_channel()
573 val = (mode->hdisplay - 1) << MCDE_CHNLXCONF_PPL_SHIFT; in mcde_configure_channel()
574 val |= (mode->vdisplay - 1) << MCDE_CHNLXCONF_LPF_SHIFT; in mcde_configure_channel()
575 writel(val, mcde->regs + conf); in mcde_configure_channel()
583 writel(val, mcde->regs + stat); in mcde_configure_channel()
584 writel(0, mcde->regs + bgcol); in mcde_configure_channel()
586 /* Set up muxing: connect the channel to the desired FIFO */ in mcde_configure_channel()
587 switch (fifo) { in mcde_configure_channel()
590 mcde->regs + mux); in mcde_configure_channel()
594 mcde->regs + mux); in mcde_configure_channel()
599 static void mcde_configure_fifo(struct mcde *mcde, enum mcde_fifo fifo, in mcde_configure_fifo() argument
607 switch (fifo) { in mcde_configure_fifo()
625 /* Select the formatter to use for this FIFO */ in mcde_configure_fifo()
627 writel(val, mcde->regs + ctrl); in mcde_configure_fifo()
629 /* Blend source with Alpha 0xff on FIFO */ in mcde_configure_fifo()
632 writel(val, mcde->regs + cr0); in mcde_configure_fifo()
634 /* Set-up from mcde_fmtr_dsi.c, fmtr_dsi_enable_video() */ in mcde_configure_fifo()
636 /* Use the MCDE clock for this FIFO */ in mcde_configure_fifo()
640 writel(val, mcde->regs + cr1); in mcde_configure_fifo()
691 if (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) in mcde_configure_dsi_formatter()
693 switch (mcde->mdsi->format) { in mcde_configure_dsi_formatter()
711 dev_err(mcde->dev, "unknown DSI format\n"); in mcde_configure_dsi_formatter()
714 writel(val, mcde->regs + conf0); in mcde_configure_dsi_formatter()
716 writel(formatter_frame, mcde->regs + frame); in mcde_configure_dsi_formatter()
717 writel(pkt_size, mcde->regs + pkt); in mcde_configure_dsi_formatter()
718 writel(0, mcde->regs + sync); in mcde_configure_dsi_formatter()
724 writel(val, mcde->regs + cmdw); in mcde_configure_dsi_formatter()
730 writel(0, mcde->regs + delay0); in mcde_configure_dsi_formatter()
731 writel(0, mcde->regs + delay1); in mcde_configure_dsi_formatter()
734 static void mcde_enable_fifo(struct mcde *mcde, enum mcde_fifo fifo) in mcde_enable_fifo() argument
739 switch (fifo) { in mcde_enable_fifo()
747 dev_err(mcde->dev, "cannot enable FIFO %c\n", in mcde_enable_fifo()
748 'A' + fifo); in mcde_enable_fifo()
752 spin_lock(&mcde->flow_lock); in mcde_enable_fifo()
753 val = readl(mcde->regs + cr); in mcde_enable_fifo()
755 writel(val, mcde->regs + cr); in mcde_enable_fifo()
756 mcde->flow_active++; in mcde_enable_fifo()
757 spin_unlock(&mcde->flow_lock); in mcde_enable_fifo()
760 static void mcde_disable_fifo(struct mcde *mcde, enum mcde_fifo fifo, in mcde_disable_fifo() argument
767 switch (fifo) { in mcde_disable_fifo()
775 dev_err(mcde->dev, "cannot disable FIFO %c\n", in mcde_disable_fifo()
776 'A' + fifo); in mcde_disable_fifo()
780 spin_lock(&mcde->flow_lock); in mcde_disable_fifo()
781 val = readl(mcde->regs + cr); in mcde_disable_fifo()
783 writel(val, mcde->regs + cr); in mcde_disable_fifo()
784 mcde->flow_active = 0; in mcde_disable_fifo()
785 spin_unlock(&mcde->flow_lock); in mcde_disable_fifo()
791 while (readl(mcde->regs + cr) & MCDE_CRX0_FLOEN) { in mcde_disable_fifo()
793 if (!--timeout) { in mcde_disable_fifo()
794 dev_err(mcde->dev, in mcde_disable_fifo()
795 "FIFO timeout while clearing FIFO %c\n", in mcde_disable_fifo()
796 'A' + fifo); in mcde_disable_fifo()
803 * This drains a pipe i.e. a FIFO connected to a certain channel
805 static void mcde_drain_pipe(struct mcde *mcde, enum mcde_fifo fifo, in mcde_drain_pipe() argument
812 switch (fifo) { in mcde_drain_pipe()
836 val = readl(mcde->regs + ctrl); in mcde_drain_pipe()
838 dev_err(mcde->dev, "Channel A FIFO not empty (handover)\n"); in mcde_drain_pipe()
839 /* Attempt to clear the FIFO */ in mcde_drain_pipe()
840 mcde_enable_fifo(mcde, fifo); in mcde_drain_pipe()
841 /* Trigger a software sync out on respective channel (0-3) */ in mcde_drain_pipe()
842 writel(MCDE_CHNLXSYNCHSW_SW_TRIG, mcde->regs + synsw); in mcde_drain_pipe()
843 /* Disable FIFO A flow again */ in mcde_drain_pipe()
844 mcde_disable_fifo(mcde, fifo, true); in mcde_drain_pipe()
852 * packets smaller than or equal to the fifo size. in mcde_dsi_get_pkt_div()
867 struct drm_crtc *crtc = &pipe->crtc; in mcde_display_enable()
868 struct drm_plane *plane = &pipe->plane; in mcde_display_enable()
869 struct drm_device *drm = crtc->dev; in mcde_display_enable()
871 const struct drm_display_mode *mode = &cstate->mode; in mcde_display_enable()
872 struct drm_framebuffer *fb = plane->state->fb; in mcde_display_enable()
873 u32 format = fb->format->format; in mcde_display_enable()
874 u32 formatter_ppl = mode->hdisplay; /* pixels per line */ in mcde_display_enable()
875 u32 formatter_lpf = mode->vdisplay; /* lines per frame */ in mcde_display_enable()
877 int cpp = fb->format->cpp[0]; in mcde_display_enable()
886 ret = regulator_enable(mcde->epod); in mcde_display_enable()
888 dev_err(drm->dev, "can't re-enable EPOD regulator\n"); in mcde_display_enable()
892 dev_info(drm->dev, "enable MCDE, %d x %d format %s\n", in mcde_display_enable()
893 mode->hdisplay, mode->vdisplay, in mcde_display_enable()
895 if (!mcde->mdsi) { in mcde_display_enable()
896 /* TODO: deal with this for non-DSI output */ in mcde_display_enable()
897 dev_err(drm->dev, "no DSI master attached!\n"); in mcde_display_enable()
901 /* Set up the main control, watermark level at 7 */ in mcde_display_enable()
914 writel(val, mcde->regs + MCDE_CONF0); in mcde_display_enable()
918 writel(0, mcde->regs + MCDE_IMSCERR); in mcde_display_enable()
919 writel(0xFFFFFFFF, mcde->regs + MCDE_RISERR); in mcde_display_enable()
921 dev_info(drm->dev, "output in %s mode, format %dbpp\n", in mcde_display_enable()
922 (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ? in mcde_display_enable()
924 mipi_dsi_pixel_format_to_bpp(mcde->mdsi->format)); in mcde_display_enable()
926 mipi_dsi_pixel_format_to_bpp(mcde->mdsi->format) / 8; in mcde_display_enable()
927 dev_info(drm->dev, "overlay CPP %d bytes, DSI CPP %d bytes\n", in mcde_display_enable()
934 * Set up FIFO A watermark level: in mcde_display_enable()
942 fifo_wtrmrk = mode->hdisplay; in mcde_display_enable()
943 if (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) { in mcde_display_enable()
948 /* The FIFO is 640 entries deep on this v3 hardware */ in mcde_display_enable()
949 pkt_div = mcde_dsi_get_pkt_div(mode->hdisplay, 640); in mcde_display_enable()
951 dev_dbg(drm->dev, "FIFO watermark after flooring: %d bytes\n", in mcde_display_enable()
953 dev_dbg(drm->dev, "Packet divisor: %d bytes\n", pkt_div); in mcde_display_enable()
958 if (!(mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO)) in mcde_display_enable()
961 dev_dbg(drm->dev, "DSI packet size: %d * %d bytes per line\n", in mcde_display_enable()
963 dev_dbg(drm->dev, "Overlay frame size: %u bytes\n", in mcde_display_enable()
964 mode->hdisplay * mode->vdisplay * cpp); in mcde_display_enable()
965 mcde->stride = mode->hdisplay * cpp; in mcde_display_enable()
966 dev_dbg(drm->dev, "Overlay line stride: %u bytes\n", in mcde_display_enable()
967 mcde->stride); in mcde_display_enable()
970 dev_dbg(drm->dev, "Formatter frame size: %u bytes\n", formatter_frame); in mcde_display_enable()
972 /* Drain the FIFO A + channel 0 pipe so we have a clean slate */ in mcde_display_enable()
977 * EXTSRC 0 -> OVERLAY 0 -> CHANNEL 0 -> FIFO A -> DSI FORMATTER 0 in mcde_display_enable()
993 * Configure pixel-per-line and line-per-frame for channel 0 and then in mcde_display_enable()
994 * route channel 0 to FIFO A in mcde_display_enable()
998 /* Configure FIFO A to use DSI formatter 0 */ in mcde_display_enable()
1010 mcde_dsi_enable(mcde->bridge); in mcde_display_enable()
1016 switch (mcde->flow_mode) { in mcde_display_enable()
1021 if (mode->flags & DRM_MODE_FLAG_NVSYNC) in mcde_display_enable()
1025 writel(val, mcde->regs + MCDE_VSCRC0); in mcde_display_enable()
1027 val = readl(mcde->regs + MCDE_CRC); in mcde_display_enable()
1029 writel(val, mcde->regs + MCDE_CRC); in mcde_display_enable()
1042 * modes (command or video) we start the FIFO flow in mcde_display_enable()
1046 if (mcde->flow_mode != MCDE_COMMAND_ONESHOT_FLOW) { in mcde_display_enable()
1048 dev_dbg(mcde->dev, "started MCDE video FIFO flow\n"); in mcde_display_enable()
1052 val = readl(mcde->regs + MCDE_CR); in mcde_display_enable()
1054 writel(val, mcde->regs + MCDE_CR); in mcde_display_enable()
1056 dev_info(drm->dev, "MCDE display is enabled\n"); in mcde_display_enable()
1061 struct drm_crtc *crtc = &pipe->crtc; in mcde_display_disable()
1062 struct drm_device *drm = crtc->dev; in mcde_display_disable()
1069 /* Disable FIFO A flow */ in mcde_display_disable()
1073 mcde_dsi_disable(mcde->bridge); in mcde_display_disable()
1075 event = crtc->state->event; in mcde_display_disable()
1077 crtc->state->event = NULL; in mcde_display_disable()
1079 spin_lock_irq(&crtc->dev->event_lock); in mcde_display_disable()
1081 spin_unlock_irq(&crtc->dev->event_lock); in mcde_display_disable()
1084 ret = regulator_disable(mcde->epod); in mcde_display_disable()
1086 dev_err(drm->dev, "can't disable EPOD regulator\n"); in mcde_display_disable()
1090 dev_info(drm->dev, "MCDE display is disabled\n"); in mcde_display_disable()
1096 if (mcde->flow_mode == MCDE_COMMAND_BTA_TE_FLOW) in mcde_start_flow()
1097 mcde_dsi_te_request(mcde->mdsi); in mcde_start_flow()
1099 /* Enable FIFO A flow */ in mcde_start_flow()
1109 if (mcde->flow_mode == MCDE_COMMAND_ONESHOT_FLOW) { in mcde_start_flow()
1112 mcde->regs + MCDE_CHNL0SYNCHSW); in mcde_start_flow()
1115 * Disable FIFO A flow again: since we are using TE sync we in mcde_start_flow()
1116 * need to wait for the FIFO to drain before we continue in mcde_start_flow()
1124 dev_dbg(mcde->dev, "started MCDE FIFO flow\n"); in mcde_start_flow()
1130 writel(buffer_address, mcde->regs + MCDE_EXTSRCXA0); in mcde_set_extsrc()
1135 writel(buffer_address + mcde->stride, mcde->regs + MCDE_EXTSRCXA1); in mcde_set_extsrc()
1141 struct drm_crtc *crtc = &pipe->crtc; in mcde_display_update()
1142 struct drm_device *drm = crtc->dev; in mcde_display_update()
1144 struct drm_pending_vblank_event *event = crtc->state->event; in mcde_display_update()
1145 struct drm_plane *plane = &pipe->plane; in mcde_display_update()
1146 struct drm_plane_state *pstate = plane->state; in mcde_display_update()
1147 struct drm_framebuffer *fb = pstate->fb; in mcde_display_update()
1155 crtc->state->event = NULL; in mcde_display_update()
1157 spin_lock_irq(&crtc->dev->event_lock); in mcde_display_update()
1165 if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) { in mcde_display_update()
1166 dev_dbg(mcde->dev, "arm vblank event\n"); in mcde_display_update()
1169 dev_dbg(mcde->dev, "insert fake vblank event\n"); in mcde_display_update()
1173 spin_unlock_irq(&crtc->dev->event_lock); in mcde_display_update()
1183 dev_info_once(mcde->dev, "first update of display contents\n"); in mcde_display_update()
1188 if (mcde->flow_active == 0) in mcde_display_update()
1196 dev_info(mcde->dev, "ignored a display update\n"); in mcde_display_update()
1202 struct drm_crtc *crtc = &pipe->crtc; in mcde_display_enable_vblank()
1203 struct drm_device *drm = crtc->dev; in mcde_display_enable_vblank()
1214 writel(val, mcde->regs + MCDE_IMSCPP); in mcde_display_enable_vblank()
1221 struct drm_crtc *crtc = &pipe->crtc; in mcde_display_disable_vblank()
1222 struct drm_device *drm = crtc->dev; in mcde_display_disable_vblank()
1226 writel(0, mcde->regs + MCDE_IMSCPP); in mcde_display_disable_vblank()
1228 writel(0xFFFFFFFF, mcde->regs + MCDE_RISPP); in mcde_display_disable_vblank()
1264 ret = drm_simple_display_pipe_init(drm, &mcde->pipe, in mcde_display_init()
1268 mcde->connector); in mcde_display_init()