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