]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00153216-2 mxc_dispdrv: add dvi display driver support
authorJason Chen <b02280@freescale.com>
Mon, 18 Jul 2011 08:36:26 +0000 (16:36 +0800)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:09:18 +0000 (14:09 +0200)
change dvi display driver to mxc_dispdrv.

Signed-off-by: Jason Chen <b02280@freescale.com>
drivers/video/mxc/Makefile
drivers/video/mxc/mxc_ddc.c [deleted file]
drivers/video/mxc/mxc_dvi.c [new file with mode: 0644]
drivers/video/mxc/mxc_edid.c

index 89f19269f233cb593027b24362cc81b80100083b..4fdb822105f1eb30049cf088023c3d35d0979137 100644 (file)
@@ -1,7 +1,7 @@
 obj-$(CONFIG_FB_MXC_TVOUT_TVE)                 += tve.o
 obj-$(CONFIG_FB_MXC_SII902X)                    += mxcfb_sii902x.o
 obj-$(CONFIG_FB_MXC_LDB)                       += ldb.o
-#obj-$(CONFIG_FB_MODE_HELPERS)                 += mxc_edid.o mxc_ddc.o
+obj-$(CONFIG_FB_MODE_HELPERS)                  += mxc_edid.o mxc_dvi.o
 ifeq ($(CONFIG_ARCH_MX21)$(CONFIG_ARCH_MX27)$(CONFIG_ARCH_MX25),y)
        obj-$(CONFIG_FB_MXC_TVOUT)              += fs453.o
        obj-$(CONFIG_FB_MXC_SYNC_PANEL)         += mx2fb.o mxcfb_modedb.o
diff --git a/drivers/video/mxc/mxc_ddc.c b/drivers/video/mxc/mxc_ddc.c
deleted file mode 100644 (file)
index 60b74cd..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/*!
- * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
- */
-
-/*!
- * @file mxc_edid.c
- *
- * @brief MXC EDID driver
- *
- * @ingroup Framebuffer
- */
-
-/*!
- * Include files
- */
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mxcfb.h>
-#include <linux/fsl_devices.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/regulator/consumer.h>
-#include <mach/mxc_edid.h>
-#include "../edid.h"
-
-#define MXC_EDID_LENGTH (EDID_LENGTH*4)
-
-struct mxc_ddc_data {
-       struct platform_device *pdev;
-       struct i2c_client *client;
-       struct delayed_work det_work;
-       struct fb_info *fbi;
-       struct mxc_edid_cfg edid_cfg;
-       u8 cable_plugin;
-       u8 edid[MXC_EDID_LENGTH];
-
-       u32 di;
-       void (*init)(void);
-       int (*update)(void);
-       struct regulator *analog_reg;
-} mxc_ddc;
-
-#define MXC_ENABLE     1
-#define MXC_DISABLE    2
-static int g_enable_ddc;
-
-static ssize_t mxc_ddc_show_state(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       if (mxc_ddc.cable_plugin == 0)
-               strcpy(buf, "plugout\n");
-       else
-               strcpy(buf, "plugin\n");
-
-       return strlen(buf);
-}
-
-static DEVICE_ATTR(cable_state, S_IRUGO, mxc_ddc_show_state, NULL);
-
-static ssize_t mxc_ddc_show_name(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       strcpy(buf, mxc_ddc.fbi->fix.id);
-       sprintf(buf+strlen(buf), "\n");
-
-       return strlen(buf);
-}
-
-static DEVICE_ATTR(fb_name, S_IRUGO, mxc_ddc_show_name, NULL);
-
-static ssize_t mxc_ddc_show_edid(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       int i, j, len = 0;
-
-       for (j = 0; j < MXC_EDID_LENGTH/16; j++) {
-               for (i = 0; i < 16; i++)
-                       len += sprintf(buf+len, "0x%02X ",
-                                       mxc_ddc.edid[j*16 + i]);
-               len += sprintf(buf+len, "\n");
-       }
-
-       return len;
-}
-
-static DEVICE_ATTR(edid, S_IRUGO, mxc_ddc_show_edid, NULL);
-
-static void det_worker(struct work_struct *work)
-{
-       char event_string[16];
-       char *envp[] = { event_string, NULL };
-
-       /* cable connection changes */
-       if (mxc_ddc.update()) {
-               u8 edid_old[MXC_EDID_LENGTH];
-               mxc_ddc.cable_plugin = 1;
-               sprintf(event_string, "EVENT=plugin");
-
-               memcpy(edid_old, mxc_ddc.edid, MXC_EDID_LENGTH);
-
-               if (mxc_edid_read(mxc_ddc.client->adapter, mxc_ddc.client->addr,
-                               mxc_ddc.edid, &mxc_ddc.edid_cfg, mxc_ddc.fbi) < 0)
-                       dev_err(&mxc_ddc.client->dev,
-                                       "MXC ddc: read edid fail\n");
-               else {
-                       if (!memcmp(edid_old, mxc_ddc.edid, MXC_EDID_LENGTH))
-                               dev_info(&mxc_ddc.client->dev,
-                                       "Sii902x: same edid\n");
-                       else if (mxc_ddc.fbi->monspecs.modedb_len > 0) {
-                               int i;
-                               const struct fb_videomode *mode;
-                               struct fb_videomode m;
-
-                               /* make sure fb is powerdown */
-                               acquire_console_sem();
-                               fb_blank(mxc_ddc.fbi, FB_BLANK_POWERDOWN);
-                               release_console_sem();
-
-                               fb_destroy_modelist(&mxc_ddc.fbi->modelist);
-
-                               for (i = 0; i < mxc_ddc.fbi->monspecs.modedb_len; i++)
-                                       /*FIXME now we do not support interlaced mode */
-                                       if (!(mxc_ddc.fbi->monspecs.modedb[i].vmode & FB_VMODE_INTERLACED))
-                                               fb_add_videomode(&mxc_ddc.fbi->monspecs.modedb[i],
-                                                               &mxc_ddc.fbi->modelist);
-
-                               fb_var_to_videomode(&m, &mxc_ddc.fbi->var);
-                               mode = fb_find_nearest_mode(&m,
-                                               &mxc_ddc.fbi->modelist);
-
-                               fb_videomode_to_var(&mxc_ddc.fbi->var, mode);
-
-                               mxc_ddc.fbi->var.activate |= FB_ACTIVATE_FORCE;
-                               acquire_console_sem();
-                               mxc_ddc.fbi->flags |= FBINFO_MISC_USEREVENT;
-                               fb_set_var(mxc_ddc.fbi, &mxc_ddc.fbi->var);
-                               mxc_ddc.fbi->flags &= ~FBINFO_MISC_USEREVENT;
-                               release_console_sem();
-
-                               acquire_console_sem();
-                               fb_blank(mxc_ddc.fbi, FB_BLANK_UNBLANK);
-                               release_console_sem();
-                       }
-               }
-       } else {
-               mxc_ddc.cable_plugin = 0;
-               sprintf(event_string, "EVENT=plugout");
-       }
-
-       kobject_uevent_env(&mxc_ddc.pdev->dev.kobj, KOBJ_CHANGE, envp);
-}
-
-static irqreturn_t mxc_ddc_detect_handler(int irq, void *data)
-{
-       if (mxc_ddc.fbi)
-               schedule_delayed_work(&(mxc_ddc.det_work), msecs_to_jiffies(300));
-       return IRQ_HANDLED;
-}
-
-static int mxc_ddc_fb_event(struct notifier_block *nb, unsigned long val, void *v)
-{
-       struct fb_event *event = v;
-       struct fb_info *fbi = event->info;
-
-       if ((mxc_ddc.di)) {
-               if (strcmp(event->info->fix.id, "DISP3 BG - DI1"))
-                       return 0;
-       } else {
-               if (strcmp(event->info->fix.id, "DISP3 BG"))
-                       return 0;
-       }
-
-       switch (val) {
-       case FB_EVENT_FB_REGISTERED:
-               if (mxc_ddc.fbi != NULL)
-                       break;
-               mxc_ddc.fbi = fbi;
-               break;
-       }
-       return 0;
-}
-
-static struct notifier_block nb = {
-       .notifier_call = mxc_ddc_fb_event,
-};
-
-static int __devinit mxc_ddc_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
-{
-       int ret = 0;
-       struct fb_info edid_fbi;
-       struct mxc_ddc_platform_data *plat = client->dev.platform_data;
-
-       if (plat->boot_enable && !g_enable_ddc)
-               g_enable_ddc = MXC_ENABLE;
-       if (!g_enable_ddc)
-               g_enable_ddc = MXC_DISABLE;
-
-       if (g_enable_ddc == MXC_DISABLE) {
-               printk(KERN_WARNING "By setting, DDC driver will not be enabled\n");
-               return -ENODEV;
-       }
-
-       mxc_ddc.client = client;
-       mxc_ddc.di = plat->di;
-       mxc_ddc.init = plat->init;
-       mxc_ddc.update = plat->update;
-
-       if (!mxc_ddc.update)
-               return -EINVAL;
-
-       mxc_ddc.analog_reg = regulator_get(&mxc_ddc.pdev->dev, plat->analog_regulator);
-       if (!IS_ERR(mxc_ddc.analog_reg)) {
-               regulator_set_voltage(mxc_ddc.analog_reg, 2775000, 2775000);
-               regulator_enable(mxc_ddc.analog_reg);
-       }
-
-       if (mxc_ddc.init)
-               mxc_ddc.init();
-
-       if (mxc_ddc.update()) {
-               mxc_ddc.cable_plugin = 1;
-               /* try to read edid */
-               if (mxc_edid_read(client->adapter, client->addr,
-                                       mxc_ddc.edid, &mxc_ddc.edid_cfg, &edid_fbi) < 0)
-                       dev_warn(&client->dev, "Can not read edid\n");
-#if defined(CONFIG_MXC_IPU_V3) && defined(CONFIG_FB_MXC_SYNC_PANEL)
-               else
-                       mxcfb_register_mode(mxc_ddc.di, edid_fbi.monspecs.modedb,
-                                       edid_fbi.monspecs.modedb_len, MXC_DISP_DDC_DEV);
-#endif
-       } else
-               mxc_ddc.cable_plugin = 0;
-
-       if (client->irq) {
-               ret = request_irq(client->irq, mxc_ddc_detect_handler,
-                               IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-                               "ddc_det", &mxc_ddc);
-               if (ret < 0) {
-                       dev_warn(&client->dev,
-                               "MXC ddc: cound not request det irq %d\n",
-                               client->irq);
-                       goto err;
-               } else {
-                       INIT_DELAYED_WORK(&(mxc_ddc.det_work), det_worker);
-                       ret = device_create_file(&mxc_ddc.pdev->dev, &dev_attr_fb_name);
-                       if (ret < 0)
-                               dev_warn(&client->dev,
-                                       "MXC ddc: cound not create sys node for fb name\n");
-                       ret = device_create_file(&mxc_ddc.pdev->dev, &dev_attr_cable_state);
-                       if (ret < 0)
-                               dev_warn(&client->dev,
-                                       "MXC ddc: cound not create sys node for cable state\n");
-                       ret = device_create_file(&mxc_ddc.pdev->dev, &dev_attr_edid);
-                       if (ret < 0)
-                               dev_warn(&client->dev,
-                                       "MXC ddc: cound not create sys node for edid\n");
-               }
-       }
-
-       fb_register_client(&nb);
-
-err:
-       return ret;
-}
-
-static int __devexit mxc_ddc_remove(struct i2c_client *client)
-{
-       fb_unregister_client(&nb);
-       if (!IS_ERR(mxc_ddc.analog_reg))
-               regulator_disable(mxc_ddc.analog_reg);
-       return 0;
-}
-
-static int __init enable_ddc_setup(char *options)
-{
-       if (!strcmp(options, "=off"))
-               g_enable_ddc = MXC_DISABLE;
-       else
-               g_enable_ddc = MXC_ENABLE;
-
-       return 1;
-}
-__setup("ddc", enable_ddc_setup);
-
-static const struct i2c_device_id mxc_ddc_id[] = {
-       { "mxc_ddc", 0 },
-       {},
-};
-MODULE_DEVICE_TABLE(i2c, mxc_ddc_id);
-
-static struct i2c_driver mxc_ddc_i2c_driver = {
-       .driver = {
-                  .name = "mxc_ddc",
-                  },
-       .probe = mxc_ddc_probe,
-       .remove = mxc_ddc_remove,
-       .id_table = mxc_ddc_id,
-};
-
-static int __init mxc_ddc_init(void)
-{
-       int ret;
-
-       memset(&mxc_ddc, 0, sizeof(mxc_ddc));
-
-       mxc_ddc.pdev = platform_device_register_simple("mxc_ddc", 0, NULL, 0);
-       if (IS_ERR(mxc_ddc.pdev)) {
-               printk(KERN_ERR
-                               "Unable to register MXC DDC as a platform device\n");
-               ret = PTR_ERR(mxc_ddc.pdev);
-               goto err;
-       }
-
-       return i2c_add_driver(&mxc_ddc_i2c_driver);
-err:
-       return ret;
-}
-
-static void __exit mxc_ddc_exit(void)
-{
-       i2c_del_driver(&mxc_ddc_i2c_driver);
-       platform_device_unregister(mxc_ddc.pdev);
-}
-
-module_init(mxc_ddc_init);
-module_exit(mxc_ddc_exit);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc.");
-MODULE_DESCRIPTION("MXC DDC driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/mxc/mxc_dvi.c b/drivers/video/mxc/mxc_dvi.c
new file mode 100644 (file)
index 0000000..a392cb9
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*!
+ * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
+ */
+
+/*!
+ * @file mxc_dvi.c
+ *
+ * @brief MXC DVI driver
+ *
+ * @ingroup Framebuffer
+ */
+
+/*!
+ * Include files
+ */
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/fsl_devices.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/regulator/consumer.h>
+#include <mach/mxc_edid.h>
+#include "mxc_dispdrv.h"
+#include "../edid.h"
+
+#define MXC_EDID_LENGTH (EDID_LENGTH*4)
+
+#define DISPDRV_DVI    "dvi"
+
+struct mxc_dvi_data {
+       struct i2c_client *client;
+       struct platform_device *pdev;
+       struct mxc_dispdrv_entry *disp_dvi;
+       struct delayed_work det_work;
+       struct fb_info *fbi;
+       struct mxc_edid_cfg edid_cfg;
+       u8 cable_plugin;
+       u8 edid[MXC_EDID_LENGTH];
+
+       u32 ipu;
+       u32 di;
+       void (*init)(void);
+       int (*update)(void);
+       struct regulator *analog_reg;
+};
+
+static ssize_t mxc_dvi_show_state(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct mxc_dvi_data *dvi = dev_get_drvdata(dev);
+
+       if (dvi->cable_plugin == 0)
+               strcpy(buf, "plugout\n");
+       else
+               strcpy(buf, "plugin\n");
+
+       return strlen(buf);
+}
+
+static DEVICE_ATTR(cable_state, S_IRUGO, mxc_dvi_show_state, NULL);
+
+static ssize_t mxc_dvi_show_name(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct mxc_dvi_data *dvi = dev_get_drvdata(dev);
+
+       strcpy(buf, dvi->fbi->fix.id);
+       sprintf(buf+strlen(buf), "\n");
+
+       return strlen(buf);
+}
+
+static DEVICE_ATTR(fb_name, S_IRUGO, mxc_dvi_show_name, NULL);
+
+static ssize_t mxc_dvi_show_edid(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct mxc_dvi_data *dvi = dev_get_drvdata(dev);
+       int i, j, len = 0;
+
+       for (j = 0; j < MXC_EDID_LENGTH/16; j++) {
+               for (i = 0; i < 16; i++)
+                       len += sprintf(buf+len, "0x%02X ",
+                                       dvi->edid[j*16 + i]);
+               len += sprintf(buf+len, "\n");
+       }
+
+       return len;
+}
+
+static DEVICE_ATTR(edid, S_IRUGO, mxc_dvi_show_edid, NULL);
+
+static void det_worker(struct work_struct *work)
+{
+       struct delayed_work *delay_work = to_delayed_work(work);
+       struct mxc_dvi_data *dvi =
+               container_of(delay_work, struct mxc_dvi_data, det_work);
+       char event_string[16];
+       char *envp[] = { event_string, NULL };
+
+       /* cable connection changes */
+       if (dvi->update()) {
+               u8 edid_old[MXC_EDID_LENGTH];
+               dvi->cable_plugin = 1;
+               sprintf(event_string, "EVENT=plugin");
+
+               memcpy(edid_old, dvi->edid, MXC_EDID_LENGTH);
+
+               if (mxc_edid_read(dvi->client->adapter, dvi->client->addr,
+                               dvi->edid, &dvi->edid_cfg, dvi->fbi) < 0)
+                       dev_err(&dvi->client->dev,
+                                       "MXC dvi: read edid fail\n");
+               else {
+                       if (!memcmp(edid_old, dvi->edid, MXC_EDID_LENGTH))
+                               dev_info(&dvi->client->dev,
+                                       "Sii902x: same edid\n");
+                       else if (dvi->fbi->monspecs.modedb_len > 0) {
+                               int i;
+                               const struct fb_videomode *mode;
+                               struct fb_videomode m;
+
+                               fb_destroy_modelist(&dvi->fbi->modelist);
+
+                               for (i = 0; i < dvi->fbi->monspecs.modedb_len; i++)
+                                       /*FIXME now we do not support interlaced mode */
+                                       if (!(dvi->fbi->monspecs.modedb[i].vmode & FB_VMODE_INTERLACED))
+                                               fb_add_videomode(&dvi->fbi->monspecs.modedb[i],
+                                                               &dvi->fbi->modelist);
+
+                               fb_var_to_videomode(&m, &dvi->fbi->var);
+                               mode = fb_find_nearest_mode(&m,
+                                               &dvi->fbi->modelist);
+
+                               fb_videomode_to_var(&dvi->fbi->var, mode);
+
+                               dvi->fbi->var.activate |= FB_ACTIVATE_FORCE;
+                               console_lock();
+                               dvi->fbi->flags |= FBINFO_MISC_USEREVENT;
+                               fb_set_var(dvi->fbi, &dvi->fbi->var);
+                               dvi->fbi->flags &= ~FBINFO_MISC_USEREVENT;
+                               console_unlock();
+                       }
+               }
+       } else {
+               dvi->cable_plugin = 0;
+               sprintf(event_string, "EVENT=plugout");
+       }
+
+       kobject_uevent_env(&dvi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+}
+
+static irqreturn_t mxc_dvi_detect_handler(int irq, void *data)
+{
+       struct mxc_dvi_data *dvi = data;
+       schedule_delayed_work(&(dvi->det_work), msecs_to_jiffies(300));
+       return IRQ_HANDLED;
+}
+
+static int dvi_init(struct mxc_dispdrv_entry *disp)
+{
+       int ret = 0;
+       struct mxc_dvi_data *dvi = mxc_dispdrv_getdata(disp);
+       struct mxc_dispdrv_setting *setting = mxc_dispdrv_getsetting(disp);
+       struct fsl_mxc_dvi_platform_data *plat = dvi->client->dev.platform_data;
+
+       setting->dev_id = dvi->ipu = plat->ipu_id;
+       setting->disp_id = dvi->di = plat->disp_id;
+       setting->if_fmt = IPU_PIX_FMT_RGB24;
+       dvi->fbi = setting->fbi;
+       dvi->init = plat->init;
+       dvi->update = plat->update;
+
+       dvi->analog_reg = regulator_get(&dvi->pdev->dev, plat->analog_regulator);
+       if (!IS_ERR(dvi->analog_reg)) {
+               regulator_set_voltage(dvi->analog_reg, 2775000, 2775000);
+               regulator_enable(dvi->analog_reg);
+       }
+
+       if (dvi->init)
+               dvi->init();
+
+       /* get video mode from edid */
+       if (!dvi->update)
+               return -EINVAL;
+       else {
+               bool found = false;
+
+               INIT_LIST_HEAD(&dvi->fbi->modelist);
+               if (dvi->update()) {
+                       dvi->cable_plugin = 1;
+                       /* try to read edid */
+                       if (mxc_edid_read(dvi->client->adapter, dvi->client->addr,
+                                       dvi->edid, &dvi->edid_cfg, dvi->fbi) < 0)
+                               dev_warn(&dvi->client->dev, "Can not read edid\n");
+                       else if (dvi->fbi->monspecs.modedb_len > 0) {
+                               int i;
+                               const struct fb_videomode *mode;
+                               struct fb_videomode m;
+
+                               for (i = 0; i < dvi->fbi->monspecs.modedb_len; i++) {
+                                       /*FIXME now we do not support interlaced mode */
+                                       if (!(dvi->fbi->monspecs.modedb[i].vmode
+                                               & FB_VMODE_INTERLACED))
+                                               fb_add_videomode(
+                                                       &dvi->fbi->monspecs.modedb[i],
+                                                       &dvi->fbi->modelist);
+                               }
+
+                               fb_find_mode(&dvi->fbi->var, dvi->fbi, setting->dft_mode_str,
+                                               NULL, 0, NULL, setting->default_bpp);
+
+                               fb_var_to_videomode(&m, &dvi->fbi->var);
+                               mode = fb_find_nearest_mode(&m,
+                                               &dvi->fbi->modelist);
+                               fb_videomode_to_var(&dvi->fbi->var, mode);
+                               found = 1;
+                       }
+               } else
+                       dvi->cable_plugin = 0;
+
+               if (!found) {
+                       ret = fb_find_mode(&dvi->fbi->var, dvi->fbi, setting->dft_mode_str,
+                                       NULL, 0, NULL, setting->default_bpp);
+                       if (!ret)
+                               return -EINVAL;
+               }
+       }
+
+       /* cable detection */
+       if (dvi->client->irq) {
+               ret = request_irq(dvi->client->irq, mxc_dvi_detect_handler,
+                               IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+                               "dvi_det", dvi);
+               if (ret < 0) {
+                       dev_warn(&dvi->client->dev,
+                               "MXC dvi: cound not request det irq %d\n",
+                               dvi->client->irq);
+                       goto err;
+               } else {
+                       INIT_DELAYED_WORK(&(dvi->det_work), det_worker);
+                       ret = device_create_file(&dvi->pdev->dev, &dev_attr_fb_name);
+                       if (ret < 0)
+                               dev_warn(&dvi->client->dev,
+                                       "MXC dvi: cound not create sys node for fb name\n");
+                       ret = device_create_file(&dvi->pdev->dev, &dev_attr_cable_state);
+                       if (ret < 0)
+                               dev_warn(&dvi->client->dev,
+                                       "MXC dvi: cound not create sys node for cable state\n");
+                       ret = device_create_file(&dvi->pdev->dev, &dev_attr_edid);
+                       if (ret < 0)
+                               dev_warn(&dvi->client->dev,
+                                       "MXC dvi: cound not create sys node for edid\n");
+
+                       dev_set_drvdata(&dvi->pdev->dev, dvi);
+               }
+       }
+
+err:
+       return ret;
+}
+
+static void dvi_deinit(struct mxc_dispdrv_entry *disp)
+{
+       struct mxc_dvi_data *dvi = mxc_dispdrv_getdata(disp);
+
+       if (!IS_ERR(dvi->analog_reg))
+               regulator_disable(dvi->analog_reg);
+
+       free_irq(dvi->client->irq, dvi);
+}
+
+static struct mxc_dispdrv_driver dvi_drv = {
+       .name   = DISPDRV_DVI,
+       .init   = dvi_init,
+       .deinit = dvi_deinit,
+};
+
+static int __devinit mxc_dvi_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       struct mxc_dvi_data *dvi;
+       int ret = 0;
+
+       if (!i2c_check_functionality(client->adapter,
+                               I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+               return -ENODEV;
+
+       dvi = kzalloc(sizeof(struct mxc_dvi_data), GFP_KERNEL);
+       if (!dvi) {
+               ret = -ENOMEM;
+               goto alloc_failed;
+       }
+
+       dvi->pdev = platform_device_register_simple("mxc_dvi", 0, NULL, 0);
+       if (IS_ERR(dvi->pdev)) {
+               printk(KERN_ERR
+                               "Unable to register MXC DVI as a platform device\n");
+               ret = PTR_ERR(dvi->pdev);
+               goto pdev_reg_failed;
+       }
+
+       dvi->client = client;
+       dvi->disp_dvi = mxc_dispdrv_register(&dvi_drv);
+       mxc_dispdrv_setdata(dvi->disp_dvi, dvi);
+
+       i2c_set_clientdata(client, dvi);
+
+       return ret;
+
+pdev_reg_failed:
+       kfree(dvi);
+alloc_failed:
+       return ret;
+}
+
+static int __devexit mxc_dvi_remove(struct i2c_client *client)
+{
+       struct mxc_dvi_data *dvi = i2c_get_clientdata(client);
+
+       mxc_dispdrv_unregister(dvi->disp_dvi);
+       platform_device_unregister(dvi->pdev);
+       kfree(dvi);
+       return 0;
+}
+
+static const struct i2c_device_id mxc_dvi_id[] = {
+       { "mxc_dvi", 0 },
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, mxc_dvi_id);
+
+static struct i2c_driver mxc_dvi_i2c_driver = {
+       .driver = {
+                  .name = "mxc_dvi",
+                  },
+       .probe = mxc_dvi_probe,
+       .remove = mxc_dvi_remove,
+       .id_table = mxc_dvi_id,
+};
+
+static int __init mxc_dvi_init(void)
+{
+       return i2c_add_driver(&mxc_dvi_i2c_driver);
+}
+
+static void __exit mxc_dvi_exit(void)
+{
+       i2c_del_driver(&mxc_dvi_i2c_driver);
+}
+
+module_init(mxc_dvi_init);
+module_exit(mxc_dvi_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC DVI driver");
+MODULE_LICENSE("GPL");
index dae7b4f6c9cdd55b0c201fa00d77dc29b9b7e4e5..4229df771d00759f9ad42127ec8c1176a24d6867 100644 (file)
@@ -39,7 +39,7 @@
 #define DPRINTK(fmt, args...)
 #endif
 
-const struct fb_videomode cea_modes[64] = {
+const struct fb_videomode mxc_cea_mode[64] = {
        /* #1: 640x480p@59.94/60Hz */
        [1] = {
                NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
@@ -203,10 +203,10 @@ int mxc_edid_parse_ext_blk(unsigned char *edid,
                        while (i < blklen) {
                                index++;
                                cea_idx = edid[index] & 0x7f;
-                               if (cea_idx < ARRAY_SIZE(cea_modes) &&
-                                       (cea_modes[cea_idx].xres)) {
+                               if (cea_idx < ARRAY_SIZE(mxc_cea_mode) &&
+                                       (mxc_cea_mode[cea_idx].xres)) {
                                        DPRINTK("Support CEA Format #%d\n", cea_idx);
-                                       mode[num] = cea_modes[cea_idx];
+                                       mode[num] = mxc_cea_mode[cea_idx];
                                        mode[num].flag |= FB_MODE_IS_STANDARD;
                                        num++;
                                }
@@ -392,13 +392,13 @@ int mxc_edid_var_to_vic(struct fb_var_screeninfo *var)
        int i;
        struct fb_videomode m;
 
-       for (i = 0; i < ARRAY_SIZE(cea_modes); i++) {
+       for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
                fb_var_to_videomode(&m, var);
-               if (fb_mode_is_equal(&m, &cea_modes[i]))
+               if (fb_mode_is_equal(&m, &mxc_cea_mode[i]))
                        break;
        }
 
-       if (i == ARRAY_SIZE(cea_modes))
+       if (i == ARRAY_SIZE(mxc_cea_mode))
                return 0;
 
        return i;