403 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			403 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0 */
 | |
| /*
 | |
|  * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
 | |
|  *
 | |
|  * Author: Zhang Yubing <yubing.zhang@rock-chips.com>
 | |
|  */
 | |
| 
 | |
| #ifndef _RKX110_X120_H
 | |
| #define _RKX110_X120_H
 | |
| 
 | |
| #include <drm/drm_panel.h>
 | |
| #include <drm/drm_bridge.h>
 | |
| #include <drm/drm_connector.h>
 | |
| #include <dt-bindings/mfd/rockchip-serdes.h>
 | |
| #include <linux/i2c.h>
 | |
| #include <video/videomode.h>
 | |
| 
 | |
| #define RK_SERDES_MAX_ROUTE		2
 | |
| #define RK_SERDES_PASSTHROUGH_CNT	11
 | |
| 
 | |
| #define SERDES_VERSION_V0(type)		0x2201
 | |
| #define SERDES_VERSION_V1(type)		(type ? 0x1200001 : 0x1100001)
 | |
| 
 | |
| #define SER_GRF_CHIP_ID			0x10800
 | |
| #define DES_GRF_CHIP_ID			0x1010400
 | |
| #define HIWORD_MASK(h, l)		(GENMASK(h, l) | GENMASK(h, l) << 16)
 | |
| 
 | |
| enum {
 | |
| 	SERDES_V0 = 0,
 | |
| 	SERDES_V1,
 | |
| };
 | |
| 
 | |
| enum {
 | |
| 	LOCAL_MODE = 0,
 | |
| 	REMOTE_MODE,
 | |
| };
 | |
| 
 | |
| enum {
 | |
| 	STREAM_DISPLAY = 0,
 | |
| 	STREAM_CAMERA,
 | |
| };
 | |
| 
 | |
| enum {
 | |
| 	DEVICE_LOCAL = 0,
 | |
| 	DEVICE_REMOTE0,
 | |
| 	DEVICE_REMOTE1,
 | |
| 	DEVICE_MAX,
 | |
| };
 | |
| 
 | |
| enum {
 | |
| 	PORT_REMOTE0,
 | |
| 	PORT_REMOTE1,
 | |
| 	PORT_REMOTE_MAX,
 | |
| };
 | |
| 
 | |
| enum {
 | |
| 	LINK_LANE0,
 | |
| 	LINK_LANE1,
 | |
| 	LINK_LANE_DUAL,
 | |
| };
 | |
| 
 | |
| enum combtx_phy_mode {
 | |
| 	COMBTX_PHY_MODE_GPIO,
 | |
| 	COMBTX_PHY_MODE_VIDEO_LVDS,
 | |
| 	COMBTX_PHY_MODE_VIDEO_MIPI,
 | |
| 	COMBTX_PHY_MODE_VIDEO_MINI_LVDS,
 | |
| };
 | |
| 
 | |
| enum comb_phy_id {
 | |
| 	COMBPHY_0,
 | |
| 	COMBPHY_1,
 | |
| 	COMBPHY_MAX,
 | |
| };
 | |
| 
 | |
| enum combrx_phy_mode {
 | |
| 	COMBRX_PHY_MODE_RGB,
 | |
| 	COMBRX_PHY_MODE_VIDEO_LVDS,
 | |
| 	COMBRX_PHY_MODE_VIDEO_MIPI,
 | |
| 	COMBRX_PHY_MODE_LVDS_CAMERA,
 | |
| };
 | |
| 
 | |
| enum serdes_dsi_mode_flags {
 | |
| 	SERDES_MIPI_DSI_MODE_VIDEO = 1,
 | |
| 	SERDES_MIPI_DSI_MODE_VIDEO_BURST = 2,
 | |
| 	SERDES_MIPI_DSI_MODE_VIDEO_SYNC_PULSE = 4,
 | |
| 	SERDES_MIPI_DSI_MODE_VIDEO_HFP = 8,
 | |
| 	SERDES_MIPI_DSI_MODE_VIDEO_HBP = 16,
 | |
| 	SERDES_MIPI_DSI_MODE_EOT_PACKET = 32,
 | |
| 	SERDES_MIPI_DSI_CLOCK_NON_CONTINUOUS = 64,
 | |
| 	SERDES_MIPI_DSI_MODE_LPM = 128,
 | |
| };
 | |
| 
 | |
| enum serdes_dsi_bus_format {
 | |
| 	SERDES_MIPI_DSI_FMT_RGB888,
 | |
| 	SERDES_MIPI_DSI_FMT_RGB666,
 | |
| 	SERDES_MIPI_DSI_FMT_RGB666_PACKED,
 | |
| 	SERDES_MIPI_DSI_FMT_RGB565,
 | |
| };
 | |
| 
 | |
| enum serdes_frame_mode {
 | |
| 	SERDES_FRAME_NORMAL_MODE,
 | |
| 	SERDES_SP_PIXEL_INTERLEAVED,
 | |
| 	SERDES_SP_LEFT_RIGHT_SPLIT,
 | |
| 	SERDES_SP_LINE_INTERLEAVED,
 | |
| };
 | |
| 
 | |
| struct configure_opts_combphy {
 | |
| 	unsigned int clk_miss;
 | |
| 	unsigned int clk_post;
 | |
| 	unsigned int clk_pre;
 | |
| 	unsigned int clk_prepare;
 | |
| 	unsigned int clk_settle;
 | |
| 	unsigned int clk_term_en;
 | |
| 	unsigned int clk_trail;
 | |
| 	unsigned int clk_zero;
 | |
| 	unsigned int d_term_en;
 | |
| 	unsigned int eot;
 | |
| 	unsigned int hs_exit;
 | |
| 	unsigned int hs_prepare;
 | |
| 	unsigned int hs_settle;
 | |
| 	unsigned int hs_skip;
 | |
| 	unsigned int hs_trail;
 | |
| 	unsigned int hs_zero;
 | |
| 	unsigned int init;
 | |
| 	unsigned int lpx;
 | |
| 	unsigned int ta_get;
 | |
| 	unsigned int ta_go;
 | |
| 	unsigned int ta_sure;
 | |
| 	unsigned int wakeup;
 | |
| 	unsigned long hs_clk_rate;
 | |
| 	unsigned long lp_clk_rate;
 | |
| 	unsigned char lanes;
 | |
| };
 | |
| 
 | |
| struct rkx120_combtxphy {
 | |
| 	enum combtx_phy_mode mode;
 | |
| 	unsigned int flags;
 | |
| 	u8 ref_div;
 | |
| 	u16 fb_div;
 | |
| 	u8 rate_factor;
 | |
| 	u64 rate;
 | |
| 	struct configure_opts_combphy mipi_dphy_cfg;
 | |
| };
 | |
| 
 | |
| struct rkx110_combrxphy {
 | |
| 	enum combrx_phy_mode mode;
 | |
| 	uint8_t lanes;
 | |
| 	u64 rate;
 | |
| 	struct configure_opts_combphy mipi_dphy_cfg;
 | |
| };
 | |
| 
 | |
| struct rkx120_dsi_tx {
 | |
| 	struct rkx120_combtxphy *combtxphy;
 | |
| 
 | |
| 	int bpp; /* 24/18/16*/
 | |
| 	enum serdes_dsi_bus_format bus_format;
 | |
| 	enum serdes_dsi_mode_flags mode_flags;
 | |
| 	struct videomode *vm;
 | |
| 	uint8_t channel;
 | |
| 	uint8_t lanes;
 | |
| };
 | |
| 
 | |
| struct rkx110_dsi_rx {
 | |
| 	enum serdes_dsi_mode_flags mode_flags;
 | |
| 	struct videomode *vm;
 | |
| 	uint8_t channel;
 | |
| 	uint8_t lanes;
 | |
| };
 | |
| 
 | |
| enum {
 | |
| 	OUTPUT,
 | |
| 	INPUT,
 | |
| };
 | |
| 
 | |
| enum rk_serdes_rate {
 | |
| 	RATE_2GBPS_83M,
 | |
| 	RATE_4GBPS_83M,
 | |
| 	RATE_4GBPS_125M,
 | |
| 	RATE_4GBPS_250M,
 | |
| 	RATE_4_5GBPS_140M,
 | |
| 	RATE_4_8GBPS_150M,
 | |
| 	RATE_5GBPS_156M,
 | |
| 	RATE_6GBPS_187M,
 | |
| };
 | |
| 
 | |
| enum {
 | |
| 	FDR_RATE_MODE,
 | |
| 	HDR_RATE_MODE,
 | |
| 	QDR_RATE_MODE,
 | |
| };
 | |
| 
 | |
| enum rk_serdes_route_type {
 | |
| 	ROUTE_MULTI_SOURCE = BIT(0),
 | |
| 	ROUTE_MULTI_LANE = BIT(1),
 | |
| 	ROUTE_MULTI_CHANNEL = BIT(2),
 | |
| 	ROUTE_MULTI_REMOTE = BIT(3),
 | |
| 	ROUTE_MULTI_DSI_INPUT = BIT(20),
 | |
| 	ROUTE_MULTI_LVDS_INPUT = BIT(21),
 | |
| 	ROUTE_MULTI_MIRROR = BIT(22),
 | |
| 	ROUTE_MULTI_SPLIT = BIT(23),
 | |
| };
 | |
| 
 | |
| struct rk_serdes_pma_pll {
 | |
| 	uint32_t rate_mode;
 | |
| 	uint32_t pll_refclk_div;
 | |
| 	uint32_t pll_div;
 | |
| 	uint32_t clk_div;
 | |
| 	bool pll_div4;
 | |
| 	bool pll_fck_vco_div2;
 | |
| 	bool force_init_en;
 | |
| };
 | |
| 
 | |
| struct rk_serdes_reg {
 | |
| 	const char *name;
 | |
| 	uint32_t reg_base;
 | |
| 	uint32_t reg_len;
 | |
| };
 | |
| 
 | |
| struct rk_serdes_route {
 | |
| 	u32 stream_type;
 | |
| 	struct videomode vm;
 | |
| 	enum serdes_frame_mode frame_mode;
 | |
| 	u32 local_port0;
 | |
| 	u32 local_port1;
 | |
| 	u32 remote0_port0;
 | |
| 	u32 remote0_port1;
 | |
| 	u32 remote1_port0;
 | |
| 	u32 remote1_port1;
 | |
| 	u32 route_flag;
 | |
| };
 | |
| 
 | |
| struct rk_serdes_chip {
 | |
| 	bool is_remote;
 | |
| 	struct i2c_client *client;
 | |
| 	struct hwclk *hwclk;
 | |
| 	struct rk_serdes *serdes;
 | |
| };
 | |
| 
 | |
| struct pattern_gen {
 | |
| 	const char *name;
 | |
| 	struct rk_serdes_chip *chip;
 | |
| 	struct rk_serdes_route *route;
 | |
| 	u32 base;
 | |
| 	u32 link_src_reg;
 | |
| 	u8 link_src_offset;
 | |
| 	u8 type;
 | |
| };
 | |
| 
 | |
| struct rk_serdes_pt_pin {
 | |
| 	u32 bank;
 | |
| 	u32 pin;
 | |
| 	u32 incfgs;
 | |
| 	u32 outcfgs;
 | |
| };
 | |
| 
 | |
| struct rk_serdes_pt {
 | |
| 	u32 en_reg;
 | |
| 	u32 en_mask;
 | |
| 	u32 en_val;
 | |
| 	u32 dir_reg;
 | |
| 	u32 dir_mask;
 | |
| 	u32 dir_val;
 | |
| 	int configs;
 | |
| 	struct rk_serdes_pt_pin pt_pins[4];
 | |
| };
 | |
| 
 | |
| struct rk_serdes {
 | |
| 	struct device *dev;
 | |
| 	struct rk_serdes_chip chip[DEVICE_MAX];
 | |
| 	struct regulator *supply;
 | |
| 	struct gpio_desc *reset;
 | |
| 	struct gpio_desc *enable;
 | |
| 	struct gpio_desc *irq_gpio;
 | |
| 
 | |
| 	int irq;
 | |
| 	/*
 | |
| 	 * Control by I2C-Debug
 | |
| 	 */
 | |
| 	bool rkx110_debug;
 | |
| 	bool rkx120_debug;
 | |
| 
 | |
| 	enum rk_serdes_rate rate;
 | |
| 
 | |
| 	struct dentry *debugfs_root;
 | |
| 	struct dentry *debugfs_local;
 | |
| 	struct dentry *debugfs_remote0;
 | |
| 	struct dentry *debugfs_remote1;
 | |
| 	struct dentry *debugfs_rate;
 | |
| 
 | |
| 	struct rk_serdes_route *route[RK_SERDES_MAX_ROUTE];
 | |
| 	u32 stream_type;
 | |
| 	u32 version;
 | |
| 	u8 remote_nr;
 | |
| 	u8 lane_nr;
 | |
| 	u8 channel_nr;
 | |
| 	u8 route_nr;
 | |
| 
 | |
| 	int (*i2c_read_reg)(struct i2c_client *client, u32 addr, u32 *value);
 | |
| 	int (*i2c_write_reg)(struct i2c_client *client, u32 addr, u32 value);
 | |
| 	int (*i2c_update_bits)(struct i2c_client *client, u32 reg, u32 mask, u32 val);
 | |
| 	int (*route_prepare)(struct rk_serdes *serdes, struct rk_serdes_route *route);
 | |
| 	int (*route_enable)(struct rk_serdes *serdes, struct rk_serdes_route *route);
 | |
| 	int (*route_disable)(struct rk_serdes *serdes, struct rk_serdes_route *route);
 | |
| 	int (*route_unprepare)(struct rk_serdes *serdes, struct rk_serdes_route *route);
 | |
| 	int (*set_hwpin)(struct rk_serdes *serdes, struct i2c_client *client,
 | |
| 			 int pintype, int bank, uint32_t mpins, uint32_t param);
 | |
| };
 | |
| 
 | |
| struct cmd_ctrl_hdr {
 | |
| 	u8 dtype;       /* data type */
 | |
| 	u8 wait;        /* ms */
 | |
| 	u8 dlen;        /* payload len */
 | |
| } __packed;
 | |
| 
 | |
| struct cmd_desc {
 | |
| 	struct cmd_ctrl_hdr dchdr;
 | |
| 	u8 *payload;
 | |
| };
 | |
| 
 | |
| struct panel_cmds {
 | |
| 	u8 *buf;
 | |
| 	int blen;
 | |
| 	struct cmd_desc *cmds;
 | |
| 	int cmd_cnt;
 | |
| };
 | |
| 
 | |
| struct rk_serdes_panel;
 | |
| struct rk_serdes_panel {
 | |
| 	struct drm_panel panel;
 | |
| 	struct drm_bridge bridge;
 | |
| 	struct drm_connector connector;
 | |
| 	struct device *dev;
 | |
| 	struct rk_serdes *parent;
 | |
| 	struct rk_serdes_panel *secondary;
 | |
| 
 | |
| 	struct panel_cmds *on_cmds;
 | |
| 	struct panel_cmds *off_cmds;
 | |
| 
 | |
| 	struct regulator *supply;
 | |
| 	struct gpio_desc *enable_gpio;
 | |
| 	struct gpio_desc *reset_gpio;
 | |
| 
 | |
| 	struct rk_serdes_route route;
 | |
| 	struct rkx110_combrxphy combrxphy;
 | |
| 	struct rkx110_dsi_rx dsi_rx;
 | |
| 	struct rkx120_combtxphy combtxphy;
 | |
| 	struct rkx120_dsi_tx dsi_tx;
 | |
| 
 | |
| 	unsigned int bus_format;
 | |
| 	unsigned int id;
 | |
| 	u32 connector_type;
 | |
| 
 | |
| 	bool multi_panel;
 | |
| };
 | |
| 
 | |
| int rkx110_display_linktx_enable(struct rk_serdes *serdes, struct rk_serdes_route *route);
 | |
| void rkx110_linktx_video_enable(struct rk_serdes *serdes, u8 dev_id, bool enable);
 | |
| void rkx110_linktx_channel_enable(struct rk_serdes *serdes, u8 ch_id, u8 dev_id, bool enable);
 | |
| void rkx120_linkrx_engine_enable(struct rk_serdes *serdes, u8 en_id, u8 dev_id, bool enable);
 | |
| void rkx110_set_stream_source(struct rk_serdes *serdes, int local_port, u8 dev_id);
 | |
| int rkx120_display_linkrx_enable(struct rk_serdes *serdes,
 | |
| 				 struct rk_serdes_route *route, u8 remote_id);
 | |
| int rkx120_rgb_tx_enable(struct rk_serdes *serdes, struct rk_serdes_route *route, u8 remote_id);
 | |
| int rkx120_lvds_tx_enable(struct rk_serdes *serdes, struct rk_serdes_route *route, u8 remote_id,
 | |
| 			  u8 phy_id);
 | |
| int rkx120_lvds_tx_disable(struct rk_serdes *serdes, struct rk_serdes_route *route, u8 remote_id,
 | |
| 			   u8 phy_id);
 | |
| void rkx120_linkrx_gpi_gpo_mux_cfg(struct rk_serdes *serdes, u32 mux, u8 remote_id);
 | |
| void rkx110_linktx_gpi_gpo_mux_cfg(struct rk_serdes *serdes, u32 mux, u8 remote_id);
 | |
| int rkx110_rgb_rx_enable(struct rk_serdes *serdes, struct rk_serdes_route *route);
 | |
| int rkx110_lvds_rx_enable(struct rk_serdes *serdes, struct rk_serdes_route *route, int id);
 | |
| void rkx110_debugfs_init(struct rk_serdes_chip *chip, struct dentry *dentry);
 | |
| void rkx120_debugfs_init(struct rk_serdes_chip *chip, struct dentry *dentry);
 | |
| void rkx110_pma_set_rate(struct rk_serdes *serdes, struct rk_serdes_pma_pll *pll,
 | |
| 			 u8 pcs_id, u8 dev_id);
 | |
| void rkx120_pma_set_rate(struct rk_serdes *serdes, struct rk_serdes_pma_pll *pll,
 | |
| 			 u8 pcs_id, u8 dev_id);
 | |
| void rkx110_pcs_enable(struct rk_serdes *serdes, bool enable, u8 pcs_id, u8 dev_id);
 | |
| void rkx120_pcs_enable(struct rk_serdes *serdes, bool enable, u8 pcs_id, u8 dev_id);
 | |
| void rkx110_ser_pma_enable(struct rk_serdes *serdes, bool enable, u8 pma_id, u8 remote_id);
 | |
| void rkx120_des_pma_enable(struct rk_serdes *serdes, bool enable, u8 pma_id, u8 remote_id);
 | |
| int rkx110_linktx_wait_link_ready(struct rk_serdes *serdes, u8 id);
 | |
| int rkx120_linkrx_wait_link_ready(struct rk_serdes *serdes, u8 id);
 | |
| void rkx110_x120_pattern_gen_debugfs_create_file(struct pattern_gen *pattern_gen,
 | |
| 						 struct rk_serdes_chip *chip,
 | |
| 						 struct dentry *dentry);
 | |
| void rkx110_linktx_passthrough_cfg(struct rk_serdes *serdes, u32 client_id, u32 func_id,
 | |
| 				   bool is_rx);
 | |
| void rkx120_linkrx_passthrough_cfg(struct rk_serdes *serdes, u32 client_id, u32 func_id,
 | |
| 				   bool is_rx);
 | |
| void rkx110_irq_enable(struct rk_serdes *serdes, u8 dev_id);
 | |
| void rkx110_irq_disable(struct rk_serdes *serdes, u8 dev_id);
 | |
| int rkx110_irq_handler(struct rk_serdes *serdes, u8 dev_id);
 | |
| void rkx120_irq_enable(struct rk_serdes *serdes, u8 dev_id);
 | |
| void rkx120_irq_disable(struct rk_serdes *serdes, u8 dev_id);
 | |
| int rkx120_irq_handler(struct rk_serdes *serdes, u8 dev_id);
 | |
| 
 | |
| int rkx110_linktx_dsi_rec_start(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id, bool enable);
 | |
| int rkx110_linktx_dsi_type_select(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id, bool is_cmd);
 | |
| int rkx110_linktx_dsi_deley_length_config(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id,
 | |
| 					  u32 length);
 | |
| #endif
 |