xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/rockchip_dw_hdmi_qp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun  * Author: Algea Cao <algea.cao@rock-chips.com>
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <boot_rkimg.h>
9*4882a593Smuzhiyun #include <clk.h>
10*4882a593Smuzhiyun #include <fdtdec.h>
11*4882a593Smuzhiyun #include <regmap.h>
12*4882a593Smuzhiyun #include <syscon.h>
13*4882a593Smuzhiyun #include <asm/arch-rockchip/clock.h>
14*4882a593Smuzhiyun #include <asm/io.h>
15*4882a593Smuzhiyun #include <asm-generic/gpio.h>
16*4882a593Smuzhiyun #include <dm/of_access.h>
17*4882a593Smuzhiyun #include <dm/device.h>
18*4882a593Smuzhiyun #include <linux/dw_hdmi.h>
19*4882a593Smuzhiyun #include <linux/hdmi.h>
20*4882a593Smuzhiyun #include <linux/media-bus-format.h>
21*4882a593Smuzhiyun #include "rockchip_display.h"
22*4882a593Smuzhiyun #include "rockchip_crtc.h"
23*4882a593Smuzhiyun #include "rockchip_connector.h"
24*4882a593Smuzhiyun #include "rockchip_phy.h"
25*4882a593Smuzhiyun #include "dw_hdmi_qp.h"
26*4882a593Smuzhiyun #include "rockchip_dw_hdmi_qp.h"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define HIWORD_UPDATE(val, mask)	((val) | (mask) << 16)
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define RK3588_GRF_SOC_CON2		0x0308
31*4882a593Smuzhiyun #define RK3588_HDMI1_HPD_INT_MSK	BIT(15)
32*4882a593Smuzhiyun #define RK3588_HDMI1_HPD_INT_CLR	BIT(14)
33*4882a593Smuzhiyun #define RK3588_HDMI0_HPD_INT_MSK	BIT(13)
34*4882a593Smuzhiyun #define RK3588_HDMI0_HPD_INT_CLR	BIT(12)
35*4882a593Smuzhiyun #define RK3588_GRF_SOC_CON7		0x031c
36*4882a593Smuzhiyun #define RK3588_SET_HPD_PATH_MASK	(0x3 << 12)
37*4882a593Smuzhiyun #define RK3588_GRF_SOC_STATUS1		0x0384
38*4882a593Smuzhiyun #define RK3588_HDMI0_LOW_MORETHAN100MS	BIT(20)
39*4882a593Smuzhiyun #define RK3588_HDMI0_HPD_PORT_LEVEL	BIT(19)
40*4882a593Smuzhiyun #define RK3588_HDMI0_IHPD_PORT		BIT(18)
41*4882a593Smuzhiyun #define RK3588_HDMI0_OHPD_INT		BIT(17)
42*4882a593Smuzhiyun #define RK3588_HDMI0_LEVEL_INT		BIT(16)
43*4882a593Smuzhiyun #define RK3588_HDMI0_INTR_CHANGE_CNT	(0x7 << 13)
44*4882a593Smuzhiyun #define RK3588_HDMI1_LOW_MORETHAN100MS	BIT(28)
45*4882a593Smuzhiyun #define RK3588_HDMI1_HPD_PORT_LEVEL	BIT(27)
46*4882a593Smuzhiyun #define RK3588_HDMI1_IHPD_PORT		BIT(26)
47*4882a593Smuzhiyun #define RK3588_HDMI1_OHPD_INT		BIT(25)
48*4882a593Smuzhiyun #define RK3588_HDMI1_LEVEL_INT		BIT(24)
49*4882a593Smuzhiyun #define RK3588_HDMI1_INTR_CHANGE_CNT	(0x7 << 21)
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define RK3588_GRF_VO1_CON3		0x000c
52*4882a593Smuzhiyun #define RK3588_COLOR_FORMAT_MASK	0xf
53*4882a593Smuzhiyun #define RK3588_YUV422			0x1
54*4882a593Smuzhiyun #define RK3588_YUV444			0x2
55*4882a593Smuzhiyun #define RK3588_YUV420			0x3
56*4882a593Smuzhiyun #define RK3588_COMPRESSED_DATA		0xb
57*4882a593Smuzhiyun #define RK3588_COLOR_DEPTH_MASK		(0xf << 4)
58*4882a593Smuzhiyun #define RK3588_8BPC			0
59*4882a593Smuzhiyun #define RK3588_10BPC			(0x6 << 4)
60*4882a593Smuzhiyun #define RK3588_CECIN_MASK		BIT(8)
61*4882a593Smuzhiyun #define RK3588_SCLIN_MASK		BIT(9)
62*4882a593Smuzhiyun #define RK3588_SDAIN_MASK		BIT(10)
63*4882a593Smuzhiyun #define RK3588_MODE_MASK		BIT(11)
64*4882a593Smuzhiyun #define RK3588_COMPRESS_MODE_MASK	BIT(12)
65*4882a593Smuzhiyun #define RK3588_I2S_SEL_MASK		BIT(13)
66*4882a593Smuzhiyun #define RK3588_SPDIF_SEL_MASK		BIT(14)
67*4882a593Smuzhiyun #define RK3588_GRF_VO1_CON4		0x0010
68*4882a593Smuzhiyun #define RK3588_HDMI21_MASK		BIT(0)
69*4882a593Smuzhiyun #define RK3588_GRF_VO1_CON9		0x0024
70*4882a593Smuzhiyun #define RK3588_HDMI0_GRANT_SEL		BIT(10)
71*4882a593Smuzhiyun #define RK3588_HDMI0_GRANT_SW		BIT(11)
72*4882a593Smuzhiyun #define RK3588_HDMI1_GRANT_SEL		BIT(12)
73*4882a593Smuzhiyun #define RK3588_HDMI1_GRANT_SW		BIT(13)
74*4882a593Smuzhiyun #define RK3588_GRF_VO1_CON6		0x0018
75*4882a593Smuzhiyun #define RK3588_GRF_VO1_CON7		0x001c
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define PPS_TABLE_LEN 8
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #define COLOR_DEPTH_10BIT		BIT(31)
80*4882a593Smuzhiyun #define HDMI_FRL_MODE			BIT(30)
81*4882a593Smuzhiyun #define HDMI_EARC_MODE			BIT(29)
82*4882a593Smuzhiyun #define DATA_RATE_MASK			0xFFFFFFF
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #define HDMI20_MAX_RATE			600000
85*4882a593Smuzhiyun #define HDMI_8K60_RATE			2376000
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun enum device_type {
88*4882a593Smuzhiyun 	RK3588_HDMI
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun struct pps_data {
92*4882a593Smuzhiyun 	u32 pic_width;
93*4882a593Smuzhiyun 	u32 pic_height;
94*4882a593Smuzhiyun 	u32 slice_width;
95*4882a593Smuzhiyun 	u32 slice_height;
96*4882a593Smuzhiyun 	bool convert_rgb;
97*4882a593Smuzhiyun 	u8 bpc;
98*4882a593Smuzhiyun 	u8 bpp;
99*4882a593Smuzhiyun 	u8 raw_pps[128];
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun enum hdmi_frl_rate_per_lane {
103*4882a593Smuzhiyun 	FRL_12G_PER_LANE = 12,
104*4882a593Smuzhiyun 	FRL_10G_PER_LANE = 10,
105*4882a593Smuzhiyun 	FRL_8G_PER_LANE = 8,
106*4882a593Smuzhiyun 	FRL_6G_PER_LANE = 6,
107*4882a593Smuzhiyun 	FRL_3G_PER_LANE = 3,
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun struct rockchip_hdmi {
111*4882a593Smuzhiyun 	struct rockchip_connector connector;
112*4882a593Smuzhiyun 	int id;
113*4882a593Smuzhiyun 	struct udevice *dev;
114*4882a593Smuzhiyun 	struct regmap *regmap;
115*4882a593Smuzhiyun 	struct regmap *vo1_regmap;
116*4882a593Smuzhiyun 	void *grf;
117*4882a593Smuzhiyun 	void *vo1_grf;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	unsigned long bus_format;
120*4882a593Smuzhiyun 	unsigned long output_bus_format;
121*4882a593Smuzhiyun 	unsigned long enc_out_encoding;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	u8 max_frl_rate_per_lane;
124*4882a593Smuzhiyun 	u8 max_lanes;
125*4882a593Smuzhiyun 	bool allm_en;
126*4882a593Smuzhiyun 	u32 bus_width;
127*4882a593Smuzhiyun 	struct drm_hdmi_dsc_cap dsc_cap;
128*4882a593Smuzhiyun 	struct dw_hdmi_link_config link_cfg;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	struct clk link_clk;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	struct gpio_desc enable_gpio;
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun /*
136*4882a593Smuzhiyun  * Selected Rate Control Related Parameter Recommended Values
137*4882a593Smuzhiyun  * from DSC_v1.11 spec & C Model release: DSC_model_20161212
138*4882a593Smuzhiyun  */
139*4882a593Smuzhiyun static struct pps_data pps_datas[PPS_TABLE_LEN] = {
140*4882a593Smuzhiyun 	{
141*4882a593Smuzhiyun 		/* 7680x4320/960X96 rgb 8bpc 12bpp */
142*4882a593Smuzhiyun 		7680, 4320, 960, 96, 1, 8, 192,
143*4882a593Smuzhiyun 		{
144*4882a593Smuzhiyun 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xc0, 0x10, 0xe0,
145*4882a593Smuzhiyun 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
146*4882a593Smuzhiyun 			0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
147*4882a593Smuzhiyun 			0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
148*4882a593Smuzhiyun 			0x08, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
149*4882a593Smuzhiyun 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
150*4882a593Smuzhiyun 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
151*4882a593Smuzhiyun 			0x7d, 0x7e, 0x00, 0x82, 0x00, 0xc0, 0x09, 0x00,
152*4882a593Smuzhiyun 			0x09, 0x7e, 0x19, 0xbc, 0x19, 0xba, 0x19, 0xf8,
153*4882a593Smuzhiyun 			0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
154*4882a593Smuzhiyun 			0x2a, 0x76, 0x2a, 0x74, 0x3a, 0xb4, 0x52, 0xf4,
155*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
160*4882a593Smuzhiyun 		},
161*4882a593Smuzhiyun 	},
162*4882a593Smuzhiyun 	{
163*4882a593Smuzhiyun 		/* 7680x4320/960X96 rgb 8bpc 11bpp */
164*4882a593Smuzhiyun 		7680, 4320, 960, 96, 1, 8, 176,
165*4882a593Smuzhiyun 		{
166*4882a593Smuzhiyun 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xb0, 0x10, 0xe0,
167*4882a593Smuzhiyun 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
168*4882a593Smuzhiyun 			0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
169*4882a593Smuzhiyun 			0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
170*4882a593Smuzhiyun 			0x0f, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00,
171*4882a593Smuzhiyun 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
172*4882a593Smuzhiyun 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
173*4882a593Smuzhiyun 			0x7d, 0x7e, 0x00, 0x82, 0x01, 0x00, 0x09, 0x40,
174*4882a593Smuzhiyun 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
175*4882a593Smuzhiyun 			0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76,
176*4882a593Smuzhiyun 			0x2a, 0x76, 0x2a, 0xb4, 0x3a, 0xb4, 0x52, 0xf4,
177*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
182*4882a593Smuzhiyun 		},
183*4882a593Smuzhiyun 	},
184*4882a593Smuzhiyun 	{
185*4882a593Smuzhiyun 		/* 7680x4320/960X96 rgb 8bpc 10bpp */
186*4882a593Smuzhiyun 		7680, 4320, 960, 96, 1, 8, 160,
187*4882a593Smuzhiyun 		{
188*4882a593Smuzhiyun 			0x12, 0x00, 0x00, 0x8d, 0x30, 0xa0, 0x10, 0xe0,
189*4882a593Smuzhiyun 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
190*4882a593Smuzhiyun 			0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
191*4882a593Smuzhiyun 			0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
192*4882a593Smuzhiyun 			0x16, 0x00, 0x10, 0xec, 0x03, 0x0c, 0x20, 0x00,
193*4882a593Smuzhiyun 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
194*4882a593Smuzhiyun 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
195*4882a593Smuzhiyun 			0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
196*4882a593Smuzhiyun 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
197*4882a593Smuzhiyun 			0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
198*4882a593Smuzhiyun 			0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x5b, 0x34,
199*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
204*4882a593Smuzhiyun 		},
205*4882a593Smuzhiyun 	},
206*4882a593Smuzhiyun 	{
207*4882a593Smuzhiyun 		/* 7680x4320/960X96 rgb 8bpc 9bpp */
208*4882a593Smuzhiyun 		7680, 4320, 960, 96, 1, 8, 144,
209*4882a593Smuzhiyun 		{
210*4882a593Smuzhiyun 			0x12, 0x00, 0x00, 0x8d, 0x30, 0x90, 0x10, 0xe0,
211*4882a593Smuzhiyun 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
212*4882a593Smuzhiyun 			0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
213*4882a593Smuzhiyun 			0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
214*4882a593Smuzhiyun 			0x17, 0x00, 0x10, 0xf1, 0x03, 0x0c, 0x20, 0x00,
215*4882a593Smuzhiyun 			0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
216*4882a593Smuzhiyun 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
217*4882a593Smuzhiyun 			0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40,
218*4882a593Smuzhiyun 			0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8,
219*4882a593Smuzhiyun 			0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6,
220*4882a593Smuzhiyun 			0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x63, 0x74,
221*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
226*4882a593Smuzhiyun 		},
227*4882a593Smuzhiyun 	},
228*4882a593Smuzhiyun 	{
229*4882a593Smuzhiyun 		/* 7680x4320/960X96 rgb 10bpc 12bpp */
230*4882a593Smuzhiyun 		7680, 4320, 960, 96, 1, 10, 192,
231*4882a593Smuzhiyun 		{
232*4882a593Smuzhiyun 			0x12, 0x00, 0x00, 0xad, 0x30, 0xc0, 0x10, 0xe0,
233*4882a593Smuzhiyun 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0,
234*4882a593Smuzhiyun 			0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9,
235*4882a593Smuzhiyun 			0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa,
236*4882a593Smuzhiyun 			0x08, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
237*4882a593Smuzhiyun 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
238*4882a593Smuzhiyun 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
239*4882a593Smuzhiyun 			0x7d, 0x7e, 0x01, 0x02, 0x11, 0x80, 0x22, 0x00,
240*4882a593Smuzhiyun 			0x22, 0x7e, 0x32, 0xbc, 0x32, 0xba, 0x3a, 0xf8,
241*4882a593Smuzhiyun 			0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
242*4882a593Smuzhiyun 			0x4b, 0x76, 0x4b, 0x74, 0x5b, 0xb4, 0x73, 0xf4,
243*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
248*4882a593Smuzhiyun 		},
249*4882a593Smuzhiyun 	},
250*4882a593Smuzhiyun 	{
251*4882a593Smuzhiyun 		/* 7680x4320/960X96 rgb 10bpc 11bpp */
252*4882a593Smuzhiyun 		7680, 4320, 960, 96, 1, 10, 176,
253*4882a593Smuzhiyun 		{
254*4882a593Smuzhiyun 			0x12, 0x00, 0x00, 0xad, 0x30, 0xb0, 0x10, 0xe0,
255*4882a593Smuzhiyun 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28,
256*4882a593Smuzhiyun 			0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0,
257*4882a593Smuzhiyun 			0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33,
258*4882a593Smuzhiyun 			0x0f, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00,
259*4882a593Smuzhiyun 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
260*4882a593Smuzhiyun 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
261*4882a593Smuzhiyun 			0x7d, 0x7e, 0x01, 0x42, 0x19, 0xc0, 0x2a, 0x40,
262*4882a593Smuzhiyun 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
263*4882a593Smuzhiyun 			0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76,
264*4882a593Smuzhiyun 			0x4b, 0x76, 0x4b, 0xb4, 0x5b, 0xb4, 0x73, 0xf4,
265*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
270*4882a593Smuzhiyun 		},
271*4882a593Smuzhiyun 	},
272*4882a593Smuzhiyun 	{
273*4882a593Smuzhiyun 		/* 7680x4320/960X96 rgb 10bpc 10bpp */
274*4882a593Smuzhiyun 		7680, 4320, 960, 96, 1, 10, 160,
275*4882a593Smuzhiyun 		{
276*4882a593Smuzhiyun 			0x12, 0x00, 0x00, 0xad, 0x30, 0xa0, 0x10, 0xe0,
277*4882a593Smuzhiyun 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0,
278*4882a593Smuzhiyun 			0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0,
279*4882a593Smuzhiyun 			0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb,
280*4882a593Smuzhiyun 			0x16, 0x00, 0x10, 0xec, 0x07, 0x10, 0x20, 0x00,
281*4882a593Smuzhiyun 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
282*4882a593Smuzhiyun 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
283*4882a593Smuzhiyun 			0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
284*4882a593Smuzhiyun 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
285*4882a593Smuzhiyun 			0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
286*4882a593Smuzhiyun 			0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x7c, 0x34,
287*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
292*4882a593Smuzhiyun 		},
293*4882a593Smuzhiyun 	},
294*4882a593Smuzhiyun 	{
295*4882a593Smuzhiyun 		/* 7680x4320/960X96 rgb 10bpc 9bpp */
296*4882a593Smuzhiyun 		7680, 4320, 960, 96, 1, 10, 144,
297*4882a593Smuzhiyun 		{
298*4882a593Smuzhiyun 			0x12, 0x00, 0x00, 0xad, 0x30, 0x90, 0x10, 0xe0,
299*4882a593Smuzhiyun 			0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38,
300*4882a593Smuzhiyun 			0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7,
301*4882a593Smuzhiyun 			0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa,
302*4882a593Smuzhiyun 			0x17, 0x00, 0x10, 0xf1, 0x07, 0x10, 0x20, 0x00,
303*4882a593Smuzhiyun 			0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38,
304*4882a593Smuzhiyun 			0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
305*4882a593Smuzhiyun 			0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40,
306*4882a593Smuzhiyun 			0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
307*4882a593Smuzhiyun 			0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6,
308*4882a593Smuzhiyun 			0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x84, 0x74,
309*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313*4882a593Smuzhiyun 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
314*4882a593Smuzhiyun 		},
315*4882a593Smuzhiyun 	},
316*4882a593Smuzhiyun };
317*4882a593Smuzhiyun 
hdmi_bus_fmt_is_rgb(unsigned int bus_format)318*4882a593Smuzhiyun static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	switch (bus_format) {
321*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X24:
322*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB101010_1X30:
323*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB121212_1X36:
324*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB161616_1X48:
325*4882a593Smuzhiyun 		return true;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	default:
328*4882a593Smuzhiyun 		return false;
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun 
hdmi_bus_fmt_is_yuv444(unsigned int bus_format)332*4882a593Smuzhiyun static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun 	switch (bus_format) {
335*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV8_1X24:
336*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV10_1X30:
337*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV12_1X36:
338*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV16_1X48:
339*4882a593Smuzhiyun 		return true;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	default:
342*4882a593Smuzhiyun 		return false;
343*4882a593Smuzhiyun 	}
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
hdmi_bus_fmt_is_yuv422(unsigned int bus_format)346*4882a593Smuzhiyun static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun 	switch (bus_format) {
349*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY8_1X16:
350*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY10_1X20:
351*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY12_1X24:
352*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV8_1X16:
353*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV10_1X20:
354*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV12_1X24:
355*4882a593Smuzhiyun 		return true;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	default:
358*4882a593Smuzhiyun 		return false;
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
hdmi_bus_fmt_is_yuv420(unsigned int bus_format)362*4882a593Smuzhiyun static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun 	switch (bus_format) {
365*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
366*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
367*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
368*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
369*4882a593Smuzhiyun 		return true;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	default:
372*4882a593Smuzhiyun 	return false;
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun 
hdmi_bus_fmt_color_depth(unsigned int bus_format)376*4882a593Smuzhiyun static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun 	switch (bus_format) {
379*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X24:
380*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV8_1X24:
381*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY8_1X16:
382*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV8_1X16:
383*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
384*4882a593Smuzhiyun 		return 8;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB101010_1X30:
387*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV10_1X30:
388*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY10_1X20:
389*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV10_1X20:
390*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
391*4882a593Smuzhiyun 		return 10;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB121212_1X36:
394*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV12_1X36:
395*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY12_1X24:
396*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV12_1X24:
397*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
398*4882a593Smuzhiyun 		return 12;
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB161616_1X48:
401*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV16_1X48:
402*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
403*4882a593Smuzhiyun 		return 16;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	default:
406*4882a593Smuzhiyun 		return 0;
407*4882a593Smuzhiyun 	}
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun static unsigned int
hdmi_get_tmdsclock(struct rockchip_hdmi * hdmi,unsigned long pixelclock)411*4882a593Smuzhiyun hdmi_get_tmdsclock(struct rockchip_hdmi *hdmi, unsigned long pixelclock)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	unsigned int tmdsclock = pixelclock;
414*4882a593Smuzhiyun 	unsigned int depth =
415*4882a593Smuzhiyun 		hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	if (!hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format)) {
418*4882a593Smuzhiyun 		switch (depth) {
419*4882a593Smuzhiyun 		case 16:
420*4882a593Smuzhiyun 			tmdsclock = pixelclock * 2;
421*4882a593Smuzhiyun 			break;
422*4882a593Smuzhiyun 		case 12:
423*4882a593Smuzhiyun 			tmdsclock = pixelclock * 3 / 2;
424*4882a593Smuzhiyun 			break;
425*4882a593Smuzhiyun 		case 10:
426*4882a593Smuzhiyun 			tmdsclock = pixelclock * 5 / 4;
427*4882a593Smuzhiyun 			break;
428*4882a593Smuzhiyun 		default:
429*4882a593Smuzhiyun 			break;
430*4882a593Smuzhiyun 		}
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	return tmdsclock;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun 
hdmi_select_link_config(struct rockchip_hdmi * hdmi,struct drm_display_mode * mode,unsigned int tmdsclk)436*4882a593Smuzhiyun static void hdmi_select_link_config(struct rockchip_hdmi *hdmi,
437*4882a593Smuzhiyun 				    struct drm_display_mode *mode,
438*4882a593Smuzhiyun 				    unsigned int tmdsclk)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun 	int max_lanes, max_rate_per_lane;
441*4882a593Smuzhiyun 	int max_dsc_lanes, max_dsc_rate_per_lane;
442*4882a593Smuzhiyun 	unsigned long max_frl_rate;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	max_lanes = hdmi->max_lanes;
445*4882a593Smuzhiyun 	max_rate_per_lane = hdmi->max_frl_rate_per_lane;
446*4882a593Smuzhiyun 	max_frl_rate = max_lanes * max_rate_per_lane * 1000000;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	hdmi->link_cfg.dsc_mode = false;
449*4882a593Smuzhiyun 	hdmi->link_cfg.frl_lanes = max_lanes;
450*4882a593Smuzhiyun 	hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
451*4882a593Smuzhiyun 	hdmi->link_cfg.allm_en = hdmi->allm_en;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	if (!max_frl_rate ||
454*4882a593Smuzhiyun 	    (tmdsclk < HDMI20_MAX_RATE && mode->clock < HDMI20_MAX_RATE)) {
455*4882a593Smuzhiyun 		printf("%s use tmds mode\n", __func__);
456*4882a593Smuzhiyun 		hdmi->link_cfg.frl_mode = false;
457*4882a593Smuzhiyun 		return;
458*4882a593Smuzhiyun 	}
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	hdmi->link_cfg.frl_mode = true;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	if (!hdmi->dsc_cap.v_1p2)
463*4882a593Smuzhiyun 		return;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	max_dsc_lanes = hdmi->dsc_cap.max_lanes;
466*4882a593Smuzhiyun 	max_dsc_rate_per_lane =
467*4882a593Smuzhiyun 		hdmi->dsc_cap.max_frl_rate_per_lane;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	if (mode->clock >= HDMI_8K60_RATE &&
470*4882a593Smuzhiyun 	    !hdmi_bus_fmt_is_yuv420(hdmi->bus_format) &&
471*4882a593Smuzhiyun 	    !hdmi_bus_fmt_is_yuv422(hdmi->bus_format)) {
472*4882a593Smuzhiyun 		hdmi->link_cfg.dsc_mode = true;
473*4882a593Smuzhiyun 		hdmi->link_cfg.frl_lanes = max_dsc_lanes;
474*4882a593Smuzhiyun 		hdmi->link_cfg.rate_per_lane = max_dsc_rate_per_lane;
475*4882a593Smuzhiyun 	} else {
476*4882a593Smuzhiyun 		hdmi->link_cfg.dsc_mode = false;
477*4882a593Smuzhiyun 		hdmi->link_cfg.frl_lanes = max_lanes;
478*4882a593Smuzhiyun 		hdmi->link_cfg.rate_per_lane = max_rate_per_lane;
479*4882a593Smuzhiyun 	}
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun /////////////////////////////////////////////////////////////////////////////////////
483*4882a593Smuzhiyun 
hdmi_dsc_get_slice_height(int vactive)484*4882a593Smuzhiyun static int hdmi_dsc_get_slice_height(int vactive)
485*4882a593Smuzhiyun {
486*4882a593Smuzhiyun 	int slice_height;
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	/*
489*4882a593Smuzhiyun 	 * Slice Height determination : HDMI2.1 Section 7.7.5.2
490*4882a593Smuzhiyun 	 * Select smallest slice height >=96, that results in a valid PPS and
491*4882a593Smuzhiyun 	 * requires minimum padding lines required for final slice.
492*4882a593Smuzhiyun 	 *
493*4882a593Smuzhiyun 	 * Assumption : Vactive is even.
494*4882a593Smuzhiyun 	 */
495*4882a593Smuzhiyun 	for (slice_height = 96; slice_height <= vactive; slice_height += 2)
496*4882a593Smuzhiyun 		if (vactive % slice_height == 0)
497*4882a593Smuzhiyun 			return slice_height;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	return 0;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
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)502*4882a593Smuzhiyun static int hdmi_dsc_get_num_slices(struct rockchip_hdmi *hdmi,
503*4882a593Smuzhiyun 				   struct drm_display_mode *mode,
504*4882a593Smuzhiyun 				   int src_max_slices, int src_max_slice_width,
505*4882a593Smuzhiyun 				   int hdmi_max_slices, int hdmi_throughput)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun /* Pixel rates in KPixels/sec */
508*4882a593Smuzhiyun #define HDMI_DSC_PEAK_PIXEL_RATE		2720000
509*4882a593Smuzhiyun /*
510*4882a593Smuzhiyun  * Rates at which the source and sink are required to process pixels in each
511*4882a593Smuzhiyun  * slice, can be two levels: either at least 340000KHz or at least 40000KHz.
512*4882a593Smuzhiyun  */
513*4882a593Smuzhiyun #define HDMI_DSC_MAX_ENC_THROUGHPUT_0		340000
514*4882a593Smuzhiyun #define HDMI_DSC_MAX_ENC_THROUGHPUT_1		400000
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun /* Spec limits the slice width to 2720 pixels */
517*4882a593Smuzhiyun #define MAX_HDMI_SLICE_WIDTH			2720
518*4882a593Smuzhiyun 	int kslice_adjust;
519*4882a593Smuzhiyun 	int adjusted_clk_khz;
520*4882a593Smuzhiyun 	int min_slices;
521*4882a593Smuzhiyun 	int target_slices;
522*4882a593Smuzhiyun 	int max_throughput; /* max clock freq. in khz per slice */
523*4882a593Smuzhiyun 	int max_slice_width;
524*4882a593Smuzhiyun 	int slice_width;
525*4882a593Smuzhiyun 	int pixel_clock = mode->clock;
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	if (!hdmi_throughput)
528*4882a593Smuzhiyun 		return 0;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	/*
531*4882a593Smuzhiyun 	 * Slice Width determination : HDMI2.1 Section 7.7.5.1
532*4882a593Smuzhiyun 	 * kslice_adjust factor for 4:2:0, and 4:2:2 formats is 0.5, where as
533*4882a593Smuzhiyun 	 * for 4:4:4 is 1.0. Multiplying these factors by 10 and later
534*4882a593Smuzhiyun 	 * dividing adjusted clock value by 10.
535*4882a593Smuzhiyun 	 */
536*4882a593Smuzhiyun 	if (hdmi_bus_fmt_is_yuv444(hdmi->output_bus_format) ||
537*4882a593Smuzhiyun 	    hdmi_bus_fmt_is_rgb(hdmi->output_bus_format))
538*4882a593Smuzhiyun 		kslice_adjust = 10;
539*4882a593Smuzhiyun 	else
540*4882a593Smuzhiyun 		kslice_adjust = 5;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	/*
543*4882a593Smuzhiyun 	 * As per spec, the rate at which the source and the sink process
544*4882a593Smuzhiyun 	 * the pixels per slice are at two levels: at least 340Mhz or 400Mhz.
545*4882a593Smuzhiyun 	 * This depends upon the pixel clock rate and output formats
546*4882a593Smuzhiyun 	 * (kslice adjust).
547*4882a593Smuzhiyun 	 * If pixel clock * kslice adjust >= 2720MHz slices can be processed
548*4882a593Smuzhiyun 	 * at max 340MHz, otherwise they can be processed at max 400MHz.
549*4882a593Smuzhiyun 	 */
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	adjusted_clk_khz = DIV_ROUND_UP(kslice_adjust * pixel_clock, 10);
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	if (adjusted_clk_khz <= HDMI_DSC_PEAK_PIXEL_RATE)
554*4882a593Smuzhiyun 		max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_0;
555*4882a593Smuzhiyun 	else
556*4882a593Smuzhiyun 		max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_1;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	/*
559*4882a593Smuzhiyun 	 * Taking into account the sink's capability for maximum
560*4882a593Smuzhiyun 	 * clock per slice (in MHz) as read from HF-VSDB.
561*4882a593Smuzhiyun 	 */
562*4882a593Smuzhiyun 	max_throughput = min(max_throughput, hdmi_throughput * 1000);
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	min_slices = DIV_ROUND_UP(adjusted_clk_khz, max_throughput);
565*4882a593Smuzhiyun 	max_slice_width = min(MAX_HDMI_SLICE_WIDTH, src_max_slice_width);
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	/*
568*4882a593Smuzhiyun 	 * Keep on increasing the num of slices/line, starting from min_slices
569*4882a593Smuzhiyun 	 * per line till we get such a number, for which the slice_width is
570*4882a593Smuzhiyun 	 * just less than max_slice_width. The slices/line selected should be
571*4882a593Smuzhiyun 	 * less than or equal to the max horizontal slices that the combination
572*4882a593Smuzhiyun 	 * of PCON encoder and HDMI decoder can support.
573*4882a593Smuzhiyun 	 */
574*4882a593Smuzhiyun 	do {
575*4882a593Smuzhiyun 		if (min_slices <= 1 && src_max_slices >= 1 && hdmi_max_slices >= 1)
576*4882a593Smuzhiyun 			target_slices = 1;
577*4882a593Smuzhiyun 		else if (min_slices <= 2 && src_max_slices >= 2 && hdmi_max_slices >= 2)
578*4882a593Smuzhiyun 			target_slices = 2;
579*4882a593Smuzhiyun 		else if (min_slices <= 4 && src_max_slices >= 4 && hdmi_max_slices >= 4)
580*4882a593Smuzhiyun 			target_slices = 4;
581*4882a593Smuzhiyun 		else if (min_slices <= 8 && src_max_slices >= 8 && hdmi_max_slices >= 8)
582*4882a593Smuzhiyun 			target_slices = 8;
583*4882a593Smuzhiyun 		else if (min_slices <= 12 && src_max_slices >= 12 && hdmi_max_slices >= 12)
584*4882a593Smuzhiyun 			target_slices = 12;
585*4882a593Smuzhiyun 		else if (min_slices <= 16 && src_max_slices >= 16 && hdmi_max_slices >= 16)
586*4882a593Smuzhiyun 			target_slices = 16;
587*4882a593Smuzhiyun 		else
588*4882a593Smuzhiyun 			return 0;
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 		slice_width = DIV_ROUND_UP(mode->hdisplay, target_slices);
591*4882a593Smuzhiyun 		if (slice_width > max_slice_width)
592*4882a593Smuzhiyun 			min_slices = target_slices + 1;
593*4882a593Smuzhiyun 	} while (slice_width > max_slice_width);
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	return target_slices;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun 
hdmi_dsc_slices(struct rockchip_hdmi * hdmi,struct drm_display_mode * mode)598*4882a593Smuzhiyun static int hdmi_dsc_slices(struct rockchip_hdmi *hdmi,
599*4882a593Smuzhiyun 			   struct drm_display_mode *mode)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun 	int hdmi_throughput = hdmi->dsc_cap.clk_per_slice;
602*4882a593Smuzhiyun 	int hdmi_max_slices = hdmi->dsc_cap.max_slices;
603*4882a593Smuzhiyun 	int rk_max_slices = 8;
604*4882a593Smuzhiyun 	int rk_max_slice_width = 2048;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	return hdmi_dsc_get_num_slices(hdmi, mode, rk_max_slices,
607*4882a593Smuzhiyun 				       rk_max_slice_width,
608*4882a593Smuzhiyun 				       hdmi_max_slices, hdmi_throughput);
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 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)612*4882a593Smuzhiyun hdmi_dsc_get_bpp(struct rockchip_hdmi *hdmi, int src_fractional_bpp,
613*4882a593Smuzhiyun 		 int slice_width, int num_slices, bool hdmi_all_bpp,
614*4882a593Smuzhiyun 		 int hdmi_max_chunk_bytes)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun 	int max_dsc_bpp, min_dsc_bpp;
617*4882a593Smuzhiyun 	int target_bytes;
618*4882a593Smuzhiyun 	bool bpp_found = false;
619*4882a593Smuzhiyun 	int bpp_decrement_x16;
620*4882a593Smuzhiyun 	int bpp_target;
621*4882a593Smuzhiyun 	int bpp_target_x16;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	/*
624*4882a593Smuzhiyun 	 * Get min bpp and max bpp as per Table 7.23, in HDMI2.1 spec
625*4882a593Smuzhiyun 	 * Start with the max bpp and keep on decrementing with
626*4882a593Smuzhiyun 	 * fractional bpp, if supported by PCON DSC encoder
627*4882a593Smuzhiyun 	 *
628*4882a593Smuzhiyun 	 * for each bpp we check if no of bytes can be supported by HDMI sink
629*4882a593Smuzhiyun 	 */
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	/* only 9\10\12 bpp was tested */
632*4882a593Smuzhiyun 	min_dsc_bpp = 9;
633*4882a593Smuzhiyun 	max_dsc_bpp = 12;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	/*
636*4882a593Smuzhiyun 	 * Taking into account if all dsc_all_bpp supported by HDMI2.1 sink
637*4882a593Smuzhiyun 	 * Section 7.7.34 : Source shall not enable compressed Video
638*4882a593Smuzhiyun 	 * Transport with bpp_target settings above 12 bpp unless
639*4882a593Smuzhiyun 	 * DSC_all_bpp is set to 1.
640*4882a593Smuzhiyun 	 */
641*4882a593Smuzhiyun 	if (!hdmi_all_bpp)
642*4882a593Smuzhiyun 		max_dsc_bpp = min(max_dsc_bpp, 12);
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	/*
645*4882a593Smuzhiyun 	 * The Sink has a limit of compressed data in bytes for a scanline,
646*4882a593Smuzhiyun 	 * as described in max_chunk_bytes field in HFVSDB block of edid.
647*4882a593Smuzhiyun 	 * The no. of bytes depend on the target bits per pixel that the
648*4882a593Smuzhiyun 	 * source configures. So we start with the max_bpp and calculate
649*4882a593Smuzhiyun 	 * the target_chunk_bytes. We keep on decrementing the target_bpp,
650*4882a593Smuzhiyun 	 * till we get the target_chunk_bytes just less than what the sink's
651*4882a593Smuzhiyun 	 * max_chunk_bytes, or else till we reach the min_dsc_bpp.
652*4882a593Smuzhiyun 	 *
653*4882a593Smuzhiyun 	 * The decrement is according to the fractional support from PCON DSC
654*4882a593Smuzhiyun 	 * encoder. For fractional BPP we use bpp_target as a multiple of 16.
655*4882a593Smuzhiyun 	 *
656*4882a593Smuzhiyun 	 * bpp_target_x16 = bpp_target * 16
657*4882a593Smuzhiyun 	 * So we need to decrement by {1, 2, 4, 8, 16} for fractional bpps
658*4882a593Smuzhiyun 	 * {1/16, 1/8, 1/4, 1/2, 1} respectively.
659*4882a593Smuzhiyun 	 */
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	bpp_target = max_dsc_bpp;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	/* src does not support fractional bpp implies decrement by 16 for bppx16 */
664*4882a593Smuzhiyun 	if (!src_fractional_bpp)
665*4882a593Smuzhiyun 		src_fractional_bpp = 1;
666*4882a593Smuzhiyun 	bpp_decrement_x16 = DIV_ROUND_UP(16, src_fractional_bpp);
667*4882a593Smuzhiyun 	bpp_target_x16 = bpp_target * 16;
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 	while (bpp_target_x16 > (min_dsc_bpp * 16)) {
670*4882a593Smuzhiyun 		int bpp;
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 		bpp = DIV_ROUND_UP(bpp_target_x16, 16);
673*4882a593Smuzhiyun 		target_bytes = DIV_ROUND_UP((num_slices * slice_width * bpp), 8);
674*4882a593Smuzhiyun 		if (target_bytes <= hdmi_max_chunk_bytes) {
675*4882a593Smuzhiyun 			bpp_found = true;
676*4882a593Smuzhiyun 			break;
677*4882a593Smuzhiyun 		}
678*4882a593Smuzhiyun 		bpp_target_x16 -= bpp_decrement_x16;
679*4882a593Smuzhiyun 	}
680*4882a593Smuzhiyun 	if (bpp_found)
681*4882a593Smuzhiyun 		return bpp_target_x16;
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 	return 0;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun static int
dw_hdmi_dsc_bpp(struct rockchip_hdmi * hdmi,int num_slices,int slice_width)687*4882a593Smuzhiyun dw_hdmi_dsc_bpp(struct rockchip_hdmi *hdmi,
688*4882a593Smuzhiyun 		int num_slices, int slice_width)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun 	bool hdmi_all_bpp = hdmi->dsc_cap.all_bpp;
691*4882a593Smuzhiyun 	int fractional_bpp = 0;
692*4882a593Smuzhiyun 	int hdmi_max_chunk_bytes = hdmi->dsc_cap.total_chunk_kbytes * 1024;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	return hdmi_dsc_get_bpp(hdmi, fractional_bpp, slice_width,
695*4882a593Smuzhiyun 				num_slices, hdmi_all_bpp,
696*4882a593Smuzhiyun 				hdmi_max_chunk_bytes);
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun 
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)699*4882a593Smuzhiyun static int dw_hdmi_qp_set_link_cfg(struct rockchip_hdmi *hdmi,
700*4882a593Smuzhiyun 				   u16 pic_width, u16 pic_height,
701*4882a593Smuzhiyun 				   u16 slice_width, u16 slice_height,
702*4882a593Smuzhiyun 				   u16 bits_per_pixel, u8 bits_per_component)
703*4882a593Smuzhiyun {
704*4882a593Smuzhiyun 	int i;
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	for (i = 0; i < PPS_TABLE_LEN; i++)
707*4882a593Smuzhiyun 		if (pic_width == pps_datas[i].pic_width &&
708*4882a593Smuzhiyun 		    pic_height == pps_datas[i].pic_height &&
709*4882a593Smuzhiyun 		    slice_width == pps_datas[i].slice_width &&
710*4882a593Smuzhiyun 		    slice_height == pps_datas[i].slice_height &&
711*4882a593Smuzhiyun 		    bits_per_component == pps_datas[i].bpc &&
712*4882a593Smuzhiyun 		    bits_per_pixel == pps_datas[i].bpp &&
713*4882a593Smuzhiyun 		    hdmi_bus_fmt_is_rgb(hdmi->output_bus_format) == pps_datas[i].convert_rgb)
714*4882a593Smuzhiyun 			break;
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	if (i == PPS_TABLE_LEN) {
717*4882a593Smuzhiyun 		dev_err(hdmi->dev, "can't find pps cfg!\n");
718*4882a593Smuzhiyun 		return -EINVAL;
719*4882a593Smuzhiyun 	}
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	memcpy(hdmi->link_cfg.pps_payload, pps_datas[i].raw_pps, 128);
722*4882a593Smuzhiyun 	hdmi->link_cfg.hcactive = DIV_ROUND_UP(slice_width * (bits_per_pixel / 16), 8) *
723*4882a593Smuzhiyun 		(pic_width / slice_width);
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	return 0;
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun 
dw_hdmi_qp_dsc_configure(struct rockchip_hdmi * hdmi,struct drm_display_mode * mode)728*4882a593Smuzhiyun static void dw_hdmi_qp_dsc_configure(struct rockchip_hdmi *hdmi,
729*4882a593Smuzhiyun 				     struct drm_display_mode *mode)
730*4882a593Smuzhiyun {
731*4882a593Smuzhiyun 	int ret;
732*4882a593Smuzhiyun 	int slice_height;
733*4882a593Smuzhiyun 	int slice_width;
734*4882a593Smuzhiyun 	int bits_per_pixel;
735*4882a593Smuzhiyun 	int slice_count;
736*4882a593Smuzhiyun 	bool hdmi_is_dsc_1_2;
737*4882a593Smuzhiyun 	unsigned int depth = hdmi_bus_fmt_color_depth(hdmi->output_bus_format);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	hdmi_is_dsc_1_2 = hdmi->dsc_cap.v_1p2;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	if (!hdmi_is_dsc_1_2)
742*4882a593Smuzhiyun 		return;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	slice_height = hdmi_dsc_get_slice_height(mode->vdisplay);
745*4882a593Smuzhiyun 	if (!slice_height)
746*4882a593Smuzhiyun 		return;
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	slice_count = hdmi_dsc_slices(hdmi, mode);
749*4882a593Smuzhiyun 	if (!slice_count)
750*4882a593Smuzhiyun 		return;
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	slice_width = DIV_ROUND_UP(mode->hdisplay, slice_count);
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	bits_per_pixel = dw_hdmi_dsc_bpp(hdmi, slice_count, slice_width);
755*4882a593Smuzhiyun 	if (!bits_per_pixel)
756*4882a593Smuzhiyun 		return;
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 	ret = dw_hdmi_qp_set_link_cfg(hdmi, mode->hdisplay,
759*4882a593Smuzhiyun 				      mode->vdisplay, slice_width,
760*4882a593Smuzhiyun 				      slice_height, bits_per_pixel, depth);
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	if (ret) {
763*4882a593Smuzhiyun 		dev_err(hdmi->dev, "set vdsc cfg failed\n");
764*4882a593Smuzhiyun 		return;
765*4882a593Smuzhiyun 	}
766*4882a593Smuzhiyun 	printf("dsc_enable\n");
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun 
drm_rk_select_color(struct hdmi_edid_data * edid_data,struct base_screen_info * screen_info,enum dw_hdmi_devtype dev_type,bool output_bus_format_rgb)769*4882a593Smuzhiyun static unsigned int drm_rk_select_color(struct hdmi_edid_data *edid_data,
770*4882a593Smuzhiyun 					struct base_screen_info *screen_info,
771*4882a593Smuzhiyun 					enum dw_hdmi_devtype dev_type,
772*4882a593Smuzhiyun 					bool output_bus_format_rgb)
773*4882a593Smuzhiyun {
774*4882a593Smuzhiyun 	struct drm_display_info *info = &edid_data->display_info;
775*4882a593Smuzhiyun 	struct drm_display_mode *mode = edid_data->preferred_mode;
776*4882a593Smuzhiyun 	struct drm_hdmi_info *hdmi_info = &edid_data->display_info.hdmi;
777*4882a593Smuzhiyun 	int max_tmds_clock = info->max_tmds_clock;
778*4882a593Smuzhiyun 	bool support_dc = false;
779*4882a593Smuzhiyun 	bool mode_420 = drm_mode_is_420(info, mode);
780*4882a593Smuzhiyun 	unsigned int color_depth = 8;
781*4882a593Smuzhiyun 	unsigned int base_color = DRM_HDMI_OUTPUT_YCBCR444;
782*4882a593Smuzhiyun 	unsigned int color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
783*4882a593Smuzhiyun 	unsigned long tmdsclock, pixclock = mode->clock;
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 	if (screen_info)
786*4882a593Smuzhiyun 		base_color = screen_info->format;
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	switch (base_color) {
789*4882a593Smuzhiyun 	case DRM_HDMI_OUTPUT_YCBCR_HQ:
790*4882a593Smuzhiyun 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
791*4882a593Smuzhiyun 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
792*4882a593Smuzhiyun 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
793*4882a593Smuzhiyun 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
794*4882a593Smuzhiyun 		else if (mode_420 && pixclock >= 340000)
795*4882a593Smuzhiyun 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
796*4882a593Smuzhiyun 		break;
797*4882a593Smuzhiyun 	case DRM_HDMI_OUTPUT_YCBCR_LQ:
798*4882a593Smuzhiyun 		if (mode_420 && pixclock >= 340000)
799*4882a593Smuzhiyun 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
800*4882a593Smuzhiyun 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
801*4882a593Smuzhiyun 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
802*4882a593Smuzhiyun 		else if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
803*4882a593Smuzhiyun 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
804*4882a593Smuzhiyun 		break;
805*4882a593Smuzhiyun 	case DRM_HDMI_OUTPUT_YCBCR420:
806*4882a593Smuzhiyun 		if (mode_420 && pixclock >= 340000)
807*4882a593Smuzhiyun 			color_format = DRM_HDMI_OUTPUT_YCBCR420;
808*4882a593Smuzhiyun 		break;
809*4882a593Smuzhiyun 	case DRM_HDMI_OUTPUT_YCBCR422:
810*4882a593Smuzhiyun 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
811*4882a593Smuzhiyun 			color_format = DRM_HDMI_OUTPUT_YCBCR422;
812*4882a593Smuzhiyun 		break;
813*4882a593Smuzhiyun 	case DRM_HDMI_OUTPUT_YCBCR444:
814*4882a593Smuzhiyun 		if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
815*4882a593Smuzhiyun 			color_format = DRM_HDMI_OUTPUT_YCBCR444;
816*4882a593Smuzhiyun 		break;
817*4882a593Smuzhiyun 	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
818*4882a593Smuzhiyun 	default:
819*4882a593Smuzhiyun 		break;
820*4882a593Smuzhiyun 	}
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 	if (output_bus_format_rgb)
823*4882a593Smuzhiyun 		color_format = DRM_HDMI_OUTPUT_DEFAULT_RGB;
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	if (color_format == DRM_HDMI_OUTPUT_DEFAULT_RGB &&
826*4882a593Smuzhiyun 	    info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)
827*4882a593Smuzhiyun 		support_dc = true;
828*4882a593Smuzhiyun 	if (color_format == DRM_HDMI_OUTPUT_YCBCR444 &&
829*4882a593Smuzhiyun 	    (info->edid_hdmi_dc_modes &
830*4882a593Smuzhiyun 	     (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30)))
831*4882a593Smuzhiyun 		support_dc = true;
832*4882a593Smuzhiyun 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422)
833*4882a593Smuzhiyun 		support_dc = true;
834*4882a593Smuzhiyun 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420 &&
835*4882a593Smuzhiyun 	    info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
836*4882a593Smuzhiyun 		support_dc = true;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
839*4882a593Smuzhiyun 		pixclock *= 2;
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 	if (screen_info && screen_info->depth == 10)
842*4882a593Smuzhiyun 		color_depth = screen_info->depth;
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 	if (mode->clock >= 600000)
845*4882a593Smuzhiyun 		color_format = DRM_HDMI_OUTPUT_YCBCR420;
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	if (color_format == DRM_HDMI_OUTPUT_YCBCR422 || color_depth == 8)
848*4882a593Smuzhiyun 		tmdsclock = pixclock;
849*4882a593Smuzhiyun 	else
850*4882a593Smuzhiyun 		tmdsclock = pixclock * color_depth / 8;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	if (color_format == DRM_HDMI_OUTPUT_YCBCR420)
853*4882a593Smuzhiyun 		tmdsclock /= 2;
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	if (!max_tmds_clock)
856*4882a593Smuzhiyun 		max_tmds_clock = 340000;
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 	if (hdmi_info->max_frl_rate_per_lane && mode->clock > 600000)
859*4882a593Smuzhiyun 		max_tmds_clock =
860*4882a593Smuzhiyun 			hdmi_info->max_lanes * hdmi_info->max_frl_rate_per_lane *
861*4882a593Smuzhiyun 				1000000;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	if (tmdsclock > max_tmds_clock) {
864*4882a593Smuzhiyun 		if (max_tmds_clock >= 594000) {
865*4882a593Smuzhiyun 			color_depth = 8;
866*4882a593Smuzhiyun 		} else if (max_tmds_clock > 340000) {
867*4882a593Smuzhiyun 			if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
868*4882a593Smuzhiyun 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
869*4882a593Smuzhiyun 		} else {
870*4882a593Smuzhiyun 			color_depth = 8;
871*4882a593Smuzhiyun 			if (drm_mode_is_420(info, mode) || tmdsclock >= 594000)
872*4882a593Smuzhiyun 				color_format = DRM_HDMI_OUTPUT_YCBCR420;
873*4882a593Smuzhiyun 		}
874*4882a593Smuzhiyun 	}
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	printf("color_format:%x\n", color_format);
877*4882a593Smuzhiyun 	if (color_depth > 8 && support_dc) {
878*4882a593Smuzhiyun 		switch (color_format) {
879*4882a593Smuzhiyun 		case DRM_HDMI_OUTPUT_YCBCR444:
880*4882a593Smuzhiyun 			return MEDIA_BUS_FMT_YUV10_1X30;
881*4882a593Smuzhiyun 		case DRM_HDMI_OUTPUT_YCBCR422:
882*4882a593Smuzhiyun 			return MEDIA_BUS_FMT_YUYV10_1X20;
883*4882a593Smuzhiyun 		case DRM_HDMI_OUTPUT_YCBCR420:
884*4882a593Smuzhiyun 			return MEDIA_BUS_FMT_UYYVYY10_0_5X30;
885*4882a593Smuzhiyun 		default:
886*4882a593Smuzhiyun 			return MEDIA_BUS_FMT_RGB101010_1X30;
887*4882a593Smuzhiyun 		}
888*4882a593Smuzhiyun 	} else {
889*4882a593Smuzhiyun 		switch (color_format) {
890*4882a593Smuzhiyun 		case DRM_HDMI_OUTPUT_YCBCR444:
891*4882a593Smuzhiyun 			return MEDIA_BUS_FMT_YUV8_1X24;
892*4882a593Smuzhiyun 		case DRM_HDMI_OUTPUT_YCBCR422:
893*4882a593Smuzhiyun 			return MEDIA_BUS_FMT_YUYV8_1X16;
894*4882a593Smuzhiyun 		case DRM_HDMI_OUTPUT_YCBCR420:
895*4882a593Smuzhiyun 			return MEDIA_BUS_FMT_UYYVYY8_0_5X24;
896*4882a593Smuzhiyun 		default:
897*4882a593Smuzhiyun 			return MEDIA_BUS_FMT_RGB888_1X24;
898*4882a593Smuzhiyun 		}
899*4882a593Smuzhiyun 	}
900*4882a593Smuzhiyun }
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun #define SUPPORT_HDMI_ALLM	BIT(1)
903*4882a593Smuzhiyun 
dw_hdmi_qp_selete_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)904*4882a593Smuzhiyun void dw_hdmi_qp_selete_output(struct hdmi_edid_data *edid_data,
905*4882a593Smuzhiyun 			      struct rockchip_connector *conn,
906*4882a593Smuzhiyun 			      unsigned int *bus_format,
907*4882a593Smuzhiyun 			      struct overscan *overscan,
908*4882a593Smuzhiyun 			      enum dw_hdmi_devtype dev_type,
909*4882a593Smuzhiyun 			      bool output_bus_format_rgb,
910*4882a593Smuzhiyun 			      void *data, struct display_state *state)
911*4882a593Smuzhiyun {
912*4882a593Smuzhiyun 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
913*4882a593Smuzhiyun 	struct drm_hdmi_info *hdmi_info = &edid_data->display_info.hdmi;
914*4882a593Smuzhiyun 	int ret, i, screen_size;
915*4882a593Smuzhiyun 	struct base_disp_info base_parameter;
916*4882a593Smuzhiyun 	struct base2_disp_info *base2_parameter = state->conn_state.disp_info;
917*4882a593Smuzhiyun 	const struct base_overscan *scan;
918*4882a593Smuzhiyun 	struct base_screen_info *screen_info = NULL;
919*4882a593Smuzhiyun 	struct base2_screen_info *screen_info2 = NULL;
920*4882a593Smuzhiyun 	int max_scan = 100;
921*4882a593Smuzhiyun 	int min_scan = 51;
922*4882a593Smuzhiyun 	int offset = 0;
923*4882a593Smuzhiyun 	int color_depth;
924*4882a593Smuzhiyun 	unsigned int tmdsclk;
925*4882a593Smuzhiyun 	unsigned int pixel_clk;
926*4882a593Smuzhiyun 	bool found = false;
927*4882a593Smuzhiyun 	struct blk_desc *dev_desc;
928*4882a593Smuzhiyun 	disk_partition_t part_info;
929*4882a593Smuzhiyun 	char baseparameter_buf[8 * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun 	overscan->left_margin = max_scan;
932*4882a593Smuzhiyun 	overscan->right_margin = max_scan;
933*4882a593Smuzhiyun 	overscan->top_margin = max_scan;
934*4882a593Smuzhiyun 	overscan->bottom_margin = max_scan;
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	hdmi->max_frl_rate_per_lane = hdmi_info->max_frl_rate_per_lane;
937*4882a593Smuzhiyun 	hdmi->max_lanes = hdmi_info->max_lanes;
938*4882a593Smuzhiyun 	memcpy(&hdmi->dsc_cap, &hdmi_info->dsc_cap, sizeof(struct drm_hdmi_dsc_cap));
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 	if (output_bus_format_rgb)
941*4882a593Smuzhiyun 		*bus_format = MEDIA_BUS_FMT_RGB888_1X24;
942*4882a593Smuzhiyun 	else
943*4882a593Smuzhiyun 		*bus_format = MEDIA_BUS_FMT_YUV8_1X24;
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	if (!base2_parameter) {
946*4882a593Smuzhiyun 		dev_desc = rockchip_get_bootdev();
947*4882a593Smuzhiyun 		if (!dev_desc) {
948*4882a593Smuzhiyun 			printf("%s: Could not find device\n", __func__);
949*4882a593Smuzhiyun 			goto null_basep;
950*4882a593Smuzhiyun 		}
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 		ret = part_get_info_by_name(dev_desc, "baseparameter",
953*4882a593Smuzhiyun 					    &part_info);
954*4882a593Smuzhiyun 		if (ret < 0) {
955*4882a593Smuzhiyun 			printf("Could not find baseparameter partition\n");
956*4882a593Smuzhiyun 			goto null_basep;
957*4882a593Smuzhiyun 		}
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun read_aux:
960*4882a593Smuzhiyun 		ret = blk_dread(dev_desc, part_info.start + offset, 1,
961*4882a593Smuzhiyun 				(void *)baseparameter_buf);
962*4882a593Smuzhiyun 		if (ret < 0) {
963*4882a593Smuzhiyun 			printf("read baseparameter failed\n");
964*4882a593Smuzhiyun 			goto null_basep;
965*4882a593Smuzhiyun 		}
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun 		memcpy(&base_parameter, baseparameter_buf,
968*4882a593Smuzhiyun 		       sizeof(base_parameter));
969*4882a593Smuzhiyun 		scan = &base_parameter.scan;
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 		screen_size = sizeof(base_parameter.screen_list) /
972*4882a593Smuzhiyun 			sizeof(base_parameter.screen_list[0]);
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 		for (i = 0; i < screen_size; i++) {
975*4882a593Smuzhiyun 			if (base_parameter.screen_list[i].type ==
976*4882a593Smuzhiyun 			    DRM_MODE_CONNECTOR_HDMIA) {
977*4882a593Smuzhiyun 				found = true;
978*4882a593Smuzhiyun 				screen_info = &base_parameter.screen_list[i];
979*4882a593Smuzhiyun 				break;
980*4882a593Smuzhiyun 			}
981*4882a593Smuzhiyun 		}
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun 		if (!found && !offset) {
984*4882a593Smuzhiyun 			printf("hdmi info isn't saved in main block\n");
985*4882a593Smuzhiyun 			offset += 16;
986*4882a593Smuzhiyun 			goto read_aux;
987*4882a593Smuzhiyun 		}
988*4882a593Smuzhiyun 	} else {
989*4882a593Smuzhiyun 		bool allm_en = false;
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 		scan = &base2_parameter->overscan_info;
992*4882a593Smuzhiyun 		screen_size = sizeof(base2_parameter->screen_info) /
993*4882a593Smuzhiyun 			sizeof(base2_parameter->screen_info[0]);
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 		for (i = 0; i < screen_size; i++) {
996*4882a593Smuzhiyun 			if (base2_parameter->screen_info[i].type ==
997*4882a593Smuzhiyun 			    DRM_MODE_CONNECTOR_HDMIA) {
998*4882a593Smuzhiyun 				screen_info2 =
999*4882a593Smuzhiyun 					&base2_parameter->screen_info[i];
1000*4882a593Smuzhiyun 				break;
1001*4882a593Smuzhiyun 			}
1002*4882a593Smuzhiyun 		}
1003*4882a593Smuzhiyun 		screen_info = malloc(sizeof(*screen_info));
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 		screen_info->type = screen_info2->type;
1006*4882a593Smuzhiyun 		screen_info->mode = screen_info2->resolution;
1007*4882a593Smuzhiyun 		screen_info->format = screen_info2->format;
1008*4882a593Smuzhiyun 		screen_info->depth = screen_info2->depthc;
1009*4882a593Smuzhiyun 		screen_info->feature = screen_info2->feature;
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun 		/* check if allm is enabled */
1012*4882a593Smuzhiyun 		allm_en = base2_parameter->reserved[0] & BIT(0);
1013*4882a593Smuzhiyun 		if (allm_en && (hdmi_info->add_func & SUPPORT_HDMI_ALLM))
1014*4882a593Smuzhiyun 			hdmi->allm_en = true;
1015*4882a593Smuzhiyun 		else
1016*4882a593Smuzhiyun 			hdmi->allm_en = false;
1017*4882a593Smuzhiyun 	}
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun 	if (scan->leftscale < min_scan && scan->leftscale > 0)
1020*4882a593Smuzhiyun 		overscan->left_margin = min_scan;
1021*4882a593Smuzhiyun 	else if (scan->leftscale < max_scan && scan->leftscale > 0)
1022*4882a593Smuzhiyun 		overscan->left_margin = scan->leftscale;
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun 	if (scan->rightscale < min_scan && scan->rightscale > 0)
1025*4882a593Smuzhiyun 		overscan->right_margin = min_scan;
1026*4882a593Smuzhiyun 	else if (scan->rightscale < max_scan && scan->rightscale > 0)
1027*4882a593Smuzhiyun 		overscan->right_margin = scan->rightscale;
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 	if (scan->topscale < min_scan && scan->topscale > 0)
1030*4882a593Smuzhiyun 		overscan->top_margin = min_scan;
1031*4882a593Smuzhiyun 	else if (scan->topscale < max_scan && scan->topscale > 0)
1032*4882a593Smuzhiyun 		overscan->top_margin = scan->topscale;
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	if (scan->bottomscale < min_scan && scan->bottomscale > 0)
1035*4882a593Smuzhiyun 		overscan->bottom_margin = min_scan;
1036*4882a593Smuzhiyun 	else if (scan->bottomscale < max_scan && scan->bottomscale > 0)
1037*4882a593Smuzhiyun 		overscan->bottom_margin = scan->bottomscale;
1038*4882a593Smuzhiyun 
1039*4882a593Smuzhiyun null_basep:
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun 	if (screen_info)
1042*4882a593Smuzhiyun 		printf("base_parameter.mode:%dx%d\n",
1043*4882a593Smuzhiyun 		       screen_info->mode.hdisplay,
1044*4882a593Smuzhiyun 		       screen_info->mode.vdisplay);
1045*4882a593Smuzhiyun 	drm_rk_select_mode(edid_data, screen_info);
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun 	*bus_format = drm_rk_select_color(edid_data, screen_info,
1048*4882a593Smuzhiyun 					  dev_type, output_bus_format_rgb);
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun 	if (state->force_output) {
1051*4882a593Smuzhiyun 		memcpy(edid_data->preferred_mode, &state->force_mode,
1052*4882a593Smuzhiyun 		       sizeof(struct drm_display_mode));
1053*4882a593Smuzhiyun 		if (state->force_bus_format)
1054*4882a593Smuzhiyun 			*bus_format = state->force_bus_format;
1055*4882a593Smuzhiyun 	}
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 	hdmi->bus_format = *bus_format;
1058*4882a593Smuzhiyun 	color_depth = hdmi_bus_fmt_color_depth(*bus_format);
1059*4882a593Smuzhiyun 	pixel_clk = edid_data->preferred_mode->clock;
1060*4882a593Smuzhiyun 	tmdsclk = hdmi_get_tmdsclock(hdmi, pixel_clk);
1061*4882a593Smuzhiyun 	if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format))
1062*4882a593Smuzhiyun 		tmdsclk /= 2;
1063*4882a593Smuzhiyun 	hdmi_select_link_config(hdmi, edid_data->preferred_mode, tmdsclk);
1064*4882a593Smuzhiyun 	dw_hdmi_qp_dsc_configure(hdmi, edid_data->preferred_mode);
1065*4882a593Smuzhiyun 	if (hdmi->link_cfg.frl_mode) {
1066*4882a593Smuzhiyun 		dm_gpio_set_value(&hdmi->enable_gpio, 0);
1067*4882a593Smuzhiyun 		/* in the current version, support max 40G frl */
1068*4882a593Smuzhiyun 		if (hdmi->link_cfg.rate_per_lane >= 10) {
1069*4882a593Smuzhiyun 			hdmi->link_cfg.frl_lanes = 4;
1070*4882a593Smuzhiyun 			hdmi->link_cfg.rate_per_lane = 10;
1071*4882a593Smuzhiyun 		}
1072*4882a593Smuzhiyun 		hdmi->bus_width = hdmi->link_cfg.frl_lanes *
1073*4882a593Smuzhiyun 			hdmi->link_cfg.rate_per_lane * 1000000;
1074*4882a593Smuzhiyun 		/* 10 bit color depth and frl mode */
1075*4882a593Smuzhiyun 		if (color_depth == 10)
1076*4882a593Smuzhiyun 			hdmi->bus_width |=
1077*4882a593Smuzhiyun 				COLOR_DEPTH_10BIT | HDMI_FRL_MODE;
1078*4882a593Smuzhiyun 		else
1079*4882a593Smuzhiyun 			hdmi->bus_width |= HDMI_FRL_MODE;
1080*4882a593Smuzhiyun 	} else {
1081*4882a593Smuzhiyun 		dm_gpio_set_value(&hdmi->enable_gpio, 1);
1082*4882a593Smuzhiyun 		hdmi->bus_width =
1083*4882a593Smuzhiyun 			hdmi_get_tmdsclock(hdmi, pixel_clk * 10);
1084*4882a593Smuzhiyun 		if (hdmi_bus_fmt_is_yuv420(*bus_format))
1085*4882a593Smuzhiyun 			hdmi->bus_width /= 2;
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 		if (color_depth == 10 && !hdmi_bus_fmt_is_yuv422(*bus_format))
1088*4882a593Smuzhiyun 			hdmi->bus_width |= COLOR_DEPTH_10BIT;
1089*4882a593Smuzhiyun 	}
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	rockchip_phy_set_bus_width(conn->phy, hdmi->bus_width);
1092*4882a593Smuzhiyun }
1093*4882a593Smuzhiyun 
rk3588_set_link_mode(struct rockchip_hdmi * hdmi)1094*4882a593Smuzhiyun static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi)
1095*4882a593Smuzhiyun {
1096*4882a593Smuzhiyun 	int val;
1097*4882a593Smuzhiyun 	bool is_hdmi0;
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun 	if (!hdmi->id)
1100*4882a593Smuzhiyun 		is_hdmi0 = true;
1101*4882a593Smuzhiyun 	else
1102*4882a593Smuzhiyun 		is_hdmi0 = false;
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun 	if (!hdmi->link_cfg.frl_mode) {
1105*4882a593Smuzhiyun 		val = HIWORD_UPDATE(0, RK3588_HDMI21_MASK);
1106*4882a593Smuzhiyun 		if (is_hdmi0)
1107*4882a593Smuzhiyun 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4);
1108*4882a593Smuzhiyun 		else
1109*4882a593Smuzhiyun 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7);
1110*4882a593Smuzhiyun 
1111*4882a593Smuzhiyun 		val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1112*4882a593Smuzhiyun 		if (is_hdmi0)
1113*4882a593Smuzhiyun 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1114*4882a593Smuzhiyun 		else
1115*4882a593Smuzhiyun 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun 		return;
1118*4882a593Smuzhiyun 	}
1119*4882a593Smuzhiyun 
1120*4882a593Smuzhiyun 	val = HIWORD_UPDATE(RK3588_HDMI21_MASK, RK3588_HDMI21_MASK);
1121*4882a593Smuzhiyun 	if (is_hdmi0)
1122*4882a593Smuzhiyun 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4);
1123*4882a593Smuzhiyun 	else
1124*4882a593Smuzhiyun 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7);
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun 	if (hdmi->link_cfg.dsc_mode) {
1127*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_COMPRESS_MODE_MASK | RK3588_COMPRESSED_DATA,
1128*4882a593Smuzhiyun 				    RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1129*4882a593Smuzhiyun 		if (is_hdmi0)
1130*4882a593Smuzhiyun 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1131*4882a593Smuzhiyun 		else
1132*4882a593Smuzhiyun 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1133*4882a593Smuzhiyun 	} else {
1134*4882a593Smuzhiyun 		val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK);
1135*4882a593Smuzhiyun 		if (is_hdmi0)
1136*4882a593Smuzhiyun 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1137*4882a593Smuzhiyun 		else
1138*4882a593Smuzhiyun 			writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1139*4882a593Smuzhiyun 	}
1140*4882a593Smuzhiyun }
1141*4882a593Smuzhiyun 
rk3588_set_color_format(struct rockchip_hdmi * hdmi,u64 bus_format,u32 depth)1142*4882a593Smuzhiyun static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format,
1143*4882a593Smuzhiyun 				    u32 depth)
1144*4882a593Smuzhiyun {
1145*4882a593Smuzhiyun 	u32 val = 0;
1146*4882a593Smuzhiyun 
1147*4882a593Smuzhiyun 	switch (bus_format) {
1148*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X24:
1149*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB101010_1X30:
1150*4882a593Smuzhiyun 		val = HIWORD_UPDATE(0, RK3588_COLOR_FORMAT_MASK);
1151*4882a593Smuzhiyun 		break;
1152*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1153*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1154*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_YUV420, RK3588_COLOR_FORMAT_MASK);
1155*4882a593Smuzhiyun 		break;
1156*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV8_1X24:
1157*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV10_1X30:
1158*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_YUV444, RK3588_COLOR_FORMAT_MASK);
1159*4882a593Smuzhiyun 		break;
1160*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV10_1X20:
1161*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV8_1X16:
1162*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_YUV422, RK3588_COLOR_FORMAT_MASK);
1163*4882a593Smuzhiyun 		break;
1164*4882a593Smuzhiyun 	default:
1165*4882a593Smuzhiyun 		dev_err(hdmi->dev, "can't set correct color format\n");
1166*4882a593Smuzhiyun 		return;
1167*4882a593Smuzhiyun 	}
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun 	if (hdmi->link_cfg.dsc_mode)
1170*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_COMPRESSED_DATA, RK3588_COLOR_FORMAT_MASK);
1171*4882a593Smuzhiyun 
1172*4882a593Smuzhiyun 	if (depth == 8 || bus_format == MEDIA_BUS_FMT_YUYV10_1X20)
1173*4882a593Smuzhiyun 		val |= HIWORD_UPDATE(RK3588_8BPC, RK3588_COLOR_DEPTH_MASK);
1174*4882a593Smuzhiyun 	else
1175*4882a593Smuzhiyun 		val |= HIWORD_UPDATE(RK3588_10BPC, RK3588_COLOR_DEPTH_MASK);
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun 	if (!hdmi->id)
1178*4882a593Smuzhiyun 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1179*4882a593Smuzhiyun 	else
1180*4882a593Smuzhiyun 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1181*4882a593Smuzhiyun }
1182*4882a593Smuzhiyun 
rk3588_set_grf_cfg(void * data)1183*4882a593Smuzhiyun void rk3588_set_grf_cfg(void *data)
1184*4882a593Smuzhiyun {
1185*4882a593Smuzhiyun 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1186*4882a593Smuzhiyun 	int color_depth;
1187*4882a593Smuzhiyun 
1188*4882a593Smuzhiyun 	rk3588_set_link_mode(hdmi);
1189*4882a593Smuzhiyun 	color_depth = hdmi_bus_fmt_color_depth(hdmi->bus_format);
1190*4882a593Smuzhiyun 	rk3588_set_color_format(hdmi, hdmi->bus_format, color_depth);
1191*4882a593Smuzhiyun }
1192*4882a593Smuzhiyun 
dw_hdmi_qp_set_iomux(void * data)1193*4882a593Smuzhiyun void dw_hdmi_qp_set_iomux(void *data)
1194*4882a593Smuzhiyun {
1195*4882a593Smuzhiyun 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1196*4882a593Smuzhiyun 	u32 val;
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 	if (!hdmi->id) {
1199*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
1200*4882a593Smuzhiyun 		      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
1201*4882a593Smuzhiyun 		      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
1202*4882a593Smuzhiyun 		      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
1203*4882a593Smuzhiyun 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3);
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
1206*4882a593Smuzhiyun 				    RK3588_SET_HPD_PATH_MASK);
1207*4882a593Smuzhiyun 		writel(val, hdmi->grf + RK3588_GRF_SOC_CON7);
1208*4882a593Smuzhiyun 
1209*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
1210*4882a593Smuzhiyun 				    RK3588_HDMI0_GRANT_SEL);
1211*4882a593Smuzhiyun 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9);
1212*4882a593Smuzhiyun 	} else {
1213*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
1214*4882a593Smuzhiyun 		      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
1215*4882a593Smuzhiyun 		      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
1216*4882a593Smuzhiyun 		      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
1217*4882a593Smuzhiyun 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6);
1218*4882a593Smuzhiyun 
1219*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
1220*4882a593Smuzhiyun 				    RK3588_SET_HPD_PATH_MASK);
1221*4882a593Smuzhiyun 		writel(val, hdmi->grf + RK3588_GRF_SOC_CON7);
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 		val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL,
1224*4882a593Smuzhiyun 				    RK3588_HDMI1_GRANT_SEL);
1225*4882a593Smuzhiyun 		writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9);
1226*4882a593Smuzhiyun 	}
1227*4882a593Smuzhiyun }
1228*4882a593Smuzhiyun 
dw_hdmi_rockchip_get_link_cfg(void * data)1229*4882a593Smuzhiyun struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data)
1230*4882a593Smuzhiyun {
1231*4882a593Smuzhiyun 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1232*4882a593Smuzhiyun 
1233*4882a593Smuzhiyun 	return &hdmi->link_cfg;
1234*4882a593Smuzhiyun }
1235*4882a593Smuzhiyun 
dw_hdmi_qp_rockchip_phy_disable(struct rockchip_connector * conn,void * data,void * state)1236*4882a593Smuzhiyun static void dw_hdmi_qp_rockchip_phy_disable(struct rockchip_connector *conn, void *data,
1237*4882a593Smuzhiyun 					    void *state)
1238*4882a593Smuzhiyun {
1239*4882a593Smuzhiyun 	rockchip_phy_power_off(conn->phy);
1240*4882a593Smuzhiyun }
1241*4882a593Smuzhiyun 
dw_hdmi_qp_rockchip_genphy_init(struct rockchip_connector * conn,void * data,void * state)1242*4882a593Smuzhiyun static int dw_hdmi_qp_rockchip_genphy_init(struct rockchip_connector *conn, void *data, void *state)
1243*4882a593Smuzhiyun {
1244*4882a593Smuzhiyun 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1245*4882a593Smuzhiyun 
1246*4882a593Smuzhiyun 	dw_hdmi_qp_rockchip_phy_disable(conn, data, state);
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun 	rockchip_phy_set_bus_width(conn->phy, hdmi->bus_width);
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun 	return rockchip_phy_power_on(conn->phy);
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun 
dw_hdmi_rk3588_read_hpd(void * data)1253*4882a593Smuzhiyun static enum drm_connector_status dw_hdmi_rk3588_read_hpd(void *data)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun 	u32 val;
1256*4882a593Smuzhiyun 	int ret;
1257*4882a593Smuzhiyun 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1258*4882a593Smuzhiyun 
1259*4882a593Smuzhiyun 	val = readl(hdmi->grf + RK3588_GRF_SOC_STATUS1);
1260*4882a593Smuzhiyun 
1261*4882a593Smuzhiyun 	if (!hdmi->id) {
1262*4882a593Smuzhiyun 		if (val & RK3588_HDMI0_LEVEL_INT)
1263*4882a593Smuzhiyun 			ret = connector_status_connected;
1264*4882a593Smuzhiyun 		else
1265*4882a593Smuzhiyun 			ret = connector_status_disconnected;
1266*4882a593Smuzhiyun 	} else {
1267*4882a593Smuzhiyun 		if (val & RK3588_HDMI1_LEVEL_INT)
1268*4882a593Smuzhiyun 			ret = connector_status_connected;
1269*4882a593Smuzhiyun 		else
1270*4882a593Smuzhiyun 			ret = connector_status_disconnected;
1271*4882a593Smuzhiyun 	}
1272*4882a593Smuzhiyun 
1273*4882a593Smuzhiyun 	return ret;
1274*4882a593Smuzhiyun }
1275*4882a593Smuzhiyun 
dw_hdmi_rk3588_set_pll(struct rockchip_connector * conn,void * data,void * state)1276*4882a593Smuzhiyun static void dw_hdmi_rk3588_set_pll(struct rockchip_connector *conn, void *data, void *state)
1277*4882a593Smuzhiyun {
1278*4882a593Smuzhiyun 	struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
1279*4882a593Smuzhiyun 	u32 rate = (hdmi->bus_width & DATA_RATE_MASK) * 100;
1280*4882a593Smuzhiyun 
1281*4882a593Smuzhiyun 	clk_set_rate(&hdmi->link_clk, rate);
1282*4882a593Smuzhiyun }
1283*4882a593Smuzhiyun static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = {
1284*4882a593Smuzhiyun 	.init = dw_hdmi_qp_rockchip_genphy_init,
1285*4882a593Smuzhiyun 	.disable = dw_hdmi_qp_rockchip_phy_disable,
1286*4882a593Smuzhiyun 	.read_hpd = dw_hdmi_rk3588_read_hpd,
1287*4882a593Smuzhiyun 	.set_pll = dw_hdmi_rk3588_set_pll,
1288*4882a593Smuzhiyun };
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun static const struct rockchip_connector_funcs rockchip_dw_hdmi_qp_funcs = {
1291*4882a593Smuzhiyun 	.init = rockchip_dw_hdmi_qp_init,
1292*4882a593Smuzhiyun 	.deinit = rockchip_dw_hdmi_qp_deinit,
1293*4882a593Smuzhiyun 	.prepare = rockchip_dw_hdmi_qp_prepare,
1294*4882a593Smuzhiyun 	.enable = rockchip_dw_hdmi_qp_enable,
1295*4882a593Smuzhiyun 	.disable = rockchip_dw_hdmi_qp_disable,
1296*4882a593Smuzhiyun 	.get_timing = rockchip_dw_hdmi_qp_get_timing,
1297*4882a593Smuzhiyun 	.detect = rockchip_dw_hdmi_qp_detect,
1298*4882a593Smuzhiyun 	.get_edid = rockchip_dw_hdmi_qp_get_edid,
1299*4882a593Smuzhiyun };
1300*4882a593Smuzhiyun 
1301*4882a593Smuzhiyun const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = {
1302*4882a593Smuzhiyun 	.qp_phy_ops    = &rk3588_hdmi_phy_ops,
1303*4882a593Smuzhiyun 	.phy_name   = "samsung_hdptx_phy",
1304*4882a593Smuzhiyun 	.dev_type   = RK3588_HDMI,
1305*4882a593Smuzhiyun };
1306*4882a593Smuzhiyun 
rockchip_dw_hdmi_qp_probe(struct udevice * dev)1307*4882a593Smuzhiyun static int rockchip_dw_hdmi_qp_probe(struct udevice *dev)
1308*4882a593Smuzhiyun {
1309*4882a593Smuzhiyun 	int ret;
1310*4882a593Smuzhiyun 	struct regmap *map;
1311*4882a593Smuzhiyun 	struct rockchip_hdmi *hdmi = dev_get_priv(dev);
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun 	hdmi->dev = dev;
1314*4882a593Smuzhiyun 
1315*4882a593Smuzhiyun 	hdmi->id = of_alias_get_id(ofnode_to_np(dev->node), "hdmi");
1316*4882a593Smuzhiyun 	if (hdmi->id < 0)
1317*4882a593Smuzhiyun 		hdmi->id = 0;
1318*4882a593Smuzhiyun 
1319*4882a593Smuzhiyun 	hdmi->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
1320*4882a593Smuzhiyun 
1321*4882a593Smuzhiyun 	if (hdmi->grf <= 0) {
1322*4882a593Smuzhiyun 		dev_err(dev, "%s: Get syscon grf failed (ret=%p)\n",
1323*4882a593Smuzhiyun 			__func__, hdmi->grf);
1324*4882a593Smuzhiyun 		return -ENXIO;
1325*4882a593Smuzhiyun 	}
1326*4882a593Smuzhiyun 
1327*4882a593Smuzhiyun 	map = syscon_regmap_lookup_by_phandle(dev, "rockchip,vo1_grf");
1328*4882a593Smuzhiyun 	hdmi->vo1_grf = regmap_get_range(map, 0);
1329*4882a593Smuzhiyun 
1330*4882a593Smuzhiyun 	if (hdmi->vo1_grf <= 0) {
1331*4882a593Smuzhiyun 		dev_err(dev, "%s: Get syscon vo1 grf failed (ret=%p)\n",
1332*4882a593Smuzhiyun 			__func__, hdmi->vo1_grf);
1333*4882a593Smuzhiyun 		return -ENXIO;
1334*4882a593Smuzhiyun 	}
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun 	ret = gpio_request_by_name(dev, "enable-gpios", 0,
1337*4882a593Smuzhiyun 				   &hdmi->enable_gpio, GPIOD_IS_OUT);
1338*4882a593Smuzhiyun 	if (ret) {
1339*4882a593Smuzhiyun 		dev_err(dev, "Cannot get enable GPIO: %d\n", ret);
1340*4882a593Smuzhiyun 		return ret;
1341*4882a593Smuzhiyun 	}
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun 	ret = clk_get_by_name(dev, "link_clk", &hdmi->link_clk);
1344*4882a593Smuzhiyun 	if (ret) {
1345*4882a593Smuzhiyun 		printf("%s: can't get link_clk\n", __func__);
1346*4882a593Smuzhiyun 		return ret;
1347*4882a593Smuzhiyun 	}
1348*4882a593Smuzhiyun 
1349*4882a593Smuzhiyun 	rockchip_connector_bind(&hdmi->connector, dev, hdmi->id, &rockchip_dw_hdmi_qp_funcs,
1350*4882a593Smuzhiyun 				NULL, DRM_MODE_CONNECTOR_HDMIA);
1351*4882a593Smuzhiyun 
1352*4882a593Smuzhiyun 	return 0;
1353*4882a593Smuzhiyun }
1354*4882a593Smuzhiyun 
1355*4882a593Smuzhiyun static const struct udevice_id rockchip_dw_hdmi_qp_ids[] = {
1356*4882a593Smuzhiyun 	{
1357*4882a593Smuzhiyun 	 .compatible = "rockchip,rk3588-dw-hdmi",
1358*4882a593Smuzhiyun 	 .data = (ulong)&rk3588_hdmi_drv_data,
1359*4882a593Smuzhiyun 	}, {}
1360*4882a593Smuzhiyun };
1361*4882a593Smuzhiyun 
1362*4882a593Smuzhiyun U_BOOT_DRIVER(rockchip_dw_hdmi_qp) = {
1363*4882a593Smuzhiyun 	.name = "rockchip_dw_hdmi_qp",
1364*4882a593Smuzhiyun 	.id = UCLASS_DISPLAY,
1365*4882a593Smuzhiyun 	.of_match = rockchip_dw_hdmi_qp_ids,
1366*4882a593Smuzhiyun 	.probe	= rockchip_dw_hdmi_qp_probe,
1367*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rockchip_hdmi),
1368*4882a593Smuzhiyun };
1369