lcdc.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /*
  2. * OMAP1 internal LCD controller
  3. *
  4. * Copyright (C) 2004 Nokia Corporation
  5. * Author: Imre Deak <imre.deak@nokia.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation; either version 2 of the License, or (at your
  10. * option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. */
  21. #include <linux/module.h>
  22. #include <linux/device.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/spinlock.h>
  25. #include <linux/err.h>
  26. #include <linux/mm.h>
  27. #include <linux/fb.h>
  28. #include <linux/dma-mapping.h>
  29. #include <linux/vmalloc.h>
  30. #include <linux/clk.h>
  31. #include <linux/gfp.h>
  32. #include <mach/lcdc.h>
  33. #include <linux/omap-dma.h>
  34. #include <asm/mach-types.h>
  35. #include "omapfb.h"
  36. #include "lcdc.h"
  37. #define MODULE_NAME "lcdc"
  38. #define MAX_PALETTE_SIZE PAGE_SIZE
  39. enum lcdc_load_mode {
  40. OMAP_LCDC_LOAD_PALETTE,
  41. OMAP_LCDC_LOAD_FRAME,
  42. OMAP_LCDC_LOAD_PALETTE_AND_FRAME
  43. };
  44. static struct omap_lcd_controller {
  45. enum omapfb_update_mode update_mode;
  46. int ext_mode;
  47. unsigned long frame_offset;
  48. int screen_width;
  49. int xres;
  50. int yres;
  51. enum omapfb_color_format color_mode;
  52. int bpp;
  53. void *palette_virt;
  54. dma_addr_t palette_phys;
  55. int palette_code;
  56. int palette_size;
  57. unsigned int irq_mask;
  58. struct completion last_frame_complete;
  59. struct completion palette_load_complete;
  60. struct clk *lcd_ck;
  61. struct omapfb_device *fbdev;
  62. void (*dma_callback)(void *data);
  63. void *dma_callback_data;
  64. dma_addr_t vram_phys;
  65. void *vram_virt;
  66. unsigned long vram_size;
  67. } lcdc;
  68. static void inline enable_irqs(int mask)
  69. {
  70. lcdc.irq_mask |= mask;
  71. }
  72. static void inline disable_irqs(int mask)
  73. {
  74. lcdc.irq_mask &= ~mask;
  75. }
  76. static void set_load_mode(enum lcdc_load_mode mode)
  77. {
  78. u32 l;
  79. l = omap_readl(OMAP_LCDC_CONTROL);
  80. l &= ~(3 << 20);
  81. switch (mode) {
  82. case OMAP_LCDC_LOAD_PALETTE:
  83. l |= 1 << 20;
  84. break;
  85. case OMAP_LCDC_LOAD_FRAME:
  86. l |= 2 << 20;
  87. break;
  88. case OMAP_LCDC_LOAD_PALETTE_AND_FRAME:
  89. break;
  90. default:
  91. BUG();
  92. }
  93. omap_writel(l, OMAP_LCDC_CONTROL);
  94. }
  95. static void enable_controller(void)
  96. {
  97. u32 l;
  98. l = omap_readl(OMAP_LCDC_CONTROL);
  99. l |= OMAP_LCDC_CTRL_LCD_EN;
  100. l &= ~OMAP_LCDC_IRQ_MASK;
  101. l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE; /* enabled IRQs */
  102. omap_writel(l, OMAP_LCDC_CONTROL);
  103. }
  104. static void disable_controller_async(void)
  105. {
  106. u32 l;
  107. u32 mask;
  108. l = omap_readl(OMAP_LCDC_CONTROL);
  109. mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK;
  110. /*
  111. * Preserve the DONE mask, since we still want to get the
  112. * final DONE irq. It will be disabled in the IRQ handler.
  113. */
  114. mask &= ~OMAP_LCDC_IRQ_DONE;
  115. l &= ~mask;
  116. omap_writel(l, OMAP_LCDC_CONTROL);
  117. }
  118. static void disable_controller(void)
  119. {
  120. init_completion(&lcdc.last_frame_complete);
  121. disable_controller_async();
  122. if (!wait_for_completion_timeout(&lcdc.last_frame_complete,
  123. msecs_to_jiffies(500)))
  124. dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
  125. }
  126. static void reset_controller(u32 status)
  127. {
  128. static unsigned long reset_count;
  129. static unsigned long last_jiffies;
  130. disable_controller_async();
  131. reset_count++;
  132. if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) {
  133. dev_err(lcdc.fbdev->dev,
  134. "resetting (status %#010x,reset count %lu)\n",
  135. status, reset_count);
  136. last_jiffies = jiffies;
  137. }
  138. if (reset_count < 100) {
  139. enable_controller();
  140. } else {
  141. reset_count = 0;
  142. dev_err(lcdc.fbdev->dev,
  143. "too many reset attempts, giving up.\n");
  144. }
  145. }
  146. /*
  147. * Configure the LCD DMA according to the current mode specified by parameters
  148. * in lcdc.fbdev and fbdev->var.
  149. */
  150. static void setup_lcd_dma(void)
  151. {
  152. static const int dma_elem_type[] = {
  153. 0,
  154. OMAP_DMA_DATA_TYPE_S8,
  155. OMAP_DMA_DATA_TYPE_S16,
  156. 0,
  157. OMAP_DMA_DATA_TYPE_S32,
  158. };
  159. struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par;
  160. struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
  161. unsigned long src;
  162. int esize, xelem, yelem;
  163. src = lcdc.vram_phys + lcdc.frame_offset;
  164. switch (var->rotate) {
  165. case 0:
  166. if (plane->info.mirror || (src & 3) ||
  167. lcdc.color_mode == OMAPFB_COLOR_YUV420 ||
  168. (lcdc.xres & 1))
  169. esize = 2;
  170. else
  171. esize = 4;
  172. xelem = lcdc.xres * lcdc.bpp / 8 / esize;
  173. yelem = lcdc.yres;
  174. break;
  175. case 90:
  176. case 180:
  177. case 270:
  178. if (cpu_is_omap15xx()) {
  179. BUG();
  180. }
  181. esize = 2;
  182. xelem = lcdc.yres * lcdc.bpp / 16;
  183. yelem = lcdc.xres;
  184. break;
  185. default:
  186. BUG();
  187. return;
  188. }
  189. #ifdef VERBOSE
  190. dev_dbg(lcdc.fbdev->dev,
  191. "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",
  192. src, esize, xelem, yelem);
  193. #endif
  194. omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]);
  195. if (!cpu_is_omap15xx()) {
  196. int bpp = lcdc.bpp;
  197. /*
  198. * YUV support is only for external mode when we have the
  199. * YUV window embedded in a 16bpp frame buffer.
  200. */
  201. if (lcdc.color_mode == OMAPFB_COLOR_YUV420)
  202. bpp = 16;
  203. /* Set virtual xres elem size */
  204. omap_set_lcd_dma_b1_vxres(
  205. lcdc.screen_width * bpp / 8 / esize);
  206. /* Setup transformations */
  207. omap_set_lcd_dma_b1_rotation(var->rotate);
  208. omap_set_lcd_dma_b1_mirror(plane->info.mirror);
  209. }
  210. omap_setup_lcd_dma();
  211. }
  212. static irqreturn_t lcdc_irq_handler(int irq, void *dev_id)
  213. {
  214. u32 status;
  215. status = omap_readl(OMAP_LCDC_STATUS);
  216. if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST))
  217. reset_controller(status);
  218. else {
  219. if (status & OMAP_LCDC_STAT_DONE) {
  220. u32 l;
  221. /*
  222. * Disable IRQ_DONE. The status bit will be cleared
  223. * only when the controller is reenabled and we don't
  224. * want to get more interrupts.
  225. */
  226. l = omap_readl(OMAP_LCDC_CONTROL);
  227. l &= ~OMAP_LCDC_IRQ_DONE;
  228. omap_writel(l, OMAP_LCDC_CONTROL);
  229. complete(&lcdc.last_frame_complete);
  230. }
  231. if (status & OMAP_LCDC_STAT_LOADED_PALETTE) {
  232. disable_controller_async();
  233. complete(&lcdc.palette_load_complete);
  234. }
  235. }
  236. /*
  237. * Clear these interrupt status bits.
  238. * Sync_lost, FUF bits were cleared by disabling the LCD controller
  239. * LOADED_PALETTE can be cleared this way only in palette only
  240. * load mode. In other load modes it's cleared by disabling the
  241. * controller.
  242. */
  243. status &= ~(OMAP_LCDC_STAT_VSYNC |
  244. OMAP_LCDC_STAT_LOADED_PALETTE |
  245. OMAP_LCDC_STAT_ABC |
  246. OMAP_LCDC_STAT_LINE_INT);
  247. omap_writel(status, OMAP_LCDC_STATUS);
  248. return IRQ_HANDLED;
  249. }
  250. /*
  251. * Change to a new video mode. We defer this to a later time to avoid any
  252. * flicker and not to mess up the current LCD DMA context. For this we disable
  253. * the LCD controller, which will generate a DONE irq after the last frame has
  254. * been transferred. Then it'll be safe to reconfigure both the LCD controller
  255. * as well as the LCD DMA.
  256. */
  257. static int omap_lcdc_setup_plane(int plane, int channel_out,
  258. unsigned long offset, int screen_width,
  259. int pos_x, int pos_y, int width, int height,
  260. int color_mode)
  261. {
  262. struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;
  263. struct lcd_panel *panel = lcdc.fbdev->panel;
  264. int rot_x, rot_y;
  265. if (var->rotate == 0) {
  266. rot_x = panel->x_res;
  267. rot_y = panel->y_res;
  268. } else {
  269. rot_x = panel->y_res;
  270. rot_y = panel->x_res;
  271. }
  272. if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 ||
  273. width > rot_x || height > rot_y) {
  274. #ifdef VERBOSE
  275. dev_dbg(lcdc.fbdev->dev,
  276. "invalid plane params plane %d pos_x %d pos_y %d "
  277. "w %d h %d\n", plane, pos_x, pos_y, width, height);
  278. #endif
  279. return -EINVAL;
  280. }
  281. lcdc.frame_offset = offset;
  282. lcdc.xres = width;
  283. lcdc.yres = height;
  284. lcdc.screen_width = screen_width;
  285. lcdc.color_mode = color_mode;
  286. switch (color_mode) {
  287. case OMAPFB_COLOR_CLUT_8BPP:
  288. lcdc.bpp = 8;
  289. lcdc.palette_code = 0x3000;
  290. lcdc.palette_size = 512;
  291. break;
  292. case OMAPFB_COLOR_RGB565:
  293. lcdc.bpp = 16;
  294. lcdc.palette_code = 0x4000;
  295. lcdc.palette_size = 32;
  296. break;
  297. case OMAPFB_COLOR_RGB444:
  298. lcdc.bpp = 16;
  299. lcdc.palette_code = 0x4000;
  300. lcdc.palette_size = 32;
  301. break;
  302. case OMAPFB_COLOR_YUV420:
  303. if (lcdc.ext_mode) {
  304. lcdc.bpp = 12;
  305. break;
  306. }
  307. /* fallthrough */
  308. case OMAPFB_COLOR_YUV422:
  309. if (lcdc.ext_mode) {
  310. lcdc.bpp = 16;
  311. break;
  312. }
  313. /* fallthrough */
  314. default:
  315. /* FIXME: other BPPs.
  316. * bpp1: code 0, size 256
  317. * bpp2: code 0x1000 size 256
  318. * bpp4: code 0x2000 size 256
  319. * bpp12: code 0x4000 size 32
  320. */
  321. dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode);
  322. BUG();
  323. return -1;
  324. }
  325. if (lcdc.ext_mode) {
  326. setup_lcd_dma();
  327. return 0;
  328. }
  329. if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
  330. disable_controller();
  331. omap_stop_lcd_dma();
  332. setup_lcd_dma();
  333. enable_controller();
  334. }
  335. return 0;
  336. }
  337. static int omap_lcdc_enable_plane(int plane, int enable)
  338. {
  339. dev_dbg(lcdc.fbdev->dev,
  340. "plane %d enable %d update_mode %d ext_mode %d\n",
  341. plane, enable, lcdc.update_mode, lcdc.ext_mode);
  342. if (plane != OMAPFB_PLANE_GFX)
  343. return -EINVAL;
  344. return 0;
  345. }
  346. /*
  347. * Configure the LCD DMA for a palette load operation and do the palette
  348. * downloading synchronously. We don't use the frame+palette load mode of
  349. * the controller, since the palette can always be downloaded separately.
  350. */
  351. static void load_palette(void)
  352. {
  353. u16 *palette;
  354. palette = (u16 *)lcdc.palette_virt;
  355. *(u16 *)palette &= 0x0fff;
  356. *(u16 *)palette |= lcdc.palette_code;
  357. omap_set_lcd_dma_b1(lcdc.palette_phys,
  358. lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);
  359. omap_set_lcd_dma_single_transfer(1);
  360. omap_setup_lcd_dma();
  361. init_completion(&lcdc.palette_load_complete);
  362. enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
  363. set_load_mode(OMAP_LCDC_LOAD_PALETTE);
  364. enable_controller();
  365. if (!wait_for_completion_timeout(&lcdc.palette_load_complete,
  366. msecs_to_jiffies(500)))
  367. dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");
  368. /* The controller gets disabled in the irq handler */
  369. disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
  370. omap_stop_lcd_dma();
  371. omap_set_lcd_dma_single_transfer(lcdc.ext_mode);
  372. }
  373. /* Used only in internal controller mode */
  374. static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue,
  375. u16 transp, int update_hw_pal)
  376. {
  377. u16 *palette;
  378. if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)
  379. return -EINVAL;
  380. palette = (u16 *)lcdc.palette_virt;
  381. palette[regno] &= ~0x0fff;
  382. palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) |
  383. (blue >> 12);
  384. if (update_hw_pal) {
  385. disable_controller();
  386. omap_stop_lcd_dma();
  387. load_palette();
  388. setup_lcd_dma();
  389. set_load_mode(OMAP_LCDC_LOAD_FRAME);
  390. enable_controller();
  391. }
  392. return 0;
  393. }
  394. static void calc_ck_div(int is_tft, int pck, int *pck_div)
  395. {
  396. unsigned long lck;
  397. pck = max(1, pck);
  398. lck = clk_get_rate(lcdc.lcd_ck);
  399. *pck_div = (lck + pck - 1) / pck;
  400. if (is_tft)
  401. *pck_div = max(2, *pck_div);
  402. else
  403. *pck_div = max(3, *pck_div);
  404. if (*pck_div > 255) {
  405. /* FIXME: try to adjust logic clock divider as well */
  406. *pck_div = 255;
  407. dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n",
  408. pck / 1000);
  409. }
  410. }
  411. static void inline setup_regs(void)
  412. {
  413. u32 l;
  414. struct lcd_panel *panel = lcdc.fbdev->panel;
  415. int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
  416. unsigned long lck;
  417. int pcd;
  418. l = omap_readl(OMAP_LCDC_CONTROL);
  419. l &= ~OMAP_LCDC_CTRL_LCD_TFT;
  420. l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0;
  421. #ifdef CONFIG_MACH_OMAP_PALMTE
  422. /* FIXME:if (machine_is_omap_palmte()) { */
  423. /* PalmTE uses alternate TFT setting in 8BPP mode */
  424. l |= (is_tft && panel->bpp == 8) ? 0x810000 : 0;
  425. /* } */
  426. #endif
  427. omap_writel(l, OMAP_LCDC_CONTROL);
  428. l = omap_readl(OMAP_LCDC_TIMING2);
  429. l &= ~(((1 << 6) - 1) << 20);
  430. l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20;
  431. omap_writel(l, OMAP_LCDC_TIMING2);
  432. l = panel->x_res - 1;
  433. l |= (panel->hsw - 1) << 10;
  434. l |= (panel->hfp - 1) << 16;
  435. l |= (panel->hbp - 1) << 24;
  436. omap_writel(l, OMAP_LCDC_TIMING0);
  437. l = panel->y_res - 1;
  438. l |= (panel->vsw - 1) << 10;
  439. l |= panel->vfp << 16;
  440. l |= panel->vbp << 24;
  441. omap_writel(l, OMAP_LCDC_TIMING1);
  442. l = omap_readl(OMAP_LCDC_TIMING2);
  443. l &= ~0xff;
  444. lck = clk_get_rate(lcdc.lcd_ck);
  445. if (!panel->pcd)
  446. calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd);
  447. else {
  448. dev_warn(lcdc.fbdev->dev,
  449. "Pixel clock divider value is obsolete.\n"
  450. "Try to set pixel_clock to %lu and pcd to 0 "
  451. "in drivers/video/omap/lcd_%s.c and submit a patch.\n",
  452. lck / panel->pcd / 1000, panel->name);
  453. pcd = panel->pcd;
  454. }
  455. l |= pcd & 0xff;
  456. l |= panel->acb << 8;
  457. omap_writel(l, OMAP_LCDC_TIMING2);
  458. /* update panel info with the exact clock */
  459. panel->pixel_clock = lck / pcd / 1000;
  460. }
  461. /*
  462. * Configure the LCD controller, download the color palette and start a looped
  463. * DMA transfer of the frame image data. Called only in internal
  464. * controller mode.
  465. */
  466. static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)
  467. {
  468. int r = 0;
  469. if (mode != lcdc.update_mode) {
  470. switch (mode) {
  471. case OMAPFB_AUTO_UPDATE:
  472. setup_regs();
  473. load_palette();
  474. /* Setup and start LCD DMA */
  475. setup_lcd_dma();
  476. set_load_mode(OMAP_LCDC_LOAD_FRAME);
  477. enable_irqs(OMAP_LCDC_IRQ_DONE);
  478. /* This will start the actual DMA transfer */
  479. enable_controller();
  480. lcdc.update_mode = mode;
  481. break;
  482. case OMAPFB_UPDATE_DISABLED:
  483. disable_controller();
  484. omap_stop_lcd_dma();
  485. lcdc.update_mode = mode;
  486. break;
  487. default:
  488. r = -EINVAL;
  489. }
  490. }
  491. return r;
  492. }
  493. static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
  494. {
  495. return lcdc.update_mode;
  496. }
  497. /* PM code called only in internal controller mode */
  498. static void omap_lcdc_suspend(void)
  499. {
  500. omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED);
  501. }
  502. static void omap_lcdc_resume(void)
  503. {
  504. omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE);
  505. }
  506. static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
  507. {
  508. return;
  509. }
  510. int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data)
  511. {
  512. BUG_ON(callback == NULL);
  513. if (lcdc.dma_callback)
  514. return -EBUSY;
  515. else {
  516. lcdc.dma_callback = callback;
  517. lcdc.dma_callback_data = data;
  518. }
  519. return 0;
  520. }
  521. EXPORT_SYMBOL(omap_lcdc_set_dma_callback);
  522. void omap_lcdc_free_dma_callback(void)
  523. {
  524. lcdc.dma_callback = NULL;
  525. }
  526. EXPORT_SYMBOL(omap_lcdc_free_dma_callback);
  527. static void lcdc_dma_handler(u16 status, void *data)
  528. {
  529. if (lcdc.dma_callback)
  530. lcdc.dma_callback(lcdc.dma_callback_data);
  531. }
  532. static int alloc_palette_ram(void)
  533. {
  534. lcdc.palette_virt = dma_alloc_wc(lcdc.fbdev->dev, MAX_PALETTE_SIZE,
  535. &lcdc.palette_phys, GFP_KERNEL);
  536. if (lcdc.palette_virt == NULL) {
  537. dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n");
  538. return -ENOMEM;
  539. }
  540. memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE);
  541. return 0;
  542. }
  543. static void free_palette_ram(void)
  544. {
  545. dma_free_wc(lcdc.fbdev->dev, MAX_PALETTE_SIZE, lcdc.palette_virt,
  546. lcdc.palette_phys);
  547. }
  548. static int alloc_fbmem(struct omapfb_mem_region *region)
  549. {
  550. int bpp;
  551. int frame_size;
  552. struct lcd_panel *panel = lcdc.fbdev->panel;
  553. bpp = panel->bpp;
  554. if (bpp == 12)
  555. bpp = 16;
  556. frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res);
  557. if (region->size > frame_size)
  558. frame_size = region->size;
  559. lcdc.vram_size = frame_size;
  560. lcdc.vram_virt = dma_alloc_wc(lcdc.fbdev->dev, lcdc.vram_size,
  561. &lcdc.vram_phys, GFP_KERNEL);
  562. if (lcdc.vram_virt == NULL) {
  563. dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n");
  564. return -ENOMEM;
  565. }
  566. region->size = frame_size;
  567. region->paddr = lcdc.vram_phys;
  568. region->vaddr = lcdc.vram_virt;
  569. region->alloc = 1;
  570. memset(lcdc.vram_virt, 0, lcdc.vram_size);
  571. return 0;
  572. }
  573. static void free_fbmem(void)
  574. {
  575. dma_free_wc(lcdc.fbdev->dev, lcdc.vram_size, lcdc.vram_virt,
  576. lcdc.vram_phys);
  577. }
  578. static int setup_fbmem(struct omapfb_mem_desc *req_md)
  579. {
  580. if (!req_md->region_cnt) {
  581. dev_err(lcdc.fbdev->dev, "no memory regions defined\n");
  582. return -EINVAL;
  583. }
  584. if (req_md->region_cnt > 1) {
  585. dev_err(lcdc.fbdev->dev, "only one plane is supported\n");
  586. req_md->region_cnt = 1;
  587. }
  588. return alloc_fbmem(&req_md->region[0]);
  589. }
  590. static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
  591. struct omapfb_mem_desc *req_vram)
  592. {
  593. int r;
  594. u32 l;
  595. int rate;
  596. struct clk *tc_ck;
  597. lcdc.irq_mask = 0;
  598. lcdc.fbdev = fbdev;
  599. lcdc.ext_mode = ext_mode;
  600. l = 0;
  601. omap_writel(l, OMAP_LCDC_CONTROL);
  602. /* FIXME:
  603. * According to errata some platforms have a clock rate limitiation
  604. */
  605. lcdc.lcd_ck = clk_get(fbdev->dev, "lcd_ck");
  606. if (IS_ERR(lcdc.lcd_ck)) {
  607. dev_err(fbdev->dev, "unable to access LCD clock\n");
  608. r = PTR_ERR(lcdc.lcd_ck);
  609. goto fail0;
  610. }
  611. tc_ck = clk_get(fbdev->dev, "tc_ck");
  612. if (IS_ERR(tc_ck)) {
  613. dev_err(fbdev->dev, "unable to access TC clock\n");
  614. r = PTR_ERR(tc_ck);
  615. goto fail1;
  616. }
  617. rate = clk_get_rate(tc_ck);
  618. clk_put(tc_ck);
  619. if (machine_is_ams_delta())
  620. rate /= 4;
  621. if (machine_is_omap_h3())
  622. rate /= 3;
  623. r = clk_set_rate(lcdc.lcd_ck, rate);
  624. if (r) {
  625. dev_err(fbdev->dev, "failed to adjust LCD rate\n");
  626. goto fail1;
  627. }
  628. clk_enable(lcdc.lcd_ck);
  629. r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
  630. if (r) {
  631. dev_err(fbdev->dev, "unable to get IRQ\n");
  632. goto fail2;
  633. }
  634. r = omap_request_lcd_dma(lcdc_dma_handler, NULL);
  635. if (r) {
  636. dev_err(fbdev->dev, "unable to get LCD DMA\n");
  637. goto fail3;
  638. }
  639. omap_set_lcd_dma_single_transfer(ext_mode);
  640. omap_set_lcd_dma_ext_controller(ext_mode);
  641. if (!ext_mode)
  642. if ((r = alloc_palette_ram()) < 0)
  643. goto fail4;
  644. if ((r = setup_fbmem(req_vram)) < 0)
  645. goto fail5;
  646. pr_info("omapfb: LCDC initialized\n");
  647. return 0;
  648. fail5:
  649. if (!ext_mode)
  650. free_palette_ram();
  651. fail4:
  652. omap_free_lcd_dma();
  653. fail3:
  654. free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
  655. fail2:
  656. clk_disable(lcdc.lcd_ck);
  657. fail1:
  658. clk_put(lcdc.lcd_ck);
  659. fail0:
  660. return r;
  661. }
  662. static void omap_lcdc_cleanup(void)
  663. {
  664. if (!lcdc.ext_mode)
  665. free_palette_ram();
  666. free_fbmem();
  667. omap_free_lcd_dma();
  668. free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
  669. clk_disable(lcdc.lcd_ck);
  670. clk_put(lcdc.lcd_ck);
  671. }
  672. const struct lcd_ctrl omap1_int_ctrl = {
  673. .name = "internal",
  674. .init = omap_lcdc_init,
  675. .cleanup = omap_lcdc_cleanup,
  676. .get_caps = omap_lcdc_get_caps,
  677. .set_update_mode = omap_lcdc_set_update_mode,
  678. .get_update_mode = omap_lcdc_get_update_mode,
  679. .update_window = NULL,
  680. .suspend = omap_lcdc_suspend,
  681. .resume = omap_lcdc_resume,
  682. .setup_plane = omap_lcdc_setup_plane,
  683. .enable_plane = omap_lcdc_enable_plane,
  684. .setcolreg = omap_lcdc_setcolreg,
  685. };