#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-buf.h>
#include <linux/regulator/consumer.h>
#include <linux/media-bus-format.h>
#include <drm/drm_device.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_vblank.h>
#include <video/mipi_display.h>
#include "mcde_drm.h"
#include "mcde_display_regs.h"
enum mcde_fifo { … };
enum mcde_channel { … };
enum mcde_extsrc { … };
enum mcde_overlay { … };
enum mcde_formatter { … };
void mcde_display_irq(struct mcde *mcde)
{ … }
void mcde_display_disable_irqs(struct mcde *mcde)
{ … }
static int mcde_display_check(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *pstate,
struct drm_crtc_state *cstate)
{ … }
static int mcde_configure_extsrc(struct mcde *mcde, enum mcde_extsrc src,
u32 format)
{ … }
static void mcde_configure_overlay(struct mcde *mcde, enum mcde_overlay ovl,
enum mcde_extsrc src,
enum mcde_channel ch,
const struct drm_display_mode *mode,
u32 format, int cpp)
{ … }
static void mcde_configure_channel(struct mcde *mcde, enum mcde_channel ch,
enum mcde_fifo fifo,
const struct drm_display_mode *mode)
{ … }
static void mcde_configure_fifo(struct mcde *mcde, enum mcde_fifo fifo,
enum mcde_formatter fmt,
int fifo_wtrmrk)
{
u32 val;
u32 ctrl;
u32 cr0, cr1;
switch (fifo) {
case MCDE_FIFO_A:
ctrl = MCDE_CTRLA;
cr0 = MCDE_CRA0;
cr1 = MCDE_CRA1;
break;
case MCDE_FIFO_B:
ctrl = MCDE_CTRLB;
cr0 = MCDE_CRB0;
cr1 = MCDE_CRB1;
break;
}
val = fifo_wtrmrk << MCDE_CTRLX_FIFOWTRMRK_SHIFT;
switch (fmt) {
case MCDE_DSI_FORMATTER_0:
val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
val |= MCDE_CTRLX_FORMID_DSI0VID << MCDE_CTRLX_FORMID_SHIFT;
break;
case MCDE_DSI_FORMATTER_1:
val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
val |= MCDE_CTRLX_FORMID_DSI0CMD << MCDE_CTRLX_FORMID_SHIFT;
break;
case MCDE_DSI_FORMATTER_2:
val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
val |= MCDE_CTRLX_FORMID_DSI1VID << MCDE_CTRLX_FORMID_SHIFT;
break;
case MCDE_DSI_FORMATTER_3:
val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
val |= MCDE_CTRLX_FORMID_DSI1CMD << MCDE_CTRLX_FORMID_SHIFT;
break;
case MCDE_DSI_FORMATTER_4:
val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
val |= MCDE_CTRLX_FORMID_DSI2VID << MCDE_CTRLX_FORMID_SHIFT;
break;
case MCDE_DSI_FORMATTER_5:
val |= MCDE_CTRLX_FORMTYPE_DSI << MCDE_CTRLX_FORMTYPE_SHIFT;
val |= MCDE_CTRLX_FORMID_DSI2CMD << MCDE_CTRLX_FORMID_SHIFT;
break;
case MCDE_DPI_FORMATTER_0:
val |= MCDE_CTRLX_FORMTYPE_DPITV << MCDE_CTRLX_FORMTYPE_SHIFT;
val |= MCDE_CTRLX_FORMID_DPIA << MCDE_CTRLX_FORMID_SHIFT;
break;
case MCDE_DPI_FORMATTER_1:
val |= MCDE_CTRLX_FORMTYPE_DPITV << MCDE_CTRLX_FORMTYPE_SHIFT;
val |= MCDE_CTRLX_FORMID_DPIB << MCDE_CTRLX_FORMID_SHIFT;
break;
}
writel(val, mcde->regs + ctrl);
val = MCDE_CRX0_BLENDEN |
0xff << MCDE_CRX0_ALPHABLEND_SHIFT;
writel(val, mcde->regs + cr0);
spin_lock(&mcde->fifo_crx1_lock);
val = readl(mcde->regs + cr1);
if (mcde->dpi_output) {
struct drm_connector *connector = drm_panel_bridge_connector(mcde->bridge);
u32 bus_format;
if (!connector->display_info.num_bus_formats) {
dev_info(mcde->dev, "panel does not specify bus format, assume RGB888\n");
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
} else {
bus_format = connector->display_info.bus_formats[0];
}
val &= ~MCDE_CRX1_CDWIN_MASK;
val &= ~MCDE_CRX1_OUTBPP_MASK;
switch (bus_format) {
case MEDIA_BUS_FMT_RGB888_1X24:
val |= MCDE_CRX1_CDWIN_24BPP << MCDE_CRX1_CDWIN_SHIFT;
val |= MCDE_CRX1_OUTBPP_24BPP << MCDE_CRX1_OUTBPP_SHIFT;
break;
default:
dev_err(mcde->dev, "unknown bus format, assume RGB888\n");
val |= MCDE_CRX1_CDWIN_24BPP << MCDE_CRX1_CDWIN_SHIFT;
val |= MCDE_CRX1_OUTBPP_24BPP << MCDE_CRX1_OUTBPP_SHIFT;
break;
}
} else {
val &= ~MCDE_CRX1_CLKSEL_MASK;
val |= MCDE_CRX1_CLKSEL_MCDECLK << MCDE_CRX1_CLKSEL_SHIFT;
}
writel(val, mcde->regs + cr1);
spin_unlock(&mcde->fifo_crx1_lock);
};
static void mcde_configure_dsi_formatter(struct mcde *mcde,
enum mcde_formatter fmt,
u32 formatter_frame,
int pkt_size)
{ … }
static void mcde_enable_fifo(struct mcde *mcde, enum mcde_fifo fifo)
{ … }
static void mcde_disable_fifo(struct mcde *mcde, enum mcde_fifo fifo,
bool wait_for_drain)
{ … }
static void mcde_drain_pipe(struct mcde *mcde, enum mcde_fifo fifo,
enum mcde_channel ch)
{ … }
static int mcde_dsi_get_pkt_div(int ppl, int fifo_size)
{ … }
static void mcde_setup_dpi(struct mcde *mcde, const struct drm_display_mode *mode,
int *fifo_wtrmrk_lvl)
{ … }
static void mcde_setup_dsi(struct mcde *mcde, const struct drm_display_mode *mode,
int cpp, int *fifo_wtrmrk_lvl, int *dsi_formatter_frame,
int *dsi_pkt_size)
{ … }
static void mcde_display_enable(struct drm_simple_display_pipe *pipe,
struct drm_crtc_state *cstate,
struct drm_plane_state *plane_state)
{ … }
static void mcde_display_disable(struct drm_simple_display_pipe *pipe)
{ … }
static void mcde_start_flow(struct mcde *mcde)
{ … }
static void mcde_set_extsrc(struct mcde *mcde, u32 buffer_address)
{ … }
static void mcde_display_update(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *old_pstate)
{ … }
static int mcde_display_enable_vblank(struct drm_simple_display_pipe *pipe)
{ … }
static void mcde_display_disable_vblank(struct drm_simple_display_pipe *pipe)
{ … }
static struct drm_simple_display_pipe_funcs mcde_display_funcs = …;
int mcde_display_init(struct drm_device *drm)
{ … }
EXPORT_SYMBOL_GPL(…);