lcdc.c 18 KB

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