1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) Copyright 2020 Rockchip Electronics Co., Ltd 4 */ 5 #include <common.h> 6 #include <clk.h> 7 #include <syscon.h> 8 #include <asm/io.h> 9 #include <asm/arch-rockchip/clock.h> 10 #include <dm/of_access.h> 11 #include <dm/device.h> 12 #include <dm/read.h> 13 #include <linux/hdmi.h> 14 #include <linux/media-bus-format.h> 15 16 #include "inno_hdmi.h" 17 #include "rockchip_connector.h" 18 #include "rockchip_crtc.h" 19 #include "rockchip_display.h" 20 21 struct inno_hdmi_i2c { 22 u8 slave_reg; 23 u8 ddc_addr; 24 u8 segment_addr; 25 bool is_regaddr; 26 bool is_segment; 27 28 unsigned int scl_high_ns; 29 unsigned int scl_low_ns; 30 }; 31 32 enum inno_hdmi_dev_type { 33 RK3036_HDMI, 34 RK3128_HDMI, 35 }; 36 37 enum { 38 CSC_ITU601_16_235_TO_RGB_0_255_8BIT, 39 CSC_ITU601_0_255_TO_RGB_0_255_8BIT, 40 CSC_ITU709_16_235_TO_RGB_0_255_8BIT, 41 CSC_RGB_0_255_TO_ITU601_16_235_8BIT, 42 CSC_RGB_0_255_TO_ITU709_16_235_8BIT, 43 CSC_RGB_0_255_TO_RGB_16_235_8BIT, 44 }; 45 46 static const char coeff_csc[][24] = { 47 /* 48 * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]): 49 * R = 1.164*Y + 1.596*V - 204 50 * G = 1.164*Y - 0.391*U - 0.813*V + 154 51 * B = 1.164*Y + 2.018*U - 258 52 */ 53 { 54 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc, 55 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a, 56 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02 57 }, 58 /* 59 * YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]): 60 * R = Y + 1.402*V - 248 61 * G = Y - 0.344*U - 0.714*V + 135 62 * B = Y + 1.772*U - 227 63 */ 64 { 65 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8, 66 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87, 67 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3 68 }, 69 /* 70 * YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]): 71 * R = 1.164*Y + 1.793*V - 248 72 * G = 1.164*Y - 0.213*U - 0.534*V + 77 73 * B = 1.164*Y + 2.115*U - 289 74 */ 75 { 76 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8, 77 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d, 78 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21 79 }, 80 81 /* 82 * RGB2YUV:601 SD mode: 83 * Cb = -0.291G - 0.148R + 0.439B + 128 84 * Y = 0.504G + 0.257R + 0.098B + 16 85 * Cr = -0.368G + 0.439R - 0.071B + 128 86 */ 87 { 88 0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80, 89 0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e, 90 0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80 91 }, 92 /* 93 * RGB2YUV:709 HD mode: 94 * Cb = - 0.338G - 0.101R + 0.439B + 128 95 * Y = 0.614G + 0.183R + 0.062B + 16 96 * Cr = - 0.399G + 0.439R - 0.040B + 128 97 */ 98 { 99 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80, 100 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10, 101 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80 102 }, 103 /* 104 * RGB[0:255]2RGB[16:235]: 105 * R' = R x (235-16)/255 + 16; 106 * G' = G x (235-16)/255 + 16; 107 * B' = B x (235-16)/255 + 16; 108 */ 109 { 110 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10, 111 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 112 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10 113 }, 114 }; 115 116 struct hdmi_data_info { 117 int vic; 118 bool sink_is_hdmi; 119 bool sink_has_audio; 120 unsigned int enc_in_format; 121 unsigned int enc_out_format; 122 unsigned int colorimetry; 123 }; 124 125 struct inno_hdmi_phy_config { 126 unsigned long mpixelclock; 127 u8 pre_emphasis; /* pre-emphasis value */ 128 u8 vlev_ctr; /* voltage level control */ 129 }; 130 131 struct inno_hdmi_plat_data { 132 enum inno_hdmi_dev_type dev_type; 133 struct inno_hdmi_phy_config *phy_config; 134 }; 135 136 struct inno_hdmi { 137 struct device *dev; 138 struct drm_device *drm_dev; 139 struct ddc_adapter adap; 140 struct hdmi_edid_data edid_data; 141 struct hdmi_data_info hdmi_data; 142 143 struct clk pclk; 144 int vic; 145 void *regs; 146 void *grf; 147 148 struct inno_hdmi_i2c *i2c; 149 150 unsigned int tmds_rate; 151 const struct inno_hdmi_plat_data *plat_data; 152 153 unsigned int sample_rate; 154 unsigned int audio_cts; 155 unsigned int audio_n; 156 bool audio_enable; 157 158 struct drm_display_mode previous_mode; 159 }; 160 161 static struct inno_hdmi_phy_config rk3036_hdmi_phy_config[] = { 162 /* pixelclk pre-emp vlev */ 163 { 74250000, 0x3f, 0xbb }, 164 { 165000000, 0x6f, 0xbb }, 165 { ~0UL, 0x00, 0x00 } 166 }; 167 168 static struct inno_hdmi_phy_config rk3128_hdmi_phy_config[] = { 169 /* pixelclk pre-emp vlev */ 170 { 74250000, 0x3f, 0xaa }, 171 { 165000000, 0x5f, 0xaa }, 172 { ~0UL, 0x00, 0x00 } 173 }; 174 175 static void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val) 176 { 177 writel(val, hdmi->regs + (offset << 2)); 178 } 179 180 static u32 hdmi_readb(struct inno_hdmi *hdmi, u16 offset) 181 { 182 return readl(hdmi->regs + (offset << 2)); 183 } 184 185 static void hdmi_modb(struct inno_hdmi *hdmi, u16 offset, u32 msk, u32 val) 186 { 187 u32 temp = hdmi_readb(hdmi, offset) & ~msk; 188 189 temp |= val & msk; 190 hdmi_writeb(hdmi, offset, temp); 191 } 192 193 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable) 194 { 195 if (enable) 196 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON); 197 else 198 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF); 199 } 200 201 static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode) 202 { 203 const struct inno_hdmi_phy_config *phy_config = 204 hdmi->plat_data->phy_config; 205 206 switch (mode) { 207 case NORMAL: 208 inno_hdmi_sys_power(hdmi, false); 209 for (; phy_config->mpixelclock != ~0UL; phy_config++) 210 if (hdmi->tmds_rate <= phy_config->mpixelclock) 211 break; 212 if (!phy_config->mpixelclock) 213 return; 214 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 215 phy_config->pre_emphasis); 216 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, phy_config->vlev_ctr); 217 218 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); 219 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14); 220 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10); 221 222 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f); 223 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00); 224 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01); 225 inno_hdmi_sys_power(hdmi, true); 226 227 break; 228 229 case LOWER_PWR: 230 inno_hdmi_sys_power(hdmi, false); 231 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00); 232 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00); 233 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00); 234 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15); 235 236 break; 237 238 default: 239 dev_err(hdmi->dev, "Unknown power mode %d\n", mode); 240 } 241 } 242 243 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi) 244 { 245 int ddc_bus_freq; 246 247 ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE; 248 hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF); 249 hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF); 250 251 /* Clear the EDID interrupt flag and mute the interrupt */ 252 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0); 253 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY); 254 } 255 256 static void inno_hdmi_reset(struct inno_hdmi *hdmi) 257 { 258 u32 val; 259 u32 msk; 260 261 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL); 262 udelay(100); 263 264 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG); 265 udelay(100); 266 267 msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL; 268 val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH; 269 270 hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val); 271 272 inno_hdmi_set_pwr_mode(hdmi, NORMAL); 273 } 274 275 static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc, 276 union hdmi_infoframe *frame, u32 frame_index, 277 u32 mask, u32 disable, u32 enable) 278 { 279 if (mask) 280 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable); 281 282 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index); 283 284 if (setup_rc >= 0) { 285 u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE]; 286 ssize_t rc, i; 287 288 rc = hdmi_infoframe_pack(frame, packed_frame, 289 sizeof(packed_frame)); 290 if (rc < 0) 291 return rc; 292 293 for (i = 0; i < rc; i++) 294 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, 295 packed_frame[i]); 296 297 if (mask) 298 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable); 299 } 300 301 return setup_rc; 302 } 303 304 static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi, 305 struct drm_display_mode *mode) 306 { 307 union hdmi_infoframe frame; 308 int rc; 309 310 rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi, 311 mode); 312 313 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI, 314 m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1)); 315 } 316 317 static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, 318 struct drm_display_mode *mode) 319 { 320 union hdmi_infoframe frame; 321 int rc; 322 323 rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false); 324 325 if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444) 326 frame.avi.colorspace = HDMI_COLORSPACE_YUV444; 327 else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422) 328 frame.avi.colorspace = HDMI_COLORSPACE_YUV422; 329 else 330 frame.avi.colorspace = HDMI_COLORSPACE_RGB; 331 332 if (frame.avi.colorspace != HDMI_COLORSPACE_RGB) 333 frame.avi.colorimetry = hdmi->hdmi_data.colorimetry; 334 335 frame.avi.scan_mode = HDMI_SCAN_MODE_NONE; 336 337 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0); 338 } 339 340 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) 341 { 342 struct hdmi_data_info *data = &hdmi->hdmi_data; 343 int c0_c2_change = 0; 344 int csc_enable = 0; 345 int csc_mode = 0; 346 int auto_csc = 0; 347 int value; 348 int i; 349 350 /* Input video mode is SDR RGB24bit, data enable signal from external */ 351 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL | 352 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444)); 353 354 /* Input color hardcode to RGB, and output color hardcode to RGB888 */ 355 value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) | 356 v_VIDEO_OUTPUT_COLOR(0) | 357 v_VIDEO_INPUT_CSP(0); 358 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value); 359 360 if (data->enc_in_format == data->enc_out_format) { 361 if (data->enc_in_format == HDMI_COLORSPACE_RGB || 362 data->enc_in_format >= HDMI_COLORSPACE_YUV444) { 363 value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1); 364 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value); 365 366 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, 367 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP, 368 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) | 369 v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE)); 370 return 0; 371 } 372 } 373 374 if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) { 375 if (data->enc_in_format == HDMI_COLORSPACE_RGB && 376 data->enc_out_format == HDMI_COLORSPACE_YUV444) { 377 csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT; 378 auto_csc = AUTO_CSC_DISABLE; 379 c0_c2_change = C0_C2_CHANGE_DISABLE; 380 csc_enable = v_CSC_ENABLE; 381 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) && 382 (data->enc_out_format == HDMI_COLORSPACE_RGB)) { 383 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT; 384 auto_csc = AUTO_CSC_ENABLE; 385 c0_c2_change = C0_C2_CHANGE_DISABLE; 386 csc_enable = v_CSC_DISABLE; 387 } 388 } else { 389 if (data->enc_in_format == HDMI_COLORSPACE_RGB && 390 data->enc_out_format == HDMI_COLORSPACE_YUV444) { 391 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT; 392 auto_csc = AUTO_CSC_DISABLE; 393 c0_c2_change = C0_C2_CHANGE_DISABLE; 394 csc_enable = v_CSC_ENABLE; 395 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) && 396 (data->enc_out_format == HDMI_COLORSPACE_RGB)) { 397 csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT; 398 auto_csc = AUTO_CSC_ENABLE; 399 c0_c2_change = C0_C2_CHANGE_DISABLE; 400 csc_enable = v_CSC_DISABLE; 401 } 402 } 403 404 for (i = 0; i < 24; i++) 405 hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i, 406 coeff_csc[csc_mode][i]); 407 408 value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1); 409 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value); 410 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC | 411 m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) | 412 v_VIDEO_C0_C2_SWAP(c0_c2_change)); 413 414 return 0; 415 } 416 417 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, 418 struct drm_display_mode *mode) 419 { 420 int value; 421 422 if (hdmi->plat_data->dev_type == RK3036_HDMI) { 423 value = BIT(20) | BIT(21); 424 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BIT(4) : 0; 425 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BIT(5) : 0; 426 writel(value, hdmi->grf + 0x148); 427 } 428 /* Set detail external video timing polarity and interlace mode */ 429 value = v_EXTERANL_VIDEO(1); 430 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? 431 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0); 432 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? 433 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0); 434 value |= mode->flags & DRM_MODE_FLAG_INTERLACE ? 435 v_INETLACE(1) : v_INETLACE(0); 436 hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value); 437 438 /* Set detail external video timing */ 439 value = mode->htotal; 440 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF); 441 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF); 442 443 value = mode->htotal - mode->hdisplay; 444 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF); 445 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF); 446 447 value = mode->htotal - mode->hsync_start; 448 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF); 449 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF); 450 451 value = mode->hsync_end - mode->hsync_start; 452 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF); 453 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF); 454 455 value = mode->vtotal; 456 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF); 457 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF); 458 459 value = mode->vtotal - mode->vdisplay; 460 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF); 461 462 value = mode->vtotal - mode->vsync_start; 463 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF); 464 465 value = mode->vsync_end - mode->vsync_start; 466 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF); 467 468 hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e); 469 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c); 470 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01); 471 472 return 0; 473 } 474 475 static int inno_hdmi_setup(struct inno_hdmi *hdmi, 476 struct drm_display_mode *mode) 477 { 478 hdmi->hdmi_data.vic = drm_match_cea_mode(mode); 479 480 hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB; 481 hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB; 482 483 if (hdmi->hdmi_data.vic == 6 || hdmi->hdmi_data.vic == 7 || 484 hdmi->hdmi_data.vic == 21 || hdmi->hdmi_data.vic == 22 || 485 hdmi->hdmi_data.vic == 2 || hdmi->hdmi_data.vic == 3 || 486 hdmi->hdmi_data.vic == 17 || hdmi->hdmi_data.vic == 18) 487 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601; 488 else 489 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; 490 491 /* Mute video and audio output */ 492 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, 493 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1)); 494 495 /* Set HDMI Mode */ 496 hdmi_writeb(hdmi, HDMI_HDCP_CTRL, 497 v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi)); 498 499 inno_hdmi_config_video_timing(hdmi, mode); 500 501 inno_hdmi_config_video_csc(hdmi); 502 503 if (hdmi->hdmi_data.sink_is_hdmi) { 504 inno_hdmi_config_video_avi(hdmi, mode); 505 inno_hdmi_config_video_vsi(hdmi, mode); 506 } 507 508 /* 509 * When IP controller have configured to an accurate video 510 * timing, then the TMDS clock source would be switched to 511 * DCLK_LCDC, so we need to init the TMDS rate to mode pixel 512 * clock rate, and reconfigure the DDC clock. 513 */ 514 hdmi->tmds_rate = mode->clock * 1000; 515 inno_hdmi_i2c_init(hdmi); 516 /* Unmute video and audio output */ 517 hdmi_modb(hdmi, HDMI_AV_MUTE, m_VIDEO_BLACK, v_VIDEO_MUTE(0)); 518 if (hdmi->audio_enable) 519 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE, v_AUDIO_MUTE(0)); 520 521 return 0; 522 } 523 524 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, 525 struct i2c_msg *msgs) 526 { 527 struct inno_hdmi_i2c *i2c = hdmi->i2c; 528 unsigned int length = msgs->len; 529 unsigned char *buf = msgs->buf; 530 int interrupt = 0, i = 20; 531 532 while (i--) { 533 mdelay(50); 534 interrupt = 0; 535 interrupt = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1); 536 537 if (interrupt & m_INT_EDID_READY) 538 break; 539 } 540 541 if (!interrupt) { 542 printf("[%s] i2c read reg[0x%02x] no interrupt\n", 543 __func__, i2c->slave_reg); 544 return -EAGAIN; 545 } 546 547 /* Clear HDMI EDID interrupt flag */ 548 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY); 549 550 while (length--) 551 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR); 552 553 return 0; 554 } 555 556 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, 557 struct i2c_msg *msgs) 558 { 559 unsigned int length = msgs->len; 560 561 hdmi->i2c->segment_addr = 0; 562 hdmi->i2c->ddc_addr = 0; 563 564 /* 565 * The DDC module only support read EDID message, so 566 * we assume that each word write to this i2c adapter 567 * should be the offset of EDID word address. 568 */ 569 if (length != 1 || 570 (msgs->addr != DDC_ADDR && msgs->addr != DDC_SEGMENT_ADDR)) { 571 printf("DDC word write to i2c adapter is not EDID address\n"); 572 return -EINVAL; 573 } 574 575 if (msgs->addr == DDC_SEGMENT_ADDR) 576 hdmi->i2c->segment_addr = msgs->buf[0]; 577 if (msgs->addr == DDC_ADDR) 578 hdmi->i2c->ddc_addr = msgs->buf[0]; 579 580 /* Set edid fifo first addr */ 581 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00); 582 583 /* Set edid word address 0x00/0x80 */ 584 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr); 585 586 /* Set edid segment pointer */ 587 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr); 588 589 return 0; 590 } 591 592 static int inno_hdmi_i2c_xfer(struct ddc_adapter *adap, 593 struct i2c_msg *msgs, int num) 594 { 595 struct inno_hdmi *hdmi = container_of(adap, struct inno_hdmi, adap); 596 int i, ret = 0; 597 598 /* Clear the EDID interrupt flag and unmute the interrupt */ 599 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY); 600 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY); 601 602 for (i = 0; i < num; i++) { 603 dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n", 604 i + 1, num, msgs[i].len, msgs[i].flags); 605 606 if (msgs[i].flags & I2C_M_RD) 607 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]); 608 else 609 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]); 610 611 if (ret < 0) 612 break; 613 } 614 615 if (!ret) 616 ret = num; 617 618 /* Mute HDMI EDID interrupt */ 619 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0); 620 621 return ret; 622 } 623 624 static int rockchip_inno_hdmi_init(struct rockchip_connector *conn, struct display_state *state) 625 { 626 struct connector_state *conn_state = &state->conn_state; 627 struct inno_hdmi *hdmi; 628 struct drm_display_mode *mode_buf; 629 ofnode hdmi_node = conn->dev->node; 630 int ret; 631 632 hdmi = calloc(1, sizeof(struct inno_hdmi)); 633 if (!hdmi) 634 return -ENOMEM; 635 636 mode_buf = calloc(1, MODE_LEN * sizeof(struct drm_display_mode)); 637 if (!mode_buf) 638 return -ENOMEM; 639 640 hdmi->regs = dev_read_addr_ptr(conn->dev); 641 642 hdmi->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 643 if (hdmi->grf <= 0) { 644 printf("%s: Get syscon grf failed (ret=%p)\n", 645 __func__, hdmi->grf); 646 return -ENXIO; 647 } 648 649 hdmi->i2c = malloc(sizeof(struct inno_hdmi_i2c)); 650 if (!hdmi->i2c) 651 return -ENOMEM; 652 653 hdmi->adap.ddc_xfer = inno_hdmi_i2c_xfer; 654 655 /* 656 * Read high and low time from device tree. If not available use 657 * the default timing scl clock rate is about 99.6KHz. 658 */ 659 hdmi->i2c->scl_high_ns = 660 ofnode_read_s32_default(hdmi_node, 661 "ddc-i2c-scl-high-time-ns", 4708); 662 hdmi->i2c->scl_low_ns = 663 ofnode_read_s32_default(hdmi_node, 664 "ddc-i2c-scl-low-time-ns", 4916); 665 666 conn_state->type = DRM_MODE_CONNECTOR_HDMIA; 667 conn_state->output_mode = ROCKCHIP_OUT_MODE_AAAA; 668 669 hdmi->plat_data = (struct inno_hdmi_plat_data *)dev_get_driver_data(conn->dev); 670 hdmi->edid_data.mode_buf = mode_buf; 671 hdmi->sample_rate = 48000; 672 673 conn->data = hdmi; 674 675 inno_hdmi_reset(hdmi); 676 ret = clk_get_by_name(conn->dev, "pclk", &hdmi->pclk); 677 if (ret < 0) { 678 dev_err(hdmi->dev, "failed to get pclk: %d\n", ret); 679 return ret; 680 } 681 hdmi->tmds_rate = clk_get_rate(&hdmi->pclk); 682 inno_hdmi_i2c_init(hdmi); 683 684 /* Unmute hotplug interrupt */ 685 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1)); 686 687 return 0; 688 } 689 690 static int rockchip_inno_hdmi_enable(struct rockchip_connector *conn, struct display_state *state) 691 { 692 struct connector_state *conn_state = &state->conn_state; 693 struct drm_display_mode *mode = &conn_state->mode; 694 struct inno_hdmi *hdmi = conn->data; 695 696 if (!hdmi) 697 return -EFAULT; 698 699 /* Store the display mode for plugin/DKMS poweron events */ 700 memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); 701 702 inno_hdmi_setup(hdmi, mode); 703 inno_hdmi_set_pwr_mode(hdmi, NORMAL); 704 705 return 0; 706 } 707 708 static void rockchip_inno_hdmi_deinit(struct rockchip_connector *conn, struct display_state *state) 709 { 710 struct inno_hdmi *hdmi = conn->data; 711 712 if (hdmi->i2c) 713 free(hdmi->i2c); 714 if (hdmi) 715 free(hdmi); 716 } 717 718 static int rockchip_inno_hdmi_prepare(struct rockchip_connector *conn, struct display_state *state) 719 { 720 return 0; 721 } 722 723 static int rockchip_inno_hdmi_disable(struct rockchip_connector *conn, struct display_state *state) 724 { 725 struct inno_hdmi *hdmi = conn->data; 726 727 inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR); 728 return 0; 729 } 730 731 static int rockchip_inno_hdmi_detect(struct rockchip_connector *conn, struct display_state *state) 732 { 733 struct inno_hdmi *hdmi = conn->data; 734 735 return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ? 736 connector_status_connected : connector_status_disconnected; 737 } 738 739 static int rockchip_inno_hdmi_get_timing(struct rockchip_connector *conn, 740 struct display_state *state) 741 { 742 int i, ret = 0; 743 struct connector_state *conn_state = &state->conn_state; 744 struct drm_display_mode *mode = &conn_state->mode; 745 struct inno_hdmi *hdmi = conn->data; 746 struct edid *edid = (struct edid *)conn_state->edid; 747 const u8 def_modes_vic[6] = {16, 4, 2, 17, 31, 19}; 748 749 if (!hdmi) 750 return -EFAULT; 751 752 conn_state->edid = drm_do_get_edid(&hdmi->adap); 753 if (conn_state->edid) { 754 hdmi->hdmi_data.sink_is_hdmi = 755 drm_detect_hdmi_monitor(edid); 756 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid); 757 ret = drm_add_edid_modes(&hdmi->edid_data, conn_state->edid); 758 } 759 if (ret <= 0) { 760 hdmi->hdmi_data.sink_is_hdmi = true; 761 hdmi->hdmi_data.sink_has_audio = true; 762 do_cea_modes(&hdmi->edid_data, def_modes_vic, 763 sizeof(def_modes_vic)); 764 hdmi->edid_data.preferred_mode = &hdmi->edid_data.mode_buf[0]; 765 printf("failed to get edid\n"); 766 } 767 drm_rk_filter_whitelist(&hdmi->edid_data); 768 769 if (!drm_mode_prune_invalid(&hdmi->edid_data)) { 770 printf("can't find valid hdmi mode\n"); 771 return -EINVAL; 772 } 773 774 for (i = 0; i < hdmi->edid_data.modes; i++) 775 hdmi->edid_data.mode_buf[i].vrefresh = 776 drm_mode_vrefresh(&hdmi->edid_data.mode_buf[i]); 777 778 drm_mode_sort(&hdmi->edid_data); 779 780 *mode = *hdmi->edid_data.preferred_mode; 781 hdmi->vic = drm_match_cea_mode(mode); 782 783 printf("mode:%dx%d\n", mode->hdisplay, mode->vdisplay); 784 785 conn_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24; 786 787 return 0; 788 } 789 790 const struct rockchip_connector_funcs rockchip_inno_hdmi_funcs = { 791 .init = rockchip_inno_hdmi_init, 792 .deinit = rockchip_inno_hdmi_deinit, 793 .prepare = rockchip_inno_hdmi_prepare, 794 .enable = rockchip_inno_hdmi_enable, 795 .disable = rockchip_inno_hdmi_disable, 796 .get_timing = rockchip_inno_hdmi_get_timing, 797 .detect = rockchip_inno_hdmi_detect, 798 }; 799 800 static int rockchip_inno_hdmi_probe(struct udevice *dev) 801 { 802 int id; 803 struct rockchip_connector *conn = dev_get_priv(dev); 804 805 id = of_alias_get_id(ofnode_to_np(dev->node), "hdmi"); 806 if (id < 0) 807 id = 0; 808 809 rockchip_connector_bind(conn, dev, id, &rockchip_inno_hdmi_funcs, NULL, 810 DRM_MODE_CONNECTOR_HDMIA); 811 812 return 0; 813 } 814 815 static int rockchip_inno_hdmi_bind(struct udevice *dev) 816 { 817 return 0; 818 } 819 820 static const struct inno_hdmi_plat_data rk3036_hdmi_drv_data = { 821 .dev_type = RK3036_HDMI, 822 .phy_config = rk3036_hdmi_phy_config, 823 }; 824 825 static const struct inno_hdmi_plat_data rk3128_hdmi_drv_data = { 826 .dev_type = RK3128_HDMI, 827 .phy_config = rk3128_hdmi_phy_config, 828 }; 829 830 static const struct udevice_id rockchip_inno_hdmi_ids[] = { 831 { 832 .compatible = "rockchip,rk3036-inno-hdmi", 833 .data = (ulong)&rk3036_hdmi_drv_data, 834 }, 835 { 836 .compatible = "rockchip,rk3128-inno-hdmi", 837 .data = (ulong)&rk3128_hdmi_drv_data, 838 }, {} 839 840 }; 841 842 U_BOOT_DRIVER(rockchip_inno_hdmi) = { 843 .name = "rockchip_inno_hdmi", 844 .id = UCLASS_DISPLAY, 845 .of_match = rockchip_inno_hdmi_ids, 846 .probe = rockchip_inno_hdmi_probe, 847 .bind = rockchip_inno_hdmi_bind, 848 .priv_auto_alloc_size = sizeof(struct rockchip_connector), 849 }; 850