display.c
来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 2,061 行 · 第 1/5 页
C
2,061 行
/* * arch/arm/mach-omap2/display.c * * Copyright (C) 2005-2006 Texas Instruments, Inc. * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. * * Leveraged code from the OMAP24xx camera driver * Video-for-Linux (Version 2) camera capture driver for * the OMAP24xx camera controller. * * Author: Andy Lowe (source@mvista.com) * Copyright (C) 2004 MontaVista Software, Inc. * * History: * 20-APR-2006 Khasim Modified VRFB based Rotation equations, * The image data is always read from 0 degree * view and written to the virtual space of desired * rotation angle */#include <linux/module.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/err.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/arch/hardware.h>#include <asm/arch/display.h>#include <asm/arch/venc.h>#include <asm/arch/clock.h>extern int lpr_enabled;/* usage count for DSS power management */static int disp_usage;static int omap2_current_tvstandard = NTSC_M;static spinlock_t dss_lock;short int current_colorconv_values[2][3][3];static struct omap_dss_regs dss_ctx;static struct clk *dss1f_scale;static struct tvlcd_status_t tvlcd_status;static struct clk *dss1f, *dss1i;struct omap2_disp_dma_params { u32 ba0; u32 ba1; int row_inc; int pix_inc;};static struct layer_t { int output_dev; int in_use; int ctx_valid; /* one set of dma parameters each for LCD and TV */ struct omap2_disp_dma_params dma[2]; int size_x; int size_y;} layer[DSS_CTX_NUMBER] = { {.ctx_valid = 0,}, {.ctx_valid = 0,}, {.ctx_valid = 0,}, {.ctx_valid = 0,}, {.ctx_valid = 0,},};#define MAX_ISR_NR 8static int omap2_disp_irq;static struct { omap2_disp_isr_t isr; void *arg; unsigned int mask;} registered_isr[MAX_ISR_NR];/* VRFB offset computation parameters */#define SIDE_H 1 #define SIDE_W 0 /* GFX FIFO thresholds */#define RMODE_GFX_FIFO_HIGH_THRES 0x3FC#define RMODE_GFX_FIFO_LOW_THRES 0x3BC/* * DSS register I/O routines */static __inline__ u32dss_reg_in(u32 offset){ return omap_readl(DSS_REG_BASE + DSS_REG_OFFSET + offset);}static __inline__ u32dss_reg_out(u32 offset, u32 val){ omap_writel(val,DSS_REG_BASE + DSS_REG_OFFSET + offset); return val;}static __inline__ u32dss_reg_merge(u32 offset, u32 val, u32 mask){ u32 addr = DSS_REG_BASE + DSS_REG_OFFSET + offset; u32 new_val = (omap_readl(addr) & ~mask) | (val & mask); omap_writel(new_val, addr); return new_val;}/* * Display controller register I/O routines */static __inline__ u32dispc_reg_in(u32 offset){ return omap_readl(DSS_REG_BASE + DISPC_REG_OFFSET + offset);}static __inline__ u32dispc_reg_out(u32 offset, u32 val){ omap_writel(val, DSS_REG_BASE + DISPC_REG_OFFSET + offset); return val;}static __inline__ u32dispc_reg_merge(u32 offset, u32 val, u32 mask){ u32 addr = DSS_REG_BASE + DISPC_REG_OFFSET + offset; u32 new_val = (omap_readl(addr) & ~mask) | (val & mask); omap_writel(new_val, addr); return new_val;}/* * RFBI controller register I/O routines */static __inline__ u32rfbi_reg_in(u32 offset){ return omap_readl(DSS_REG_BASE + RFBI_REG_OFFSET + offset);}static __inline__ u32rfbi_reg_out(u32 offset, u32 val){ omap_writel(val, DSS_REG_BASE + RFBI_REG_OFFSET + offset); return val;}/* * VENC register I/O Routines */static __inline__ u32venc_reg_in(u32 offset){ return omap_readl(DSS_REG_BASE + VENC_REG_OFFSET + offset);}static __inline__ u32venc_reg_out(u32 offset, u32 val){ omap_writel(val, DSS_REG_BASE + VENC_REG_OFFSET + offset); return val;}static __inline__ u32venc_reg_merge(u32 offset, u32 val, u32 mask){ u32 addr = DSS_REG_BASE + VENC_REG_OFFSET + offset; u32 new_val = (omap_readl(addr) & ~mask) | (val & mask); omap_writel(new_val, addr); return new_val;}/* Write the color space conversion coefficients to the display controller * registers. Each coefficient is a signed 11-bit integer in the range * [-1024, 1023]. The matrix coefficients are: * [ RY RCr RCb ] * [ GY GCr GCb ] * [ BY BCr BCb ] */static voidset_colorconv(int v,int colorspace){ unsigned long ccreg; short int mtx[3][3]; int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++){ mtx[i][j] = current_colorconv_values[v][i][j]; } ccreg = (mtx[0][0] & 0x7ff) | ((mtx[0][1] & 0x7ff) << 16); dispc_reg_out(DISPC_VID_CONV_COEF0(v), ccreg); ccreg = (mtx[0][2] & 0x7ff) | ((mtx[1][0] & 0x7ff) << 16); dispc_reg_out(DISPC_VID_CONV_COEF1(v), ccreg); ccreg = (mtx[1][1] & 0x7ff) | ((mtx[1][2] & 0x7ff) << 16); dispc_reg_out(DISPC_VID_CONV_COEF2(v), ccreg); ccreg = (mtx[2][0] & 0x7ff) | ((mtx[2][1] & 0x7ff) << 16); dispc_reg_out(DISPC_VID_CONV_COEF3(v), ccreg); ccreg = mtx[2][2] & 0x7ff; dispc_reg_out(DISPC_VID_CONV_COEF4(v), ccreg); if(colorspace == V4L2_COLORSPACE_JPEG || colorspace == V4L2_COLORSPACE_SRGB){ dispc_reg_merge(DISPC_VID_ATTRIBUTES(v), DISPC_VID_ATTRIBUTES_VIDFULLRANGE, DISPC_VID_ATTRIBUTES_VIDFULLRANGE); }}static voidupdate_colorconv_mtx(int v,const short int mtx[3][3]){ int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) current_colorconv_values[v][i][j] = mtx[i][j];}voidomap2_disp_set_default_colorconv(int ltype, struct v4l2_pix_format *pix){ int v; if (ltype == OMAP2_VIDEO1) v = 0; else if (ltype == OMAP2_VIDEO2) v = 1; else return; switch (pix->colorspace) { case V4L2_COLORSPACE_SMPTE170M: case V4L2_COLORSPACE_SMPTE240M: case V4L2_COLORSPACE_BT878: case V4L2_COLORSPACE_470_SYSTEM_M: case V4L2_COLORSPACE_470_SYSTEM_BG: /* luma (Y) range lower limit is 16, BT.601 standard */ update_colorconv_mtx(v,cc_bt601); set_colorconv(v,pix->colorspace); break; case V4L2_COLORSPACE_REC709: /* luma (Y) range lower limit is 16, BT.709 standard */ update_colorconv_mtx(v,cc_bt709); set_colorconv(v,pix->colorspace); break; case V4L2_COLORSPACE_JPEG: case V4L2_COLORSPACE_SRGB: /* full luma (Y) range, assume BT.601 standard */ update_colorconv_mtx(v,cc_bt601_full); set_colorconv(v,pix->colorspace); break; }}voidomap2_disp_set_colorconv(int ltype, struct v4l2_pix_format *pix){ int v; if (ltype == OMAP2_VIDEO1) v = 0; else if (ltype == OMAP2_VIDEO2) v = 1; else return; set_colorconv(v,pix->colorspace);}/* Write the horizontal and vertical resizing coefficients to the display * controller registers. Each coefficient is a signed 8-bit integer in the * range [-128, 127] except for the middle coefficient (vc[1][i] and hc[3][i]) * which is an unsigned 8-bit integer in the range [0, 255]. The first index of * the matrix is the coefficient number (0 to 2 vertical or 0 to 4 horizontal) * and the second index is the phase (0 to 7). */static voidomap2_disp_set_resize(int v, short int *vc, short int *hc){ int i; unsigned long reg; for (i = 0; i < 8; i++) { reg = (*(hc+(8*0)+i) & 0xff) | ((*(hc+(8*1)+i) & 0xff) << 8) | ((*(hc+(8*2)+i) & 0xff) << 16) | ((*(hc+(8*3)+i) & 0xff) << 24); dispc_reg_out(DISPC_VID_FIR_COEF_H(v, i), reg); reg = (*(hc+(8*4)+i) & 0xff) | ((*(vc+(0*8)+i) & 0xff) << 8) | ((*(vc+(8*1)+i) & 0xff) << 16) | ((*(vc+(2*8)+i) & 0xff) << 24); dispc_reg_out(DISPC_VID_FIR_COEF_HV(v, i), reg); }}/*---------------------------------------------------------------------------*/voidomap2_disp_get_panel_size(int output_dev, int *width, int *height){ unsigned long size; if (output_dev == OMAP2_OUTPUT_TV) { size = dispc_reg_in(DISPC_SIZE_DIG); *width = 1 + ((size & DISPC_SIZE_DIG_PPL) >> DISPC_SIZE_DIG_PPL_SHIFT); *height = 1 + ((size & DISPC_SIZE_DIG_LPP) >> DISPC_SIZE_DIG_LPP_SHIFT); *height = *height << 1; } else if (output_dev == OMAP2_OUTPUT_LCD) { size = dispc_reg_in(DISPC_SIZE_LCD); *width = 1 + ((size & DISPC_SIZE_LCD_PPL) >> DISPC_SIZE_LCD_PPL_SHIFT); *height = 1 + ((size & DISPC_SIZE_LCD_LPP) >> DISPC_SIZE_LCD_LPP_SHIFT); }}voidomap2_disp_set_panel_size(int output_dev, int width, int height){ unsigned long size; if (output_dev == OMAP2_OUTPUT_TV) { height = height >> 1; size = ((width - 1) << DISPC_SIZE_DIG_PPL_SHIFT) & DISPC_SIZE_DIG_PPL; size |= ((height - 1) << DISPC_SIZE_DIG_LPP_SHIFT) & DISPC_SIZE_DIG_LPP; dispc_reg_out(DISPC_SIZE_DIG, size); } else if (output_dev == OMAP2_OUTPUT_LCD) { size = ((width - 1) << DISPC_SIZE_LCD_PPL_SHIFT) & DISPC_SIZE_LCD_PPL; size |= ((height - 1) << DISPC_SIZE_LCD_LPP_SHIFT) & DISPC_SIZE_LCD_LPP; //dispc_reg_out(DISPC_SIZE_LCD, size); dispc_reg_out(DISPC_SIZE_LCD,0x02FF03FF); }}static int graphics_in_use;/* Turn off the GFX, or video1, or video2 layer. */voidomap2_disp_disable_layer(int ltype){ unsigned long attributes; int digital, v; if (ltype == OMAP2_GRAPHICS) { attributes = dispc_reg_merge(DISPC_GFX_ATTRIBUTES, 0, DISPC_GFX_ATTRIBUTES_ENABLE); digital = attributes & DISPC_GFX_ATTRIBUTES_GFXCHANNELOUT; graphics_in_use = 0; } else { if (ltype == OMAP2_VIDEO1) v = 0; else if (ltype == OMAP2_VIDEO2) v = 1; else return; attributes = dispc_reg_merge(DISPC_VID_ATTRIBUTES(v), 0, DISPC_VID_ATTRIBUTES_ENABLE); digital = attributes & DISPC_VID_ATTRIBUTES_VIDCHANNELOUT; } if (digital) { /* digital output */ dispc_reg_merge(DISPC_CONTROL, DISPC_CONTROL_GODIGITAL, DISPC_CONTROL_GODIGITAL); } else { /* LCD */ dispc_reg_merge(DISPC_CONTROL, DISPC_CONTROL_GOLCD, DISPC_CONTROL_GOLCD); } dispc_reg_merge(DISPC_CONTROL, 0, DISPC_CONTROL_OVERLAYOPTIMIZATION);}/* Turn on the GFX, or video1, or video2 layer. */voidomap2_disp_enable_layer(int ltype){ unsigned long attributes; int digital, v; if (ltype == OMAP2_GRAPHICS) { attributes = dispc_reg_merge(DISPC_GFX_ATTRIBUTES, DISPC_GFX_ATTRIBUTES_ENABLE, DISPC_GFX_ATTRIBUTES_ENABLE); digital = attributes & DISPC_GFX_ATTRIBUTES_GFXCHANNELOUT; graphics_in_use = 1; } else { if (ltype == OMAP2_VIDEO1) v = 0; else if (ltype == OMAP2_VIDEO2) v = 1; else return; attributes = dispc_reg_merge(DISPC_VID_ATTRIBUTES(v), DISPC_VID_ATTRIBUTES_ENABLE, DISPC_VID_ATTRIBUTES_ENABLE); digital = attributes & DISPC_VID_ATTRIBUTES_VIDCHANNELOUT; } if (digital) { /* digital output */ dispc_reg_merge(DISPC_CONTROL, DISPC_CONTROL_GODIGITAL, DISPC_CONTROL_GODIGITAL); } else { /* LCD */ dispc_reg_merge(DISPC_CONTROL, DISPC_CONTROL_GOLCD,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?