⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slcdc.c

📁 slcdc液晶屏的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:

}


//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 + -