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