diff options
author | G, Manjunath Kondaiah <manjugk@ti.com> | 2010-12-19 09:55:02 +0530 |
---|---|---|
committer | G, Manjunath Kondaiah <manjugk@ti.com> | 2010-12-19 09:55:02 +0530 |
commit | 775a5129281078d91885ec86c53fe13aea7edfdf (patch) | |
tree | f17bce8619816d745517b5f023c08874460f62ae | |
parent | d68961fb940a6ab2fadd27b0217e7ca3e8adcbd9 (diff) | |
parent | 3f6ac2150ccb81ece59d77b471cc274ee4ec8b15 (diff) |
Merge branch 'display-next_integ' of git://dev.omapzoom.org/pub/scm/axelcx/kernel-display into L24.11
-rw-r--r-- | arch/arm/plat-omap/hdmi_lib.c | 734 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/edid.h | 387 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/hdmi_lib.h | 32 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 55 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dpi.c | 1 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 4 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.h | 1 | ||||
-rw-r--r-- | drivers/video/omap2/dss/edid.c | 331 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 802 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi.h | 339 |
10 files changed, 1420 insertions, 1266 deletions
diff --git a/arch/arm/plat-omap/hdmi_lib.c b/arch/arm/plat-omap/hdmi_lib.c index 2afba9184b37..3ac54ebd5f78 100644 --- a/arch/arm/plat-omap/hdmi_lib.c +++ b/arch/arm/plat-omap/hdmi_lib.c @@ -17,14 +17,14 @@ /* Rev history: * Yong Zhi <y-zhi@ti.com> changed SiVal macros - * added PLL/PHY code + * added PLL/PHY code * added EDID code - * moved PLL/PHY code to hdmi panel driver - * cleanup 2/08/10 - * MythriPk <mythripk@ti.com> Apr 2010 Modified to read extended EDID partition - * and handle checksum with and without extension + * moved PLL/PHY code to hdmi panel driver + * cleanup 2/08/10 + * MythriPk <mythripk@ti.com> Apr 2010 Modified to read extended EDID + * partition and handle checksum with and without + * extension * May 2010 Added support for Hot Plug Detect. - * */ #define DSS_SUBSYS_NAME "HDMI" @@ -41,180 +41,177 @@ #include <linux/seq_file.h> /* HDMI PHY */ -#define HDMI_TXPHY_TX_CTRL 0x0ul -#define HDMI_TXPHY_DIGITAL_CTRL 0x4ul -#define HDMI_TXPHY_POWER_CTRL 0x8ul +#define HDMI_TXPHY_TX_CTRL 0x0ul +#define HDMI_TXPHY_DIGITAL_CTRL 0x4ul +#define HDMI_TXPHY_POWER_CTRL 0x8ul /* HDMI Wrapper */ -#define HDMI_WP_REVISION 0x0ul -#define HDMI_WP_SYSCONFIG 0x10ul -#define HDMI_WP_IRQSTATUS_RAW 0x24ul -#define HDMI_WP_IRQSTATUS 0x28ul -#define HDMI_WP_PWR_CTRL 0x40ul -#define HDMI_WP_IRQENABLE_SET 0x2Cul -#define HDMI_WP_VIDEO_CFG 0x50ul -#define HDMI_WP_VIDEO_SIZE 0x60ul -#define HDMI_WP_VIDEO_TIMING_H 0x68ul -#define HDMI_WP_VIDEO_TIMING_V 0x6Cul -#define HDMI_WP_WP_CLK 0x70ul +#define HDMI_WP_REVISION 0x0ul +#define HDMI_WP_SYSCONFIG 0x10ul +#define HDMI_WP_IRQSTATUS_RAW 0x24ul +#define HDMI_WP_IRQSTATUS 0x28ul +#define HDMI_WP_PWR_CTRL 0x40ul +#define HDMI_WP_IRQENABLE_SET 0x2Cul +#define HDMI_WP_VIDEO_CFG 0x50ul +#define HDMI_WP_VIDEO_SIZE 0x60ul +#define HDMI_WP_VIDEO_TIMING_H 0x68ul +#define HDMI_WP_VIDEO_TIMING_V 0x6Cul +#define HDMI_WP_WP_CLK 0x70ul /* HDMI IP Core System */ -#define HDMI_CORE_SYS__VND_IDL 0x0ul -#define HDMI_CORE_SYS__DEV_IDL 0x8ul -#define HDMI_CORE_SYS__DEV_IDH 0xCul -#define HDMI_CORE_SYS__DEV_REV 0x10ul -#define HDMI_CORE_SYS__SRST 0x14ul -#define HDMI_CORE_CTRL1 0x20ul -#define HDMI_CORE_SYS__SYS_STAT 0x24ul -#define HDMI_CORE_SYS__VID_ACEN 0x124ul -#define HDMI_CORE_SYS__VID_MODE 0x128ul -#define HDMI_CORE_SYS__VID_CTRL 0x120ul -#define HDMI_CORE_SYS__INTR_STATE 0x1C0ul -#define HDMI_CORE_SYS__INTR1 0x1C4ul -#define HDMI_CORE_SYS__INTR2 0x1C8ul -#define HDMI_CORE_SYS__INTR3 0x1CCul -#define HDMI_CORE_SYS__INTR4 0x1D0ul -#define HDMI_CORE_SYS__UMASK1 0x1D4ul -#define HDMI_CORE_SYS__TMDS_CTRL 0x208ul -#define HDMI_CORE_CTRL1_VEN__FOLLOWVSYNC 0x1ul -#define HDMI_CORE_CTRL1_HEN__FOLLOWHSYNC 0x1ul -#define HDMI_CORE_CTRL1_BSEL__24BITBUS 0x1ul -#define HDMI_CORE_CTRL1_EDGE__RISINGEDGE 0x1ul - -#define HDMI_CORE_SYS__DE_DLY 0xC8ul -#define HDMI_CORE_SYS__DE_CTRL 0xCCul -#define HDMI_CORE_SYS__DE_TOP 0xD0ul -#define HDMI_CORE_SYS__DE_CNTL 0xD8ul -#define HDMI_CORE_SYS__DE_CNTH 0xDCul -#define HDMI_CORE_SYS__DE_LINL 0xE0ul -#define HDMI_CORE_SYS__DE_LINH__1 0xE4ul +#define HDMI_CORE_SYS__VND_IDL 0x0ul +#define HDMI_CORE_SYS__DEV_IDL 0x8ul +#define HDMI_CORE_SYS__DEV_IDH 0xCul +#define HDMI_CORE_SYS__DEV_REV 0x10ul +#define HDMI_CORE_SYS__SRST 0x14ul +#define HDMI_CORE_CTRL1 0x20ul +#define HDMI_CORE_SYS__SYS_STAT 0x24ul +#define HDMI_CORE_SYS__VID_ACEN 0x124ul +#define HDMI_CORE_SYS__VID_MODE 0x128ul +#define HDMI_CORE_SYS__VID_CTRL 0x120ul +#define HDMI_CORE_SYS__INTR_STATE 0x1C0ul +#define HDMI_CORE_SYS__INTR1 0x1C4ul +#define HDMI_CORE_SYS__INTR2 0x1C8ul +#define HDMI_CORE_SYS__INTR3 0x1CCul +#define HDMI_CORE_SYS__INTR4 0x1D0ul +#define HDMI_CORE_SYS__UMASK1 0x1D4ul +#define HDMI_CORE_SYS__TMDS_CTRL 0x208ul +#define HDMI_CORE_CTRL1_VEN__FOLLOWVSYNC 0x1ul +#define HDMI_CORE_CTRL1_HEN__FOLLOWHSYNC 0x1ul +#define HDMI_CORE_CTRL1_BSEL__24BITBUS 0x1ul +#define HDMI_CORE_CTRL1_EDGE__RISINGEDGE 0x1ul + +#define HDMI_CORE_SYS__DE_DLY 0xC8ul +#define HDMI_CORE_SYS__DE_CTRL 0xCCul +#define HDMI_CORE_SYS__DE_TOP 0xD0ul +#define HDMI_CORE_SYS__DE_CNTL 0xD8ul +#define HDMI_CORE_SYS__DE_CNTH 0xDCul +#define HDMI_CORE_SYS__DE_LINL 0xE0ul +#define HDMI_CORE_SYS__DE_LINH__1 0xE4ul /* HDMI IP Core Audio Video */ -#define HDMI_CORE_AV_HDMI_CTRL 0xBCul -#define HDMI_CORE_AV_DPD 0xF4ul -#define HDMI_CORE_AV_PB_CTRL1 0xF8ul -#define HDMI_CORE_AV_PB_CTRL2 0xFCul -#define HDMI_CORE_AV_AVI_TYPE 0x100ul -#define HDMI_CORE_AV_AVI_VERS 0x104ul -#define HDMI_CORE_AV_AVI_LEN 0x108ul -#define HDMI_CORE_AV_AVI_CHSUM 0x10Cul -#define HDMI_CORE_AV_AVI_DBYTE 0x110ul +#define HDMI_CORE_AV_HDMI_CTRL 0xBCul +#define HDMI_CORE_AV_DPD 0xF4ul +#define HDMI_CORE_AV_PB_CTRL1 0xF8ul +#define HDMI_CORE_AV_PB_CTRL2 0xFCul +#define HDMI_CORE_AV_AVI_TYPE 0x100ul +#define HDMI_CORE_AV_AVI_VERS 0x104ul +#define HDMI_CORE_AV_AVI_LEN 0x108ul +#define HDMI_CORE_AV_AVI_CHSUM 0x10Cul +#define HDMI_CORE_AV_AVI_DBYTE 0x110ul #define HDMI_CORE_AV_AVI_DBYTE__ELSIZE 0x4ul /* HDMI DDC E-DID */ -#define HDMI_CORE_DDC_CMD 0x3CCul +#define HDMI_CORE_DDC_CMD 0x3CCul #define HDMI_CORE_DDC_STATUS 0x3C8ul -#define HDMI_CORE_DDC_ADDR 0x3B4ul +#define HDMI_CORE_DDC_ADDR 0x3B4ul #define HDMI_CORE_DDC_OFFSET 0x3BCul #define HDMI_CORE_DDC_COUNT1 0x3C0ul #define HDMI_CORE_DDC_COUNT2 0x3C4ul -#define HDMI_CORE_DDC_DATA 0x3D0ul -#define HDMI_CORE_DDC_SEGM 0x3B8ul - -#define HDMI_WP_AUDIO_CFG 0x80ul -#define HDMI_WP_AUDIO_CFG2 0x84ul -#define HDMI_WP_AUDIO_CTRL 0x88ul -#define HDMI_WP_AUDIO_DATA 0x8Cul - -#define HDMI_CORE_AV__AVI_DBYTE 0x110ul -#define HDMI_CORE_AV__AVI_DBYTE__ELSIZE 0x4ul -#define HDMI_IP_CORE_AV__AVI_DBYTE__NELEMS 15 -#define HDMI_CORE_AV__SPD_DBYTE 0x190ul -#define HDMI_CORE_AV__SPD_DBYTE__ELSIZE 0x4ul -#define HDMI_CORE_AV__SPD_DBYTE__NELEMS 27 -#define HDMI_CORE_AV__AUDIO_DBYTE 0x210ul -#define HDMI_CORE_AV__AUDIO_DBYTE__ELSIZE 0x4ul -#define HDMI_CORE_AV__AUDIO_DBYTE__NELEMS 10 -#define HDMI_CORE_AV__MPEG_DBYTE 0x290ul -#define HDMI_CORE_AV__MPEG_DBYTE__ELSIZE 0x4ul -#define HDMI_CORE_AV__MPEG_DBYTE__NELEMS 27 -#define HDMI_CORE_AV__GEN_DBYTE 0x300ul -#define HDMI_CORE_AV__GEN_DBYTE__ELSIZE 0x4ul -#define HDMI_CORE_AV__GEN_DBYTE__NELEMS 31 -#define HDMI_CORE_AV__GEN2_DBYTE 0x380ul -#define HDMI_CORE_AV__GEN2_DBYTE__ELSIZE 0x4ul -#define HDMI_CORE_AV__GEN2_DBYTE__NELEMS 31 -#define HDMI_CORE_AV__ACR_CTRL 0x4ul -#define HDMI_CORE_AV__FREQ_SVAL 0x8ul -#define HDMI_CORE_AV__N_SVAL1 0xCul -#define HDMI_CORE_AV__N_SVAL2 0x10ul -#define HDMI_CORE_AV__N_SVAL3 0x14ul -#define HDMI_CORE_AV__CTS_SVAL1 0x18ul -#define HDMI_CORE_AV__CTS_SVAL2 0x1Cul -#define HDMI_CORE_AV__CTS_SVAL3 0x20ul -#define HDMI_CORE_AV__CTS_HVAL1 0x24ul -#define HDMI_CORE_AV__CTS_HVAL2 0x28ul -#define HDMI_CORE_AV__CTS_HVAL3 0x2Cul -#define HDMI_CORE_AV__AUD_MODE 0x50ul -#define HDMI_CORE_AV__SPDIF_CTRL 0x54ul -#define HDMI_CORE_AV__HW_SPDIF_FS 0x60ul -#define HDMI_CORE_AV__SWAP_I2S 0x64ul -#define HDMI_CORE_AV__SPDIF_ERTH 0x6Cul -#define HDMI_CORE_AV__I2S_IN_MAP 0x70ul -#define HDMI_CORE_AV__I2S_IN_CTRL 0x74ul -#define HDMI_CORE_AV__I2S_CHST0 0x78ul -#define HDMI_CORE_AV__I2S_CHST1 0x7Cul -#define HDMI_CORE_AV__I2S_CHST2 0x80ul -#define HDMI_CORE_AV__I2S_CHST4 0x84ul -#define HDMI_CORE_AV__I2S_CHST5 0x88ul -#define HDMI_CORE_AV__ASRC 0x8Cul -#define HDMI_CORE_AV__I2S_IN_LEN 0x90ul -#define HDMI_CORE_AV__HDMI_CTRL 0xBCul -#define HDMI_CORE_AV__AUDO_TXSTAT 0xC0ul -#define HDMI_CORE_AV__AUD_PAR_BUSCLK_1 0xCCul -#define HDMI_CORE_AV__AUD_PAR_BUSCLK_2 0xD0ul -#define HDMI_CORE_AV__AUD_PAR_BUSCLK_3 0xD4ul -#define HDMI_CORE_AV__TEST_TXCTRL 0xF0ul -#define HDMI_CORE_AV__DPD 0xF4ul -#define HDMI_CORE_AV__PB_CTRL1 0xF8ul -#define HDMI_CORE_AV__PB_CTRL2 0xFCul -#define HDMI_CORE_AV__AVI_TYPE 0x100ul -#define HDMI_CORE_AV__AVI_VERS 0x104ul -#define HDMI_CORE_AV__AVI_LEN 0x108ul -#define HDMI_CORE_AV__AVI_CHSUM 0x10Cul -#define HDMI_CORE_AV__SPD_TYPE 0x180ul -#define HDMI_CORE_AV__SPD_VERS 0x184ul -#define HDMI_CORE_AV__SPD_LEN 0x188ul -#define HDMI_CORE_AV__SPD_CHSUM 0x18Cul -#define HDMI_CORE_AV__AUDIO_TYPE 0x200ul -#define HDMI_CORE_AV__AUDIO_VERS 0x204ul -#define HDMI_CORE_AV__AUDIO_LEN 0x208ul -#define HDMI_CORE_AV__AUDIO_CHSUM 0x20Cul -#define HDMI_CORE_AV__MPEG_TYPE 0x280ul -#define HDMI_CORE_AV__MPEG_VERS 0x284ul -#define HDMI_CORE_AV__MPEG_LEN 0x288ul -#define HDMI_CORE_AV__MPEG_CHSUM 0x28Cul -#define HDMI_CORE_AV__CP_BYTE1 0x37Cul -#define HDMI_CORE_AV__CEC_ADDR_ID 0x3FCul - +#define HDMI_CORE_DDC_DATA 0x3D0ul +#define HDMI_CORE_DDC_SEGM 0x3B8ul + +#define HDMI_WP_AUDIO_CFG 0x80ul +#define HDMI_WP_AUDIO_CFG2 0x84ul +#define HDMI_WP_AUDIO_CTRL 0x88ul +#define HDMI_WP_AUDIO_DATA 0x8Cul + +#define HDMI_CORE_AV__AVI_DBYTE 0x110ul +#define HDMI_CORE_AV__AVI_DBYTE__ELSIZE 0x4ul +#define HDMI_IP_CORE_AV__AVI_DBYTE__NELEMS 15 +#define HDMI_CORE_AV__SPD_DBYTE 0x190ul +#define HDMI_CORE_AV__SPD_DBYTE__ELSIZE 0x4ul +#define HDMI_CORE_AV__SPD_DBYTE__NELEMS 27 +#define HDMI_CORE_AV__AUDIO_DBYTE 0x210ul +#define HDMI_CORE_AV__AUDIO_DBYTE__ELSIZE 0x4ul +#define HDMI_CORE_AV__AUDIO_DBYTE__NELEMS 10 +#define HDMI_CORE_AV__MPEG_DBYTE 0x290ul +#define HDMI_CORE_AV__MPEG_DBYTE__ELSIZE 0x4ul +#define HDMI_CORE_AV__MPEG_DBYTE__NELEMS 27 +#define HDMI_CORE_AV__GEN_DBYTE 0x300ul +#define HDMI_CORE_AV__GEN_DBYTE__ELSIZE 0x4ul +#define HDMI_CORE_AV__GEN_DBYTE__NELEMS 31 +#define HDMI_CORE_AV__GEN2_DBYTE 0x380ul +#define HDMI_CORE_AV__GEN2_DBYTE__ELSIZE 0x4ul +#define HDMI_CORE_AV__GEN2_DBYTE__NELEMS 31 +#define HDMI_CORE_AV__ACR_CTRL 0x4ul +#define HDMI_CORE_AV__FREQ_SVAL 0x8ul +#define HDMI_CORE_AV__N_SVAL1 0xCul +#define HDMI_CORE_AV__N_SVAL2 0x10ul +#define HDMI_CORE_AV__N_SVAL3 0x14ul +#define HDMI_CORE_AV__CTS_SVAL1 0x18ul +#define HDMI_CORE_AV__CTS_SVAL2 0x1Cul +#define HDMI_CORE_AV__CTS_SVAL3 0x20ul +#define HDMI_CORE_AV__CTS_HVAL1 0x24ul +#define HDMI_CORE_AV__CTS_HVAL2 0x28ul +#define HDMI_CORE_AV__CTS_HVAL3 0x2Cul +#define HDMI_CORE_AV__AUD_MODE 0x50ul +#define HDMI_CORE_AV__SPDIF_CTRL 0x54ul +#define HDMI_CORE_AV__HW_SPDIF_FS 0x60ul +#define HDMI_CORE_AV__SWAP_I2S 0x64ul +#define HDMI_CORE_AV__SPDIF_ERTH 0x6Cul +#define HDMI_CORE_AV__I2S_IN_MAP 0x70ul +#define HDMI_CORE_AV__I2S_IN_CTRL 0x74ul +#define HDMI_CORE_AV__I2S_CHST0 0x78ul +#define HDMI_CORE_AV__I2S_CHST1 0x7Cul +#define HDMI_CORE_AV__I2S_CHST2 0x80ul +#define HDMI_CORE_AV__I2S_CHST4 0x84ul +#define HDMI_CORE_AV__I2S_CHST5 0x88ul +#define HDMI_CORE_AV__ASRC 0x8Cul +#define HDMI_CORE_AV__I2S_IN_LEN 0x90ul +#define HDMI_CORE_AV__HDMI_CTRL 0xBCul +#define HDMI_CORE_AV__AUDO_TXSTAT 0xC0ul +#define HDMI_CORE_AV__AUD_PAR_BUSCLK_1 0xCCul +#define HDMI_CORE_AV__AUD_PAR_BUSCLK_2 0xD0ul +#define HDMI_CORE_AV__AUD_PAR_BUSCLK_3 0xD4ul +#define HDMI_CORE_AV__TEST_TXCTRL 0xF0ul +#define HDMI_CORE_AV__DPD 0xF4ul +#define HDMI_CORE_AV__PB_CTRL1 0xF8ul +#define HDMI_CORE_AV__PB_CTRL2 0xFCul +#define HDMI_CORE_AV__AVI_TYPE 0x100ul +#define HDMI_CORE_AV__AVI_VERS 0x104ul +#define HDMI_CORE_AV__AVI_LEN 0x108ul +#define HDMI_CORE_AV__AVI_CHSUM 0x10Cul +#define HDMI_CORE_AV__SPD_TYPE 0x180ul +#define HDMI_CORE_AV__SPD_VERS 0x184ul +#define HDMI_CORE_AV__SPD_LEN 0x188ul +#define HDMI_CORE_AV__SPD_CHSUM 0x18Cul +#define HDMI_CORE_AV__AUDIO_TYPE 0x200ul +#define HDMI_CORE_AV__AUDIO_VERS 0x204ul +#define HDMI_CORE_AV__AUDIO_LEN 0x208ul +#define HDMI_CORE_AV__AUDIO_CHSUM 0x20Cul +#define HDMI_CORE_AV__MPEG_TYPE 0x280ul +#define HDMI_CORE_AV__MPEG_VERS 0x284ul +#define HDMI_CORE_AV__MPEG_LEN 0x288ul +#define HDMI_CORE_AV__MPEG_CHSUM 0x28Cul +#define HDMI_CORE_AV__CP_BYTE1 0x37Cul +#define HDMI_CORE_AV__CEC_ADDR_ID 0x3FCul static struct { - void __iomem *base_core; /*0*/ - void __iomem *base_core_av; /*1*/ - void __iomem *base_wp; /*2*/ + void __iomem *base_core; /* 0 */ + void __iomem *base_core_av; /* 1 */ + void __iomem *base_wp; /* 2 */ struct hdmi_core_infoframe_avi avi_param; struct mutex mutex; struct list_head notifier_head; } hdmi; -int count = 0, count_hpd = 0; - static inline void hdmi_write_reg(u32 base, u16 idx, u32 val) { void __iomem *b; switch (base) { case HDMI_CORE_SYS: - b = hdmi.base_core; - break; + b = hdmi.base_core; + break; case HDMI_CORE_AV: - b = hdmi.base_core_av; - break; + b = hdmi.base_core_av; + break; case HDMI_WP: - b = hdmi.base_wp; - break; + b = hdmi.base_wp; + break; default: - BUG(); + BUG(); } __raw_writel(val, b + idx); /* DBG("write = 0x%x idx =0x%x\r\n", val, idx); */ @@ -227,16 +224,16 @@ static inline u32 hdmi_read_reg(u32 base, u16 idx) switch (base) { case HDMI_CORE_SYS: - b = hdmi.base_core; - break; + b = hdmi.base_core; + break; case HDMI_CORE_AV: - b = hdmi.base_core_av; - break; + b = hdmi.base_core_av; + break; case HDMI_WP: - b = hdmi.base_wp; - break; + b = hdmi.base_wp; + break; default: - BUG(); + BUG(); } l = __raw_readl(b + idx); @@ -246,9 +243,9 @@ static inline u32 hdmi_read_reg(u32 base, u16 idx) void hdmi_dump_regs(struct seq_file *s) { - #define DUMPREG(g, r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(g, r)) +#define DUMPREG(g, r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(g, r)) - /*wrapper registers*/ + /* wrapper registers */ DUMPREG(HDMI_WP, HDMI_WP_REVISION); DUMPREG(HDMI_WP, HDMI_WP_SYSCONFIG); DUMPREG(HDMI_WP, HDMI_WP_IRQSTATUS_RAW); @@ -305,26 +302,24 @@ void hdmi_dump_regs(struct seq_file *s) DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV__AVI_DBYTE); DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV__AVI_DBYTE); DUMPREG(HDMI_CORE_AV, HDMI_CORE_AV__AVI_DBYTE); - } -#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end)) -#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end)) +#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) +#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) #define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end)) #define FLD_MOD(orig, val, start, end) \ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) #define REG_FLD_MOD(base, idx, val, start, end) \ - hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx), val, start, end)) + hdmi_write_reg(base, idx, \ + FLD_MOD(hdmi_read_reg(base, idx), val, start, end)) #define RD_REG_32(COMP, REG) hdmi_read_reg(COMP, REG) #define WR_REG_32(COMP, REG, VAL) hdmi_write_reg(COMP, REG, (u32)(VAL)) -u8 edid_backup[512]; - int hdmi_get_pixel_append_position(void) { - printk("This is yet to be implemented"); + printk(KERN_WARNING "This is yet to be implemented"); return 0; } EXPORT_SYMBOL(hdmi_get_pixel_append_position); @@ -380,9 +375,10 @@ int hdmi_core_ddc_edid(u8 *pEDID, int ext) else REG_FLD_MOD(ins, HDMI_CORE_DDC_CMD, 0x2, 3, 0); - /* Yong: do not optimize this part of the code, seems - DDC bus needs some time to get stabilized - */ + /* + * Yong: do not optimize this part of the code, seems + * DDC bus needs some time to get stabilized + */ l = hdmi_read_reg(ins, sts); /* HDMI_CORE_DDC_STATUS__BUS_LOW */ @@ -398,12 +394,12 @@ int hdmi_core_ddc_edid(u8 *pEDID, int ext) i = ext * 128; j = 0; - while (((FLD_GET(hdmi_read_reg(ins, sts), 4, 4) == 1) - | (FLD_GET(hdmi_read_reg(ins, sts), 2, 2) == 0)) && j < 128) { - if (FLD_GET(hdmi_read_reg(ins, - sts), 2, 2) == 0) { + while (((FLD_GET(hdmi_read_reg(ins, sts), 4, 4) == 1) || + (FLD_GET(hdmi_read_reg(ins, sts), 2, 2) == 0)) && j < 128) { + if (FLD_GET(hdmi_read_reg(ins, sts), 2, 2) == 0) { /* FIFO not empty */ - pEDID[i++] = FLD_GET(hdmi_read_reg(ins, HDMI_CORE_DDC_DATA), 7, 0); + pEDID[i++] = FLD_GET( + hdmi_read_reg(ins, HDMI_CORE_DDC_DATA), 7, 0); j++; } } @@ -418,16 +414,27 @@ int hdmi_core_ddc_edid(u8 *pEDID, int ext) return 0; } -int read_edid(u8 *pEDID) +int read_edid(u8 *pEDID, u16 max_length) { int r = 0, n = 0, i = 0; + int max_ext_blocks = (max_length / 128) - 1; + r = hdmi_core_ddc_edid(pEDID, 0); if (r) { return -1; } else { n = pEDID[0x7e]; - if (n >= 3) - n = 3; + + /* + * README: need to comply with max_length set by the caller. + * Better implementation should be to allocate necessary + * memory to store EDID according to nb_block field found + * in first block + */ + + if (n > max_ext_blocks) + n = max_ext_blocks; + for (i = 1; i <= n; i++) { r = hdmi_core_ddc_edid(pEDID, i); if (r) @@ -445,45 +452,40 @@ static void hdmi_core_init(enum hdmi_deep_mode deep_color, { DBG("Enter HDMI_Core_GlobalInitVars()\n"); - /*video core*/ + /* video core */ switch (deep_color) { - case HDMI_DEEP_COLOR_24BIT: - v_cfg->CoreInputBusWide = HDMI_INPUT_8BIT; - v_cfg->CoreOutputDitherTruncation = HDMI_OUTPUTTRUNCATION_8BIT; - v_cfg->CoreDeepColorPacketED = HDMI_DEEPCOLORPACKECTDISABLE; - v_cfg->CorePacketMode = HDMI_PACKETMODERESERVEDVALUE; - break; case HDMI_DEEP_COLOR_30BIT: - v_cfg->CoreInputBusWide = HDMI_INPUT_10BIT; - v_cfg->CoreOutputDitherTruncation = HDMI_OUTPUTTRUNCATION_10BIT; - v_cfg->CoreDeepColorPacketED = HDMI_DEEPCOLORPACKECTENABLE; - v_cfg->CorePacketMode = HDMI_PACKETMODE30BITPERPIXEL; - break; + v_cfg->CoreInputBusWide = HDMI_INPUT_10BIT; + v_cfg->CoreOutputDitherTruncation = HDMI_OUTPUTTRUNCATION_10BIT; + v_cfg->CoreDeepColorPacketED = HDMI_DEEPCOLORPACKECTENABLE; + v_cfg->CorePacketMode = HDMI_PACKETMODE30BITPERPIXEL; + break; case HDMI_DEEP_COLOR_36BIT: - v_cfg->CoreInputBusWide = HDMI_INPUT_12BIT; - v_cfg->CoreOutputDitherTruncation = HDMI_OUTPUTTRUNCATION_12BIT; - v_cfg->CoreDeepColorPacketED = HDMI_DEEPCOLORPACKECTENABLE; - v_cfg->CorePacketMode = HDMI_PACKETMODE36BITPERPIXEL; - break; + v_cfg->CoreInputBusWide = HDMI_INPUT_12BIT; + v_cfg->CoreOutputDitherTruncation = HDMI_OUTPUTTRUNCATION_12BIT; + v_cfg->CoreDeepColorPacketED = HDMI_DEEPCOLORPACKECTENABLE; + v_cfg->CorePacketMode = HDMI_PACKETMODE36BITPERPIXEL; + break; + case HDMI_DEEP_COLOR_24BIT: default: - v_cfg->CoreInputBusWide = HDMI_INPUT_8BIT; - v_cfg->CoreOutputDitherTruncation = HDMI_OUTPUTTRUNCATION_8BIT; - v_cfg->CoreDeepColorPacketED = HDMI_DEEPCOLORPACKECTDISABLE; - v_cfg->CorePacketMode = HDMI_PACKETMODERESERVEDVALUE; - break; + v_cfg->CoreInputBusWide = HDMI_INPUT_8BIT; + v_cfg->CoreOutputDitherTruncation = HDMI_OUTPUTTRUNCATION_8BIT; + v_cfg->CoreDeepColorPacketED = HDMI_DEEPCOLORPACKECTDISABLE; + v_cfg->CorePacketMode = HDMI_PACKETMODERESERVEDVALUE; + break; } v_cfg->CoreHdmiDvi = HDMI_DVI; v_cfg->CoreTclkSelClkMult = FPLL10IDCK; - /*audio core*/ + /* audio core */ audio_cfg->fs = FS_44100; audio_cfg->n = 0; audio_cfg->cts = 0; - audio_cfg->layout = LAYOUT_2CH; /*2channel audio*/ + audio_cfg->layout = LAYOUT_2CH; /* 2channel audio */ audio_cfg->aud_par_busclk = 0; audio_cfg->cts_mode = CTS_MODE_HW; - /*info frame*/ + /* info frame */ avi->db1y_rgb_yuv422_yuv444 = 0; avi->db1a_active_format_off_on = 0; avi->db1b_no_vert_hori_verthori = 0; @@ -502,7 +504,7 @@ static void hdmi_core_init(enum hdmi_deep_mode deep_color, avi->db10_11_pixelendofleft = 0; avi->db12_13_pixelstartofright = 0; - /*packet enable and repeat*/ + /* packet enable and repeat */ r_p->AudioPacketED = 0; r_p->AudioPacketRepeat = 0; r_p->AVIInfoFrameED = 0; @@ -542,26 +544,25 @@ static void hdmi_core_swreset_assert(void) } /* DSS_HDMI_CORE_VIDEO_CONFIG */ -static int hdmi_core_video_config( - struct hdmi_core_video_config_t *cfg) +static int hdmi_core_video_config(struct hdmi_core_video_config_t *cfg) { u32 name = HDMI_CORE_SYS; u32 av_name = HDMI_CORE_AV; u32 r = 0; - /*sys_ctrl1 default configuration not tunable*/ + /* sys_ctrl1 default configuration not tunable */ u32 ven; u32 hen; u32 bsel; u32 edge; - /*sys_ctrl1 default configuration not tunable*/ + /* sys_ctrl1 default configuration not tunable */ ven = HDMI_CORE_CTRL1_VEN__FOLLOWVSYNC; hen = HDMI_CORE_CTRL1_HEN__FOLLOWHSYNC; bsel = HDMI_CORE_CTRL1_BSEL__24BITBUS; edge = HDMI_CORE_CTRL1_EDGE__RISINGEDGE; - /*sys_ctrl1 default configuration not tunable*/ + /* sys_ctrl1 default configuration not tunable */ r = hdmi_read_reg(name, HDMI_CORE_CTRL1); r = FLD_MOD(r, ven, 5, 5); r = FLD_MOD(r, hen, 4, 4); @@ -571,11 +572,10 @@ static int hdmi_core_video_config( REG_FLD_MOD(name, HDMI_CORE_SYS__VID_ACEN, cfg->CoreInputBusWide, 7, 6); - /*Vid_Mode */ + /* Vid_Mode */ r = hdmi_read_reg(name, HDMI_CORE_SYS__VID_MODE); - /*dither truncation configuration*/ - if (cfg->CoreOutputDitherTruncation > - HDMI_OUTPUTTRUNCATION_12BIT) { + /* dither truncation configuration */ + if (cfg->CoreOutputDitherTruncation > HDMI_OUTPUTTRUNCATION_12BIT) { r = FLD_MOD(r, cfg->CoreOutputDitherTruncation - 3, 7, 6); r = FLD_MOD(r, 1, 5, 5); } else { @@ -584,14 +584,14 @@ static int hdmi_core_video_config( } hdmi_write_reg(name, HDMI_CORE_SYS__VID_MODE, r); - /*HDMI_Ctrl*/ + /* HDMI_CTRL */ r = hdmi_read_reg(av_name, HDMI_CORE_AV_HDMI_CTRL); r = FLD_MOD(r, cfg->CoreDeepColorPacketED, 6, 6); r = FLD_MOD(r, cfg->CorePacketMode, 5, 3); r = FLD_MOD(r, cfg->CoreHdmiDvi, 0, 0); hdmi_write_reg(av_name, HDMI_CORE_AV_HDMI_CTRL, r); - /*TMDS_CTRL*/ + /* TMDS_CTRL */ REG_FLD_MOD(name, HDMI_CORE_SYS__TMDS_CTRL, cfg->CoreTclkSelClkMult, 6, 5); @@ -613,21 +613,24 @@ static int hdmi_core_audio_config(u32 name, u8 size1; u16 size0; - /*CTS_MODE*/ + /* CTS_MODE */ WR_REG_32(name, HDMI_CORE_AV__ACR_CTRL, - ((0x0 << 2) | /* MCLK_EN (0: Mclk is not used)*/ - (0x1 << 1) | /* CTS Request Enable (1:Packet Enable, 0:Disable) */ - (audio_cfg->cts_mode << 0))); /* CTS Source Select (1:SW, 0:HW)*/ + /* MCLK_EN (0: Mclk is not used) */ + (0x0 << 2) | + /* CTS Request Enable (1:Packet Enable, 0:Disable) */ + (0x1 << 1) | + /* CTS Source Select (1:SW, 0:HW) */ + (audio_cfg->cts_mode << 0)); REG_FLD_MOD(name, HDMI_CORE_AV__FREQ_SVAL, 0, 2, 0); REG_FLD_MOD(name, HDMI_CORE_AV__N_SVAL1, audio_cfg->n, 7, 0); - REG_FLD_MOD(name, HDMI_CORE_AV__N_SVAL2, (audio_cfg->n >> 8), 7, 0); - REG_FLD_MOD(name, HDMI_CORE_AV__N_SVAL3, (audio_cfg->n >> 16), 7, 0); - REG_FLD_MOD(name, HDMI_CORE_AV__CTS_SVAL1, (audio_cfg->cts), 7, 0); - REG_FLD_MOD(name, HDMI_CORE_AV__CTS_SVAL2, (audio_cfg->cts >> 8), 7, 0); - REG_FLD_MOD(name, HDMI_CORE_AV__CTS_SVAL3, (audio_cfg->cts >> 16), 7, 0); + REG_FLD_MOD(name, HDMI_CORE_AV__N_SVAL2, audio_cfg->n >> 8, 7, 0); + REG_FLD_MOD(name, HDMI_CORE_AV__N_SVAL3, audio_cfg->n >> 16, 7, 0); + REG_FLD_MOD(name, HDMI_CORE_AV__CTS_SVAL1, audio_cfg->cts, 7, 0); + REG_FLD_MOD(name, HDMI_CORE_AV__CTS_SVAL2, audio_cfg->cts >> 8, 7, 0); + REG_FLD_MOD(name, HDMI_CORE_AV__CTS_SVAL3, audio_cfg->cts >> 16, 7, 0); - /*number of channel*/ + /* number of channel */ REG_FLD_MOD(name, HDMI_CORE_AV__HDMI_CTRL, audio_cfg->layout, 2, 1); REG_FLD_MOD(name, HDMI_CORE_AV__AUD_PAR_BUSCLK_1, audio_cfg->aud_par_busclk, 7, 0); @@ -635,45 +638,45 @@ static int hdmi_core_audio_config(u32 name, (audio_cfg->aud_par_busclk >> 8), 7, 0); REG_FLD_MOD(name, HDMI_CORE_AV__AUD_PAR_BUSCLK_3, (audio_cfg->aud_par_busclk >> 16), 7, 0); - /* FS_OVERRIDE = 1 because // input is used*/ + /* FS_OVERRIDE = 1 because // input is used */ WR_REG_32(name, HDMI_CORE_AV__SPDIF_CTRL, 0x1); - /* refer to table209 p192 in func core spec*/ + /* refer to table209 p192 in func core spec */ WR_REG_32(name, HDMI_CORE_AV__I2S_CHST4, audio_cfg->fs); - /* audio config is mainly due to wrapper hardware connection - and so are fixe (hardware) I2S deserializer is by-pass - so I2S configuration is not needed (I2S don't care). - Wrapper are directly connected at the I2S deserialiser - output level so some register call I2S... need to be - programm to configure this parallel bus, there configuration - is also fixe and due to the hardware connection (I2S hardware) - */ + /* + * audio config is mainly due to wrapper hardware connection + * and so are fixe (hardware) I2S deserializer is by-pass + * so I2S configuration is not needed (I2S don't care). + * Wrapper are directly connected at the I2S deserialiser + * output level so some register call I2S... need to be + * programm to configure this parallel bus, there configuration + * is also fixe and due to the hardware connection (I2S hardware) + */ WR_REG_32(name, HDMI_CORE_AV__I2S_IN_CTRL, - (0 << 7) | /* HBRA_ON */ - (1 << 6) | /* SCK_EDGE Sample clock is rising */ - (0 << 5) | /* CBIT_ORDER */ - (0 << 4) | /* VBit, 0x0=PCM, 0x1=compressed */ - (0 << 3) | /* I2S_WS, 0xdon't care */ - (0 << 2) | /* I2S_JUST, 0=left-justified 1=right-justified */ - (0 << 1) | /* I2S_DIR, 0xdon't care */ - (0)); /* I2S_SHIFT, 0x0 don't care*/ + (0 << 7) | /* HBRA_ON */ + (1 << 6) | /* SCK_EDGE Sample clock is rising */ + (0 << 5) | /* CBIT_ORDER */ + (0 << 4) | /* VBit, 0x0=PCM, 0x1=compressed */ + (0 << 3) | /* I2S_WS, 0xdon't care */ + (0 << 2) | /* I2S_JUST, 0=left- 1=right-justified */ + (0 << 1) | /* I2S_DIR, 0xdon't care */ + (0)); /* I2S_SHIFT, 0x0 don't care */ WR_REG_32(name, HDMI_CORE_AV__I2S_CHST5, /* mode only */ - (0 << 4) | /* FS_ORIG */ - (1 << 1) | /* I2S lenght 16bits (refer doc) */ - (0));/* Audio sample lenght */ + (0 << 4) | /* FS_ORIG */ + (1 << 1) | /* I2S lenght 16bits (refer doc) */ + (0)); /* Audio sample lenght */ WR_REG_32(name, HDMI_CORE_AV__I2S_IN_LEN, /* mode only */ - (0xb)); /* In lenght b=>24bits i2s hardware */ + (0xb)); /* In length b=>24bits i2s hardware */ - /*channel enable depend of the layout*/ + /* channel enable depend of the layout */ if (audio_cfg->layout == LAYOUT_2CH) { SD3_EN = 0x0; SD2_EN = 0x0; SD1_EN = 0x0; SD0_EN = 0x1; - } - if (audio_cfg->layout == LAYOUT_8CH) { + } else if (audio_cfg->layout == LAYOUT_8CH) { SD3_EN = 0x1; SD2_EN = 0x1; SD1_EN = 0x1; @@ -681,20 +684,20 @@ static int hdmi_core_audio_config(u32 name, } WR_REG_32(name, HDMI_CORE_AV__AUD_MODE, - (SD3_EN << 7) | /* SD3_EN */ - (SD2_EN << 6) | /* SD2_EN */ - (SD1_EN << 5) | /* SD1_EN */ - (SD0_EN << 4) | /* SD0_EN */ - (0 << 3) | /* DSD_EN */ - (1 << 2) | /* AUD_PAR_EN*/ - (0 << 1) | /* SPDIF_EN*/ - (0)); /* AUD_EN*/ + (SD3_EN << 7) | /* SD3_EN */ + (SD2_EN << 6) | /* SD2_EN */ + (SD1_EN << 5) | /* SD1_EN */ + (SD0_EN << 4) | /* SD0_EN */ + (0 << 3) | /* DSD_EN */ + (1 << 2) | /* AUD_PAR_EN */ + (0 << 1) | /* SPDIF_EN */ + (0)); /* AUD_EN */ /* Audio info frame setting refer to CEA-861-d spec p75 */ - /* 0x0 because on HDMI CT must be = 0 / -1 because 1 is for 2 channel*/ + /* 0x0 because on HDMI CT must be = 0 / -1 because 1 is for 2 channel */ DBYTE1 = 0x0 + (audio_cfg->if_channel_number - 1); DBYTE2 = (audio_cfg->if_fs << 2) + audio_cfg->if_sample_size; - /*channel location according to CEA spec*/ + /* channel location according to CEA spec */ DBYTE4 = audio_cfg->if_audio_channel_location; CHSUM = 0x100-0x84-0x01-0x0A-DBYTE1-DBYTE2-DBYTE4; @@ -702,7 +705,8 @@ static int hdmi_core_audio_config(u32 name, WR_REG_32(name, HDMI_CORE_AV__AUDIO_TYPE, 0x084); WR_REG_32(name, HDMI_CORE_AV__AUDIO_VERS, 0x001); WR_REG_32(name, HDMI_CORE_AV__AUDIO_LEN, 0x00A); - WR_REG_32(name, HDMI_CORE_AV__AUDIO_CHSUM, CHSUM); /*don't care on VMP*/ + /* don't care on VMP */ + WR_REG_32(name, HDMI_CORE_AV__AUDIO_CHSUM, CHSUM); size0 = HDMI_CORE_AV__AUDIO_DBYTE; size1 = HDMI_CORE_AV__AUDIO_DBYTE__ELSIZE; @@ -733,27 +737,39 @@ static int hdmi_core_audio_config(u32 name, int hdmi_core_read_avi_infoframe(struct hdmi_core_infoframe_avi *info_avi) { - info_avi->db1y_rgb_yuv422_yuv444 = hdmi.avi_param.db1y_rgb_yuv422_yuv444; - info_avi->db1a_active_format_off_on = hdmi.avi_param.db1a_active_format_off_on; - info_avi->db1b_no_vert_hori_verthori = hdmi.avi_param.db1b_no_vert_hori_verthori; + info_avi->db1y_rgb_yuv422_yuv444 = + hdmi.avi_param.db1y_rgb_yuv422_yuv444; + info_avi->db1a_active_format_off_on = + hdmi.avi_param.db1a_active_format_off_on; + info_avi->db1b_no_vert_hori_verthori = + hdmi.avi_param.db1b_no_vert_hori_verthori; info_avi->db1s_0_1_2 = hdmi.avi_param.db1s_0_1_2; - info_avi->db2c_no_itu601_itu709_extented = hdmi.avi_param.db2c_no_itu601_itu709_extented; + info_avi->db2c_no_itu601_itu709_extented = + hdmi.avi_param.db2c_no_itu601_itu709_extented; info_avi->db2m_no_43_169 = hdmi.avi_param.db2m_no_43_169; info_avi->db2r_same_43_169_149 = hdmi.avi_param.db2r_same_43_169_149; info_avi->db3itc_no_yes = hdmi.avi_param.db3itc_no_yes; - info_avi->db3ec_xvyuv601_xvyuv709 = hdmi.avi_param.db3ec_xvyuv601_xvyuv709; + info_avi->db3ec_xvyuv601_xvyuv709 = + hdmi.avi_param.db3ec_xvyuv601_xvyuv709; info_avi->db3q_default_lr_fr = hdmi.avi_param.db3q_default_lr_fr; - info_avi->db3sc_no_hori_vert_horivert = hdmi.avi_param.db3sc_no_hori_vert_horivert; + info_avi->db3sc_no_hori_vert_horivert = + hdmi.avi_param.db3sc_no_hori_vert_horivert; info_avi->db4vic_videocode = hdmi.avi_param.db4vic_videocode; - info_avi->db5pr_no_2_3_4_5_6_7_8_9_10 = hdmi.avi_param.db5pr_no_2_3_4_5_6_7_8_9_10; + info_avi->db5pr_no_2_3_4_5_6_7_8_9_10 = + hdmi.avi_param.db5pr_no_2_3_4_5_6_7_8_9_10; info_avi->db6_7_lineendoftop = hdmi.avi_param.db6_7_lineendoftop; - info_avi->db8_9_linestartofbottom = hdmi.avi_param.db8_9_linestartofbottom; - info_avi->db10_11_pixelendofleft = hdmi.avi_param.db10_11_pixelendofleft; - info_avi->db12_13_pixelstartofright = hdmi.avi_param.db12_13_pixelstartofright; + info_avi->db8_9_linestartofbottom = + hdmi.avi_param.db8_9_linestartofbottom; + info_avi->db10_11_pixelendofleft = + hdmi.avi_param.db10_11_pixelendofleft; + info_avi->db12_13_pixelstartofright = + hdmi.avi_param.db12_13_pixelstartofright; + return 0; } -static int hdmi_core_audio_infoframe_avi(struct hdmi_core_infoframe_avi info_avi) +static int hdmi_core_audio_infoframe_avi( + struct hdmi_core_infoframe_avi info_avi) { u16 offset; int dbyte, dbyte_size; @@ -762,7 +778,7 @@ static int hdmi_core_audio_infoframe_avi(struct hdmi_core_infoframe_avi info_avi dbyte = HDMI_CORE_AV_AVI_DBYTE; dbyte_size = HDMI_CORE_AV_AVI_DBYTE__ELSIZE; - /*info frame video*/ + /* info frame video */ sum += 0x82 + 0x002 + 0x00D; hdmi_write_reg(HDMI_CORE_AV, HDMI_CORE_AV_AVI_TYPE, 0x082); hdmi_write_reg(HDMI_CORE_AV, HDMI_CORE_AV_AVI_VERS, 0x002); @@ -850,57 +866,101 @@ int hdmi_configure_csc(enum hdmi_core_av_csc csc) { int var; switch (csc) { - /*Setting the AVI infroframe to respective color mode - * As the quantization is in default mode ie it selects - * full range for RGB (except for VGA ) and limited range - * for YUV we dont have to make any changes for this */ + /* + * Setting the AVI infroframe to respective color mode + * As the quantization is in default mode ie it selects + * full range for RGB (except for VGA ) and limited range + * for YUV we dont have to make any changes for this + */ case RGB: - hdmi.avi_param.db1y_rgb_yuv422_yuv444 = INFOFRAME_AVI_DB1Y_RGB; - hdmi_core_audio_infoframe_avi(hdmi.avi_param); - var = hdmi_read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_ACEN); - var = FLD_MOD(var, 0, 2, 2); - hdmi_write_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_ACEN, var); - break; + hdmi.avi_param.db1y_rgb_yuv422_yuv444 = INFOFRAME_AVI_DB1Y_RGB; + hdmi_core_audio_infoframe_avi(hdmi.avi_param); + var = hdmi_read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_ACEN); + var = FLD_MOD(var, 0, 2, 2); + hdmi_write_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_ACEN, var); + break; case RGB_TO_YUV: - hdmi.avi_param.db1y_rgb_yuv422_yuv444 = INFOFRAME_AVI_DB1Y_YUV422; - hdmi_core_audio_infoframe_avi(hdmi.avi_param); - var = hdmi_read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_ACEN); - var = FLD_MOD(var, 1, 2, 2); - hdmi_write_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_ACEN, var); - break; + hdmi.avi_param.db1y_rgb_yuv422_yuv444 = + INFOFRAME_AVI_DB1Y_YUV422; + hdmi_core_audio_infoframe_avi(hdmi.avi_param); + var = hdmi_read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_ACEN); + var = FLD_MOD(var, 1, 2, 2); + hdmi_write_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_ACEN, var); + break; case YUV_TO_RGB: - hdmi.avi_param.db1y_rgb_yuv422_yuv444 = INFOFRAME_AVI_DB1Y_RGB; - hdmi_core_audio_infoframe_avi(hdmi.avi_param); - var = hdmi_read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_MODE); - var = FLD_MOD(var, 1, 3, 3); - hdmi_write_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_MODE, var); - break; + hdmi.avi_param.db1y_rgb_yuv422_yuv444 = INFOFRAME_AVI_DB1Y_RGB; + hdmi_core_audio_infoframe_avi(hdmi.avi_param); + var = hdmi_read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_MODE); + var = FLD_MOD(var, 1, 3, 3); + hdmi_write_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__VID_MODE, var); + break; default: - break; + break; } return 0; +} +int hdmi_configure_lrfr(enum hdmi_range lr_fr, int force_set) +{ + int var; + switch (lr_fr) { + /* + * Setting the AVI infroframe to respective limited range + * 0 if for limited range 1 for full range + */ + case HDMI_LIMITED_RANGE: + hdmi.avi_param.db3q_default_lr_fr = INFOFRAME_AVI_DB3Q_LR; + hdmi_core_audio_infoframe_avi(hdmi.avi_param); + if (force_set) { + var = hdmi_read_reg(HDMI_CORE_SYS, + HDMI_CORE_SYS__VID_ACEN); + var = FLD_MOD(var, 1, 1, 1); + hdmi_write_reg(HDMI_CORE_SYS, + HDMI_CORE_SYS__VID_ACEN, var); + } + break; + case HDMI_FULL_RANGE: + if (hdmi.avi_param.db1y_rgb_yuv422_yuv444 == + INFOFRAME_AVI_DB1Y_YUV422) { + printk(KERN_ERR"It is only limited range for YUV"); + return -1; + } + hdmi.avi_param.db3q_default_lr_fr = INFOFRAME_AVI_DB3Q_FR; + hdmi_core_audio_infoframe_avi(hdmi.avi_param); + if (force_set) { + var = hdmi_read_reg(HDMI_CORE_SYS, + HDMI_CORE_SYS__VID_MODE); + var = FLD_MOD(var, 1, 4, 4); + hdmi_write_reg(HDMI_CORE_SYS, + HDMI_CORE_SYS__VID_MODE, var); + } + break; + default: + break; + } + return 0; } + static int hdmi_core_av_packet_config(u32 name, struct hdmi_core_packet_enable_repeat r_p) { - /*enable/repeat the infoframe*/ + /* enable/repeat the infoframe */ hdmi_write_reg(name, HDMI_CORE_AV_PB_CTRL1, - (r_p.MPEGInfoFrameED << 7)| - (r_p.MPEGInfoFrameRepeat << 6)| - (r_p.AudioPacketED << 5)| - (r_p.AudioPacketRepeat << 4)| - (r_p.SPDInfoFrameED << 3)| - (r_p.SPDInfoFrameRepeat << 2)| - (r_p.AVIInfoFrameED << 1)| + (r_p.MPEGInfoFrameED << 7) | + (r_p.MPEGInfoFrameRepeat << 6) | + (r_p.AudioPacketED << 5) | + (r_p.AudioPacketRepeat << 4) | + (r_p.SPDInfoFrameED << 3) | + (r_p.SPDInfoFrameRepeat << 2) | + (r_p.AVIInfoFrameED << 1) | (r_p.AVIInfoFrameRepeat)); - /*enable/repeat the packet*/ + /* enable/repeat the packet */ hdmi_write_reg(name, HDMI_CORE_AV_PB_CTRL2, - (r_p.GeneralcontrolPacketED << 3)| - (r_p.GeneralcontrolPacketRepeat << 2)| - (r_p.GenericPacketED << 1)| + (r_p.GeneralcontrolPacketED << 3) | + (r_p.GeneralcontrolPacketRepeat << 2) | + (r_p.GenericPacketED << 1) | (r_p.GenericPacketRepeat)); return 0; } @@ -958,7 +1018,6 @@ static void hdmi_w1_init(struct hdmi_video_timing *t_p, audio_dma->dma_or_irq = HDMI_THRESHOLD_DMA; audio_dma->threshold_value = 0x10; audio_dma->block_start_end = HDMI_BLOCK_STARTEND_ON; - } @@ -1013,8 +1072,8 @@ int hdmi_w1_set_wait_phy_pwr(HDMI_PhyPwr_t val) DBG("*** Set PHY power mode to %d\n", val); REG_FLD_MOD(HDMI_WP, HDMI_WP_PWR_CTRL, val, 7, 6); - if (hdmi_w1_wait_for_bit_change(HDMI_WP, - HDMI_WP_PWR_CTRL, 5, 4, val) != val) { + if (hdmi_w1_wait_for_bit_change(HDMI_WP, HDMI_WP_PWR_CTRL, 5, 4, val) + != val) { ERR("Failed to set PHY power mode to %d\n", val); return -ENODEV; } @@ -1027,8 +1086,8 @@ int hdmi_w1_set_wait_pll_pwr(HDMI_PllPwr_t val) REG_FLD_MOD(HDMI_WP, HDMI_WP_PWR_CTRL, val, 3, 2); /* wait till PHY_PWR_STATUS=ON */ - if (hdmi_w1_wait_for_bit_change(HDMI_WP, - HDMI_WP_PWR_CTRL, 1, 0, val) != val) { + if (hdmi_w1_wait_for_bit_change(HDMI_WP, HDMI_WP_PWR_CTRL, 1, 0, val) + != val) { ERR("Failed to set PHY_PWR_STATUS to ON\n"); return -ENODEV; } @@ -1131,36 +1190,35 @@ static int hdmi_w1_audio_config_format(u32 name, /* Wakeup */ value = 0x1030022; hdmi_write_reg(name, HDMI_WP_AUDIO_CFG, value); - DBG("HDMI_WP_AUDIO_CFG = 0x%x \n", value); + DBG("HDMI_WP_AUDIO_CFG = 0x%x\n", value); return ret; } static int hdmi_w1_audio_config_dma(u32 name, struct hdmi_audio_dma *audio_dma) - { int ret = 0; u32 value = 0; value = hdmi_read_reg(name, HDMI_WP_AUDIO_CFG2); value &= 0xffffff00; - value |= (audio_dma->block_size); + value |= audio_dma->block_size; value &= 0xffff00ff; - value |= ((audio_dma->dma_transfer) << 8); + value |= audio_dma->dma_transfer << 8; /* Wakeup */ value = 0x20C0; hdmi_write_reg(name, HDMI_WP_AUDIO_CFG2, value); - DBG("HDMI_WP_AUDIO_CFG2 = 0x%x \n", value); + DBG("HDMI_WP_AUDIO_CFG2 = 0x%x\n", value); value = hdmi_read_reg(name, HDMI_WP_AUDIO_CTRL); value &= 0xfffffdff; - value |= ((audio_dma->dma_or_irq)<<9); + value |= audio_dma->dma_or_irq << 9; value &= 0xfffffe00; - value |= (audio_dma->threshold_value); + value |= audio_dma->threshold_value; /* Wakeup */ value = 0x020; hdmi_write_reg(name, HDMI_WP_AUDIO_CTRL, value); - DBG("HDMI_WP_AUDIO_CTRL = 0x%x \n", value); + DBG("HDMI_WP_AUDIO_CTRL = 0x%x\n", value); return ret; } @@ -1215,7 +1273,7 @@ int hdmi_lib_enable(struct hdmi_config *cfg) u32 av_name = HDMI_CORE_AV; - /*HDMI*/ + /* HDMI */ struct hdmi_video_timing VideoTimingParam; struct hdmi_video_format VideoFormatParam; struct hdmi_video_interface VideoInterfaceParam; @@ -1223,7 +1281,7 @@ int hdmi_lib_enable(struct hdmi_config *cfg) struct hdmi_audio_format audio_fmt; struct hdmi_audio_dma audio_dma; - /*HDMI core*/ + /* HDMI core */ struct hdmi_core_video_config_t v_core_cfg; struct hdmi_core_audio_config audio_cfg; struct hdmi_core_packet_enable_repeat repeat_param; @@ -1249,7 +1307,7 @@ int hdmi_lib_enable(struct hdmi_config *cfg) hdmi_w1_video_config_timing(&VideoTimingParam); - /*video config*/ + /* video config */ switch (cfg->deep_color) { case 0: VideoFormatParam.packingMode = HDMI_PACK_24b_RGB_YUV444_YUV422; @@ -1286,10 +1344,10 @@ int hdmi_lib_enable(struct hdmi_config *cfg) /****************************** CORE *******************************/ /************* configure core video part ********************************/ - /*set software reset in the core*/ + /* set software reset in the core */ hdmi_core_swreset_assert(); - /*power down off*/ + /* power down off */ hdmi_core_powerdown_disable(); v_core_cfg.CoreHdmiDvi = cfg->hdmi_dvi; @@ -1341,11 +1399,11 @@ int hdmi_lib_enable(struct hdmi_config *cfg) hdmi_core_audio_config(av_name, &audio_cfg); hdmi_core_audio_mode_enable(av_name); - /*release software reset in the core*/ + /* release software reset in the core */ hdmi_core_swreset_release(); - /*configure packet*/ - /*info frame video see doc CEA861-D page 65*/ + /* configure packet */ + /* info frame video see doc CEA861-D page 65 */ hdmi.avi_param.db1y_rgb_yuv422_yuv444 = INFOFRAME_AVI_DB1Y_RGB; hdmi.avi_param.db1a_active_format_off_on = INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; @@ -1367,7 +1425,7 @@ int hdmi_lib_enable(struct hdmi_config *cfg) r = hdmi_core_audio_infoframe_avi(hdmi.avi_param); - /*enable/repeat the infoframe*/ + /* enable/repeat the infoframe */ repeat_param.AVIInfoFrameED = PACKETENABLE; repeat_param.AVIInfoFrameRepeat = PACKETREPEATON; /* wakeup */ @@ -1403,7 +1461,6 @@ int hdmi_lib_init(void){ INIT_LIST_HEAD(&hdmi.notifier_head); rev = hdmi_read_reg(HDMI_WP, HDMI_WP_REVISION); - printk(KERN_INFO "OMAP HDMI W1 rev %d.%d\n", FLD_GET(rev, 10, 8), FLD_GET(rev, 5, 0)); @@ -1436,13 +1493,13 @@ int hdmi_set_irqs(void) hdmi_w1_irq_enable(&pIrqVectorEnable); r = hdmi_read_reg(HDMI_WP, HDMI_WP_IRQENABLE_SET); - DBG("Irqenable %x \n", r); + DBG("Irqenable %x\n", r); hpd = hdmi_read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__UMASK1); DBG("%x hpd\n", hpd); return 0; } -/* Interrupt handler*/ +/* Interrupt handler */ void HDMI_W1_HPD_handler(int *r) { u32 val, set = 0, hpd_intr; @@ -1491,15 +1548,14 @@ void HDMI_W1_HPD_handler(int *r) hdmi_write_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__INTR1, hpd_intr); mdelay(30); hdmi_set_irqs(); - /*Read to flush*/ + /* Read to flush */ hdmi_read_reg(HDMI_CORE_SYS, HDMI_CORE_SYS__INTR1); } - -/* wrapper functions to be used until L24.5 release*/ -int HDMI_CORE_DDC_READEDID(u32 name, u8 *p) +/* wrapper functions to be used until L24.5 release */ +int HDMI_CORE_DDC_READEDID(u32 name, u8 *p, u16 max_length) { - int r = read_edid(p); + int r = read_edid(p, max_length); return r; } @@ -1553,7 +1609,7 @@ int hdmi_w1_wrapper_enable(u32 instanceName) int hdmi_w1_wrapper_disable(u32 instanceName) { - hdmi_w1_audio_enable(); + hdmi_w1_audio_disable(); printk(KERN_INFO "Wrapper disabled...\n"); return 0; } diff --git a/arch/arm/plat-omap/include/plat/edid.h b/arch/arm/plat-omap/include/plat/edid.h index 21d8459cbfdc..0358bfd4cb8e 100644 --- a/arch/arm/plat-omap/include/plat/edid.h +++ b/arch/arm/plat-omap/include/plat/edid.h @@ -3,7 +3,7 @@ * * Copyright (C) 2009 Texas Instruments * Author: Mythri P K <mythripk@ti.com> - * with some of the ENUM's and structure derived from Yong Zhi's + * with some of the ENUM's and structure derived from Yong Zhi's * hdmi.h(Now obsolete) * * EDID.c to read the EDID content , given the 256 Bytes EDID. @@ -20,7 +20,6 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. * History: - * */ #ifndef _EDID_H_ @@ -29,96 +28,97 @@ #include <plat/display.h> /* HDMI EDID Extension Data Block Tags */ -#define HDMI_EDID_EX_DATABLOCK_TAG_MASK 0xE0 -#define HDMI_EDID_EX_DATABLOCK_LEN_MASK 0x1F - - -#define EDID_TIMING_DESCRIPTOR_SIZE 0x12 -#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 -#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 -#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 -#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 - - -#define HDMI_EDID_DETAILED_TIMING_OFFSET 0x36 /*EDID Detailed Timing - Info 0 begin offset*/ -#define HDMI_EDID_PIX_CLK_OFFSET 0 -#define HDMI_EDID_H_ACTIVE_OFFSET 2 -#define HDMI_EDID_H_BLANKING_OFFSET 3 -#define HDMI_EDID_V_ACTIVE_OFFSET 5 -#define HDMI_EDID_V_BLANKING_OFFSET 6 -#define HDMI_EDID_H_SYNC_OFFSET 8 -#define HDMI_EDID_H_SYNC_PW_OFFSET 9 -#define HDMI_EDID_V_SYNC_OFFSET 10 -#define HDMI_EDID_V_SYNC_PW_OFFSET 10 -#define HDMI_EDID_H_IMAGE_SIZE_OFFSET 12 -#define HDMI_EDID_V_IMAGE_SIZE_OFFSET 13 -#define HDMI_EDID_H_BORDER_OFFSET 15 -#define HDMI_EDID_V_BORDER_OFFSET 16 -#define HDMI_EDID_FLAGS_OFFSET 17 - -/* HDMI Connected States */ -#define HDMI_STATE_NOMONITOR 0 /* No HDMI monitor connected*/ -#define HDMI_STATE_CONNECTED 1 /* HDMI monitor connected but powered off*/ -#define HDMI_STATE_ON 2 /* HDMI monitor connected and powered on*/ - - -/* HDMI EDID Length */ -#define HDMI_EDID_MAX_LENGTH 512 - -/* HDMI EDID DTDs */ -#define HDMI_EDID_MAX_DTDS 4 - -/* HDMI EDID DTD Tags */ -#define HDMI_EDID_DTD_TAG_MONITOR_NAME 0xFC -#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM 0xFF -#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS 0xFD -#define HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA 0xFA -#define HDMI_EDID_DTD_TAG_COLOR_POINT_DATA 0xFB -#define HDMI_EDID_DTD_TAG_ASCII_STRING 0xFE - -#define HDMI_IMG_FORMAT_MAX_LENGTH 20 -#define HDMI_AUDIO_FORMAT_MAX_LENGTH 10 - -/* HDMI EDID Extenion Data Block Values: Video */ -#define HDMI_EDID_EX_VIDEO_NATIVE 0x80 -#define HDMI_EDID_EX_VIDEO_MASK 0x7F -#define HDMI_EDID_EX_VIDEO_MAX 35 - -#define HDMI_EDID_EX_VIDEO_640x480p_60Hz_4_3 1 -#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_4_3 2 -#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_16_9 3 -#define HDMI_EDID_EX_VIDEO_1280x720p_60Hz_16_9 4 -#define HDMI_EDID_EX_VIDEO_1920x1080i_60Hz_16_9 5 -#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_4_3 6 -#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_16_9 7 -#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_4_3 8 -#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_16_9 9 -#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_4_3 10 -#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_16_9 11 -#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_4_3 12 -#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_16_9 13 -#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_4_3 14 -#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_16_9 15 -#define HDMI_EDID_EX_VIDEO_1920x1080p_60Hz_16_9 16 -#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_4_3 17 -#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_16_9 18 -#define HDMI_EDID_EX_VIDEO_1280x720p_50Hz_16_9 19 -#define HDMI_EDID_EX_VIDEO_1920x1080i_50Hz_16_9 20 -#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_4_3 21 -#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_16_9 22 -#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_4_3 23 -#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_16_9 24 -#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_4_3 25 -#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_16_9 26 -#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_4_3 27 -#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_16_9 28 -#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_4_3 29 -#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_16_9 30 -#define HDMI_EDID_EX_VIDEO_1920x1080p_50Hz_16_9 31 -#define HDMI_EDID_EX_VIDEO_1920x1080p_24Hz_16_9 32 -#define HDMI_EDID_EX_VIDEO_1920x1080p_25Hz_16_9 33 -#define HDMI_EDID_EX_VIDEO_1920x1080p_30Hz_16_9 34 +#define HDMI_EDID_EX_DATABLOCK_TAG_MASK 0xE0 +#define HDMI_EDID_EX_DATABLOCK_LEN_MASK 0x1F + +#define EDID_TIMING_DESCRIPTOR_SIZE 0x12 +#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 +#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 +#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 +#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 + +/* EDID Detailed Timing Info 0 begin offset */ +#define HDMI_EDID_DETAILED_TIMING_OFFSET 0x36 + +#define HDMI_EDID_PIX_CLK_OFFSET 0 +#define HDMI_EDID_H_ACTIVE_OFFSET 2 +#define HDMI_EDID_H_BLANKING_OFFSET 3 +#define HDMI_EDID_V_ACTIVE_OFFSET 5 +#define HDMI_EDID_V_BLANKING_OFFSET 6 +#define HDMI_EDID_H_SYNC_OFFSET 8 +#define HDMI_EDID_H_SYNC_PW_OFFSET 9 +#define HDMI_EDID_V_SYNC_OFFSET 10 +#define HDMI_EDID_V_SYNC_PW_OFFSET 11 +#define HDMI_EDID_H_IMAGE_SIZE_OFFSET 12 +#define HDMI_EDID_V_IMAGE_SIZE_OFFSET 13 +#define HDMI_EDID_H_BORDER_OFFSET 15 +#define HDMI_EDID_V_BORDER_OFFSET 16 +#define HDMI_EDID_FLAGS_OFFSET 17 + +/* HDMI Connected States */ +#define HDMI_STATE_NOMONITOR 0 /* No HDMI monitor connected*/ +#define HDMI_STATE_CONNECTED 1 /* HDMI monitor connected but powered off */ +#define HDMI_STATE_ON 2 /* HDMI monitor connected and powered on*/ + +/* HDMI EDID Length */ +#define HDMI_EDID_MAX_LENGTH 512 + +/* HDMI EDID DTDs */ +#define HDMI_EDID_MAX_DTDS 4 + +/* HDMI EDID DTD Tags */ +#define HDMI_EDID_DTD_TAG_MONITOR_NAME 0xFC +#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM 0xFF +#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS 0xFD +#define HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA 0xFA +#define HDMI_EDID_DTD_TAG_COLOR_POINT_DATA 0xFB +#define HDMI_EDID_DTD_TAG_ASCII_STRING 0xFE + +#define HDMI_IMG_FORMAT_MAX_LENGTH 20 +#define HDMI_AUDIO_FORMAT_MAX_LENGTH 10 + +/* HDMI EDID Extenion Data Block Values: Video */ +#define HDMI_EDID_EX_VIDEO_NATIVE 0x80 +#define HDMI_EDID_EX_VIDEO_MASK 0x7F +#define HDMI_EDID_EX_VIDEO_MAX 35 + +#define HDMI_EDID_EX_VIDEO_640x480p_60Hz_4_3 1 +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_4_3 2 +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_16_9 3 +#define HDMI_EDID_EX_VIDEO_1280x720p_60Hz_16_9 4 +#define HDMI_EDID_EX_VIDEO_1920x1080i_60Hz_16_9 5 +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_4_3 6 +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_16_9 7 +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_4_3 8 +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_16_9 9 +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_4_3 10 +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_16_9 11 +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_4_3 12 +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_16_9 13 +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_4_3 14 +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_16_9 15 +#define HDMI_EDID_EX_VIDEO_1920x1080p_60Hz_16_9 16 +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_4_3 17 +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_16_9 18 +#define HDMI_EDID_EX_VIDEO_1280x720p_50Hz_16_9 19 +#define HDMI_EDID_EX_VIDEO_1920x1080i_50Hz_16_9 20 +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_4_3 21 +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_16_9 22 +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_4_3 23 +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_16_9 24 +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_4_3 25 +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_16_9 26 +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_4_3 27 +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_16_9 28 +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_4_3 29 +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_16_9 30 +#define HDMI_EDID_EX_VIDEO_1920x1080p_50Hz_16_9 31 +#define HDMI_EDID_EX_VIDEO_1920x1080p_24Hz_16_9 32 +#define HDMI_EDID_EX_VIDEO_1920x1080p_25Hz_16_9 33 +#define HDMI_EDID_EX_VIDEO_1920x1080p_30Hz_16_9 34 + +#define OMAP_HDMI_TIMINGS_NB 34 +#define OMAP_HDMI_TIMINGS_VESA_START 15 #ifdef __cplusplus extern "C" { @@ -132,149 +132,141 @@ enum extension_edid_db { }; struct img_edid { -bool pref; -int code; + bool pref; + int code; }; struct image_format { -int length; -struct img_edid fmt[HDMI_IMG_FORMAT_MAX_LENGTH]; + int length; + struct img_edid fmt[HDMI_IMG_FORMAT_MAX_LENGTH]; }; struct audio_edid { -int num_of_ch; -int format; + int num_of_ch; + int format; }; struct audio_format { -int length; -struct audio_edid fmt[HDMI_AUDIO_FORMAT_MAX_LENGTH]; + int length; + struct audio_edid fmt[HDMI_AUDIO_FORMAT_MAX_LENGTH]; }; struct latency { -int vid_latency; /*Video Latency (if indicated, value=1+ms/2 with a max of 251 meaning 500ms)*/ -int aud_latency; -int int_vid_latency; -int int_aud_latency; + /* vid: if indicated, value=1+ms/2 with a max of 251 meaning 500ms */ + int vid_latency; + + int aud_latency; + int int_vid_latency; + int int_aud_latency; }; struct deep_color { -bool bit_30; -bool bit_36; -int max_tmds_freq; + bool bit_30; + bool bit_36; + int max_tmds_freq; }; /* Video Descriptor Block */ - struct HDMI_EDID_DTD_VIDEO { - - u16 pixel_clock; /* 54-55 */ - u8 horiz_active; /* 56 */ - u8 horiz_blanking; /* 57 */ - u8 horiz_high; /* 58 */ - u8 vert_active; /* 59 */ - u8 vert_blanking; /* 60 */ - u8 vert_high; /* 61 */ - u8 horiz_sync_offset; /* 62 */ - u8 horiz_sync_pulse; /* 63 */ - u8 vert_sync_pulse; /* 64 */ - u8 sync_pulse_high; /* 65 */ - u8 horiz_image_size; /* 66 */ - u8 vert_image_size; /* 67 */ - u8 image_size_high; /* 68 */ - u8 horiz_border; /* 69 */ - u8 vert_border; /* 70 */ - u8 misc_settings; /* 71 */ + u16 pixel_clock; /* 54-55 */ + u8 horiz_active; /* 56 */ + u8 horiz_blanking; /* 57 */ + u8 horiz_high; /* 58 */ + u8 vert_active; /* 59 */ + u8 vert_blanking; /* 60 */ + u8 vert_high; /* 61 */ + u8 horiz_sync_offset; /* 62 */ + u8 horiz_sync_pulse; /* 63 */ + u8 vert_sync_pulse; /* 64 */ + u8 sync_pulse_high; /* 65 */ + u8 horiz_image_size; /* 66 */ + u8 vert_image_size; /* 67 */ + u8 image_size_high; /* 68 */ + u8 horiz_border; /* 69 */ + u8 vert_border; /* 70 */ + u8 misc_settings; /* 71 */ }; - -/* Monitor Limits Descriptor Block */ - +/* Monitor Limits Descriptor Block */ struct HDMI_EDID_DTD_MONITOR { - u16 pixel_clock; /* 54-55*/ - u8 _reserved1; /* 56 */ - u8 block_type; /* 57 */ - u8 _reserved2; /* 58 */ - u8 min_vert_freq; /* 59 */ - u8 max_vert_freq; /* 60 */ - u8 min_horiz_freq; /* 61 */ - u8 max_horiz_freq; /* 62 */ - u8 pixel_clock_mhz; /* 63 */ - u8 GTF[2]; /* 64 -65 */ - u8 start_horiz_freq; /* 66 */ - u8 C; /* 67 */ - u8 M[2]; /* 68-69 */ - u8 K; /* 70 */ - u8 J; /* 71 */ + u16 pixel_clock; /* 54-55*/ + u8 _reserved1; /* 56 */ + u8 block_type; /* 57 */ + u8 _reserved2; /* 58 */ + u8 min_vert_freq; /* 59 */ + u8 max_vert_freq; /* 60 */ + u8 min_horiz_freq; /* 61 */ + u8 max_horiz_freq; /* 62 */ + u8 pixel_clock_mhz; /* 63 */ + u8 GTF[2]; /* 64 -65 */ + u8 start_horiz_freq; /* 66 */ + u8 C; /* 67 */ + u8 M[2]; /* 68-69 */ + u8 K; /* 70 */ + u8 J; /* 71 */ } __attribute__ ((packed)); -/* Text Descriptor Block */ +/* Text Descriptor Block */ struct HDMI_EDID_DTD_TEXT { - - u16 pixel_clock; /* 54-55 */ - u8 _reserved1; /* 56 */ - u8 block_type; /* 57 */ - u8 _reserved2; /* 58 */ - u8 text[13]; /* 59-71 */ - + u16 pixel_clock; /* 54-55 */ + u8 _reserved1; /* 56 */ + u8 block_type; /* 57 */ + u8 _reserved2; /* 58 */ + u8 text[13]; /* 59-71 */ } __attribute__ ((packed)); - -/* DTD Union */ +/* DTD Union */ union HDMI_EDID_DTD { - struct HDMI_EDID_DTD_VIDEO video; - struct HDMI_EDID_DTD_TEXT monitor_name; - struct HDMI_EDID_DTD_TEXT monitor_serial_number; - struct HDMI_EDID_DTD_TEXT ascii; - struct HDMI_EDID_DTD_MONITOR monitor_limits; - + struct HDMI_EDID_DTD_VIDEO video; + struct HDMI_EDID_DTD_TEXT monitor_name; + struct HDMI_EDID_DTD_TEXT monitor_serial_number; + struct HDMI_EDID_DTD_TEXT ascii; + struct HDMI_EDID_DTD_MONITOR monitor_limits; } __attribute__ ((packed)); -/* EDID struct */ +/* EDID struct */ struct HDMI_EDID { - u8 header[8]; /* 00-07 */ - u16 manufacturerID; /* 08-09 */ - u16 product_id; /* 10-11 */ - u32 serial_number; /* 12-15 */ - u8 week_manufactured; /* 16 */ - u8 year_manufactured; /* 17 */ - u8 edid_version; /* 18 */ - u8 edid_revision; /* 19 */ - u8 video_in_definition; /* 20 */ - u8 max_horiz_image_size; /* 21 */ - u8 max_vert_image_size; /* 22 */ - u8 display_gamma; /* 23 */ - u8 power_features; /* 24 */ - u8 chroma_info[10]; /* 25-34 */ - u8 timing_1; /* 35 */ - u8 timing_2; /* 36 */ - u8 timing_3; /* 37 */ - u8 std_timings[16]; /* 38-53 */ - - union HDMI_EDID_DTD DTD[4]; /* 54-125 */ - - u8 extension_edid; /* 126 */ - u8 checksum; /* 127 */ - u8 extension_tag; /* 00 (extensions follow EDID) */ - u8 extention_rev; /* 01 */ - u8 offset_dtd; /* 02 */ - u8 num_dtd; /* 03 */ - - u8 data_block[123]; /* 04 - 126 */ - u8 extension_checksum; /* 127 */ - - u8 ext_datablock[256]; - + u8 header[8]; /* 00-07 */ + u16 manufacturerID; /* 08-09 */ + u16 product_id; /* 10-11 */ + u32 serial_number; /* 12-15 */ + u8 week_manufactured; /* 16 */ + u8 year_manufactured; /* 17 */ + u8 edid_version; /* 18 */ + u8 edid_revision; /* 19 */ + u8 video_in_definition; /* 20 */ + u8 max_horiz_image_size; /* 21 */ + u8 max_vert_image_size; /* 22 */ + u8 display_gamma; /* 23 */ + u8 power_features; /* 24 */ + u8 chroma_info[10]; /* 25-34 */ + u8 timing_1; /* 35 */ + u8 timing_2; /* 36 */ + u8 timing_3; /* 37 */ + u8 std_timings[16]; /* 38-53 */ + + union HDMI_EDID_DTD DTD[4]; /* 54-125 */ + + u8 extension_edid; /* 126 */ + u8 checksum; /* 127 */ + u8 extension_tag; /* 00 (extensions follow EDID) */ + u8 extention_rev; /* 01 */ + u8 offset_dtd; /* 02 */ + u8 num_dtd; /* 03 */ + + u8 data_block[123]; /* 04 - 126 */ + u8 extension_checksum; /* 127 */ + + u8 ext_datablock[256]; } __attribute__ ((packed)); - - int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd, struct omap_video_timings *timings); void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid , struct omap_video_timings *timings); -int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock, int *offset); +int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock, + int *offset); int hdmi_get_image_format(u8 *edid, struct image_format *format); int hdmi_get_audio_format(u8 *edid, struct audio_format *format); void hdmi_get_av_delay(u8 *edid, struct latency *lat); @@ -286,4 +278,3 @@ int hdmi_tv_yuv_supported(u8 *edid); #endif #endif - diff --git a/arch/arm/plat-omap/include/plat/hdmi_lib.h b/arch/arm/plat-omap/include/plat/hdmi_lib.h index 94cad47ed9ee..fecf2ae86554 100644 --- a/arch/arm/plat-omap/include/plat/hdmi_lib.h +++ b/arch/arm/plat-omap/include/plat/hdmi_lib.h @@ -19,12 +19,12 @@ #include <linux/string.h> -#define HDMI_WP 0x58006000 +#define HDMI_WP 0x58006000 #define HDMI_CORE_SYS 0x58006400 #define HDMI_CORE_AV 0x58006900 -#define HDMI_HDCP 0x58007000 +#define HDMI_HDCP 0x58007000 -#define HDMI_WP_AUDIO_DATA 0x8Cul +#define HDMI_WP_AUDIO_DATA 0x8Cul #define DBG(format, ...) \ printk(KERN_DEBUG "hdmi: " format, ## __VA_ARGS__) @@ -108,10 +108,10 @@ enum hdmi_core_tclkselclkmult { struct hdmi_core_video_config_t { enum hdmi_core_inputbus_width CoreInputBusWide; - enum hdmi_core_dither_trunc CoreOutputDitherTruncation; - enum hdmi_core_deepcolor_ed CoreDeepColorPacketED; - enum hdmi_core_packet_mode CorePacketMode; - enum hdmi_core_hdmi_dvi CoreHdmiDvi; + enum hdmi_core_dither_trunc CoreOutputDitherTruncation; + enum hdmi_core_deepcolor_ed CoreDeepColorPacketED; + enum hdmi_core_packet_mode CorePacketMode; + enum hdmi_core_hdmi_dvi CoreHdmiDvi; enum hdmi_core_tclkselclkmult CoreTclkSelClkMult; }; @@ -340,6 +340,12 @@ enum hdmi_deep_mode { HDMI_DEEP_COLOR_30BIT = 1, HDMI_DEEP_COLOR_36BIT = 2 }; + +enum hdmi_range { + HDMI_LIMITED_RANGE = 0, + HDMI_FULL_RANGE = 1, +}; + struct hdmi_video_format { enum hdmi_packing_mode packingMode; u32 linePerPanel; @@ -434,10 +440,10 @@ struct hdmi_notifier { struct list_head list; }; -#define HDMI_CONNECT 0x01 -#define HDMI_DISCONNECT 0x02 -#define HDMI_HPD 0x04 -#define HDMI_FIRST_HPD 0x08 +#define HDMI_CONNECT 0x01 +#define HDMI_DISCONNECT 0x02 +#define HDMI_HPD 0x04 +#define HDMI_FIRST_HPD 0x08 /* Function prototype */ int HDMI_W1_StopVideoFrame(u32); @@ -449,13 +455,13 @@ int hdmi_w1_wrapper_disable(u32); int hdmi_w1_wrapper_enable(u32); int hdmi_w1_stop_audio_transfer(u32); int hdmi_w1_start_audio_transfer(u32); -int HDMI_CORE_DDC_READEDID(u32 Core, u8 *data); +int HDMI_CORE_DDC_READEDID(u32 Core, u8 *data, u16 max_length); int hdmi_lib_enable(struct hdmi_config *cfg); void HDMI_W1_HPD_handler(int *r); int hdmi_lib_init(void); void hdmi_lib_exit(void); int hdmi_configure_csc(enum hdmi_core_av_csc csc); - +int hdmi_configure_lrfr(enum hdmi_range, int force_set); void hdmi_add_notifier(struct hdmi_notifier *notifier); void hdmi_remove_notifier(struct hdmi_notifier *notifier); void hdmi_notify_hpd(int state); diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 2ef4677a5760..efeb839bf719 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1303,6 +1303,61 @@ static void _dispc_setup_color_conv_coef(void) REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); } +void dispc_setup_color_fr_lr(int range) +{ + struct color_conv_coef { + int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; + int full_range; + }; + const struct color_conv_coef ctbl_bt601_5_lr = { + 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, + }; + const struct color_conv_coef ctbl_bt601_5_fr = { + 256, 351, 0, 256, -179, -86, 256, 0, 443, 1, + }; + + const struct color_conv_coef *ct; + +#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) + + if (range) + ct = &ctbl_bt601_5_fr; + /*Full range selected if range = 1 else default limited range*/ + else + ct = &ctbl_bt601_5_lr; + + dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); + dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); + + dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); + dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); + if (cpu_is_omap44xx()) { + dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 0), + CVAL(ct->rcr, ct->ry)); + dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 1), + CVAL(ct->gy, ct->rcb)); + dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 2), + CVAL(ct->gcb, ct->gcr)); + dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 3), + CVAL(ct->bcr, ct->by)); + dispc_write_reg(DISPC_VID_V3_WB_CONV_COEF(0, 4), + CVAL(0, ct->bcb)); + REG_FLD_MOD(DISPC_VID_V3_WB_ATTRIBUTES(0), + ct->full_range, 11, 11); + } + +#undef CVAL + + REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); + REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); +} + static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 33e046ee209c..2519640b0ef6 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -164,7 +164,6 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL -err1: dsi_pll_uninit(ix); #endif err0: diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 20cb27f04336..b6bc39513573 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1307,6 +1307,10 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, DSSDBG("PLL init\n"); + /* The SCPClk is required for PLL and complexio registers on OMAP4 */ + if (cpu_is_omap44xx()) + REG_FLD_MOD(ix, DSI_CLK_CTRL, 1, 14, 14); + enable_clocks(1); dsi_enable_pll_clock(ix, 1); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 76d0c39b3990..2c6928674a78 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -436,6 +436,7 @@ void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); void dispc_enable_gamma_table(bool enable); void dispc_set_idle_mode(void); +void dispc_setup_color_fr_lr(int range); void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y); void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); diff --git a/drivers/video/omap2/dss/edid.c b/drivers/video/omap2/dss/edid.c index 68daf042054f..4f2dbcda0651 100644 --- a/drivers/video/omap2/dss/edid.c +++ b/drivers/video/omap2/dss/edid.c @@ -3,7 +3,7 @@ * * Copyright (C) 2009 Texas Instruments * Author: Mythri P K <mythripk@ti.com> - * With EDID parsing for DVI Monitor from Rob Clark <rob@ti.com> + * With EDID parsing for DVI Monitor from Rob Clark <rob@ti.com> * * EDID.c to read the EDID content , given the 256 Bytes EDID. * @@ -39,48 +39,49 @@ #include <linux/fs.h> #include <plat/edid.h> +/* All of the OMAP4 supported timing values */ +const struct omap_video_timings omap_hdmi_timings[OMAP_HDMI_TIMINGS_NB] = { + {640, 480, 25200, 96, 16, 48, 2, 10, 33}, + {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, + {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, + {720, 480, 27027, 62, 16, 60, 6, 9, 30}, + {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, + {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, + {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, + {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, + {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, + {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, + {720, 576, 27000, 64, 12, 68, 5, 5, 39}, + {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, + {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, + {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, + {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, + /* Vesa frome here */ + {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, + {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, + {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, + {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, + {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, + {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, + {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, + {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, + {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, + {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, + {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, + {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, + {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, + {1920, 1080, 148500, 44, 88, 80, 5, 4, 36}, + {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, + {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, + {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, + {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, + {1280, 720, 74250, 40, 110, 220, 5, 5, 20} +}; -/*This is the structure which has all supported timing values that OMAP4 supports*/ -const struct omap_video_timings omap_hdmi_timings[32] = { - {640, 480, 25200, 96, 16, 48, 2, 10, 33}, - {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, - {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, - {720, 480, 27000, 62, 16, 60, 6, 9, 30}, - {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, - {1440, 240, 27000, 124, 38, 114, 3, 4, 15}, - {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, - {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, - {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, - {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, - {720, 576, 27000, 64, 12, 68, 5, 5, 39}, - {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, - {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, - {2880, 480, 108000, 248, 64, 240, 6, 9, 30}, - /*Vesa frome here*/ - {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, - {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, - {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, - {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, - {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, - {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, - {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, - {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, - {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, - {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, - {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, - {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, - {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, - {1920, 1080, 148500, 44, 88, 80, 5, 4, 36}, - {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, - {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, - {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, - {1280, 800, 79500, 32, 48, 80, 6, 3, 14} } ; - -int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd, struct omap_video_timings *timings) +int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd, + struct omap_video_timings *timings) { - if (edid_dtd->video.pixel_clock) { - struct HDMI_EDID_DTD_VIDEO *vid = &edid_dtd->video; timings->pixel_clock = 10 * vid->pixel_clock; @@ -103,98 +104,103 @@ int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd, struct omap_video_timing (((u16)vid->vert_high & 0x0f) << 8)) - (timings->vfp + timings->vsw); return 0; - } else { - switch (edid_dtd->monitor_name.block_type) { - case HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA: - printk(KERN_INFO "standard timing data\n"); - return 1; - case HDMI_EDID_DTD_TAG_COLOR_POINT_DATA: - printk(KERN_INFO "color point data\n"); - return 1; - case HDMI_EDID_DTD_TAG_MONITOR_NAME: - printk(KERN_INFO "monitor name: %s\n", edid_dtd->monitor_name.text); - return 1; - case HDMI_EDID_DTD_TAG_MONITOR_LIMITS: { - int i, max_area = 0, best_idx = -1; - struct HDMI_EDID_DTD_MONITOR *limits = &edid_dtd->monitor_limits; + } + + switch (edid_dtd->monitor_name.block_type) { + case HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA: + printk(KERN_INFO "standard timing data\n"); + return 1; + case HDMI_EDID_DTD_TAG_COLOR_POINT_DATA: + printk(KERN_INFO "color point data\n"); + return 1; + case HDMI_EDID_DTD_TAG_MONITOR_NAME: + printk(KERN_INFO "monitor name: %s\n", + edid_dtd->monitor_name.text); + return 1; + case HDMI_EDID_DTD_TAG_MONITOR_LIMITS: + { + int i, max_area = 0, best_idx = -1; + struct HDMI_EDID_DTD_MONITOR *limits = + &edid_dtd->monitor_limits; + + printk(KERN_INFO "monitor limits\n"); + printk(KERN_INFO " min_vert_freq=%d\n", limits->min_vert_freq); + printk(KERN_INFO " max_vert_freq=%d\n", limits->max_vert_freq); + printk(KERN_INFO " min_horiz_freq=%d\n", + limits->min_horiz_freq); + printk(KERN_INFO " max_horiz_freq=%d\n", + limits->max_horiz_freq); + printk(KERN_INFO " pixel_clock_mhz=%d\n", + limits->pixel_clock_mhz * 10); - printk(KERN_INFO "monitor limits\n"); - printk(KERN_INFO " min_vert_freq=%d\n", - limits->min_vert_freq); - printk(KERN_INFO " max_vert_freq=%d\n", - limits->max_vert_freq); - printk(KERN_INFO " min_horiz_freq=%d\n", - limits->min_horiz_freq); - printk(KERN_INFO " max_horiz_freq=%d\n", - limits->max_horiz_freq); - printk(KERN_INFO " pixel_clock_mhz=%d\n", - limits->pixel_clock_mhz * 10); + /* find the highest matching resolution (w*h) */ - /* loop through supported timings, and find the best matching - * resolution.. where highest resolution (w*h) is considered - * as best */ + /* + * XXX since this is mainly for DVI monitors, should we only + * support VESA timings? My monitor at home would pick + * 1920x1080 otherwise, but that seems to not work well (monitor + * blanks out and comes back, and picture doesn't fill full + * screen, but leaves a black bar on left (native res is + * 2048x1152). However if I only consider VESA timings, it picks + * 1680x1050 and the picture is stable and fills whole screen + */ + for (i = OMAP_HDMI_TIMINGS_VESA_START; + i < OMAP_HDMI_TIMINGS_NB; i++) { + const struct omap_video_timings *timings = + &omap_hdmi_timings[i]; + int hz, hscan, pixclock; + int vtotal, htotal; + htotal = timings->hbp + timings->hfp + + timings->hsw + timings->x_res; + vtotal = timings->vbp + timings->vfp + + timings->vsw + timings->y_res; - /* XXX since this is mainly for DVI monitors, should we only - * support VESA timings? My monitor at home would pick 1920x1080 * otherwise, but that seems to not work well (monitor blanks out and * comes back, and picture doesn't fill full screen, but leaves a black * bar on left (native res is 2048x1152). However if I only consider - * VESA timings, it picks 1680x1050 and the picture is stable and fills * whole screen.. - */ - for (i = 14; i < 32; i++) { - const struct omap_video_timings *timings = - &omap_hdmi_timings[i]; - int hz, hscan, pixclock; - int vtotal, htotal; - htotal = timings->hbp + timings->hfp + - timings->hsw + timings->x_res; - vtotal = timings->vbp + timings->vfp + - timings->vsw + timings->y_res; - /* NOTE: We dont support interlaced mode for VESA */ - pixclock = timings->pixel_clock * 1000; - hscan = (pixclock + htotal / 2) / htotal; - hscan = (hscan + 500) / 1000 * 1000; - hz = (hscan + vtotal / 2) / vtotal; - hscan /= 1000; - pixclock /= 1000000; - printk(KERN_DEBUG "debug only pixclock=%d, hscan=%d, hz=%d\n", - pixclock, hscan, hz); - if ((pixclock < (limits->pixel_clock_mhz * 10)) && - (limits->min_horiz_freq <= hscan) && - (hscan <= limits->max_horiz_freq) && - (limits->min_vert_freq <= hz) && - (hz <= limits->max_vert_freq)) { - int area = timings->x_res * timings->y_res; - printk(KERN_INFO " -> %d: %dx%d\n", i, timings->x_res, - timings->y_res); - if (area > max_area) { - max_area = area; - best_idx = i; - } + /* NOTE: We don't support interlaced mode for VESA */ + pixclock = timings->pixel_clock * 1000; + hscan = (pixclock + htotal / 2) / htotal; + hscan = (hscan + 500) / 1000 * 1000; + hz = (hscan + vtotal / 2) / vtotal; + hscan /= 1000; + pixclock /= 1000000; + printk(KERN_DEBUG "debug only pixclock=%d, hscan=%d, hz=%d\n", + pixclock, hscan, hz); + if ((pixclock < (limits->pixel_clock_mhz * 10)) && + (limits->min_horiz_freq <= hscan) && + (hscan <= limits->max_horiz_freq) && + (limits->min_vert_freq <= hz) && + (hz <= limits->max_vert_freq)) { + int area = timings->x_res * timings->y_res; + printk(KERN_INFO " -> %d: %dx%d\n", i, + timings->x_res, timings->y_res); + if (area > max_area) { + max_area = area; + best_idx = i; } } - if (best_idx > 0) { - *timings = omap_hdmi_timings[best_idx]; - printk(KERN_INFO "found best resolution: %dx%d (%d)\n", - timings->x_res, timings->y_res, best_idx); - } - return 0; } - case HDMI_EDID_DTD_TAG_ASCII_STRING: - printk(KERN_INFO "ascii string: %s\n", edid_dtd->ascii.text); - return 1; - case HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM: - printk(KERN_INFO "monitor serialnum: %s\n", - edid_dtd->monitor_serial_number.text); - return 1; - default: - printk(KERN_INFO "unsupported EDID descriptor block format\n"); - return 1; + if (best_idx > 0) { + *timings = omap_hdmi_timings[best_idx]; + printk(KERN_INFO "found best resolution: %dx%d (%d)\n", + timings->x_res, timings->y_res, best_idx); } + return 0; + } + case HDMI_EDID_DTD_TAG_ASCII_STRING: + printk(KERN_INFO "ascii string: %s\n", edid_dtd->ascii.text); + return 1; + case HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM: + printk(KERN_INFO "monitor serialnum: %s\n", + edid_dtd->monitor_serial_number.text); + return 1; + default: + printk(KERN_INFO "unsupported EDID descriptor block format\n"); + return 1; } } void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid , struct omap_video_timings *timings) { - timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) | edid[current_descriptor_addrs + 2]); timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) @@ -209,39 +215,40 @@ void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid , (timings->hfp + timings->hsw); timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4); timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F); - timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) + timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | edid[current_descriptor_addrs + 6]) - (timings->vfp + timings->vsw); } -int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock, int *offset) +int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock, + int *offset) { int current_byte, disp, i = 0, length = 0; - if (edid[0x7e] != 0x00) { - printk(KERN_INFO "Extension block present"); - disp = edid[(0x80) + 2]; - printk("db %d %x ", datablock, disp); - if (disp != 0x4) { - i = 0x80 + 0x4; - printk("%x", i); - while (i < (0x80 + disp)) { - current_byte = edid[i]; - printk("i = %x " - "cur_byte = %x " - " (current_byte & HDMI_EDID_EX_DATABLOCK_TAG_MASK)" - " = %d", - i, current_byte, - (current_byte & HDMI_EDID_EX_DATABLOCK_TAG_MASK)); - if ((current_byte >> 5) == datablock) { - *offset = i; - printk("datablock %d %d ", datablock, *offset); - return 0; - } else { - length = (current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK) + 1; - i += length; - } - } + if (edid[0x7e] == 0x00) + return 1; + + disp = edid[(0x80) + 2]; + printk(KERN_INFO "Extension block present db %d %x\n", datablock, disp); + if (disp == 0x4) + return 1; + + i = 0x80 + 0x4; + printk(KERN_INFO "%x\n", i); + while (i < (0x80 + disp)) { + current_byte = edid[i]; + printk(KERN_INFO "i = %x cur_byte = %x (cur_byte & EX_DATABLOCK_TAG_MASK) = %d\n", + i, current_byte, + (current_byte & HDMI_EDID_EX_DATABLOCK_TAG_MASK)); + if ((current_byte >> 5) == datablock) { + *offset = i; + printk(KERN_INFO "datablock %d %d\n", + datablock, *offset); + return 0; + } else { + length = (current_byte & + HDMI_EDID_EX_DATABLOCK_LEN_MASK) + 1; + i += length; } } return 1; @@ -253,19 +260,20 @@ int hdmi_get_image_format(u8 *edid, struct image_format *format) enum extension_edid_db vsdb = DATABLOCK_VIDEO; format->length = 0; - memset(format->fmt, 0, sizeof(struct img_edid) * HDMI_IMG_FORMAT_MAX_LENGTH); + memset(format->fmt, 0, sizeof(format->fmt)); if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) { current_byte = edid[offset]; length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK; + if (length >= HDMI_IMG_FORMAT_MAX_LENGTH) format->length = HDMI_IMG_FORMAT_MAX_LENGTH; else format->length = length; + for (j = 1 ; j < length ; j++) { current_byte = edid[offset+j]; format->fmt[j-1].code = current_byte & 0x7F; format->fmt[j-1].pref = current_byte & 0x80; - } } return 0; @@ -277,7 +285,7 @@ int hdmi_get_audio_format(u8 *edid, struct audio_format *format) enum extension_edid_db vsdb = DATABLOCK_AUDIO; format->length = 0; - memset(format->fmt, 0, sizeof(struct audio_edid) * HDMI_AUDIO_FORMAT_MAX_LENGTH); + memset(format->fmt, 0, sizeof(format->fmt)); if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) { current_byte = edid[offset]; @@ -292,9 +300,9 @@ int hdmi_get_audio_format(u8 *edid, struct audio_format *format) if (j%3 == 1) { current_byte = edid[offset + j]; format->fmt[j-1].format = current_byte & 0x78; - format->fmt[j-1].num_of_ch = (current_byte & 0x07) + 1; + format->fmt[j-1].num_of_ch = + (current_byte & 0x07) + 1; } - } } return 0; @@ -323,30 +331,25 @@ void hdmi_deep_color_support_info(u8 *edid, struct deep_color *format) { int offset, current_byte, length = 0; enum extension_edid_db vsdb = DATABLOCK_VENDOR; - memset(format, 0, sizeof(struct deep_color)); + memset(format, 0, sizeof(*format)); + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) { current_byte = edid[offset]; length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK; if (length >= 6) { - format->bit_30 = - ((current_byte + 6) & 0x10); - format->bit_36 = - ((current_byte + 6) & 0x20); - } - if (length >= 7) { - format->max_tmds_freq = - ((current_byte + 7)) * 5; + format->bit_30 = ((current_byte + 6) & 0x10); + format->bit_36 = ((current_byte + 6) & 0x20); } + if (length >= 7) + format->max_tmds_freq = ((current_byte + 7)) * 5; } } int hdmi_tv_yuv_supported(u8 *edid) { - if (edid[0x7e] != 0x00) { - if (edid[0x83] & 0x30) { - printk(KERN_INFO "YUV supported"); - return 1; - } + if (edid[0x7e] != 0x00 && edid[0x83] & 0x30) { + printk(KERN_INFO "YUV supported"); + return 1; } return 0; } diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 492b9acc943d..6666aa465f72 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -18,11 +18,13 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. * History: - * Mythripk <mythripk@ti.com> Apr 2010 Modified for EDID reading and adding OMAP - * related timing + * Mythripk <mythripk@ti.com> Apr 2010 Modified for EDID reading and adding + * OMAP related timing * May 2010 Added support of Hot Plug Detect - * July 2010 Redesigned HDMI EDID for Auto-detect of timing - * August 2010 Char device user space control for HDMI + * July 2010 Redesigned HDMI EDID for Auto-detect + * of timing + * August 2010 Char device user space control for + * HDMI */ #define DSS_SUBSYS_NAME "HDMI" @@ -57,7 +59,8 @@ static void hdmi_get_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings); static void hdmi_set_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings); -static void hdmi_set_custom_edid_timing_code(struct omap_dss_device *dssdev, int code , int mode); +static void hdmi_set_custom_edid_timing_code(struct omap_dss_device *dssdev, + int code , int mode); static void hdmi_get_edid(struct omap_dss_device *dssdev); static int hdmi_check_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings); @@ -72,13 +75,13 @@ static int hdmi_release(struct inode *inode, struct file *filp); static int hdmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); - -/*Structures for chardevice move this to panel*/ +/* Structures for chardevice move this to panel */ static int hdmi_major; static struct cdev hdmi_cdev; static dev_t hdmi_dev_id; -/*This is a basic structure read and write ioctls will be added to configure parameters*/ -static struct file_operations hdmi_fops = { + +/* Read and write ioctls will be added to configure parameters */ +static const struct file_operations hdmi_fops = { .owner = THIS_MODULE, .open = hdmi_open, .release = hdmi_release, @@ -99,10 +102,10 @@ static bool user_hpd_state; /* user hpd state */ #define HDMI_PLLCTRL 0x58006200 #define HDMI_PHY 0x58006300 -u8 edid[HDMI_EDID_MAX_LENGTH] = {0}; -u8 edid_set = false; -u8 header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; -u8 hpd_mode = 0, custom_set = 0; +static u8 edid[HDMI_EDID_MAX_LENGTH] = {0}; +static u8 edid_set; +static u8 header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; +static u8 hpd_mode, custom_set; enum hdmi_ioctl_cmds { HDMI_ENABLE, @@ -130,78 +133,84 @@ struct hdmi_hvsync_pol { int hsync_pol; }; -/*This is the structure which has all supported timing values that OMAP4 supports*/ -const struct omap_video_timings all_timings_direct[32] = { - {640, 480, 25200, 96, 16, 48, 2, 10, 33}, - {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, - {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, - {720, 480, 27000, 62, 16, 60, 6, 9, 30}, - {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, - {1440, 240, 27000, 124, 38, 114, 3, 4, 15}, - {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, - {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, - {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, - {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, - {720, 576, 27000, 64, 12, 68, 5, 5, 39}, - {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, - {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, - {2880, 480, 108000, 248, 64, 240, 6, 9, 30}, - /*Vesa frome here*/ - {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, - {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, - {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, - {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, - {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, - {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, - {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, - {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, - {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, - {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, - {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, - {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, - {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, - {1920, 1080, 148500, 44, 88, 80, 5, 4, 36}, - {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, - {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, - {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, - {1280, 800, 79500, 32, 48, 80, 6, 3, 14} }; - -/*This is a static Mapping array which maps the timing values with corresponding CEA / VESA code*/ -int code_index[32] = {1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, - /* <--14 CEA 17--> vesa*/ - 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A, - 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B}; - -/*Static mapping of the Timing values with the corresponding Vsync and Hsync polarity*/ -const struct hdmi_hvsync_pol hvpol_mapping[32] = { - {0, 0}, {1, 1}, {1, 1}, {0, 0}, - {0, 0}, {0, 0}, {0, 0}, {1, 1}, - {1, 1}, {1, 1}, {0, 0}, {0, 0}, - {1, 1}, {0, 0}, {0, 0}, {1, 1}, - {1, 1}, {1, 0}, {1, 0}, {1, 1}, - {1, 1}, {1, 1}, {0, 0}, {1, 0}, - {1, 0}, {1, 0}, {1, 1}, {1, 1}, - {0, 1}, {0, 1}, {0, 1}, {0, 1} }; - -/*This is revere static mapping which maps the CEA / VESA code to the corresponding timing values*/ -/* note: table is 10 entries per line to make it easier to find index.. */ -int code_cea[39] = { - -1, 0, 3, 3, 2, 8, 5, 5, -1, -1, - -1, -1, -1, -1, -1, -1, 9, 10, 10, 1, - 7, 6, 6, -1, -1, -1, -1, -1, -1, 11, - 11, 12, -1, -1, -1, 13, 13, 4, 4}; - -/* note: table is 10 entries per line to make it easier to find index.. */ -int code_vesa[83] = { - -1, -1, -1, -1, 14, -1, -1, -1, -1, 15, - -1, -1, -1, -1, 16, -1, 22, -1, -1, -1, - -1, -1, 28, 17, -1, -1, -1, 31, 18, -1, - -1, -1, 20, -1, -1, 21, -1, -1, -1, 19, - -1, 29, 23, -1, -1, -1, -1, 24, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 30, 25, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 26, 27}; +/* All supported timing values that OMAP4 supports */ +static const +struct omap_video_timings all_timings_direct[OMAP_HDMI_TIMINGS_NB] = { + {640, 480, 25200, 96, 16, 48, 2, 10, 33}, + {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, + {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, + {720, 480, 27027, 62, 16, 60, 6, 9, 30}, + {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, + {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, + {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, + {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, + {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, + {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, + {720, 576, 27000, 64, 12, 68, 5, 5, 39}, + {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, + {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, + {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, + {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, + /*Vesa frome here*/ + {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, + {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, + {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, + {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, + {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, + {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, + {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, + {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, + {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, + {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, + {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, + {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, + {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, + {1920, 1080, 148500, 44, 88, 80, 5, 4, 36}, + {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, + {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, + {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, + {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, + {1280, 720, 74250, 40, 110, 220, 5, 5, 20} }; + +/* Array which maps the timing values with corresponding CEA / VESA code */ +static int code_index[OMAP_HDMI_TIMINGS_NB] = { + 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32, + /* <--15 CEA 17--> vesa*/ + 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A, + 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B +}; + +/* Mapping the Timing values with the corresponding Vsync and Hsync polarity */ +static const struct hdmi_hvsync_pol hvpol_mapping[OMAP_HDMI_TIMINGS_NB] = { + {0, 0}, {1, 1}, {1, 1}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {1, 1}, + {1, 1}, {1, 1}, {0, 0}, {0, 0}, + {1, 1}, {0, 0}, {1, 1},/*VESA*/ + {0, 0}, {1, 1}, {1, 1}, {1, 0}, + {1, 0}, {1, 1}, {1, 1}, {1, 1}, + {0, 0}, {1, 0}, {1, 0}, {1, 0}, + {1, 1}, {1, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {1, 1} +}; + +/* Map CEA / VESA code to the corresponding timing values (10 entries/line) */ +static int code_cea[39] = { + -1, 0, 3, 3, 2, 8, 5, 5, -1, -1, + -1, -1, -1, -1, -1, -1, 9, 10, 10, 1, + 7, 6, 6, -1, -1, -1, -1, -1, -1, 11, + 11, 12, 14, -1, -1, 13, 13, 4, 4 +}; + +int code_vesa[85] = { + -1, -1, -1, -1, 15, -1, -1, -1, -1, 16, + -1, -1, -1, -1, 17, -1, 23, -1, -1, -1, + -1, -1, 29, 18, -1, -1, -1, 32, 19, -1, + -1, -1, 21, -1, -1, 22, -1, -1, -1, 20, + -1, 30, 24, -1, -1, -1, -1, 25, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 31, 26, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 27, 28, -1, 33}; struct hdmi { struct kobject kobj; @@ -211,11 +220,12 @@ struct hdmi { int code; int mode; int deep_color; + int lr_fr; + int force_set; struct hdmi_config cfg; struct omap_display_platform_data *pdata; struct platform_device *pdev; -}; -struct hdmi hdmi; +} hdmi; struct hdmi_cm { int code; @@ -223,7 +233,8 @@ struct hdmi_cm { }; struct omap_video_timings edid_timings; -static void update_cfg (struct hdmi_config *cfg, struct omap_video_timings *timings) +static void update_cfg(struct hdmi_config *cfg, + struct omap_video_timings *timings) { cfg->ppl = timings->x_res; cfg->lpp = timings->y_res; @@ -248,13 +259,13 @@ static inline void hdmi_write_reg(u32 base, u16 idx, u32 val) switch (base) { case HDMI_PHY: - b = hdmi.base_phy; - break; + b = hdmi.base_phy; + break; case HDMI_PLLCTRL: - b = hdmi.base_pll; - break; + b = hdmi.base_pll; + break; default: - BUG(); + BUG(); } __raw_writel(val, b + idx); /* DBG("write = 0x%x idx =0x%x\r\n", val, idx); */ @@ -267,13 +278,13 @@ static inline u32 hdmi_read_reg(u32 base, u16 idx) switch (base) { case HDMI_PHY: - b = hdmi.base_phy; - break; + b = hdmi.base_phy; + break; case HDMI_PLLCTRL: - b = hdmi.base_pll; - break; + b = hdmi.base_pll; + break; default: - BUG(); + BUG(); } l = __raw_readl(b + idx); @@ -288,8 +299,6 @@ static inline u32 hdmi_read_reg(u32 base, u16 idx) #define REG_FLD_MOD(b, i, v, s, e) \ hdmi_write_reg(b, i, FLD_MOD(hdmi_read_reg(b, i), v, s, e)) - - static ssize_t hdmi_edid_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -315,17 +324,13 @@ static ssize_t hdmi_yuv_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - int enabled; - enabled = simple_strtoul(buf, NULL, 10); - if (enabled) - hdmi_configure_csc(RGB_TO_YUV); - else - hdmi_configure_csc(RGB); - - return size; + unsigned long yuv; + int r = strict_strtoul(buf, 0, &yuv); + if (r == 0) + hdmi_configure_csc(yuv ? RGB_TO_YUV : RGB); + return r ? : size; } - static ssize_t hdmi_deepcolor_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -336,15 +341,79 @@ static ssize_t hdmi_deepcolor_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - int deepcolor; - deepcolor = simple_strtoul(buf, NULL, 0); - hdmi.deep_color = deepcolor; + unsigned long deep_color; + int r = strict_strtoul(buf, 0, &deep_color); + if (r || deep_color > 2) + return -EINVAL; + hdmi.deep_color = deep_color; + return size; +} + +/* + * This function is used to configure Limited range/full range + * with RGB format , with YUV format Full range is not supported + * Please refer to section 6.6 Video quantization ranges in HDMI 1.3a + * specification for more details. + * Now conversion to Full range or limited range can either be done at + * display controller or HDMI IP ,This function allows to select either + * Please note : To convert to full range it is better to convert the video + * in the dispc to full range as there will be no loss of data , if a + * limited range data is sent ot HDMI and converted to Full range in HDMI + * the data quality would not be good. + */ +static void hdmi_configure_lr_fr(void) +{ + int ret = 0; + if (hdmi.mode == 0 || (hdmi.mode == 1 && hdmi.code == 1)) { + ret = hdmi_configure_lrfr(HDMI_FULL_RANGE, 0); + if (!ret) + dispc_setup_color_fr_lr(1); + return; + } + if (hdmi.lr_fr) { + ret = hdmi_configure_lrfr(HDMI_FULL_RANGE, hdmi.force_set); + if (!ret && !hdmi.force_set) + dispc_setup_color_fr_lr(1); + } else { + ret = hdmi_configure_lrfr(HDMI_LIMITED_RANGE, hdmi.force_set); + if (!ret && !hdmi.force_set) + dispc_setup_color_fr_lr(0); + } +} + +static ssize_t hdmi_lr_fr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d:%d\n", hdmi.lr_fr, hdmi.force_set); +} + +static ssize_t hdmi_lr_fr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int lr_fr, force_set = 0; + if (!*buf || !strchr("yY1nN0", *buf)) + return -EINVAL; + lr_fr = !!strchr("yY1", *buf++); + if (*buf && *buf != '\n') { + if (!strchr(" \t,:", *buf++) || + !*buf || !strchr("yY1nN0", *buf)) + return -EINVAL; + force_set = !!strchr("yY1", *buf++); + } + if (*buf && strcmp(buf, "\n")) + return -EINVAL; + hdmi.lr_fr = lr_fr; + hdmi.force_set = force_set; + hdmi_configure_lr_fr(); return size; } static DEVICE_ATTR(edid, S_IRUGO, hdmi_edid_show, hdmi_edid_store); static DEVICE_ATTR(yuv, S_IRUGO | S_IWUSR, hdmi_yuv_supported, hdmi_yuv_set); -static DEVICE_ATTR(deepcolor, S_IRUGO | S_IWUSR, hdmi_deepcolor_show, hdmi_deepcolor_store); +static DEVICE_ATTR(deepcolor, S_IRUGO | S_IWUSR, hdmi_deepcolor_show, + hdmi_deepcolor_store); +static DEVICE_ATTR(lr_fr, S_IRUGO | S_IWUSR, hdmi_lr_fr_show, hdmi_lr_fr_store); static int set_hdmi_hot_plug_status(struct omap_dss_device *dssdev, bool onoff) { @@ -378,18 +447,24 @@ static int hdmi_release(struct inode *inode, struct file *filp) return 0; } +static struct omap_dss_device *get_hdmi_device(void) +{ + int match(struct omap_dss_device *dssdev, void *arg) + { + return sysfs_streq(dssdev->name , "hdmi"); + } + + return omap_dss_find_device(NULL, match); +} + static int hdmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct omap_dss_device *dssdev = NULL; - const char *buf = "hdmi"; + struct omap_dss_device *dssdev = get_hdmi_device(); int r = 0; - int match(struct omap_dss_device *dssdev2 , void *data) - { - const char *str = data; - return sysfs_streq(dssdev2->name , str); - } - dssdev = omap_dss_find_device((void *)buf , match); + + if (dssdev == NULL) + return -EIO; switch (cmd) { case HDMI_ENABLE: @@ -397,7 +472,6 @@ static int hdmi_ioctl(struct inode *inode, struct file *file, /* set HDMI full power on resume (in case suspended) */ is_hdmi_on = true; break; - case HDMI_DISABLE: hdmi_disable_display(dssdev); break; @@ -461,7 +535,6 @@ static void compute_pll(int clkin, int phy, int refclk; u32 temp, mf; - refclk = clkin / (n + 1); temp = phy * 100/(refclk); @@ -473,19 +546,16 @@ static void compute_pll(int clkin, int phy, mf = (phy - pi->regm * refclk) * 262144; pi->regmf = mf/(refclk); - if (phy > 1000 * 100) { - pi->dcofreq = 1; - pi->regsd = ((pi->regm * 384)/((n + 1) * 250) + 5)/10; - } else { - pi->dcofreq = 0; - pi->regsd = 0; - } + pi->dcofreq = phy > 1000 * 100; + + pi->regsd = ((pi->regm * clkin / 10) / ((n + 1) * 250) + 5) / 10; DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); } -static int hdmi_pll_init(int refsel, int dcofreq, struct hdmi_pll_info *fmt, u16 sd) +static int hdmi_pll_init(int refsel, int dcofreq, struct hdmi_pll_info *fmt, + u16 sd) { u32 r; unsigned t = 500000; @@ -510,8 +580,9 @@ static int hdmi_pll_init(int refsel, int dcofreq, struct hdmi_pll_info *fmt, u16 /* divider programming for 1080p */ REG_FLD_MOD(pll, PLLCTRL_CFG3, sd, 17, 10); r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ - } else + } else { r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ + } hdmi_write_reg(pll, PLLCTRL_CFG2, r); @@ -519,11 +590,14 @@ static int hdmi_pll_init(int refsel, int dcofreq, struct hdmi_pll_info *fmt, u16 r = FLD_MOD(r, fmt->regm2, 24, 18); r = FLD_MOD(r, fmt->regmf, 17, 0); + hdmi_write_reg(pll, PLLCTRL_CFG4, r); + /* go now */ REG_FLD_MOD(pll, PLLCTRL_PLL_GO, 0x1ul, 0, 0); /* wait for bit change */ while (FLD_GET(hdmi_read_reg(pll, PLLCTRL_PLL_GO), 0, 0)) + ; /* Wait till the lock bit is set */ /* read PLL status */ @@ -559,10 +633,11 @@ static int hdmi_pll_reset(void) return -ENODEV; } } + return 0; } -int hdmi_pll_program(struct hdmi_pll_info *fmt) +static int hdmi_pll_program(struct hdmi_pll_info *fmt) { u32 r; int refsel; @@ -574,15 +649,13 @@ int hdmi_pll_program(struct hdmi_pll_info *fmt) /* power off PLL */ PllPwrWaitParam = HDMI_PLLPWRCMD_ALLOFF; - r = HDMI_W1_SetWaitPllPwrState(HDMI_WP, - PllPwrWaitParam); + r = HDMI_W1_SetWaitPllPwrState(HDMI_WP, PllPwrWaitParam); if (r) return r; /* power on PLL */ PllPwrWaitParam = HDMI_PLLPWRCMD_BOTHON_ALLCLKS; - r = HDMI_W1_SetWaitPllPwrState(HDMI_WP, - PllPwrWaitParam); + r = HDMI_W1_SetWaitPllPwrState(HDMI_WP, PllPwrWaitParam); if (r) return r; @@ -621,8 +694,7 @@ static int hdmi_phy_init(u32 w1, REG_FLD_MOD(phy, HDMI_TXPHY_TX_CTRL, tmds, 31, 30); /* write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ - hdmi_write_reg(phy, HDMI_TXPHY_DIGITAL_CTRL, - 0xF0000000); + hdmi_write_reg(phy, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); /* setup max LDO voltage */ REG_FLD_MOD(phy, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); @@ -666,15 +738,16 @@ static int get_timings_index(void) static int hdmi_panel_probe(struct omap_dss_device *dssdev) { int code; - printk("ENTER hdmi_panel_probe()\n"); + printk(KERN_DEBUG "ENTER hdmi_panel_probe()\n"); dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; hdmi.deep_color = 0; + hdmi.lr_fr = HDMI_LIMITED_RANGE; code = get_timings_index(); dssdev->panel.timings = all_timings_direct[code]; - printk("hdmi_panel_probe x_res= %d y_res = %d", \ + printk(KERN_INFO "hdmi_panel_probe x_res= %d y_res = %d", \ dssdev->panel.timings.x_res, dssdev->panel.timings.y_res); mdelay(50); @@ -684,7 +757,6 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev) static void hdmi_panel_remove(struct omap_dss_device *dssdev) { - } static bool hdmi_panel_is_enabled(struct omap_dss_device *dssdev) @@ -751,14 +823,15 @@ int hdmi_init(struct platform_device *pdev) { int r = 0, hdmi_irq; struct resource *hdmi_mem; - printk("Enter hdmi_init()\n"); + printk(KERN_INFO "Enter hdmi_init()\n"); hdmi.pdata = pdev->dev.platform_data; hdmi.pdev = pdev; mutex_init(&hdmi.lock); hdmi_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); - hdmi.base_pll = ioremap((hdmi_mem->start + 0x200), resource_size(hdmi_mem)); + hdmi.base_pll = ioremap(hdmi_mem->start + 0x200, + resource_size(hdmi_mem)); if (!hdmi.base_pll) { ERR("can't ioremap pll\n"); return -ENOMEM; @@ -778,7 +851,7 @@ int hdmi_init(struct platform_device *pdev) /* Get the major number for this module */ r = alloc_chrdev_region(&hdmi_dev_id, 0, 1, "hdmi_panel"); if (r) { - printk("HDMI: Cound not register character device\n"); + printk(KERN_WARNING "HDMI: Cound not register character device\n"); return -ENOMEM; } @@ -793,19 +866,15 @@ int hdmi_init(struct platform_device *pdev) /* add char driver */ r = cdev_add(&hdmi_cdev, hdmi_dev_id, 1); if (r) { - printk("HDMI: Could not add hdmi char driver\n"); + printk(KERN_WARNING "HDMI: Could not add hdmi char driver\n"); unregister_chrdev_region(hdmi_dev_id, 1); return -ENOMEM; } hdmi_irq = platform_get_irq(pdev, 0); - r = request_irq(hdmi_irq, - hdmi_irq_handler, - 0, "OMAP HDMI", (void *)0); - + r = request_irq(hdmi_irq, hdmi_irq_handler, 0, "OMAP HDMI", (void *)0); return omap_dss_register_driver(&hdmi_driver); - } void hdmi_exit(void) @@ -820,11 +889,11 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) { int r = 0; int code = 0; - int dirty = false; + int dirty; struct omap_video_timings *p; struct hdmi_pll_info pll_data; struct deep_color *vsdb_format = NULL; - int clkin, n, phy, max_tmds, temp = 0, tmds_freq; + int clkin, n, phy = 0, max_tmds = 0, temp = 0, tmds_freq; hdmi_power = HDMI_POWER_FULL; code = get_timings_index(); @@ -835,7 +904,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) p = &dssdev->panel.timings; if (!custom_set) { - code = get_timings_index(); DSSDBG("No edid set thus will be calling hdmi_read_edid"); @@ -847,13 +915,12 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) vsdb_format = kzalloc(sizeof(*vsdb_format), GFP_KERNEL); hdmi_deep_color_support_info(edid, vsdb_format); - printk("%d deep color bit 30 %d deep color 36 bit %d max tmds freq", - vsdb_format->bit_30, vsdb_format->bit_36, vsdb_format->max_tmds_freq); + printk(KERN_INFO "%d deep color bit 30 %d deep color 36 bit " + " %d max tmds freq", vsdb_format->bit_30, + vsdb_format->bit_36, vsdb_format->max_tmds_freq); max_tmds = vsdb_format->max_tmds_freq * 500; - if (get_timings_index() != code) { - dirty = true; - } + dirty = get_timings_index() != code; } else { dirty = true; } @@ -867,8 +934,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) DSSDBG("hdmi_power on x_res= %d y_res = %d", \ dssdev->panel.timings.x_res, dssdev->panel.timings.y_res); - DSSDBG("hdmi_power on code= %d mode = %d", hdmi.code, - hdmi.mode); + DSSDBG("hdmi_power on code= %d mode = %d", hdmi.code, hdmi.mode); clkin = 3840; /* 38.4 mHz */ n = 15; /* this is a constant for our math */ @@ -879,37 +945,38 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) hdmi.cfg.deep_color = 0; break; case 1: + temp = (p->pixel_clock * 125) / 100 ; if (!custom_set) { - temp = (p->pixel_clock * 125) / 100 ; if (vsdb_format->bit_30) { if (max_tmds != 0 && max_tmds >= temp) - phy = (p->pixel_clock * 125) / 100; + phy = temp; } else { - printk(KERN_ERR"TV does not support Deep color"); + printk(KERN_ERR "TV does not support Deep color"); goto err; } } else { - phy = (p->pixel_clock * 125) / 100; + phy = temp; } hdmi.cfg.deep_color = 1; break; case 2: - if (p->pixel_clock != 148500) { - if (!custom_set) { - temp = (int)(p->pixel_clock * 150) / 100; - if (vsdb_format->bit_36) { - if (max_tmds != 0 && max_tmds >= temp) - phy = (p->pixel_clock * 150) / 100; - } else { - printk(KERN_ERR"TV does not support Deep color"); - goto err; - } - } else - phy = (p->pixel_clock * 150) / 100; - } else { + if (p->pixel_clock == 148500) { printk(KERN_ERR"36 bit deep color not supported"); goto err; } + + temp = (p->pixel_clock * 150) / 100; + if (!custom_set) { + if (vsdb_format->bit_36) { + if (max_tmds != 0 && max_tmds >= temp) + phy = temp; + } else { + printk(KERN_ERR "TV does not support Deep color"); + goto err; + } + } else { + phy = temp; + } hdmi.cfg.deep_color = 2; break; } @@ -920,9 +987,8 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) dispc_enable_digit_out(0); - if (dirty) { + if (dirty) omap_dss_notify(dssdev, OMAP_DSS_SIZE_CHANGE); - } /* config the PLL and PHY first */ r = hdmi_pll_program(&pll_data); @@ -932,7 +998,8 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) goto err; } - if (phy <= 50000) /*TMDS freq_out in the PHY should be set based on the TMDS clock*/ + /* TMDS freq_out in the PHY should be set based on the TMDS clock */ + if (phy <= 50000) tmds_freq = 0x0; else if ((phy > 50000) && (phy <= 100000)) tmds_freq = 0x1; @@ -965,6 +1032,8 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) hdmi_lib_enable(&hdmi.cfg); + hdmi_configure_lr_fr(); + /* these settings are independent of overlays */ dss_switch_tv_hdmi(1); @@ -997,48 +1066,46 @@ err: return r; } -int hdmi_min_enable(void) +static int hdmi_min_enable(void) { int r; DSSDBG("hdmi_min_enable"); hdmi_power = HDMI_POWER_MIN; r = hdmi_phy_init(HDMI_WP, HDMI_PHY, 0); - if (r) { + if (r) DSSERR("Failed to start PHY\n"); - } hdmi.cfg.hdmi_dvi = hdmi.mode; hdmi.cfg.video_format = hdmi.code; hdmi_lib_enable(&hdmi.cfg); return 0; } -static spinlock_t irqstatus_lock = SPIN_LOCK_UNLOCKED; -static volatile int irqstatus; +static DEFINE_SPINLOCK(irqstatus_lock); -void hdmi_work_queue(struct work_struct *work) -{ - struct omap_dss_device *dssdev = NULL; - const char *buf = "hdmi"; +struct hdmi_work_struct { + struct work_struct work; int r; - unsigned long flags; +}; - int match(struct omap_dss_device *dssdev2 , void *data) - { - const char *str = data; - return sysfs_streq(dssdev2->name , str); - } - dssdev = omap_dss_find_device((void *)buf , match); - DSSDBG("found hdmi handle %s" , dssdev->name); +static void hdmi_work_queue(struct work_struct *ws) +{ + struct hdmi_work_struct *work = + container_of(ws, struct hdmi_work_struct, work); + struct omap_dss_device *dssdev = get_hdmi_device(); + int r = work->r; - spin_lock_irqsave(&irqstatus_lock, flags); - r = irqstatus; - irqstatus = 0; - spin_unlock_irqrestore(&irqstatus_lock, flags); + mutex_lock(&hdmi.lock); + if (dssdev == NULL || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + /* HDMI is disabled, there cannot be any HDMI irqs */ + goto done; + + DSSDBG("found hdmi handle %s" , dssdev->name); DSSDBG("irqstatus=%08x\n hdp_mode = %d dssdev->state = %d, " "hdmi_power = %d", r, hpd_mode, dssdev->state, hdmi_power); - if ((r & HDMI_DISCONNECT) && (hdmi_power == HDMI_POWER_FULL) && (hpd_mode == 1)) { + if ((r & HDMI_DISCONNECT) && (hdmi_power == HDMI_POWER_FULL) && + (hpd_mode == 1)) { set_hdmi_hot_plug_status(dssdev, false); /* ignore return value for now */ @@ -1047,7 +1114,9 @@ void hdmi_work_queue(struct work_struct *work) * audio/video enough time to stop operations. However, if * user reconnects HDMI, response will be delayed. */ + mutex_unlock(&hdmi.lock); mdelay(1000); + mutex_lock(&hdmi.lock); DSSINFO("Display disabled\n"); HDMI_W1_StopVideoFrame(HDMI_WP); @@ -1072,12 +1141,18 @@ void hdmi_work_queue(struct work_struct *work) hdmi_enable_clocks(1); is_hdmi_on = true; hdmi_set_power(dssdev); + mutex_unlock(&hdmi.lock); mdelay(1000); + mutex_lock(&hdmi.lock); + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + /* HDMI is disabled, no need to process */ + goto done; } if ((r & HDMI_HPD) && (hpd_mode == 1)) { - + mutex_unlock(&hdmi.lock); mdelay(1000); + mutex_lock(&hdmi.lock); /* * HDMI should already be full on. We use this to read EDID @@ -1094,38 +1169,35 @@ void hdmi_work_queue(struct work_struct *work) /* ignore return value for now */ } +done: + mutex_unlock(&hdmi.lock); kfree(work); } static irqreturn_t hdmi_irq_handler(int irq, void *arg) { - struct work_struct *work; + struct hdmi_work_struct *work; unsigned long flags; int r = 0; - int work_pending; + + /* process interrupt in critical section to handle conflicts */ + spin_lock_irqsave(&irqstatus_lock, flags); HDMI_W1_HPD_handler(&r); - DSSDBG("r=%08x, prev irqstatus=%08x\n", r, irqstatus); + DSSDBG("Received IRQ r=%08x\n", r); - if (((r & HDMI_CONNECT) || (r & HDMI_HPD)) && (hpd_mode == 1)) + if (((r & HDMI_CONNECT) || (r & HDMI_HPD)) && (hpd_mode == 1)) hdmi_enable_clocks(1); - - spin_lock_irqsave(&irqstatus_lock, flags); - work_pending = irqstatus; - if (r & HDMI_DISCONNECT) - irqstatus &= ~HDMI_CONNECT; - if (r & HDMI_CONNECT) - irqstatus &= ~HDMI_DISCONNECT; - irqstatus |= r; spin_unlock_irqrestore(&irqstatus_lock, flags); - if (r && !work_pending) { - work = kmalloc(sizeof(struct work_struct), GFP_KERNEL); + if (r) { + work = kmalloc(sizeof(*work), GFP_KERNEL); if (work) { - INIT_WORK(work, hdmi_work_queue); - schedule_work(work); + INIT_WORK(&work->work, hdmi_work_queue); + work->r = r; + schedule_work(&work->work); } else { printk(KERN_ERR "Cannot allocate memory to create work"); } @@ -1166,7 +1238,6 @@ static void hdmi_power_off(struct omap_dss_device *dssdev) dss_mainclk_state_disable(true); /* reset to default */ - } static int hdmi_start_display(struct omap_dss_device *dssdev) @@ -1360,9 +1431,10 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev, } } -static void hdmi_set_custom_edid_timing_code(struct omap_dss_device *dssdev, int code , int mode) +static void hdmi_set_custom_edid_timing_code(struct omap_dss_device *dssdev, + int code , int mode) { - if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { /* turn the hdmi off and on to get new timings to use */ hdmi_disable_display(dssdev); hdmi.code = code; @@ -1383,41 +1455,37 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) for (i = 0; i < 32; i++) { temp = all_timings_direct[i]; - if ((temp.pixel_clock == timing->pixel_clock) && - (temp.x_res == timing->x_res) && - (temp.y_res == timing->y_res)) { - - temp_hsync = temp.hfp + temp.hsw + temp.hbp; - timing_hsync = timing->hfp + timing->hsw + timing->hbp; - temp_vsync = temp.vfp + temp.vsw + temp.vbp; - timing_vsync = timing->vfp + timing->vsw + timing->vbp; - - printk("Temp_hsync = %d , temp_vsync = %d , \ - timing_hsync = %d, timing_vsync = %d", \ - temp_hsync, temp_hsync, timing_hsync, timing_vsync); - - if ((temp_hsync == timing_hsync) && (temp_vsync == timing_vsync)) { - code = i; - cm.code = code_index[i]; - if (code < 14) - cm.mode = 1; - else - cm.mode = 0; - DSSDBG("Hdmi_code = %d mode = %d\n", cm.code, cm.mode); - print_omap_video_timings(&temp); - break; - } - } + if (temp.pixel_clock != timing->pixel_clock || + temp.x_res != timing->x_res || + temp.y_res != timing->y_res) + continue; + temp_hsync = temp.hfp + temp.hsw + temp.hbp; + timing_hsync = timing->hfp + timing->hsw + timing->hbp; + temp_vsync = temp.vfp + temp.vsw + temp.vbp; + timing_vsync = timing->vfp + timing->vsw + timing->vbp; + + printk(KERN_INFO "Temp_hsync = %d, temp_vsync = %d, " + "timing_hsync = %d, timing_vsync = %d", + temp_hsync, temp_hsync, timing_hsync, timing_vsync); + + if (temp_hsync == timing_hsync && temp_vsync == timing_vsync) { + code = i; + cm.code = code_index[i]; + cm.mode = code < 14; + DSSDBG("Hdmi_code = %d mode = %d\n", cm.code, cm.mode); + print_omap_video_timings(&temp); + break; + } } return cm; } static void hdmi_get_edid(struct omap_dss_device *dssdev) { - u8 i = 0, flag = 0, mark = 0; - int count, offset, effective_addrs, current_descriptor_addrs = 0; - struct HDMI_EDID * edid_st = (struct HDMI_EDID *)edid; + u8 i = 0, mark = 0, *e; + int offset, addr; + struct HDMI_EDID *edid_st = (struct HDMI_EDID *)edid; struct image_format *img_format; struct audio_format *aud_format; struct deep_color *vsdb_format; @@ -1429,107 +1497,96 @@ static void hdmi_get_edid(struct omap_dss_device *dssdev) vsdb_format = kzalloc(sizeof(*vsdb_format), GFP_KERNEL); lat = kzalloc(sizeof(*lat), GFP_KERNEL); - if (edid_set != 1) { - printk(KERN_WARNING "Display doesnt seem to be enabled invalid read\n"); - if (HDMI_CORE_DDC_READEDID(HDMI_CORE_SYS, edid) != 0) { - printk(KERN_WARNING "HDMI failed to read E-EDID\n"); - } - for (i = 0x00; i < 0x08; i++) { - if (edid[i] == header[i]) - continue; - else { - flag = 1; - break; - } - } - if (flag == 0) - edid_set = 1; + if (!edid_set) { + printk(KERN_WARNING "Display doesn't seem to be enabled invalid read\n"); + if (HDMI_CORE_DDC_READEDID(HDMI_CORE_SYS, edid, + HDMI_EDID_MAX_LENGTH) != 0) + printk(KERN_WARNING "HDMI failed to read E-EDID\n"); + edid_set = !memcmp(edid, header, sizeof(header)); } mdelay(1000); - printk("\nHeader:\n"); - for (i = 0x00; i < 0x08; i++) - printk("%02x ", edid[i]); - printk("\nVendor & Product:\n"); - for (i = 0x08; i < 0x12; i++) - printk("%02x ", edid[i]); - printk("\nEDID Structure:\n"); - for (i = 0x12; i < 0x14; i++) - printk("%02x ", edid[i]); - printk("\nBasic Display Parameter:\n"); - for (i = 0x14; i < 0x19; i++) - printk("%02x ", edid[i]); - printk("\nColor Characteristics:\n"); - for (i = 0x19; i < 0x23; i++) - printk("%02x ", edid[i]); - printk("\nEstablished timings:\n"); - for (i = 0x23; i < 0x26; i++) - printk("%02x ", edid[i]); - printk("\nStandard timings:\n"); - for (i = 0x26; i < 0x36; i++) - printk("%02x ", edid[i]); - - for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { - current_descriptor_addrs = - EDID_DESCRIPTOR_BLOCK0_ADDRESS + - count * EDID_TIMING_DESCRIPTOR_SIZE; - printk("Extension 0 Block %d", count); - get_edid_timing_info(&edid_st->DTD[count], &timings); - if (!dss_debug) { - dss_debug = 1; - mark = 1; - } - print_omap_video_timings(&timings); - if (mark) - dss_debug = 0; - } + e = edid; + printk(KERN_INFO "\nHeader:\n%02x\t%02x\t%02x\t%02x\t%02x\t%02x\t" + "%02x\t%02x\n", e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7]); + e += 8; + printk(KERN_INFO "Vendor & Product:\n%02x\t%02x\t%02x\t%02x\t%02x\t" + "%02x\t%02x\t%02x\t%02x\t%02x\n", + e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9]); + e += 10; + printk(KERN_INFO "EDID Structure:\n%02x\t%02x\n", + e[0], e[1]); + e += 2; + printk(KERN_INFO "Basic Display Parameter:\n%02x\t%02x\t%02x\t%02x\t%02x\n", + e[0], e[1], e[2], e[3], e[4]); + e += 5; + printk(KERN_INFO "Color Characteristics:\n%02x\t%02x\t%02x\t%02x\t" + "%02x\t%02x\t%02x\t%02x\t%02x\t%02x\n", + e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9]); + e += 10; + printk(KERN_INFO "Established timings:\n%02x\t%02x\t%02x\n", + e[0], e[1], e[2]); + e += 3; + printk(KERN_INFO "Standard timings:\n%02x\t%02x\t%02x\t%02x\t%02x\t" + "%02x\t%02x\t%02x\n", + e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7]); + e += 8; + printk(KERN_INFO "%02x\t%02x\t%02x\t%02x\t%02x\t%02x\t%02x\t%02x\n", + e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7]); + e += 8; + + for (i = 0; i < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; i++) { + printk(KERN_INFO "Extension 0 Block %d\n", i); + get_edid_timing_info(&edid_st->DTD[i], &timings); + mark = dss_debug; + dss_debug = 1; + print_omap_video_timings(&timings); + dss_debug = mark; + } if (edid[0x7e] != 0x00) { offset = edid[EDID_DESCRIPTOR_BLOCK1_ADDRESS + 2]; - printk("\n offset %x\n", offset); + printk(KERN_INFO "offset %x\n", offset); if (offset != 0) { - effective_addrs = EDID_DESCRIPTOR_BLOCK1_ADDRESS - + offset; + addr = EDID_DESCRIPTOR_BLOCK1_ADDRESS + offset; /*to determine the number of descriptor blocks */ - for (count = 0; - count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; - count++) { - current_descriptor_addrs = effective_addrs + - count * EDID_TIMING_DESCRIPTOR_SIZE; - printk("Extension 1 Block %d", count); - get_eedid_timing_info(current_descriptor_addrs, edid , - &timings); - if (!dss_debug) { + for (i = 0; i < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; + i++) { + printk(KERN_INFO "Extension 1 Block %d", i); + get_eedid_timing_info(addr, edid, &timings); + addr += EDID_TIMING_DESCRIPTOR_SIZE; + mark = dss_debug; dss_debug = 1; - mark = 1; - } - print_omap_video_timings(&timings); - if (mark) - dss_debug = 0; + print_omap_video_timings(&timings); + dss_debug = mark; } } } hdmi_get_image_format(edid, img_format); - printk("%d audio length\n", img_format->length); + printk(KERN_INFO "%d audio length\n", img_format->length); for (i = 0 ; i < img_format->length ; i++) - printk("%d %d pref code\n", img_format->fmt[i].pref, img_format->fmt[i].code); + printk(KERN_INFO "%d %d pref code\n", + img_format->fmt[i].pref, img_format->fmt[i].code); hdmi_get_audio_format(edid, aud_format); - printk("%d audio length\n", aud_format->length); + printk(KERN_INFO "%d audio length\n", aud_format->length); for (i = 0 ; i < aud_format->length ; i++) - printk("%d %d format num_of_channels\n", aud_format->fmt[i].format, - aud_format->fmt[i].num_of_ch); + printk(KERN_INFO "%d %d format num_of_channels\n", + aud_format->fmt[i].format, + aud_format->fmt[i].num_of_ch); hdmi_deep_color_support_info(edid, vsdb_format); - printk("%d deep color bit 30 %d deep color 36 bit %d max tmds freq", - vsdb_format->bit_30, vsdb_format->bit_36, vsdb_format->max_tmds_freq); + printk(KERN_INFO "%d deep color bit 30 %d deep color 36 bit " + "%d max tmds freq", vsdb_format->bit_30, vsdb_format->bit_36, + vsdb_format->max_tmds_freq); hdmi_get_av_delay(edid, lat); - printk("%d vid_latency %d aud_latency %d interlaced vid latency" - "%d interlaced aud latency", lat->vid_latency, lat->aud_latency, + printk(KERN_INFO "%d vid_latency %d aud_latency " + "%d interlaced vid latency %d interlaced aud latency", + lat->vid_latency, lat->aud_latency, lat->int_vid_latency, lat->int_aud_latency); - printk("YUV supported %d", hdmi_tv_yuv_supported(edid)); + printk(KERN_INFO "YUV supported %d", hdmi_tv_yuv_supported(edid)); kfree(img_format); kfree(aud_format); @@ -1537,7 +1594,6 @@ static void hdmi_get_edid(struct omap_dss_device *dssdev) kfree(lat); } - static int hdmi_check_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { @@ -1551,7 +1607,7 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev, int hdmi_init_display(struct omap_dss_device *dssdev) { - printk("init_display\n"); + printk(KERN_DEBUG "init_display\n"); /* register HDMI specific sysfs files */ /* note: custom_edid_timing should perhaps be moved here too, @@ -1564,6 +1620,8 @@ int hdmi_init_display(struct omap_dss_device *dssdev) DSSERR("failed to create sysfs file\n"); if (device_create_file(&dssdev->dev, &dev_attr_deepcolor)) DSSERR("failed to create sysfs file\n"); + if (device_create_file(&dssdev->dev, &dev_attr_lr_fr)) + DSSERR("failed to create sysfs file\n"); return 0; } @@ -1574,18 +1632,17 @@ static int hdmi_read_edid(struct omap_video_timings *dp) memset(edid, 0, HDMI_EDID_MAX_LENGTH); - if (!edid_set) { - ret = HDMI_CORE_DDC_READEDID(HDMI_CORE_SYS, edid); - } - if (ret != 0) + if (!edid_set) + ret = HDMI_CORE_DDC_READEDID(HDMI_CORE_SYS, edid, + HDMI_EDID_MAX_LENGTH); + if (ret != 0) { printk(KERN_WARNING "HDMI failed to read E-EDID\n"); - else { + } else { if (!memcmp(edid, header, sizeof(header))) { /* search for timings of default resolution */ if (get_edid_timing_data((struct HDMI_EDID *) edid)) edid_set = true; } - } if (!edid_set) { @@ -1603,60 +1660,52 @@ static int hdmi_read_edid(struct omap_video_timings *dp) return r; } - -/*------------------------------------------------------------------------------ - | Function : get_edid_timing_data - +------------------------------------------------------------------------------ - | Description : This function gets the resolution information from EDID - | - | Parameters : void - | - | Returns : void - +----------------------------------------------------------------------------*/ +/* + *------------------------------------------------------------------------------ + * Function : get_edid_timing_data + *------------------------------------------------------------------------------ + * Description : This function gets the resolution information from EDID + * + * Parameters : void + * + * Returns : void + *------------------------------------------------------------------------------ + */ static int get_edid_timing_data(struct HDMI_EDID *edid) { - u8 count, code, offset = 0, effective_addrs = 0, current_descriptor_addrs = 0; + u8 i, code, offset = 0, addr = 0; struct hdmi_cm cm; /* Seach block 0, there are 4 DTDs arranged in priority order */ - for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { - get_edid_timing_info(&edid->DTD[count], &edid_timings); - DSSDBG("Block0 [%d] timings:", count); + for (i = 0; i < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; i++) { + get_edid_timing_info(&edid->DTD[i], &edid_timings); + DSSDBG("Block0 [%d] timings:", i); print_omap_video_timings(&edid_timings); cm = hdmi_get_code(&edid_timings); - DSSDBG("Block0[%d] value matches code = %d , mode = %d",\ - count, cm.code, cm.mode); + DSSDBG("Block0[%d] value matches code = %d , mode = %d", + i, cm.code, cm.mode); if (cm.code == -1) continue; - else { - hdmi.code = cm.code; - hdmi.mode = cm.mode; - DSSDBG("code = %d , mode = %d", hdmi.code, hdmi.mode); - return 1; - } - + hdmi.code = cm.code; + hdmi.mode = cm.mode; + DSSDBG("code = %d , mode = %d", hdmi.code, hdmi.mode); + return 1; } if (edid->extension_edid != 0x00) { offset = edid->offset_dtd; if (offset != 0) - effective_addrs = EDID_DESCRIPTOR_BLOCK1_ADDRESS - + offset; - for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; count++) { - current_descriptor_addrs = - effective_addrs + count * EDID_TIMING_DESCRIPTOR_SIZE; - get_eedid_timing_info(current_descriptor_addrs, (u8 *)edid,\ - &edid_timings); + addr = EDID_DESCRIPTOR_BLOCK1_ADDRESS + offset; + for (i = 0; i < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; i++) { + get_eedid_timing_info(addr, (u8 *)edid, &edid_timings); + addr += EDID_TIMING_DESCRIPTOR_SIZE; cm = hdmi_get_code(&edid_timings); - DSSDBG("Block1[%d] value matches code = %d , mode = %d",\ - count, cm.code, cm.mode); + DSSDBG("Block1[%d] value matches code = %d , mode = %d", + i, cm.code, cm.mode); if (cm.code == -1) continue; - else { - hdmi.code = cm.code; - hdmi.mode = cm.mode; - DSSDBG("code = %d , mode = %d", hdmi.code, hdmi.mode); - return 1; - } - + hdmi.code = cm.code; + hdmi.mode = cm.mode; + DSSDBG("code = %d , mode = %d", hdmi.code, hdmi.mode); + return 1; } } /*As last resort, check for best standard timing supported:*/ @@ -1678,7 +1727,6 @@ static int get_edid_timing_data(struct HDMI_EDID *edid) code = code_vesa[hdmi.code]; edid_timings = all_timings_direct[code]; return 1; - } bool is_hdmi_interlaced(void) diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h index 10fd54b64325..31ad5699b324 100644 --- a/drivers/video/omap2/dss/hdmi.h +++ b/drivers/video/omap2/dss/hdmi.h @@ -14,94 +14,92 @@ #define HDMI_EDID_DETAILED_TIMING_OFFSET 0x36 /*EDID Detailed Timing Info 0 begin offset*/ -#define HDMI_EDID_PIX_CLK_OFFSET 0 -#define HDMI_EDID_H_ACTIVE_OFFSET 2 -#define HDMI_EDID_H_BLANKING_OFFSET 3 -#define HDMI_EDID_V_ACTIVE_OFFSET 5 -#define HDMI_EDID_V_BLANKING_OFFSET 6 -#define HDMI_EDID_H_SYNC_OFFSET 8 -#define HDMI_EDID_H_SYNC_PW_OFFSET 9 -#define HDMI_EDID_V_SYNC_OFFSET 10 -#define HDMI_EDID_V_SYNC_PW_OFFSET 10 -#define HDMI_EDID_H_IMAGE_SIZE_OFFSET 12 -#define HDMI_EDID_V_IMAGE_SIZE_OFFSET 13 -#define HDMI_EDID_H_BORDER_OFFSET 15 -#define HDMI_EDID_V_BORDER_OFFSET 16 -#define HDMI_EDID_FLAGS_OFFSET 17 - - -#define EDID_TIMING_DESCRIPTOR_SIZE 0x12 -#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 -#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 -#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 -#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 - -/* HDMI Connected States */ -#define HDMI_STATE_NOMONITOR 0 /* No HDMI monitor connected*/ -#define HDMI_STATE_CONNECTED 1 /* HDMI monitor connected but powered off*/ -#define HDMI_STATE_ON 2 /* HDMI monitor connected and powered on*/ - - -/* HDMI EDID Length */ -#define HDMI_EDID_MAX_LENGTH 256 - -/* HDMI EDID DTDs */ -#define HDMI_EDID_MAX_DTDS 4 - -/* HDMI EDID DTD Tags */ -#define HDMI_EDID_DTD_TAG_MONITOR_NAME 0xFC -#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM 0xFF -#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS 0xFD - - -/* HDMI EDID Extension Data Block Tags */ -#define HDMI_EDID_EX_DATABLOCK_TAG_MASK 0xE0 -#define HDMI_EDID_EX_DATABLOCK_LEN_MASK 0x1F - -#define HDMI_EDID_EX_DATABLOCK_AUDIO 0x20 -#define HDMI_EDID_EX_DATABLOCK_VIDEO 0x40 -#define HDMI_EDID_EX_DATABLOCK_VENDOR 0x60 -#define HDMI_EDID_EX_DATABLOCK_SPEAKERS 0x80 - -/* HDMI EDID Extenion Data Block Values: Video */ -#define HDMI_EDID_EX_VIDEO_NATIVE 0x80 -#define HDMI_EDID_EX_VIDEO_MASK 0x7F -#define HDMI_EDID_EX_VIDEO_MAX 35 - -#define HDMI_EDID_EX_VIDEO_640x480p_60Hz_4_3 1 -#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_4_3 2 -#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_16_9 3 -#define HDMI_EDID_EX_VIDEO_1280x720p_60Hz_16_9 4 -#define HDMI_EDID_EX_VIDEO_1920x1080i_60Hz_16_9 5 -#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_4_3 6 -#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_16_9 7 -#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_4_3 8 -#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_16_9 9 -#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_4_3 10 -#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_16_9 11 -#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_4_3 12 -#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_16_9 13 -#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_4_3 14 -#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_16_9 15 -#define HDMI_EDID_EX_VIDEO_1920x1080p_60Hz_16_9 16 -#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_4_3 17 -#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_16_9 18 -#define HDMI_EDID_EX_VIDEO_1280x720p_50Hz_16_9 19 -#define HDMI_EDID_EX_VIDEO_1920x1080i_50Hz_16_9 20 -#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_4_3 21 -#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_16_9 22 -#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_4_3 23 -#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_16_9 24 -#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_4_3 25 -#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_16_9 26 -#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_4_3 27 -#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_16_9 28 -#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_4_3 29 -#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_16_9 30 -#define HDMI_EDID_EX_VIDEO_1920x1080p_50Hz_16_9 31 -#define HDMI_EDID_EX_VIDEO_1920x1080p_24Hz_16_9 32 -#define HDMI_EDID_EX_VIDEO_1920x1080p_25Hz_16_9 33 -#define HDMI_EDID_EX_VIDEO_1920x1080p_30Hz_16_9 34 +#define HDMI_EDID_PIX_CLK_OFFSET 0 +#define HDMI_EDID_H_ACTIVE_OFFSET 2 +#define HDMI_EDID_H_BLANKING_OFFSET 3 +#define HDMI_EDID_V_ACTIVE_OFFSET 5 +#define HDMI_EDID_V_BLANKING_OFFSET 6 +#define HDMI_EDID_H_SYNC_OFFSET 8 +#define HDMI_EDID_H_SYNC_PW_OFFSET 9 +#define HDMI_EDID_V_SYNC_OFFSET 10 +#define HDMI_EDID_V_SYNC_PW_OFFSET 10 +#define HDMI_EDID_H_IMAGE_SIZE_OFFSET 12 +#define HDMI_EDID_V_IMAGE_SIZE_OFFSET 13 +#define HDMI_EDID_H_BORDER_OFFSET 15 +#define HDMI_EDID_V_BORDER_OFFSET 16 +#define HDMI_EDID_FLAGS_OFFSET 17 + +#define EDID_TIMING_DESCRIPTOR_SIZE 0x12 +#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 +#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 +#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 +#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 + +/* HDMI Connected States */ +#define HDMI_STATE_NOMONITOR 0 /* No HDMI monitor connected*/ +#define HDMI_STATE_CONNECTED 1 /* HDMI monitor connected but powered off*/ +#define HDMI_STATE_ON 2 /* HDMI monitor connected and powered on*/ + + +/* HDMI EDID Length */ +#define HDMI_EDID_MAX_LENGTH 256 + +/* HDMI EDID DTDs */ +#define HDMI_EDID_MAX_DTDS 4 + +/* HDMI EDID DTD Tags */ +#define HDMI_EDID_DTD_TAG_MONITOR_NAME 0xFC +#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM 0xFF +#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS 0xFD + +/* HDMI EDID Extension Data Block Tags */ +#define HDMI_EDID_EX_DATABLOCK_TAG_MASK 0xE0 +#define HDMI_EDID_EX_DATABLOCK_LEN_MASK 0x1F + +#define HDMI_EDID_EX_DATABLOCK_AUDIO 0x20 +#define HDMI_EDID_EX_DATABLOCK_VIDEO 0x40 +#define HDMI_EDID_EX_DATABLOCK_VENDOR 0x60 +#define HDMI_EDID_EX_DATABLOCK_SPEAKERS 0x80 + +/* HDMI EDID Extenion Data Block Values: Video */ +#define HDMI_EDID_EX_VIDEO_NATIVE 0x80 +#define HDMI_EDID_EX_VIDEO_MASK 0x7F +#define HDMI_EDID_EX_VIDEO_MAX 35 + +#define HDMI_EDID_EX_VIDEO_640x480p_60Hz_4_3 1 +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_4_3 2 +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_16_9 3 +#define HDMI_EDID_EX_VIDEO_1280x720p_60Hz_16_9 4 +#define HDMI_EDID_EX_VIDEO_1920x1080i_60Hz_16_9 5 +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_4_3 6 +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_16_9 7 +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_4_3 8 +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_16_9 9 +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_4_3 10 +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_16_9 11 +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_4_3 12 +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_16_9 13 +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_4_3 14 +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_16_9 15 +#define HDMI_EDID_EX_VIDEO_1920x1080p_60Hz_16_9 16 +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_4_3 17 +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_16_9 18 +#define HDMI_EDID_EX_VIDEO_1280x720p_50Hz_16_9 19 +#define HDMI_EDID_EX_VIDEO_1920x1080i_50Hz_16_9 20 +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_4_3 21 +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_16_9 22 +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_4_3 23 +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_16_9 24 +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_4_3 25 +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_16_9 26 +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_4_3 27 +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_16_9 28 +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_4_3 29 +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_16_9 30 +#define HDMI_EDID_EX_VIDEO_1920x1080p_50Hz_16_9 31 +#define HDMI_EDID_EX_VIDEO_1920x1080p_24Hz_16_9 32 +#define HDMI_EDID_EX_VIDEO_1920x1080p_25Hz_16_9 33 +#define HDMI_EDID_EX_VIDEO_1920x1080p_30Hz_16_9 34 /*--------------------------------------------------------------------- */ @@ -109,108 +107,103 @@ extern "C" { #endif - -/* Video Descriptor Block */ +/* Video Descriptor Block */ typedef struct { - u8 pixel_clock[2]; /* 54-55 */ - u8 horiz_active; /* 56 */ - u8 horiz_blanking; /* 57 */ - u8 horiz_high; /* 58 */ - u8 vert_active; /* 59 */ - u8 vert_blanking; /* 60 */ - u8 vert_high; /* 61 */ - u8 horiz_sync_offset; /* 62 */ - u8 horiz_sync_pulse; /* 63 */ - u8 vert_sync_pulse; /* 64 */ - u8 sync_pulse_high; /* 65 */ - u8 horiz_image_size; /* 66 */ - u8 vert_image_size; /* 67 */ - u8 image_size_high; /* 68 */ - u8 horiz_border; /* 69 */ - u8 vert_border; /* 70 */ - u8 misc_settings; /* 71 */ + u8 pixel_clock[2]; /* 54-55 */ + u8 horiz_active; /* 56 */ + u8 horiz_blanking; /* 57 */ + u8 horiz_high; /* 58 */ + u8 vert_active; /* 59 */ + u8 vert_blanking; /* 60 */ + u8 vert_high; /* 61 */ + u8 horiz_sync_offset; /* 62 */ + u8 horiz_sync_pulse; /* 63 */ + u8 vert_sync_pulse; /* 64 */ + u8 sync_pulse_high; /* 65 */ + u8 horiz_image_size; /* 66 */ + u8 vert_image_size; /* 67 */ + u8 image_size_high; /* 68 */ + u8 horiz_border; /* 69 */ + u8 vert_border; /* 70 */ + u8 misc_settings; /* 71 */ } HDMI_EDID_DTD_VIDEO; - -/* Monitor Limits Descriptor Block */ +/* Monitor Limits Descriptor Block */ typedef struct { - u8 pixel_clock[2]; /* 54-55*/ - u8 _reserved1; /* 56 */ - u8 block_type; /* 57 */ - u8 _reserved2; /* 58 */ - u8 min_vert_freq; /* 59 */ - u8 max_vert_freq; /* 60 */ - u8 min_horiz_freq; /* 61 */ - u8 max_horiz_freq; /* 62 */ - u8 pixel_clock_mhz; /* 63 */ - - u8 GTF[2]; /* 64 -65 */ - u8 start_horiz_freq; /* 66 */ - u8 C; /* 67 */ - u8 M[2]; /* 68-69 */ - u8 K; /* 70 */ - u8 J; /* 71 */ + u8 pixel_clock[2]; /* 54-55*/ + u8 _reserved1; /* 56 */ + u8 block_type; /* 57 */ + u8 _reserved2; /* 58 */ + u8 min_vert_freq; /* 59 */ + u8 max_vert_freq; /* 60 */ + u8 min_horiz_freq; /* 61 */ + u8 max_horiz_freq; /* 62 */ + u8 pixel_clock_mhz; /* 63 */ + + u8 GTF[2]; /* 64 -65 */ + u8 start_horiz_freq; /* 66 */ + u8 C; /* 67 */ + u8 M[2]; /* 68-69 */ + u8 K; /* 70 */ + u8 J; /* 71 */ } HDMI_EDID_DTD_MONITOR; - -/* Text Descriptor Block */ +/* Text Descriptor Block */ typedef struct { - u8 pixel_clock[2]; /* 54-55 */ - u8 _reserved1; /* 56 */ - u8 block_type; /* 57 */ - u8 _reserved2; /* 58 */ + u8 pixel_clock[2]; /* 54-55 */ + u8 _reserved1; /* 56 */ + u8 block_type; /* 57 */ + u8 _reserved2; /* 58 */ - u8 text[13]; /* 59-71 */ + u8 text[13]; /* 59-71 */ } HDMI_EDID_DTD_TEXT; - -/* DTD Union */ +/* DTD Union */ typedef union { - HDMI_EDID_DTD_VIDEO video; - HDMI_EDID_DTD_TEXT monitor_name; - HDMI_EDID_DTD_TEXT monitor_serial_number; - HDMI_EDID_DTD_MONITOR monitor_limits; + HDMI_EDID_DTD_VIDEO video; + HDMI_EDID_DTD_TEXT monitor_name; + HDMI_EDID_DTD_TEXT monitor_serial_number; + HDMI_EDID_DTD_MONITOR monitor_limits; } HDMI_EDID_DTD; - -/* EDID struct */ +/* EDID struct */ typedef struct { - u8 header[8]; /* 00-07 */ - u8 manufacturerID[2]; /* 08-09 */ - u8 product_id[2]; /* 10-11 */ - u8 serial_number[4]; /* 12-15 */ - u8 week_manufactured; /* 16 */ - u8 year_manufactured; /* 17 */ - u8 edid_version; /* 18 */ - u8 edid_revision; /* 19 */ - - u8 video_in_definition; /* 20 */ - u8 max_horiz_image_size; /* 21 */ - u8 max_vert_image_size; /* 22 */ - u8 display_gamma; /* 23 */ - u8 power_features; /* 24 */ - u8 chroma_info[10]; /* 25-34 */ - u8 timing_1; /* 35 */ - u8 timing_2; /* 36 */ - u8 timing_3; /* 37 */ - u8 std_timings[16]; /* 38-53 */ - - HDMI_EDID_DTD DTD[4]; /* 72-125 */ - - u8 extension_edid; /* 126 */ - u8 checksum; /* 127 */ - - u8 extension_tag; /* 00 (extensions follow EDID) */ - u8 extention_rev; /* 01 */ - u8 offset_dtd; /* 02 */ - u8 num_dtd; /* 03 */ - - u8 data_block[123]; /* 04 - 126 */ - u8 extension_checksum; /* 127 */ + u8 header[8]; /* 00-07 */ + u8 manufacturerID[2]; /* 08-09 */ + u8 product_id[2]; /* 10-11 */ + u8 serial_number[4]; /* 12-15 */ + u8 week_manufactured; /* 16 */ + u8 year_manufactured; /* 17 */ + u8 edid_version; /* 18 */ + u8 edid_revision; /* 19 */ + + u8 video_in_definition; /* 20 */ + u8 max_horiz_image_size;/* 21 */ + u8 max_vert_image_size; /* 22 */ + u8 display_gamma; /* 23 */ + u8 power_features; /* 24 */ + u8 chroma_info[10]; /* 25-34 */ + u8 timing_1; /* 35 */ + u8 timing_2; /* 36 */ + u8 timing_3; /* 37 */ + u8 std_timings[16]; /* 38-53 */ + + HDMI_EDID_DTD DTD[4]; /* 72-125 */ + + u8 extension_edid; /* 126 */ + u8 checksum; /* 127 */ + + u8 extension_tag; /* 00 (extensions follow EDID) */ + u8 extention_rev; /* 01 */ + u8 offset_dtd; /* 02 */ + u8 num_dtd; /* 03 */ + + u8 data_block[123]; /* 04 - 126 */ + u8 extension_checksum; /* 127 */ } HDMI_EDID; @@ -229,5 +222,3 @@ enum hdmi_ioctl_cmds { #endif #endif - - |