162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
462306a36Sopenharmony_ci * Author:
562306a36Sopenharmony_ci *      Chris Zhong <zyw@rock-chips.com>
662306a36Sopenharmony_ci *      Nickey Yang <nickey.yang@rock-chips.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/clk.h>
1062306a36Sopenharmony_ci#include <linux/iopoll.h>
1162306a36Sopenharmony_ci#include <linux/math64.h>
1262306a36Sopenharmony_ci#include <linux/mfd/syscon.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/of_device.h>
1562306a36Sopenharmony_ci#include <linux/of_platform.h>
1662306a36Sopenharmony_ci#include <linux/phy/phy.h>
1762306a36Sopenharmony_ci#include <linux/platform_device.h>
1862306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1962306a36Sopenharmony_ci#include <linux/regmap.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <video/mipi_display.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <drm/bridge/dw_mipi_dsi.h>
2462306a36Sopenharmony_ci#include <drm/drm_mipi_dsi.h>
2562306a36Sopenharmony_ci#include <drm/drm_of.h>
2662306a36Sopenharmony_ci#include <drm/drm_simple_kms_helper.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include "rockchip_drm_drv.h"
2962306a36Sopenharmony_ci#include "rockchip_drm_vop.h"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define DSI_PHY_RSTZ			0xa0
3262306a36Sopenharmony_ci#define PHY_DISFORCEPLL			0
3362306a36Sopenharmony_ci#define PHY_ENFORCEPLL			BIT(3)
3462306a36Sopenharmony_ci#define PHY_DISABLECLK			0
3562306a36Sopenharmony_ci#define PHY_ENABLECLK			BIT(2)
3662306a36Sopenharmony_ci#define PHY_RSTZ			0
3762306a36Sopenharmony_ci#define PHY_UNRSTZ			BIT(1)
3862306a36Sopenharmony_ci#define PHY_SHUTDOWNZ			0
3962306a36Sopenharmony_ci#define PHY_UNSHUTDOWNZ			BIT(0)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define DSI_PHY_IF_CFG			0xa4
4262306a36Sopenharmony_ci#define N_LANES(n)			((((n) - 1) & 0x3) << 0)
4362306a36Sopenharmony_ci#define PHY_STOP_WAIT_TIME(cycle)	(((cycle) & 0xff) << 8)
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define DSI_PHY_STATUS			0xb0
4662306a36Sopenharmony_ci#define LOCK				BIT(0)
4762306a36Sopenharmony_ci#define STOP_STATE_CLK_LANE		BIT(2)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define DSI_PHY_TST_CTRL0		0xb4
5062306a36Sopenharmony_ci#define PHY_TESTCLK			BIT(1)
5162306a36Sopenharmony_ci#define PHY_UNTESTCLK			0
5262306a36Sopenharmony_ci#define PHY_TESTCLR			BIT(0)
5362306a36Sopenharmony_ci#define PHY_UNTESTCLR			0
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define DSI_PHY_TST_CTRL1		0xb8
5662306a36Sopenharmony_ci#define PHY_TESTEN			BIT(16)
5762306a36Sopenharmony_ci#define PHY_UNTESTEN			0
5862306a36Sopenharmony_ci#define PHY_TESTDOUT(n)			(((n) & 0xff) << 8)
5962306a36Sopenharmony_ci#define PHY_TESTDIN(n)			(((n) & 0xff) << 0)
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define DSI_INT_ST0			0xbc
6262306a36Sopenharmony_ci#define DSI_INT_ST1			0xc0
6362306a36Sopenharmony_ci#define DSI_INT_MSK0			0xc4
6462306a36Sopenharmony_ci#define DSI_INT_MSK1			0xc8
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#define PHY_STATUS_TIMEOUT_US		10000
6762306a36Sopenharmony_ci#define CMD_PKT_STATUS_TIMEOUT_US	20000
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define BYPASS_VCO_RANGE	BIT(7)
7062306a36Sopenharmony_ci#define VCO_RANGE_CON_SEL(val)	(((val) & 0x7) << 3)
7162306a36Sopenharmony_ci#define VCO_IN_CAP_CON_DEFAULT	(0x0 << 1)
7262306a36Sopenharmony_ci#define VCO_IN_CAP_CON_LOW	(0x1 << 1)
7362306a36Sopenharmony_ci#define VCO_IN_CAP_CON_HIGH	(0x2 << 1)
7462306a36Sopenharmony_ci#define REF_BIAS_CUR_SEL	BIT(0)
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define CP_CURRENT_3UA	0x1
7762306a36Sopenharmony_ci#define CP_CURRENT_4_5UA	0x2
7862306a36Sopenharmony_ci#define CP_CURRENT_7_5UA	0x6
7962306a36Sopenharmony_ci#define CP_CURRENT_6UA	0x9
8062306a36Sopenharmony_ci#define CP_CURRENT_12UA	0xb
8162306a36Sopenharmony_ci#define CP_CURRENT_SEL(val)	((val) & 0xf)
8262306a36Sopenharmony_ci#define CP_PROGRAM_EN		BIT(7)
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci#define LPF_RESISTORS_15_5KOHM	0x1
8562306a36Sopenharmony_ci#define LPF_RESISTORS_13KOHM	0x2
8662306a36Sopenharmony_ci#define LPF_RESISTORS_11_5KOHM	0x4
8762306a36Sopenharmony_ci#define LPF_RESISTORS_10_5KOHM	0x8
8862306a36Sopenharmony_ci#define LPF_RESISTORS_8KOHM	0x10
8962306a36Sopenharmony_ci#define LPF_PROGRAM_EN		BIT(6)
9062306a36Sopenharmony_ci#define LPF_RESISTORS_SEL(val)	((val) & 0x3f)
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#define HSFREQRANGE_SEL(val)	(((val) & 0x3f) << 1)
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci#define INPUT_DIVIDER(val)	(((val) - 1) & 0x7f)
9562306a36Sopenharmony_ci#define LOW_PROGRAM_EN		0
9662306a36Sopenharmony_ci#define HIGH_PROGRAM_EN		BIT(7)
9762306a36Sopenharmony_ci#define LOOP_DIV_LOW_SEL(val)	(((val) - 1) & 0x1f)
9862306a36Sopenharmony_ci#define LOOP_DIV_HIGH_SEL(val)	((((val) - 1) >> 5) & 0xf)
9962306a36Sopenharmony_ci#define PLL_LOOP_DIV_EN		BIT(5)
10062306a36Sopenharmony_ci#define PLL_INPUT_DIV_EN	BIT(4)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci#define POWER_CONTROL		BIT(6)
10362306a36Sopenharmony_ci#define INTERNAL_REG_CURRENT	BIT(3)
10462306a36Sopenharmony_ci#define BIAS_BLOCK_ON		BIT(2)
10562306a36Sopenharmony_ci#define BANDGAP_ON		BIT(0)
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci#define TER_RESISTOR_HIGH	BIT(7)
10862306a36Sopenharmony_ci#define	TER_RESISTOR_LOW	0
10962306a36Sopenharmony_ci#define LEVEL_SHIFTERS_ON	BIT(6)
11062306a36Sopenharmony_ci#define TER_CAL_DONE		BIT(5)
11162306a36Sopenharmony_ci#define SETRD_MAX		(0x7 << 2)
11262306a36Sopenharmony_ci#define POWER_MANAGE		BIT(1)
11362306a36Sopenharmony_ci#define TER_RESISTORS_ON	BIT(0)
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci#define BIASEXTR_SEL(val)	((val) & 0x7)
11662306a36Sopenharmony_ci#define BANDGAP_SEL(val)	((val) & 0x7)
11762306a36Sopenharmony_ci#define TLP_PROGRAM_EN		BIT(7)
11862306a36Sopenharmony_ci#define THS_PRE_PROGRAM_EN	BIT(7)
11962306a36Sopenharmony_ci#define THS_ZERO_PROGRAM_EN	BIT(6)
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci#define PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL		0x10
12262306a36Sopenharmony_ci#define PLL_CP_CONTROL_PLL_LOCK_BYPASS			0x11
12362306a36Sopenharmony_ci#define PLL_LPF_AND_CP_CONTROL				0x12
12462306a36Sopenharmony_ci#define PLL_INPUT_DIVIDER_RATIO				0x17
12562306a36Sopenharmony_ci#define PLL_LOOP_DIVIDER_RATIO				0x18
12662306a36Sopenharmony_ci#define PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL	0x19
12762306a36Sopenharmony_ci#define BANDGAP_AND_BIAS_CONTROL			0x20
12862306a36Sopenharmony_ci#define TERMINATION_RESISTER_CONTROL			0x21
12962306a36Sopenharmony_ci#define AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY		0x22
13062306a36Sopenharmony_ci#define HS_RX_CONTROL_OF_LANE_CLK			0x34
13162306a36Sopenharmony_ci#define HS_RX_CONTROL_OF_LANE_0				0x44
13262306a36Sopenharmony_ci#define HS_RX_CONTROL_OF_LANE_1				0x54
13362306a36Sopenharmony_ci#define HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL	0x60
13462306a36Sopenharmony_ci#define HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL	0x61
13562306a36Sopenharmony_ci#define HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL	0x62
13662306a36Sopenharmony_ci#define HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL	0x63
13762306a36Sopenharmony_ci#define HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL	0x64
13862306a36Sopenharmony_ci#define HS_TX_CLOCK_LANE_POST_TIME_CONTROL		0x65
13962306a36Sopenharmony_ci#define HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL	0x70
14062306a36Sopenharmony_ci#define HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL	0x71
14162306a36Sopenharmony_ci#define HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL	0x72
14262306a36Sopenharmony_ci#define HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL	0x73
14362306a36Sopenharmony_ci#define HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL		0x74
14462306a36Sopenharmony_ci#define HS_RX_DATA_LANE_THS_SETTLE_CONTROL		0x75
14562306a36Sopenharmony_ci#define HS_RX_CONTROL_OF_LANE_2				0x84
14662306a36Sopenharmony_ci#define HS_RX_CONTROL_OF_LANE_3				0x94
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci#define DW_MIPI_NEEDS_PHY_CFG_CLK	BIT(0)
14962306a36Sopenharmony_ci#define DW_MIPI_NEEDS_GRF_CLK		BIT(1)
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci#define PX30_GRF_PD_VO_CON1		0x0438
15262306a36Sopenharmony_ci#define PX30_DSI_FORCETXSTOPMODE	(0xf << 7)
15362306a36Sopenharmony_ci#define PX30_DSI_FORCERXMODE		BIT(6)
15462306a36Sopenharmony_ci#define PX30_DSI_TURNDISABLE		BIT(5)
15562306a36Sopenharmony_ci#define PX30_DSI_LCDC_SEL		BIT(0)
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci#define RK3288_GRF_SOC_CON6		0x025c
15862306a36Sopenharmony_ci#define RK3288_DSI0_LCDC_SEL		BIT(6)
15962306a36Sopenharmony_ci#define RK3288_DSI1_LCDC_SEL		BIT(9)
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci#define RK3399_GRF_SOC_CON20		0x6250
16262306a36Sopenharmony_ci#define RK3399_DSI0_LCDC_SEL		BIT(0)
16362306a36Sopenharmony_ci#define RK3399_DSI1_LCDC_SEL		BIT(4)
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci#define RK3399_GRF_SOC_CON22		0x6258
16662306a36Sopenharmony_ci#define RK3399_DSI0_TURNREQUEST		(0xf << 12)
16762306a36Sopenharmony_ci#define RK3399_DSI0_TURNDISABLE		(0xf << 8)
16862306a36Sopenharmony_ci#define RK3399_DSI0_FORCETXSTOPMODE	(0xf << 4)
16962306a36Sopenharmony_ci#define RK3399_DSI0_FORCERXMODE		(0xf << 0)
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci#define RK3399_GRF_SOC_CON23		0x625c
17262306a36Sopenharmony_ci#define RK3399_DSI1_TURNDISABLE		(0xf << 12)
17362306a36Sopenharmony_ci#define RK3399_DSI1_FORCETXSTOPMODE	(0xf << 8)
17462306a36Sopenharmony_ci#define RK3399_DSI1_FORCERXMODE		(0xf << 4)
17562306a36Sopenharmony_ci#define RK3399_DSI1_ENABLE		(0xf << 0)
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci#define RK3399_GRF_SOC_CON24		0x6260
17862306a36Sopenharmony_ci#define RK3399_TXRX_MASTERSLAVEZ	BIT(7)
17962306a36Sopenharmony_ci#define RK3399_TXRX_ENABLECLK		BIT(6)
18062306a36Sopenharmony_ci#define RK3399_TXRX_BASEDIR		BIT(5)
18162306a36Sopenharmony_ci#define RK3399_TXRX_SRC_SEL_ISP0	BIT(4)
18262306a36Sopenharmony_ci#define RK3399_TXRX_TURNREQUEST		GENMASK(3, 0)
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci#define RK3568_GRF_VO_CON2		0x0368
18562306a36Sopenharmony_ci#define RK3568_DSI0_SKEWCALHS		(0x1f << 11)
18662306a36Sopenharmony_ci#define RK3568_DSI0_FORCETXSTOPMODE	(0xf << 4)
18762306a36Sopenharmony_ci#define RK3568_DSI0_TURNDISABLE		BIT(2)
18862306a36Sopenharmony_ci#define RK3568_DSI0_FORCERXMODE		BIT(0)
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci/*
19162306a36Sopenharmony_ci * Note these registers do not appear in the datasheet, they are
19262306a36Sopenharmony_ci * however present in the BSP driver which is where these values
19362306a36Sopenharmony_ci * come from. Name GRF_VO_CON3 is assumed.
19462306a36Sopenharmony_ci */
19562306a36Sopenharmony_ci#define RK3568_GRF_VO_CON3		0x36c
19662306a36Sopenharmony_ci#define RK3568_DSI1_SKEWCALHS		(0x1f << 11)
19762306a36Sopenharmony_ci#define RK3568_DSI1_FORCETXSTOPMODE	(0xf << 4)
19862306a36Sopenharmony_ci#define RK3568_DSI1_TURNDISABLE		BIT(2)
19962306a36Sopenharmony_ci#define RK3568_DSI1_FORCERXMODE		BIT(0)
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci#define HIWORD_UPDATE(val, mask)	(val | (mask) << 16)
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_cienum {
20462306a36Sopenharmony_ci	DW_DSI_USAGE_IDLE,
20562306a36Sopenharmony_ci	DW_DSI_USAGE_DSI,
20662306a36Sopenharmony_ci	DW_DSI_USAGE_PHY,
20762306a36Sopenharmony_ci};
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cienum {
21062306a36Sopenharmony_ci	BANDGAP_97_07,
21162306a36Sopenharmony_ci	BANDGAP_98_05,
21262306a36Sopenharmony_ci	BANDGAP_99_02,
21362306a36Sopenharmony_ci	BANDGAP_100_00,
21462306a36Sopenharmony_ci	BANDGAP_93_17,
21562306a36Sopenharmony_ci	BANDGAP_94_15,
21662306a36Sopenharmony_ci	BANDGAP_95_12,
21762306a36Sopenharmony_ci	BANDGAP_96_10,
21862306a36Sopenharmony_ci};
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cienum {
22162306a36Sopenharmony_ci	BIASEXTR_87_1,
22262306a36Sopenharmony_ci	BIASEXTR_91_5,
22362306a36Sopenharmony_ci	BIASEXTR_95_9,
22462306a36Sopenharmony_ci	BIASEXTR_100,
22562306a36Sopenharmony_ci	BIASEXTR_105_94,
22662306a36Sopenharmony_ci	BIASEXTR_111_88,
22762306a36Sopenharmony_ci	BIASEXTR_118_8,
22862306a36Sopenharmony_ci	BIASEXTR_127_7,
22962306a36Sopenharmony_ci};
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistruct rockchip_dw_dsi_chip_data {
23262306a36Sopenharmony_ci	u32 reg;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	u32 lcdsel_grf_reg;
23562306a36Sopenharmony_ci	u32 lcdsel_big;
23662306a36Sopenharmony_ci	u32 lcdsel_lit;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	u32 enable_grf_reg;
23962306a36Sopenharmony_ci	u32 enable;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	u32 lanecfg1_grf_reg;
24262306a36Sopenharmony_ci	u32 lanecfg1;
24362306a36Sopenharmony_ci	u32 lanecfg2_grf_reg;
24462306a36Sopenharmony_ci	u32 lanecfg2;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	int (*dphy_rx_init)(struct phy *phy);
24762306a36Sopenharmony_ci	int (*dphy_rx_power_on)(struct phy *phy);
24862306a36Sopenharmony_ci	int (*dphy_rx_power_off)(struct phy *phy);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	unsigned int flags;
25162306a36Sopenharmony_ci	unsigned int max_data_lanes;
25262306a36Sopenharmony_ci};
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistruct dw_mipi_dsi_rockchip {
25562306a36Sopenharmony_ci	struct device *dev;
25662306a36Sopenharmony_ci	struct rockchip_encoder encoder;
25762306a36Sopenharmony_ci	void __iomem *base;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	struct regmap *grf_regmap;
26062306a36Sopenharmony_ci	struct clk *pclk;
26162306a36Sopenharmony_ci	struct clk *pllref_clk;
26262306a36Sopenharmony_ci	struct clk *grf_clk;
26362306a36Sopenharmony_ci	struct clk *phy_cfg_clk;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	/* dual-channel */
26662306a36Sopenharmony_ci	bool is_slave;
26762306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *slave;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	/* optional external dphy */
27062306a36Sopenharmony_ci	struct phy *phy;
27162306a36Sopenharmony_ci	union phy_configure_opts phy_opts;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	/* being a phy for other mipi hosts */
27462306a36Sopenharmony_ci	unsigned int usage_mode;
27562306a36Sopenharmony_ci	struct mutex usage_mutex;
27662306a36Sopenharmony_ci	struct phy *dphy;
27762306a36Sopenharmony_ci	struct phy_configure_opts_mipi_dphy dphy_config;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	unsigned int lane_mbps; /* per lane */
28062306a36Sopenharmony_ci	u16 input_div;
28162306a36Sopenharmony_ci	u16 feedback_div;
28262306a36Sopenharmony_ci	u32 format;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	struct dw_mipi_dsi *dmd;
28562306a36Sopenharmony_ci	const struct rockchip_dw_dsi_chip_data *cdata;
28662306a36Sopenharmony_ci	struct dw_mipi_dsi_plat_data pdata;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	bool dsi_bound;
28962306a36Sopenharmony_ci};
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_cistatic struct dw_mipi_dsi_rockchip *to_dsi(struct drm_encoder *encoder)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	return container_of(rkencoder, struct dw_mipi_dsi_rockchip, encoder);
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_cistruct dphy_pll_parameter_map {
29962306a36Sopenharmony_ci	unsigned int max_mbps;
30062306a36Sopenharmony_ci	u8 hsfreqrange;
30162306a36Sopenharmony_ci	u8 icpctrl;
30262306a36Sopenharmony_ci	u8 lpfctrl;
30362306a36Sopenharmony_ci};
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci/* The table is based on 27MHz DPHY pll reference clock. */
30662306a36Sopenharmony_cistatic const struct dphy_pll_parameter_map dppa_map[] = {
30762306a36Sopenharmony_ci	{  89, 0x00, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
30862306a36Sopenharmony_ci	{  99, 0x10, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
30962306a36Sopenharmony_ci	{ 109, 0x20, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
31062306a36Sopenharmony_ci	{ 129, 0x01, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
31162306a36Sopenharmony_ci	{ 139, 0x11, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
31262306a36Sopenharmony_ci	{ 149, 0x21, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
31362306a36Sopenharmony_ci	{ 169, 0x02, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
31462306a36Sopenharmony_ci	{ 179, 0x12, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
31562306a36Sopenharmony_ci	{ 199, 0x22, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
31662306a36Sopenharmony_ci	{ 219, 0x03, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
31762306a36Sopenharmony_ci	{ 239, 0x13, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
31862306a36Sopenharmony_ci	{ 249, 0x23, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
31962306a36Sopenharmony_ci	{ 269, 0x04, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM },
32062306a36Sopenharmony_ci	{ 299, 0x14, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM },
32162306a36Sopenharmony_ci	{ 329, 0x05, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
32262306a36Sopenharmony_ci	{ 359, 0x15, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
32362306a36Sopenharmony_ci	{ 399, 0x25, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
32462306a36Sopenharmony_ci	{ 449, 0x06, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
32562306a36Sopenharmony_ci	{ 499, 0x16, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
32662306a36Sopenharmony_ci	{ 549, 0x07, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM },
32762306a36Sopenharmony_ci	{ 599, 0x17, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM },
32862306a36Sopenharmony_ci	{ 649, 0x08, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
32962306a36Sopenharmony_ci	{ 699, 0x18, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
33062306a36Sopenharmony_ci	{ 749, 0x09, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
33162306a36Sopenharmony_ci	{ 799, 0x19, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
33262306a36Sopenharmony_ci	{ 849, 0x29, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
33362306a36Sopenharmony_ci	{ 899, 0x39, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
33462306a36Sopenharmony_ci	{ 949, 0x0a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
33562306a36Sopenharmony_ci	{ 999, 0x1a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
33662306a36Sopenharmony_ci	{1049, 0x2a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
33762306a36Sopenharmony_ci	{1099, 0x3a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
33862306a36Sopenharmony_ci	{1149, 0x0b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
33962306a36Sopenharmony_ci	{1199, 0x1b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
34062306a36Sopenharmony_ci	{1249, 0x2b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
34162306a36Sopenharmony_ci	{1299, 0x3b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
34262306a36Sopenharmony_ci	{1349, 0x0c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
34362306a36Sopenharmony_ci	{1399, 0x1c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
34462306a36Sopenharmony_ci	{1449, 0x2c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
34562306a36Sopenharmony_ci	{1500, 0x3c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }
34662306a36Sopenharmony_ci};
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_cistatic int max_mbps_to_parameter(unsigned int max_mbps)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	int i;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(dppa_map); i++)
35362306a36Sopenharmony_ci		if (dppa_map[i].max_mbps >= max_mbps)
35462306a36Sopenharmony_ci			return i;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	return -EINVAL;
35762306a36Sopenharmony_ci}
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_cistatic inline void dsi_write(struct dw_mipi_dsi_rockchip *dsi, u32 reg, u32 val)
36062306a36Sopenharmony_ci{
36162306a36Sopenharmony_ci	writel(val, dsi->base + reg);
36262306a36Sopenharmony_ci}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_cistatic void dw_mipi_dsi_phy_write(struct dw_mipi_dsi_rockchip *dsi,
36562306a36Sopenharmony_ci				  u8 test_code,
36662306a36Sopenharmony_ci				  u8 test_data)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	/*
36962306a36Sopenharmony_ci	 * With the falling edge on TESTCLK, the TESTDIN[7:0] signal content
37062306a36Sopenharmony_ci	 * is latched internally as the current test code. Test data is
37162306a36Sopenharmony_ci	 * programmed internally by rising edge on TESTCLK.
37262306a36Sopenharmony_ci	 */
37362306a36Sopenharmony_ci	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_TESTEN | PHY_TESTDOUT(0) |
37662306a36Sopenharmony_ci					  PHY_TESTDIN(test_code));
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLK | PHY_UNTESTCLR);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_UNTESTEN | PHY_TESTDOUT(0) |
38162306a36Sopenharmony_ci					  PHY_TESTDIN(test_data));
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci/*
38762306a36Sopenharmony_ci * ns2bc - Nanoseconds to byte clock cycles
38862306a36Sopenharmony_ci */
38962306a36Sopenharmony_cistatic inline unsigned int ns2bc(struct dw_mipi_dsi_rockchip *dsi, int ns)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	return DIV_ROUND_UP(ns * dsi->lane_mbps / 8, 1000);
39262306a36Sopenharmony_ci}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci/*
39562306a36Sopenharmony_ci * ns2ui - Nanoseconds to UI time periods
39662306a36Sopenharmony_ci */
39762306a36Sopenharmony_cistatic inline unsigned int ns2ui(struct dw_mipi_dsi_rockchip *dsi, int ns)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	return DIV_ROUND_UP(ns * dsi->lane_mbps, 1000);
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_cistatic int dw_mipi_dsi_phy_init(void *priv_data)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = priv_data;
40562306a36Sopenharmony_ci	int ret, i, vco;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	if (dsi->phy)
40862306a36Sopenharmony_ci		return 0;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	/*
41162306a36Sopenharmony_ci	 * Get vco from frequency(lane_mbps)
41262306a36Sopenharmony_ci	 * vco	frequency table
41362306a36Sopenharmony_ci	 * 000 - between   80 and  200 MHz
41462306a36Sopenharmony_ci	 * 001 - between  200 and  300 MHz
41562306a36Sopenharmony_ci	 * 010 - between  300 and  500 MHz
41662306a36Sopenharmony_ci	 * 011 - between  500 and  700 MHz
41762306a36Sopenharmony_ci	 * 100 - between  700 and  900 MHz
41862306a36Sopenharmony_ci	 * 101 - between  900 and 1100 MHz
41962306a36Sopenharmony_ci	 * 110 - between 1100 and 1300 MHz
42062306a36Sopenharmony_ci	 * 111 - between 1300 and 1500 MHz
42162306a36Sopenharmony_ci	 */
42262306a36Sopenharmony_ci	vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200;
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	i = max_mbps_to_parameter(dsi->lane_mbps);
42562306a36Sopenharmony_ci	if (i < 0) {
42662306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev,
42762306a36Sopenharmony_ci			      "failed to get parameter for %dmbps clock\n",
42862306a36Sopenharmony_ci			      dsi->lane_mbps);
42962306a36Sopenharmony_ci		return i;
43062306a36Sopenharmony_ci	}
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	ret = clk_prepare_enable(dsi->phy_cfg_clk);
43362306a36Sopenharmony_ci	if (ret) {
43462306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "Failed to enable phy_cfg_clk\n");
43562306a36Sopenharmony_ci		return ret;
43662306a36Sopenharmony_ci	}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL,
43962306a36Sopenharmony_ci			      BYPASS_VCO_RANGE |
44062306a36Sopenharmony_ci			      VCO_RANGE_CON_SEL(vco) |
44162306a36Sopenharmony_ci			      VCO_IN_CAP_CON_LOW |
44262306a36Sopenharmony_ci			      REF_BIAS_CUR_SEL);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, PLL_CP_CONTROL_PLL_LOCK_BYPASS,
44562306a36Sopenharmony_ci			      CP_CURRENT_SEL(dppa_map[i].icpctrl));
44662306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, PLL_LPF_AND_CP_CONTROL,
44762306a36Sopenharmony_ci			      CP_PROGRAM_EN | LPF_PROGRAM_EN |
44862306a36Sopenharmony_ci			      LPF_RESISTORS_SEL(dppa_map[i].lpfctrl));
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_0,
45162306a36Sopenharmony_ci			      HSFREQRANGE_SEL(dppa_map[i].hsfreqrange));
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, PLL_INPUT_DIVIDER_RATIO,
45462306a36Sopenharmony_ci			      INPUT_DIVIDER(dsi->input_div));
45562306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
45662306a36Sopenharmony_ci			      LOOP_DIV_LOW_SEL(dsi->feedback_div) |
45762306a36Sopenharmony_ci			      LOW_PROGRAM_EN);
45862306a36Sopenharmony_ci	/*
45962306a36Sopenharmony_ci	 * We need set PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL immediately
46062306a36Sopenharmony_ci	 * to make the configured LSB effective according to IP simulation
46162306a36Sopenharmony_ci	 * and lab test results.
46262306a36Sopenharmony_ci	 * Only in this way can we get correct mipi phy pll frequency.
46362306a36Sopenharmony_ci	 */
46462306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL,
46562306a36Sopenharmony_ci			      PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
46662306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
46762306a36Sopenharmony_ci			      LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
46862306a36Sopenharmony_ci			      HIGH_PROGRAM_EN);
46962306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL,
47062306a36Sopenharmony_ci			      PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY,
47362306a36Sopenharmony_ci			      LOW_PROGRAM_EN | BIASEXTR_SEL(BIASEXTR_127_7));
47462306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY,
47562306a36Sopenharmony_ci			      HIGH_PROGRAM_EN | BANDGAP_SEL(BANDGAP_96_10));
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, BANDGAP_AND_BIAS_CONTROL,
47862306a36Sopenharmony_ci			      POWER_CONTROL | INTERNAL_REG_CURRENT |
47962306a36Sopenharmony_ci			      BIAS_BLOCK_ON | BANDGAP_ON);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL,
48262306a36Sopenharmony_ci			      TER_RESISTOR_LOW | TER_CAL_DONE |
48362306a36Sopenharmony_ci			      SETRD_MAX | TER_RESISTORS_ON);
48462306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL,
48562306a36Sopenharmony_ci			      TER_RESISTOR_HIGH | LEVEL_SHIFTERS_ON |
48662306a36Sopenharmony_ci			      SETRD_MAX | POWER_MANAGE |
48762306a36Sopenharmony_ci			      TER_RESISTORS_ON);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL,
49062306a36Sopenharmony_ci			      TLP_PROGRAM_EN | ns2bc(dsi, 500));
49162306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL,
49262306a36Sopenharmony_ci			      THS_PRE_PROGRAM_EN | ns2ui(dsi, 40));
49362306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL,
49462306a36Sopenharmony_ci			      THS_ZERO_PROGRAM_EN | ns2bc(dsi, 300));
49562306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL,
49662306a36Sopenharmony_ci			      THS_PRE_PROGRAM_EN | ns2ui(dsi, 100));
49762306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL,
49862306a36Sopenharmony_ci			      BIT(5) | ns2bc(dsi, 100));
49962306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_POST_TIME_CONTROL,
50062306a36Sopenharmony_ci			      BIT(5) | (ns2bc(dsi, 60) + 7));
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL,
50362306a36Sopenharmony_ci			      TLP_PROGRAM_EN | ns2bc(dsi, 500));
50462306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL,
50562306a36Sopenharmony_ci			      THS_PRE_PROGRAM_EN | (ns2ui(dsi, 50) + 20));
50662306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL,
50762306a36Sopenharmony_ci			      THS_ZERO_PROGRAM_EN | (ns2bc(dsi, 140) + 2));
50862306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL,
50962306a36Sopenharmony_ci			      THS_PRE_PROGRAM_EN | (ns2ui(dsi, 60) + 8));
51062306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL,
51162306a36Sopenharmony_ci			      BIT(5) | ns2bc(dsi, 100));
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	clk_disable_unprepare(dsi->phy_cfg_clk);
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	return ret;
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistatic void dw_mipi_dsi_phy_power_on(void *priv_data)
51962306a36Sopenharmony_ci{
52062306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = priv_data;
52162306a36Sopenharmony_ci	int ret;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	ret = phy_set_mode(dsi->phy, PHY_MODE_MIPI_DPHY);
52462306a36Sopenharmony_ci	if (ret) {
52562306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "failed to set phy mode: %d\n", ret);
52662306a36Sopenharmony_ci		return;
52762306a36Sopenharmony_ci	}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	phy_configure(dsi->phy, &dsi->phy_opts);
53062306a36Sopenharmony_ci	phy_power_on(dsi->phy);
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_cistatic void dw_mipi_dsi_phy_power_off(void *priv_data)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = priv_data;
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	phy_power_off(dsi->phy);
53862306a36Sopenharmony_ci}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_cistatic int
54162306a36Sopenharmony_cidw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
54262306a36Sopenharmony_ci			  unsigned long mode_flags, u32 lanes, u32 format,
54362306a36Sopenharmony_ci			  unsigned int *lane_mbps)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = priv_data;
54662306a36Sopenharmony_ci	int bpp;
54762306a36Sopenharmony_ci	unsigned long mpclk, tmp;
54862306a36Sopenharmony_ci	unsigned int target_mbps = 1000;
54962306a36Sopenharmony_ci	unsigned int max_mbps = dppa_map[ARRAY_SIZE(dppa_map) - 1].max_mbps;
55062306a36Sopenharmony_ci	unsigned long best_freq = 0;
55162306a36Sopenharmony_ci	unsigned long fvco_min, fvco_max, fin, fout;
55262306a36Sopenharmony_ci	unsigned int min_prediv, max_prediv;
55362306a36Sopenharmony_ci	unsigned int _prediv, best_prediv;
55462306a36Sopenharmony_ci	unsigned long _fbdiv, best_fbdiv;
55562306a36Sopenharmony_ci	unsigned long min_delta = ULONG_MAX;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	dsi->format = format;
55862306a36Sopenharmony_ci	bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
55962306a36Sopenharmony_ci	if (bpp < 0) {
56062306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev,
56162306a36Sopenharmony_ci			      "failed to get bpp for pixel format %d\n",
56262306a36Sopenharmony_ci			      dsi->format);
56362306a36Sopenharmony_ci		return bpp;
56462306a36Sopenharmony_ci	}
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	mpclk = DIV_ROUND_UP(mode->clock, MSEC_PER_SEC);
56762306a36Sopenharmony_ci	if (mpclk) {
56862306a36Sopenharmony_ci		/* take 1 / 0.8, since mbps must big than bandwidth of RGB */
56962306a36Sopenharmony_ci		tmp = mpclk * (bpp / lanes) * 10 / 8;
57062306a36Sopenharmony_ci		if (tmp < max_mbps)
57162306a36Sopenharmony_ci			target_mbps = tmp;
57262306a36Sopenharmony_ci		else
57362306a36Sopenharmony_ci			DRM_DEV_ERROR(dsi->dev,
57462306a36Sopenharmony_ci				      "DPHY clock frequency is out of range\n");
57562306a36Sopenharmony_ci	}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	/* for external phy only a the mipi_dphy_config is necessary */
57862306a36Sopenharmony_ci	if (dsi->phy) {
57962306a36Sopenharmony_ci		phy_mipi_dphy_get_default_config(mode->clock * 1000 * 10 / 8,
58062306a36Sopenharmony_ci						 bpp, lanes,
58162306a36Sopenharmony_ci						 &dsi->phy_opts.mipi_dphy);
58262306a36Sopenharmony_ci		dsi->lane_mbps = target_mbps;
58362306a36Sopenharmony_ci		*lane_mbps = dsi->lane_mbps;
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci		return 0;
58662306a36Sopenharmony_ci	}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	fin = clk_get_rate(dsi->pllref_clk);
58962306a36Sopenharmony_ci	fout = target_mbps * USEC_PER_SEC;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	/* constraint: 5Mhz <= Fref / N <= 40MHz */
59262306a36Sopenharmony_ci	min_prediv = DIV_ROUND_UP(fin, 40 * USEC_PER_SEC);
59362306a36Sopenharmony_ci	max_prediv = fin / (5 * USEC_PER_SEC);
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	/* constraint: 80MHz <= Fvco <= 1500Mhz */
59662306a36Sopenharmony_ci	fvco_min = 80 * USEC_PER_SEC;
59762306a36Sopenharmony_ci	fvco_max = 1500 * USEC_PER_SEC;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
60062306a36Sopenharmony_ci		u64 tmp;
60162306a36Sopenharmony_ci		u32 delta;
60262306a36Sopenharmony_ci		/* Fvco = Fref * M / N */
60362306a36Sopenharmony_ci		tmp = (u64)fout * _prediv;
60462306a36Sopenharmony_ci		do_div(tmp, fin);
60562306a36Sopenharmony_ci		_fbdiv = tmp;
60662306a36Sopenharmony_ci		/*
60762306a36Sopenharmony_ci		 * Due to the use of a "by 2 pre-scaler," the range of the
60862306a36Sopenharmony_ci		 * feedback multiplication value M is limited to even division
60962306a36Sopenharmony_ci		 * numbers, and m must be greater than 6, not bigger than 512.
61062306a36Sopenharmony_ci		 */
61162306a36Sopenharmony_ci		if (_fbdiv < 6 || _fbdiv > 512)
61262306a36Sopenharmony_ci			continue;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci		_fbdiv += _fbdiv % 2;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci		tmp = (u64)_fbdiv * fin;
61762306a36Sopenharmony_ci		do_div(tmp, _prediv);
61862306a36Sopenharmony_ci		if (tmp < fvco_min || tmp > fvco_max)
61962306a36Sopenharmony_ci			continue;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci		delta = abs(fout - tmp);
62262306a36Sopenharmony_ci		if (delta < min_delta) {
62362306a36Sopenharmony_ci			best_prediv = _prediv;
62462306a36Sopenharmony_ci			best_fbdiv = _fbdiv;
62562306a36Sopenharmony_ci			min_delta = delta;
62662306a36Sopenharmony_ci			best_freq = tmp;
62762306a36Sopenharmony_ci		}
62862306a36Sopenharmony_ci	}
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	if (best_freq) {
63162306a36Sopenharmony_ci		dsi->lane_mbps = DIV_ROUND_UP(best_freq, USEC_PER_SEC);
63262306a36Sopenharmony_ci		*lane_mbps = dsi->lane_mbps;
63362306a36Sopenharmony_ci		dsi->input_div = best_prediv;
63462306a36Sopenharmony_ci		dsi->feedback_div = best_fbdiv;
63562306a36Sopenharmony_ci	} else {
63662306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "Can not find best_freq for DPHY\n");
63762306a36Sopenharmony_ci		return -EINVAL;
63862306a36Sopenharmony_ci	}
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	return 0;
64162306a36Sopenharmony_ci}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_cistruct hstt {
64462306a36Sopenharmony_ci	unsigned int maxfreq;
64562306a36Sopenharmony_ci	struct dw_mipi_dsi_dphy_timing timing;
64662306a36Sopenharmony_ci};
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp)	\
64962306a36Sopenharmony_ci{					\
65062306a36Sopenharmony_ci	.maxfreq = _maxfreq,		\
65162306a36Sopenharmony_ci	.timing = {			\
65262306a36Sopenharmony_ci		.clk_lp2hs = _c_lp2hs,	\
65362306a36Sopenharmony_ci		.clk_hs2lp = _c_hs2lp,	\
65462306a36Sopenharmony_ci		.data_lp2hs = _d_lp2hs,	\
65562306a36Sopenharmony_ci		.data_hs2lp = _d_hs2lp,	\
65662306a36Sopenharmony_ci	}				\
65762306a36Sopenharmony_ci}
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci/* Table A-3 High-Speed Transition Times */
66062306a36Sopenharmony_cistatic struct hstt hstt_table[] = {
66162306a36Sopenharmony_ci	HSTT(  90,  32, 20,  26, 13),
66262306a36Sopenharmony_ci	HSTT( 100,  35, 23,  28, 14),
66362306a36Sopenharmony_ci	HSTT( 110,  32, 22,  26, 13),
66462306a36Sopenharmony_ci	HSTT( 130,  31, 20,  27, 13),
66562306a36Sopenharmony_ci	HSTT( 140,  33, 22,  26, 14),
66662306a36Sopenharmony_ci	HSTT( 150,  33, 21,  26, 14),
66762306a36Sopenharmony_ci	HSTT( 170,  32, 20,  27, 13),
66862306a36Sopenharmony_ci	HSTT( 180,  36, 23,  30, 15),
66962306a36Sopenharmony_ci	HSTT( 200,  40, 22,  33, 15),
67062306a36Sopenharmony_ci	HSTT( 220,  40, 22,  33, 15),
67162306a36Sopenharmony_ci	HSTT( 240,  44, 24,  36, 16),
67262306a36Sopenharmony_ci	HSTT( 250,  48, 24,  38, 17),
67362306a36Sopenharmony_ci	HSTT( 270,  48, 24,  38, 17),
67462306a36Sopenharmony_ci	HSTT( 300,  50, 27,  41, 18),
67562306a36Sopenharmony_ci	HSTT( 330,  56, 28,  45, 18),
67662306a36Sopenharmony_ci	HSTT( 360,  59, 28,  48, 19),
67762306a36Sopenharmony_ci	HSTT( 400,  61, 30,  50, 20),
67862306a36Sopenharmony_ci	HSTT( 450,  67, 31,  55, 21),
67962306a36Sopenharmony_ci	HSTT( 500,  73, 31,  59, 22),
68062306a36Sopenharmony_ci	HSTT( 550,  79, 36,  63, 24),
68162306a36Sopenharmony_ci	HSTT( 600,  83, 37,  68, 25),
68262306a36Sopenharmony_ci	HSTT( 650,  90, 38,  73, 27),
68362306a36Sopenharmony_ci	HSTT( 700,  95, 40,  77, 28),
68462306a36Sopenharmony_ci	HSTT( 750, 102, 40,  84, 28),
68562306a36Sopenharmony_ci	HSTT( 800, 106, 42,  87, 30),
68662306a36Sopenharmony_ci	HSTT( 850, 113, 44,  93, 31),
68762306a36Sopenharmony_ci	HSTT( 900, 118, 47,  98, 32),
68862306a36Sopenharmony_ci	HSTT( 950, 124, 47, 102, 34),
68962306a36Sopenharmony_ci	HSTT(1000, 130, 49, 107, 35),
69062306a36Sopenharmony_ci	HSTT(1050, 135, 51, 111, 37),
69162306a36Sopenharmony_ci	HSTT(1100, 139, 51, 114, 38),
69262306a36Sopenharmony_ci	HSTT(1150, 146, 54, 120, 40),
69362306a36Sopenharmony_ci	HSTT(1200, 153, 57, 125, 41),
69462306a36Sopenharmony_ci	HSTT(1250, 158, 58, 130, 42),
69562306a36Sopenharmony_ci	HSTT(1300, 163, 58, 135, 44),
69662306a36Sopenharmony_ci	HSTT(1350, 168, 60, 140, 45),
69762306a36Sopenharmony_ci	HSTT(1400, 172, 64, 144, 47),
69862306a36Sopenharmony_ci	HSTT(1450, 176, 65, 148, 48),
69962306a36Sopenharmony_ci	HSTT(1500, 181, 66, 153, 50)
70062306a36Sopenharmony_ci};
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_cistatic int
70362306a36Sopenharmony_cidw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
70462306a36Sopenharmony_ci			   struct dw_mipi_dsi_dphy_timing *timing)
70562306a36Sopenharmony_ci{
70662306a36Sopenharmony_ci	int i;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(hstt_table); i++)
70962306a36Sopenharmony_ci		if (lane_mbps < hstt_table[i].maxfreq)
71062306a36Sopenharmony_ci			break;
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	if (i == ARRAY_SIZE(hstt_table))
71362306a36Sopenharmony_ci		i--;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	*timing = hstt_table[i].timing;
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	return 0;
71862306a36Sopenharmony_ci}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_cistatic const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_rockchip_phy_ops = {
72162306a36Sopenharmony_ci	.init = dw_mipi_dsi_phy_init,
72262306a36Sopenharmony_ci	.power_on = dw_mipi_dsi_phy_power_on,
72362306a36Sopenharmony_ci	.power_off = dw_mipi_dsi_phy_power_off,
72462306a36Sopenharmony_ci	.get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
72562306a36Sopenharmony_ci	.get_timing = dw_mipi_dsi_phy_get_timing,
72662306a36Sopenharmony_ci};
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_cistatic void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi)
72962306a36Sopenharmony_ci{
73062306a36Sopenharmony_ci	if (dsi->cdata->lanecfg1_grf_reg)
73162306a36Sopenharmony_ci		regmap_write(dsi->grf_regmap, dsi->cdata->lanecfg1_grf_reg,
73262306a36Sopenharmony_ci					      dsi->cdata->lanecfg1);
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	if (dsi->cdata->lanecfg2_grf_reg)
73562306a36Sopenharmony_ci		regmap_write(dsi->grf_regmap, dsi->cdata->lanecfg2_grf_reg,
73662306a36Sopenharmony_ci					      dsi->cdata->lanecfg2);
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	if (dsi->cdata->enable_grf_reg)
73962306a36Sopenharmony_ci		regmap_write(dsi->grf_regmap, dsi->cdata->enable_grf_reg,
74062306a36Sopenharmony_ci					      dsi->cdata->enable);
74162306a36Sopenharmony_ci}
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_cistatic void dw_mipi_dsi_rockchip_set_lcdsel(struct dw_mipi_dsi_rockchip *dsi,
74462306a36Sopenharmony_ci					    int mux)
74562306a36Sopenharmony_ci{
74662306a36Sopenharmony_ci	if (dsi->cdata->lcdsel_grf_reg)
74762306a36Sopenharmony_ci		regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg,
74862306a36Sopenharmony_ci			mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big);
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_cistatic int
75262306a36Sopenharmony_cidw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,
75362306a36Sopenharmony_ci				 struct drm_crtc_state *crtc_state,
75462306a36Sopenharmony_ci				 struct drm_connector_state *conn_state)
75562306a36Sopenharmony_ci{
75662306a36Sopenharmony_ci	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
75762306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder);
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	switch (dsi->format) {
76062306a36Sopenharmony_ci	case MIPI_DSI_FMT_RGB888:
76162306a36Sopenharmony_ci		s->output_mode = ROCKCHIP_OUT_MODE_P888;
76262306a36Sopenharmony_ci		break;
76362306a36Sopenharmony_ci	case MIPI_DSI_FMT_RGB666:
76462306a36Sopenharmony_ci		s->output_mode = ROCKCHIP_OUT_MODE_P666;
76562306a36Sopenharmony_ci		break;
76662306a36Sopenharmony_ci	case MIPI_DSI_FMT_RGB565:
76762306a36Sopenharmony_ci		s->output_mode = ROCKCHIP_OUT_MODE_P565;
76862306a36Sopenharmony_ci		break;
76962306a36Sopenharmony_ci	default:
77062306a36Sopenharmony_ci		WARN_ON(1);
77162306a36Sopenharmony_ci		return -EINVAL;
77262306a36Sopenharmony_ci	}
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	s->output_type = DRM_MODE_CONNECTOR_DSI;
77562306a36Sopenharmony_ci	if (dsi->slave)
77662306a36Sopenharmony_ci		s->output_flags = ROCKCHIP_OUTPUT_DSI_DUAL;
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	return 0;
77962306a36Sopenharmony_ci}
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_cistatic void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
78262306a36Sopenharmony_ci{
78362306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder);
78462306a36Sopenharmony_ci	int ret, mux;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node,
78762306a36Sopenharmony_ci						&dsi->encoder.encoder);
78862306a36Sopenharmony_ci	if (mux < 0)
78962306a36Sopenharmony_ci		return;
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	/*
79262306a36Sopenharmony_ci	 * For the RK3399, the clk of grf must be enabled before writing grf
79362306a36Sopenharmony_ci	 * register. And for RK3288 or other soc, this grf_clk must be NULL,
79462306a36Sopenharmony_ci	 * the clk_prepare_enable return true directly.
79562306a36Sopenharmony_ci	 */
79662306a36Sopenharmony_ci	ret = clk_prepare_enable(dsi->grf_clk);
79762306a36Sopenharmony_ci	if (ret) {
79862306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
79962306a36Sopenharmony_ci		return;
80062306a36Sopenharmony_ci	}
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	dw_mipi_dsi_rockchip_set_lcdsel(dsi, mux);
80362306a36Sopenharmony_ci	if (dsi->slave)
80462306a36Sopenharmony_ci		dw_mipi_dsi_rockchip_set_lcdsel(dsi->slave, mux);
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	clk_disable_unprepare(dsi->grf_clk);
80762306a36Sopenharmony_ci}
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_cistatic const struct drm_encoder_helper_funcs
81062306a36Sopenharmony_cidw_mipi_dsi_encoder_helper_funcs = {
81162306a36Sopenharmony_ci	.atomic_check = dw_mipi_dsi_encoder_atomic_check,
81262306a36Sopenharmony_ci	.enable = dw_mipi_dsi_encoder_enable,
81362306a36Sopenharmony_ci};
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_cistatic int rockchip_dsi_drm_create_encoder(struct dw_mipi_dsi_rockchip *dsi,
81662306a36Sopenharmony_ci					   struct drm_device *drm_dev)
81762306a36Sopenharmony_ci{
81862306a36Sopenharmony_ci	struct drm_encoder *encoder = &dsi->encoder.encoder;
81962306a36Sopenharmony_ci	int ret;
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
82262306a36Sopenharmony_ci							     dsi->dev->of_node);
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_DSI);
82562306a36Sopenharmony_ci	if (ret) {
82662306a36Sopenharmony_ci		DRM_ERROR("Failed to initialize encoder with drm\n");
82762306a36Sopenharmony_ci		return ret;
82862306a36Sopenharmony_ci	}
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	drm_encoder_helper_add(encoder, &dw_mipi_dsi_encoder_helper_funcs);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	return 0;
83362306a36Sopenharmony_ci}
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_cistatic struct device
83662306a36Sopenharmony_ci*dw_mipi_dsi_rockchip_find_second(struct dw_mipi_dsi_rockchip *dsi)
83762306a36Sopenharmony_ci{
83862306a36Sopenharmony_ci	const struct of_device_id *match;
83962306a36Sopenharmony_ci	struct device_node *node = NULL, *local;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	match = of_match_device(dsi->dev->driver->of_match_table, dsi->dev);
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	local = of_graph_get_remote_node(dsi->dev->of_node, 1, 0);
84462306a36Sopenharmony_ci	if (!local)
84562306a36Sopenharmony_ci		return NULL;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	while ((node = of_find_compatible_node(node, NULL,
84862306a36Sopenharmony_ci					       match->compatible))) {
84962306a36Sopenharmony_ci		struct device_node *remote;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci		/* found ourself */
85262306a36Sopenharmony_ci		if (node == dsi->dev->of_node)
85362306a36Sopenharmony_ci			continue;
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci		remote = of_graph_get_remote_node(node, 1, 0);
85662306a36Sopenharmony_ci		if (!remote)
85762306a36Sopenharmony_ci			continue;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci		/* same display device in port1-ep0 for both */
86062306a36Sopenharmony_ci		if (remote == local) {
86162306a36Sopenharmony_ci			struct dw_mipi_dsi_rockchip *dsi2;
86262306a36Sopenharmony_ci			struct platform_device *pdev;
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci			pdev = of_find_device_by_node(node);
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci			/*
86762306a36Sopenharmony_ci			 * we have found the second, so will either return it
86862306a36Sopenharmony_ci			 * or return with an error. In any case won't need the
86962306a36Sopenharmony_ci			 * nodes anymore nor continue the loop.
87062306a36Sopenharmony_ci			 */
87162306a36Sopenharmony_ci			of_node_put(remote);
87262306a36Sopenharmony_ci			of_node_put(node);
87362306a36Sopenharmony_ci			of_node_put(local);
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci			if (!pdev)
87662306a36Sopenharmony_ci				return ERR_PTR(-EPROBE_DEFER);
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci			dsi2 = platform_get_drvdata(pdev);
87962306a36Sopenharmony_ci			if (!dsi2) {
88062306a36Sopenharmony_ci				platform_device_put(pdev);
88162306a36Sopenharmony_ci				return ERR_PTR(-EPROBE_DEFER);
88262306a36Sopenharmony_ci			}
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci			return &pdev->dev;
88562306a36Sopenharmony_ci		}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci		of_node_put(remote);
88862306a36Sopenharmony_ci	}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	of_node_put(local);
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	return NULL;
89362306a36Sopenharmony_ci}
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_cistatic int dw_mipi_dsi_rockchip_bind(struct device *dev,
89662306a36Sopenharmony_ci				     struct device *master,
89762306a36Sopenharmony_ci				     void *data)
89862306a36Sopenharmony_ci{
89962306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev);
90062306a36Sopenharmony_ci	struct drm_device *drm_dev = data;
90162306a36Sopenharmony_ci	struct device *second;
90262306a36Sopenharmony_ci	bool master1, master2;
90362306a36Sopenharmony_ci	int ret;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	second = dw_mipi_dsi_rockchip_find_second(dsi);
90662306a36Sopenharmony_ci	if (IS_ERR(second))
90762306a36Sopenharmony_ci		return PTR_ERR(second);
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	if (second) {
91062306a36Sopenharmony_ci		master1 = of_property_read_bool(dsi->dev->of_node,
91162306a36Sopenharmony_ci						"clock-master");
91262306a36Sopenharmony_ci		master2 = of_property_read_bool(second->of_node,
91362306a36Sopenharmony_ci						"clock-master");
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci		if (master1 && master2) {
91662306a36Sopenharmony_ci			DRM_DEV_ERROR(dsi->dev, "only one clock-master allowed\n");
91762306a36Sopenharmony_ci			return -EINVAL;
91862306a36Sopenharmony_ci		}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci		if (!master1 && !master2) {
92162306a36Sopenharmony_ci			DRM_DEV_ERROR(dsi->dev, "no clock-master defined\n");
92262306a36Sopenharmony_ci			return -EINVAL;
92362306a36Sopenharmony_ci		}
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci		/* we are the slave in dual-DSI */
92662306a36Sopenharmony_ci		if (!master1) {
92762306a36Sopenharmony_ci			dsi->is_slave = true;
92862306a36Sopenharmony_ci			return 0;
92962306a36Sopenharmony_ci		}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci		dsi->slave = dev_get_drvdata(second);
93262306a36Sopenharmony_ci		if (!dsi->slave) {
93362306a36Sopenharmony_ci			DRM_DEV_ERROR(dev, "could not get slaves data\n");
93462306a36Sopenharmony_ci			return -ENODEV;
93562306a36Sopenharmony_ci		}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci		dsi->slave->is_slave = true;
93862306a36Sopenharmony_ci		dw_mipi_dsi_set_slave(dsi->dmd, dsi->slave->dmd);
93962306a36Sopenharmony_ci		put_device(second);
94062306a36Sopenharmony_ci	}
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	pm_runtime_get_sync(dsi->dev);
94362306a36Sopenharmony_ci	if (dsi->slave)
94462306a36Sopenharmony_ci		pm_runtime_get_sync(dsi->slave->dev);
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	ret = clk_prepare_enable(dsi->pllref_clk);
94762306a36Sopenharmony_ci	if (ret) {
94862306a36Sopenharmony_ci		DRM_DEV_ERROR(dev, "Failed to enable pllref_clk: %d\n", ret);
94962306a36Sopenharmony_ci		goto out_pm_runtime;
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	/*
95362306a36Sopenharmony_ci	 * With the GRF clock running, write lane and dual-mode configurations
95462306a36Sopenharmony_ci	 * that won't change immediately. If we waited until enable() to do
95562306a36Sopenharmony_ci	 * this, things like panel preparation would not be able to send
95662306a36Sopenharmony_ci	 * commands over DSI.
95762306a36Sopenharmony_ci	 */
95862306a36Sopenharmony_ci	ret = clk_prepare_enable(dsi->grf_clk);
95962306a36Sopenharmony_ci	if (ret) {
96062306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
96162306a36Sopenharmony_ci		goto out_pll_clk;
96262306a36Sopenharmony_ci	}
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	dw_mipi_dsi_rockchip_config(dsi);
96562306a36Sopenharmony_ci	if (dsi->slave)
96662306a36Sopenharmony_ci		dw_mipi_dsi_rockchip_config(dsi->slave);
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	clk_disable_unprepare(dsi->grf_clk);
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	ret = rockchip_dsi_drm_create_encoder(dsi, drm_dev);
97162306a36Sopenharmony_ci	if (ret) {
97262306a36Sopenharmony_ci		DRM_DEV_ERROR(dev, "Failed to create drm encoder\n");
97362306a36Sopenharmony_ci		goto out_pll_clk;
97462306a36Sopenharmony_ci	}
97562306a36Sopenharmony_ci	rockchip_drm_encoder_set_crtc_endpoint_id(&dsi->encoder,
97662306a36Sopenharmony_ci						  dev->of_node, 0, 0);
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	ret = dw_mipi_dsi_bind(dsi->dmd, &dsi->encoder.encoder);
97962306a36Sopenharmony_ci	if (ret) {
98062306a36Sopenharmony_ci		DRM_DEV_ERROR(dev, "Failed to bind: %d\n", ret);
98162306a36Sopenharmony_ci		goto out_pll_clk;
98262306a36Sopenharmony_ci	}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	dsi->dsi_bound = true;
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	return 0;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ciout_pll_clk:
98962306a36Sopenharmony_ci	clk_disable_unprepare(dsi->pllref_clk);
99062306a36Sopenharmony_ciout_pm_runtime:
99162306a36Sopenharmony_ci	pm_runtime_put(dsi->dev);
99262306a36Sopenharmony_ci	if (dsi->slave)
99362306a36Sopenharmony_ci		pm_runtime_put(dsi->slave->dev);
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	return ret;
99662306a36Sopenharmony_ci}
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_cistatic void dw_mipi_dsi_rockchip_unbind(struct device *dev,
99962306a36Sopenharmony_ci					struct device *master,
100062306a36Sopenharmony_ci					void *data)
100162306a36Sopenharmony_ci{
100262306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	if (dsi->is_slave)
100562306a36Sopenharmony_ci		return;
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	dsi->dsi_bound = false;
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	dw_mipi_dsi_unbind(dsi->dmd);
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	clk_disable_unprepare(dsi->pllref_clk);
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	pm_runtime_put(dsi->dev);
101462306a36Sopenharmony_ci	if (dsi->slave)
101562306a36Sopenharmony_ci		pm_runtime_put(dsi->slave->dev);
101662306a36Sopenharmony_ci}
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_cistatic const struct component_ops dw_mipi_dsi_rockchip_ops = {
101962306a36Sopenharmony_ci	.bind	= dw_mipi_dsi_rockchip_bind,
102062306a36Sopenharmony_ci	.unbind	= dw_mipi_dsi_rockchip_unbind,
102162306a36Sopenharmony_ci};
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_cistatic int dw_mipi_dsi_rockchip_host_attach(void *priv_data,
102462306a36Sopenharmony_ci					    struct mipi_dsi_device *device)
102562306a36Sopenharmony_ci{
102662306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = priv_data;
102762306a36Sopenharmony_ci	struct device *second;
102862306a36Sopenharmony_ci	int ret;
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	mutex_lock(&dsi->usage_mutex);
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	if (dsi->usage_mode != DW_DSI_USAGE_IDLE) {
103362306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "dsi controller already in use\n");
103462306a36Sopenharmony_ci		mutex_unlock(&dsi->usage_mutex);
103562306a36Sopenharmony_ci		return -EBUSY;
103662306a36Sopenharmony_ci	}
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	dsi->usage_mode = DW_DSI_USAGE_DSI;
103962306a36Sopenharmony_ci	mutex_unlock(&dsi->usage_mutex);
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	ret = component_add(dsi->dev, &dw_mipi_dsi_rockchip_ops);
104262306a36Sopenharmony_ci	if (ret) {
104362306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "Failed to register component: %d\n",
104462306a36Sopenharmony_ci					ret);
104562306a36Sopenharmony_ci		goto out;
104662306a36Sopenharmony_ci	}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	second = dw_mipi_dsi_rockchip_find_second(dsi);
104962306a36Sopenharmony_ci	if (IS_ERR(second)) {
105062306a36Sopenharmony_ci		ret = PTR_ERR(second);
105162306a36Sopenharmony_ci		goto out;
105262306a36Sopenharmony_ci	}
105362306a36Sopenharmony_ci	if (second) {
105462306a36Sopenharmony_ci		ret = component_add(second, &dw_mipi_dsi_rockchip_ops);
105562306a36Sopenharmony_ci		if (ret) {
105662306a36Sopenharmony_ci			DRM_DEV_ERROR(second,
105762306a36Sopenharmony_ci				      "Failed to register component: %d\n",
105862306a36Sopenharmony_ci				      ret);
105962306a36Sopenharmony_ci			goto out;
106062306a36Sopenharmony_ci		}
106162306a36Sopenharmony_ci	}
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	return 0;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ciout:
106662306a36Sopenharmony_ci	mutex_lock(&dsi->usage_mutex);
106762306a36Sopenharmony_ci	dsi->usage_mode = DW_DSI_USAGE_IDLE;
106862306a36Sopenharmony_ci	mutex_unlock(&dsi->usage_mutex);
106962306a36Sopenharmony_ci	return ret;
107062306a36Sopenharmony_ci}
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_cistatic int dw_mipi_dsi_rockchip_host_detach(void *priv_data,
107362306a36Sopenharmony_ci					    struct mipi_dsi_device *device)
107462306a36Sopenharmony_ci{
107562306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = priv_data;
107662306a36Sopenharmony_ci	struct device *second;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	second = dw_mipi_dsi_rockchip_find_second(dsi);
107962306a36Sopenharmony_ci	if (second && !IS_ERR(second))
108062306a36Sopenharmony_ci		component_del(second, &dw_mipi_dsi_rockchip_ops);
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	component_del(dsi->dev, &dw_mipi_dsi_rockchip_ops);
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	mutex_lock(&dsi->usage_mutex);
108562306a36Sopenharmony_ci	dsi->usage_mode = DW_DSI_USAGE_IDLE;
108662306a36Sopenharmony_ci	mutex_unlock(&dsi->usage_mutex);
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	return 0;
108962306a36Sopenharmony_ci}
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_cistatic const struct dw_mipi_dsi_host_ops dw_mipi_dsi_rockchip_host_ops = {
109262306a36Sopenharmony_ci	.attach = dw_mipi_dsi_rockchip_host_attach,
109362306a36Sopenharmony_ci	.detach = dw_mipi_dsi_rockchip_host_detach,
109462306a36Sopenharmony_ci};
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_cistatic int dw_mipi_dsi_rockchip_dphy_bind(struct device *dev,
109762306a36Sopenharmony_ci					  struct device *master,
109862306a36Sopenharmony_ci					  void *data)
109962306a36Sopenharmony_ci{
110062306a36Sopenharmony_ci	/*
110162306a36Sopenharmony_ci	 * Nothing to do when used as a dphy.
110262306a36Sopenharmony_ci	 * Just make the rest of Rockchip-DRM happy
110362306a36Sopenharmony_ci	 * by being here.
110462306a36Sopenharmony_ci	 */
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	return 0;
110762306a36Sopenharmony_ci}
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_cistatic void dw_mipi_dsi_rockchip_dphy_unbind(struct device *dev,
111062306a36Sopenharmony_ci					     struct device *master,
111162306a36Sopenharmony_ci					     void *data)
111262306a36Sopenharmony_ci{
111362306a36Sopenharmony_ci	/* Nothing to do when used as a dphy. */
111462306a36Sopenharmony_ci}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_cistatic const struct component_ops dw_mipi_dsi_rockchip_dphy_ops = {
111762306a36Sopenharmony_ci	.bind	= dw_mipi_dsi_rockchip_dphy_bind,
111862306a36Sopenharmony_ci	.unbind	= dw_mipi_dsi_rockchip_dphy_unbind,
111962306a36Sopenharmony_ci};
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_cistatic int dw_mipi_dsi_dphy_init(struct phy *phy)
112262306a36Sopenharmony_ci{
112362306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
112462306a36Sopenharmony_ci	int ret;
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	mutex_lock(&dsi->usage_mutex);
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	if (dsi->usage_mode != DW_DSI_USAGE_IDLE) {
112962306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "dsi controller already in use\n");
113062306a36Sopenharmony_ci		mutex_unlock(&dsi->usage_mutex);
113162306a36Sopenharmony_ci		return -EBUSY;
113262306a36Sopenharmony_ci	}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	dsi->usage_mode = DW_DSI_USAGE_PHY;
113562306a36Sopenharmony_ci	mutex_unlock(&dsi->usage_mutex);
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	ret = component_add(dsi->dev, &dw_mipi_dsi_rockchip_dphy_ops);
113862306a36Sopenharmony_ci	if (ret < 0)
113962306a36Sopenharmony_ci		goto err_graph;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	if (dsi->cdata->dphy_rx_init) {
114262306a36Sopenharmony_ci		ret = clk_prepare_enable(dsi->pclk);
114362306a36Sopenharmony_ci		if (ret < 0)
114462306a36Sopenharmony_ci			goto err_init;
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci		ret = clk_prepare_enable(dsi->grf_clk);
114762306a36Sopenharmony_ci		if (ret) {
114862306a36Sopenharmony_ci			clk_disable_unprepare(dsi->pclk);
114962306a36Sopenharmony_ci			goto err_init;
115062306a36Sopenharmony_ci		}
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci		ret = dsi->cdata->dphy_rx_init(phy);
115362306a36Sopenharmony_ci		clk_disable_unprepare(dsi->grf_clk);
115462306a36Sopenharmony_ci		clk_disable_unprepare(dsi->pclk);
115562306a36Sopenharmony_ci		if (ret < 0)
115662306a36Sopenharmony_ci			goto err_init;
115762306a36Sopenharmony_ci	}
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	return 0;
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_cierr_init:
116262306a36Sopenharmony_ci	component_del(dsi->dev, &dw_mipi_dsi_rockchip_dphy_ops);
116362306a36Sopenharmony_cierr_graph:
116462306a36Sopenharmony_ci	mutex_lock(&dsi->usage_mutex);
116562306a36Sopenharmony_ci	dsi->usage_mode = DW_DSI_USAGE_IDLE;
116662306a36Sopenharmony_ci	mutex_unlock(&dsi->usage_mutex);
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	return ret;
116962306a36Sopenharmony_ci}
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_cistatic int dw_mipi_dsi_dphy_exit(struct phy *phy)
117262306a36Sopenharmony_ci{
117362306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	component_del(dsi->dev, &dw_mipi_dsi_rockchip_dphy_ops);
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci	mutex_lock(&dsi->usage_mutex);
117862306a36Sopenharmony_ci	dsi->usage_mode = DW_DSI_USAGE_IDLE;
117962306a36Sopenharmony_ci	mutex_unlock(&dsi->usage_mutex);
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	return 0;
118262306a36Sopenharmony_ci}
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_cistatic int dw_mipi_dsi_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
118562306a36Sopenharmony_ci{
118662306a36Sopenharmony_ci	struct phy_configure_opts_mipi_dphy *config = &opts->mipi_dphy;
118762306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
118862306a36Sopenharmony_ci	int ret;
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
119162306a36Sopenharmony_ci	if (ret)
119262306a36Sopenharmony_ci		return ret;
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	dsi->dphy_config = *config;
119562306a36Sopenharmony_ci	dsi->lane_mbps = div_u64(config->hs_clk_rate, 1000 * 1000 * 1);
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	return 0;
119862306a36Sopenharmony_ci}
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_cistatic int dw_mipi_dsi_dphy_power_on(struct phy *phy)
120162306a36Sopenharmony_ci{
120262306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
120362306a36Sopenharmony_ci	int i, ret;
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	DRM_DEV_DEBUG(dsi->dev, "lanes %d - data_rate_mbps %u\n",
120662306a36Sopenharmony_ci		      dsi->dphy_config.lanes, dsi->lane_mbps);
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	i = max_mbps_to_parameter(dsi->lane_mbps);
120962306a36Sopenharmony_ci	if (i < 0) {
121062306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "failed to get parameter for %dmbps clock\n",
121162306a36Sopenharmony_ci			      dsi->lane_mbps);
121262306a36Sopenharmony_ci		return i;
121362306a36Sopenharmony_ci	}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(dsi->dev);
121662306a36Sopenharmony_ci	if (ret < 0) {
121762306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "failed to enable device: %d\n", ret);
121862306a36Sopenharmony_ci		return ret;
121962306a36Sopenharmony_ci	}
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	ret = clk_prepare_enable(dsi->pclk);
122262306a36Sopenharmony_ci	if (ret) {
122362306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "Failed to enable pclk: %d\n", ret);
122462306a36Sopenharmony_ci		goto err_pclk;
122562306a36Sopenharmony_ci	}
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	ret = clk_prepare_enable(dsi->grf_clk);
122862306a36Sopenharmony_ci	if (ret) {
122962306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
123062306a36Sopenharmony_ci		goto err_grf_clk;
123162306a36Sopenharmony_ci	}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	ret = clk_prepare_enable(dsi->phy_cfg_clk);
123462306a36Sopenharmony_ci	if (ret) {
123562306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "Failed to enable phy_cfg_clk: %d\n", ret);
123662306a36Sopenharmony_ci		goto err_phy_cfg_clk;
123762306a36Sopenharmony_ci	}
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	/* do soc-variant specific init */
124062306a36Sopenharmony_ci	if (dsi->cdata->dphy_rx_power_on) {
124162306a36Sopenharmony_ci		ret = dsi->cdata->dphy_rx_power_on(phy);
124262306a36Sopenharmony_ci		if (ret < 0) {
124362306a36Sopenharmony_ci			DRM_DEV_ERROR(dsi->dev, "hardware-specific phy bringup failed: %d\n", ret);
124462306a36Sopenharmony_ci			goto err_pwr_on;
124562306a36Sopenharmony_ci		}
124662306a36Sopenharmony_ci	}
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	/*
124962306a36Sopenharmony_ci	 * Configure hsfreqrange according to frequency values
125062306a36Sopenharmony_ci	 * Set clock lane and hsfreqrange by lane0(test code 0x44)
125162306a36Sopenharmony_ci	 */
125262306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_CLK, 0);
125362306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_0,
125462306a36Sopenharmony_ci			      HSFREQRANGE_SEL(dppa_map[i].hsfreqrange));
125562306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_1, 0);
125662306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_2, 0);
125762306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_3, 0);
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	/* Normal operation */
126062306a36Sopenharmony_ci	dw_mipi_dsi_phy_write(dsi, 0x0, 0);
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	clk_disable_unprepare(dsi->phy_cfg_clk);
126362306a36Sopenharmony_ci	clk_disable_unprepare(dsi->grf_clk);
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	return ret;
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_cierr_pwr_on:
126862306a36Sopenharmony_ci	clk_disable_unprepare(dsi->phy_cfg_clk);
126962306a36Sopenharmony_cierr_phy_cfg_clk:
127062306a36Sopenharmony_ci	clk_disable_unprepare(dsi->grf_clk);
127162306a36Sopenharmony_cierr_grf_clk:
127262306a36Sopenharmony_ci	clk_disable_unprepare(dsi->pclk);
127362306a36Sopenharmony_cierr_pclk:
127462306a36Sopenharmony_ci	pm_runtime_put(dsi->dev);
127562306a36Sopenharmony_ci	return ret;
127662306a36Sopenharmony_ci}
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_cistatic int dw_mipi_dsi_dphy_power_off(struct phy *phy)
127962306a36Sopenharmony_ci{
128062306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
128162306a36Sopenharmony_ci	int ret;
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	ret = clk_prepare_enable(dsi->grf_clk);
128462306a36Sopenharmony_ci	if (ret) {
128562306a36Sopenharmony_ci		DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
128662306a36Sopenharmony_ci		return ret;
128762306a36Sopenharmony_ci	}
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	if (dsi->cdata->dphy_rx_power_off) {
129062306a36Sopenharmony_ci		ret = dsi->cdata->dphy_rx_power_off(phy);
129162306a36Sopenharmony_ci		if (ret < 0)
129262306a36Sopenharmony_ci			DRM_DEV_ERROR(dsi->dev, "hardware-specific phy shutdown failed: %d\n", ret);
129362306a36Sopenharmony_ci	}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	clk_disable_unprepare(dsi->grf_clk);
129662306a36Sopenharmony_ci	clk_disable_unprepare(dsi->pclk);
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	pm_runtime_put(dsi->dev);
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci	return ret;
130162306a36Sopenharmony_ci}
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_cistatic const struct phy_ops dw_mipi_dsi_dphy_ops = {
130462306a36Sopenharmony_ci	.configure	= dw_mipi_dsi_dphy_configure,
130562306a36Sopenharmony_ci	.power_on	= dw_mipi_dsi_dphy_power_on,
130662306a36Sopenharmony_ci	.power_off	= dw_mipi_dsi_dphy_power_off,
130762306a36Sopenharmony_ci	.init		= dw_mipi_dsi_dphy_init,
130862306a36Sopenharmony_ci	.exit		= dw_mipi_dsi_dphy_exit,
130962306a36Sopenharmony_ci};
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_cistatic int __maybe_unused dw_mipi_dsi_rockchip_resume(struct device *dev)
131262306a36Sopenharmony_ci{
131362306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev);
131462306a36Sopenharmony_ci	int ret;
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	/*
131762306a36Sopenharmony_ci	 * Re-configure DSI state, if we were previously initialized. We need
131862306a36Sopenharmony_ci	 * to do this before rockchip_drm_drv tries to re-enable() any panels.
131962306a36Sopenharmony_ci	 */
132062306a36Sopenharmony_ci	if (dsi->dsi_bound) {
132162306a36Sopenharmony_ci		ret = clk_prepare_enable(dsi->grf_clk);
132262306a36Sopenharmony_ci		if (ret) {
132362306a36Sopenharmony_ci			DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
132462306a36Sopenharmony_ci			return ret;
132562306a36Sopenharmony_ci		}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci		dw_mipi_dsi_rockchip_config(dsi);
132862306a36Sopenharmony_ci		if (dsi->slave)
132962306a36Sopenharmony_ci			dw_mipi_dsi_rockchip_config(dsi->slave);
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci		clk_disable_unprepare(dsi->grf_clk);
133262306a36Sopenharmony_ci	}
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	return 0;
133562306a36Sopenharmony_ci}
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_cistatic const struct dev_pm_ops dw_mipi_dsi_rockchip_pm_ops = {
133862306a36Sopenharmony_ci	SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, dw_mipi_dsi_rockchip_resume)
133962306a36Sopenharmony_ci};
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_cistatic int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
134262306a36Sopenharmony_ci{
134362306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
134462306a36Sopenharmony_ci	struct device_node *np = dev->of_node;
134562306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi;
134662306a36Sopenharmony_ci	struct phy_provider *phy_provider;
134762306a36Sopenharmony_ci	struct resource *res;
134862306a36Sopenharmony_ci	const struct rockchip_dw_dsi_chip_data *cdata =
134962306a36Sopenharmony_ci				of_device_get_match_data(dev);
135062306a36Sopenharmony_ci	int ret, i;
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
135362306a36Sopenharmony_ci	if (!dsi)
135462306a36Sopenharmony_ci		return -ENOMEM;
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
135762306a36Sopenharmony_ci	dsi->base = devm_ioremap_resource(dev, res);
135862306a36Sopenharmony_ci	if (IS_ERR(dsi->base)) {
135962306a36Sopenharmony_ci		DRM_DEV_ERROR(dev, "Unable to get dsi registers\n");
136062306a36Sopenharmony_ci		return PTR_ERR(dsi->base);
136162306a36Sopenharmony_ci	}
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	i = 0;
136462306a36Sopenharmony_ci	while (cdata[i].reg) {
136562306a36Sopenharmony_ci		if (cdata[i].reg == res->start) {
136662306a36Sopenharmony_ci			dsi->cdata = &cdata[i];
136762306a36Sopenharmony_ci			break;
136862306a36Sopenharmony_ci		}
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci		i++;
137162306a36Sopenharmony_ci	}
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	if (!dsi->cdata) {
137462306a36Sopenharmony_ci		DRM_DEV_ERROR(dev, "no dsi-config for %s node\n", np->name);
137562306a36Sopenharmony_ci		return -EINVAL;
137662306a36Sopenharmony_ci	}
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	/* try to get a possible external dphy */
137962306a36Sopenharmony_ci	dsi->phy = devm_phy_optional_get(dev, "dphy");
138062306a36Sopenharmony_ci	if (IS_ERR(dsi->phy)) {
138162306a36Sopenharmony_ci		ret = PTR_ERR(dsi->phy);
138262306a36Sopenharmony_ci		DRM_DEV_ERROR(dev, "failed to get mipi dphy: %d\n", ret);
138362306a36Sopenharmony_ci		return ret;
138462306a36Sopenharmony_ci	}
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	dsi->pclk = devm_clk_get(dev, "pclk");
138762306a36Sopenharmony_ci	if (IS_ERR(dsi->pclk)) {
138862306a36Sopenharmony_ci		ret = PTR_ERR(dsi->pclk);
138962306a36Sopenharmony_ci		DRM_DEV_ERROR(dev, "Unable to get pclk: %d\n", ret);
139062306a36Sopenharmony_ci		return ret;
139162306a36Sopenharmony_ci	}
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	dsi->pllref_clk = devm_clk_get(dev, "ref");
139462306a36Sopenharmony_ci	if (IS_ERR(dsi->pllref_clk)) {
139562306a36Sopenharmony_ci		if (dsi->phy) {
139662306a36Sopenharmony_ci			/*
139762306a36Sopenharmony_ci			 * if external phy is present, pll will be
139862306a36Sopenharmony_ci			 * generated there.
139962306a36Sopenharmony_ci			 */
140062306a36Sopenharmony_ci			dsi->pllref_clk = NULL;
140162306a36Sopenharmony_ci		} else {
140262306a36Sopenharmony_ci			ret = PTR_ERR(dsi->pllref_clk);
140362306a36Sopenharmony_ci			DRM_DEV_ERROR(dev,
140462306a36Sopenharmony_ci				      "Unable to get pll reference clock: %d\n",
140562306a36Sopenharmony_ci				      ret);
140662306a36Sopenharmony_ci			return ret;
140762306a36Sopenharmony_ci		}
140862306a36Sopenharmony_ci	}
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci	if (dsi->cdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
141162306a36Sopenharmony_ci		dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
141262306a36Sopenharmony_ci		if (IS_ERR(dsi->phy_cfg_clk)) {
141362306a36Sopenharmony_ci			ret = PTR_ERR(dsi->phy_cfg_clk);
141462306a36Sopenharmony_ci			DRM_DEV_ERROR(dev,
141562306a36Sopenharmony_ci				      "Unable to get phy_cfg_clk: %d\n", ret);
141662306a36Sopenharmony_ci			return ret;
141762306a36Sopenharmony_ci		}
141862306a36Sopenharmony_ci	}
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci	if (dsi->cdata->flags & DW_MIPI_NEEDS_GRF_CLK) {
142162306a36Sopenharmony_ci		dsi->grf_clk = devm_clk_get(dev, "grf");
142262306a36Sopenharmony_ci		if (IS_ERR(dsi->grf_clk)) {
142362306a36Sopenharmony_ci			ret = PTR_ERR(dsi->grf_clk);
142462306a36Sopenharmony_ci			DRM_DEV_ERROR(dev, "Unable to get grf_clk: %d\n", ret);
142562306a36Sopenharmony_ci			return ret;
142662306a36Sopenharmony_ci		}
142762306a36Sopenharmony_ci	}
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	dsi->grf_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
143062306a36Sopenharmony_ci	if (IS_ERR(dsi->grf_regmap)) {
143162306a36Sopenharmony_ci		DRM_DEV_ERROR(dev, "Unable to get rockchip,grf\n");
143262306a36Sopenharmony_ci		return PTR_ERR(dsi->grf_regmap);
143362306a36Sopenharmony_ci	}
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ci	dsi->dev = dev;
143662306a36Sopenharmony_ci	dsi->pdata.base = dsi->base;
143762306a36Sopenharmony_ci	dsi->pdata.max_data_lanes = dsi->cdata->max_data_lanes;
143862306a36Sopenharmony_ci	dsi->pdata.phy_ops = &dw_mipi_dsi_rockchip_phy_ops;
143962306a36Sopenharmony_ci	dsi->pdata.host_ops = &dw_mipi_dsi_rockchip_host_ops;
144062306a36Sopenharmony_ci	dsi->pdata.priv_data = dsi;
144162306a36Sopenharmony_ci	platform_set_drvdata(pdev, dsi);
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	mutex_init(&dsi->usage_mutex);
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci	dsi->dphy = devm_phy_create(dev, NULL, &dw_mipi_dsi_dphy_ops);
144662306a36Sopenharmony_ci	if (IS_ERR(dsi->dphy)) {
144762306a36Sopenharmony_ci		DRM_DEV_ERROR(&pdev->dev, "failed to create PHY\n");
144862306a36Sopenharmony_ci		return PTR_ERR(dsi->dphy);
144962306a36Sopenharmony_ci	}
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci	phy_set_drvdata(dsi->dphy, dsi);
145262306a36Sopenharmony_ci	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
145362306a36Sopenharmony_ci	if (IS_ERR(phy_provider))
145462306a36Sopenharmony_ci		return PTR_ERR(phy_provider);
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci	dsi->dmd = dw_mipi_dsi_probe(pdev, &dsi->pdata);
145762306a36Sopenharmony_ci	if (IS_ERR(dsi->dmd)) {
145862306a36Sopenharmony_ci		ret = PTR_ERR(dsi->dmd);
145962306a36Sopenharmony_ci		if (ret != -EPROBE_DEFER)
146062306a36Sopenharmony_ci			DRM_DEV_ERROR(dev,
146162306a36Sopenharmony_ci				      "Failed to probe dw_mipi_dsi: %d\n", ret);
146262306a36Sopenharmony_ci		return ret;
146362306a36Sopenharmony_ci	}
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_ci	return 0;
146662306a36Sopenharmony_ci}
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_cistatic void dw_mipi_dsi_rockchip_remove(struct platform_device *pdev)
146962306a36Sopenharmony_ci{
147062306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = platform_get_drvdata(pdev);
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci	dw_mipi_dsi_remove(dsi->dmd);
147362306a36Sopenharmony_ci}
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_cistatic const struct rockchip_dw_dsi_chip_data px30_chip_data[] = {
147662306a36Sopenharmony_ci	{
147762306a36Sopenharmony_ci		.reg = 0xff450000,
147862306a36Sopenharmony_ci		.lcdsel_grf_reg = PX30_GRF_PD_VO_CON1,
147962306a36Sopenharmony_ci		.lcdsel_big = HIWORD_UPDATE(0, PX30_DSI_LCDC_SEL),
148062306a36Sopenharmony_ci		.lcdsel_lit = HIWORD_UPDATE(PX30_DSI_LCDC_SEL,
148162306a36Sopenharmony_ci					    PX30_DSI_LCDC_SEL),
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci		.lanecfg1_grf_reg = PX30_GRF_PD_VO_CON1,
148462306a36Sopenharmony_ci		.lanecfg1 = HIWORD_UPDATE(0, PX30_DSI_TURNDISABLE |
148562306a36Sopenharmony_ci					     PX30_DSI_FORCERXMODE |
148662306a36Sopenharmony_ci					     PX30_DSI_FORCETXSTOPMODE),
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci		.max_data_lanes = 4,
148962306a36Sopenharmony_ci	},
149062306a36Sopenharmony_ci	{ /* sentinel */ }
149162306a36Sopenharmony_ci};
149262306a36Sopenharmony_ci
149362306a36Sopenharmony_cistatic const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = {
149462306a36Sopenharmony_ci	{
149562306a36Sopenharmony_ci		.reg = 0xff960000,
149662306a36Sopenharmony_ci		.lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
149762306a36Sopenharmony_ci		.lcdsel_big = HIWORD_UPDATE(0, RK3288_DSI0_LCDC_SEL),
149862306a36Sopenharmony_ci		.lcdsel_lit = HIWORD_UPDATE(RK3288_DSI0_LCDC_SEL, RK3288_DSI0_LCDC_SEL),
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci		.max_data_lanes = 4,
150162306a36Sopenharmony_ci	},
150262306a36Sopenharmony_ci	{
150362306a36Sopenharmony_ci		.reg = 0xff964000,
150462306a36Sopenharmony_ci		.lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
150562306a36Sopenharmony_ci		.lcdsel_big = HIWORD_UPDATE(0, RK3288_DSI1_LCDC_SEL),
150662306a36Sopenharmony_ci		.lcdsel_lit = HIWORD_UPDATE(RK3288_DSI1_LCDC_SEL, RK3288_DSI1_LCDC_SEL),
150762306a36Sopenharmony_ci
150862306a36Sopenharmony_ci		.max_data_lanes = 4,
150962306a36Sopenharmony_ci	},
151062306a36Sopenharmony_ci	{ /* sentinel */ }
151162306a36Sopenharmony_ci};
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_cistatic int rk3399_dphy_tx1rx1_init(struct phy *phy)
151462306a36Sopenharmony_ci{
151562306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	/*
151862306a36Sopenharmony_ci	 * Set TX1RX1 source to isp1.
151962306a36Sopenharmony_ci	 * Assume ISP0 is supplied by the RX0 dphy.
152062306a36Sopenharmony_ci	 */
152162306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
152262306a36Sopenharmony_ci		     HIWORD_UPDATE(0, RK3399_TXRX_SRC_SEL_ISP0));
152362306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
152462306a36Sopenharmony_ci		     HIWORD_UPDATE(0, RK3399_TXRX_MASTERSLAVEZ));
152562306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
152662306a36Sopenharmony_ci		     HIWORD_UPDATE(0, RK3399_TXRX_BASEDIR));
152762306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
152862306a36Sopenharmony_ci		     HIWORD_UPDATE(0, RK3399_DSI1_ENABLE));
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	return 0;
153162306a36Sopenharmony_ci}
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_cistatic int rk3399_dphy_tx1rx1_power_on(struct phy *phy)
153462306a36Sopenharmony_ci{
153562306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci	/* tester reset pulse */
153862306a36Sopenharmony_ci	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_TESTCLR);
153962306a36Sopenharmony_ci	usleep_range(100, 150);
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
154262306a36Sopenharmony_ci		     HIWORD_UPDATE(0, RK3399_TXRX_MASTERSLAVEZ));
154362306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
154462306a36Sopenharmony_ci		     HIWORD_UPDATE(RK3399_TXRX_BASEDIR, RK3399_TXRX_BASEDIR));
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
154762306a36Sopenharmony_ci		     HIWORD_UPDATE(0, RK3399_DSI1_FORCERXMODE));
154862306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
154962306a36Sopenharmony_ci		     HIWORD_UPDATE(0, RK3399_DSI1_FORCETXSTOPMODE));
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	/* Disable lane turn around, which is ignored in receive mode */
155262306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
155362306a36Sopenharmony_ci		     HIWORD_UPDATE(0, RK3399_TXRX_TURNREQUEST));
155462306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
155562306a36Sopenharmony_ci		     HIWORD_UPDATE(RK3399_DSI1_TURNDISABLE,
155662306a36Sopenharmony_ci				   RK3399_DSI1_TURNDISABLE));
155762306a36Sopenharmony_ci	usleep_range(100, 150);
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
156062306a36Sopenharmony_ci	usleep_range(100, 150);
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	/* Enable dphy lanes */
156362306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
156462306a36Sopenharmony_ci		     HIWORD_UPDATE(GENMASK(dsi->dphy_config.lanes - 1, 0),
156562306a36Sopenharmony_ci				   RK3399_DSI1_ENABLE));
156662306a36Sopenharmony_ci
156762306a36Sopenharmony_ci	usleep_range(100, 150);
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	return 0;
157062306a36Sopenharmony_ci}
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_cistatic int rk3399_dphy_tx1rx1_power_off(struct phy *phy)
157362306a36Sopenharmony_ci{
157462306a36Sopenharmony_ci	struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
157762306a36Sopenharmony_ci		     HIWORD_UPDATE(0, RK3399_DSI1_ENABLE));
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	return 0;
158062306a36Sopenharmony_ci}
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_cistatic const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = {
158362306a36Sopenharmony_ci	{
158462306a36Sopenharmony_ci		.reg = 0xff960000,
158562306a36Sopenharmony_ci		.lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
158662306a36Sopenharmony_ci		.lcdsel_big = HIWORD_UPDATE(0, RK3399_DSI0_LCDC_SEL),
158762306a36Sopenharmony_ci		.lcdsel_lit = HIWORD_UPDATE(RK3399_DSI0_LCDC_SEL,
158862306a36Sopenharmony_ci					    RK3399_DSI0_LCDC_SEL),
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci		.lanecfg1_grf_reg = RK3399_GRF_SOC_CON22,
159162306a36Sopenharmony_ci		.lanecfg1 = HIWORD_UPDATE(0, RK3399_DSI0_TURNREQUEST |
159262306a36Sopenharmony_ci					     RK3399_DSI0_TURNDISABLE |
159362306a36Sopenharmony_ci					     RK3399_DSI0_FORCETXSTOPMODE |
159462306a36Sopenharmony_ci					     RK3399_DSI0_FORCERXMODE),
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci		.flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
159762306a36Sopenharmony_ci		.max_data_lanes = 4,
159862306a36Sopenharmony_ci	},
159962306a36Sopenharmony_ci	{
160062306a36Sopenharmony_ci		.reg = 0xff968000,
160162306a36Sopenharmony_ci		.lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
160262306a36Sopenharmony_ci		.lcdsel_big = HIWORD_UPDATE(0, RK3399_DSI1_LCDC_SEL),
160362306a36Sopenharmony_ci		.lcdsel_lit = HIWORD_UPDATE(RK3399_DSI1_LCDC_SEL,
160462306a36Sopenharmony_ci					    RK3399_DSI1_LCDC_SEL),
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci		.lanecfg1_grf_reg = RK3399_GRF_SOC_CON23,
160762306a36Sopenharmony_ci		.lanecfg1 = HIWORD_UPDATE(0, RK3399_DSI1_TURNDISABLE |
160862306a36Sopenharmony_ci					     RK3399_DSI1_FORCETXSTOPMODE |
160962306a36Sopenharmony_ci					     RK3399_DSI1_FORCERXMODE |
161062306a36Sopenharmony_ci					     RK3399_DSI1_ENABLE),
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci		.lanecfg2_grf_reg = RK3399_GRF_SOC_CON24,
161362306a36Sopenharmony_ci		.lanecfg2 = HIWORD_UPDATE(RK3399_TXRX_MASTERSLAVEZ |
161462306a36Sopenharmony_ci					  RK3399_TXRX_ENABLECLK,
161562306a36Sopenharmony_ci					  RK3399_TXRX_MASTERSLAVEZ |
161662306a36Sopenharmony_ci					  RK3399_TXRX_ENABLECLK |
161762306a36Sopenharmony_ci					  RK3399_TXRX_BASEDIR),
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_ci		.enable_grf_reg = RK3399_GRF_SOC_CON23,
162062306a36Sopenharmony_ci		.enable = HIWORD_UPDATE(RK3399_DSI1_ENABLE, RK3399_DSI1_ENABLE),
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci		.flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
162362306a36Sopenharmony_ci		.max_data_lanes = 4,
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci		.dphy_rx_init = rk3399_dphy_tx1rx1_init,
162662306a36Sopenharmony_ci		.dphy_rx_power_on = rk3399_dphy_tx1rx1_power_on,
162762306a36Sopenharmony_ci		.dphy_rx_power_off = rk3399_dphy_tx1rx1_power_off,
162862306a36Sopenharmony_ci	},
162962306a36Sopenharmony_ci	{ /* sentinel */ }
163062306a36Sopenharmony_ci};
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_cistatic const struct rockchip_dw_dsi_chip_data rk3568_chip_data[] = {
163362306a36Sopenharmony_ci	{
163462306a36Sopenharmony_ci		.reg = 0xfe060000,
163562306a36Sopenharmony_ci		.lanecfg1_grf_reg = RK3568_GRF_VO_CON2,
163662306a36Sopenharmony_ci		.lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI0_SKEWCALHS |
163762306a36Sopenharmony_ci					  RK3568_DSI0_FORCETXSTOPMODE |
163862306a36Sopenharmony_ci					  RK3568_DSI0_TURNDISABLE |
163962306a36Sopenharmony_ci					  RK3568_DSI0_FORCERXMODE),
164062306a36Sopenharmony_ci		.max_data_lanes = 4,
164162306a36Sopenharmony_ci	},
164262306a36Sopenharmony_ci	{
164362306a36Sopenharmony_ci		.reg = 0xfe070000,
164462306a36Sopenharmony_ci		.lanecfg1_grf_reg = RK3568_GRF_VO_CON3,
164562306a36Sopenharmony_ci		.lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI1_SKEWCALHS |
164662306a36Sopenharmony_ci					  RK3568_DSI1_FORCETXSTOPMODE |
164762306a36Sopenharmony_ci					  RK3568_DSI1_TURNDISABLE |
164862306a36Sopenharmony_ci					  RK3568_DSI1_FORCERXMODE),
164962306a36Sopenharmony_ci		.max_data_lanes = 4,
165062306a36Sopenharmony_ci	},
165162306a36Sopenharmony_ci	{ /* sentinel */ }
165262306a36Sopenharmony_ci};
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_cistatic const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = {
165562306a36Sopenharmony_ci	{
165662306a36Sopenharmony_ci	 .compatible = "rockchip,px30-mipi-dsi",
165762306a36Sopenharmony_ci	 .data = &px30_chip_data,
165862306a36Sopenharmony_ci	}, {
165962306a36Sopenharmony_ci	 .compatible = "rockchip,rk3288-mipi-dsi",
166062306a36Sopenharmony_ci	 .data = &rk3288_chip_data,
166162306a36Sopenharmony_ci	}, {
166262306a36Sopenharmony_ci	 .compatible = "rockchip,rk3399-mipi-dsi",
166362306a36Sopenharmony_ci	 .data = &rk3399_chip_data,
166462306a36Sopenharmony_ci	}, {
166562306a36Sopenharmony_ci	 .compatible = "rockchip,rk3568-mipi-dsi",
166662306a36Sopenharmony_ci	 .data = &rk3568_chip_data,
166762306a36Sopenharmony_ci	},
166862306a36Sopenharmony_ci	{ /* sentinel */ }
166962306a36Sopenharmony_ci};
167062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, dw_mipi_dsi_rockchip_dt_ids);
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_cistruct platform_driver dw_mipi_dsi_rockchip_driver = {
167362306a36Sopenharmony_ci	.probe		= dw_mipi_dsi_rockchip_probe,
167462306a36Sopenharmony_ci	.remove_new	= dw_mipi_dsi_rockchip_remove,
167562306a36Sopenharmony_ci	.driver		= {
167662306a36Sopenharmony_ci		.of_match_table = dw_mipi_dsi_rockchip_dt_ids,
167762306a36Sopenharmony_ci		.pm	= &dw_mipi_dsi_rockchip_pm_ops,
167862306a36Sopenharmony_ci		.name	= "dw-mipi-dsi-rockchip",
167962306a36Sopenharmony_ci		/*
168062306a36Sopenharmony_ci		 * For dual-DSI display, one DSI pokes at the other DSI's
168162306a36Sopenharmony_ci		 * drvdata in dw_mipi_dsi_rockchip_find_second(). This is not
168262306a36Sopenharmony_ci		 * safe for asynchronous probe.
168362306a36Sopenharmony_ci		 */
168462306a36Sopenharmony_ci		.probe_type = PROBE_FORCE_SYNCHRONOUS,
168562306a36Sopenharmony_ci	},
168662306a36Sopenharmony_ci};
1687