18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd 48c2ecf20Sopenharmony_ci * Author: 58c2ecf20Sopenharmony_ci * Chris Zhong <zyw@rock-chips.com> 68c2ecf20Sopenharmony_ci * Nickey Yang <nickey.yang@rock-chips.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/clk.h> 108c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 118c2ecf20Sopenharmony_ci#include <linux/math64.h> 128c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/of_device.h> 158c2ecf20Sopenharmony_ci#include <linux/phy/phy.h> 168c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 178c2ecf20Sopenharmony_ci#include <linux/regmap.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <video/mipi_display.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <drm/bridge/dw_mipi_dsi.h> 228c2ecf20Sopenharmony_ci#include <drm/drm_mipi_dsi.h> 238c2ecf20Sopenharmony_ci#include <drm/drm_of.h> 248c2ecf20Sopenharmony_ci#include <drm/drm_simple_kms_helper.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include "rockchip_drm_drv.h" 278c2ecf20Sopenharmony_ci#include "rockchip_drm_vop.h" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define DSI_PHY_RSTZ 0xa0 308c2ecf20Sopenharmony_ci#define PHY_DISFORCEPLL 0 318c2ecf20Sopenharmony_ci#define PHY_ENFORCEPLL BIT(3) 328c2ecf20Sopenharmony_ci#define PHY_DISABLECLK 0 338c2ecf20Sopenharmony_ci#define PHY_ENABLECLK BIT(2) 348c2ecf20Sopenharmony_ci#define PHY_RSTZ 0 358c2ecf20Sopenharmony_ci#define PHY_UNRSTZ BIT(1) 368c2ecf20Sopenharmony_ci#define PHY_SHUTDOWNZ 0 378c2ecf20Sopenharmony_ci#define PHY_UNSHUTDOWNZ BIT(0) 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define DSI_PHY_IF_CFG 0xa4 408c2ecf20Sopenharmony_ci#define N_LANES(n) ((((n) - 1) & 0x3) << 0) 418c2ecf20Sopenharmony_ci#define PHY_STOP_WAIT_TIME(cycle) (((cycle) & 0xff) << 8) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define DSI_PHY_STATUS 0xb0 448c2ecf20Sopenharmony_ci#define LOCK BIT(0) 458c2ecf20Sopenharmony_ci#define STOP_STATE_CLK_LANE BIT(2) 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define DSI_PHY_TST_CTRL0 0xb4 488c2ecf20Sopenharmony_ci#define PHY_TESTCLK BIT(1) 498c2ecf20Sopenharmony_ci#define PHY_UNTESTCLK 0 508c2ecf20Sopenharmony_ci#define PHY_TESTCLR BIT(0) 518c2ecf20Sopenharmony_ci#define PHY_UNTESTCLR 0 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define DSI_PHY_TST_CTRL1 0xb8 548c2ecf20Sopenharmony_ci#define PHY_TESTEN BIT(16) 558c2ecf20Sopenharmony_ci#define PHY_UNTESTEN 0 568c2ecf20Sopenharmony_ci#define PHY_TESTDOUT(n) (((n) & 0xff) << 8) 578c2ecf20Sopenharmony_ci#define PHY_TESTDIN(n) (((n) & 0xff) << 0) 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define DSI_INT_ST0 0xbc 608c2ecf20Sopenharmony_ci#define DSI_INT_ST1 0xc0 618c2ecf20Sopenharmony_ci#define DSI_INT_MSK0 0xc4 628c2ecf20Sopenharmony_ci#define DSI_INT_MSK1 0xc8 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#define PHY_STATUS_TIMEOUT_US 10000 658c2ecf20Sopenharmony_ci#define CMD_PKT_STATUS_TIMEOUT_US 20000 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci#define BYPASS_VCO_RANGE BIT(7) 688c2ecf20Sopenharmony_ci#define VCO_RANGE_CON_SEL(val) (((val) & 0x7) << 3) 698c2ecf20Sopenharmony_ci#define VCO_IN_CAP_CON_DEFAULT (0x0 << 1) 708c2ecf20Sopenharmony_ci#define VCO_IN_CAP_CON_LOW (0x1 << 1) 718c2ecf20Sopenharmony_ci#define VCO_IN_CAP_CON_HIGH (0x2 << 1) 728c2ecf20Sopenharmony_ci#define REF_BIAS_CUR_SEL BIT(0) 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#define CP_CURRENT_3UA 0x1 758c2ecf20Sopenharmony_ci#define CP_CURRENT_4_5UA 0x2 768c2ecf20Sopenharmony_ci#define CP_CURRENT_7_5UA 0x6 778c2ecf20Sopenharmony_ci#define CP_CURRENT_6UA 0x9 788c2ecf20Sopenharmony_ci#define CP_CURRENT_12UA 0xb 798c2ecf20Sopenharmony_ci#define CP_CURRENT_SEL(val) ((val) & 0xf) 808c2ecf20Sopenharmony_ci#define CP_PROGRAM_EN BIT(7) 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#define LPF_RESISTORS_15_5KOHM 0x1 838c2ecf20Sopenharmony_ci#define LPF_RESISTORS_13KOHM 0x2 848c2ecf20Sopenharmony_ci#define LPF_RESISTORS_11_5KOHM 0x4 858c2ecf20Sopenharmony_ci#define LPF_RESISTORS_10_5KOHM 0x8 868c2ecf20Sopenharmony_ci#define LPF_RESISTORS_8KOHM 0x10 878c2ecf20Sopenharmony_ci#define LPF_PROGRAM_EN BIT(6) 888c2ecf20Sopenharmony_ci#define LPF_RESISTORS_SEL(val) ((val) & 0x3f) 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci#define HSFREQRANGE_SEL(val) (((val) & 0x3f) << 1) 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#define INPUT_DIVIDER(val) (((val) - 1) & 0x7f) 938c2ecf20Sopenharmony_ci#define LOW_PROGRAM_EN 0 948c2ecf20Sopenharmony_ci#define HIGH_PROGRAM_EN BIT(7) 958c2ecf20Sopenharmony_ci#define LOOP_DIV_LOW_SEL(val) (((val) - 1) & 0x1f) 968c2ecf20Sopenharmony_ci#define LOOP_DIV_HIGH_SEL(val) ((((val) - 1) >> 5) & 0xf) 978c2ecf20Sopenharmony_ci#define PLL_LOOP_DIV_EN BIT(5) 988c2ecf20Sopenharmony_ci#define PLL_INPUT_DIV_EN BIT(4) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#define POWER_CONTROL BIT(6) 1018c2ecf20Sopenharmony_ci#define INTERNAL_REG_CURRENT BIT(3) 1028c2ecf20Sopenharmony_ci#define BIAS_BLOCK_ON BIT(2) 1038c2ecf20Sopenharmony_ci#define BANDGAP_ON BIT(0) 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci#define TER_RESISTOR_HIGH BIT(7) 1068c2ecf20Sopenharmony_ci#define TER_RESISTOR_LOW 0 1078c2ecf20Sopenharmony_ci#define LEVEL_SHIFTERS_ON BIT(6) 1088c2ecf20Sopenharmony_ci#define TER_CAL_DONE BIT(5) 1098c2ecf20Sopenharmony_ci#define SETRD_MAX (0x7 << 2) 1108c2ecf20Sopenharmony_ci#define POWER_MANAGE BIT(1) 1118c2ecf20Sopenharmony_ci#define TER_RESISTORS_ON BIT(0) 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci#define BIASEXTR_SEL(val) ((val) & 0x7) 1148c2ecf20Sopenharmony_ci#define BANDGAP_SEL(val) ((val) & 0x7) 1158c2ecf20Sopenharmony_ci#define TLP_PROGRAM_EN BIT(7) 1168c2ecf20Sopenharmony_ci#define THS_PRE_PROGRAM_EN BIT(7) 1178c2ecf20Sopenharmony_ci#define THS_ZERO_PROGRAM_EN BIT(6) 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci#define PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL 0x10 1208c2ecf20Sopenharmony_ci#define PLL_CP_CONTROL_PLL_LOCK_BYPASS 0x11 1218c2ecf20Sopenharmony_ci#define PLL_LPF_AND_CP_CONTROL 0x12 1228c2ecf20Sopenharmony_ci#define PLL_INPUT_DIVIDER_RATIO 0x17 1238c2ecf20Sopenharmony_ci#define PLL_LOOP_DIVIDER_RATIO 0x18 1248c2ecf20Sopenharmony_ci#define PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL 0x19 1258c2ecf20Sopenharmony_ci#define BANDGAP_AND_BIAS_CONTROL 0x20 1268c2ecf20Sopenharmony_ci#define TERMINATION_RESISTER_CONTROL 0x21 1278c2ecf20Sopenharmony_ci#define AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY 0x22 1288c2ecf20Sopenharmony_ci#define HS_RX_CONTROL_OF_LANE_0 0x44 1298c2ecf20Sopenharmony_ci#define HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL 0x60 1308c2ecf20Sopenharmony_ci#define HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL 0x61 1318c2ecf20Sopenharmony_ci#define HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL 0x62 1328c2ecf20Sopenharmony_ci#define HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL 0x63 1338c2ecf20Sopenharmony_ci#define HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL 0x64 1348c2ecf20Sopenharmony_ci#define HS_TX_CLOCK_LANE_POST_TIME_CONTROL 0x65 1358c2ecf20Sopenharmony_ci#define HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL 0x70 1368c2ecf20Sopenharmony_ci#define HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL 0x71 1378c2ecf20Sopenharmony_ci#define HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL 0x72 1388c2ecf20Sopenharmony_ci#define HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL 0x73 1398c2ecf20Sopenharmony_ci#define HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL 0x74 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci#define DW_MIPI_NEEDS_PHY_CFG_CLK BIT(0) 1428c2ecf20Sopenharmony_ci#define DW_MIPI_NEEDS_GRF_CLK BIT(1) 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci#define PX30_GRF_PD_VO_CON1 0x0438 1458c2ecf20Sopenharmony_ci#define PX30_DSI_FORCETXSTOPMODE (0xf << 7) 1468c2ecf20Sopenharmony_ci#define PX30_DSI_FORCERXMODE BIT(6) 1478c2ecf20Sopenharmony_ci#define PX30_DSI_TURNDISABLE BIT(5) 1488c2ecf20Sopenharmony_ci#define PX30_DSI_LCDC_SEL BIT(0) 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci#define RK3288_GRF_SOC_CON6 0x025c 1518c2ecf20Sopenharmony_ci#define RK3288_DSI0_LCDC_SEL BIT(6) 1528c2ecf20Sopenharmony_ci#define RK3288_DSI1_LCDC_SEL BIT(9) 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci#define RK3399_GRF_SOC_CON20 0x6250 1558c2ecf20Sopenharmony_ci#define RK3399_DSI0_LCDC_SEL BIT(0) 1568c2ecf20Sopenharmony_ci#define RK3399_DSI1_LCDC_SEL BIT(4) 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci#define RK3399_GRF_SOC_CON22 0x6258 1598c2ecf20Sopenharmony_ci#define RK3399_DSI0_TURNREQUEST (0xf << 12) 1608c2ecf20Sopenharmony_ci#define RK3399_DSI0_TURNDISABLE (0xf << 8) 1618c2ecf20Sopenharmony_ci#define RK3399_DSI0_FORCETXSTOPMODE (0xf << 4) 1628c2ecf20Sopenharmony_ci#define RK3399_DSI0_FORCERXMODE (0xf << 0) 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci#define RK3399_GRF_SOC_CON23 0x625c 1658c2ecf20Sopenharmony_ci#define RK3399_DSI1_TURNDISABLE (0xf << 12) 1668c2ecf20Sopenharmony_ci#define RK3399_DSI1_FORCETXSTOPMODE (0xf << 8) 1678c2ecf20Sopenharmony_ci#define RK3399_DSI1_FORCERXMODE (0xf << 4) 1688c2ecf20Sopenharmony_ci#define RK3399_DSI1_ENABLE (0xf << 0) 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci#define RK3399_GRF_SOC_CON24 0x6260 1718c2ecf20Sopenharmony_ci#define RK3399_TXRX_MASTERSLAVEZ BIT(7) 1728c2ecf20Sopenharmony_ci#define RK3399_TXRX_ENABLECLK BIT(6) 1738c2ecf20Sopenharmony_ci#define RK3399_TXRX_BASEDIR BIT(5) 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci#define to_dsi(nm) container_of(nm, struct dw_mipi_dsi_rockchip, nm) 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cienum { 1808c2ecf20Sopenharmony_ci BANDGAP_97_07, 1818c2ecf20Sopenharmony_ci BANDGAP_98_05, 1828c2ecf20Sopenharmony_ci BANDGAP_99_02, 1838c2ecf20Sopenharmony_ci BANDGAP_100_00, 1848c2ecf20Sopenharmony_ci BANDGAP_93_17, 1858c2ecf20Sopenharmony_ci BANDGAP_94_15, 1868c2ecf20Sopenharmony_ci BANDGAP_95_12, 1878c2ecf20Sopenharmony_ci BANDGAP_96_10, 1888c2ecf20Sopenharmony_ci}; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cienum { 1918c2ecf20Sopenharmony_ci BIASEXTR_87_1, 1928c2ecf20Sopenharmony_ci BIASEXTR_91_5, 1938c2ecf20Sopenharmony_ci BIASEXTR_95_9, 1948c2ecf20Sopenharmony_ci BIASEXTR_100, 1958c2ecf20Sopenharmony_ci BIASEXTR_105_94, 1968c2ecf20Sopenharmony_ci BIASEXTR_111_88, 1978c2ecf20Sopenharmony_ci BIASEXTR_118_8, 1988c2ecf20Sopenharmony_ci BIASEXTR_127_7, 1998c2ecf20Sopenharmony_ci}; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistruct rockchip_dw_dsi_chip_data { 2028c2ecf20Sopenharmony_ci u32 reg; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci u32 lcdsel_grf_reg; 2058c2ecf20Sopenharmony_ci u32 lcdsel_big; 2068c2ecf20Sopenharmony_ci u32 lcdsel_lit; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci u32 enable_grf_reg; 2098c2ecf20Sopenharmony_ci u32 enable; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci u32 lanecfg1_grf_reg; 2128c2ecf20Sopenharmony_ci u32 lanecfg1; 2138c2ecf20Sopenharmony_ci u32 lanecfg2_grf_reg; 2148c2ecf20Sopenharmony_ci u32 lanecfg2; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci unsigned int flags; 2178c2ecf20Sopenharmony_ci unsigned int max_data_lanes; 2188c2ecf20Sopenharmony_ci}; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistruct dw_mipi_dsi_rockchip { 2218c2ecf20Sopenharmony_ci struct device *dev; 2228c2ecf20Sopenharmony_ci struct drm_encoder encoder; 2238c2ecf20Sopenharmony_ci void __iomem *base; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci struct regmap *grf_regmap; 2268c2ecf20Sopenharmony_ci struct clk *pllref_clk; 2278c2ecf20Sopenharmony_ci struct clk *grf_clk; 2288c2ecf20Sopenharmony_ci struct clk *phy_cfg_clk; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* dual-channel */ 2318c2ecf20Sopenharmony_ci bool is_slave; 2328c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *slave; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci /* optional external dphy */ 2358c2ecf20Sopenharmony_ci struct phy *phy; 2368c2ecf20Sopenharmony_ci union phy_configure_opts phy_opts; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci unsigned int lane_mbps; /* per lane */ 2398c2ecf20Sopenharmony_ci u16 input_div; 2408c2ecf20Sopenharmony_ci u16 feedback_div; 2418c2ecf20Sopenharmony_ci u32 format; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci struct dw_mipi_dsi *dmd; 2448c2ecf20Sopenharmony_ci const struct rockchip_dw_dsi_chip_data *cdata; 2458c2ecf20Sopenharmony_ci struct dw_mipi_dsi_plat_data pdata; 2468c2ecf20Sopenharmony_ci}; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cistruct dphy_pll_parameter_map { 2498c2ecf20Sopenharmony_ci unsigned int max_mbps; 2508c2ecf20Sopenharmony_ci u8 hsfreqrange; 2518c2ecf20Sopenharmony_ci u8 icpctrl; 2528c2ecf20Sopenharmony_ci u8 lpfctrl; 2538c2ecf20Sopenharmony_ci}; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci/* The table is based on 27MHz DPHY pll reference clock. */ 2568c2ecf20Sopenharmony_cistatic const struct dphy_pll_parameter_map dppa_map[] = { 2578c2ecf20Sopenharmony_ci { 89, 0x00, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM }, 2588c2ecf20Sopenharmony_ci { 99, 0x10, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM }, 2598c2ecf20Sopenharmony_ci { 109, 0x20, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM }, 2608c2ecf20Sopenharmony_ci { 129, 0x01, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM }, 2618c2ecf20Sopenharmony_ci { 139, 0x11, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM }, 2628c2ecf20Sopenharmony_ci { 149, 0x21, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM }, 2638c2ecf20Sopenharmony_ci { 169, 0x02, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM }, 2648c2ecf20Sopenharmony_ci { 179, 0x12, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM }, 2658c2ecf20Sopenharmony_ci { 199, 0x22, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM }, 2668c2ecf20Sopenharmony_ci { 219, 0x03, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM }, 2678c2ecf20Sopenharmony_ci { 239, 0x13, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM }, 2688c2ecf20Sopenharmony_ci { 249, 0x23, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM }, 2698c2ecf20Sopenharmony_ci { 269, 0x04, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM }, 2708c2ecf20Sopenharmony_ci { 299, 0x14, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM }, 2718c2ecf20Sopenharmony_ci { 329, 0x05, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM }, 2728c2ecf20Sopenharmony_ci { 359, 0x15, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM }, 2738c2ecf20Sopenharmony_ci { 399, 0x25, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM }, 2748c2ecf20Sopenharmony_ci { 449, 0x06, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM }, 2758c2ecf20Sopenharmony_ci { 499, 0x16, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM }, 2768c2ecf20Sopenharmony_ci { 549, 0x07, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM }, 2778c2ecf20Sopenharmony_ci { 599, 0x17, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM }, 2788c2ecf20Sopenharmony_ci { 649, 0x08, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM }, 2798c2ecf20Sopenharmony_ci { 699, 0x18, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM }, 2808c2ecf20Sopenharmony_ci { 749, 0x09, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM }, 2818c2ecf20Sopenharmony_ci { 799, 0x19, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM }, 2828c2ecf20Sopenharmony_ci { 849, 0x29, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM }, 2838c2ecf20Sopenharmony_ci { 899, 0x39, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM }, 2848c2ecf20Sopenharmony_ci { 949, 0x0a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM }, 2858c2ecf20Sopenharmony_ci { 999, 0x1a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM }, 2868c2ecf20Sopenharmony_ci {1049, 0x2a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM }, 2878c2ecf20Sopenharmony_ci {1099, 0x3a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM }, 2888c2ecf20Sopenharmony_ci {1149, 0x0b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }, 2898c2ecf20Sopenharmony_ci {1199, 0x1b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }, 2908c2ecf20Sopenharmony_ci {1249, 0x2b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }, 2918c2ecf20Sopenharmony_ci {1299, 0x3b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }, 2928c2ecf20Sopenharmony_ci {1349, 0x0c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }, 2938c2ecf20Sopenharmony_ci {1399, 0x1c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }, 2948c2ecf20Sopenharmony_ci {1449, 0x2c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }, 2958c2ecf20Sopenharmony_ci {1500, 0x3c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM } 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int max_mbps_to_parameter(unsigned int max_mbps) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci int i; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(dppa_map); i++) 3038c2ecf20Sopenharmony_ci if (dppa_map[i].max_mbps >= max_mbps) 3048c2ecf20Sopenharmony_ci return i; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci return -EINVAL; 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistatic inline void dsi_write(struct dw_mipi_dsi_rockchip *dsi, u32 reg, u32 val) 3108c2ecf20Sopenharmony_ci{ 3118c2ecf20Sopenharmony_ci writel(val, dsi->base + reg); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic inline u32 dsi_read(struct dw_mipi_dsi_rockchip *dsi, u32 reg) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci return readl(dsi->base + reg); 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic inline void dsi_set(struct dw_mipi_dsi_rockchip *dsi, u32 reg, u32 mask) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci dsi_write(dsi, reg, dsi_read(dsi, reg) | mask); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic inline void dsi_update_bits(struct dw_mipi_dsi_rockchip *dsi, u32 reg, 3258c2ecf20Sopenharmony_ci u32 mask, u32 val) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci dsi_write(dsi, reg, (dsi_read(dsi, reg) & ~mask) | val); 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic void dw_mipi_dsi_phy_write(struct dw_mipi_dsi_rockchip *dsi, 3318c2ecf20Sopenharmony_ci u8 test_code, 3328c2ecf20Sopenharmony_ci u8 test_data) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci /* 3358c2ecf20Sopenharmony_ci * With the falling edge on TESTCLK, the TESTDIN[7:0] signal content 3368c2ecf20Sopenharmony_ci * is latched internally as the current test code. Test data is 3378c2ecf20Sopenharmony_ci * programmed internally by rising edge on TESTCLK. 3388c2ecf20Sopenharmony_ci */ 3398c2ecf20Sopenharmony_ci dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_TESTEN | PHY_TESTDOUT(0) | 3428c2ecf20Sopenharmony_ci PHY_TESTDIN(test_code)); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLK | PHY_UNTESTCLR); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_UNTESTEN | PHY_TESTDOUT(0) | 3478c2ecf20Sopenharmony_ci PHY_TESTDIN(test_data)); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci/** 3538c2ecf20Sopenharmony_ci * ns2bc - Nanoseconds to byte clock cycles 3548c2ecf20Sopenharmony_ci */ 3558c2ecf20Sopenharmony_cistatic inline unsigned int ns2bc(struct dw_mipi_dsi_rockchip *dsi, int ns) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci return DIV_ROUND_UP(ns * dsi->lane_mbps / 8, 1000); 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci/** 3618c2ecf20Sopenharmony_ci * ns2ui - Nanoseconds to UI time periods 3628c2ecf20Sopenharmony_ci */ 3638c2ecf20Sopenharmony_cistatic inline unsigned int ns2ui(struct dw_mipi_dsi_rockchip *dsi, int ns) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci return DIV_ROUND_UP(ns * dsi->lane_mbps, 1000); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic int dw_mipi_dsi_phy_init(void *priv_data) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = priv_data; 3718c2ecf20Sopenharmony_ci int ret, i, vco; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (dsi->phy) 3748c2ecf20Sopenharmony_ci return 0; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* 3778c2ecf20Sopenharmony_ci * Get vco from frequency(lane_mbps) 3788c2ecf20Sopenharmony_ci * vco frequency table 3798c2ecf20Sopenharmony_ci * 000 - between 80 and 200 MHz 3808c2ecf20Sopenharmony_ci * 001 - between 200 and 300 MHz 3818c2ecf20Sopenharmony_ci * 010 - between 300 and 500 MHz 3828c2ecf20Sopenharmony_ci * 011 - between 500 and 700 MHz 3838c2ecf20Sopenharmony_ci * 100 - between 700 and 900 MHz 3848c2ecf20Sopenharmony_ci * 101 - between 900 and 1100 MHz 3858c2ecf20Sopenharmony_ci * 110 - between 1100 and 1300 MHz 3868c2ecf20Sopenharmony_ci * 111 - between 1300 and 1500 MHz 3878c2ecf20Sopenharmony_ci */ 3888c2ecf20Sopenharmony_ci vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci i = max_mbps_to_parameter(dsi->lane_mbps); 3918c2ecf20Sopenharmony_ci if (i < 0) { 3928c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, 3938c2ecf20Sopenharmony_ci "failed to get parameter for %dmbps clock\n", 3948c2ecf20Sopenharmony_ci dsi->lane_mbps); 3958c2ecf20Sopenharmony_ci return i; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci ret = clk_prepare_enable(dsi->phy_cfg_clk); 3998c2ecf20Sopenharmony_ci if (ret) { 4008c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, "Failed to enable phy_cfg_clk\n"); 4018c2ecf20Sopenharmony_ci return ret; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL, 4058c2ecf20Sopenharmony_ci BYPASS_VCO_RANGE | 4068c2ecf20Sopenharmony_ci VCO_RANGE_CON_SEL(vco) | 4078c2ecf20Sopenharmony_ci VCO_IN_CAP_CON_LOW | 4088c2ecf20Sopenharmony_ci REF_BIAS_CUR_SEL); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, PLL_CP_CONTROL_PLL_LOCK_BYPASS, 4118c2ecf20Sopenharmony_ci CP_CURRENT_SEL(dppa_map[i].icpctrl)); 4128c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, PLL_LPF_AND_CP_CONTROL, 4138c2ecf20Sopenharmony_ci CP_PROGRAM_EN | LPF_PROGRAM_EN | 4148c2ecf20Sopenharmony_ci LPF_RESISTORS_SEL(dppa_map[i].lpfctrl)); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_0, 4178c2ecf20Sopenharmony_ci HSFREQRANGE_SEL(dppa_map[i].hsfreqrange)); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, PLL_INPUT_DIVIDER_RATIO, 4208c2ecf20Sopenharmony_ci INPUT_DIVIDER(dsi->input_div)); 4218c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO, 4228c2ecf20Sopenharmony_ci LOOP_DIV_LOW_SEL(dsi->feedback_div) | 4238c2ecf20Sopenharmony_ci LOW_PROGRAM_EN); 4248c2ecf20Sopenharmony_ci /* 4258c2ecf20Sopenharmony_ci * We need set PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL immediately 4268c2ecf20Sopenharmony_ci * to make the configured LSB effective according to IP simulation 4278c2ecf20Sopenharmony_ci * and lab test results. 4288c2ecf20Sopenharmony_ci * Only in this way can we get correct mipi phy pll frequency. 4298c2ecf20Sopenharmony_ci */ 4308c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL, 4318c2ecf20Sopenharmony_ci PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN); 4328c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO, 4338c2ecf20Sopenharmony_ci LOOP_DIV_HIGH_SEL(dsi->feedback_div) | 4348c2ecf20Sopenharmony_ci HIGH_PROGRAM_EN); 4358c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL, 4368c2ecf20Sopenharmony_ci PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY, 4398c2ecf20Sopenharmony_ci LOW_PROGRAM_EN | BIASEXTR_SEL(BIASEXTR_127_7)); 4408c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY, 4418c2ecf20Sopenharmony_ci HIGH_PROGRAM_EN | BANDGAP_SEL(BANDGAP_96_10)); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, BANDGAP_AND_BIAS_CONTROL, 4448c2ecf20Sopenharmony_ci POWER_CONTROL | INTERNAL_REG_CURRENT | 4458c2ecf20Sopenharmony_ci BIAS_BLOCK_ON | BANDGAP_ON); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL, 4488c2ecf20Sopenharmony_ci TER_RESISTOR_LOW | TER_CAL_DONE | 4498c2ecf20Sopenharmony_ci SETRD_MAX | TER_RESISTORS_ON); 4508c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL, 4518c2ecf20Sopenharmony_ci TER_RESISTOR_HIGH | LEVEL_SHIFTERS_ON | 4528c2ecf20Sopenharmony_ci SETRD_MAX | POWER_MANAGE | 4538c2ecf20Sopenharmony_ci TER_RESISTORS_ON); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL, 4568c2ecf20Sopenharmony_ci TLP_PROGRAM_EN | ns2bc(dsi, 500)); 4578c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL, 4588c2ecf20Sopenharmony_ci THS_PRE_PROGRAM_EN | ns2ui(dsi, 40)); 4598c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL, 4608c2ecf20Sopenharmony_ci THS_ZERO_PROGRAM_EN | ns2bc(dsi, 300)); 4618c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL, 4628c2ecf20Sopenharmony_ci THS_PRE_PROGRAM_EN | ns2ui(dsi, 100)); 4638c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL, 4648c2ecf20Sopenharmony_ci BIT(5) | ns2bc(dsi, 100)); 4658c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_POST_TIME_CONTROL, 4668c2ecf20Sopenharmony_ci BIT(5) | (ns2bc(dsi, 60) + 7)); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL, 4698c2ecf20Sopenharmony_ci TLP_PROGRAM_EN | ns2bc(dsi, 500)); 4708c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL, 4718c2ecf20Sopenharmony_ci THS_PRE_PROGRAM_EN | (ns2ui(dsi, 50) + 20)); 4728c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL, 4738c2ecf20Sopenharmony_ci THS_ZERO_PROGRAM_EN | (ns2bc(dsi, 140) + 2)); 4748c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL, 4758c2ecf20Sopenharmony_ci THS_PRE_PROGRAM_EN | (ns2ui(dsi, 60) + 8)); 4768c2ecf20Sopenharmony_ci dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL, 4778c2ecf20Sopenharmony_ci BIT(5) | ns2bc(dsi, 100)); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci clk_disable_unprepare(dsi->phy_cfg_clk); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci return ret; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_cistatic void dw_mipi_dsi_phy_power_on(void *priv_data) 4858c2ecf20Sopenharmony_ci{ 4868c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = priv_data; 4878c2ecf20Sopenharmony_ci int ret; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci ret = phy_set_mode(dsi->phy, PHY_MODE_MIPI_DPHY); 4908c2ecf20Sopenharmony_ci if (ret) { 4918c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, "failed to set phy mode: %d\n", ret); 4928c2ecf20Sopenharmony_ci return; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci phy_configure(dsi->phy, &dsi->phy_opts); 4968c2ecf20Sopenharmony_ci phy_power_on(dsi->phy); 4978c2ecf20Sopenharmony_ci} 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_cistatic void dw_mipi_dsi_phy_power_off(void *priv_data) 5008c2ecf20Sopenharmony_ci{ 5018c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = priv_data; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci phy_power_off(dsi->phy); 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_cistatic int 5078c2ecf20Sopenharmony_cidw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode, 5088c2ecf20Sopenharmony_ci unsigned long mode_flags, u32 lanes, u32 format, 5098c2ecf20Sopenharmony_ci unsigned int *lane_mbps) 5108c2ecf20Sopenharmony_ci{ 5118c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = priv_data; 5128c2ecf20Sopenharmony_ci int bpp; 5138c2ecf20Sopenharmony_ci unsigned long mpclk, tmp; 5148c2ecf20Sopenharmony_ci unsigned int target_mbps = 1000; 5158c2ecf20Sopenharmony_ci unsigned int max_mbps = dppa_map[ARRAY_SIZE(dppa_map) - 1].max_mbps; 5168c2ecf20Sopenharmony_ci unsigned long best_freq = 0; 5178c2ecf20Sopenharmony_ci unsigned long fvco_min, fvco_max, fin, fout; 5188c2ecf20Sopenharmony_ci unsigned int min_prediv, max_prediv; 5198c2ecf20Sopenharmony_ci unsigned int _prediv, best_prediv; 5208c2ecf20Sopenharmony_ci unsigned long _fbdiv, best_fbdiv; 5218c2ecf20Sopenharmony_ci unsigned long min_delta = ULONG_MAX; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci dsi->format = format; 5248c2ecf20Sopenharmony_ci bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); 5258c2ecf20Sopenharmony_ci if (bpp < 0) { 5268c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, 5278c2ecf20Sopenharmony_ci "failed to get bpp for pixel format %d\n", 5288c2ecf20Sopenharmony_ci dsi->format); 5298c2ecf20Sopenharmony_ci return bpp; 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci mpclk = DIV_ROUND_UP(mode->clock, MSEC_PER_SEC); 5338c2ecf20Sopenharmony_ci if (mpclk) { 5348c2ecf20Sopenharmony_ci /* take 1 / 0.8, since mbps must big than bandwidth of RGB */ 5358c2ecf20Sopenharmony_ci tmp = mpclk * (bpp / lanes) * 10 / 8; 5368c2ecf20Sopenharmony_ci if (tmp < max_mbps) 5378c2ecf20Sopenharmony_ci target_mbps = tmp; 5388c2ecf20Sopenharmony_ci else 5398c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, 5408c2ecf20Sopenharmony_ci "DPHY clock frequency is out of range\n"); 5418c2ecf20Sopenharmony_ci } 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* for external phy only a the mipi_dphy_config is necessary */ 5448c2ecf20Sopenharmony_ci if (dsi->phy) { 5458c2ecf20Sopenharmony_ci phy_mipi_dphy_get_default_config(mode->clock * 1000 * 10 / 8, 5468c2ecf20Sopenharmony_ci bpp, lanes, 5478c2ecf20Sopenharmony_ci &dsi->phy_opts.mipi_dphy); 5488c2ecf20Sopenharmony_ci dsi->lane_mbps = target_mbps; 5498c2ecf20Sopenharmony_ci *lane_mbps = dsi->lane_mbps; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci return 0; 5528c2ecf20Sopenharmony_ci } 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci fin = clk_get_rate(dsi->pllref_clk); 5558c2ecf20Sopenharmony_ci fout = target_mbps * USEC_PER_SEC; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci /* constraint: 5Mhz <= Fref / N <= 40MHz */ 5588c2ecf20Sopenharmony_ci min_prediv = DIV_ROUND_UP(fin, 40 * USEC_PER_SEC); 5598c2ecf20Sopenharmony_ci max_prediv = fin / (5 * USEC_PER_SEC); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci /* constraint: 80MHz <= Fvco <= 1500Mhz */ 5628c2ecf20Sopenharmony_ci fvco_min = 80 * USEC_PER_SEC; 5638c2ecf20Sopenharmony_ci fvco_max = 1500 * USEC_PER_SEC; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) { 5668c2ecf20Sopenharmony_ci u64 tmp; 5678c2ecf20Sopenharmony_ci u32 delta; 5688c2ecf20Sopenharmony_ci /* Fvco = Fref * M / N */ 5698c2ecf20Sopenharmony_ci tmp = (u64)fout * _prediv; 5708c2ecf20Sopenharmony_ci do_div(tmp, fin); 5718c2ecf20Sopenharmony_ci _fbdiv = tmp; 5728c2ecf20Sopenharmony_ci /* 5738c2ecf20Sopenharmony_ci * Due to the use of a "by 2 pre-scaler," the range of the 5748c2ecf20Sopenharmony_ci * feedback multiplication value M is limited to even division 5758c2ecf20Sopenharmony_ci * numbers, and m must be greater than 6, not bigger than 512. 5768c2ecf20Sopenharmony_ci */ 5778c2ecf20Sopenharmony_ci if (_fbdiv < 6 || _fbdiv > 512) 5788c2ecf20Sopenharmony_ci continue; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci _fbdiv += _fbdiv % 2; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci tmp = (u64)_fbdiv * fin; 5838c2ecf20Sopenharmony_ci do_div(tmp, _prediv); 5848c2ecf20Sopenharmony_ci if (tmp < fvco_min || tmp > fvco_max) 5858c2ecf20Sopenharmony_ci continue; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci delta = abs(fout - tmp); 5888c2ecf20Sopenharmony_ci if (delta < min_delta) { 5898c2ecf20Sopenharmony_ci best_prediv = _prediv; 5908c2ecf20Sopenharmony_ci best_fbdiv = _fbdiv; 5918c2ecf20Sopenharmony_ci min_delta = delta; 5928c2ecf20Sopenharmony_ci best_freq = tmp; 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci if (best_freq) { 5978c2ecf20Sopenharmony_ci dsi->lane_mbps = DIV_ROUND_UP(best_freq, USEC_PER_SEC); 5988c2ecf20Sopenharmony_ci *lane_mbps = dsi->lane_mbps; 5998c2ecf20Sopenharmony_ci dsi->input_div = best_prediv; 6008c2ecf20Sopenharmony_ci dsi->feedback_div = best_fbdiv; 6018c2ecf20Sopenharmony_ci } else { 6028c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, "Can not find best_freq for DPHY\n"); 6038c2ecf20Sopenharmony_ci return -EINVAL; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci return 0; 6078c2ecf20Sopenharmony_ci} 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_cistruct hstt { 6108c2ecf20Sopenharmony_ci unsigned int maxfreq; 6118c2ecf20Sopenharmony_ci struct dw_mipi_dsi_dphy_timing timing; 6128c2ecf20Sopenharmony_ci}; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp) \ 6158c2ecf20Sopenharmony_ci{ \ 6168c2ecf20Sopenharmony_ci .maxfreq = _maxfreq, \ 6178c2ecf20Sopenharmony_ci .timing = { \ 6188c2ecf20Sopenharmony_ci .clk_lp2hs = _c_lp2hs, \ 6198c2ecf20Sopenharmony_ci .clk_hs2lp = _c_hs2lp, \ 6208c2ecf20Sopenharmony_ci .data_lp2hs = _d_lp2hs, \ 6218c2ecf20Sopenharmony_ci .data_hs2lp = _d_hs2lp, \ 6228c2ecf20Sopenharmony_ci } \ 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci/* Table A-3 High-Speed Transition Times */ 6268c2ecf20Sopenharmony_cistruct hstt hstt_table[] = { 6278c2ecf20Sopenharmony_ci HSTT( 90, 32, 20, 26, 13), 6288c2ecf20Sopenharmony_ci HSTT( 100, 35, 23, 28, 14), 6298c2ecf20Sopenharmony_ci HSTT( 110, 32, 22, 26, 13), 6308c2ecf20Sopenharmony_ci HSTT( 130, 31, 20, 27, 13), 6318c2ecf20Sopenharmony_ci HSTT( 140, 33, 22, 26, 14), 6328c2ecf20Sopenharmony_ci HSTT( 150, 33, 21, 26, 14), 6338c2ecf20Sopenharmony_ci HSTT( 170, 32, 20, 27, 13), 6348c2ecf20Sopenharmony_ci HSTT( 180, 36, 23, 30, 15), 6358c2ecf20Sopenharmony_ci HSTT( 200, 40, 22, 33, 15), 6368c2ecf20Sopenharmony_ci HSTT( 220, 40, 22, 33, 15), 6378c2ecf20Sopenharmony_ci HSTT( 240, 44, 24, 36, 16), 6388c2ecf20Sopenharmony_ci HSTT( 250, 48, 24, 38, 17), 6398c2ecf20Sopenharmony_ci HSTT( 270, 48, 24, 38, 17), 6408c2ecf20Sopenharmony_ci HSTT( 300, 50, 27, 41, 18), 6418c2ecf20Sopenharmony_ci HSTT( 330, 56, 28, 45, 18), 6428c2ecf20Sopenharmony_ci HSTT( 360, 59, 28, 48, 19), 6438c2ecf20Sopenharmony_ci HSTT( 400, 61, 30, 50, 20), 6448c2ecf20Sopenharmony_ci HSTT( 450, 67, 31, 55, 21), 6458c2ecf20Sopenharmony_ci HSTT( 500, 73, 31, 59, 22), 6468c2ecf20Sopenharmony_ci HSTT( 550, 79, 36, 63, 24), 6478c2ecf20Sopenharmony_ci HSTT( 600, 83, 37, 68, 25), 6488c2ecf20Sopenharmony_ci HSTT( 650, 90, 38, 73, 27), 6498c2ecf20Sopenharmony_ci HSTT( 700, 95, 40, 77, 28), 6508c2ecf20Sopenharmony_ci HSTT( 750, 102, 40, 84, 28), 6518c2ecf20Sopenharmony_ci HSTT( 800, 106, 42, 87, 30), 6528c2ecf20Sopenharmony_ci HSTT( 850, 113, 44, 93, 31), 6538c2ecf20Sopenharmony_ci HSTT( 900, 118, 47, 98, 32), 6548c2ecf20Sopenharmony_ci HSTT( 950, 124, 47, 102, 34), 6558c2ecf20Sopenharmony_ci HSTT(1000, 130, 49, 107, 35), 6568c2ecf20Sopenharmony_ci HSTT(1050, 135, 51, 111, 37), 6578c2ecf20Sopenharmony_ci HSTT(1100, 139, 51, 114, 38), 6588c2ecf20Sopenharmony_ci HSTT(1150, 146, 54, 120, 40), 6598c2ecf20Sopenharmony_ci HSTT(1200, 153, 57, 125, 41), 6608c2ecf20Sopenharmony_ci HSTT(1250, 158, 58, 130, 42), 6618c2ecf20Sopenharmony_ci HSTT(1300, 163, 58, 135, 44), 6628c2ecf20Sopenharmony_ci HSTT(1350, 168, 60, 140, 45), 6638c2ecf20Sopenharmony_ci HSTT(1400, 172, 64, 144, 47), 6648c2ecf20Sopenharmony_ci HSTT(1450, 176, 65, 148, 48), 6658c2ecf20Sopenharmony_ci HSTT(1500, 181, 66, 153, 50) 6668c2ecf20Sopenharmony_ci}; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_cistatic int 6698c2ecf20Sopenharmony_cidw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps, 6708c2ecf20Sopenharmony_ci struct dw_mipi_dsi_dphy_timing *timing) 6718c2ecf20Sopenharmony_ci{ 6728c2ecf20Sopenharmony_ci int i; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(hstt_table); i++) 6758c2ecf20Sopenharmony_ci if (lane_mbps < hstt_table[i].maxfreq) 6768c2ecf20Sopenharmony_ci break; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci if (i == ARRAY_SIZE(hstt_table)) 6798c2ecf20Sopenharmony_ci i--; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci *timing = hstt_table[i].timing; 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci return 0; 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_rockchip_phy_ops = { 6878c2ecf20Sopenharmony_ci .init = dw_mipi_dsi_phy_init, 6888c2ecf20Sopenharmony_ci .power_on = dw_mipi_dsi_phy_power_on, 6898c2ecf20Sopenharmony_ci .power_off = dw_mipi_dsi_phy_power_off, 6908c2ecf20Sopenharmony_ci .get_lane_mbps = dw_mipi_dsi_get_lane_mbps, 6918c2ecf20Sopenharmony_ci .get_timing = dw_mipi_dsi_phy_get_timing, 6928c2ecf20Sopenharmony_ci}; 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi) 6958c2ecf20Sopenharmony_ci{ 6968c2ecf20Sopenharmony_ci if (dsi->cdata->lanecfg1_grf_reg) 6978c2ecf20Sopenharmony_ci regmap_write(dsi->grf_regmap, dsi->cdata->lanecfg1_grf_reg, 6988c2ecf20Sopenharmony_ci dsi->cdata->lanecfg1); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci if (dsi->cdata->lanecfg2_grf_reg) 7018c2ecf20Sopenharmony_ci regmap_write(dsi->grf_regmap, dsi->cdata->lanecfg2_grf_reg, 7028c2ecf20Sopenharmony_ci dsi->cdata->lanecfg2); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci if (dsi->cdata->enable_grf_reg) 7058c2ecf20Sopenharmony_ci regmap_write(dsi->grf_regmap, dsi->cdata->enable_grf_reg, 7068c2ecf20Sopenharmony_ci dsi->cdata->enable); 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_cistatic void dw_mipi_dsi_rockchip_set_lcdsel(struct dw_mipi_dsi_rockchip *dsi, 7108c2ecf20Sopenharmony_ci int mux) 7118c2ecf20Sopenharmony_ci{ 7128c2ecf20Sopenharmony_ci regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg, 7138c2ecf20Sopenharmony_ci mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big); 7148c2ecf20Sopenharmony_ci} 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cistatic int 7178c2ecf20Sopenharmony_cidw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder, 7188c2ecf20Sopenharmony_ci struct drm_crtc_state *crtc_state, 7198c2ecf20Sopenharmony_ci struct drm_connector_state *conn_state) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); 7228c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci switch (dsi->format) { 7258c2ecf20Sopenharmony_ci case MIPI_DSI_FMT_RGB888: 7268c2ecf20Sopenharmony_ci s->output_mode = ROCKCHIP_OUT_MODE_P888; 7278c2ecf20Sopenharmony_ci break; 7288c2ecf20Sopenharmony_ci case MIPI_DSI_FMT_RGB666: 7298c2ecf20Sopenharmony_ci s->output_mode = ROCKCHIP_OUT_MODE_P666; 7308c2ecf20Sopenharmony_ci break; 7318c2ecf20Sopenharmony_ci case MIPI_DSI_FMT_RGB565: 7328c2ecf20Sopenharmony_ci s->output_mode = ROCKCHIP_OUT_MODE_P565; 7338c2ecf20Sopenharmony_ci break; 7348c2ecf20Sopenharmony_ci default: 7358c2ecf20Sopenharmony_ci WARN_ON(1); 7368c2ecf20Sopenharmony_ci return -EINVAL; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci s->output_type = DRM_MODE_CONNECTOR_DSI; 7408c2ecf20Sopenharmony_ci if (dsi->slave) 7418c2ecf20Sopenharmony_ci s->output_flags = ROCKCHIP_OUTPUT_DSI_DUAL; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci return 0; 7448c2ecf20Sopenharmony_ci} 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_cistatic void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) 7478c2ecf20Sopenharmony_ci{ 7488c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder); 7498c2ecf20Sopenharmony_ci int ret, mux; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, 7528c2ecf20Sopenharmony_ci &dsi->encoder); 7538c2ecf20Sopenharmony_ci if (mux < 0) 7548c2ecf20Sopenharmony_ci return; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci pm_runtime_get_sync(dsi->dev); 7578c2ecf20Sopenharmony_ci if (dsi->slave) 7588c2ecf20Sopenharmony_ci pm_runtime_get_sync(dsi->slave->dev); 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci /* 7618c2ecf20Sopenharmony_ci * For the RK3399, the clk of grf must be enabled before writing grf 7628c2ecf20Sopenharmony_ci * register. And for RK3288 or other soc, this grf_clk must be NULL, 7638c2ecf20Sopenharmony_ci * the clk_prepare_enable return true directly. 7648c2ecf20Sopenharmony_ci */ 7658c2ecf20Sopenharmony_ci ret = clk_prepare_enable(dsi->grf_clk); 7668c2ecf20Sopenharmony_ci if (ret) { 7678c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret); 7688c2ecf20Sopenharmony_ci return; 7698c2ecf20Sopenharmony_ci } 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci dw_mipi_dsi_rockchip_set_lcdsel(dsi, mux); 7728c2ecf20Sopenharmony_ci if (dsi->slave) 7738c2ecf20Sopenharmony_ci dw_mipi_dsi_rockchip_set_lcdsel(dsi->slave, mux); 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci clk_disable_unprepare(dsi->grf_clk); 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci if (dsi->slave) 7838c2ecf20Sopenharmony_ci pm_runtime_put(dsi->slave->dev); 7848c2ecf20Sopenharmony_ci pm_runtime_put(dsi->dev); 7858c2ecf20Sopenharmony_ci} 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_cistatic const struct drm_encoder_helper_funcs 7888c2ecf20Sopenharmony_cidw_mipi_dsi_encoder_helper_funcs = { 7898c2ecf20Sopenharmony_ci .atomic_check = dw_mipi_dsi_encoder_atomic_check, 7908c2ecf20Sopenharmony_ci .enable = dw_mipi_dsi_encoder_enable, 7918c2ecf20Sopenharmony_ci .disable = dw_mipi_dsi_encoder_disable, 7928c2ecf20Sopenharmony_ci}; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_cistatic int rockchip_dsi_drm_create_encoder(struct dw_mipi_dsi_rockchip *dsi, 7958c2ecf20Sopenharmony_ci struct drm_device *drm_dev) 7968c2ecf20Sopenharmony_ci{ 7978c2ecf20Sopenharmony_ci struct drm_encoder *encoder = &dsi->encoder; 7988c2ecf20Sopenharmony_ci int ret; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, 8018c2ecf20Sopenharmony_ci dsi->dev->of_node); 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_DSI); 8048c2ecf20Sopenharmony_ci if (ret) { 8058c2ecf20Sopenharmony_ci DRM_ERROR("Failed to initialize encoder with drm\n"); 8068c2ecf20Sopenharmony_ci return ret; 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci drm_encoder_helper_add(encoder, &dw_mipi_dsi_encoder_helper_funcs); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci return 0; 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_cistatic struct device 8158c2ecf20Sopenharmony_ci*dw_mipi_dsi_rockchip_find_second(struct dw_mipi_dsi_rockchip *dsi) 8168c2ecf20Sopenharmony_ci{ 8178c2ecf20Sopenharmony_ci const struct of_device_id *match; 8188c2ecf20Sopenharmony_ci struct device_node *node = NULL, *local; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci match = of_match_device(dsi->dev->driver->of_match_table, dsi->dev); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci local = of_graph_get_remote_node(dsi->dev->of_node, 1, 0); 8238c2ecf20Sopenharmony_ci if (!local) 8248c2ecf20Sopenharmony_ci return NULL; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci while ((node = of_find_compatible_node(node, NULL, 8278c2ecf20Sopenharmony_ci match->compatible))) { 8288c2ecf20Sopenharmony_ci struct device_node *remote; 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci /* found ourself */ 8318c2ecf20Sopenharmony_ci if (node == dsi->dev->of_node) 8328c2ecf20Sopenharmony_ci continue; 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci remote = of_graph_get_remote_node(node, 1, 0); 8358c2ecf20Sopenharmony_ci if (!remote) 8368c2ecf20Sopenharmony_ci continue; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci /* same display device in port1-ep0 for both */ 8398c2ecf20Sopenharmony_ci if (remote == local) { 8408c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi2; 8418c2ecf20Sopenharmony_ci struct platform_device *pdev; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci pdev = of_find_device_by_node(node); 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci /* 8468c2ecf20Sopenharmony_ci * we have found the second, so will either return it 8478c2ecf20Sopenharmony_ci * or return with an error. In any case won't need the 8488c2ecf20Sopenharmony_ci * nodes anymore nor continue the loop. 8498c2ecf20Sopenharmony_ci */ 8508c2ecf20Sopenharmony_ci of_node_put(remote); 8518c2ecf20Sopenharmony_ci of_node_put(node); 8528c2ecf20Sopenharmony_ci of_node_put(local); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci if (!pdev) 8558c2ecf20Sopenharmony_ci return ERR_PTR(-EPROBE_DEFER); 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci dsi2 = platform_get_drvdata(pdev); 8588c2ecf20Sopenharmony_ci if (!dsi2) { 8598c2ecf20Sopenharmony_ci platform_device_put(pdev); 8608c2ecf20Sopenharmony_ci return ERR_PTR(-EPROBE_DEFER); 8618c2ecf20Sopenharmony_ci } 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci return &pdev->dev; 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci of_node_put(remote); 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci of_node_put(local); 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci return NULL; 8728c2ecf20Sopenharmony_ci} 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_cistatic int dw_mipi_dsi_rockchip_bind(struct device *dev, 8758c2ecf20Sopenharmony_ci struct device *master, 8768c2ecf20Sopenharmony_ci void *data) 8778c2ecf20Sopenharmony_ci{ 8788c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev); 8798c2ecf20Sopenharmony_ci struct drm_device *drm_dev = data; 8808c2ecf20Sopenharmony_ci struct device *second; 8818c2ecf20Sopenharmony_ci bool master1, master2; 8828c2ecf20Sopenharmony_ci int ret; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci second = dw_mipi_dsi_rockchip_find_second(dsi); 8858c2ecf20Sopenharmony_ci if (IS_ERR(second)) 8868c2ecf20Sopenharmony_ci return PTR_ERR(second); 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci if (second) { 8898c2ecf20Sopenharmony_ci master1 = of_property_read_bool(dsi->dev->of_node, 8908c2ecf20Sopenharmony_ci "clock-master"); 8918c2ecf20Sopenharmony_ci master2 = of_property_read_bool(second->of_node, 8928c2ecf20Sopenharmony_ci "clock-master"); 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci if (master1 && master2) { 8958c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, "only one clock-master allowed\n"); 8968c2ecf20Sopenharmony_ci return -EINVAL; 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci if (!master1 && !master2) { 9008c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, "no clock-master defined\n"); 9018c2ecf20Sopenharmony_ci return -EINVAL; 9028c2ecf20Sopenharmony_ci } 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci /* we are the slave in dual-DSI */ 9058c2ecf20Sopenharmony_ci if (!master1) { 9068c2ecf20Sopenharmony_ci dsi->is_slave = true; 9078c2ecf20Sopenharmony_ci return 0; 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci dsi->slave = dev_get_drvdata(second); 9118c2ecf20Sopenharmony_ci if (!dsi->slave) { 9128c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, "could not get slaves data\n"); 9138c2ecf20Sopenharmony_ci return -ENODEV; 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci dsi->slave->is_slave = true; 9178c2ecf20Sopenharmony_ci dw_mipi_dsi_set_slave(dsi->dmd, dsi->slave->dmd); 9188c2ecf20Sopenharmony_ci put_device(second); 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci ret = clk_prepare_enable(dsi->pllref_clk); 9228c2ecf20Sopenharmony_ci if (ret) { 9238c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, "Failed to enable pllref_clk: %d\n", ret); 9248c2ecf20Sopenharmony_ci return ret; 9258c2ecf20Sopenharmony_ci } 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci /* 9288c2ecf20Sopenharmony_ci * With the GRF clock running, write lane and dual-mode configurations 9298c2ecf20Sopenharmony_ci * that won't change immediately. If we waited until enable() to do 9308c2ecf20Sopenharmony_ci * this, things like panel preparation would not be able to send 9318c2ecf20Sopenharmony_ci * commands over DSI. 9328c2ecf20Sopenharmony_ci */ 9338c2ecf20Sopenharmony_ci ret = clk_prepare_enable(dsi->grf_clk); 9348c2ecf20Sopenharmony_ci if (ret) { 9358c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret); 9368c2ecf20Sopenharmony_ci return ret; 9378c2ecf20Sopenharmony_ci } 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci dw_mipi_dsi_rockchip_config(dsi); 9408c2ecf20Sopenharmony_ci if (dsi->slave) 9418c2ecf20Sopenharmony_ci dw_mipi_dsi_rockchip_config(dsi->slave); 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci clk_disable_unprepare(dsi->grf_clk); 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci ret = rockchip_dsi_drm_create_encoder(dsi, drm_dev); 9468c2ecf20Sopenharmony_ci if (ret) { 9478c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, "Failed to create drm encoder\n"); 9488c2ecf20Sopenharmony_ci return ret; 9498c2ecf20Sopenharmony_ci } 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci ret = dw_mipi_dsi_bind(dsi->dmd, &dsi->encoder); 9528c2ecf20Sopenharmony_ci if (ret) { 9538c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, "Failed to bind: %d\n", ret); 9548c2ecf20Sopenharmony_ci return ret; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci return 0; 9588c2ecf20Sopenharmony_ci} 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic void dw_mipi_dsi_rockchip_unbind(struct device *dev, 9618c2ecf20Sopenharmony_ci struct device *master, 9628c2ecf20Sopenharmony_ci void *data) 9638c2ecf20Sopenharmony_ci{ 9648c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev); 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci if (dsi->is_slave) 9678c2ecf20Sopenharmony_ci return; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci dw_mipi_dsi_unbind(dsi->dmd); 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci clk_disable_unprepare(dsi->pllref_clk); 9728c2ecf20Sopenharmony_ci} 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_cistatic const struct component_ops dw_mipi_dsi_rockchip_ops = { 9758c2ecf20Sopenharmony_ci .bind = dw_mipi_dsi_rockchip_bind, 9768c2ecf20Sopenharmony_ci .unbind = dw_mipi_dsi_rockchip_unbind, 9778c2ecf20Sopenharmony_ci}; 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_cistatic int dw_mipi_dsi_rockchip_host_attach(void *priv_data, 9808c2ecf20Sopenharmony_ci struct mipi_dsi_device *device) 9818c2ecf20Sopenharmony_ci{ 9828c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = priv_data; 9838c2ecf20Sopenharmony_ci struct device *second; 9848c2ecf20Sopenharmony_ci int ret; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci ret = component_add(dsi->dev, &dw_mipi_dsi_rockchip_ops); 9878c2ecf20Sopenharmony_ci if (ret) { 9888c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, "Failed to register component: %d\n", 9898c2ecf20Sopenharmony_ci ret); 9908c2ecf20Sopenharmony_ci return ret; 9918c2ecf20Sopenharmony_ci } 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci second = dw_mipi_dsi_rockchip_find_second(dsi); 9948c2ecf20Sopenharmony_ci if (IS_ERR(second)) 9958c2ecf20Sopenharmony_ci return PTR_ERR(second); 9968c2ecf20Sopenharmony_ci if (second) { 9978c2ecf20Sopenharmony_ci ret = component_add(second, &dw_mipi_dsi_rockchip_ops); 9988c2ecf20Sopenharmony_ci if (ret) { 9998c2ecf20Sopenharmony_ci DRM_DEV_ERROR(second, 10008c2ecf20Sopenharmony_ci "Failed to register component: %d\n", 10018c2ecf20Sopenharmony_ci ret); 10028c2ecf20Sopenharmony_ci return ret; 10038c2ecf20Sopenharmony_ci } 10048c2ecf20Sopenharmony_ci } 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci return 0; 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_cistatic int dw_mipi_dsi_rockchip_host_detach(void *priv_data, 10108c2ecf20Sopenharmony_ci struct mipi_dsi_device *device) 10118c2ecf20Sopenharmony_ci{ 10128c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = priv_data; 10138c2ecf20Sopenharmony_ci struct device *second; 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci second = dw_mipi_dsi_rockchip_find_second(dsi); 10168c2ecf20Sopenharmony_ci if (second && !IS_ERR(second)) 10178c2ecf20Sopenharmony_ci component_del(second, &dw_mipi_dsi_rockchip_ops); 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci component_del(dsi->dev, &dw_mipi_dsi_rockchip_ops); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci return 0; 10228c2ecf20Sopenharmony_ci} 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_cistatic const struct dw_mipi_dsi_host_ops dw_mipi_dsi_rockchip_host_ops = { 10258c2ecf20Sopenharmony_ci .attach = dw_mipi_dsi_rockchip_host_attach, 10268c2ecf20Sopenharmony_ci .detach = dw_mipi_dsi_rockchip_host_detach, 10278c2ecf20Sopenharmony_ci}; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_cistatic int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev) 10308c2ecf20Sopenharmony_ci{ 10318c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 10328c2ecf20Sopenharmony_ci struct device_node *np = dev->of_node; 10338c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi; 10348c2ecf20Sopenharmony_ci struct resource *res; 10358c2ecf20Sopenharmony_ci const struct rockchip_dw_dsi_chip_data *cdata = 10368c2ecf20Sopenharmony_ci of_device_get_match_data(dev); 10378c2ecf20Sopenharmony_ci int ret, i; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); 10408c2ecf20Sopenharmony_ci if (!dsi) 10418c2ecf20Sopenharmony_ci return -ENOMEM; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10448c2ecf20Sopenharmony_ci dsi->base = devm_ioremap_resource(dev, res); 10458c2ecf20Sopenharmony_ci if (IS_ERR(dsi->base)) { 10468c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, "Unable to get dsi registers\n"); 10478c2ecf20Sopenharmony_ci return PTR_ERR(dsi->base); 10488c2ecf20Sopenharmony_ci } 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci i = 0; 10518c2ecf20Sopenharmony_ci while (cdata[i].reg) { 10528c2ecf20Sopenharmony_ci if (cdata[i].reg == res->start) { 10538c2ecf20Sopenharmony_ci dsi->cdata = &cdata[i]; 10548c2ecf20Sopenharmony_ci break; 10558c2ecf20Sopenharmony_ci } 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci i++; 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci if (!dsi->cdata) { 10618c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, "no dsi-config for %s node\n", np->name); 10628c2ecf20Sopenharmony_ci return -EINVAL; 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci /* try to get a possible external dphy */ 10668c2ecf20Sopenharmony_ci dsi->phy = devm_phy_optional_get(dev, "dphy"); 10678c2ecf20Sopenharmony_ci if (IS_ERR(dsi->phy)) { 10688c2ecf20Sopenharmony_ci ret = PTR_ERR(dsi->phy); 10698c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, "failed to get mipi dphy: %d\n", ret); 10708c2ecf20Sopenharmony_ci return ret; 10718c2ecf20Sopenharmony_ci } 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci dsi->pllref_clk = devm_clk_get(dev, "ref"); 10748c2ecf20Sopenharmony_ci if (IS_ERR(dsi->pllref_clk)) { 10758c2ecf20Sopenharmony_ci if (dsi->phy) { 10768c2ecf20Sopenharmony_ci /* 10778c2ecf20Sopenharmony_ci * if external phy is present, pll will be 10788c2ecf20Sopenharmony_ci * generated there. 10798c2ecf20Sopenharmony_ci */ 10808c2ecf20Sopenharmony_ci dsi->pllref_clk = NULL; 10818c2ecf20Sopenharmony_ci } else { 10828c2ecf20Sopenharmony_ci ret = PTR_ERR(dsi->pllref_clk); 10838c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, 10848c2ecf20Sopenharmony_ci "Unable to get pll reference clock: %d\n", 10858c2ecf20Sopenharmony_ci ret); 10868c2ecf20Sopenharmony_ci return ret; 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci if (dsi->cdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) { 10918c2ecf20Sopenharmony_ci dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg"); 10928c2ecf20Sopenharmony_ci if (IS_ERR(dsi->phy_cfg_clk)) { 10938c2ecf20Sopenharmony_ci ret = PTR_ERR(dsi->phy_cfg_clk); 10948c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, 10958c2ecf20Sopenharmony_ci "Unable to get phy_cfg_clk: %d\n", ret); 10968c2ecf20Sopenharmony_ci return ret; 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci } 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci if (dsi->cdata->flags & DW_MIPI_NEEDS_GRF_CLK) { 11018c2ecf20Sopenharmony_ci dsi->grf_clk = devm_clk_get(dev, "grf"); 11028c2ecf20Sopenharmony_ci if (IS_ERR(dsi->grf_clk)) { 11038c2ecf20Sopenharmony_ci ret = PTR_ERR(dsi->grf_clk); 11048c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, "Unable to get grf_clk: %d\n", ret); 11058c2ecf20Sopenharmony_ci return ret; 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci } 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci dsi->grf_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 11108c2ecf20Sopenharmony_ci if (IS_ERR(dsi->grf_regmap)) { 11118c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dsi->dev, "Unable to get rockchip,grf\n"); 11128c2ecf20Sopenharmony_ci return PTR_ERR(dsi->grf_regmap); 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci dsi->dev = dev; 11168c2ecf20Sopenharmony_ci dsi->pdata.base = dsi->base; 11178c2ecf20Sopenharmony_ci dsi->pdata.max_data_lanes = dsi->cdata->max_data_lanes; 11188c2ecf20Sopenharmony_ci dsi->pdata.phy_ops = &dw_mipi_dsi_rockchip_phy_ops; 11198c2ecf20Sopenharmony_ci dsi->pdata.host_ops = &dw_mipi_dsi_rockchip_host_ops; 11208c2ecf20Sopenharmony_ci dsi->pdata.priv_data = dsi; 11218c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, dsi); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci dsi->dmd = dw_mipi_dsi_probe(pdev, &dsi->pdata); 11248c2ecf20Sopenharmony_ci if (IS_ERR(dsi->dmd)) { 11258c2ecf20Sopenharmony_ci ret = PTR_ERR(dsi->dmd); 11268c2ecf20Sopenharmony_ci if (ret != -EPROBE_DEFER) 11278c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, 11288c2ecf20Sopenharmony_ci "Failed to probe dw_mipi_dsi: %d\n", ret); 11298c2ecf20Sopenharmony_ci goto err_clkdisable; 11308c2ecf20Sopenharmony_ci } 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci return 0; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_cierr_clkdisable: 11358c2ecf20Sopenharmony_ci clk_disable_unprepare(dsi->pllref_clk); 11368c2ecf20Sopenharmony_ci return ret; 11378c2ecf20Sopenharmony_ci} 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_cistatic int dw_mipi_dsi_rockchip_remove(struct platform_device *pdev) 11408c2ecf20Sopenharmony_ci{ 11418c2ecf20Sopenharmony_ci struct dw_mipi_dsi_rockchip *dsi = platform_get_drvdata(pdev); 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci dw_mipi_dsi_remove(dsi->dmd); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci return 0; 11468c2ecf20Sopenharmony_ci} 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_cistatic const struct rockchip_dw_dsi_chip_data px30_chip_data[] = { 11498c2ecf20Sopenharmony_ci { 11508c2ecf20Sopenharmony_ci .reg = 0xff450000, 11518c2ecf20Sopenharmony_ci .lcdsel_grf_reg = PX30_GRF_PD_VO_CON1, 11528c2ecf20Sopenharmony_ci .lcdsel_big = HIWORD_UPDATE(0, PX30_DSI_LCDC_SEL), 11538c2ecf20Sopenharmony_ci .lcdsel_lit = HIWORD_UPDATE(PX30_DSI_LCDC_SEL, 11548c2ecf20Sopenharmony_ci PX30_DSI_LCDC_SEL), 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci .lanecfg1_grf_reg = PX30_GRF_PD_VO_CON1, 11578c2ecf20Sopenharmony_ci .lanecfg1 = HIWORD_UPDATE(0, PX30_DSI_TURNDISABLE | 11588c2ecf20Sopenharmony_ci PX30_DSI_FORCERXMODE | 11598c2ecf20Sopenharmony_ci PX30_DSI_FORCETXSTOPMODE), 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci .max_data_lanes = 4, 11628c2ecf20Sopenharmony_ci }, 11638c2ecf20Sopenharmony_ci { /* sentinel */ } 11648c2ecf20Sopenharmony_ci}; 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cistatic const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = { 11678c2ecf20Sopenharmony_ci { 11688c2ecf20Sopenharmony_ci .reg = 0xff960000, 11698c2ecf20Sopenharmony_ci .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, 11708c2ecf20Sopenharmony_ci .lcdsel_big = HIWORD_UPDATE(0, RK3288_DSI0_LCDC_SEL), 11718c2ecf20Sopenharmony_ci .lcdsel_lit = HIWORD_UPDATE(RK3288_DSI0_LCDC_SEL, RK3288_DSI0_LCDC_SEL), 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci .max_data_lanes = 4, 11748c2ecf20Sopenharmony_ci }, 11758c2ecf20Sopenharmony_ci { 11768c2ecf20Sopenharmony_ci .reg = 0xff964000, 11778c2ecf20Sopenharmony_ci .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, 11788c2ecf20Sopenharmony_ci .lcdsel_big = HIWORD_UPDATE(0, RK3288_DSI1_LCDC_SEL), 11798c2ecf20Sopenharmony_ci .lcdsel_lit = HIWORD_UPDATE(RK3288_DSI1_LCDC_SEL, RK3288_DSI1_LCDC_SEL), 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci .max_data_lanes = 4, 11828c2ecf20Sopenharmony_ci }, 11838c2ecf20Sopenharmony_ci { /* sentinel */ } 11848c2ecf20Sopenharmony_ci}; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_cistatic const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = { 11878c2ecf20Sopenharmony_ci { 11888c2ecf20Sopenharmony_ci .reg = 0xff960000, 11898c2ecf20Sopenharmony_ci .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, 11908c2ecf20Sopenharmony_ci .lcdsel_big = HIWORD_UPDATE(0, RK3399_DSI0_LCDC_SEL), 11918c2ecf20Sopenharmony_ci .lcdsel_lit = HIWORD_UPDATE(RK3399_DSI0_LCDC_SEL, 11928c2ecf20Sopenharmony_ci RK3399_DSI0_LCDC_SEL), 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci .lanecfg1_grf_reg = RK3399_GRF_SOC_CON22, 11958c2ecf20Sopenharmony_ci .lanecfg1 = HIWORD_UPDATE(0, RK3399_DSI0_TURNREQUEST | 11968c2ecf20Sopenharmony_ci RK3399_DSI0_TURNDISABLE | 11978c2ecf20Sopenharmony_ci RK3399_DSI0_FORCETXSTOPMODE | 11988c2ecf20Sopenharmony_ci RK3399_DSI0_FORCERXMODE), 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK, 12018c2ecf20Sopenharmony_ci .max_data_lanes = 4, 12028c2ecf20Sopenharmony_ci }, 12038c2ecf20Sopenharmony_ci { 12048c2ecf20Sopenharmony_ci .reg = 0xff968000, 12058c2ecf20Sopenharmony_ci .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, 12068c2ecf20Sopenharmony_ci .lcdsel_big = HIWORD_UPDATE(0, RK3399_DSI1_LCDC_SEL), 12078c2ecf20Sopenharmony_ci .lcdsel_lit = HIWORD_UPDATE(RK3399_DSI1_LCDC_SEL, 12088c2ecf20Sopenharmony_ci RK3399_DSI1_LCDC_SEL), 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci .lanecfg1_grf_reg = RK3399_GRF_SOC_CON23, 12118c2ecf20Sopenharmony_ci .lanecfg1 = HIWORD_UPDATE(0, RK3399_DSI1_TURNDISABLE | 12128c2ecf20Sopenharmony_ci RK3399_DSI1_FORCETXSTOPMODE | 12138c2ecf20Sopenharmony_ci RK3399_DSI1_FORCERXMODE | 12148c2ecf20Sopenharmony_ci RK3399_DSI1_ENABLE), 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci .lanecfg2_grf_reg = RK3399_GRF_SOC_CON24, 12178c2ecf20Sopenharmony_ci .lanecfg2 = HIWORD_UPDATE(RK3399_TXRX_MASTERSLAVEZ | 12188c2ecf20Sopenharmony_ci RK3399_TXRX_ENABLECLK, 12198c2ecf20Sopenharmony_ci RK3399_TXRX_MASTERSLAVEZ | 12208c2ecf20Sopenharmony_ci RK3399_TXRX_ENABLECLK | 12218c2ecf20Sopenharmony_ci RK3399_TXRX_BASEDIR), 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci .enable_grf_reg = RK3399_GRF_SOC_CON23, 12248c2ecf20Sopenharmony_ci .enable = HIWORD_UPDATE(RK3399_DSI1_ENABLE, RK3399_DSI1_ENABLE), 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK, 12278c2ecf20Sopenharmony_ci .max_data_lanes = 4, 12288c2ecf20Sopenharmony_ci }, 12298c2ecf20Sopenharmony_ci { /* sentinel */ } 12308c2ecf20Sopenharmony_ci}; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_cistatic const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = { 12338c2ecf20Sopenharmony_ci { 12348c2ecf20Sopenharmony_ci .compatible = "rockchip,px30-mipi-dsi", 12358c2ecf20Sopenharmony_ci .data = &px30_chip_data, 12368c2ecf20Sopenharmony_ci }, { 12378c2ecf20Sopenharmony_ci .compatible = "rockchip,rk3288-mipi-dsi", 12388c2ecf20Sopenharmony_ci .data = &rk3288_chip_data, 12398c2ecf20Sopenharmony_ci }, { 12408c2ecf20Sopenharmony_ci .compatible = "rockchip,rk3399-mipi-dsi", 12418c2ecf20Sopenharmony_ci .data = &rk3399_chip_data, 12428c2ecf20Sopenharmony_ci }, 12438c2ecf20Sopenharmony_ci { /* sentinel */ } 12448c2ecf20Sopenharmony_ci}; 12458c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, dw_mipi_dsi_rockchip_dt_ids); 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_cistruct platform_driver dw_mipi_dsi_rockchip_driver = { 12488c2ecf20Sopenharmony_ci .probe = dw_mipi_dsi_rockchip_probe, 12498c2ecf20Sopenharmony_ci .remove = dw_mipi_dsi_rockchip_remove, 12508c2ecf20Sopenharmony_ci .driver = { 12518c2ecf20Sopenharmony_ci .of_match_table = dw_mipi_dsi_rockchip_dt_ids, 12528c2ecf20Sopenharmony_ci .name = "dw-mipi-dsi-rockchip", 12538c2ecf20Sopenharmony_ci /* 12548c2ecf20Sopenharmony_ci * For dual-DSI display, one DSI pokes at the other DSI's 12558c2ecf20Sopenharmony_ci * drvdata in dw_mipi_dsi_rockchip_find_second(). This is not 12568c2ecf20Sopenharmony_ci * safe for asynchronous probe. 12578c2ecf20Sopenharmony_ci */ 12588c2ecf20Sopenharmony_ci .probe_type = PROBE_FORCE_SYNCHRONOUS, 12598c2ecf20Sopenharmony_ci }, 12608c2ecf20Sopenharmony_ci}; 1261