drivers/gpu/drm/meson/meson_dw_mipi_dsi.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
Extension
.c
Size
9816 bytes
Lines
357
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct meson_dw_mipi_dsi {
	struct meson_drm *priv;
	struct device *dev;
	void __iomem *base;
	struct phy *phy;
	union phy_configure_opts phy_opts;
	struct dw_mipi_dsi *dmd;
	struct dw_mipi_dsi_plat_data pdata;
	struct mipi_dsi_device *dsi_device;
	const struct drm_display_mode *mode;
	struct clk *bit_clk;
	struct clk *px_clk;
	struct reset_control *top_rst;
};

#define encoder_to_meson_dw_mipi_dsi(x) \
	container_of(x, struct meson_dw_mipi_dsi, encoder)

static void meson_dw_mipi_dsi_hw_init(struct meson_dw_mipi_dsi *mipi_dsi)
{
	/* Software reset */
	writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
			    MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
			    MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
			    MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
			    mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);
	writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
			    MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
			    0, mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);

	/* Enable clocks */
	writel_bits_relaxed(MIPI_DSI_TOP_CLK_SYSCLK_EN | MIPI_DSI_TOP_CLK_PIXCLK_EN,
			    MIPI_DSI_TOP_CLK_SYSCLK_EN | MIPI_DSI_TOP_CLK_PIXCLK_EN,
			    mipi_dsi->base + MIPI_DSI_TOP_CLK_CNTL);

	/* Take memory out of power down */
	writel_relaxed(0, mipi_dsi->base + MIPI_DSI_TOP_MEM_PD);
}

static int dw_mipi_dsi_phy_init(void *priv_data)
{
	struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
	unsigned int dpi_data_format, venc_data_width;
	int ret;

	/* Set the bit clock rate to hs_clk_rate */
	ret = clk_set_rate(mipi_dsi->bit_clk,
			   mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate);
	if (ret) {
		dev_err(mipi_dsi->dev, "Failed to set DSI Bit clock rate %lu (ret %d)\n",
			mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate, ret);
		return ret;
	}

	/* Make sure the rate of the bit clock is not modified by someone else */
	ret = clk_rate_exclusive_get(mipi_dsi->bit_clk);
	if (ret) {
		dev_err(mipi_dsi->dev,
			"Failed to set the exclusivity on the bit clock rate (ret %d)\n", ret);
		return ret;
	}

	clk_disable_unprepare(mipi_dsi->px_clk);
	ret = clk_set_rate(mipi_dsi->px_clk, mipi_dsi->mode->clock * 1000);

	if (ret) {
		dev_err(mipi_dsi->dev, "Failed to set DSI Pixel clock rate %u (%d)\n",
			mipi_dsi->mode->clock * 1000, ret);
		return ret;
	}

	ret = clk_prepare_enable(mipi_dsi->px_clk);
	if (ret) {
		dev_err(mipi_dsi->dev, "Failed to enable DSI Pixel clock (ret %d)\n", ret);
		return ret;
	}

	switch (mipi_dsi->dsi_device->format) {
	case MIPI_DSI_FMT_RGB888:
		dpi_data_format = DPI_COLOR_24BIT;
		venc_data_width = VENC_IN_COLOR_24B;
		break;
	case MIPI_DSI_FMT_RGB666:
		dpi_data_format = DPI_COLOR_18BIT_CFG_2;
		venc_data_width = VENC_IN_COLOR_18B;
		break;
	default:
		return -EINVAL;
	}

Annotation

Implementation Notes