- 论坛徽章:
- 0
|
- /*
- *
- * drivers/w90x950_12864lcdm.c
- *
- * (c) 2010 Adem Zhu<dengbo.zhu@gmail.com>
- *
- * W90x950 128X64 TN LCD pane Model driver
- *
- */
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/delay.h>
- #include <asm/uaccess.h>
- #include <asm/arch/hardware.h>
- #include <asm/io.h>
- #include <asm/arch/w90x900_reg.h>
- #define LCDM12864_MAJOR (79)
- #define DEV_NAME "lcdm128x64"
- #define LCDM12864_RESET (0x00)
- /* refrest LCDM, no arg */
- #define LCDM12864_REFRESH_BLOCK_IN_PAGE (0x01)
- /* arg is pointer of struct lcdm12864_refresh_block */
- struct lcdm12864_refresh_block
- {
- unsigned char page;
- unsigned char startx;
- unsigned char endx;
- unsigned char length;
- unsigned char *data;
- };
- #define LCDM12864_BACKLIGHT_CTRL (0x02)
- /* the LCDM backlight is on when arg is a non-zero value */
- /*
- hardware definitions.
- LCDM_CS <=> GPIO D2
- LCDM_RES <=> GPIO D3
- LCDM_A0 <=> GPIO D0
- LCDM_SCK <=> GPIO D5
- LCDM_SDA <=> GPIO D6
- LCDM_BACKLIGHT <=> GPIO D1
- */
- static void hw_128X64_sendbyte(unsigned char db)
- {
- long value;
- int index;
- for (index = 0; index < 8; index ++)
- {
- value = inl(REG_GPIOD_DATAOUT);
- value &= ~(1<<6);
- if (db & 0x80)
- {
- value |= (1<<6);
- }
- outl(value, REG_GPIOD_DATAOUT); /* flush LCDM_SDA */
- outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 5), REG_GPIOD_DATAOUT); /*clock down LCDM_SCK (GPIO D5)*/
- db <<= 1;
- outl(inl(REG_GPIOD_DATAOUT) | (1 << 5), REG_GPIOD_DATAOUT); /*clock up LCDM_SCK (GPIO D5)*/
- }
- }
- static void hw_128X64_init(void)
- {
- outl(inl(REG_GPIOD_DATAOUT) | (1 << 5), REG_GPIOD_DATAOUT); /*default: clock up LCDM_SCK (GPIO D5)*/
- outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 0), REG_GPIOD_DATAOUT); /*pull down LCDM_A0 (GPIO D0)*/
- outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 2), REG_GPIOD_DATAOUT); /*pull down LCDM_CS (GPIO D2)*/
- }
- static void hw_128X64_reset(void) /* Reset the module */
- {
- outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 3), REG_GPIOD_DATAOUT); /*pull down LCDM_RES (GPIO D3)*/
- udelay(1000);
- outl(inl(REG_GPIOD_DATAOUT) | (1 << 3), REG_GPIOD_DATAOUT); /*pull up LCDM_RES (GPIO D3)*/
- udelay(1000);
- }
- static void hw_128X64_open(void)
- {
- /* Booster ratio set : 5X */
- hw_128X64_sendbyte(0xf8);
- udelay(999);
- hw_128X64_sendbyte(0x01);
- udelay(999);
- /* Segment Driver Direction Select : Normal */
- hw_128X64_sendbyte(0xa0);
- udelay(999);
- /* Common Output Mode Select : Normal */
- hw_128X64_sendbyte(0xc0);
- udelay(999);
- /* LCD Bias Set : 1/65 duty, 1/9 bias */
- hw_128X64_sendbyte(0xa2);
- udelay(2000);
- /* power control set */
- hw_128X64_sendbyte(0x2c);
- udelay(2000);
- hw_128X64_sendbyte(0x2e);
- udelay(2000);
- hw_128X64_sendbyte(0x2f);
- udelay(2000);
- /* power control set */
- hw_128X64_sendbyte(0x25);
- udelay(999);
- /* The Electronic Volume Mode Set */
- hw_128X64_sendbyte(0x81);
- udelay(999);
- hw_128X64_sendbyte(34);
- udelay(999);
- /* Display all points off */
- hw_128X64_sendbyte(0xa4);
- udelay(999);
- /* Display ON mode */
- hw_128X64_sendbyte(0xaf);
- udelay(999);
- }
- static void hw_128X64_set_startline(unsigned char start_line)
- {
- /* 0 1 Display start address */
- hw_128X64_sendbyte((start_line & 0x3f) | 0x40);
- }
- static void hw_128X64_set_page(unsigned char page)
- {
- /* 1 0 1 1 page address */
- hw_128X64_sendbyte((page & 0x0f) | 0xb0);
- }
- static void hw_128X64_set_column(unsigned char column)
- {
- /* 0 0 0 1 higher bits */
- hw_128X64_sendbyte(((column >> 4) & 0x0f) | 0x10);
- /* 0 0 0 0 lower bits */
- hw_128X64_sendbyte(column & 0x0f);
- }
- static void hw_128X64_writedata(unsigned char db)
- {
- outl(inl(REG_GPIOD_DATAOUT) | (1 << 0), REG_GPIOD_DATAOUT); /*pull up LCDM_A0 (GPIO D0)*/
- /* data */
- hw_128X64_sendbyte(db);
- outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 0), REG_GPIOD_DATAOUT); /*pull down LCDM_A0 (GPIO D0)*/
- }
- static void lcdm_reset(void) /* reset lcd model : init & reset & open & set_startline */
- {
- hw_128X64_init();
- hw_128X64_reset();
- hw_128X64_open();
- hw_128X64_set_startline(0);
- }
- static void lcdm_refresh_block_in_page(unsigned char page, unsigned char startx, unsigned char endx, char * data)
- {
- int cnt = (endx - startx + 1);
- hw_128X64_set_page(page);
- hw_128X64_set_column(startx);
- for (;cnt--;)
- {
- hw_128X64_writedata(*data ++);
- }
- }
- static int w90x950_12864lcdm_open(struct inode *inode, struct file *file)
- {
- return 0;
- }
- static int w90x950_12864lcdm_close(struct inode *inode, struct file *file)
- {
- return 0;
- }
- static int w90x950_12864lcdm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
- {
- struct lcdm12864_refresh_block refresh_cmd;
- unsigned char *buf;
- switch (cmd)
- {
- case LCDM12864_RESET: /* reset lcd module */
- lcdm_reset();
- return 0;
- break;
- case LCDM12864_REFRESH_BLOCK_IN_PAGE:
- if (!arg)
- return -EINVAL;
- if (copy_from_user(&refresh_cmd, (const void *)arg, sizeof(struct lcdm12864_refresh_block)))
- return -EFAULT;
- if (refresh_cmd.length != refresh_cmd.endx - refresh_cmd.startx + 1)
- return -EINVAL;
- /* allocate memory */
- buf = kzalloc(refresh_cmd.length, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- if (copy_from_user(buf, refresh_cmd.data, refresh_cmd.length))
- {
- kfree(buf);
- return -EFAULT;
- }
- lcdm_refresh_block_in_page(refresh_cmd.page, refresh_cmd.startx, refresh_cmd.endx, refresh_cmd.data);
- kfree(buf);
- return 0;
- break;
- case LCDM12864_BACKLIGHT_CTRL:
- if (arg)
- {
- outl(inl(REG_GPIOD_DATAOUT) | (1 << 1), REG_GPIOD_DATAOUT); /*pull up LCDM_BACKLIGHT (GPIO D1)*/
- }
- else
- {
- outl(inl(REG_GPIOD_DATAOUT) & ~(1 << 1), REG_GPIOD_DATAOUT); /*pull down LCDM_BACKLIGHT (GPIO D1)*/
- };
- return 0;
- break;
- }
- return -EINVAL;
- }
- struct file_operations w90x950_12864lcdm_fops =
- {
- owner: THIS_MODULE,
- open: w90x950_12864lcdm_open,
- ioctl: w90x950_12864lcdm_ioctl,
- release: w90x950_12864lcdm_close,
- };
- static int __init w90x950_12864lcdm_init(void)
- {
- if (register_chrdev(LCDM12864_MAJOR, DEV_NAME, &w90x950_12864lcdm_fops) < 0)
- {
- printk("can't get major %d\n", LCDM12864_MAJOR);
- return -1;
- }
- /* config the all io pins (D0, D1, D2, D3, D5, D6) */
- outl(inl(REG_MFSEL) & ~0x00f0, REG_MFSEL); /* configure GPIOD to IO function. */
- outl(inl(REG_GPIOD_DIR) | 0x006f, REG_GPIOD_DIR); /* configure output pins. */
- outl(inl(REG_GPIODPE) | 0x006f, REG_GPIODPE); /* configure pins as pullup. */
- lcdm_reset();
- printk("W90X950 128X64 TN LCDM driver started successfully!\n");
- return(0);
- }
- static void __exit w90x950_12864lcdm_exit(void)
- {
- unregister_chrdev(LCDM12864_MAJOR, DEV_NAME);
- }
- module_init(w90x950_12864lcdm_init);
- module_exit(w90x950_12864lcdm_exit);
- MODULE_AUTHOR("Adem Zhu <dengbo.zhu@gmail.com>");
- MODULE_DESCRIPTION("NUC950 128X64 TN LCD pane Model driver");
- MODULE_LICENSE("GPL");
|
|