jz4740_fb.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  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/pinctrl/consumer.h>
  20. #include <linux/clk.h>
  21. #include <linux/delay.h>
  22. #include <linux/console.h>
  23. #include <linux/fb.h>
  24. #include <linux/dma-mapping.h>
  25. #include <asm/mach-jz4740/jz4740_fb.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. /* Based on CNVT_TOHW macro from skeletonfb.c */
  131. static inline uint32_t jzfb_convert_color_to_hw(unsigned val,
  132. struct fb_bitfield *bf)
  133. {
  134. return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset;
  135. }
  136. static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
  137. unsigned blue, unsigned transp, struct fb_info *fb)
  138. {
  139. uint32_t color;
  140. if (regno >= 16)
  141. return -EINVAL;
  142. color = jzfb_convert_color_to_hw(red, &fb->var.red);
  143. color |= jzfb_convert_color_to_hw(green, &fb->var.green);
  144. color |= jzfb_convert_color_to_hw(blue, &fb->var.blue);
  145. color |= jzfb_convert_color_to_hw(transp, &fb->var.transp);
  146. ((uint32_t *)(fb->pseudo_palette))[regno] = color;
  147. return 0;
  148. }
  149. static int jzfb_get_controller_bpp(struct jzfb *jzfb)
  150. {
  151. switch (jzfb->pdata->bpp) {
  152. case 18:
  153. case 24:
  154. return 32;
  155. case 15:
  156. return 16;
  157. default:
  158. return jzfb->pdata->bpp;
  159. }
  160. }
  161. static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb,
  162. struct fb_var_screeninfo *var)
  163. {
  164. size_t i;
  165. struct fb_videomode *mode = jzfb->pdata->modes;
  166. for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
  167. if (mode->xres == var->xres && mode->yres == var->yres)
  168. return mode;
  169. }
  170. return NULL;
  171. }
  172. static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
  173. {
  174. struct jzfb *jzfb = fb->par;
  175. struct fb_videomode *mode;
  176. if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
  177. var->bits_per_pixel != jzfb->pdata->bpp)
  178. return -EINVAL;
  179. mode = jzfb_get_mode(jzfb, var);
  180. if (mode == NULL)
  181. return -EINVAL;
  182. fb_videomode_to_var(var, mode);
  183. switch (jzfb->pdata->bpp) {
  184. case 8:
  185. break;
  186. case 15:
  187. var->red.offset = 10;
  188. var->red.length = 5;
  189. var->green.offset = 6;
  190. var->green.length = 5;
  191. var->blue.offset = 0;
  192. var->blue.length = 5;
  193. break;
  194. case 16:
  195. var->red.offset = 11;
  196. var->red.length = 5;
  197. var->green.offset = 5;
  198. var->green.length = 6;
  199. var->blue.offset = 0;
  200. var->blue.length = 5;
  201. break;
  202. case 18:
  203. var->red.offset = 16;
  204. var->red.length = 6;
  205. var->green.offset = 8;
  206. var->green.length = 6;
  207. var->blue.offset = 0;
  208. var->blue.length = 6;
  209. var->bits_per_pixel = 32;
  210. break;
  211. case 32:
  212. case 24:
  213. var->transp.offset = 24;
  214. var->transp.length = 8;
  215. var->red.offset = 16;
  216. var->red.length = 8;
  217. var->green.offset = 8;
  218. var->green.length = 8;
  219. var->blue.offset = 0;
  220. var->blue.length = 8;
  221. var->bits_per_pixel = 32;
  222. break;
  223. default:
  224. break;
  225. }
  226. return 0;
  227. }
  228. static int jzfb_set_par(struct fb_info *info)
  229. {
  230. struct jzfb *jzfb = info->par;
  231. struct jz4740_fb_platform_data *pdata = jzfb->pdata;
  232. struct fb_var_screeninfo *var = &info->var;
  233. struct fb_videomode *mode;
  234. uint16_t hds, vds;
  235. uint16_t hde, vde;
  236. uint16_t ht, vt;
  237. uint32_t ctrl;
  238. uint32_t cfg;
  239. unsigned long rate;
  240. mode = jzfb_get_mode(jzfb, var);
  241. if (mode == NULL)
  242. return -EINVAL;
  243. if (mode == info->mode)
  244. return 0;
  245. info->mode = mode;
  246. hds = mode->hsync_len + mode->left_margin;
  247. hde = hds + mode->xres;
  248. ht = hde + mode->right_margin;
  249. vds = mode->vsync_len + mode->upper_margin;
  250. vde = vds + mode->yres;
  251. vt = vde + mode->lower_margin;
  252. ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
  253. switch (pdata->bpp) {
  254. case 1:
  255. ctrl |= JZ_LCD_CTRL_BPP_1;
  256. break;
  257. case 2:
  258. ctrl |= JZ_LCD_CTRL_BPP_2;
  259. break;
  260. case 4:
  261. ctrl |= JZ_LCD_CTRL_BPP_4;
  262. break;
  263. case 8:
  264. ctrl |= JZ_LCD_CTRL_BPP_8;
  265. break;
  266. case 15:
  267. ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */
  268. case 16:
  269. ctrl |= JZ_LCD_CTRL_BPP_15_16;
  270. break;
  271. case 18:
  272. case 24:
  273. case 32:
  274. ctrl |= JZ_LCD_CTRL_BPP_18_24;
  275. break;
  276. default:
  277. break;
  278. }
  279. cfg = pdata->lcd_type & 0xf;
  280. if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
  281. cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
  282. if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
  283. cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
  284. if (pdata->pixclk_falling_edge)
  285. cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
  286. if (pdata->date_enable_active_low)
  287. cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
  288. if (pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT)
  289. cfg |= JZ_LCD_CFG_18_BIT;
  290. if (mode->pixclock) {
  291. rate = PICOS2KHZ(mode->pixclock) * 1000;
  292. mode->refresh = rate / vt / ht;
  293. } else {
  294. if (pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
  295. rate = mode->refresh * (vt + 2 * mode->xres) * ht;
  296. else
  297. rate = mode->refresh * vt * ht;
  298. mode->pixclock = KHZ2PICOS(rate / 1000);
  299. }
  300. mutex_lock(&jzfb->lock);
  301. if (!jzfb->is_enabled)
  302. clk_enable(jzfb->ldclk);
  303. else
  304. ctrl |= JZ_LCD_CTRL_ENABLE;
  305. switch (pdata->lcd_type) {
  306. case JZ_LCD_TYPE_SPECIAL_TFT_1:
  307. case JZ_LCD_TYPE_SPECIAL_TFT_2:
  308. case JZ_LCD_TYPE_SPECIAL_TFT_3:
  309. writel(pdata->special_tft_config.spl, jzfb->base + JZ_REG_LCD_SPL);
  310. writel(pdata->special_tft_config.cls, jzfb->base + JZ_REG_LCD_CLS);
  311. writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_PS);
  312. writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_REV);
  313. break;
  314. default:
  315. cfg |= JZ_LCD_CFG_PS_DISABLE;
  316. cfg |= JZ_LCD_CFG_CLS_DISABLE;
  317. cfg |= JZ_LCD_CFG_SPL_DISABLE;
  318. cfg |= JZ_LCD_CFG_REV_DISABLE;
  319. break;
  320. }
  321. writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC);
  322. writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC);
  323. writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT);
  324. writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH);
  325. writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV);
  326. writel(cfg, jzfb->base + JZ_REG_LCD_CFG);
  327. writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
  328. if (!jzfb->is_enabled)
  329. clk_disable_unprepare(jzfb->ldclk);
  330. mutex_unlock(&jzfb->lock);
  331. clk_set_rate(jzfb->lpclk, rate);
  332. clk_set_rate(jzfb->ldclk, rate * 3);
  333. return 0;
  334. }
  335. static void jzfb_enable(struct jzfb *jzfb)
  336. {
  337. uint32_t ctrl;
  338. clk_prepare_enable(jzfb->ldclk);
  339. pinctrl_pm_select_default_state(&jzfb->pdev->dev);
  340. writel(0, jzfb->base + JZ_REG_LCD_STATE);
  341. writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
  342. ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
  343. ctrl |= JZ_LCD_CTRL_ENABLE;
  344. ctrl &= ~JZ_LCD_CTRL_DISABLE;
  345. writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
  346. }
  347. static void jzfb_disable(struct jzfb *jzfb)
  348. {
  349. uint32_t ctrl;
  350. ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
  351. ctrl |= JZ_LCD_CTRL_DISABLE;
  352. writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
  353. do {
  354. ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
  355. } while (!(ctrl & JZ_LCD_STATE_DISABLED));
  356. pinctrl_pm_select_sleep_state(&jzfb->pdev->dev);
  357. clk_disable_unprepare(jzfb->ldclk);
  358. }
  359. static int jzfb_blank(int blank_mode, struct fb_info *info)
  360. {
  361. struct jzfb *jzfb = info->par;
  362. switch (blank_mode) {
  363. case FB_BLANK_UNBLANK:
  364. mutex_lock(&jzfb->lock);
  365. if (jzfb->is_enabled) {
  366. mutex_unlock(&jzfb->lock);
  367. return 0;
  368. }
  369. jzfb_enable(jzfb);
  370. jzfb->is_enabled = 1;
  371. mutex_unlock(&jzfb->lock);
  372. break;
  373. default:
  374. mutex_lock(&jzfb->lock);
  375. if (!jzfb->is_enabled) {
  376. mutex_unlock(&jzfb->lock);
  377. return 0;
  378. }
  379. jzfb_disable(jzfb);
  380. jzfb->is_enabled = 0;
  381. mutex_unlock(&jzfb->lock);
  382. break;
  383. }
  384. return 0;
  385. }
  386. static int jzfb_alloc_devmem(struct jzfb *jzfb)
  387. {
  388. int max_videosize = 0;
  389. struct fb_videomode *mode = jzfb->pdata->modes;
  390. void *page;
  391. int i;
  392. for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
  393. if (max_videosize < mode->xres * mode->yres)
  394. max_videosize = mode->xres * mode->yres;
  395. }
  396. max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3;
  397. jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
  398. sizeof(*jzfb->framedesc),
  399. &jzfb->framedesc_phys, GFP_KERNEL);
  400. if (!jzfb->framedesc)
  401. return -ENOMEM;
  402. jzfb->vidmem_size = PAGE_ALIGN(max_videosize);
  403. jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
  404. jzfb->vidmem_size,
  405. &jzfb->vidmem_phys, GFP_KERNEL);
  406. if (!jzfb->vidmem)
  407. goto err_free_framedesc;
  408. for (page = jzfb->vidmem;
  409. page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
  410. page += PAGE_SIZE) {
  411. SetPageReserved(virt_to_page(page));
  412. }
  413. jzfb->framedesc->next = jzfb->framedesc_phys;
  414. jzfb->framedesc->addr = jzfb->vidmem_phys;
  415. jzfb->framedesc->id = 0xdeafbead;
  416. jzfb->framedesc->cmd = 0;
  417. jzfb->framedesc->cmd |= max_videosize / 4;
  418. return 0;
  419. err_free_framedesc:
  420. dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
  421. jzfb->framedesc, jzfb->framedesc_phys);
  422. return -ENOMEM;
  423. }
  424. static void jzfb_free_devmem(struct jzfb *jzfb)
  425. {
  426. dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
  427. jzfb->vidmem, jzfb->vidmem_phys);
  428. dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
  429. jzfb->framedesc, jzfb->framedesc_phys);
  430. }
  431. static struct fb_ops jzfb_ops = {
  432. .owner = THIS_MODULE,
  433. .fb_check_var = jzfb_check_var,
  434. .fb_set_par = jzfb_set_par,
  435. .fb_blank = jzfb_blank,
  436. .fb_fillrect = sys_fillrect,
  437. .fb_copyarea = sys_copyarea,
  438. .fb_imageblit = sys_imageblit,
  439. .fb_setcolreg = jzfb_setcolreg,
  440. };
  441. static int jzfb_probe(struct platform_device *pdev)
  442. {
  443. int ret;
  444. struct jzfb *jzfb;
  445. struct fb_info *fb;
  446. struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
  447. struct resource *mem;
  448. if (!pdata) {
  449. dev_err(&pdev->dev, "Missing platform data\n");
  450. return -ENXIO;
  451. }
  452. fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
  453. if (!fb) {
  454. dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
  455. return -ENOMEM;
  456. }
  457. fb->fbops = &jzfb_ops;
  458. fb->flags = FBINFO_DEFAULT;
  459. jzfb = fb->par;
  460. jzfb->pdev = pdev;
  461. jzfb->pdata = pdata;
  462. jzfb->ldclk = devm_clk_get(&pdev->dev, "lcd");
  463. if (IS_ERR(jzfb->ldclk)) {
  464. ret = PTR_ERR(jzfb->ldclk);
  465. dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
  466. goto err_framebuffer_release;
  467. }
  468. jzfb->lpclk = devm_clk_get(&pdev->dev, "lcd_pclk");
  469. if (IS_ERR(jzfb->lpclk)) {
  470. ret = PTR_ERR(jzfb->lpclk);
  471. dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
  472. goto err_framebuffer_release;
  473. }
  474. mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  475. jzfb->base = devm_ioremap_resource(&pdev->dev, mem);
  476. if (IS_ERR(jzfb->base)) {
  477. ret = PTR_ERR(jzfb->base);
  478. goto err_framebuffer_release;
  479. }
  480. platform_set_drvdata(pdev, jzfb);
  481. mutex_init(&jzfb->lock);
  482. fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
  483. &fb->modelist);
  484. fb_videomode_to_var(&fb->var, pdata->modes);
  485. fb->var.bits_per_pixel = pdata->bpp;
  486. jzfb_check_var(&fb->var, fb);
  487. ret = jzfb_alloc_devmem(jzfb);
  488. if (ret) {
  489. dev_err(&pdev->dev, "Failed to allocate video memory\n");
  490. goto err_framebuffer_release;
  491. }
  492. fb->fix = jzfb_fix;
  493. fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
  494. fb->fix.mmio_start = mem->start;
  495. fb->fix.mmio_len = resource_size(mem);
  496. fb->fix.smem_start = jzfb->vidmem_phys;
  497. fb->fix.smem_len = fb->fix.line_length * fb->var.yres;
  498. fb->screen_base = jzfb->vidmem;
  499. fb->pseudo_palette = jzfb->pseudo_palette;
  500. fb_alloc_cmap(&fb->cmap, 256, 0);
  501. clk_prepare_enable(jzfb->ldclk);
  502. jzfb->is_enabled = 1;
  503. writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
  504. fb->mode = NULL;
  505. jzfb_set_par(fb);
  506. ret = register_framebuffer(fb);
  507. if (ret) {
  508. dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
  509. goto err_free_devmem;
  510. }
  511. jzfb->fb = fb;
  512. return 0;
  513. err_free_devmem:
  514. fb_dealloc_cmap(&fb->cmap);
  515. jzfb_free_devmem(jzfb);
  516. err_framebuffer_release:
  517. framebuffer_release(fb);
  518. return ret;
  519. }
  520. static int jzfb_remove(struct platform_device *pdev)
  521. {
  522. struct jzfb *jzfb = platform_get_drvdata(pdev);
  523. jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
  524. fb_dealloc_cmap(&jzfb->fb->cmap);
  525. jzfb_free_devmem(jzfb);
  526. framebuffer_release(jzfb->fb);
  527. return 0;
  528. }
  529. #ifdef CONFIG_PM
  530. static int jzfb_suspend(struct device *dev)
  531. {
  532. struct jzfb *jzfb = dev_get_drvdata(dev);
  533. console_lock();
  534. fb_set_suspend(jzfb->fb, 1);
  535. console_unlock();
  536. mutex_lock(&jzfb->lock);
  537. if (jzfb->is_enabled)
  538. jzfb_disable(jzfb);
  539. mutex_unlock(&jzfb->lock);
  540. return 0;
  541. }
  542. static int jzfb_resume(struct device *dev)
  543. {
  544. struct jzfb *jzfb = dev_get_drvdata(dev);
  545. clk_prepare_enable(jzfb->ldclk);
  546. mutex_lock(&jzfb->lock);
  547. if (jzfb->is_enabled)
  548. jzfb_enable(jzfb);
  549. mutex_unlock(&jzfb->lock);
  550. console_lock();
  551. fb_set_suspend(jzfb->fb, 0);
  552. console_unlock();
  553. return 0;
  554. }
  555. static const struct dev_pm_ops jzfb_pm_ops = {
  556. .suspend = jzfb_suspend,
  557. .resume = jzfb_resume,
  558. .poweroff = jzfb_suspend,
  559. .restore = jzfb_resume,
  560. };
  561. #define JZFB_PM_OPS (&jzfb_pm_ops)
  562. #else
  563. #define JZFB_PM_OPS NULL
  564. #endif
  565. static struct platform_driver jzfb_driver = {
  566. .probe = jzfb_probe,
  567. .remove = jzfb_remove,
  568. .driver = {
  569. .name = "jz4740-fb",
  570. .pm = JZFB_PM_OPS,
  571. },
  572. };
  573. module_platform_driver(jzfb_driver);
  574. MODULE_LICENSE("GPL");
  575. MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
  576. MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver");
  577. MODULE_ALIAS("platform:jz4740-fb");