#include <mach/gpio.h>
#include <mach/iomux.h>
#include <linux/i2c.h>
+#include <linux/uaccess.h>
+#if defined(CONFIG_DEBUG_FS)
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#endif
+
#include "cat66121_hdmi.h"
#include "cat66121_hdmi_hw.h"
+#define HDMI_POLL_MDELAY 100
struct cat66121_hdmi_pdata *cat66121_hdmi = NULL;
struct hdmi *hdmi=NULL;
extern struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name);
extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);
extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);
-static void check_status_func(struct work_struct *work);
static void cat66121_irq_work_func(struct work_struct *work);
-static DECLARE_DELAYED_WORK(check_status_work,check_status_func);
-
-static void check_status_func(struct work_struct *work)
-{
- if(HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) & B_TX_INT_ACTIVE){
- cat66121_irq_work_func(NULL);
- }
- schedule_delayed_work(&check_status_work, msecs_to_jiffies(5000));
-}
#if 0
int cat66121_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
void (*hdcp_irq_cb)(int status),
return;
}
- #ifdef HDMI_USE_IRQ
- if(hdmi->irq)
+ if(hdmi->irq != INVALID_GPIO)
disable_irq(hdmi->irq);
- #endif
mutex_unlock(&hdmi->enable_mutex);
hdmi->command = HDMI_CONFIG_ENABLE;
wait_for_completion_interruptible_timeout(&hdmi->complete,
msecs_to_jiffies(5000));
flush_delayed_work(&hdmi->delay_work);
- cancel_delayed_work_sync(&check_status_work);
return;
}
mutex_lock(&hdmi->enable_mutex);
hdmi->suspend = 0;
- #ifdef HDMI_USE_IRQ
- if(hdmi->enable && hdmi->irq) {
+ if(hdmi->irq == INVALID_GPIO){
+ queue_delayed_work(cat66121_hdmi->workqueue, &cat66121_hdmi->delay_work, HDMI_POLL_MDELAY);
+ }else if(hdmi->enable){
enable_irq(hdmi->irq);
}
- #else
- queue_delayed_work(cat66121_hdmi->workqueue, &cat66121_hdmi->delay_work, 100);
- #endif
queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
- schedule_delayed_work(&check_status_work, msecs_to_jiffies(5000));
mutex_unlock(&hdmi->enable_mutex);
return;
}
if(hdmi->hdcp_irq_cb)
hdmi->hdcp_irq_cb(0);
}
- #ifndef HDMI_USE_IRQ
- queue_delayed_work(cat66121_hdmi->workqueue, &cat66121_hdmi->delay_work, 100);
- #endif
+ if(hdmi->irq == INVALID_GPIO){
+ queue_delayed_work(cat66121_hdmi->workqueue, &cat66121_hdmi->delay_work, HDMI_POLL_MDELAY);
+ }
}
}
-#ifdef HDMI_USE_IRQ
-static irqreturn_t cat66121_irq(int irq, void *dev_id)
+static irqreturn_t cat66121_thread_interrupt(int irq, void *dev_id)
{
- printk(KERN_INFO "cat66121 irq triggered.\n");
- schedule_work(&cat66121_hdmi->irq_work);
- return IRQ_HANDLED;
+ cat66121_irq_work_func(NULL);
+ msleep(HDMI_POLL_MDELAY);
+ hdmi_dbg(hdmi->dev, "%s irq=%d\n", __func__,irq);
+ return IRQ_HANDLED;
}
-#endif
-#ifdef HDMI_DEBUG
+
+#if defined(CONFIG_DEBUG_FS)
static int hdmi_read_p0_reg(struct i2c_client *client, char reg, char *val)
{
return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
{
return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
}
-static ssize_t hdmi_show_reg_attrs(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int hdmi_reg_show(struct seq_file *s, void *v)
{
- int i,size=0;
+ int i;
char val;
struct i2c_client *client=cat66121_hdmi->client;
{
hdmi_read_p0_reg(client, i, &val);
if(i%16==0)
- size += sprintf(buf+size,"\n>>>hdmi_hdmi %x:",i);
- size += sprintf(buf+size," %2x",val);
+ seq_printf(s,"\n>>>hdmi_hdmi %x:",i);
+ seq_printf(s," %2x",val);
}
+ seq_printf(s,"\n");
- return size;
+ return 0;
}
-static ssize_t hdmi_store_reg_attrs(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
+
+static ssize_t hdmi_reg_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
struct i2c_client *client=NULL;
- static char val=0,reg=0;
+ u32 reg,val;
+ char kbuf[25];
client = cat66121_hdmi->client;
- printk("/**********hdmi reg config******/");
+
+ if (copy_from_user(kbuf, buf, count))
+ return -EFAULT;
+ sscanf(kbuf, "%x%x", ®,&val);
+ hdmi_write_p0_reg(client, reg, (u8*)&val);
- sscanf(buf, "%x%x", &val,®);
- hdmi_write_p0_reg(client, reg, &val);
- return size;
+ return count;
}
-static struct device_attribute hdmi_attrs[] = {
- __ATTR(reg_ctl, 0777,hdmi_show_reg_attrs,hdmi_store_reg_attrs),
+static int hdmi_reg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file,hdmi_reg_show,hdmi);
+}
+
+static const struct file_operations hdmi_reg_fops = {
+ .owner = THIS_MODULE,
+ .open = hdmi_reg_open,
+ .read = seq_read,
+ .write = hdmi_reg_write,
+ .llseek = seq_lseek,
+ .release = single_release,
};
#endif
static int cat66121_hdmi_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
- int rc = 0;
+ int rc = 0;
struct rk_hdmi_platform_data *pdata = client->dev.platform_data;
cat66121_hdmi = kzalloc(sizeof(struct cat66121_hdmi_pdata), GFP_KERNEL);
if(!cat66121_hdmi)
{
- dev_err(&client->dev, "no memory for state\n");
- return -ENOMEM;
- }
+ dev_err(&client->dev, "no memory for state\n");
+ return -ENOMEM;
+ }
cat66121_hdmi->client = client;
i2c_set_clientdata(client, cat66121_hdmi);
goto err_request_lcdc;
}
}
+
if(cat66121_detect_device()!=1){
- dev_err(hdmi->dev, "can't find it6610 device \n");
+ dev_err(hdmi->dev, "can't find it66121 device \n");
rc = -ENXIO;
goto err_request_lcdc;
}
+ if(client->irq == 0){
+ dev_err(hdmi->dev, "can't find it66121 irq\n");
+ dev_err(hdmi->dev, " please set irq or use irq INVALID_GPIO for poll mode\n");
+ rc = -ENXIO;
+ goto err_request_lcdc;
+ }
+ hdmi->irq = gpio_to_irq(client->irq);
hdmi->xscale = 100;
hdmi->yscale = 100;
hdmi->insert = cat66121_hdmi_sys_insert;
cat66121_hdmi_sys_init();
-#ifdef HDMI_DEBUG
- device_create_file(&(client->dev), &hdmi_attrs[0]);
+
+#if defined(CONFIG_DEBUG_FS)
+ {
+ struct dentry *debugfs_dir = debugfs_create_dir("it66121", NULL);
+ if (IS_ERR(debugfs_dir))
+ {
+ dev_err(&client->dev,"failed to create debugfs dir for it66121!\n");
+ }
+ else
+ debugfs_create_file("hdmi", S_IRUSR,debugfs_dir,hdmi,&hdmi_reg_fops);
+ }
#endif
-#ifdef HDMI_USE_IRQ
if(client->irq != INVALID_GPIO) {
- INIT_WORK(&cat66121_hdmi->irq_work, cat66121_irq_work_func);
- schedule_work(&cat66121_hdmi->irq_work);
+ cat66121_irq_work_func(NULL);
if((rc = gpio_request(client->irq, "hdmi gpio")) < 0)
- {
- dev_err(&client->dev, "fail to request gpio %d\n", client->irq);
- goto err_request_lcdc;
- }
+ {
+ dev_err(&client->dev, "fail to request gpio %d\n", client->irq);
+ goto err_request_lcdc;
+ }
- schedule_delayed_work(&check_status_work, msecs_to_jiffies(5000));
- hdmi->irq = gpio_to_irq(client->irq);
cat66121_hdmi->gpio = client->irq;
- gpio_pull_updown(client->irq, GPIOPullUp);
- gpio_direction_input(client->irq);
- if((rc = request_irq(hdmi->irq, cat66121_irq, IRQF_TRIGGER_FALLING, NULL, hdmi)) < 0)
- {
- dev_err(&client->dev, "fail to request hdmi irq\n");
- goto err_request_irq;
- }
- }
- else
-#else
- {
+ gpio_pull_updown(client->irq, GPIOPullUp);
+ gpio_direction_input(client->irq);
+ if((rc = request_threaded_irq(hdmi->irq, NULL ,cat66121_thread_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, dev_name(&client->dev), hdmi)) < 0)
+ {
+ dev_err(&client->dev, "fail to request hdmi irq\n");
+ goto err_request_irq;
+ }
+ }else{
cat66121_hdmi->workqueue = create_singlethread_workqueue("cat66121 irq");
INIT_DELAYED_WORK(&(cat66121_hdmi->delay_work), cat66121_irq_work_func);
cat66121_irq_work_func(NULL);
}
-#endif
dev_info(&client->dev, "cat66121 hdmi i2c probe ok\n");