jz4740_fb.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. /*
  2. * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
  3. * JZ4740 SoC LCD framebuffer driver
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. *
  10. * You should have received a copy of the GNU General Public License along
  11. * with this program; if not, write to the Free Software Foundation, Inc.,
  12. * 675 Mass Ave, Cambridge, MA 02139, USA.
  13. *
  14. */
  15. #include <linux/kernel.h>
  16. #include <linux/module.h>
  17. #include <linux/mutex.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/clk.h>
  20. #include <linux/delay.h>
  21. #include <linux/console.h>
  22. #include <linux/fb.h>
  23. #include <linux/dma-mapping.h>
  24. #include <asm/mach-jz4740/jz4740_fb.h>
  25. #include <asm/mach-jz4740/gpio.h>
  26. #define JZ_REG_LCD_CFG 0x00
  27. #define JZ_REG_LCD_VSYNC 0x04
  28. #define JZ_REG_LCD_HSYNC 0x08
  29. #define JZ_REG_LCD_VAT 0x0C
  30. #define JZ_REG_LCD_DAH 0x10
  31. #define JZ_REG_LCD_DAV 0x14
  32. #define JZ_REG_LCD_PS 0x18
  33. #define JZ_REG_LCD_CLS 0x1C
  34. #define JZ_REG_LCD_SPL 0x20
  35. #define JZ_REG_LCD_REV 0x24
  36. #define JZ_REG_LCD_CTRL 0x30
  37. #define JZ_REG_LCD_STATE 0x34
  38. #define JZ_REG_LCD_IID 0x38
  39. #define JZ_REG_LCD_DA0 0x40
  40. #define JZ_REG_LCD_SA0 0x44
  41. #define JZ_REG_LCD_FID0 0x48
  42. #define JZ_REG_LCD_CMD0 0x4C
  43. #define JZ_REG_LCD_DA1 0x50
  44. #define JZ_REG_LCD_SA1 0x54
  45. #define JZ_REG_LCD_FID1 0x58
  46. #define JZ_REG_LCD_CMD1 0x5C
  47. #define JZ_LCD_CFG_SLCD BIT(31)
  48. #define JZ_LCD_CFG_PS_DISABLE BIT(23)
  49. #define JZ_LCD_CFG_CLS_DISABLE BIT(22)
  50. #define JZ_LCD_CFG_SPL_DISABLE BIT(21)
  51. #define JZ_LCD_CFG_REV_DISABLE BIT(20)
  52. #define JZ_LCD_CFG_HSYNCM BIT(19)
  53. #define JZ_LCD_CFG_PCLKM BIT(18)
  54. #define JZ_LCD_CFG_INV BIT(17)
  55. #define JZ_LCD_CFG_SYNC_DIR BIT(16)
  56. #define JZ_LCD_CFG_PS_POLARITY BIT(15)
  57. #define JZ_LCD_CFG_CLS_POLARITY BIT(14)
  58. #define JZ_LCD_CFG_SPL_POLARITY BIT(13)
  59. #define JZ_LCD_CFG_REV_POLARITY BIT(12)
  60. #define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11)
  61. #define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10)
  62. #define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)
  63. #define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)
  64. #define JZ_LCD_CFG_18_BIT BIT(7)
  65. #define JZ_LCD_CFG_PDW (BIT(5) | BIT(4))
  66. #define JZ_LCD_CFG_MODE_MASK 0xf
  67. #define JZ_LCD_CTRL_BURST_4 (0x0 << 28)
  68. #define JZ_LCD_CTRL_BURST_8 (0x1 << 28)
  69. #define JZ_LCD_CTRL_BURST_16 (0x2 << 28)
  70. #define JZ_LCD_CTRL_RGB555 BIT(27)
  71. #define JZ_LCD_CTRL_OFUP BIT(26)
  72. #define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24)
  73. #define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24)
  74. #define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24)
  75. #define JZ_LCD_CTRL_PDD_MASK (0xff << 16)
  76. #define JZ_LCD_CTRL_EOF_IRQ BIT(13)
  77. #define JZ_LCD_CTRL_SOF_IRQ BIT(12)
  78. #define JZ_LCD_CTRL_OFU_IRQ BIT(11)
  79. #define JZ_LCD_CTRL_IFU0_IRQ BIT(10)
  80. #define JZ_LCD_CTRL_IFU1_IRQ BIT(9)
  81. #define JZ_LCD_CTRL_DD_IRQ BIT(8)
  82. #define JZ_LCD_CTRL_QDD_IRQ BIT(7)
  83. #define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6)
  84. #define JZ_LCD_CTRL_LSB_FISRT BIT(5)
  85. #define JZ_LCD_CTRL_DISABLE BIT(4)
  86. #define JZ_LCD_CTRL_ENABLE BIT(3)
  87. #define JZ_LCD_CTRL_BPP_1 0x0
  88. #define JZ_LCD_CTRL_BPP_2 0x1
  89. #define JZ_LCD_CTRL_BPP_4 0x2
  90. #define JZ_LCD_CTRL_BPP_8 0x3
  91. #define JZ_LCD_CTRL_BPP_15_16 0x4
  92. #define JZ_LCD_CTRL_BPP_18_24 0x5
  93. #define JZ_LCD_CMD_SOF_IRQ BIT(31)
  94. #define JZ_LCD_CMD_EOF_IRQ BIT(30)
  95. #define JZ_LCD_CMD_ENABLE_PAL BIT(28)
  96. #define JZ_LCD_SYNC_MASK 0x3ff
  97. #define JZ_LCD_STATE_DISABLED BIT(0)
  98. struct jzfb_framedesc {
  99. uint32_t next;
  100. uint32_t addr;
  101. uint32_t id;
  102. uint32_t cmd;
  103. } __packed;
  104. struct jzfb {
  105. struct fb_info *fb;
  106. struct platform_device *pdev;
  107. void __iomem *base;
  108. struct resource *mem;
  109. struct jz4740_fb_platform_data *pdata;
  110. size_t vidmem_size;
  111. void *vidmem;
  112. dma_addr_t vidmem_phys;
  113. struct jzfb_framedesc *framedesc;
  114. dma_addr_t framedesc_phys;
  115. struct clk *ldclk;
  116. struct clk *lpclk;
  117. unsigned is_enabled:1;
  118. struct mutex lock;
  119. uint32_t pseudo_palette[16];
  120. };
  121. static const struct fb_fix_screeninfo jzfb_fix = {
  122. .id = "JZ4740 FB",
  123. .type = FB_TYPE_PACKED_PIXELS,
  124. .visual = FB_VISUAL_TRUECOLOR,
  125. .xpanstep = 0,
  126. .ypanstep = 0,
  127. .ywrapstep = 0,
  128. .accel = FB_ACCEL_NONE,
  129. };
  130. static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = {
  131. JZ_GPIO_BULK_PIN(LCD_PCLK),
  132. JZ_GPIO_BULK_PIN(LCD_HSYNC),
  133. JZ_GPIO_BULK_PIN(LCD_VSYNC),
  134. JZ_GPIO_BULK_PIN(LCD_DE),
  135. JZ_GPIO_BULK_PIN(LCD_PS),
  136. JZ_GPIO_BULK_PIN(LCD_REV),
  137. JZ_GPIO_BULK_PIN(LCD_CLS),
  138. JZ_GPIO_BULK_PIN(LCD_SPL),
  139. };
  140. static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = {
  141. JZ_GPIO_BULK_PIN(LCD_DATA0),
  142. JZ_GPIO_BULK_PIN(LCD_DATA1),
  143. JZ_GPIO_BULK_PIN(LCD_DATA2),
  144. JZ_GPIO_BULK_PIN(LCD_DATA3),
  145. JZ_GPIO_BULK_PIN(LCD_DATA4),
  146. JZ_GPIO_BULK_PIN(LCD_DATA5),
  147. JZ_GPIO_BULK_PIN(LCD_DATA6),
  148. JZ_GPIO_BULK_PIN(LCD_DATA7),
  149. JZ_GPIO_BULK_PIN(LCD_DATA8),
  150. JZ_GPIO_BULK_PIN(LCD_DATA9),
  151. JZ_GPIO_BULK_PIN(LCD_DATA10),
  152. JZ_GPIO_BULK_PIN(LCD_DATA11),
  153. JZ_GPIO_BULK_PIN(LCD_DATA12),
  154. JZ_GPIO_BULK_PIN(LCD_DATA13),
  155. JZ_GPIO_BULK_PIN(LCD_DATA14),
  156. JZ_GPIO_BULK_PIN(LCD_DATA15),
  157. JZ_GPIO_BULK_PIN(LCD_DATA16),
  158. JZ_GPIO_BULK_PIN(LCD_DATA17),
  159. };
  160. static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
  161. {
  162. unsigned int num;
  163. switch (jzfb->pdata->lcd_type) {
  164. case JZ_LCD_TYPE_GENERIC_16_BIT:
  165. num = 4;
  166. break;
  167. case JZ_LCD_TYPE_GENERIC_18_BIT:
  168. num = 4;
  169. break;
  170. case JZ_LCD_TYPE_8BIT_SERIAL:
  171. num = 3;
  172. break;
  173. case JZ_LCD_TYPE_SPECIAL_TFT_1:
  174. case JZ_LCD_TYPE_SPECIAL_TFT_2:
  175. case JZ_LCD_TYPE_SPECIAL_TFT_3:
  176. num = 8;
  177. break;
  178. default:
  179. num = 0;
  180. break;
  181. }
  182. return num;
  183. }
  184. static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
  185. {
  186. unsigned int num;
  187. switch (jzfb->pdata->lcd_type) {
  188. case JZ_LCD_TYPE_GENERIC_16_BIT:
  189. num = 16;
  190. break;
  191. case JZ_LCD_TYPE_GENERIC_18_BIT:
  192. num = 18;
  193. break;
  194. case JZ_LCD_TYPE_8BIT_SERIAL:
  195. num = 8;
  196. break;
  197. case JZ_LCD_TYPE_SPECIAL_TFT_1:
  198. case JZ_LCD_TYPE_SPECIAL_TFT_2:
  199. case JZ_LCD_TYPE_SPECIAL_TFT_3:
  200. if (jzfb->pdata->bpp == 18)
  201. num = 18;
  202. else
  203. num = 16;
  204. break;
  205. default:
  206. num = 0;
  207. break;
  208. }
  209. return num;
  210. }
  211. /* Based on CNVT_TOHW macro from skeletonfb.c */
  212. static inline uint32_t jzfb_convert_color_to_hw(unsigned val,
  213. struct fb_bitfield *bf)
  214. {
  215. return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset;
  216. }
  217. static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
  218. unsigned blue, unsigned transp, struct fb_info *fb)
  219. {
  220. uint32_t color;
  221. if (regno >= 16)
  222. return -EINVAL;
  223. color = jzfb_convert_color_to_hw(red, &fb->var.red);
  224. color |= jzfb_convert_color_to_hw(green, &fb->var.green);
  225. color |= jzfb_convert_color_to_hw(blue, &fb->var.blue);
  226. color |= jzfb_convert_color_to_hw(transp, &fb->var.transp);
  227. ((uint32_t *)(fb->pseudo_palette))[regno] = color;
  228. return 0;
  229. }
  230. static int jzfb_get_controller_bpp(struct jzfb *jzfb)
  231. {
  232. switch (jzfb->pdata->bpp) {
  233. case 18:
  234. case 24:
  235. return 32;
  236. case 15:
  237. return 16;
  238. default:
  239. return jzfb->pdata->bpp;
  240. }
  241. }
  242. static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb,
  243. struct fb_var_screeninfo *var)
  244. {
  245. size_t i;
  246. struct fb_videomode *mode = jzfb->pdata->modes;
  247. for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
  248. if (mode->xres == var->xres && mode->yres == var->yres)
  249. return mode;
  250. }
  251. return NULL;
  252. }
  253. static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
  254. {
  255. struct jzfb *jzfb = fb->par;
  256. struct fb_videomode *mode;
  257. if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
  258. var->bits_per_pixel != jzfb->pdata->bpp)
  259. return -EINVAL;
  260. mode = jzfb_get_mode(jzfb, var);
  261. if (mode == NULL)
  262. return -EINVAL;
  263. fb_videomode_to_var(var, mode);
  264. switch (jzfb->pdata->bpp) {
  265. case 8:
  266. break;
  267. case 15:
  268. var->red.offset = 10;
  269. var->red.length = 5;
  270. var->green.offset = 6;
  271. var->green.length = 5;
  272. var->blue.offset = 0;
  273. var->blue.length = 5;
  274. break;
  275. case 16:
  276. var->red.offset = 11;
  277. var->red.length = 5;
  278. var->green.offset = 5;
  279. var->green.length = 6;
  280. var->blue.offset = 0;
  281. var->blue.length = 5;
  282. break;
  283. case 18:
  284. var->red.offset = 16;
  285. var->red.length = 6;
  286. var->green.offset = 8;
  287. var->green.length = 6;
  288. var->blue.offset = 0;
  289. var->blue.length = 6;
  290. var->bits_per_pixel = 32;
  291. break;
  292. case 32:
  293. case 24:
  294. var->transp.offset = 24;
  295. var->transp.length = 8;
  296. var->red.offset = 16;
  297. var->red.length = 8;
  298. var->green.offset = 8;
  299. var->green.length = 8;
  300. var->blue.offset = 0;
  301. var->blue.length = 8;
  302. var->bits_per_pixel = 32;
  303. break;
  304. default:
  305. break;
  306. }
  307. return 0;
  308. }
  309. static int jzfb_set_par(struct fb_info *info)
  310. {
  311. struct jzfb *jzfb = info->par;
  312. struct jz4740_fb_platform_data *pdata = jzfb->pdata;
  313. struct fb_var_screeninfo *var = &info->var;
  314. struct fb_videomode *mode;
  315. uint16_t hds, vds;
  316. uint16_t hde, vde;
  317. uint16_t ht, vt;
  318. uint32_t ctrl;
  319. uint32_t cfg;
  320. unsigned long rate;
  321. mode = jzfb_get_mode(jzfb, var);
  322. if (mode == NULL)
  323. return -EINVAL;
  324. if (mode == info->mode)
  325. return 0;
  326. info->mode = mode;
  327. hds = mode->hsync_len + mode->left_margin;
  328. hde = hds + mode->xres;
  329. ht = hde + mode->right_margin;
  330. vds = mode->vsync_len + mode->upper_margin;
  331. vde = vds + mode->yres;
  332. vt = vde + mode->lower_margin;
  333. ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
  334. switch (pdata->bpp) {
  335. case 1:
  336. ctrl |= JZ_LCD_CTRL_BPP_1;
  337. break;
  338. case 2:
  339. ctrl |= JZ_LCD_CTRL_BPP_2;
  340. break;
  341. case 4:
  342. ctrl |= JZ_LCD_CTRL_BPP_4;
  343. break;
  344. case 8:
  345. ctrl |= JZ_LCD_CTRL_BPP_8;
  346. break;
  347. case 15:
  348. ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */
  349. case 16:
  350. ctrl |= JZ_LCD_CTRL_BPP_15_16;
  351. break;
  352. case 18:
  353. case 24:
  354. case 32:
  355. ctrl |= JZ_LCD_CTRL_BPP_18_24;
  356. break;
  357. default:
  358. break;
  359. }
  360. cfg = pdata->lcd_type & 0xf;
  361. if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
  362. cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
  363. if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
  364. cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
  365. if (pdata->pixclk_falling_edge)
  366. cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
  367. if (pdata->date_enable_active_low)
  368. cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
  369. if (pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT)
  370. cfg |= JZ_LCD_CFG_18_BIT;
  371. if (mode->pixclock) {
  372. rate = PICOS2KHZ(mode->pixclock) * 1000;
  373. mode->refresh = rate / vt / ht;
  374. } else {
  375. if (pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
  376. rate = mode->refresh * (vt + 2 * mode->xres) * ht;
  377. else
  378. rate = mode->refresh * vt * ht;
  379. mode->pixclock = KHZ2PICOS(rate / 1000);
  380. }
  381. mutex_lock(&jzfb->lock);
  382. if (!jzfb->is_enabled)
  383. clk_enable(jzfb->ldclk);
  384. else
  385. ctrl |= JZ_LCD_CTRL_ENABLE;
  386. switch (pdata->lcd_type) {
  387. case JZ_LCD_TYPE_SPECIAL_TFT_1:
  388. case JZ_LCD_TYPE_SPECIAL_TFT_2:
  389. case JZ_LCD_TYPE_SPECIAL_TFT_3:
  390. writel(pdata->special_tft_config.spl, jzfb->base + JZ_REG_LCD_SPL);
  391. writel(pdata->special_tft_config.cls, jzfb->base + JZ_REG_LCD_CLS);
  392. writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_PS);
  393. writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_REV);
  394. break;
  395. default:
  396. cfg |= JZ_LCD_CFG_PS_DISABLE;
  397. cfg |= JZ_LCD_CFG_CLS_DISABLE;
  398. cfg |= JZ_LCD_CFG_SPL_DISABLE;
  399. cfg |= JZ_LCD_CFG_REV_DISABLE;
  400. break;
  401. }
  402. writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC);
  403. writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC);
  404. writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT);
  405. writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH);
  406. writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV);
  407. writel(cfg, jzfb->base + JZ_REG_LCD_CFG);
  408. writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
  409. if (!jzfb->is_enabled)
  410. clk_disable_unprepare(jzfb->ldclk);
  411. mutex_unlock(&jzfb->lock);
  412. clk_set_rate(jzfb->lpclk, rate);
  413. clk_set_rate(jzfb->ldclk, rate * 3);
  414. return 0;
  415. }
  416. static void jzfb_enable(struct jzfb *jzfb)
  417. {
  418. uint32_t ctrl;
  419. clk_prepare_enable(jzfb->ldclk);
  420. jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
  421. jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
  422. writel(0, jzfb->base + JZ_REG_LCD_STATE);
  423. writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
  424. ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
  425. ctrl |= JZ_LCD_CTRL_ENABLE;
  426. ctrl &= ~JZ_LCD_CTRL_DISABLE;
  427. writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
  428. }
  429. static void jzfb_disable(struct jzfb *jzfb)
  430. {
  431. uint32_t ctrl;
  432. ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
  433. ctrl |= JZ_LCD_CTRL_DISABLE;
  434. writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
  435. do {
  436. ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
  437. } while (!(ctrl & JZ_LCD_STATE_DISABLED));
  438. jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
  439. jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
  440. clk_disable_unprepare(jzfb->ldclk);
  441. }
  442. static int jzfb_blank(int blank_mode, struct fb_info *info)
  443. {
  444. struct jzfb *jzfb = info->par;
  445. switch (blank_mode) {
  446. case FB_BLANK_UNBLANK:
  447. mutex_lock(&jzfb->lock);
  448. if (jzfb->is_enabled) {
  449. mutex_unlock(&jzfb->lock);
  450. return 0;
  451. }
  452. jzfb_enable(jzfb);
  453. jzfb->is_enabled = 1;
  454. mutex_unlock(&jzfb->lock);
  455. break;
  456. default:
  457. mutex_lock(&jzfb->lock);
  458. if (!jzfb->is_enabled) {
  459. mutex_unlock(&jzfb->lock);
  460. return 0;
  461. }
  462. jzfb_disable(jzfb);
  463. jzfb->is_enabled = 0;
  464. mutex_unlock(&jzfb->lock);
  465. break;
  466. }
  467. return 0;
  468. }
  469. static int jzfb_alloc_devmem(struct jzfb *jzfb)
  470. {
  471. int max_videosize = 0;
  472. struct fb_videomode *mode = jzfb->pdata->modes;
  473. void *page;
  474. int i;
  475. for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
  476. if (max_videosize < mode->xres * mode->yres)
  477. max_videosize = mode->xres * mode->yres;
  478. }
  479. max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3;
  480. jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
  481. sizeof(*jzfb->framedesc),
  482. &jzfb->framedesc_phys, GFP_KERNEL);
  483. if (!jzfb->framedesc)
  484. return -ENOMEM;
  485. jzfb->vidmem_size = PAGE_ALIGN(max_videosize);
  486. jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
  487. jzfb->vidmem_size,
  488. &jzfb->vidmem_phys, GFP_KERNEL);
  489. if (!jzfb->vidmem)
  490. goto err_free_framedesc;
  491. for (page = jzfb->vidmem;
  492. page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
  493. page += PAGE_SIZE) {
  494. SetPageReserved(virt_to_page(page));
  495. }
  496. jzfb->framedesc->next = jzfb->framedesc_phys;
  497. jzfb->framedesc->addr = jzfb->vidmem_phys;
  498. jzfb->framedesc->id = 0xdeafbead;
  499. jzfb->framedesc->cmd = 0;
  500. jzfb->framedesc->cmd |= max_videosize / 4;
  501. return 0;
  502. err_free_framedesc:
  503. dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
  504. jzfb->framedesc, jzfb->framedesc_phys);
  505. return -ENOMEM;
  506. }
  507. static void jzfb_free_devmem(struct jzfb *jzfb)
  508. {
  509. dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
  510. jzfb->vidmem, jzfb->vidmem_phys);
  511. dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
  512. jzfb->framedesc, jzfb->framedesc_phys);
  513. }
  514. static struct fb_ops jzfb_ops = {
  515. .owner = THIS_MODULE,
  516. .fb_check_var = jzfb_check_var,
  517. .fb_set_par = jzfb_set_par,
  518. .fb_blank = jzfb_blank,
  519. .fb_fillrect = sys_fillrect,
  520. .fb_copyarea = sys_copyarea,
  521. .fb_imageblit = sys_imageblit,
  522. .fb_setcolreg = jzfb_setcolreg,
  523. };
  524. static int jzfb_probe(struct platform_device *pdev)
  525. {
  526. int ret;
  527. struct jzfb *jzfb;
  528. struct fb_info *fb;
  529. struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
  530. struct resource *mem;
  531. if (!pdata) {
  532. dev_err(&pdev->dev, "Missing platform data\n");
  533. return -ENXIO;
  534. }
  535. fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
  536. if (!fb) {
  537. dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
  538. return -ENOMEM;
  539. }
  540. fb->fbops = &jzfb_ops;
  541. fb->flags = FBINFO_DEFAULT;
  542. jzfb = fb->par;
  543. jzfb->pdev = pdev;
  544. jzfb->pdata = pdata;
  545. jzfb->ldclk = devm_clk_get(&pdev->dev, "lcd");
  546. if (IS_ERR(jzfb->ldclk)) {
  547. ret = PTR_ERR(jzfb->ldclk);
  548. dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
  549. goto err_framebuffer_release;
  550. }
  551. jzfb->lpclk = devm_clk_get(&pdev->dev, "lcd_pclk");
  552. if (IS_ERR(jzfb->lpclk)) {
  553. ret = PTR_ERR(jzfb->lpclk);
  554. dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
  555. goto err_framebuffer_release;
  556. }
  557. mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  558. jzfb->base = devm_ioremap_resource(&pdev->dev, mem);
  559. if (IS_ERR(jzfb->base)) {
  560. ret = PTR_ERR(jzfb->base);
  561. goto err_framebuffer_release;
  562. }
  563. platform_set_drvdata(pdev, jzfb);
  564. mutex_init(&jzfb->lock);
  565. fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
  566. &fb->modelist);
  567. fb_videomode_to_var(&fb->var, pdata->modes);
  568. fb->var.bits_per_pixel = pdata->bpp;
  569. jzfb_check_var(&fb->var, fb);
  570. ret = jzfb_alloc_devmem(jzfb);
  571. if (ret) {
  572. dev_err(&pdev->dev, "Failed to allocate video memory\n");
  573. goto err_framebuffer_release;
  574. }
  575. fb->fix = jzfb_fix;
  576. fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
  577. fb->fix.mmio_start = mem->start;
  578. fb->fix.mmio_len = resource_size(mem);
  579. fb->fix.smem_start = jzfb->vidmem_phys;
  580. fb->fix.smem_len = fb->fix.line_length * fb->var.yres;
  581. fb->screen_base = jzfb->vidmem;
  582. fb->pseudo_palette = jzfb->pseudo_palette;
  583. fb_alloc_cmap(&fb->cmap, 256, 0);
  584. clk_prepare_enable(jzfb->ldclk);
  585. jzfb->is_enabled = 1;
  586. writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
  587. fb->mode = NULL;
  588. jzfb_set_par(fb);
  589. jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
  590. jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
  591. ret = register_framebuffer(fb);
  592. if (ret) {
  593. dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
  594. goto err_free_devmem;
  595. }
  596. jzfb->fb = fb;
  597. return 0;
  598. err_free_devmem:
  599. jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
  600. jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
  601. fb_dealloc_cmap(&fb->cmap);
  602. jzfb_free_devmem(jzfb);
  603. err_framebuffer_release:
  604. framebuffer_release(fb);
  605. return ret;
  606. }
  607. static int jzfb_remove(struct platform_device *pdev)
  608. {
  609. struct jzfb *jzfb = platform_get_drvdata(pdev);
  610. jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
  611. jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
  612. jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
  613. fb_dealloc_cmap(&jzfb->fb->cmap);
  614. jzfb_free_devmem(jzfb);
  615. framebuffer_release(jzfb->fb);
  616. return 0;
  617. }
  618. #ifdef CONFIG_PM
  619. static int jzfb_suspend(struct device *dev)
  620. {
  621. struct jzfb *jzfb = dev_get_drvdata(dev);
  622. console_lock();
  623. fb_set_suspend(jzfb->fb, 1);
  624. console_unlock();
  625. mutex_lock(&jzfb->lock);
  626. if (jzfb->is_enabled)
  627. jzfb_disable(jzfb);
  628. mutex_unlock(&jzfb->lock);
  629. return 0;
  630. }
  631. static int jzfb_resume(struct device *dev)
  632. {
  633. struct jzfb *jzfb = dev_get_drvdata(dev);
  634. clk_prepare_enable(jzfb->ldclk);
  635. mutex_lock(&jzfb->lock);
  636. if (jzfb->is_enabled)
  637. jzfb_enable(jzfb);
  638. mutex_unlock(&jzfb->lock);
  639. console_lock();
  640. fb_set_suspend(jzfb->fb, 0);
  641. console_unlock();
  642. return 0;
  643. }
  644. static const struct dev_pm_ops jzfb_pm_ops = {
  645. .suspend = jzfb_suspend,
  646. .resume = jzfb_resume,
  647. .poweroff = jzfb_suspend,
  648. .restore = jzfb_resume,
  649. };
  650. #define JZFB_PM_OPS (&jzfb_pm_ops)
  651. #else
  652. #define JZFB_PM_OPS NULL
  653. #endif
  654. static struct platform_driver jzfb_driver = {
  655. .probe = jzfb_probe,
  656. .remove = jzfb_remove,
  657. .driver = {
  658. .name = "jz4740-fb",
  659. .pm = JZFB_PM_OPS,
  660. },
  661. };
  662. module_platform_driver(jzfb_driver);
  663. MODULE_LICENSE("GPL");
  664. MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
  665. MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver");
  666. MODULE_ALIAS("platform:jz4740-fb");