drivers/spi/spi_test.c 这个文件可以细看,是详细分析spi驱动的好文件。
//ili9225g.c驱动,屏驱动芯片ili9225芯片
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include "ili9225g.h"
/* IOCTL commands */
#define ILI9225G_IOC_MAGIC 's'
#define ILI9225G_IOC_WR_BUFFER_SIZE _IOW(ILI9225G_IOC_MAGIC, 2, __u32)
#define ILI9225G_IOC_BACKLIGHT_CONTROL _IOW(ILI9225G_IOC_MAGIC, 3, __u32)
static struct spi_device *spi;
static unsigned long buffer_size=220*176*2;
static unsigned char *buffer;
struct ili9225g_board_info
{
int reset_gpio;
int rs_gpio;
int backlight_gpio;
int te_gpio;
};
#define SPIDEV_MAJOR 153 /* assigned */
static struct class *ili9225g_class;
struct ili9225g_board_info ili9225g_board = {
.reset_gpio = GPIO_PB(17),
.rs_gpio = GPIO_PB(18),
.backlight_gpio = GPIO_PC(9),
.te_gpio = GPIO_PA(22),
};
#define RESET(a) do{gpio_direction_output(ili9225g_board.reset_gpio, a);}while(0)
#define RS(a) do{gpio_direction_output(ili9225g_board.rs_gpio, a);}while(0)
#define TE(a) do{gpio_direction_output(ili9225g_board.te_gpio, a);}while(0)
#define BACKLIGHT(a) do{gpio_direction_output(ili9225g_board.backlight_gpio, a);}while(0)
static int write_command(unsigned char value_l,unsigned char value_h)
{
unsigned short data;
int ret;
struct spi_message msg;
struct spi_transfer t[] = {
{
.tx_buf = &data,
.len = 2,
.delay_usecs = 0,
}
};
RS(0);
data = value_l|(value_h<<8);
spi_message_init(&msg);
spi_message_add_tail(&t[0], &msg);
ret = spi_sync(spi, &msg);
RS(1);
if (ret < 0)
{
return -1;
}
return 0;
}
static int write_data(unsigned char value_l,unsigned char value_h)
{
unsigned short data;
int ret;
struct spi_message msg;
struct spi_transfer t[] = {
{
.tx_buf = &data,
.len = 2,
.delay_usecs = 0,
}
};
data = value_l|(value_h<<8);
spi_message_init(&msg);
spi_message_add_tail(&t[0], &msg);
ret = spi_sync(spi, &msg);
if (ret < 0)
{
return -1;
}
return 0;
}
static void inti_ili9225g(void)
{
printk("inti_ili9225g\n");
RESET(1);
mdelay(1);
RESET(0);
mdelay(10);
RESET(1);
mdelay(200);
write_command(0x00,0xD0),
write_data(0x00,0x03),
write_command(0x00,0xEB),
write_data(0x0B,0x00),
write_command(0x00,0xEC),
write_data(0x00,0x4F),
write_command(0x00,0xC7),
write_data(0x03,0x0F), //**
write_command(0x00,0x01),
write_data(0x01,0x1C),
write_command(0x00,0x02),
write_data(0x01,0x00),
write_command(0x00,0x03),
write_data(0x10,0x30), //1230 RGB/BGR 16/18Bit
write_command(0x00,0x07),
write_data(0x00,0x00),
write_command(0x00,0x08),
write_data(0x08,0x08),
write_command(0x00,0x0F),
write_data(0x09,0x01),
mdelay(50); //delay 50 ms;
write_command(0x00,0x10),
write_data(0x00,0x00),
write_command(0x00,0x11),
write_data(0x1B,0x41),
mdelay(50);
write_command(0x00,0x12),
write_data(0x20,0x0E),
write_command(0x00,0x13),
write_data(0x00,0x58), //GVDD4.4
write_command(0x00,0x14),
write_data(0x4A,0x47), //VCOM
write_command(0x00,0x30),
write_data(0x00,0x00),
write_command(0x00,0x31),
write_data(0x00,0xdb),
write_command(0x00,0x32),
write_data(0x00,0x00),
write_command(0x00,0x33),
write_data(0x00,0x00),
write_command(0x00,0x34),
write_data(0x00,0xdb),
write_command(0x00,0x35),
write_data(0x00,0x00),
write_command(0x00,0x36),
write_data(0x00,0xAF),
write_command(0x00,0x37),
write_data(0x00,0x00),
write_command(0x00,0x38),
write_data(0x00,0xDB),
write_command(0x00,0x39),
write_data(0x00,0x00),
write_command(0x00,0x50),
write_data(0x00,0x00),
write_command(0x00,0x51),
write_data(0x05,0x03),
write_command(0x00,0x52),
write_data(0x0C,0x06),
write_command(0x00,0x53),
write_data(0x04,0x00),
write_command(0x00,0x54),
write_data(0x06,0x0C),
write_command(0x00,0x55),
write_data(0x03,0x05),
write_command(0x00,0x56),
write_data(0x00,0x00),
write_command(0x00,0x57),
write_data(0x00,0x04),
write_command(0x00,0x58),
write_data(0x0E,0x00),
write_command(0x00,0x59),
write_data(0x00,0x0E),
write_command(0x00,0x20),
write_data(0x00,0x00),
write_command(0x00,0x21),
write_data(0x00,0x00),
write_command(0x00,0x07),
write_data(0x10,0x17),
mdelay(200);
write_command(0x00,0x22);
}
static int ili9225g_open(struct inode *inode,struct file *file)
{
printk("ili9225g_open\n");
return 0;
}
static int ili9225g_read(struct file *file, char __user *user_buf, size_t size, loff_t *ppos)
{
return 0;
}
static int spi_write_array_data(const char *buf,size_t count)
{
int ret;
struct spi_message msg;
struct spi_transfer t[]={
{
.tx_buf = buf,
.len = count,
.delay_usecs= 0,
},
};
spi_message_init(&msg);
spi_message_add_tail(&t[0], &msg);
ret = spi_sync(spi, &msg);
if (ret < 0)
{
return -1;
}
return 0;
}
static int ili9225g_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
int ret,tmp;
unsigned char *p;
tmp=count;
if(tmp>buffer_size){
printk("buffer size too big\n");
tmp=buffer_size;
}
ret=copy_from_user(buffer,buf,tmp);
if(ret != 0)
return -ENOMEM;
p=buffer;
TE(0);
spi_write_array_data(p,tmp);
TE(1);
return 0;
}
static long ili9225g_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int state;
switch(cmd)
{
case ILI9225G_IOC_WR_BUFFER_SIZE:
kfree(buffer);
buffer_size=*(unsigned long*)arg;
buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!buffer) {
return -ENOMEM;
}
printk("1 args's %ld\n",*(unsigned long*)arg);
break;
case ILI9225G_IOC_BACKLIGHT_CONTROL:
state=*(unsigned long*)arg;
BACKLIGHT(state);
break;
default:
printk("cmd:%x,arg=%ld",cmd,*(unsigned long*)arg);
}
return 0;
}
static const struct file_operations ili9225g_fops =
{
.owner = THIS_MODULE,
.open = ili9225g_open,
.read = ili9225g_read,
.write = ili9225g_write,
.unlocked_ioctl = ili9225g_ioctl,
};
//字符设备
static struct cdev *ili9225g_cdev;
struct device *class_dev;
static int ili9225g_spidev_probe(struct spi_device *spi_dev)
{
/* Initialize the driver data */
printk("ili9225g_spidev_probe\n");
spi = spi_dev;
TE(1);
inti_ili9225g();
#if 0
int i=0;
for(i=0;i<176*220;i++)
write_data(0x01,0xf0);
#endif
buffer = kmalloc(buffer_size, GFP_KERNEL);
if(buffer==NULL)
printk("kmalloc error\n");
return 0;
}
static int ili9225g_spidev_remove(struct spi_device *spi_dev)
{
spi = NULL;
return 0;
}
static struct spi_driver spidev_spi_driver = {
.driver = {
.name = "spidev",
.owner = THIS_MODULE,
},
.probe = ili9225g_spidev_probe,
.remove = ili9225g_spidev_remove,
};
static int __init ili9225g_init(void)
{
int ret,status;
//这是设备号的数据类型
dev_t ili9225g_devid;
//申请gpio管脚资源
ret = gpio_request(ili9225g_board.reset_gpio,"ili9225g_reset");
if(ret){
printk("gpio requrest fail %d\n",ili9225g_board.reset_gpio);
}
ret = gpio_request(ili9225g_board.rs_gpio,"ili9225g_rs");
if(ret){
printk("gpio requrest fail %d\n",ili9225g_board.rs_gpio);
}
ret = gpio_request(ili9225g_board.backlight_gpio,"ili9225g_backlight");
if(ret){
printk("gpio requrest fail %d\n",ili9225g_board.backlight_gpio);
}
ret = gpio_request(ili9225g_board.te_gpio,"ili9225g_te");
if(ret){
printk("gpio requrest fail %d\n",ili9225g_board.te_gpio);
}
//申请设备号,还有一个函数register_chrdev_region也是可以
alloc_chrdev_region(&ili9225g_devid, 0, 32768, "ili9225g");
#if 1
//动态申请cdev内存
ili9225g_cdev = cdev_alloc();
//初始化cdev成员,建立cdev与file_operations之间的联系
cdev_init(ili9225g_cdev, &ili9225g_fops);
ili9225g_cdev->owner = THIS_MODULE;
//向系统添加一个cdev字符设备,完成cdev注册
cdev_add(ili9225g_cdev, ili9225g_devid, 1);
#else
register_chrdev(231, "ili9225g", &ili9225g_fops);
#endif
//创建class目录下的文件
ili9225g_class=class_create(THIS_MODULE, "ili9225g");
class_dev=device_create(ili9225g_class, NULL, ili9225g_devid, NULL, "ili9225g");
status = spi_register_driver(&spidev_spi_driver);
if (status < 0) {
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
}
return 0;
}
static void __exit ili9225g_exit(void)
{
printk("ili9225g_exit\n");
gpio_free(ili9225g_board.rs_gpio);
gpio_free(ili9225g_board.reset_gpio);
gpio_free(ili9225g_board.backlight_gpio);
kfree(buffer);
spi_unregister_driver(&spidev_spi_driver);
#if 1
cdev_del(ili9225g_cdev);
#else
// unregister_chrdev(231, "ili9225g");
#endif
device_unregister(class_dev);
class_destroy(ili9225g_class);
}
module_init(ili9225g_init);
module_exit(ili9225g_exit);
//MODULE_LICENSE("GPL v2");
MODULE_LICENSE("GPL");
////////////////////////////////////////////////////////////
//ili9225g_test.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUF_SIZE (220*176*2)
#define RW 20
#define RH 20
void drawRect(short * buffer ,int x,int y){
int i ;
for( i = 0;i<220*176;i++){
buffer[i] = 0x001f;
}
for( i = 0;i
buffer[y*176+x+i] = 0xf800;
buffer[(y+RH)*176+x+i] = 0xf800;
}
for( i = 0;i
buffer[x+(y+i)*176] = 0xf800;
buffer[RW+x+(y+i)*176] = 0xf800;
}
}
int main()
{
int ret;
int fd;
fd=open("/dev/ili9225g",O_RDWR);
if(fd<0){
printf("can't open device\n");
return -1;
}
unsigned char buf[BUF_SIZE];
unsigned char buf1[BUF_SIZE];
unsigned char buf2[BUF_SIZE];
// 5 6 5
//RRRR RGGG GGGB BBBB
//char c='a';
int i;
#if 1
for(i = 0;i
buf[i++] = 0xf8;
buf[i++] = 0x00;
}
for(i = 0;i
buf1[i++] = 0x07;
buf1[i++] = 0xe0;
}
for(i = 0;i
buf2[i++] = 0x00;
buf2[i++] = 0x1f;
}
#endif
struct timespec time1 = {0, 0};
int j=30;
clock_gettime(CLOCK_MONOTONIC, &time1);
long long t=((long long)time1.tv_sec*1000000 + (long long)time1.tv_nsec/1000);
// printf("CLOCK_REALTIME: %d, %d\n", time1.tv_sec, time1.tv_nsec/1000);
int x=0;
while(1){
x++;
if((x+RW)>=220)x = 0;
drawRect((short *)buf,x,30);
write(fd,buf,BUF_SIZE);
// usleep(200*1000);
}
clock_gettime(CLOCK_MONOTONIC, &time1);
long long t1=((long long)time1.tv_sec*1000000 + (long long)time1.tv_nsec/1000);
printf("CLOCK_REALTIME1: %d\n",(t1-t)/1000);
return 0 ;
}
阅读(2535) | 评论(0) | 转发(0) |