diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-02-13 14:31:38 +0100 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-04-17 07:10:19 +0200 |
commit | f7018c21350204c4cf628462f229d44d03545254 (patch) | |
tree | 408787177164cf51cc06f7aabdb04fcff8d2b6aa /drivers/video/omap/lcdc.c | |
parent | video: bf54x-lq043fb: fix build error (diff) | |
download | linux-f7018c21350204c4cf628462f229d44d03545254.tar.xz linux-f7018c21350204c4cf628462f229d44d03545254.zip |
video: move fbdev to drivers/video/fbdev
The drivers/video directory is a mess. It contains generic video related
files, directories for backlight, console, linux logo, lots of fbdev
device drivers, fbdev framework files.
Make some order into the chaos by creating drivers/video/fbdev
directory, and move all fbdev related files there.
No functionality is changed, although I guess it is possible that some
subtle Makefile build order related issue could be created by this
patch.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Rob Clark <robdclark@gmail.com>
Acked-by: Jingoo Han <jg1.han@samsung.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/video/omap/lcdc.c')
-rw-r--r-- | drivers/video/omap/lcdc.c | 856 |
1 files changed, 0 insertions, 856 deletions
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c deleted file mode 100644 index b52f62595f65..000000000000 --- a/drivers/video/omap/lcdc.c +++ /dev/null @@ -1,856 +0,0 @@ -/* - * OMAP1 internal LCD controller - * - * Copyright (C) 2004 Nokia Corporation - * Author: Imre Deak <imre.deak@nokia.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include <linux/module.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/err.h> -#include <linux/mm.h> -#include <linux/fb.h> -#include <linux/dma-mapping.h> -#include <linux/vmalloc.h> -#include <linux/clk.h> -#include <linux/gfp.h> - -#include <mach/lcdc.h> -#include <linux/omap-dma.h> - -#include <asm/mach-types.h> - -#include "omapfb.h" - -#include "lcdc.h" - -#define MODULE_NAME "lcdc" - -#define MAX_PALETTE_SIZE PAGE_SIZE - -enum lcdc_load_mode { - OMAP_LCDC_LOAD_PALETTE, - OMAP_LCDC_LOAD_FRAME, - OMAP_LCDC_LOAD_PALETTE_AND_FRAME -}; - -static struct omap_lcd_controller { - enum omapfb_update_mode update_mode; - int ext_mode; - - unsigned long frame_offset; - int screen_width; - int xres; - int yres; - - enum omapfb_color_format color_mode; - int bpp; - void *palette_virt; - dma_addr_t palette_phys; - int palette_code; - int palette_size; - - unsigned int irq_mask; - struct completion last_frame_complete; - struct completion palette_load_complete; - struct clk *lcd_ck; - struct omapfb_device *fbdev; - - void (*dma_callback)(void *data); - void *dma_callback_data; - - int fbmem_allocated; - dma_addr_t vram_phys; - void *vram_virt; - unsigned long vram_size; -} lcdc; - -static void inline enable_irqs(int mask) -{ - lcdc.irq_mask |= mask; -} - -static void inline disable_irqs(int mask) -{ - lcdc.irq_mask &= ~mask; -} - -static void set_load_mode(enum lcdc_load_mode mode) -{ - u32 l; - - l = omap_readl(OMAP_LCDC_CONTROL); - l &= ~(3 << 20); - switch (mode) { - case OMAP_LCDC_LOAD_PALETTE: - l |= 1 << 20; - break; - case OMAP_LCDC_LOAD_FRAME: - l |= 2 << 20; - break; - case OMAP_LCDC_LOAD_PALETTE_AND_FRAME: - break; - default: - BUG(); - } - omap_writel(l, OMAP_LCDC_CONTROL); -} - -static void enable_controller(void) -{ - u32 l; - - l = omap_readl(OMAP_LCDC_CONTROL); - l |= OMAP_LCDC_CTRL_LCD_EN; - l &= ~OMAP_LCDC_IRQ_MASK; - l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE; /* enabled IRQs */ - omap_writel(l, OMAP_LCDC_CONTROL); -} - -static void disable_controller_async(void) -{ - u32 l; - u32 mask; - - l = omap_readl(OMAP_LCDC_CONTROL); - mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK; - /* - * Preserve the DONE mask, since we still want to get the - * final DONE irq. It will be disabled in the IRQ handler. - */ - mask &= ~OMAP_LCDC_IRQ_DONE; - l &= ~mask; - omap_writel(l, OMAP_LCDC_CONTROL); -} - -static void disable_controller(void) -{ - init_completion(&lcdc.last_frame_complete); - disable_controller_async(); - if (!wait_for_completion_timeout(&lcdc.last_frame_complete, - msecs_to_jiffies(500))) - dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n"); -} - -static void reset_controller(u32 status) -{ - static unsigned long reset_count; - static unsigned long last_jiffies; - - disable_controller_async(); - reset_count++; - if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) { - dev_err(lcdc.fbdev->dev, - "resetting (status %#010x,reset count %lu)\n", - status, reset_count); - last_jiffies = jiffies; - } - if (reset_count < 100) { - enable_controller(); - } else { - reset_count = 0; - dev_err(lcdc.fbdev->dev, - "too many reset attempts, giving up.\n"); - } -} - -/* - * Configure the LCD DMA according to the current mode specified by parameters - * in lcdc.fbdev and fbdev->var. - */ -static void setup_lcd_dma(void) -{ - static const int dma_elem_type[] = { - 0, - OMAP_DMA_DATA_TYPE_S8, - OMAP_DMA_DATA_TYPE_S16, - 0, - OMAP_DMA_DATA_TYPE_S32, - }; - struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par; - struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var; - unsigned long src; - int esize, xelem, yelem; - - src = lcdc.vram_phys + lcdc.frame_offset; - - switch (var->rotate) { - case 0: - if (plane->info.mirror || (src & 3) || - lcdc.color_mode == OMAPFB_COLOR_YUV420 || - (lcdc.xres & 1)) - esize = 2; - else - esize = 4; - xelem = lcdc.xres * lcdc.bpp / 8 / esize; - yelem = lcdc.yres; - break; - case 90: - case 180: - case 270: - if (cpu_is_omap15xx()) { - BUG(); - } - esize = 2; - xelem = lcdc.yres * lcdc.bpp / 16; - yelem = lcdc.xres; - break; - default: - BUG(); - return; - } -#ifdef VERBOSE - dev_dbg(lcdc.fbdev->dev, - "setup_dma: src %#010lx esize %d xelem %d yelem %d\n", - src, esize, xelem, yelem); -#endif - omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]); - if (!cpu_is_omap15xx()) { - int bpp = lcdc.bpp; - - /* - * YUV support is only for external mode when we have the - * YUV window embedded in a 16bpp frame buffer. - */ - if (lcdc.color_mode == OMAPFB_COLOR_YUV420) - bpp = 16; - /* Set virtual xres elem size */ - omap_set_lcd_dma_b1_vxres( - lcdc.screen_width * bpp / 8 / esize); - /* Setup transformations */ - omap_set_lcd_dma_b1_rotation(var->rotate); - omap_set_lcd_dma_b1_mirror(plane->info.mirror); - } - omap_setup_lcd_dma(); -} - -static irqreturn_t lcdc_irq_handler(int irq, void *dev_id) -{ - u32 status; - - status = omap_readl(OMAP_LCDC_STATUS); - - if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST)) - reset_controller(status); - else { - if (status & OMAP_LCDC_STAT_DONE) { - u32 l; - - /* - * Disable IRQ_DONE. The status bit will be cleared - * only when the controller is reenabled and we don't - * want to get more interrupts. - */ - l = omap_readl(OMAP_LCDC_CONTROL); - l &= ~OMAP_LCDC_IRQ_DONE; - omap_writel(l, OMAP_LCDC_CONTROL); - complete(&lcdc.last_frame_complete); - } - if (status & OMAP_LCDC_STAT_LOADED_PALETTE) { - disable_controller_async(); - complete(&lcdc.palette_load_complete); - } - } - - /* - * Clear these interrupt status bits. - * Sync_lost, FUF bits were cleared by disabling the LCD controller - * LOADED_PALETTE can be cleared this way only in palette only - * load mode. In other load modes it's cleared by disabling the - * controller. - */ - status &= ~(OMAP_LCDC_STAT_VSYNC | - OMAP_LCDC_STAT_LOADED_PALETTE | - OMAP_LCDC_STAT_ABC | - OMAP_LCDC_STAT_LINE_INT); - omap_writel(status, OMAP_LCDC_STATUS); - return IRQ_HANDLED; -} - -/* - * Change to a new video mode. We defer this to a later time to avoid any - * flicker and not to mess up the current LCD DMA context. For this we disable - * the LCD controller, which will generate a DONE irq after the last frame has - * been transferred. Then it'll be safe to reconfigure both the LCD controller - * as well as the LCD DMA. - */ -static int omap_lcdc_setup_plane(int plane, int channel_out, - unsigned long offset, int screen_width, - int pos_x, int pos_y, int width, int height, - int color_mode) -{ - struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var; - struct lcd_panel *panel = lcdc.fbdev->panel; - int rot_x, rot_y; - - if (var->rotate == 0) { - rot_x = panel->x_res; - rot_y = panel->y_res; - } else { - rot_x = panel->y_res; - rot_y = panel->x_res; - } - if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 || - width > rot_x || height > rot_y) { -#ifdef VERBOSE - dev_dbg(lcdc.fbdev->dev, - "invalid plane params plane %d pos_x %d pos_y %d " - "w %d h %d\n", plane, pos_x, pos_y, width, height); -#endif - return -EINVAL; - } - - lcdc.frame_offset = offset; - lcdc.xres = width; - lcdc.yres = height; - lcdc.screen_width = screen_width; - lcdc.color_mode = color_mode; - - switch (color_mode) { - case OMAPFB_COLOR_CLUT_8BPP: - lcdc.bpp = 8; - lcdc.palette_code = 0x3000; - lcdc.palette_size = 512; - break; - case OMAPFB_COLOR_RGB565: - lcdc.bpp = 16; - lcdc.palette_code = 0x4000; - lcdc.palette_size = 32; - break; - case OMAPFB_COLOR_RGB444: - lcdc.bpp = 16; - lcdc.palette_code = 0x4000; - lcdc.palette_size = 32; - break; - case OMAPFB_COLOR_YUV420: - if (lcdc.ext_mode) { - lcdc.bpp = 12; - break; - } - /* fallthrough */ - case OMAPFB_COLOR_YUV422: - if (lcdc.ext_mode) { - lcdc.bpp = 16; - break; - } - /* fallthrough */ - default: - /* FIXME: other BPPs. - * bpp1: code 0, size 256 - * bpp2: code 0x1000 size 256 - * bpp4: code 0x2000 size 256 - * bpp12: code 0x4000 size 32 - */ - dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode); - BUG(); - return -1; - } - - if (lcdc.ext_mode) { - setup_lcd_dma(); - return 0; - } - - if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) { - disable_controller(); - omap_stop_lcd_dma(); - setup_lcd_dma(); - enable_controller(); - } - - return 0; -} - -static int omap_lcdc_enable_plane(int plane, int enable) -{ - dev_dbg(lcdc.fbdev->dev, - "plane %d enable %d update_mode %d ext_mode %d\n", - plane, enable, lcdc.update_mode, lcdc.ext_mode); - if (plane != OMAPFB_PLANE_GFX) - return -EINVAL; - - return 0; -} - -/* - * Configure the LCD DMA for a palette load operation and do the palette - * downloading synchronously. We don't use the frame+palette load mode of - * the controller, since the palette can always be downloaded separately. - */ -static void load_palette(void) -{ - u16 *palette; - - palette = (u16 *)lcdc.palette_virt; - - *(u16 *)palette &= 0x0fff; - *(u16 *)palette |= lcdc.palette_code; - - omap_set_lcd_dma_b1(lcdc.palette_phys, - lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32); - - omap_set_lcd_dma_single_transfer(1); - omap_setup_lcd_dma(); - - init_completion(&lcdc.palette_load_complete); - enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE); - set_load_mode(OMAP_LCDC_LOAD_PALETTE); - enable_controller(); - if (!wait_for_completion_timeout(&lcdc.palette_load_complete, - msecs_to_jiffies(500))) - dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n"); - /* The controller gets disabled in the irq handler */ - disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE); - omap_stop_lcd_dma(); - - omap_set_lcd_dma_single_transfer(lcdc.ext_mode); -} - -/* Used only in internal controller mode */ -static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue, - u16 transp, int update_hw_pal) -{ - u16 *palette; - - if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255) - return -EINVAL; - - palette = (u16 *)lcdc.palette_virt; - - palette[regno] &= ~0x0fff; - palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) | - (blue >> 12); - - if (update_hw_pal) { - disable_controller(); - omap_stop_lcd_dma(); - load_palette(); - setup_lcd_dma(); - set_load_mode(OMAP_LCDC_LOAD_FRAME); - enable_controller(); - } - - return 0; -} - -static void calc_ck_div(int is_tft, int pck, int *pck_div) -{ - unsigned long lck; - - pck = max(1, pck); - lck = clk_get_rate(lcdc.lcd_ck); - *pck_div = (lck + pck - 1) / pck; - if (is_tft) - *pck_div = max(2, *pck_div); - else - *pck_div = max(3, *pck_div); - if (*pck_div > 255) { - /* FIXME: try to adjust logic clock divider as well */ - *pck_div = 255; - dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n", - pck / 1000); - } -} - -static void inline setup_regs(void) -{ - u32 l; - struct lcd_panel *panel = lcdc.fbdev->panel; - int is_tft = panel->config & OMAP_LCDC_PANEL_TFT; - unsigned long lck; - int pcd; - - l = omap_readl(OMAP_LCDC_CONTROL); - l &= ~OMAP_LCDC_CTRL_LCD_TFT; - l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0; -#ifdef CONFIG_MACH_OMAP_PALMTE -/* FIXME:if (machine_is_omap_palmte()) { */ - /* PalmTE uses alternate TFT setting in 8BPP mode */ - l |= (is_tft && panel->bpp == 8) ? 0x810000 : 0; -/* } */ -#endif - omap_writel(l, OMAP_LCDC_CONTROL); - - l = omap_readl(OMAP_LCDC_TIMING2); - l &= ~(((1 << 6) - 1) << 20); - l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20; - omap_writel(l, OMAP_LCDC_TIMING2); - - l = panel->x_res - 1; - l |= (panel->hsw - 1) << 10; - l |= (panel->hfp - 1) << 16; - l |= (panel->hbp - 1) << 24; - omap_writel(l, OMAP_LCDC_TIMING0); - - l = panel->y_res - 1; - l |= (panel->vsw - 1) << 10; - l |= panel->vfp << 16; - l |= panel->vbp << 24; - omap_writel(l, OMAP_LCDC_TIMING1); - - l = omap_readl(OMAP_LCDC_TIMING2); - l &= ~0xff; - - lck = clk_get_rate(lcdc.lcd_ck); - - if (!panel->pcd) - calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd); - else { - dev_warn(lcdc.fbdev->dev, - "Pixel clock divider value is obsolete.\n" - "Try to set pixel_clock to %lu and pcd to 0 " - "in drivers/video/omap/lcd_%s.c and submit a patch.\n", - lck / panel->pcd / 1000, panel->name); - - pcd = panel->pcd; - } - l |= pcd & 0xff; - l |= panel->acb << 8; - omap_writel(l, OMAP_LCDC_TIMING2); - - /* update panel info with the exact clock */ - panel->pixel_clock = lck / pcd / 1000; -} - -/* - * Configure the LCD controller, download the color palette and start a looped - * DMA transfer of the frame image data. Called only in internal - * controller mode. - */ -static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode) -{ - int r = 0; - - if (mode != lcdc.update_mode) { - switch (mode) { - case OMAPFB_AUTO_UPDATE: - setup_regs(); - load_palette(); - - /* Setup and start LCD DMA */ - setup_lcd_dma(); - - set_load_mode(OMAP_LCDC_LOAD_FRAME); - enable_irqs(OMAP_LCDC_IRQ_DONE); - /* This will start the actual DMA transfer */ - enable_controller(); - lcdc.update_mode = mode; - break; - case OMAPFB_UPDATE_DISABLED: - disable_controller(); - omap_stop_lcd_dma(); - lcdc.update_mode = mode; - break; - default: - r = -EINVAL; - } - } - - return r; -} - -static enum omapfb_update_mode omap_lcdc_get_update_mode(void) -{ - return lcdc.update_mode; -} - -/* PM code called only in internal controller mode */ -static void omap_lcdc_suspend(void) -{ - omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED); -} - -static void omap_lcdc_resume(void) -{ - omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE); -} - -static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps) -{ - return; -} - -int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data) -{ - BUG_ON(callback == NULL); - - if (lcdc.dma_callback) - return -EBUSY; - else { - lcdc.dma_callback = callback; - lcdc.dma_callback_data = data; - } - return 0; -} -EXPORT_SYMBOL(omap_lcdc_set_dma_callback); - -void omap_lcdc_free_dma_callback(void) -{ - lcdc.dma_callback = NULL; -} -EXPORT_SYMBOL(omap_lcdc_free_dma_callback); - -static void lcdc_dma_handler(u16 status, void *data) -{ - if (lcdc.dma_callback) - lcdc.dma_callback(lcdc.dma_callback_data); -} - -static int mmap_kern(void) -{ - struct vm_struct *kvma; - struct vm_area_struct vma; - pgprot_t pgprot; - unsigned long vaddr; - - kvma = get_vm_area(lcdc.vram_size, VM_IOREMAP); - if (kvma == NULL) { - dev_err(lcdc.fbdev->dev, "can't get kernel vm area\n"); - return -ENOMEM; - } - vma.vm_mm = &init_mm; - - vaddr = (unsigned long)kvma->addr; - vma.vm_start = vaddr; - vma.vm_end = vaddr + lcdc.vram_size; - - pgprot = pgprot_writecombine(pgprot_kernel); - if (io_remap_pfn_range(&vma, vaddr, - lcdc.vram_phys >> PAGE_SHIFT, - lcdc.vram_size, pgprot) < 0) { - dev_err(lcdc.fbdev->dev, "kernel mmap for FB memory failed\n"); - return -EAGAIN; - } - - lcdc.vram_virt = (void *)vaddr; - - return 0; -} - -static void unmap_kern(void) -{ - vunmap(lcdc.vram_virt); -} - -static int alloc_palette_ram(void) -{ - lcdc.palette_virt = dma_alloc_writecombine(lcdc.fbdev->dev, - MAX_PALETTE_SIZE, &lcdc.palette_phys, GFP_KERNEL); - if (lcdc.palette_virt == NULL) { - dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n"); - return -ENOMEM; - } - memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE); - - return 0; -} - -static void free_palette_ram(void) -{ - dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE, - lcdc.palette_virt, lcdc.palette_phys); -} - -static int alloc_fbmem(struct omapfb_mem_region *region) -{ - int bpp; - int frame_size; - struct lcd_panel *panel = lcdc.fbdev->panel; - - bpp = panel->bpp; - if (bpp == 12) - bpp = 16; - frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res); - if (region->size > frame_size) - frame_size = region->size; - lcdc.vram_size = frame_size; - lcdc.vram_virt = dma_alloc_writecombine(lcdc.fbdev->dev, - lcdc.vram_size, &lcdc.vram_phys, GFP_KERNEL); - if (lcdc.vram_virt == NULL) { - dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n"); - return -ENOMEM; - } - region->size = frame_size; - region->paddr = lcdc.vram_phys; - region->vaddr = lcdc.vram_virt; - region->alloc = 1; - - memset(lcdc.vram_virt, 0, lcdc.vram_size); - - return 0; -} - -static void free_fbmem(void) -{ - dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size, - lcdc.vram_virt, lcdc.vram_phys); -} - -static int setup_fbmem(struct omapfb_mem_desc *req_md) -{ - int r; - - if (!req_md->region_cnt) { - dev_err(lcdc.fbdev->dev, "no memory regions defined\n"); - return -EINVAL; - } - - if (req_md->region_cnt > 1) { - dev_err(lcdc.fbdev->dev, "only one plane is supported\n"); - req_md->region_cnt = 1; - } - - if (req_md->region[0].paddr == 0) { - lcdc.fbmem_allocated = 1; - if ((r = alloc_fbmem(&req_md->region[0])) < 0) - return r; - return 0; - } - - lcdc.vram_phys = req_md->region[0].paddr; - lcdc.vram_size = req_md->region[0].size; - - if ((r = mmap_kern()) < 0) - return r; - - dev_dbg(lcdc.fbdev->dev, "vram at %08x size %08lx mapped to 0x%p\n", - lcdc.vram_phys, lcdc.vram_size, lcdc.vram_virt); - - return 0; -} - -static void cleanup_fbmem(void) -{ - if (lcdc.fbmem_allocated) - free_fbmem(); - else - unmap_kern(); -} - -static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode, - struct omapfb_mem_desc *req_vram) -{ - int r; - u32 l; - int rate; - struct clk *tc_ck; - - lcdc.irq_mask = 0; - - lcdc.fbdev = fbdev; - lcdc.ext_mode = ext_mode; - - l = 0; - omap_writel(l, OMAP_LCDC_CONTROL); - - /* FIXME: - * According to errata some platforms have a clock rate limitiation - */ - lcdc.lcd_ck = clk_get(fbdev->dev, "lcd_ck"); - if (IS_ERR(lcdc.lcd_ck)) { - dev_err(fbdev->dev, "unable to access LCD clock\n"); - r = PTR_ERR(lcdc.lcd_ck); - goto fail0; - } - - tc_ck = clk_get(fbdev->dev, "tc_ck"); - if (IS_ERR(tc_ck)) { - dev_err(fbdev->dev, "unable to access TC clock\n"); - r = PTR_ERR(tc_ck); - goto fail1; - } - - rate = clk_get_rate(tc_ck); - clk_put(tc_ck); - - if (machine_is_ams_delta()) - rate /= 4; - if (machine_is_omap_h3()) - rate /= 3; - r = clk_set_rate(lcdc.lcd_ck, rate); - if (r) { - dev_err(fbdev->dev, "failed to adjust LCD rate\n"); - goto fail1; - } - clk_enable(lcdc.lcd_ck); - - r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev); - if (r) { - dev_err(fbdev->dev, "unable to get IRQ\n"); - goto fail2; - } - - r = omap_request_lcd_dma(lcdc_dma_handler, NULL); - if (r) { - dev_err(fbdev->dev, "unable to get LCD DMA\n"); - goto fail3; - } - - omap_set_lcd_dma_single_transfer(ext_mode); - omap_set_lcd_dma_ext_controller(ext_mode); - - if (!ext_mode) - if ((r = alloc_palette_ram()) < 0) - goto fail4; - - if ((r = setup_fbmem(req_vram)) < 0) - goto fail5; - - pr_info("omapfb: LCDC initialized\n"); - - return 0; -fail5: - if (!ext_mode) - free_palette_ram(); -fail4: - omap_free_lcd_dma(); -fail3: - free_irq(OMAP_LCDC_IRQ, lcdc.fbdev); -fail2: - clk_disable(lcdc.lcd_ck); -fail1: - clk_put(lcdc.lcd_ck); -fail0: - return r; -} - -static void omap_lcdc_cleanup(void) -{ - if (!lcdc.ext_mode) - free_palette_ram(); - cleanup_fbmem(); - omap_free_lcd_dma(); - free_irq(OMAP_LCDC_IRQ, lcdc.fbdev); - clk_disable(lcdc.lcd_ck); - clk_put(lcdc.lcd_ck); -} - -const struct lcd_ctrl omap1_int_ctrl = { - .name = "internal", - .init = omap_lcdc_init, - .cleanup = omap_lcdc_cleanup, - .get_caps = omap_lcdc_get_caps, - .set_update_mode = omap_lcdc_set_update_mode, - .get_update_mode = omap_lcdc_get_update_mode, - .update_window = NULL, - .suspend = omap_lcdc_suspend, - .resume = omap_lcdc_resume, - .setup_plane = omap_lcdc_setup_plane, - .enable_plane = omap_lcdc_enable_plane, - .setcolreg = omap_lcdc_setcolreg, -}; |