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