xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_dw_hdmi_qp.c (revision 4ae62432f149484c9f1fa685a696f98c19bb2d31)
128671edaSAlgea Cao // SPDX-License-Identifier: GPL-2.0
228671edaSAlgea Cao /*
328671edaSAlgea Cao  * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
428671edaSAlgea Cao  * Author: Algea Cao <algea.cao@rock-chips.com>
528671edaSAlgea Cao  */
628671edaSAlgea Cao 
728671edaSAlgea Cao #include <common.h>
828671edaSAlgea Cao #include <boot_rkimg.h>
98c597bcaSAlgea Cao #include <clk.h>
1028671edaSAlgea Cao #include <fdtdec.h>
1128671edaSAlgea Cao #include <regmap.h>
1228671edaSAlgea Cao #include <syscon.h>
1328671edaSAlgea Cao #include <asm/arch-rockchip/clock.h>
1428671edaSAlgea Cao #include <asm/io.h>
1528671edaSAlgea Cao #include <asm-generic/gpio.h>
1628671edaSAlgea Cao #include <dm/of_access.h>
1728671edaSAlgea Cao #include <dm/device.h>
1828671edaSAlgea Cao #include <linux/dw_hdmi.h>
1928671edaSAlgea Cao #include <linux/hdmi.h>
2028671edaSAlgea Cao #include <linux/media-bus-format.h>
2128671edaSAlgea Cao #include "rockchip_display.h"
2228671edaSAlgea Cao #include "rockchip_crtc.h"
2328671edaSAlgea Cao #include "rockchip_connector.h"
2428671edaSAlgea Cao #include "rockchip_phy.h"
2528671edaSAlgea Cao #include "dw_hdmi_qp.h"
2628671edaSAlgea Cao #include "rockchip_dw_hdmi_qp.h"
2728671edaSAlgea Cao 
2828671edaSAlgea Cao #define HIWORD_UPDATE(val, mask)	((val) | (mask) << 16)
2928671edaSAlgea Cao 
30463abfccSAlgea Cao #define RK3576_IOC_MISC_CON0		0xa400
31463abfccSAlgea Cao #define RK3576_HDMITX_HPD_INT_MSK	BIT(2)
32463abfccSAlgea Cao #define RK3576_HDMITX_HPD_INT_CLR	BIT(1)
33463abfccSAlgea Cao #define RK3576_IOC_HDMITX_HPD_STATUS	0xa440
34463abfccSAlgea Cao #define RK3576_HDMITX_LOW_MORETHAN100MS	BIT(7)
35463abfccSAlgea Cao #define RK3576_HDMITX_HPD_PORT_LEVEL	BIT(6)
36463abfccSAlgea Cao #define RK3576_HDMITX_IHPD_PORT		BIT(5)
37463abfccSAlgea Cao #define RK3576_HDMITX_OHPD_INT		BIT(4)
38463abfccSAlgea Cao #define RK3576_HDMITX_LEVEL_INT		BIT(3)
39463abfccSAlgea Cao #define RK3576_HDMITX_INTR_CHANGE_CNT	0x7
40463abfccSAlgea Cao 
41463abfccSAlgea Cao #define RK3576_VO0_GRF_SOC_CON1		0x0004
42463abfccSAlgea Cao #define RK3576_HDMITX_FRL_MOD		BIT(0)
43463abfccSAlgea Cao #define RK3576_HDMI_HDCP14_MEM_EN	BIT(15)
44463abfccSAlgea Cao 
45463abfccSAlgea Cao #define RK3576_VO0_GRF_SOC_CON8		0x0020
46463abfccSAlgea Cao #define RK3576_COLOR_FORMAT_MASK	(0xf << 4)
47463abfccSAlgea Cao #define RK3576_COLOR_DEPTH_MASK		(0xf << 8)
48463abfccSAlgea Cao #define RK3576_RGB			(0 << 4)
49463abfccSAlgea Cao #define RK3576_YUV422			(0x1 << 4)
50463abfccSAlgea Cao #define RK3576_YUV444			(0x2 << 4)
51463abfccSAlgea Cao #define RK3576_YUV420			(0x3 << 4)
52463abfccSAlgea Cao #define RK3576_8BPC			(0x0 << 8)
53463abfccSAlgea Cao #define RK3576_10BPC			(0x6 << 8)
54463abfccSAlgea Cao #define RK3576_CECIN_MASK		BIT(3)
55463abfccSAlgea Cao 
56463abfccSAlgea Cao #define RK3576_VO0_GRF_SOC_CON12	0x0030
57463abfccSAlgea Cao #define RK3576_GRF_OSDA_DLYN		(0xf << 12)
58463abfccSAlgea Cao #define RK3576_GRF_OSDA_DIV		(0x7f << 1)
59463abfccSAlgea Cao #define RK3576_GRF_OSDA_DLY_EN		BIT(0)
60463abfccSAlgea Cao 
61463abfccSAlgea Cao #define RK3576_VO0_GRF_SOC_CON14	0x0038
62463abfccSAlgea Cao #define RK3576_I2S_SEL_MASK		BIT(0)
63463abfccSAlgea Cao #define RK3576_SPDIF_SEL_MASK		BIT(1)
64463abfccSAlgea Cao #define RK3576_SCLIN_MASK		BIT(4)
65463abfccSAlgea Cao #define RK3576_SDAIN_MASK		BIT(5)
66463abfccSAlgea Cao #define RK3576_HDMITX_GRANT_SEL		BIT(6)
67463abfccSAlgea Cao 
6828671edaSAlgea Cao #define RK3588_GRF_SOC_CON2		0x0308
6928671edaSAlgea Cao #define RK3588_HDMI1_HPD_INT_MSK	BIT(15)
7028671edaSAlgea Cao #define RK3588_HDMI1_HPD_INT_CLR	BIT(14)
7128671edaSAlgea Cao #define RK3588_HDMI0_HPD_INT_MSK	BIT(13)
7228671edaSAlgea Cao #define RK3588_HDMI0_HPD_INT_CLR	BIT(12)
7328671edaSAlgea Cao #define RK3588_GRF_SOC_CON7		0x031c
7428671edaSAlgea Cao #define RK3588_SET_HPD_PATH_MASK	(0x3 << 12)
7528671edaSAlgea Cao #define RK3588_GRF_SOC_STATUS1		0x0384
7628671edaSAlgea Cao #define RK3588_HDMI0_LOW_MORETHAN100MS	BIT(20)
7728671edaSAlgea Cao #define RK3588_HDMI0_HPD_PORT_LEVEL	BIT(19)
7828671edaSAlgea Cao #define RK3588_HDMI0_IHPD_PORT		BIT(18)
7928671edaSAlgea Cao #define RK3588_HDMI0_OHPD_INT		BIT(17)
8028671edaSAlgea Cao #define RK3588_HDMI0_LEVEL_INT		BIT(16)
8128671edaSAlgea Cao #define RK3588_HDMI0_INTR_CHANGE_CNT	(0x7 << 13)
8228671edaSAlgea Cao #define RK3588_HDMI1_LOW_MORETHAN100MS	BIT(28)
8328671edaSAlgea Cao #define RK3588_HDMI1_HPD_PORT_LEVEL	BIT(27)
8428671edaSAlgea Cao #define RK3588_HDMI1_IHPD_PORT		BIT(26)
8528671edaSAlgea Cao #define RK3588_HDMI1_OHPD_INT		BIT(25)
8628671edaSAlgea Cao #define RK3588_HDMI1_LEVEL_INT		BIT(24)
8728671edaSAlgea Cao #define RK3588_HDMI1_INTR_CHANGE_CNT	(0x7 << 21)
8828671edaSAlgea Cao 
8928671edaSAlgea Cao #define RK3588_GRF_VO1_CON3		0x000c
9028671edaSAlgea Cao #define RK3588_COLOR_FORMAT_MASK	0xf
91bc291652SAlgea Cao #define RK3588_YUV422			0x1
9228671edaSAlgea Cao #define RK3588_YUV444			0x2
9328671edaSAlgea Cao #define RK3588_YUV420			0x3
9428671edaSAlgea Cao #define RK3588_COMPRESSED_DATA		0xb
9528671edaSAlgea Cao #define RK3588_COLOR_DEPTH_MASK		(0xf << 4)
96d62f6dc0SAlgea Cao #define RK3588_8BPC			0
9728671edaSAlgea Cao #define RK3588_10BPC			(0x6 << 4)
9828671edaSAlgea Cao #define RK3588_CECIN_MASK		BIT(8)
9928671edaSAlgea Cao #define RK3588_SCLIN_MASK		BIT(9)
10028671edaSAlgea Cao #define RK3588_SDAIN_MASK		BIT(10)
10128671edaSAlgea Cao #define RK3588_MODE_MASK		BIT(11)
10228671edaSAlgea Cao #define RK3588_COMPRESS_MODE_MASK	BIT(12)
10328671edaSAlgea Cao #define RK3588_I2S_SEL_MASK		BIT(13)
10428671edaSAlgea Cao #define RK3588_SPDIF_SEL_MASK		BIT(14)
10528671edaSAlgea Cao #define RK3588_GRF_VO1_CON4		0x0010
10628671edaSAlgea Cao #define RK3588_HDMI21_MASK		BIT(0)
10728671edaSAlgea Cao #define RK3588_GRF_VO1_CON9		0x0024
10828671edaSAlgea Cao #define RK3588_HDMI0_GRANT_SEL		BIT(10)
10928671edaSAlgea Cao #define RK3588_HDMI0_GRANT_SW		BIT(11)
11028671edaSAlgea Cao #define RK3588_HDMI1_GRANT_SEL		BIT(12)
11128671edaSAlgea Cao #define RK3588_HDMI1_GRANT_SW		BIT(13)
11228671edaSAlgea Cao #define RK3588_GRF_VO1_CON6		0x0018
11328671edaSAlgea Cao #define RK3588_GRF_VO1_CON7		0x001c
11428671edaSAlgea Cao 
11528671edaSAlgea Cao #define COLOR_DEPTH_10BIT		BIT(31)
11628671edaSAlgea Cao #define HDMI_FRL_MODE			BIT(30)
11728671edaSAlgea Cao #define HDMI_EARC_MODE			BIT(29)
1188c597bcaSAlgea Cao #define DATA_RATE_MASK			0xFFFFFFF
11928671edaSAlgea Cao 
12028671edaSAlgea Cao #define HDMI20_MAX_RATE			600000
12128671edaSAlgea Cao #define HDMI_8K60_RATE			2376000
12228671edaSAlgea Cao 
12328671edaSAlgea Cao struct pps_data {
12428671edaSAlgea Cao 	u32 pic_width;
12528671edaSAlgea Cao 	u32 pic_height;
12628671edaSAlgea Cao 	u32 slice_width;
12728671edaSAlgea Cao 	u32 slice_height;
12828671edaSAlgea Cao 	bool convert_rgb;
12928671edaSAlgea Cao 	u8 bpc;
13028671edaSAlgea Cao 	u8 bpp;
13128671edaSAlgea Cao 	u8 raw_pps[128];
13228671edaSAlgea Cao };
13328671edaSAlgea Cao 
13428671edaSAlgea Cao enum hdmi_frl_rate_per_lane {
13528671edaSAlgea Cao 	FRL_12G_PER_LANE = 12,
13628671edaSAlgea Cao 	FRL_10G_PER_LANE = 10,
13728671edaSAlgea Cao 	FRL_8G_PER_LANE = 8,
13828671edaSAlgea Cao 	FRL_6G_PER_LANE = 6,
13928671edaSAlgea Cao 	FRL_3G_PER_LANE = 3,
14028671edaSAlgea Cao };
14128671edaSAlgea Cao 
142463abfccSAlgea Cao struct rockchip_hdmi;
143463abfccSAlgea Cao 
144463abfccSAlgea Cao struct rockchip_hdmi_chip_ops {
145463abfccSAlgea Cao 	void (*set_link_mode)(struct rockchip_hdmi *hdmi);
146463abfccSAlgea Cao 	void (*set_color_format)(struct rockchip_hdmi *hdmi, u64 bus_format, u32 depth);
147463abfccSAlgea Cao 	void (*get_grf_color_fmt)(struct rockchip_hdmi *hdmi, u32 *fmt, u32 *depth);
148463abfccSAlgea Cao 	void (*io_path_init)(struct rockchip_hdmi *hdmi);
149463abfccSAlgea Cao 	enum drm_connector_status (*read_hpd)(struct rockchip_hdmi *hdmi);
150463abfccSAlgea Cao };
151463abfccSAlgea Cao 
15228671edaSAlgea Cao struct rockchip_hdmi {
1530594ce39SZhang Yubing 	struct rockchip_connector connector;
15428671edaSAlgea Cao 	int id;
15528671edaSAlgea Cao 	struct udevice *dev;
15628671edaSAlgea Cao 	struct regmap *regmap;
15728671edaSAlgea Cao 	struct regmap *vo1_regmap;
15828671edaSAlgea Cao 	void *grf;
159463abfccSAlgea Cao 	void *vo0_grf;
16028671edaSAlgea Cao 	void *vo1_grf;
16128671edaSAlgea Cao 
16228671edaSAlgea Cao 	unsigned long bus_format;
16328671edaSAlgea Cao 	unsigned long output_bus_format;
16428671edaSAlgea Cao 	unsigned long enc_out_encoding;
16528671edaSAlgea Cao 
16628671edaSAlgea Cao 	u8 max_frl_rate_per_lane;
16728671edaSAlgea Cao 	u8 max_lanes;
1682afea1f0SAlgea Cao 	bool allm_en;
169*4ae62432SAlgea Cao 	bool force_disable_dsc;
17028671edaSAlgea Cao 	u32 bus_width;
171463abfccSAlgea Cao 	u32 sda_falling_delay_ns;
17228671edaSAlgea Cao 	struct drm_hdmi_dsc_cap dsc_cap;
17328671edaSAlgea Cao 	struct dw_hdmi_link_config link_cfg;
17428671edaSAlgea Cao 
1758c597bcaSAlgea Cao 	struct clk link_clk;
1768c597bcaSAlgea Cao 
17728671edaSAlgea Cao 	struct gpio_desc enable_gpio;
178463abfccSAlgea Cao 	const struct dw_hdmi_plat_data *plat_data;
179463abfccSAlgea Cao 	struct rockchip_hdmi_chip_ops *ops;
18028671edaSAlgea Cao };
18128671edaSAlgea Cao 
18228671edaSAlgea Cao /*
18328671edaSAlgea Cao  * Selected Rate Control Related Parameter Recommended Values
18428671edaSAlgea Cao  * from DSC_v1.11 spec & C Model release: DSC_model_20161212
18528671edaSAlgea Cao  */
186*4ae62432SAlgea Cao static struct pps_data pps_datas[] = {
18728671edaSAlgea Cao 	{
18828671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 8bpc 12bpp */
18928671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 8, 192,
19028671edaSAlgea Cao 		{
19128671edaSAlgea Cao 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xc0, 0x10, 0xe0,
19228671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
19328671edaSAlgea Cao 			0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
19428671edaSAlgea Cao 			0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
19528671edaSAlgea Cao 			0x08, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
19628671edaSAlgea Cao 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
19728671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
19828671edaSAlgea Cao 			0x7d, 0x7e, 0x00, 0x82, 0x00, 0xc0, 0x09, 0x00,
19928671edaSAlgea Cao 			0x09, 0x7e, 0x19, 0xbc, 0x19, 0xba, 0x19, 0xf8,
20028671edaSAlgea Cao 			0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
20128671edaSAlgea Cao 			0x2a, 0x76, 0x2a, 0x74, 0x3a, 0xb4, 0x52, 0xf4,
20228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20328671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20428671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20528671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
20728671edaSAlgea Cao 		},
20828671edaSAlgea Cao 	},
20928671edaSAlgea Cao 	{
21028671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 8bpc 11bpp */
21128671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 8, 176,
21228671edaSAlgea Cao 		{
21328671edaSAlgea Cao 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xb0, 0x10, 0xe0,
21428671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
21528671edaSAlgea Cao 			0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
21628671edaSAlgea Cao 			0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
21728671edaSAlgea Cao 			0x0f, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
21828671edaSAlgea Cao 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
21928671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
22028671edaSAlgea Cao 			0x7d, 0x7e, 0x00, 0x82, 0x01, 0x00, 0x09, 0x40,
22128671edaSAlgea Cao 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
22228671edaSAlgea Cao 			0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
22328671edaSAlgea Cao 			0x2a, 0x76, 0x2a, 0xb4, 0x3a, 0xb4, 0x52, 0xf4,
22428671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22528671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22728671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
22928671edaSAlgea Cao 		},
23028671edaSAlgea Cao 	},
23128671edaSAlgea Cao 	{
23228671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 8bpc 10bpp */
23328671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 8, 160,
23428671edaSAlgea Cao 		{
23528671edaSAlgea Cao 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xa0, 0x10, 0xe0,
23628671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
23728671edaSAlgea Cao 			0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
23828671edaSAlgea Cao 			0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
23928671edaSAlgea Cao 			0x16, 0x00, 0x10, 0xec, 0x03, 0x0c, 0x20, 0x00,
24028671edaSAlgea Cao 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
24128671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
24228671edaSAlgea Cao 			0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
24328671edaSAlgea Cao 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
24428671edaSAlgea Cao 			0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
24528671edaSAlgea Cao 			0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x5b, 0x34,
24628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24728671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24928671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25028671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
25128671edaSAlgea Cao 		},
25228671edaSAlgea Cao 	},
25328671edaSAlgea Cao 	{
25428671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 8bpc 9bpp */
25528671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 8, 144,
25628671edaSAlgea Cao 		{
25728671edaSAlgea Cao 			0x12, 0x00, 0x00, 0x8d, 0x30, 0x90, 0x10, 0xe0,
25828671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
25928671edaSAlgea Cao 			0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
26028671edaSAlgea Cao 			0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
26128671edaSAlgea Cao 			0x17, 0x00, 0x10, 0xf1, 0x03, 0x0c, 0x20, 0x00,
26228671edaSAlgea Cao 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
26328671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
26428671edaSAlgea Cao 			0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
26528671edaSAlgea Cao 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
26628671edaSAlgea Cao 			0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
26728671edaSAlgea Cao 			0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x63, 0x74,
26828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26928671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27028671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27128671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
27328671edaSAlgea Cao 		},
27428671edaSAlgea Cao 	},
27528671edaSAlgea Cao 	{
276*4ae62432SAlgea Cao 		/* 7680x4320/960X96 rgb 8bpc 8bpp */
277*4ae62432SAlgea Cao 		7680, 4320, 960, 96, 1, 8, 128,
278*4ae62432SAlgea Cao 		{
279*4ae62432SAlgea Cao 			0x12, 0x00, 0x00, 0x8d, 0x30, 0x80, 0x10, 0xe0,
280*4ae62432SAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x03, 0xc0,
281*4ae62432SAlgea Cao 			0x02, 0x00, 0x03, 0x58, 0x00, 0x20, 0x0a, 0x63,
282*4ae62432SAlgea Cao 			0x00, 0x0d, 0x00, 0x0f, 0x01, 0x44, 0x00, 0x99,
283*4ae62432SAlgea Cao 			0x18, 0x00, 0x10, 0xf0, 0x03, 0x0c, 0x20, 0x00,
284*4ae62432SAlgea Cao 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
285*4ae62432SAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
286*4ae62432SAlgea Cao 			0x7d, 0x7e, 0x01, 0x02, 0x01, 0x00, 0x09, 0x40,
287*4ae62432SAlgea Cao 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
288*4ae62432SAlgea Cao 			0x1a, 0x38, 0x1a, 0x78, 0x22, 0xb6, 0x2a, 0xb6,
289*4ae62432SAlgea Cao 			0x2a, 0xf6, 0x2a, 0xf4, 0x43, 0x34, 0x63, 0x74,
290*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
295*4ae62432SAlgea Cao 		},
296*4ae62432SAlgea Cao 	},
297*4ae62432SAlgea Cao 	{
29828671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 10bpc 12bpp */
29928671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 10, 192,
30028671edaSAlgea Cao 		{
30128671edaSAlgea Cao 			0x12, 0x00, 0x00, 0xad, 0x30, 0xc0, 0x10, 0xe0,
30228671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
30328671edaSAlgea Cao 			0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
30428671edaSAlgea Cao 			0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
30528671edaSAlgea Cao 			0x08, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
30628671edaSAlgea Cao 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
30728671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
30828671edaSAlgea Cao 			0x7d, 0x7e, 0x01, 0x02, 0x11, 0x80, 0x22, 0x00,
30928671edaSAlgea Cao 			0x22, 0x7e, 0x32, 0xbc, 0x32, 0xba, 0x3a, 0xf8,
31028671edaSAlgea Cao 			0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
31128671edaSAlgea Cao 			0x4b, 0x76, 0x4b, 0x74, 0x5b, 0xb4, 0x73, 0xf4,
31228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31328671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31428671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31528671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
31728671edaSAlgea Cao 		},
31828671edaSAlgea Cao 	},
31928671edaSAlgea Cao 	{
32028671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 10bpc 11bpp */
32128671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 10, 176,
32228671edaSAlgea Cao 		{
32328671edaSAlgea Cao 			0x12, 0x00, 0x00, 0xad, 0x30, 0xb0, 0x10, 0xe0,
32428671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
32528671edaSAlgea Cao 			0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
32628671edaSAlgea Cao 			0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
32728671edaSAlgea Cao 			0x0f, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
32828671edaSAlgea Cao 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
32928671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
33028671edaSAlgea Cao 			0x7d, 0x7e, 0x01, 0x42, 0x19, 0xc0, 0x2a, 0x40,
33128671edaSAlgea Cao 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
33228671edaSAlgea Cao 			0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
33328671edaSAlgea Cao 			0x4b, 0x76, 0x4b, 0xb4, 0x5b, 0xb4, 0x73, 0xf4,
33428671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33528671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33728671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
33928671edaSAlgea Cao 		},
34028671edaSAlgea Cao 	},
34128671edaSAlgea Cao 	{
34228671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 10bpc 10bpp */
34328671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 10, 160,
34428671edaSAlgea Cao 		{
34528671edaSAlgea Cao 			0x12, 0x00, 0x00, 0xad, 0x30, 0xa0, 0x10, 0xe0,
34628671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
34728671edaSAlgea Cao 			0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
34828671edaSAlgea Cao 			0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
34928671edaSAlgea Cao 			0x16, 0x00, 0x10, 0xec, 0x07, 0x10, 0x20, 0x00,
35028671edaSAlgea Cao 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
35128671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
35228671edaSAlgea Cao 			0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
35328671edaSAlgea Cao 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
35428671edaSAlgea Cao 			0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
35528671edaSAlgea Cao 			0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x7c, 0x34,
35628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35728671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35928671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36028671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
36128671edaSAlgea Cao 		},
36228671edaSAlgea Cao 	},
36328671edaSAlgea Cao 	{
36428671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 10bpc 9bpp */
36528671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 10, 144,
36628671edaSAlgea Cao 		{
36728671edaSAlgea Cao 			0x12, 0x00, 0x00, 0xad, 0x30, 0x90, 0x10, 0xe0,
36828671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
36928671edaSAlgea Cao 			0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
37028671edaSAlgea Cao 			0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
37128671edaSAlgea Cao 			0x17, 0x00, 0x10, 0xf1, 0x07, 0x10, 0x20, 0x00,
37228671edaSAlgea Cao 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
37328671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
37428671edaSAlgea Cao 			0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
37528671edaSAlgea Cao 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
37628671edaSAlgea Cao 			0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
37728671edaSAlgea Cao 			0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x84, 0x74,
37828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37928671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38028671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38128671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
38328671edaSAlgea Cao 		},
38428671edaSAlgea Cao 	},
385*4ae62432SAlgea Cao 	{
386*4ae62432SAlgea Cao 		/* 7680x4320/960X96 rgb 10bpc 8bpp */
387*4ae62432SAlgea Cao 		7680, 4320, 960, 96, 1, 10, 128,
388*4ae62432SAlgea Cao 		{
389*4ae62432SAlgea Cao 			0x12, 0x00, 0x00, 0xad, 0x30, 0x80, 0x10, 0xe0,
390*4ae62432SAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x03, 0xc0,
391*4ae62432SAlgea Cao 			0x02, 0x00, 0x03, 0x58, 0x00, 0x20, 0x0a, 0x63,
392*4ae62432SAlgea Cao 			0x00, 0x0d, 0x00, 0x0f, 0x01, 0x44, 0x00, 0x99,
393*4ae62432SAlgea Cao 			0x18, 0x00, 0x10, 0xf0, 0x07, 0x10, 0x20, 0x00,
394*4ae62432SAlgea Cao 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
395*4ae62432SAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
396*4ae62432SAlgea Cao 			0x7d, 0x7e, 0x02, 0x02, 0x22, 0x00, 0x2a, 0x40,
397*4ae62432SAlgea Cao 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
398*4ae62432SAlgea Cao 			0x3b, 0x38, 0x3b, 0x78, 0x43, 0xb6, 0x4b, 0xb6,
399*4ae62432SAlgea Cao 			0x4b, 0xf6, 0x4b, 0xf4, 0x64, 0x34, 0x84, 0x74,
400*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404*4ae62432SAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
405*4ae62432SAlgea Cao 		},
406*4ae62432SAlgea Cao 	},
40728671edaSAlgea Cao };
40828671edaSAlgea Cao 
hdmi_bus_fmt_is_rgb(unsigned int bus_format)40928671edaSAlgea Cao static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
41028671edaSAlgea Cao {
41128671edaSAlgea Cao 	switch (bus_format) {
41228671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB888_1X24:
41328671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB101010_1X30:
41428671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB121212_1X36:
41528671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB161616_1X48:
41628671edaSAlgea Cao 		return true;
41728671edaSAlgea Cao 
41828671edaSAlgea Cao 	default:
41928671edaSAlgea Cao 		return false;
42028671edaSAlgea Cao 	}
42128671edaSAlgea Cao }
42228671edaSAlgea Cao 
hdmi_bus_fmt_is_yuv444(unsigned int bus_format)42328671edaSAlgea Cao static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
42428671edaSAlgea Cao {
42528671edaSAlgea Cao 	switch (bus_format) {
42628671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV8_1X24:
42728671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV10_1X30:
42828671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV12_1X36:
42928671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV16_1X48:
43028671edaSAlgea Cao 		return true;
43128671edaSAlgea Cao 
43228671edaSAlgea Cao 	default:
43328671edaSAlgea Cao 		return false;
43428671edaSAlgea Cao 	}
43528671edaSAlgea Cao }
43628671edaSAlgea Cao 
hdmi_bus_fmt_is_yuv422(unsigned int bus_format)43728671edaSAlgea Cao static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
43828671edaSAlgea Cao {
43928671edaSAlgea Cao 	switch (bus_format) {
44028671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY8_1X16:
44128671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY10_1X20:
44228671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY12_1X24:
443bc291652SAlgea Cao 	case MEDIA_BUS_FMT_YUYV8_1X16:
444bc291652SAlgea Cao 	case MEDIA_BUS_FMT_YUYV10_1X20:
445bc291652SAlgea Cao 	case MEDIA_BUS_FMT_YUYV12_1X24:
44628671edaSAlgea Cao 		return true;
44728671edaSAlgea Cao 
44828671edaSAlgea Cao 	default:
44928671edaSAlgea Cao 		return false;
45028671edaSAlgea Cao 	}
45128671edaSAlgea Cao }
45228671edaSAlgea Cao 
hdmi_bus_fmt_is_yuv420(unsigned int bus_format)45328671edaSAlgea Cao static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
45428671edaSAlgea Cao {
45528671edaSAlgea Cao 	switch (bus_format) {
45628671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
45728671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
45828671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
45928671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
46028671edaSAlgea Cao 		return true;
46128671edaSAlgea Cao 
46228671edaSAlgea Cao 	default:
46328671edaSAlgea Cao 	return false;
46428671edaSAlgea Cao 	}
46528671edaSAlgea Cao }
46628671edaSAlgea Cao 
hdmi_bus_fmt_color_depth(unsigned int bus_format)46728671edaSAlgea Cao static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
46828671edaSAlgea Cao {
46928671edaSAlgea Cao 	switch (bus_format) {
47028671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB888_1X24:
47128671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV8_1X24:
47228671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY8_1X16:
473bc291652SAlgea Cao 	case MEDIA_BUS_FMT_YUYV8_1X16:
47428671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
47528671edaSAlgea Cao 		return 8;
47628671edaSAlgea Cao 
47728671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB101010_1X30:
47828671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV10_1X30:
47928671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY10_1X20:
480bc291652SAlgea Cao 	case MEDIA_BUS_FMT_YUYV10_1X20:
48128671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
48228671edaSAlgea Cao 		return 10;
48328671edaSAlgea Cao 
48428671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB121212_1X36:
48528671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV12_1X36:
48628671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY12_1X24:
487bc291652SAlgea Cao 	case MEDIA_BUS_FMT_YUYV12_1X24:
48828671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
48928671edaSAlgea Cao 		return 12;
49028671edaSAlgea Cao 
49128671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB161616_1X48:
49228671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV16_1X48:
49328671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
49428671edaSAlgea Cao 		return 16;
49528671edaSAlgea Cao 
49628671edaSAlgea Cao 	default:
49728671edaSAlgea Cao 		return 0;
49828671edaSAlgea Cao 	}
49928671edaSAlgea Cao }
50028671edaSAlgea Cao 
50128671edaSAlgea Cao static unsigned int
hdmi_get_tmdsclock(struct rockchip_hdmi * hdmi,unsigned long pixelclock)50228671edaSAlgea Cao hdmi_get_tmdsclock(struct rockchip_hdmi *hdmi, unsigned long pixelclock)
50328671edaSAlgea Cao {
50428671edaSAlgea Cao 	unsigned int tmdsclock = pixelclock;
50528671edaSAlgea Cao 	unsigned int depth =
50628671edaSAlgea Cao 		hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
50728671edaSAlgea Cao 
50828671edaSAlgea Cao 	if (!hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format)) {
50928671edaSAlgea Cao 		switch (depth) {
51028671edaSAlgea Cao 		case 16:
51128671edaSAlgea Cao 			tmdsclock = pixelclock * 2;
51228671edaSAlgea Cao 			break;
51328671edaSAlgea Cao 		case 12:
51428671edaSAlgea Cao 			tmdsclock = pixelclock * 3 / 2;
51528671edaSAlgea Cao 			break;
51628671edaSAlgea Cao 		case 10:
51728671edaSAlgea Cao 			tmdsclock = pixelclock * 5 / 4;
51828671edaSAlgea Cao 			break;
51928671edaSAlgea Cao 		default:
52028671edaSAlgea Cao 			break;
52128671edaSAlgea Cao 		}
52228671edaSAlgea Cao 	}
52328671edaSAlgea Cao 
52428671edaSAlgea Cao 	return tmdsclock;
52528671edaSAlgea Cao }
52628671edaSAlgea Cao 
527*4ae62432SAlgea Cao static bool
rockchip_hdmi_if_dsc_enable(struct rockchip_hdmi * hdmi,unsigned int tmdsclk)528*4ae62432SAlgea Cao rockchip_hdmi_if_dsc_enable(struct rockchip_hdmi *hdmi, unsigned int tmdsclk)
529*4ae62432SAlgea Cao {
530*4ae62432SAlgea Cao 	u64 data_rate;
531*4ae62432SAlgea Cao 	u64 frl_rate = (u64)hdmi->link_cfg.frl_lanes *
532*4ae62432SAlgea Cao 		hdmi->link_cfg.rate_per_lane * 1000000;
533*4ae62432SAlgea Cao 	u8 bpp = hdmi_bus_fmt_color_depth(hdmi->bus_format) * 3;
534*4ae62432SAlgea Cao 
535*4ae62432SAlgea Cao 	/* rk3588 dsc can't support yuv420/422 dsc */
536*4ae62432SAlgea Cao 	if (hdmi_bus_fmt_is_yuv420(hdmi->bus_format) ||
537*4ae62432SAlgea Cao 	    hdmi_bus_fmt_is_yuv422(hdmi->bus_format))
538*4ae62432SAlgea Cao 		return false;
539*4ae62432SAlgea Cao 
540*4ae62432SAlgea Cao 	data_rate = (u64)tmdsclk * bpp;
541*4ae62432SAlgea Cao 	data_rate = DIV_ROUND_UP_ULL(data_rate * 18, 16);
542*4ae62432SAlgea Cao 
543*4ae62432SAlgea Cao 	if (data_rate > frl_rate)
544*4ae62432SAlgea Cao 		return true;
545*4ae62432SAlgea Cao 
546*4ae62432SAlgea Cao 	return false;
547*4ae62432SAlgea Cao }
548*4ae62432SAlgea Cao 
hdmi_select_link_config(struct rockchip_hdmi * hdmi,struct drm_display_mode * mode,unsigned int tmdsclk)54928671edaSAlgea Cao static void hdmi_select_link_config(struct rockchip_hdmi *hdmi,
55028671edaSAlgea Cao 				    struct drm_display_mode *mode,
55128671edaSAlgea Cao 				    unsigned int tmdsclk)
55228671edaSAlgea Cao {
55328671edaSAlgea Cao 	int max_lanes, max_rate_per_lane;
55428671edaSAlgea Cao 	int max_dsc_lanes, max_dsc_rate_per_lane;
55528671edaSAlgea Cao 	unsigned long max_frl_rate;
55628671edaSAlgea Cao 
55728671edaSAlgea Cao 	max_lanes = hdmi->max_lanes;
55828671edaSAlgea Cao 	max_rate_per_lane = hdmi->max_frl_rate_per_lane;
55928671edaSAlgea Cao 	max_frl_rate = max_lanes * max_rate_per_lane * 1000000;
56028671edaSAlgea Cao 
56128671edaSAlgea Cao 	hdmi->link_cfg.dsc_mode = false;
56228671edaSAlgea Cao 	hdmi->link_cfg.frl_lanes = max_lanes;
56328671edaSAlgea Cao 	hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
5642afea1f0SAlgea Cao 	hdmi->link_cfg.allm_en = hdmi->allm_en;
56528671edaSAlgea Cao 
566daae102bSAlgea Cao 	if (!max_frl_rate ||
567daae102bSAlgea Cao 	    (tmdsclk < HDMI20_MAX_RATE && mode->clock < HDMI20_MAX_RATE)) {
56828671edaSAlgea Cao 		printf("%s use tmds mode\n", __func__);
56928671edaSAlgea Cao 		hdmi->link_cfg.frl_mode = false;
57028671edaSAlgea Cao 		return;
57128671edaSAlgea Cao 	}
57228671edaSAlgea Cao 
57328671edaSAlgea Cao 	hdmi->link_cfg.frl_mode = true;
57428671edaSAlgea Cao 
57528671edaSAlgea Cao 	if (!hdmi->dsc_cap.v_1p2)
57628671edaSAlgea Cao 		return;
57728671edaSAlgea Cao 
57828671edaSAlgea Cao 	max_dsc_lanes = hdmi->dsc_cap.max_lanes;
57928671edaSAlgea Cao 	max_dsc_rate_per_lane =
58028671edaSAlgea Cao 		hdmi->dsc_cap.max_frl_rate_per_lane;
58128671edaSAlgea Cao 
582*4ae62432SAlgea Cao 	if (rockchip_hdmi_if_dsc_enable(hdmi, tmdsclk)) {
58328671edaSAlgea Cao 		hdmi->link_cfg.dsc_mode = true;
58428671edaSAlgea Cao 		hdmi->link_cfg.frl_lanes = max_dsc_lanes;
58528671edaSAlgea Cao 		hdmi->link_cfg.rate_per_lane = max_dsc_rate_per_lane;
58628671edaSAlgea Cao 	} else {
58728671edaSAlgea Cao 		hdmi->link_cfg.dsc_mode = false;
58828671edaSAlgea Cao 		hdmi->link_cfg.frl_lanes = max_lanes;
58928671edaSAlgea Cao 		hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
59028671edaSAlgea Cao 	}
59128671edaSAlgea Cao }
59228671edaSAlgea Cao 
59328671edaSAlgea Cao /////////////////////////////////////////////////////////////////////////////////////
59428671edaSAlgea Cao 
hdmi_dsc_get_slice_height(int vactive)59528671edaSAlgea Cao static int hdmi_dsc_get_slice_height(int vactive)
59628671edaSAlgea Cao {
59728671edaSAlgea Cao 	int slice_height;
59828671edaSAlgea Cao 
59928671edaSAlgea Cao 	/*
60028671edaSAlgea Cao 	 * Slice Height determination : HDMI2.1 Section 7.7.5.2
60128671edaSAlgea Cao 	 * Select smallest slice height >=96, that results in a valid PPS and
60228671edaSAlgea Cao 	 * requires minimum padding lines required for final slice.
60328671edaSAlgea Cao 	 *
60428671edaSAlgea Cao 	 * Assumption : Vactive is even.
60528671edaSAlgea Cao 	 */
60628671edaSAlgea Cao 	for (slice_height = 96; slice_height <= vactive; slice_height += 2)
60728671edaSAlgea Cao 		if (vactive % slice_height == 0)
60828671edaSAlgea Cao 			return slice_height;
60928671edaSAlgea Cao 
61028671edaSAlgea Cao 	return 0;
61128671edaSAlgea Cao }
61228671edaSAlgea Cao 
hdmi_dsc_get_num_slices(struct rockchip_hdmi * hdmi,struct drm_display_mode * mode,int src_max_slices,int src_max_slice_width,int hdmi_max_slices,int hdmi_throughput)61328671edaSAlgea Cao static int hdmi_dsc_get_num_slices(struct rockchip_hdmi *hdmi,
61428671edaSAlgea Cao 				   struct drm_display_mode *mode,
61528671edaSAlgea Cao 				   int src_max_slices, int src_max_slice_width,
61628671edaSAlgea Cao 				   int hdmi_max_slices, int hdmi_throughput)
61728671edaSAlgea Cao {
61828671edaSAlgea Cao /* Pixel rates in KPixels/sec */
61928671edaSAlgea Cao #define HDMI_DSC_PEAK_PIXEL_RATE		2720000
62028671edaSAlgea Cao /*
62128671edaSAlgea Cao  * Rates at which the source and sink are required to process pixels in each
62228671edaSAlgea Cao  * slice, can be two levels: either at least 340000KHz or at least 40000KHz.
62328671edaSAlgea Cao  */
62428671edaSAlgea Cao #define HDMI_DSC_MAX_ENC_THROUGHPUT_0		340000
62528671edaSAlgea Cao #define HDMI_DSC_MAX_ENC_THROUGHPUT_1		400000
62628671edaSAlgea Cao 
62728671edaSAlgea Cao /* Spec limits the slice width to 2720 pixels */
62828671edaSAlgea Cao #define MAX_HDMI_SLICE_WIDTH			2720
62928671edaSAlgea Cao 	int kslice_adjust;
63028671edaSAlgea Cao 	int adjusted_clk_khz;
63128671edaSAlgea Cao 	int min_slices;
63228671edaSAlgea Cao 	int target_slices;
63328671edaSAlgea Cao 	int max_throughput; /* max clock freq. in khz per slice */
63428671edaSAlgea Cao 	int max_slice_width;
63528671edaSAlgea Cao 	int slice_width;
63628671edaSAlgea Cao 	int pixel_clock = mode->clock;
63728671edaSAlgea Cao 
63828671edaSAlgea Cao 	if (!hdmi_throughput)
63928671edaSAlgea Cao 		return 0;
64028671edaSAlgea Cao 
64128671edaSAlgea Cao 	/*
64228671edaSAlgea Cao 	 * Slice Width determination : HDMI2.1 Section 7.7.5.1
64328671edaSAlgea Cao 	 * kslice_adjust factor for 4:2:0, and 4:2:2 formats is 0.5, where as
64428671edaSAlgea Cao 	 * for 4:4:4 is 1.0. Multiplying these factors by 10 and later
64528671edaSAlgea Cao 	 * dividing adjusted clock value by 10.
64628671edaSAlgea Cao 	 */
64728671edaSAlgea Cao 	if (hdmi_bus_fmt_is_yuv444(hdmi->output_bus_format) ||
64828671edaSAlgea Cao 	    hdmi_bus_fmt_is_rgb(hdmi->output_bus_format))
64928671edaSAlgea Cao 		kslice_adjust = 10;
65028671edaSAlgea Cao 	else
65128671edaSAlgea Cao 		kslice_adjust = 5;
65228671edaSAlgea Cao 
65328671edaSAlgea Cao 	/*
65428671edaSAlgea Cao 	 * As per spec, the rate at which the source and the sink process
65528671edaSAlgea Cao 	 * the pixels per slice are at two levels: at least 340Mhz or 400Mhz.
65628671edaSAlgea Cao 	 * This depends upon the pixel clock rate and output formats
65728671edaSAlgea Cao 	 * (kslice adjust).
65828671edaSAlgea Cao 	 * If pixel clock * kslice adjust >= 2720MHz slices can be processed
65928671edaSAlgea Cao 	 * at max 340MHz, otherwise they can be processed at max 400MHz.
66028671edaSAlgea Cao 	 */
66128671edaSAlgea Cao 
66228671edaSAlgea Cao 	adjusted_clk_khz = DIV_ROUND_UP(kslice_adjust * pixel_clock, 10);
66328671edaSAlgea Cao 
66428671edaSAlgea Cao 	if (adjusted_clk_khz <= HDMI_DSC_PEAK_PIXEL_RATE)
66528671edaSAlgea Cao 		max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_0;
66628671edaSAlgea Cao 	else
66728671edaSAlgea Cao 		max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_1;
66828671edaSAlgea Cao 
66928671edaSAlgea Cao 	/*
67028671edaSAlgea Cao 	 * Taking into account the sink's capability for maximum
67128671edaSAlgea Cao 	 * clock per slice (in MHz) as read from HF-VSDB.
67228671edaSAlgea Cao 	 */
67328671edaSAlgea Cao 	max_throughput = min(max_throughput, hdmi_throughput * 1000);
67428671edaSAlgea Cao 
67528671edaSAlgea Cao 	min_slices = DIV_ROUND_UP(adjusted_clk_khz, max_throughput);
67628671edaSAlgea Cao 	max_slice_width = min(MAX_HDMI_SLICE_WIDTH, src_max_slice_width);
67728671edaSAlgea Cao 
67828671edaSAlgea Cao 	/*
67928671edaSAlgea Cao 	 * Keep on increasing the num of slices/line, starting from min_slices
68028671edaSAlgea Cao 	 * per line till we get such a number, for which the slice_width is
68128671edaSAlgea Cao 	 * just less than max_slice_width. The slices/line selected should be
68228671edaSAlgea Cao 	 * less than or equal to the max horizontal slices that the combination
68328671edaSAlgea Cao 	 * of PCON encoder and HDMI decoder can support.
68428671edaSAlgea Cao 	 */
68528671edaSAlgea Cao 	do {
68628671edaSAlgea Cao 		if (min_slices <= 1 && src_max_slices >= 1 && hdmi_max_slices >= 1)
68728671edaSAlgea Cao 			target_slices = 1;
68828671edaSAlgea Cao 		else if (min_slices <= 2 && src_max_slices >= 2 && hdmi_max_slices >= 2)
68928671edaSAlgea Cao 			target_slices = 2;
69028671edaSAlgea Cao 		else if (min_slices <= 4 && src_max_slices >= 4 && hdmi_max_slices >= 4)
69128671edaSAlgea Cao 			target_slices = 4;
69228671edaSAlgea Cao 		else if (min_slices <= 8 && src_max_slices >= 8 && hdmi_max_slices >= 8)
69328671edaSAlgea Cao 			target_slices = 8;
69428671edaSAlgea Cao 		else if (min_slices <= 12 && src_max_slices >= 12 && hdmi_max_slices >= 12)
69528671edaSAlgea Cao 			target_slices = 12;
69628671edaSAlgea Cao 		else if (min_slices <= 16 && src_max_slices >= 16 && hdmi_max_slices >= 16)
69728671edaSAlgea Cao 			target_slices = 16;
69828671edaSAlgea Cao 		else
69928671edaSAlgea Cao 			return 0;
70028671edaSAlgea Cao 
70128671edaSAlgea Cao 		slice_width = DIV_ROUND_UP(mode->hdisplay, target_slices);
70228671edaSAlgea Cao 		if (slice_width > max_slice_width)
70328671edaSAlgea Cao 			min_slices = target_slices + 1;
70428671edaSAlgea Cao 	} while (slice_width > max_slice_width);
70528671edaSAlgea Cao 
70628671edaSAlgea Cao 	return target_slices;
70728671edaSAlgea Cao }
70828671edaSAlgea Cao 
hdmi_dsc_slices(struct rockchip_hdmi * hdmi,struct drm_display_mode * mode)70928671edaSAlgea Cao static int hdmi_dsc_slices(struct rockchip_hdmi *hdmi,
71028671edaSAlgea Cao 			   struct drm_display_mode *mode)
71128671edaSAlgea Cao {
71228671edaSAlgea Cao 	int hdmi_throughput = hdmi->dsc_cap.clk_per_slice;
71328671edaSAlgea Cao 	int hdmi_max_slices = hdmi->dsc_cap.max_slices;
71428671edaSAlgea Cao 	int rk_max_slices = 8;
71528671edaSAlgea Cao 	int rk_max_slice_width = 2048;
71628671edaSAlgea Cao 
71728671edaSAlgea Cao 	return hdmi_dsc_get_num_slices(hdmi, mode, rk_max_slices,
71828671edaSAlgea Cao 				       rk_max_slice_width,
71928671edaSAlgea Cao 				       hdmi_max_slices, hdmi_throughput);
72028671edaSAlgea Cao }
72128671edaSAlgea Cao 
72228671edaSAlgea Cao static int
hdmi_dsc_get_bpp(struct rockchip_hdmi * hdmi,int src_fractional_bpp,int slice_width,int num_slices,bool hdmi_all_bpp,int hdmi_max_chunk_bytes,u64 pixel_clk)72328671edaSAlgea Cao hdmi_dsc_get_bpp(struct rockchip_hdmi *hdmi, int src_fractional_bpp,
72428671edaSAlgea Cao 		 int slice_width, int num_slices, bool hdmi_all_bpp,
725*4ae62432SAlgea Cao 		 int hdmi_max_chunk_bytes, u64 pixel_clk)
72628671edaSAlgea Cao {
72728671edaSAlgea Cao 	int max_dsc_bpp, min_dsc_bpp;
72828671edaSAlgea Cao 	int target_bytes;
72928671edaSAlgea Cao 	bool bpp_found = false;
73028671edaSAlgea Cao 	int bpp_decrement_x16;
73128671edaSAlgea Cao 	int bpp_target;
73228671edaSAlgea Cao 	int bpp_target_x16;
733*4ae62432SAlgea Cao 	u64 frl_rate, dsc_rate, original_rate;
734*4ae62432SAlgea Cao 	u8 original_bpp = hdmi_bus_fmt_color_depth(hdmi->output_bus_format) * 3;
73528671edaSAlgea Cao 
736*4ae62432SAlgea Cao 	if (!original_bpp) {
737*4ae62432SAlgea Cao 		dev_err(hdmi->dev, "can't get original_bpp\n");
738*4ae62432SAlgea Cao 		return 0;
739*4ae62432SAlgea Cao 	}
74028671edaSAlgea Cao 	/*
74128671edaSAlgea Cao 	 * Get min bpp and max bpp as per Table 7.23, in HDMI2.1 spec
74228671edaSAlgea Cao 	 * Start with the max bpp and keep on decrementing with
74328671edaSAlgea Cao 	 * fractional bpp, if supported by PCON DSC encoder
74428671edaSAlgea Cao 	 *
74528671edaSAlgea Cao 	 * for each bpp we check if no of bytes can be supported by HDMI sink
74628671edaSAlgea Cao 	 */
74728671edaSAlgea Cao 
74828671edaSAlgea Cao 	/* only 9\10\12 bpp was tested */
749*4ae62432SAlgea Cao 	min_dsc_bpp = 8;
75028671edaSAlgea Cao 	max_dsc_bpp = 12;
75128671edaSAlgea Cao 
75228671edaSAlgea Cao 	/*
75328671edaSAlgea Cao 	 * Taking into account if all dsc_all_bpp supported by HDMI2.1 sink
75428671edaSAlgea Cao 	 * Section 7.7.34 : Source shall not enable compressed Video
75528671edaSAlgea Cao 	 * Transport with bpp_target settings above 12 bpp unless
75628671edaSAlgea Cao 	 * DSC_all_bpp is set to 1.
75728671edaSAlgea Cao 	 */
75828671edaSAlgea Cao 	if (!hdmi_all_bpp)
75928671edaSAlgea Cao 		max_dsc_bpp = min(max_dsc_bpp, 12);
76028671edaSAlgea Cao 
76128671edaSAlgea Cao 	/*
76228671edaSAlgea Cao 	 * The Sink has a limit of compressed data in bytes for a scanline,
76328671edaSAlgea Cao 	 * as described in max_chunk_bytes field in HFVSDB block of edid.
76428671edaSAlgea Cao 	 * The no. of bytes depend on the target bits per pixel that the
76528671edaSAlgea Cao 	 * source configures. So we start with the max_bpp and calculate
76628671edaSAlgea Cao 	 * the target_chunk_bytes. We keep on decrementing the target_bpp,
76728671edaSAlgea Cao 	 * till we get the target_chunk_bytes just less than what the sink's
76828671edaSAlgea Cao 	 * max_chunk_bytes, or else till we reach the min_dsc_bpp.
76928671edaSAlgea Cao 	 *
77028671edaSAlgea Cao 	 * The decrement is according to the fractional support from PCON DSC
77128671edaSAlgea Cao 	 * encoder. For fractional BPP we use bpp_target as a multiple of 16.
77228671edaSAlgea Cao 	 *
77328671edaSAlgea Cao 	 * bpp_target_x16 = bpp_target * 16
77428671edaSAlgea Cao 	 * So we need to decrement by {1, 2, 4, 8, 16} for fractional bpps
77528671edaSAlgea Cao 	 * {1/16, 1/8, 1/4, 1/2, 1} respectively.
77628671edaSAlgea Cao 	 */
777*4ae62432SAlgea Cao 	frl_rate = (u64)hdmi->link_cfg.frl_lanes *
778*4ae62432SAlgea Cao 		hdmi->link_cfg.rate_per_lane * 1000000;
77928671edaSAlgea Cao 	bpp_target = max_dsc_bpp;
78028671edaSAlgea Cao 
781*4ae62432SAlgea Cao 	/* hdmi frl mode is 16b18b encoded */
782*4ae62432SAlgea Cao 	original_rate = DIV_ROUND_UP_ULL(pixel_clk * original_bpp * 18, 16);
783*4ae62432SAlgea Cao 
78428671edaSAlgea Cao 	/* src does not support fractional bpp implies decrement by 16 for bppx16 */
78528671edaSAlgea Cao 	if (!src_fractional_bpp)
78628671edaSAlgea Cao 		src_fractional_bpp = 1;
78728671edaSAlgea Cao 	bpp_decrement_x16 = DIV_ROUND_UP(16, src_fractional_bpp);
78828671edaSAlgea Cao 	bpp_target_x16 = bpp_target * 16;
78928671edaSAlgea Cao 
790*4ae62432SAlgea Cao 	while (bpp_target_x16 >= (min_dsc_bpp * 16)) {
79128671edaSAlgea Cao 		int bpp;
79228671edaSAlgea Cao 
79328671edaSAlgea Cao 		bpp = DIV_ROUND_UP(bpp_target_x16, 16);
794*4ae62432SAlgea Cao 		target_bytes =
795*4ae62432SAlgea Cao 			DIV_ROUND_UP((num_slices * slice_width * bpp), 8);
796*4ae62432SAlgea Cao 		dsc_rate = DIV_ROUND_UP_ULL(original_rate * bpp_target_x16,
797*4ae62432SAlgea Cao 					    original_bpp * 16);
798*4ae62432SAlgea Cao 
799*4ae62432SAlgea Cao 		if (target_bytes <= hdmi_max_chunk_bytes &&
800*4ae62432SAlgea Cao 		    dsc_rate <= frl_rate) {
80128671edaSAlgea Cao 			bpp_found = true;
80228671edaSAlgea Cao 			break;
80328671edaSAlgea Cao 		}
80428671edaSAlgea Cao 		bpp_target_x16 -= bpp_decrement_x16;
80528671edaSAlgea Cao 	}
80628671edaSAlgea Cao 	if (bpp_found)
80728671edaSAlgea Cao 		return bpp_target_x16;
80828671edaSAlgea Cao 
80928671edaSAlgea Cao 	return 0;
81028671edaSAlgea Cao }
81128671edaSAlgea Cao 
81228671edaSAlgea Cao static int
dw_hdmi_dsc_bpp(struct rockchip_hdmi * hdmi,int num_slices,int slice_width,u64 pixel_clk)81328671edaSAlgea Cao dw_hdmi_dsc_bpp(struct rockchip_hdmi *hdmi,
814*4ae62432SAlgea Cao 		int num_slices, int slice_width, u64 pixel_clk)
81528671edaSAlgea Cao {
81628671edaSAlgea Cao 	bool hdmi_all_bpp = hdmi->dsc_cap.all_bpp;
81728671edaSAlgea Cao 	int fractional_bpp = 0;
81828671edaSAlgea Cao 	int hdmi_max_chunk_bytes = hdmi->dsc_cap.total_chunk_kbytes * 1024;
81928671edaSAlgea Cao 
82028671edaSAlgea Cao 	return hdmi_dsc_get_bpp(hdmi, fractional_bpp, slice_width,
82128671edaSAlgea Cao 				num_slices, hdmi_all_bpp,
822*4ae62432SAlgea Cao 				hdmi_max_chunk_bytes, pixel_clk);
82328671edaSAlgea Cao }
82428671edaSAlgea Cao 
dw_hdmi_qp_set_link_cfg(struct rockchip_hdmi * hdmi,u16 pic_width,u16 pic_height,u16 slice_width,u16 slice_height,u16 bits_per_pixel,u8 bits_per_component)82528671edaSAlgea Cao static int dw_hdmi_qp_set_link_cfg(struct rockchip_hdmi *hdmi,
82628671edaSAlgea Cao 				   u16 pic_width, u16 pic_height,
82728671edaSAlgea Cao 				   u16 slice_width, u16 slice_height,
82828671edaSAlgea Cao 				   u16 bits_per_pixel, u8 bits_per_component)
82928671edaSAlgea Cao {
83028671edaSAlgea Cao 	int i;
83128671edaSAlgea Cao 
832*4ae62432SAlgea Cao 	for (i = 0; i < ARRAY_SIZE(pps_datas); i++)
83328671edaSAlgea Cao 		if (pic_width == pps_datas[i].pic_width &&
83428671edaSAlgea Cao 		    pic_height == pps_datas[i].pic_height &&
83528671edaSAlgea Cao 		    slice_width == pps_datas[i].slice_width &&
83628671edaSAlgea Cao 		    slice_height == pps_datas[i].slice_height &&
83728671edaSAlgea Cao 		    bits_per_component == pps_datas[i].bpc &&
838*4ae62432SAlgea Cao 		    bits_per_pixel == pps_datas[i].bpp)
83928671edaSAlgea Cao 			break;
84028671edaSAlgea Cao 
841*4ae62432SAlgea Cao 	if (i == ARRAY_SIZE(pps_datas)) {
84228671edaSAlgea Cao 		dev_err(hdmi->dev, "can't find pps cfg!\n");
84328671edaSAlgea Cao 		return -EINVAL;
84428671edaSAlgea Cao 	}
84528671edaSAlgea Cao 
84628671edaSAlgea Cao 	memcpy(hdmi->link_cfg.pps_payload, pps_datas[i].raw_pps, 128);
847*4ae62432SAlgea Cao 
848*4ae62432SAlgea Cao 	/* if yuv dsc format */
849*4ae62432SAlgea Cao 	if (hdmi_bus_fmt_is_rgb(hdmi->output_bus_format))
850*4ae62432SAlgea Cao 		hdmi->link_cfg.pps_payload[4] |= BIT(4);
851*4ae62432SAlgea Cao 	else
852*4ae62432SAlgea Cao 		hdmi->link_cfg.pps_payload[4] &= ~BIT(4);
853*4ae62432SAlgea Cao 
85428671edaSAlgea Cao 	hdmi->link_cfg.hcactive = DIV_ROUND_UP(slice_width * (bits_per_pixel / 16), 8) *
85528671edaSAlgea Cao 		(pic_width / slice_width);
85628671edaSAlgea Cao 
85728671edaSAlgea Cao 	return 0;
85828671edaSAlgea Cao }
85928671edaSAlgea Cao 
dw_hdmi_qp_dsc_configure(struct rockchip_hdmi * hdmi,struct crtc_state * s,struct drm_display_mode * mode)86028671edaSAlgea Cao static void dw_hdmi_qp_dsc_configure(struct rockchip_hdmi *hdmi,
861*4ae62432SAlgea Cao 				     struct crtc_state *s,
86228671edaSAlgea Cao 				     struct drm_display_mode *mode)
86328671edaSAlgea Cao {
86428671edaSAlgea Cao 	int ret;
86528671edaSAlgea Cao 	int slice_height;
86628671edaSAlgea Cao 	int slice_width;
86728671edaSAlgea Cao 	int bits_per_pixel;
86828671edaSAlgea Cao 	int slice_count;
86928671edaSAlgea Cao 	bool hdmi_is_dsc_1_2;
87028671edaSAlgea Cao 	unsigned int depth = hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
87128671edaSAlgea Cao 
87228671edaSAlgea Cao 	hdmi_is_dsc_1_2 = hdmi->dsc_cap.v_1p2;
87328671edaSAlgea Cao 
87428671edaSAlgea Cao 	if (!hdmi_is_dsc_1_2)
87528671edaSAlgea Cao 		return;
87628671edaSAlgea Cao 
877*4ae62432SAlgea Cao 	if (hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format) ||
878*4ae62432SAlgea Cao 	    hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format)) {
879*4ae62432SAlgea Cao 		dev_err(hdmi->dev, "dsc can't support yuv422/420\n");
880*4ae62432SAlgea Cao 		return;
881*4ae62432SAlgea Cao 	}
882*4ae62432SAlgea Cao 
88328671edaSAlgea Cao 	slice_height = hdmi_dsc_get_slice_height(mode->vdisplay);
88428671edaSAlgea Cao 	if (!slice_height)
88528671edaSAlgea Cao 		return;
88628671edaSAlgea Cao 
88728671edaSAlgea Cao 	slice_count = hdmi_dsc_slices(hdmi, mode);
88828671edaSAlgea Cao 	if (!slice_count)
88928671edaSAlgea Cao 		return;
89028671edaSAlgea Cao 
89128671edaSAlgea Cao 	slice_width = DIV_ROUND_UP(mode->hdisplay, slice_count);
89228671edaSAlgea Cao 
893*4ae62432SAlgea Cao 	bits_per_pixel =
894*4ae62432SAlgea Cao 		dw_hdmi_dsc_bpp(hdmi, slice_count, slice_width, mode->clock);
89528671edaSAlgea Cao 	if (!bits_per_pixel)
89628671edaSAlgea Cao 		return;
89728671edaSAlgea Cao 
89828671edaSAlgea Cao 	ret = dw_hdmi_qp_set_link_cfg(hdmi, mode->hdisplay,
89928671edaSAlgea Cao 				      mode->vdisplay, slice_width,
90028671edaSAlgea Cao 				      slice_height, bits_per_pixel, depth);
90128671edaSAlgea Cao 
90228671edaSAlgea Cao 	if (ret) {
90328671edaSAlgea Cao 		dev_err(hdmi->dev, "set vdsc cfg failed\n");
90428671edaSAlgea Cao 		return;
90528671edaSAlgea Cao 	}
90628671edaSAlgea Cao 	printf("dsc_enable\n");
907*4ae62432SAlgea Cao 
908*4ae62432SAlgea Cao 	s->dsc_enable = 1;
909*4ae62432SAlgea Cao 	s->dsc_sink_cap.version_major = 1;
910*4ae62432SAlgea Cao 	s->dsc_sink_cap.version_minor = 2;
911*4ae62432SAlgea Cao 	s->dsc_sink_cap.slice_width = slice_width;
912*4ae62432SAlgea Cao 	s->dsc_sink_cap.slice_height = slice_height;
913*4ae62432SAlgea Cao 	s->dsc_sink_cap.target_bits_per_pixel_x16 = bits_per_pixel;
914*4ae62432SAlgea Cao 	s->dsc_sink_cap.block_pred = 1;
915*4ae62432SAlgea Cao 	s->dsc_sink_cap.native_420 = 0;
916*4ae62432SAlgea Cao 
917*4ae62432SAlgea Cao 	memcpy(&s->pps, hdmi->link_cfg.pps_payload, 128);
91828671edaSAlgea Cao }
91928671edaSAlgea Cao 
drm_rk_select_color(struct rockchip_hdmi * hdmi,struct hdmi_edid_data * edid_data,struct base_screen_info * screen_info,enum dw_hdmi_devtype dev_type,bool output_bus_format_rgb)920*4ae62432SAlgea Cao static unsigned int drm_rk_select_color(struct rockchip_hdmi *hdmi,
921*4ae62432SAlgea Cao 					struct hdmi_edid_data *edid_data,
92228671edaSAlgea Cao 					struct base_screen_info *screen_info,
92328671edaSAlgea Cao 					enum dw_hdmi_devtype dev_type,
92428671edaSAlgea Cao 					bool output_bus_format_rgb)
92528671edaSAlgea Cao {
92628671edaSAlgea Cao 	struct drm_display_info *info = &edid_data->display_info;
92728671edaSAlgea Cao 	struct drm_display_mode *mode = edid_data->preferred_mode;
928c466e63bSAlgea Cao 	struct drm_hdmi_info *hdmi_info = &edid_data->display_info.hdmi;
92928671edaSAlgea Cao 	int max_tmds_clock = info->max_tmds_clock;
93028671edaSAlgea Cao 	bool support_dc = false;
93128671edaSAlgea Cao 	bool mode_420 = drm_mode_is_420(info, mode);
93228671edaSAlgea Cao 	unsigned int color_depth = 8;
9330a6aa9d3SAlgea Cao 	unsigned int base_color = DRM_HDMI_OUTPUT_YCBCR444;
93428671edaSAlgea Cao 	unsigned int color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
93528671edaSAlgea Cao 	unsigned long tmdsclock, pixclock = mode->clock;
93628671edaSAlgea Cao 
93728671edaSAlgea Cao 	if (screen_info)
93828671edaSAlgea Cao 		base_color = screen_info->format;
93928671edaSAlgea Cao 
94028671edaSAlgea Cao 	switch (base_color) {
94128671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR_HQ:
94228671edaSAlgea Cao 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
94328671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
94428671edaSAlgea Cao 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
94528671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
946a5aec6bfSAlgea Cao 		else if (mode_420 && pixclock >= 340000)
94728671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
94828671edaSAlgea Cao 		break;
94928671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR_LQ:
950a5aec6bfSAlgea Cao 		if (mode_420 && pixclock >= 340000)
95128671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
95228671edaSAlgea Cao 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
95328671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
95428671edaSAlgea Cao 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
95528671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
95628671edaSAlgea Cao 		break;
95728671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR420:
958a5aec6bfSAlgea Cao 		if (mode_420 && pixclock >= 340000)
95928671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
96028671edaSAlgea Cao 		break;
96128671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR422:
96228671edaSAlgea Cao 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
96328671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
96428671edaSAlgea Cao 		break;
96528671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR444:
96628671edaSAlgea Cao 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
96728671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
96828671edaSAlgea Cao 		break;
96928671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
97028671edaSAlgea Cao 	default:
97128671edaSAlgea Cao 		break;
97228671edaSAlgea Cao 	}
97328671edaSAlgea Cao 
97428671edaSAlgea Cao 	if (output_bus_format_rgb)
97528671edaSAlgea Cao 		color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
97628671edaSAlgea Cao 
97728671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_DEFAULT_RGB &&
97828671edaSAlgea Cao 	    info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
97928671edaSAlgea Cao 		support_dc = true;
98028671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR444 &&
98128671edaSAlgea Cao 	    (info->edid_hdmi_dc_modes &
98228671edaSAlgea Cao 	     (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30)))
98328671edaSAlgea Cao 		support_dc = true;
98428671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422)
98528671edaSAlgea Cao 		support_dc = true;
98628671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420 &&
98728671edaSAlgea Cao 	    info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
98828671edaSAlgea Cao 		support_dc = true;
98928671edaSAlgea Cao 
99028671edaSAlgea Cao 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
99128671edaSAlgea Cao 		pixclock *= 2;
99228671edaSAlgea Cao 
99328671edaSAlgea Cao 	if (screen_info && screen_info->depth == 10)
99428671edaSAlgea Cao 		color_depth = screen_info->depth;
99528671edaSAlgea Cao 
996*4ae62432SAlgea Cao 	if (drm_mode_is_420_only(info, mode) ||
997*4ae62432SAlgea Cao 	    (mode->clock > 1188000 &&
998*4ae62432SAlgea Cao 	     (color_format == DRM_HDMI_OUTPUT_YCBCR422 ||
999*4ae62432SAlgea Cao 	      hdmi->force_disable_dsc)))
1000c466e63bSAlgea Cao 		color_format = DRM_HDMI_OUTPUT_YCBCR420;
1001c466e63bSAlgea Cao 
100228671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422 || color_depth == 8)
100328671edaSAlgea Cao 		tmdsclock = pixclock;
100428671edaSAlgea Cao 	else
100528671edaSAlgea Cao 		tmdsclock = pixclock * color_depth / 8;
100628671edaSAlgea Cao 
100728671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420)
100828671edaSAlgea Cao 		tmdsclock /= 2;
100928671edaSAlgea Cao 
101028671edaSAlgea Cao 	if (!max_tmds_clock)
101128671edaSAlgea Cao 		max_tmds_clock = 340000;
101228671edaSAlgea Cao 
1013c466e63bSAlgea Cao 	if (hdmi_info->max_frl_rate_per_lane && mode->clock > 600000)
1014c466e63bSAlgea Cao 		max_tmds_clock =
1015c466e63bSAlgea Cao 			hdmi_info->max_lanes * hdmi_info->max_frl_rate_per_lane *
1016c466e63bSAlgea Cao 				1000000;
1017c466e63bSAlgea Cao 
1018c466e63bSAlgea Cao 	if (tmdsclock > max_tmds_clock) {
1019c466e63bSAlgea Cao 		if (max_tmds_clock >= 594000) {
102028671edaSAlgea Cao 			color_depth = 8;
1021c466e63bSAlgea Cao 		} else if (max_tmds_clock > 340000) {
1022c466e63bSAlgea Cao 			if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
102328671edaSAlgea Cao 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
1024c466e63bSAlgea Cao 		} else {
1025c466e63bSAlgea Cao 			color_depth = 8;
1026c466e63bSAlgea Cao 			if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
1027c466e63bSAlgea Cao 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
1028c466e63bSAlgea Cao 		}
102928671edaSAlgea Cao 	}
103028671edaSAlgea Cao 
103128671edaSAlgea Cao 	printf("color_format:%x\n", color_format);
103228671edaSAlgea Cao 	if (color_depth > 8 && support_dc) {
103328671edaSAlgea Cao 		switch (color_format) {
103428671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR444:
103528671edaSAlgea Cao 			return MEDIA_BUS_FMT_YUV10_1X30;
103628671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR422:
1037bc291652SAlgea Cao 			return MEDIA_BUS_FMT_YUYV10_1X20;
103828671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR420:
103928671edaSAlgea Cao 			return MEDIA_BUS_FMT_UYYVYY10_0_5X30;
104028671edaSAlgea Cao 		default:
104128671edaSAlgea Cao 			return MEDIA_BUS_FMT_RGB101010_1X30;
104228671edaSAlgea Cao 		}
104328671edaSAlgea Cao 	} else {
104428671edaSAlgea Cao 		switch (color_format) {
104528671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR444:
104628671edaSAlgea Cao 			return MEDIA_BUS_FMT_YUV8_1X24;
104728671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR422:
1048bc291652SAlgea Cao 			return MEDIA_BUS_FMT_YUYV8_1X16;
104928671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR420:
105028671edaSAlgea Cao 			return MEDIA_BUS_FMT_UYYVYY8_0_5X24;
105128671edaSAlgea Cao 		default:
105228671edaSAlgea Cao 			return MEDIA_BUS_FMT_RGB888_1X24;
105328671edaSAlgea Cao 		}
105428671edaSAlgea Cao 	}
105528671edaSAlgea Cao }
105628671edaSAlgea Cao 
10572afea1f0SAlgea Cao #define SUPPORT_HDMI_ALLM	BIT(1)
10582afea1f0SAlgea Cao 
dw_hdmi_qp_select_output(struct hdmi_edid_data * edid_data,struct rockchip_connector * conn,unsigned int * bus_format,struct overscan * overscan,enum dw_hdmi_devtype dev_type,bool output_bus_format_rgb,void * data,struct display_state * state)1059463abfccSAlgea Cao void dw_hdmi_qp_select_output(struct hdmi_edid_data *edid_data,
10600594ce39SZhang Yubing 			      struct rockchip_connector *conn,
106128671edaSAlgea Cao 			      unsigned int *bus_format,
106228671edaSAlgea Cao 			      struct overscan *overscan,
106328671edaSAlgea Cao 			      enum dw_hdmi_devtype dev_type,
106428671edaSAlgea Cao 			      bool output_bus_format_rgb,
10650d7a8537SAlgea Cao 			      void *data, struct display_state *state)
106628671edaSAlgea Cao {
106728671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
106828671edaSAlgea Cao 	struct drm_hdmi_info *hdmi_info = &edid_data->display_info.hdmi;
106928671edaSAlgea Cao 	int ret, i, screen_size;
107028671edaSAlgea Cao 	struct base_disp_info base_parameter;
10710594ce39SZhang Yubing 	struct base2_disp_info *base2_parameter = state->conn_state.disp_info;
107228671edaSAlgea Cao 	const struct base_overscan *scan;
107328671edaSAlgea Cao 	struct base_screen_info *screen_info = NULL;
107428671edaSAlgea Cao 	struct base2_screen_info *screen_info2 = NULL;
1075*4ae62432SAlgea Cao 	struct crtc_state *s = &state->crtc_state;
107628671edaSAlgea Cao 	int max_scan = 100;
107728671edaSAlgea Cao 	int min_scan = 51;
107828671edaSAlgea Cao 	int offset = 0;
107928671edaSAlgea Cao 	int color_depth;
108028671edaSAlgea Cao 	unsigned int tmdsclk;
108128671edaSAlgea Cao 	unsigned int pixel_clk;
108228671edaSAlgea Cao 	bool found = false;
108328671edaSAlgea Cao 	struct blk_desc *dev_desc;
108428671edaSAlgea Cao 	disk_partition_t part_info;
108528671edaSAlgea Cao 	char baseparameter_buf[8 * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
108628671edaSAlgea Cao 
108728671edaSAlgea Cao 	overscan->left_margin = max_scan;
108828671edaSAlgea Cao 	overscan->right_margin = max_scan;
108928671edaSAlgea Cao 	overscan->top_margin = max_scan;
109028671edaSAlgea Cao 	overscan->bottom_margin = max_scan;
109128671edaSAlgea Cao 
109228671edaSAlgea Cao 	hdmi->max_frl_rate_per_lane = hdmi_info->max_frl_rate_per_lane;
109328671edaSAlgea Cao 	hdmi->max_lanes = hdmi_info->max_lanes;
109428671edaSAlgea Cao 	memcpy(&hdmi->dsc_cap, &hdmi_info->dsc_cap, sizeof(struct drm_hdmi_dsc_cap));
109528671edaSAlgea Cao 
109628671edaSAlgea Cao 	if (output_bus_format_rgb)
109728671edaSAlgea Cao 		*bus_format = MEDIA_BUS_FMT_RGB888_1X24;
109828671edaSAlgea Cao 	else
109928671edaSAlgea Cao 		*bus_format = MEDIA_BUS_FMT_YUV8_1X24;
110028671edaSAlgea Cao 
110128671edaSAlgea Cao 	if (!base2_parameter) {
110228671edaSAlgea Cao 		dev_desc = rockchip_get_bootdev();
110328671edaSAlgea Cao 		if (!dev_desc) {
110428671edaSAlgea Cao 			printf("%s: Could not find device\n", __func__);
110528671edaSAlgea Cao 			goto null_basep;
110628671edaSAlgea Cao 		}
110728671edaSAlgea Cao 
110828671edaSAlgea Cao 		ret = part_get_info_by_name(dev_desc, "baseparameter",
110928671edaSAlgea Cao 					    &part_info);
111028671edaSAlgea Cao 		if (ret < 0) {
111128671edaSAlgea Cao 			printf("Could not find baseparameter partition\n");
111228671edaSAlgea Cao 			goto null_basep;
111328671edaSAlgea Cao 		}
111428671edaSAlgea Cao 
111528671edaSAlgea Cao read_aux:
111628671edaSAlgea Cao 		ret = blk_dread(dev_desc, part_info.start + offset, 1,
111728671edaSAlgea Cao 				(void *)baseparameter_buf);
111828671edaSAlgea Cao 		if (ret < 0) {
111928671edaSAlgea Cao 			printf("read baseparameter failed\n");
112028671edaSAlgea Cao 			goto null_basep;
112128671edaSAlgea Cao 		}
112228671edaSAlgea Cao 
112328671edaSAlgea Cao 		memcpy(&base_parameter, baseparameter_buf,
112428671edaSAlgea Cao 		       sizeof(base_parameter));
112528671edaSAlgea Cao 		scan = &base_parameter.scan;
112628671edaSAlgea Cao 
112728671edaSAlgea Cao 		screen_size = sizeof(base_parameter.screen_list) /
112828671edaSAlgea Cao 			sizeof(base_parameter.screen_list[0]);
112928671edaSAlgea Cao 
113028671edaSAlgea Cao 		for (i = 0; i < screen_size; i++) {
113128671edaSAlgea Cao 			if (base_parameter.screen_list[i].type ==
113228671edaSAlgea Cao 			    DRM_MODE_CONNECTOR_HDMIA) {
113328671edaSAlgea Cao 				found = true;
113428671edaSAlgea Cao 				screen_info = &base_parameter.screen_list[i];
113528671edaSAlgea Cao 				break;
113628671edaSAlgea Cao 			}
113728671edaSAlgea Cao 		}
113828671edaSAlgea Cao 
113928671edaSAlgea Cao 		if (!found && !offset) {
114028671edaSAlgea Cao 			printf("hdmi info isn't saved in main block\n");
114128671edaSAlgea Cao 			offset += 16;
114228671edaSAlgea Cao 			goto read_aux;
114328671edaSAlgea Cao 		}
114428671edaSAlgea Cao 	} else {
11452afea1f0SAlgea Cao 		bool allm_en = false;
11462afea1f0SAlgea Cao 
114728671edaSAlgea Cao 		scan = &base2_parameter->overscan_info;
114828671edaSAlgea Cao 		screen_size = sizeof(base2_parameter->screen_info) /
114928671edaSAlgea Cao 			sizeof(base2_parameter->screen_info[0]);
115028671edaSAlgea Cao 
115128671edaSAlgea Cao 		for (i = 0; i < screen_size; i++) {
115228671edaSAlgea Cao 			if (base2_parameter->screen_info[i].type ==
115328671edaSAlgea Cao 			    DRM_MODE_CONNECTOR_HDMIA) {
115428671edaSAlgea Cao 				screen_info2 =
115528671edaSAlgea Cao 					&base2_parameter->screen_info[i];
115628671edaSAlgea Cao 				break;
115728671edaSAlgea Cao 			}
115828671edaSAlgea Cao 		}
115928671edaSAlgea Cao 		screen_info = malloc(sizeof(*screen_info));
116028671edaSAlgea Cao 
116128671edaSAlgea Cao 		screen_info->type = screen_info2->type;
116228671edaSAlgea Cao 		screen_info->mode = screen_info2->resolution;
116328671edaSAlgea Cao 		screen_info->format = screen_info2->format;
116428671edaSAlgea Cao 		screen_info->depth = screen_info2->depthc;
116528671edaSAlgea Cao 		screen_info->feature = screen_info2->feature;
11662afea1f0SAlgea Cao 
11672afea1f0SAlgea Cao 		/* check if allm is enabled */
11682afea1f0SAlgea Cao 		allm_en = base2_parameter->reserved[0] & BIT(0);
11692afea1f0SAlgea Cao 		if (allm_en && (hdmi_info->add_func & SUPPORT_HDMI_ALLM))
11702afea1f0SAlgea Cao 			hdmi->allm_en = true;
11712afea1f0SAlgea Cao 		else
11722afea1f0SAlgea Cao 			hdmi->allm_en = false;
117328671edaSAlgea Cao 	}
117428671edaSAlgea Cao 
117528671edaSAlgea Cao 	if (scan->leftscale < min_scan && scan->leftscale > 0)
117628671edaSAlgea Cao 		overscan->left_margin = min_scan;
117728671edaSAlgea Cao 	else if (scan->leftscale < max_scan && scan->leftscale > 0)
117828671edaSAlgea Cao 		overscan->left_margin = scan->leftscale;
117928671edaSAlgea Cao 
118028671edaSAlgea Cao 	if (scan->rightscale < min_scan && scan->rightscale > 0)
118128671edaSAlgea Cao 		overscan->right_margin = min_scan;
118228671edaSAlgea Cao 	else if (scan->rightscale < max_scan && scan->rightscale > 0)
118328671edaSAlgea Cao 		overscan->right_margin = scan->rightscale;
118428671edaSAlgea Cao 
118528671edaSAlgea Cao 	if (scan->topscale < min_scan && scan->topscale > 0)
118628671edaSAlgea Cao 		overscan->top_margin = min_scan;
118728671edaSAlgea Cao 	else if (scan->topscale < max_scan && scan->topscale > 0)
118828671edaSAlgea Cao 		overscan->top_margin = scan->topscale;
118928671edaSAlgea Cao 
119028671edaSAlgea Cao 	if (scan->bottomscale < min_scan && scan->bottomscale > 0)
119128671edaSAlgea Cao 		overscan->bottom_margin = min_scan;
119228671edaSAlgea Cao 	else if (scan->bottomscale < max_scan && scan->bottomscale > 0)
119328671edaSAlgea Cao 		overscan->bottom_margin = scan->bottomscale;
119428671edaSAlgea Cao 
119528671edaSAlgea Cao null_basep:
119628671edaSAlgea Cao 
119728671edaSAlgea Cao 	if (screen_info)
119828671edaSAlgea Cao 		printf("base_parameter.mode:%dx%d\n",
119928671edaSAlgea Cao 		       screen_info->mode.hdisplay,
120028671edaSAlgea Cao 		       screen_info->mode.vdisplay);
120128671edaSAlgea Cao 	drm_rk_select_mode(edid_data, screen_info);
120228671edaSAlgea Cao 
1203*4ae62432SAlgea Cao 	*bus_format = drm_rk_select_color(hdmi, edid_data, screen_info,
120428671edaSAlgea Cao 					  dev_type, output_bus_format_rgb);
120528671edaSAlgea Cao 
1206*4ae62432SAlgea Cao 	hdmi->output_bus_format = *bus_format;
12070d7a8537SAlgea Cao 	if (state->force_output) {
12080d7a8537SAlgea Cao 		memcpy(edid_data->preferred_mode, &state->force_mode,
12090d7a8537SAlgea Cao 		       sizeof(struct drm_display_mode));
12100d7a8537SAlgea Cao 		if (state->force_bus_format)
12110d7a8537SAlgea Cao 			*bus_format = state->force_bus_format;
12120d7a8537SAlgea Cao 	}
12130d7a8537SAlgea Cao 
121428671edaSAlgea Cao 	hdmi->bus_format = *bus_format;
121528671edaSAlgea Cao 	color_depth = hdmi_bus_fmt_color_depth(*bus_format);
121628671edaSAlgea Cao 	pixel_clk = edid_data->preferred_mode->clock;
121728671edaSAlgea Cao 	tmdsclk = hdmi_get_tmdsclock(hdmi, pixel_clk);
121828671edaSAlgea Cao 	if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format))
121928671edaSAlgea Cao 		tmdsclk /= 2;
122028671edaSAlgea Cao 	hdmi_select_link_config(hdmi, edid_data->preferred_mode, tmdsclk);
1221*4ae62432SAlgea Cao 
1222*4ae62432SAlgea Cao 	s->dsc_enable = 0;
1223*4ae62432SAlgea Cao 	if (hdmi->link_cfg.dsc_mode)
1224*4ae62432SAlgea Cao 		dw_hdmi_qp_dsc_configure(hdmi, s, edid_data->preferred_mode);
122528671edaSAlgea Cao 	if (hdmi->link_cfg.frl_mode) {
1226af006bcbSChen Shunqing 		if (dm_gpio_is_valid(&hdmi->enable_gpio))
122728671edaSAlgea Cao 			dm_gpio_set_value(&hdmi->enable_gpio, 0);
122828671edaSAlgea Cao 		/* in the current version, support max 40G frl */
122928671edaSAlgea Cao 		if (hdmi->link_cfg.rate_per_lane >= 10) {
123028671edaSAlgea Cao 			hdmi->link_cfg.frl_lanes = 4;
123128671edaSAlgea Cao 			hdmi->link_cfg.rate_per_lane = 10;
123228671edaSAlgea Cao 		}
123328671edaSAlgea Cao 		hdmi->bus_width = hdmi->link_cfg.frl_lanes *
123428671edaSAlgea Cao 			hdmi->link_cfg.rate_per_lane * 1000000;
123528671edaSAlgea Cao 		/* 10 bit color depth and frl mode */
123628671edaSAlgea Cao 		if (color_depth == 10)
123728671edaSAlgea Cao 			hdmi->bus_width |=
123828671edaSAlgea Cao 				COLOR_DEPTH_10BIT | HDMI_FRL_MODE;
123928671edaSAlgea Cao 		else
124028671edaSAlgea Cao 			hdmi->bus_width |= HDMI_FRL_MODE;
124128671edaSAlgea Cao 	} else {
1242af006bcbSChen Shunqing 		if (dm_gpio_is_valid(&hdmi->enable_gpio))
124328671edaSAlgea Cao 			dm_gpio_set_value(&hdmi->enable_gpio, 1);
124428671edaSAlgea Cao 		hdmi->bus_width =
124528671edaSAlgea Cao 			hdmi_get_tmdsclock(hdmi, pixel_clk * 10);
124628671edaSAlgea Cao 		if (hdmi_bus_fmt_is_yuv420(*bus_format))
124728671edaSAlgea Cao 			hdmi->bus_width /= 2;
124828671edaSAlgea Cao 
1249bc291652SAlgea Cao 		if (color_depth == 10 && !hdmi_bus_fmt_is_yuv422(*bus_format))
125028671edaSAlgea Cao 			hdmi->bus_width |= COLOR_DEPTH_10BIT;
125128671edaSAlgea Cao 	}
125297273498SAlgea Cao 
12530594ce39SZhang Yubing 	rockchip_phy_set_bus_width(conn->phy, hdmi->bus_width);
125428671edaSAlgea Cao }
125528671edaSAlgea Cao 
dw_hdmi_qp_check_enable_gpio(void * data)1256200f72c9SAlgea Cao bool dw_hdmi_qp_check_enable_gpio(void *data)
1257200f72c9SAlgea Cao {
1258200f72c9SAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1259200f72c9SAlgea Cao 
1260200f72c9SAlgea Cao 	if (!hdmi->enable_gpio.dev)
1261200f72c9SAlgea Cao 		return false;
1262200f72c9SAlgea Cao 	else
1263200f72c9SAlgea Cao 		return true;
1264200f72c9SAlgea Cao }
1265200f72c9SAlgea Cao 
rk3576_set_link_mode(struct rockchip_hdmi * hdmi)1266463abfccSAlgea Cao static void rk3576_set_link_mode(struct rockchip_hdmi *hdmi)
1267463abfccSAlgea Cao {
1268463abfccSAlgea Cao 	int val;
1269463abfccSAlgea Cao 
1270463abfccSAlgea Cao 	if (!hdmi->link_cfg.frl_mode)
1271463abfccSAlgea Cao 		val = HIWORD_UPDATE(0, RK3576_HDMITX_FRL_MOD);
1272463abfccSAlgea Cao 	else
1273463abfccSAlgea Cao 		val = HIWORD_UPDATE(RK3576_HDMITX_FRL_MOD, RK3576_HDMITX_FRL_MOD);
1274463abfccSAlgea Cao 	writel(val, hdmi->vo0_grf + RK3576_VO0_GRF_SOC_CON1);
1275463abfccSAlgea Cao }
1276463abfccSAlgea Cao 
rk3588_set_link_mode(struct rockchip_hdmi * hdmi)127728671edaSAlgea Cao static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi)
127828671edaSAlgea Cao {
127928671edaSAlgea Cao 	int val;
128028671edaSAlgea Cao 	bool is_hdmi0;
128128671edaSAlgea Cao 
128228671edaSAlgea Cao 	if (!hdmi->id)
128328671edaSAlgea Cao 		is_hdmi0 = true;
128428671edaSAlgea Cao 	else
128528671edaSAlgea Cao 		is_hdmi0 = false;
128628671edaSAlgea Cao 
128728671edaSAlgea Cao 	if (!hdmi->link_cfg.frl_mode) {
128828671edaSAlgea Cao 		val = HIWORD_UPDATE(0, RK3588_HDMI21_MASK);
128928671edaSAlgea Cao 		if (is_hdmi0)
129028671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4);
129128671edaSAlgea Cao 		else
129228671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7);
129328671edaSAlgea Cao 
129428671edaSAlgea Cao 		val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
129528671edaSAlgea Cao 		if (is_hdmi0)
129628671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
129728671edaSAlgea Cao 		else
129828671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
129928671edaSAlgea Cao 
130028671edaSAlgea Cao 		return;
130128671edaSAlgea Cao 	}
130228671edaSAlgea Cao 
130328671edaSAlgea Cao 	val = HIWORD_UPDATE(RK3588_HDMI21_MASK, RK3588_HDMI21_MASK);
130428671edaSAlgea Cao 	if (is_hdmi0)
130528671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4);
130628671edaSAlgea Cao 	else
130728671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7);
130828671edaSAlgea Cao 
130928671edaSAlgea Cao 	if (hdmi->link_cfg.dsc_mode) {
131028671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_COMPRESS_MODE_MASK | RK3588_COMPRESSED_DATA,
131128671edaSAlgea Cao 				    RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
131228671edaSAlgea Cao 		if (is_hdmi0)
131328671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
131428671edaSAlgea Cao 		else
131528671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
131628671edaSAlgea Cao 	} else {
131728671edaSAlgea Cao 		val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
131828671edaSAlgea Cao 		if (is_hdmi0)
131928671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
132028671edaSAlgea Cao 		else
132128671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
132228671edaSAlgea Cao 	}
132328671edaSAlgea Cao }
132428671edaSAlgea Cao 
rk3576_set_color_format(struct rockchip_hdmi * hdmi,u64 bus_format,u32 depth)1325463abfccSAlgea Cao static void rk3576_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format,
1326463abfccSAlgea Cao 				    u32 depth)
1327463abfccSAlgea Cao {
1328463abfccSAlgea Cao 	u32 val = 0;
1329463abfccSAlgea Cao 
1330463abfccSAlgea Cao 	switch (bus_format) {
1331463abfccSAlgea Cao 	case MEDIA_BUS_FMT_RGB888_1X24:
1332463abfccSAlgea Cao 	case MEDIA_BUS_FMT_RGB101010_1X30:
1333463abfccSAlgea Cao 		val = HIWORD_UPDATE(0, RK3576_COLOR_FORMAT_MASK);
1334463abfccSAlgea Cao 		break;
1335463abfccSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1336463abfccSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1337463abfccSAlgea Cao 		val = HIWORD_UPDATE(RK3576_YUV420, RK3576_COLOR_FORMAT_MASK);
1338463abfccSAlgea Cao 		break;
1339463abfccSAlgea Cao 	case MEDIA_BUS_FMT_YUV8_1X24:
1340463abfccSAlgea Cao 	case MEDIA_BUS_FMT_YUV10_1X30:
1341463abfccSAlgea Cao 		val = HIWORD_UPDATE(RK3576_YUV444, RK3576_COLOR_FORMAT_MASK);
1342463abfccSAlgea Cao 		break;
1343463abfccSAlgea Cao 	case MEDIA_BUS_FMT_YUYV10_1X20:
1344463abfccSAlgea Cao 	case MEDIA_BUS_FMT_YUYV8_1X16:
1345463abfccSAlgea Cao 		val = HIWORD_UPDATE(RK3576_YUV422, RK3576_COLOR_FORMAT_MASK);
1346463abfccSAlgea Cao 		break;
1347463abfccSAlgea Cao 	default:
1348463abfccSAlgea Cao 		printf("can't set correct color format\n");
1349463abfccSAlgea Cao 		return;
1350463abfccSAlgea Cao 	}
1351463abfccSAlgea Cao 
1352463abfccSAlgea Cao 	if (depth == 8 || bus_format == MEDIA_BUS_FMT_YUYV10_1X20)
1353463abfccSAlgea Cao 		val |= HIWORD_UPDATE(RK3576_8BPC, RK3576_COLOR_DEPTH_MASK);
1354463abfccSAlgea Cao 	else
1355463abfccSAlgea Cao 		val |= HIWORD_UPDATE(RK3576_10BPC, RK3576_COLOR_DEPTH_MASK);
1356463abfccSAlgea Cao 
1357463abfccSAlgea Cao 	writel(val, hdmi->vo0_grf + RK3576_VO0_GRF_SOC_CON8);
1358463abfccSAlgea Cao }
1359463abfccSAlgea Cao 
rk3588_set_color_format(struct rockchip_hdmi * hdmi,u64 bus_format,u32 depth)136028671edaSAlgea Cao static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format,
136128671edaSAlgea Cao 				    u32 depth)
136228671edaSAlgea Cao {
136328671edaSAlgea Cao 	u32 val = 0;
136428671edaSAlgea Cao 
136528671edaSAlgea Cao 	switch (bus_format) {
136628671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB888_1X24:
136728671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB101010_1X30:
136828671edaSAlgea Cao 		val = HIWORD_UPDATE(0, RK3588_COLOR_FORMAT_MASK);
136928671edaSAlgea Cao 		break;
137028671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
137128671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
137228671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_YUV420, RK3588_COLOR_FORMAT_MASK);
137328671edaSAlgea Cao 		break;
137428671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV8_1X24:
137528671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV10_1X30:
137628671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_YUV444, RK3588_COLOR_FORMAT_MASK);
137728671edaSAlgea Cao 		break;
1378bc291652SAlgea Cao 	case MEDIA_BUS_FMT_YUYV10_1X20:
1379bc291652SAlgea Cao 	case MEDIA_BUS_FMT_YUYV8_1X16:
1380bc291652SAlgea Cao 		val = HIWORD_UPDATE(RK3588_YUV422, RK3588_COLOR_FORMAT_MASK);
1381bc291652SAlgea Cao 		break;
138228671edaSAlgea Cao 	default:
138328671edaSAlgea Cao 		dev_err(hdmi->dev, "can't set correct color format\n");
138428671edaSAlgea Cao 		return;
138528671edaSAlgea Cao 	}
138628671edaSAlgea Cao 
138728671edaSAlgea Cao 	if (hdmi->link_cfg.dsc_mode)
138828671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_COMPRESSED_DATA, RK3588_COLOR_FORMAT_MASK);
138928671edaSAlgea Cao 
1390bc291652SAlgea Cao 	if (depth == 8 || bus_format == MEDIA_BUS_FMT_YUYV10_1X20)
139128671edaSAlgea Cao 		val |= HIWORD_UPDATE(RK3588_8BPC, RK3588_COLOR_DEPTH_MASK);
139228671edaSAlgea Cao 	else
139328671edaSAlgea Cao 		val |= HIWORD_UPDATE(RK3588_10BPC, RK3588_COLOR_DEPTH_MASK);
139428671edaSAlgea Cao 
139528671edaSAlgea Cao 	if (!hdmi->id)
139628671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
139728671edaSAlgea Cao 	else
139828671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
139928671edaSAlgea Cao }
140028671edaSAlgea Cao 
dw_hdmi_qp_set_grf_cfg(void * data)1401463abfccSAlgea Cao void dw_hdmi_qp_set_grf_cfg(void *data)
140228671edaSAlgea Cao {
140328671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
140428671edaSAlgea Cao 	int color_depth;
140528671edaSAlgea Cao 
1406463abfccSAlgea Cao 	hdmi->ops->set_link_mode(hdmi);
140728671edaSAlgea Cao 	color_depth = hdmi_bus_fmt_color_depth(hdmi->bus_format);
1408463abfccSAlgea Cao 	hdmi->ops->set_color_format(hdmi, hdmi->bus_format, color_depth);
140928671edaSAlgea Cao }
141028671edaSAlgea Cao 
1411463abfccSAlgea Cao static
dw_hdmi_qp_rockchip_sda_delay_cal(struct rockchip_hdmi * hdmi,u8 * sda_dlyn,u8 * sda_div)1412463abfccSAlgea Cao void dw_hdmi_qp_rockchip_sda_delay_cal(struct rockchip_hdmi *hdmi, u8 *sda_dlyn, u8 *sda_div)
141328671edaSAlgea Cao {
1414463abfccSAlgea Cao 	u8 i;
1415463abfccSAlgea Cao 	u32 val;
1416463abfccSAlgea Cao 
1417463abfccSAlgea Cao 	for (i = 0; i <= 127; i++) {
1418463abfccSAlgea Cao 		val = DIV_ROUND_UP(hdmi->sda_falling_delay_ns, (i + 1) * 40);
1419463abfccSAlgea Cao 
1420463abfccSAlgea Cao 		if (val <= 15)
1421463abfccSAlgea Cao 			break;
1422463abfccSAlgea Cao 	}
1423463abfccSAlgea Cao 
1424463abfccSAlgea Cao 	if (i > 127) {
1425463abfccSAlgea Cao 		dev_err(hdmi->dev, "delay %d ns,can't calculate correct sda falling delay cfg\n",
1426463abfccSAlgea Cao 			hdmi->sda_falling_delay_ns);
1427463abfccSAlgea Cao 		return;
1428463abfccSAlgea Cao 	}
1429463abfccSAlgea Cao 
1430463abfccSAlgea Cao 	*sda_div = i;
1431463abfccSAlgea Cao 	*sda_dlyn = val;
1432463abfccSAlgea Cao }
1433463abfccSAlgea Cao 
rk3576_io_path_init(struct rockchip_hdmi * hdmi)1434463abfccSAlgea Cao static void rk3576_io_path_init(struct rockchip_hdmi *hdmi)
1435463abfccSAlgea Cao {
1436463abfccSAlgea Cao 	u32 val;
1437463abfccSAlgea Cao 	u8 sda_dlyn = 0, sda_div = 0;
1438463abfccSAlgea Cao 
1439463abfccSAlgea Cao 	val = HIWORD_UPDATE(RK3576_SCLIN_MASK, RK3576_SCLIN_MASK) |
1440463abfccSAlgea Cao 	      HIWORD_UPDATE(RK3576_SDAIN_MASK, RK3576_SDAIN_MASK) |
1441463abfccSAlgea Cao 	      HIWORD_UPDATE(RK3576_HDMITX_GRANT_SEL, RK3576_HDMITX_GRANT_SEL) |
1442463abfccSAlgea Cao 	      HIWORD_UPDATE(RK3576_I2S_SEL_MASK, RK3576_I2S_SEL_MASK);
1443463abfccSAlgea Cao 	writel(val, hdmi->vo0_grf + RK3576_VO0_GRF_SOC_CON14);
1444463abfccSAlgea Cao 
1445463abfccSAlgea Cao 	val = HIWORD_UPDATE(0, RK3576_HDMITX_HPD_INT_MSK);
1446463abfccSAlgea Cao 	writel(val, hdmi->grf + RK3576_IOC_MISC_CON0);
1447463abfccSAlgea Cao 
1448463abfccSAlgea Cao 	if (hdmi->sda_falling_delay_ns) {
1449463abfccSAlgea Cao 		dw_hdmi_qp_rockchip_sda_delay_cal(hdmi, &sda_dlyn, &sda_div);
1450463abfccSAlgea Cao 		if (sda_dlyn) {
1451463abfccSAlgea Cao 			val = HIWORD_UPDATE(sda_dlyn << 12, RK3576_GRF_OSDA_DLYN) |
1452463abfccSAlgea Cao 			      HIWORD_UPDATE(sda_div << 1, RK3576_GRF_OSDA_DIV) |
1453463abfccSAlgea Cao 			      HIWORD_UPDATE(1, RK3576_GRF_OSDA_DLY_EN);
1454463abfccSAlgea Cao 
1455463abfccSAlgea Cao 			writel(val, hdmi->vo0_grf + RK3576_VO0_GRF_SOC_CON12);
1456463abfccSAlgea Cao 		}
1457463abfccSAlgea Cao 	}
1458463abfccSAlgea Cao }
1459463abfccSAlgea Cao 
rk3588_io_path_init(struct rockchip_hdmi * hdmi)1460463abfccSAlgea Cao static void rk3588_io_path_init(struct rockchip_hdmi *hdmi)
1461463abfccSAlgea Cao {
146228671edaSAlgea Cao 	u32 val;
146328671edaSAlgea Cao 
146428671edaSAlgea Cao 	if (!hdmi->id) {
146528671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
146628671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
146728671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
146828671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
146928671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
147028671edaSAlgea Cao 
147128671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
147228671edaSAlgea Cao 				    RK3588_SET_HPD_PATH_MASK);
147328671edaSAlgea Cao 		writel(val, hdmi->grf + RK3588_GRF_SOC_CON7);
147428671edaSAlgea Cao 
147528671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
147628671edaSAlgea Cao 				    RK3588_HDMI0_GRANT_SEL);
147728671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9);
147828671edaSAlgea Cao 	} else {
147928671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
148028671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
148128671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
148228671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
148328671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
148428671edaSAlgea Cao 
148528671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
148628671edaSAlgea Cao 				    RK3588_SET_HPD_PATH_MASK);
148728671edaSAlgea Cao 		writel(val, hdmi->grf + RK3588_GRF_SOC_CON7);
148828671edaSAlgea Cao 
148928671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
149028671edaSAlgea Cao 				    RK3588_HDMI1_GRANT_SEL);
149128671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9);
149228671edaSAlgea Cao 	}
149328671edaSAlgea Cao }
149428671edaSAlgea Cao 
dw_hdmi_qp_io_path_init(void * data)1495463abfccSAlgea Cao void dw_hdmi_qp_io_path_init(void *data)
1496463abfccSAlgea Cao {
1497463abfccSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1498463abfccSAlgea Cao 
1499463abfccSAlgea Cao 	hdmi->ops->io_path_init(hdmi);
1500463abfccSAlgea Cao }
1501463abfccSAlgea Cao 
dw_hdmi_rockchip_get_link_cfg(void * data)150228671edaSAlgea Cao struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data)
150328671edaSAlgea Cao {
150428671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
150528671edaSAlgea Cao 
150628671edaSAlgea Cao 	return &hdmi->link_cfg;
150728671edaSAlgea Cao }
150828671edaSAlgea Cao 
dw_hdmi_qp_rockchip_phy_disable(struct rockchip_connector * conn,void * data,void * state)15090594ce39SZhang Yubing static void dw_hdmi_qp_rockchip_phy_disable(struct rockchip_connector *conn, void *data,
15100594ce39SZhang Yubing 					    void *state)
151128671edaSAlgea Cao {
15120594ce39SZhang Yubing 	rockchip_phy_power_off(conn->phy);
151328671edaSAlgea Cao }
151428671edaSAlgea Cao 
dw_hdmi_qp_rockchip_genphy_init(struct rockchip_connector * conn,void * data,void * state)15150594ce39SZhang Yubing static int dw_hdmi_qp_rockchip_genphy_init(struct rockchip_connector *conn, void *data, void *state)
151628671edaSAlgea Cao {
151728671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
151828671edaSAlgea Cao 
15190594ce39SZhang Yubing 	dw_hdmi_qp_rockchip_phy_disable(conn, data, state);
152028671edaSAlgea Cao 
15210594ce39SZhang Yubing 	rockchip_phy_set_bus_width(conn->phy, hdmi->bus_width);
152228671edaSAlgea Cao 
15230594ce39SZhang Yubing 	return rockchip_phy_power_on(conn->phy);
152428671edaSAlgea Cao }
152528671edaSAlgea Cao 
rk3576_read_hpd(struct rockchip_hdmi * hdmi)1526463abfccSAlgea Cao static enum drm_connector_status rk3576_read_hpd(struct rockchip_hdmi *hdmi)
152728671edaSAlgea Cao {
152828671edaSAlgea Cao 	u32 val;
152928671edaSAlgea Cao 	int ret;
1530463abfccSAlgea Cao 
1531463abfccSAlgea Cao 	val = readl(hdmi->grf + RK3576_IOC_HDMITX_HPD_STATUS);
1532463abfccSAlgea Cao 
1533463abfccSAlgea Cao 	if (val & RK3576_HDMITX_LEVEL_INT)
1534463abfccSAlgea Cao 		ret = connector_status_connected;
1535463abfccSAlgea Cao 	else
1536463abfccSAlgea Cao 		ret = connector_status_disconnected;
1537463abfccSAlgea Cao 
1538463abfccSAlgea Cao 	return ret;
1539463abfccSAlgea Cao }
1540463abfccSAlgea Cao 
rk3588_read_hpd(struct rockchip_hdmi * hdmi)1541463abfccSAlgea Cao static enum drm_connector_status rk3588_read_hpd(struct rockchip_hdmi *hdmi)
1542463abfccSAlgea Cao {
1543463abfccSAlgea Cao 	u32 val;
1544463abfccSAlgea Cao 	int ret;
154528671edaSAlgea Cao 
154628671edaSAlgea Cao 	val = readl(hdmi->grf + RK3588_GRF_SOC_STATUS1);
154728671edaSAlgea Cao 
154828671edaSAlgea Cao 	if (!hdmi->id) {
154928671edaSAlgea Cao 		if (val & RK3588_HDMI0_LEVEL_INT)
155028671edaSAlgea Cao 			ret = connector_status_connected;
155128671edaSAlgea Cao 		else
155228671edaSAlgea Cao 			ret = connector_status_disconnected;
155328671edaSAlgea Cao 	} else {
155428671edaSAlgea Cao 		if (val & RK3588_HDMI1_LEVEL_INT)
155528671edaSAlgea Cao 			ret = connector_status_connected;
155628671edaSAlgea Cao 		else
155728671edaSAlgea Cao 			ret = connector_status_disconnected;
155828671edaSAlgea Cao 	}
155928671edaSAlgea Cao 
156028671edaSAlgea Cao 	return ret;
156128671edaSAlgea Cao }
156228671edaSAlgea Cao 
rockchip_hdmi_qp_read_hpd(void * data)1563463abfccSAlgea Cao static enum drm_connector_status rockchip_hdmi_qp_read_hpd(void *data)
1564463abfccSAlgea Cao {
1565463abfccSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1566463abfccSAlgea Cao 
1567463abfccSAlgea Cao 	return hdmi->ops->read_hpd(hdmi);
1568463abfccSAlgea Cao }
1569463abfccSAlgea Cao 
rockchip_hdmi_qp_set_pll(struct rockchip_connector * conn,void * data,void * state)1570463abfccSAlgea Cao static void rockchip_hdmi_qp_set_pll(struct rockchip_connector *conn, void *data, void *state)
157128671edaSAlgea Cao {
157228671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
15738c597bcaSAlgea Cao 	u32 rate = (hdmi->bus_width & DATA_RATE_MASK) * 100;
157428671edaSAlgea Cao 
15758c597bcaSAlgea Cao 	clk_set_rate(&hdmi->link_clk, rate);
157628671edaSAlgea Cao }
1577463abfccSAlgea Cao 
1578463abfccSAlgea Cao static const struct dw_hdmi_qp_phy_ops rockchip_hdmi_qp_phy_ops = {
157928671edaSAlgea Cao 	.init = dw_hdmi_qp_rockchip_genphy_init,
158028671edaSAlgea Cao 	.disable = dw_hdmi_qp_rockchip_phy_disable,
1581463abfccSAlgea Cao 	.read_hpd = rockchip_hdmi_qp_read_hpd,
1582463abfccSAlgea Cao 	.set_pll = rockchip_hdmi_qp_set_pll,
158328671edaSAlgea Cao };
158428671edaSAlgea Cao 
158528671edaSAlgea Cao static const struct rockchip_connector_funcs rockchip_dw_hdmi_qp_funcs = {
158628671edaSAlgea Cao 	.init = rockchip_dw_hdmi_qp_init,
158728671edaSAlgea Cao 	.deinit = rockchip_dw_hdmi_qp_deinit,
158828671edaSAlgea Cao 	.prepare = rockchip_dw_hdmi_qp_prepare,
15891d642d95SAlgea Cao 	.check = rockchip_dw_hdmi_qp_check,
159028671edaSAlgea Cao 	.enable = rockchip_dw_hdmi_qp_enable,
159128671edaSAlgea Cao 	.disable = rockchip_dw_hdmi_qp_disable,
159228671edaSAlgea Cao 	.get_timing = rockchip_dw_hdmi_qp_get_timing,
159328671edaSAlgea Cao 	.detect = rockchip_dw_hdmi_qp_detect,
159428671edaSAlgea Cao 	.get_edid = rockchip_dw_hdmi_qp_get_edid,
159528671edaSAlgea Cao };
159628671edaSAlgea Cao 
1597463abfccSAlgea Cao static const struct rockchip_hdmi_chip_ops rk3576_chip_ops = {
1598463abfccSAlgea Cao 	.set_link_mode = rk3576_set_link_mode,
1599463abfccSAlgea Cao 	.set_color_format = rk3576_set_color_format,
1600463abfccSAlgea Cao 	.io_path_init = rk3576_io_path_init,
1601463abfccSAlgea Cao 	.read_hpd = rk3576_read_hpd,
1602463abfccSAlgea Cao };
1603463abfccSAlgea Cao 
1604463abfccSAlgea Cao const struct dw_hdmi_plat_data rk3576_hdmi_drv_data = {
1605463abfccSAlgea Cao 	.qp_phy_ops    = &rockchip_hdmi_qp_phy_ops,
160628671edaSAlgea Cao 	.phy_name   = "samsung_hdptx_phy",
1607463abfccSAlgea Cao 	.chip_ops   = (void *)&rk3576_chip_ops,
1608463abfccSAlgea Cao 	.dev_type   = RK3576_HDMI,
1609463abfccSAlgea Cao };
1610463abfccSAlgea Cao 
1611463abfccSAlgea Cao static const struct rockchip_hdmi_chip_ops rk3588_chip_ops = {
1612463abfccSAlgea Cao 	.set_link_mode = rk3588_set_link_mode,
1613463abfccSAlgea Cao 	.set_color_format = rk3588_set_color_format,
1614463abfccSAlgea Cao 	.io_path_init = rk3588_io_path_init,
1615463abfccSAlgea Cao 	.read_hpd = rk3588_read_hpd,
1616463abfccSAlgea Cao };
1617463abfccSAlgea Cao 
1618463abfccSAlgea Cao const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = {
1619463abfccSAlgea Cao 	.qp_phy_ops    = &rockchip_hdmi_qp_phy_ops,
1620463abfccSAlgea Cao 	.phy_name   = "samsung_hdptx_phy",
1621463abfccSAlgea Cao 	.chip_ops   = (void *)&rk3588_chip_ops,
162228671edaSAlgea Cao 	.dev_type   = RK3588_HDMI,
162328671edaSAlgea Cao };
162428671edaSAlgea Cao 
rockchip_dw_hdmi_qp_probe(struct udevice * dev)162528671edaSAlgea Cao static int rockchip_dw_hdmi_qp_probe(struct udevice *dev)
162628671edaSAlgea Cao {
162728671edaSAlgea Cao 	int ret;
162828671edaSAlgea Cao 	struct regmap *map;
162928671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = dev_get_priv(dev);
1630463abfccSAlgea Cao 	ofnode hdmi_node = dev->node;
163128671edaSAlgea Cao 
163228671edaSAlgea Cao 	hdmi->dev = dev;
1633463abfccSAlgea Cao 	hdmi->plat_data = (const struct dw_hdmi_plat_data *)dev_get_driver_data(dev);
163428671edaSAlgea Cao 
163528671edaSAlgea Cao 	hdmi->id = of_alias_get_id(ofnode_to_np(dev->node), "hdmi");
163628671edaSAlgea Cao 	if (hdmi->id < 0)
163728671edaSAlgea Cao 		hdmi->id = 0;
163828671edaSAlgea Cao 
1639463abfccSAlgea Cao 	map = syscon_regmap_lookup_by_phandle(dev, "rockchip,grf");
1640463abfccSAlgea Cao 	hdmi->grf = regmap_get_range(map, 0);
164128671edaSAlgea Cao 
164228671edaSAlgea Cao 	if (hdmi->grf <= 0) {
164328671edaSAlgea Cao 		dev_err(dev, "%s: Get syscon grf failed (ret=%p)\n",
164428671edaSAlgea Cao 			__func__, hdmi->grf);
164528671edaSAlgea Cao 		return -ENXIO;
164628671edaSAlgea Cao 	}
164728671edaSAlgea Cao 
1648463abfccSAlgea Cao 	if (hdmi->plat_data->dev_type == RK3588_HDMI) {
164928671edaSAlgea Cao 		map = syscon_regmap_lookup_by_phandle(dev, "rockchip,vo1_grf");
165028671edaSAlgea Cao 		hdmi->vo1_grf = regmap_get_range(map, 0);
165128671edaSAlgea Cao 
165228671edaSAlgea Cao 		if (hdmi->vo1_grf <= 0) {
165328671edaSAlgea Cao 			dev_err(dev, "%s: Get syscon vo1 grf failed (ret=%p)\n",
165428671edaSAlgea Cao 				__func__, hdmi->vo1_grf);
165528671edaSAlgea Cao 			return -ENXIO;
165628671edaSAlgea Cao 		}
1657463abfccSAlgea Cao 	} else if (hdmi->plat_data->dev_type == RK3576_HDMI) {
1658463abfccSAlgea Cao 		map = syscon_regmap_lookup_by_phandle(dev, "rockchip,vo0_grf");
1659463abfccSAlgea Cao 		hdmi->vo0_grf = regmap_get_range(map, 0);
1660463abfccSAlgea Cao 
1661463abfccSAlgea Cao 		if (hdmi->vo0_grf <= 0) {
1662463abfccSAlgea Cao 			dev_err(dev, "%s: Get syscon vo0 grf failed (ret=%p)\n",
1663463abfccSAlgea Cao 				__func__, hdmi->vo0_grf);
1664463abfccSAlgea Cao 			return -ENXIO;
1665463abfccSAlgea Cao 		}
1666463abfccSAlgea Cao 	}
1667463abfccSAlgea Cao 
1668463abfccSAlgea Cao 	hdmi->sda_falling_delay_ns =
1669463abfccSAlgea Cao 		ofnode_read_u32_default(hdmi_node, "rockchip,sda-falling-delay-ns", 0);
167028671edaSAlgea Cao 
167128671edaSAlgea Cao 	ret = gpio_request_by_name(dev, "enable-gpios", 0,
167228671edaSAlgea Cao 				   &hdmi->enable_gpio, GPIOD_IS_OUT);
1673200f72c9SAlgea Cao 	if (ret && ret != -ENOENT) {
167428671edaSAlgea Cao 		dev_err(dev, "Cannot get enable GPIO: %d\n", ret);
167528671edaSAlgea Cao 		return ret;
167628671edaSAlgea Cao 	}
167728671edaSAlgea Cao 
16788c597bcaSAlgea Cao 	ret = clk_get_by_name(dev, "link_clk", &hdmi->link_clk);
16798c597bcaSAlgea Cao 	if (ret) {
16808c597bcaSAlgea Cao 		printf("%s: can't get link_clk\n", __func__);
16818c597bcaSAlgea Cao 		return ret;
16828c597bcaSAlgea Cao 	}
16838c597bcaSAlgea Cao 
1684*4ae62432SAlgea Cao 	hdmi->force_disable_dsc =
1685*4ae62432SAlgea Cao 		ofnode_read_bool(hdmi_node, "force-disable-dsc");
1686*4ae62432SAlgea Cao 
1687463abfccSAlgea Cao 	hdmi->ops = (struct rockchip_hdmi_chip_ops *)hdmi->plat_data->chip_ops;
1688463abfccSAlgea Cao 
16890594ce39SZhang Yubing 	rockchip_connector_bind(&hdmi->connector, dev, hdmi->id, &rockchip_dw_hdmi_qp_funcs,
16900594ce39SZhang Yubing 				NULL, DRM_MODE_CONNECTOR_HDMIA);
16910594ce39SZhang Yubing 
169228671edaSAlgea Cao 	return 0;
169328671edaSAlgea Cao }
169428671edaSAlgea Cao 
169528671edaSAlgea Cao static const struct udevice_id rockchip_dw_hdmi_qp_ids[] = {
169628671edaSAlgea Cao 	{
169728671edaSAlgea Cao 	 .compatible = "rockchip,rk3588-dw-hdmi",
16980594ce39SZhang Yubing 	 .data = (ulong)&rk3588_hdmi_drv_data,
1699463abfccSAlgea Cao 	},
1700463abfccSAlgea Cao 	{
1701463abfccSAlgea Cao 	 .compatible = "rockchip,rk3576-dw-hdmi",
1702463abfccSAlgea Cao 	 .data = (ulong)&rk3576_hdmi_drv_data,
170328671edaSAlgea Cao 	}, {}
170428671edaSAlgea Cao };
170528671edaSAlgea Cao 
170628671edaSAlgea Cao U_BOOT_DRIVER(rockchip_dw_hdmi_qp) = {
170728671edaSAlgea Cao 	.name = "rockchip_dw_hdmi_qp",
170828671edaSAlgea Cao 	.id = UCLASS_DISPLAY,
170928671edaSAlgea Cao 	.of_match = rockchip_dw_hdmi_qp_ids,
171028671edaSAlgea Cao 	.probe	= rockchip_dw_hdmi_qp_probe,
171128671edaSAlgea Cao 	.priv_auto_alloc_size = sizeof(struct rockchip_hdmi),
171228671edaSAlgea Cao };
1713