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