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