tc35876x-dsi-lvds.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. /*
  2. * Copyright © 2011 Intel Corporation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. *
  23. */
  24. #include "mdfld_dsi_dpi.h"
  25. #include "mdfld_output.h"
  26. #include "mdfld_dsi_pkg_sender.h"
  27. #include "tc35876x-dsi-lvds.h"
  28. #include <linux/i2c/tc35876x.h>
  29. #include <linux/kernel.h>
  30. #include <linux/module.h>
  31. #include <asm/intel_scu_ipc.h>
  32. static struct i2c_client *tc35876x_client;
  33. static struct i2c_client *cmi_lcd_i2c_client;
  34. #define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
  35. #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
  36. /* DSI D-PHY Layer Registers */
  37. #define D0W_DPHYCONTTX 0x0004
  38. #define CLW_DPHYCONTRX 0x0020
  39. #define D0W_DPHYCONTRX 0x0024
  40. #define D1W_DPHYCONTRX 0x0028
  41. #define D2W_DPHYCONTRX 0x002C
  42. #define D3W_DPHYCONTRX 0x0030
  43. #define COM_DPHYCONTRX 0x0038
  44. #define CLW_CNTRL 0x0040
  45. #define D0W_CNTRL 0x0044
  46. #define D1W_CNTRL 0x0048
  47. #define D2W_CNTRL 0x004C
  48. #define D3W_CNTRL 0x0050
  49. #define DFTMODE_CNTRL 0x0054
  50. /* DSI PPI Layer Registers */
  51. #define PPI_STARTPPI 0x0104
  52. #define PPI_BUSYPPI 0x0108
  53. #define PPI_LINEINITCNT 0x0110
  54. #define PPI_LPTXTIMECNT 0x0114
  55. #define PPI_LANEENABLE 0x0134
  56. #define PPI_TX_RX_TA 0x013C
  57. #define PPI_CLS_ATMR 0x0140
  58. #define PPI_D0S_ATMR 0x0144
  59. #define PPI_D1S_ATMR 0x0148
  60. #define PPI_D2S_ATMR 0x014C
  61. #define PPI_D3S_ATMR 0x0150
  62. #define PPI_D0S_CLRSIPOCOUNT 0x0164
  63. #define PPI_D1S_CLRSIPOCOUNT 0x0168
  64. #define PPI_D2S_CLRSIPOCOUNT 0x016C
  65. #define PPI_D3S_CLRSIPOCOUNT 0x0170
  66. #define CLS_PRE 0x0180
  67. #define D0S_PRE 0x0184
  68. #define D1S_PRE 0x0188
  69. #define D2S_PRE 0x018C
  70. #define D3S_PRE 0x0190
  71. #define CLS_PREP 0x01A0
  72. #define D0S_PREP 0x01A4
  73. #define D1S_PREP 0x01A8
  74. #define D2S_PREP 0x01AC
  75. #define D3S_PREP 0x01B0
  76. #define CLS_ZERO 0x01C0
  77. #define D0S_ZERO 0x01C4
  78. #define D1S_ZERO 0x01C8
  79. #define D2S_ZERO 0x01CC
  80. #define D3S_ZERO 0x01D0
  81. #define PPI_CLRFLG 0x01E0
  82. #define PPI_CLRSIPO 0x01E4
  83. #define HSTIMEOUT 0x01F0
  84. #define HSTIMEOUTENABLE 0x01F4
  85. /* DSI Protocol Layer Registers */
  86. #define DSI_STARTDSI 0x0204
  87. #define DSI_BUSYDSI 0x0208
  88. #define DSI_LANEENABLE 0x0210
  89. #define DSI_LANESTATUS0 0x0214
  90. #define DSI_LANESTATUS1 0x0218
  91. #define DSI_INTSTATUS 0x0220
  92. #define DSI_INTMASK 0x0224
  93. #define DSI_INTCLR 0x0228
  94. #define DSI_LPTXTO 0x0230
  95. /* DSI General Registers */
  96. #define DSIERRCNT 0x0300
  97. /* DSI Application Layer Registers */
  98. #define APLCTRL 0x0400
  99. #define RDPKTLN 0x0404
  100. /* Video Path Registers */
  101. #define VPCTRL 0x0450
  102. #define HTIM1 0x0454
  103. #define HTIM2 0x0458
  104. #define VTIM1 0x045C
  105. #define VTIM2 0x0460
  106. #define VFUEN 0x0464
  107. /* LVDS Registers */
  108. #define LVMX0003 0x0480
  109. #define LVMX0407 0x0484
  110. #define LVMX0811 0x0488
  111. #define LVMX1215 0x048C
  112. #define LVMX1619 0x0490
  113. #define LVMX2023 0x0494
  114. #define LVMX2427 0x0498
  115. #define LVCFG 0x049C
  116. #define LVPHY0 0x04A0
  117. #define LVPHY1 0x04A4
  118. /* System Registers */
  119. #define SYSSTAT 0x0500
  120. #define SYSRST 0x0504
  121. /* GPIO Registers */
  122. /*#define GPIOC 0x0520*/
  123. #define GPIOO 0x0524
  124. #define GPIOI 0x0528
  125. /* I2C Registers */
  126. #define I2CTIMCTRL 0x0540
  127. #define I2CMADDR 0x0544
  128. #define WDATAQ 0x0548
  129. #define RDATAQ 0x054C
  130. /* Chip/Rev Registers */
  131. #define IDREG 0x0580
  132. /* Debug Registers */
  133. #define DEBUG00 0x05A0
  134. #define DEBUG01 0x05A4
  135. /* Panel CABC registers */
  136. #define PANEL_PWM_CONTROL 0x90
  137. #define PANEL_FREQ_DIVIDER_HI 0x91
  138. #define PANEL_FREQ_DIVIDER_LO 0x92
  139. #define PANEL_DUTY_CONTROL 0x93
  140. #define PANEL_MODIFY_RGB 0x94
  141. #define PANEL_FRAMERATE_CONTROL 0x96
  142. #define PANEL_PWM_MIN 0x97
  143. #define PANEL_PWM_REF 0x98
  144. #define PANEL_PWM_MAX 0x99
  145. #define PANEL_ALLOW_DISTORT 0x9A
  146. #define PANEL_BYPASS_PWMI 0x9B
  147. /* Panel color management registers */
  148. #define PANEL_CM_ENABLE 0x700
  149. #define PANEL_CM_HUE 0x701
  150. #define PANEL_CM_SATURATION 0x702
  151. #define PANEL_CM_INTENSITY 0x703
  152. #define PANEL_CM_BRIGHTNESS 0x704
  153. #define PANEL_CM_CE_ENABLE 0x705
  154. #define PANEL_CM_PEAK_EN 0x710
  155. #define PANEL_CM_GAIN 0x711
  156. #define PANEL_CM_HUETABLE_START 0x730
  157. #define PANEL_CM_HUETABLE_END 0x747 /* inclusive */
  158. /* Input muxing for registers LVMX0003...LVMX2427 */
  159. enum {
  160. INPUT_R0, /* 0 */
  161. INPUT_R1,
  162. INPUT_R2,
  163. INPUT_R3,
  164. INPUT_R4,
  165. INPUT_R5,
  166. INPUT_R6,
  167. INPUT_R7,
  168. INPUT_G0, /* 8 */
  169. INPUT_G1,
  170. INPUT_G2,
  171. INPUT_G3,
  172. INPUT_G4,
  173. INPUT_G5,
  174. INPUT_G6,
  175. INPUT_G7,
  176. INPUT_B0, /* 16 */
  177. INPUT_B1,
  178. INPUT_B2,
  179. INPUT_B3,
  180. INPUT_B4,
  181. INPUT_B5,
  182. INPUT_B6,
  183. INPUT_B7,
  184. INPUT_HSYNC, /* 24 */
  185. INPUT_VSYNC,
  186. INPUT_DE,
  187. LOGIC_0,
  188. /* 28...31 undefined */
  189. };
  190. #define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00) \
  191. (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) | \
  192. FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
  193. /**
  194. * tc35876x_regw - Write DSI-LVDS bridge register using I2C
  195. * @client: struct i2c_client to use
  196. * @reg: register address
  197. * @value: value to write
  198. *
  199. * Returns 0 on success, or a negative error value.
  200. */
  201. static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
  202. {
  203. int r;
  204. u8 tx_data[] = {
  205. /* NOTE: Register address big-endian, data little-endian. */
  206. (reg >> 8) & 0xff,
  207. reg & 0xff,
  208. value & 0xff,
  209. (value >> 8) & 0xff,
  210. (value >> 16) & 0xff,
  211. (value >> 24) & 0xff,
  212. };
  213. struct i2c_msg msgs[] = {
  214. {
  215. .addr = client->addr,
  216. .flags = 0,
  217. .buf = tx_data,
  218. .len = ARRAY_SIZE(tx_data),
  219. },
  220. };
  221. r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
  222. if (r < 0) {
  223. dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
  224. __func__, reg, value, r);
  225. return r;
  226. }
  227. if (r < ARRAY_SIZE(msgs)) {
  228. dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
  229. __func__, reg, value, r);
  230. return -EAGAIN;
  231. }
  232. dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n",
  233. __func__, reg, value);
  234. return 0;
  235. }
  236. /**
  237. * tc35876x_regr - Read DSI-LVDS bridge register using I2C
  238. * @client: struct i2c_client to use
  239. * @reg: register address
  240. * @value: pointer for storing the value
  241. *
  242. * Returns 0 on success, or a negative error value.
  243. */
  244. static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
  245. {
  246. int r;
  247. u8 tx_data[] = {
  248. (reg >> 8) & 0xff,
  249. reg & 0xff,
  250. };
  251. u8 rx_data[4];
  252. struct i2c_msg msgs[] = {
  253. {
  254. .addr = client->addr,
  255. .flags = 0,
  256. .buf = tx_data,
  257. .len = ARRAY_SIZE(tx_data),
  258. },
  259. {
  260. .addr = client->addr,
  261. .flags = I2C_M_RD,
  262. .buf = rx_data,
  263. .len = ARRAY_SIZE(rx_data),
  264. },
  265. };
  266. r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
  267. if (r < 0) {
  268. dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
  269. reg, r);
  270. return r;
  271. }
  272. if (r < ARRAY_SIZE(msgs)) {
  273. dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
  274. reg, r);
  275. return -EAGAIN;
  276. }
  277. *value = rx_data[0] << 24 | rx_data[1] << 16 |
  278. rx_data[2] << 8 | rx_data[3];
  279. dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
  280. reg, *value);
  281. return 0;
  282. }
  283. void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state)
  284. {
  285. struct tc35876x_platform_data *pdata;
  286. if (WARN(!tc35876x_client, "%s called before probe", __func__))
  287. return;
  288. dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
  289. pdata = dev_get_platdata(&tc35876x_client->dev);
  290. if (pdata->gpio_bridge_reset == -1)
  291. return;
  292. if (state) {
  293. gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
  294. mdelay(10);
  295. } else {
  296. /* Pull MIPI Bridge reset pin to Low */
  297. gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
  298. mdelay(20);
  299. /* Pull MIPI Bridge reset pin to High */
  300. gpio_set_value_cansleep(pdata->gpio_bridge_reset, 1);
  301. mdelay(40);
  302. }
  303. }
  304. void tc35876x_configure_lvds_bridge(struct drm_device *dev)
  305. {
  306. struct i2c_client *i2c = tc35876x_client;
  307. u32 ppi_lptxtimecnt;
  308. u32 txtagocnt;
  309. u32 txtasurecnt;
  310. u32 id;
  311. if (WARN(!tc35876x_client, "%s called before probe", __func__))
  312. return;
  313. dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
  314. if (!tc35876x_regr(i2c, IDREG, &id))
  315. dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
  316. else
  317. dev_err(&tc35876x_client->dev, "Cannot read ID\n");
  318. ppi_lptxtimecnt = 4;
  319. txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
  320. txtasurecnt = 3 * ppi_lptxtimecnt / 2;
  321. tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
  322. FLD_VAL(txtasurecnt, 10, 0));
  323. tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
  324. tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
  325. tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
  326. tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
  327. tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
  328. /* Enabling MIPI & PPI lanes, Enable 4 lanes */
  329. tc35876x_regw(i2c, PPI_LANEENABLE,
  330. BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
  331. tc35876x_regw(i2c, DSI_LANEENABLE,
  332. BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
  333. tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
  334. tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
  335. /* Setting LVDS output frequency */
  336. tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
  337. FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
  338. /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
  339. tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
  340. /* Horizontal back porch and horizontal pulse width. 0x00280028 */
  341. tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
  342. /* Horizontal front porch and horizontal active video size. 0x00500500*/
  343. tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
  344. /* Vertical back porch and vertical sync pulse width. 0x000e000a */
  345. tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
  346. /* Vertical front porch and vertical display size. 0x000e0320 */
  347. tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
  348. /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
  349. tc35876x_regw(i2c, VFUEN, BIT(0));
  350. /* Soft reset LCD controller. */
  351. tc35876x_regw(i2c, SYSRST, BIT(2));
  352. /* LVDS-TX input muxing */
  353. tc35876x_regw(i2c, LVMX0003,
  354. INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2));
  355. tc35876x_regw(i2c, LVMX0407,
  356. INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6));
  357. tc35876x_regw(i2c, LVMX0811,
  358. INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3));
  359. tc35876x_regw(i2c, LVMX1215,
  360. INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5));
  361. tc35876x_regw(i2c, LVMX1619,
  362. INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0));
  363. tc35876x_regw(i2c, LVMX2023,
  364. INPUT_MUX(LOGIC_0, INPUT_B7, INPUT_B6, INPUT_B5));
  365. tc35876x_regw(i2c, LVMX2427,
  366. INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
  367. /* Enable LVDS transmitter. */
  368. tc35876x_regw(i2c, LVCFG, BIT(0));
  369. /* Clear notifications. Don't write reserved bits. Was write 0xffffffff
  370. * to 0x0288, must be in error?! */
  371. tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
  372. }
  373. #define GPIOPWMCTRL 0x38F
  374. #define PWM0CLKDIV0 0x62 /* low byte */
  375. #define PWM0CLKDIV1 0x61 /* high byte */
  376. #define SYSTEMCLK 19200000UL /* 19.2 MHz */
  377. #define PWM_FREQUENCY 9600 /* Hz */
  378. /* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */
  379. static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f)
  380. {
  381. return (baseclk - f) / f;
  382. }
  383. static void tc35876x_brightness_init(struct drm_device *dev)
  384. {
  385. int ret;
  386. u8 pwmctrl;
  387. u16 clkdiv;
  388. /* Make sure the PWM reference is the 19.2 MHz system clock. Read first
  389. * instead of setting directly to catch potential conflicts between PWM
  390. * users. */
  391. ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl);
  392. if (ret || pwmctrl != 0x01) {
  393. if (ret)
  394. dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n");
  395. else
  396. dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl);
  397. ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01);
  398. if (ret)
  399. dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n");
  400. }
  401. clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY);
  402. ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
  403. if (!ret)
  404. ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff);
  405. if (ret)
  406. dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n");
  407. else
  408. dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n",
  409. clkdiv, PWM_FREQUENCY);
  410. }
  411. #define PWM0DUTYCYCLE 0x67
  412. void tc35876x_brightness_control(struct drm_device *dev, int level)
  413. {
  414. int ret;
  415. u8 duty_val;
  416. u8 panel_duty_val;
  417. level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
  418. /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
  419. duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
  420. /* I won't pretend to understand this formula. The panel spec is quite
  421. * bad engrish.
  422. */
  423. panel_duty_val = (2 * level - 100) * 0xA9 /
  424. MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
  425. ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
  426. if (ret)
  427. dev_err(&tc35876x_client->dev, "%s: ipc write fail\n",
  428. __func__);
  429. if (cmi_lcd_i2c_client) {
  430. ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
  431. PANEL_PWM_MAX, panel_duty_val);
  432. if (ret < 0)
  433. dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n",
  434. __func__);
  435. }
  436. }
  437. void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
  438. {
  439. struct tc35876x_platform_data *pdata;
  440. if (WARN(!tc35876x_client, "%s called before probe", __func__))
  441. return;
  442. dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
  443. pdata = dev_get_platdata(&tc35876x_client->dev);
  444. if (pdata->gpio_panel_bl_en != -1)
  445. gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0);
  446. if (pdata->gpio_panel_vadd != -1)
  447. gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0);
  448. }
  449. void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
  450. {
  451. struct tc35876x_platform_data *pdata;
  452. struct drm_psb_private *dev_priv = dev->dev_private;
  453. if (WARN(!tc35876x_client, "%s called before probe", __func__))
  454. return;
  455. dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
  456. pdata = dev_get_platdata(&tc35876x_client->dev);
  457. if (pdata->gpio_panel_vadd != -1) {
  458. gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1);
  459. msleep(260);
  460. }
  461. if (cmi_lcd_i2c_client) {
  462. int ret;
  463. dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n");
  464. /* Bit 4 is average_saving. Setting it to 1, the brightness is
  465. * referenced to the average of the frame content. 0 means
  466. * reference to the maximum of frame contents. Bits 3:0 are
  467. * allow_distort. When set to a nonzero value, all color values
  468. * between 255-allow_distort*2 and 255 are mapped to the
  469. * 255-allow_distort*2 value.
  470. */
  471. ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
  472. PANEL_ALLOW_DISTORT, 0x10);
  473. if (ret < 0)
  474. dev_err(&cmi_lcd_i2c_client->dev,
  475. "i2c write failed (%d)\n", ret);
  476. ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
  477. PANEL_BYPASS_PWMI, 0);
  478. if (ret < 0)
  479. dev_err(&cmi_lcd_i2c_client->dev,
  480. "i2c write failed (%d)\n", ret);
  481. /* Set minimum brightness value - this is tunable */
  482. ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
  483. PANEL_PWM_MIN, 0x35);
  484. if (ret < 0)
  485. dev_err(&cmi_lcd_i2c_client->dev,
  486. "i2c write failed (%d)\n", ret);
  487. }
  488. if (pdata->gpio_panel_bl_en != -1)
  489. gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 1);
  490. tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
  491. }
  492. static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev)
  493. {
  494. struct drm_display_mode *mode;
  495. dev_dbg(&dev->pdev->dev, "%s\n", __func__);
  496. mode = kzalloc(sizeof(*mode), GFP_KERNEL);
  497. if (!mode)
  498. return NULL;
  499. /* FIXME: do this properly. */
  500. mode->hdisplay = 1280;
  501. mode->vdisplay = 800;
  502. mode->hsync_start = 1360;
  503. mode->hsync_end = 1400;
  504. mode->htotal = 1440;
  505. mode->vsync_start = 814;
  506. mode->vsync_end = 824;
  507. mode->vtotal = 838;
  508. mode->clock = 33324 << 1;
  509. dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay);
  510. dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay);
  511. dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start);
  512. dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end);
  513. dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal);
  514. dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start);
  515. dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end);
  516. dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal);
  517. dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock);
  518. drm_mode_set_name(mode);
  519. drm_mode_set_crtcinfo(mode, 0);
  520. mode->type |= DRM_MODE_TYPE_PREFERRED;
  521. return mode;
  522. }
  523. /* DV1 Active area 216.96 x 135.6 mm */
  524. #define DV1_PANEL_WIDTH 217
  525. #define DV1_PANEL_HEIGHT 136
  526. static int tc35876x_get_panel_info(struct drm_device *dev, int pipe,
  527. struct panel_info *pi)
  528. {
  529. if (!dev || !pi)
  530. return -EINVAL;
  531. pi->width_mm = DV1_PANEL_WIDTH;
  532. pi->height_mm = DV1_PANEL_HEIGHT;
  533. return 0;
  534. }
  535. static int tc35876x_bridge_probe(struct i2c_client *client,
  536. const struct i2c_device_id *id)
  537. {
  538. struct tc35876x_platform_data *pdata;
  539. dev_info(&client->dev, "%s\n", __func__);
  540. if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  541. dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
  542. __func__);
  543. return -ENODEV;
  544. }
  545. pdata = dev_get_platdata(&client->dev);
  546. if (!pdata) {
  547. dev_err(&client->dev, "%s: no platform data\n", __func__);
  548. return -ENODEV;
  549. }
  550. if (pdata->gpio_bridge_reset != -1) {
  551. gpio_request(pdata->gpio_bridge_reset, "tc35876x bridge reset");
  552. gpio_direction_output(pdata->gpio_bridge_reset, 0);
  553. }
  554. if (pdata->gpio_panel_bl_en != -1) {
  555. gpio_request(pdata->gpio_panel_bl_en, "tc35876x panel bl en");
  556. gpio_direction_output(pdata->gpio_panel_bl_en, 0);
  557. }
  558. if (pdata->gpio_panel_vadd != -1) {
  559. gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd");
  560. gpio_direction_output(pdata->gpio_panel_vadd, 0);
  561. }
  562. tc35876x_client = client;
  563. return 0;
  564. }
  565. static int tc35876x_bridge_remove(struct i2c_client *client)
  566. {
  567. struct tc35876x_platform_data *pdata = dev_get_platdata(&client->dev);
  568. dev_dbg(&client->dev, "%s\n", __func__);
  569. if (pdata->gpio_bridge_reset != -1)
  570. gpio_free(pdata->gpio_bridge_reset);
  571. if (pdata->gpio_panel_bl_en != -1)
  572. gpio_free(pdata->gpio_panel_bl_en);
  573. if (pdata->gpio_panel_vadd != -1)
  574. gpio_free(pdata->gpio_panel_vadd);
  575. tc35876x_client = NULL;
  576. return 0;
  577. }
  578. static const struct i2c_device_id tc35876x_bridge_id[] = {
  579. { "i2c_disp_brig", 0 },
  580. { }
  581. };
  582. MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
  583. static struct i2c_driver tc35876x_bridge_i2c_driver = {
  584. .driver = {
  585. .name = "i2c_disp_brig",
  586. },
  587. .id_table = tc35876x_bridge_id,
  588. .probe = tc35876x_bridge_probe,
  589. .remove = tc35876x_bridge_remove,
  590. };
  591. /* LCD panel I2C */
  592. static int cmi_lcd_i2c_probe(struct i2c_client *client,
  593. const struct i2c_device_id *id)
  594. {
  595. dev_info(&client->dev, "%s\n", __func__);
  596. if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  597. dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
  598. __func__);
  599. return -ENODEV;
  600. }
  601. cmi_lcd_i2c_client = client;
  602. return 0;
  603. }
  604. static int cmi_lcd_i2c_remove(struct i2c_client *client)
  605. {
  606. dev_dbg(&client->dev, "%s\n", __func__);
  607. cmi_lcd_i2c_client = NULL;
  608. return 0;
  609. }
  610. static const struct i2c_device_id cmi_lcd_i2c_id[] = {
  611. { "cmi-lcd", 0 },
  612. { }
  613. };
  614. MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id);
  615. static struct i2c_driver cmi_lcd_i2c_driver = {
  616. .driver = {
  617. .name = "cmi-lcd",
  618. },
  619. .id_table = cmi_lcd_i2c_id,
  620. .probe = cmi_lcd_i2c_probe,
  621. .remove = cmi_lcd_i2c_remove,
  622. };
  623. /* HACK to create I2C device while it's not created by platform code */
  624. #define CMI_LCD_I2C_ADAPTER 2
  625. #define CMI_LCD_I2C_ADDR 0x60
  626. static int cmi_lcd_hack_create_device(void)
  627. {
  628. struct i2c_adapter *adapter;
  629. struct i2c_client *client;
  630. struct i2c_board_info info = {
  631. .type = "cmi-lcd",
  632. .addr = CMI_LCD_I2C_ADDR,
  633. };
  634. pr_debug("%s\n", __func__);
  635. adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER);
  636. if (!adapter) {
  637. pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
  638. CMI_LCD_I2C_ADAPTER);
  639. return -EINVAL;
  640. }
  641. client = i2c_new_device(adapter, &info);
  642. if (!client) {
  643. pr_err("%s: i2c_new_device() failed\n", __func__);
  644. i2c_put_adapter(adapter);
  645. return -EINVAL;
  646. }
  647. return 0;
  648. }
  649. static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = {
  650. .dpms = mdfld_dsi_dpi_dpms,
  651. .mode_fixup = mdfld_dsi_dpi_mode_fixup,
  652. .prepare = mdfld_dsi_dpi_prepare,
  653. .mode_set = mdfld_dsi_dpi_mode_set,
  654. .commit = mdfld_dsi_dpi_commit,
  655. };
  656. static const struct drm_encoder_funcs tc35876x_encoder_funcs = {
  657. .destroy = drm_encoder_cleanup,
  658. };
  659. const struct panel_funcs mdfld_tc35876x_funcs = {
  660. .encoder_funcs = &tc35876x_encoder_funcs,
  661. .encoder_helper_funcs = &tc35876x_encoder_helper_funcs,
  662. .get_config_mode = tc35876x_get_config_mode,
  663. .get_panel_info = tc35876x_get_panel_info,
  664. };
  665. void tc35876x_init(struct drm_device *dev)
  666. {
  667. int r;
  668. dev_dbg(&dev->pdev->dev, "%s\n", __func__);
  669. cmi_lcd_hack_create_device();
  670. r = i2c_add_driver(&cmi_lcd_i2c_driver);
  671. if (r < 0)
  672. dev_err(&dev->pdev->dev,
  673. "%s: i2c_add_driver() for %s failed (%d)\n",
  674. __func__, cmi_lcd_i2c_driver.driver.name, r);
  675. r = i2c_add_driver(&tc35876x_bridge_i2c_driver);
  676. if (r < 0)
  677. dev_err(&dev->pdev->dev,
  678. "%s: i2c_add_driver() for %s failed (%d)\n",
  679. __func__, tc35876x_bridge_i2c_driver.driver.name, r);
  680. tc35876x_brightness_init(dev);
  681. }
  682. void tc35876x_exit(void)
  683. {
  684. pr_debug("%s\n", __func__);
  685. i2c_del_driver(&tc35876x_bridge_i2c_driver);
  686. if (cmi_lcd_i2c_client)
  687. i2c_del_driver(&cmi_lcd_i2c_driver);
  688. }