CFAF240400DT initialization

gen4ik

New member
Code:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>

#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>

#include <asm/io.h>
#include<linux/delay.h>
#include <linux/uaccess.h>

#include <linux/screen_info.h>

#include <linux/gfp.h>

#include "lcd.h"

//static int lcd_fb_thread(void *param);

struct lcd_fb_par {
	struct task_struct  	*lcd_fb_thread_task;
	struct platform_device  *pdev;
	u8                  	*buffer;
	u8                  	*shadow;
};

static struct fb_fix_screeninfo lcd_fb_fix __devinitdata = {
	.id             = "lcd_fb",
	.type           = FB_TYPE_PACKED_PIXELS,
	.visual         = FB_VISUAL_TRUECOLOR,
	.xpanstep       = 0,
	.ypanstep       = 0,
	.ywrapstep      = 0,
	.line_length    = X_RES * B_PP / 8,
	.accel          = FB_ACCEL_NONE,
};

static struct fb_var_screeninfo lcd_fb_var __devinitdata = {
	.xres           = X_RES,
	.yres           = Y_RES,
	.xres_virtual   = X_RES,
	.yres_virtual   = Y_RES,
	.height         = -1,
	.width          = -1,
	.vmode          = FB_VMODE_NONINTERLACED,
	.bits_per_pixel = B_PP,
	.red            = { 11, 5, 0 },
	.green          = { 5, 6, 0 },
	.blue           = { 0, 5, 0 },
	.nonstd         = 0,
};


//**********************************************************************************************************************************************
static void write_command(unsigned short command)
{
	unsigned short cmd=0;
	CLR_CS;
	CLR_CD;
	SET_RD;
	SET_WR;

	//cmd=command & 8;
	__raw_writel( command, PORTD + PIO_ODSR);//PORT INIT

	CLR_WR;
	
	SET_WR;

	SET_CS;
}
static void write_data(unsigned short data)
{
	unsigned short dd=0;
	CLR_CS;
	SET_CD;
	SET_RD;
	SET_WR;

	//dd=data & 0xFF00;
	__raw_writel( data, PORTD + PIO_ODSR);//PORT INIT

	CLR_WR;
	
	SET_WR;

	SET_CS;

	// keeps the display from going wonky -- don't know why this is.
	__raw_writel( 0xFFFF, PORTD + PIO_ODSR);//PORT INIT

}

static void lcd_cls(unsigned short data)
{
	unsigned short i,j;
	write_command(0x0200);    // GRAM Address Set (Horizontal Address) (R200h)
	write_data(0x0000);       // Page 30 of SPFD5420A Datasheet
	write_command(0x0201);    // GRAM Address Set (Vertical Address) (R201h)
	write_data(0x0000);       // Page 30 of SPFD5420A Datasheet

	write_command(0x0202);    // Write Data to GRAM (R202h)

	

	for(i=0;i<400;i++)
	{
		for(j=0;j<240;j++)
		{
			write_data(data);
		}
	}
}

static void spfd5420Command(unsigned short cmmd,unsigned short data)
{
	//Command
	CLR_CS;//Chip select on
	CLR_CD;
	SET_RD;
	SET_WR;
	__raw_writel( cmmd, PORTD + PIO_ODSR);//PORT INIT

	CLR_WR;
	SET_WR;
	//SET_CS;
	//*********************

	//Data
	//CLR_CS;
	SET_CD;
	//SET_RD;
	//SET_WR;

	//dd=data & 0xFF00;
	__raw_writel( data, PORTD + PIO_ODSR);//PORT INIT

	CLR_WR;
	
	SET_WR;

	SET_CS;//Chip select off


	//write_command(cmmd);	
	//write_data(data);
}




static void lcd_test(void)
{
	
	unsigned int i,j;
	write_command(0x0200);    // GRAM Address Set (Horizontal Address) (R200h)
	write_data(0x0000);       // Page 30 of SPFD5420A Datasheet
	write_command(0x0201);    // GRAM Address Set (Vertical Address) (R201h)
	write_data(0x0000);       // Page 30 of SPFD5420A Datasheet

	write_command(0x0202);    // Write Data to GRAM (R202h)

	for(i=0;i<240;i++)
	for(j=0;j<400;j++)
	{
		if(i>209)write_data(1);
		else if(i>179)write_data(BLUE);
		else if(i>149)write_data(RED);
		else if(i>119)write_data(GREEN);
		else if(i>89)write_data(CYAN);
		else if(i>59)write_data(MAGENTA);
		else if(i>29)write_data(YELLOW);
		else write_data(WHITE);
	}

}


//******************************************************************************************************************
//******************************************************************************************************************
/*
	

	

	

	
	//--------------- Normal set ---------------//
	
	//--------------- Panel interface control 1~6 ---------------//
	

	//--------------- Partial display ---------------//



*/












static void init1_lcd(void)
{

	__raw_writel( LCD_CMMD_MASK, PORTC + PIO_PER);//PORT INIT
	__raw_writel( LCD_CMMD_MASK, PORTC + PIO_OER);//PORT OUT INIT

	__raw_writel( LCD_DATA_MASK, PORTD + PIO_PER);//PORT INIT  LCD_DATA_MASK
	__raw_writel( LCD_DATA_MASK, PORTD + PIO_OER);//PORT OUT INIT
	__raw_writel( LCD_DATA_MASK, PORTD + PIO_OWER);//PORT OUT INIT
//***************************************************
	__raw_writel( LCD_CMMD_MASK, PORTC + PIO_SODR);//PORT OUT INIT

	__raw_writel( 0xFFFF, PORTD + PIO_ODSR);

	CLR_RESET;
	mdelay(100);
	SET_RESET;
	mdelay(250);
	mdelay(250);
	mdelay(250);
	mdelay(250);
	




  spfd5420Command(0x0606, 0x0000);    // Pin Control (R606h)
  ndelay(500);
  spfd5420Command(0x0007, 0x0001);    // Display Control 1 (R007h)
  ndelay(500);
  spfd5420Command(0x0110, 0x0001);    // Power Control 6(R110h)
  ndelay(500);
  spfd5420Command(0x0100, 0x17B0);    // Power Control 1 (R100h)
  spfd5420Command(0x0101, 0x0147);    // Power Control 2 (R101h)
  spfd5420Command(0x0102, 0x019D);    // Power Control 3 (R102h)
  spfd5420Command(0x0103, 0x3600);    // Power Control 4 (R103h)
  spfd5420Command(0x0281, 0x0010);    // NVM read data 2 (R281h)  
  ndelay(500);
  spfd5420Command(0x0102, 0x01BD);    // Power Control 3 (R102h)
  ndelay(500);

  //--------------- Power control 1~6 ---------------//
  spfd5420Command(0x0100, 0x16B0);    // Power Control 1 (R100h)
  spfd5420Command(0x0101, 0x0147);    // Power Control 2 (R101h)
  spfd5420Command(0x0102, 0x01BD);    // Power Control 3 (R102h)
  spfd5420Command(0x0103, 0x2d00);    // Power Control 4 (R103h)
  spfd5420Command(0x0107, 0x0000);    // Power Control 5 (R107h)
  spfd5420Command(0x0110, 0x0001);    // Power Control 6(R110h)
  spfd5420Command(0x0280, 0x0000);    // NVM read data 1 (R280h)
  spfd5420Command(0x0281, 0x0006);    // NVM read data 2 (R281h)
  spfd5420Command(0x0282, 0x0000);    // NVM read data 3 (R282h)

  //------- Gamma 2.2 control (R300h to R30Fh) ------//
  spfd5420Command(0x0300, 0X0101); 
  spfd5420Command(0x0301, 0x0b27); 
  spfd5420Command(0x0302, 0x132A); 
  spfd5420Command(0x0303, 0x2A13); 
  spfd5420Command(0x0304, 0x270B); 
  spfd5420Command(0x0305, 0x0101); 
  spfd5420Command(0x0306, 0x1205); 
  spfd5420Command(0x0307, 0x0512); 
  spfd5420Command(0x0308, 0X0005); 
  spfd5420Command(0x0309, 0x0003); 
  spfd5420Command(0x030A, 0X0F04); 
  spfd5420Command(0x030B, 0x0F00); 
  spfd5420Command(0x030C, 0x000F); 
  spfd5420Command(0x030D, 0x040F);    
  spfd5420Command(0x030E, 0x0300);    
  spfd5420Command(0x030F, 0x0500);    


  spfd5420Command(0x0400, 0x3100);    // Base Image Number of Line (R400h)0x3500 0x3100->400 dots
  spfd5420Command(0x0401, 0x0001);    // Base Image Display Control (R401h) 0x0001
  spfd5420Command(0x0404, 0x0000);    // Based Image Vertical Scroll Control (R404h)
  

  //--------------- Normal set ---------------//
  spfd5420Command(0x0000, 0x0000);    // ID Read Register (R000h)
  spfd5420Command(0x0001, 0x0100);    // Driver Output Control Register (R001h) 0x0100
  spfd5420Command(0x0002, 0x0100);    // LCD Driving Waveform Control (R002h)
  spfd5420Command(0x0003, 0x1018);    // Entry Mode (R003h)//0x1030
  spfd5420Command(0x0006, 0x0000);    // Display Control 1 (R007h)
  spfd5420Command(0x0008, 0x0808);    // Display Control 2 (R008h)
  spfd5420Command(0x0009, 0x0001);    // Display Control 3 (R009h)
  spfd5420Command(0x000B, 0x0010);    // Low Power Control (R00Bh)
  spfd5420Command(0x000C, 0x0000);    // External Display Interface Control 1 (R00Ch)
  spfd5420Command(0x000F, 0x0000);    // External Display Interface Control 2 (R00Fh)
  spfd5420Command(0x0007, 0x0001);    // Display Control 1 (R007h)

  //--------------- Panel interface control 1~6 ---------------//
  spfd5420Command(0x0010, 0x0012);    // Panel Interface Control 1 (R010h)  //0x0012
  spfd5420Command(0x0011, 0x0202);    // Panel Interface Control 2 (R011h)
  spfd5420Command(0x0012, 0x0300);    // Panel Interface control 3 (R012h)
  spfd5420Command(0x0020, 0x021E);    // Panel Interface control 4 (R020h)
  spfd5420Command(0x0021, 0x0202);    // Panel Interface Control 5 (021Rh)
  spfd5420Command(0x0022, 0x0100);    // Panel Interface Control 6 (R022h)
  spfd5420Command(0x0090, 0x8000);    // Frame Marker Control (R090h)            //0x8000

  //--------------- Partial display ---------------//

  spfd5420Command(0x0210, 0x0000);    // Window Horizontal RAM Address Start (R210h)
  spfd5420Command(0x0211, 0x00EF);    // Window Horziontal RAM Address End (R211h)  0x00EF
  spfd5420Command(0x0212, 0x0000);    // Window Vertical RAM Address Start (R212h)
  spfd5420Command(0x0213, 0x018F);    // Window Vertical RAM Address End (R213h)    0x018F
  spfd5420Command(0x0500, 0X0000);    // Display Position - Partial Display 1 (R500h)
  spfd5420Command(0x0501, 0X0000);    // RAM Address Start - Partial Display 1 (R501h)
  spfd5420Command(0x0502, 0X0000);    // RAM Address End - Partail Display 1 (R502h)
  spfd5420Command(0x0503, 0x0000);    // Display Position - Partial Display 2 (R503h)
  spfd5420Command(0x0504, 0x0000);    // RAM Address Start – Partial Display 2 (R504h)
  spfd5420Command(0x0505, 0x0000);    // RAM Address End – Partial Display 2 (R505h)
  spfd5420Command(0x0606, 0x0000);    // Pin Control (R606h)
  spfd5420Command(0x06F0, 0X0000);    // NVM Access Control (R6F0h)

  //--------------- Display on --------------------//
  spfd5420Command(0x0007, 0x0173);    // Display Control 1 (R007h)
  ndelay(500);
  spfd5420Command(0x0007, 0x0171);    // Display Control 1 (R007h)
  ndelay(500);
  spfd5420Command(0x0007, 0x0173);    // Display Control 1 (R007h)
}


//**************************************************************************************************************************************************
















static int lcd_fb_blank(int blank_mode, struct fb_info *info)
{
//	struct lcd_fb_par *par = info->par;

	switch (blank_mode) {
	case FB_BLANK_UNBLANK:
//		spi_command(par->spi, DISPON);
//		break;
	case FB_BLANK_NORMAL:
	case FB_BLANK_VSYNC_SUSPEND:
	case FB_BLANK_HSYNC_SUSPEND:
	case FB_BLANK_POWERDOWN:
//		spi_command(par->spi, DISPOFF);
//		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int lcd_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
	unsigned long size, offset;

	size = vma->vm_end - vma->vm_start;
	offset = vma->vm_pgoff << PAGE_SHIFT;

	offset += info->fix.smem_start;
	if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
			    size, vma->vm_page_prot))
		return -EAGAIN;

	printk(KERN_INFO "lcd_fb: mmap framebuffer P(%lx)->V(%lx), size %lx\n",
		offset, vma->vm_start, size);
	return 0;
}

static int lcd_fb_fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
			 u_int transp, struct fb_info *info)
{
	if (regno >= 256)
		return -EINVAL;

	if (info->var.grayscale) {
		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
		red = green = blue =
		    (red * 77 + green * 151 + blue * 28) >> 8;
	}

	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {

		u32 value;
		/* Place color in the pseudopalette */
		if (regno > 16)
			return -EINVAL;

		red   >>= (16 - info->var.red.length);
		green >>= (16 - info->var.green.length);
		blue  >>= (16 - info->var.blue.length);

		value = (red   << info->var.red.offset) |
			(green << info->var.green.offset)|
			(blue  << info->var.blue.offset);
		value &= 0xFFFF;

		((u32 *) (info->pseudo_palette))[regno] = value;
	}
	return 0;
}



static struct fb_ops lcd_fb_ops = {
	.owner          = THIS_MODULE,
	//.fb_read        = fb_sys_read,
	//.fb_write       = fb_sys_write,
	//.fb_fillrect    = sys_fillrect,
	//.fb_copyarea    = sys_copyarea,
	//.fb_imageblit   = sys_imageblit,
	.fb_blank       = lcd_fb_blank,
	.fb_mmap        = lcd_fb_mmap,
	.fb_setcolreg   = lcd_fb_fb_setcolreg,
};

static int lcd_fb_thread(void *param)
{
	struct lcd_fb_par *par = (struct lcd_fb_par *)param;
	int  i,ii;
	unsigned short data;
	set_user_nice(current, 5); 

	while(!kthread_should_stop()) {
		/* Optimize refresh: transfer image only when it has changed */
		if(memcmp(par->shadow, par->buffer, MEM_LEN)) 
		{
			memcpy(par->shadow, par->buffer, MEM_LEN);
			unsigned short *fb=(unsigned short*)par->buffer;

			
			spfd5420Command(0x0200,0x0000);
			spfd5420Command(0x0201,0x0000);

			
			CLR_CS;
			//Command ************************
			CLR_CD;
			SET_RD;
			SET_WR;
			__raw_writel( 0x0202, PORTD + PIO_ODSR);//PORT INIT

			CLR_WR;//Pulse
			SET_WR;
			//********************************
			//Data 
			SET_CD;
			//SET_RD;

			for(i = 0; i < MEM_LEN/2; i++) // += 2
			{
				
				__raw_writel( *fb++, PORTD + PIO_ODSR);//PORT INIT
				CLR_WR;
				SET_WR;
				
			}
			SET_WR;
			SET_CS;
			
		
		}
		
		schedule_timeout_interruptible(REFR_TIME);
	}

	return 0;
}


//static int __devinit lcd_probe(struct platform_device *pdev)
static int __init lcd_probe(struct platform_device *pdev)
{
	int retval=-ENOMEM;

	
	//struct device	*dev = &pdev->dev;
	struct fb_info *info;
	struct lcd_fb_par *par;


	init1_lcd();
		


	printk(KERN_WARNING "framebuffer_alloc\n");
	info = framebuffer_alloc(sizeof(struct lcd_fb_par),&pdev->dev);//dev &spi->dev
	if(!info)
		return retval;
	

	printk(KERN_WARNING "info->screen_base alloc_pages_exact\n");
	info->screen_base = alloc_pages_exact(MEM_LEN, GFP_DMA | __GFP_ZERO);
	if(!info->screen_base)
		goto err;
	printk(KERN_INFO "info->screen_base 0x%x\n",info->screen_base);
	

	info->fbops = &lcd_fb_ops;
	info->var = lcd_fb_var;
	info->fix = lcd_fb_fix;

	info->fix.smem_len = MEM_LEN;
	info->fix.smem_start = (unsigned long)virt_to_phys(info->screen_base);
	info->screen_size = info->fix.smem_len;
	info->flags = FBINFO_FLAG_DEFAULT;

	//pseudo palette
	printk(KERN_INFO "pseudo_palette alloc_pages_exact\n");
	info->pseudo_palette = alloc_pages_exact(MEM_LEN, GFP_DMA | __GFP_ZERO);
	if(!info->pseudo_palette)
		goto err1;
	printk(KERN_INFO "info->pseudo_palette 0x%x\n",info->pseudo_palette);
	//cmap
	printk(KERN_INFO "fb_alloc_cmap\n");
	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
		goto err2;
	}

	par = info->par;
	par->pdev = pdev;
	par->buffer = info->screen_base;
	
	printk(KERN_INFO "kmalloc par->shadow\n");
	par->shadow = kmalloc(MEM_LEN, GFP_KERNEL | GFP_DMA);
	if(!par->shadow)
		goto err2;
	printk(KERN_INFO "par->shadow 0x%x\n",par->shadow);

	printk(KERN_INFO "register_framebuffer\n");
	retval = register_framebuffer(info);
	if (retval < 0)
		goto err3;
	printk(KERN_INFO "retval=%i\n",retval);

	printk(KERN_INFO "dev_set_drvdata\n");
	dev_set_drvdata(&pdev->dev, info);

	printk(KERN_INFO "kthread_run\n");
	par->lcd_fb_thread_task = kthread_run(lcd_fb_thread, par, "lcd");

	retval = -EIO;
	if(IS_ERR(par->lcd_fb_thread_task))
		goto err3;
	
	printk(KERN_INFO "fb%d: %s frame buffer device, %lx base address %dK of video memory\n",
	       info->node, info->fix.id, info->fix.smem_start, info->fix.smem_len >> 10);

	printk(KERN_INFO "Alles OK\n");
	mdelay(1000);
	return 0;
	
err3:
	printk(KERN_INFO "err3\n");
	kfree(par->shadow);
err2:
	printk(KERN_INFO "err2\n");
	free_pages_exact(info->pseudo_palette, MEM_LEN);
err1:
	printk(KERN_INFO "err1\n");
	free_pages_exact(par->buffer, MEM_LEN);
err:
	printk(KERN_INFO "err\n");
	framebuffer_release(info);
	return retval;
	
	return 0;
}
//static int __devexit lcd_remove(struct platform_device *pdev)
static int __exit lcd_remove(struct platform_device *pdev)
{
	struct fb_info *info = dev_get_drvdata(&pdev->dev);

	if (info) {
		struct lcd_fb_par *par = info->par;

		unregister_framebuffer(info);
		free_pages_exact(par->buffer, MEM_LEN);
		kfree(par->shadow);
		framebuffer_release(info);

		kthread_stop(par->lcd_fb_thread_task);
	}
	return 0;
}

static struct platform_driver lcd_driver = 
{
	.probe = lcd_probe,
	.remove = __exit_p(lcd_remove),
	.driver.name = "lcd_fb",
	.driver.owner = THIS_MODULE,

};

static struct platform_device lcd_device = {
	.name	= "lcd_fb",
};

static int lcd_init(void)
{
	int ret;
	

	ret = platform_driver_register(&lcd_driver);
	printk(KERN_INFO "driver_register :%i\n",ret);

	if (!ret) {
		ret = platform_device_register(&lcd_device);
		printk(KERN_INFO "device_register :%i\n",ret);
		if (ret)
		{
			printk(KERN_INFO "driver_unregister\n");
			platform_driver_unregister(&lcd_driver);
		}	
	}
	return ret;
}

static void lcd_exit(void)
{
	printk(KERN_INFO "lcd_exit\n");
	platform_device_unregister(&lcd_device);
	platform_driver_unregister(&lcd_driver);
}


module_init(lcd_init);
module_exit(lcd_exit);


MODULE_AUTHOR("Heinrich");
MODULE_LICENSE("GPL");
Looking for additional LCD resources? Check out our LCD blog for the latest developments in LCD technology.
 
Top