sii9234.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2017 Samsung Electronics
  4. *
  5. * Authors:
  6. * Tomasz Stanislawski <t.stanislaws@samsung.com>
  7. * Maciej Purski <m.purski@samsung.com>
  8. *
  9. * Based on sii9234 driver created by:
  10. * Adam Hampson <ahampson@sta.samsung.com>
  11. * Erik Gilling <konkers@android.com>
  12. * Shankar Bandal <shankar.b@samsung.com>
  13. * Dharam Kumar <dharam.kr@samsung.com>
  14. */
  15. #include <drm/bridge/mhl.h>
  16. #include <drm/drm_bridge.h>
  17. #include <drm/drm_crtc.h>
  18. #include <drm/drm_edid.h>
  19. #include <linux/delay.h>
  20. #include <linux/err.h>
  21. #include <linux/gpio/consumer.h>
  22. #include <linux/i2c.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/irq.h>
  25. #include <linux/kernel.h>
  26. #include <linux/module.h>
  27. #include <linux/mutex.h>
  28. #include <linux/regulator/consumer.h>
  29. #include <linux/slab.h>
  30. #define CBUS_DEVCAP_OFFSET 0x80
  31. #define SII9234_MHL_VERSION 0x11
  32. #define SII9234_SCRATCHPAD_SIZE 0x10
  33. #define SII9234_INT_STAT_SIZE 0x33
  34. #define BIT_TMDS_CCTRL_TMDS_OE BIT(4)
  35. #define MHL_HPD_OUT_OVR_EN BIT(4)
  36. #define MHL_HPD_OUT_OVR_VAL BIT(5)
  37. #define MHL_INIT_TIMEOUT 0x0C
  38. /* MHL Tx registers and bits */
  39. #define MHL_TX_SRST 0x05
  40. #define MHL_TX_SYSSTAT_REG 0x09
  41. #define MHL_TX_INTR1_REG 0x71
  42. #define MHL_TX_INTR4_REG 0x74
  43. #define MHL_TX_INTR1_ENABLE_REG 0x75
  44. #define MHL_TX_INTR4_ENABLE_REG 0x78
  45. #define MHL_TX_INT_CTRL_REG 0x79
  46. #define MHL_TX_TMDS_CCTRL 0x80
  47. #define MHL_TX_DISC_CTRL1_REG 0x90
  48. #define MHL_TX_DISC_CTRL2_REG 0x91
  49. #define MHL_TX_DISC_CTRL3_REG 0x92
  50. #define MHL_TX_DISC_CTRL4_REG 0x93
  51. #define MHL_TX_DISC_CTRL5_REG 0x94
  52. #define MHL_TX_DISC_CTRL6_REG 0x95
  53. #define MHL_TX_DISC_CTRL7_REG 0x96
  54. #define MHL_TX_DISC_CTRL8_REG 0x97
  55. #define MHL_TX_STAT2_REG 0x99
  56. #define MHL_TX_MHLTX_CTL1_REG 0xA0
  57. #define MHL_TX_MHLTX_CTL2_REG 0xA1
  58. #define MHL_TX_MHLTX_CTL4_REG 0xA3
  59. #define MHL_TX_MHLTX_CTL6_REG 0xA5
  60. #define MHL_TX_MHLTX_CTL7_REG 0xA6
  61. #define RSEN_STATUS BIT(2)
  62. #define HPD_CHANGE_INT BIT(6)
  63. #define RSEN_CHANGE_INT BIT(5)
  64. #define RGND_READY_INT BIT(6)
  65. #define VBUS_LOW_INT BIT(5)
  66. #define CBUS_LKOUT_INT BIT(4)
  67. #define MHL_DISC_FAIL_INT BIT(3)
  68. #define MHL_EST_INT BIT(2)
  69. #define HPD_CHANGE_INT_MASK BIT(6)
  70. #define RSEN_CHANGE_INT_MASK BIT(5)
  71. #define RGND_READY_MASK BIT(6)
  72. #define CBUS_LKOUT_MASK BIT(4)
  73. #define MHL_DISC_FAIL_MASK BIT(3)
  74. #define MHL_EST_MASK BIT(2)
  75. #define SKIP_GND BIT(6)
  76. #define ATT_THRESH_SHIFT 0x04
  77. #define ATT_THRESH_MASK (0x03 << ATT_THRESH_SHIFT)
  78. #define USB_D_OEN BIT(3)
  79. #define DEGLITCH_TIME_MASK 0x07
  80. #define DEGLITCH_TIME_2MS 0
  81. #define DEGLITCH_TIME_4MS 1
  82. #define DEGLITCH_TIME_8MS 2
  83. #define DEGLITCH_TIME_16MS 3
  84. #define DEGLITCH_TIME_40MS 4
  85. #define DEGLITCH_TIME_50MS 5
  86. #define DEGLITCH_TIME_60MS 6
  87. #define DEGLITCH_TIME_128MS 7
  88. #define USB_D_OVR BIT(7)
  89. #define USB_ID_OVR BIT(6)
  90. #define DVRFLT_SEL BIT(5)
  91. #define BLOCK_RGND_INT BIT(4)
  92. #define SKIP_DEG BIT(3)
  93. #define CI2CA_POL BIT(2)
  94. #define CI2CA_WKUP BIT(1)
  95. #define SINGLE_ATT BIT(0)
  96. #define USB_D_ODN BIT(5)
  97. #define VBUS_CHECK BIT(2)
  98. #define RGND_INTP_MASK 0x03
  99. #define RGND_INTP_OPEN 0
  100. #define RGND_INTP_2K 1
  101. #define RGND_INTP_1K 2
  102. #define RGND_INTP_SHORT 3
  103. /* HDMI registers */
  104. #define HDMI_RX_TMDS0_CCTRL1_REG 0x10
  105. #define HDMI_RX_TMDS_CLK_EN_REG 0x11
  106. #define HDMI_RX_TMDS_CH_EN_REG 0x12
  107. #define HDMI_RX_PLL_CALREFSEL_REG 0x17
  108. #define HDMI_RX_PLL_VCOCAL_REG 0x1A
  109. #define HDMI_RX_EQ_DATA0_REG 0x22
  110. #define HDMI_RX_EQ_DATA1_REG 0x23
  111. #define HDMI_RX_EQ_DATA2_REG 0x24
  112. #define HDMI_RX_EQ_DATA3_REG 0x25
  113. #define HDMI_RX_EQ_DATA4_REG 0x26
  114. #define HDMI_RX_TMDS_ZONE_CTRL_REG 0x4C
  115. #define HDMI_RX_TMDS_MODE_CTRL_REG 0x4D
  116. /* CBUS registers */
  117. #define CBUS_INT_STATUS_1_REG 0x08
  118. #define CBUS_INTR1_ENABLE_REG 0x09
  119. #define CBUS_MSC_REQ_ABORT_REASON_REG 0x0D
  120. #define CBUS_INT_STATUS_2_REG 0x1E
  121. #define CBUS_INTR2_ENABLE_REG 0x1F
  122. #define CBUS_LINK_CONTROL_2_REG 0x31
  123. #define CBUS_MHL_STATUS_REG_0 0xB0
  124. #define CBUS_MHL_STATUS_REG_1 0xB1
  125. #define BIT_CBUS_RESET BIT(3)
  126. #define SET_HPD_DOWNSTREAM BIT(6)
  127. /* TPI registers */
  128. #define TPI_DPD_REG 0x3D
  129. /* Timeouts in msec */
  130. #define T_SRC_VBUS_CBUS_TO_STABLE 200
  131. #define T_SRC_CBUS_FLOAT 100
  132. #define T_SRC_CBUS_DEGLITCH 2
  133. #define T_SRC_RXSENSE_DEGLITCH 110
  134. #define MHL1_MAX_CLK 75000 /* in kHz */
  135. #define I2C_TPI_ADDR 0x3D
  136. #define I2C_HDMI_ADDR 0x49
  137. #define I2C_CBUS_ADDR 0x64
  138. enum sii9234_state {
  139. ST_OFF,
  140. ST_D3,
  141. ST_RGND_INIT,
  142. ST_RGND_1K,
  143. ST_RSEN_HIGH,
  144. ST_MHL_ESTABLISHED,
  145. ST_FAILURE_DISCOVERY,
  146. ST_FAILURE,
  147. };
  148. struct sii9234 {
  149. struct i2c_client *client[4];
  150. struct drm_bridge bridge;
  151. struct device *dev;
  152. struct gpio_desc *gpio_reset;
  153. int i2c_error;
  154. struct regulator_bulk_data supplies[4];
  155. struct mutex lock; /* Protects fields below and device registers */
  156. enum sii9234_state state;
  157. };
  158. enum sii9234_client_id {
  159. I2C_MHL,
  160. I2C_TPI,
  161. I2C_HDMI,
  162. I2C_CBUS,
  163. };
  164. static const char * const sii9234_client_name[] = {
  165. [I2C_MHL] = "MHL",
  166. [I2C_TPI] = "TPI",
  167. [I2C_HDMI] = "HDMI",
  168. [I2C_CBUS] = "CBUS",
  169. };
  170. static int sii9234_writeb(struct sii9234 *ctx, int id, int offset,
  171. int value)
  172. {
  173. int ret;
  174. struct i2c_client *client = ctx->client[id];
  175. if (ctx->i2c_error)
  176. return ctx->i2c_error;
  177. ret = i2c_smbus_write_byte_data(client, offset, value);
  178. if (ret < 0)
  179. dev_err(ctx->dev, "writeb: %4s[0x%02x] <- 0x%02x\n",
  180. sii9234_client_name[id], offset, value);
  181. ctx->i2c_error = ret;
  182. return ret;
  183. }
  184. static int sii9234_writebm(struct sii9234 *ctx, int id, int offset,
  185. int value, int mask)
  186. {
  187. int ret;
  188. struct i2c_client *client = ctx->client[id];
  189. if (ctx->i2c_error)
  190. return ctx->i2c_error;
  191. ret = i2c_smbus_write_byte(client, offset);
  192. if (ret < 0) {
  193. dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n",
  194. sii9234_client_name[id], offset, value);
  195. ctx->i2c_error = ret;
  196. return ret;
  197. }
  198. ret = i2c_smbus_read_byte(client);
  199. if (ret < 0) {
  200. dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n",
  201. sii9234_client_name[id], offset, value);
  202. ctx->i2c_error = ret;
  203. return ret;
  204. }
  205. value = (value & mask) | (ret & ~mask);
  206. ret = i2c_smbus_write_byte_data(client, offset, value);
  207. if (ret < 0) {
  208. dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n",
  209. sii9234_client_name[id], offset, value);
  210. ctx->i2c_error = ret;
  211. }
  212. return ret;
  213. }
  214. static int sii9234_readb(struct sii9234 *ctx, int id, int offset)
  215. {
  216. int ret;
  217. struct i2c_client *client = ctx->client[id];
  218. if (ctx->i2c_error)
  219. return ctx->i2c_error;
  220. ret = i2c_smbus_write_byte(client, offset);
  221. if (ret < 0) {
  222. dev_err(ctx->dev, "readb: %4s[0x%02x]\n",
  223. sii9234_client_name[id], offset);
  224. ctx->i2c_error = ret;
  225. return ret;
  226. }
  227. ret = i2c_smbus_read_byte(client);
  228. if (ret < 0) {
  229. dev_err(ctx->dev, "readb: %4s[0x%02x]\n",
  230. sii9234_client_name[id], offset);
  231. ctx->i2c_error = ret;
  232. }
  233. return ret;
  234. }
  235. static int sii9234_clear_error(struct sii9234 *ctx)
  236. {
  237. int ret = ctx->i2c_error;
  238. ctx->i2c_error = 0;
  239. return ret;
  240. }
  241. #define mhl_tx_writeb(sii9234, offset, value) \
  242. sii9234_writeb(sii9234, I2C_MHL, offset, value)
  243. #define mhl_tx_writebm(sii9234, offset, value, mask) \
  244. sii9234_writebm(sii9234, I2C_MHL, offset, value, mask)
  245. #define mhl_tx_readb(sii9234, offset) \
  246. sii9234_readb(sii9234, I2C_MHL, offset)
  247. #define cbus_writeb(sii9234, offset, value) \
  248. sii9234_writeb(sii9234, I2C_CBUS, offset, value)
  249. #define cbus_writebm(sii9234, offset, value, mask) \
  250. sii9234_writebm(sii9234, I2C_CBUS, offset, value, mask)
  251. #define cbus_readb(sii9234, offset) \
  252. sii9234_readb(sii9234, I2C_CBUS, offset)
  253. #define hdmi_writeb(sii9234, offset, value) \
  254. sii9234_writeb(sii9234, I2C_HDMI, offset, value)
  255. #define hdmi_writebm(sii9234, offset, value, mask) \
  256. sii9234_writebm(sii9234, I2C_HDMI, offset, value, mask)
  257. #define hdmi_readb(sii9234, offset) \
  258. sii9234_readb(sii9234, I2C_HDMI, offset)
  259. #define tpi_writeb(sii9234, offset, value) \
  260. sii9234_writeb(sii9234, I2C_TPI, offset, value)
  261. #define tpi_writebm(sii9234, offset, value, mask) \
  262. sii9234_writebm(sii9234, I2C_TPI, offset, value, mask)
  263. #define tpi_readb(sii9234, offset) \
  264. sii9234_readb(sii9234, I2C_TPI, offset)
  265. static u8 sii9234_tmds_control(struct sii9234 *ctx, bool enable)
  266. {
  267. mhl_tx_writebm(ctx, MHL_TX_TMDS_CCTRL, enable ? ~0 : 0,
  268. BIT_TMDS_CCTRL_TMDS_OE);
  269. mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, enable ? ~0 : 0,
  270. MHL_HPD_OUT_OVR_EN | MHL_HPD_OUT_OVR_VAL);
  271. return sii9234_clear_error(ctx);
  272. }
  273. static int sii9234_cbus_reset(struct sii9234 *ctx)
  274. {
  275. int i;
  276. mhl_tx_writebm(ctx, MHL_TX_SRST, ~0, BIT_CBUS_RESET);
  277. msleep(T_SRC_CBUS_DEGLITCH);
  278. mhl_tx_writebm(ctx, MHL_TX_SRST, 0, BIT_CBUS_RESET);
  279. for (i = 0; i < 4; i++) {
  280. /*
  281. * Enable WRITE_STAT interrupt for writes to all
  282. * 4 MSC Status registers.
  283. */
  284. cbus_writeb(ctx, 0xE0 + i, 0xF2);
  285. /*
  286. * Enable SET_INT interrupt for writes to all
  287. * 4 MSC Interrupt registers.
  288. */
  289. cbus_writeb(ctx, 0xF0 + i, 0xF2);
  290. }
  291. return sii9234_clear_error(ctx);
  292. }
  293. /* Require to chek mhl imformation of samsung in cbus_init_register */
  294. static int sii9234_cbus_init(struct sii9234 *ctx)
  295. {
  296. cbus_writeb(ctx, 0x07, 0xF2);
  297. cbus_writeb(ctx, 0x40, 0x03);
  298. cbus_writeb(ctx, 0x42, 0x06);
  299. cbus_writeb(ctx, 0x36, 0x0C);
  300. cbus_writeb(ctx, 0x3D, 0xFD);
  301. cbus_writeb(ctx, 0x1C, 0x01);
  302. cbus_writeb(ctx, 0x1D, 0x0F);
  303. cbus_writeb(ctx, 0x44, 0x02);
  304. /* Setup our devcap */
  305. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEV_STATE, 0x00);
  306. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_MHL_VERSION,
  307. SII9234_MHL_VERSION);
  308. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_CAT,
  309. MHL_DCAP_CAT_SOURCE);
  310. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_H, 0x01);
  311. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_L, 0x41);
  312. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VID_LINK_MODE,
  313. MHL_DCAP_VID_LINK_RGB444 | MHL_DCAP_VID_LINK_YCBCR444);
  314. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VIDEO_TYPE,
  315. MHL_DCAP_VT_GRAPHICS);
  316. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_LOG_DEV_MAP,
  317. MHL_DCAP_LD_GUI);
  318. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_BANDWIDTH, 0x0F);
  319. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_FEATURE_FLAG,
  320. MHL_DCAP_FEATURE_RCP_SUPPORT | MHL_DCAP_FEATURE_RAP_SUPPORT
  321. | MHL_DCAP_FEATURE_SP_SUPPORT);
  322. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_H, 0x0);
  323. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_L, 0x0);
  324. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_SCRATCHPAD_SIZE,
  325. SII9234_SCRATCHPAD_SIZE);
  326. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_INT_STAT_SIZE,
  327. SII9234_INT_STAT_SIZE);
  328. cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_RESERVED, 0);
  329. cbus_writebm(ctx, 0x31, 0x0C, 0x0C);
  330. cbus_writeb(ctx, 0x30, 0x01);
  331. cbus_writebm(ctx, 0x3C, 0x30, 0x38);
  332. cbus_writebm(ctx, 0x22, 0x0D, 0x0F);
  333. cbus_writebm(ctx, 0x2E, 0x15, 0x15);
  334. cbus_writeb(ctx, CBUS_INTR1_ENABLE_REG, 0);
  335. cbus_writeb(ctx, CBUS_INTR2_ENABLE_REG, 0);
  336. return sii9234_clear_error(ctx);
  337. }
  338. static void force_usb_id_switch_open(struct sii9234 *ctx)
  339. {
  340. /* Disable CBUS discovery */
  341. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0, 0x01);
  342. /* Force USB ID switch to open */
  343. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR);
  344. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86);
  345. /* Force upstream HPD to 0 when not in MHL mode. */
  346. mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x30);
  347. }
  348. static void release_usb_id_switch_open(struct sii9234 *ctx)
  349. {
  350. msleep(T_SRC_CBUS_FLOAT);
  351. /* Clear USB ID switch to open */
  352. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR);
  353. /* Enable CBUS discovery */
  354. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 0x01);
  355. }
  356. static int sii9234_power_init(struct sii9234 *ctx)
  357. {
  358. /* Force the SiI9234 into the D0 state. */
  359. tpi_writeb(ctx, TPI_DPD_REG, 0x3F);
  360. /* Enable TxPLL Clock */
  361. hdmi_writeb(ctx, HDMI_RX_TMDS_CLK_EN_REG, 0x01);
  362. /* Enable Tx Clock Path & Equalizer */
  363. hdmi_writeb(ctx, HDMI_RX_TMDS_CH_EN_REG, 0x15);
  364. /* Power Up TMDS */
  365. mhl_tx_writeb(ctx, 0x08, 0x35);
  366. return sii9234_clear_error(ctx);
  367. }
  368. static int sii9234_hdmi_init(struct sii9234 *ctx)
  369. {
  370. hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);
  371. hdmi_writeb(ctx, HDMI_RX_PLL_CALREFSEL_REG, 0x03);
  372. hdmi_writeb(ctx, HDMI_RX_PLL_VCOCAL_REG, 0x20);
  373. hdmi_writeb(ctx, HDMI_RX_EQ_DATA0_REG, 0x8A);
  374. hdmi_writeb(ctx, HDMI_RX_EQ_DATA1_REG, 0x6A);
  375. hdmi_writeb(ctx, HDMI_RX_EQ_DATA2_REG, 0xAA);
  376. hdmi_writeb(ctx, HDMI_RX_EQ_DATA3_REG, 0xCA);
  377. hdmi_writeb(ctx, HDMI_RX_EQ_DATA4_REG, 0xEA);
  378. hdmi_writeb(ctx, HDMI_RX_TMDS_ZONE_CTRL_REG, 0xA0);
  379. hdmi_writeb(ctx, HDMI_RX_TMDS_MODE_CTRL_REG, 0x00);
  380. mhl_tx_writeb(ctx, MHL_TX_TMDS_CCTRL, 0x34);
  381. hdmi_writeb(ctx, 0x45, 0x44);
  382. hdmi_writeb(ctx, 0x31, 0x0A);
  383. hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);
  384. return sii9234_clear_error(ctx);
  385. }
  386. static int sii9234_mhl_tx_ctl_int(struct sii9234 *ctx)
  387. {
  388. mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0xD0);
  389. mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL2_REG, 0xFC);
  390. mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL4_REG, 0xEB);
  391. mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL7_REG, 0x0C);
  392. return sii9234_clear_error(ctx);
  393. }
  394. static int sii9234_reset(struct sii9234 *ctx)
  395. {
  396. int ret;
  397. sii9234_clear_error(ctx);
  398. ret = sii9234_power_init(ctx);
  399. if (ret < 0)
  400. return ret;
  401. ret = sii9234_cbus_reset(ctx);
  402. if (ret < 0)
  403. return ret;
  404. ret = sii9234_hdmi_init(ctx);
  405. if (ret < 0)
  406. return ret;
  407. ret = sii9234_mhl_tx_ctl_int(ctx);
  408. if (ret < 0)
  409. return ret;
  410. /* Enable HDCP Compliance safety */
  411. mhl_tx_writeb(ctx, 0x2B, 0x01);
  412. /* CBUS discovery cycle time for each drive and float = 150us */
  413. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0x04, 0x06);
  414. /* Clear bit 6 (reg_skip_rgnd) */
  415. mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL2_REG, (1 << 7) /* Reserved */
  416. | 2 << ATT_THRESH_SHIFT | DEGLITCH_TIME_50MS);
  417. /*
  418. * Changed from 66 to 65 for 94[1:0] = 01 = 5k reg_cbusmhl_pup_sel
  419. * 1.8V CBUS VTH & GND threshold
  420. * to meet CTS 3.3.7.2 spec
  421. */
  422. mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77);
  423. cbus_writebm(ctx, CBUS_LINK_CONTROL_2_REG, ~0, MHL_INIT_TIMEOUT);
  424. mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL6_REG, 0xA0);
  425. /* RGND & single discovery attempt (RGND blocking) */
  426. mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT |
  427. DVRFLT_SEL | SINGLE_ATT);
  428. /* Use VBUS path of discovery state machine */
  429. mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL8_REG, 0);
  430. /* 0x92[3] sets the CBUS / ID switch */
  431. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR);
  432. /*
  433. * To allow RGND engine to operate correctly.
  434. * When moving the chip from D2 to D0 (power up, init regs)
  435. * the values should be
  436. * 94[1:0] = 01 reg_cbusmhl_pup_sel[1:0] should be set for 5k
  437. * 93[7:6] = 10 reg_cbusdisc_pup_sel[1:0] should be
  438. * set for 10k (default)
  439. * 93[5:4] = 00 reg_cbusidle_pup_sel[1:0] = open (default)
  440. */
  441. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86);
  442. /*
  443. * Change from CC to 8C to match 5K
  444. * to meet CTS 3.3.72 spec
  445. */
  446. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C);
  447. /* Configure the interrupt as active high */
  448. mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x06);
  449. msleep(25);
  450. /* Release usb_id switch */
  451. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR);
  452. mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL1_REG, 0x27);
  453. ret = sii9234_clear_error(ctx);
  454. if (ret < 0)
  455. return ret;
  456. ret = sii9234_cbus_init(ctx);
  457. if (ret < 0)
  458. return ret;
  459. /* Enable Auto soft reset on SCDT = 0 */
  460. mhl_tx_writeb(ctx, 0x05, 0x04);
  461. /* HDMI Transcode mode enable */
  462. mhl_tx_writeb(ctx, 0x0D, 0x1C);
  463. mhl_tx_writeb(ctx, MHL_TX_INTR4_ENABLE_REG,
  464. RGND_READY_MASK | CBUS_LKOUT_MASK
  465. | MHL_DISC_FAIL_MASK | MHL_EST_MASK);
  466. mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, 0x60);
  467. /* This point is very important before measure RGND impedance */
  468. force_usb_id_switch_open(ctx);
  469. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, 0, 0xF0);
  470. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL5_REG, 0, 0x03);
  471. release_usb_id_switch_open(ctx);
  472. /* Force upstream HPD to 0 when not in MHL mode */
  473. mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 1 << 5);
  474. mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, ~0, 1 << 4);
  475. return sii9234_clear_error(ctx);
  476. }
  477. static int sii9234_goto_d3(struct sii9234 *ctx)
  478. {
  479. int ret;
  480. dev_dbg(ctx->dev, "sii9234: detection started d3\n");
  481. ret = sii9234_reset(ctx);
  482. if (ret < 0)
  483. goto exit;
  484. hdmi_writeb(ctx, 0x01, 0x03);
  485. tpi_writebm(ctx, TPI_DPD_REG, 0, 1);
  486. /* I2C above is expected to fail because power goes down */
  487. sii9234_clear_error(ctx);
  488. ctx->state = ST_D3;
  489. return 0;
  490. exit:
  491. dev_err(ctx->dev, "%s failed\n", __func__);
  492. return -1;
  493. }
  494. static int sii9234_hw_on(struct sii9234 *ctx)
  495. {
  496. return regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
  497. }
  498. static void sii9234_hw_off(struct sii9234 *ctx)
  499. {
  500. gpiod_set_value(ctx->gpio_reset, 1);
  501. msleep(20);
  502. regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
  503. }
  504. static void sii9234_hw_reset(struct sii9234 *ctx)
  505. {
  506. gpiod_set_value(ctx->gpio_reset, 1);
  507. msleep(20);
  508. gpiod_set_value(ctx->gpio_reset, 0);
  509. }
  510. static void sii9234_cable_in(struct sii9234 *ctx)
  511. {
  512. int ret;
  513. mutex_lock(&ctx->lock);
  514. if (ctx->state != ST_OFF)
  515. goto unlock;
  516. ret = sii9234_hw_on(ctx);
  517. if (ret < 0)
  518. goto unlock;
  519. sii9234_hw_reset(ctx);
  520. sii9234_goto_d3(ctx);
  521. /* To avoid irq storm, when hw is in meta state */
  522. enable_irq(to_i2c_client(ctx->dev)->irq);
  523. unlock:
  524. mutex_unlock(&ctx->lock);
  525. }
  526. static void sii9234_cable_out(struct sii9234 *ctx)
  527. {
  528. mutex_lock(&ctx->lock);
  529. if (ctx->state == ST_OFF)
  530. goto unlock;
  531. disable_irq(to_i2c_client(ctx->dev)->irq);
  532. tpi_writeb(ctx, TPI_DPD_REG, 0);
  533. /* Turn on&off hpd festure for only QCT HDMI */
  534. sii9234_hw_off(ctx);
  535. ctx->state = ST_OFF;
  536. unlock:
  537. mutex_unlock(&ctx->lock);
  538. }
  539. static enum sii9234_state sii9234_rgnd_ready_irq(struct sii9234 *ctx)
  540. {
  541. int value;
  542. if (ctx->state == ST_D3) {
  543. int ret;
  544. dev_dbg(ctx->dev, "RGND_READY_INT\n");
  545. sii9234_hw_reset(ctx);
  546. ret = sii9234_reset(ctx);
  547. if (ret < 0) {
  548. dev_err(ctx->dev, "sii9234_reset() failed\n");
  549. return ST_FAILURE;
  550. }
  551. return ST_RGND_INIT;
  552. }
  553. /* Got interrupt in inappropriate state */
  554. if (ctx->state != ST_RGND_INIT)
  555. return ST_FAILURE;
  556. value = mhl_tx_readb(ctx, MHL_TX_STAT2_REG);
  557. if (sii9234_clear_error(ctx))
  558. return ST_FAILURE;
  559. if ((value & RGND_INTP_MASK) != RGND_INTP_1K) {
  560. dev_warn(ctx->dev, "RGND is not 1k\n");
  561. return ST_RGND_INIT;
  562. }
  563. dev_dbg(ctx->dev, "RGND 1K!!\n");
  564. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C);
  565. mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77);
  566. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, 0x05);
  567. if (sii9234_clear_error(ctx))
  568. return ST_FAILURE;
  569. msleep(T_SRC_VBUS_CBUS_TO_STABLE);
  570. return ST_RGND_1K;
  571. }
  572. static enum sii9234_state sii9234_mhl_established(struct sii9234 *ctx)
  573. {
  574. dev_dbg(ctx->dev, "mhl est interrupt\n");
  575. /* Discovery override */
  576. mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0x10);
  577. /* Increase DDC translation layer timer (byte mode) */
  578. cbus_writeb(ctx, 0x07, 0x32);
  579. cbus_writebm(ctx, 0x44, ~0, 1 << 1);
  580. /* Keep the discovery enabled. Need RGND interrupt */
  581. mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 1);
  582. mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG,
  583. RSEN_CHANGE_INT_MASK | HPD_CHANGE_INT_MASK);
  584. if (sii9234_clear_error(ctx))
  585. return ST_FAILURE;
  586. return ST_MHL_ESTABLISHED;
  587. }
  588. static enum sii9234_state sii9234_hpd_change(struct sii9234 *ctx)
  589. {
  590. int value;
  591. value = cbus_readb(ctx, CBUS_MSC_REQ_ABORT_REASON_REG);
  592. if (sii9234_clear_error(ctx))
  593. return ST_FAILURE;
  594. if (value & SET_HPD_DOWNSTREAM) {
  595. /* Downstream HPD High, Enable TMDS */
  596. sii9234_tmds_control(ctx, true);
  597. } else {
  598. /* Downstream HPD Low, Disable TMDS */
  599. sii9234_tmds_control(ctx, false);
  600. }
  601. return ctx->state;
  602. }
  603. static enum sii9234_state sii9234_rsen_change(struct sii9234 *ctx)
  604. {
  605. int value;
  606. /* Work_around code to handle wrong interrupt */
  607. if (ctx->state != ST_RGND_1K) {
  608. dev_err(ctx->dev, "RSEN_HIGH without RGND_1K\n");
  609. return ST_FAILURE;
  610. }
  611. value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG);
  612. if (value < 0)
  613. return ST_FAILURE;
  614. if (value & RSEN_STATUS) {
  615. dev_dbg(ctx->dev, "MHL cable connected.. RSEN High\n");
  616. return ST_RSEN_HIGH;
  617. }
  618. dev_dbg(ctx->dev, "RSEN lost\n");
  619. /*
  620. * Once RSEN loss is confirmed,we need to check
  621. * based on cable status and chip power status,whether
  622. * it is SINK Loss(HDMI cable not connected, TV Off)
  623. * or MHL cable disconnection
  624. * TODO: Define the below mhl_disconnection()
  625. */
  626. msleep(T_SRC_RXSENSE_DEGLITCH);
  627. value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG);
  628. if (value < 0)
  629. return ST_FAILURE;
  630. dev_dbg(ctx->dev, "sys_stat: %x\n", value);
  631. if (value & RSEN_STATUS) {
  632. dev_dbg(ctx->dev, "RSEN recovery\n");
  633. return ST_RSEN_HIGH;
  634. }
  635. dev_dbg(ctx->dev, "RSEN Really LOW\n");
  636. /* To meet CTS 3.3.22.2 spec */
  637. sii9234_tmds_control(ctx, false);
  638. force_usb_id_switch_open(ctx);
  639. release_usb_id_switch_open(ctx);
  640. return ST_FAILURE;
  641. }
  642. static irqreturn_t sii9234_irq_thread(int irq, void *data)
  643. {
  644. struct sii9234 *ctx = data;
  645. int intr1, intr4;
  646. int intr1_en, intr4_en;
  647. int cbus_intr1, cbus_intr2;
  648. dev_dbg(ctx->dev, "%s\n", __func__);
  649. mutex_lock(&ctx->lock);
  650. intr1 = mhl_tx_readb(ctx, MHL_TX_INTR1_REG);
  651. intr4 = mhl_tx_readb(ctx, MHL_TX_INTR4_REG);
  652. intr1_en = mhl_tx_readb(ctx, MHL_TX_INTR1_ENABLE_REG);
  653. intr4_en = mhl_tx_readb(ctx, MHL_TX_INTR4_ENABLE_REG);
  654. cbus_intr1 = cbus_readb(ctx, CBUS_INT_STATUS_1_REG);
  655. cbus_intr2 = cbus_readb(ctx, CBUS_INT_STATUS_2_REG);
  656. if (sii9234_clear_error(ctx))
  657. goto done;
  658. dev_dbg(ctx->dev, "irq %02x/%02x %02x/%02x %02x/%02x\n",
  659. intr1, intr1_en, intr4, intr4_en, cbus_intr1, cbus_intr2);
  660. if (intr4 & RGND_READY_INT)
  661. ctx->state = sii9234_rgnd_ready_irq(ctx);
  662. if (intr1 & RSEN_CHANGE_INT)
  663. ctx->state = sii9234_rsen_change(ctx);
  664. if (intr4 & MHL_EST_INT)
  665. ctx->state = sii9234_mhl_established(ctx);
  666. if (intr1 & HPD_CHANGE_INT)
  667. ctx->state = sii9234_hpd_change(ctx);
  668. if (intr4 & CBUS_LKOUT_INT)
  669. ctx->state = ST_FAILURE;
  670. if (intr4 & MHL_DISC_FAIL_INT)
  671. ctx->state = ST_FAILURE_DISCOVERY;
  672. done:
  673. /* Clean interrupt status and pending flags */
  674. mhl_tx_writeb(ctx, MHL_TX_INTR1_REG, intr1);
  675. mhl_tx_writeb(ctx, MHL_TX_INTR4_REG, intr4);
  676. cbus_writeb(ctx, CBUS_MHL_STATUS_REG_0, 0xFF);
  677. cbus_writeb(ctx, CBUS_MHL_STATUS_REG_1, 0xFF);
  678. cbus_writeb(ctx, CBUS_INT_STATUS_1_REG, cbus_intr1);
  679. cbus_writeb(ctx, CBUS_INT_STATUS_2_REG, cbus_intr2);
  680. sii9234_clear_error(ctx);
  681. if (ctx->state == ST_FAILURE) {
  682. dev_dbg(ctx->dev, "try to reset after failure\n");
  683. sii9234_hw_reset(ctx);
  684. sii9234_goto_d3(ctx);
  685. }
  686. if (ctx->state == ST_FAILURE_DISCOVERY) {
  687. dev_err(ctx->dev, "discovery failed, no power for MHL?\n");
  688. tpi_writebm(ctx, TPI_DPD_REG, 0, 1);
  689. ctx->state = ST_D3;
  690. }
  691. mutex_unlock(&ctx->lock);
  692. return IRQ_HANDLED;
  693. }
  694. static int sii9234_init_resources(struct sii9234 *ctx,
  695. struct i2c_client *client)
  696. {
  697. struct i2c_adapter *adapter = client->adapter;
  698. int ret;
  699. if (!ctx->dev->of_node) {
  700. dev_err(ctx->dev, "not DT device\n");
  701. return -ENODEV;
  702. }
  703. ctx->gpio_reset = devm_gpiod_get(ctx->dev, "reset", GPIOD_OUT_LOW);
  704. if (IS_ERR(ctx->gpio_reset)) {
  705. dev_err(ctx->dev, "failed to get reset gpio from DT\n");
  706. return PTR_ERR(ctx->gpio_reset);
  707. }
  708. ctx->supplies[0].supply = "avcc12";
  709. ctx->supplies[1].supply = "avcc33";
  710. ctx->supplies[2].supply = "iovcc18";
  711. ctx->supplies[3].supply = "cvcc12";
  712. ret = devm_regulator_bulk_get(ctx->dev, 4, ctx->supplies);
  713. if (ret) {
  714. if (ret != -EPROBE_DEFER)
  715. dev_err(ctx->dev, "regulator_bulk failed\n");
  716. return ret;
  717. }
  718. ctx->client[I2C_MHL] = client;
  719. ctx->client[I2C_TPI] = devm_i2c_new_dummy_device(&client->dev, adapter,
  720. I2C_TPI_ADDR);
  721. if (IS_ERR(ctx->client[I2C_TPI])) {
  722. dev_err(ctx->dev, "failed to create TPI client\n");
  723. return PTR_ERR(ctx->client[I2C_TPI]);
  724. }
  725. ctx->client[I2C_HDMI] = devm_i2c_new_dummy_device(&client->dev, adapter,
  726. I2C_HDMI_ADDR);
  727. if (IS_ERR(ctx->client[I2C_HDMI])) {
  728. dev_err(ctx->dev, "failed to create HDMI RX client\n");
  729. return PTR_ERR(ctx->client[I2C_HDMI]);
  730. }
  731. ctx->client[I2C_CBUS] = devm_i2c_new_dummy_device(&client->dev, adapter,
  732. I2C_CBUS_ADDR);
  733. if (IS_ERR(ctx->client[I2C_CBUS])) {
  734. dev_err(ctx->dev, "failed to create CBUS client\n");
  735. return PTR_ERR(ctx->client[I2C_CBUS]);
  736. }
  737. return 0;
  738. }
  739. static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge)
  740. {
  741. return container_of(bridge, struct sii9234, bridge);
  742. }
  743. static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge,
  744. const struct drm_display_info *info,
  745. const struct drm_display_mode *mode)
  746. {
  747. if (mode->clock > MHL1_MAX_CLK)
  748. return MODE_CLOCK_HIGH;
  749. return MODE_OK;
  750. }
  751. static const struct drm_bridge_funcs sii9234_bridge_funcs = {
  752. .mode_valid = sii9234_mode_valid,
  753. };
  754. static int sii9234_probe(struct i2c_client *client,
  755. const struct i2c_device_id *id)
  756. {
  757. struct i2c_adapter *adapter = client->adapter;
  758. struct sii9234 *ctx;
  759. struct device *dev = &client->dev;
  760. int ret;
  761. ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
  762. if (!ctx)
  763. return -ENOMEM;
  764. ctx->dev = dev;
  765. mutex_init(&ctx->lock);
  766. if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
  767. dev_err(dev, "I2C adapter lacks SMBUS feature\n");
  768. return -EIO;
  769. }
  770. if (!client->irq) {
  771. dev_err(dev, "no irq provided\n");
  772. return -EINVAL;
  773. }
  774. irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
  775. ret = devm_request_threaded_irq(dev, client->irq, NULL,
  776. sii9234_irq_thread,
  777. IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
  778. "sii9234", ctx);
  779. if (ret < 0) {
  780. dev_err(dev, "failed to install IRQ handler\n");
  781. return ret;
  782. }
  783. ret = sii9234_init_resources(ctx, client);
  784. if (ret < 0)
  785. return ret;
  786. i2c_set_clientdata(client, ctx);
  787. ctx->bridge.funcs = &sii9234_bridge_funcs;
  788. ctx->bridge.of_node = dev->of_node;
  789. drm_bridge_add(&ctx->bridge);
  790. sii9234_cable_in(ctx);
  791. return 0;
  792. }
  793. static int sii9234_remove(struct i2c_client *client)
  794. {
  795. struct sii9234 *ctx = i2c_get_clientdata(client);
  796. sii9234_cable_out(ctx);
  797. drm_bridge_remove(&ctx->bridge);
  798. return 0;
  799. }
  800. static const struct of_device_id sii9234_dt_match[] = {
  801. { .compatible = "sil,sii9234" },
  802. { },
  803. };
  804. MODULE_DEVICE_TABLE(of, sii9234_dt_match);
  805. static const struct i2c_device_id sii9234_id[] = {
  806. { "SII9234", 0 },
  807. { },
  808. };
  809. MODULE_DEVICE_TABLE(i2c, sii9234_id);
  810. static struct i2c_driver sii9234_driver = {
  811. .driver = {
  812. .name = "sii9234",
  813. .of_match_table = sii9234_dt_match,
  814. },
  815. .probe = sii9234_probe,
  816. .remove = sii9234_remove,
  817. .id_table = sii9234_id,
  818. };
  819. module_i2c_driver(sii9234_driver);
  820. MODULE_LICENSE("GPL");