brintos

brintos / linux-shallow public Read only

0
0
Text · 20.8 KiB · b201238 Raw
800 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) STMicroelectronics SA 20174 *5 * Authors: Philippe Cornu <philippe.cornu@st.com>6 *          Yannick Fertre <yannick.fertre@st.com>7 */8 9#include <linux/clk.h>10#include <linux/clk-provider.h>11#include <linux/iopoll.h>12#include <linux/kernel.h>13#include <linux/mod_devicetable.h>14#include <linux/module.h>15#include <linux/platform_device.h>16#include <linux/pm_runtime.h>17#include <linux/regulator/consumer.h>18 19#include <video/mipi_display.h>20 21#include <drm/bridge/dw_mipi_dsi.h>22#include <drm/drm_mipi_dsi.h>23#include <drm/drm_print.h>24 25#define HWVER_130			0x31333000	/* IP version 1.30 */26#define HWVER_131			0x31333100	/* IP version 1.31 */27 28/* DSI digital registers & bit definitions */29#define DSI_VERSION			0x0030#define VERSION				GENMASK(31, 8)31 32/* DSI wrapper registers & bit definitions */33/* Note: registers are named as in the Reference Manual */34#define DSI_WCFGR	0x0400		/* Wrapper ConFiGuration Reg */35#define WCFGR_DSIM	BIT(0)		/* DSI Mode */36#define WCFGR_COLMUX	GENMASK(3, 1)	/* COLor MUltipleXing */37 38#define DSI_WCR		0x0404		/* Wrapper Control Reg */39#define WCR_DSIEN	BIT(3)		/* DSI ENable */40 41#define DSI_WISR	0x040C		/* Wrapper Interrupt and Status Reg */42#define WISR_PLLLS	BIT(8)		/* PLL Lock Status */43#define WISR_RRS	BIT(12)		/* Regulator Ready Status */44 45#define DSI_WPCR0	0x0418		/* Wrapper Phy Conf Reg 0 */46#define WPCR0_UIX4	GENMASK(5, 0)	/* Unit Interval X 4 */47#define WPCR0_TDDL	BIT(16)		/* Turn Disable Data Lanes */48 49#define DSI_WRPCR	0x0430		/* Wrapper Regulator & Pll Ctrl Reg */50#define WRPCR_PLLEN	BIT(0)		/* PLL ENable */51#define WRPCR_NDIV	GENMASK(8, 2)	/* pll loop DIVision Factor */52#define WRPCR_IDF	GENMASK(14, 11)	/* pll Input Division Factor */53#define WRPCR_ODF	GENMASK(17, 16)	/* pll Output Division Factor */54#define WRPCR_REGEN	BIT(24)		/* REGulator ENable */55#define WRPCR_BGREN	BIT(28)		/* BandGap Reference ENable */56#define IDF_MIN		157#define IDF_MAX		758#define NDIV_MIN	1059#define NDIV_MAX	12560#define ODF_MIN		161#define ODF_MAX		862 63/* dsi color format coding according to the datasheet */64enum dsi_color {65	DSI_RGB565_CONF1,66	DSI_RGB565_CONF2,67	DSI_RGB565_CONF3,68	DSI_RGB666_CONF1,69	DSI_RGB666_CONF2,70	DSI_RGB888,71};72 73#define LANE_MIN_KBPS	3125074#define LANE_MAX_KBPS	50000075 76/* Sleep & timeout for regulator on/off, pll lock/unlock & fifo empty */77#define SLEEP_US	100078#define TIMEOUT_US	20000079 80struct dw_mipi_dsi_stm {81	void __iomem *base;82	struct device *dev;83	struct clk *pllref_clk;84	struct clk *pclk;85	struct clk_hw txbyte_clk;86	struct dw_mipi_dsi *dsi;87	struct dw_mipi_dsi_plat_data pdata;88	u32 hw_version;89	int lane_min_kbps;90	int lane_max_kbps;91	struct regulator *vdd_supply;92};93 94static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val)95{96	writel(val, dsi->base + reg);97}98 99static inline u32 dsi_read(struct dw_mipi_dsi_stm *dsi, u32 reg)100{101	return readl(dsi->base + reg);102}103 104static inline void dsi_set(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 mask)105{106	dsi_write(dsi, reg, dsi_read(dsi, reg) | mask);107}108 109static inline void dsi_clear(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 mask)110{111	dsi_write(dsi, reg, dsi_read(dsi, reg) & ~mask);112}113 114static inline void dsi_update_bits(struct dw_mipi_dsi_stm *dsi, u32 reg,115				   u32 mask, u32 val)116{117	dsi_write(dsi, reg, (dsi_read(dsi, reg) & ~mask) | val);118}119 120static enum dsi_color dsi_color_from_mipi(enum mipi_dsi_pixel_format fmt)121{122	switch (fmt) {123	case MIPI_DSI_FMT_RGB888:124		return DSI_RGB888;125	case MIPI_DSI_FMT_RGB666:126		return DSI_RGB666_CONF2;127	case MIPI_DSI_FMT_RGB666_PACKED:128		return DSI_RGB666_CONF1;129	case MIPI_DSI_FMT_RGB565:130		return DSI_RGB565_CONF1;131	default:132		DRM_DEBUG_DRIVER("MIPI color invalid, so we use rgb888\n");133	}134	return DSI_RGB888;135}136 137static int dsi_pll_get_clkout_khz(int clkin_khz, int idf, int ndiv, int odf)138{139	int divisor = idf * odf;140 141	/* prevent from division by 0 */142	if (!divisor)143		return 0;144 145	return DIV_ROUND_CLOSEST(clkin_khz * ndiv, divisor);146}147 148static int dsi_pll_get_params(struct dw_mipi_dsi_stm *dsi,149			      int clkin_khz, int clkout_khz,150			      int *idf, int *ndiv, int *odf)151{152	int i, o, n, n_min, n_max;153	int fvco_min, fvco_max, delta, best_delta; /* all in khz */154 155	/* Early checks preventing division by 0 & odd results */156	if (clkin_khz <= 0 || clkout_khz <= 0)157		return -EINVAL;158 159	fvco_min = dsi->lane_min_kbps * 2 * ODF_MAX;160	fvco_max = dsi->lane_max_kbps * 2 * ODF_MIN;161 162	best_delta = 1000000; /* big started value (1000000khz) */163 164	for (i = IDF_MIN; i <= IDF_MAX; i++) {165		/* Compute ndiv range according to Fvco */166		n_min = ((fvco_min * i) / (2 * clkin_khz)) + 1;167		n_max = (fvco_max * i) / (2 * clkin_khz);168 169		/* No need to continue idf loop if we reach ndiv max */170		if (n_min >= NDIV_MAX)171			break;172 173		/* Clamp ndiv to valid values */174		if (n_min < NDIV_MIN)175			n_min = NDIV_MIN;176		if (n_max > NDIV_MAX)177			n_max = NDIV_MAX;178 179		for (o = ODF_MIN; o <= ODF_MAX; o *= 2) {180			n = DIV_ROUND_CLOSEST(i * o * clkout_khz, clkin_khz);181			/* Check ndiv according to vco range */182			if (n < n_min || n > n_max)183				continue;184			/* Check if new delta is better & saves parameters */185			delta = dsi_pll_get_clkout_khz(clkin_khz, i, n, o) -186				clkout_khz;187			if (delta < 0)188				delta = -delta;189			if (delta < best_delta) {190				*idf = i;191				*ndiv = n;192				*odf = o;193				best_delta = delta;194			}195			/* fast return in case of "perfect result" */196			if (!delta)197				return 0;198		}199	}200 201	return 0;202}203 204#define clk_to_dw_mipi_dsi_stm(clk) \205	container_of(clk, struct dw_mipi_dsi_stm, txbyte_clk)206 207static void dw_mipi_dsi_clk_disable(struct clk_hw *clk)208{209	struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(clk);210 211	DRM_DEBUG_DRIVER("\n");212 213	/* Disable the DSI PLL */214	dsi_clear(dsi, DSI_WRPCR, WRPCR_PLLEN);215 216	/* Disable the regulator */217	dsi_clear(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);218}219 220static int dw_mipi_dsi_clk_enable(struct clk_hw *clk)221{222	struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(clk);223	u32 val;224	int ret;225 226	DRM_DEBUG_DRIVER("\n");227 228	/* Enable the regulator */229	dsi_set(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);230	ret = readl_poll_timeout_atomic(dsi->base + DSI_WISR, val, val & WISR_RRS,231					SLEEP_US, TIMEOUT_US);232	if (ret)233		DRM_DEBUG_DRIVER("!TIMEOUT! waiting REGU, let's continue\n");234 235	/* Enable the DSI PLL & wait for its lock */236	dsi_set(dsi, DSI_WRPCR, WRPCR_PLLEN);237	ret = readl_poll_timeout_atomic(dsi->base + DSI_WISR, val, val & WISR_PLLLS,238					SLEEP_US, TIMEOUT_US);239	if (ret)240		DRM_DEBUG_DRIVER("!TIMEOUT! waiting PLL, let's continue\n");241 242	return 0;243}244 245static int dw_mipi_dsi_clk_is_enabled(struct clk_hw *hw)246{247	struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);248 249	return dsi_read(dsi, DSI_WRPCR) & WRPCR_PLLEN;250}251 252static unsigned long dw_mipi_dsi_clk_recalc_rate(struct clk_hw *hw,253						 unsigned long parent_rate)254{255	struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);256	unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;257	u32 val;258 259	DRM_DEBUG_DRIVER("\n");260 261	pll_in_khz = (unsigned int)(parent_rate / 1000);262 263	val = dsi_read(dsi, DSI_WRPCR);264 265	idf = (val & WRPCR_IDF) >> 11;266	if (!idf)267		idf = 1;268	ndiv = (val & WRPCR_NDIV) >> 2;269	odf = int_pow(2, (val & WRPCR_ODF) >> 16);270 271	/* Get the adjusted pll out value */272	pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);273 274	return (unsigned long)pll_out_khz * 1000;275}276 277static long dw_mipi_dsi_clk_round_rate(struct clk_hw *hw, unsigned long rate,278				       unsigned long *parent_rate)279{280	struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);281	unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;282	int ret;283 284	DRM_DEBUG_DRIVER("\n");285 286	pll_in_khz = (unsigned int)(*parent_rate / 1000);287 288	/* Compute best pll parameters */289	idf = 0;290	ndiv = 0;291	odf = 0;292 293	ret = dsi_pll_get_params(dsi, pll_in_khz, rate / 1000,294				 &idf, &ndiv, &odf);295	if (ret)296		DRM_WARN("Warning dsi_pll_get_params(): bad params\n");297 298	/* Get the adjusted pll out value */299	pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);300 301	return pll_out_khz * 1000;302}303 304static int dw_mipi_dsi_clk_set_rate(struct clk_hw *hw, unsigned long rate,305				    unsigned long parent_rate)306{307	struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);308	unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;309	int ret;310	u32 val;311 312	DRM_DEBUG_DRIVER("\n");313 314	pll_in_khz = (unsigned int)(parent_rate / 1000);315 316	/* Compute best pll parameters */317	idf = 0;318	ndiv = 0;319	odf = 0;320 321	ret = dsi_pll_get_params(dsi, pll_in_khz, rate / 1000, &idf, &ndiv, &odf);322	if (ret)323		DRM_WARN("Warning dsi_pll_get_params(): bad params\n");324 325	/* Get the adjusted pll out value */326	pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);327 328	/* Set the PLL division factors */329	dsi_update_bits(dsi, DSI_WRPCR,	WRPCR_NDIV | WRPCR_IDF | WRPCR_ODF,330			(ndiv << 2) | (idf << 11) | ((ffs(odf) - 1) << 16));331 332	/* Compute uix4 & set the bit period in high-speed mode */333	val = 4000000 / pll_out_khz;334	dsi_update_bits(dsi, DSI_WPCR0, WPCR0_UIX4, val);335 336	return 0;337}338 339static void dw_mipi_dsi_clk_unregister(void *data)340{341	struct dw_mipi_dsi_stm *dsi = data;342 343	DRM_DEBUG_DRIVER("\n");344 345	of_clk_del_provider(dsi->dev->of_node);346	clk_hw_unregister(&dsi->txbyte_clk);347}348 349static const struct clk_ops dw_mipi_dsi_stm_clk_ops = {350	.enable = dw_mipi_dsi_clk_enable,351	.disable = dw_mipi_dsi_clk_disable,352	.is_enabled = dw_mipi_dsi_clk_is_enabled,353	.recalc_rate = dw_mipi_dsi_clk_recalc_rate,354	.round_rate = dw_mipi_dsi_clk_round_rate,355	.set_rate = dw_mipi_dsi_clk_set_rate,356};357 358static struct clk_init_data cdata_init = {359	.name = "ck_dsi_phy",360	.ops = &dw_mipi_dsi_stm_clk_ops,361	.parent_names = (const char * []) {"ck_hse"},362	.num_parents = 1,363};364 365static int dw_mipi_dsi_clk_register(struct dw_mipi_dsi_stm *dsi,366				    struct device *dev)367{368	struct device_node *node = dev->of_node;369	int ret;370 371	DRM_DEBUG_DRIVER("Registering clk\n");372 373	dsi->txbyte_clk.init = &cdata_init;374 375	ret = clk_hw_register(dev, &dsi->txbyte_clk);376	if (ret)377		return ret;378 379	ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get,380				     &dsi->txbyte_clk);381	if (ret)382		clk_hw_unregister(&dsi->txbyte_clk);383 384	return ret;385}386 387static int dw_mipi_dsi_phy_init(void *priv_data)388{389	struct dw_mipi_dsi_stm *dsi = priv_data;390	int ret;391 392	ret = clk_prepare_enable(dsi->txbyte_clk.clk);393	return ret;394}395 396static void dw_mipi_dsi_phy_power_on(void *priv_data)397{398	struct dw_mipi_dsi_stm *dsi = priv_data;399 400	DRM_DEBUG_DRIVER("\n");401 402	/* Enable the DSI wrapper */403	dsi_set(dsi, DSI_WCR, WCR_DSIEN);404}405 406static void dw_mipi_dsi_phy_power_off(void *priv_data)407{408	struct dw_mipi_dsi_stm *dsi = priv_data;409 410	DRM_DEBUG_DRIVER("\n");411 412	clk_disable_unprepare(dsi->txbyte_clk.clk);413 414	/* Disable the DSI wrapper */415	dsi_clear(dsi, DSI_WCR, WCR_DSIEN);416}417 418static int419dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,420			  unsigned long mode_flags, u32 lanes, u32 format,421			  unsigned int *lane_mbps)422{423	struct dw_mipi_dsi_stm *dsi = priv_data;424	unsigned int pll_in_khz, pll_out_khz;425	int ret, bpp;426 427	pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);428 429	/* Compute requested pll out */430	bpp = mipi_dsi_pixel_format_to_bpp(format);431	pll_out_khz = mode->clock * bpp / lanes;432 433	/* Add 20% to pll out to be higher than pixel bw (burst mode only) */434	if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST)435		pll_out_khz = (pll_out_khz * 12) / 10;436 437	if (pll_out_khz > dsi->lane_max_kbps) {438		pll_out_khz = dsi->lane_max_kbps;439		DRM_WARN("Warning max phy mbps is used\n");440	}441	if (pll_out_khz < dsi->lane_min_kbps) {442		pll_out_khz = dsi->lane_min_kbps;443		DRM_WARN("Warning min phy mbps is used\n");444	}445 446	ret = clk_set_rate((dsi->txbyte_clk.clk), pll_out_khz * 1000);447	if (ret)448		DRM_DEBUG_DRIVER("ERROR Could not set rate of %d to %s clk->name",449				 pll_out_khz, clk_hw_get_name(&dsi->txbyte_clk));450 451	/* Select video mode by resetting DSIM bit */452	dsi_clear(dsi, DSI_WCFGR, WCFGR_DSIM);453 454	/* Select the color coding */455	dsi_update_bits(dsi, DSI_WCFGR, WCFGR_COLMUX,456			dsi_color_from_mipi(format) << 1);457 458	*lane_mbps = pll_out_khz / 1000;459 460	DRM_DEBUG_DRIVER("pll_in %ukHz pll_out %ukHz lane_mbps %uMHz\n",461			 pll_in_khz, pll_out_khz, *lane_mbps);462 463	return 0;464}465 466#define DSI_PHY_DELAY(fp, vp, mbps) DIV_ROUND_UP((fp) * (mbps) + 1000 * (vp), 8000)467 468static int469dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,470			   struct dw_mipi_dsi_dphy_timing *timing)471{472	/*473	 * From STM32MP157 datasheet, valid for STM32F469, STM32F7x9, STM32H747474	 * phy_clkhs2lp_time = (272+136*UI)/(8*UI)475	 * phy_clklp2hs_time = (512+40*UI)/(8*UI)476	 * phy_hs2lp_time = (192+64*UI)/(8*UI)477	 * phy_lp2hs_time = (256+32*UI)/(8*UI)478	 */479	timing->clk_hs2lp = DSI_PHY_DELAY(272, 136, lane_mbps);480	timing->clk_lp2hs = DSI_PHY_DELAY(512, 40, lane_mbps);481	timing->data_hs2lp = DSI_PHY_DELAY(192, 64, lane_mbps);482	timing->data_lp2hs = DSI_PHY_DELAY(256, 32, lane_mbps);483 484	return 0;485}486 487#define CLK_TOLERANCE_HZ 50488 489static enum drm_mode_status490dw_mipi_dsi_stm_mode_valid(void *priv_data,491			   const struct drm_display_mode *mode,492			   unsigned long mode_flags, u32 lanes, u32 format)493{494	struct dw_mipi_dsi_stm *dsi = priv_data;495	unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;496	int ret, bpp;497 498	bpp = mipi_dsi_pixel_format_to_bpp(format);499	if (bpp < 0)500		return MODE_BAD;501 502	/* Compute requested pll out */503	pll_out_khz = mode->clock * bpp / lanes;504 505	if (pll_out_khz > dsi->lane_max_kbps)506		return MODE_CLOCK_HIGH;507 508	if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {509		/* Add 20% to pll out to be higher than pixel bw */510		pll_out_khz = (pll_out_khz * 12) / 10;511	} else {512		if (pll_out_khz < dsi->lane_min_kbps)513			return MODE_CLOCK_LOW;514	}515 516	/* Compute best pll parameters */517	idf = 0;518	ndiv = 0;519	odf = 0;520	pll_in_khz = clk_get_rate(dsi->pllref_clk) / 1000;521	ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz, &idf, &ndiv, &odf);522	if (ret) {523		DRM_WARN("Warning dsi_pll_get_params(): bad params\n");524		return MODE_ERROR;525	}526 527	if (!(mode_flags & MIPI_DSI_MODE_VIDEO_BURST)) {528		unsigned int px_clock_hz, target_px_clock_hz, lane_mbps;529		int dsi_short_packet_size_px, hfp, hsync, hbp, delay_to_lp;530		struct dw_mipi_dsi_dphy_timing dphy_timing;531 532		/* Get the adjusted pll out value */533		pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);534 535		px_clock_hz = DIV_ROUND_CLOSEST_ULL(1000ULL * pll_out_khz * lanes, bpp);536		target_px_clock_hz = mode->clock * 1000;537		/*538		 * Filter modes according to the clock value, particularly useful for539		 * hdmi modes that require precise pixel clocks.540		 */541		if (px_clock_hz < target_px_clock_hz - CLK_TOLERANCE_HZ ||542		    px_clock_hz > target_px_clock_hz + CLK_TOLERANCE_HZ)543			return MODE_CLOCK_RANGE;544 545		/* sync packets are codes as DSI short packets (4 bytes) */546		dsi_short_packet_size_px = DIV_ROUND_UP(4 * BITS_PER_BYTE, bpp);547 548		hfp = mode->hsync_start - mode->hdisplay;549		hsync = mode->hsync_end - mode->hsync_start;550		hbp = mode->htotal - mode->hsync_end;551 552		/* hsync must be longer than 4 bytes HSS packets */553		if (hsync < dsi_short_packet_size_px)554			return MODE_HSYNC_NARROW;555 556		if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {557			/* HBP must be longer than 4 bytes HSE packets */558			if (hbp < dsi_short_packet_size_px)559				return MODE_HSYNC_NARROW;560			hbp -= dsi_short_packet_size_px;561		} else {562			/* With sync events HBP extends in the hsync */563			hbp += hsync - dsi_short_packet_size_px;564		}565 566		lane_mbps = pll_out_khz / 1000;567		ret = dw_mipi_dsi_phy_get_timing(priv_data, lane_mbps, &dphy_timing);568		if (ret)569			return MODE_ERROR;570		/*571		 * In non-burst mode DSI has to enter in LP during HFP572		 * (horizontal front porch) or HBP (horizontal back porch) to573		 * resync with LTDC pixel clock.574		 */575		delay_to_lp = DIV_ROUND_UP((dphy_timing.data_hs2lp + dphy_timing.data_lp2hs) *576					   lanes * BITS_PER_BYTE, bpp);577		if (hfp < delay_to_lp && hbp < delay_to_lp)578			return MODE_HSYNC;579	}580 581	return MODE_OK;582}583 584static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = {585	.init = dw_mipi_dsi_phy_init,586	.power_on = dw_mipi_dsi_phy_power_on,587	.power_off = dw_mipi_dsi_phy_power_off,588	.get_lane_mbps = dw_mipi_dsi_get_lane_mbps,589	.get_timing = dw_mipi_dsi_phy_get_timing,590};591 592static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data = {593	.max_data_lanes = 2,594	.mode_valid = dw_mipi_dsi_stm_mode_valid,595	.phy_ops = &dw_mipi_dsi_stm_phy_ops,596};597 598static const struct of_device_id dw_mipi_dsi_stm_dt_ids[] = {599	{ .compatible = "st,stm32-dsi", .data = &dw_mipi_dsi_stm_plat_data, },600	{ },601};602MODULE_DEVICE_TABLE(of, dw_mipi_dsi_stm_dt_ids);603 604static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)605{606	struct device *dev = &pdev->dev;607	struct dw_mipi_dsi_stm *dsi;608	const struct dw_mipi_dsi_plat_data *pdata = of_device_get_match_data(dev);609	int ret;610 611	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);612	if (!dsi)613		return -ENOMEM;614 615	dsi->base = devm_platform_ioremap_resource(pdev, 0);616	if (IS_ERR(dsi->base)) {617		ret = PTR_ERR(dsi->base);618		DRM_ERROR("Unable to get dsi registers %d\n", ret);619		return ret;620	}621 622	dsi->vdd_supply = devm_regulator_get(dev, "phy-dsi");623	if (IS_ERR(dsi->vdd_supply)) {624		ret = PTR_ERR(dsi->vdd_supply);625		dev_err_probe(dev, ret, "Failed to request regulator\n");626		return ret;627	}628 629	ret = regulator_enable(dsi->vdd_supply);630	if (ret) {631		DRM_ERROR("Failed to enable regulator: %d\n", ret);632		return ret;633	}634 635	dsi->pllref_clk = devm_clk_get(dev, "ref");636	if (IS_ERR(dsi->pllref_clk)) {637		ret = PTR_ERR(dsi->pllref_clk);638		dev_err_probe(dev, ret, "Unable to get pll reference clock\n");639		goto err_clk_get;640	}641 642	ret = clk_prepare_enable(dsi->pllref_clk);643	if (ret) {644		DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);645		goto err_clk_get;646	}647 648	dsi->pclk = devm_clk_get(dev, "pclk");649	if (IS_ERR(dsi->pclk)) {650		ret = PTR_ERR(dsi->pclk);651		DRM_ERROR("Unable to get peripheral clock: %d\n", ret);652		goto err_dsi_probe;653	}654 655	ret = clk_prepare_enable(dsi->pclk);656	if (ret) {657		DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);658		goto err_dsi_probe;659	}660 661	dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;662	clk_disable_unprepare(dsi->pclk);663 664	if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {665		ret = -ENODEV;666		DRM_ERROR("bad dsi hardware version\n");667		goto err_dsi_probe;668	}669 670	/* set lane capabilities according to hw version */671	dsi->lane_min_kbps = LANE_MIN_KBPS;672	dsi->lane_max_kbps = LANE_MAX_KBPS;673	if (dsi->hw_version == HWVER_131) {674		dsi->lane_min_kbps *= 2;675		dsi->lane_max_kbps *= 2;676	}677 678	dsi->pdata = *pdata;679	dsi->pdata.base = dsi->base;680	dsi->pdata.priv_data = dsi;681 682	dsi->pdata.max_data_lanes = 2;683	dsi->pdata.phy_ops = &dw_mipi_dsi_stm_phy_ops;684 685	platform_set_drvdata(pdev, dsi);686 687	dsi->dsi = dw_mipi_dsi_probe(pdev, &dsi->pdata);688	if (IS_ERR(dsi->dsi)) {689		ret = PTR_ERR(dsi->dsi);690		dev_err_probe(dev, ret, "Failed to initialize mipi dsi host\n");691		goto err_dsi_probe;692	}693 694	/*695	 * We need to wait for the generic bridge to probe before enabling and696	 * register the internal pixel clock.697	 */698	ret = clk_prepare_enable(dsi->pclk);699	if (ret) {700		DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);701		goto err_dsi_probe;702	}703 704	ret = dw_mipi_dsi_clk_register(dsi, dev);705	if (ret) {706		DRM_ERROR("Failed to register DSI pixel clock: %d\n", ret);707		clk_disable_unprepare(dsi->pclk);708		goto err_dsi_probe;709	}710 711	clk_disable_unprepare(dsi->pclk);712 713	return 0;714 715err_dsi_probe:716	clk_disable_unprepare(dsi->pllref_clk);717err_clk_get:718	regulator_disable(dsi->vdd_supply);719 720	return ret;721}722 723static void dw_mipi_dsi_stm_remove(struct platform_device *pdev)724{725	struct dw_mipi_dsi_stm *dsi = platform_get_drvdata(pdev);726 727	dw_mipi_dsi_remove(dsi->dsi);728	clk_disable_unprepare(dsi->pllref_clk);729	dw_mipi_dsi_clk_unregister(dsi);730	regulator_disable(dsi->vdd_supply);731}732 733static int dw_mipi_dsi_stm_suspend(struct device *dev)734{735	struct dw_mipi_dsi_stm *dsi = dev_get_drvdata(dev);736 737	DRM_DEBUG_DRIVER("\n");738 739	clk_disable_unprepare(dsi->pllref_clk);740	clk_disable_unprepare(dsi->pclk);741	regulator_disable(dsi->vdd_supply);742 743	return 0;744}745 746static int dw_mipi_dsi_stm_resume(struct device *dev)747{748	struct dw_mipi_dsi_stm *dsi = dev_get_drvdata(dev);749	int ret;750 751	DRM_DEBUG_DRIVER("\n");752 753	ret = regulator_enable(dsi->vdd_supply);754	if (ret) {755		DRM_ERROR("Failed to enable regulator: %d\n", ret);756		return ret;757	}758 759	ret = clk_prepare_enable(dsi->pclk);760	if (ret) {761		regulator_disable(dsi->vdd_supply);762		DRM_ERROR("Failed to enable pclk: %d\n", ret);763		return ret;764	}765 766	ret = clk_prepare_enable(dsi->pllref_clk);767	if (ret) {768		clk_disable_unprepare(dsi->pclk);769		regulator_disable(dsi->vdd_supply);770		DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);771		return ret;772	}773 774	return 0;775}776 777static const struct dev_pm_ops dw_mipi_dsi_stm_pm_ops = {778	SYSTEM_SLEEP_PM_OPS(dw_mipi_dsi_stm_suspend,779			    dw_mipi_dsi_stm_resume)780	RUNTIME_PM_OPS(dw_mipi_dsi_stm_suspend,781		       dw_mipi_dsi_stm_resume, NULL)782};783 784static struct platform_driver dw_mipi_dsi_stm_driver = {785	.probe		= dw_mipi_dsi_stm_probe,786	.remove_new	= dw_mipi_dsi_stm_remove,787	.driver		= {788		.of_match_table = dw_mipi_dsi_stm_dt_ids,789		.name	= "stm32-display-dsi",790		.pm = &dw_mipi_dsi_stm_pm_ops,791	},792};793 794module_platform_driver(dw_mipi_dsi_stm_driver);795 796MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");797MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");798MODULE_DESCRIPTION("STMicroelectronics DW MIPI DSI host controller driver");799MODULE_LICENSE("GPL v2");800