panel-sony-acx565akm.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  1. /*
  2. * Sony ACX565AKM LCD Panel driver
  3. *
  4. * Copyright (C) 2010 Nokia Corporation
  5. *
  6. * Original Driver Author: Imre Deak <imre.deak@nokia.com>
  7. * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com>
  8. * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License version 2 as published by
  12. * the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  17. * more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along with
  20. * this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. #include <linux/kernel.h>
  23. #include <linux/module.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/delay.h>
  26. #include <linux/spi/spi.h>
  27. #include <linux/jiffies.h>
  28. #include <linux/sched.h>
  29. #include <linux/backlight.h>
  30. #include <linux/fb.h>
  31. #include <linux/gpio.h>
  32. #include <video/omapdss.h>
  33. #include <video/omap-panel-data.h>
  34. #define MIPID_CMD_READ_DISP_ID 0x04
  35. #define MIPID_CMD_READ_RED 0x06
  36. #define MIPID_CMD_READ_GREEN 0x07
  37. #define MIPID_CMD_READ_BLUE 0x08
  38. #define MIPID_CMD_READ_DISP_STATUS 0x09
  39. #define MIPID_CMD_RDDSDR 0x0F
  40. #define MIPID_CMD_SLEEP_IN 0x10
  41. #define MIPID_CMD_SLEEP_OUT 0x11
  42. #define MIPID_CMD_DISP_OFF 0x28
  43. #define MIPID_CMD_DISP_ON 0x29
  44. #define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
  45. #define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
  46. #define MIPID_CMD_WRITE_CTRL_DISP 0x53
  47. #define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
  48. #define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
  49. #define CTRL_DISP_BACKLIGHT_ON (1 << 2)
  50. #define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
  51. #define MIPID_CMD_READ_CTRL_DISP 0x54
  52. #define MIPID_CMD_WRITE_CABC 0x55
  53. #define MIPID_CMD_READ_CABC 0x56
  54. #define MIPID_VER_LPH8923 3
  55. #define MIPID_VER_LS041Y3 4
  56. #define MIPID_VER_L4F00311 8
  57. #define MIPID_VER_ACX565AKM 9
  58. struct panel_drv_data {
  59. struct omap_dss_device dssdev;
  60. struct omap_dss_device *in;
  61. int reset_gpio;
  62. int datapairs;
  63. struct omap_video_timings videomode;
  64. char *name;
  65. int enabled;
  66. int model;
  67. int revision;
  68. u8 display_id[3];
  69. unsigned has_bc:1;
  70. unsigned has_cabc:1;
  71. unsigned cabc_mode;
  72. unsigned long hw_guard_end; /* next value of jiffies
  73. when we can issue the
  74. next sleep in/out command */
  75. unsigned long hw_guard_wait; /* max guard time in jiffies */
  76. struct spi_device *spi;
  77. struct mutex mutex;
  78. struct backlight_device *bl_dev;
  79. };
  80. static const struct omap_video_timings acx565akm_panel_timings = {
  81. .x_res = 800,
  82. .y_res = 480,
  83. .pixel_clock = 24000,
  84. .hfp = 28,
  85. .hsw = 4,
  86. .hbp = 24,
  87. .vfp = 3,
  88. .vsw = 3,
  89. .vbp = 4,
  90. .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
  91. .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
  92. .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
  93. .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
  94. .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
  95. };
  96. #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
  97. static void acx565akm_transfer(struct panel_drv_data *ddata, int cmd,
  98. const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
  99. {
  100. struct spi_message m;
  101. struct spi_transfer *x, xfer[5];
  102. int r;
  103. BUG_ON(ddata->spi == NULL);
  104. spi_message_init(&m);
  105. memset(xfer, 0, sizeof(xfer));
  106. x = &xfer[0];
  107. cmd &= 0xff;
  108. x->tx_buf = &cmd;
  109. x->bits_per_word = 9;
  110. x->len = 2;
  111. if (rlen > 1 && wlen == 0) {
  112. /*
  113. * Between the command and the response data there is a
  114. * dummy clock cycle. Add an extra bit after the command
  115. * word to account for this.
  116. */
  117. x->bits_per_word = 10;
  118. cmd <<= 1;
  119. }
  120. spi_message_add_tail(x, &m);
  121. if (wlen) {
  122. x++;
  123. x->tx_buf = wbuf;
  124. x->len = wlen;
  125. x->bits_per_word = 9;
  126. spi_message_add_tail(x, &m);
  127. }
  128. if (rlen) {
  129. x++;
  130. x->rx_buf = rbuf;
  131. x->len = rlen;
  132. spi_message_add_tail(x, &m);
  133. }
  134. r = spi_sync(ddata->spi, &m);
  135. if (r < 0)
  136. dev_dbg(&ddata->spi->dev, "spi_sync %d\n", r);
  137. }
  138. static inline void acx565akm_cmd(struct panel_drv_data *ddata, int cmd)
  139. {
  140. acx565akm_transfer(ddata, cmd, NULL, 0, NULL, 0);
  141. }
  142. static inline void acx565akm_write(struct panel_drv_data *ddata,
  143. int reg, const u8 *buf, int len)
  144. {
  145. acx565akm_transfer(ddata, reg, buf, len, NULL, 0);
  146. }
  147. static inline void acx565akm_read(struct panel_drv_data *ddata,
  148. int reg, u8 *buf, int len)
  149. {
  150. acx565akm_transfer(ddata, reg, NULL, 0, buf, len);
  151. }
  152. static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
  153. {
  154. ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
  155. ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
  156. }
  157. static void hw_guard_wait(struct panel_drv_data *ddata)
  158. {
  159. unsigned long wait = ddata->hw_guard_end - jiffies;
  160. if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
  161. set_current_state(TASK_UNINTERRUPTIBLE);
  162. schedule_timeout(wait);
  163. }
  164. }
  165. static void set_sleep_mode(struct panel_drv_data *ddata, int on)
  166. {
  167. int cmd;
  168. if (on)
  169. cmd = MIPID_CMD_SLEEP_IN;
  170. else
  171. cmd = MIPID_CMD_SLEEP_OUT;
  172. /*
  173. * We have to keep 120msec between sleep in/out commands.
  174. * (8.2.15, 8.2.16).
  175. */
  176. hw_guard_wait(ddata);
  177. acx565akm_cmd(ddata, cmd);
  178. hw_guard_start(ddata, 120);
  179. }
  180. static void set_display_state(struct panel_drv_data *ddata, int enabled)
  181. {
  182. int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
  183. acx565akm_cmd(ddata, cmd);
  184. }
  185. static int panel_enabled(struct panel_drv_data *ddata)
  186. {
  187. u32 disp_status;
  188. int enabled;
  189. acx565akm_read(ddata, MIPID_CMD_READ_DISP_STATUS,
  190. (u8 *)&disp_status, 4);
  191. disp_status = __be32_to_cpu(disp_status);
  192. enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
  193. dev_dbg(&ddata->spi->dev,
  194. "LCD panel %senabled by bootloader (status 0x%04x)\n",
  195. enabled ? "" : "not ", disp_status);
  196. return enabled;
  197. }
  198. static int panel_detect(struct panel_drv_data *ddata)
  199. {
  200. acx565akm_read(ddata, MIPID_CMD_READ_DISP_ID, ddata->display_id, 3);
  201. dev_dbg(&ddata->spi->dev, "MIPI display ID: %02x%02x%02x\n",
  202. ddata->display_id[0],
  203. ddata->display_id[1],
  204. ddata->display_id[2]);
  205. switch (ddata->display_id[0]) {
  206. case 0x10:
  207. ddata->model = MIPID_VER_ACX565AKM;
  208. ddata->name = "acx565akm";
  209. ddata->has_bc = 1;
  210. ddata->has_cabc = 1;
  211. break;
  212. case 0x29:
  213. ddata->model = MIPID_VER_L4F00311;
  214. ddata->name = "l4f00311";
  215. break;
  216. case 0x45:
  217. ddata->model = MIPID_VER_LPH8923;
  218. ddata->name = "lph8923";
  219. break;
  220. case 0x83:
  221. ddata->model = MIPID_VER_LS041Y3;
  222. ddata->name = "ls041y3";
  223. break;
  224. default:
  225. ddata->name = "unknown";
  226. dev_err(&ddata->spi->dev, "invalid display ID\n");
  227. return -ENODEV;
  228. }
  229. ddata->revision = ddata->display_id[1];
  230. dev_info(&ddata->spi->dev, "omapfb: %s rev %02x LCD detected\n",
  231. ddata->name, ddata->revision);
  232. return 0;
  233. }
  234. /*----------------------Backlight Control-------------------------*/
  235. static void enable_backlight_ctrl(struct panel_drv_data *ddata, int enable)
  236. {
  237. u16 ctrl;
  238. acx565akm_read(ddata, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
  239. if (enable) {
  240. ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
  241. CTRL_DISP_BACKLIGHT_ON;
  242. } else {
  243. ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
  244. CTRL_DISP_BACKLIGHT_ON);
  245. }
  246. ctrl |= 1 << 8;
  247. acx565akm_write(ddata, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
  248. }
  249. static void set_cabc_mode(struct panel_drv_data *ddata, unsigned mode)
  250. {
  251. u16 cabc_ctrl;
  252. ddata->cabc_mode = mode;
  253. if (!ddata->enabled)
  254. return;
  255. cabc_ctrl = 0;
  256. acx565akm_read(ddata, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
  257. cabc_ctrl &= ~3;
  258. cabc_ctrl |= (1 << 8) | (mode & 3);
  259. acx565akm_write(ddata, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
  260. }
  261. static unsigned get_cabc_mode(struct panel_drv_data *ddata)
  262. {
  263. return ddata->cabc_mode;
  264. }
  265. static unsigned get_hw_cabc_mode(struct panel_drv_data *ddata)
  266. {
  267. u8 cabc_ctrl;
  268. acx565akm_read(ddata, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
  269. return cabc_ctrl & 3;
  270. }
  271. static void acx565akm_set_brightness(struct panel_drv_data *ddata, int level)
  272. {
  273. int bv;
  274. bv = level | (1 << 8);
  275. acx565akm_write(ddata, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
  276. if (level)
  277. enable_backlight_ctrl(ddata, 1);
  278. else
  279. enable_backlight_ctrl(ddata, 0);
  280. }
  281. static int acx565akm_get_actual_brightness(struct panel_drv_data *ddata)
  282. {
  283. u8 bv;
  284. acx565akm_read(ddata, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
  285. return bv;
  286. }
  287. static int acx565akm_bl_update_status(struct backlight_device *dev)
  288. {
  289. struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
  290. int r;
  291. int level;
  292. dev_dbg(&ddata->spi->dev, "%s\n", __func__);
  293. mutex_lock(&ddata->mutex);
  294. if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
  295. dev->props.power == FB_BLANK_UNBLANK)
  296. level = dev->props.brightness;
  297. else
  298. level = 0;
  299. r = 0;
  300. if (ddata->has_bc)
  301. acx565akm_set_brightness(ddata, level);
  302. else
  303. r = -ENODEV;
  304. mutex_unlock(&ddata->mutex);
  305. return r;
  306. }
  307. static int acx565akm_bl_get_intensity(struct backlight_device *dev)
  308. {
  309. struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
  310. dev_dbg(&dev->dev, "%s\n", __func__);
  311. if (!ddata->has_bc)
  312. return -ENODEV;
  313. if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
  314. dev->props.power == FB_BLANK_UNBLANK) {
  315. if (ddata->has_bc)
  316. return acx565akm_get_actual_brightness(ddata);
  317. else
  318. return dev->props.brightness;
  319. }
  320. return 0;
  321. }
  322. static const struct backlight_ops acx565akm_bl_ops = {
  323. .get_brightness = acx565akm_bl_get_intensity,
  324. .update_status = acx565akm_bl_update_status,
  325. };
  326. /*--------------------Auto Brightness control via Sysfs---------------------*/
  327. static const char * const cabc_modes[] = {
  328. "off", /* always used when CABC is not supported */
  329. "ui",
  330. "still-image",
  331. "moving-image",
  332. };
  333. static ssize_t show_cabc_mode(struct device *dev,
  334. struct device_attribute *attr,
  335. char *buf)
  336. {
  337. struct panel_drv_data *ddata = dev_get_drvdata(dev);
  338. const char *mode_str;
  339. int mode;
  340. int len;
  341. if (!ddata->has_cabc)
  342. mode = 0;
  343. else
  344. mode = get_cabc_mode(ddata);
  345. mode_str = "unknown";
  346. if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
  347. mode_str = cabc_modes[mode];
  348. len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
  349. return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
  350. }
  351. static ssize_t store_cabc_mode(struct device *dev,
  352. struct device_attribute *attr,
  353. const char *buf, size_t count)
  354. {
  355. struct panel_drv_data *ddata = dev_get_drvdata(dev);
  356. int i;
  357. for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
  358. const char *mode_str = cabc_modes[i];
  359. int cmp_len = strlen(mode_str);
  360. if (count > 0 && buf[count - 1] == '\n')
  361. count--;
  362. if (count != cmp_len)
  363. continue;
  364. if (strncmp(buf, mode_str, cmp_len) == 0)
  365. break;
  366. }
  367. if (i == ARRAY_SIZE(cabc_modes))
  368. return -EINVAL;
  369. if (!ddata->has_cabc && i != 0)
  370. return -EINVAL;
  371. mutex_lock(&ddata->mutex);
  372. set_cabc_mode(ddata, i);
  373. mutex_unlock(&ddata->mutex);
  374. return count;
  375. }
  376. static ssize_t show_cabc_available_modes(struct device *dev,
  377. struct device_attribute *attr,
  378. char *buf)
  379. {
  380. struct panel_drv_data *ddata = dev_get_drvdata(dev);
  381. int len;
  382. int i;
  383. if (!ddata->has_cabc)
  384. return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
  385. for (i = 0, len = 0;
  386. len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
  387. len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
  388. i ? " " : "", cabc_modes[i],
  389. i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
  390. return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
  391. }
  392. static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
  393. show_cabc_mode, store_cabc_mode);
  394. static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
  395. show_cabc_available_modes, NULL);
  396. static struct attribute *bldev_attrs[] = {
  397. &dev_attr_cabc_mode.attr,
  398. &dev_attr_cabc_available_modes.attr,
  399. NULL,
  400. };
  401. static struct attribute_group bldev_attr_group = {
  402. .attrs = bldev_attrs,
  403. };
  404. static int acx565akm_connect(struct omap_dss_device *dssdev)
  405. {
  406. struct panel_drv_data *ddata = to_panel_data(dssdev);
  407. struct omap_dss_device *in = ddata->in;
  408. int r;
  409. if (omapdss_device_is_connected(dssdev))
  410. return 0;
  411. r = in->ops.sdi->connect(in, dssdev);
  412. if (r)
  413. return r;
  414. return 0;
  415. }
  416. static void acx565akm_disconnect(struct omap_dss_device *dssdev)
  417. {
  418. struct panel_drv_data *ddata = to_panel_data(dssdev);
  419. struct omap_dss_device *in = ddata->in;
  420. if (!omapdss_device_is_connected(dssdev))
  421. return;
  422. in->ops.sdi->disconnect(in, dssdev);
  423. }
  424. static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
  425. {
  426. struct panel_drv_data *ddata = to_panel_data(dssdev);
  427. struct omap_dss_device *in = ddata->in;
  428. int r;
  429. dev_dbg(&ddata->spi->dev, "%s\n", __func__);
  430. in->ops.sdi->set_timings(in, &ddata->videomode);
  431. in->ops.sdi->set_datapairs(in, ddata->datapairs);
  432. r = in->ops.sdi->enable(in);
  433. if (r) {
  434. pr_err("%s sdi enable failed\n", __func__);
  435. return r;
  436. }
  437. /*FIXME tweak me */
  438. msleep(50);
  439. if (gpio_is_valid(ddata->reset_gpio))
  440. gpio_set_value(ddata->reset_gpio, 1);
  441. if (ddata->enabled) {
  442. dev_dbg(&ddata->spi->dev, "panel already enabled\n");
  443. return 0;
  444. }
  445. /*
  446. * We have to meet all the following delay requirements:
  447. * 1. tRW: reset pulse width 10usec (7.12.1)
  448. * 2. tRT: reset cancel time 5msec (7.12.1)
  449. * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
  450. * case (7.6.2)
  451. * 4. 120msec before the sleep out command (7.12.1)
  452. */
  453. msleep(120);
  454. set_sleep_mode(ddata, 0);
  455. ddata->enabled = 1;
  456. /* 5msec between sleep out and the next command. (8.2.16) */
  457. usleep_range(5000, 10000);
  458. set_display_state(ddata, 1);
  459. set_cabc_mode(ddata, ddata->cabc_mode);
  460. mutex_unlock(&ddata->mutex);
  461. return acx565akm_bl_update_status(ddata->bl_dev);
  462. }
  463. static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
  464. {
  465. struct panel_drv_data *ddata = to_panel_data(dssdev);
  466. struct omap_dss_device *in = ddata->in;
  467. dev_dbg(dssdev->dev, "%s\n", __func__);
  468. if (!ddata->enabled)
  469. return;
  470. set_display_state(ddata, 0);
  471. set_sleep_mode(ddata, 1);
  472. ddata->enabled = 0;
  473. /*
  474. * We have to provide PCLK,HS,VS signals for 2 frames (worst case
  475. * ~50msec) after sending the sleep in command and asserting the
  476. * reset signal. We probably could assert the reset w/o the delay
  477. * but we still delay to avoid possible artifacts. (7.6.1)
  478. */
  479. msleep(50);
  480. if (gpio_is_valid(ddata->reset_gpio))
  481. gpio_set_value(ddata->reset_gpio, 0);
  482. /* FIXME need to tweak this delay */
  483. msleep(100);
  484. in->ops.sdi->disable(in);
  485. }
  486. static int acx565akm_enable(struct omap_dss_device *dssdev)
  487. {
  488. struct panel_drv_data *ddata = to_panel_data(dssdev);
  489. int r;
  490. dev_dbg(dssdev->dev, "%s\n", __func__);
  491. if (!omapdss_device_is_connected(dssdev))
  492. return -ENODEV;
  493. if (omapdss_device_is_enabled(dssdev))
  494. return 0;
  495. mutex_lock(&ddata->mutex);
  496. r = acx565akm_panel_power_on(dssdev);
  497. mutex_unlock(&ddata->mutex);
  498. if (r)
  499. return r;
  500. dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
  501. return 0;
  502. }
  503. static void acx565akm_disable(struct omap_dss_device *dssdev)
  504. {
  505. struct panel_drv_data *ddata = to_panel_data(dssdev);
  506. dev_dbg(dssdev->dev, "%s\n", __func__);
  507. if (!omapdss_device_is_enabled(dssdev))
  508. return;
  509. mutex_lock(&ddata->mutex);
  510. acx565akm_panel_power_off(dssdev);
  511. mutex_unlock(&ddata->mutex);
  512. dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
  513. }
  514. static void acx565akm_set_timings(struct omap_dss_device *dssdev,
  515. struct omap_video_timings *timings)
  516. {
  517. struct panel_drv_data *ddata = to_panel_data(dssdev);
  518. struct omap_dss_device *in = ddata->in;
  519. ddata->videomode = *timings;
  520. dssdev->panel.timings = *timings;
  521. in->ops.sdi->set_timings(in, timings);
  522. }
  523. static void acx565akm_get_timings(struct omap_dss_device *dssdev,
  524. struct omap_video_timings *timings)
  525. {
  526. struct panel_drv_data *ddata = to_panel_data(dssdev);
  527. *timings = ddata->videomode;
  528. }
  529. static int acx565akm_check_timings(struct omap_dss_device *dssdev,
  530. struct omap_video_timings *timings)
  531. {
  532. struct panel_drv_data *ddata = to_panel_data(dssdev);
  533. struct omap_dss_device *in = ddata->in;
  534. return in->ops.sdi->check_timings(in, timings);
  535. }
  536. static struct omap_dss_driver acx565akm_ops = {
  537. .connect = acx565akm_connect,
  538. .disconnect = acx565akm_disconnect,
  539. .enable = acx565akm_enable,
  540. .disable = acx565akm_disable,
  541. .set_timings = acx565akm_set_timings,
  542. .get_timings = acx565akm_get_timings,
  543. .check_timings = acx565akm_check_timings,
  544. .get_resolution = omapdss_default_get_resolution,
  545. };
  546. static int acx565akm_probe_pdata(struct spi_device *spi)
  547. {
  548. const struct panel_acx565akm_platform_data *pdata;
  549. struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
  550. struct omap_dss_device *dssdev, *in;
  551. pdata = dev_get_platdata(&spi->dev);
  552. ddata->reset_gpio = pdata->reset_gpio;
  553. in = omap_dss_find_output(pdata->source);
  554. if (in == NULL) {
  555. dev_err(&spi->dev, "failed to find video source '%s'\n",
  556. pdata->source);
  557. return -EPROBE_DEFER;
  558. }
  559. ddata->in = in;
  560. ddata->datapairs = pdata->datapairs;
  561. dssdev = &ddata->dssdev;
  562. dssdev->name = pdata->name;
  563. return 0;
  564. }
  565. static int acx565akm_probe(struct spi_device *spi)
  566. {
  567. struct panel_drv_data *ddata;
  568. struct omap_dss_device *dssdev;
  569. struct backlight_device *bldev;
  570. int max_brightness, brightness;
  571. struct backlight_properties props;
  572. int r;
  573. dev_dbg(&spi->dev, "%s\n", __func__);
  574. spi->mode = SPI_MODE_3;
  575. ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
  576. if (ddata == NULL)
  577. return -ENOMEM;
  578. dev_set_drvdata(&spi->dev, ddata);
  579. ddata->spi = spi;
  580. mutex_init(&ddata->mutex);
  581. if (dev_get_platdata(&spi->dev)) {
  582. r = acx565akm_probe_pdata(spi);
  583. if (r)
  584. return r;
  585. } else {
  586. return -ENODEV;
  587. }
  588. if (gpio_is_valid(ddata->reset_gpio)) {
  589. r = devm_gpio_request_one(&spi->dev, ddata->reset_gpio,
  590. GPIOF_OUT_INIT_LOW, "lcd reset");
  591. if (r)
  592. goto err_gpio;
  593. }
  594. if (gpio_is_valid(ddata->reset_gpio))
  595. gpio_set_value(ddata->reset_gpio, 1);
  596. /*
  597. * After reset we have to wait 5 msec before the first
  598. * command can be sent.
  599. */
  600. usleep_range(5000, 10000);
  601. ddata->enabled = panel_enabled(ddata);
  602. r = panel_detect(ddata);
  603. if (!ddata->enabled && gpio_is_valid(ddata->reset_gpio))
  604. gpio_set_value(ddata->reset_gpio, 0);
  605. if (r) {
  606. dev_err(&spi->dev, "%s panel detect error\n", __func__);
  607. goto err_detect;
  608. }
  609. memset(&props, 0, sizeof(props));
  610. props.fb_blank = FB_BLANK_UNBLANK;
  611. props.power = FB_BLANK_UNBLANK;
  612. props.type = BACKLIGHT_RAW;
  613. bldev = backlight_device_register("acx565akm", &ddata->spi->dev,
  614. ddata, &acx565akm_bl_ops, &props);
  615. ddata->bl_dev = bldev;
  616. if (ddata->has_cabc) {
  617. r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
  618. if (r) {
  619. dev_err(&bldev->dev,
  620. "%s failed to create sysfs files\n", __func__);
  621. goto err_sysfs;
  622. }
  623. ddata->cabc_mode = get_hw_cabc_mode(ddata);
  624. }
  625. max_brightness = 255;
  626. if (ddata->has_bc)
  627. brightness = acx565akm_get_actual_brightness(ddata);
  628. else
  629. brightness = 0;
  630. bldev->props.max_brightness = max_brightness;
  631. bldev->props.brightness = brightness;
  632. acx565akm_bl_update_status(bldev);
  633. ddata->videomode = acx565akm_panel_timings;
  634. dssdev = &ddata->dssdev;
  635. dssdev->dev = &spi->dev;
  636. dssdev->driver = &acx565akm_ops;
  637. dssdev->type = OMAP_DISPLAY_TYPE_SDI;
  638. dssdev->owner = THIS_MODULE;
  639. dssdev->panel.timings = ddata->videomode;
  640. r = omapdss_register_display(dssdev);
  641. if (r) {
  642. dev_err(&spi->dev, "Failed to register panel\n");
  643. goto err_reg;
  644. }
  645. return 0;
  646. err_reg:
  647. sysfs_remove_group(&bldev->dev.kobj, &bldev_attr_group);
  648. err_sysfs:
  649. backlight_device_unregister(bldev);
  650. err_detect:
  651. err_gpio:
  652. omap_dss_put_device(ddata->in);
  653. return r;
  654. }
  655. static int acx565akm_remove(struct spi_device *spi)
  656. {
  657. struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
  658. struct omap_dss_device *dssdev = &ddata->dssdev;
  659. struct omap_dss_device *in = ddata->in;
  660. dev_dbg(&ddata->spi->dev, "%s\n", __func__);
  661. sysfs_remove_group(&ddata->bl_dev->dev.kobj, &bldev_attr_group);
  662. backlight_device_unregister(ddata->bl_dev);
  663. omapdss_unregister_display(dssdev);
  664. acx565akm_disable(dssdev);
  665. acx565akm_disconnect(dssdev);
  666. omap_dss_put_device(in);
  667. return 0;
  668. }
  669. static struct spi_driver acx565akm_driver = {
  670. .driver = {
  671. .name = "acx565akm",
  672. .owner = THIS_MODULE,
  673. },
  674. .probe = acx565akm_probe,
  675. .remove = acx565akm_remove,
  676. };
  677. module_spi_driver(acx565akm_driver);
  678. MODULE_AUTHOR("Nokia Corporation");
  679. MODULE_DESCRIPTION("acx565akm LCD Driver");
  680. MODULE_LICENSE("GPL");