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