pxa168fb.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. /*
  2. * linux/drivers/video/pxa168fb.c -- Marvell PXA168 LCD Controller
  3. *
  4. * Copyright (C) 2008 Marvell International Ltd.
  5. * All rights reserved.
  6. *
  7. * 2009-02-16 adapted from original version for PXA168/910
  8. * Jun Nie <njun@marvell.com>
  9. *
  10. * This file is subject to the terms and conditions of the GNU General Public
  11. * License. See the file COPYING in the main directory of this archive for
  12. * more details.
  13. */
  14. #include <linux/module.h>
  15. #include <linux/kernel.h>
  16. #include <linux/sched.h>
  17. #include <linux/string.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/slab.h>
  20. #include <linux/fb.h>
  21. #include <linux/delay.h>
  22. #include <linux/init.h>
  23. #include <linux/io.h>
  24. #include <linux/ioport.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/dma-mapping.h>
  27. #include <linux/clk.h>
  28. #include <linux/err.h>
  29. #include <linux/uaccess.h>
  30. #include <video/pxa168fb.h>
  31. #include "pxa168fb.h"
  32. #define DEFAULT_REFRESH 60 /* Hz */
  33. static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
  34. {
  35. /*
  36. * Pseudocolor mode?
  37. */
  38. if (var->bits_per_pixel == 8)
  39. return PIX_FMT_PSEUDOCOLOR;
  40. /*
  41. * Check for 565/1555.
  42. */
  43. if (var->bits_per_pixel == 16 && var->red.length <= 5 &&
  44. var->green.length <= 6 && var->blue.length <= 5) {
  45. if (var->transp.length == 0) {
  46. if (var->red.offset >= var->blue.offset)
  47. return PIX_FMT_RGB565;
  48. else
  49. return PIX_FMT_BGR565;
  50. }
  51. if (var->transp.length == 1 && var->green.length <= 5) {
  52. if (var->red.offset >= var->blue.offset)
  53. return PIX_FMT_RGB1555;
  54. else
  55. return PIX_FMT_BGR1555;
  56. }
  57. }
  58. /*
  59. * Check for 888/A888.
  60. */
  61. if (var->bits_per_pixel <= 32 && var->red.length <= 8 &&
  62. var->green.length <= 8 && var->blue.length <= 8) {
  63. if (var->bits_per_pixel == 24 && var->transp.length == 0) {
  64. if (var->red.offset >= var->blue.offset)
  65. return PIX_FMT_RGB888PACK;
  66. else
  67. return PIX_FMT_BGR888PACK;
  68. }
  69. if (var->bits_per_pixel == 32 && var->transp.length == 8) {
  70. if (var->red.offset >= var->blue.offset)
  71. return PIX_FMT_RGBA888;
  72. else
  73. return PIX_FMT_BGRA888;
  74. } else {
  75. if (var->red.offset >= var->blue.offset)
  76. return PIX_FMT_RGB888UNPACK;
  77. else
  78. return PIX_FMT_BGR888UNPACK;
  79. }
  80. }
  81. return -EINVAL;
  82. }
  83. static void set_pix_fmt(struct fb_var_screeninfo *var, int pix_fmt)
  84. {
  85. switch (pix_fmt) {
  86. case PIX_FMT_RGB565:
  87. var->bits_per_pixel = 16;
  88. var->red.offset = 11; var->red.length = 5;
  89. var->green.offset = 5; var->green.length = 6;
  90. var->blue.offset = 0; var->blue.length = 5;
  91. var->transp.offset = 0; var->transp.length = 0;
  92. break;
  93. case PIX_FMT_BGR565:
  94. var->bits_per_pixel = 16;
  95. var->red.offset = 0; var->red.length = 5;
  96. var->green.offset = 5; var->green.length = 6;
  97. var->blue.offset = 11; var->blue.length = 5;
  98. var->transp.offset = 0; var->transp.length = 0;
  99. break;
  100. case PIX_FMT_RGB1555:
  101. var->bits_per_pixel = 16;
  102. var->red.offset = 10; var->red.length = 5;
  103. var->green.offset = 5; var->green.length = 5;
  104. var->blue.offset = 0; var->blue.length = 5;
  105. var->transp.offset = 15; var->transp.length = 1;
  106. break;
  107. case PIX_FMT_BGR1555:
  108. var->bits_per_pixel = 16;
  109. var->red.offset = 0; var->red.length = 5;
  110. var->green.offset = 5; var->green.length = 5;
  111. var->blue.offset = 10; var->blue.length = 5;
  112. var->transp.offset = 15; var->transp.length = 1;
  113. break;
  114. case PIX_FMT_RGB888PACK:
  115. var->bits_per_pixel = 24;
  116. var->red.offset = 16; var->red.length = 8;
  117. var->green.offset = 8; var->green.length = 8;
  118. var->blue.offset = 0; var->blue.length = 8;
  119. var->transp.offset = 0; var->transp.length = 0;
  120. break;
  121. case PIX_FMT_BGR888PACK:
  122. var->bits_per_pixel = 24;
  123. var->red.offset = 0; var->red.length = 8;
  124. var->green.offset = 8; var->green.length = 8;
  125. var->blue.offset = 16; var->blue.length = 8;
  126. var->transp.offset = 0; var->transp.length = 0;
  127. break;
  128. case PIX_FMT_RGBA888:
  129. var->bits_per_pixel = 32;
  130. var->red.offset = 16; var->red.length = 8;
  131. var->green.offset = 8; var->green.length = 8;
  132. var->blue.offset = 0; var->blue.length = 8;
  133. var->transp.offset = 24; var->transp.length = 8;
  134. break;
  135. case PIX_FMT_BGRA888:
  136. var->bits_per_pixel = 32;
  137. var->red.offset = 0; var->red.length = 8;
  138. var->green.offset = 8; var->green.length = 8;
  139. var->blue.offset = 16; var->blue.length = 8;
  140. var->transp.offset = 24; var->transp.length = 8;
  141. break;
  142. case PIX_FMT_PSEUDOCOLOR:
  143. var->bits_per_pixel = 8;
  144. var->red.offset = 0; var->red.length = 8;
  145. var->green.offset = 0; var->green.length = 8;
  146. var->blue.offset = 0; var->blue.length = 8;
  147. var->transp.offset = 0; var->transp.length = 0;
  148. break;
  149. }
  150. }
  151. static void set_mode(struct pxa168fb_info *fbi, struct fb_var_screeninfo *var,
  152. struct fb_videomode *mode, int pix_fmt, int ystretch)
  153. {
  154. struct fb_info *info = fbi->info;
  155. set_pix_fmt(var, pix_fmt);
  156. var->xres = mode->xres;
  157. var->yres = mode->yres;
  158. var->xres_virtual = max(var->xres, var->xres_virtual);
  159. if (ystretch)
  160. var->yres_virtual = info->fix.smem_len /
  161. (var->xres_virtual * (var->bits_per_pixel >> 3));
  162. else
  163. var->yres_virtual = max(var->yres, var->yres_virtual);
  164. var->grayscale = 0;
  165. var->accel_flags = FB_ACCEL_NONE;
  166. var->pixclock = mode->pixclock;
  167. var->left_margin = mode->left_margin;
  168. var->right_margin = mode->right_margin;
  169. var->upper_margin = mode->upper_margin;
  170. var->lower_margin = mode->lower_margin;
  171. var->hsync_len = mode->hsync_len;
  172. var->vsync_len = mode->vsync_len;
  173. var->sync = mode->sync;
  174. var->vmode = FB_VMODE_NONINTERLACED;
  175. var->rotate = FB_ROTATE_UR;
  176. }
  177. static int pxa168fb_check_var(struct fb_var_screeninfo *var,
  178. struct fb_info *info)
  179. {
  180. struct pxa168fb_info *fbi = info->par;
  181. int pix_fmt;
  182. /*
  183. * Determine which pixel format we're going to use.
  184. */
  185. pix_fmt = determine_best_pix_fmt(var);
  186. if (pix_fmt < 0)
  187. return pix_fmt;
  188. set_pix_fmt(var, pix_fmt);
  189. fbi->pix_fmt = pix_fmt;
  190. /*
  191. * Basic geometry sanity checks.
  192. */
  193. if (var->xoffset + var->xres > var->xres_virtual)
  194. return -EINVAL;
  195. if (var->yoffset + var->yres > var->yres_virtual)
  196. return -EINVAL;
  197. if (var->xres + var->right_margin +
  198. var->hsync_len + var->left_margin > 2048)
  199. return -EINVAL;
  200. if (var->yres + var->lower_margin +
  201. var->vsync_len + var->upper_margin > 2048)
  202. return -EINVAL;
  203. /*
  204. * Check size of framebuffer.
  205. */
  206. if (var->xres_virtual * var->yres_virtual *
  207. (var->bits_per_pixel >> 3) > info->fix.smem_len)
  208. return -EINVAL;
  209. return 0;
  210. }
  211. /*
  212. * The hardware clock divider has an integer and a fractional
  213. * stage:
  214. *
  215. * clk2 = clk_in / integer_divider
  216. * clk_out = clk2 * (1 - (fractional_divider >> 12))
  217. *
  218. * Calculate integer and fractional divider for given clk_in
  219. * and clk_out.
  220. */
  221. static void set_clock_divider(struct pxa168fb_info *fbi,
  222. const struct fb_videomode *m)
  223. {
  224. int divider_int;
  225. int needed_pixclk;
  226. u64 div_result;
  227. u32 x = 0;
  228. /*
  229. * Notice: The field pixclock is used by linux fb
  230. * is in pixel second. E.g. struct fb_videomode &
  231. * struct fb_var_screeninfo
  232. */
  233. /*
  234. * Check input values.
  235. */
  236. if (!m || !m->pixclock || !m->refresh) {
  237. dev_err(fbi->dev, "Input refresh or pixclock is wrong.\n");
  238. return;
  239. }
  240. /*
  241. * Using PLL/AXI clock.
  242. */
  243. x = 0x80000000;
  244. /*
  245. * Calc divider according to refresh rate.
  246. */
  247. div_result = 1000000000000ll;
  248. do_div(div_result, m->pixclock);
  249. needed_pixclk = (u32)div_result;
  250. divider_int = clk_get_rate(fbi->clk) / needed_pixclk;
  251. /* check whether divisor is too small. */
  252. if (divider_int < 2) {
  253. dev_warn(fbi->dev, "Warning: clock source is too slow. "
  254. "Try smaller resolution\n");
  255. divider_int = 2;
  256. }
  257. /*
  258. * Set setting to reg.
  259. */
  260. x |= divider_int;
  261. writel(x, fbi->reg_base + LCD_CFG_SCLK_DIV);
  262. }
  263. static void set_dma_control0(struct pxa168fb_info *fbi)
  264. {
  265. u32 x;
  266. /*
  267. * Set bit to enable graphics DMA.
  268. */
  269. x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
  270. x &= ~CFG_GRA_ENA_MASK;
  271. x |= fbi->active ? CFG_GRA_ENA(1) : CFG_GRA_ENA(0);
  272. /*
  273. * If we are in a pseudo-color mode, we need to enable
  274. * palette lookup.
  275. */
  276. if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR)
  277. x |= 0x10000000;
  278. /*
  279. * Configure hardware pixel format.
  280. */
  281. x &= ~(0xF << 16);
  282. x |= (fbi->pix_fmt >> 1) << 16;
  283. /*
  284. * Check red and blue pixel swap.
  285. * 1. source data swap
  286. * 2. panel output data swap
  287. */
  288. x &= ~(1 << 12);
  289. x |= ((fbi->pix_fmt & 1) ^ (fbi->panel_rbswap)) << 12;
  290. writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL0);
  291. }
  292. static void set_dma_control1(struct pxa168fb_info *fbi, int sync)
  293. {
  294. u32 x;
  295. /*
  296. * Configure default bits: vsync triggers DMA, gated clock
  297. * enable, power save enable, configure alpha registers to
  298. * display 100% graphics, and set pixel command.
  299. */
  300. x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL1);
  301. x |= 0x2032ff81;
  302. /*
  303. * We trigger DMA on the falling edge of vsync if vsync is
  304. * active low, or on the rising edge if vsync is active high.
  305. */
  306. if (!(sync & FB_SYNC_VERT_HIGH_ACT))
  307. x |= 0x08000000;
  308. writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL1);
  309. }
  310. static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset)
  311. {
  312. struct pxa168fb_info *fbi = info->par;
  313. struct fb_var_screeninfo *var = &info->var;
  314. int pixel_offset;
  315. unsigned long addr;
  316. pixel_offset = (yoffset * var->xres_virtual) + xoffset;
  317. addr = fbi->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3));
  318. writel(addr, fbi->reg_base + LCD_CFG_GRA_START_ADDR0);
  319. }
  320. static void set_dumb_panel_control(struct fb_info *info)
  321. {
  322. struct pxa168fb_info *fbi = info->par;
  323. struct pxa168fb_mach_info *mi = dev_get_platdata(fbi->dev);
  324. u32 x;
  325. /*
  326. * Preserve enable flag.
  327. */
  328. x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL) & 0x00000001;
  329. x |= (fbi->is_blanked ? 0x7 : mi->dumb_mode) << 28;
  330. x |= mi->gpio_output_data << 20;
  331. x |= mi->gpio_output_mask << 12;
  332. x |= mi->panel_rgb_reverse_lanes ? 0x00000080 : 0;
  333. x |= mi->invert_composite_blank ? 0x00000040 : 0;
  334. x |= (info->var.sync & FB_SYNC_COMP_HIGH_ACT) ? 0x00000020 : 0;
  335. x |= mi->invert_pix_val_ena ? 0x00000010 : 0;
  336. x |= (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x00000008;
  337. x |= (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x00000004;
  338. x |= mi->invert_pixclock ? 0x00000002 : 0;
  339. writel(x, fbi->reg_base + LCD_SPU_DUMB_CTRL);
  340. }
  341. static void set_dumb_screen_dimensions(struct fb_info *info)
  342. {
  343. struct pxa168fb_info *fbi = info->par;
  344. struct fb_var_screeninfo *v = &info->var;
  345. int x;
  346. int y;
  347. x = v->xres + v->right_margin + v->hsync_len + v->left_margin;
  348. y = v->yres + v->lower_margin + v->vsync_len + v->upper_margin;
  349. writel((y << 16) | x, fbi->reg_base + LCD_SPUT_V_H_TOTAL);
  350. }
  351. static int pxa168fb_set_par(struct fb_info *info)
  352. {
  353. struct pxa168fb_info *fbi = info->par;
  354. struct fb_var_screeninfo *var = &info->var;
  355. struct fb_videomode mode;
  356. u32 x;
  357. /*
  358. * Set additional mode info.
  359. */
  360. if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR)
  361. info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
  362. else
  363. info->fix.visual = FB_VISUAL_TRUECOLOR;
  364. info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
  365. info->fix.ypanstep = var->yres;
  366. /*
  367. * Disable panel output while we setup the display.
  368. */
  369. x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL);
  370. writel(x & ~1, fbi->reg_base + LCD_SPU_DUMB_CTRL);
  371. /*
  372. * Configure global panel parameters.
  373. */
  374. writel((var->yres << 16) | var->xres,
  375. fbi->reg_base + LCD_SPU_V_H_ACTIVE);
  376. /*
  377. * convet var to video mode
  378. */
  379. fb_var_to_videomode(&mode, &info->var);
  380. /* Calculate clock divisor. */
  381. set_clock_divider(fbi, &mode);
  382. /* Configure dma ctrl regs. */
  383. set_dma_control0(fbi);
  384. set_dma_control1(fbi, info->var.sync);
  385. /*
  386. * Configure graphics DMA parameters.
  387. */
  388. x = readl(fbi->reg_base + LCD_CFG_GRA_PITCH);
  389. x = (x & ~0xFFFF) | ((var->xres_virtual * var->bits_per_pixel) >> 3);
  390. writel(x, fbi->reg_base + LCD_CFG_GRA_PITCH);
  391. writel((var->yres << 16) | var->xres,
  392. fbi->reg_base + LCD_SPU_GRA_HPXL_VLN);
  393. writel((var->yres << 16) | var->xres,
  394. fbi->reg_base + LCD_SPU_GZM_HPXL_VLN);
  395. /*
  396. * Configure dumb panel ctrl regs & timings.
  397. */
  398. set_dumb_panel_control(info);
  399. set_dumb_screen_dimensions(info);
  400. writel((var->left_margin << 16) | var->right_margin,
  401. fbi->reg_base + LCD_SPU_H_PORCH);
  402. writel((var->upper_margin << 16) | var->lower_margin,
  403. fbi->reg_base + LCD_SPU_V_PORCH);
  404. /*
  405. * Re-enable panel output.
  406. */
  407. x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL);
  408. writel(x | 1, fbi->reg_base + LCD_SPU_DUMB_CTRL);
  409. return 0;
  410. }
  411. static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
  412. {
  413. return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
  414. }
  415. static u32 to_rgb(u16 red, u16 green, u16 blue)
  416. {
  417. red >>= 8;
  418. green >>= 8;
  419. blue >>= 8;
  420. return (red << 16) | (green << 8) | blue;
  421. }
  422. static int
  423. pxa168fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
  424. unsigned int blue, unsigned int trans, struct fb_info *info)
  425. {
  426. struct pxa168fb_info *fbi = info->par;
  427. u32 val;
  428. if (info->var.grayscale)
  429. red = green = blue = (19595 * red + 38470 * green +
  430. 7471 * blue) >> 16;
  431. if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) {
  432. val = chan_to_field(red, &info->var.red);
  433. val |= chan_to_field(green, &info->var.green);
  434. val |= chan_to_field(blue , &info->var.blue);
  435. fbi->pseudo_palette[regno] = val;
  436. }
  437. if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
  438. val = to_rgb(red, green, blue);
  439. writel(val, fbi->reg_base + LCD_SPU_SRAM_WRDAT);
  440. writel(0x8300 | regno, fbi->reg_base + LCD_SPU_SRAM_CTRL);
  441. }
  442. return 0;
  443. }
  444. static int pxa168fb_blank(int blank, struct fb_info *info)
  445. {
  446. struct pxa168fb_info *fbi = info->par;
  447. fbi->is_blanked = (blank == FB_BLANK_UNBLANK) ? 0 : 1;
  448. set_dumb_panel_control(info);
  449. return 0;
  450. }
  451. static int pxa168fb_pan_display(struct fb_var_screeninfo *var,
  452. struct fb_info *info)
  453. {
  454. set_graphics_start(info, var->xoffset, var->yoffset);
  455. return 0;
  456. }
  457. static irqreturn_t pxa168fb_handle_irq(int irq, void *dev_id)
  458. {
  459. struct pxa168fb_info *fbi = dev_id;
  460. u32 isr = readl(fbi->reg_base + SPU_IRQ_ISR);
  461. if ((isr & GRA_FRAME_IRQ0_ENA_MASK)) {
  462. writel(isr & (~GRA_FRAME_IRQ0_ENA_MASK),
  463. fbi->reg_base + SPU_IRQ_ISR);
  464. return IRQ_HANDLED;
  465. }
  466. return IRQ_NONE;
  467. }
  468. static const struct fb_ops pxa168fb_ops = {
  469. .owner = THIS_MODULE,
  470. FB_DEFAULT_IOMEM_OPS,
  471. .fb_check_var = pxa168fb_check_var,
  472. .fb_set_par = pxa168fb_set_par,
  473. .fb_setcolreg = pxa168fb_setcolreg,
  474. .fb_blank = pxa168fb_blank,
  475. .fb_pan_display = pxa168fb_pan_display,
  476. };
  477. static void pxa168fb_init_mode(struct fb_info *info,
  478. struct pxa168fb_mach_info *mi)
  479. {
  480. struct pxa168fb_info *fbi = info->par;
  481. struct fb_var_screeninfo *var = &info->var;
  482. u32 total_w, total_h, refresh;
  483. u64 div_result;
  484. const struct fb_videomode *m;
  485. /*
  486. * Set default value
  487. */
  488. refresh = DEFAULT_REFRESH;
  489. /* try to find best video mode. */
  490. m = fb_find_best_mode(&info->var, &info->modelist);
  491. if (m)
  492. fb_videomode_to_var(&info->var, m);
  493. /* Init settings. */
  494. var->xres_virtual = var->xres;
  495. var->yres_virtual = info->fix.smem_len /
  496. (var->xres_virtual * (var->bits_per_pixel >> 3));
  497. dev_dbg(fbi->dev, "pxa168fb: find best mode: res = %dx%d\n",
  498. var->xres, var->yres);
  499. /* correct pixclock. */
  500. total_w = var->xres + var->left_margin + var->right_margin +
  501. var->hsync_len;
  502. total_h = var->yres + var->upper_margin + var->lower_margin +
  503. var->vsync_len;
  504. div_result = 1000000000000ll;
  505. do_div(div_result, total_w * total_h * refresh);
  506. var->pixclock = (u32)div_result;
  507. }
  508. static int pxa168fb_probe(struct platform_device *pdev)
  509. {
  510. struct pxa168fb_mach_info *mi;
  511. struct fb_info *info = NULL;
  512. struct pxa168fb_info *fbi = NULL;
  513. struct resource *res;
  514. struct clk *clk;
  515. int irq, ret;
  516. mi = dev_get_platdata(&pdev->dev);
  517. if (mi == NULL) {
  518. dev_err(&pdev->dev, "no platform data defined\n");
  519. return -EINVAL;
  520. }
  521. clk = devm_clk_get(&pdev->dev, "LCDCLK");
  522. if (IS_ERR(clk))
  523. return dev_err_probe(&pdev->dev, PTR_ERR(clk),
  524. "unable to get LCDCLK");
  525. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  526. if (res == NULL) {
  527. dev_err(&pdev->dev, "no IO memory defined\n");
  528. return -ENOENT;
  529. }
  530. irq = platform_get_irq(pdev, 0);
  531. if (irq < 0)
  532. return -ENOENT;
  533. info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev);
  534. if (info == NULL) {
  535. return -ENOMEM;
  536. }
  537. /* Initialize private data */
  538. fbi = info->par;
  539. fbi->info = info;
  540. fbi->clk = clk;
  541. fbi->dev = &pdev->dev;
  542. fbi->panel_rbswap = mi->panel_rbswap;
  543. fbi->is_blanked = 0;
  544. fbi->active = mi->active;
  545. /*
  546. * Initialise static fb parameters.
  547. */
  548. info->flags = FBINFO_PARTIAL_PAN_OK |
  549. FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
  550. info->node = -1;
  551. strscpy(info->fix.id, mi->id, 16);
  552. info->fix.type = FB_TYPE_PACKED_PIXELS;
  553. info->fix.type_aux = 0;
  554. info->fix.xpanstep = 0;
  555. info->fix.ypanstep = 0;
  556. info->fix.ywrapstep = 0;
  557. info->fix.mmio_start = res->start;
  558. info->fix.mmio_len = resource_size(res);
  559. info->fix.accel = FB_ACCEL_NONE;
  560. info->fbops = &pxa168fb_ops;
  561. info->pseudo_palette = fbi->pseudo_palette;
  562. /*
  563. * Map LCD controller registers.
  564. */
  565. fbi->reg_base = devm_ioremap(&pdev->dev, res->start,
  566. resource_size(res));
  567. if (fbi->reg_base == NULL) {
  568. ret = -ENOMEM;
  569. goto failed_free_info;
  570. }
  571. /*
  572. * Allocate framebuffer memory.
  573. */
  574. info->fix.smem_len = PAGE_ALIGN(DEFAULT_FB_SIZE);
  575. info->screen_base = dma_alloc_wc(fbi->dev, info->fix.smem_len,
  576. &fbi->fb_start_dma, GFP_KERNEL);
  577. if (info->screen_base == NULL) {
  578. ret = -ENOMEM;
  579. goto failed_free_info;
  580. }
  581. info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
  582. set_graphics_start(info, 0, 0);
  583. /*
  584. * Set video mode according to platform data.
  585. */
  586. set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1);
  587. fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist);
  588. /*
  589. * init video mode data.
  590. */
  591. pxa168fb_init_mode(info, mi);
  592. /*
  593. * Fill in sane defaults.
  594. */
  595. ret = pxa168fb_check_var(&info->var, info);
  596. if (ret)
  597. goto failed_free_fbmem;
  598. /*
  599. * enable controller clock
  600. */
  601. clk_prepare_enable(fbi->clk);
  602. pxa168fb_set_par(info);
  603. /*
  604. * Configure default register values.
  605. */
  606. writel(0, fbi->reg_base + LCD_SPU_BLANKCOLOR);
  607. writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL);
  608. writel(0, fbi->reg_base + LCD_CFG_GRA_START_ADDR1);
  609. writel(0, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN);
  610. writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
  611. writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
  612. fbi->reg_base + LCD_SPU_SRAM_PARA1);
  613. /*
  614. * Allocate color map.
  615. */
  616. if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
  617. ret = -ENOMEM;
  618. goto failed_free_clk;
  619. }
  620. /*
  621. * Register irq handler.
  622. */
  623. ret = devm_request_irq(&pdev->dev, irq, pxa168fb_handle_irq,
  624. IRQF_SHARED, info->fix.id, fbi);
  625. if (ret < 0) {
  626. dev_err(&pdev->dev, "unable to request IRQ\n");
  627. ret = -ENXIO;
  628. goto failed_free_cmap;
  629. }
  630. /*
  631. * Enable GFX interrupt
  632. */
  633. writel(GRA_FRAME_IRQ0_ENA(0x1), fbi->reg_base + SPU_IRQ_ENA);
  634. /*
  635. * Register framebuffer.
  636. */
  637. ret = register_framebuffer(info);
  638. if (ret < 0) {
  639. dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret);
  640. ret = -ENXIO;
  641. goto failed_free_cmap;
  642. }
  643. platform_set_drvdata(pdev, fbi);
  644. return 0;
  645. failed_free_cmap:
  646. fb_dealloc_cmap(&info->cmap);
  647. failed_free_clk:
  648. clk_disable_unprepare(fbi->clk);
  649. failed_free_fbmem:
  650. dma_free_wc(fbi->dev, info->fix.smem_len,
  651. info->screen_base, fbi->fb_start_dma);
  652. failed_free_info:
  653. framebuffer_release(info);
  654. dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret);
  655. return ret;
  656. }
  657. static void pxa168fb_remove(struct platform_device *pdev)
  658. {
  659. struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
  660. struct fb_info *info;
  661. unsigned int data;
  662. if (!fbi)
  663. return;
  664. /* disable DMA transfer */
  665. data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
  666. data &= ~CFG_GRA_ENA_MASK;
  667. writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0);
  668. info = fbi->info;
  669. unregister_framebuffer(info);
  670. writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA);
  671. if (info->cmap.len)
  672. fb_dealloc_cmap(&info->cmap);
  673. dma_free_wc(fbi->dev, info->fix.smem_len,
  674. info->screen_base, info->fix.smem_start);
  675. clk_disable_unprepare(fbi->clk);
  676. framebuffer_release(info);
  677. }
  678. static struct platform_driver pxa168fb_driver = {
  679. .driver = {
  680. .name = "pxa168-fb",
  681. },
  682. .probe = pxa168fb_probe,
  683. .remove = pxa168fb_remove,
  684. };
  685. module_platform_driver(pxa168fb_driver);
  686. MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
  687. "Green Wan <gwan@marvell.com>");
  688. MODULE_DESCRIPTION("Framebuffer driver for PXA168/910");
  689. MODULE_LICENSE("GPL");