pxa168fb.c 20 KB

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