xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_dw_hdmi_qp.c (revision 97273498da82e2cda5bc4f50d3347cebb6d4442c)
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>
928671edaSAlgea Cao #include <fdtdec.h>
1028671edaSAlgea Cao #include <regmap.h>
1128671edaSAlgea Cao #include <syscon.h>
1228671edaSAlgea Cao #include <asm/arch-rockchip/clock.h>
1328671edaSAlgea Cao #include <asm/io.h>
1428671edaSAlgea Cao #include <asm-generic/gpio.h>
1528671edaSAlgea Cao #include <dm/of_access.h>
1628671edaSAlgea Cao #include <dm/device.h>
1728671edaSAlgea Cao #include <linux/dw_hdmi.h>
1828671edaSAlgea Cao #include <linux/hdmi.h>
1928671edaSAlgea Cao #include <linux/media-bus-format.h>
2028671edaSAlgea Cao #include "rockchip_display.h"
2128671edaSAlgea Cao #include "rockchip_crtc.h"
2228671edaSAlgea Cao #include "rockchip_connector.h"
2328671edaSAlgea Cao #include "rockchip_phy.h"
2428671edaSAlgea Cao #include "dw_hdmi_qp.h"
2528671edaSAlgea Cao #include "rockchip_dw_hdmi_qp.h"
2628671edaSAlgea Cao 
2728671edaSAlgea Cao #define HIWORD_UPDATE(val, mask)	((val) | (mask) << 16)
2828671edaSAlgea Cao 
2928671edaSAlgea Cao #define RK3588_GRF_SOC_CON2		0x0308
3028671edaSAlgea Cao #define RK3588_HDMI1_HPD_INT_MSK	BIT(15)
3128671edaSAlgea Cao #define RK3588_HDMI1_HPD_INT_CLR	BIT(14)
3228671edaSAlgea Cao #define RK3588_HDMI0_HPD_INT_MSK	BIT(13)
3328671edaSAlgea Cao #define RK3588_HDMI0_HPD_INT_CLR	BIT(12)
3428671edaSAlgea Cao #define RK3588_GRF_SOC_CON7		0x031c
3528671edaSAlgea Cao #define RK3588_SET_HPD_PATH_MASK	(0x3 << 12)
3628671edaSAlgea Cao #define RK3588_GRF_SOC_STATUS1		0x0384
3728671edaSAlgea Cao #define RK3588_HDMI0_LOW_MORETHAN100MS	BIT(20)
3828671edaSAlgea Cao #define RK3588_HDMI0_HPD_PORT_LEVEL	BIT(19)
3928671edaSAlgea Cao #define RK3588_HDMI0_IHPD_PORT		BIT(18)
4028671edaSAlgea Cao #define RK3588_HDMI0_OHPD_INT		BIT(17)
4128671edaSAlgea Cao #define RK3588_HDMI0_LEVEL_INT		BIT(16)
4228671edaSAlgea Cao #define RK3588_HDMI0_INTR_CHANGE_CNT	(0x7 << 13)
4328671edaSAlgea Cao #define RK3588_HDMI1_LOW_MORETHAN100MS	BIT(28)
4428671edaSAlgea Cao #define RK3588_HDMI1_HPD_PORT_LEVEL	BIT(27)
4528671edaSAlgea Cao #define RK3588_HDMI1_IHPD_PORT		BIT(26)
4628671edaSAlgea Cao #define RK3588_HDMI1_OHPD_INT		BIT(25)
4728671edaSAlgea Cao #define RK3588_HDMI1_LEVEL_INT		BIT(24)
4828671edaSAlgea Cao #define RK3588_HDMI1_INTR_CHANGE_CNT	(0x7 << 21)
4928671edaSAlgea Cao 
5028671edaSAlgea Cao #define RK3588_GRF_VO1_CON3		0x000c
5128671edaSAlgea Cao #define RK3588_COLOR_FORMAT_MASK	0xf
5228671edaSAlgea Cao #define RK3588_YUV444			0x2
5328671edaSAlgea Cao #define RK3588_YUV420			0x3
5428671edaSAlgea Cao #define RK3588_COMPRESSED_DATA		0xb
5528671edaSAlgea Cao #define RK3588_COLOR_DEPTH_MASK		(0xf << 4)
5628671edaSAlgea Cao #define RK3588_8BPC			(0x5 << 4)
5728671edaSAlgea Cao #define RK3588_10BPC			(0x6 << 4)
5828671edaSAlgea Cao #define RK3588_CECIN_MASK		BIT(8)
5928671edaSAlgea Cao #define RK3588_SCLIN_MASK		BIT(9)
6028671edaSAlgea Cao #define RK3588_SDAIN_MASK		BIT(10)
6128671edaSAlgea Cao #define RK3588_MODE_MASK		BIT(11)
6228671edaSAlgea Cao #define RK3588_COMPRESS_MODE_MASK	BIT(12)
6328671edaSAlgea Cao #define RK3588_I2S_SEL_MASK		BIT(13)
6428671edaSAlgea Cao #define RK3588_SPDIF_SEL_MASK		BIT(14)
6528671edaSAlgea Cao #define RK3588_GRF_VO1_CON4		0x0010
6628671edaSAlgea Cao #define RK3588_HDMI21_MASK		BIT(0)
6728671edaSAlgea Cao #define RK3588_GRF_VO1_CON9		0x0024
6828671edaSAlgea Cao #define RK3588_HDMI0_GRANT_SEL		BIT(10)
6928671edaSAlgea Cao #define RK3588_HDMI0_GRANT_SW		BIT(11)
7028671edaSAlgea Cao #define RK3588_HDMI1_GRANT_SEL		BIT(12)
7128671edaSAlgea Cao #define RK3588_HDMI1_GRANT_SW		BIT(13)
7228671edaSAlgea Cao #define RK3588_GRF_VO1_CON6		0x0018
7328671edaSAlgea Cao #define RK3588_GRF_VO1_CON7		0x001c
7428671edaSAlgea Cao 
7528671edaSAlgea Cao #define PPS_TABLE_LEN 8
7628671edaSAlgea Cao 
7728671edaSAlgea Cao #define COLOR_DEPTH_10BIT		BIT(31)
7828671edaSAlgea Cao #define HDMI_FRL_MODE			BIT(30)
7928671edaSAlgea Cao #define HDMI_EARC_MODE			BIT(29)
8028671edaSAlgea Cao 
8128671edaSAlgea Cao #define HDMI20_MAX_RATE			600000
8228671edaSAlgea Cao #define HDMI_8K60_RATE			2376000
8328671edaSAlgea Cao 
8428671edaSAlgea Cao enum device_type {
8528671edaSAlgea Cao 	RK3588_HDMI
8628671edaSAlgea Cao };
8728671edaSAlgea Cao 
8828671edaSAlgea Cao struct pps_data {
8928671edaSAlgea Cao 	u32 pic_width;
9028671edaSAlgea Cao 	u32 pic_height;
9128671edaSAlgea Cao 	u32 slice_width;
9228671edaSAlgea Cao 	u32 slice_height;
9328671edaSAlgea Cao 	bool convert_rgb;
9428671edaSAlgea Cao 	u8 bpc;
9528671edaSAlgea Cao 	u8 bpp;
9628671edaSAlgea Cao 	u8 raw_pps[128];
9728671edaSAlgea Cao };
9828671edaSAlgea Cao 
9928671edaSAlgea Cao enum hdmi_frl_rate_per_lane {
10028671edaSAlgea Cao 	FRL_12G_PER_LANE = 12,
10128671edaSAlgea Cao 	FRL_10G_PER_LANE = 10,
10228671edaSAlgea Cao 	FRL_8G_PER_LANE = 8,
10328671edaSAlgea Cao 	FRL_6G_PER_LANE = 6,
10428671edaSAlgea Cao 	FRL_3G_PER_LANE = 3,
10528671edaSAlgea Cao };
10628671edaSAlgea Cao 
10728671edaSAlgea Cao struct rockchip_hdmi {
10828671edaSAlgea Cao 	int id;
10928671edaSAlgea Cao 	struct udevice *dev;
11028671edaSAlgea Cao 	struct regmap *regmap;
11128671edaSAlgea Cao 	struct regmap *vo1_regmap;
11228671edaSAlgea Cao 	void *grf;
11328671edaSAlgea Cao 	void *vo1_grf;
11428671edaSAlgea Cao 
11528671edaSAlgea Cao 	unsigned long bus_format;
11628671edaSAlgea Cao 	unsigned long output_bus_format;
11728671edaSAlgea Cao 	unsigned long enc_out_encoding;
11828671edaSAlgea Cao 
11928671edaSAlgea Cao 	u8 max_frl_rate_per_lane;
12028671edaSAlgea Cao 	u8 max_lanes;
12128671edaSAlgea Cao 	u32 bus_width;
12228671edaSAlgea Cao 	struct drm_hdmi_dsc_cap dsc_cap;
12328671edaSAlgea Cao 	struct dw_hdmi_link_config link_cfg;
12428671edaSAlgea Cao 
12528671edaSAlgea Cao 	struct gpio_desc enable_gpio;
12628671edaSAlgea Cao };
12728671edaSAlgea Cao 
12828671edaSAlgea Cao /*
12928671edaSAlgea Cao  * Selected Rate Control Related Parameter Recommended Values
13028671edaSAlgea Cao  * from DSC_v1.11 spec & C Model release: DSC_model_20161212
13128671edaSAlgea Cao  */
13228671edaSAlgea Cao static struct pps_data pps_datas[PPS_TABLE_LEN] = {
13328671edaSAlgea Cao 	{
13428671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 8bpc 12bpp */
13528671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 8, 192,
13628671edaSAlgea Cao 		{
13728671edaSAlgea Cao 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xc0, 0x10, 0xe0,
13828671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
13928671edaSAlgea Cao 			0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
14028671edaSAlgea Cao 			0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
14128671edaSAlgea Cao 			0x08, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
14228671edaSAlgea Cao 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
14328671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
14428671edaSAlgea Cao 			0x7d, 0x7e, 0x00, 0x82, 0x00, 0xc0, 0x09, 0x00,
14528671edaSAlgea Cao 			0x09, 0x7e, 0x19, 0xbc, 0x19, 0xba, 0x19, 0xf8,
14628671edaSAlgea Cao 			0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
14728671edaSAlgea Cao 			0x2a, 0x76, 0x2a, 0x74, 0x3a, 0xb4, 0x52, 0xf4,
14828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14928671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15028671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15128671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
15328671edaSAlgea Cao 		},
15428671edaSAlgea Cao 	},
15528671edaSAlgea Cao 	{
15628671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 8bpc 11bpp */
15728671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 8, 176,
15828671edaSAlgea Cao 		{
15928671edaSAlgea Cao 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xb0, 0x10, 0xe0,
16028671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
16128671edaSAlgea Cao 			0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
16228671edaSAlgea Cao 			0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
16328671edaSAlgea Cao 			0x0f, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
16428671edaSAlgea Cao 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
16528671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
16628671edaSAlgea Cao 			0x7d, 0x7e, 0x00, 0x82, 0x01, 0x00, 0x09, 0x40,
16728671edaSAlgea Cao 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
16828671edaSAlgea Cao 			0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
16928671edaSAlgea Cao 			0x2a, 0x76, 0x2a, 0xb4, 0x3a, 0xb4, 0x52, 0xf4,
17028671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17128671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17328671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17428671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
17528671edaSAlgea Cao 		},
17628671edaSAlgea Cao 	},
17728671edaSAlgea Cao 	{
17828671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 8bpc 10bpp */
17928671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 8, 160,
18028671edaSAlgea Cao 		{
18128671edaSAlgea Cao 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xa0, 0x10, 0xe0,
18228671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
18328671edaSAlgea Cao 			0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
18428671edaSAlgea Cao 			0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
18528671edaSAlgea Cao 			0x16, 0x00, 0x10, 0xec, 0x03, 0x0c, 0x20, 0x00,
18628671edaSAlgea Cao 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
18728671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
18828671edaSAlgea Cao 			0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
18928671edaSAlgea Cao 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
19028671edaSAlgea Cao 			0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
19128671edaSAlgea Cao 			0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x5b, 0x34,
19228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19328671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19428671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19528671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
19728671edaSAlgea Cao 		},
19828671edaSAlgea Cao 	},
19928671edaSAlgea Cao 	{
20028671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 8bpc 9bpp */
20128671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 8, 144,
20228671edaSAlgea Cao 		{
20328671edaSAlgea Cao 			0x12, 0x00, 0x00, 0x8d, 0x30, 0x90, 0x10, 0xe0,
20428671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
20528671edaSAlgea Cao 			0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
20628671edaSAlgea Cao 			0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
20728671edaSAlgea Cao 			0x17, 0x00, 0x10, 0xf1, 0x03, 0x0c, 0x20, 0x00,
20828671edaSAlgea Cao 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
20928671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
21028671edaSAlgea Cao 			0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
21128671edaSAlgea Cao 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
21228671edaSAlgea Cao 			0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
21328671edaSAlgea Cao 			0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x63, 0x74,
21428671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21528671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21728671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
21928671edaSAlgea Cao 		},
22028671edaSAlgea Cao 	},
22128671edaSAlgea Cao 	{
22228671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 10bpc 12bpp */
22328671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 10, 192,
22428671edaSAlgea Cao 		{
22528671edaSAlgea Cao 			0x12, 0x00, 0x00, 0xad, 0x30, 0xc0, 0x10, 0xe0,
22628671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
22728671edaSAlgea Cao 			0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
22828671edaSAlgea Cao 			0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
22928671edaSAlgea Cao 			0x08, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
23028671edaSAlgea Cao 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
23128671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
23228671edaSAlgea Cao 			0x7d, 0x7e, 0x01, 0x02, 0x11, 0x80, 0x22, 0x00,
23328671edaSAlgea Cao 			0x22, 0x7e, 0x32, 0xbc, 0x32, 0xba, 0x3a, 0xf8,
23428671edaSAlgea Cao 			0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
23528671edaSAlgea Cao 			0x4b, 0x76, 0x4b, 0x74, 0x5b, 0xb4, 0x73, 0xf4,
23628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23728671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23928671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24028671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
24128671edaSAlgea Cao 		},
24228671edaSAlgea Cao 	},
24328671edaSAlgea Cao 	{
24428671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 10bpc 11bpp */
24528671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 10, 176,
24628671edaSAlgea Cao 		{
24728671edaSAlgea Cao 			0x12, 0x00, 0x00, 0xad, 0x30, 0xb0, 0x10, 0xe0,
24828671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
24928671edaSAlgea Cao 			0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
25028671edaSAlgea Cao 			0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
25128671edaSAlgea Cao 			0x0f, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
25228671edaSAlgea Cao 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
25328671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
25428671edaSAlgea Cao 			0x7d, 0x7e, 0x01, 0x42, 0x19, 0xc0, 0x2a, 0x40,
25528671edaSAlgea Cao 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
25628671edaSAlgea Cao 			0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
25728671edaSAlgea Cao 			0x4b, 0x76, 0x4b, 0xb4, 0x5b, 0xb4, 0x73, 0xf4,
25828671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25928671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26028671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26128671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
26328671edaSAlgea Cao 		},
26428671edaSAlgea Cao 	},
26528671edaSAlgea Cao 	{
26628671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 10bpc 10bpp */
26728671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 10, 160,
26828671edaSAlgea Cao 		{
26928671edaSAlgea Cao 			0x12, 0x00, 0x00, 0xad, 0x30, 0xa0, 0x10, 0xe0,
27028671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
27128671edaSAlgea Cao 			0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
27228671edaSAlgea Cao 			0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
27328671edaSAlgea Cao 			0x16, 0x00, 0x10, 0xec, 0x07, 0x10, 0x20, 0x00,
27428671edaSAlgea Cao 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
27528671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
27628671edaSAlgea Cao 			0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
27728671edaSAlgea Cao 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
27828671edaSAlgea Cao 			0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
27928671edaSAlgea Cao 			0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x7c, 0x34,
28028671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28128671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28328671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28428671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
28528671edaSAlgea Cao 		},
28628671edaSAlgea Cao 	},
28728671edaSAlgea Cao 	{
28828671edaSAlgea Cao 		/* 7680x4320/960X96 rgb 10bpc 9bpp */
28928671edaSAlgea Cao 		7680, 4320, 960, 96, 1, 10, 144,
29028671edaSAlgea Cao 		{
29128671edaSAlgea Cao 			0x12, 0x00, 0x00, 0xad, 0x30, 0x90, 0x10, 0xe0,
29228671edaSAlgea Cao 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
29328671edaSAlgea Cao 			0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
29428671edaSAlgea Cao 			0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
29528671edaSAlgea Cao 			0x17, 0x00, 0x10, 0xf1, 0x07, 0x10, 0x20, 0x00,
29628671edaSAlgea Cao 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
29728671edaSAlgea Cao 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
29828671edaSAlgea Cao 			0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
29928671edaSAlgea Cao 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
30028671edaSAlgea Cao 			0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
30128671edaSAlgea Cao 			0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x84, 0x74,
30228671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30328671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30428671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30528671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30628671edaSAlgea Cao 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
30728671edaSAlgea Cao 		},
30828671edaSAlgea Cao 	},
30928671edaSAlgea Cao };
31028671edaSAlgea Cao 
31128671edaSAlgea Cao static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
31228671edaSAlgea Cao {
31328671edaSAlgea Cao 	switch (bus_format) {
31428671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB888_1X24:
31528671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB101010_1X30:
31628671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB121212_1X36:
31728671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB161616_1X48:
31828671edaSAlgea Cao 		return true;
31928671edaSAlgea Cao 
32028671edaSAlgea Cao 	default:
32128671edaSAlgea Cao 		return false;
32228671edaSAlgea Cao 	}
32328671edaSAlgea Cao }
32428671edaSAlgea Cao 
32528671edaSAlgea Cao static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
32628671edaSAlgea Cao {
32728671edaSAlgea Cao 	switch (bus_format) {
32828671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV8_1X24:
32928671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV10_1X30:
33028671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV12_1X36:
33128671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV16_1X48:
33228671edaSAlgea Cao 		return true;
33328671edaSAlgea Cao 
33428671edaSAlgea Cao 	default:
33528671edaSAlgea Cao 		return false;
33628671edaSAlgea Cao 	}
33728671edaSAlgea Cao }
33828671edaSAlgea Cao 
33928671edaSAlgea Cao static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
34028671edaSAlgea Cao {
34128671edaSAlgea Cao 	switch (bus_format) {
34228671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY8_1X16:
34328671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY10_1X20:
34428671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY12_1X24:
34528671edaSAlgea Cao 		return true;
34628671edaSAlgea Cao 
34728671edaSAlgea Cao 	default:
34828671edaSAlgea Cao 		return false;
34928671edaSAlgea Cao 	}
35028671edaSAlgea Cao }
35128671edaSAlgea Cao 
35228671edaSAlgea Cao static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
35328671edaSAlgea Cao {
35428671edaSAlgea Cao 	switch (bus_format) {
35528671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
35628671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
35728671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
35828671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
35928671edaSAlgea Cao 		return true;
36028671edaSAlgea Cao 
36128671edaSAlgea Cao 	default:
36228671edaSAlgea Cao 	return false;
36328671edaSAlgea Cao 	}
36428671edaSAlgea Cao }
36528671edaSAlgea Cao 
36628671edaSAlgea Cao static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
36728671edaSAlgea Cao {
36828671edaSAlgea Cao 	switch (bus_format) {
36928671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB888_1X24:
37028671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV8_1X24:
37128671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY8_1X16:
37228671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
37328671edaSAlgea Cao 		return 8;
37428671edaSAlgea Cao 
37528671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB101010_1X30:
37628671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV10_1X30:
37728671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY10_1X20:
37828671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
37928671edaSAlgea Cao 		return 10;
38028671edaSAlgea Cao 
38128671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB121212_1X36:
38228671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV12_1X36:
38328671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYVY12_1X24:
38428671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
38528671edaSAlgea Cao 		return 12;
38628671edaSAlgea Cao 
38728671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB161616_1X48:
38828671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV16_1X48:
38928671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
39028671edaSAlgea Cao 		return 16;
39128671edaSAlgea Cao 
39228671edaSAlgea Cao 	default:
39328671edaSAlgea Cao 		return 0;
39428671edaSAlgea Cao 	}
39528671edaSAlgea Cao }
39628671edaSAlgea Cao 
39728671edaSAlgea Cao static unsigned int
39828671edaSAlgea Cao hdmi_get_tmdsclock(struct rockchip_hdmi *hdmi, unsigned long pixelclock)
39928671edaSAlgea Cao {
40028671edaSAlgea Cao 	unsigned int tmdsclock = pixelclock;
40128671edaSAlgea Cao 	unsigned int depth =
40228671edaSAlgea Cao 		hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
40328671edaSAlgea Cao 
40428671edaSAlgea Cao 	if (!hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format)) {
40528671edaSAlgea Cao 		switch (depth) {
40628671edaSAlgea Cao 		case 16:
40728671edaSAlgea Cao 			tmdsclock = pixelclock * 2;
40828671edaSAlgea Cao 			break;
40928671edaSAlgea Cao 		case 12:
41028671edaSAlgea Cao 			tmdsclock = pixelclock * 3 / 2;
41128671edaSAlgea Cao 			break;
41228671edaSAlgea Cao 		case 10:
41328671edaSAlgea Cao 			tmdsclock = pixelclock * 5 / 4;
41428671edaSAlgea Cao 			break;
41528671edaSAlgea Cao 		default:
41628671edaSAlgea Cao 			break;
41728671edaSAlgea Cao 		}
41828671edaSAlgea Cao 	}
41928671edaSAlgea Cao 
42028671edaSAlgea Cao 	return tmdsclock;
42128671edaSAlgea Cao }
42228671edaSAlgea Cao 
42328671edaSAlgea Cao static void hdmi_select_link_config(struct rockchip_hdmi *hdmi,
42428671edaSAlgea Cao 				    struct drm_display_mode *mode,
42528671edaSAlgea Cao 				    unsigned int tmdsclk)
42628671edaSAlgea Cao {
42728671edaSAlgea Cao 	int max_lanes, max_rate_per_lane;
42828671edaSAlgea Cao 	int max_dsc_lanes, max_dsc_rate_per_lane;
42928671edaSAlgea Cao 	unsigned long max_frl_rate;
43028671edaSAlgea Cao 
43128671edaSAlgea Cao 	max_lanes = hdmi->max_lanes;
43228671edaSAlgea Cao 	max_rate_per_lane = hdmi->max_frl_rate_per_lane;
43328671edaSAlgea Cao 	max_frl_rate = max_lanes * max_rate_per_lane * 1000000;
43428671edaSAlgea Cao 
43528671edaSAlgea Cao 	hdmi->link_cfg.dsc_mode = false;
43628671edaSAlgea Cao 	hdmi->link_cfg.frl_lanes = max_lanes;
43728671edaSAlgea Cao 	hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
43828671edaSAlgea Cao 
43928671edaSAlgea Cao 	if (!max_frl_rate || tmdsclk < HDMI20_MAX_RATE) {
44028671edaSAlgea Cao 		printf("%s use tmds mode\n", __func__);
44128671edaSAlgea Cao 		hdmi->link_cfg.frl_mode = false;
44228671edaSAlgea Cao 		return;
44328671edaSAlgea Cao 	}
44428671edaSAlgea Cao 
44528671edaSAlgea Cao 	hdmi->link_cfg.frl_mode = true;
44628671edaSAlgea Cao 
44728671edaSAlgea Cao 	if (!hdmi->dsc_cap.v_1p2)
44828671edaSAlgea Cao 		return;
44928671edaSAlgea Cao 
45028671edaSAlgea Cao 	max_dsc_lanes = hdmi->dsc_cap.max_lanes;
45128671edaSAlgea Cao 	max_dsc_rate_per_lane =
45228671edaSAlgea Cao 		hdmi->dsc_cap.max_frl_rate_per_lane;
45328671edaSAlgea Cao 
45428671edaSAlgea Cao 	if (mode->clock >= HDMI_8K60_RATE &&
45528671edaSAlgea Cao 	    !hdmi_bus_fmt_is_yuv420(hdmi->bus_format) &&
45628671edaSAlgea Cao 	    !hdmi_bus_fmt_is_yuv422(hdmi->bus_format)) {
45728671edaSAlgea Cao 		hdmi->link_cfg.dsc_mode = true;
45828671edaSAlgea Cao 		hdmi->link_cfg.frl_lanes = max_dsc_lanes;
45928671edaSAlgea Cao 		hdmi->link_cfg.rate_per_lane = max_dsc_rate_per_lane;
46028671edaSAlgea Cao 	} else {
46128671edaSAlgea Cao 		hdmi->link_cfg.dsc_mode = false;
46228671edaSAlgea Cao 		hdmi->link_cfg.frl_lanes = max_lanes;
46328671edaSAlgea Cao 		hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
46428671edaSAlgea Cao 	}
46528671edaSAlgea Cao }
46628671edaSAlgea Cao 
46728671edaSAlgea Cao /////////////////////////////////////////////////////////////////////////////////////
46828671edaSAlgea Cao 
46928671edaSAlgea Cao static int hdmi_dsc_get_slice_height(int vactive)
47028671edaSAlgea Cao {
47128671edaSAlgea Cao 	int slice_height;
47228671edaSAlgea Cao 
47328671edaSAlgea Cao 	/*
47428671edaSAlgea Cao 	 * Slice Height determination : HDMI2.1 Section 7.7.5.2
47528671edaSAlgea Cao 	 * Select smallest slice height >=96, that results in a valid PPS and
47628671edaSAlgea Cao 	 * requires minimum padding lines required for final slice.
47728671edaSAlgea Cao 	 *
47828671edaSAlgea Cao 	 * Assumption : Vactive is even.
47928671edaSAlgea Cao 	 */
48028671edaSAlgea Cao 	for (slice_height = 96; slice_height <= vactive; slice_height += 2)
48128671edaSAlgea Cao 		if (vactive % slice_height == 0)
48228671edaSAlgea Cao 			return slice_height;
48328671edaSAlgea Cao 
48428671edaSAlgea Cao 	return 0;
48528671edaSAlgea Cao }
48628671edaSAlgea Cao 
48728671edaSAlgea Cao static int hdmi_dsc_get_num_slices(struct rockchip_hdmi *hdmi,
48828671edaSAlgea Cao 				   struct drm_display_mode *mode,
48928671edaSAlgea Cao 				   int src_max_slices, int src_max_slice_width,
49028671edaSAlgea Cao 				   int hdmi_max_slices, int hdmi_throughput)
49128671edaSAlgea Cao {
49228671edaSAlgea Cao /* Pixel rates in KPixels/sec */
49328671edaSAlgea Cao #define HDMI_DSC_PEAK_PIXEL_RATE		2720000
49428671edaSAlgea Cao /*
49528671edaSAlgea Cao  * Rates at which the source and sink are required to process pixels in each
49628671edaSAlgea Cao  * slice, can be two levels: either at least 340000KHz or at least 40000KHz.
49728671edaSAlgea Cao  */
49828671edaSAlgea Cao #define HDMI_DSC_MAX_ENC_THROUGHPUT_0		340000
49928671edaSAlgea Cao #define HDMI_DSC_MAX_ENC_THROUGHPUT_1		400000
50028671edaSAlgea Cao 
50128671edaSAlgea Cao /* Spec limits the slice width to 2720 pixels */
50228671edaSAlgea Cao #define MAX_HDMI_SLICE_WIDTH			2720
50328671edaSAlgea Cao 	int kslice_adjust;
50428671edaSAlgea Cao 	int adjusted_clk_khz;
50528671edaSAlgea Cao 	int min_slices;
50628671edaSAlgea Cao 	int target_slices;
50728671edaSAlgea Cao 	int max_throughput; /* max clock freq. in khz per slice */
50828671edaSAlgea Cao 	int max_slice_width;
50928671edaSAlgea Cao 	int slice_width;
51028671edaSAlgea Cao 	int pixel_clock = mode->clock;
51128671edaSAlgea Cao 
51228671edaSAlgea Cao 	if (!hdmi_throughput)
51328671edaSAlgea Cao 		return 0;
51428671edaSAlgea Cao 
51528671edaSAlgea Cao 	/*
51628671edaSAlgea Cao 	 * Slice Width determination : HDMI2.1 Section 7.7.5.1
51728671edaSAlgea Cao 	 * kslice_adjust factor for 4:2:0, and 4:2:2 formats is 0.5, where as
51828671edaSAlgea Cao 	 * for 4:4:4 is 1.0. Multiplying these factors by 10 and later
51928671edaSAlgea Cao 	 * dividing adjusted clock value by 10.
52028671edaSAlgea Cao 	 */
52128671edaSAlgea Cao 	if (hdmi_bus_fmt_is_yuv444(hdmi->output_bus_format) ||
52228671edaSAlgea Cao 	    hdmi_bus_fmt_is_rgb(hdmi->output_bus_format))
52328671edaSAlgea Cao 		kslice_adjust = 10;
52428671edaSAlgea Cao 	else
52528671edaSAlgea Cao 		kslice_adjust = 5;
52628671edaSAlgea Cao 
52728671edaSAlgea Cao 	/*
52828671edaSAlgea Cao 	 * As per spec, the rate at which the source and the sink process
52928671edaSAlgea Cao 	 * the pixels per slice are at two levels: at least 340Mhz or 400Mhz.
53028671edaSAlgea Cao 	 * This depends upon the pixel clock rate and output formats
53128671edaSAlgea Cao 	 * (kslice adjust).
53228671edaSAlgea Cao 	 * If pixel clock * kslice adjust >= 2720MHz slices can be processed
53328671edaSAlgea Cao 	 * at max 340MHz, otherwise they can be processed at max 400MHz.
53428671edaSAlgea Cao 	 */
53528671edaSAlgea Cao 
53628671edaSAlgea Cao 	adjusted_clk_khz = DIV_ROUND_UP(kslice_adjust * pixel_clock, 10);
53728671edaSAlgea Cao 
53828671edaSAlgea Cao 	if (adjusted_clk_khz <= HDMI_DSC_PEAK_PIXEL_RATE)
53928671edaSAlgea Cao 		max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_0;
54028671edaSAlgea Cao 	else
54128671edaSAlgea Cao 		max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_1;
54228671edaSAlgea Cao 
54328671edaSAlgea Cao 	/*
54428671edaSAlgea Cao 	 * Taking into account the sink's capability for maximum
54528671edaSAlgea Cao 	 * clock per slice (in MHz) as read from HF-VSDB.
54628671edaSAlgea Cao 	 */
54728671edaSAlgea Cao 	max_throughput = min(max_throughput, hdmi_throughput * 1000);
54828671edaSAlgea Cao 
54928671edaSAlgea Cao 	min_slices = DIV_ROUND_UP(adjusted_clk_khz, max_throughput);
55028671edaSAlgea Cao 	max_slice_width = min(MAX_HDMI_SLICE_WIDTH, src_max_slice_width);
55128671edaSAlgea Cao 
55228671edaSAlgea Cao 	/*
55328671edaSAlgea Cao 	 * Keep on increasing the num of slices/line, starting from min_slices
55428671edaSAlgea Cao 	 * per line till we get such a number, for which the slice_width is
55528671edaSAlgea Cao 	 * just less than max_slice_width. The slices/line selected should be
55628671edaSAlgea Cao 	 * less than or equal to the max horizontal slices that the combination
55728671edaSAlgea Cao 	 * of PCON encoder and HDMI decoder can support.
55828671edaSAlgea Cao 	 */
55928671edaSAlgea Cao 	do {
56028671edaSAlgea Cao 		if (min_slices <= 1 && src_max_slices >= 1 && hdmi_max_slices >= 1)
56128671edaSAlgea Cao 			target_slices = 1;
56228671edaSAlgea Cao 		else if (min_slices <= 2 && src_max_slices >= 2 && hdmi_max_slices >= 2)
56328671edaSAlgea Cao 			target_slices = 2;
56428671edaSAlgea Cao 		else if (min_slices <= 4 && src_max_slices >= 4 && hdmi_max_slices >= 4)
56528671edaSAlgea Cao 			target_slices = 4;
56628671edaSAlgea Cao 		else if (min_slices <= 8 && src_max_slices >= 8 && hdmi_max_slices >= 8)
56728671edaSAlgea Cao 			target_slices = 8;
56828671edaSAlgea Cao 		else if (min_slices <= 12 && src_max_slices >= 12 && hdmi_max_slices >= 12)
56928671edaSAlgea Cao 			target_slices = 12;
57028671edaSAlgea Cao 		else if (min_slices <= 16 && src_max_slices >= 16 && hdmi_max_slices >= 16)
57128671edaSAlgea Cao 			target_slices = 16;
57228671edaSAlgea Cao 		else
57328671edaSAlgea Cao 			return 0;
57428671edaSAlgea Cao 
57528671edaSAlgea Cao 		slice_width = DIV_ROUND_UP(mode->hdisplay, target_slices);
57628671edaSAlgea Cao 		if (slice_width > max_slice_width)
57728671edaSAlgea Cao 			min_slices = target_slices + 1;
57828671edaSAlgea Cao 	} while (slice_width > max_slice_width);
57928671edaSAlgea Cao 
58028671edaSAlgea Cao 	return target_slices;
58128671edaSAlgea Cao }
58228671edaSAlgea Cao 
58328671edaSAlgea Cao static int hdmi_dsc_slices(struct rockchip_hdmi *hdmi,
58428671edaSAlgea Cao 			   struct drm_display_mode *mode)
58528671edaSAlgea Cao {
58628671edaSAlgea Cao 	int hdmi_throughput = hdmi->dsc_cap.clk_per_slice;
58728671edaSAlgea Cao 	int hdmi_max_slices = hdmi->dsc_cap.max_slices;
58828671edaSAlgea Cao 	int rk_max_slices = 8;
58928671edaSAlgea Cao 	int rk_max_slice_width = 2048;
59028671edaSAlgea Cao 
59128671edaSAlgea Cao 	return hdmi_dsc_get_num_slices(hdmi, mode, rk_max_slices,
59228671edaSAlgea Cao 				       rk_max_slice_width,
59328671edaSAlgea Cao 				       hdmi_max_slices, hdmi_throughput);
59428671edaSAlgea Cao }
59528671edaSAlgea Cao 
59628671edaSAlgea Cao static int
59728671edaSAlgea Cao hdmi_dsc_get_bpp(struct rockchip_hdmi *hdmi, int src_fractional_bpp,
59828671edaSAlgea Cao 		 int slice_width, int num_slices, bool hdmi_all_bpp,
59928671edaSAlgea Cao 		 int hdmi_max_chunk_bytes)
60028671edaSAlgea Cao {
60128671edaSAlgea Cao 	int max_dsc_bpp, min_dsc_bpp;
60228671edaSAlgea Cao 	int target_bytes;
60328671edaSAlgea Cao 	bool bpp_found = false;
60428671edaSAlgea Cao 	int bpp_decrement_x16;
60528671edaSAlgea Cao 	int bpp_target;
60628671edaSAlgea Cao 	int bpp_target_x16;
60728671edaSAlgea Cao 
60828671edaSAlgea Cao 	/*
60928671edaSAlgea Cao 	 * Get min bpp and max bpp as per Table 7.23, in HDMI2.1 spec
61028671edaSAlgea Cao 	 * Start with the max bpp and keep on decrementing with
61128671edaSAlgea Cao 	 * fractional bpp, if supported by PCON DSC encoder
61228671edaSAlgea Cao 	 *
61328671edaSAlgea Cao 	 * for each bpp we check if no of bytes can be supported by HDMI sink
61428671edaSAlgea Cao 	 */
61528671edaSAlgea Cao 
61628671edaSAlgea Cao 	/* only 9\10\12 bpp was tested */
61728671edaSAlgea Cao 	min_dsc_bpp = 9;
61828671edaSAlgea Cao 	max_dsc_bpp = 12;
61928671edaSAlgea Cao 
62028671edaSAlgea Cao 	/*
62128671edaSAlgea Cao 	 * Taking into account if all dsc_all_bpp supported by HDMI2.1 sink
62228671edaSAlgea Cao 	 * Section 7.7.34 : Source shall not enable compressed Video
62328671edaSAlgea Cao 	 * Transport with bpp_target settings above 12 bpp unless
62428671edaSAlgea Cao 	 * DSC_all_bpp is set to 1.
62528671edaSAlgea Cao 	 */
62628671edaSAlgea Cao 	if (!hdmi_all_bpp)
62728671edaSAlgea Cao 		max_dsc_bpp = min(max_dsc_bpp, 12);
62828671edaSAlgea Cao 
62928671edaSAlgea Cao 	/*
63028671edaSAlgea Cao 	 * The Sink has a limit of compressed data in bytes for a scanline,
63128671edaSAlgea Cao 	 * as described in max_chunk_bytes field in HFVSDB block of edid.
63228671edaSAlgea Cao 	 * The no. of bytes depend on the target bits per pixel that the
63328671edaSAlgea Cao 	 * source configures. So we start with the max_bpp and calculate
63428671edaSAlgea Cao 	 * the target_chunk_bytes. We keep on decrementing the target_bpp,
63528671edaSAlgea Cao 	 * till we get the target_chunk_bytes just less than what the sink's
63628671edaSAlgea Cao 	 * max_chunk_bytes, or else till we reach the min_dsc_bpp.
63728671edaSAlgea Cao 	 *
63828671edaSAlgea Cao 	 * The decrement is according to the fractional support from PCON DSC
63928671edaSAlgea Cao 	 * encoder. For fractional BPP we use bpp_target as a multiple of 16.
64028671edaSAlgea Cao 	 *
64128671edaSAlgea Cao 	 * bpp_target_x16 = bpp_target * 16
64228671edaSAlgea Cao 	 * So we need to decrement by {1, 2, 4, 8, 16} for fractional bpps
64328671edaSAlgea Cao 	 * {1/16, 1/8, 1/4, 1/2, 1} respectively.
64428671edaSAlgea Cao 	 */
64528671edaSAlgea Cao 
64628671edaSAlgea Cao 	bpp_target = max_dsc_bpp;
64728671edaSAlgea Cao 
64828671edaSAlgea Cao 	/* src does not support fractional bpp implies decrement by 16 for bppx16 */
64928671edaSAlgea Cao 	if (!src_fractional_bpp)
65028671edaSAlgea Cao 		src_fractional_bpp = 1;
65128671edaSAlgea Cao 	bpp_decrement_x16 = DIV_ROUND_UP(16, src_fractional_bpp);
65228671edaSAlgea Cao 	bpp_target_x16 = bpp_target * 16;
65328671edaSAlgea Cao 
65428671edaSAlgea Cao 	while (bpp_target_x16 > (min_dsc_bpp * 16)) {
65528671edaSAlgea Cao 		int bpp;
65628671edaSAlgea Cao 
65728671edaSAlgea Cao 		bpp = DIV_ROUND_UP(bpp_target_x16, 16);
65828671edaSAlgea Cao 		target_bytes = DIV_ROUND_UP((num_slices * slice_width * bpp), 8);
65928671edaSAlgea Cao 		if (target_bytes <= hdmi_max_chunk_bytes) {
66028671edaSAlgea Cao 			bpp_found = true;
66128671edaSAlgea Cao 			break;
66228671edaSAlgea Cao 		}
66328671edaSAlgea Cao 		bpp_target_x16 -= bpp_decrement_x16;
66428671edaSAlgea Cao 	}
66528671edaSAlgea Cao 	if (bpp_found)
66628671edaSAlgea Cao 		return bpp_target_x16;
66728671edaSAlgea Cao 
66828671edaSAlgea Cao 	return 0;
66928671edaSAlgea Cao }
67028671edaSAlgea Cao 
67128671edaSAlgea Cao static int
67228671edaSAlgea Cao dw_hdmi_dsc_bpp(struct rockchip_hdmi *hdmi,
67328671edaSAlgea Cao 		int num_slices, int slice_width)
67428671edaSAlgea Cao {
67528671edaSAlgea Cao 	bool hdmi_all_bpp = hdmi->dsc_cap.all_bpp;
67628671edaSAlgea Cao 	int fractional_bpp = 0;
67728671edaSAlgea Cao 	int hdmi_max_chunk_bytes = hdmi->dsc_cap.total_chunk_kbytes * 1024;
67828671edaSAlgea Cao 
67928671edaSAlgea Cao 	return hdmi_dsc_get_bpp(hdmi, fractional_bpp, slice_width,
68028671edaSAlgea Cao 				num_slices, hdmi_all_bpp,
68128671edaSAlgea Cao 				hdmi_max_chunk_bytes);
68228671edaSAlgea Cao }
68328671edaSAlgea Cao 
68428671edaSAlgea Cao static int dw_hdmi_qp_set_link_cfg(struct rockchip_hdmi *hdmi,
68528671edaSAlgea Cao 				   u16 pic_width, u16 pic_height,
68628671edaSAlgea Cao 				   u16 slice_width, u16 slice_height,
68728671edaSAlgea Cao 				   u16 bits_per_pixel, u8 bits_per_component)
68828671edaSAlgea Cao {
68928671edaSAlgea Cao 	int i;
69028671edaSAlgea Cao 
69128671edaSAlgea Cao 	for (i = 0; i < PPS_TABLE_LEN; i++)
69228671edaSAlgea Cao 		if (pic_width == pps_datas[i].pic_width &&
69328671edaSAlgea Cao 		    pic_height == pps_datas[i].pic_height &&
69428671edaSAlgea Cao 		    slice_width == pps_datas[i].slice_width &&
69528671edaSAlgea Cao 		    slice_height == pps_datas[i].slice_height &&
69628671edaSAlgea Cao 		    bits_per_component == pps_datas[i].bpc &&
69728671edaSAlgea Cao 		    bits_per_pixel == pps_datas[i].bpp &&
69828671edaSAlgea Cao 		    hdmi_bus_fmt_is_rgb(hdmi->output_bus_format) == pps_datas[i].convert_rgb)
69928671edaSAlgea Cao 			break;
70028671edaSAlgea Cao 
70128671edaSAlgea Cao 	if (i == PPS_TABLE_LEN) {
70228671edaSAlgea Cao 		dev_err(hdmi->dev, "can't find pps cfg!\n");
70328671edaSAlgea Cao 		return -EINVAL;
70428671edaSAlgea Cao 	}
70528671edaSAlgea Cao 
70628671edaSAlgea Cao 	memcpy(hdmi->link_cfg.pps_payload, pps_datas[i].raw_pps, 128);
70728671edaSAlgea Cao 	hdmi->link_cfg.hcactive = DIV_ROUND_UP(slice_width * (bits_per_pixel / 16), 8) *
70828671edaSAlgea Cao 		(pic_width / slice_width);
70928671edaSAlgea Cao 
71028671edaSAlgea Cao 	return 0;
71128671edaSAlgea Cao }
71228671edaSAlgea Cao 
71328671edaSAlgea Cao static void dw_hdmi_qp_dsc_configure(struct rockchip_hdmi *hdmi,
71428671edaSAlgea Cao 				     struct drm_display_mode *mode)
71528671edaSAlgea Cao {
71628671edaSAlgea Cao 	int ret;
71728671edaSAlgea Cao 	int slice_height;
71828671edaSAlgea Cao 	int slice_width;
71928671edaSAlgea Cao 	int bits_per_pixel;
72028671edaSAlgea Cao 	int slice_count;
72128671edaSAlgea Cao 	bool hdmi_is_dsc_1_2;
72228671edaSAlgea Cao 	unsigned int depth = hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
72328671edaSAlgea Cao 
72428671edaSAlgea Cao 	hdmi_is_dsc_1_2 = hdmi->dsc_cap.v_1p2;
72528671edaSAlgea Cao 
72628671edaSAlgea Cao 	if (!hdmi_is_dsc_1_2)
72728671edaSAlgea Cao 		return;
72828671edaSAlgea Cao 
72928671edaSAlgea Cao 	slice_height = hdmi_dsc_get_slice_height(mode->vdisplay);
73028671edaSAlgea Cao 	if (!slice_height)
73128671edaSAlgea Cao 		return;
73228671edaSAlgea Cao 
73328671edaSAlgea Cao 	slice_count = hdmi_dsc_slices(hdmi, mode);
73428671edaSAlgea Cao 	if (!slice_count)
73528671edaSAlgea Cao 		return;
73628671edaSAlgea Cao 
73728671edaSAlgea Cao 	slice_width = DIV_ROUND_UP(mode->hdisplay, slice_count);
73828671edaSAlgea Cao 
73928671edaSAlgea Cao 	bits_per_pixel = dw_hdmi_dsc_bpp(hdmi, slice_count, slice_width);
74028671edaSAlgea Cao 	if (!bits_per_pixel)
74128671edaSAlgea Cao 		return;
74228671edaSAlgea Cao 
74328671edaSAlgea Cao 	ret = dw_hdmi_qp_set_link_cfg(hdmi, mode->hdisplay,
74428671edaSAlgea Cao 				      mode->vdisplay, slice_width,
74528671edaSAlgea Cao 				      slice_height, bits_per_pixel, depth);
74628671edaSAlgea Cao 
74728671edaSAlgea Cao 	if (ret) {
74828671edaSAlgea Cao 		dev_err(hdmi->dev, "set vdsc cfg failed\n");
74928671edaSAlgea Cao 		return;
75028671edaSAlgea Cao 	}
75128671edaSAlgea Cao 	printf("dsc_enable\n");
75228671edaSAlgea Cao }
75328671edaSAlgea Cao 
75428671edaSAlgea Cao static unsigned int drm_rk_select_color(struct hdmi_edid_data *edid_data,
75528671edaSAlgea Cao 					struct base_screen_info *screen_info,
75628671edaSAlgea Cao 					enum dw_hdmi_devtype dev_type,
75728671edaSAlgea Cao 					bool output_bus_format_rgb)
75828671edaSAlgea Cao {
75928671edaSAlgea Cao 	struct drm_display_info *info = &edid_data->display_info;
76028671edaSAlgea Cao 	struct drm_display_mode *mode = edid_data->preferred_mode;
76128671edaSAlgea Cao 	int max_tmds_clock = info->max_tmds_clock;
76228671edaSAlgea Cao 	bool support_dc = false;
76328671edaSAlgea Cao 	bool mode_420 = drm_mode_is_420(info, mode);
76428671edaSAlgea Cao 	unsigned int color_depth = 8;
76528671edaSAlgea Cao 	unsigned int base_color = DRM_HDMI_OUTPUT_DEFAULT_RGB;
76628671edaSAlgea Cao 	unsigned int color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
76728671edaSAlgea Cao 	unsigned long tmdsclock, pixclock = mode->clock;
76828671edaSAlgea Cao 
76928671edaSAlgea Cao 	if (screen_info)
77028671edaSAlgea Cao 		base_color = screen_info->format;
77128671edaSAlgea Cao 
77228671edaSAlgea Cao 	switch (base_color) {
77328671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR_HQ:
77428671edaSAlgea Cao 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
77528671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
77628671edaSAlgea Cao 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
77728671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
77828671edaSAlgea Cao 		else if (mode_420)
77928671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
78028671edaSAlgea Cao 		break;
78128671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR_LQ:
78228671edaSAlgea Cao 		if (mode_420)
78328671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
78428671edaSAlgea Cao 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
78528671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
78628671edaSAlgea Cao 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
78728671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
78828671edaSAlgea Cao 		break;
78928671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR420:
79028671edaSAlgea Cao 		if (mode_420)
79128671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
79228671edaSAlgea Cao 		break;
79328671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR422:
79428671edaSAlgea Cao 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
79528671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
79628671edaSAlgea Cao 		break;
79728671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_YCBCR444:
79828671edaSAlgea Cao 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
79928671edaSAlgea Cao 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
80028671edaSAlgea Cao 		break;
80128671edaSAlgea Cao 	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
80228671edaSAlgea Cao 	default:
80328671edaSAlgea Cao 		break;
80428671edaSAlgea Cao 	}
80528671edaSAlgea Cao 
80628671edaSAlgea Cao 	if (output_bus_format_rgb)
80728671edaSAlgea Cao 		color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
80828671edaSAlgea Cao 
80928671edaSAlgea Cao 	if (pixclock > 340000)
81028671edaSAlgea Cao 		color_format = DRM_HDMI_OUTPUT_YCBCR420;
81128671edaSAlgea Cao 
81228671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_DEFAULT_RGB &&
81328671edaSAlgea Cao 	    info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
81428671edaSAlgea Cao 		support_dc = true;
81528671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR444 &&
81628671edaSAlgea Cao 	    (info->edid_hdmi_dc_modes &
81728671edaSAlgea Cao 	     (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30)))
81828671edaSAlgea Cao 		support_dc = true;
81928671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422)
82028671edaSAlgea Cao 		support_dc = true;
82128671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420 &&
82228671edaSAlgea Cao 	    info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
82328671edaSAlgea Cao 		support_dc = true;
82428671edaSAlgea Cao 
82528671edaSAlgea Cao 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
82628671edaSAlgea Cao 		pixclock *= 2;
82728671edaSAlgea Cao 
82828671edaSAlgea Cao 	if (screen_info && screen_info->depth == 10)
82928671edaSAlgea Cao 		color_depth = screen_info->depth;
83028671edaSAlgea Cao 
83128671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422 || color_depth == 8)
83228671edaSAlgea Cao 		tmdsclock = pixclock;
83328671edaSAlgea Cao 	else
83428671edaSAlgea Cao 		tmdsclock = pixclock * color_depth / 8;
83528671edaSAlgea Cao 
83628671edaSAlgea Cao 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420)
83728671edaSAlgea Cao 		tmdsclock /= 2;
83828671edaSAlgea Cao 
83928671edaSAlgea Cao 	if (!max_tmds_clock)
84028671edaSAlgea Cao 		max_tmds_clock = 340000;
84128671edaSAlgea Cao 
84228671edaSAlgea Cao 	if (tmdsclock > max_tmds_clock) {
84328671edaSAlgea Cao 		if (max_tmds_clock >= 594000) {
84428671edaSAlgea Cao 			color_depth = 8;
84528671edaSAlgea Cao 		} else if (max_tmds_clock > 340000) {
84628671edaSAlgea Cao 			if (drm_mode_is_420(info, mode))
84728671edaSAlgea Cao 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
84828671edaSAlgea Cao 		} else {
84928671edaSAlgea Cao 			color_depth = 8;
85028671edaSAlgea Cao 			if (drm_mode_is_420(info, mode))
85128671edaSAlgea Cao 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
85228671edaSAlgea Cao 		}
85328671edaSAlgea Cao 	}
85428671edaSAlgea Cao 
85528671edaSAlgea Cao 	printf("color_format:%x\n", color_format);
85628671edaSAlgea Cao 	if (color_depth > 8 && support_dc) {
85728671edaSAlgea Cao 		switch (color_format) {
85828671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR444:
85928671edaSAlgea Cao 			return MEDIA_BUS_FMT_YUV10_1X30;
86028671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR422:
86128671edaSAlgea Cao 			return MEDIA_BUS_FMT_UYVY10_1X20;
86228671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR420:
86328671edaSAlgea Cao 			return MEDIA_BUS_FMT_UYYVYY10_0_5X30;
86428671edaSAlgea Cao 		default:
86528671edaSAlgea Cao 			return MEDIA_BUS_FMT_RGB101010_1X30;
86628671edaSAlgea Cao 		}
86728671edaSAlgea Cao 	} else {
86828671edaSAlgea Cao 		switch (color_format) {
86928671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR444:
87028671edaSAlgea Cao 			return MEDIA_BUS_FMT_YUV8_1X24;
87128671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR422:
87228671edaSAlgea Cao 			return MEDIA_BUS_FMT_UYVY8_1X16;
87328671edaSAlgea Cao 		case DRM_HDMI_OUTPUT_YCBCR420:
87428671edaSAlgea Cao 			return MEDIA_BUS_FMT_UYYVYY8_0_5X24;
87528671edaSAlgea Cao 		default:
87628671edaSAlgea Cao 			return MEDIA_BUS_FMT_RGB888_1X24;
87728671edaSAlgea Cao 		}
87828671edaSAlgea Cao 	}
87928671edaSAlgea Cao }
88028671edaSAlgea Cao 
88128671edaSAlgea Cao void dw_hdmi_qp_selete_output(struct hdmi_edid_data *edid_data,
88228671edaSAlgea Cao 			      struct connector_state *conn_state,
88328671edaSAlgea Cao 			      unsigned int *bus_format,
88428671edaSAlgea Cao 			      struct overscan *overscan,
88528671edaSAlgea Cao 			      enum dw_hdmi_devtype dev_type,
88628671edaSAlgea Cao 			      bool output_bus_format_rgb,
8870d7a8537SAlgea Cao 			      void *data, struct display_state *state)
88828671edaSAlgea Cao {
88928671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
89028671edaSAlgea Cao 	struct drm_hdmi_info *hdmi_info = &edid_data->display_info.hdmi;
89128671edaSAlgea Cao 	int ret, i, screen_size;
89228671edaSAlgea Cao 	struct base_disp_info base_parameter;
89328671edaSAlgea Cao 	struct base2_disp_info *base2_parameter = conn_state->disp_info;
89428671edaSAlgea Cao 	const struct base_overscan *scan;
89528671edaSAlgea Cao 	struct base_screen_info *screen_info = NULL;
89628671edaSAlgea Cao 	struct base2_screen_info *screen_info2 = NULL;
89728671edaSAlgea Cao 	int max_scan = 100;
89828671edaSAlgea Cao 	int min_scan = 51;
89928671edaSAlgea Cao 	int offset = 0;
90028671edaSAlgea Cao 	int color_depth;
90128671edaSAlgea Cao 	unsigned int tmdsclk;
90228671edaSAlgea Cao 	unsigned int pixel_clk;
90328671edaSAlgea Cao 	bool found = false;
90428671edaSAlgea Cao 	struct blk_desc *dev_desc;
90528671edaSAlgea Cao 	disk_partition_t part_info;
90628671edaSAlgea Cao 	char baseparameter_buf[8 * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
90728671edaSAlgea Cao 
90828671edaSAlgea Cao 	overscan->left_margin = max_scan;
90928671edaSAlgea Cao 	overscan->right_margin = max_scan;
91028671edaSAlgea Cao 	overscan->top_margin = max_scan;
91128671edaSAlgea Cao 	overscan->bottom_margin = max_scan;
91228671edaSAlgea Cao 
91328671edaSAlgea Cao 	hdmi->max_frl_rate_per_lane = hdmi_info->max_frl_rate_per_lane;
91428671edaSAlgea Cao 	hdmi->max_lanes = hdmi_info->max_lanes;
91528671edaSAlgea Cao 	memcpy(&hdmi->dsc_cap, &hdmi_info->dsc_cap, sizeof(struct drm_hdmi_dsc_cap));
91628671edaSAlgea Cao 
91728671edaSAlgea Cao 	if (output_bus_format_rgb)
91828671edaSAlgea Cao 		*bus_format = MEDIA_BUS_FMT_RGB888_1X24;
91928671edaSAlgea Cao 	else
92028671edaSAlgea Cao 		*bus_format = MEDIA_BUS_FMT_YUV8_1X24;
92128671edaSAlgea Cao 
92228671edaSAlgea Cao 	if (!base2_parameter) {
92328671edaSAlgea Cao 		dev_desc = rockchip_get_bootdev();
92428671edaSAlgea Cao 		if (!dev_desc) {
92528671edaSAlgea Cao 			printf("%s: Could not find device\n", __func__);
92628671edaSAlgea Cao 			goto null_basep;
92728671edaSAlgea Cao 		}
92828671edaSAlgea Cao 
92928671edaSAlgea Cao 		ret = part_get_info_by_name(dev_desc, "baseparameter",
93028671edaSAlgea Cao 					    &part_info);
93128671edaSAlgea Cao 		if (ret < 0) {
93228671edaSAlgea Cao 			printf("Could not find baseparameter partition\n");
93328671edaSAlgea Cao 			goto null_basep;
93428671edaSAlgea Cao 		}
93528671edaSAlgea Cao 
93628671edaSAlgea Cao read_aux:
93728671edaSAlgea Cao 		ret = blk_dread(dev_desc, part_info.start + offset, 1,
93828671edaSAlgea Cao 				(void *)baseparameter_buf);
93928671edaSAlgea Cao 		if (ret < 0) {
94028671edaSAlgea Cao 			printf("read baseparameter failed\n");
94128671edaSAlgea Cao 			goto null_basep;
94228671edaSAlgea Cao 		}
94328671edaSAlgea Cao 
94428671edaSAlgea Cao 		memcpy(&base_parameter, baseparameter_buf,
94528671edaSAlgea Cao 		       sizeof(base_parameter));
94628671edaSAlgea Cao 		scan = &base_parameter.scan;
94728671edaSAlgea Cao 
94828671edaSAlgea Cao 		screen_size = sizeof(base_parameter.screen_list) /
94928671edaSAlgea Cao 			sizeof(base_parameter.screen_list[0]);
95028671edaSAlgea Cao 
95128671edaSAlgea Cao 		for (i = 0; i < screen_size; i++) {
95228671edaSAlgea Cao 			if (base_parameter.screen_list[i].type ==
95328671edaSAlgea Cao 			    DRM_MODE_CONNECTOR_HDMIA) {
95428671edaSAlgea Cao 				found = true;
95528671edaSAlgea Cao 				screen_info = &base_parameter.screen_list[i];
95628671edaSAlgea Cao 				break;
95728671edaSAlgea Cao 			}
95828671edaSAlgea Cao 		}
95928671edaSAlgea Cao 
96028671edaSAlgea Cao 		if (!found && !offset) {
96128671edaSAlgea Cao 			printf("hdmi info isn't saved in main block\n");
96228671edaSAlgea Cao 			offset += 16;
96328671edaSAlgea Cao 			goto read_aux;
96428671edaSAlgea Cao 		}
96528671edaSAlgea Cao 	} else {
96628671edaSAlgea Cao 		scan = &base2_parameter->overscan_info;
96728671edaSAlgea Cao 		screen_size = sizeof(base2_parameter->screen_info) /
96828671edaSAlgea Cao 			sizeof(base2_parameter->screen_info[0]);
96928671edaSAlgea Cao 
97028671edaSAlgea Cao 		for (i = 0; i < screen_size; i++) {
97128671edaSAlgea Cao 			if (base2_parameter->screen_info[i].type ==
97228671edaSAlgea Cao 			    DRM_MODE_CONNECTOR_HDMIA) {
97328671edaSAlgea Cao 				screen_info2 =
97428671edaSAlgea Cao 					&base2_parameter->screen_info[i];
97528671edaSAlgea Cao 				break;
97628671edaSAlgea Cao 			}
97728671edaSAlgea Cao 		}
97828671edaSAlgea Cao 		screen_info = malloc(sizeof(*screen_info));
97928671edaSAlgea Cao 
98028671edaSAlgea Cao 		screen_info->type = screen_info2->type;
98128671edaSAlgea Cao 		screen_info->mode = screen_info2->resolution;
98228671edaSAlgea Cao 		screen_info->format = screen_info2->format;
98328671edaSAlgea Cao 		screen_info->depth = screen_info2->depthc;
98428671edaSAlgea Cao 		screen_info->feature = screen_info2->feature;
98528671edaSAlgea Cao 	}
98628671edaSAlgea Cao 
98728671edaSAlgea Cao 	if (scan->leftscale < min_scan && scan->leftscale > 0)
98828671edaSAlgea Cao 		overscan->left_margin = min_scan;
98928671edaSAlgea Cao 	else if (scan->leftscale < max_scan && scan->leftscale > 0)
99028671edaSAlgea Cao 		overscan->left_margin = scan->leftscale;
99128671edaSAlgea Cao 
99228671edaSAlgea Cao 	if (scan->rightscale < min_scan && scan->rightscale > 0)
99328671edaSAlgea Cao 		overscan->right_margin = min_scan;
99428671edaSAlgea Cao 	else if (scan->rightscale < max_scan && scan->rightscale > 0)
99528671edaSAlgea Cao 		overscan->right_margin = scan->rightscale;
99628671edaSAlgea Cao 
99728671edaSAlgea Cao 	if (scan->topscale < min_scan && scan->topscale > 0)
99828671edaSAlgea Cao 		overscan->top_margin = min_scan;
99928671edaSAlgea Cao 	else if (scan->topscale < max_scan && scan->topscale > 0)
100028671edaSAlgea Cao 		overscan->top_margin = scan->topscale;
100128671edaSAlgea Cao 
100228671edaSAlgea Cao 	if (scan->bottomscale < min_scan && scan->bottomscale > 0)
100328671edaSAlgea Cao 		overscan->bottom_margin = min_scan;
100428671edaSAlgea Cao 	else if (scan->bottomscale < max_scan && scan->bottomscale > 0)
100528671edaSAlgea Cao 		overscan->bottom_margin = scan->bottomscale;
100628671edaSAlgea Cao 
100728671edaSAlgea Cao null_basep:
100828671edaSAlgea Cao 
100928671edaSAlgea Cao 	if (screen_info)
101028671edaSAlgea Cao 		printf("base_parameter.mode:%dx%d\n",
101128671edaSAlgea Cao 		       screen_info->mode.hdisplay,
101228671edaSAlgea Cao 		       screen_info->mode.vdisplay);
101328671edaSAlgea Cao 	drm_rk_select_mode(edid_data, screen_info);
101428671edaSAlgea Cao 
101528671edaSAlgea Cao 	*bus_format = drm_rk_select_color(edid_data, screen_info,
101628671edaSAlgea Cao 					  dev_type, output_bus_format_rgb);
101728671edaSAlgea Cao 
10180d7a8537SAlgea Cao 	if (state->force_output) {
10190d7a8537SAlgea Cao 		memcpy(edid_data->preferred_mode, &state->force_mode,
10200d7a8537SAlgea Cao 		       sizeof(struct drm_display_mode));
10210d7a8537SAlgea Cao 		if (state->force_bus_format)
10220d7a8537SAlgea Cao 			*bus_format = state->force_bus_format;
10230d7a8537SAlgea Cao 	}
10240d7a8537SAlgea Cao 
102528671edaSAlgea Cao 	hdmi->bus_format = *bus_format;
102628671edaSAlgea Cao 	color_depth = hdmi_bus_fmt_color_depth(*bus_format);
102728671edaSAlgea Cao 	pixel_clk = edid_data->preferred_mode->clock;
102828671edaSAlgea Cao 	tmdsclk = hdmi_get_tmdsclock(hdmi, pixel_clk);
102928671edaSAlgea Cao 	if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format))
103028671edaSAlgea Cao 		tmdsclk /= 2;
103128671edaSAlgea Cao 	hdmi_select_link_config(hdmi, edid_data->preferred_mode, tmdsclk);
103228671edaSAlgea Cao 	dw_hdmi_qp_dsc_configure(hdmi, edid_data->preferred_mode);
103328671edaSAlgea Cao 	if (hdmi->link_cfg.frl_mode) {
103428671edaSAlgea Cao 		dm_gpio_set_value(&hdmi->enable_gpio, 0);
103528671edaSAlgea Cao 		/* in the current version, support max 40G frl */
103628671edaSAlgea Cao 		if (hdmi->link_cfg.rate_per_lane >= 10) {
103728671edaSAlgea Cao 			hdmi->link_cfg.frl_lanes = 4;
103828671edaSAlgea Cao 			hdmi->link_cfg.rate_per_lane = 10;
103928671edaSAlgea Cao 		}
104028671edaSAlgea Cao 		hdmi->bus_width = hdmi->link_cfg.frl_lanes *
104128671edaSAlgea Cao 			hdmi->link_cfg.rate_per_lane * 1000000;
104228671edaSAlgea Cao 		/* 10 bit color depth and frl mode */
104328671edaSAlgea Cao 		if (color_depth == 10)
104428671edaSAlgea Cao 			hdmi->bus_width |=
104528671edaSAlgea Cao 				COLOR_DEPTH_10BIT | HDMI_FRL_MODE;
104628671edaSAlgea Cao 		else
104728671edaSAlgea Cao 			hdmi->bus_width |= HDMI_FRL_MODE;
104828671edaSAlgea Cao 	} else {
104928671edaSAlgea Cao 		dm_gpio_set_value(&hdmi->enable_gpio, 1);
105028671edaSAlgea Cao 		hdmi->bus_width =
105128671edaSAlgea Cao 			hdmi_get_tmdsclock(hdmi, pixel_clk * 10);
105228671edaSAlgea Cao 		if (hdmi_bus_fmt_is_yuv420(*bus_format))
105328671edaSAlgea Cao 			hdmi->bus_width /= 2;
105428671edaSAlgea Cao 
105528671edaSAlgea Cao 		if (color_depth == 10)
105628671edaSAlgea Cao 			hdmi->bus_width |= COLOR_DEPTH_10BIT;
105728671edaSAlgea Cao 	}
1058*97273498SAlgea Cao 
1059*97273498SAlgea Cao 	rockchip_phy_set_bus_width(conn_state->phy, hdmi->bus_width);
106028671edaSAlgea Cao }
106128671edaSAlgea Cao 
106228671edaSAlgea Cao static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi)
106328671edaSAlgea Cao {
106428671edaSAlgea Cao 	int val;
106528671edaSAlgea Cao 	bool is_hdmi0;
106628671edaSAlgea Cao 
106728671edaSAlgea Cao 	if (!hdmi->id)
106828671edaSAlgea Cao 		is_hdmi0 = true;
106928671edaSAlgea Cao 	else
107028671edaSAlgea Cao 		is_hdmi0 = false;
107128671edaSAlgea Cao 
107228671edaSAlgea Cao 	if (!hdmi->link_cfg.frl_mode) {
107328671edaSAlgea Cao 		val = HIWORD_UPDATE(0, RK3588_HDMI21_MASK);
107428671edaSAlgea Cao 		if (is_hdmi0)
107528671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4);
107628671edaSAlgea Cao 		else
107728671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7);
107828671edaSAlgea Cao 
107928671edaSAlgea Cao 		val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
108028671edaSAlgea Cao 		if (is_hdmi0)
108128671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
108228671edaSAlgea Cao 		else
108328671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
108428671edaSAlgea Cao 
108528671edaSAlgea Cao 		return;
108628671edaSAlgea Cao 	}
108728671edaSAlgea Cao 
108828671edaSAlgea Cao 	val = HIWORD_UPDATE(RK3588_HDMI21_MASK, RK3588_HDMI21_MASK);
108928671edaSAlgea Cao 	if (is_hdmi0)
109028671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4);
109128671edaSAlgea Cao 	else
109228671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7);
109328671edaSAlgea Cao 
109428671edaSAlgea Cao 	if (hdmi->link_cfg.dsc_mode) {
109528671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_COMPRESS_MODE_MASK | RK3588_COMPRESSED_DATA,
109628671edaSAlgea Cao 				    RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
109728671edaSAlgea Cao 		if (is_hdmi0)
109828671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
109928671edaSAlgea Cao 		else
110028671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
110128671edaSAlgea Cao 	} else {
110228671edaSAlgea Cao 		val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
110328671edaSAlgea Cao 		if (is_hdmi0)
110428671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
110528671edaSAlgea Cao 		else
110628671edaSAlgea Cao 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
110728671edaSAlgea Cao 	}
110828671edaSAlgea Cao }
110928671edaSAlgea Cao 
111028671edaSAlgea Cao static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format,
111128671edaSAlgea Cao 				    u32 depth)
111228671edaSAlgea Cao {
111328671edaSAlgea Cao 	u32 val = 0;
111428671edaSAlgea Cao 
111528671edaSAlgea Cao 	switch (bus_format) {
111628671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB888_1X24:
111728671edaSAlgea Cao 	case MEDIA_BUS_FMT_RGB101010_1X30:
111828671edaSAlgea Cao 		val = HIWORD_UPDATE(0, RK3588_COLOR_FORMAT_MASK);
111928671edaSAlgea Cao 		break;
112028671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
112128671edaSAlgea Cao 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
112228671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_YUV420, RK3588_COLOR_FORMAT_MASK);
112328671edaSAlgea Cao 		break;
112428671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV8_1X24:
112528671edaSAlgea Cao 	case MEDIA_BUS_FMT_YUV10_1X30:
112628671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_YUV444, RK3588_COLOR_FORMAT_MASK);
112728671edaSAlgea Cao 		break;
112828671edaSAlgea Cao 	default:
112928671edaSAlgea Cao 		dev_err(hdmi->dev, "can't set correct color format\n");
113028671edaSAlgea Cao 		return;
113128671edaSAlgea Cao 	}
113228671edaSAlgea Cao 
113328671edaSAlgea Cao 	if (hdmi->link_cfg.dsc_mode)
113428671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_COMPRESSED_DATA, RK3588_COLOR_FORMAT_MASK);
113528671edaSAlgea Cao 
113628671edaSAlgea Cao 	if (depth == 8)
113728671edaSAlgea Cao 		val |= HIWORD_UPDATE(RK3588_8BPC, RK3588_COLOR_DEPTH_MASK);
113828671edaSAlgea Cao 	else
113928671edaSAlgea Cao 		val |= HIWORD_UPDATE(RK3588_10BPC, RK3588_COLOR_DEPTH_MASK);
114028671edaSAlgea Cao 
114128671edaSAlgea Cao 	if (!hdmi->id)
114228671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
114328671edaSAlgea Cao 	else
114428671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
114528671edaSAlgea Cao }
114628671edaSAlgea Cao 
114728671edaSAlgea Cao void rk3588_set_grf_cfg(void *data)
114828671edaSAlgea Cao {
114928671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
115028671edaSAlgea Cao 	int color_depth;
115128671edaSAlgea Cao 
115228671edaSAlgea Cao 	rk3588_set_link_mode(hdmi);
115328671edaSAlgea Cao 	color_depth = hdmi_bus_fmt_color_depth(hdmi->bus_format);
115428671edaSAlgea Cao 	rk3588_set_color_format(hdmi, hdmi->bus_format, color_depth);
115528671edaSAlgea Cao }
115628671edaSAlgea Cao 
115728671edaSAlgea Cao void dw_hdmi_qp_set_iomux(void *data)
115828671edaSAlgea Cao {
115928671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
116028671edaSAlgea Cao 	u32 val;
116128671edaSAlgea Cao 
116228671edaSAlgea Cao 	if (!hdmi->id) {
116328671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
116428671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
116528671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
116628671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
116728671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
116828671edaSAlgea Cao 
116928671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
117028671edaSAlgea Cao 				    RK3588_SET_HPD_PATH_MASK);
117128671edaSAlgea Cao 		writel(val, hdmi->grf + RK3588_GRF_SOC_CON7);
117228671edaSAlgea Cao 
117328671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
117428671edaSAlgea Cao 				    RK3588_HDMI0_GRANT_SEL);
117528671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9);
117628671edaSAlgea Cao 	} else {
117728671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
117828671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
117928671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
118028671edaSAlgea Cao 		      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
118128671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
118228671edaSAlgea Cao 
118328671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
118428671edaSAlgea Cao 				    RK3588_SET_HPD_PATH_MASK);
118528671edaSAlgea Cao 		writel(val, hdmi->grf + RK3588_GRF_SOC_CON7);
118628671edaSAlgea Cao 
118728671edaSAlgea Cao 		val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
118828671edaSAlgea Cao 				    RK3588_HDMI1_GRANT_SEL);
118928671edaSAlgea Cao 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9);
119028671edaSAlgea Cao 	}
119128671edaSAlgea Cao }
119228671edaSAlgea Cao 
119328671edaSAlgea Cao struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data)
119428671edaSAlgea Cao {
119528671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
119628671edaSAlgea Cao 
119728671edaSAlgea Cao 	return &hdmi->link_cfg;
119828671edaSAlgea Cao }
119928671edaSAlgea Cao 
120028671edaSAlgea Cao static void dw_hdmi_qp_rockchip_phy_disable(void *data, void *state)
120128671edaSAlgea Cao {
120228671edaSAlgea Cao 	struct display_state *display_state = (struct display_state *)state;
120328671edaSAlgea Cao 	struct connector_state *conn_state = &display_state->conn_state;
120428671edaSAlgea Cao 
120528671edaSAlgea Cao 	rockchip_phy_power_off(conn_state->phy);
120628671edaSAlgea Cao }
120728671edaSAlgea Cao 
120828671edaSAlgea Cao static int dw_hdmi_qp_rockchip_genphy_init(void *data, void *state)
120928671edaSAlgea Cao {
121028671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
121128671edaSAlgea Cao 	struct display_state *display_state = (struct display_state *)state;
121228671edaSAlgea Cao 	struct connector_state *conn_state = &display_state->conn_state;
121328671edaSAlgea Cao 
121428671edaSAlgea Cao 	dw_hdmi_qp_rockchip_phy_disable(data, state);
121528671edaSAlgea Cao 
121628671edaSAlgea Cao 	rockchip_phy_set_bus_width(conn_state->phy, hdmi->bus_width);
121728671edaSAlgea Cao 
121828671edaSAlgea Cao 	return rockchip_phy_power_on(conn_state->phy);
121928671edaSAlgea Cao }
122028671edaSAlgea Cao 
122128671edaSAlgea Cao static enum drm_connector_status dw_hdmi_rk3588_read_hpd(void *data)
122228671edaSAlgea Cao {
122328671edaSAlgea Cao 	u32 val;
122428671edaSAlgea Cao 	int ret;
122528671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
122628671edaSAlgea Cao 
122728671edaSAlgea Cao 	val = readl(hdmi->grf + RK3588_GRF_SOC_STATUS1);
122828671edaSAlgea Cao 
122928671edaSAlgea Cao 	if (!hdmi->id) {
123028671edaSAlgea Cao 		if (val & RK3588_HDMI0_LEVEL_INT)
123128671edaSAlgea Cao 			ret = connector_status_connected;
123228671edaSAlgea Cao 		else
123328671edaSAlgea Cao 			ret = connector_status_disconnected;
123428671edaSAlgea Cao 	} else {
123528671edaSAlgea Cao 		if (val & RK3588_HDMI1_LEVEL_INT)
123628671edaSAlgea Cao 			ret = connector_status_connected;
123728671edaSAlgea Cao 		else
123828671edaSAlgea Cao 			ret = connector_status_disconnected;
123928671edaSAlgea Cao 	}
124028671edaSAlgea Cao 
124128671edaSAlgea Cao 	return ret;
124228671edaSAlgea Cao }
124328671edaSAlgea Cao 
124428671edaSAlgea Cao static void dw_hdmi_rk3588_set_pll(void *data, void *state)
124528671edaSAlgea Cao {
124628671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
124728671edaSAlgea Cao 	struct display_state *display_state = (struct display_state *)state;
124828671edaSAlgea Cao 	struct connector_state *conn_state = &display_state->conn_state;
124928671edaSAlgea Cao 	struct drm_display_mode *mode = &conn_state->mode;
125028671edaSAlgea Cao 
125128671edaSAlgea Cao 	if (hdmi_bus_fmt_is_yuv420(hdmi->bus_format))
125228671edaSAlgea Cao 		rockchip_phy_set_pll(conn_state->phy, mode->clock / 2 * 1000);
125328671edaSAlgea Cao 	else
125428671edaSAlgea Cao 		rockchip_phy_set_pll(conn_state->phy, mode->clock * 1000);
125528671edaSAlgea Cao }
125628671edaSAlgea Cao 
125728671edaSAlgea Cao static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = {
125828671edaSAlgea Cao 	.init = dw_hdmi_qp_rockchip_genphy_init,
125928671edaSAlgea Cao 	.disable = dw_hdmi_qp_rockchip_phy_disable,
126028671edaSAlgea Cao 	.read_hpd = dw_hdmi_rk3588_read_hpd,
126128671edaSAlgea Cao 	.set_pll = dw_hdmi_rk3588_set_pll,
126228671edaSAlgea Cao };
126328671edaSAlgea Cao 
126428671edaSAlgea Cao static const struct rockchip_connector_funcs rockchip_dw_hdmi_qp_funcs = {
126528671edaSAlgea Cao 	.pre_init = rockchip_dw_hdmi_qp_pre_init,
126628671edaSAlgea Cao 	.init = rockchip_dw_hdmi_qp_init,
126728671edaSAlgea Cao 	.deinit = rockchip_dw_hdmi_qp_deinit,
126828671edaSAlgea Cao 	.prepare = rockchip_dw_hdmi_qp_prepare,
126928671edaSAlgea Cao 	.enable = rockchip_dw_hdmi_qp_enable,
127028671edaSAlgea Cao 	.disable = rockchip_dw_hdmi_qp_disable,
127128671edaSAlgea Cao 	.get_timing = rockchip_dw_hdmi_qp_get_timing,
127228671edaSAlgea Cao 	.detect = rockchip_dw_hdmi_qp_detect,
127328671edaSAlgea Cao 	.get_edid = rockchip_dw_hdmi_qp_get_edid,
127428671edaSAlgea Cao };
127528671edaSAlgea Cao 
127628671edaSAlgea Cao const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = {
127728671edaSAlgea Cao 	.qp_phy_ops    = &rk3588_hdmi_phy_ops,
127828671edaSAlgea Cao 	.phy_name   = "samsung_hdptx_phy",
127928671edaSAlgea Cao 	.dev_type   = RK3588_HDMI,
128028671edaSAlgea Cao };
128128671edaSAlgea Cao 
128228671edaSAlgea Cao static int rockchip_dw_hdmi_qp_probe(struct udevice *dev)
128328671edaSAlgea Cao {
128428671edaSAlgea Cao 	int ret;
128528671edaSAlgea Cao 	struct regmap *map;
128628671edaSAlgea Cao 	struct rockchip_hdmi *hdmi = dev_get_priv(dev);
128728671edaSAlgea Cao 
128828671edaSAlgea Cao 	hdmi->dev = dev;
128928671edaSAlgea Cao 
129028671edaSAlgea Cao 	hdmi->id = of_alias_get_id(ofnode_to_np(dev->node), "hdmi");
129128671edaSAlgea Cao 	if (hdmi->id < 0)
129228671edaSAlgea Cao 		hdmi->id = 0;
129328671edaSAlgea Cao 
129428671edaSAlgea Cao 	hdmi->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
129528671edaSAlgea Cao 
129628671edaSAlgea Cao 	if (hdmi->grf <= 0) {
129728671edaSAlgea Cao 		dev_err(dev, "%s: Get syscon grf failed (ret=%p)\n",
129828671edaSAlgea Cao 			__func__, hdmi->grf);
129928671edaSAlgea Cao 		return -ENXIO;
130028671edaSAlgea Cao 	}
130128671edaSAlgea Cao 
130228671edaSAlgea Cao 	map = syscon_regmap_lookup_by_phandle(dev, "rockchip,vo1_grf");
130328671edaSAlgea Cao 	hdmi->vo1_grf = regmap_get_range(map, 0);
130428671edaSAlgea Cao 
130528671edaSAlgea Cao 	if (hdmi->vo1_grf <= 0) {
130628671edaSAlgea Cao 		dev_err(dev, "%s: Get syscon vo1 grf failed (ret=%p)\n",
130728671edaSAlgea Cao 			__func__, hdmi->vo1_grf);
130828671edaSAlgea Cao 		return -ENXIO;
130928671edaSAlgea Cao 	}
131028671edaSAlgea Cao 
131128671edaSAlgea Cao 	ret = gpio_request_by_name(dev, "enable-gpios", 0,
131228671edaSAlgea Cao 				   &hdmi->enable_gpio, GPIOD_IS_OUT);
131328671edaSAlgea Cao 	if (ret) {
131428671edaSAlgea Cao 		dev_err(dev, "Cannot get enable GPIO: %d\n", ret);
131528671edaSAlgea Cao 		return ret;
131628671edaSAlgea Cao 	}
131728671edaSAlgea Cao 
131828671edaSAlgea Cao 	return 0;
131928671edaSAlgea Cao }
132028671edaSAlgea Cao 
132128671edaSAlgea Cao static const struct rockchip_connector rk3588_dw_hdmi_qp_data = {
132228671edaSAlgea Cao 	.funcs = &rockchip_dw_hdmi_qp_funcs,
132328671edaSAlgea Cao 	.data = &rk3588_hdmi_drv_data,
132428671edaSAlgea Cao };
132528671edaSAlgea Cao 
132628671edaSAlgea Cao static const struct udevice_id rockchip_dw_hdmi_qp_ids[] = {
132728671edaSAlgea Cao 	{
132828671edaSAlgea Cao 	 .compatible = "rockchip,rk3588-dw-hdmi",
132928671edaSAlgea Cao 	 .data = (ulong)&rk3588_dw_hdmi_qp_data,
133028671edaSAlgea Cao 	}, {}
133128671edaSAlgea Cao };
133228671edaSAlgea Cao 
133328671edaSAlgea Cao U_BOOT_DRIVER(rockchip_dw_hdmi_qp) = {
133428671edaSAlgea Cao 	.name = "rockchip_dw_hdmi_qp",
133528671edaSAlgea Cao 	.id = UCLASS_DISPLAY,
133628671edaSAlgea Cao 	.of_match = rockchip_dw_hdmi_qp_ids,
133728671edaSAlgea Cao 	.probe	= rockchip_dw_hdmi_qp_probe,
133828671edaSAlgea Cao 	.priv_auto_alloc_size = sizeof(struct rockchip_hdmi),
133928671edaSAlgea Cao };
1340