📄 slcdc.c
字号:
}
//for command transfer, it is very short, will not use interrupt
int slcdc_send_cmd(u32 length)
{
u32 status;
//disable interrupt
_reg_SLCDC_LCD_CTRL_STAT &=0xffffff7f;
//set length
_reg_SLCDC_DBUF_SIZE = length;
//set automode 00 for command
_reg_SLCDC_LCD_CTRL_STAT &= 0x000001ff;
//set GO
_reg_SLCDC_LCD_CTRL_STAT |= 0x1;
//polling for data transfer finish
status = _reg_SLCDC_LCD_CTRL_STAT;
while((!(status & SLCDC_TRANSFER_ERROR))&&(status & SLCDC_TRANSFER_BUSY))
{
status = _reg_SLCDC_LCD_CTRL_STAT;
}
if(status & SLCDC_TRANSFER_ERROR)
{
TRACE("send cmd error status=0x%x \n",status);
return 1;
}
else
{
_reg_SLCDC_LCD_CTRL_STAT |= 0x40;
_reg_SLCDC_LCD_CTRL_STAT |= 0x20;
return 0;
}
}
void slcdc_send_data(u32 length)
{
//enable interrupt
#ifdef USING_INTERRUPT_SLCDC
_reg_SLCDC_LCD_CTRL_STAT |= ~0xffffff7f;
#endif
//set length
_reg_SLCDC_DBUF_SIZE = length;
//set automode 01 for data
_reg_SLCDC_LCD_CTRL_STAT |= 0x00000800;
//set GO
_reg_SLCDC_LCD_CTRL_STAT |= 0x1;
#ifdef USING_INTERRUPT_SLCDC
interruptible_sleep_on(&slcdc_wait);
#else
while((_reg_SLCDC_LCD_CTRL_STAT &0x00000004)!=0);
_reg_SLCDC_LCD_CTRL_STAT |= 0x40;
_reg_SLCDC_LCD_CTRL_STAT |= 0x20;
#endif
return;
}
static void slcdc_isr(int irq, void *dev_id, struct pt_regs *regs)
{
u32 status;
status = _reg_SLCDC_LCD_CTRL_STAT;
//clear interrupt
_reg_SLCDC_LCD_CTRL_STAT |= 0x40;
wake_up_interruptible(&slcdc_wait);
return;
}
int slcdc_init_buffer(void)
{
u_int required_pages;
u_int extra_pages;
u_int order;
struct page *page;
u16 *allocated_region;
TRACE("slcdc data buffer size = %x \n",(unsigned int)SLCDC_DATA_MEM_SIZE);
if(g_slcdc_dbuffer_address != NULL)
return -EINVAL;
if(g_slcdc_cbuffer_address != NULL)
return -EINVAL;
/*find order required to allocate enough memory for it*/
required_pages = SLCDC_DATA_MEM_SIZE >> PAGE_SHIFT;
for (order = 0; required_pages >> order; order++){;}
extra_pages = (1 << order) - required_pages;
TRACE("PAGE_SHIFT=0x%x required_pages=0x%x\n",PAGE_SHIFT,required_pages);
TRACE("extra_page=0x%x \n",extra_pages);
if((allocated_region = (u_char *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)) == NULL)
{
FAILED("can not allocated memory\n");
return -ENOMEM;
}
g_slcdc_dbuffer_address = (u_char *)allocated_region + (extra_pages << PAGE_SHIFT);
g_slcdc_dbuffer_phyaddress = (u_char *)__virt_to_phys((u_long)g_slcdc_dbuffer_address);
TRACE("g_slcdc_dbuffer_address=0x%x \n",(unsigned long)g_slcdc_dbuffer_address);
/* Free all pages that we don't need but were given to us because */
/* __get_free_pages() works on powers of 2. */
for (;extra_pages;extra_pages--)
free_page((u_int)allocated_region + ((extra_pages-1) << PAGE_SHIFT));
/* Set reserved flag for fb memory to allow it to be remapped into */
/* user space by the common fbmem driver using remap_page_range(). */
for(page = virt_to_page(g_slcdc_dbuffer_address);
page < virt_to_page(g_slcdc_dbuffer_address + SLCDC_DATA_MEM_SIZE);
page++)
{
mem_map_reserve(page);
}
slcdc_par.screen_start_address =(u_char*)((u_long)g_slcdc_dbuffer_phyaddress);
slcdc_par.v_screen_start_address =(u_char*)((u_long)g_slcdc_dbuffer_address);
TRACE("startaddr= 0x%x, phyaddr=0x%x , size=0x%x \n",slcdc_par.screen_start_address,slcdc_par.v_screen_start_address,SLCDC_DATA_MEM_SIZE);
memset(slcdc_par.v_screen_start_address,0,SLCDC_DATA_MEM_SIZE);
g_slcdc_cbuffer_address = consistent_alloc(GFP_KERNEL|GFP_DMA,(SLCDC_CMD_MEM_SIZE+4),&g_slcdc_cbuffer_phyaddress);
g_slcdc_cbuffer_address = (u_long)g_slcdc_cbuffer_address&0xfffffff4;
g_slcdc_cbuffer_phyaddress = (u_long)g_slcdc_cbuffer_phyaddress&0xfffffff4;
TRACE("slcdc data buffer address = %x cmd buffer address= %x \n",(unsigned int)slcdc_par.screen_start_address,g_slcdc_cbuffer_address);
return 0;
}
int slcdc_free_buffer(void)
{
struct page *page;
u_int required_pages;
required_pages = SLCDC_DATA_MEM_SIZE >> PAGE_SHIFT;
//free command buffer
if(g_slcdc_cbuffer_address != NULL)
consistent_free(g_slcdc_cbuffer_address,SLCDC_CMD_MEM_SIZE,g_slcdc_cbuffer_phyaddress);
else
return -EINVAL;
//free data buffer
for(page = virt_to_page(g_slcdc_dbuffer_address);
page < virt_to_page(g_slcdc_dbuffer_address + SLCDC_DATA_MEM_SIZE);
page++)
{
mem_map_unreserve(page);
}
for (;required_pages;required_pages--)
free_page((u_int)g_slcdc_dbuffer_address + ((required_pages-1) << PAGE_SHIFT));
return 0;
}
/**
*@brief slcdc mmap function
*
* Function Name: slcdc_mmap
*
*
* Description: This is the memory map routine for this driver,will setup the memory map used in this driver.
*
*@param filp the pointer to the file descripter
*@param vma the pointer to the vma structure related to the driver
*
*@return int return status
* @li 0 sucessful
* @li other failed
* Modification History:
* Dec,2003, Karen first version
*
**/
static int slcdc_mmap(struct file *filp, struct vm_area_struct *vma)
{
unsigned long page,pos;
unsigned long start = (unsigned long)vma->vm_start;
unsigned long size = (unsigned long)(vma->vm_end-vma->vm_start);
if(size > SLCDC_DATA_MEM_SIZE)
return -EINVAL;
pos = (unsigned long)slcdc_par.v_screen_start_address;
while(size>0){
page = virt_to_phys((void*)pos);
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
// This is an IO map - tell maydump to skip this VMA
vma->vm_flags |= VM_IO;
if(remap_page_range(start,page,PAGE_SIZE,PAGE_SHARED))
return -EAGAIN;
start+= PAGE_SIZE;
pos+= PAGE_SIZE;
size-= PAGE_SIZE;
}
return 0;
}
void slcdc_display_on()
{
u16* databuffer = NULL;
_reg_SLCDC_DBADDR = (u32)g_slcdc_cbuffer_phyaddress;
//put cmd into cmd buffer
databuffer = g_slcdc_cbuffer_address;
//put cmd into cmd buffer
*databuffer = SLCDC_CMD_DISON;
//send cmd
slcdc_send_cmd(1);
//delay
slcdc_delay(0xffff);
//send cmd
slcdc_send_cmd(1);
//delay
slcdc_delay(0xffff);
}
void slcdc_display_off()
{
u16* databuffer = NULL;
//Cause LCD module to enter sleep mode.Bu sure to input display OFF command to turn off the display before inputting the SLPIN command
//Keep the logic power supply turned on for 40ms after the LCD module enters the sleep mode.
//put cmd into cmd buffer
databuffer = slcdc_par.v_screen_start_address;
//send cmd SLPIN
*databuffer = SLCDC_CMD_SLPIN;
slcdc_send_cmd(1);
//put reset high
#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
//delay for 50ms
slcdc_delay(0xffff);
//put cmd into cmd buffer
*databuffer = SLCDC_CMD_DISOFF;
//send cmd DISOFF
slcdc_send_cmd(1);
TRACE("disoff \n");
slcdc_delay(0xffff);
}
void slcdc_display_normal()
{
u16* databuffer = NULL;
databuffer = slcdc_par.v_screen_start_address;
*databuffer = SLCDC_CMD_DISNOR;
//send cmd
slcdc_send_cmd(1);
//delay
slcdc_delay(100);
}
void slcdc_sleep_out()
{
u16* databuffer = NULL;
databuffer = slcdc_par.v_screen_start_address;
*databuffer = SLCDC_CMD_SLPOUT;
//send cmd
slcdc_send_cmd(1);
//delay
slcdc_delay(0xffff);
}
void slcdc_display_ctl()
{
int i;
#ifdef SLCDC_SERIAL_MODE
u16 disctl[11] = {0x1c00,0x0200, 0x8200,0x0000,
0x1e00,0xe000, 0x0000,0xdc00,
0x0000,0x0200, 0x0000};
#else
u16 disctl[11] = {0x1c,0x02, 0x82,0x00,
0x1e,0xe0, 0x00,0xdc,
0x00,0x02, 0x00};
#endif
u16* databuffer = NULL;
//It make various display timing settings.
databuffer = slcdc_par.v_screen_start_address;
//put cmd into cmd buffer
*databuffer = SLCDC_CMD_DISCTL;
//send cmd
slcdc_send_cmd(1);
slcdc_delay(2000);
//put parameter into data buffer
for(i=0;i<11;i++)
{
*databuffer = disctl[i];
databuffer++;
}
//send data
slcdc_send_data(11);
}
void slcdc_page_set()
{
//It specify a page address area in order to access the display data RAM from the MPU. Be sure to set both starting and ending pages.
int i;
u16* databuffer = NULL;
#ifdef SLCDC_SERIAL_MODE
u16 pset[4] = {0x0000,0x0000, 0xb100,0x0000};
#else
u16 pset[4] = {0x00,0x00, 0xb1,0x00};
#endif
databuffer = (u16*)(slcdc_par.v_screen_start_address);
//put cmd into cmd buffer
*databuffer = SLCDC_CMD_SD_PSET;
//send cmd
slcdc_send_cmd(1);
slcdc_delay(20000);
//put parameter into data buffer
for(i=0;i<4;i++)
{
*databuffer = pset[i];
databuffer++;
}
//send data
slcdc_send_data(4);
slcdc_delay(20000);
}
void slcdc_col_set()
{
//It specify starting and ending collumns.
int i;
#ifdef SLCDC_SERIAL_MODE
u16 cset[4] = {0x0200,0x0000, 0xb100,0x0000};
#else
u16 cset[4] = {0x02,0x00, 0xb1,0x00};
#endif
u16* databuffer = NULL;
databuffer = (u16*)(slcdc_par.v_screen_start_address);
//put cmd into cmd buffer
*databuffer = SLCDC_CMD_SD_CSET;
//send cmd
slcdc_send_cmd(1);
slcdc_delay(20000);
//put parameter into data buffer
for(i=0;i<4;i++)
{
*databuffer = cset[i];
databuffer++;
}
//send data
slcdc_send_data(4);
slcdc_delay(20000);
}
void slcdc_data_ctl()
{
u8* databuffer = NULL;
databuffer = (u8*)(slcdc_par.v_screen_start_address);
*databuffer = SLCDC_CMD_DATCTL;
//send cmd
slcdc_send_cmd(1);
slcdc_delay(20000);
*databuffer = 0x28;
//send data
slcdc_send_data(1);
slcdc_delay(20000);
}
void slcdc_volctl(void)
{
u16* databuffer = NULL;
databuffer = slcdc_par.v_screen_start_address;
*databuffer = SLCDC_CMD_VOLCTR;
//send cmd
slcdc_send_cmd(1);
slcdc_delay(20000);
#ifdef SLCDC_SERIAL_MODE
*databuffer = 0x9f00;
#else
*databuffer = 0x9f;
#endif
//send data
slcdc_send_data(1);
slcdc_delay(20000);
}
void slcdc_ascset()
{
int i;
#ifdef SLCDC_SERIAL_MODE
u16 lcd_para_ASCSET[7] = {0x0000, 0x0000, 0x1f00, 0x0100,
0x1f00, 0x0100, 0x0300};
#else
u16 lcd_para_ASCSET[7] = {0x00, 0x00, 0x1f, 0x01,
0x1f, 0x01, 0x03};
#endif
u16* databuffer = NULL;
databuffer = (u16*)(slcdc_par.v_screen_start_address);
//put cmd into cmd buffer
*databuffer = SLCDC_CMD_ASCSET;
//put parameter into data buffer
//send cmd
slcdc_send_cmd(1);
slcdc_delay(2000);
for(i=0; i<7; i++)
{
*databuffer = lcd_para_ASCSET[i];
databuffer++;
}
//send data
slcdc_send_data(7);
slcdc_delay(20000);
}
void slcdc_scstart(void)
{
int i;
u16 lcd_para_SCSTART[2]= { 0x00, 0x00};
u16* databuffer = NULL;
databuffer = (u16*)(slcdc_par.v_screen_start_address);
//put cmd into cmd buffer
*databuffer = SLCDC_CMD_SCSTART;
//put parameter into data buffer
//send cmd
slcdc_send_cmd(1);
slcdc_delay(10000);
for(i=0; i<2; i++)
{
*databuffer = lcd_para_SCSTART[i];
databuffer++;
}
//send data
slcdc_send_data(2);
slcdc_delay(20000);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -