bfin-lq035q1-fb.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. /*
  2. * Blackfin LCD Framebuffer driver SHARP LQ035Q1DH02
  3. *
  4. * Copyright 2008-2009 Analog Devices Inc.
  5. * Licensed under the GPL-2 or later.
  6. */
  7. #define DRIVER_NAME "bfin-lq035q1"
  8. #define pr_fmt(fmt) DRIVER_NAME ": " fmt
  9. #include <linux/module.h>
  10. #include <linux/kernel.h>
  11. #include <linux/errno.h>
  12. #include <linux/string.h>
  13. #include <linux/fb.h>
  14. #include <linux/slab.h>
  15. #include <linux/init.h>
  16. #include <linux/types.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/device.h>
  19. #include <linux/backlight.h>
  20. #include <linux/lcd.h>
  21. #include <linux/dma-mapping.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/spi/spi.h>
  24. #include <asm/blackfin.h>
  25. #include <asm/irq.h>
  26. #include <asm/dma.h>
  27. #include <asm/portmux.h>
  28. #include <asm/gptimers.h>
  29. #include <asm/bfin-lq035q1.h>
  30. #if defined(BF533_FAMILY) || defined(BF538_FAMILY)
  31. #define TIMER_HSYNC_id TIMER1_id
  32. #define TIMER_HSYNCbit TIMER1bit
  33. #define TIMER_HSYNC_STATUS_TRUN TIMER_STATUS_TRUN1
  34. #define TIMER_HSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL1
  35. #define TIMER_HSYNC_STATUS_TOVF TIMER_STATUS_TOVF1
  36. #define TIMER_VSYNC_id TIMER2_id
  37. #define TIMER_VSYNCbit TIMER2bit
  38. #define TIMER_VSYNC_STATUS_TRUN TIMER_STATUS_TRUN2
  39. #define TIMER_VSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL2
  40. #define TIMER_VSYNC_STATUS_TOVF TIMER_STATUS_TOVF2
  41. #else
  42. #define TIMER_HSYNC_id TIMER0_id
  43. #define TIMER_HSYNCbit TIMER0bit
  44. #define TIMER_HSYNC_STATUS_TRUN TIMER_STATUS_TRUN0
  45. #define TIMER_HSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL0
  46. #define TIMER_HSYNC_STATUS_TOVF TIMER_STATUS_TOVF0
  47. #define TIMER_VSYNC_id TIMER1_id
  48. #define TIMER_VSYNCbit TIMER1bit
  49. #define TIMER_VSYNC_STATUS_TRUN TIMER_STATUS_TRUN1
  50. #define TIMER_VSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL1
  51. #define TIMER_VSYNC_STATUS_TOVF TIMER_STATUS_TOVF1
  52. #endif
  53. #define LCD_X_RES 320 /* Horizontal Resolution */
  54. #define LCD_Y_RES 240 /* Vertical Resolution */
  55. #define DMA_BUS_SIZE 16
  56. #define USE_RGB565_16_BIT_PPI
  57. #ifdef USE_RGB565_16_BIT_PPI
  58. #define LCD_BPP 16 /* Bit Per Pixel */
  59. #define CLOCKS_PER_PIX 1
  60. #define CPLD_PIPELINE_DELAY_COR 0 /* NO CPLB */
  61. #endif
  62. /* Interface 16/18-bit TFT over an 8-bit wide PPI using a small Programmable Logic Device (CPLD)
  63. * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165
  64. */
  65. #ifdef USE_RGB565_8_BIT_PPI
  66. #define LCD_BPP 16 /* Bit Per Pixel */
  67. #define CLOCKS_PER_PIX 2
  68. #define CPLD_PIPELINE_DELAY_COR 3 /* RGB565 */
  69. #endif
  70. #ifdef USE_RGB888_8_BIT_PPI
  71. #define LCD_BPP 24 /* Bit Per Pixel */
  72. #define CLOCKS_PER_PIX 3
  73. #define CPLD_PIPELINE_DELAY_COR 5 /* RGB888 */
  74. #endif
  75. /*
  76. * HS and VS timing parameters (all in number of PPI clk ticks)
  77. */
  78. #define U_LINE 4 /* Blanking Lines */
  79. #define H_ACTPIX (LCD_X_RES * CLOCKS_PER_PIX) /* active horizontal pixel */
  80. #define H_PERIOD (336 * CLOCKS_PER_PIX) /* HS period */
  81. #define H_PULSE (2 * CLOCKS_PER_PIX) /* HS pulse width */
  82. #define H_START (7 * CLOCKS_PER_PIX + CPLD_PIPELINE_DELAY_COR) /* first valid pixel */
  83. #define V_LINES (LCD_Y_RES + U_LINE) /* total vertical lines */
  84. #define V_PULSE (2 * CLOCKS_PER_PIX) /* VS pulse width (1-5 H_PERIODs) */
  85. #define V_PERIOD (H_PERIOD * V_LINES) /* VS period */
  86. #define ACTIVE_VIDEO_MEM_OFFSET ((U_LINE / 2) * LCD_X_RES * (LCD_BPP / 8))
  87. #define BFIN_LCD_NBR_PALETTE_ENTRIES 256
  88. #define PPI_TX_MODE 0x2
  89. #define PPI_XFER_TYPE_11 0xC
  90. #define PPI_PORT_CFG_01 0x10
  91. #define PPI_POLS_1 0x8000
  92. #if (CLOCKS_PER_PIX > 1)
  93. #define PPI_PMODE (DLEN_8 | PACK_EN)
  94. #else
  95. #define PPI_PMODE (DLEN_16)
  96. #endif
  97. #define LQ035_INDEX 0x74
  98. #define LQ035_DATA 0x76
  99. #define LQ035_DRIVER_OUTPUT_CTL 0x1
  100. #define LQ035_SHUT_CTL 0x11
  101. #define LQ035_DRIVER_OUTPUT_MASK (LQ035_LR | LQ035_TB | LQ035_BGR | LQ035_REV)
  102. #define LQ035_DRIVER_OUTPUT_DEFAULT (0x2AEF & ~LQ035_DRIVER_OUTPUT_MASK)
  103. #define LQ035_SHUT (1 << 0) /* Shutdown */
  104. #define LQ035_ON (0 << 0) /* Shutdown */
  105. struct bfin_lq035q1fb_info {
  106. struct fb_info *fb;
  107. struct device *dev;
  108. struct spi_driver spidrv;
  109. struct bfin_lq035q1fb_disp_info *disp_info;
  110. unsigned char *fb_buffer; /* RGB Buffer */
  111. dma_addr_t dma_handle;
  112. int lq035_open_cnt;
  113. int irq;
  114. spinlock_t lock; /* lock */
  115. u32 pseudo_pal[16];
  116. };
  117. static int nocursor;
  118. module_param(nocursor, int, 0644);
  119. MODULE_PARM_DESC(nocursor, "cursor enable/disable");
  120. struct spi_control {
  121. unsigned short mode;
  122. };
  123. static int lq035q1_control(struct spi_device *spi, unsigned char reg, unsigned short value)
  124. {
  125. int ret;
  126. u8 regs[3] = { LQ035_INDEX, 0, 0 };
  127. u8 dat[3] = { LQ035_DATA, 0, 0 };
  128. if (!spi)
  129. return -ENODEV;
  130. regs[2] = reg;
  131. dat[1] = value >> 8;
  132. dat[2] = value & 0xFF;
  133. ret = spi_write(spi, regs, ARRAY_SIZE(regs));
  134. ret |= spi_write(spi, dat, ARRAY_SIZE(dat));
  135. return ret;
  136. }
  137. static int __devinit lq035q1_spidev_probe(struct spi_device *spi)
  138. {
  139. int ret;
  140. struct spi_control *ctl;
  141. struct bfin_lq035q1fb_info *info = container_of(spi->dev.driver,
  142. struct bfin_lq035q1fb_info,
  143. spidrv.driver);
  144. ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
  145. if (!ctl)
  146. return -ENOMEM;
  147. ctl->mode = (info->disp_info->mode &
  148. LQ035_DRIVER_OUTPUT_MASK) | LQ035_DRIVER_OUTPUT_DEFAULT;
  149. ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
  150. ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
  151. if (ret)
  152. return ret;
  153. spi_set_drvdata(spi, ctl);
  154. return 0;
  155. }
  156. static int lq035q1_spidev_remove(struct spi_device *spi)
  157. {
  158. return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
  159. }
  160. #ifdef CONFIG_PM
  161. static int lq035q1_spidev_suspend(struct spi_device *spi, pm_message_t state)
  162. {
  163. return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
  164. }
  165. static int lq035q1_spidev_resume(struct spi_device *spi)
  166. {
  167. int ret;
  168. struct spi_control *ctl = spi_get_drvdata(spi);
  169. ret = lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
  170. if (ret)
  171. return ret;
  172. return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
  173. }
  174. #else
  175. # define lq035q1_spidev_suspend NULL
  176. # define lq035q1_spidev_resume NULL
  177. #endif
  178. /* Power down all displays on reboot, poweroff or halt */
  179. static void lq035q1_spidev_shutdown(struct spi_device *spi)
  180. {
  181. lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
  182. }
  183. static int lq035q1_backlight(struct bfin_lq035q1fb_info *info, unsigned arg)
  184. {
  185. if (info->disp_info->use_bl)
  186. gpio_set_value(info->disp_info->gpio_bl, arg);
  187. return 0;
  188. }
  189. static void bfin_lq035q1_config_ppi(struct bfin_lq035q1fb_info *fbi)
  190. {
  191. bfin_write_PPI_DELAY(H_START);
  192. bfin_write_PPI_COUNT(H_ACTPIX - 1);
  193. bfin_write_PPI_FRAME(V_LINES);
  194. bfin_write_PPI_CONTROL(PPI_TX_MODE | /* output mode , PORT_DIR */
  195. PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
  196. PPI_PORT_CFG_01 | /* two frame sync PORT_CFG */
  197. PPI_PMODE | /* 8/16 bit data length / PACK_EN? */
  198. PPI_POLS_1); /* faling edge syncs POLS */
  199. }
  200. static inline void bfin_lq035q1_disable_ppi(void)
  201. {
  202. bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
  203. }
  204. static inline void bfin_lq035q1_enable_ppi(void)
  205. {
  206. bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
  207. }
  208. static void bfin_lq035q1_start_timers(void)
  209. {
  210. enable_gptimers(TIMER_VSYNCbit | TIMER_HSYNCbit);
  211. }
  212. static void bfin_lq035q1_stop_timers(void)
  213. {
  214. disable_gptimers(TIMER_HSYNCbit | TIMER_VSYNCbit);
  215. set_gptimer_status(0, TIMER_HSYNC_STATUS_TRUN | TIMER_VSYNC_STATUS_TRUN |
  216. TIMER_HSYNC_STATUS_TIMIL | TIMER_VSYNC_STATUS_TIMIL |
  217. TIMER_HSYNC_STATUS_TOVF | TIMER_VSYNC_STATUS_TOVF);
  218. }
  219. static void bfin_lq035q1_init_timers(void)
  220. {
  221. bfin_lq035q1_stop_timers();
  222. set_gptimer_period(TIMER_HSYNC_id, H_PERIOD);
  223. set_gptimer_pwidth(TIMER_HSYNC_id, H_PULSE);
  224. set_gptimer_config(TIMER_HSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
  225. TIMER_TIN_SEL | TIMER_CLK_SEL|
  226. TIMER_EMU_RUN);
  227. set_gptimer_period(TIMER_VSYNC_id, V_PERIOD);
  228. set_gptimer_pwidth(TIMER_VSYNC_id, V_PULSE);
  229. set_gptimer_config(TIMER_VSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
  230. TIMER_TIN_SEL | TIMER_CLK_SEL |
  231. TIMER_EMU_RUN);
  232. }
  233. static void bfin_lq035q1_config_dma(struct bfin_lq035q1fb_info *fbi)
  234. {
  235. set_dma_config(CH_PPI,
  236. set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
  237. INTR_DISABLE, DIMENSION_2D,
  238. DATA_SIZE_16,
  239. DMA_NOSYNC_KEEP_DMA_BUF));
  240. set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
  241. set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
  242. set_dma_y_count(CH_PPI, V_LINES);
  243. set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
  244. set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
  245. }
  246. #if (CLOCKS_PER_PIX == 1)
  247. static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
  248. P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
  249. P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
  250. P_PPI0_D6, P_PPI0_D7, P_PPI0_D8,
  251. P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
  252. P_PPI0_D12, P_PPI0_D13, P_PPI0_D14,
  253. P_PPI0_D15, 0};
  254. #else
  255. static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
  256. P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
  257. P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
  258. P_PPI0_D6, P_PPI0_D7, 0};
  259. #endif
  260. static inline void bfin_lq035q1_free_ports(void)
  261. {
  262. peripheral_free_list(ppi0_req_16);
  263. if (ANOMALY_05000400)
  264. gpio_free(P_IDENT(P_PPI0_FS3));
  265. }
  266. static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev)
  267. {
  268. /* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode:
  269. * Drive PPI_FS3 Low
  270. */
  271. if (ANOMALY_05000400) {
  272. int ret = gpio_request(P_IDENT(P_PPI0_FS3), "PPI_FS3");
  273. if (ret)
  274. return ret;
  275. gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
  276. }
  277. if (peripheral_request_list(ppi0_req_16, DRIVER_NAME)) {
  278. dev_err(&pdev->dev, "requesting peripherals failed\n");
  279. return -EFAULT;
  280. }
  281. return 0;
  282. }
  283. static int bfin_lq035q1_fb_open(struct fb_info *info, int user)
  284. {
  285. struct bfin_lq035q1fb_info *fbi = info->par;
  286. spin_lock(&fbi->lock);
  287. fbi->lq035_open_cnt++;
  288. if (fbi->lq035_open_cnt <= 1) {
  289. bfin_lq035q1_disable_ppi();
  290. SSYNC();
  291. bfin_lq035q1_config_dma(fbi);
  292. bfin_lq035q1_config_ppi(fbi);
  293. bfin_lq035q1_init_timers();
  294. /* start dma */
  295. enable_dma(CH_PPI);
  296. bfin_lq035q1_enable_ppi();
  297. bfin_lq035q1_start_timers();
  298. lq035q1_backlight(fbi, 1);
  299. }
  300. spin_unlock(&fbi->lock);
  301. return 0;
  302. }
  303. static int bfin_lq035q1_fb_release(struct fb_info *info, int user)
  304. {
  305. struct bfin_lq035q1fb_info *fbi = info->par;
  306. spin_lock(&fbi->lock);
  307. fbi->lq035_open_cnt--;
  308. if (fbi->lq035_open_cnt <= 0) {
  309. lq035q1_backlight(fbi, 0);
  310. bfin_lq035q1_disable_ppi();
  311. SSYNC();
  312. disable_dma(CH_PPI);
  313. bfin_lq035q1_stop_timers();
  314. }
  315. spin_unlock(&fbi->lock);
  316. return 0;
  317. }
  318. static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var,
  319. struct fb_info *info)
  320. {
  321. switch (var->bits_per_pixel) {
  322. #if (LCD_BPP == 24)
  323. case 24:/* TRUECOLOUR, 16m */
  324. #else
  325. case 16:/* DIRECTCOLOUR, 64k */
  326. #endif
  327. var->red.offset = info->var.red.offset;
  328. var->green.offset = info->var.green.offset;
  329. var->blue.offset = info->var.blue.offset;
  330. var->red.length = info->var.red.length;
  331. var->green.length = info->var.green.length;
  332. var->blue.length = info->var.blue.length;
  333. var->transp.offset = 0;
  334. var->transp.length = 0;
  335. var->transp.msb_right = 0;
  336. var->red.msb_right = 0;
  337. var->green.msb_right = 0;
  338. var->blue.msb_right = 0;
  339. break;
  340. default:
  341. pr_debug("%s: depth not supported: %u BPP\n", __func__,
  342. var->bits_per_pixel);
  343. return -EINVAL;
  344. }
  345. if (info->var.xres != var->xres || info->var.yres != var->yres ||
  346. info->var.xres_virtual != var->xres_virtual ||
  347. info->var.yres_virtual != var->yres_virtual) {
  348. pr_debug("%s: Resolution not supported: X%u x Y%u \n",
  349. __func__, var->xres, var->yres);
  350. return -EINVAL;
  351. }
  352. /*
  353. * Memory limit
  354. */
  355. if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
  356. pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
  357. __func__, var->yres_virtual);
  358. return -ENOMEM;
  359. }
  360. return 0;
  361. }
  362. int bfin_lq035q1_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
  363. {
  364. if (nocursor)
  365. return 0;
  366. else
  367. return -EINVAL; /* just to force soft_cursor() call */
  368. }
  369. static int bfin_lq035q1_fb_setcolreg(u_int regno, u_int red, u_int green,
  370. u_int blue, u_int transp,
  371. struct fb_info *info)
  372. {
  373. if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
  374. return -EINVAL;
  375. if (info->var.grayscale) {
  376. /* grayscale = 0.30*R + 0.59*G + 0.11*B */
  377. red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
  378. }
  379. if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
  380. u32 value;
  381. /* Place color in the pseudopalette */
  382. if (regno > 16)
  383. return -EINVAL;
  384. red >>= (16 - info->var.red.length);
  385. green >>= (16 - info->var.green.length);
  386. blue >>= (16 - info->var.blue.length);
  387. value = (red << info->var.red.offset) |
  388. (green << info->var.green.offset) |
  389. (blue << info->var.blue.offset);
  390. value &= 0xFFFFFF;
  391. ((u32 *) (info->pseudo_palette))[regno] = value;
  392. }
  393. return 0;
  394. }
  395. static struct fb_ops bfin_lq035q1_fb_ops = {
  396. .owner = THIS_MODULE,
  397. .fb_open = bfin_lq035q1_fb_open,
  398. .fb_release = bfin_lq035q1_fb_release,
  399. .fb_check_var = bfin_lq035q1_fb_check_var,
  400. .fb_fillrect = cfb_fillrect,
  401. .fb_copyarea = cfb_copyarea,
  402. .fb_imageblit = cfb_imageblit,
  403. .fb_cursor = bfin_lq035q1_fb_cursor,
  404. .fb_setcolreg = bfin_lq035q1_fb_setcolreg,
  405. };
  406. static irqreturn_t bfin_lq035q1_irq_error(int irq, void *dev_id)
  407. {
  408. /*struct bfin_lq035q1fb_info *info = (struct bfin_lq035q1fb_info *)dev_id;*/
  409. u16 status = bfin_read_PPI_STATUS();
  410. bfin_write_PPI_STATUS(-1);
  411. if (status) {
  412. bfin_lq035q1_disable_ppi();
  413. disable_dma(CH_PPI);
  414. /* start dma */
  415. enable_dma(CH_PPI);
  416. bfin_lq035q1_enable_ppi();
  417. bfin_write_PPI_STATUS(-1);
  418. }
  419. return IRQ_HANDLED;
  420. }
  421. static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
  422. {
  423. struct bfin_lq035q1fb_info *info;
  424. struct fb_info *fbinfo;
  425. int ret;
  426. ret = request_dma(CH_PPI, DRIVER_NAME"_CH_PPI");
  427. if (ret < 0) {
  428. dev_err(&pdev->dev, "PPI DMA unavailable\n");
  429. goto out1;
  430. }
  431. fbinfo = framebuffer_alloc(sizeof(*info), &pdev->dev);
  432. if (!fbinfo) {
  433. ret = -ENOMEM;
  434. goto out2;
  435. }
  436. info = fbinfo->par;
  437. info->fb = fbinfo;
  438. info->dev = &pdev->dev;
  439. info->disp_info = pdev->dev.platform_data;
  440. platform_set_drvdata(pdev, fbinfo);
  441. strcpy(fbinfo->fix.id, DRIVER_NAME);
  442. fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
  443. fbinfo->fix.type_aux = 0;
  444. fbinfo->fix.xpanstep = 0;
  445. fbinfo->fix.ypanstep = 0;
  446. fbinfo->fix.ywrapstep = 0;
  447. fbinfo->fix.accel = FB_ACCEL_NONE;
  448. fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
  449. fbinfo->var.nonstd = 0;
  450. fbinfo->var.activate = FB_ACTIVATE_NOW;
  451. fbinfo->var.height = -1;
  452. fbinfo->var.width = -1;
  453. fbinfo->var.accel_flags = 0;
  454. fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
  455. fbinfo->var.xres = LCD_X_RES;
  456. fbinfo->var.xres_virtual = LCD_X_RES;
  457. fbinfo->var.yres = LCD_Y_RES;
  458. fbinfo->var.yres_virtual = LCD_Y_RES;
  459. fbinfo->var.bits_per_pixel = LCD_BPP;
  460. if (info->disp_info->mode & LQ035_BGR) {
  461. #if (LCD_BPP == 24)
  462. fbinfo->var.red.offset = 0;
  463. fbinfo->var.green.offset = 8;
  464. fbinfo->var.blue.offset = 16;
  465. #else
  466. fbinfo->var.red.offset = 0;
  467. fbinfo->var.green.offset = 5;
  468. fbinfo->var.blue.offset = 11;
  469. #endif
  470. } else {
  471. #if (LCD_BPP == 24)
  472. fbinfo->var.red.offset = 16;
  473. fbinfo->var.green.offset = 8;
  474. fbinfo->var.blue.offset = 0;
  475. #else
  476. fbinfo->var.red.offset = 11;
  477. fbinfo->var.green.offset = 5;
  478. fbinfo->var.blue.offset = 0;
  479. #endif
  480. }
  481. fbinfo->var.transp.offset = 0;
  482. #if (LCD_BPP == 24)
  483. fbinfo->var.red.length = 8;
  484. fbinfo->var.green.length = 8;
  485. fbinfo->var.blue.length = 8;
  486. #else
  487. fbinfo->var.red.length = 5;
  488. fbinfo->var.green.length = 6;
  489. fbinfo->var.blue.length = 5;
  490. #endif
  491. fbinfo->var.transp.length = 0;
  492. fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8
  493. + ACTIVE_VIDEO_MEM_OFFSET;
  494. fbinfo->fix.line_length = fbinfo->var.xres_virtual *
  495. fbinfo->var.bits_per_pixel / 8;
  496. fbinfo->fbops = &bfin_lq035q1_fb_ops;
  497. fbinfo->flags = FBINFO_FLAG_DEFAULT;
  498. info->fb_buffer =
  499. dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
  500. GFP_KERNEL);
  501. if (NULL == info->fb_buffer) {
  502. dev_err(&pdev->dev, "couldn't allocate dma buffer\n");
  503. ret = -ENOMEM;
  504. goto out3;
  505. }
  506. fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
  507. fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
  508. fbinfo->fbops = &bfin_lq035q1_fb_ops;
  509. fbinfo->pseudo_palette = &info->pseudo_pal;
  510. ret = fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0);
  511. if (ret < 0) {
  512. dev_err(&pdev->dev, "failed to allocate colormap (%d entries)\n",
  513. BFIN_LCD_NBR_PALETTE_ENTRIES);
  514. goto out4;
  515. }
  516. ret = bfin_lq035q1_request_ports(pdev);
  517. if (ret) {
  518. dev_err(&pdev->dev, "couldn't request gpio port\n");
  519. goto out6;
  520. }
  521. info->irq = platform_get_irq(pdev, 0);
  522. if (info->irq < 0) {
  523. ret = -EINVAL;
  524. goto out7;
  525. }
  526. ret = request_irq(info->irq, bfin_lq035q1_irq_error, IRQF_DISABLED,
  527. DRIVER_NAME" PPI ERROR", info);
  528. if (ret < 0) {
  529. dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n");
  530. goto out7;
  531. }
  532. info->spidrv.driver.name = DRIVER_NAME"-spi";
  533. info->spidrv.probe = lq035q1_spidev_probe;
  534. info->spidrv.remove = __devexit_p(lq035q1_spidev_remove);
  535. info->spidrv.shutdown = lq035q1_spidev_shutdown;
  536. info->spidrv.suspend = lq035q1_spidev_suspend;
  537. info->spidrv.resume = lq035q1_spidev_resume;
  538. ret = spi_register_driver(&info->spidrv);
  539. if (ret < 0) {
  540. dev_err(&pdev->dev, "couldn't register SPI Interface\n");
  541. goto out8;
  542. }
  543. if (info->disp_info->use_bl) {
  544. ret = gpio_request(info->disp_info->gpio_bl, "LQ035 Backlight");
  545. if (ret) {
  546. dev_err(&pdev->dev, "failed to request GPIO %d\n",
  547. info->disp_info->gpio_bl);
  548. goto out9;
  549. }
  550. gpio_direction_output(info->disp_info->gpio_bl, 0);
  551. }
  552. ret = register_framebuffer(fbinfo);
  553. if (ret < 0) {
  554. dev_err(&pdev->dev, "unable to register framebuffer\n");
  555. goto out10;
  556. }
  557. dev_info(&pdev->dev, "%dx%d %d-bit RGB FrameBuffer initialized\n",
  558. LCD_X_RES, LCD_Y_RES, LCD_BPP);
  559. return 0;
  560. out10:
  561. if (info->disp_info->use_bl)
  562. gpio_free(info->disp_info->gpio_bl);
  563. out9:
  564. spi_unregister_driver(&info->spidrv);
  565. out8:
  566. free_irq(info->irq, info);
  567. out7:
  568. bfin_lq035q1_free_ports();
  569. out6:
  570. fb_dealloc_cmap(&fbinfo->cmap);
  571. out4:
  572. dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
  573. info->dma_handle);
  574. out3:
  575. framebuffer_release(fbinfo);
  576. out2:
  577. free_dma(CH_PPI);
  578. out1:
  579. platform_set_drvdata(pdev, NULL);
  580. return ret;
  581. }
  582. static int __devexit bfin_lq035q1_remove(struct platform_device *pdev)
  583. {
  584. struct fb_info *fbinfo = platform_get_drvdata(pdev);
  585. struct bfin_lq035q1fb_info *info = fbinfo->par;
  586. if (info->disp_info->use_bl)
  587. gpio_free(info->disp_info->gpio_bl);
  588. spi_unregister_driver(&info->spidrv);
  589. unregister_framebuffer(fbinfo);
  590. free_dma(CH_PPI);
  591. free_irq(info->irq, info);
  592. if (info->fb_buffer != NULL)
  593. dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
  594. info->dma_handle);
  595. fb_dealloc_cmap(&fbinfo->cmap);
  596. bfin_lq035q1_free_ports();
  597. platform_set_drvdata(pdev, NULL);
  598. framebuffer_release(fbinfo);
  599. dev_info(&pdev->dev, "unregistered LCD driver\n");
  600. return 0;
  601. }
  602. #ifdef CONFIG_PM
  603. static int bfin_lq035q1_suspend(struct device *dev)
  604. {
  605. struct fb_info *fbinfo = dev_get_drvdata(dev);
  606. struct bfin_lq035q1fb_info *info = fbinfo->par;
  607. if (info->lq035_open_cnt) {
  608. lq035q1_backlight(info, 0);
  609. bfin_lq035q1_disable_ppi();
  610. SSYNC();
  611. disable_dma(CH_PPI);
  612. bfin_lq035q1_stop_timers();
  613. bfin_write_PPI_STATUS(-1);
  614. }
  615. return 0;
  616. }
  617. static int bfin_lq035q1_resume(struct device *dev)
  618. {
  619. struct fb_info *fbinfo = dev_get_drvdata(dev);
  620. struct bfin_lq035q1fb_info *info = fbinfo->par;
  621. if (info->lq035_open_cnt) {
  622. bfin_lq035q1_disable_ppi();
  623. SSYNC();
  624. bfin_lq035q1_config_dma(info);
  625. bfin_lq035q1_config_ppi(info);
  626. bfin_lq035q1_init_timers();
  627. /* start dma */
  628. enable_dma(CH_PPI);
  629. bfin_lq035q1_enable_ppi();
  630. bfin_lq035q1_start_timers();
  631. lq035q1_backlight(info, 1);
  632. }
  633. return 0;
  634. }
  635. static struct dev_pm_ops bfin_lq035q1_dev_pm_ops = {
  636. .suspend = bfin_lq035q1_suspend,
  637. .resume = bfin_lq035q1_resume,
  638. };
  639. #endif
  640. static struct platform_driver bfin_lq035q1_driver = {
  641. .probe = bfin_lq035q1_probe,
  642. .remove = __devexit_p(bfin_lq035q1_remove),
  643. .driver = {
  644. .name = DRIVER_NAME,
  645. #ifdef CONFIG_PM
  646. .pm = &bfin_lq035q1_dev_pm_ops,
  647. #endif
  648. },
  649. };
  650. static int __init bfin_lq035q1_driver_init(void)
  651. {
  652. return platform_driver_register(&bfin_lq035q1_driver);
  653. }
  654. module_init(bfin_lq035q1_driver_init);
  655. static void __exit bfin_lq035q1_driver_cleanup(void)
  656. {
  657. platform_driver_unregister(&bfin_lq035q1_driver);
  658. }
  659. module_exit(bfin_lq035q1_driver_cleanup);
  660. MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
  661. MODULE_LICENSE("GPL");