📄 slcdc.c
字号:
/*
* 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
*
* Copyright (C) 2002 Motorola Semiconductors HK Ltd
*
*/
///@example slcdctest.c test driver using EPSON L2F50032T00 serial mode
///
/**
*
* @defgroup SLCDC SLCDC driver
**/
/**@{*/
/**
* @file slcdc.c
* @brief slcdc driver source code
*
* This is the basic release for SLCDC driver, which is to support EPSON L2F50032T00 16bit seria mode5-6-5 \n
* and parallel mode. This driver acts as a standard character device, which can be dinamically loaded.\n
* For example, you can refer to slcdctest.c file.
*
* Modification History:
* 15,Dec,2003 Karen Kang
*
* @bug
**/
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/wrapper.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/miscdevice.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/tqueue.h>
#include <linux/wait.h>
#include <linux/pm.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/uaccess.h> /* get_user,copy_to_user */
#include <asm/irq.h>
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/arch/apmc.h>
#ifdef CONFIG_ARCH_MX2ADS
#include <asm/arch/mx2.h>
#endif
#define MODULE_NAME "slcdc"
//#define DBMX_DEBUG 1
#ifdef DBMX_DEBUG
#define TRACE(fmt, args...) \
{ \
printk("\n %s:%d:%s:",__FILE__, __LINE__,__FUNCTION__); \
printk(fmt, ## args);\
}
#else
#define TRACE(fmt, args...)
#endif
#define FAILED(fmt, args...) \
{ \
printk("\n %s:%d:%s:",__FILE__, __LINE__,__FUNCTION__); \
printk(fmt, ## args);\
}
#define INFO(fmt, args...) \
{ \
printk("\n"); \
printk(fmt, ## args);\
}
/*@brief definition for SLCDC_LCD_TXCONFIG */
#define SLCDC_IMG_8L 0x00020000
/*@brief config macro for serial mode or parallel mode */
#define SLCDC_SERIAL_MODE
//#define SLCDC_PARALLE_MODE
/**
*@name ioctl command macro definitions
*@brief definition for SLCDC ioctl cmd,these command definition is different for serial \n
* mode and paralel mode ,in this driver, we have not supported all these commands, \n
* please check the ioctl function for details.
**/
/**@{*/
//definition for SLCDC cmd
/* same as Epson 10043 & 50052 */
#ifdef SLCDC_SERIAL_MODE
#define SLCDC_CMD_DISON 0xaf00 /*!< 1. display on */
#define SLCDC_CMD_DISOFF 0xae00 /*!< 2. display off*/
#define SLCDC_CMD_DISNOR 0xa600 /*!< 3. normal display*/
#define SLCDC_CMD_DISINV 0xa700 /*!< 4. inverse display*/
#define SLCDC_CMD_DISCTL 0xca00 /*!< 5. display control*/
#define SLCDC_CMD_SLPIN 0x9500 /*!< 10.sleep in*/
#define SLCDC_CMD_SLPOUT 0x9400 /*!< 11.sleep out*/
#define SLCDC_CMD_SD_PSET 0x7500 /*!< 12.page address set*/
#define SLCDC_CMD_SD_CSET 0x1500 /*!< 14.column address set*/
#define SLCDC_CMD_DATCTL 0xbc /*!< 16.data scan direction, etc.*/
#define SLCDC_CMD_RAMWR 0x5c00 /*!< 17.writing to memory*/
#define SLCDC_CMD_PTLIN 0xa800 /*!< 19.partial display in*/
#define SLCDC_CMD_PTLOUT 0xa900 /*!< 20.partial display out*/
/* value different from 10043 but same as 50052 */
#define SLCDC_CMD_VOLCTR 0xc600 /*!< 25.Electronic volume control*/
/* commands not found in 10043 but in 50052*/
#define SLCDC_CMD_GCP64 0xcb00 /*!< 6. 64 grayscale pulse positon set*/
#define SLCDC_CMD_GCP16 0xcc00 /*!< 7. 16 grayscale pulse positon set*/
#define SLCDC_CMD_GSSET 0xcd00 /*!< 8. grayscale set*/
#define SLCDC_CMD_RAMRD 0x5d00 /*!< 18.memory read*/
#define SLCDC_CMD_ASCSET 0xaa00 /*!< 21.area scroll set*/
#define SLCDC_CMD_SCSTART 0xab00 /*!< 22.scroll start set*/
#define SLCDC_CMD_EPCTIN 0x6100 /*!< 26.Power IC control for EVR*/
#define SLCDC_CMD_EPCTOUT 0x6200 /*!< 27.Power IC control for EVR*/
#else
#define SLCDC_CMD_DISON 0xaf ///1. display on
#define SLCDC_CMD_DISOFF 0xae ///2. display off
#define SLCDC_CMD_DISNOR 0xa6 ///3. normal display
#define SLCDC_CMD_DISINV 0xa7 ///4. inverse display
#define SLCDC_CMD_DISCTL 0xca ///5. display control
#define SLCDC_CMD_SLPIN 0x95 ///10.sleep in
#define SLCDC_CMD_SLPOUT 0x94 ///11.sleep out
#define SLCDC_CMD_SD_PSET 0x75 ///12.page address set
#define SLCDC_CMD_SD_CSET 0x15 ///14.column address set
#define SLCDC_CMD_DATCTL 0xbc ///16.data scan direction, etc.
//#define SLCDC_CMD_DATCTL 0xbc00 ///16.data scan direction, etc.
#define SLCDC_CMD_RAMWR 0x5c ///17.writing to memory
#define SLCDC_CMD_PTLIN 0xa8 ///19.partial display in
#define SLCDC_CMD_PTLOUT 0xa9 ///20.partial display out
/* value different from 10043 but same as 50052 */
#define SLCDC_CMD_VOLCTR 0xc6 ///25.Electronic volume control
/* commands not found in 10043 but in 50052*/
#define SLCDC_CMD_GCP64 0xcb ///6. 64 grayscale pulse positon set
#define SLCDC_CMD_GCP16 0xcc ///7. 16 grayscale pulse positon set
#define SLCDC_CMD_GSSET 0xcd ///8. grayscale set
#define SLCDC_CMD_RAMRD 0x5d ///18.memory read
#define SLCDC_CMD_ASCSET 0xaa ///21.area scroll set
#define SLCDC_CMD_SCSTART 0xab ///22.scroll start set
#define SLCDC_CMD_EPCTIN 0x61 ///26.Power IC control for EVR
#define SLCDC_CMD_EPCTOUT 0x62 ///27.Power IC control for EVR
#endif
/**@}*/
#define SLCDC_IRQ 60
#define SLCDC_CMD_MEM_SIZE 4
#define SLCDC_WIDTH 176
#define SLCDC_HIGH 220
#define SLCDC_BPP 16
//#define SLCDC_PIXEL_MEM_SIZE 77400
#define SLCDC_PIXEL_MEM_SIZE (SLCDC_WIDTH*SLCDC_HIGH*SLCDC_BPP)/8
#define _SLCDC_DATA_SIZE_ (SLCDC_PIXEL_MEM_SIZE + 32)
#define SLCDC_DATA_MEM_SIZE (PAGE_ALIGN(_SLCDC_DATA_SIZE_ + PAGE_SIZE * 2))
//bit mask definition in STAT/CTRL register
#define SLCDC_TRANSFER_BUSY 0x4
#define SLCDC_TRANSFER_ERROR 0x10
//<<<<<< Global Variable
u16 * g_slcdc_dbuffer_address;//used for SLCDC data buffer
u16 * g_slcdc_dbuffer_phyaddress;//physical address for SLCDC data buffer
u16 * g_slcdc_cbuffer_address;//used for SLCDC command buffer
u16 * g_slcdc_cbuffer_phyaddress;//physical address for SLCDC command buffer
static wait_queue_head_t slcdc_wait;
static int g_slcdc_major=0;
static devfs_handle_t g_devfs_handle;
static wait_queue_head_t slcdc_wait;
struct pm_dev *g_slcdc_pm;
static int g_slcdc_status;
struct apmc_user *g_Slcdc_apmc;
#define SLCDC_OPEN_STATUS 0x0001
#define SLCDC_SUSPEND_STATUS 0x0002
int slcdc_open(struct inode * inode, struct file * filp);
int slcdc_release(struct inode * inode, struct file * filp);
static int slcdc_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg);
static int slcdc_mmap(struct file *filp, struct vm_area_struct *vma);
typedef struct{
u16* screen_start_address;
u16* v_screen_start_address;
}slcdc_par_t;
slcdc_par_t slcdc_par;
struct file_operations g_slcdc_fops =
{
open: slcdc_open,
release: slcdc_release,
ioctl: slcdc_ioctl,
mmap: slcdc_mmap,
};
//>>>>>> Global Variable
//#define SLCDC_MUX_LCDC
#define SLCDC_MUX_SDHC2
#define USING_INTERRUPT_SLCDC
void slcdc_delay(int num)
{
volatile int i,j;
j = 0;
for(i=0;i<num;i++)
{
j++;
}
}
/**
*@brief slcdc gpio configure routine for serial mode
*
* Function Name: slcdc_gpio_serial
*
*
* Description:This routine will implement gpio configurations for serial mode both for\n
* LCDC mux and SDHC2 mux, you can use macro SLCDC_MUX_LCDC or SLCDC_MUX_SDHC2 \n
* to choose the right way according to your hardware configuration.
*
*
*@return None
*
* Modification History:
* Dec,2003 Karen update for MX21 TO2
* Jun,2004 Shirley update for LCDC mux
*
**/
void slcdc_gpio_serial(void)
{
#ifdef SLCDC_MUX_LCDC
//configure slcdc gpio setting using pa24~27 (AIN), muxed with LCD panel
_reg_GPIO_GIUS(GPIOA) |= 0x0f000000;
_reg_GPIO_DDIR(GPIOA) |= 0x0f000000;
_reg_GPIO_OCR2(GPIOA) &= ~0x00ff0000;
#endif
#ifdef SLCDC_MUX_SDHC2
//configure slcdc gpio setting using pb6~9(AIN), muxed with SDHC2
_reg_GPIO_GIUS(GPIOB) |= 0x000003C0;
_reg_GPIO_DDIR(GPIOB) |= 0x000003C0;
_reg_GPIO_OCR1(GPIOB) &= ~0x000ff000;
#endif
}
/**
*@brief slcdc gpio configure routine for parallel mode
*
* Function Name: slcdc_gpio_paralle
*
*
* Description:This routine will implement gpio configurations for parralel mode both for\n
* LCDC mux and SDHC2 mux, you can use macro SLCDC_MUX_LCDC or SLCDC_MUX_SDHC2 \n
* to choose the right way according to your hardware configuration.
*
*
*@return None
*
* Modification History:
* Jun,2004 Shirley update for LCDC mux
*
**/
void slcdc_gpio_paralle(void)
{
#ifdef SLCDC_MUX_LCDC
//configure slcdc gpio setting using pa25/26 and pa6~21 (AIN), muxed with LCD panel
_reg_GPIO_GIUS(GPIOA) |= 0x06bfffc0;
_reg_GPIO_DDIR(GPIOA) |= 0x06bfffc0;
_reg_GPIO_OCR1(GPIOA) &= ~0xfffff000;
_reg_GPIO_OCR2(GPIOA) &= ~0x003c0fff;
_reg_GPIO_OCR2(GPIOA) |= 0x0000c000;
_reg_GPIO_DR(GPIOA) &= ~(1<<23);
#endif
#ifdef SLCDC_MUX_SDHC2
//configure slcdc gpio setting using pb7-8/pb25-31/pc5-pc13, muxed with SDHC2; ##need hardware test
_reg_GPIO_GIUS(GPIOB) |= 0xfe000180;
_reg_GPIO_DDIR(GPIOB) |= 0xfe000180;
_reg_GPIO_OCR1(GPIOB) &= ~0x0003c000;
_reg_GPIO_OCR2(GPIOB) &= ~0xfffc0000;
_reg_GPIO_GIUS(GPIOC) |= 0x00003FE0;
_reg_GPIO_DDIR(GPIOC) |= 0x00003FE0;
_reg_GPIO_OCR1(GPIOC) &= ~0x0FFFFC00;
#endif
}
void slcdc_reset(int level)
{
if(level == 0)
{
#ifdef SLCDC_MUX_LCDC
//OE_ACD as a reset pin
_reg_GPIO_GIUS(GPIOA) |= 0x80000000;
_reg_GPIO_OCR2(GPIOA) |= 0xc0000000;
_reg_GPIO_DDIR(GPIOA) |= 0x80000000;
//set reset pin to low
_reg_GPIO_DR(GPIOA) &= 0x7fffffff;
#endif
#ifdef SLCDC_MUX_SDHC2
//SD2_D1 as reset pin
_reg_GPIO_GIUS(GPIOB) |= 0x00000020;
_reg_GPIO_OCR1(GPIOB) |= 0x00000c00;
_reg_GPIO_DDIR(GPIOB) |= 0x00000020;
//set reset pin to low
_reg_GPIO_DR(GPIOB) &= 0xffffffdf;
#endif
}
else
{
#ifdef SLCDC_MUX_LCDC
//set reset pin to high
_reg_GPIO_DR(GPIOA) |= 0x80000000;
#endif
#ifdef SLCDC_MUX_SDHC2
//set reset pin to high
_reg_GPIO_DR(GPIOB) |= 0x00000020;
#endif
}
}
void slcdc_init_dev(void)
{
_reg_MAX_SLV_SGPCR(3) |= 0x00040000;
_reg_SYS_PCSR |= 0x00000004;//set LCD/SLCD bus master high priority
//enable the slcd clk
_reg_CRM_PCCR0 |= 0x02200000;
}
void slcdc_init_reg(void)
{
_reg_SLCDC_DBADDR = 0;
_reg_SLCDC_DBUF_SIZE = 0;
_reg_SLCDC_CBADDR = 0;
_reg_SLCDC_CBUF_SIZE = 0;
_reg_SLCDC_CBUF_SSIZE = 0;
_reg_SLCDC_FIFO_CONFIG = 0;
_reg_SLCDC_LCD_CONFIG = 0;
_reg_SLCDC_LCD_TXCONFIG = 0;
_reg_SLCDC_LCD_CTRL_STAT= 0;
_reg_SLCDC_LCD_CLKCONFIG= 0;
}
void slcdc_config(int datlen)
{
u32 xfrmode, sckpol,worddefcom,imgend=0,worddefwrite=0,worddefdat = 0;
if(datlen == 8)
{
imgend = 0x2;//8-bit little endian;
worddefdat = 0;//8-bit data
worddefwrite = 10;
}
else if(datlen == 16)
{
imgend = 0x1;//16-bit little endian;
worddefdat = 1;//16-bit data
worddefwrite = 1;
}
worddefcom = 1;
#ifdef SLCDC_SERIAL_MODE
xfrmode = 0;//serial mode
#else
xfrmode = 1;//paralle mode
#endif
sckpol = 1;//falling edge
//config to be little endian serial 16bit
_reg_SLCDC_LCD_TXCONFIG = (imgend<<16)|(worddefdat<<4)|(worddefcom<<3)|(xfrmode<<2)|(sckpol);
// printk("SLCDC_TXCONFIG = %x \n",_reg_SLCDC_LCD_TXCONFIG);
//config dma setting
_reg_SLCDC_FIFO_CONFIG = 5;//burst length is 4 32-bit words
//config buffer address setting
_reg_SLCDC_DBADDR = (u32)(slcdc_par.screen_start_address);
_reg_SLCDC_CBADDR = (u32)g_slcdc_cbuffer_phyaddress;
//config clk setting
_reg_SLCDC_LCD_CLKCONFIG = 0x3;
//set GO 0
_reg_SLCDC_LCD_CTRL_STAT = 0;
slcdc_delay(5000);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -