linux/drivers/gpu/drm/mcde/mcde_display.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2018 Linus Walleij <[email protected]>
 * Parts of this file were based on the MCDE driver by Marcus Lorentzon
 * (C) ST-Ericsson SA 2013
 */
#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;

	/*
	 * Select the formatter to use for this FIFO
	 *
	 * The register definitions imply that different IDs should be used
	 * by the DSI formatters depending on if they are in VID or CMD
	 * mode, and the manual says they are dedicated but identical.
	 * The vendor code uses them as it seems fit.
	 */
	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);

	/* Blend source with Alpha 0xff on FIFO */
	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);
	/*
	 * Set-up from mcde_fmtr_dsi.c, fmtr_dsi_enable_video()
	 * FIXME: a different clock needs to be selected for TV out.
	 */
	if (mcde->dpi_output) {
		struct drm_connector *connector = drm_panel_bridge_connector(mcde->bridge);
		u32 bus_format;

		/* Assume RGB888 24 bit if we have no further info */
		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];
		}

		/*
		 * Set up the CDWIN and OUTBPP for the LCD
		 *
		 * FIXME: fill this in if you know the correspondance between the MIPI
		 * DPI specification and the media bus formats.
		 */
		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 {
		/* Use the MCDE clock for DSI */
		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)
{}

/*
 * This drains a pipe i.e. a FIFO connected to a certain channel
 */
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();