brintos

brintos / linux-shallow public Read only

0
0
Text · 23.1 KiB · 2347f8d Raw
918 lines · c
1// SPDX-License-Identifier: GPL-2.0+2 3/*4 * Copyright 2022,2023 NXP5 */6 7#include <linux/bitfield.h>8#include <linux/bits.h>9#include <linux/clk.h>10#include <linux/delay.h>11#include <linux/math.h>12#include <linux/media-bus-format.h>13#include <linux/mfd/syscon.h>14#include <linux/module.h>15#include <linux/of.h>16#include <linux/phy/phy.h>17#include <linux/phy/phy-mipi-dphy.h>18#include <linux/platform_device.h>19#include <linux/regmap.h>20 21#include <drm/bridge/dw_mipi_dsi.h>22#include <drm/drm_bridge.h>23#include <drm/drm_mipi_dsi.h>24#include <drm/drm_modes.h>25 26/* DPHY PLL configuration registers */27#define DSI_REG				0x4c28#define  CFGCLKFREQRANGE_MASK		GENMASK(5, 0)29#define  CFGCLKFREQRANGE(x)		FIELD_PREP(CFGCLKFREQRANGE_MASK, (x))30#define  CLKSEL_MASK			GENMASK(7, 6)31#define  CLKSEL_STOP			FIELD_PREP(CLKSEL_MASK, 0)32#define  CLKSEL_GEN			FIELD_PREP(CLKSEL_MASK, 1)33#define  CLKSEL_EXT			FIELD_PREP(CLKSEL_MASK, 2)34#define  HSFREQRANGE_MASK		GENMASK(14, 8)35#define  HSFREQRANGE(x)			FIELD_PREP(HSFREQRANGE_MASK, (x))36#define  UPDATE_PLL			BIT(17)37#define  SHADOW_CLR			BIT(18)38#define  CLK_EXT			BIT(19)39 40#define DSI_WRITE_REG0			0x5041#define  M_MASK				GENMASK(9, 0)42#define  M(x)				FIELD_PREP(M_MASK, ((x) - 2))43#define  N_MASK				GENMASK(13, 10)44#define  N(x)				FIELD_PREP(N_MASK, ((x) - 1))45#define  VCO_CTRL_MASK			GENMASK(19, 14)46#define  VCO_CTRL(x)			FIELD_PREP(VCO_CTRL_MASK, (x))47#define  PROP_CTRL_MASK			GENMASK(25, 20)48#define  PROP_CTRL(x)			FIELD_PREP(PROP_CTRL_MASK, (x))49#define  INT_CTRL_MASK			GENMASK(31, 26)50#define  INT_CTRL(x)			FIELD_PREP(INT_CTRL_MASK, (x))51 52#define DSI_WRITE_REG1			0x5453#define  GMP_CTRL_MASK			GENMASK(1, 0)54#define  GMP_CTRL(x)			FIELD_PREP(GMP_CTRL_MASK, (x))55#define  CPBIAS_CTRL_MASK		GENMASK(8, 2)56#define  CPBIAS_CTRL(x)			FIELD_PREP(CPBIAS_CTRL_MASK, (x))57#define  PLL_SHADOW_CTRL		BIT(9)58 59/* display mux control register */60#define DISPLAY_MUX			0x6061#define  MIPI_DSI_RGB666_MAP_CFG	GENMASK(7, 6)62#define  RGB666_CONFIG1			FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 0)63#define  RGB666_CONFIG2			FIELD_PREP(MIPI_DSI_RGB666_MAP_CFG, 1)64#define  MIPI_DSI_RGB565_MAP_CFG	GENMASK(5, 4)65#define  RGB565_CONFIG1			FIELD_PREP(MIPI_DSI_RGB565_MAP_CFG, 0)66#define  RGB565_CONFIG2			FIELD_PREP(MIPI_DSI_RGB565_MAP_CFG, 1)67#define  RGB565_CONFIG3			FIELD_PREP(MIPI_DSI_RGB565_MAP_CFG, 2)68#define  LCDIF_CROSS_LINE_PATTERN	GENMASK(3, 0)69#define  RGB888_TO_RGB888		FIELD_PREP(LCDIF_CROSS_LINE_PATTERN, 0)70#define  RGB888_TO_RGB666		FIELD_PREP(LCDIF_CROSS_LINE_PATTERN, 6)71#define  RGB565_TO_RGB565		FIELD_PREP(LCDIF_CROSS_LINE_PATTERN, 7)72 73#define MHZ(x)				((x) * 1000000UL)74 75#define REF_CLK_RATE_MAX		MHZ(64)76#define REF_CLK_RATE_MIN		MHZ(2)77#define FOUT_MAX			MHZ(1250)78#define FOUT_MIN			MHZ(40)79#define FVCO_DIV_FACTOR			MHZ(80)80 81#define MBPS(x)				((x) * 1000000UL)82 83#define DATA_RATE_MAX_SPEED		MBPS(2500)84#define DATA_RATE_MIN_SPEED		MBPS(80)85 86#define M_MAX				625UL87#define M_MIN				64UL88 89#define N_MAX				16U90#define N_MIN				1U91 92struct imx93_dsi {93	struct device *dev;94	struct regmap *regmap;95	struct clk *clk_pixel;96	struct clk *clk_ref;97	struct clk *clk_cfg;98	struct dw_mipi_dsi *dmd;99	struct dw_mipi_dsi_plat_data pdata;100	union phy_configure_opts phy_cfg;101	unsigned long ref_clk_rate;102	u32 format;103};104 105struct dphy_pll_cfg {106	u32 m;	/* PLL Feedback Multiplication Ratio */107	u32 n;	/* PLL Input Frequency Division Ratio */108};109 110struct dphy_pll_vco_prop {111	unsigned long max_fout;112	u8 vco_cntl;113	u8 prop_cntl;114};115 116struct dphy_pll_hsfreqrange {117	unsigned long max_mbps;118	u8 hsfreqrange;119};120 121/* DPHY Databook Table 3-13 Charge-pump Programmability */122static const struct dphy_pll_vco_prop vco_prop_map[] = {123	{   55, 0x3f, 0x0d },124	{   82, 0x37, 0x0d },125	{  110, 0x2f, 0x0d },126	{  165, 0x27, 0x0d },127	{  220, 0x1f, 0x0d },128	{  330, 0x17, 0x0d },129	{  440, 0x0f, 0x0d },130	{  660, 0x07, 0x0d },131	{ 1149, 0x03, 0x0d },132	{ 1152, 0x01, 0x0d },133	{ 1250, 0x01, 0x0e },134};135 136/* DPHY Databook Table 5-7 Frequency Ranges and Defaults */137static const struct dphy_pll_hsfreqrange hsfreqrange_map[] = {138	{   89, 0x00 },139	{   99, 0x10 },140	{  109, 0x20 },141	{  119, 0x30 },142	{  129, 0x01 },143	{  139, 0x11 },144	{  149, 0x21 },145	{  159, 0x31 },146	{  169, 0x02 },147	{  179, 0x12 },148	{  189, 0x22 },149	{  204, 0x32 },150	{  219, 0x03 },151	{  234, 0x13 },152	{  249, 0x23 },153	{  274, 0x33 },154	{  299, 0x04 },155	{  324, 0x14 },156	{  349, 0x25 },157	{  399, 0x35 },158	{  449, 0x05 },159	{  499, 0x16 },160	{  549, 0x26 },161	{  599, 0x37 },162	{  649, 0x07 },163	{  699, 0x18 },164	{  749, 0x28 },165	{  799, 0x39 },166	{  849, 0x09 },167	{  899, 0x19 },168	{  949, 0x29 },169	{  999, 0x3a },170	{ 1049, 0x0a },171	{ 1099, 0x1a },172	{ 1149, 0x2a },173	{ 1199, 0x3b },174	{ 1249, 0x0b },175	{ 1299, 0x1b },176	{ 1349, 0x2b },177	{ 1399, 0x3c },178	{ 1449, 0x0c },179	{ 1499, 0x1c },180	{ 1549, 0x2c },181	{ 1599, 0x3d },182	{ 1649, 0x0d },183	{ 1699, 0x1d },184	{ 1749, 0x2e },185	{ 1799, 0x3e },186	{ 1849, 0x0e },187	{ 1899, 0x1e },188	{ 1949, 0x2f },189	{ 1999, 0x3f },190	{ 2049, 0x0f },191	{ 2099, 0x40 },192	{ 2149, 0x41 },193	{ 2199, 0x42 },194	{ 2249, 0x43 },195	{ 2299, 0x44 },196	{ 2349, 0x45 },197	{ 2399, 0x46 },198	{ 2449, 0x47 },199	{ 2499, 0x48 },200	{ 2500, 0x49 },201};202 203static void dphy_pll_write(struct imx93_dsi *dsi, unsigned int reg, u32 value)204{205	int ret;206 207	ret = regmap_write(dsi->regmap, reg, value);208	if (ret < 0)209		dev_err(dsi->dev, "failed to write 0x%08x to pll reg 0x%x: %d\n",210			value, reg, ret);211}212 213static inline unsigned long data_rate_to_fout(unsigned long data_rate)214{215	/* Fout is half of data rate */216	return data_rate / 2;217}218 219static int220dphy_pll_get_configure_from_opts(struct imx93_dsi *dsi,221				 struct phy_configure_opts_mipi_dphy *dphy_opts,222				 struct dphy_pll_cfg *cfg)223{224	struct device *dev = dsi->dev;225	unsigned long fin = dsi->ref_clk_rate;226	unsigned long fout;227	unsigned long best_fout = 0;228	unsigned int fvco_div;229	unsigned int min_n, max_n, n, best_n = UINT_MAX;230	unsigned long m, best_m = 0;231	unsigned long min_delta = ULONG_MAX;232	unsigned long delta;233	u64 tmp;234 235	if (dphy_opts->hs_clk_rate < DATA_RATE_MIN_SPEED ||236	    dphy_opts->hs_clk_rate > DATA_RATE_MAX_SPEED) {237		dev_dbg(dev, "invalid data rate per lane: %lu\n",238			dphy_opts->hs_clk_rate);239		return -EINVAL;240	}241 242	fout = data_rate_to_fout(dphy_opts->hs_clk_rate);243 244	/* DPHY Databook 3.3.6.1 Output Frequency */245	/* Fout = Fvco / Fvco_div = (Fin * M) / (Fvco_div * N) */246	/* Fvco_div could be 1/2/4/8 according to Fout range. */247	fvco_div = 8UL / min(DIV_ROUND_UP(fout, FVCO_DIV_FACTOR), 8UL);248 249	/* limitation: 2MHz <= Fin / N <= 8MHz */250	min_n = DIV_ROUND_UP_ULL((u64)fin, MHZ(8));251	max_n = DIV_ROUND_DOWN_ULL((u64)fin, MHZ(2));252 253	/* clamp possible N(s) */254	min_n = clamp(min_n, N_MIN, N_MAX);255	max_n = clamp(max_n, N_MIN, N_MAX);256 257	dev_dbg(dev, "Fout = %lu, Fvco_div = %u, n_range = [%u, %u]\n",258		fout, fvco_div, min_n, max_n);259 260	for (n = min_n; n <= max_n; n++) {261		/* M = (Fout * N * Fvco_div) / Fin */262		m = DIV_ROUND_CLOSEST(fout * n * fvco_div, fin);263 264		/* check M range */265		if (m < M_MIN || m > M_MAX)266			continue;267 268		/* calculate temporary Fout */269		tmp = m * fin;270		do_div(tmp, n * fvco_div);271		if (tmp < FOUT_MIN || tmp > FOUT_MAX)272			continue;273 274		delta = abs(fout - tmp);275		if (delta < min_delta) {276			best_n = n;277			best_m = m;278			min_delta = delta;279			best_fout = tmp;280		}281	}282 283	if (best_fout) {284		cfg->m = best_m;285		cfg->n = best_n;286		dev_dbg(dev, "best Fout = %lu, m = %u, n = %u\n",287			best_fout, cfg->m, cfg->n);288	} else {289		dev_dbg(dev, "failed to find best Fout\n");290		return -EINVAL;291	}292 293	return 0;294}295 296static void dphy_pll_clear_shadow(struct imx93_dsi *dsi)297{298	/* Reference DPHY Databook Figure 3-3 Initialization Timing Diagram. */299	/* Select clock generation first. */300	dphy_pll_write(dsi, DSI_REG, CLKSEL_GEN);301 302	/* Clear shadow after clock selection is done a while. */303	fsleep(1);304	dphy_pll_write(dsi, DSI_REG, CLKSEL_GEN | SHADOW_CLR);305 306	/* A minimum pulse of 5ns on shadow_clear signal. */307	fsleep(1);308	dphy_pll_write(dsi, DSI_REG, CLKSEL_GEN);309}310 311static unsigned long dphy_pll_get_cfgclkrange(struct imx93_dsi *dsi)312{313	/*314	 * DPHY Databook Table 4-4 System Control Signals mentions an equation315	 * for cfgclkfreqrange[5:0].316	 */317	return (clk_get_rate(dsi->clk_cfg) / MHZ(1) - 17) * 4;318}319 320static u8321dphy_pll_get_hsfreqrange(struct phy_configure_opts_mipi_dphy *dphy_opts)322{323	unsigned long mbps = dphy_opts->hs_clk_rate / MHZ(1);324	int i;325 326	for (i = 0; i < ARRAY_SIZE(hsfreqrange_map); i++)327		if (mbps <= hsfreqrange_map[i].max_mbps)328			return hsfreqrange_map[i].hsfreqrange;329 330	return 0;331}332 333static u8 dphy_pll_get_vco(struct phy_configure_opts_mipi_dphy *dphy_opts)334{335	unsigned long fout = data_rate_to_fout(dphy_opts->hs_clk_rate) / MHZ(1);336	int i;337 338	for (i = 0; i < ARRAY_SIZE(vco_prop_map); i++)339		if (fout <= vco_prop_map[i].max_fout)340			return vco_prop_map[i].vco_cntl;341 342	return 0;343}344 345static u8 dphy_pll_get_prop(struct phy_configure_opts_mipi_dphy *dphy_opts)346{347	unsigned long fout = data_rate_to_fout(dphy_opts->hs_clk_rate) / MHZ(1);348	int i;349 350	for (i = 0; i < ARRAY_SIZE(vco_prop_map); i++)351		if (fout <= vco_prop_map[i].max_fout)352			return vco_prop_map[i].prop_cntl;353 354	return 0;355}356 357static int dphy_pll_update(struct imx93_dsi *dsi)358{359	int ret;360 361	ret = regmap_update_bits(dsi->regmap, DSI_REG, UPDATE_PLL, UPDATE_PLL);362	if (ret < 0) {363		dev_err(dsi->dev, "failed to set UPDATE_PLL: %d\n", ret);364		return ret;365	}366 367	/*368	 * The updatepll signal should be asserted for a minimum of four clkin369	 * cycles, according to DPHY Databook Figure 3-3 Initialization Timing370	 * Diagram.371	 */372	fsleep(10);373 374	ret = regmap_update_bits(dsi->regmap, DSI_REG, UPDATE_PLL, 0);375	if (ret < 0) {376		dev_err(dsi->dev, "failed to clear UPDATE_PLL: %d\n", ret);377		return ret;378	}379 380	return 0;381}382 383static int dphy_pll_configure(struct imx93_dsi *dsi, union phy_configure_opts *opts)384{385	struct dphy_pll_cfg cfg = { 0 };386	u32 val;387	int ret;388 389	ret = dphy_pll_get_configure_from_opts(dsi, &opts->mipi_dphy, &cfg);390	if (ret) {391		dev_err(dsi->dev, "failed to get phy pll cfg %d\n", ret);392		return ret;393	}394 395	dphy_pll_clear_shadow(dsi);396 397	/* DSI_REG */398	val = CLKSEL_GEN |399	      CFGCLKFREQRANGE(dphy_pll_get_cfgclkrange(dsi)) |400	      HSFREQRANGE(dphy_pll_get_hsfreqrange(&opts->mipi_dphy));401	dphy_pll_write(dsi, DSI_REG, val);402 403	/* DSI_WRITE_REG0 */404	val = M(cfg.m) | N(cfg.n) | INT_CTRL(0) |405	      VCO_CTRL(dphy_pll_get_vco(&opts->mipi_dphy)) |406	      PROP_CTRL(dphy_pll_get_prop(&opts->mipi_dphy));407	dphy_pll_write(dsi, DSI_WRITE_REG0, val);408 409	/* DSI_WRITE_REG1 */410	dphy_pll_write(dsi, DSI_WRITE_REG1, GMP_CTRL(1) | CPBIAS_CTRL(0x10));411 412	ret = clk_prepare_enable(dsi->clk_ref);413	if (ret < 0) {414		dev_err(dsi->dev, "failed to enable ref clock: %d\n", ret);415		return ret;416	}417 418	/*419	 * At least 10 refclk cycles are required before updatePLL assertion,420	 * according to DPHY Databook Figure 3-3 Initialization Timing Diagram.421	 */422	fsleep(10);423 424	ret = dphy_pll_update(dsi);425	if (ret < 0) {426		clk_disable_unprepare(dsi->clk_ref);427		return ret;428	}429 430	return 0;431}432 433static void dphy_pll_clear_reg(struct imx93_dsi *dsi)434{435	dphy_pll_write(dsi, DSI_REG, 0);436	dphy_pll_write(dsi, DSI_WRITE_REG0, 0);437	dphy_pll_write(dsi, DSI_WRITE_REG1, 0);438}439 440static int dphy_pll_init(struct imx93_dsi *dsi)441{442	int ret;443 444	ret = clk_prepare_enable(dsi->clk_cfg);445	if (ret < 0) {446		dev_err(dsi->dev, "failed to enable config clock: %d\n", ret);447		return ret;448	}449 450	dphy_pll_clear_reg(dsi);451 452	return 0;453}454 455static void dphy_pll_uninit(struct imx93_dsi *dsi)456{457	dphy_pll_clear_reg(dsi);458	clk_disable_unprepare(dsi->clk_cfg);459}460 461static void dphy_pll_power_off(struct imx93_dsi *dsi)462{463	dphy_pll_clear_reg(dsi);464	clk_disable_unprepare(dsi->clk_ref);465}466 467static int imx93_dsi_get_phy_configure_opts(struct imx93_dsi *dsi,468					    const struct drm_display_mode *mode,469					    union phy_configure_opts *phy_cfg,470					    u32 lanes, u32 format)471{472	struct device *dev = dsi->dev;473	int bpp;474	int ret;475 476	bpp = mipi_dsi_pixel_format_to_bpp(format);477	if (bpp < 0) {478		dev_dbg(dev, "failed to get bpp for pixel format %d\n", format);479		return -EINVAL;480	}481 482	ret = phy_mipi_dphy_get_default_config(mode->clock * MSEC_PER_SEC, bpp,483					       lanes, &phy_cfg->mipi_dphy);484	if (ret < 0) {485		dev_dbg(dev, "failed to get default phy cfg %d\n", ret);486		return ret;487	}488 489	return 0;490}491 492static enum drm_mode_status493imx93_dsi_validate_mode(struct imx93_dsi *dsi, const struct drm_display_mode *mode)494{495	struct drm_bridge *bridge = dw_mipi_dsi_get_bridge(dsi->dmd);496 497	/* Get the last bridge */498	while (drm_bridge_get_next_bridge(bridge))499		bridge = drm_bridge_get_next_bridge(bridge);500 501	if ((bridge->ops & DRM_BRIDGE_OP_DETECT) &&502	    (bridge->ops & DRM_BRIDGE_OP_EDID)) {503		unsigned long pixel_clock_rate = mode->clock * 1000;504		unsigned long rounded_rate;505 506		/* Allow +/-0.5% pixel clock rate deviation */507		rounded_rate = clk_round_rate(dsi->clk_pixel, pixel_clock_rate);508		if (rounded_rate < pixel_clock_rate * 995 / 1000 ||509		    rounded_rate > pixel_clock_rate * 1005 / 1000) {510			dev_dbg(dsi->dev, "failed to round clock for mode " DRM_MODE_FMT "\n",511				DRM_MODE_ARG(mode));512			return MODE_NOCLOCK;513		}514	}515 516	return MODE_OK;517}518 519static enum drm_mode_status520imx93_dsi_validate_phy(struct imx93_dsi *dsi, const struct drm_display_mode *mode,521		       unsigned long mode_flags, u32 lanes, u32 format)522{523	union phy_configure_opts phy_cfg;524	struct dphy_pll_cfg cfg = { 0 };525	struct device *dev = dsi->dev;526	int ret;527 528	ret = imx93_dsi_get_phy_configure_opts(dsi, mode, &phy_cfg, lanes,529					       format);530	if (ret < 0) {531		dev_dbg(dev, "failed to get phy cfg opts %d\n", ret);532		return MODE_ERROR;533	}534 535	ret = dphy_pll_get_configure_from_opts(dsi, &phy_cfg.mipi_dphy, &cfg);536	if (ret < 0) {537		dev_dbg(dev, "failed to get phy pll cfg %d\n", ret);538		return MODE_NOCLOCK;539	}540 541	return MODE_OK;542}543 544static enum drm_mode_status545imx93_dsi_mode_valid(void *priv_data, const struct drm_display_mode *mode,546		     unsigned long mode_flags, u32 lanes, u32 format)547{548	struct imx93_dsi *dsi = priv_data;549	struct device *dev = dsi->dev;550	enum drm_mode_status ret;551 552	ret = imx93_dsi_validate_mode(dsi, mode);553	if (ret != MODE_OK) {554		dev_dbg(dev, "failed to validate mode " DRM_MODE_FMT "\n",555			DRM_MODE_ARG(mode));556		return ret;557	}558 559	ret = imx93_dsi_validate_phy(dsi, mode, mode_flags, lanes, format);560	if (ret != MODE_OK) {561		dev_dbg(dev, "failed to validate phy for mode " DRM_MODE_FMT "\n",562			DRM_MODE_ARG(mode));563		return ret;564	}565 566	return MODE_OK;567}568 569static bool imx93_dsi_mode_fixup(void *priv_data,570				 const struct drm_display_mode *mode,571				 struct drm_display_mode *adjusted_mode)572{573	struct imx93_dsi *dsi = priv_data;574	unsigned long pixel_clock_rate;575	unsigned long rounded_rate;576 577	pixel_clock_rate = mode->clock * 1000;578	rounded_rate = clk_round_rate(dsi->clk_pixel, pixel_clock_rate);579 580	memcpy(adjusted_mode, mode, sizeof(*mode));581	adjusted_mode->clock = rounded_rate / 1000;582 583	dev_dbg(dsi->dev, "adj clock %d for mode " DRM_MODE_FMT "\n",584		adjusted_mode->clock, DRM_MODE_ARG(mode));585 586	return true;587}588 589static u32 *imx93_dsi_get_input_bus_fmts(void *priv_data,590					 struct drm_bridge *bridge,591					 struct drm_bridge_state *bridge_state,592					 struct drm_crtc_state *crtc_state,593					 struct drm_connector_state *conn_state,594					 u32 output_fmt,595					 unsigned int *num_input_fmts)596{597	u32 *input_fmts, input_fmt;598 599	*num_input_fmts = 0;600 601	switch (output_fmt) {602	case MEDIA_BUS_FMT_RGB888_1X24:603	case MEDIA_BUS_FMT_RGB666_1X18:604	case MEDIA_BUS_FMT_FIXED:605		input_fmt = MEDIA_BUS_FMT_RGB888_1X24;606		break;607	case MEDIA_BUS_FMT_RGB565_1X16:608		input_fmt = output_fmt;609		break;610	default:611		return NULL;612	}613 614	input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);615	if (!input_fmts)616		return NULL;617	input_fmts[0] = input_fmt;618	*num_input_fmts = 1;619 620	return input_fmts;621}622 623static int imx93_dsi_phy_init(void *priv_data)624{625	struct imx93_dsi *dsi = priv_data;626	unsigned int fmt = 0;627	int ret;628 629	switch (dsi->format) {630	case MIPI_DSI_FMT_RGB888:631		fmt = RGB888_TO_RGB888;632		break;633	case MIPI_DSI_FMT_RGB666:634		fmt = RGB888_TO_RGB666;635		regmap_update_bits(dsi->regmap, DISPLAY_MUX,636				   MIPI_DSI_RGB666_MAP_CFG, RGB666_CONFIG2);637		break;638	case MIPI_DSI_FMT_RGB666_PACKED:639		fmt = RGB888_TO_RGB666;640		regmap_update_bits(dsi->regmap, DISPLAY_MUX,641				   MIPI_DSI_RGB666_MAP_CFG, RGB666_CONFIG1);642		break;643	case MIPI_DSI_FMT_RGB565:644		fmt = RGB565_TO_RGB565;645		regmap_update_bits(dsi->regmap, DISPLAY_MUX,646				   MIPI_DSI_RGB565_MAP_CFG, RGB565_CONFIG1);647		break;648	}649 650	regmap_update_bits(dsi->regmap, DISPLAY_MUX, LCDIF_CROSS_LINE_PATTERN, fmt);651 652	ret = dphy_pll_init(dsi);653	if (ret < 0) {654		dev_err(dsi->dev, "failed to init phy pll: %d\n", ret);655		return ret;656	}657 658	ret = dphy_pll_configure(dsi, &dsi->phy_cfg);659	if (ret < 0) {660		dev_err(dsi->dev, "failed to configure phy pll: %d\n", ret);661		dphy_pll_uninit(dsi);662		return ret;663	}664 665	return 0;666}667 668static void imx93_dsi_phy_power_off(void *priv_data)669{670	struct imx93_dsi *dsi = priv_data;671 672	dphy_pll_power_off(dsi);673	dphy_pll_uninit(dsi);674}675 676static int677imx93_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,678			unsigned long mode_flags, u32 lanes, u32 format,679			unsigned int *lane_mbps)680{681	struct imx93_dsi *dsi = priv_data;682	union phy_configure_opts phy_cfg;683	struct device *dev = dsi->dev;684	int ret;685 686	ret = imx93_dsi_get_phy_configure_opts(dsi, mode, &phy_cfg, lanes,687					       format);688	if (ret < 0) {689		dev_dbg(dev, "failed to get phy cfg opts %d\n", ret);690		return ret;691	}692 693	*lane_mbps = DIV_ROUND_UP(phy_cfg.mipi_dphy.hs_clk_rate, USEC_PER_SEC);694 695	memcpy(&dsi->phy_cfg, &phy_cfg, sizeof(phy_cfg));696 697	dev_dbg(dev, "get lane_mbps %u for mode " DRM_MODE_FMT "\n",698		*lane_mbps, DRM_MODE_ARG(mode));699 700	return 0;701}702 703/* High-Speed Transition Times */704struct hstt {705	unsigned int maxfreq;706	struct dw_mipi_dsi_dphy_timing timing;707};708 709#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp)	\710{								\711	.maxfreq = (_maxfreq),					\712	.timing = {						\713		.clk_lp2hs = (_c_lp2hs),			\714		.clk_hs2lp = (_c_hs2lp),			\715		.data_lp2hs = (_d_lp2hs),			\716		.data_hs2lp = (_d_hs2lp),			\717	}							\718}719 720/* DPHY Databook Table A-4 High-Speed Transition Times */721static const struct hstt hstt_table[] = {722	HSTT(80,    21,  17,  15, 10),723	HSTT(90,    23,  17,  16, 10),724	HSTT(100,   22,  17,  16, 10),725	HSTT(110,   25,  18,  17, 11),726	HSTT(120,   26,  20,  18, 11),727	HSTT(130,   27,  19,  19, 11),728	HSTT(140,   27,  19,  19, 11),729	HSTT(150,   28,  20,  20, 12),730	HSTT(160,   30,  21,  22, 13),731	HSTT(170,   30,  21,  23, 13),732	HSTT(180,   31,  21,  23, 13),733	HSTT(190,   32,  22,  24, 13),734	HSTT(205,   35,  22,  25, 13),735	HSTT(220,   37,  26,  27, 15),736	HSTT(235,   38,  28,  27, 16),737	HSTT(250,   41,  29,  30, 17),738	HSTT(275,   43,  29,  32, 18),739	HSTT(300,   45,  32,  35, 19),740	HSTT(325,   48,  33,  36, 18),741	HSTT(350,   51,  35,  40, 20),742	HSTT(400,   59,  37,  44, 21),743	HSTT(450,   65,  40,  49, 23),744	HSTT(500,   71,  41,  54, 24),745	HSTT(550,   77,  44,  57, 26),746	HSTT(600,   82,  46,  64, 27),747	HSTT(650,   87,  48,  67, 28),748	HSTT(700,   94,  52,  71, 29),749	HSTT(750,   99,  52,  75, 31),750	HSTT(800,  105,  55,  82, 32),751	HSTT(850,  110,  58,  85, 32),752	HSTT(900,  115,  58,  88, 35),753	HSTT(950,  120,  62,  93, 36),754	HSTT(1000, 128,  63,  99, 38),755	HSTT(1050, 132,  65, 102, 38),756	HSTT(1100, 138,  67, 106, 39),757	HSTT(1150, 146,  69, 112, 42),758	HSTT(1200, 151,  71, 117, 43),759	HSTT(1250, 153,  74, 120, 45),760	HSTT(1300, 160,  73, 124, 46),761	HSTT(1350, 165,  76, 130, 47),762	HSTT(1400, 172,  78, 134, 49),763	HSTT(1450, 177,  80, 138, 49),764	HSTT(1500, 183,  81, 143, 52),765	HSTT(1550, 191,  84, 147, 52),766	HSTT(1600, 194,  85, 152, 52),767	HSTT(1650, 201,  86, 155, 53),768	HSTT(1700, 208,  88, 161, 53),769	HSTT(1750, 212,  89, 165, 53),770	HSTT(1800, 220,  90, 171, 54),771	HSTT(1850, 223,  92, 175, 54),772	HSTT(1900, 231,  91, 180, 55),773	HSTT(1950, 236,  95, 185, 56),774	HSTT(2000, 243,  97, 190, 56),775	HSTT(2050, 248,  99, 194, 58),776	HSTT(2100, 252, 100, 199, 59),777	HSTT(2150, 259, 102, 204, 61),778	HSTT(2200, 266, 105, 210, 62),779	HSTT(2250, 269, 109, 213, 63),780	HSTT(2300, 272, 109, 217, 65),781	HSTT(2350, 281, 112, 225, 66),782	HSTT(2400, 283, 115, 226, 66),783	HSTT(2450, 282, 115, 226, 67),784	HSTT(2500, 281, 118, 227, 67),785};786 787static int imx93_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,788				    struct dw_mipi_dsi_dphy_timing *timing)789{790	struct imx93_dsi *dsi = priv_data;791	struct device *dev = dsi->dev;792	int i;793 794	for (i = 0; i < ARRAY_SIZE(hstt_table); i++)795		if (lane_mbps <= hstt_table[i].maxfreq)796			break;797 798	if (i == ARRAY_SIZE(hstt_table)) {799		dev_err(dev, "failed to get phy timing for lane_mbps %u\n",800			lane_mbps);801		return -EINVAL;802	}803 804	*timing = hstt_table[i].timing;805 806	dev_dbg(dev, "get phy timing for %u <= %u (lane_mbps)\n",807		lane_mbps, hstt_table[i].maxfreq);808 809	return 0;810}811 812static const struct dw_mipi_dsi_phy_ops imx93_dsi_phy_ops = {813	.init = imx93_dsi_phy_init,814	.power_off = imx93_dsi_phy_power_off,815	.get_lane_mbps = imx93_dsi_get_lane_mbps,816	.get_timing = imx93_dsi_phy_get_timing,817};818 819static int imx93_dsi_host_attach(void *priv_data, struct mipi_dsi_device *device)820{821	struct imx93_dsi *dsi = priv_data;822 823	dsi->format = device->format;824 825	return 0;826}827 828static const struct dw_mipi_dsi_host_ops imx93_dsi_host_ops = {829	.attach = imx93_dsi_host_attach,830};831 832static int imx93_dsi_probe(struct platform_device *pdev)833{834	struct device *dev = &pdev->dev;835	struct device_node *np = dev->of_node;836	struct imx93_dsi *dsi;837	int ret;838 839	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);840	if (!dsi)841		return -ENOMEM;842 843	dsi->regmap = syscon_regmap_lookup_by_phandle(np, "fsl,media-blk-ctrl");844	if (IS_ERR(dsi->regmap)) {845		ret = PTR_ERR(dsi->regmap);846		dev_err(dev, "failed to get block ctrl regmap: %d\n", ret);847		return ret;848	}849 850	dsi->clk_pixel = devm_clk_get(dev, "pix");851	if (IS_ERR(dsi->clk_pixel))852		return dev_err_probe(dev, PTR_ERR(dsi->clk_pixel),853				     "failed to get pixel clock\n");854 855	dsi->clk_cfg = devm_clk_get(dev, "phy_cfg");856	if (IS_ERR(dsi->clk_cfg))857		return dev_err_probe(dev, PTR_ERR(dsi->clk_cfg),858				     "failed to get phy cfg clock\n");859 860	dsi->clk_ref = devm_clk_get(dev, "phy_ref");861	if (IS_ERR(dsi->clk_ref))862		return dev_err_probe(dev, PTR_ERR(dsi->clk_ref),863				     "failed to get phy ref clock\n");864 865	dsi->ref_clk_rate = clk_get_rate(dsi->clk_ref);866	if (dsi->ref_clk_rate < REF_CLK_RATE_MIN ||867	    dsi->ref_clk_rate > REF_CLK_RATE_MAX) {868		dev_err(dev, "invalid phy ref clock rate %lu\n",869			dsi->ref_clk_rate);870		return -EINVAL;871	}872	dev_dbg(dev, "phy ref clock rate: %lu\n", dsi->ref_clk_rate);873 874	dsi->dev = dev;875	dsi->pdata.max_data_lanes = 4;876	dsi->pdata.mode_valid = imx93_dsi_mode_valid;877	dsi->pdata.mode_fixup = imx93_dsi_mode_fixup;878	dsi->pdata.get_input_bus_fmts = imx93_dsi_get_input_bus_fmts;879	dsi->pdata.phy_ops = &imx93_dsi_phy_ops;880	dsi->pdata.host_ops = &imx93_dsi_host_ops;881	dsi->pdata.priv_data = dsi;882	platform_set_drvdata(pdev, dsi);883 884	dsi->dmd = dw_mipi_dsi_probe(pdev, &dsi->pdata);885	if (IS_ERR(dsi->dmd))886		return dev_err_probe(dev, PTR_ERR(dsi->dmd),887				     "failed to probe dw_mipi_dsi\n");888 889	return 0;890}891 892static void imx93_dsi_remove(struct platform_device *pdev)893{894	struct imx93_dsi *dsi = platform_get_drvdata(pdev);895 896	dw_mipi_dsi_remove(dsi->dmd);897}898 899static const struct of_device_id imx93_dsi_dt_ids[] = {900	{ .compatible = "fsl,imx93-mipi-dsi", },901	{ /* sentinel */ }902};903MODULE_DEVICE_TABLE(of, imx93_dsi_dt_ids);904 905static struct platform_driver imx93_dsi_driver = {906	.probe	= imx93_dsi_probe,907	.remove_new = imx93_dsi_remove,908	.driver	= {909		.of_match_table = imx93_dsi_dt_ids,910		.name = "imx93_mipi_dsi",911	},912};913module_platform_driver(imx93_dsi_driver);914 915MODULE_DESCRIPTION("Freescale i.MX93 MIPI DSI driver");916MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>");917MODULE_LICENSE("GPL");918