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 1060 static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi) 1061 { 1062 int val; 1063 bool is_hdmi0; 1064 1065 if (!hdmi->id) 1066 is_hdmi0 = true; 1067 else 1068 is_hdmi0 = false; 1069 1070 if (!hdmi->link_cfg.frl_mode) { 1071 val = HIWORD_UPDATE(0, RK3588_HDMI21_MASK); 1072 if (is_hdmi0) 1073 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4); 1074 else 1075 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7); 1076 1077 val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK); 1078 if (is_hdmi0) 1079 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3); 1080 else 1081 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6); 1082 1083 return; 1084 } 1085 1086 val = HIWORD_UPDATE(RK3588_HDMI21_MASK, RK3588_HDMI21_MASK); 1087 if (is_hdmi0) 1088 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON4); 1089 else 1090 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON7); 1091 1092 if (hdmi->link_cfg.dsc_mode) { 1093 val = HIWORD_UPDATE(RK3588_COMPRESS_MODE_MASK | RK3588_COMPRESSED_DATA, 1094 RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK); 1095 if (is_hdmi0) 1096 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3); 1097 else 1098 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6); 1099 } else { 1100 val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK); 1101 if (is_hdmi0) 1102 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3); 1103 else 1104 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6); 1105 } 1106 } 1107 1108 static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format, 1109 u32 depth) 1110 { 1111 u32 val = 0; 1112 1113 switch (bus_format) { 1114 case MEDIA_BUS_FMT_RGB888_1X24: 1115 case MEDIA_BUS_FMT_RGB101010_1X30: 1116 val = HIWORD_UPDATE(0, RK3588_COLOR_FORMAT_MASK); 1117 break; 1118 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1119 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1120 val = HIWORD_UPDATE(RK3588_YUV420, RK3588_COLOR_FORMAT_MASK); 1121 break; 1122 case MEDIA_BUS_FMT_YUV8_1X24: 1123 case MEDIA_BUS_FMT_YUV10_1X30: 1124 val = HIWORD_UPDATE(RK3588_YUV444, RK3588_COLOR_FORMAT_MASK); 1125 break; 1126 default: 1127 dev_err(hdmi->dev, "can't set correct color format\n"); 1128 return; 1129 } 1130 1131 if (hdmi->link_cfg.dsc_mode) 1132 val = HIWORD_UPDATE(RK3588_COMPRESSED_DATA, RK3588_COLOR_FORMAT_MASK); 1133 1134 if (depth == 8) 1135 val |= HIWORD_UPDATE(RK3588_8BPC, RK3588_COLOR_DEPTH_MASK); 1136 else 1137 val |= HIWORD_UPDATE(RK3588_10BPC, RK3588_COLOR_DEPTH_MASK); 1138 1139 if (!hdmi->id) 1140 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3); 1141 else 1142 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6); 1143 } 1144 1145 void rk3588_set_grf_cfg(void *data) 1146 { 1147 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 1148 int color_depth; 1149 1150 rk3588_set_link_mode(hdmi); 1151 color_depth = hdmi_bus_fmt_color_depth(hdmi->bus_format); 1152 rk3588_set_color_format(hdmi, hdmi->bus_format, color_depth); 1153 } 1154 1155 void dw_hdmi_qp_set_iomux(void *data) 1156 { 1157 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 1158 u32 val; 1159 1160 if (!hdmi->id) { 1161 val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | 1162 HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | 1163 HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | 1164 HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); 1165 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON3); 1166 1167 val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, 1168 RK3588_SET_HPD_PATH_MASK); 1169 writel(val, hdmi->grf + RK3588_GRF_SOC_CON7); 1170 1171 val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, 1172 RK3588_HDMI0_GRANT_SEL); 1173 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9); 1174 } else { 1175 val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | 1176 HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | 1177 HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | 1178 HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); 1179 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON6); 1180 1181 val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, 1182 RK3588_SET_HPD_PATH_MASK); 1183 writel(val, hdmi->grf + RK3588_GRF_SOC_CON7); 1184 1185 val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL, 1186 RK3588_HDMI1_GRANT_SEL); 1187 writel(val, hdmi->vo1_grf + RK3588_GRF_VO1_CON9); 1188 } 1189 } 1190 1191 struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data) 1192 { 1193 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 1194 1195 return &hdmi->link_cfg; 1196 } 1197 1198 static void dw_hdmi_qp_rockchip_phy_disable(void *data, void *state) 1199 { 1200 struct display_state *display_state = (struct display_state *)state; 1201 struct connector_state *conn_state = &display_state->conn_state; 1202 1203 rockchip_phy_power_off(conn_state->phy); 1204 } 1205 1206 static int dw_hdmi_qp_rockchip_genphy_init(void *data, void *state) 1207 { 1208 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 1209 struct display_state *display_state = (struct display_state *)state; 1210 struct connector_state *conn_state = &display_state->conn_state; 1211 1212 dw_hdmi_qp_rockchip_phy_disable(data, state); 1213 1214 rockchip_phy_set_bus_width(conn_state->phy, hdmi->bus_width); 1215 1216 return rockchip_phy_power_on(conn_state->phy); 1217 } 1218 1219 static enum drm_connector_status dw_hdmi_rk3588_read_hpd(void *data) 1220 { 1221 u32 val; 1222 int ret; 1223 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 1224 1225 val = readl(hdmi->grf + RK3588_GRF_SOC_STATUS1); 1226 1227 if (!hdmi->id) { 1228 if (val & RK3588_HDMI0_LEVEL_INT) 1229 ret = connector_status_connected; 1230 else 1231 ret = connector_status_disconnected; 1232 } else { 1233 if (val & RK3588_HDMI1_LEVEL_INT) 1234 ret = connector_status_connected; 1235 else 1236 ret = connector_status_disconnected; 1237 } 1238 1239 return ret; 1240 } 1241 1242 static void dw_hdmi_rk3588_set_pll(void *data, void *state) 1243 { 1244 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 1245 struct display_state *display_state = (struct display_state *)state; 1246 struct connector_state *conn_state = &display_state->conn_state; 1247 struct drm_display_mode *mode = &conn_state->mode; 1248 1249 if (hdmi_bus_fmt_is_yuv420(hdmi->bus_format)) 1250 rockchip_phy_set_pll(conn_state->phy, mode->clock / 2 * 1000); 1251 else 1252 rockchip_phy_set_pll(conn_state->phy, mode->clock * 1000); 1253 } 1254 1255 static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = { 1256 .init = dw_hdmi_qp_rockchip_genphy_init, 1257 .disable = dw_hdmi_qp_rockchip_phy_disable, 1258 .read_hpd = dw_hdmi_rk3588_read_hpd, 1259 .set_pll = dw_hdmi_rk3588_set_pll, 1260 }; 1261 1262 static const struct rockchip_connector_funcs rockchip_dw_hdmi_qp_funcs = { 1263 .pre_init = rockchip_dw_hdmi_qp_pre_init, 1264 .init = rockchip_dw_hdmi_qp_init, 1265 .deinit = rockchip_dw_hdmi_qp_deinit, 1266 .prepare = rockchip_dw_hdmi_qp_prepare, 1267 .enable = rockchip_dw_hdmi_qp_enable, 1268 .disable = rockchip_dw_hdmi_qp_disable, 1269 .get_timing = rockchip_dw_hdmi_qp_get_timing, 1270 .detect = rockchip_dw_hdmi_qp_detect, 1271 .get_edid = rockchip_dw_hdmi_qp_get_edid, 1272 }; 1273 1274 const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = { 1275 .qp_phy_ops = &rk3588_hdmi_phy_ops, 1276 .phy_name = "samsung_hdptx_phy", 1277 .dev_type = RK3588_HDMI, 1278 }; 1279 1280 static int rockchip_dw_hdmi_qp_probe(struct udevice *dev) 1281 { 1282 int ret; 1283 struct regmap *map; 1284 struct rockchip_hdmi *hdmi = dev_get_priv(dev); 1285 1286 hdmi->dev = dev; 1287 1288 hdmi->id = of_alias_get_id(ofnode_to_np(dev->node), "hdmi"); 1289 if (hdmi->id < 0) 1290 hdmi->id = 0; 1291 1292 hdmi->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 1293 1294 if (hdmi->grf <= 0) { 1295 dev_err(dev, "%s: Get syscon grf failed (ret=%p)\n", 1296 __func__, hdmi->grf); 1297 return -ENXIO; 1298 } 1299 1300 map = syscon_regmap_lookup_by_phandle(dev, "rockchip,vo1_grf"); 1301 hdmi->vo1_grf = regmap_get_range(map, 0); 1302 1303 if (hdmi->vo1_grf <= 0) { 1304 dev_err(dev, "%s: Get syscon vo1 grf failed (ret=%p)\n", 1305 __func__, hdmi->vo1_grf); 1306 return -ENXIO; 1307 } 1308 1309 ret = gpio_request_by_name(dev, "enable-gpios", 0, 1310 &hdmi->enable_gpio, GPIOD_IS_OUT); 1311 if (ret) { 1312 dev_err(dev, "Cannot get enable GPIO: %d\n", ret); 1313 return ret; 1314 } 1315 1316 return 0; 1317 } 1318 1319 static const struct rockchip_connector rk3588_dw_hdmi_qp_data = { 1320 .funcs = &rockchip_dw_hdmi_qp_funcs, 1321 .data = &rk3588_hdmi_drv_data, 1322 }; 1323 1324 static const struct udevice_id rockchip_dw_hdmi_qp_ids[] = { 1325 { 1326 .compatible = "rockchip,rk3588-dw-hdmi", 1327 .data = (ulong)&rk3588_dw_hdmi_qp_data, 1328 }, {} 1329 }; 1330 1331 U_BOOT_DRIVER(rockchip_dw_hdmi_qp) = { 1332 .name = "rockchip_dw_hdmi_qp", 1333 .id = UCLASS_DISPLAY, 1334 .of_match = rockchip_dw_hdmi_qp_ids, 1335 .probe = rockchip_dw_hdmi_qp_probe, 1336 .priv_auto_alloc_size = sizeof(struct rockchip_hdmi), 1337 }; 1338