0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <drm/bridge/mhl.h>
0016 #include <drm/drm_bridge.h>
0017 #include <drm/drm_crtc.h>
0018 #include <drm/drm_edid.h>
0019
0020 #include <linux/delay.h>
0021 #include <linux/err.h>
0022 #include <linux/gpio/consumer.h>
0023 #include <linux/i2c.h>
0024 #include <linux/interrupt.h>
0025 #include <linux/irq.h>
0026 #include <linux/kernel.h>
0027 #include <linux/module.h>
0028 #include <linux/mutex.h>
0029 #include <linux/regulator/consumer.h>
0030 #include <linux/slab.h>
0031
0032 #define CBUS_DEVCAP_OFFSET 0x80
0033
0034 #define SII9234_MHL_VERSION 0x11
0035 #define SII9234_SCRATCHPAD_SIZE 0x10
0036 #define SII9234_INT_STAT_SIZE 0x33
0037
0038 #define BIT_TMDS_CCTRL_TMDS_OE BIT(4)
0039 #define MHL_HPD_OUT_OVR_EN BIT(4)
0040 #define MHL_HPD_OUT_OVR_VAL BIT(5)
0041 #define MHL_INIT_TIMEOUT 0x0C
0042
0043
0044 #define MHL_TX_SRST 0x05
0045 #define MHL_TX_SYSSTAT_REG 0x09
0046 #define MHL_TX_INTR1_REG 0x71
0047 #define MHL_TX_INTR4_REG 0x74
0048 #define MHL_TX_INTR1_ENABLE_REG 0x75
0049 #define MHL_TX_INTR4_ENABLE_REG 0x78
0050 #define MHL_TX_INT_CTRL_REG 0x79
0051 #define MHL_TX_TMDS_CCTRL 0x80
0052 #define MHL_TX_DISC_CTRL1_REG 0x90
0053 #define MHL_TX_DISC_CTRL2_REG 0x91
0054 #define MHL_TX_DISC_CTRL3_REG 0x92
0055 #define MHL_TX_DISC_CTRL4_REG 0x93
0056 #define MHL_TX_DISC_CTRL5_REG 0x94
0057 #define MHL_TX_DISC_CTRL6_REG 0x95
0058 #define MHL_TX_DISC_CTRL7_REG 0x96
0059 #define MHL_TX_DISC_CTRL8_REG 0x97
0060 #define MHL_TX_STAT2_REG 0x99
0061 #define MHL_TX_MHLTX_CTL1_REG 0xA0
0062 #define MHL_TX_MHLTX_CTL2_REG 0xA1
0063 #define MHL_TX_MHLTX_CTL4_REG 0xA3
0064 #define MHL_TX_MHLTX_CTL6_REG 0xA5
0065 #define MHL_TX_MHLTX_CTL7_REG 0xA6
0066
0067 #define RSEN_STATUS BIT(2)
0068 #define HPD_CHANGE_INT BIT(6)
0069 #define RSEN_CHANGE_INT BIT(5)
0070 #define RGND_READY_INT BIT(6)
0071 #define VBUS_LOW_INT BIT(5)
0072 #define CBUS_LKOUT_INT BIT(4)
0073 #define MHL_DISC_FAIL_INT BIT(3)
0074 #define MHL_EST_INT BIT(2)
0075 #define HPD_CHANGE_INT_MASK BIT(6)
0076 #define RSEN_CHANGE_INT_MASK BIT(5)
0077
0078 #define RGND_READY_MASK BIT(6)
0079 #define CBUS_LKOUT_MASK BIT(4)
0080 #define MHL_DISC_FAIL_MASK BIT(3)
0081 #define MHL_EST_MASK BIT(2)
0082
0083 #define SKIP_GND BIT(6)
0084
0085 #define ATT_THRESH_SHIFT 0x04
0086 #define ATT_THRESH_MASK (0x03 << ATT_THRESH_SHIFT)
0087 #define USB_D_OEN BIT(3)
0088 #define DEGLITCH_TIME_MASK 0x07
0089 #define DEGLITCH_TIME_2MS 0
0090 #define DEGLITCH_TIME_4MS 1
0091 #define DEGLITCH_TIME_8MS 2
0092 #define DEGLITCH_TIME_16MS 3
0093 #define DEGLITCH_TIME_40MS 4
0094 #define DEGLITCH_TIME_50MS 5
0095 #define DEGLITCH_TIME_60MS 6
0096 #define DEGLITCH_TIME_128MS 7
0097
0098 #define USB_D_OVR BIT(7)
0099 #define USB_ID_OVR BIT(6)
0100 #define DVRFLT_SEL BIT(5)
0101 #define BLOCK_RGND_INT BIT(4)
0102 #define SKIP_DEG BIT(3)
0103 #define CI2CA_POL BIT(2)
0104 #define CI2CA_WKUP BIT(1)
0105 #define SINGLE_ATT BIT(0)
0106
0107 #define USB_D_ODN BIT(5)
0108 #define VBUS_CHECK BIT(2)
0109 #define RGND_INTP_MASK 0x03
0110 #define RGND_INTP_OPEN 0
0111 #define RGND_INTP_2K 1
0112 #define RGND_INTP_1K 2
0113 #define RGND_INTP_SHORT 3
0114
0115
0116 #define HDMI_RX_TMDS0_CCTRL1_REG 0x10
0117 #define HDMI_RX_TMDS_CLK_EN_REG 0x11
0118 #define HDMI_RX_TMDS_CH_EN_REG 0x12
0119 #define HDMI_RX_PLL_CALREFSEL_REG 0x17
0120 #define HDMI_RX_PLL_VCOCAL_REG 0x1A
0121 #define HDMI_RX_EQ_DATA0_REG 0x22
0122 #define HDMI_RX_EQ_DATA1_REG 0x23
0123 #define HDMI_RX_EQ_DATA2_REG 0x24
0124 #define HDMI_RX_EQ_DATA3_REG 0x25
0125 #define HDMI_RX_EQ_DATA4_REG 0x26
0126 #define HDMI_RX_TMDS_ZONE_CTRL_REG 0x4C
0127 #define HDMI_RX_TMDS_MODE_CTRL_REG 0x4D
0128
0129
0130 #define CBUS_INT_STATUS_1_REG 0x08
0131 #define CBUS_INTR1_ENABLE_REG 0x09
0132 #define CBUS_MSC_REQ_ABORT_REASON_REG 0x0D
0133 #define CBUS_INT_STATUS_2_REG 0x1E
0134 #define CBUS_INTR2_ENABLE_REG 0x1F
0135 #define CBUS_LINK_CONTROL_2_REG 0x31
0136 #define CBUS_MHL_STATUS_REG_0 0xB0
0137 #define CBUS_MHL_STATUS_REG_1 0xB1
0138
0139 #define BIT_CBUS_RESET BIT(3)
0140 #define SET_HPD_DOWNSTREAM BIT(6)
0141
0142
0143 #define TPI_DPD_REG 0x3D
0144
0145
0146 #define T_SRC_VBUS_CBUS_TO_STABLE 200
0147 #define T_SRC_CBUS_FLOAT 100
0148 #define T_SRC_CBUS_DEGLITCH 2
0149 #define T_SRC_RXSENSE_DEGLITCH 110
0150
0151 #define MHL1_MAX_CLK 75000
0152
0153 #define I2C_TPI_ADDR 0x3D
0154 #define I2C_HDMI_ADDR 0x49
0155 #define I2C_CBUS_ADDR 0x64
0156
0157 enum sii9234_state {
0158 ST_OFF,
0159 ST_D3,
0160 ST_RGND_INIT,
0161 ST_RGND_1K,
0162 ST_RSEN_HIGH,
0163 ST_MHL_ESTABLISHED,
0164 ST_FAILURE_DISCOVERY,
0165 ST_FAILURE,
0166 };
0167
0168 struct sii9234 {
0169 struct i2c_client *client[4];
0170 struct drm_bridge bridge;
0171 struct device *dev;
0172 struct gpio_desc *gpio_reset;
0173 int i2c_error;
0174 struct regulator_bulk_data supplies[4];
0175
0176 struct mutex lock;
0177 enum sii9234_state state;
0178 };
0179
0180 enum sii9234_client_id {
0181 I2C_MHL,
0182 I2C_TPI,
0183 I2C_HDMI,
0184 I2C_CBUS,
0185 };
0186
0187 static const char * const sii9234_client_name[] = {
0188 [I2C_MHL] = "MHL",
0189 [I2C_TPI] = "TPI",
0190 [I2C_HDMI] = "HDMI",
0191 [I2C_CBUS] = "CBUS",
0192 };
0193
0194 static int sii9234_writeb(struct sii9234 *ctx, int id, int offset,
0195 int value)
0196 {
0197 int ret;
0198 struct i2c_client *client = ctx->client[id];
0199
0200 if (ctx->i2c_error)
0201 return ctx->i2c_error;
0202
0203 ret = i2c_smbus_write_byte_data(client, offset, value);
0204 if (ret < 0)
0205 dev_err(ctx->dev, "writeb: %4s[0x%02x] <- 0x%02x\n",
0206 sii9234_client_name[id], offset, value);
0207 ctx->i2c_error = ret;
0208
0209 return ret;
0210 }
0211
0212 static int sii9234_writebm(struct sii9234 *ctx, int id, int offset,
0213 int value, int mask)
0214 {
0215 int ret;
0216 struct i2c_client *client = ctx->client[id];
0217
0218 if (ctx->i2c_error)
0219 return ctx->i2c_error;
0220
0221 ret = i2c_smbus_write_byte(client, offset);
0222 if (ret < 0) {
0223 dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n",
0224 sii9234_client_name[id], offset, value);
0225 ctx->i2c_error = ret;
0226 return ret;
0227 }
0228
0229 ret = i2c_smbus_read_byte(client);
0230 if (ret < 0) {
0231 dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n",
0232 sii9234_client_name[id], offset, value);
0233 ctx->i2c_error = ret;
0234 return ret;
0235 }
0236
0237 value = (value & mask) | (ret & ~mask);
0238
0239 ret = i2c_smbus_write_byte_data(client, offset, value);
0240 if (ret < 0) {
0241 dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n",
0242 sii9234_client_name[id], offset, value);
0243 ctx->i2c_error = ret;
0244 }
0245
0246 return ret;
0247 }
0248
0249 static int sii9234_readb(struct sii9234 *ctx, int id, int offset)
0250 {
0251 int ret;
0252 struct i2c_client *client = ctx->client[id];
0253
0254 if (ctx->i2c_error)
0255 return ctx->i2c_error;
0256
0257 ret = i2c_smbus_write_byte(client, offset);
0258 if (ret < 0) {
0259 dev_err(ctx->dev, "readb: %4s[0x%02x]\n",
0260 sii9234_client_name[id], offset);
0261 ctx->i2c_error = ret;
0262 return ret;
0263 }
0264
0265 ret = i2c_smbus_read_byte(client);
0266 if (ret < 0) {
0267 dev_err(ctx->dev, "readb: %4s[0x%02x]\n",
0268 sii9234_client_name[id], offset);
0269 ctx->i2c_error = ret;
0270 }
0271
0272 return ret;
0273 }
0274
0275 static int sii9234_clear_error(struct sii9234 *ctx)
0276 {
0277 int ret = ctx->i2c_error;
0278
0279 ctx->i2c_error = 0;
0280
0281 return ret;
0282 }
0283
0284 #define mhl_tx_writeb(sii9234, offset, value) \
0285 sii9234_writeb(sii9234, I2C_MHL, offset, value)
0286 #define mhl_tx_writebm(sii9234, offset, value, mask) \
0287 sii9234_writebm(sii9234, I2C_MHL, offset, value, mask)
0288 #define mhl_tx_readb(sii9234, offset) \
0289 sii9234_readb(sii9234, I2C_MHL, offset)
0290 #define cbus_writeb(sii9234, offset, value) \
0291 sii9234_writeb(sii9234, I2C_CBUS, offset, value)
0292 #define cbus_writebm(sii9234, offset, value, mask) \
0293 sii9234_writebm(sii9234, I2C_CBUS, offset, value, mask)
0294 #define cbus_readb(sii9234, offset) \
0295 sii9234_readb(sii9234, I2C_CBUS, offset)
0296 #define hdmi_writeb(sii9234, offset, value) \
0297 sii9234_writeb(sii9234, I2C_HDMI, offset, value)
0298 #define hdmi_writebm(sii9234, offset, value, mask) \
0299 sii9234_writebm(sii9234, I2C_HDMI, offset, value, mask)
0300 #define hdmi_readb(sii9234, offset) \
0301 sii9234_readb(sii9234, I2C_HDMI, offset)
0302 #define tpi_writeb(sii9234, offset, value) \
0303 sii9234_writeb(sii9234, I2C_TPI, offset, value)
0304 #define tpi_writebm(sii9234, offset, value, mask) \
0305 sii9234_writebm(sii9234, I2C_TPI, offset, value, mask)
0306 #define tpi_readb(sii9234, offset) \
0307 sii9234_readb(sii9234, I2C_TPI, offset)
0308
0309 static u8 sii9234_tmds_control(struct sii9234 *ctx, bool enable)
0310 {
0311 mhl_tx_writebm(ctx, MHL_TX_TMDS_CCTRL, enable ? ~0 : 0,
0312 BIT_TMDS_CCTRL_TMDS_OE);
0313 mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, enable ? ~0 : 0,
0314 MHL_HPD_OUT_OVR_EN | MHL_HPD_OUT_OVR_VAL);
0315 return sii9234_clear_error(ctx);
0316 }
0317
0318 static int sii9234_cbus_reset(struct sii9234 *ctx)
0319 {
0320 int i;
0321
0322 mhl_tx_writebm(ctx, MHL_TX_SRST, ~0, BIT_CBUS_RESET);
0323 msleep(T_SRC_CBUS_DEGLITCH);
0324 mhl_tx_writebm(ctx, MHL_TX_SRST, 0, BIT_CBUS_RESET);
0325
0326 for (i = 0; i < 4; i++) {
0327
0328
0329
0330
0331 cbus_writeb(ctx, 0xE0 + i, 0xF2);
0332
0333
0334
0335
0336 cbus_writeb(ctx, 0xF0 + i, 0xF2);
0337 }
0338
0339 return sii9234_clear_error(ctx);
0340 }
0341
0342
0343 static int sii9234_cbus_init(struct sii9234 *ctx)
0344 {
0345 cbus_writeb(ctx, 0x07, 0xF2);
0346 cbus_writeb(ctx, 0x40, 0x03);
0347 cbus_writeb(ctx, 0x42, 0x06);
0348 cbus_writeb(ctx, 0x36, 0x0C);
0349 cbus_writeb(ctx, 0x3D, 0xFD);
0350 cbus_writeb(ctx, 0x1C, 0x01);
0351 cbus_writeb(ctx, 0x1D, 0x0F);
0352 cbus_writeb(ctx, 0x44, 0x02);
0353
0354 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEV_STATE, 0x00);
0355 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_MHL_VERSION,
0356 SII9234_MHL_VERSION);
0357 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_CAT,
0358 MHL_DCAP_CAT_SOURCE);
0359 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_H, 0x01);
0360 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_L, 0x41);
0361 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VID_LINK_MODE,
0362 MHL_DCAP_VID_LINK_RGB444 | MHL_DCAP_VID_LINK_YCBCR444);
0363 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VIDEO_TYPE,
0364 MHL_DCAP_VT_GRAPHICS);
0365 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_LOG_DEV_MAP,
0366 MHL_DCAP_LD_GUI);
0367 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_BANDWIDTH, 0x0F);
0368 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_FEATURE_FLAG,
0369 MHL_DCAP_FEATURE_RCP_SUPPORT | MHL_DCAP_FEATURE_RAP_SUPPORT
0370 | MHL_DCAP_FEATURE_SP_SUPPORT);
0371 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_H, 0x0);
0372 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_L, 0x0);
0373 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_SCRATCHPAD_SIZE,
0374 SII9234_SCRATCHPAD_SIZE);
0375 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_INT_STAT_SIZE,
0376 SII9234_INT_STAT_SIZE);
0377 cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_RESERVED, 0);
0378 cbus_writebm(ctx, 0x31, 0x0C, 0x0C);
0379 cbus_writeb(ctx, 0x30, 0x01);
0380 cbus_writebm(ctx, 0x3C, 0x30, 0x38);
0381 cbus_writebm(ctx, 0x22, 0x0D, 0x0F);
0382 cbus_writebm(ctx, 0x2E, 0x15, 0x15);
0383 cbus_writeb(ctx, CBUS_INTR1_ENABLE_REG, 0);
0384 cbus_writeb(ctx, CBUS_INTR2_ENABLE_REG, 0);
0385
0386 return sii9234_clear_error(ctx);
0387 }
0388
0389 static void force_usb_id_switch_open(struct sii9234 *ctx)
0390 {
0391
0392 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0, 0x01);
0393
0394 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR);
0395 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86);
0396
0397 mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x30);
0398 }
0399
0400 static void release_usb_id_switch_open(struct sii9234 *ctx)
0401 {
0402 msleep(T_SRC_CBUS_FLOAT);
0403
0404 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR);
0405
0406 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 0x01);
0407 }
0408
0409 static int sii9234_power_init(struct sii9234 *ctx)
0410 {
0411
0412 tpi_writeb(ctx, TPI_DPD_REG, 0x3F);
0413
0414 hdmi_writeb(ctx, HDMI_RX_TMDS_CLK_EN_REG, 0x01);
0415
0416 hdmi_writeb(ctx, HDMI_RX_TMDS_CH_EN_REG, 0x15);
0417
0418 mhl_tx_writeb(ctx, 0x08, 0x35);
0419 return sii9234_clear_error(ctx);
0420 }
0421
0422 static int sii9234_hdmi_init(struct sii9234 *ctx)
0423 {
0424 hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);
0425 hdmi_writeb(ctx, HDMI_RX_PLL_CALREFSEL_REG, 0x03);
0426 hdmi_writeb(ctx, HDMI_RX_PLL_VCOCAL_REG, 0x20);
0427 hdmi_writeb(ctx, HDMI_RX_EQ_DATA0_REG, 0x8A);
0428 hdmi_writeb(ctx, HDMI_RX_EQ_DATA1_REG, 0x6A);
0429 hdmi_writeb(ctx, HDMI_RX_EQ_DATA2_REG, 0xAA);
0430 hdmi_writeb(ctx, HDMI_RX_EQ_DATA3_REG, 0xCA);
0431 hdmi_writeb(ctx, HDMI_RX_EQ_DATA4_REG, 0xEA);
0432 hdmi_writeb(ctx, HDMI_RX_TMDS_ZONE_CTRL_REG, 0xA0);
0433 hdmi_writeb(ctx, HDMI_RX_TMDS_MODE_CTRL_REG, 0x00);
0434 mhl_tx_writeb(ctx, MHL_TX_TMDS_CCTRL, 0x34);
0435 hdmi_writeb(ctx, 0x45, 0x44);
0436 hdmi_writeb(ctx, 0x31, 0x0A);
0437 hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);
0438
0439 return sii9234_clear_error(ctx);
0440 }
0441
0442 static int sii9234_mhl_tx_ctl_int(struct sii9234 *ctx)
0443 {
0444 mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0xD0);
0445 mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL2_REG, 0xFC);
0446 mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL4_REG, 0xEB);
0447 mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL7_REG, 0x0C);
0448
0449 return sii9234_clear_error(ctx);
0450 }
0451
0452 static int sii9234_reset(struct sii9234 *ctx)
0453 {
0454 int ret;
0455
0456 sii9234_clear_error(ctx);
0457
0458 ret = sii9234_power_init(ctx);
0459 if (ret < 0)
0460 return ret;
0461 ret = sii9234_cbus_reset(ctx);
0462 if (ret < 0)
0463 return ret;
0464 ret = sii9234_hdmi_init(ctx);
0465 if (ret < 0)
0466 return ret;
0467 ret = sii9234_mhl_tx_ctl_int(ctx);
0468 if (ret < 0)
0469 return ret;
0470
0471
0472 mhl_tx_writeb(ctx, 0x2B, 0x01);
0473
0474 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0x04, 0x06);
0475
0476 mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL2_REG, (1 << 7)
0477 | 2 << ATT_THRESH_SHIFT | DEGLITCH_TIME_50MS);
0478
0479
0480
0481
0482
0483 mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77);
0484 cbus_writebm(ctx, CBUS_LINK_CONTROL_2_REG, ~0, MHL_INIT_TIMEOUT);
0485 mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL6_REG, 0xA0);
0486
0487 mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT |
0488 DVRFLT_SEL | SINGLE_ATT);
0489
0490 mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL8_REG, 0);
0491
0492 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR);
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86);
0503
0504
0505
0506
0507 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C);
0508
0509 mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x06);
0510
0511 msleep(25);
0512
0513
0514 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR);
0515 mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL1_REG, 0x27);
0516
0517 ret = sii9234_clear_error(ctx);
0518 if (ret < 0)
0519 return ret;
0520 ret = sii9234_cbus_init(ctx);
0521 if (ret < 0)
0522 return ret;
0523
0524
0525 mhl_tx_writeb(ctx, 0x05, 0x04);
0526
0527 mhl_tx_writeb(ctx, 0x0D, 0x1C);
0528 mhl_tx_writeb(ctx, MHL_TX_INTR4_ENABLE_REG,
0529 RGND_READY_MASK | CBUS_LKOUT_MASK
0530 | MHL_DISC_FAIL_MASK | MHL_EST_MASK);
0531 mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, 0x60);
0532
0533
0534 force_usb_id_switch_open(ctx);
0535 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, 0, 0xF0);
0536 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL5_REG, 0, 0x03);
0537 release_usb_id_switch_open(ctx);
0538
0539
0540 mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 1 << 5);
0541 mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, ~0, 1 << 4);
0542
0543 return sii9234_clear_error(ctx);
0544 }
0545
0546 static int sii9234_goto_d3(struct sii9234 *ctx)
0547 {
0548 int ret;
0549
0550 dev_dbg(ctx->dev, "sii9234: detection started d3\n");
0551
0552 ret = sii9234_reset(ctx);
0553 if (ret < 0)
0554 goto exit;
0555
0556 hdmi_writeb(ctx, 0x01, 0x03);
0557 tpi_writebm(ctx, TPI_DPD_REG, 0, 1);
0558
0559 sii9234_clear_error(ctx);
0560
0561 ctx->state = ST_D3;
0562
0563 return 0;
0564 exit:
0565 dev_err(ctx->dev, "%s failed\n", __func__);
0566 return -1;
0567 }
0568
0569 static int sii9234_hw_on(struct sii9234 *ctx)
0570 {
0571 return regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
0572 }
0573
0574 static void sii9234_hw_off(struct sii9234 *ctx)
0575 {
0576 gpiod_set_value(ctx->gpio_reset, 1);
0577 msleep(20);
0578 regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
0579 }
0580
0581 static void sii9234_hw_reset(struct sii9234 *ctx)
0582 {
0583 gpiod_set_value(ctx->gpio_reset, 1);
0584 msleep(20);
0585 gpiod_set_value(ctx->gpio_reset, 0);
0586 }
0587
0588 static void sii9234_cable_in(struct sii9234 *ctx)
0589 {
0590 int ret;
0591
0592 mutex_lock(&ctx->lock);
0593 if (ctx->state != ST_OFF)
0594 goto unlock;
0595 ret = sii9234_hw_on(ctx);
0596 if (ret < 0)
0597 goto unlock;
0598
0599 sii9234_hw_reset(ctx);
0600 sii9234_goto_d3(ctx);
0601
0602 enable_irq(to_i2c_client(ctx->dev)->irq);
0603
0604 unlock:
0605 mutex_unlock(&ctx->lock);
0606 }
0607
0608 static void sii9234_cable_out(struct sii9234 *ctx)
0609 {
0610 mutex_lock(&ctx->lock);
0611
0612 if (ctx->state == ST_OFF)
0613 goto unlock;
0614
0615 disable_irq(to_i2c_client(ctx->dev)->irq);
0616 tpi_writeb(ctx, TPI_DPD_REG, 0);
0617
0618 sii9234_hw_off(ctx);
0619
0620 ctx->state = ST_OFF;
0621
0622 unlock:
0623 mutex_unlock(&ctx->lock);
0624 }
0625
0626 static enum sii9234_state sii9234_rgnd_ready_irq(struct sii9234 *ctx)
0627 {
0628 int value;
0629
0630 if (ctx->state == ST_D3) {
0631 int ret;
0632
0633 dev_dbg(ctx->dev, "RGND_READY_INT\n");
0634 sii9234_hw_reset(ctx);
0635
0636 ret = sii9234_reset(ctx);
0637 if (ret < 0) {
0638 dev_err(ctx->dev, "sii9234_reset() failed\n");
0639 return ST_FAILURE;
0640 }
0641
0642 return ST_RGND_INIT;
0643 }
0644
0645
0646 if (ctx->state != ST_RGND_INIT)
0647 return ST_FAILURE;
0648
0649 value = mhl_tx_readb(ctx, MHL_TX_STAT2_REG);
0650 if (sii9234_clear_error(ctx))
0651 return ST_FAILURE;
0652
0653 if ((value & RGND_INTP_MASK) != RGND_INTP_1K) {
0654 dev_warn(ctx->dev, "RGND is not 1k\n");
0655 return ST_RGND_INIT;
0656 }
0657 dev_dbg(ctx->dev, "RGND 1K!!\n");
0658 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C);
0659 mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77);
0660 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, 0x05);
0661 if (sii9234_clear_error(ctx))
0662 return ST_FAILURE;
0663
0664 msleep(T_SRC_VBUS_CBUS_TO_STABLE);
0665 return ST_RGND_1K;
0666 }
0667
0668 static enum sii9234_state sii9234_mhl_established(struct sii9234 *ctx)
0669 {
0670 dev_dbg(ctx->dev, "mhl est interrupt\n");
0671
0672
0673 mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0x10);
0674
0675 cbus_writeb(ctx, 0x07, 0x32);
0676 cbus_writebm(ctx, 0x44, ~0, 1 << 1);
0677
0678 mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 1);
0679 mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG,
0680 RSEN_CHANGE_INT_MASK | HPD_CHANGE_INT_MASK);
0681
0682 if (sii9234_clear_error(ctx))
0683 return ST_FAILURE;
0684
0685 return ST_MHL_ESTABLISHED;
0686 }
0687
0688 static enum sii9234_state sii9234_hpd_change(struct sii9234 *ctx)
0689 {
0690 int value;
0691
0692 value = cbus_readb(ctx, CBUS_MSC_REQ_ABORT_REASON_REG);
0693 if (sii9234_clear_error(ctx))
0694 return ST_FAILURE;
0695
0696 if (value & SET_HPD_DOWNSTREAM) {
0697
0698 sii9234_tmds_control(ctx, true);
0699 } else {
0700
0701 sii9234_tmds_control(ctx, false);
0702 }
0703
0704 return ctx->state;
0705 }
0706
0707 static enum sii9234_state sii9234_rsen_change(struct sii9234 *ctx)
0708 {
0709 int value;
0710
0711
0712 if (ctx->state != ST_RGND_1K) {
0713 dev_err(ctx->dev, "RSEN_HIGH without RGND_1K\n");
0714 return ST_FAILURE;
0715 }
0716 value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG);
0717 if (value < 0)
0718 return ST_FAILURE;
0719
0720 if (value & RSEN_STATUS) {
0721 dev_dbg(ctx->dev, "MHL cable connected.. RSEN High\n");
0722 return ST_RSEN_HIGH;
0723 }
0724 dev_dbg(ctx->dev, "RSEN lost\n");
0725
0726
0727
0728
0729
0730
0731
0732 msleep(T_SRC_RXSENSE_DEGLITCH);
0733 value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG);
0734 if (value < 0)
0735 return ST_FAILURE;
0736 dev_dbg(ctx->dev, "sys_stat: %x\n", value);
0737
0738 if (value & RSEN_STATUS) {
0739 dev_dbg(ctx->dev, "RSEN recovery\n");
0740 return ST_RSEN_HIGH;
0741 }
0742 dev_dbg(ctx->dev, "RSEN Really LOW\n");
0743
0744 sii9234_tmds_control(ctx, false);
0745 force_usb_id_switch_open(ctx);
0746 release_usb_id_switch_open(ctx);
0747
0748 return ST_FAILURE;
0749 }
0750
0751 static irqreturn_t sii9234_irq_thread(int irq, void *data)
0752 {
0753 struct sii9234 *ctx = data;
0754 int intr1, intr4;
0755 int intr1_en, intr4_en;
0756 int cbus_intr1, cbus_intr2;
0757
0758 dev_dbg(ctx->dev, "%s\n", __func__);
0759
0760 mutex_lock(&ctx->lock);
0761
0762 intr1 = mhl_tx_readb(ctx, MHL_TX_INTR1_REG);
0763 intr4 = mhl_tx_readb(ctx, MHL_TX_INTR4_REG);
0764 intr1_en = mhl_tx_readb(ctx, MHL_TX_INTR1_ENABLE_REG);
0765 intr4_en = mhl_tx_readb(ctx, MHL_TX_INTR4_ENABLE_REG);
0766 cbus_intr1 = cbus_readb(ctx, CBUS_INT_STATUS_1_REG);
0767 cbus_intr2 = cbus_readb(ctx, CBUS_INT_STATUS_2_REG);
0768
0769 if (sii9234_clear_error(ctx))
0770 goto done;
0771
0772 dev_dbg(ctx->dev, "irq %02x/%02x %02x/%02x %02x/%02x\n",
0773 intr1, intr1_en, intr4, intr4_en, cbus_intr1, cbus_intr2);
0774
0775 if (intr4 & RGND_READY_INT)
0776 ctx->state = sii9234_rgnd_ready_irq(ctx);
0777 if (intr1 & RSEN_CHANGE_INT)
0778 ctx->state = sii9234_rsen_change(ctx);
0779 if (intr4 & MHL_EST_INT)
0780 ctx->state = sii9234_mhl_established(ctx);
0781 if (intr1 & HPD_CHANGE_INT)
0782 ctx->state = sii9234_hpd_change(ctx);
0783 if (intr4 & CBUS_LKOUT_INT)
0784 ctx->state = ST_FAILURE;
0785 if (intr4 & MHL_DISC_FAIL_INT)
0786 ctx->state = ST_FAILURE_DISCOVERY;
0787
0788 done:
0789
0790 mhl_tx_writeb(ctx, MHL_TX_INTR1_REG, intr1);
0791 mhl_tx_writeb(ctx, MHL_TX_INTR4_REG, intr4);
0792 cbus_writeb(ctx, CBUS_MHL_STATUS_REG_0, 0xFF);
0793 cbus_writeb(ctx, CBUS_MHL_STATUS_REG_1, 0xFF);
0794 cbus_writeb(ctx, CBUS_INT_STATUS_1_REG, cbus_intr1);
0795 cbus_writeb(ctx, CBUS_INT_STATUS_2_REG, cbus_intr2);
0796
0797 sii9234_clear_error(ctx);
0798
0799 if (ctx->state == ST_FAILURE) {
0800 dev_dbg(ctx->dev, "try to reset after failure\n");
0801 sii9234_hw_reset(ctx);
0802 sii9234_goto_d3(ctx);
0803 }
0804
0805 if (ctx->state == ST_FAILURE_DISCOVERY) {
0806 dev_err(ctx->dev, "discovery failed, no power for MHL?\n");
0807 tpi_writebm(ctx, TPI_DPD_REG, 0, 1);
0808 ctx->state = ST_D3;
0809 }
0810
0811 mutex_unlock(&ctx->lock);
0812
0813 return IRQ_HANDLED;
0814 }
0815
0816 static int sii9234_init_resources(struct sii9234 *ctx,
0817 struct i2c_client *client)
0818 {
0819 struct i2c_adapter *adapter = client->adapter;
0820 int ret;
0821
0822 if (!ctx->dev->of_node) {
0823 dev_err(ctx->dev, "not DT device\n");
0824 return -ENODEV;
0825 }
0826
0827 ctx->gpio_reset = devm_gpiod_get(ctx->dev, "reset", GPIOD_OUT_LOW);
0828 if (IS_ERR(ctx->gpio_reset)) {
0829 dev_err(ctx->dev, "failed to get reset gpio from DT\n");
0830 return PTR_ERR(ctx->gpio_reset);
0831 }
0832
0833 ctx->supplies[0].supply = "avcc12";
0834 ctx->supplies[1].supply = "avcc33";
0835 ctx->supplies[2].supply = "iovcc18";
0836 ctx->supplies[3].supply = "cvcc12";
0837 ret = devm_regulator_bulk_get(ctx->dev, 4, ctx->supplies);
0838 if (ret) {
0839 if (ret != -EPROBE_DEFER)
0840 dev_err(ctx->dev, "regulator_bulk failed\n");
0841 return ret;
0842 }
0843
0844 ctx->client[I2C_MHL] = client;
0845
0846 ctx->client[I2C_TPI] = devm_i2c_new_dummy_device(&client->dev, adapter,
0847 I2C_TPI_ADDR);
0848 if (IS_ERR(ctx->client[I2C_TPI])) {
0849 dev_err(ctx->dev, "failed to create TPI client\n");
0850 return PTR_ERR(ctx->client[I2C_TPI]);
0851 }
0852
0853 ctx->client[I2C_HDMI] = devm_i2c_new_dummy_device(&client->dev, adapter,
0854 I2C_HDMI_ADDR);
0855 if (IS_ERR(ctx->client[I2C_HDMI])) {
0856 dev_err(ctx->dev, "failed to create HDMI RX client\n");
0857 return PTR_ERR(ctx->client[I2C_HDMI]);
0858 }
0859
0860 ctx->client[I2C_CBUS] = devm_i2c_new_dummy_device(&client->dev, adapter,
0861 I2C_CBUS_ADDR);
0862 if (IS_ERR(ctx->client[I2C_CBUS])) {
0863 dev_err(ctx->dev, "failed to create CBUS client\n");
0864 return PTR_ERR(ctx->client[I2C_CBUS]);
0865 }
0866
0867 return 0;
0868 }
0869
0870 static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge)
0871 {
0872 return container_of(bridge, struct sii9234, bridge);
0873 }
0874
0875 static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge,
0876 const struct drm_display_info *info,
0877 const struct drm_display_mode *mode)
0878 {
0879 if (mode->clock > MHL1_MAX_CLK)
0880 return MODE_CLOCK_HIGH;
0881
0882 return MODE_OK;
0883 }
0884
0885 static const struct drm_bridge_funcs sii9234_bridge_funcs = {
0886 .mode_valid = sii9234_mode_valid,
0887 };
0888
0889 static int sii9234_probe(struct i2c_client *client,
0890 const struct i2c_device_id *id)
0891 {
0892 struct i2c_adapter *adapter = client->adapter;
0893 struct sii9234 *ctx;
0894 struct device *dev = &client->dev;
0895 int ret;
0896
0897 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0898 if (!ctx)
0899 return -ENOMEM;
0900
0901 ctx->dev = dev;
0902 mutex_init(&ctx->lock);
0903
0904 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
0905 dev_err(dev, "I2C adapter lacks SMBUS feature\n");
0906 return -EIO;
0907 }
0908
0909 if (!client->irq) {
0910 dev_err(dev, "no irq provided\n");
0911 return -EINVAL;
0912 }
0913
0914 irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
0915 ret = devm_request_threaded_irq(dev, client->irq, NULL,
0916 sii9234_irq_thread,
0917 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
0918 "sii9234", ctx);
0919 if (ret < 0) {
0920 dev_err(dev, "failed to install IRQ handler\n");
0921 return ret;
0922 }
0923
0924 ret = sii9234_init_resources(ctx, client);
0925 if (ret < 0)
0926 return ret;
0927
0928 i2c_set_clientdata(client, ctx);
0929
0930 ctx->bridge.funcs = &sii9234_bridge_funcs;
0931 ctx->bridge.of_node = dev->of_node;
0932 drm_bridge_add(&ctx->bridge);
0933
0934 sii9234_cable_in(ctx);
0935
0936 return 0;
0937 }
0938
0939 static int sii9234_remove(struct i2c_client *client)
0940 {
0941 struct sii9234 *ctx = i2c_get_clientdata(client);
0942
0943 sii9234_cable_out(ctx);
0944 drm_bridge_remove(&ctx->bridge);
0945
0946 return 0;
0947 }
0948
0949 static const struct of_device_id sii9234_dt_match[] = {
0950 { .compatible = "sil,sii9234" },
0951 { },
0952 };
0953 MODULE_DEVICE_TABLE(of, sii9234_dt_match);
0954
0955 static const struct i2c_device_id sii9234_id[] = {
0956 { "SII9234", 0 },
0957 { },
0958 };
0959 MODULE_DEVICE_TABLE(i2c, sii9234_id);
0960
0961 static struct i2c_driver sii9234_driver = {
0962 .driver = {
0963 .name = "sii9234",
0964 .of_match_table = sii9234_dt_match,
0965 },
0966 .probe = sii9234_probe,
0967 .remove = sii9234_remove,
0968 .id_table = sii9234_id,
0969 };
0970
0971 module_i2c_driver(sii9234_driver);
0972 MODULE_LICENSE("GPL");