panel-picodlp.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /*
  2. * picodlp panel driver
  3. * picodlp_i2c_driver: i2c_client driver
  4. *
  5. * Copyright (C) 2009-2011 Texas Instruments
  6. * Author: Mythri P K <mythripk@ti.com>
  7. * Mayuresh Janorkar <mayur@ti.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License version 2 as published by
  11. * the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  16. * more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along with
  19. * this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include <linux/module.h>
  22. #include <linux/input.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/interrupt.h>
  25. #include <linux/firmware.h>
  26. #include <linux/slab.h>
  27. #include <linux/mutex.h>
  28. #include <linux/i2c.h>
  29. #include <linux/delay.h>
  30. #include <linux/gpio.h>
  31. #include <video/omapdss.h>
  32. #include <video/omap-panel-picodlp.h>
  33. #include "panel-picodlp.h"
  34. struct picodlp_data {
  35. struct mutex lock;
  36. struct i2c_client *picodlp_i2c_client;
  37. };
  38. static struct i2c_board_info picodlp_i2c_board_info = {
  39. I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b),
  40. };
  41. struct picodlp_i2c_data {
  42. struct mutex xfer_lock;
  43. };
  44. static struct i2c_device_id picodlp_i2c_id[] = {
  45. { "picodlp_i2c_driver", 0 },
  46. { }
  47. };
  48. struct picodlp_i2c_command {
  49. u8 reg;
  50. u32 value;
  51. };
  52. static struct omap_video_timings pico_ls_timings = {
  53. .x_res = 864,
  54. .y_res = 480,
  55. .hsw = 7,
  56. .hfp = 11,
  57. .hbp = 7,
  58. .pixel_clock = 19200,
  59. .vsw = 2,
  60. .vfp = 3,
  61. .vbp = 14,
  62. .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
  63. .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
  64. .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
  65. .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
  66. .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
  67. };
  68. static inline struct picodlp_panel_data
  69. *get_panel_data(const struct omap_dss_device *dssdev)
  70. {
  71. return (struct picodlp_panel_data *) dssdev->data;
  72. }
  73. static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg)
  74. {
  75. u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4];
  76. struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
  77. struct i2c_msg msg[2];
  78. mutex_lock(&picodlp_i2c_data->xfer_lock);
  79. msg[0].addr = client->addr;
  80. msg[0].flags = 0;
  81. msg[0].len = 2;
  82. msg[0].buf = read_cmd;
  83. msg[1].addr = client->addr;
  84. msg[1].flags = I2C_M_RD;
  85. msg[1].len = 4;
  86. msg[1].buf = data;
  87. i2c_transfer(client->adapter, msg, 2);
  88. mutex_unlock(&picodlp_i2c_data->xfer_lock);
  89. return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24));
  90. }
  91. static int picodlp_i2c_write_block(struct i2c_client *client,
  92. u8 *data, int len)
  93. {
  94. struct i2c_msg msg;
  95. int i, r, msg_count = 1;
  96. struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
  97. if (len < 1 || len > 32) {
  98. dev_err(&client->dev,
  99. "too long syn_write_block len %d\n", len);
  100. return -EIO;
  101. }
  102. mutex_lock(&picodlp_i2c_data->xfer_lock);
  103. msg.addr = client->addr;
  104. msg.flags = 0;
  105. msg.len = len;
  106. msg.buf = data;
  107. r = i2c_transfer(client->adapter, &msg, msg_count);
  108. mutex_unlock(&picodlp_i2c_data->xfer_lock);
  109. /*
  110. * i2c_transfer returns:
  111. * number of messages sent in case of success
  112. * a negative error number in case of failure
  113. */
  114. if (r != msg_count)
  115. goto err;
  116. /* In case of success */
  117. for (i = 0; i < len; i++)
  118. dev_dbg(&client->dev,
  119. "addr %x bw 0x%02x[%d]: 0x%02x\n",
  120. client->addr, data[0] + i, i, data[i]);
  121. return 0;
  122. err:
  123. dev_err(&client->dev, "picodlp_i2c_write error\n");
  124. return r;
  125. }
  126. static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value)
  127. {
  128. u8 data[5];
  129. int i;
  130. data[0] = reg;
  131. for (i = 1; i < 5; i++)
  132. data[i] = (value >> (32 - (i) * 8)) & 0xFF;
  133. return picodlp_i2c_write_block(client, data, 5);
  134. }
  135. static int picodlp_i2c_write_array(struct i2c_client *client,
  136. const struct picodlp_i2c_command commands[],
  137. int count)
  138. {
  139. int i, r = 0;
  140. for (i = 0; i < count; i++) {
  141. r = picodlp_i2c_write(client, commands[i].reg,
  142. commands[i].value);
  143. if (r)
  144. return r;
  145. }
  146. return r;
  147. }
  148. static int picodlp_wait_for_dma_done(struct i2c_client *client)
  149. {
  150. u8 trial = 100;
  151. do {
  152. msleep(1);
  153. if (!trial--)
  154. return -ETIMEDOUT;
  155. } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS);
  156. return 0;
  157. }
  158. /**
  159. * picodlp_i2c_init: i2c_initialization routine
  160. * client: i2c_client for communication
  161. *
  162. * return
  163. * 0 : Success, no error
  164. * error code : Failure
  165. */
  166. static int picodlp_i2c_init(struct i2c_client *client)
  167. {
  168. int r;
  169. static const struct picodlp_i2c_command init_cmd_set1[] = {
  170. {SOFT_RESET, 1},
  171. {DMD_PARK_TRIGGER, 1},
  172. {MISC_REG, 5},
  173. {SEQ_CONTROL, 0},
  174. {SEQ_VECTOR, 0x100},
  175. {DMD_BLOCK_COUNT, 7},
  176. {DMD_VCC_CONTROL, 0x109},
  177. {DMD_PARK_PULSE_COUNT, 0xA},
  178. {DMD_PARK_PULSE_WIDTH, 0xB},
  179. {DMD_PARK_DELAY, 0x2ED},
  180. {DMD_SHADOW_ENABLE, 0},
  181. {FLASH_OPCODE, 0xB},
  182. {FLASH_DUMMY_BYTES, 1},
  183. {FLASH_ADDR_BYTES, 3},
  184. {PBC_CONTROL, 0},
  185. {FLASH_START_ADDR, CMT_LUT_0_START_ADDR},
  186. {FLASH_READ_BYTES, CMT_LUT_0_SIZE},
  187. {CMT_SPLASH_LUT_START_ADDR, 0},
  188. {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL},
  189. {PBC_CONTROL, 1},
  190. };
  191. static const struct picodlp_i2c_command init_cmd_set2[] = {
  192. {PBC_CONTROL, 0},
  193. {CMT_SPLASH_LUT_DEST_SELECT, 0},
  194. {PBC_CONTROL, 0},
  195. {FLASH_START_ADDR, SEQUENCE_0_START_ADDR},
  196. {FLASH_READ_BYTES, SEQUENCE_0_SIZE},
  197. {SEQ_RESET_LUT_START_ADDR, 0},
  198. {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT},
  199. {PBC_CONTROL, 1},
  200. };
  201. static const struct picodlp_i2c_command init_cmd_set3[] = {
  202. {PBC_CONTROL, 0},
  203. {SEQ_RESET_LUT_DEST_SELECT, 0},
  204. {PBC_CONTROL, 0},
  205. {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR},
  206. {FLASH_READ_BYTES, DRC_TABLE_0_SIZE},
  207. {SEQ_RESET_LUT_START_ADDR, 0},
  208. {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL},
  209. {PBC_CONTROL, 1},
  210. };
  211. static const struct picodlp_i2c_command init_cmd_set4[] = {
  212. {PBC_CONTROL, 0},
  213. {SEQ_RESET_LUT_DEST_SELECT, 0},
  214. {SDC_ENABLE, 1},
  215. {AGC_CTRL, 7},
  216. {CCA_C1A, 0x100},
  217. {CCA_C1B, 0x0},
  218. {CCA_C1C, 0x0},
  219. {CCA_C2A, 0x0},
  220. {CCA_C2B, 0x100},
  221. {CCA_C2C, 0x0},
  222. {CCA_C3A, 0x0},
  223. {CCA_C3B, 0x0},
  224. {CCA_C3C, 0x100},
  225. {CCA_C7A, 0x100},
  226. {CCA_C7B, 0x100},
  227. {CCA_C7C, 0x100},
  228. {CCA_ENABLE, 1},
  229. {CPU_IF_MODE, 1},
  230. {SHORT_FLIP, 1},
  231. {CURTAIN_CONTROL, 0},
  232. {DMD_PARK_TRIGGER, 0},
  233. {R_DRIVE_CURRENT, 0x298},
  234. {G_DRIVE_CURRENT, 0x298},
  235. {B_DRIVE_CURRENT, 0x298},
  236. {RGB_DRIVER_ENABLE, 7},
  237. {SEQ_CONTROL, 0},
  238. {ACTGEN_CONTROL, 0x10},
  239. {SEQUENCE_MODE, SEQ_LOCK},
  240. {DATA_FORMAT, RGB888},
  241. {INPUT_RESOLUTION, WVGA_864_LANDSCAPE},
  242. {INPUT_SOURCE, PARALLEL_RGB},
  243. {CPU_IF_SYNC_METHOD, 1},
  244. {SEQ_CONTROL, 1}
  245. };
  246. r = picodlp_i2c_write_array(client, init_cmd_set1,
  247. ARRAY_SIZE(init_cmd_set1));
  248. if (r)
  249. return r;
  250. r = picodlp_wait_for_dma_done(client);
  251. if (r)
  252. return r;
  253. r = picodlp_i2c_write_array(client, init_cmd_set2,
  254. ARRAY_SIZE(init_cmd_set2));
  255. if (r)
  256. return r;
  257. r = picodlp_wait_for_dma_done(client);
  258. if (r)
  259. return r;
  260. r = picodlp_i2c_write_array(client, init_cmd_set3,
  261. ARRAY_SIZE(init_cmd_set3));
  262. if (r)
  263. return r;
  264. r = picodlp_wait_for_dma_done(client);
  265. if (r)
  266. return r;
  267. r = picodlp_i2c_write_array(client, init_cmd_set4,
  268. ARRAY_SIZE(init_cmd_set4));
  269. if (r)
  270. return r;
  271. return 0;
  272. }
  273. static int picodlp_i2c_probe(struct i2c_client *client,
  274. const struct i2c_device_id *id)
  275. {
  276. struct picodlp_i2c_data *picodlp_i2c_data;
  277. picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL);
  278. if (!picodlp_i2c_data)
  279. return -ENOMEM;
  280. mutex_init(&picodlp_i2c_data->xfer_lock);
  281. i2c_set_clientdata(client, picodlp_i2c_data);
  282. return 0;
  283. }
  284. static int picodlp_i2c_remove(struct i2c_client *client)
  285. {
  286. struct picodlp_i2c_data *picodlp_i2c_data =
  287. i2c_get_clientdata(client);
  288. kfree(picodlp_i2c_data);
  289. return 0;
  290. }
  291. static struct i2c_driver picodlp_i2c_driver = {
  292. .driver = {
  293. .name = "picodlp_i2c_driver",
  294. },
  295. .probe = picodlp_i2c_probe,
  296. .remove = picodlp_i2c_remove,
  297. .id_table = picodlp_i2c_id,
  298. };
  299. static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
  300. {
  301. int r, trial = 100;
  302. struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
  303. struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
  304. if (dssdev->platform_enable) {
  305. r = dssdev->platform_enable(dssdev);
  306. if (r)
  307. return r;
  308. }
  309. gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
  310. msleep(1);
  311. gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
  312. while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) {
  313. if (!trial--) {
  314. dev_err(&dssdev->dev, "emu_done signal not"
  315. " going high\n");
  316. return -ETIMEDOUT;
  317. }
  318. msleep(5);
  319. }
  320. /*
  321. * As per dpp2600 programming guide,
  322. * it is required to sleep for 1000ms after emu_done signal goes high
  323. * then only i2c commands can be successfully sent to dpp2600
  324. */
  325. msleep(1000);
  326. omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
  327. omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
  328. r = omapdss_dpi_display_enable(dssdev);
  329. if (r) {
  330. dev_err(&dssdev->dev, "failed to enable DPI\n");
  331. goto err1;
  332. }
  333. r = picodlp_i2c_init(picod->picodlp_i2c_client);
  334. if (r)
  335. goto err;
  336. dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
  337. return r;
  338. err:
  339. omapdss_dpi_display_disable(dssdev);
  340. err1:
  341. if (dssdev->platform_disable)
  342. dssdev->platform_disable(dssdev);
  343. return r;
  344. }
  345. static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
  346. {
  347. struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
  348. omapdss_dpi_display_disable(dssdev);
  349. gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
  350. gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
  351. if (dssdev->platform_disable)
  352. dssdev->platform_disable(dssdev);
  353. }
  354. static int picodlp_panel_probe(struct omap_dss_device *dssdev)
  355. {
  356. struct picodlp_data *picod;
  357. struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
  358. struct i2c_adapter *adapter;
  359. struct i2c_client *picodlp_i2c_client;
  360. int r = 0, picodlp_adapter_id;
  361. dssdev->panel.timings = pico_ls_timings;
  362. picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
  363. if (!picod)
  364. return -ENOMEM;
  365. mutex_init(&picod->lock);
  366. picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id;
  367. adapter = i2c_get_adapter(picodlp_adapter_id);
  368. if (!adapter) {
  369. dev_err(&dssdev->dev, "can't get i2c adapter\n");
  370. r = -ENODEV;
  371. goto err;
  372. }
  373. picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
  374. if (!picodlp_i2c_client) {
  375. dev_err(&dssdev->dev, "can't add i2c device::"
  376. " picodlp_i2c_client is NULL\n");
  377. r = -ENODEV;
  378. goto err;
  379. }
  380. picod->picodlp_i2c_client = picodlp_i2c_client;
  381. dev_set_drvdata(&dssdev->dev, picod);
  382. return r;
  383. err:
  384. kfree(picod);
  385. return r;
  386. }
  387. static void picodlp_panel_remove(struct omap_dss_device *dssdev)
  388. {
  389. struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
  390. i2c_unregister_device(picod->picodlp_i2c_client);
  391. dev_set_drvdata(&dssdev->dev, NULL);
  392. dev_dbg(&dssdev->dev, "removing picodlp panel\n");
  393. kfree(picod);
  394. }
  395. static int picodlp_panel_enable(struct omap_dss_device *dssdev)
  396. {
  397. struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
  398. int r;
  399. dev_dbg(&dssdev->dev, "enabling picodlp panel\n");
  400. mutex_lock(&picod->lock);
  401. if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
  402. mutex_unlock(&picod->lock);
  403. return -EINVAL;
  404. }
  405. r = picodlp_panel_power_on(dssdev);
  406. mutex_unlock(&picod->lock);
  407. return r;
  408. }
  409. static void picodlp_panel_disable(struct omap_dss_device *dssdev)
  410. {
  411. struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
  412. mutex_lock(&picod->lock);
  413. /* Turn off DLP Power */
  414. if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
  415. picodlp_panel_power_off(dssdev);
  416. dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
  417. mutex_unlock(&picod->lock);
  418. dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
  419. }
  420. static void picodlp_get_resolution(struct omap_dss_device *dssdev,
  421. u16 *xres, u16 *yres)
  422. {
  423. *xres = dssdev->panel.timings.x_res;
  424. *yres = dssdev->panel.timings.y_res;
  425. }
  426. static struct omap_dss_driver picodlp_driver = {
  427. .probe = picodlp_panel_probe,
  428. .remove = picodlp_panel_remove,
  429. .enable = picodlp_panel_enable,
  430. .disable = picodlp_panel_disable,
  431. .get_resolution = picodlp_get_resolution,
  432. .driver = {
  433. .name = "picodlp_panel",
  434. .owner = THIS_MODULE,
  435. },
  436. };
  437. static int __init picodlp_init(void)
  438. {
  439. int r = 0;
  440. r = i2c_add_driver(&picodlp_i2c_driver);
  441. if (r) {
  442. printk(KERN_WARNING "picodlp_i2c_driver" \
  443. " registration failed\n");
  444. return r;
  445. }
  446. r = omap_dss_register_driver(&picodlp_driver);
  447. if (r)
  448. i2c_del_driver(&picodlp_i2c_driver);
  449. return r;
  450. }
  451. static void __exit picodlp_exit(void)
  452. {
  453. i2c_del_driver(&picodlp_i2c_driver);
  454. omap_dss_unregister_driver(&picodlp_driver);
  455. }
  456. module_init(picodlp_init);
  457. module_exit(picodlp_exit);
  458. MODULE_AUTHOR("Mythri P K <mythripk@ti.com>");
  459. MODULE_DESCRIPTION("picodlp driver");
  460. MODULE_LICENSE("GPL");