0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/irq.h>
0009 #include <linux/clk.h>
0010 #include <linux/delay.h>
0011 #include <linux/err.h>
0012 #include <linux/hdmi.h>
0013 #include <linux/mfd/syscon.h>
0014 #include <linux/module.h>
0015 #include <linux/mutex.h>
0016 #include <linux/of_device.h>
0017
0018 #include <drm/drm_atomic_helper.h>
0019 #include <drm/drm_edid.h>
0020 #include <drm/drm_of.h>
0021 #include <drm/drm_probe_helper.h>
0022 #include <drm/drm_simple_kms_helper.h>
0023
0024 #include "rockchip_drm_drv.h"
0025 #include "rockchip_drm_vop.h"
0026
0027 #include "inno_hdmi.h"
0028
0029 struct hdmi_data_info {
0030 int vic;
0031 bool sink_has_audio;
0032 unsigned int enc_in_format;
0033 unsigned int enc_out_format;
0034 unsigned int colorimetry;
0035 };
0036
0037 struct inno_hdmi_i2c {
0038 struct i2c_adapter adap;
0039
0040 u8 ddc_addr;
0041 u8 segment_addr;
0042
0043 struct mutex lock;
0044 struct completion cmp;
0045 };
0046
0047 struct inno_hdmi {
0048 struct device *dev;
0049 struct drm_device *drm_dev;
0050
0051 int irq;
0052 struct clk *pclk;
0053 void __iomem *regs;
0054
0055 struct drm_connector connector;
0056 struct rockchip_encoder encoder;
0057
0058 struct inno_hdmi_i2c *i2c;
0059 struct i2c_adapter *ddc;
0060
0061 unsigned int tmds_rate;
0062
0063 struct hdmi_data_info hdmi_data;
0064 struct drm_display_mode previous_mode;
0065 };
0066
0067 static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder)
0068 {
0069 struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
0070
0071 return container_of(rkencoder, struct inno_hdmi, encoder);
0072 }
0073
0074 static struct inno_hdmi *connector_to_inno_hdmi(struct drm_connector *connector)
0075 {
0076 return container_of(connector, struct inno_hdmi, connector);
0077 }
0078
0079 enum {
0080 CSC_ITU601_16_235_TO_RGB_0_255_8BIT,
0081 CSC_ITU601_0_255_TO_RGB_0_255_8BIT,
0082 CSC_ITU709_16_235_TO_RGB_0_255_8BIT,
0083 CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
0084 CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
0085 CSC_RGB_0_255_TO_RGB_16_235_8BIT,
0086 };
0087
0088 static const char coeff_csc[][24] = {
0089
0090
0091
0092
0093
0094
0095 {
0096 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
0097 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
0098 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02
0099 },
0100
0101
0102
0103
0104
0105
0106 {
0107 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
0108 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
0109 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3
0110 },
0111
0112
0113
0114
0115
0116
0117 {
0118 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
0119 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
0120 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21
0121 },
0122
0123
0124
0125
0126
0127
0128
0129 {
0130 0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
0131 0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
0132 0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
0133 },
0134
0135
0136
0137
0138
0139
0140 {
0141 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
0142 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
0143 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
0144 },
0145
0146
0147
0148
0149
0150
0151 {
0152 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
0153 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0154 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10
0155 },
0156 };
0157
0158 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
0159 {
0160 return readl_relaxed(hdmi->regs + (offset) * 0x04);
0161 }
0162
0163 static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
0164 {
0165 writel_relaxed(val, hdmi->regs + (offset) * 0x04);
0166 }
0167
0168 static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
0169 u32 msk, u32 val)
0170 {
0171 u8 temp = hdmi_readb(hdmi, offset) & ~msk;
0172
0173 temp |= val & msk;
0174 hdmi_writeb(hdmi, offset, temp);
0175 }
0176
0177 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
0178 {
0179 int ddc_bus_freq;
0180
0181 ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
0182
0183 hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
0184 hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
0185
0186
0187 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
0188 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
0189 }
0190
0191 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
0192 {
0193 if (enable)
0194 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
0195 else
0196 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
0197 }
0198
0199 static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
0200 {
0201 switch (mode) {
0202 case NORMAL:
0203 inno_hdmi_sys_power(hdmi, false);
0204
0205 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f);
0206 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb);
0207
0208 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
0209 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
0210 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
0211 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
0212 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
0213 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
0214
0215 inno_hdmi_sys_power(hdmi, true);
0216 break;
0217
0218 case LOWER_PWR:
0219 inno_hdmi_sys_power(hdmi, false);
0220 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
0221 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
0222 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
0223 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
0224
0225 break;
0226
0227 default:
0228 DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
0229 }
0230 }
0231
0232 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
0233 {
0234 u32 val;
0235 u32 msk;
0236
0237 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
0238 udelay(100);
0239
0240 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
0241 udelay(100);
0242
0243 msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
0244 val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
0245 hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
0246
0247 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
0248 }
0249
0250 static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc,
0251 union hdmi_infoframe *frame, u32 frame_index,
0252 u32 mask, u32 disable, u32 enable)
0253 {
0254 if (mask)
0255 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable);
0256
0257 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index);
0258
0259 if (setup_rc >= 0) {
0260 u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
0261 ssize_t rc, i;
0262
0263 rc = hdmi_infoframe_pack(frame, packed_frame,
0264 sizeof(packed_frame));
0265 if (rc < 0)
0266 return rc;
0267
0268 for (i = 0; i < rc; i++)
0269 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
0270 packed_frame[i]);
0271
0272 if (mask)
0273 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable);
0274 }
0275
0276 return setup_rc;
0277 }
0278
0279 static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
0280 struct drm_display_mode *mode)
0281 {
0282 union hdmi_infoframe frame;
0283 int rc;
0284
0285 rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
0286 &hdmi->connector,
0287 mode);
0288
0289 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,
0290 m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1));
0291 }
0292
0293 static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
0294 struct drm_display_mode *mode)
0295 {
0296 union hdmi_infoframe frame;
0297 int rc;
0298
0299 rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
0300 &hdmi->connector,
0301 mode);
0302
0303 if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
0304 frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
0305 else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422)
0306 frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
0307 else
0308 frame.avi.colorspace = HDMI_COLORSPACE_RGB;
0309
0310 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0);
0311 }
0312
0313 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
0314 {
0315 struct hdmi_data_info *data = &hdmi->hdmi_data;
0316 int c0_c2_change = 0;
0317 int csc_enable = 0;
0318 int csc_mode = 0;
0319 int auto_csc = 0;
0320 int value;
0321 int i;
0322
0323
0324 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
0325 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444));
0326
0327
0328 value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
0329 v_VIDEO_OUTPUT_COLOR(0) |
0330 v_VIDEO_INPUT_CSP(0);
0331 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
0332
0333 if (data->enc_in_format == data->enc_out_format) {
0334 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) ||
0335 (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) {
0336 value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
0337 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
0338
0339 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
0340 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
0341 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
0342 v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
0343 return 0;
0344 }
0345 }
0346
0347 if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) {
0348 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
0349 (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
0350 csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
0351 auto_csc = AUTO_CSC_DISABLE;
0352 c0_c2_change = C0_C2_CHANGE_DISABLE;
0353 csc_enable = v_CSC_ENABLE;
0354 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
0355 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
0356 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
0357 auto_csc = AUTO_CSC_ENABLE;
0358 c0_c2_change = C0_C2_CHANGE_DISABLE;
0359 csc_enable = v_CSC_DISABLE;
0360 }
0361 } else {
0362 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
0363 (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
0364 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
0365 auto_csc = AUTO_CSC_DISABLE;
0366 c0_c2_change = C0_C2_CHANGE_DISABLE;
0367 csc_enable = v_CSC_ENABLE;
0368 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
0369 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
0370 csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
0371 auto_csc = AUTO_CSC_ENABLE;
0372 c0_c2_change = C0_C2_CHANGE_DISABLE;
0373 csc_enable = v_CSC_DISABLE;
0374 }
0375 }
0376
0377 for (i = 0; i < 24; i++)
0378 hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
0379 coeff_csc[csc_mode][i]);
0380
0381 value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
0382 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
0383 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
0384 m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) |
0385 v_VIDEO_C0_C2_SWAP(c0_c2_change));
0386
0387 return 0;
0388 }
0389
0390 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
0391 struct drm_display_mode *mode)
0392 {
0393 int value;
0394
0395
0396 value = v_EXTERANL_VIDEO(1);
0397 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
0398 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
0399 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
0400 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
0401 value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
0402 v_INETLACE(1) : v_INETLACE(0);
0403 hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
0404
0405
0406 value = mode->htotal;
0407 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
0408 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
0409
0410 value = mode->htotal - mode->hdisplay;
0411 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
0412 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
0413
0414 value = mode->hsync_start - mode->hdisplay;
0415 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
0416 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
0417
0418 value = mode->hsync_end - mode->hsync_start;
0419 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
0420 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
0421
0422 value = mode->vtotal;
0423 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
0424 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
0425
0426 value = mode->vtotal - mode->vdisplay;
0427 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
0428
0429 value = mode->vsync_start - mode->vdisplay;
0430 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
0431
0432 value = mode->vsync_end - mode->vsync_start;
0433 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
0434
0435 hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
0436 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
0437 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
0438
0439 return 0;
0440 }
0441
0442 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
0443 struct drm_display_mode *mode)
0444 {
0445 struct drm_display_info *display = &hdmi->connector.display_info;
0446
0447 hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
0448
0449 hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
0450 hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
0451
0452 if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) ||
0453 (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) ||
0454 (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) ||
0455 (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18))
0456 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
0457 else
0458 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
0459
0460
0461 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
0462 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
0463
0464
0465 hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
0466 v_HDMI_DVI(display->is_hdmi));
0467
0468 inno_hdmi_config_video_timing(hdmi, mode);
0469
0470 inno_hdmi_config_video_csc(hdmi);
0471
0472 if (display->is_hdmi) {
0473 inno_hdmi_config_video_avi(hdmi, mode);
0474 inno_hdmi_config_video_vsi(hdmi, mode);
0475 }
0476
0477
0478
0479
0480
0481
0482
0483 hdmi->tmds_rate = mode->clock * 1000;
0484 inno_hdmi_i2c_init(hdmi);
0485
0486
0487 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
0488 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
0489
0490 return 0;
0491 }
0492
0493 static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
0494 struct drm_display_mode *mode,
0495 struct drm_display_mode *adj_mode)
0496 {
0497 struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
0498
0499 inno_hdmi_setup(hdmi, adj_mode);
0500
0501
0502 memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
0503 }
0504
0505 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
0506 {
0507 struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
0508
0509 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
0510 }
0511
0512 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
0513 {
0514 struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
0515
0516 inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
0517 }
0518
0519 static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
0520 const struct drm_display_mode *mode,
0521 struct drm_display_mode *adj_mode)
0522 {
0523 return true;
0524 }
0525
0526 static int
0527 inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
0528 struct drm_crtc_state *crtc_state,
0529 struct drm_connector_state *conn_state)
0530 {
0531 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
0532
0533 s->output_mode = ROCKCHIP_OUT_MODE_P888;
0534 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
0535
0536 return 0;
0537 }
0538
0539 static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
0540 .enable = inno_hdmi_encoder_enable,
0541 .disable = inno_hdmi_encoder_disable,
0542 .mode_fixup = inno_hdmi_encoder_mode_fixup,
0543 .mode_set = inno_hdmi_encoder_mode_set,
0544 .atomic_check = inno_hdmi_encoder_atomic_check,
0545 };
0546
0547 static enum drm_connector_status
0548 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
0549 {
0550 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
0551
0552 return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
0553 connector_status_connected : connector_status_disconnected;
0554 }
0555
0556 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
0557 {
0558 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
0559 struct edid *edid;
0560 int ret = 0;
0561
0562 if (!hdmi->ddc)
0563 return 0;
0564
0565 edid = drm_get_edid(connector, hdmi->ddc);
0566 if (edid) {
0567 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
0568 drm_connector_update_edid_property(connector, edid);
0569 ret = drm_add_edid_modes(connector, edid);
0570 kfree(edid);
0571 }
0572
0573 return ret;
0574 }
0575
0576 static enum drm_mode_status
0577 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
0578 struct drm_display_mode *mode)
0579 {
0580 return MODE_OK;
0581 }
0582
0583 static int
0584 inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
0585 uint32_t maxX, uint32_t maxY)
0586 {
0587 return drm_helper_probe_single_connector_modes(connector, 1920, 1080);
0588 }
0589
0590 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
0591 {
0592 drm_connector_unregister(connector);
0593 drm_connector_cleanup(connector);
0594 }
0595
0596 static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
0597 .fill_modes = inno_hdmi_probe_single_connector_modes,
0598 .detect = inno_hdmi_connector_detect,
0599 .destroy = inno_hdmi_connector_destroy,
0600 .reset = drm_atomic_helper_connector_reset,
0601 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0602 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0603 };
0604
0605 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
0606 .get_modes = inno_hdmi_connector_get_modes,
0607 .mode_valid = inno_hdmi_connector_mode_valid,
0608 };
0609
0610 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
0611 {
0612 struct drm_encoder *encoder = &hdmi->encoder.encoder;
0613 struct device *dev = hdmi->dev;
0614
0615 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
0616
0617
0618
0619
0620
0621
0622
0623 if (encoder->possible_crtcs == 0)
0624 return -EPROBE_DEFER;
0625
0626 drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
0627 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
0628
0629 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
0630
0631 drm_connector_helper_add(&hdmi->connector,
0632 &inno_hdmi_connector_helper_funcs);
0633 drm_connector_init_with_ddc(drm, &hdmi->connector,
0634 &inno_hdmi_connector_funcs,
0635 DRM_MODE_CONNECTOR_HDMIA,
0636 hdmi->ddc);
0637
0638 drm_connector_attach_encoder(&hdmi->connector, encoder);
0639
0640 return 0;
0641 }
0642
0643 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
0644 {
0645 struct inno_hdmi_i2c *i2c = hdmi->i2c;
0646 u8 stat;
0647
0648 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
0649 if (!(stat & m_INT_EDID_READY))
0650 return IRQ_NONE;
0651
0652
0653 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
0654
0655 complete(&i2c->cmp);
0656
0657 return IRQ_HANDLED;
0658 }
0659
0660 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
0661 {
0662 struct inno_hdmi *hdmi = dev_id;
0663 irqreturn_t ret = IRQ_NONE;
0664 u8 interrupt;
0665
0666 if (hdmi->i2c)
0667 ret = inno_hdmi_i2c_irq(hdmi);
0668
0669 interrupt = hdmi_readb(hdmi, HDMI_STATUS);
0670 if (interrupt & m_INT_HOTPLUG) {
0671 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
0672 ret = IRQ_WAKE_THREAD;
0673 }
0674
0675 return ret;
0676 }
0677
0678 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
0679 {
0680 struct inno_hdmi *hdmi = dev_id;
0681
0682 drm_helper_hpd_irq_event(hdmi->connector.dev);
0683
0684 return IRQ_HANDLED;
0685 }
0686
0687 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
0688 {
0689 int length = msgs->len;
0690 u8 *buf = msgs->buf;
0691 int ret;
0692
0693 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
0694 if (!ret)
0695 return -EAGAIN;
0696
0697 while (length--)
0698 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
0699
0700 return 0;
0701 }
0702
0703 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
0704 {
0705
0706
0707
0708
0709
0710 if ((msgs->len != 1) ||
0711 ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
0712 return -EINVAL;
0713
0714 reinit_completion(&hdmi->i2c->cmp);
0715
0716 if (msgs->addr == DDC_SEGMENT_ADDR)
0717 hdmi->i2c->segment_addr = msgs->buf[0];
0718 if (msgs->addr == DDC_ADDR)
0719 hdmi->i2c->ddc_addr = msgs->buf[0];
0720
0721
0722 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
0723
0724
0725 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
0726
0727
0728 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
0729
0730 return 0;
0731 }
0732
0733 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
0734 struct i2c_msg *msgs, int num)
0735 {
0736 struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
0737 struct inno_hdmi_i2c *i2c = hdmi->i2c;
0738 int i, ret = 0;
0739
0740 mutex_lock(&i2c->lock);
0741
0742
0743 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
0744 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
0745
0746 for (i = 0; i < num; i++) {
0747 DRM_DEV_DEBUG(hdmi->dev,
0748 "xfer: num: %d/%d, len: %d, flags: %#x\n",
0749 i + 1, num, msgs[i].len, msgs[i].flags);
0750
0751 if (msgs[i].flags & I2C_M_RD)
0752 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
0753 else
0754 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
0755
0756 if (ret < 0)
0757 break;
0758 }
0759
0760 if (!ret)
0761 ret = num;
0762
0763
0764 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
0765
0766 mutex_unlock(&i2c->lock);
0767
0768 return ret;
0769 }
0770
0771 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
0772 {
0773 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
0774 }
0775
0776 static const struct i2c_algorithm inno_hdmi_algorithm = {
0777 .master_xfer = inno_hdmi_i2c_xfer,
0778 .functionality = inno_hdmi_i2c_func,
0779 };
0780
0781 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
0782 {
0783 struct i2c_adapter *adap;
0784 struct inno_hdmi_i2c *i2c;
0785 int ret;
0786
0787 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
0788 if (!i2c)
0789 return ERR_PTR(-ENOMEM);
0790
0791 mutex_init(&i2c->lock);
0792 init_completion(&i2c->cmp);
0793
0794 adap = &i2c->adap;
0795 adap->class = I2C_CLASS_DDC;
0796 adap->owner = THIS_MODULE;
0797 adap->dev.parent = hdmi->dev;
0798 adap->dev.of_node = hdmi->dev->of_node;
0799 adap->algo = &inno_hdmi_algorithm;
0800 strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
0801 i2c_set_adapdata(adap, hdmi);
0802
0803 ret = i2c_add_adapter(adap);
0804 if (ret) {
0805 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
0806 devm_kfree(hdmi->dev, i2c);
0807 return ERR_PTR(ret);
0808 }
0809
0810 hdmi->i2c = i2c;
0811
0812 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
0813
0814 return adap;
0815 }
0816
0817 static int inno_hdmi_bind(struct device *dev, struct device *master,
0818 void *data)
0819 {
0820 struct platform_device *pdev = to_platform_device(dev);
0821 struct drm_device *drm = data;
0822 struct inno_hdmi *hdmi;
0823 int irq;
0824 int ret;
0825
0826 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
0827 if (!hdmi)
0828 return -ENOMEM;
0829
0830 hdmi->dev = dev;
0831 hdmi->drm_dev = drm;
0832
0833 hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
0834 if (IS_ERR(hdmi->regs))
0835 return PTR_ERR(hdmi->regs);
0836
0837 hdmi->pclk = devm_clk_get(hdmi->dev, "pclk");
0838 if (IS_ERR(hdmi->pclk)) {
0839 DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n");
0840 return PTR_ERR(hdmi->pclk);
0841 }
0842
0843 ret = clk_prepare_enable(hdmi->pclk);
0844 if (ret) {
0845 DRM_DEV_ERROR(hdmi->dev,
0846 "Cannot enable HDMI pclk clock: %d\n", ret);
0847 return ret;
0848 }
0849
0850 irq = platform_get_irq(pdev, 0);
0851 if (irq < 0) {
0852 ret = irq;
0853 goto err_disable_clk;
0854 }
0855
0856 inno_hdmi_reset(hdmi);
0857
0858 hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
0859 if (IS_ERR(hdmi->ddc)) {
0860 ret = PTR_ERR(hdmi->ddc);
0861 hdmi->ddc = NULL;
0862 goto err_disable_clk;
0863 }
0864
0865
0866
0867
0868
0869
0870
0871 hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
0872 inno_hdmi_i2c_init(hdmi);
0873
0874 ret = inno_hdmi_register(drm, hdmi);
0875 if (ret)
0876 goto err_put_adapter;
0877
0878 dev_set_drvdata(dev, hdmi);
0879
0880
0881 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
0882
0883 ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
0884 inno_hdmi_irq, IRQF_SHARED,
0885 dev_name(dev), hdmi);
0886 if (ret < 0)
0887 goto err_cleanup_hdmi;
0888
0889 return 0;
0890 err_cleanup_hdmi:
0891 hdmi->connector.funcs->destroy(&hdmi->connector);
0892 hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder);
0893 err_put_adapter:
0894 i2c_put_adapter(hdmi->ddc);
0895 err_disable_clk:
0896 clk_disable_unprepare(hdmi->pclk);
0897 return ret;
0898 }
0899
0900 static void inno_hdmi_unbind(struct device *dev, struct device *master,
0901 void *data)
0902 {
0903 struct inno_hdmi *hdmi = dev_get_drvdata(dev);
0904
0905 hdmi->connector.funcs->destroy(&hdmi->connector);
0906 hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder);
0907
0908 i2c_put_adapter(hdmi->ddc);
0909 clk_disable_unprepare(hdmi->pclk);
0910 }
0911
0912 static const struct component_ops inno_hdmi_ops = {
0913 .bind = inno_hdmi_bind,
0914 .unbind = inno_hdmi_unbind,
0915 };
0916
0917 static int inno_hdmi_probe(struct platform_device *pdev)
0918 {
0919 return component_add(&pdev->dev, &inno_hdmi_ops);
0920 }
0921
0922 static int inno_hdmi_remove(struct platform_device *pdev)
0923 {
0924 component_del(&pdev->dev, &inno_hdmi_ops);
0925
0926 return 0;
0927 }
0928
0929 static const struct of_device_id inno_hdmi_dt_ids[] = {
0930 { .compatible = "rockchip,rk3036-inno-hdmi",
0931 },
0932 {},
0933 };
0934 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
0935
0936 struct platform_driver inno_hdmi_driver = {
0937 .probe = inno_hdmi_probe,
0938 .remove = inno_hdmi_remove,
0939 .driver = {
0940 .name = "innohdmi-rockchip",
0941 .of_match_table = inno_hdmi_dt_ids,
0942 },
0943 };