diff options
author | Danny Nold <dannynold@freescale.com> | 2011-09-01 22:46:05 -0500 |
---|---|---|
committer | Danny Nold <dannynold@freescale.com> | 2011-09-02 16:47:19 -0500 |
commit | b337f54a44761f5760eb495c29969ba38a801ec6 (patch) | |
tree | d42ae7407b31510c57fd61b374ffab5bd7068aaf | |
parent | 2a2d8cfdd72e3940f38b9faf49767b77c16ef6f6 (diff) |
ENGR00154436-2 - MXC HDMI: Support complete feature set
- 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>
-rw-r--r-- | drivers/mxc/ipu3/ipu_common.c | 18 | ||||
-rw-r--r-- | drivers/video/mxc/mxc_edid.c | 108 | ||||
-rw-r--r-- | drivers/video/mxc_hdmi.c | 2187 | ||||
-rw-r--r-- | include/linux/fsl_devices.h | 10 |
4 files changed, 856 insertions, 1467 deletions
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c index 11e8a580cdc2..5cb9dc0b474e 100644 --- a/drivers/mxc/ipu3/ipu_common.c +++ b/drivers/mxc/ipu3/ipu_common.c @@ -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); diff --git a/drivers/video/mxc/mxc_edid.c b/drivers/video/mxc/mxc_edid.c index 9c4f094ea166..9e7c87ef43cc 100644 --- a/drivers/video/mxc/mxc_edid.c +++ b/drivers/video/mxc/mxc_edid.c @@ -40,80 +40,120 @@ #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) diff --git a/drivers/video/mxc_hdmi.c b/drivers/video/mxc_hdmi.c index 383e738224e6..7690151e9d1a 100644 --- a/drivers/video/mxc_hdmi.c +++ b/drivers/video/mxc_hdmi.c @@ -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" @@ -67,352 +67,18 @@ #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; diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 22635b152bd2..4f9e869a4fae 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -230,6 +230,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; |