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