pxa168fb.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  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 <[email protected]>
  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_check_var = pxa168fb_check_var,
  471. .fb_set_par = pxa168fb_set_par,
  472. .fb_setcolreg = pxa168fb_setcolreg,
  473. .fb_blank = pxa168fb_blank,
  474. .fb_pan_display = pxa168fb_pan_display,
  475. .fb_fillrect = cfb_fillrect,
  476. .fb_copyarea = cfb_copyarea,
  477. .fb_imageblit = cfb_imageblit,
  478. };
  479. static void pxa168fb_init_mode(struct fb_info *info,
  480. struct pxa168fb_mach_info *mi)
  481. {
  482. struct pxa168fb_info *fbi = info->par;
  483. struct fb_var_screeninfo *var = &info->var;
  484. u32 total_w, total_h, refresh;
  485. u64 div_result;
  486. const struct fb_videomode *m;
  487. /*
  488. * Set default value
  489. */
  490. refresh = DEFAULT_REFRESH;
  491. /* try to find best video mode. */
  492. m = fb_find_best_mode(&info->var, &info->modelist);
  493. if (m)
  494. fb_videomode_to_var(&info->var, m);
  495. /* Init settings. */
  496. var->xres_virtual = var->xres;
  497. var->yres_virtual = info->fix.smem_len /
  498. (var->xres_virtual * (var->bits_per_pixel >> 3));
  499. dev_dbg(fbi->dev, "pxa168fb: find best mode: res = %dx%d\n",
  500. var->xres, var->yres);
  501. /* correct pixclock. */
  502. total_w = var->xres + var->left_margin + var->right_margin +
  503. var->hsync_len;
  504. total_h = var->yres + var->upper_margin + var->lower_margin +
  505. var->vsync_len;
  506. div_result = 1000000000000ll;
  507. do_div(div_result, total_w * total_h * refresh);
  508. var->pixclock = (u32)div_result;
  509. }
  510. static int pxa168fb_probe(struct platform_device *pdev)
  511. {
  512. struct pxa168fb_mach_info *mi;
  513. struct fb_info *info = NULL;
  514. struct pxa168fb_info *fbi = NULL;
  515. struct resource *res;
  516. struct clk *clk;
  517. int irq, ret;
  518. mi = dev_get_platdata(&pdev->dev);
  519. if (mi == NULL) {
  520. dev_err(&pdev->dev, "no platform data defined\n");
  521. return -EINVAL;
  522. }
  523. clk = devm_clk_get(&pdev->dev, "LCDCLK");
  524. if (IS_ERR(clk))
  525. return dev_err_probe(&pdev->dev, PTR_ERR(clk),
  526. "unable to get LCDCLK");
  527. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  528. if (res == NULL) {
  529. dev_err(&pdev->dev, "no IO memory defined\n");
  530. return -ENOENT;
  531. }
  532. irq = platform_get_irq(pdev, 0);
  533. if (irq < 0)
  534. return -ENOENT;
  535. info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev);
  536. if (info == NULL) {
  537. return -ENOMEM;
  538. }
  539. /* Initialize private data */
  540. fbi = info->par;
  541. fbi->info = info;
  542. fbi->clk = clk;
  543. fbi->dev = info->dev = &pdev->dev;
  544. fbi->panel_rbswap = mi->panel_rbswap;
  545. fbi->is_blanked = 0;
  546. fbi->active = mi->active;
  547. /*
  548. * Initialise static fb parameters.
  549. */
  550. info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
  551. FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
  552. info->node = -1;
  553. strscpy(info->fix.id, mi->id, 16);
  554. info->fix.type = FB_TYPE_PACKED_PIXELS;
  555. info->fix.type_aux = 0;
  556. info->fix.xpanstep = 0;
  557. info->fix.ypanstep = 0;
  558. info->fix.ywrapstep = 0;
  559. info->fix.mmio_start = res->start;
  560. info->fix.mmio_len = resource_size(res);
  561. info->fix.accel = FB_ACCEL_NONE;
  562. info->fbops = &pxa168fb_ops;
  563. info->pseudo_palette = fbi->pseudo_palette;
  564. /*
  565. * Map LCD controller registers.
  566. */
  567. fbi->reg_base = devm_ioremap(&pdev->dev, res->start,
  568. resource_size(res));
  569. if (fbi->reg_base == NULL) {
  570. ret = -ENOMEM;
  571. goto failed_free_info;
  572. }
  573. /*
  574. * Allocate framebuffer memory.
  575. */
  576. info->fix.smem_len = PAGE_ALIGN(DEFAULT_FB_SIZE);
  577. info->screen_base = dma_alloc_wc(fbi->dev, info->fix.smem_len,
  578. &fbi->fb_start_dma, GFP_KERNEL);
  579. if (info->screen_base == NULL) {
  580. ret = -ENOMEM;
  581. goto failed_free_info;
  582. }
  583. info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
  584. set_graphics_start(info, 0, 0);
  585. /*
  586. * Set video mode according to platform data.
  587. */
  588. set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1);
  589. fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist);
  590. /*
  591. * init video mode data.
  592. */
  593. pxa168fb_init_mode(info, mi);
  594. /*
  595. * Fill in sane defaults.
  596. */
  597. ret = pxa168fb_check_var(&info->var, info);
  598. if (ret)
  599. goto failed_free_fbmem;
  600. /*
  601. * enable controller clock
  602. */
  603. clk_prepare_enable(fbi->clk);
  604. pxa168fb_set_par(info);
  605. /*
  606. * Configure default register values.
  607. */
  608. writel(0, fbi->reg_base + LCD_SPU_BLANKCOLOR);
  609. writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL);
  610. writel(0, fbi->reg_base + LCD_CFG_GRA_START_ADDR1);
  611. writel(0, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN);
  612. writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
  613. writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
  614. fbi->reg_base + LCD_SPU_SRAM_PARA1);
  615. /*
  616. * Allocate color map.
  617. */
  618. if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
  619. ret = -ENOMEM;
  620. goto failed_free_clk;
  621. }
  622. /*
  623. * Register irq handler.
  624. */
  625. ret = devm_request_irq(&pdev->dev, irq, pxa168fb_handle_irq,
  626. IRQF_SHARED, info->fix.id, fbi);
  627. if (ret < 0) {
  628. dev_err(&pdev->dev, "unable to request IRQ\n");
  629. ret = -ENXIO;
  630. goto failed_free_cmap;
  631. }
  632. /*
  633. * Enable GFX interrupt
  634. */
  635. writel(GRA_FRAME_IRQ0_ENA(0x1), fbi->reg_base + SPU_IRQ_ENA);
  636. /*
  637. * Register framebuffer.
  638. */
  639. ret = register_framebuffer(info);
  640. if (ret < 0) {
  641. dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret);
  642. ret = -ENXIO;
  643. goto failed_free_cmap;
  644. }
  645. platform_set_drvdata(pdev, fbi);
  646. return 0;
  647. failed_free_cmap:
  648. fb_dealloc_cmap(&info->cmap);
  649. failed_free_clk:
  650. clk_disable_unprepare(fbi->clk);
  651. failed_free_fbmem:
  652. dma_free_wc(fbi->dev, info->fix.smem_len,
  653. info->screen_base, fbi->fb_start_dma);
  654. failed_free_info:
  655. framebuffer_release(info);
  656. dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret);
  657. return ret;
  658. }
  659. static int pxa168fb_remove(struct platform_device *pdev)
  660. {
  661. struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
  662. struct fb_info *info;
  663. unsigned int data;
  664. if (!fbi)
  665. return 0;
  666. /* disable DMA transfer */
  667. data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
  668. data &= ~CFG_GRA_ENA_MASK;
  669. writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0);
  670. info = fbi->info;
  671. unregister_framebuffer(info);
  672. writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA);
  673. if (info->cmap.len)
  674. fb_dealloc_cmap(&info->cmap);
  675. dma_free_wc(fbi->dev, info->fix.smem_len,
  676. info->screen_base, info->fix.smem_start);
  677. clk_disable_unprepare(fbi->clk);
  678. framebuffer_release(info);
  679. return 0;
  680. }
  681. static struct platform_driver pxa168fb_driver = {
  682. .driver = {
  683. .name = "pxa168-fb",
  684. },
  685. .probe = pxa168fb_probe,
  686. .remove = pxa168fb_remove,
  687. };
  688. module_platform_driver(pxa168fb_driver);
  689. MODULE_AUTHOR("Lennert Buytenhek <[email protected]> "
  690. "Green Wan <[email protected]>");
  691. MODULE_DESCRIPTION("Framebuffer driver for PXA168/910");
  692. MODULE_LICENSE("GPL");