root/drivers/gpu/drm/rockchip/inno_hdmi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hdmi_readb
  2. hdmi_writeb
  3. hdmi_modb
  4. inno_hdmi_i2c_init
  5. inno_hdmi_sys_power
  6. inno_hdmi_set_pwr_mode
  7. inno_hdmi_reset
  8. inno_hdmi_upload_frame
  9. inno_hdmi_config_video_vsi
  10. inno_hdmi_config_video_avi
  11. inno_hdmi_config_video_csc
  12. inno_hdmi_config_video_timing
  13. inno_hdmi_setup
  14. inno_hdmi_encoder_mode_set
  15. inno_hdmi_encoder_enable
  16. inno_hdmi_encoder_disable
  17. inno_hdmi_encoder_mode_fixup
  18. inno_hdmi_encoder_atomic_check
  19. inno_hdmi_connector_detect
  20. inno_hdmi_connector_get_modes
  21. inno_hdmi_connector_mode_valid
  22. inno_hdmi_probe_single_connector_modes
  23. inno_hdmi_connector_destroy
  24. inno_hdmi_register
  25. inno_hdmi_i2c_irq
  26. inno_hdmi_hardirq
  27. inno_hdmi_irq
  28. inno_hdmi_i2c_read
  29. inno_hdmi_i2c_write
  30. inno_hdmi_i2c_xfer
  31. inno_hdmi_i2c_func
  32. inno_hdmi_i2c_adapter
  33. inno_hdmi_bind
  34. inno_hdmi_unbind
  35. inno_hdmi_probe
  36. inno_hdmi_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
   4  *    Zheng Yang <zhengyang@rock-chips.com>
   5  *    Yakir Yang <ykk@rock-chips.com>
   6  */
   7 
   8 #include <linux/irq.h>
   9 #include <linux/clk.h>
  10 #include <linux/delay.h>
  11 #include <linux/err.h>
  12 #include <linux/hdmi.h>
  13 #include <linux/mfd/syscon.h>
  14 #include <linux/module.h>
  15 #include <linux/mutex.h>
  16 #include <linux/of_device.h>
  17 
  18 #include <drm/drm_atomic_helper.h>
  19 #include <drm/drm_edid.h>
  20 #include <drm/drm_of.h>
  21 #include <drm/drm_probe_helper.h>
  22 
  23 #include "rockchip_drm_drv.h"
  24 #include "rockchip_drm_vop.h"
  25 
  26 #include "inno_hdmi.h"
  27 
  28 #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x)
  29 
  30 struct hdmi_data_info {
  31         int vic;
  32         bool sink_is_hdmi;
  33         bool sink_has_audio;
  34         unsigned int enc_in_format;
  35         unsigned int enc_out_format;
  36         unsigned int colorimetry;
  37 };
  38 
  39 struct inno_hdmi_i2c {
  40         struct i2c_adapter adap;
  41 
  42         u8 ddc_addr;
  43         u8 segment_addr;
  44 
  45         struct mutex lock;
  46         struct completion cmp;
  47 };
  48 
  49 struct inno_hdmi {
  50         struct device *dev;
  51         struct drm_device *drm_dev;
  52 
  53         int irq;
  54         struct clk *pclk;
  55         void __iomem *regs;
  56 
  57         struct drm_connector    connector;
  58         struct drm_encoder      encoder;
  59 
  60         struct inno_hdmi_i2c *i2c;
  61         struct i2c_adapter *ddc;
  62 
  63         unsigned int tmds_rate;
  64 
  65         struct hdmi_data_info   hdmi_data;
  66         struct drm_display_mode previous_mode;
  67 };
  68 
  69 enum {
  70         CSC_ITU601_16_235_TO_RGB_0_255_8BIT,
  71         CSC_ITU601_0_255_TO_RGB_0_255_8BIT,
  72         CSC_ITU709_16_235_TO_RGB_0_255_8BIT,
  73         CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
  74         CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
  75         CSC_RGB_0_255_TO_RGB_16_235_8BIT,
  76 };
  77 
  78 static const char coeff_csc[][24] = {
  79         /*
  80          * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]):
  81          *   R = 1.164*Y + 1.596*V - 204
  82          *   G = 1.164*Y - 0.391*U - 0.813*V + 154
  83          *   B = 1.164*Y + 2.018*U - 258
  84          */
  85         {
  86                 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
  87                 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
  88                 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02
  89         },
  90         /*
  91          * YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
  92          *   R = Y + 1.402*V - 248
  93          *   G = Y - 0.344*U - 0.714*V + 135
  94          *   B = Y + 1.772*U - 227
  95          */
  96         {
  97                 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
  98                 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
  99                 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3
 100         },
 101         /*
 102          * YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
 103          *   R = 1.164*Y + 1.793*V - 248
 104          *   G = 1.164*Y - 0.213*U - 0.534*V + 77
 105          *   B = 1.164*Y + 2.115*U - 289
 106          */
 107         {
 108                 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
 109                 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
 110                 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21
 111         },
 112 
 113         /*
 114          * RGB2YUV:601 SD mode:
 115          *   Cb = -0.291G - 0.148R + 0.439B + 128
 116          *   Y  = 0.504G  + 0.257R + 0.098B + 16
 117          *   Cr = -0.368G + 0.439R - 0.071B + 128
 118          */
 119         {
 120                 0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
 121                 0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
 122                 0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
 123         },
 124         /*
 125          * RGB2YUV:709 HD mode:
 126          *   Cb = - 0.338G - 0.101R + 0.439B + 128
 127          *   Y  = 0.614G   + 0.183R + 0.062B + 16
 128          *   Cr = - 0.399G + 0.439R - 0.040B + 128
 129          */
 130         {
 131                 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
 132                 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
 133                 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
 134         },
 135         /*
 136          * RGB[0:255]2RGB[16:235]:
 137          *   R' = R x (235-16)/255 + 16;
 138          *   G' = G x (235-16)/255 + 16;
 139          *   B' = B x (235-16)/255 + 16;
 140          */
 141         {
 142                 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
 143                 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
 144                 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10
 145         },
 146 };
 147 
 148 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
 149 {
 150         return readl_relaxed(hdmi->regs + (offset) * 0x04);
 151 }
 152 
 153 static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
 154 {
 155         writel_relaxed(val, hdmi->regs + (offset) * 0x04);
 156 }
 157 
 158 static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
 159                              u32 msk, u32 val)
 160 {
 161         u8 temp = hdmi_readb(hdmi, offset) & ~msk;
 162 
 163         temp |= val & msk;
 164         hdmi_writeb(hdmi, offset, temp);
 165 }
 166 
 167 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
 168 {
 169         int ddc_bus_freq;
 170 
 171         ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
 172 
 173         hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
 174         hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
 175 
 176         /* Clear the EDID interrupt flag and mute the interrupt */
 177         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
 178         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
 179 }
 180 
 181 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
 182 {
 183         if (enable)
 184                 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
 185         else
 186                 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
 187 }
 188 
 189 static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
 190 {
 191         switch (mode) {
 192         case NORMAL:
 193                 inno_hdmi_sys_power(hdmi, false);
 194 
 195                 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f);
 196                 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb);
 197 
 198                 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
 199                 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
 200                 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
 201                 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
 202                 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
 203                 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
 204 
 205                 inno_hdmi_sys_power(hdmi, true);
 206                 break;
 207 
 208         case LOWER_PWR:
 209                 inno_hdmi_sys_power(hdmi, false);
 210                 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
 211                 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
 212                 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
 213                 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
 214 
 215                 break;
 216 
 217         default:
 218                 DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
 219         }
 220 }
 221 
 222 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
 223 {
 224         u32 val;
 225         u32 msk;
 226 
 227         hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
 228         udelay(100);
 229 
 230         hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
 231         udelay(100);
 232 
 233         msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
 234         val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
 235         hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
 236 
 237         inno_hdmi_set_pwr_mode(hdmi, NORMAL);
 238 }
 239 
 240 static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc,
 241                                   union hdmi_infoframe *frame, u32 frame_index,
 242                                   u32 mask, u32 disable, u32 enable)
 243 {
 244         if (mask)
 245                 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable);
 246 
 247         hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index);
 248 
 249         if (setup_rc >= 0) {
 250                 u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
 251                 ssize_t rc, i;
 252 
 253                 rc = hdmi_infoframe_pack(frame, packed_frame,
 254                                          sizeof(packed_frame));
 255                 if (rc < 0)
 256                         return rc;
 257 
 258                 for (i = 0; i < rc; i++)
 259                         hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
 260                                     packed_frame[i]);
 261 
 262                 if (mask)
 263                         hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable);
 264         }
 265 
 266         return setup_rc;
 267 }
 268 
 269 static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
 270                                       struct drm_display_mode *mode)
 271 {
 272         union hdmi_infoframe frame;
 273         int rc;
 274 
 275         rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
 276                                                          &hdmi->connector,
 277                                                          mode);
 278 
 279         return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,
 280                 m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1));
 281 }
 282 
 283 static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
 284                                       struct drm_display_mode *mode)
 285 {
 286         union hdmi_infoframe frame;
 287         int rc;
 288 
 289         rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
 290                                                       &hdmi->connector,
 291                                                       mode);
 292 
 293         if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
 294                 frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
 295         else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422)
 296                 frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
 297         else
 298                 frame.avi.colorspace = HDMI_COLORSPACE_RGB;
 299 
 300         return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0);
 301 }
 302 
 303 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
 304 {
 305         struct hdmi_data_info *data = &hdmi->hdmi_data;
 306         int c0_c2_change = 0;
 307         int csc_enable = 0;
 308         int csc_mode = 0;
 309         int auto_csc = 0;
 310         int value;
 311         int i;
 312 
 313         /* Input video mode is SDR RGB24bit, data enable signal from external */
 314         hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
 315                     v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444));
 316 
 317         /* Input color hardcode to RGB, and output color hardcode to RGB888 */
 318         value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
 319                 v_VIDEO_OUTPUT_COLOR(0) |
 320                 v_VIDEO_INPUT_CSP(0);
 321         hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
 322 
 323         if (data->enc_in_format == data->enc_out_format) {
 324                 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) ||
 325                     (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) {
 326                         value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
 327                         hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
 328 
 329                         hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
 330                                   m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
 331                                   v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
 332                                   v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
 333                         return 0;
 334                 }
 335         }
 336 
 337         if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) {
 338                 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
 339                     (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
 340                         csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
 341                         auto_csc = AUTO_CSC_DISABLE;
 342                         c0_c2_change = C0_C2_CHANGE_DISABLE;
 343                         csc_enable = v_CSC_ENABLE;
 344                 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
 345                            (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
 346                         csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
 347                         auto_csc = AUTO_CSC_ENABLE;
 348                         c0_c2_change = C0_C2_CHANGE_DISABLE;
 349                         csc_enable = v_CSC_DISABLE;
 350                 }
 351         } else {
 352                 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
 353                     (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
 354                         csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
 355                         auto_csc = AUTO_CSC_DISABLE;
 356                         c0_c2_change = C0_C2_CHANGE_DISABLE;
 357                         csc_enable = v_CSC_ENABLE;
 358                 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
 359                            (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
 360                         csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
 361                         auto_csc = AUTO_CSC_ENABLE;
 362                         c0_c2_change = C0_C2_CHANGE_DISABLE;
 363                         csc_enable = v_CSC_DISABLE;
 364                 }
 365         }
 366 
 367         for (i = 0; i < 24; i++)
 368                 hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
 369                             coeff_csc[csc_mode][i]);
 370 
 371         value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
 372         hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
 373         hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
 374                   m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) |
 375                   v_VIDEO_C0_C2_SWAP(c0_c2_change));
 376 
 377         return 0;
 378 }
 379 
 380 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
 381                                          struct drm_display_mode *mode)
 382 {
 383         int value;
 384 
 385         /* Set detail external video timing polarity and interlace mode */
 386         value = v_EXTERANL_VIDEO(1);
 387         value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
 388                  v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
 389         value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
 390                  v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
 391         value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
 392                  v_INETLACE(1) : v_INETLACE(0);
 393         hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
 394 
 395         /* Set detail external video timing */
 396         value = mode->htotal;
 397         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
 398         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
 399 
 400         value = mode->htotal - mode->hdisplay;
 401         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
 402         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
 403 
 404         value = mode->hsync_start - mode->hdisplay;
 405         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
 406         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
 407 
 408         value = mode->hsync_end - mode->hsync_start;
 409         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
 410         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
 411 
 412         value = mode->vtotal;
 413         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
 414         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
 415 
 416         value = mode->vtotal - mode->vdisplay;
 417         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
 418 
 419         value = mode->vsync_start - mode->vdisplay;
 420         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
 421 
 422         value = mode->vsync_end - mode->vsync_start;
 423         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
 424 
 425         hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
 426         hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
 427         hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
 428 
 429         return 0;
 430 }
 431 
 432 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
 433                            struct drm_display_mode *mode)
 434 {
 435         hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
 436 
 437         hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
 438         hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
 439 
 440         if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) ||
 441             (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) ||
 442             (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) ||
 443             (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18))
 444                 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
 445         else
 446                 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
 447 
 448         /* Mute video and audio output */
 449         hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
 450                   v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
 451 
 452         /* Set HDMI Mode */
 453         hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
 454                     v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi));
 455 
 456         inno_hdmi_config_video_timing(hdmi, mode);
 457 
 458         inno_hdmi_config_video_csc(hdmi);
 459 
 460         if (hdmi->hdmi_data.sink_is_hdmi) {
 461                 inno_hdmi_config_video_avi(hdmi, mode);
 462                 inno_hdmi_config_video_vsi(hdmi, mode);
 463         }
 464 
 465         /*
 466          * When IP controller have configured to an accurate video
 467          * timing, then the TMDS clock source would be switched to
 468          * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
 469          * clock rate, and reconfigure the DDC clock.
 470          */
 471         hdmi->tmds_rate = mode->clock * 1000;
 472         inno_hdmi_i2c_init(hdmi);
 473 
 474         /* Unmute video and audio output */
 475         hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
 476                   v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
 477 
 478         return 0;
 479 }
 480 
 481 static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
 482                                        struct drm_display_mode *mode,
 483                                        struct drm_display_mode *adj_mode)
 484 {
 485         struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
 486 
 487         inno_hdmi_setup(hdmi, adj_mode);
 488 
 489         /* Store the display mode for plugin/DPMS poweron events */
 490         memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
 491 }
 492 
 493 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
 494 {
 495         struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
 496 
 497         inno_hdmi_set_pwr_mode(hdmi, NORMAL);
 498 }
 499 
 500 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
 501 {
 502         struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
 503 
 504         inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
 505 }
 506 
 507 static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
 508                                          const struct drm_display_mode *mode,
 509                                          struct drm_display_mode *adj_mode)
 510 {
 511         return true;
 512 }
 513 
 514 static int
 515 inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
 516                                struct drm_crtc_state *crtc_state,
 517                                struct drm_connector_state *conn_state)
 518 {
 519         struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
 520 
 521         s->output_mode = ROCKCHIP_OUT_MODE_P888;
 522         s->output_type = DRM_MODE_CONNECTOR_HDMIA;
 523 
 524         return 0;
 525 }
 526 
 527 static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
 528         .enable     = inno_hdmi_encoder_enable,
 529         .disable    = inno_hdmi_encoder_disable,
 530         .mode_fixup = inno_hdmi_encoder_mode_fixup,
 531         .mode_set   = inno_hdmi_encoder_mode_set,
 532         .atomic_check = inno_hdmi_encoder_atomic_check,
 533 };
 534 
 535 static struct drm_encoder_funcs inno_hdmi_encoder_funcs = {
 536         .destroy = drm_encoder_cleanup,
 537 };
 538 
 539 static enum drm_connector_status
 540 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
 541 {
 542         struct inno_hdmi *hdmi = to_inno_hdmi(connector);
 543 
 544         return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
 545                 connector_status_connected : connector_status_disconnected;
 546 }
 547 
 548 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
 549 {
 550         struct inno_hdmi *hdmi = to_inno_hdmi(connector);
 551         struct edid *edid;
 552         int ret = 0;
 553 
 554         if (!hdmi->ddc)
 555                 return 0;
 556 
 557         edid = drm_get_edid(connector, hdmi->ddc);
 558         if (edid) {
 559                 hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
 560                 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
 561                 drm_connector_update_edid_property(connector, edid);
 562                 ret = drm_add_edid_modes(connector, edid);
 563                 kfree(edid);
 564         }
 565 
 566         return ret;
 567 }
 568 
 569 static enum drm_mode_status
 570 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
 571                                struct drm_display_mode *mode)
 572 {
 573         return MODE_OK;
 574 }
 575 
 576 static int
 577 inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
 578                                        uint32_t maxX, uint32_t maxY)
 579 {
 580         return drm_helper_probe_single_connector_modes(connector, 1920, 1080);
 581 }
 582 
 583 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
 584 {
 585         drm_connector_unregister(connector);
 586         drm_connector_cleanup(connector);
 587 }
 588 
 589 static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
 590         .fill_modes = inno_hdmi_probe_single_connector_modes,
 591         .detect = inno_hdmi_connector_detect,
 592         .destroy = inno_hdmi_connector_destroy,
 593         .reset = drm_atomic_helper_connector_reset,
 594         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 595         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 596 };
 597 
 598 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
 599         .get_modes = inno_hdmi_connector_get_modes,
 600         .mode_valid = inno_hdmi_connector_mode_valid,
 601 };
 602 
 603 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
 604 {
 605         struct drm_encoder *encoder = &hdmi->encoder;
 606         struct device *dev = hdmi->dev;
 607 
 608         encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
 609 
 610         /*
 611          * If we failed to find the CRTC(s) which this encoder is
 612          * supposed to be connected to, it's because the CRTC has
 613          * not been registered yet.  Defer probing, and hope that
 614          * the required CRTC is added later.
 615          */
 616         if (encoder->possible_crtcs == 0)
 617                 return -EPROBE_DEFER;
 618 
 619         drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
 620         drm_encoder_init(drm, encoder, &inno_hdmi_encoder_funcs,
 621                          DRM_MODE_ENCODER_TMDS, NULL);
 622 
 623         hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 624 
 625         drm_connector_helper_add(&hdmi->connector,
 626                                  &inno_hdmi_connector_helper_funcs);
 627         drm_connector_init(drm, &hdmi->connector, &inno_hdmi_connector_funcs,
 628                            DRM_MODE_CONNECTOR_HDMIA);
 629 
 630         drm_connector_attach_encoder(&hdmi->connector, encoder);
 631 
 632         return 0;
 633 }
 634 
 635 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
 636 {
 637         struct inno_hdmi_i2c *i2c = hdmi->i2c;
 638         u8 stat;
 639 
 640         stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
 641         if (!(stat & m_INT_EDID_READY))
 642                 return IRQ_NONE;
 643 
 644         /* Clear HDMI EDID interrupt flag */
 645         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
 646 
 647         complete(&i2c->cmp);
 648 
 649         return IRQ_HANDLED;
 650 }
 651 
 652 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
 653 {
 654         struct inno_hdmi *hdmi = dev_id;
 655         irqreturn_t ret = IRQ_NONE;
 656         u8 interrupt;
 657 
 658         if (hdmi->i2c)
 659                 ret = inno_hdmi_i2c_irq(hdmi);
 660 
 661         interrupt = hdmi_readb(hdmi, HDMI_STATUS);
 662         if (interrupt & m_INT_HOTPLUG) {
 663                 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
 664                 ret = IRQ_WAKE_THREAD;
 665         }
 666 
 667         return ret;
 668 }
 669 
 670 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
 671 {
 672         struct inno_hdmi *hdmi = dev_id;
 673 
 674         drm_helper_hpd_irq_event(hdmi->connector.dev);
 675 
 676         return IRQ_HANDLED;
 677 }
 678 
 679 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
 680 {
 681         int length = msgs->len;
 682         u8 *buf = msgs->buf;
 683         int ret;
 684 
 685         ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
 686         if (!ret)
 687                 return -EAGAIN;
 688 
 689         while (length--)
 690                 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
 691 
 692         return 0;
 693 }
 694 
 695 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
 696 {
 697         /*
 698          * The DDC module only support read EDID message, so
 699          * we assume that each word write to this i2c adapter
 700          * should be the offset of EDID word address.
 701          */
 702         if ((msgs->len != 1) ||
 703             ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
 704                 return -EINVAL;
 705 
 706         reinit_completion(&hdmi->i2c->cmp);
 707 
 708         if (msgs->addr == DDC_SEGMENT_ADDR)
 709                 hdmi->i2c->segment_addr = msgs->buf[0];
 710         if (msgs->addr == DDC_ADDR)
 711                 hdmi->i2c->ddc_addr = msgs->buf[0];
 712 
 713         /* Set edid fifo first addr */
 714         hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
 715 
 716         /* Set edid word address 0x00/0x80 */
 717         hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
 718 
 719         /* Set edid segment pointer */
 720         hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
 721 
 722         return 0;
 723 }
 724 
 725 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
 726                               struct i2c_msg *msgs, int num)
 727 {
 728         struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
 729         struct inno_hdmi_i2c *i2c = hdmi->i2c;
 730         int i, ret = 0;
 731 
 732         mutex_lock(&i2c->lock);
 733 
 734         /* Clear the EDID interrupt flag and unmute the interrupt */
 735         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
 736         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
 737 
 738         for (i = 0; i < num; i++) {
 739                 DRM_DEV_DEBUG(hdmi->dev,
 740                               "xfer: num: %d/%d, len: %d, flags: %#x\n",
 741                               i + 1, num, msgs[i].len, msgs[i].flags);
 742 
 743                 if (msgs[i].flags & I2C_M_RD)
 744                         ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
 745                 else
 746                         ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
 747 
 748                 if (ret < 0)
 749                         break;
 750         }
 751 
 752         if (!ret)
 753                 ret = num;
 754 
 755         /* Mute HDMI EDID interrupt */
 756         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
 757 
 758         mutex_unlock(&i2c->lock);
 759 
 760         return ret;
 761 }
 762 
 763 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
 764 {
 765         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 766 }
 767 
 768 static const struct i2c_algorithm inno_hdmi_algorithm = {
 769         .master_xfer    = inno_hdmi_i2c_xfer,
 770         .functionality  = inno_hdmi_i2c_func,
 771 };
 772 
 773 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
 774 {
 775         struct i2c_adapter *adap;
 776         struct inno_hdmi_i2c *i2c;
 777         int ret;
 778 
 779         i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
 780         if (!i2c)
 781                 return ERR_PTR(-ENOMEM);
 782 
 783         mutex_init(&i2c->lock);
 784         init_completion(&i2c->cmp);
 785 
 786         adap = &i2c->adap;
 787         adap->class = I2C_CLASS_DDC;
 788         adap->owner = THIS_MODULE;
 789         adap->dev.parent = hdmi->dev;
 790         adap->dev.of_node = hdmi->dev->of_node;
 791         adap->algo = &inno_hdmi_algorithm;
 792         strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
 793         i2c_set_adapdata(adap, hdmi);
 794 
 795         ret = i2c_add_adapter(adap);
 796         if (ret) {
 797                 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
 798                 devm_kfree(hdmi->dev, i2c);
 799                 return ERR_PTR(ret);
 800         }
 801 
 802         hdmi->i2c = i2c;
 803 
 804         DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
 805 
 806         return adap;
 807 }
 808 
 809 static int inno_hdmi_bind(struct device *dev, struct device *master,
 810                                  void *data)
 811 {
 812         struct platform_device *pdev = to_platform_device(dev);
 813         struct drm_device *drm = data;
 814         struct inno_hdmi *hdmi;
 815         struct resource *iores;
 816         int irq;
 817         int ret;
 818 
 819         hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
 820         if (!hdmi)
 821                 return -ENOMEM;
 822 
 823         hdmi->dev = dev;
 824         hdmi->drm_dev = drm;
 825 
 826         iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 827         hdmi->regs = devm_ioremap_resource(dev, iores);
 828         if (IS_ERR(hdmi->regs))
 829                 return PTR_ERR(hdmi->regs);
 830 
 831         hdmi->pclk = devm_clk_get(hdmi->dev, "pclk");
 832         if (IS_ERR(hdmi->pclk)) {
 833                 DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n");
 834                 return PTR_ERR(hdmi->pclk);
 835         }
 836 
 837         ret = clk_prepare_enable(hdmi->pclk);
 838         if (ret) {
 839                 DRM_DEV_ERROR(hdmi->dev,
 840                               "Cannot enable HDMI pclk clock: %d\n", ret);
 841                 return ret;
 842         }
 843 
 844         irq = platform_get_irq(pdev, 0);
 845         if (irq < 0) {
 846                 ret = irq;
 847                 goto err_disable_clk;
 848         }
 849 
 850         inno_hdmi_reset(hdmi);
 851 
 852         hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
 853         if (IS_ERR(hdmi->ddc)) {
 854                 ret = PTR_ERR(hdmi->ddc);
 855                 hdmi->ddc = NULL;
 856                 goto err_disable_clk;
 857         }
 858 
 859         /*
 860          * When IP controller haven't configured to an accurate video
 861          * timing, then the TMDS clock source would be switched to
 862          * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
 863          * and reconfigure the DDC clock.
 864          */
 865         hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
 866         inno_hdmi_i2c_init(hdmi);
 867 
 868         ret = inno_hdmi_register(drm, hdmi);
 869         if (ret)
 870                 goto err_put_adapter;
 871 
 872         dev_set_drvdata(dev, hdmi);
 873 
 874         /* Unmute hotplug interrupt */
 875         hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
 876 
 877         ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
 878                                         inno_hdmi_irq, IRQF_SHARED,
 879                                         dev_name(dev), hdmi);
 880         if (ret < 0)
 881                 goto err_cleanup_hdmi;
 882 
 883         return 0;
 884 err_cleanup_hdmi:
 885         hdmi->connector.funcs->destroy(&hdmi->connector);
 886         hdmi->encoder.funcs->destroy(&hdmi->encoder);
 887 err_put_adapter:
 888         i2c_put_adapter(hdmi->ddc);
 889 err_disable_clk:
 890         clk_disable_unprepare(hdmi->pclk);
 891         return ret;
 892 }
 893 
 894 static void inno_hdmi_unbind(struct device *dev, struct device *master,
 895                              void *data)
 896 {
 897         struct inno_hdmi *hdmi = dev_get_drvdata(dev);
 898 
 899         hdmi->connector.funcs->destroy(&hdmi->connector);
 900         hdmi->encoder.funcs->destroy(&hdmi->encoder);
 901 
 902         i2c_put_adapter(hdmi->ddc);
 903         clk_disable_unprepare(hdmi->pclk);
 904 }
 905 
 906 static const struct component_ops inno_hdmi_ops = {
 907         .bind   = inno_hdmi_bind,
 908         .unbind = inno_hdmi_unbind,
 909 };
 910 
 911 static int inno_hdmi_probe(struct platform_device *pdev)
 912 {
 913         return component_add(&pdev->dev, &inno_hdmi_ops);
 914 }
 915 
 916 static int inno_hdmi_remove(struct platform_device *pdev)
 917 {
 918         component_del(&pdev->dev, &inno_hdmi_ops);
 919 
 920         return 0;
 921 }
 922 
 923 static const struct of_device_id inno_hdmi_dt_ids[] = {
 924         { .compatible = "rockchip,rk3036-inno-hdmi",
 925         },
 926         {},
 927 };
 928 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
 929 
 930 struct platform_driver inno_hdmi_driver = {
 931         .probe  = inno_hdmi_probe,
 932         .remove = inno_hdmi_remove,
 933         .driver = {
 934                 .name = "innohdmi-rockchip",
 935                 .of_match_table = inno_hdmi_dt_ids,
 936         },
 937 };

/* [<][>][^][v][top][bottom][index][help] */