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