omapfb_lcdc.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 263 行
C
263 行
/* * File: drivers/video/omap/omapfb_main.c * * Support code for the internal LCD controller on TI OMAP boards * * Copyright (C) 2004 Nokia Corporation * Author: Imre Deak <imre.deak@nokia.com> * * Acknowledgements: * Juha Yrjola <juha.yrjola@nokia.com> - Modifications * * 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/config.h>#include <linux/module.h>#include <linux/mm.h>#include <linux/fb.h>#include <asm/arch/dma.h>#include "omapfb.h"#include "lcdc.h"#include "debug.h"/* Configure the LCD DMA according to the current mode specified by parameters * in fbdev and fbdev->var. */static void lcddma_setup_mode(struct omapfb_device *fbdev){ static const int dma_elem_type[] = { 0, OMAP_DMA_DATA_TYPE_S8, OMAP_DMA_DATA_TYPE_S16, 0, OMAP_DMA_DATA_TYPE_S32, }; struct fb_var_screeninfo *var = &fbdev->fb_info->var; unsigned long src; int esize, xelem, yelem; src = fbdev->lcddma_handle + fbdev->vis_frame_org + fbdev->view_org; switch (var->rotate) { case 0: esize = fbdev->mirror || (src & 3) ? 2 : 4; xelem = var->xres * var->bits_per_pixel / 8 / esize; yelem = var->yres; break; case 90: case 180: case 270: esize = 2; xelem = var->xres * var->bits_per_pixel / 16; yelem = var->yres; break; default: BUG(); return; } DBGPRINT(1, "setup_dma: src=%#010x esize=%d xelem=%d yelem=%d\n", src, esize, xelem, yelem); omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]); omap_set_lcd_dma_single_transfer(0); if (!cpu_is_omap1510()) { /* Set virtual xres elem size */ omap_set_lcd_dma_b1_vxres( fbdev->fb_info->fix.line_length / esize); /* Setup transformations */ omap_set_lcd_dma_b1_rotation(var->rotate); omap_set_lcd_dma_b1_mirror(fbdev->mirror); omap_set_lcd_dma_b1_scale(fbdev->xscale, fbdev->yscale); }}/* 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 controler, 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 void omapfb_lcdc_change_mode(struct omapfb_device *fbdev){ DBGENTER(1); if (fbdev->ext_lcdc) { BUG(); return; } omap_stop_lcd_dma(); if (!irqs_disabled()) { /* Defer LCD DMA reprogramming for a safe time to avoid * the tearing effect. */ omap_lcdc_enable_irqs(OMAP_LCDC_IRQ_DONE); fbdev->state = OMAPFB_MODE_CHANGE; omap_lcdc_disable_async(); } else { /* If IRQs are disabled change mode here synchronously. */ omap_lcdc_disable(); lcddma_setup_mode(fbdev); omap_setup_lcd_dma(); omap_lcdc_enable(); } DBGLEAVE(1);}/* Called by the LCD DMA core when the last frame has been transferred after * disabling the LCD controller, or when palette loading has been finished. * We use the DONE event for changing to a new mode to avoid any flicker. */static void lcdc_irq_handler(u32 status, unsigned long data){ struct omapfb_device *fbdev = (struct omapfb_device *)data; DBGENTER(2); DBGPRINT(2, "status=%#010x\n", status); if (likely((status & OMAP_LCDC_STAT_DONE) && fbdev->state == OMAPFB_MODE_CHANGE)) { /* Reprogram DMA and restart lcdc */ lcddma_setup_mode(fbdev); omap_setup_lcd_dma(); fbdev->state = OMAPFB_ACTIVE; omap_lcdc_enable(); } if (status & OMAP_LCDC_STAT_LOADED_PALETTE) { omap_lcdc_disable_async(); complete(&fbdev->load_complete); } DBGLEAVE(2);}/* 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 seperately. */static void omapfb_lcdc_load_palette(struct omapfb_device *fbdev){ DBGENTER(1); omap_lcdc_init_palette(fbdev->panel->video_mode, fbdev->lcddma_base + fbdev->palette_org, fbdev->palette_size); omap_set_lcd_dma_b1(fbdev->lcddma_handle + fbdev->palette_org, fbdev->palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32); omap_set_lcd_dma_single_transfer(1); omap_setup_lcd_dma(); init_completion(&fbdev->load_complete); omap_lcdc_enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE); omap_lcdc_set_load_mode(OMAP_LCDC_LOAD_PALETTE); omap_lcdc_enable(); wait_for_completion(&fbdev->load_complete); /* The controller gets disabled in the irq handler */ omap_lcdc_disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE); omap_stop_lcd_dma(); DBGLEAVE(1);}/* Configure the LCD controller, download the color palette and start a looped * DMA transfer of the frame image data. */static void omapfb_lcdc_start(struct omapfb_device *fbdev){ DBGENTER(1); omap_lcdc_set_config(fbdev->panel->config & LCD_PANEL_TFT, fbdev->panel->signals); omap_lcdc_set_video_mode(fbdev->panel->video_mode); omapfb_lcdc_load_palette(fbdev); /* Setup and start LCD DMA */ lcddma_setup_mode(fbdev); omap_setup_lcd_dma(); omap_lcdc_set_load_mode(OMAP_LCDC_LOAD_FRAME); omap_lcdc_enable_irqs(OMAP_LCDC_IRQ_DONE); /* This will start the actual DMA transfer */ omap_lcdc_enable(); DBGLEAVE(1);}/* Stop the looped LCD DMA transfer */static void omapfb_lcdc_stop(struct omapfb_device *fbdev){ DBGENTER(1); omap_lcdc_disable(); omap_stop_lcd_dma(); DBGLEAVE(1);}static int omapfb_lcdc_init(struct omapfb_device *fbdev){ int size, xres, yres, r; r = omap_lcdc_init(); if (r < 0) { PRNERR("LCDC initialization failed\n"); return r; } xres = fbdev->panel->video_mode->x_res; yres = fbdev->panel->video_mode->y_res; fbdev->palette_size = omap_lcdc_get_palette_size(fbdev->panel->video_mode); size = (fbdev->palette_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); size += xres * fbdev->panel->video_mode->bpp / 8 * yres; fbdev->lcddma_mem_size = size; fbdev->frame0_org = (fbdev->palette_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); fbdev->palette_org = fbdev->frame0_org - fbdev->palette_size; r = omap_request_lcd_dma(NULL, NULL); if (r) { PRNERR("unable to get LCD DMA\n"); goto lcdc_cleanup; } r = omap_lcdc_request(fbdev, lcdc_irq_handler, (unsigned long)fbdev); if (r) { PRNERR("unable to request LCD controller\n"); goto free_dma; } return 0;free_dma: omap_free_lcd_dma();lcdc_cleanup: omap_lcdc_cleanup(); return r;}static void omapfb_lcdc_cleanup(struct omapfb_device *fbdev){ omap_lcdc_release(fbdev); omap_free_lcd_dma(); omap_lcdc_cleanup();}struct lcd_ctrl omapfb_lcdc_ctrl = { .name = "internal", .init = omapfb_lcdc_init, .cleanup = omapfb_lcdc_cleanup, .start = omapfb_lcdc_start, .stop = omapfb_lcdc_stop, .suspend = NULL, .resume = NULL, .change_mode = omapfb_lcdc_change_mode,};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?