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