]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00154436-2 - MXC HDMI: Support complete feature set
authorDanny Nold <dannynold@freescale.com>
Fri, 2 Sep 2011 03:46:05 +0000 (22:46 -0500)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:33:11 +0000 (08:33 +0200)
- Cleaned up video mode configuration in HDMI driver
- Add support for configurable ipu-to-hdmi mappings
- Add hotplug support.
- Adapt interrupt handling to account for sharing interrupt with HDMI audio
- Remove audio configuration
- Change code to only use CEA HDMI modes
- Add support for AVI InfoFrame
- Add aspect ratio to EDID mode data
- Add rounding support to IPU pix clk setup
- Add powerdown/powerup flow
- Support FB notifications
- Remove build warnings

Signed-off-by: Danny Nold <dannynold@freescale.com>
drivers/mxc/ipu3/ipu_common.c
drivers/video/mxc/mxc_edid.c
drivers/video/mxc_hdmi.c
include/linux/fsl_devices.h

index 11e8a580cdc2a72145dc0b3212d7079d5ef10e02..5cb9dc0b474e9f4c9237775ef02a1820967e4499 100644 (file)
@@ -149,7 +149,7 @@ static unsigned long _ipu_pixel_clk_get_rate(struct clk *clk)
 
 static unsigned long _ipu_pixel_clk_round_rate(struct clk *clk, unsigned long rate)
 {
-       u32 div, div1;
+       u32 div;
        u32 parent_rate = clk_get_rate(clk->parent) * 16;
        /*
         * Calculate divider
@@ -163,11 +163,11 @@ static unsigned long _ipu_pixel_clk_round_rate(struct clk *clk, unsigned long ra
        if (div & ~0xFEF)
                div &= 0xFF8;
        else {
-               div1 = div & 0xFE0;
-               if ((parent_rate / div1 - parent_rate / div) < rate / 4)
-                       div = div1;
-               else
-                       div &= 0xFF8;
+               /* Round up divider if it gets us closer to desired pix clk */
+               if ((div & 0xC) == 0xC) {
+                       div += 0x10;
+                       div &= ~0xF;
+               }
        }
        return parent_rate / div;
 }
@@ -178,6 +178,12 @@ static int _ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate)
        u32 div = (clk_get_rate(clk->parent) * 16) / rate;
        unsigned long lock_flags;
 
+       /* Round up divider if it gets us closer to desired pix clk */
+       if ((div & 0xC) == 0xC) {
+               div += 0x10;
+               div &= ~0xF;
+       }
+
        spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
        ipu_di_write(ipu, clk->id, div, DI_BS_CLKGEN0);
 
index 9c4f094ea166e70c56ae1edea22a69b078e572f5..9e7c87ef43ccaa02de881bafbf4aba85b077d761 100644 (file)
 #endif
 
 const struct fb_videomode mxc_cea_mode[64] = {
-       /* #1: 640x480p@59.94/60Hz */
+       /* #1: 640x480p@59.94/60Hz 4:3 */
        [1] = {
                NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_4_3,
        },
-       /* #3: 720x480p@59.94/60Hz */
+       /* #2: 720x480p@59.94/60Hz 4:3 */
+       [2] = {
+               NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_4_3,
+       },
+       /* #3: 720x480p@59.94/60Hz 16:9 */
        [3] = {
                NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
        },
-       /* #4: 1280x720p@59.94/60Hz */
+       /* #4: 1280x720p@59.94/60Hz 16:9 */
        [4] = {
                NULL, 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5,
                FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
        },
-       /* #5: 1920x1080i@59.94/60Hz */
+       /* #5: 1920x1080i@59.94/60Hz 16:9 */
        [5] = {
                NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
                FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_INTERLACED, 0,
+               FB_VMODE_INTERLACED, FB_MODE_ASPECT_16_9,
+       },
+       /* #6: 720(1440)x480iH@59.94/60Hz 4:3 */
+       [6] = {
+               NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
+               FB_VMODE_INTERLACED, FB_MODE_ASPECT_4_3,
        },
-       /* #7: 720(1440)x480iH@59.94/60Hz */
+       /* #7: 720(1440)x480iH@59.94/60Hz 16:9 */
        [7] = {
                NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
-               FB_VMODE_INTERLACED, 0,
+               FB_VMODE_INTERLACED, FB_MODE_ASPECT_16_9,
        },
-       /* #9: 720(1440)x240pH@59.94/60Hz */
+       /* #8: 720(1440)x240pH@59.94/60Hz 4:3 */
+       [8] = {
+               NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
+       },
+       /* #9: 720(1440)x240pH@59.94/60Hz 16:9 */
        [9] = {
                NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
        },
-       /* #16: 1920x1080p@60Hz */
+       /* #16: 1920x1080p@60Hz 16:9 */
        [16] = {
                NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
                FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
+       },
+       /* #17: 720x576pH@50Hz 4:3 */
+       [17] = {
+               NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_4_3,
        },
-       /* #18: 720x576pH@50Hz */
+       /* #18: 720x576pH@50Hz 16:9 */
        [18] = {
                NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
        },
        /* #19: 1280x720p@50Hz */
        [19] = {
                NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
                FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
        },
        /* #20: 1920x1080i@50Hz */
        [20] = {
                NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
                FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_INTERLACED, 0,
+               FB_VMODE_INTERLACED, FB_MODE_ASPECT_16_9,
        },
        /* #31: 1920x1080p@50Hz */
        [31] = {
                NULL, 50, 1920, 1080, 6734, 148, 528, 36, 4, 44, 5,
                FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
        },
        /* #32: 1920x1080p@23.98/24Hz */
        [32] = {
                NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
                FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_16_9,
        },
        /* #35: (2880)x480p4x@59.94/60Hz */
        [35] = {
                NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0,
-               FB_VMODE_NONINTERLACED, 0,
+               FB_VMODE_NONINTERLACED, FB_MODE_ASPECT_4_3,
        },
 };
 
+/*
+ * We have a special version of fb_mode_is_equal that ignores
+ * pixclock, since for many CEA modes, 2 frequencies are supported
+ * e.g. 640x480 @ 60Hz or 59.94Hz
+ */
+int mxc_edid_fb_mode_is_equal(const struct fb_videomode *mode1,
+                    const struct fb_videomode *mode2)
+{
+       return (mode1->xres         == mode2->xres &&
+               mode1->yres         == mode2->yres &&
+               mode1->hsync_len    == mode2->hsync_len &&
+               mode1->vsync_len    == mode2->vsync_len &&
+               mode1->left_margin  == mode2->left_margin &&
+               mode1->right_margin == mode2->right_margin &&
+               mode1->upper_margin == mode2->upper_margin &&
+               mode1->lower_margin == mode2->lower_margin &&
+               mode1->sync         == mode2->sync &&
+               mode1->vmode        == mode2->vmode);
+}
+
 static void get_detailed_timing(unsigned char *block,
                                struct fb_videomode *mode)
 {
@@ -398,7 +438,7 @@ int mxc_edid_var_to_vic(struct fb_var_screeninfo *var)
 
        for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
                fb_var_to_videomode(&m, var);
-               if (fb_mode_is_equal(&m, &mxc_cea_mode[i]))
+               if (mxc_edid_fb_mode_is_equal(&m, &mxc_cea_mode[i]))
                        break;
        }
 
@@ -407,8 +447,32 @@ int mxc_edid_var_to_vic(struct fb_var_screeninfo *var)
 
        return i;
 }
+
 EXPORT_SYMBOL(mxc_edid_var_to_vic);
 
+int mxc_edid_mode_to_vic(const struct fb_videomode *mode)
+{
+       int i;
+       u32 aspect_flags = FB_MODE_ASPECT_16_9 | FB_MODE_ASPECT_4_3;
+
+       for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
+               if (mxc_edid_fb_mode_is_equal(mode, &mxc_cea_mode[i])) {
+                       if (mode->flag & FB_MODE_IS_STANDARD) {
+                               if ((mode->flag & aspect_flags) ==
+                                       mxc_cea_mode[i].flag)
+                                       break;
+                       } else
+                               break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(mxc_cea_mode))
+               return 0;
+
+       return i;
+}
+EXPORT_SYMBOL(mxc_edid_mode_to_vic);
+
 /* make sure edid has 512 bytes*/
 int mxc_edid_read(struct i2c_adapter *adp, unsigned short addr,
        unsigned char *edid, struct mxc_edid_cfg *cfg, struct fb_info *fbi)
index 383e738224e6a189183c926e81bdb8935da903d7..7690151e9d1ac252c2b7b13460adae64042028f1 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
@@ -56,6 +55,7 @@
 #include <mach/mxc_edid.h>
 #include "mxc/mxc_dispdrv.h"
 
+#include <linux/mfd/mxc-hdmi-core.h>
 #include <mach/mxc_hdmi.h>
 
 #define DISPDRV_HDMI   "hdmi"
 #define NUM_CEA_VIDEO_MODES    64
 #define DEFAULT_VIDEO_MODE     16 /* 1080P */
 
-/* VIC = Video ID Code */
-static struct fb_videomode hdmi_cea_video_modes[NUM_CEA_VIDEO_MODES] = {
-       { /* 1 */
-               .xres = 640,
-               .yres = 480,
-               .refresh = 60,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 60,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 60,
-       },
-       {
-               .xres = 1280,
-               .yres = 720,
-               .refresh = 60,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 60,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 60,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 60,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 240,
-               .refresh = 60,
-       },
-       {
-               .xres = 720,
-               .yres = 240,
-               .refresh = 60,
-       },
-       { /* 10 */
-               .xres = 2880,
-               .yres = 480,
-               .refresh = 60,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 2880,
-               .yres = 480,
-               .refresh = 60,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 2880,
-               .yres = 240,
-               .refresh = 60,
-       },
-       {
-               .xres = 2880,
-               .yres = 240,
-               .refresh = 60,
-       },
-       {
-               .xres = 1440,
-               .yres = 480,
-               .refresh = 60,
-       },
-       {
-               .xres = 1440,
-               .yres = 480,
-               .refresh = 60,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 60,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 50,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 50,
-       },
-       {
-               .xres = 1280,
-               .yres = 720,
-               .refresh = 50,
-       },
-       { /* 20 */
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 50,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 50,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 50,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 288,
-               .refresh = 50,
-       },
-       {
-               .xres = 720,
-               .yres = 288,
-               .refresh = 50,
-       },
-       {
-               .xres = 2880,
-               .yres = 576,
-               .refresh = 50,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 2880,
-               .yres = 576,
-               .refresh = 50,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 2880,
-               .yres = 288,
-               .refresh = 50,
-       },
-       {
-               .xres = 2880,
-               .yres = 288,
-               .refresh = 50,
-       },
-       {
-               .xres = 1440,
-               .yres = 576,
-               .refresh = 50,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       { /* 30 */
-               .xres = 1440,
-               .yres = 576,
-               .refresh = 50,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 50,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 24,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 25,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 30,
-       },
-       {
-               .xres = 2880,
-               .yres = 480,
-               .refresh = 60,
-       },
-       {
-               .xres = 2880,
-               .yres = 480,
-               .refresh = 60,
-       },
-       {
-               .xres = 2880,
-               .yres = 576,
-               .refresh = 50,
-       },
-       {
-               .xres = 2880,
-               .yres = 576,
-               .refresh = 50,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 50,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       { /* 40 */
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 100,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 1280,
-               .yres = 720,
-               .refresh = 100,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 100,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 100,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 100,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 100,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 120,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 1280,
-               .yres = 720,
-               .refresh = 120,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 120,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 120,
-       },
-       { /* 50 */
-               .xres = 720,
-               .yres = 480,
-               .refresh = 120,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 120,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 200,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 200,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 200,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 576,
-               .refresh = 200,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 240,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 240,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 240,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       {
-               .xres = 720,
-               .yres = 480,
-               .refresh = 240,
-               .flag = FB_VMODE_INTERLACED,
-       },
-       { /* 60 */
-               .xres = 1280,
-               .yres = 720,
-               .refresh = 24,
-       },
-       {
-               .xres = 1280,
-               .yres = 720,
-               .refresh = 25,
-       },
-       {
-               .xres = 1280,
-               .yres = 720,
-               .refresh = 30,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 120,
-       },
-       {
-               .xres = 1920,
-               .yres = 1080,
-               .refresh = 100,
-       },
-};
+#define HDMI_IH_PHY_RX_SENSE   (HDMI_IH_PHY_STAT0_RX_SENSE0 |\
+                               HDMI_IH_PHY_STAT0_RX_SENSE1 |\
+                               HDMI_IH_PHY_STAT0_RX_SENSE2 |\
+                               HDMI_IH_PHY_STAT0_RX_SENSE3)
+#define HDMI_PHY_RX_SENSE      (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 |\
+                               HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
+
+#define RGB                    0
+#define YCBCR444               1
+#define YCBCR422_16BITS                2
+#define YCBCR422_8BITS         3
+#define XVYCC444               4
 
 enum hdmi_datamap {
        RGB444_8B = 0x01,
@@ -441,28 +107,14 @@ enum hdmi_colorimetry {
 };
 
 struct hdmi_vmode {
-       unsigned int mCode;
        unsigned int mHdmiDviSel;
-       unsigned int mRVBlankInOSC;
-       unsigned int mRefreshRate;
-       unsigned int mHImageSize;
-       unsigned int mVImageSize;
-       unsigned int mHActive;
-       unsigned int mVActive;
-       unsigned int mHBlanking;
-       unsigned int mVBlanking;
-       unsigned int mHSyncOffset;
-       unsigned int mVSyncOffset;
-       unsigned int mHSyncPulseWidth;
-       unsigned int mVSyncPulseWidth;
        unsigned int mHSyncPolarity;
        unsigned int mVSyncPolarity;
-       unsigned int mDataEnablePolarity;
        unsigned int mInterlaced;
+       unsigned int mDataEnablePolarity;
        unsigned int mPixelClock;
-       unsigned int mHBorder;
-       unsigned int mVBorder;
        unsigned int mPixelRepetitionInput;
+       unsigned int mPixelRepetitionOutput;
 };
 
 struct hdmi_data_info {
@@ -475,647 +127,27 @@ struct hdmi_data_info {
        struct hdmi_vmode video_mode;
 };
 
-enum hotplug_state {
-       HDMI_HOTPLUG_DISCONNECTED,
-       HDMI_HOTPLUG_CONNECTED,
-       HDMI_HOTPLUG_EDID_DONE,
-};
-
 struct mxc_hdmi {
-       void __iomem *base;
-       enum hotplug_state hp_state;    /* hot-plug status */
-
-       struct regulator *io_reg;
-       struct regulator *analog_reg;
+       struct platform_device *pdev;
+       struct platform_device *core_pdev;
        struct mxc_dispdrv_entry *disp_mxc_hdmi;
-       struct hdmi_data_info hdmi_data;
+       struct fb_info *fbi;
        struct clk *hdmi_clk;
+       struct delayed_work det_work;
+       struct notifier_block nb;
 
+       struct hdmi_data_info hdmi_data;
+       int vic;
        struct mxc_edid_cfg edid_cfg;
        u8 edid[HDMI_EDID_LEN];
-
-       struct platform_device *pdev;
-       struct fb_info *fbi;
-       struct mutex mutex;             /* Protect the info pointer */
-       struct delayed_work edid_work;
-       struct fb_var_screeninfo var;
-       struct fb_monspecs monspec;
-       struct notifier_block nb;
+       bool fb_reg;
+       bool need_mode_change;
+       bool cable_plugin;
+       u8 latest_intr_stat;
 };
 
 struct i2c_client *hdmi_i2c;
 
-static irqreturn_t mxc_hdmi_hotplug(int irq, void *dev_id)
-{
-}
-
-/*!
- * this submodule is responsible for the video/audio data composition.
- */
-void hdmi_set_video_mode(struct hdmi_vmode *vmode)
-{
-       vmode->mHBorder = 0;
-       vmode->mVBorder = 0;
-       vmode->mPixelRepetitionInput = 0;
-       vmode->mHImageSize = 16;
-       vmode->mVImageSize = 9;
-
-       switch (vmode->mCode) {
-       case 1:                         /* 640x480p @ 59.94/60Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-               vmode->mHActive = 640;
-               vmode->mVActive = 480;
-               vmode->mHBlanking = 160;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 16;
-               vmode->mVSyncOffset = 10;
-               vmode->mHSyncPulseWidth = 96;
-               vmode->mVSyncPulseWidth = 2;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE; /* not(progressive_nI) */
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 59940) ? 2517 : 2520;
-               break;
-       case 2:                         /* 720x480p @ 59.94/60Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 3:                         /* 720x480p @ 59.94/60Hz 16:9 */
-               vmode->mHActive = 720;
-               vmode->mVActive = 480;
-               vmode->mHBlanking = 138;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 16;
-               vmode->mVSyncOffset = 9;
-               vmode->mHSyncPulseWidth = 62;
-               vmode->mVSyncPulseWidth = 6;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 59940) ? 2700 : 2702;
-               break;
-       case 4:                         /* 1280x720p @ 59.94/60Hz 16:9 */
-               vmode->mHActive = 1280;
-               vmode->mVActive = 720;
-               vmode->mHBlanking = 370;
-               vmode->mVBlanking = 30;
-               vmode->mHSyncOffset = 110;
-               vmode->mVSyncOffset = 5;
-               vmode->mHSyncPulseWidth = 40;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 59940) ? 7417 : 7425;
-               break;
-       case 5:                         /* 1920x1080i @ 59.94/60Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 540;
-               vmode->mHBlanking = 280;
-               vmode->mVBlanking = 22;
-               vmode->mHSyncOffset = 88;
-               vmode->mVSyncOffset = 2;
-               vmode->mHSyncPulseWidth = 44;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 59940) ? 7417 : 7425;
-               break;
-       case 6:                         /* 720(1440)x480i @ 59.94/60Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 7:                         /* 720(1440)x480i @ 59.94/60Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 240;
-               vmode->mHBlanking = 276;
-               vmode->mVBlanking = 22;
-               vmode->mHSyncOffset = 38;
-               vmode->mVSyncOffset = 4;
-               vmode->mHSyncPulseWidth = 124;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 59940) ? 2700 : 2702;
-               vmode->mPixelRepetitionInput = 1;
-               break;
-       case 8: /* 720(1440)x240p @ 59.826/60.054/59.886/60.115Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 9: /* 720(1440)x240p @ 59.826/60.054/59.886/60.115Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 240;
-               vmode->mHBlanking = 276;
-               vmode->mVBlanking = (vmode->mRefreshRate > 60000) ? 22 : 23;
-               vmode->mHSyncOffset = 38;
-               vmode->mVSyncOffset = (vmode->mRefreshRate > 60000) ? 4 : 5;
-               vmode->mHSyncPulseWidth = 124;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       ((vmode->mRefreshRate == 60054) ||
-                       vmode->mRefreshRate == 59826)
-                       ? 2700 : 2702; /*  else 60.115/59.886 Hz */
-               vmode->mPixelRepetitionInput = 1;
-               break;
-       case 10:                        /* 2880x480i @ 59.94/60Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 11:                        /* 2880x480i @ 59.94/60Hz 16:9 */
-               vmode->mHActive = 2880;
-               vmode->mVActive = 240;
-               vmode->mHBlanking = 552;
-               vmode->mVBlanking = 22;
-               vmode->mHSyncOffset = 76;
-               vmode->mVSyncOffset = 4;
-               vmode->mHSyncPulseWidth = 248;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 59940) ? 5400 : 5405;
-               break;
-       case 12:        /* 2880x240p @ 59.826/60.054/59.886/60.115Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 13:        /* 2880x240p @ 59.826/60.054/59.886/60.115Hz 16:9 */
-               vmode->mHActive = 2880;
-               vmode->mVActive = 240;
-               vmode->mHBlanking = 552;
-               vmode->mVBlanking = (vmode->mRefreshRate > 60000) ? 22 : 23;
-               vmode->mHSyncOffset = 76;
-               vmode->mVSyncOffset = (vmode->mRefreshRate > 60000) ? 4 : 5;
-               vmode->mHSyncPulseWidth = 248;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       ((vmode->mRefreshRate == 60054) ||
-                       vmode->mRefreshRate == 59826)
-                       ? 5400 : 5405; /*  else 60.115/59.886 Hz */
-               break;
-       case 14:                        /* 1440x480p @ 59.94/60Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 15:                        /* 1440x480p @ 59.94/60Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 480;
-               vmode->mHBlanking = 276;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 32;
-               vmode->mVSyncOffset = 9;
-               vmode->mHSyncPulseWidth = 124;
-               vmode->mVSyncPulseWidth = 6;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 59940) ? 5400 : 5405;
-               break;
-       case 16:                        /* 1920x1080p @ 59.94/60Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 1080;
-               vmode->mHBlanking = 280;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 88;
-               vmode->mVSyncOffset = 4;
-               vmode->mHSyncPulseWidth = 44;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 59940) ? 14835 : 14850;
-               break;
-       case 17:                        /* 720x576p @ 50Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 18:                        /* 720x576p @ 50Hz 16:9 */
-               vmode->mHActive = 720;
-               vmode->mVActive = 576;
-               vmode->mHBlanking = 144;
-               vmode->mVBlanking = 49;
-               vmode->mHSyncOffset = 12;
-               vmode->mVSyncOffset = 5;
-               vmode->mHSyncPulseWidth = 64;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 2700;
-               break;
-       case 19:                        /* 1280x720p @ 50Hz 16:9 */
-               vmode->mHActive = 1280;
-               vmode->mVActive = 720;
-               vmode->mHBlanking = 700;
-               vmode->mVBlanking = 30;
-               vmode->mHSyncOffset = 440;
-               vmode->mVSyncOffset = 5;
-               vmode->mHSyncPulseWidth = 40;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 7425;
-               break;
-       case 20:                        /* 1920x1080i @ 50Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 540;
-               vmode->mHBlanking = 720;
-               vmode->mVBlanking = 22;
-               vmode->mHSyncOffset = 528;
-               vmode->mVSyncOffset = 2;
-               vmode->mHSyncPulseWidth = 44;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock = 7425;
-               break;
-       case 21:                        /* 720(1440)x576i @ 50Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 22:                        /* 720(1440)x576i @ 50Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 288;
-               vmode->mHBlanking = 288;
-               vmode->mVBlanking = 24;
-               vmode->mHSyncOffset = 24;
-               vmode->mVSyncOffset = 2;
-               vmode->mHSyncPulseWidth = 126;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock = 2700;
-               vmode->mPixelRepetitionInput = 1;
-               break;
-       case 23:                        /* 720(1440)x288p @ 50Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 24:                        /* 720(1440)x288p @ 50Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 288;
-               vmode->mHBlanking = 288;
-               vmode->mVBlanking =
-                       (vmode->mRefreshRate == 50080) ?
-                       24 : ((vmode->mRefreshRate == 49920) ? 25 : 26);
-               vmode->mHSyncOffset = 24;
-               vmode->mVSyncOffset =
-                       (vmode->mRefreshRate == 50080) ?
-                       2 : ((vmode->mRefreshRate == 49920) ? 3 : 4);
-               vmode->mHSyncPulseWidth = 126;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 2700;
-               vmode->mPixelRepetitionInput = 1;
-               break;
-       case 25:                        /* 2880x576i @ 50Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 26:                        /* 2880x576i @ 50Hz 16:9 */
-               vmode->mHActive = 2880;
-               vmode->mVActive = 288;
-               vmode->mHBlanking = 576;
-               vmode->mVBlanking = 24;
-               vmode->mHSyncOffset = 48;
-               vmode->mVSyncOffset = 2;
-               vmode->mHSyncPulseWidth = 252;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock = 5400;
-               break;
-       case 27:                        /* 2880x288p @ 50Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 28:                        /* 2880x288p @ 50Hz 16:9 */
-               vmode->mHActive = 2880;
-               vmode->mVActive = 288;
-               vmode->mHBlanking = 576;
-               vmode->mVBlanking =
-                       (vmode->mRefreshRate == 50080) ?
-                       24 : ((vmode->mRefreshRate == 49920) ? 25 : 26);
-               vmode->mHSyncOffset = 48;
-               vmode->mVSyncOffset =
-                       (vmode->mRefreshRate == 50080) ?
-                       2 : ((vmode->mRefreshRate == 49920) ? 3 : 4);
-               vmode->mHSyncPulseWidth = 252;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 5400;
-               break;
-       case 29:                        /* 1440x576p @ 50Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 30:                        /* 1440x576p @ 50Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 576;
-               vmode->mHBlanking = 288;
-               vmode->mVBlanking = 49;
-               vmode->mHSyncOffset = 24;
-               vmode->mVSyncOffset = 5;
-               vmode->mHSyncPulseWidth = 128;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 5400;
-               break;
-       case 31:                        /* 1920x1080p @ 50Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 1080;
-               vmode->mHBlanking = 720;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 528;
-               vmode->mVSyncOffset = 4;
-               vmode->mHSyncPulseWidth = 44;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 14850;
-               break;
-       case 32:                        /* 1920x1080p @ 23.976/24Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 1080;
-               vmode->mHBlanking = 830;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 638;
-               vmode->mVSyncOffset = 4;
-               vmode->mHSyncPulseWidth = 44;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 23976) ? 7417 : 7425;
-               break;
-       case 33:                        /* 1920x1080p @ 25Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 1080;
-               vmode->mHBlanking = 720;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 528;
-               vmode->mVSyncOffset = 4;
-               vmode->mHSyncPulseWidth = 44;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 7425;
-               break;
-       case 34:                        /* 1920x1080p @ 29.97/30Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 1080;
-               vmode->mHBlanking = 280;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 88;
-               vmode->mVSyncOffset = 4;
-               vmode->mHSyncPulseWidth = 44;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 29970) ? 7417 : 7425;
-               break;
-       case 35:                        /* 2880x480p @ 60Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 36:                        /* 2880x480p @ 60Hz 16:9 */
-               vmode->mHActive = 2880;
-               vmode->mVActive = 480;
-               vmode->mHBlanking = 552;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 64;
-               vmode->mVSyncOffset = 9;
-               vmode->mHSyncPulseWidth = 248;
-               vmode->mVSyncPulseWidth = 6;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 59940) ? 10800 : 10810;
-               break;
-       case 37:                        /* 2880x576p @ 50Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 38:                        /* 2880x576p @ 50Hz 16:9 */
-               vmode->mHActive = 2880;
-               vmode->mVActive = 576;
-               vmode->mHBlanking = 576;
-               vmode->mVBlanking = 49;
-               vmode->mHSyncOffset = 48;
-               vmode->mVSyncOffset = 5;
-               vmode->mHSyncPulseWidth = 256;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 10800;
-               break;
-       case 39:                /* 1920x1080i (1250 total) @ 50Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 540;
-               vmode->mHBlanking = 384;
-               vmode->mVBlanking = 85;
-               vmode->mHSyncOffset = 32;
-               vmode->mVSyncOffset = 23;
-               vmode->mHSyncPulseWidth = 168;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock = 7200;
-               break;
-       case 40:                        /* 1920x1080i @ 100Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 540;
-               vmode->mHBlanking = 720;
-               vmode->mVBlanking = 22;
-               vmode->mHSyncOffset = 528;
-               vmode->mVSyncOffset = 2;
-               vmode->mHSyncPulseWidth = 44;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock = 14850;
-               break;
-       case 41:                        /* 1280x720p @ 100Hz 16:9 */
-               vmode->mHActive = 1280;
-               vmode->mVActive = 720;
-               vmode->mHBlanking = 700;
-               vmode->mVBlanking = 30;
-               vmode->mHSyncOffset = 440;
-               vmode->mVSyncOffset = 5;
-               vmode->mHSyncPulseWidth = 40;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 14850;
-               break;
-       case 42:                        /* 720x576p @ 100Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 43:                        /* 720x576p @ 100Hz 16:9 */
-               vmode->mHActive = 720;
-               vmode->mVActive = 576;
-               vmode->mHBlanking = 144;
-               vmode->mVBlanking = 49;
-               vmode->mHSyncOffset = 12;
-               vmode->mVSyncOffset = 5;
-               vmode->mHSyncPulseWidth = 64;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 5400;
-               break;
-       case 44:                        /* 720(1440)x576i @ 100Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 45:                        /* 720(1440)x576i @ 100Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 288;
-               vmode->mHBlanking = 288;
-               vmode->mVBlanking = 24;
-               vmode->mHSyncOffset = 24;
-               vmode->mVSyncOffset = 2;
-               vmode->mHSyncPulseWidth = 126;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock = 5400;
-               vmode->mPixelRepetitionInput = 1;
-               break;
-       case 46:                        /* 1920x1080i @ 119.88/120Hz 16:9 */
-               vmode->mHActive = 1920;
-               vmode->mVActive = 540;
-               vmode->mHBlanking = 288;
-               vmode->mVBlanking = 22;
-               vmode->mHSyncOffset = 88;
-               vmode->mVSyncOffset = 2;
-               vmode->mHSyncPulseWidth = 44;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 119880) ? 14835 : 14850;
-               break;
-       case 47:                        /* 1280x720p @ 119.88/120Hz 16:9 */
-               vmode->mHActive = 1280;
-               vmode->mVActive = 720;
-               vmode->mHBlanking = 370;
-               vmode->mVBlanking = 30;
-               vmode->mHSyncOffset = 110;
-               vmode->mVSyncOffset = 5;
-               vmode->mHSyncPulseWidth = 40;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = TRUE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 119880) ? 14835 : 14850;
-               break;
-       case 48:                        /* 720x480p @ 119.88/120Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 49:                        /* 720x480p @ 119.88/120Hz 16:9 */
-               vmode->mHActive = 720;
-               vmode->mVActive = 480;
-               vmode->mHBlanking = 138;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 16;
-               vmode->mVSyncOffset = 9;
-               vmode->mHSyncPulseWidth = 62;
-               vmode->mVSyncPulseWidth = 6;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 119880) ? 5400 : 5405;
-               break;
-       case 50:                /* 720(1440)x480i @ 119.88/120Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 51:                /* 720(1440)x480i @ 119.88/120Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 240;
-               vmode->mHBlanking = 276;
-               vmode->mVBlanking = 22;
-               vmode->mHSyncOffset = 38;
-               vmode->mVSyncOffset = 4;
-               vmode->mHSyncPulseWidth = 124;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 119880) ? 5400 : 5405;
-               vmode->mPixelRepetitionInput = 1;
-               break;
-       case 52:                        /* 720X576p @ 200Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 53:                        /* 720X576p @ 200Hz 16:9 */
-               vmode->mHActive = 720;
-               vmode->mVActive = 576;
-               vmode->mHBlanking = 144;
-               vmode->mVBlanking = 49;
-               vmode->mHSyncOffset = 12;
-               vmode->mVSyncOffset = 5;
-               vmode->mHSyncPulseWidth = 64;
-               vmode->mVSyncPulseWidth = 5;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock = 10800;
-               break;
-       case 54:                        /* 720(1440)x576i @ 200Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 55:                        /* 720(1440)x576i @ 200Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 288;
-               vmode->mHBlanking = 288;
-               vmode->mVBlanking = 24;
-               vmode->mHSyncOffset = 24;
-               vmode->mVSyncOffset = 2;
-               vmode->mHSyncPulseWidth = 126;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock = 10800;
-               vmode->mPixelRepetitionInput = 1;
-               break;
-       case 56:                        /* 720x480p @ 239.76/240Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 57:                        /* 720x480p @ 239.76/240Hz 16:9 */
-               vmode->mHActive = 720;
-               vmode->mVActive = 480;
-               vmode->mHBlanking = 138;
-               vmode->mVBlanking = 45;
-               vmode->mHSyncOffset = 16;
-               vmode->mVSyncOffset = 9;
-               vmode->mHSyncPulseWidth = 62;
-               vmode->mVSyncPulseWidth = 6;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = FALSE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 239760) ? 10800 : 10810;
-               break;
-       case 58:                /* 720(1440)x480i @ 239.76/240Hz 4:3 */
-               vmode->mHImageSize = 4;
-               vmode->mVImageSize = 3;
-       case 59:                /* 720(1440)x480i @ 239.76/240Hz 16:9 */
-               vmode->mHActive = 1440;
-               vmode->mVActive = 240;
-               vmode->mHBlanking = 276;
-               vmode->mVBlanking = 22;
-               vmode->mHSyncOffset = 38;
-               vmode->mVSyncOffset = 4;
-               vmode->mHSyncPulseWidth = 124;
-               vmode->mVSyncPulseWidth = 3;
-               vmode->mHSyncPolarity = vmode->mVSyncPolarity = FALSE;
-               vmode->mInterlaced = TRUE;
-               vmode->mPixelClock =
-                       (vmode->mRefreshRate == 239760) ? 10800 : 10810;
-               vmode->mPixelRepetitionInput = 1;
-               break;
-       default:
-               vmode->mCode = -1;
-               return;
-       }
-       return;
-}
-
 /*!
  * this submodule is responsible for the video data synchronization.
  * for example, for RGB 4:4:4 input, the data map is defined as
@@ -1164,19 +196,19 @@ void hdmi_video_sample(struct mxc_hdmi *hdmi)
        val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
                ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
                HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
-       writeb(val, hdmi->base + HDMI_TX_INVID0);
+       hdmi_writeb(val, HDMI_TX_INVID0);
 
        /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
        val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
                HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
                HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
-       writeb(val, hdmi->base + HDMI_TX_INSTUFFING);
-       writeb(0x0, hdmi->base + HDMI_TX_GYDATA0);
-       writeb(0x0, hdmi->base + HDMI_TX_GYDATA1);
-       writeb(0x0, hdmi->base + HDMI_TX_RCRDATA0);
-       writeb(0x0, hdmi->base + HDMI_TX_RCRDATA1);
-       writeb(0x0, hdmi->base + HDMI_TX_BCBDATA0);
-       writeb(0x0, hdmi->base + HDMI_TX_BCBDATA1);
+       hdmi_writeb(val, HDMI_TX_INSTUFFING);
+       hdmi_writeb(0x0, HDMI_TX_GYDATA0);
+       hdmi_writeb(0x0, HDMI_TX_GYDATA1);
+       hdmi_writeb(0x0, HDMI_TX_RCRDATA0);
+       hdmi_writeb(0x0, HDMI_TX_RCRDATA1);
+       hdmi_writeb(0x0, HDMI_TX_BCBDATA0);
+       hdmi_writeb(0x0, HDMI_TX_BCBDATA1);
 }
 
 static int isColorSpaceConversion(struct mxc_hdmi *hdmi)
@@ -1207,6 +239,7 @@ void update_csc_coeffs(struct mxc_hdmi *hdmi)
        unsigned short csc_coeff[3][4];
        unsigned int csc_scale = 1;
        u8 val;
+       bool coeff_selected = false;
 
        if (isColorSpaceConversion(hdmi) == TRUE) { /* csc needed */
                if (hdmi->hdmi_data.enc_out_format == eRGB) {
@@ -1227,6 +260,7 @@ void update_csc_coeffs(struct mxc_hdmi *hdmi)
                                csc_coeff[2][3] = 0x7e3b;
 
                                csc_scale = 1;
+                               coeff_selected = true;
                        } else if (hdmi->hdmi_data.colorimetry == eITU709) {
                                csc_coeff[0][0] = 0x2000;
                                csc_coeff[0][1] = 0x7106;
@@ -1244,6 +278,7 @@ void update_csc_coeffs(struct mxc_hdmi *hdmi)
                                csc_coeff[2][3] = 0x7e25;
 
                                csc_scale = 1;
+                               coeff_selected = true;
                        }
                } else if (hdmi->hdmi_data.enc_in_format == eRGB) {
                        if (hdmi->hdmi_data.colorimetry == eITU601) {
@@ -1257,12 +292,13 @@ void update_csc_coeffs(struct mxc_hdmi *hdmi)
                                csc_coeff[1][2] = 0x7acc;
                                csc_coeff[1][3] = 0x0200;
 
-                               csc_coeff[1][0] = 0x6acd;
-                               csc_coeff[1][1] = 0x7534;
-                               csc_coeff[1][2] = 0x2000;
-                               csc_coeff[1][3] = 0x0200;
+                               csc_coeff[2][0] = 0x6acd;
+                               csc_coeff[2][1] = 0x7534;
+                               csc_coeff[2][2] = 0x2000;
+                               csc_coeff[2][3] = 0x0200;
 
                                csc_scale = 1;
+                               coeff_selected = true;
                        } else if (hdmi->hdmi_data.colorimetry == eITU709) {
                                csc_coeff[0][0] = 0x2dc5;
                                csc_coeff[0][1] = 0x0d9b;
@@ -1280,9 +316,12 @@ void update_csc_coeffs(struct mxc_hdmi *hdmi)
                                csc_coeff[2][3] = 0x0200;
 
                                csc_scale = 1;
+                               coeff_selected = true;
                        }
                }
-       } else {
+       }
+
+       if (!coeff_selected) {
                csc_coeff[0][0] = 0x2000;
                csc_coeff[0][1] = 0x0000;
                csc_coeff[0][2] = 0x0000;
@@ -1302,61 +341,61 @@ void update_csc_coeffs(struct mxc_hdmi *hdmi)
        }
 
        /* Update CSC parameters in HDMI CSC registers */
-       writeb((unsigned char)(csc_coeff[0][0] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_A1_LSB);
-       writeb((unsigned char)(csc_coeff[0][0] >> 8),
-               hdmi->base + HDMI_CSC_COEF_A1_MSB);
-       writeb((unsigned char)(csc_coeff[0][1] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_A2_LSB);
-       writeb((unsigned char)(csc_coeff[0][1] >> 8),
-               hdmi->base + HDMI_CSC_COEF_A2_MSB);
-       writeb((unsigned char)(csc_coeff[0][2] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_A3_LSB);
-       writeb((unsigned char)(csc_coeff[0][2] >> 8),
-               hdmi->base + HDMI_CSC_COEF_A3_MSB);
-       writeb((unsigned char)(csc_coeff[0][3] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_A4_LSB);
-       writeb((unsigned char)(csc_coeff[0][3] >> 8),
-               hdmi->base + HDMI_CSC_COEF_A4_MSB);
-
-       writeb((unsigned char)(csc_coeff[1][0] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_B1_LSB);
-       writeb((unsigned char)(csc_coeff[1][0] >> 8),
-               hdmi->base + HDMI_CSC_COEF_B1_MSB);
-       writeb((unsigned char)(csc_coeff[1][1] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_B2_LSB);
-       writeb((unsigned char)(csc_coeff[1][1] >> 8),
-               hdmi->base + HDMI_CSC_COEF_B2_MSB);
-       writeb((unsigned char)(csc_coeff[1][2] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_B3_LSB);
-       writeb((unsigned char)(csc_coeff[1][2] >> 8),
-               hdmi->base + HDMI_CSC_COEF_B3_MSB);
-       writeb((unsigned char)(csc_coeff[1][3] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_B4_LSB);
-       writeb((unsigned char)(csc_coeff[1][3] >> 8),
-               hdmi->base + HDMI_CSC_COEF_B4_MSB);
-
-       writeb((unsigned char)(csc_coeff[2][0] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_C1_LSB);
-       writeb((unsigned char)(csc_coeff[2][0] >> 8),
-               hdmi->base + HDMI_CSC_COEF_C1_MSB);
-       writeb((unsigned char)(csc_coeff[2][1] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_C2_LSB);
-       writeb((unsigned char)(csc_coeff[2][1] >> 8),
-               hdmi->base + HDMI_CSC_COEF_C2_MSB);
-       writeb((unsigned char)(csc_coeff[2][2] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_C3_LSB);
-       writeb((unsigned char)(csc_coeff[2][2] >> 8),
-               hdmi->base + HDMI_CSC_COEF_C3_MSB);
-       writeb((unsigned char)(csc_coeff[2][3] & 0xFF),
-               hdmi->base + HDMI_CSC_COEF_C4_LSB);
-       writeb((unsigned char)(csc_coeff[2][3] >> 8),
-               hdmi->base + HDMI_CSC_COEF_C4_MSB);
-
-       readb(hdmi->base + HDMI_CSC_SCALE);
+       hdmi_writeb((unsigned char)(csc_coeff[0][0] & 0xFF),
+               HDMI_CSC_COEF_A1_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[0][0] >> 8),
+               HDMI_CSC_COEF_A1_MSB);
+       hdmi_writeb((unsigned char)(csc_coeff[0][1] & 0xFF),
+               HDMI_CSC_COEF_A2_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[0][1] >> 8),
+               HDMI_CSC_COEF_A2_MSB);
+       hdmi_writeb((unsigned char)(csc_coeff[0][2] & 0xFF),
+               HDMI_CSC_COEF_A3_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[0][2] >> 8),
+               HDMI_CSC_COEF_A3_MSB);
+       hdmi_writeb((unsigned char)(csc_coeff[0][3] & 0xFF),
+               HDMI_CSC_COEF_A4_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[0][3] >> 8),
+               HDMI_CSC_COEF_A4_MSB);
+
+       hdmi_writeb((unsigned char)(csc_coeff[1][0] & 0xFF),
+               HDMI_CSC_COEF_B1_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[1][0] >> 8),
+               HDMI_CSC_COEF_B1_MSB);
+       hdmi_writeb((unsigned char)(csc_coeff[1][1] & 0xFF),
+               HDMI_CSC_COEF_B2_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[1][1] >> 8),
+               HDMI_CSC_COEF_B2_MSB);
+       hdmi_writeb((unsigned char)(csc_coeff[1][2] & 0xFF),
+               HDMI_CSC_COEF_B3_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[1][2] >> 8),
+               HDMI_CSC_COEF_B3_MSB);
+       hdmi_writeb((unsigned char)(csc_coeff[1][3] & 0xFF),
+               HDMI_CSC_COEF_B4_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[1][3] >> 8),
+               HDMI_CSC_COEF_B4_MSB);
+
+       hdmi_writeb((unsigned char)(csc_coeff[2][0] & 0xFF),
+               HDMI_CSC_COEF_C1_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[2][0] >> 8),
+               HDMI_CSC_COEF_C1_MSB);
+       hdmi_writeb((unsigned char)(csc_coeff[2][1] & 0xFF),
+               HDMI_CSC_COEF_C2_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[2][1] >> 8),
+               HDMI_CSC_COEF_C2_MSB);
+       hdmi_writeb((unsigned char)(csc_coeff[2][2] & 0xFF),
+               HDMI_CSC_COEF_C3_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[2][2] >> 8),
+               HDMI_CSC_COEF_C3_MSB);
+       hdmi_writeb((unsigned char)(csc_coeff[2][3] & 0xFF),
+               HDMI_CSC_COEF_C4_LSB);
+       hdmi_writeb((unsigned char)(csc_coeff[2][3] >> 8),
+               HDMI_CSC_COEF_C4_MSB);
+
+       val = hdmi_readb(HDMI_CSC_SCALE);
        val &= ~HDMI_CSC_SCALE_CSCSCALE_MASK;
        val |= csc_scale & HDMI_CSC_SCALE_CSCSCALE_MASK;
-       writeb(val, hdmi->base + HDMI_CSC_SCALE);
+       hdmi_writeb(val, HDMI_CSC_SCALE);
 }
 
 void hdmi_video_csc(struct mxc_hdmi *hdmi)
@@ -1384,11 +423,11 @@ void hdmi_video_csc(struct mxc_hdmi *hdmi)
                return;
 
        /*configure the CSC registers */
-       writeb(interpolation | decimation, hdmi->base + HDMI_CSC_CFG);
-       val = readb(hdmi->base + HDMI_CSC_SCALE);
+       hdmi_writeb(interpolation | decimation, HDMI_CSC_CFG);
+       val = hdmi_readb(HDMI_CSC_SCALE);
        val &= ~HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK;
        val |= color_depth;
-       writeb(val, hdmi->base + HDMI_CSC_SCALE);
+       hdmi_writeb(val, HDMI_CSC_SCALE);
 
        update_csc_coeffs(hdmi);
 }
@@ -1441,79 +480,79 @@ void hdmi_video_packetize(struct mxc_hdmi *hdmi)
                ((hdmi_data->pix_repet_factor <<
                HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
                HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
-       writeb(val, hdmi->base + HDMI_VP_PR_CD);
+       hdmi_writeb(val, HDMI_VP_PR_CD);
 
-       val = readb(hdmi->base + HDMI_VP_STUFF);
+       val = hdmi_readb(HDMI_VP_STUFF);
        val &= ~HDMI_VP_STUFF_PR_STUFFING_MASK;
        val |= HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE;
-       writeb(val, hdmi->base + HDMI_VP_STUFF);
+       hdmi_writeb(val, HDMI_VP_STUFF);
 
        /* Data from pixel repeater block */
        if (hdmi_data->pix_repet_factor > 1) {
-               val = readb(hdmi->base + HDMI_VP_CONF);
+               val = hdmi_readb(HDMI_VP_CONF);
                val &= ~(HDMI_VP_CONF_PR_EN_MASK |
                        HDMI_VP_CONF_BYPASS_SELECT_MASK);
                val |= HDMI_VP_CONF_PR_EN_ENABLE |
                        HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
-               writeb(val, hdmi->base + HDMI_VP_CONF);
+               hdmi_writeb(val, HDMI_VP_CONF);
        } else { /* data from packetizer block */
-               val = readb(hdmi->base + HDMI_VP_CONF);
+               val = hdmi_readb(HDMI_VP_CONF);
                val &= ~(HDMI_VP_CONF_PR_EN_MASK |
                        HDMI_VP_CONF_BYPASS_SELECT_MASK);
                val |= HDMI_VP_CONF_PR_EN_DISABLE |
                        HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
-               writeb(val, hdmi->base + HDMI_VP_CONF);
+               hdmi_writeb(val, HDMI_VP_CONF);
        }
 
-       val = readb(hdmi->base + HDMI_VP_STUFF);
+       val = hdmi_readb(HDMI_VP_STUFF);
        val &= ~HDMI_VP_STUFF_IDEFAULT_PHASE_MASK;
        val |= 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET;
-       writeb(val, hdmi->base + HDMI_VP_STUFF);
+       hdmi_writeb(val, HDMI_VP_STUFF);
 
-       writeb(remap_size, hdmi->base + HDMI_VP_REMAP);
+       hdmi_writeb(remap_size, HDMI_VP_REMAP);
 
        if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
-               val = readb(hdmi->base + HDMI_VP_CONF);
+               val = hdmi_readb(HDMI_VP_CONF);
                val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
                        HDMI_VP_CONF_PP_EN_ENMASK |
                        HDMI_VP_CONF_YCC422_EN_MASK);
                val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
                        HDMI_VP_CONF_PP_EN_ENABLE |
                        HDMI_VP_CONF_YCC422_EN_DISABLE;
-               writeb(val, hdmi->base + HDMI_VP_CONF);
+               hdmi_writeb(val, HDMI_VP_CONF);
        } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
-               val = readb(hdmi->base + HDMI_VP_CONF);
+               val = hdmi_readb(HDMI_VP_CONF);
                val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
                        HDMI_VP_CONF_PP_EN_ENMASK |
                        HDMI_VP_CONF_YCC422_EN_MASK);
                val |= HDMI_VP_CONF_BYPASS_EN_DISABLE |
                        HDMI_VP_CONF_PP_EN_DISABLE |
                        HDMI_VP_CONF_YCC422_EN_ENABLE;
-               writeb(val, hdmi->base + HDMI_VP_CONF);
+               hdmi_writeb(val, HDMI_VP_CONF);
        } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
-               val = readb(hdmi->base + HDMI_VP_CONF);
+               val = hdmi_readb(HDMI_VP_CONF);
                val &= ~(HDMI_VP_CONF_BYPASS_EN_MASK |
                        HDMI_VP_CONF_PP_EN_ENMASK |
                        HDMI_VP_CONF_YCC422_EN_MASK);
                val |= HDMI_VP_CONF_BYPASS_EN_ENABLE |
                        HDMI_VP_CONF_PP_EN_DISABLE |
                        HDMI_VP_CONF_YCC422_EN_DISABLE;
-               writeb(val, hdmi->base + HDMI_VP_CONF);
+               hdmi_writeb(val, HDMI_VP_CONF);
        } else {
                return;
        }
 
-       val = readb(hdmi->base + HDMI_VP_STUFF);
+       val = hdmi_readb(HDMI_VP_STUFF);
        val &= ~(HDMI_VP_STUFF_PP_STUFFING_MASK |
                HDMI_VP_STUFF_YCC422_STUFFING_MASK);
        val |= HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
                HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE;
-       writeb(val, hdmi->base + HDMI_VP_STUFF);
+       hdmi_writeb(val, HDMI_VP_STUFF);
 
-       val = readb(hdmi->base + HDMI_VP_CONF);
+       val = hdmi_readb(HDMI_VP_CONF);
        val &= ~HDMI_VP_CONF_OUTPUT_SELECTOR_MASK;
        val |= output_select;
-       writeb(val, hdmi->base + HDMI_VP_CONF);
+       hdmi_writeb(val, HDMI_VP_CONF);
 }
 
 void hdmi_video_force_output(struct mxc_hdmi *hdmi, unsigned char force)
@@ -1521,94 +560,73 @@ void hdmi_video_force_output(struct mxc_hdmi *hdmi, unsigned char force)
        u8 val;
 
        if (force == TRUE) {
-               writeb(0x00, hdmi->base + HDMI_FC_DBGTMDS2);   /* R */
-               writeb(0x00, hdmi->base + HDMI_FC_DBGTMDS1);   /* G */
-               writeb(0xFF, hdmi->base + HDMI_FC_DBGTMDS0);   /* B */
-               val = readb(hdmi->base + HDMI_FC_DBGFORCE);
+               hdmi_writeb(0x00, HDMI_FC_DBGTMDS2);   /* R */
+               hdmi_writeb(0x00, HDMI_FC_DBGTMDS1);   /* G */
+               hdmi_writeb(0xFF, HDMI_FC_DBGTMDS0);   /* B */
+               val = hdmi_readb(HDMI_FC_DBGFORCE);
                val |= HDMI_FC_DBGFORCE_FORCEVIDEO;
-               writeb(val, hdmi->base + HDMI_FC_DBGFORCE);
+               hdmi_writeb(val, HDMI_FC_DBGFORCE);
        } else {
-               val = readb(hdmi->base + HDMI_FC_DBGFORCE);
+               val = hdmi_readb(HDMI_FC_DBGFORCE);
                val &= ~HDMI_FC_DBGFORCE_FORCEVIDEO;
-               writeb(val, hdmi->base + HDMI_FC_DBGFORCE);
-               writeb(0x00, hdmi->base + HDMI_FC_DBGTMDS2);   /* R */
-               writeb(0x00, hdmi->base + HDMI_FC_DBGTMDS1);   /* G */
-               writeb(0x00, hdmi->base + HDMI_FC_DBGTMDS0);   /* B */
+               hdmi_writeb(val, HDMI_FC_DBGFORCE);
+               hdmi_writeb(0x00, HDMI_FC_DBGTMDS2);   /* R */
+               hdmi_writeb(0x00, HDMI_FC_DBGTMDS1);   /* G */
+               hdmi_writeb(0x00, HDMI_FC_DBGTMDS0);   /* B */
        }
 }
 
 static inline void hdmi_phy_test_clear(struct mxc_hdmi *hdmi,
                                                unsigned char bit)
 {
-       u8 val = readb(hdmi->base + HDMI_PHY_TST0);
+       u8 val = hdmi_readb(HDMI_PHY_TST0);
        val &= ~HDMI_PHY_TST0_TSTCLR_MASK;
        val |= (bit << HDMI_PHY_TST0_TSTCLR_OFFSET) &
                HDMI_PHY_TST0_TSTCLR_MASK;
-       writeb(val, hdmi->base + HDMI_PHY_TST0);
+       hdmi_writeb(val, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_enable(struct mxc_hdmi *hdmi,
                                                unsigned char bit)
 {
-       u8 val = readb(hdmi->base + HDMI_PHY_TST0);
+       u8 val = hdmi_readb(HDMI_PHY_TST0);
        val &= ~HDMI_PHY_TST0_TSTEN_MASK;
        val |= (bit << HDMI_PHY_TST0_TSTEN_OFFSET) &
                HDMI_PHY_TST0_TSTEN_MASK;
-       writeb(val, hdmi->base + HDMI_PHY_TST0);
+       hdmi_writeb(val, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_clock(struct mxc_hdmi *hdmi,
                                                unsigned char bit)
 {
-       u8 val = readb(hdmi->base + HDMI_PHY_TST0);
+       u8 val = hdmi_readb(HDMI_PHY_TST0);
        val &= ~HDMI_PHY_TST0_TSTCLK_MASK;
        val |= (bit << HDMI_PHY_TST0_TSTCLK_OFFSET) &
                HDMI_PHY_TST0_TSTCLK_MASK;
-       writeb(val, hdmi->base + HDMI_PHY_TST0);
+       hdmi_writeb(val, HDMI_PHY_TST0);
 }
 
 static inline void hdmi_phy_test_din(struct mxc_hdmi *hdmi,
                                                unsigned char bit)
 {
-       writeb(bit, hdmi->base + HDMI_PHY_TST1);
+       hdmi_writeb(bit, HDMI_PHY_TST1);
 }
 
 static inline void hdmi_phy_test_dout(struct mxc_hdmi *hdmi,
                                                unsigned char bit)
 {
-       writeb(bit, hdmi->base + HDMI_PHY_TST2);
-}
-
-static int hdmi_phy_test_control(struct mxc_hdmi *hdmi, unsigned char value)
-{
-       hdmi_phy_test_din(hdmi, value);
-       hdmi_phy_test_enable(hdmi, 1);
-       hdmi_phy_test_clock(hdmi, 1);
-       hdmi_phy_test_clock(hdmi, 0);
-       hdmi_phy_test_enable(hdmi, 0);
-
-       return TRUE;
-}
-
-static int hdmi_phy_test_data(struct mxc_hdmi *hdmi, unsigned char value)
-{
-       hdmi_phy_test_din(hdmi, value);
-       hdmi_phy_test_enable(hdmi, 0);
-       hdmi_phy_test_clock(hdmi, 1);
-       hdmi_phy_test_clock(hdmi, 0);
-
-       return TRUE;
+       hdmi_writeb(bit, HDMI_PHY_TST2);
 }
 
 int hdmi_phy_wait_i2c_done(struct mxc_hdmi *hdmi, int msec)
 {
        unsigned char val = 0;
-       val = readb(hdmi->base + HDMI_IH_I2CMPHY_STAT0) & 0x3;
+       val = hdmi_readb(HDMI_IH_I2CMPHY_STAT0) & 0x3;
        while (val == 0) {
                udelay(1000);
                if (msec-- == 0)
                        return FALSE;
-               val = readb(hdmi->base + HDMI_IH_I2CMPHY_STAT0) & 0x3;
+               val = hdmi_readb(HDMI_IH_I2CMPHY_STAT0) & 0x3;
        }
        return TRUE;
 }
@@ -1616,14 +634,14 @@ int hdmi_phy_wait_i2c_done(struct mxc_hdmi *hdmi, int msec)
 int hdmi_phy_i2c_write(struct mxc_hdmi *hdmi, unsigned short data,
                                unsigned char addr)
 {
-       writeb(0xFF, hdmi->base + HDMI_IH_I2CMPHY_STAT0);
-       writeb(addr, hdmi->base + HDMI_PHY_I2CM_ADDRESS_ADDR);
-       writeb((unsigned char)(data >> 8),
-               hdmi->base + HDMI_PHY_I2CM_DATAO_1_ADDR);
-       writeb((unsigned char)(data >> 0),
-               hdmi->base + HDMI_PHY_I2CM_DATAO_0_ADDR);
-       writeb(HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
-               hdmi->base + HDMI_PHY_I2CM_OPERATION_ADDR);
+       hdmi_writeb(0xFF, HDMI_IH_I2CMPHY_STAT0);
+       hdmi_writeb(addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
+       hdmi_writeb((unsigned char)(data >> 8),
+               HDMI_PHY_I2CM_DATAO_1_ADDR);
+       hdmi_writeb((unsigned char)(data >> 0),
+               HDMI_PHY_I2CM_DATAO_0_ADDR);
+       hdmi_writeb(HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
+               HDMI_PHY_I2CM_OPERATION_ADDR);
        hdmi_phy_wait_i2c_done(hdmi, 1000);
        return TRUE;
 }
@@ -1632,13 +650,13 @@ unsigned short hdmi_phy_i2c_read(struct mxc_hdmi *hdmi, unsigned char addr)
 {
        unsigned short data;
        unsigned char msb = 0, lsb = 0;
-       writeb(0xFF, hdmi->base + HDMI_IH_I2CMPHY_STAT0);
-       writeb(addr, hdmi->base + HDMI_PHY_I2CM_ADDRESS_ADDR);
-       writeb(HDMI_PHY_I2CM_OPERATION_ADDR_READ,
-               hdmi->base + HDMI_PHY_I2CM_OPERATION_ADDR);
+       hdmi_writeb(0xFF, HDMI_IH_I2CMPHY_STAT0);
+       hdmi_writeb(addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
+       hdmi_writeb(HDMI_PHY_I2CM_OPERATION_ADDR_READ,
+               HDMI_PHY_I2CM_OPERATION_ADDR);
        hdmi_phy_wait_i2c_done(hdmi, 1000);
-       msb = readb(hdmi->base + HDMI_PHY_I2CM_DATAI_1_ADDR);
-       lsb = readb(hdmi->base + HDMI_PHY_I2CM_DATAI_0_ADDR);
+       msb = hdmi_readb(HDMI_PHY_I2CM_DATAI_1_ADDR);
+       lsb = hdmi_readb(HDMI_PHY_I2CM_DATAI_0_ADDR);
        data = (msb << 8) | lsb;
        return data;
 }
@@ -1658,7 +676,6 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
                                unsigned char cRes, int cscOn, int audioOn,
                                int cecOn, int hdcpOn)
 {
-       unsigned short clk = 0, rep = 0;
        u8 val;
 
        /* color resolution 0 is 8 bit colour depth */
@@ -1670,44 +687,11 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
        else if (cRes != 8 && cRes != 12)
                return FALSE;
 
-       switch (hdmi->hdmi_data.video_mode.mPixelClock) {
-       case 2520:
-               clk = 0x93C1;
-               rep = (cRes == 8) ? 0x6A4A : 0x6653;
-               break;
-       case 2700:
-               clk = 0x96C1;
-               rep = (cRes == 8) ? 0x6A4A : 0x6653;
-               break;
-       case 5400:
-               clk = 0x8CC3;
-               rep = (cRes == 8) ? 0x6A4A : 0x6653;
-               break;
-       case 7200:
-               clk = 0x90C4;
-               rep = (cRes == 8) ? 0x6A4A : 0x6654;
-               break;
-       case 7425:
-               clk = 0x95C8;
-               rep = (cRes == 8) ? 0x6A4A : 0x6654;
-               break;
-       case 10800:
-               clk = 0x98C6;
-               rep = (cRes == 8) ? 0x6A4A : 0x6653;
-               break;
-       case 14850:
-               clk = 0x89C9;
-               rep = (cRes == 8) ? 0x6A4A : 0x6654;
-               break;
-       default:
-               return FALSE;
-       }
-
        if (cscOn)
                val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
        else
                val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
-       writeb(val, hdmi->base + HDMI_MC_FLOWCTRL);
+       hdmi_writeb(val, HDMI_MC_FLOWCTRL);
 
 #if 0
        /* clock gate == 0 => turn on modules */
@@ -1738,39 +722,35 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
        val |= audioOn ? HDMI_MC_CLKDIS_AUDCLK_DISABLE_DISABLE :
                HDMI_MC_CLKDIS_AUDCLK_DISABLE_ENABLE;
 #endif
-       writeb(val, hdmi->base + HDMI_MC_CLKDIS);
+       hdmi_writeb(val, HDMI_MC_CLKDIS);
 
        /* gen2 tx power off */
-       val = readb(hdmi->base + HDMI_PHY_CONF0);
+       val = hdmi_readb(HDMI_PHY_CONF0);
        val &= ~HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
        val |= HDMI_PHY_CONF0_GEN2_TXPWRON_POWER_OFF;
-       writeb(val, hdmi->base + HDMI_PHY_CONF0);
+       hdmi_writeb(val, HDMI_PHY_CONF0);
 
        /* gen2 pddq */
-       val = readb(hdmi->base + HDMI_PHY_CONF0);
+       val = hdmi_readb(HDMI_PHY_CONF0);
        val &= ~HDMI_PHY_CONF0_GEN2_PDDQ_MASK;
        val |= HDMI_PHY_CONF0_GEN2_PDDQ_ENABLE;
-       writeb(val, hdmi->base + HDMI_PHY_CONF0);
+       hdmi_writeb(val, HDMI_PHY_CONF0);
 
        /* PHY reset */
-#if 0
-       writeb(HDMI_MC_PHYRSTZ_ASSERT, hdmi->base + HDMI_MC_PHYRSTZ);
-       writeb(HDMI_MC_PHYRSTZ_DEASSERT, hdmi->base + HDMI_MC_PHYRSTZ);
-#else
-       writeb(HDMI_MC_PHYRSTZ_DEASSERT, hdmi->base + HDMI_MC_PHYRSTZ);
-       writeb(HDMI_MC_PHYRSTZ_ASSERT, hdmi->base + HDMI_MC_PHYRSTZ);
-#endif
+       hdmi_writeb(HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
+       hdmi_writeb(HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
 
-       writeb(HDMI_MC_HEACPHY_RST_ASSERT,
-               hdmi->base + HDMI_MC_HEACPHY_RST);
+       hdmi_writeb(HDMI_MC_HEACPHY_RST_ASSERT,
+               HDMI_MC_HEACPHY_RST);
 
        hdmi_phy_test_clear(hdmi, 1);
-       writeb(HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
-                       hdmi->base + HDMI_PHY_I2CM_SLAVE_ADDR);
+       hdmi_writeb(HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
+                       HDMI_PHY_I2CM_SLAVE_ADDR);
        hdmi_phy_test_clear(hdmi, 0);
 
        switch (hdmi->hdmi_data.video_mode.mPixelClock) {
-       case 2520:
+       case 25200000: /* 60 Hz */
+       case 24780000: /* 59 Hz (rounded down from 59.94) */
                switch (cRes) {
                case 8:
                        /* PLL/MPLL Cfg */
@@ -1814,7 +794,7 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
                        return FALSE;
                }
                break;
-       case 2700:
+       case 27000000:
                switch (cRes) {
                case 8:
                        hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06);
@@ -1853,7 +833,7 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
                        return FALSE;
                }
                break;
-       case 5400:
+       case 54000000:
                switch (cRes) {
                case 8:
                        hdmi_phy_i2c_write(hdmi, 0x0140, 0x06);
@@ -1892,7 +872,7 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
                        return FALSE;
                }
                break;
-       case 7200:
+       case 72000000:
                switch (cRes) {
                case 8:
                        hdmi_phy_i2c_write(hdmi, 0x0140, 0x06);
@@ -1931,7 +911,7 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
                        return FALSE;
                }
                break;
-       case 7425:
+       case 74250000:
                switch (cRes) {
                case 8:
                        hdmi_phy_i2c_write(hdmi, 0x0140, 0x06);
@@ -1970,7 +950,7 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
                        return FALSE;
                }
                break;
-       case 10800:
+       case 108000000:
                switch (cRes) {
                case 8:
                        hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
@@ -2009,7 +989,7 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
                        return FALSE;
                }
                break;
-       case 14850:
+       case 148500000:
                switch (cRes) {
                case 8:
                        hdmi_phy_i2c_write(hdmi, 0x00a0, 0x06);
@@ -2049,23 +1029,26 @@ int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
                }
                break;
        default:
+               dev_err(&hdmi->pdev->dev,
+                               "Pixel clock %d - unsupported by HDMI\n",
+                               hdmi->hdmi_data.video_mode.mPixelClock);
                return FALSE;
        }
 
        /* gen2 tx power on */
-       val = readb(hdmi->base + HDMI_PHY_CONF0);
+       val = hdmi_readb(HDMI_PHY_CONF0);
        val &= ~HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
        val |= HDMI_PHY_CONF0_GEN2_TXPWRON_POWER_ON;
-       writeb(val, hdmi->base + HDMI_PHY_CONF0);
+       hdmi_writeb(val, HDMI_PHY_CONF0);
 
-       val = readb(hdmi->base + HDMI_PHY_CONF0);
+       val = hdmi_readb(HDMI_PHY_CONF0);
        val &= ~HDMI_PHY_CONF0_GEN2_PDDQ_MASK;
        val |= HDMI_PHY_CONF0_GEN2_PDDQ_DISABLE;
-       writeb(val, hdmi->base + HDMI_PHY_CONF0);
+       hdmi_writeb(val, HDMI_PHY_CONF0);
 
        udelay(1000);
 
-       if ((readb(hdmi->base + HDMI_PHY_STAT0) & 0x01) == 0)
+       if ((hdmi_readb(HDMI_PHY_STAT0) & 0x01) == 0)
                return FALSE;
 
        return TRUE;
@@ -2075,10 +1058,7 @@ void hdmi_phy_init(struct mxc_hdmi *hdmi, unsigned char de)
 {
        u8 val;
 
-       /* configure the interrupt mask of source PHY. */
-       writeb(0xFF, hdmi->base + HDMI_PHY_MASK0);
-
-       val = readb(hdmi->base + HDMI_PHY_CONF0);
+       val = hdmi_readb(HDMI_PHY_CONF0);
        /* set the DE polarity */
        val |= (de << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET) &
                HDMI_PHY_CONF0_SELDATAENPOL_MASK;
@@ -2088,21 +1068,17 @@ void hdmi_phy_init(struct mxc_hdmi *hdmi, unsigned char de)
        /* enable TMDS output */
        val |= (1 << HDMI_PHY_CONF0_ENTMDS_OFFSET) &
                HDMI_PHY_CONF0_ENTMDS_MASK;
-       writeb(val, hdmi->base + HDMI_PHY_CONF0);
+       hdmi_writeb(val, HDMI_PHY_CONF0);
 
-       /* PHY power down disable (i.e., enable PHY) */
-       val = readb(hdmi->base + HDMI_PHY_CONF0);
+       /* PHY power enable */
+       val = hdmi_readb(HDMI_PHY_CONF0);
        val |= (1 << HDMI_PHY_CONF0_PDZ_OFFSET) &
                HDMI_PHY_CONF0_PDZ_MASK;
-       writeb(val, hdmi->base + HDMI_PHY_CONF0);
+       hdmi_writeb(val, HDMI_PHY_CONF0);
 
        hdmi_phy_configure(hdmi, 0, 8, FALSE, FALSE, FALSE, FALSE);
 }
 
-void hdmi_tx_tmds_clock(unsigned short tmdsclk, int i2cfsmode)
-{
-}
-
 void hdmi_tx_hdcp_config(struct mxc_hdmi *hdmi)
 {
        u8 de, val;
@@ -2113,48 +1089,160 @@ void hdmi_tx_hdcp_config(struct mxc_hdmi *hdmi)
                de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
 
        /* disable rx detect */
-       val = readb(hdmi->base + HDMI_A_HDCPCFG0);
+       val = hdmi_readb(HDMI_A_HDCPCFG0);
        val &= HDMI_A_HDCPCFG0_RXDETECT_MASK;
        val |= HDMI_A_HDCPCFG0_RXDETECT_DISABLE;
-       writeb(val, hdmi->base + HDMI_A_HDCPCFG0);
+       hdmi_writeb(val, HDMI_A_HDCPCFG0);
 
-       val = readb(hdmi->base + HDMI_A_VIDPOLCFG);
+       val = hdmi_readb(HDMI_A_VIDPOLCFG);
        val &= HDMI_A_VIDPOLCFG_DATAENPOL_MASK;
        val |= de;
-       writeb(val, hdmi->base + HDMI_A_VIDPOLCFG);
+       hdmi_writeb(val, HDMI_A_VIDPOLCFG);
 
-       val = readb(hdmi->base + HDMI_A_HDCPCFG1);
+       val = hdmi_readb(HDMI_A_HDCPCFG1);
        val &= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK;
        val |= HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE;
-       writeb(val, hdmi->base + HDMI_A_HDCPCFG1);
-
-       hdmi_tx_tmds_clock(0, 0);
-}
-
-void hdmi_audio_mute(struct mxc_hdmi *hdmi, int en)
-{
-       u8 val;
-       val = readb(hdmi->base + HDMI_FC_AUDSCONF);
-       val &= HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK;
-       val |= ((en == TRUE) ? 0xF : 0) <<
-               HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET;
-       writeb(val, hdmi->base + HDMI_FC_AUDSCONF);
+       hdmi_writeb(val, HDMI_A_HDCPCFG1);
 }
 
 void preamble_filter_set(struct mxc_hdmi *hdmi, unsigned char value,
                                unsigned char channel)
 {
        if (channel == 0)
-               writeb(value, hdmi->base + HDMI_FC_CH0PREAM);
+               hdmi_writeb(value, HDMI_FC_CH0PREAM);
        else if (channel == 1)
-               writeb(value, hdmi->base + HDMI_FC_CH1PREAM);
+               hdmi_writeb(value, HDMI_FC_CH1PREAM);
        else if (channel == 2)
-               writeb(value, hdmi->base + HDMI_FC_CH2PREAM);
+               hdmi_writeb(value, HDMI_FC_CH2PREAM);
        else
 
        return;
 }
 
+static void hdmi_config_AVI(struct mxc_hdmi *hdmi)
+{
+       u8 val;
+       u8 pix_fmt;
+       u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry;
+       struct fb_videomode mode;
+       const struct fb_videomode *edid_mode;
+       bool aspect_16_9;
+
+       dev_dbg(&hdmi->pdev->dev, "set up AVI frame\n");
+
+       fb_var_to_videomode(&mode, &hdmi->fbi->var);
+       /* Use mode from list extracted from EDID to get aspect ratio */
+       if (!list_empty(&hdmi->fbi->modelist)) {
+               edid_mode = fb_find_nearest_mode(&mode, &hdmi->fbi->modelist);
+               if (edid_mode->flag & FB_MODE_ASPECT_16_9)
+                       aspect_16_9 = true;
+               else
+                       aspect_16_9 = false;
+       } else
+               aspect_16_9 = false;
+
+       /********************************************
+        * AVI Data Byte 1
+        ********************************************/
+       if (hdmi->edid_cfg.cea_ycbcr444)
+               pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR444;
+       else if (hdmi->edid_cfg.cea_ycbcr422)
+               pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR422;
+       else
+               pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_RGB;
+
+       /*
+        * Active format identification data is present in the AVI InfoFrame.
+        * No scan info, no bar data
+        */
+       val = pix_fmt |
+               HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT |
+               HDMI_FC_AVICONF0_BAR_DATA_NO_DATA |
+               HDMI_FC_AVICONF0_SCAN_INFO_NODATA;
+
+       hdmi_writeb(val, HDMI_FC_AVICONF0);
+
+       /********************************************
+        * AVI Data Byte 2
+        ********************************************/
+
+       /*  Set the Aspect Ratio */
+       if (aspect_16_9) {
+               act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9;
+               coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9;
+       } else {
+               act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3;
+               coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3;
+       }
+
+       /* Set up colorimetry */
+       if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
+               colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO;
+               if (hdmi->hdmi_data.colorimetry == eITU601)
+                       ext_colorimetry =
+                               HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+               else /* hdmi->hdmi_data.colorimetry == eITU709 */
+                       ext_colorimetry =
+                               HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709;
+       } else if (hdmi->hdmi_data.enc_out_format != RGB) {
+               if (hdmi->hdmi_data.colorimetry == eITU601)
+                       colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE;
+               else /* hdmi->hdmi_data.colorimetry == eITU709 */
+                       colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR;
+               ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+       } else { /* Carries no data */
+               colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA;
+               ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+       }
+
+       val = colorimetry | coded_ratio | act_ratio;
+       hdmi_writeb(val, HDMI_FC_AVICONF1);
+
+       /********************************************
+        * AVI Data Byte 3
+        ********************************************/
+
+       val = HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA | ext_colorimetry |
+               HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT |
+               HDMI_FC_AVICONF2_SCALING_NONE;
+       hdmi_writeb(val, HDMI_FC_AVICONF2);
+
+       /********************************************
+        * AVI Data Byte 4
+        ********************************************/
+       hdmi_writeb(hdmi->vic, HDMI_FC_AVIVID);
+
+       /********************************************
+        * AVI Data Byte 5
+        ********************************************/
+
+       /* Set up input and output pixel repetition */
+       val = (((hdmi->hdmi_data.video_mode.mPixelRepetitionInput + 1) <<
+               HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) &
+               HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) |
+               ((hdmi->hdmi_data.video_mode.mPixelRepetitionOutput <<
+               HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) &
+               HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
+       hdmi_writeb(val, HDMI_FC_PRCONF);
+
+       /* IT Content and quantization range = don't care */
+       val = HDMI_FC_AVICONF2_IT_CONTENT_TYPE_GRAPHICS |
+               HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED;
+       hdmi_writeb(val, HDMI_FC_AVICONF3);
+
+       /********************************************
+        * AVI Data Bytes 6-13
+        ********************************************/
+       hdmi_writeb(0, HDMI_FC_AVIETB0);
+       hdmi_writeb(0, HDMI_FC_AVIETB1);
+       hdmi_writeb(0, HDMI_FC_AVISBB0);
+       hdmi_writeb(0, HDMI_FC_AVISBB1);
+       hdmi_writeb(0, HDMI_FC_AVIELB0);
+       hdmi_writeb(0, HDMI_FC_AVIELB1);
+       hdmi_writeb(0, HDMI_FC_AVISRB0);
+       hdmi_writeb(0, HDMI_FC_AVISRB1);
+}
+
 /*!
  * this submodule is responsible for the video/audio data composition.
  */
@@ -2162,113 +1250,103 @@ void hdmi_av_composer(struct mxc_hdmi *hdmi)
 {
        unsigned char i = 0;
        u8 val;
+       struct fb_info *fbi = hdmi->fbi;
+       struct fb_videomode fb_mode;
+       struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
+       int hblank, vblank;
+
+       fb_var_to_videomode(&fb_mode, &fbi->var);
+
+       vmode->mHSyncPolarity =
+               (fb_mode.sync & FB_SYNC_HOR_HIGH_ACT) ? TRUE : FALSE;
+       vmode->mVSyncPolarity =
+               (fb_mode.sync & FB_SYNC_VERT_HIGH_ACT) ? TRUE : FALSE;
+       vmode->mInterlaced =
+               (fb_mode.vmode & FB_VMODE_INTERLACED) ? TRUE : FALSE;
+       vmode->mPixelClock = (fb_mode.xres + fb_mode.left_margin +
+               fb_mode.right_margin + fb_mode.hsync_len) * (fb_mode.yres +
+               fb_mode.upper_margin + fb_mode.lower_margin +
+               fb_mode.vsync_len) * fb_mode.refresh;
 
-       hdmi_set_video_mode(&hdmi->hdmi_data.video_mode);
+       /* Expose pixel clock for audio driver */
+       mxc_hdmi_pixel_clk = vmode->mPixelClock;
+
+       dev_dbg(&hdmi->pdev->dev, "final pixclk = %d\n", vmode->mPixelClock);
 
        /* Set up HDMI_FC_INVIDCONF */
        val = ((hdmi->hdmi_data.hdcp_enable == TRUE) ?
                HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
                HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
-       val |= ((hdmi->hdmi_data.video_mode.mVSyncPolarity == TRUE) ?
+       val |= ((vmode->mVSyncPolarity == TRUE) ?
                HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
                HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
-       val |= ((hdmi->hdmi_data.video_mode.mHSyncPolarity == TRUE) ?
+       val |= ((vmode->mHSyncPolarity == TRUE) ?
                HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
                HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
-       val |= ((hdmi->hdmi_data.video_mode.mDataEnablePolarity == TRUE) ?
+       val |= ((vmode->mDataEnablePolarity == TRUE) ?
                HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
                HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
-       val |= ((hdmi->hdmi_data.video_mode.mHdmiDviSel == TRUE) ?
+       val |= ((vmode->mHdmiDviSel == TRUE) ?
                HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
                HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
-       if (hdmi->hdmi_data.video_mode.mCode == 39)
+       if (hdmi->vic == 39)
                val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
        else
-               val |= ((hdmi->hdmi_data.video_mode.mInterlaced == TRUE) ?
+               val |= ((vmode->mInterlaced == TRUE) ?
                        HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
                        HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW);
-       val |= ((hdmi->hdmi_data.video_mode.mInterlaced == TRUE) ?
+       val |= ((vmode->mInterlaced == TRUE) ?
                HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
                HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE);
-       writeb(val, hdmi->base + HDMI_FC_INVIDCONF);
+       hdmi_writeb(val, HDMI_FC_INVIDCONF);
 
        /* Set up horizontal active pixel region width */
-       writeb(hdmi->hdmi_data.video_mode.mHActive,
-                       hdmi->base + HDMI_FC_INHACTV0);
-       writeb(hdmi->hdmi_data.video_mode.mHActive >> 8,
-                       hdmi->base + HDMI_FC_INHACTV1);
+       hdmi_writeb(fb_mode.xres,
+                       HDMI_FC_INHACTV0);
+       hdmi_writeb(fb_mode.xres >> 8,
+                       HDMI_FC_INHACTV1);
 
        /* Set up horizontal blanking pixel region width */
-       writeb(hdmi->hdmi_data.video_mode.mHBlanking,
-                       hdmi->base + HDMI_FC_INHBLANK0);
-       writeb(hdmi->hdmi_data.video_mode.mHBlanking >> 8,
-                       hdmi->base + HDMI_FC_INHBLANK1);
+       hblank = fb_mode.left_margin + fb_mode.right_margin +
+               fb_mode.hsync_len;
+       hdmi_writeb(hblank, HDMI_FC_INHBLANK0);
+       hdmi_writeb(hblank >> 8, HDMI_FC_INHBLANK1);
 
        /* Set up vertical blanking pixel region width */
-       writeb(hdmi->hdmi_data.video_mode.mVActive,
-                       hdmi->base + HDMI_FC_INVACTV0);
-       writeb(hdmi->hdmi_data.video_mode.mVActive >> 8,
-                       hdmi->base + HDMI_FC_INVACTV1);
+       hdmi_writeb(fb_mode.yres, HDMI_FC_INVACTV0);
+       hdmi_writeb(fb_mode.yres >> 8, HDMI_FC_INVACTV1);
 
        /* Set up vertical blanking pixel region width */
-       writeb(hdmi->hdmi_data.video_mode.mVBlanking,
-                       hdmi->base + HDMI_FC_INVBLANK);
+       vblank = fb_mode.upper_margin + fb_mode.lower_margin +
+               fb_mode.vsync_len;
+       hdmi_writeb(vblank, HDMI_FC_INVBLANK);
 
        /* Set up HSYNC active edge delay width (in pixel clks) */
-       writeb(hdmi->hdmi_data.video_mode.mHSyncOffset,
-                       hdmi->base + HDMI_FC_HSYNCINDELAY0);
-       writeb(hdmi->hdmi_data.video_mode.mHSyncOffset >> 8,
-                       hdmi->base + HDMI_FC_HSYNCINDELAY1);
+       hdmi_writeb(fb_mode.right_margin, HDMI_FC_HSYNCINDELAY0);
+       hdmi_writeb(fb_mode.right_margin >> 8, HDMI_FC_HSYNCINDELAY1);
 
        /* Set up HSYNC active pulse width (in pixel clks) */
-       writeb(hdmi->hdmi_data.video_mode.mHSyncPulseWidth,
-                       hdmi->base + HDMI_FC_HSYNCINWIDTH0);
-       writeb(hdmi->hdmi_data.video_mode.mHSyncPulseWidth >> 8,
-                       hdmi->base + HDMI_FC_HSYNCINWIDTH1);
-
-       /* Set up vertical blanking pixel region width */
-       writeb(hdmi->hdmi_data.video_mode.mVBlanking,
-                       hdmi->base + HDMI_FC_INVBLANK);
+       hdmi_writeb(fb_mode.hsync_len, HDMI_FC_HSYNCINWIDTH0);
+       hdmi_writeb(fb_mode.hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
 
        /* Set up VSYNC active edge delay (in pixel clks) */
-       writeb(hdmi->hdmi_data.video_mode.mVSyncOffset,
-                       hdmi->base + HDMI_FC_VSYNCINDELAY);
+       hdmi_writeb(fb_mode.lower_margin, HDMI_FC_VSYNCINDELAY);
 
        /* Set up VSYNC active edge delay (in pixel clks) */
-       writeb(hdmi->hdmi_data.video_mode.mVSyncPulseWidth,
-                       hdmi->base + HDMI_FC_VSYNCINWIDTH);
+       hdmi_writeb(fb_mode.vsync_len, HDMI_FC_VSYNCINWIDTH);
 
        /* control period minimum duration */
-       writeb(12, hdmi->base + HDMI_FC_CTRLDUR);
-       writeb(32, hdmi->base + HDMI_FC_EXCTRLDUR);
-       writeb(1, hdmi->base + HDMI_FC_EXCTRLSPAC);
+       hdmi_writeb(12, HDMI_FC_CTRLDUR);
+       hdmi_writeb(32, HDMI_FC_EXCTRLDUR);
+       hdmi_writeb(1, HDMI_FC_EXCTRLSPAC);
 
        for (i = 0; i < 3; i++)
                preamble_filter_set(hdmi, (i + 1) * 11, i);
 
-       /* Set up input and output pixel repetition */
-       val = (((hdmi->hdmi_data.video_mode.mPixelRepetitionInput + 1) <<
-               HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) &
-               HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) |
-               ((0 << HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) &
-               HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK);
-       writeb(val, hdmi->base + HDMI_FC_PRCONF);
-
-       /* AVI - underscan , IT601 */
-       writeb(0x20, hdmi->base + HDMI_FC_AVICONF0);
-       writeb(0x40, hdmi->base + HDMI_FC_AVICONF1);
+       /* configure AVI InfoFrame */
+       hdmi_config_AVI(hdmi);
 }
 
-static void mxc_hdmi_poweron(struct mxc_hdmi *hdmi)
-{
-       struct fsl_mxc_lcd_platform_data *plat = hdmi->pdev->dev.platform_data;
-
-       dev_dbg(&hdmi->pdev->dev, "power on\n");
-
-       /* Enable pins to HDMI */
-       if (plat->enable_pins)
-               plat->enable_pins();
-}
 static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi,
                        struct fb_info *fbi)
 {
@@ -2287,9 +1365,20 @@ static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi,
        return ret;
 }
 
+static void mxc_hdmi_poweron(struct mxc_hdmi *hdmi)
+{
+       struct fsl_mxc_hdmi_platform_data *plat = hdmi->pdev->dev.platform_data;
+
+       dev_dbg(&hdmi->pdev->dev, "power on\n");
+
+       /* Enable pins to HDMI */
+       if (plat->enable_pins)
+               plat->enable_pins();
+}
+
 static void mxc_hdmi_poweroff(struct mxc_hdmi *hdmi)
 {
-       struct fsl_mxc_lcd_platform_data *plat = hdmi->pdev->dev.platform_data;
+       struct fsl_mxc_hdmi_platform_data *plat = hdmi->pdev->dev.platform_data;
 
        dev_dbg(&hdmi->pdev->dev, "power off\n");
 
@@ -2298,18 +1387,281 @@ static void mxc_hdmi_poweroff(struct mxc_hdmi *hdmi)
                plat->disable_pins();
 }
 
+static void mxc_hdmi_rx_powerup(struct mxc_hdmi *hdmi)
+{
+       u8 val;
+
+       dev_dbg(&hdmi->pdev->dev, "rx power up\n");
+
+       /* Enable HDMI PHY - Set PDDQ=0 and TXPWRON=1 */
+       val = hdmi_readb(HDMI_PHY_CONF0);
+       val &= ~(HDMI_PHY_CONF0_GEN2_PDDQ_MASK |
+               HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
+       val |= HDMI_PHY_CONF0_GEN2_PDDQ_DISABLE |
+               HDMI_PHY_CONF0_GEN2_TXPWRON_POWER_ON;
+       hdmi_writeb(val, HDMI_PHY_CONF0);
+
+       if (hdmi->need_mode_change && hdmi->fb_reg) {
+               dev_dbg(&hdmi->pdev->dev, "HDMI changing FB mode\n");
+               hdmi->fbi->var.activate |= FB_ACTIVATE_FORCE;
+               console_lock();
+               hdmi->fbi->flags |= FBINFO_MISC_USEREVENT;
+               fb_set_var(hdmi->fbi, &hdmi->fbi->var);
+               hdmi->fbi->flags &= ~FBINFO_MISC_USEREVENT;
+               console_unlock();
+               hdmi->need_mode_change = false;
+       }
+}
+
+static void mxc_hdmi_rx_powerdown(struct mxc_hdmi *hdmi)
+{
+       u8 val;
+
+       dev_dbg(&hdmi->pdev->dev, "rx power down\n");
+
+       /* Disable HDMI PHY - Set PDDQ=1 and TXPWRON=0 */
+       val = hdmi_readb(HDMI_PHY_CONF0);
+       val &= ~(HDMI_PHY_CONF0_GEN2_PDDQ_MASK |
+               HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
+       val |= HDMI_PHY_CONF0_GEN2_PDDQ_ENABLE |
+               HDMI_PHY_CONF0_GEN2_TXPWRON_POWER_OFF;
+       hdmi_writeb(val, HDMI_PHY_CONF0);
+}
+
+static int mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi)
+{
+       int ret;
+
+       dev_dbg(&hdmi->pdev->dev, "cable connected\n");
+
+       hdmi->cable_plugin = true;
+
+       /* edid read */
+       ret = mxc_hdmi_read_edid(hdmi, hdmi->fbi);
+       if (ret == -1)
+               dev_err(&hdmi->pdev->dev,
+                               "read edid fail\n");
+       else if (ret == -2)
+               dev_info(&hdmi->pdev->dev,
+                               "same edid\n");
+       else {
+               if (hdmi->fbi->monspecs.modedb_len > 0) {
+                       int i;
+                       const struct fb_videomode *mode;
+                       struct fb_videomode m;
+
+                       fb_destroy_modelist(&hdmi->fbi->modelist);
+
+                       for (i = 0; i < hdmi->fbi->monspecs.modedb_len; i++) {
+                               /*
+                                * Check whether mode is supported by HDMI.
+                                * We do not currently support interlaced modes
+                                */
+                               if (mxc_edid_mode_to_vic(&hdmi->fbi->monspecs.modedb[i]) &&
+                                       !(hdmi->fbi->monspecs.modedb[i].vmode
+                                       & FB_VMODE_INTERLACED))
+                                       fb_add_videomode(&hdmi->fbi->monspecs.modedb[i],
+                                                       &hdmi->fbi->modelist);
+                       }
+
+                       fb_var_to_videomode(&m, &hdmi->fbi->var);
+                       mode = fb_find_nearest_mode(&m,
+                                       &hdmi->fbi->modelist);
+
+                       fb_videomode_to_var(&hdmi->fbi->var, mode);
+                       hdmi->need_mode_change = true;
+               }
+       }
+       return 0;
+}
+
+static void mxc_hdmi_cable_disconnected(struct mxc_hdmi *hdmi)
+{
+       hdmi->cable_plugin = false;
+}
+
+static void det_worker(struct work_struct *work)
+{
+       struct delayed_work *delay_work = to_delayed_work(work);
+       struct mxc_hdmi *hdmi =
+               container_of(delay_work, struct mxc_hdmi, det_work);
+       u32 phy_int_stat, phy_int_pol, phy_int_mask;
+       u8 val;
+
+       /* Use saved interrupt status, since it was cleared in IST */
+       phy_int_stat = hdmi->latest_intr_stat;
+       phy_int_pol = hdmi_readb(HDMI_PHY_POL0);
+
+       /* check cable status */
+       if (phy_int_stat & HDMI_IH_PHY_STAT0_HPD) {
+               /* cable connection changes */
+               if (phy_int_pol & HDMI_PHY_HPD) {
+                       dev_dbg(&hdmi->pdev->dev, "EVENT=plugin");
+                       mxc_hdmi_cable_connected(hdmi);
+
+                       /* Make HPD intr active low to capture unplug event */
+                       val = hdmi_readb(HDMI_PHY_POL0);
+                       val &= ~HDMI_PHY_HPD;
+                       hdmi_writeb(val, HDMI_PHY_POL0);
+               } else if (!(phy_int_pol & HDMI_PHY_HPD)) {
+                       dev_dbg(&hdmi->pdev->dev, "EVENT=plugout");
+                       mxc_hdmi_cable_disconnected(hdmi);
+
+                       /* Make HPD intr active high to capture plugin event */
+                       val = hdmi_readb(HDMI_PHY_POL0);
+                       val |= HDMI_PHY_HPD;
+                       hdmi_writeb(val, HDMI_PHY_POL0);
+               } else
+                       dev_dbg(&hdmi->pdev->dev, "EVENT=none?");
+       }
+
+       /* check rx power */
+       if (phy_int_stat & HDMI_IH_PHY_RX_SENSE) {
+               if ((phy_int_pol & HDMI_PHY_RX_SENSE)) {
+                       mxc_hdmi_rx_powerup(hdmi);
+
+                       /* Change RX Sense pol to capture RX disable */
+                       val = hdmi_readb(HDMI_PHY_POL0);
+                       val &= ~HDMI_PHY_RX_SENSE;
+                       hdmi_writeb(val, HDMI_PHY_POL0);
+               } else if (!(phy_int_pol & HDMI_PHY_RX_SENSE)) {
+                       mxc_hdmi_rx_powerdown(hdmi);
+
+                       /* Change RX Sense pol to capture RX enable */
+                       val = hdmi_readb(HDMI_PHY_POL0);
+                       val |= HDMI_PHY_RX_SENSE;
+                       hdmi_writeb(val, HDMI_PHY_POL0);
+               } else
+                       dev_err(&hdmi->pdev->dev,
+                               "Received RX sense event but no change\n");
+       }
+
+       /* Re-enable RX Sense and HPD interrupts */
+       phy_int_mask = hdmi_readb(HDMI_PHY_MASK0);
+       phy_int_mask &= ~(HDMI_PHY_RX_SENSE | HDMI_PHY_HPD);
+       hdmi_writeb(phy_int_mask, HDMI_PHY_MASK0);
+}
+
+static irqreturn_t mxc_hdmi_hotplug(int irq, void *data)
+{
+       struct mxc_hdmi *hdmi = data;
+       u8 val, intr_stat;
+
+       /* Capture status - used in det_worker ISR */
+       intr_stat = hdmi_readb(HDMI_IH_PHY_STAT0);
+       if ((intr_stat & (HDMI_IH_PHY_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) == 0)
+               return IRQ_HANDLED;
+
+       dev_dbg(&hdmi->pdev->dev, "Hotplug interrupt received\n");
+       hdmi->latest_intr_stat = intr_stat;
+
+       /* Unmask interrupts until handled */
+       val = hdmi_readb(HDMI_PHY_MASK0);
+       val |= HDMI_PHY_RX_SENSE | HDMI_PHY_HPD;
+       hdmi_writeb(val, HDMI_PHY_MASK0);
+
+       /* Clear Hotplug/RX Sense interrupts */
+       hdmi_writeb(HDMI_IH_PHY_STAT0_HPD |
+               HDMI_IH_PHY_STAT0_TX_PHY_LOCK |
+               HDMI_IH_PHY_STAT0_RX_SENSE0 |
+               HDMI_IH_PHY_STAT0_RX_SENSE1 |
+               HDMI_IH_PHY_STAT0_RX_SENSE2 |
+               HDMI_IH_PHY_STAT0_RX_SENSE3,
+               HDMI_IH_PHY_STAT0);
+
+       schedule_delayed_work(&(hdmi->det_work), msecs_to_jiffies(20));
+
+       return IRQ_HANDLED;
+}
+
+static int mxc_hdmi_setup(struct mxc_hdmi *hdmi)
+{
+       struct fb_videomode m;
+       const struct fb_videomode *edid_mode;
+
+       fb_var_to_videomode(&m, &hdmi->fbi->var);
+       if (!list_empty(&hdmi->fbi->modelist)) {
+               edid_mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist);
+
+               hdmi->vic = mxc_edid_mode_to_vic(edid_mode);
+       } else
+               hdmi->vic = 0;
+
+       if (hdmi->vic == 0) {
+               dev_dbg(&hdmi->pdev->dev, "Non-CEA mode used in HDMI\n");
+               hdmi->vic = DEFAULT_VIDEO_MODE;
+               hdmi->hdmi_data.video_mode.mHdmiDviSel = FALSE;
+       } else
+               hdmi->hdmi_data.video_mode.mHdmiDviSel = TRUE;
+
+       if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
+               (hdmi->vic == 21) || (hdmi->vic == 22) ||
+               (hdmi->vic == 2) || (hdmi->vic == 3) ||
+               (hdmi->vic == 17) || (hdmi->vic == 18))
+               hdmi->hdmi_data.colorimetry = eITU601;
+       else
+               hdmi->hdmi_data.colorimetry = eITU709;
+
+       if ((hdmi->vic == 10) || (hdmi->vic == 11) ||
+               (hdmi->vic == 12) || (hdmi->vic == 13) ||
+               (hdmi->vic == 14) || (hdmi->vic == 15) ||
+               (hdmi->vic == 25) || (hdmi->vic == 26) ||
+               (hdmi->vic == 27) || (hdmi->vic == 28) ||
+               (hdmi->vic == 29) || (hdmi->vic == 30) ||
+               (hdmi->vic == 35) || (hdmi->vic == 36) ||
+               (hdmi->vic == 37) || (hdmi->vic == 38))
+               hdmi->hdmi_data.video_mode.mPixelRepetitionOutput = 1;
+       else
+               hdmi->hdmi_data.video_mode.mPixelRepetitionOutput = 0;
+
+       hdmi->hdmi_data.video_mode.mPixelRepetitionInput = 0;
+
+       /* TODO: Get input format from IPU (via FB driver iface) */
+       hdmi->hdmi_data.enc_in_format = eRGB;
+
+       hdmi->hdmi_data.enc_out_format = RGB;
+       if (hdmi->edid_cfg.hdmi_cap) {
+               if (hdmi->edid_cfg.cea_ycbcr444)
+                       hdmi->hdmi_data.enc_out_format = YCBCR444;
+               else if (hdmi->edid_cfg.cea_ycbcr422)
+                       hdmi->hdmi_data.enc_out_format = YCBCR422_8BITS;
+       }
+
+       hdmi->hdmi_data.enc_color_depth = 8;
+       hdmi->hdmi_data.pix_repet_factor = 0;
+       hdmi->hdmi_data.hdcp_enable = 0;
+       hdmi->hdmi_data.video_mode.mDataEnablePolarity = TRUE;
+
+       hdmi_video_force_output(hdmi, TRUE);
+       hdmi_av_composer(hdmi);
+       hdmi_video_packetize(hdmi);
+       hdmi_video_csc(hdmi);
+       hdmi_video_sample(hdmi);
+       hdmi_tx_hdcp_config(hdmi);
+       hdmi_phy_init(hdmi, TRUE);
+       hdmi_video_force_output(hdmi, FALSE);
+
+       return 0;
+}
+
 static int mxc_hdmi_fb_event(struct notifier_block *nb,
                                        unsigned long val, void *v)
 {
        struct fb_event *event = v;
-       struct fb_info *fbi = event->info;
        struct mxc_hdmi *hdmi = container_of(nb, struct mxc_hdmi, nb);
 
        if (strcmp(event->info->fix.id, hdmi->fbi->fix.id))
                return 0;
 
        switch (val) {
+       case FB_EVENT_FB_REGISTERED:
+               hdmi->fb_reg = true;
+               break;
+       case FB_EVENT_FB_UNREGISTERED:
+               hdmi->fb_reg = false;
+               break;
        case FB_EVENT_MODE_CHANGE:
+               mxc_hdmi_setup(hdmi);
                break;
        case FB_EVENT_BLANK:
                if (*((int *)event->data) == FB_BLANK_UNBLANK)
@@ -2321,51 +1673,17 @@ static int mxc_hdmi_fb_event(struct notifier_block *nb,
        return 0;
 }
 
-static bool hdmi_is_mode_equal(struct fb_videomode *mode1,
-       struct fb_videomode *mode2)
-{
-       if ((mode1->xres == mode2->xres) &&
-               (mode1->yres == mode2->yres) &&
-               ((mode1->refresh >= mode2->refresh - 1) &&
-               (mode1->refresh <= mode2->refresh + 1)) &&
-               ((mode1->flag & mode2->flag) == mode2->flag))
-               return true;
-       else
-               return false;
-}
-
-static int mxc_hdmi_get_vmode(struct fb_info *fbi)
-{
-       int i;
-       int vci_code = 0;
-       struct fb_videomode m;
-
-       fb_var_to_videomode(&m, &fbi->var);
-
-       for (i = 1; i < NUM_CEA_VIDEO_MODES; i++)
-               if (hdmi_is_mode_equal(&m, &hdmi_cea_video_modes[i-1])) {
-                       vci_code = i;
-                       break;
-               }
-
-       return vci_code;
-}
-
-
 static int mxc_hdmi_disp_init(struct mxc_dispdrv_entry *disp)
 {
        int ret = 0;
        struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
        struct mxc_dispdrv_setting *setting = mxc_dispdrv_getsetting(disp);
-       struct fsl_mxc_lcd_platform_data *plat = hdmi->pdev->dev.platform_data;
-       struct resource *res =
-               platform_get_resource(hdmi->pdev, IORESOURCE_MEM, 0);
+       struct fsl_mxc_hdmi_platform_data *plat = hdmi->pdev->dev.platform_data;
        int irq = platform_get_irq(hdmi->pdev, 0);
        bool found = false;
-       int i;
-       int mCode;
+       u8 val;
 
-       if (!res || !plat || irq < 0)
+       if (!plat || irq < 0)
                return -ENODEV;
 
        setting->dev_id = plat->ipu_id;
@@ -2374,23 +1692,6 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_entry *disp)
 
        hdmi->fbi = setting->fbi;
 
-       if (plat->io_reg) {
-               hdmi->io_reg = regulator_get(&hdmi->pdev->dev, plat->io_reg);
-               if (!IS_ERR(hdmi->io_reg)) {
-                       regulator_set_voltage(hdmi->io_reg, 3300000, 3300000);
-                       regulator_enable(hdmi->io_reg);
-               }
-       }
-       if (plat->analog_reg) {
-               hdmi->analog_reg =
-                       regulator_get(&hdmi->pdev->dev, plat->analog_reg);
-               if (!IS_ERR(hdmi->analog_reg)) {
-                       regulator_set_voltage(hdmi->analog_reg,
-                                               1300000, 1300000);
-                       regulator_enable(hdmi->analog_reg);
-               }
-       }
-
        /* Claim HDMI pins */
        if (plat->get_pins)
                if (!plat->get_pins()) {
@@ -2398,6 +1699,10 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_entry *disp)
                        goto egetpins;
                }
 
+       /* Initialize HDMI */
+       if (plat->init)
+               plat->init(plat->ipu_id, plat->disp_id);
+
        hdmi->hdmi_clk = clk_get(&hdmi->pdev->dev, "hdmi_isfr_clk");
        if (IS_ERR(hdmi->hdmi_clk)) {
                ret = PTR_ERR(hdmi->hdmi_clk);
@@ -2414,68 +1719,58 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_entry *disp)
        }
        dev_dbg(&hdmi->pdev->dev, "Enabled HDMI clocks\n");
 
-       if (!request_mem_region(res->start, resource_size(res),
-                               dev_name(&hdmi->pdev->dev))) {
-               dev_err(&hdmi->pdev->dev,
-                       "HDMI register region already claimed\n");
-               ret = -EBUSY;
-               goto ereqreg;
-       }
-
-       hdmi->base = ioremap(res->start, resource_size(res));
-       if (!hdmi->base) {
-               dev_err(&hdmi->pdev->dev,
-                       "HDMI register iomap failed\n");
-               ret = -ENOMEM;
-               goto emap;
-       }
-
        /* Product and revision IDs */
        dev_info(&hdmi->pdev->dev,
                "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
-               readb(hdmi->base + HDMI_DESIGN_ID),
-               readb(hdmi->base + HDMI_REVISION_ID),
-               readb(hdmi->base + HDMI_PRODUCT_ID0),
-               readb(hdmi->base + HDMI_PRODUCT_ID1));
+               hdmi_readb(HDMI_DESIGN_ID),
+               hdmi_readb(HDMI_REVISION_ID),
+               hdmi_readb(HDMI_PRODUCT_ID0),
+               hdmi_readb(HDMI_PRODUCT_ID1));
 
-       ret = request_irq(irq, mxc_hdmi_hotplug, 0,
-                         dev_name(&hdmi->pdev->dev), hdmi);
-       if (ret < 0) {
-               dev_err(&hdmi->pdev->dev, "Unable to request irq: %d\n", ret);
-               goto ereqirq;
-       }
+       INIT_LIST_HEAD(&hdmi->fbi->modelist);
 
        /* try to read edid */
        ret = mxc_hdmi_read_edid(hdmi, hdmi->fbi);
        if (ret < 0)
                dev_warn(&hdmi->pdev->dev, "Can not read edid\n");
-       else {
-               INIT_LIST_HEAD(&hdmi->fbi->modelist);
-               if (hdmi->fbi->monspecs.modedb_len > 0) {
-                       int i;
-                       const struct fb_videomode *mode;
-                       struct fb_videomode m;
-
-                       for (i = 0; i < hdmi->fbi->monspecs.modedb_len; i++) {
-                               /*FIXME now we do not support interlaced mode */
-                               if (!(hdmi->fbi->monspecs.modedb[i].vmode
-                                               & FB_VMODE_INTERLACED)) {
-                                       fb_add_videomode(
-                                               &hdmi->fbi->monspecs.modedb[i],
-                                               &hdmi->fbi->modelist);
-                               }
+       else if (hdmi->fbi->monspecs.modedb_len > 0) {
+               int i;
+               const struct fb_videomode *mode;
+               struct fb_videomode m;
+               struct fb_var_screeninfo var;
+
+               for (i = 0; i < hdmi->fbi->monspecs.modedb_len; i++) {
+                       /*
+                        * Check whether mode is supported by HDMI.
+                        * Also, we do not currently support interlaced modes
+                        */
+                       fb_videomode_to_var(&var, &hdmi->fbi->monspecs.modedb[i]);
+                       if (mxc_edid_mode_to_vic(&hdmi->fbi->monspecs.modedb[i]) &&
+                               !(hdmi->fbi->monspecs.modedb[i].vmode
+                               & FB_VMODE_INTERLACED)) {
+                               dev_dbg(&hdmi->pdev->dev, "Adding mode %d:", i);
+                               dev_dbg(&hdmi->pdev->dev,
+                                       "xres = %d, yres = %d, freq = %d\n",
+                                       hdmi->fbi->monspecs.modedb[i].xres,
+                                       hdmi->fbi->monspecs.modedb[i].yres,
+                                       hdmi->fbi->monspecs.modedb[i].refresh);
+                               fb_add_videomode(
+                                       &hdmi->fbi->monspecs.modedb[i],
+                                       &hdmi->fbi->modelist);
                        }
+               }
 
-                       fb_find_mode(&hdmi->fbi->var, hdmi->fbi,
-                               setting->dft_mode_str, NULL, 0, NULL,
-                               setting->default_bpp);
+               fb_find_mode(&hdmi->fbi->var, hdmi->fbi,
+                       setting->dft_mode_str, NULL, 0, NULL,
+                       setting->default_bpp);
 
-                       fb_var_to_videomode(&m, &hdmi->fbi->var);
-                       mode = fb_find_nearest_mode(&m,
-                                       &hdmi->fbi->modelist);
-                       fb_videomode_to_var(&hdmi->fbi->var, mode);
-                       found = 1;
-               }
+               fb_var_to_videomode(&m, &hdmi->fbi->var);
+               mode = fb_find_nearest_mode(&m,
+                               &hdmi->fbi->modelist);
+               fb_videomode_to_var(&hdmi->fbi->var, mode);
+               found = 1;
+
+               hdmi->need_mode_change = true;
        }
 
        if (!found) {
@@ -2488,38 +1783,50 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_entry *disp)
                }
        }
 
+       ret = request_irq(irq, mxc_hdmi_hotplug, IRQF_SHARED,
+                         dev_name(&hdmi->pdev->dev), hdmi);
+       if (ret < 0) {
+               dev_err(&hdmi->pdev->dev,
+                       "Unable to request irq: %d\n", ret);
+               goto ereqirq;
+       }
+
+       INIT_DELAYED_WORK(&(hdmi->det_work), det_worker);
+
+       /* Configure registers related to HDMI interrupt
+        * generation before registering IRQ. */
+       hdmi_writeb(HDMI_PHY_RX_SENSE | HDMI_PHY_HPD,
+               HDMI_PHY_POL0);
+
+       /* enable cable hot plug irq */
+       val = HDMI_PHY_RX_SENSE | HDMI_PHY_HPD;
+       val = ~val;
+       hdmi_writeb(val, HDMI_PHY_MASK0);
+
+       /* Clear Hotplug/RX Sense interrupts */
+       hdmi_writeb(HDMI_IH_PHY_STAT0_HPD |
+               HDMI_IH_PHY_STAT0_TX_PHY_LOCK |
+               HDMI_IH_PHY_STAT0_RX_SENSE0 |
+               HDMI_IH_PHY_STAT0_RX_SENSE1 |
+               HDMI_IH_PHY_STAT0_RX_SENSE2 |
+               HDMI_IH_PHY_STAT0_RX_SENSE3,
+               HDMI_IH_PHY_STAT0);
+
+       hdmi_writeb(~(HDMI_IH_PHY_STAT0_HPD |
+               HDMI_IH_PHY_STAT0_RX_SENSE0 |
+               HDMI_IH_PHY_STAT0_RX_SENSE1 |
+               HDMI_IH_PHY_STAT0_RX_SENSE2 |
+               HDMI_IH_PHY_STAT0_RX_SENSE3),
+               HDMI_IH_MUTE_PHY_STAT0);
+
        hdmi->nb.notifier_call = mxc_hdmi_fb_event;
        ret = fb_register_client(&hdmi->nb);
        if (ret < 0)
                goto efbclient;
 
-       mCode = mxc_hdmi_get_vmode(hdmi->fbi);
-       if (mCode == 0)
-               mCode = DEFAULT_VIDEO_MODE;
-
        memset(&hdmi->hdmi_data, 0, sizeof(struct hdmi_data_info));
 
-       hdmi->hdmi_data.enc_in_format = eRGB;
-       hdmi->hdmi_data.enc_out_format = eRGB;
-       hdmi->hdmi_data.enc_color_depth = 8;
-       hdmi->hdmi_data.colorimetry = eITU601;
-       hdmi->hdmi_data.pix_repet_factor = 0;
-       hdmi->hdmi_data.hdcp_enable = 0;
-       hdmi->hdmi_data.video_mode.mCode = mCode;
-       hdmi->hdmi_data.video_mode.mHdmiDviSel = TRUE;
-       hdmi->hdmi_data.video_mode.mRVBlankInOSC = FALSE;
-       hdmi->hdmi_data.video_mode.mRefreshRate = 60000;
-       hdmi->hdmi_data.video_mode.mDataEnablePolarity = TRUE;
-
-       hdmi_video_force_output(hdmi, TRUE);
-       hdmi_av_composer(hdmi);
-       hdmi_video_packetize(hdmi);
-       hdmi_video_csc(hdmi);
-       hdmi_video_sample(hdmi);
-       hdmi_audio_mute(hdmi, TRUE);
-       hdmi_tx_hdcp_config(hdmi);
-       hdmi_phy_init(hdmi, TRUE);
-       hdmi_video_force_output(hdmi, FALSE);
+       mxc_hdmi_setup(hdmi);
 
        return ret;
 
@@ -2527,10 +1834,6 @@ efbclient:
        free_irq(irq, hdmi);
 efindmode:
 ereqirq:
-       iounmap(hdmi->base);
-emap:
-       release_mem_region(res->start, resource_size(res));
-ereqreg:
        clk_disable(hdmi->hdmi_clk);
 erate:
        clk_put(hdmi->hdmi_clk);
@@ -2542,7 +1845,7 @@ egetpins:
 static void mxc_hdmi_disp_deinit(struct mxc_dispdrv_entry *disp)
 {
        struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp);
-       struct fsl_mxc_lcd_platform_data *plat = hdmi->pdev->dev.platform_data;
+       struct fsl_mxc_hdmi_platform_data *plat = hdmi->pdev->dev.platform_data;
 
        fb_unregister_client(&hdmi->nb);
 
@@ -2563,7 +1866,7 @@ static struct mxc_dispdrv_driver mxc_hdmi_drv = {
        .deinit = mxc_hdmi_disp_deinit,
 };
 
-static int __init mxc_hdmi_probe(struct platform_device *pdev)
+static int __devinit mxc_hdmi_probe(struct platform_device *pdev)
 {
        struct mxc_hdmi *hdmi;
        int ret = 0;
@@ -2581,6 +1884,14 @@ static int __init mxc_hdmi_probe(struct platform_device *pdev)
 
        hdmi->pdev = pdev;
 
+       hdmi->core_pdev = platform_device_alloc("mxc_hdmi_core", -1);
+       if (!hdmi->core_pdev) {
+               pr_err("%s failed platform_device_alloc for hdmi core\n",
+                       __func__);
+               ret = -ENOMEM;
+               goto ecore;
+       }
+
        hdmi->disp_mxc_hdmi = mxc_dispdrv_register(&mxc_hdmi_drv);
        if (IS_ERR(hdmi->disp_mxc_hdmi)) {
                dev_err(&pdev->dev, "Failed to register dispdrv - 0x%x\n",
@@ -2594,16 +1905,16 @@ static int __init mxc_hdmi_probe(struct platform_device *pdev)
 
        return 0;
 edispdrv:
+       platform_device_put(hdmi->core_pdev);
+ecore:
        kfree(hdmi);
 ealloc:
        return ret;
 }
 
-static int  mxc_hdmi_remove(struct platform_device *pdev)
+static int mxc_hdmi_remove(struct platform_device *pdev)
 {
-       struct fsl_mxc_lcd_platform_data *pdata = pdev->dev.platform_data;
        struct mxc_hdmi *hdmi = platform_get_drvdata(pdev);
-       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        int irq = platform_get_irq(pdev, 0);
 
        fb_unregister_client(&hdmi->nb);
@@ -2612,8 +1923,6 @@ static int  mxc_hdmi_remove(struct platform_device *pdev)
        free_irq(irq, hdmi);
        clk_disable(hdmi->hdmi_clk);
        clk_put(hdmi->hdmi_clk);
-       iounmap(hdmi->base);
-       release_mem_region(res->start, resource_size(res));
        kfree(hdmi);
 
        return 0;
index b54458f25fb5d5fe7317cb3d167bb21a0938a88c..2b8fc9b61efb291ee4d6919e9cf4ae72ea59abe2 100644 (file)
@@ -235,6 +235,16 @@ struct fsl_mxc_dvi_platform_data {
        int disp_id;
 };
 
+struct fsl_mxc_hdmi_platform_data {
+       void (*init) (int, int);
+       int (*get_pins) (void);
+       void (*put_pins) (void);
+       void (*enable_pins) (void);
+       void (*disable_pins) (void);
+       int ipu_id;
+       int disp_id;
+};
+
 struct fsl_mxc_camera_platform_data {
        char *core_regulator;
        char *io_regulator;