241 lines
5.5 KiB
C
241 lines
5.5 KiB
C
/*
|
|
* gsc3280_emidisp.c - driver for Emi Display in Loongson soc
|
|
*
|
|
* Copyright (C) 2012 Loongson Corporation
|
|
*
|
|
* 2013-01-31
|
|
*/
|
|
#include <linux/types.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/module.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/ioport.h>
|
|
#include <linux/init.h>
|
|
#include <linux/err.h>
|
|
#include <linux/rcupdate.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/io.h>
|
|
#include <linux/of.h>
|
|
#include <linux/completion.h>
|
|
#include <asm/io.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/fcntl.h>
|
|
#include <asm/uaccess.h>
|
|
#include <linux/gpio.h>
|
|
#include <gsc3280/gpio.h>
|
|
#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");
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|