video: tegra: dc: provide debugfs to force hotplug
Jon Mayo [Sun, 10 Feb 2013 05:42:13 +0000 (21:42 -0800)]
debugfs node tegra_hdmi/hotplug controls the override.
0 for normal hpd, 1 for force on, -1 for force off

Change-Id: I41bfbcd26460924ed60bd27de68046ff77b1e869
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/208201
Reviewed-by: Harshada Kale <hkale@nvidia.com>
Tested-by: Harshada Kale <hkale@nvidia.com>

arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/hdmi.c

index 70aebde..fc22f24 100644 (file)
@@ -483,6 +483,7 @@ struct tegra_dc_out {
 
        int                             dcc_bus;
        int                             hotplug_gpio;
+       int                             hotplug_state; /* 0 normal 1 force on */
        const char                      *parent_clk;
        const char                      *parent_clk_backup;
 
index 7e0fb42..ad505f1 100644 (file)
@@ -754,6 +754,15 @@ bool tegra_dc_hpd(struct tegra_dc *dc)
        int sense;
        int level;
 
+       if (WARN_ON(!dc || !dc->out))
+               return false;
+
+       if (dc->out->hotplug_state != 0) {
+               if (dc->out->hotplug_state == 1) /* force on */
+                       return true;
+               if (dc->out->hotplug_state == -1) /* force off */
+                       return false;
+       }
        level = gpio_get_value_cansleep(dc->out->hotplug_gpio);
 
        sense = dc->out->flags & TEGRA_DC_OUT_HOTPLUG_MASK;
index bb67f69..7d0cb14 100644 (file)
@@ -449,12 +449,12 @@ static inline void tegra_hdmi_clrsetbits(struct tegra_dc_hdmi_data *hdmi,
 }
 
 #ifdef CONFIG_DEBUG_FS
-static int dbg_hdmi_show(struct seq_file *s, void *unused)
+static int dbg_hdmi_show(struct seq_file *m, void *unused)
 {
-       struct tegra_dc_hdmi_data *hdmi = s->private;
+       struct tegra_dc_hdmi_data *hdmi = m->private;
 
 #define DUMP_REG(a) do {                                               \
-               seq_printf(s, "%-32s\t%03x\t%08lx\n",                   \
+               seq_printf(m, "%-32s\t%03x\t%08lx\n",                   \
                       #a, a, tegra_hdmi_readl(hdmi, a));               \
        } while (0)
 
@@ -626,18 +626,68 @@ static int dbg_hdmi_show(struct seq_file *s, void *unused)
        return 0;
 }
 
-static int dbg_hdmi_open(struct inode *inode, struct file *file)
+static int dbg_hdmi_show_open(struct inode *inode, struct file *file)
 {
        return single_open(file, dbg_hdmi_show, inode->i_private);
 }
 
-static const struct file_operations dbg_fops = {
-       .open           = dbg_hdmi_open,
+static const struct file_operations dbg_hdmi_show_fops = {
+       .open           = dbg_hdmi_show_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = single_release,
 };
 
+static int dbg_hotplug_show(struct seq_file *m, void *unused)
+{
+       struct tegra_dc_hdmi_data *hdmi = m->private;
+       struct tegra_dc *dc = hdmi->dc;
+
+       if (WARN_ON(!hdmi || !dc || !dc->out))
+               return -EINVAL;
+
+       seq_put_decimal_ll(m, '\0', dc->out->hotplug_state);
+       seq_putc(m, '\n');
+       return 0;
+}
+
+static int dbg_hotplug_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dbg_hotplug_show, inode->i_private);
+}
+
+static int dbg_hotplug_write(struct file *file, const char __user *addr,
+       size_t len, loff_t *pos)
+{
+       struct seq_file *m = file->private_data; /* single_open() initialized */
+       struct tegra_dc_hdmi_data *hdmi = m->private;
+       struct tegra_dc *dc = hdmi->dc;
+       int ret;
+       long new_state;
+
+       if (WARN_ON(!hdmi || !dc || !dc->out))
+               return -EINVAL;
+
+       ret = kstrtol_from_user(addr, len, 10, &new_state);
+       if (ret < 0)
+               return ret;
+
+       dc->out->hotplug_state = new_state;
+
+       queue_delayed_work(system_nrt_wq, &hdmi->work,
+               msecs_to_jiffies(100));
+
+       return len;
+}
+
+static const struct file_operations dbg_hotplug_fops = {
+       .open           = dbg_hotplug_open,
+       .read           = seq_read,
+       .write          = dbg_hotplug_write,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static struct dentry *hdmidir;
 
 static void tegra_dc_hdmi_debug_create(struct tegra_dc_hdmi_data *hdmi)
@@ -648,7 +698,11 @@ static void tegra_dc_hdmi_debug_create(struct tegra_dc_hdmi_data *hdmi)
        if (!hdmidir)
                return;
        retval = debugfs_create_file("regs", S_IRUGO, hdmidir, hdmi,
-               &dbg_fops);
+               &dbg_hdmi_show_fops);
+       if (!retval)
+               goto free_out;
+       retval = debugfs_create_file("hotplug", S_IRUGO, hdmidir, hdmi,
+               &dbg_hotplug_fops);
        if (!retval)
                goto free_out;
        return;
@@ -909,6 +963,7 @@ static void tegra_dc_hdmi_detect_worker(struct work_struct *work)
        tegra_dc_set_default_videomode(dc);
 #endif
        if (!tegra_dc_hdmi_detect(dc)) {
+               dev_dbg(&dc->ndev->dev, "HDMI disconnect\n");
                dc->connected = false;
                tegra_dc_disable(dc);