/* * gsc3280_emidisp.c - driver for Emi Display in Loongson soc * * Copyright (C) 2012 Loongson Corporation * * 2013-01-31 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gsc3280_emidisp.h" /*----------------------------------------------------------------------------*/ enum { EMI_LIGHG_PIN = 0, RESET_PIN, MAX_PIN_NR, }; struct gpio emidsip_gpios[MAX_PIN_NR] = { {gsc3280_GPA(0), GPIOF_OUT_INIT_HIGH, "emidisp_back_light"}, {gsc3280_GPA(1), GPIOF_OUT_INIT_HIGH, "emidisp_reset"} }; #define EMI_DISP_GET_IOMUX() \ do {\ ;\ } while (0) #define EMI_DISP_RELEASE_IOMUX() \ do {\ ;\ } while (0) /*----------------------------------------------------------------------------*/ struct gsc3280_emidisp { struct cdev cdev; struct class *emidisp_class; dev_t dev; }; struct gsc3280_emidisp emidisp_priv; /*----------------------------------------------------------------------------*/ static void emi_wr_dat(unsigned char uc_dat) { EMI_DISP_GET_IOMUX(); DAT_OPT = uc_dat; EMI_DISP_RELEASE_IOMUX(); } static void emi_wr_cmd(unsigned char uc_cmd) { EMI_DISP_GET_IOMUX(); CMD_OPT = uc_cmd; EMI_DISP_RELEASE_IOMUX(); } static void reset_emi_disp_dev(void) { //RST Set reset pin low sleep high gpio_set_value(emidsip_gpios[RESET_PIN].gpio, 0); udelay(1000); gpio_set_value(emidsip_gpios[RESET_PIN].gpio, 1); return; } static void emi_disp_back_light(unsigned char val) { gpio_set_value(emidsip_gpios[EMI_LIGHG_PIN].gpio, !!val); } /*----------------------------------------------------------------------------*/ /* */ static ssize_t emidisp_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { return 0; } /*----------------------------------------------------------------------------*/ /* */ static ssize_t emidisp_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { return 0; } /*----------------------------------------------------------------------------*/ /* */ static long emidisp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned char val = 0; if (_IOC_TYPE(cmd) != EMIDISP_IOC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > EMIDISP_IOC_MAXNR) return -ENOTTY; __get_user(val, (unsigned char*)arg); switch(cmd) { case EMIDISP_CMD: if (arg) emi_wr_cmd(val); break; case EMIDISP_DAT: if (arg) emi_wr_dat(val); break; case EMIDISP_RST: reset_emi_disp_dev(); break; case EMIDISP_BACK: emi_disp_back_light(val); break; default: return -ENOTTY; } return 0; } static int emidisp_open(struct inode *inode, struct file *filp) { int ret = 0; ret = gpio_request_array(emidsip_gpios, sizeof(emidsip_gpios)/sizeof(emidsip_gpios[0])); if (ret < 0) return ret; return 0; } static int emidisp_release(struct inode *inode, struct file *filp) { gpio_free_array(emidsip_gpios, sizeof(emidsip_gpios)/sizeof(emidsip_gpios[0])); return 0; } struct file_operations emidisp_fops = { .owner = THIS_MODULE, .read = emidisp_read, .write = emidisp_write, .unlocked_ioctl = emidisp_ioctl, .open = emidisp_open, .release = emidisp_release, }; /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ static int __init gsc3280_emidisp_init(void) { int err; int result; int major; result = alloc_chrdev_region(&emidisp_priv.dev, 0, 0, "emidisp"); major = MAJOR(emidisp_priv.dev); if (result < 0) { printk(KERN_WARNING "emidisp: can't get major %d\n", major); return result; } cdev_init(&emidisp_priv.cdev, &emidisp_fops); emidisp_priv.cdev.owner = THIS_MODULE; emidisp_priv.cdev.ops = &emidisp_fops; err = cdev_add(&emidisp_priv.cdev, emidisp_priv.dev, 1); if (err) { printk(KERN_NOTICE "Error[%d] cdev_add emidisp\n", err); return -1; } emidisp_priv.emidisp_class = class_create(THIS_MODULE, "gsc3280_emidisp"); if (IS_ERR(emidisp_priv.emidisp_class)) { printk(KERN_ERR "Failed in create gsc3280_cdev class\n"); return -1; } device_create(emidisp_priv.emidisp_class, NULL, emidisp_priv.dev, NULL, "emidisp"); return 0; } /*----------------------------------------------------------------------------*/ static void __exit gsc3280_emidisp_exit(void) { cdev_del(&emidisp_priv.cdev); unregister_chrdev_region(emidisp_priv.dev, 1); device_destroy(emidisp_priv.emidisp_class, emidisp_priv.dev); class_destroy(emidisp_priv.emidisp_class); } /*----------------------------------------------------------------------------*/ module_init(gsc3280_emidisp_init); module_exit(gsc3280_emidisp_exit); /*----------------------------------------------------------------------------*/ MODULE_AUTHOR("ansonn.wang@gmail.com"); MODULE_DESCRIPTION("gsc3280 emi Display driver"); MODULE_LICENSE("GPL"); /*----------------------------------------------------------------------------*/