diff --git a/packages/linux/patches/linux-2.6.38-rc8-301-V5_Add_display_type_HDMI_to_DSS2.patch b/packages/linux/patches/linux-2.6.38-rc8-301-V5_Add_display_type_HDMI_to_DSS2.patch new file mode 100644 index 0000000000..4a2b1280e4 --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-301-V5_Add_display_type_HDMI_to_DSS2.patch @@ -0,0 +1,123 @@ +Adding HDMI type in dss_features , overlay and +the manager so that HDMI type of display will be recognized. + +Signed-off-by: Mythri P K +--- + arch/arm/plat-omap/include/plat/display.h | 1 + + drivers/video/omap2/dss/display.c | 2 ++ + drivers/video/omap2/dss/dss_features.c | 2 +- + drivers/video/omap2/dss/manager.c | 9 +++++++-- + drivers/video/omap2/dss/overlay.c | 6 ++++-- + 5 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h +index e81ca66..5e04ddc 100644 +--- a/arch/arm/plat-omap/include/plat/display.h ++++ b/arch/arm/plat-omap/include/plat/display.h +@@ -58,6 +58,7 @@ enum omap_display_type { + OMAP_DISPLAY_TYPE_SDI = 1 << 2, + OMAP_DISPLAY_TYPE_DSI = 1 << 3, + OMAP_DISPLAY_TYPE_VENC = 1 << 4, ++ OMAP_DISPLAY_TYPE_HDMI = 1 << 5, + }; + + enum omap_plane { +diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c +index 7d96b72..c40bcbd 100644 +--- a/drivers/video/omap2/dss/display.c ++++ b/drivers/video/omap2/dss/display.c +@@ -342,6 +342,7 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) + return 16; + case OMAP_DISPLAY_TYPE_VENC: + case OMAP_DISPLAY_TYPE_SDI: ++ case OMAP_DISPLAY_TYPE_HDMI: + return 24; + default: + BUG(); +@@ -368,6 +369,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev, + case OMAP_DISPLAY_TYPE_DPI: + bpp = dssdev->phy.dpi.data_lines; + break; ++ case OMAP_DISPLAY_TYPE_HDMI: + case OMAP_DISPLAY_TYPE_VENC: + case OMAP_DISPLAY_TYPE_SDI: + bpp = 24; +diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c +index 6eb6ec6..86dc848 100644 +--- a/drivers/video/omap2/dss/dss_features.c ++++ b/drivers/video/omap2/dss/dss_features.c +@@ -115,7 +115,7 @@ static const enum omap_display_type omap4_dss_supported_displays[] = { + OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, + + /* OMAP_DSS_CHANNEL_DIGIT */ +- OMAP_DISPLAY_TYPE_VENC, ++ OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI, + + /* OMAP_DSS_CHANNEL_LCD2 */ + OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | +diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c +index 1f53bf2..bcd37ec 100644 +--- a/drivers/video/omap2/dss/manager.c ++++ b/drivers/video/omap2/dss/manager.c +@@ -515,6 +515,8 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) + + if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { + irq = DISPC_IRQ_EVSYNC_ODD; ++ } else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) { ++ irq = DISPC_IRQ_EVSYNC_EVEN; + } else { + if (mgr->id == OMAP_DSS_CHANNEL_LCD) + irq = DISPC_IRQ_VSYNC; +@@ -536,7 +538,8 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) + if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return 0; + +- if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { ++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC ++ || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { + irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; + } else { + if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { +@@ -613,7 +616,8 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) + if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return 0; + +- if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { ++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC ++ || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { + irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; + } else { + if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { +@@ -1377,6 +1381,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) + case OMAP_DISPLAY_TYPE_DBI: + case OMAP_DISPLAY_TYPE_SDI: + case OMAP_DISPLAY_TYPE_VENC: ++ case OMAP_DISPLAY_TYPE_HDMI: + default_get_overlay_fifo_thresholds(ovl->id, size, + &oc->burst_size, &oc->fifo_low, + &oc->fifo_high); +diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c +index 996e9a4..f1aca6d 100644 +--- a/drivers/video/omap2/dss/overlay.c ++++ b/drivers/video/omap2/dss/overlay.c +@@ -679,7 +679,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) + lcd2_mgr->set_device(lcd2_mgr, dssdev); + mgr = lcd2_mgr; + } +- } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { ++ } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC ++ && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { + if (!lcd_mgr->device || force) { + if (lcd_mgr->device) + lcd_mgr->unset_device(lcd_mgr); +@@ -688,7 +689,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) + } + } + +- if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { ++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC ++ || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { + if (!tv_mgr->device || force) { + if (tv_mgr->device) + tv_mgr->unset_device(tv_mgr); +-- 1.5.6.3 diff --git a/packages/linux/patches/linux-2.6.38-rc8-302-V5_Select_between_HDMI_VENC_clock_source.patch b/packages/linux/patches/linux-2.6.38-rc8-302-V5_Select_between_HDMI_VENC_clock_source.patch new file mode 100644 index 0000000000..663f5fe18e --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-302-V5_Select_between_HDMI_VENC_clock_source.patch @@ -0,0 +1,47 @@ +Signed-off-by: Mythri P K +--- + drivers/video/omap2/dss/dss.c | 5 +++++ + drivers/video/omap2/dss/dss.h | 6 ++++++ + 2 files changed, 11 insertions(+), 0 deletions(-) + +diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c +index aed9345..0be83c8 100644 +--- a/drivers/video/omap2/dss/dss.c ++++ b/drivers/video/omap2/dss/dss.c +@@ -605,6 +605,11 @@ void dss_set_dac_pwrdn_bgz(bool enable) + REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ + } + ++void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) ++{ ++ REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ ++} ++ + static int dss_init(void) + { + int r; +diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h +index b845468..c2c0fcf 100644 +--- a/drivers/video/omap2/dss/dss.h ++++ b/drivers/video/omap2/dss/dss.h +@@ -132,6 +132,11 @@ struct dss_clk_source_name { + const char *clksrc_name; + }; + ++enum dss_hdmi_venc_clk_source_select { ++ DSS_VENC_TV_CLK = 0, ++ DSS_HDMI_M_PCLK = 1, ++}; ++ + struct dss_clock_info { + /* rates that we get with dividers below */ + unsigned long fck; +@@ -220,6 +225,7 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); + int dss_init_platform_driver(void); + void dss_uninit_platform_driver(void); + ++void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); + void dss_save_context(void); + void dss_restore_context(void); + void dss_clk_enable(enum dss_clock clks); +-- 1.5.6.3 diff --git a/packages/linux/patches/linux-2.6.38-rc8-303-V5_Dispc_gamma_enable_set-reset_function_for_TV.patch b/packages/linux/patches/linux-2.6.38-rc8-303-V5_Dispc_gamma_enable_set-reset_function_for_TV.patch new file mode 100644 index 0000000000..60a995f9e1 --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-303-V5_Dispc_gamma_enable_set-reset_function_for_TV.patch @@ -0,0 +1,46 @@ +Adding function to reset/set gamma table bit for TV interface +currentl only support for disabled is added. + +Signed-off-by: Mythri P K +--- + drivers/video/omap2/dss/dispc.c | 13 +++++++++++++ + drivers/video/omap2/dss/dss.h | 1 + + 2 files changed, 14 insertions(+), 0 deletions(-) + +diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c +index b8c576a..9b86f5f 100644 +--- a/drivers/video/omap2/dss/dispc.c ++++ b/drivers/video/omap2/dss/dispc.c +@@ -1008,6 +1008,19 @@ void dispc_set_burst_size(enum omap_plane plane, + enable_clocks(0); + } + ++void dispc_enable_gamma_table(bool enable) ++{ ++ /* This is partially implemented to support only ++ * disabling of the gamma table. ++ */ ++ if (enable) { ++ DSSWARN("Gamma table enabling for TV not yet supported"); ++ return; ++ } ++ ++ REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); ++} ++ + static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) + { + u32 val; +diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h +index c2c0fcf..9f563a6 100644 +--- a/drivers/video/omap2/dss/dss.h ++++ b/drivers/video/omap2/dss/dss.h +@@ -376,6 +376,7 @@ void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); + void dispc_set_channel_out(enum omap_plane plane, + enum omap_channel channel_out); + ++void dispc_enable_gamma_table(bool enable); + int dispc_setup_plane(enum omap_plane plane, + u32 paddr, u16 screen_width, + u16 pos_x, u16 pos_y, +-- 1.5.6.3 diff --git a/packages/linux/patches/linux-2.6.38-rc8-304-V5_HDMI_driver_header_file_addition.patch b/packages/linux/patches/linux-2.6.38-rc8-304-V5_HDMI_driver_header_file_addition.patch new file mode 100644 index 0000000000..4cde7027ea --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-304-V5_HDMI_driver_header_file_addition.patch @@ -0,0 +1,431 @@ +Adding the hdmi interface driver header file (hdmi.h) to the dss driver. +Register and structure declaration done here. + +Signed-off-by: Mythri P K +--- + drivers/video/omap2/dss/hdmi.h | 415 ++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 415 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/hdmi.h + +diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h +new file mode 100644 +index 0000000..9887ab9 +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi.h +@@ -0,0 +1,415 @@ ++/* ++ * hdmi.h ++ * ++ * HDMI driver definition for TI OMAP4 processors. ++ * ++ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see . ++ */ ++ ++#ifndef _OMAP4_DSS_HDMI_H_ ++#define _OMAP4_DSS_HDMI_H_ ++ ++#include ++#include ++ ++#define HDMI_WP 0x0 ++#define HDMI_CORE_SYS 0x400 ++#define HDMI_CORE_AV 0x900 ++#define HDMI_PLLCTRL 0x200 ++#define HDMI_PHY 0x300 ++ ++struct hdmi_reg { u16 idx; }; ++ ++#define HDMI_REG(idx) ((const struct hdmi_reg) { idx }) ++ ++/* HDMI Wrapper */ ++#define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx) ++ ++#define HDMI_WP_REVISION HDMI_WP_REG(0x0) ++#define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10) ++#define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24) ++#define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28) ++#define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40) ++#define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C) ++#define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50) ++#define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60) ++#define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) ++#define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) ++#define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) ++ ++/* HDMI IP Core System */ ++#define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) ++ ++#define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0) ++#define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8) ++#define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC) ++#define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10) ++#define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14) ++#define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20) ++#define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24) ++#define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124) ++#define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128) ++#define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0) ++#define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4) ++#define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8) ++#define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC) ++#define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0) ++#define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4) ++#define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208) ++#define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8) ++#define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC) ++#define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0) ++#define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8) ++#define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC) ++#define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0) ++#define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4) ++#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 ++#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 ++#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 ++#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 ++ ++/* HDMI DDC E-DID */ ++#define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC) ++#define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8) ++#define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4) ++#define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC) ++#define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0) ++#define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4) ++#define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0) ++#define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8) ++ ++/* HDMI IP Core Audio Video */ ++#define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx) ++ ++#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) ++#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) ++#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) ++#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) ++#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) ++#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) ++#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) ++#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) ++#define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110) ++#define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) ++#define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) ++#define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) ++#define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) ++#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) ++#define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) ++#define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31) ++#define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380) ++#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31) ++#define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4) ++#define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8) ++#define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC) ++#define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10) ++#define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14) ++#define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18) ++#define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C) ++#define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20) ++#define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24) ++#define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28) ++#define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C) ++#define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50) ++#define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54) ++#define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60) ++#define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64) ++#define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C) ++#define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70) ++#define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74) ++#define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78) ++#define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C) ++#define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80) ++#define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84) ++#define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88) ++#define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C) ++#define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90) ++#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) ++#define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0) ++#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC) ++#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0) ++#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4) ++#define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0) ++#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) ++#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) ++#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) ++#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) ++#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) ++#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) ++#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) ++#define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180) ++#define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) ++#define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) ++#define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) ++#define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) ++#define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) ++#define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) ++#define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C) ++#define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C) ++#define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC) ++#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 ++#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 ++#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 ++#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 ++ ++/* PLL */ ++#define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx) ++ ++#define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0) ++#define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4) ++#define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8) ++#define PLLCTRL_CFG1 HDMI_PLL_REG(0xC) ++#define PLLCTRL_CFG2 HDMI_PLL_REG(0x10) ++#define PLLCTRL_CFG3 HDMI_PLL_REG(0x14) ++#define PLLCTRL_CFG4 HDMI_PLL_REG(0x20) ++ ++/* HDMI PHY */ ++#define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx) ++ ++#define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0) ++#define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4) ++#define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8) ++#define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC) ++ ++/* HDMI EDID Length */ ++#define HDMI_EDID_MAX_LENGTH 256 ++#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 OMAP_HDMI_TIMINGS_NB 34 ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end)) ++#define REG_GET(idx, start, end) \ ++ FLD_GET(hdmi_read_reg(idx), start, end) ++ ++/* HDMI timing structure */ ++struct hdmi_timings { ++ struct omap_video_timings timings; ++ int vsync_pol; ++ int hsync_pol; ++}; ++ ++enum hdmi_phy_pwr { ++ HDMI_PHYPWRCMD_OFF = 0, ++ HDMI_PHYPWRCMD_LDOON = 1, ++ HDMI_PHYPWRCMD_TXON = 2 ++}; ++ ++enum hdmi_pll_pwr { ++ HDMI_PLLPWRCMD_ALLOFF = 0, ++ HDMI_PLLPWRCMD_PLLONLY = 1, ++ HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, ++ HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 ++}; ++ ++enum hdmi_clk_refsel { ++ HDMI_REFSEL_PCLK = 0, ++ HDMI_REFSEL_REF1 = 1, ++ HDMI_REFSEL_REF2 = 2, ++ HDMI_REFSEL_SYSCLK = 3 ++}; ++ ++enum hdmi_core_inputbus_width { ++ HDMI_INPUT_8BIT = 0, ++ HDMI_INPUT_10BIT = 1, ++ HDMI_INPUT_12BIT = 2 ++}; ++ ++enum hdmi_core_dither_trunc { ++ HDMI_OUTPUTTRUNCATION_8BIT = 0, ++ HDMI_OUTPUTTRUNCATION_10BIT = 1, ++ HDMI_OUTPUTTRUNCATION_12BIT = 2, ++ HDMI_OUTPUTDITHER_8BIT = 3, ++ HDMI_OUTPUTDITHER_10BIT = 4, ++ HDMI_OUTPUTDITHER_12BIT = 5 ++}; ++ ++enum hdmi_core_deepcolor_ed { ++ HDMI_DEEPCOLORPACKECTDISABLE = 0, ++ HDMI_DEEPCOLORPACKECTENABLE = 1 ++}; ++ ++enum hdmi_core_packet_mode { ++ HDMI_PACKETMODERESERVEDVALUE = 0, ++ HDMI_PACKETMODE24BITPERPIXEL = 4, ++ HDMI_PACKETMODE30BITPERPIXEL = 5, ++ HDMI_PACKETMODE36BITPERPIXEL = 6, ++ HDMI_PACKETMODE48BITPERPIXEL = 7 ++}; ++ ++enum hdmi_core_hdmi_dvi { ++ HDMI_DVI = 0, ++ HDMI_HDMI = 1 ++}; ++ ++enum hdmi_core_tclkselclkmult { ++ HDMI_FPLL05IDCK = 0, ++ HDMI_FPLL10IDCK = 1, ++ HDMI_FPLL20IDCK = 2, ++ HDMI_FPLL40IDCK = 3 ++}; ++ ++enum hdmi_core_packet_ctrl { ++ HDMI_PACKETENABLE = 1, ++ HDMI_PACKETDISABLE = 0, ++ HDMI_PACKETREPEATON = 1, ++ HDMI_PACKETREPEATOFF = 0 ++}; ++ ++/* INFOFRAME_AVI_ definitions */ ++enum hdmi_core_infoframe { ++ HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, ++ HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, ++ HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2, ++ HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0, ++ HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1, ++ HDMI_INFOFRAME_AVI_DB1B_NO = 0, ++ HDMI_INFOFRAME_AVI_DB1B_VERT = 1, ++ HDMI_INFOFRAME_AVI_DB1B_HORI = 2, ++ HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3, ++ HDMI_INFOFRAME_AVI_DB1S_0 = 0, ++ HDMI_INFOFRAME_AVI_DB1S_1 = 1, ++ HDMI_INFOFRAME_AVI_DB1S_2 = 2, ++ HDMI_INFOFRAME_AVI_DB2C_NO = 0, ++ HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1, ++ HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2, ++ HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3, ++ HDMI_INFOFRAME_AVI_DB2M_NO = 0, ++ HDMI_INFOFRAME_AVI_DB2M_43 = 1, ++ HDMI_INFOFRAME_AVI_DB2M_169 = 2, ++ HDMI_INFOFRAME_AVI_DB2R_SAME = 8, ++ HDMI_INFOFRAME_AVI_DB2R_43 = 9, ++ HDMI_INFOFRAME_AVI_DB2R_169 = 10, ++ HDMI_INFOFRAME_AVI_DB2R_149 = 11, ++ HDMI_INFOFRAME_AVI_DB3ITC_NO = 0, ++ HDMI_INFOFRAME_AVI_DB3ITC_YES = 1, ++ HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0, ++ HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1, ++ HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0, ++ HDMI_INFOFRAME_AVI_DB3Q_LR = 1, ++ HDMI_INFOFRAME_AVI_DB3Q_FR = 2, ++ HDMI_INFOFRAME_AVI_DB3SC_NO = 0, ++ HDMI_INFOFRAME_AVI_DB3SC_HORI = 1, ++ HDMI_INFOFRAME_AVI_DB3SC_VERT = 2, ++ HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3, ++ HDMI_INFOFRAME_AVI_DB5PR_NO = 0, ++ HDMI_INFOFRAME_AVI_DB5PR_2 = 1, ++ HDMI_INFOFRAME_AVI_DB5PR_3 = 2, ++ HDMI_INFOFRAME_AVI_DB5PR_4 = 3, ++ HDMI_INFOFRAME_AVI_DB5PR_5 = 4, ++ HDMI_INFOFRAME_AVI_DB5PR_6 = 5, ++ HDMI_INFOFRAME_AVI_DB5PR_7 = 6, ++ HDMI_INFOFRAME_AVI_DB5PR_8 = 7, ++ HDMI_INFOFRAME_AVI_DB5PR_9 = 8, ++ HDMI_INFOFRAME_AVI_DB5PR_10 = 9 ++}; ++ ++enum hdmi_packing_mode { ++ HDMI_PACK_10b_RGB_YUV444 = 0, ++ HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, ++ HDMI_PACK_20b_YUV422 = 2, ++ HDMI_PACK_ALREADYPACKED = 7 ++}; ++ ++struct hdmi_core_video_config { ++ enum hdmi_core_inputbus_width ip_bus_width; ++ enum hdmi_core_dither_trunc op_dither_truc; ++ enum hdmi_core_deepcolor_ed deep_color_pkt; ++ enum hdmi_core_packet_mode pkt_mode; ++ enum hdmi_core_hdmi_dvi hdmi_dvi; ++ enum hdmi_core_tclkselclkmult tclk_sel_clkmult; ++}; ++ ++/* ++ * Refer to section 8.2 in HDMI 1.3 specification for ++ * details about infoframe databytes ++ */ ++struct hdmi_core_infoframe_avi { ++ u8 db1_format; ++ /* Y0, Y1 rgb,yCbCr */ ++ u8 db1_active_info; ++ /* A0 Active information Present */ ++ u8 db1_bar_info_dv; ++ /* B0, B1 Bar info data valid */ ++ u8 db1_scan_info; ++ /* S0, S1 scan information */ ++ u8 db2_colorimetry; ++ /* C0, C1 colorimetry */ ++ u8 db2_aspect_ratio; ++ /* M0, M1 Aspect ratio (4:3, 16:9) */ ++ u8 db2_active_fmt_ar; ++ /* R0...R3 Active format aspect ratio */ ++ u8 db3_itc; ++ /* ITC IT content. */ ++ u8 db3_ec; ++ /* EC0, EC1, EC2 Extended colorimetry */ ++ u8 db3_q_range; ++ /* Q1, Q0 Quantization range */ ++ u8 db3_nup_scaling; ++ /* SC1, SC0 Non-uniform picture scaling */ ++ u8 db4_videocode; ++ /* VIC0..6 Video format identification */ ++ u8 db5_pixel_repeat; ++ /* PR0..PR3 Pixel repetition factor */ ++ u16 db6_7_line_eoftop; ++ /* Line number end of top bar */ ++ u16 db8_9_line_sofbottom; ++ /* Line number start of bottom bar */ ++ u16 db10_11_pixel_eofleft; ++ /* Pixel number end of left bar */ ++ u16 db12_13_pixel_sofright; ++ /* Pixel number start of right bar */ ++}; ++ ++struct hdmi_core_packet_enable_repeat { ++ u32 audio_pkt; ++ u32 audio_pkt_repeat; ++ u32 avi_infoframe; ++ u32 avi_infoframe_repeat; ++ u32 gen_cntrl_pkt; ++ u32 gen_cntrl_pkt_repeat; ++ u32 generic_pkt; ++ u32 generic_pkt_repeat; ++}; ++ ++struct hdmi_video_format { ++ enum hdmi_packing_mode packing_mode; ++ u32 y_res; /* Line per panel */ ++ u32 x_res; /* pixel per line */ ++}; ++ ++struct hdmi_video_interface { ++ int vsp; /* Vsync polarity */ ++ int hsp; /* Hsync polarity */ ++ int interlacing; ++ int tm; /* Timing mode */ ++}; ++ ++struct hdmi_cm { ++ int code; ++ int mode; ++}; ++ ++struct hdmi_config { ++ struct hdmi_timings timings; ++ u16 interlace; ++ struct hdmi_cm cm; ++}; ++ ++#endif +-- 1.5.6.3 diff --git a/packages/linux/patches/linux-2.6.38-rc8-305-V5_HDMI_driver_addition_in_the_DSS.patch b/packages/linux/patches/linux-2.6.38-rc8-305-V5_HDMI_driver_addition_in_the_DSS.patch new file mode 100644 index 0000000000..37d58f9b98 --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-305-V5_HDMI_driver_addition_in_the_DSS.patch @@ -0,0 +1,1418 @@ +Adding the hdmi interface driver(hdmi.c) to the dss driver. +It configures the audio and video portion of HDMI based on +functionality called by the panel driver. + +Signed-off-by: Mythri P K + Yong Zhi +--- + drivers/video/omap2/dss/display.c | 3 + + drivers/video/omap2/dss/dss.h | 34 + + drivers/video/omap2/dss/hdmi.c | 1332 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 1369 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/hdmi.c + +diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c +index c40bcbd..a85a6f3 100644 +--- a/drivers/video/omap2/dss/display.c ++++ b/drivers/video/omap2/dss/display.c +@@ -418,6 +418,9 @@ void dss_init_device(struct platform_device *pdev, + r = dsi_init_display(dssdev); + break; + #endif ++ case OMAP_DISPLAY_TYPE_HDMI: ++ r = hdmi_init_display(dssdev); ++ break; + default: + DSSERR("Support for display '%s' not compiled in.\n", + dssdev->name); +diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h +index 9f563a6..6bf923c 100644 +--- a/drivers/video/omap2/dss/dss.h ++++ b/drivers/video/omap2/dss/dss.h +@@ -179,6 +179,16 @@ struct dsi_clock_info { + bool use_sys_clk; + }; + ++/* HDMI PLL structure */ ++struct hdmi_pll_info { ++ u16 regn; ++ u16 regm; ++ u32 regmf; ++ u16 regm2; ++ u16 regsd; ++ u16 dcofreq; ++}; ++ + struct seq_file; + struct platform_device; + +@@ -450,6 +460,30 @@ static inline void venc_uninit_platform_driver(void) + } + #endif + ++/* HDMI */ ++#ifdef CONFIG_OMAP4_DSS_HDMI ++int hdmi_init_platform_driver(void); ++void hdmi_uninit_platform_driver(void); ++int hdmi_init_display(struct omap_dss_device *dssdev); ++#else ++static inline int hdmi_init_display(struct omap_dss_device *dssdev) ++{ ++ return 0; ++} ++static inline int hdmi_init_platform_driver(void) ++{ ++ return 0; ++} ++static inline void hdmi_uninit_platform_driver(void) ++{ ++} ++#endif ++int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); ++void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); ++void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); ++int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings); ++ + /* RFBI */ + #ifdef CONFIG_OMAP2_DSS_RFBI + int rfbi_init_platform_driver(void); +diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c +new file mode 100644 +index 0000000..e0e2cbb +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi.c +@@ -0,0 +1,1332 @@ ++/* ++ * hdmi.c ++ * ++ * HDMI interface DSS driver setting for TI's OMAP4 family of processor. ++ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ ++ * Authors: Yong Zhi ++ * Mythri pk ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "HDMI" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dss.h" ++#include "hdmi.h" ++ ++static struct { ++ struct mutex lock; ++ struct omap_display_platform_data *pdata; ++ struct platform_device *pdev; ++ void __iomem *base_wp; /* HDMI wrapper */ ++ int code; ++ int mode; ++ u8 edid[HDMI_EDID_MAX_LENGTH]; ++ u8 edid_set; ++ bool custom_set; ++ struct hdmi_config cfg; ++} hdmi; ++ ++/* ++ * Logic for the below structure : ++ * user enters the CEA or VESA timings by specifying the HDMI/DVI code. ++ * There is a correspondence between CEA/VESA timing and code , Please ++ * refer to section 6.3 in HDMI 1.3 specification for timing code. ++ * In the below structure, cea_vesa_timings corresponds to all OMAP4 ++ * supported CEA and VESA timing values. ++ * code_cea corresponds to the CEA code , It is used to get the timing ++ * from cea_vesa_timing array. Similarly with code_vesa. ++ * code_index is used for back mapping, That is once EDID is read from ++ * the TV, EDID is parsed to find the timing values and then map it to ++ * corresponding CEA or VESA index. ++ */ ++ ++static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { ++ { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0}, ++ { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1}, ++ { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}, ++ { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0}, ++ { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0}, ++ { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0}, ++ { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0}, ++ { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1}, ++ { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1}, ++ { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1}, ++ { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0}, ++ { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0}, ++ { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1}, ++ { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0}, ++ { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1}, ++ /* VESA From Here */ ++ { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0}, ++ { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1}, ++ { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1}, ++ { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0}, ++ { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0}, ++ { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1}, ++ { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1}, ++ { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1}, ++ { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0}, ++ { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0}, ++ { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0}, ++ { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0}, ++ { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1}, ++ { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1}, ++ { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1}, ++ { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1}, ++ { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1}, ++ { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1}, ++ { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1} ++}; ++ ++/* ++ * This is a static mapping array which maps the timing values ++ * with corresponding CEA / VESA code ++ */ ++static const 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 ++}; ++ ++/* ++ * This is reverse static mapping which maps the CEA / VESA code ++ * to the corresponding timing values ++ */ ++static const 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 ++}; ++ ++static const 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}; ++ ++static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; ++ ++static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val) ++{ ++ __raw_writel(val, hdmi.base_wp + idx.idx); ++} ++ ++static inline u32 hdmi_read_reg(const struct hdmi_reg idx) ++{ ++ return __raw_readl(hdmi.base_wp + idx.idx); ++} ++ ++static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, ++ int b2, int b1, u32 val) ++{ ++ u32 t = 0; ++ while (val != REG_GET(idx, b2, b1)) { ++ udelay(1); ++ if (t++ > 10000) ++ return !val; ++ } ++ return val; ++} ++ ++int hdmi_init_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("init_display\n"); ++ ++ return 0; ++} ++ ++static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq, ++ struct hdmi_pll_info *fmt, u16 sd) ++{ ++ u32 r; ++ ++ /* PLL start always use manual mode */ ++ REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0); ++ ++ r = hdmi_read_reg(PLLCTRL_CFG1); ++ r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ ++ r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */ ++ ++ hdmi_write_reg(PLLCTRL_CFG1, r); ++ ++ r = hdmi_read_reg(PLLCTRL_CFG2); ++ ++ r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ ++ r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ ++ r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ ++ ++ if (dcofreq) { ++ /* divider programming for frequency beyond 1000Mhz */ ++ REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10); ++ r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ ++ } else { ++ r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ ++ } ++ ++ hdmi_write_reg(PLLCTRL_CFG2, r); ++ ++ r = hdmi_read_reg(PLLCTRL_CFG4); ++ r = FLD_MOD(r, fmt->regm2, 24, 18); ++ r = FLD_MOD(r, fmt->regmf, 17, 0); ++ ++ hdmi_write_reg(PLLCTRL_CFG4, r); ++ ++ /* go now */ ++ REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0); ++ ++ /* wait for bit change */ ++ if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) { ++ DSSERR("PLL GO bit not set\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* Wait till the lock bit is set in PLL status */ ++ if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { ++ DSSWARN("cannot lock PLL\n"); ++ DSSWARN("CFG1 0x%x\n", ++ hdmi_read_reg(PLLCTRL_CFG1)); ++ DSSWARN("CFG2 0x%x\n", ++ hdmi_read_reg(PLLCTRL_CFG2)); ++ DSSWARN("CFG4 0x%x\n", ++ hdmi_read_reg(PLLCTRL_CFG4)); ++ return -ETIMEDOUT; ++ } ++ ++ DSSDBG("PLL locked!\n"); ++ ++ return 0; ++} ++ ++/* PHY_PWR_CMD */ ++static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val) ++{ ++ /* Command for power control of HDMI PHY */ ++ REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6); ++ ++ /* Status of the power control of HDMI PHY */ ++ if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) { ++ DSSERR("Failed to set PHY power mode to %d\n", val); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++/* PLL_PWR_CMD */ ++static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val) ++{ ++ /* Command for power control of HDMI PLL */ ++ REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2); ++ ++ /* wait till PHY_PWR_STATUS is set */ ++ if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) { ++ DSSERR("Failed to set PHY_PWR_STATUS\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int hdmi_pll_reset(void) ++{ ++ /* SYSRESET controlled by power FSM */ ++ REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3); ++ ++ /* READ 0x0 reset is in progress */ ++ if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { ++ DSSERR("Failed to sysreset PLL\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int hdmi_phy_init(void) ++{ ++ u16 r = 0; ++ ++ r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON); ++ if (r) ++ return r; ++ ++ r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON); ++ if (r) ++ return r; ++ ++ /* ++ * Read address 0 in order to get the SCP reset done completed ++ * Dummy access performed to make sure reset is done ++ */ ++ hdmi_read_reg(HDMI_TXPHY_TX_CTRL); ++ ++ /* ++ * Write to phy address 0 to configure the clock ++ * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field ++ */ ++ REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); ++ ++ /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ ++ hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); ++ ++ /* Setup max LDO voltage */ ++ REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); ++ ++ /* Write to phy address 3 to change the polarity control */ ++ REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); ++ ++ return 0; ++} ++ ++static int hdmi_wait_softreset(void) ++{ ++ /* reset W1 */ ++ REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0); ++ ++ /* wait till SOFTRESET == 0 */ ++ if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) { ++ DSSERR("sysconfig reset failed\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int hdmi_pll_program(struct hdmi_pll_info *fmt) ++{ ++ u16 r = 0; ++ enum hdmi_clk_refsel refsel; ++ ++ /* wait for wrapper reset */ ++ r = hdmi_wait_softreset(); ++ if (r) ++ return r; ++ ++ r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); ++ if (r) ++ return r; ++ ++ r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS); ++ if (r) ++ return r; ++ ++ r = hdmi_pll_reset(); ++ if (r) ++ return r; ++ ++ refsel = HDMI_REFSEL_SYSCLK; ++ ++ r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); ++ if (r) ++ return r; ++ ++ return 0; ++} ++ ++static void hdmi_phy_off(void) ++{ ++ hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF); ++} ++ ++static int hdmi_core_ddc_edid(u8 *pedid, int ext) ++{ ++ u32 i, j; ++ char checksum = 0; ++ u32 offset = 0; ++ ++ /* Turn on CLK for DDC */ ++ REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0); ++ ++ /* ++ * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / ++ * right shifted values( The behavior is not consistent and seen only ++ * with some TV's) ++ */ ++ usleep_range(800, 1000); ++ ++ if (!ext) { ++ /* Clk SCL Devices */ ++ REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0); ++ ++ /* HDMI_CORE_DDC_STATUS_IN_PROG */ ++ if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, ++ 4, 4, 0) != 0) { ++ DSSERR("Failed to program DDC\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* Clear FIFO */ ++ REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0); ++ ++ /* HDMI_CORE_DDC_STATUS_IN_PROG */ ++ if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, ++ 4, 4, 0) != 0) { ++ DSSERR("Failed to program DDC\n"); ++ return -ETIMEDOUT; ++ } ++ ++ } else { ++ if (ext % 2 != 0) ++ offset = 0x80; ++ } ++ ++ /* Load Segment Address Register */ ++ REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0); ++ ++ /* Load Slave Address Register */ ++ REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); ++ ++ /* Load Offset Address Register */ ++ REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0); ++ ++ /* Load Byte Count */ ++ REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); ++ REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); ++ ++ /* Set DDC_CMD */ ++ if (ext) ++ REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0); ++ else ++ REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0); ++ ++ /* HDMI_CORE_DDC_STATUS_BUS_LOW */ ++ if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) { ++ DSSWARN("I2C Bus Low?\n"); ++ return -EIO; ++ } ++ /* HDMI_CORE_DDC_STATUS_NO_ACK */ ++ if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) { ++ DSSWARN("I2C No Ack\n"); ++ return -EIO; ++ } ++ ++ i = ext * 128; ++ j = 0; ++ while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) || ++ (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && ++ j < 128) { ++ ++ if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) { ++ /* FIFO not empty */ ++ pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0); ++ j++; ++ } ++ } ++ ++ for (j = 0; j < 128; j++) ++ checksum += pedid[j]; ++ ++ if (checksum != 0) { ++ DSSERR("E-EDID checksum failed!!\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static 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 r; ++ } else { ++ n = pedid[0x7e]; ++ ++ /* ++ * 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) ++ return r; ++ } ++ } ++ return 0; ++} ++ ++static int get_timings_index(void) ++{ ++ int code; ++ ++ if (hdmi.mode == 0) ++ code = code_vesa[hdmi.code]; ++ else ++ code = code_cea[hdmi.code]; ++ ++ if (code == -1) { ++ /* HDMI code 4 corresponds to 640 * 480 VGA */ ++ hdmi.code = 4; ++ /* DVI mode 1 corresponds to HDMI 0 to DVI */ ++ hdmi.mode = HDMI_DVI; ++ ++ code = code_vesa[hdmi.code]; ++ } ++ return code; ++} ++ ++static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) ++{ ++ int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; ++ int timing_vsync = 0, timing_hsync = 0; ++ struct omap_video_timings temp; ++ struct hdmi_cm cm = {-1}; ++ DSSDBG("hdmi_get_code\n"); ++ ++ for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) { ++ temp = cea_vesa_timings[i].timings; ++ 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; ++ ++ DSSDBG("temp_hsync = %d , temp_vsync = %d" ++ "timing_hsync = %d, timing_vsync = %d\n", ++ 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 = HDMI_HDMI; ++ else ++ cm.mode = HDMI_DVI; ++ DSSDBG("Hdmi_code = %d mode = %d\n", ++ cm.code, cm.mode); ++ break; ++ } ++ } ++ } ++ ++ return cm; ++} ++ ++static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid , ++ struct omap_video_timings *timings) ++{ ++ /* X and Y resolution */ ++ 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) | ++ edid[current_descriptor_addrs + 5]); ++ ++ timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) | ++ edid[current_descriptor_addrs]); ++ ++ timings->pixel_clock = 10 * timings->pixel_clock; ++ ++ /* HORIZONTAL FRONT PORCH */ ++ timings->hfp = edid[current_descriptor_addrs + 8] | ++ ((edid[current_descriptor_addrs + 11] & 0xc0) << 2); ++ /* HORIZONTAL SYNC WIDTH */ ++ timings->hsw = edid[current_descriptor_addrs + 9] | ++ ((edid[current_descriptor_addrs + 11] & 0x30) << 4); ++ /* HORIZONTAL BACK PORCH */ ++ timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) | ++ edid[current_descriptor_addrs + 3]) - ++ (timings->hfp + timings->hsw); ++ /* VERTICAL FRONT PORCH */ ++ timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) | ++ ((edid[current_descriptor_addrs + 11] & 0x0f) << 2); ++ /* VERTICAL SYNC WIDTH */ ++ timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) | ++ ((edid[current_descriptor_addrs + 11] & 0x03) << 4); ++ /* VERTICAL BACK PORCH */ ++ timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | ++ edid[current_descriptor_addrs + 6]) - ++ (timings->vfp + timings->vsw); ++ ++} ++ ++/* Description : This function gets the resolution information from EDID */ ++static void get_edid_timing_data(u8 *edid) ++{ ++ u8 count; ++ u16 current_descriptor_addrs; ++ struct hdmi_cm cm; ++ struct omap_video_timings edid_timings; ++ ++ /* seach block 0, there are 4 DTDs arranged in priority order */ ++ for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { ++ current_descriptor_addrs = ++ EDID_DESCRIPTOR_BLOCK0_ADDRESS + ++ count * EDID_TIMING_DESCRIPTOR_SIZE; ++ get_horz_vert_timing_info(current_descriptor_addrs, ++ edid, &edid_timings); ++ cm = hdmi_get_code(&edid_timings); ++ DSSDBG("Block0[%d] value matches code = %d , mode = %d\n", ++ count, cm.code, cm.mode); ++ if (cm.code == -1) { ++ continue; ++ } else { ++ hdmi.code = cm.code; ++ hdmi.mode = cm.mode; ++ DSSDBG("code = %d , mode = %d\n", ++ hdmi.code, hdmi.mode); ++ return; ++ } ++ } ++ if (edid[0x7e] != 0x00) { ++ for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; ++ count++) { ++ current_descriptor_addrs = ++ EDID_DESCRIPTOR_BLOCK1_ADDRESS + ++ count * EDID_TIMING_DESCRIPTOR_SIZE; ++ get_horz_vert_timing_info(current_descriptor_addrs, ++ edid, &edid_timings); ++ cm = hdmi_get_code(&edid_timings); ++ DSSDBG("Block1[%d] value matches code = %d, mode = %d", ++ count, cm.code, cm.mode); ++ if (cm.code == -1) { ++ continue; ++ } else { ++ hdmi.code = cm.code; ++ hdmi.mode = cm.mode; ++ DSSDBG("code = %d , mode = %d\n", ++ hdmi.code, hdmi.mode); ++ return; ++ } ++ } ++ } ++ ++ DSSINFO("no valid timing found , falling back to VGA\n"); ++ hdmi.code = 4; /* setting default value of 640 480 VGA */ ++ hdmi.mode = HDMI_DVI; ++} ++ ++static void hdmi_read_edid(struct omap_video_timings *dp) ++{ ++ int ret = 0, code; ++ ++ memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH); ++ ++ if (!hdmi.edid_set) ++ ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH); ++ ++ if (!ret) { ++ if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { ++ /* search for timings of default resolution */ ++ get_edid_timing_data(hdmi.edid); ++ hdmi.edid_set = true; ++ } ++ } else { ++ DSSWARN("failed to read E-EDID\n"); ++ } ++ ++ if (!hdmi.edid_set) { ++ DSSINFO("fallback to VGA\n"); ++ hdmi.code = 4; /* setting default value of 640 480 VGA */ ++ hdmi.mode = HDMI_DVI; ++ } ++ ++ code = get_timings_index(); ++ ++ *dp = cea_vesa_timings[code].timings; ++} ++ ++static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, ++ struct hdmi_core_infoframe_avi *avi_cfg, ++ struct hdmi_core_packet_enable_repeat *repeat_cfg) ++{ ++ DSSDBG("Enter hdmi_core_init\n"); ++ ++ /* video core */ ++ video_cfg->ip_bus_width = HDMI_INPUT_8BIT; ++ video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; ++ video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; ++ video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; ++ video_cfg->hdmi_dvi = HDMI_DVI; ++ video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; ++ ++ /* info frame */ ++ avi_cfg->db1_format = 0; ++ avi_cfg->db1_active_info = 0; ++ avi_cfg->db1_bar_info_dv = 0; ++ avi_cfg->db1_scan_info = 0; ++ avi_cfg->db2_colorimetry = 0; ++ avi_cfg->db2_aspect_ratio = 0; ++ avi_cfg->db2_active_fmt_ar = 0; ++ avi_cfg->db3_itc = 0; ++ avi_cfg->db3_ec = 0; ++ avi_cfg->db3_q_range = 0; ++ avi_cfg->db3_nup_scaling = 0; ++ avi_cfg->db4_videocode = 0; ++ avi_cfg->db5_pixel_repeat = 0; ++ avi_cfg->db6_7_line_eoftop = 0 ; ++ avi_cfg->db8_9_line_sofbottom = 0; ++ avi_cfg->db10_11_pixel_eofleft = 0; ++ avi_cfg->db12_13_pixel_sofright = 0; ++ ++ /* packet enable and repeat */ ++ repeat_cfg->audio_pkt = 0; ++ repeat_cfg->audio_pkt_repeat = 0; ++ repeat_cfg->avi_infoframe = 0; ++ repeat_cfg->avi_infoframe_repeat = 0; ++ repeat_cfg->gen_cntrl_pkt = 0; ++ repeat_cfg->gen_cntrl_pkt_repeat = 0; ++ repeat_cfg->generic_pkt = 0; ++ repeat_cfg->generic_pkt_repeat = 0; ++} ++ ++static void hdmi_core_powerdown_disable(void) ++{ ++ DSSDBG("Enter hdmi_core_powerdown_disable\n"); ++ REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0); ++} ++ ++static void hdmi_core_swreset_release(void) ++{ ++ DSSDBG("Enter hdmi_core_swreset_release\n"); ++ REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0); ++} ++ ++static void hdmi_core_swreset_assert(void) ++{ ++ DSSDBG("Enter hdmi_core_swreset_assert\n"); ++ REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0); ++} ++ ++/* DSS_HDMI_CORE_VIDEO_CONFIG */ ++static void hdmi_core_video_config(struct hdmi_core_video_config *cfg) ++{ ++ u32 r = 0; ++ ++ /* sys_ctrl1 default configuration not tunable */ ++ r = hdmi_read_reg(HDMI_CORE_CTRL1); ++ r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); ++ r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); ++ r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); ++ r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); ++ hdmi_write_reg(HDMI_CORE_CTRL1, r); ++ ++ REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); ++ ++ /* Vid_Mode */ ++ r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE); ++ ++ /* dither truncation configuration */ ++ if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { ++ r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); ++ r = FLD_MOD(r, 1, 5, 5); ++ } else { ++ r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); ++ r = FLD_MOD(r, 0, 5, 5); ++ } ++ hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r); ++ ++ /* HDMI_Ctrl */ ++ r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL); ++ r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); ++ r = FLD_MOD(r, cfg->pkt_mode, 5, 3); ++ r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); ++ hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r); ++ ++ /* TMDS_CTRL */ ++ REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL, ++ cfg->tclk_sel_clkmult, 6, 5); ++} ++ ++static void hdmi_core_aux_infoframe_avi_config( ++ struct hdmi_core_infoframe_avi info_avi) ++{ ++ u32 val; ++ char sum = 0, checksum = 0; ++ ++ sum += 0x82 + 0x002 + 0x00D; ++ hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082); ++ hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002); ++ hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D); ++ ++ val = (info_avi.db1_format << 5) | ++ (info_avi.db1_active_info << 4) | ++ (info_avi.db1_bar_info_dv << 2) | ++ (info_avi.db1_scan_info); ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val); ++ sum += val; ++ ++ val = (info_avi.db2_colorimetry << 6) | ++ (info_avi.db2_aspect_ratio << 4) | ++ (info_avi.db2_active_fmt_ar); ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val); ++ sum += val; ++ ++ val = (info_avi.db3_itc << 7) | ++ (info_avi.db3_ec << 4) | ++ (info_avi.db3_q_range << 2) | ++ (info_avi.db3_nup_scaling); ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val); ++ sum += val; ++ ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode); ++ sum += info_avi.db4_videocode; ++ ++ val = info_avi.db5_pixel_repeat; ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val); ++ sum += val; ++ ++ val = info_avi.db6_7_line_eoftop & 0x00FF; ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val); ++ sum += val; ++ ++ val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val); ++ sum += val; ++ ++ val = info_avi.db8_9_line_sofbottom & 0x00FF; ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val); ++ sum += val; ++ ++ val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val); ++ sum += val; ++ ++ val = info_avi.db10_11_pixel_eofleft & 0x00FF; ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val); ++ sum += val; ++ ++ val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val); ++ sum += val; ++ ++ val = info_avi.db12_13_pixel_sofright & 0x00FF; ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val); ++ sum += val; ++ ++ val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); ++ hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val); ++ sum += val; ++ ++ checksum = 0x100 - sum; ++ hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum); ++} ++ ++static void hdmi_core_av_packet_config( ++ struct hdmi_core_packet_enable_repeat repeat_cfg) ++{ ++ /* enable/repeat the infoframe */ ++ hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1, ++ (repeat_cfg.audio_pkt << 5) | ++ (repeat_cfg.audio_pkt_repeat << 4) | ++ (repeat_cfg.avi_infoframe << 1) | ++ (repeat_cfg.avi_infoframe_repeat)); ++ ++ /* enable/repeat the packet */ ++ hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2, ++ (repeat_cfg.gen_cntrl_pkt << 3) | ++ (repeat_cfg.gen_cntrl_pkt_repeat << 2) | ++ (repeat_cfg.generic_pkt << 1) | ++ (repeat_cfg.generic_pkt_repeat)); ++} ++ ++static void hdmi_wp_init(struct omap_video_timings *timings, ++ struct hdmi_video_format *video_fmt, ++ struct hdmi_video_interface *video_int) ++{ ++ DSSDBG("Enter hdmi_wp_init\n"); ++ ++ timings->hbp = 0; ++ timings->hfp = 0; ++ timings->hsw = 0; ++ timings->vbp = 0; ++ timings->vfp = 0; ++ timings->vsw = 0; ++ ++ video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; ++ video_fmt->y_res = 0; ++ video_fmt->x_res = 0; ++ ++ video_int->vsp = 0; ++ video_int->hsp = 0; ++ ++ video_int->interlacing = 0; ++ video_int->tm = 0; /* HDMI_TIMING_SLAVE */ ++ ++} ++ ++static void hdmi_wp_video_start(bool start) ++{ ++ REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31); ++} ++ ++static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, ++ struct omap_video_timings *timings, struct hdmi_config *param) ++{ ++ DSSDBG("Enter hdmi_wp_video_init_format\n"); ++ ++ video_fmt->y_res = param->timings.timings.y_res; ++ video_fmt->x_res = param->timings.timings.x_res; ++ ++ timings->hbp = param->timings.timings.hbp; ++ timings->hfp = param->timings.timings.hfp; ++ timings->hsw = param->timings.timings.hsw; ++ timings->vbp = param->timings.timings.vbp; ++ timings->vfp = param->timings.timings.vfp; ++ timings->vsw = param->timings.timings.vsw; ++} ++ ++static void hdmi_wp_video_config_format( ++ struct hdmi_video_format *video_fmt) ++{ ++ u32 l = 0; ++ ++ REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8); ++ ++ l |= FLD_VAL(video_fmt->y_res, 31, 16); ++ l |= FLD_VAL(video_fmt->x_res, 15, 0); ++ hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l); ++} ++ ++static void hdmi_wp_video_config_interface( ++ struct hdmi_video_interface *video_int) ++{ ++ u32 r; ++ DSSDBG("Enter hdmi_wp_video_config_interface\n"); ++ ++ r = hdmi_read_reg(HDMI_WP_VIDEO_CFG); ++ r = FLD_MOD(r, video_int->vsp, 7, 7); ++ r = FLD_MOD(r, video_int->hsp, 6, 6); ++ r = FLD_MOD(r, video_int->interlacing, 3, 3); ++ r = FLD_MOD(r, video_int->tm, 1, 0); ++ hdmi_write_reg(HDMI_WP_VIDEO_CFG, r); ++} ++ ++static void hdmi_wp_video_config_timing( ++ struct omap_video_timings *timings) ++{ ++ u32 timing_h = 0; ++ u32 timing_v = 0; ++ ++ DSSDBG("Enter hdmi_wp_video_config_timing\n"); ++ ++ timing_h |= FLD_VAL(timings->hbp, 31, 20); ++ timing_h |= FLD_VAL(timings->hfp, 19, 8); ++ timing_h |= FLD_VAL(timings->hsw, 7, 0); ++ hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h); ++ ++ timing_v |= FLD_VAL(timings->vbp, 31, 20); ++ timing_v |= FLD_VAL(timings->vfp, 19, 8); ++ timing_v |= FLD_VAL(timings->vsw, 7, 0); ++ hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v); ++} ++ ++static void hdmi_basic_configure(struct hdmi_config *cfg) ++{ ++ /* HDMI */ ++ struct omap_video_timings video_timing; ++ struct hdmi_video_format video_format; ++ struct hdmi_video_interface video_interface; ++ /* HDMI core */ ++ struct hdmi_core_infoframe_avi avi_cfg; ++ struct hdmi_core_video_config v_core_cfg; ++ struct hdmi_core_packet_enable_repeat repeat_cfg; ++ ++ hdmi_wp_init(&video_timing, &video_format, ++ &video_interface); ++ ++ hdmi_core_init(&v_core_cfg, ++ &avi_cfg, ++ &repeat_cfg); ++ ++ hdmi_wp_video_init_format(&video_format, ++ &video_timing, cfg); ++ ++ hdmi_wp_video_config_timing(&video_timing); ++ ++ /* video config */ ++ video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; ++ ++ hdmi_wp_video_config_format(&video_format); ++ ++ video_interface.vsp = cfg->timings.vsync_pol; ++ video_interface.hsp = cfg->timings.hsync_pol; ++ video_interface.interlacing = cfg->interlace; ++ video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ ++ ++ hdmi_wp_video_config_interface(&video_interface); ++ ++ /* ++ * configure core video part ++ * set software reset in the core ++ */ ++ hdmi_core_swreset_assert(); ++ ++ /* power down off */ ++ hdmi_core_powerdown_disable(); ++ ++ v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; ++ v_core_cfg.hdmi_dvi = cfg->cm.mode; ++ ++ hdmi_core_video_config(&v_core_cfg); ++ ++ /* release software reset in the core */ ++ hdmi_core_swreset_release(); ++ ++ /* ++ * configure packet ++ * info frame video see doc CEA861-D page 65 ++ */ ++ avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; ++ avi_cfg.db1_active_info = ++ HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; ++ avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; ++ avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; ++ avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; ++ avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; ++ avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; ++ avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; ++ avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; ++ avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; ++ avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; ++ avi_cfg.db4_videocode = cfg->cm.code; ++ avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; ++ avi_cfg.db6_7_line_eoftop = 0; ++ avi_cfg.db8_9_line_sofbottom = 0; ++ avi_cfg.db10_11_pixel_eofleft = 0; ++ avi_cfg.db12_13_pixel_sofright = 0; ++ ++ hdmi_core_aux_infoframe_avi_config(avi_cfg); ++ ++ /* enable/repeat the infoframe */ ++ repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; ++ repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; ++ /* wakeup */ ++ repeat_cfg.audio_pkt = HDMI_PACKETENABLE; ++ repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; ++ hdmi_core_av_packet_config(repeat_cfg); ++} ++ ++static void update_hdmi_timings(struct hdmi_config *cfg, ++ struct omap_video_timings *timings, int code) ++{ ++ cfg->timings.timings.x_res = timings->x_res; ++ cfg->timings.timings.y_res = timings->y_res; ++ cfg->timings.timings.hbp = timings->hbp; ++ cfg->timings.timings.hfp = timings->hfp; ++ cfg->timings.timings.hsw = timings->hsw; ++ cfg->timings.timings.vbp = timings->vbp; ++ cfg->timings.timings.vfp = timings->vfp; ++ cfg->timings.timings.vsw = timings->vsw; ++ cfg->timings.timings.pixel_clock = timings->pixel_clock; ++ cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol; ++ cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; ++} ++ ++static void hdmi_compute_pll(unsigned long clkin, int phy, ++ int n, struct hdmi_pll_info *pi) ++{ ++ unsigned long refclk; ++ u32 mf; ++ ++ /* ++ * Input clock is predivided by N + 1 ++ * out put of which is reference clk ++ */ ++ refclk = clkin / (n + 1); ++ pi->regn = n; ++ ++ /* ++ * multiplier is pixel_clk/ref_clk ++ * Multiplying by 100 to avoid fractional part removal ++ */ ++ pi->regm = (phy * 100/(refclk))/100; ++ pi->regm2 = 1; ++ ++ /* ++ * fractional multiplier is remainder of the difference between ++ * multiplier and actual phy(required pixel clock thus should be ++ * multiplied by 218(262144) divided by the reference clock ++ */ ++ mf = (phy - pi->regm * refclk) * 262144; ++ pi->regmf = mf/(refclk); ++ ++ /* ++ * Dcofreq should be set to 1 if required pixel clock ++ * is greater than 1000MHz ++ */ ++ 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 void hdmi_enable_clocks(int enable) ++{ ++ if (enable) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | ++ DSS_CLK_SYSCK | DSS_CLK_VIDFCK); ++ else ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | ++ DSS_CLK_SYSCK | DSS_CLK_VIDFCK); ++} ++ ++static int hdmi_power_on(struct omap_dss_device *dssdev) ++{ ++ int r, code = 0; ++ struct hdmi_pll_info pll_data; ++ struct omap_video_timings *p; ++ int clkin, n, phy; ++ ++ hdmi_enable_clocks(1); ++ ++ dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); ++ ++ p = &dssdev->panel.timings; ++ ++ DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", ++ dssdev->panel.timings.x_res, ++ dssdev->panel.timings.y_res); ++ ++ if (!hdmi.custom_set) { ++ DSSDBG("Read EDID as no EDID is not set on poweron\n"); ++ hdmi_read_edid(p); ++ } ++ code = get_timings_index(); ++ dssdev->panel.timings = cea_vesa_timings[code].timings; ++ update_hdmi_timings(&hdmi.cfg, p, code); ++ ++ clkin = 3840; /* 38.4 MHz */ ++ n = 15; /* this is a constant for our math */ ++ phy = p->pixel_clock; ++ ++ hdmi_compute_pll(clkin, phy, n, &pll_data); ++ ++ hdmi_wp_video_start(0); ++ ++ /* config the PLL and PHY first */ ++ r = hdmi_pll_program(&pll_data); ++ if (r) { ++ DSSDBG("Failed to lock PLL\n"); ++ goto err; ++ } ++ ++ r = hdmi_phy_init(); ++ if (r) { ++ DSSDBG("Failed to start PHY\n"); ++ goto err; ++ } ++ ++ hdmi.cfg.cm.mode = hdmi.mode; ++ hdmi.cfg.cm.code = hdmi.code; ++ hdmi_basic_configure(&hdmi.cfg); ++ ++ /* Make selection of HDMI in DSS */ ++ dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); ++ ++ /* Select the dispc clock source as PRCM clock, to ensure that it is not ++ * DSI PLL source as the clock selected by DSI PLL might not be ++ * sufficient for the resolution selected / that can be changed ++ * dynamically by user. This can be moved to single location , say ++ * Boardfile. ++ */ ++ dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); ++ ++ /* bypass TV gamma table */ ++ dispc_enable_gamma_table(0); ++ ++ /* tv size */ ++ dispc_set_digit_size(dssdev->panel.timings.x_res, ++ dssdev->panel.timings.y_res); ++ ++ dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); ++ ++ hdmi_wp_video_start(1); ++ ++ return 0; ++err: ++ hdmi_enable_clocks(0); ++ return -EIO; ++} ++ ++static void hdmi_power_off(struct omap_dss_device *dssdev) ++{ ++ dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); ++ ++ hdmi_wp_video_start(0); ++ hdmi_phy_off(); ++ hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); ++ hdmi_enable_clocks(0); ++ ++ hdmi.edid_set = 0; ++} ++ ++int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct hdmi_cm cm; ++ ++ cm = hdmi_get_code(timings); ++ if (cm.code == -1) { ++ DSSERR("Invalid timing entered\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++ ++} ++ ++void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) ++{ ++ struct hdmi_cm cm; ++ ++ hdmi.custom_set = 1; ++ cm = hdmi_get_code(&dssdev->panel.timings); ++ hdmi.code = cm.code; ++ hdmi.mode = cm.mode; ++ omapdss_hdmi_display_enable(dssdev); ++ hdmi.custom_set = 0; ++} ++ ++int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("ENTER hdmi_display_enable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ r = omap_dss_start_device(dssdev); ++ if (r) { ++ DSSERR("failed to start device\n"); ++ goto err0; ++ } ++ ++ if (dssdev->platform_enable) { ++ r = dssdev->platform_enable(dssdev); ++ if (r) { ++ DSSERR("failed to enable GPIO's\n"); ++ goto err1; ++ } ++ } ++ ++ r = hdmi_power_on(dssdev); ++ if (r) { ++ DSSERR("failed to power on device\n"); ++ goto err2; ++ } ++ ++ mutex_unlock(&hdmi.lock); ++ return 0; ++ ++err2: ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++err1: ++ omap_dss_stop_device(dssdev); ++err0: ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++ ++void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("Enter hdmi_display_disable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ hdmi_power_off(dssdev); ++ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ omap_dss_stop_device(dssdev); ++ ++ mutex_unlock(&hdmi.lock); ++} ++ ++/* HDMI HW IP initialisation */ ++static int omapdss_hdmihw_probe(struct platform_device *pdev) ++{ ++ struct resource *hdmi_mem; ++ ++ hdmi.pdata = pdev->dev.platform_data; ++ hdmi.pdev = pdev; ++ ++ mutex_init(&hdmi.lock); ++ ++ hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); ++ if (!hdmi_mem) { ++ DSSERR("can't get IORESOURCE_MEM HDMI\n"); ++ return -EINVAL; ++ } ++ ++ /* Base address taken from platform */ ++ hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); ++ if (!hdmi.base_wp) { ++ DSSERR("can't ioremap WP\n"); ++ return -ENOMEM; ++ } ++ ++ hdmi_panel_init(); ++ ++ return 0; ++} ++ ++static int omapdss_hdmihw_remove(struct platform_device *pdev) ++{ ++ hdmi_panel_exit(); ++ ++ iounmap(hdmi.base_wp); ++ ++ return 0; ++} ++ ++static struct platform_driver omapdss_hdmihw_driver = { ++ .probe = omapdss_hdmihw_probe, ++ .remove = omapdss_hdmihw_remove, ++ .driver = { ++ .name = "omapdss_hdmi", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++int hdmi_init_platform_driver(void) ++{ ++ return platform_driver_register(&omapdss_hdmihw_driver); ++} ++ ++void hdmi_uninit_platform_driver(void) ++{ ++ return platform_driver_unregister(&omapdss_hdmihw_driver); ++} +-- 1.5.6.3 diff --git a/packages/linux/patches/linux-2.6.38-rc8-306-V5_HDMI_panel_driver_addition_in_the_DSS.patch b/packages/linux/patches/linux-2.6.38-rc8-306-V5_HDMI_panel_driver_addition_in_the_DSS.patch new file mode 100644 index 0000000000..8d2cdcc739 --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-306-V5_HDMI_panel_driver_addition_in_the_DSS.patch @@ -0,0 +1,252 @@ +The panel driver(hdmi_omap4_panel.c) in omap2/dss acts as a controller +to manage the enable and disable requests and synchronize audio and video. + +Signed-off-by: Mythri P K +--- + drivers/video/omap2/dss/dss.h | 2 + + drivers/video/omap2/dss/hdmi_omap4_panel.c | 222 ++++++++++++++++++++++++++++ + 2 files changed, 224 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/hdmi_omap4_panel.c + +diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h +index 6bf923c..05ccd00 100644 +--- a/drivers/video/omap2/dss/dss.h ++++ b/drivers/video/omap2/dss/dss.h +@@ -483,6 +483,8 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); + void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); + int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, + struct omap_video_timings *timings); ++int hdmi_panel_init(void); ++void hdmi_panel_exit(void); + + /* RFBI */ + #ifdef CONFIG_OMAP2_DSS_RFBI +diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c +new file mode 100644 +index 0000000..ffb5de9 +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c +@@ -0,0 +1,222 @@ ++/* ++ * hdmi_omap4_panel.c ++ * ++ * HDMI library support functions for TI OMAP4 processors. ++ * ++ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ ++ * Authors: Mythri P k ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dss.h" ++ ++static struct { ++ struct mutex hdmi_lock; ++} hdmi; ++ ++ ++static int hdmi_panel_probe(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("ENTER hdmi_panel_probe\n"); ++ ++ dssdev->panel.config = OMAP_DSS_LCD_TFT | ++ OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; ++ ++ /* ++ * Initialize the timings to 640 * 480 ++ * This is only for framebuffer update not for TV timing setting ++ * Setting TV timing will be done only on enable ++ */ ++ dssdev->panel.timings.x_res = 640; ++ dssdev->panel.timings.y_res = 480; ++ ++ DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", ++ dssdev->panel.timings.x_res, ++ dssdev->panel.timings.y_res); ++ return 0; ++} ++ ++static void hdmi_panel_remove(struct omap_dss_device *dssdev) ++{ ++ ++} ++ ++static int hdmi_panel_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ DSSDBG("ENTER hdmi_panel_enable\n"); ++ ++ mutex_lock(&hdmi.hdmi_lock); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ r = omapdss_hdmi_display_enable(dssdev); ++ if (r) { ++ DSSERR("failed to power on\n"); ++ goto err; ++ } ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++err: ++ mutex_unlock(&hdmi.hdmi_lock); ++ ++ return r; ++} ++ ++static void hdmi_panel_disable(struct omap_dss_device *dssdev) ++{ ++ mutex_lock(&hdmi.hdmi_lock); ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) ++ omapdss_hdmi_display_disable(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ ++ mutex_unlock(&hdmi.hdmi_lock); ++} ++ ++static int hdmi_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ mutex_lock(&hdmi.hdmi_lock); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; ++ ++ omapdss_hdmi_display_disable(dssdev); ++ ++err: ++ mutex_unlock(&hdmi.hdmi_lock); ++ ++ return r; ++} ++ ++static int hdmi_panel_resume(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ mutex_lock(&hdmi.hdmi_lock); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ r = omapdss_hdmi_display_enable(dssdev); ++ if (r) { ++ DSSERR("failed to power on\n"); ++ goto err; ++ } ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++err: ++ mutex_unlock(&hdmi.hdmi_lock); ++ ++ return r; ++} ++ ++static void hdmi_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ mutex_lock(&hdmi.hdmi_lock); ++ ++ *timings = dssdev->panel.timings; ++ ++ mutex_unlock(&hdmi.hdmi_lock); ++} ++ ++static void hdmi_set_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ DSSDBG("hdmi_set_timings\n"); ++ ++ mutex_lock(&hdmi.hdmi_lock); ++ ++ dssdev->panel.timings = *timings; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { ++ /* turn the hdmi off and on to get new timings to use */ ++ omapdss_hdmi_display_disable(dssdev); ++ omapdss_hdmi_display_set_timing(dssdev); ++ } ++ ++ mutex_unlock(&hdmi.hdmi_lock); ++} ++ ++static int hdmi_check_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ int r = 0; ++ ++ DSSDBG("hdmi_check_timings\n"); ++ ++ mutex_lock(&hdmi.hdmi_lock); ++ ++ r = omapdss_hdmi_display_check_timing(dssdev, timings); ++ if (r) { ++ DSSERR("Timing cannot be applied\n"); ++ goto err; ++ } ++err: ++ mutex_unlock(&hdmi.hdmi_lock); ++ return r; ++} ++ ++static struct omap_dss_driver hdmi_driver = { ++ .probe = hdmi_panel_probe, ++ .remove = hdmi_panel_remove, ++ .enable = hdmi_panel_enable, ++ .disable = hdmi_panel_disable, ++ .suspend = hdmi_panel_suspend, ++ .resume = hdmi_panel_resume, ++ .get_timings = hdmi_get_timings, ++ .set_timings = hdmi_set_timings, ++ .check_timings = hdmi_check_timings, ++ .driver = { ++ .name = "hdmi_panel", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++int hdmi_panel_init(void) ++{ ++ mutex_init(&hdmi.hdmi_lock); ++ ++ omap_dss_register_driver(&hdmi_driver); ++ ++ return 0; ++} ++ ++void hdmi_panel_exit(void) ++{ ++ omap_dss_unregister_driver(&hdmi_driver); ++ ++} +-- 1.5.6.3 diff --git a/packages/linux/patches/linux-2.6.38-rc8-307-V5_Add_makefile_and_kconfig_changes_to_enable_HDMI_in_OMAP4.patch b/packages/linux/patches/linux-2.6.38-rc8-307-V5_Add_makefile_and_kconfig_changes_to_enable_HDMI_in_OMAP4.patch new file mode 100644 index 0000000000..f95348bc66 --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-307-V5_Add_makefile_and_kconfig_changes_to_enable_HDMI_in_OMAP4.patch @@ -0,0 +1,36 @@ +Signed-off-by: Mythri P K +--- + drivers/video/omap2/dss/Kconfig | 8 ++++++++ + drivers/video/omap2/dss/Makefile | 2 ++ + 2 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig +index db01473..bfc5da0 100644 +--- a/drivers/video/omap2/dss/Kconfig ++++ b/drivers/video/omap2/dss/Kconfig +@@ -60,6 +60,14 @@ config OMAP2_DSS_VENC + help + OMAP Video Encoder support for S-Video and composite TV-out. + ++config OMAP4_DSS_HDMI ++ bool "HDMI support" ++ depends on ARCH_OMAP4 ++ default y ++ help ++ HDMI Interface. This adds the High Definition Multimedia Interface. ++ See http://www.hdmi.org/ for HDMI specification. ++ + config OMAP2_DSS_SDI + bool "SDI support" + depends on ARCH_OMAP3 +diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile +index 7db17b5..10d9d3b 100644 +--- a/drivers/video/omap2/dss/Makefile ++++ b/drivers/video/omap2/dss/Makefile +@@ -5,3 +5,5 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o + omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o + omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o + omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o ++omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ ++ hdmi_omap4_panel.o +-- 1.5.6.3 diff --git a/packages/linux/patches/linux-2.6.38-rc8-308-V5_Call_to_HDMI_module_init_to_register_driver.patch b/packages/linux/patches/linux-2.6.38-rc8-308-V5_Call_to_HDMI_module_init_to_register_driver.patch new file mode 100644 index 0000000000..75ca4de0c8 --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-308-V5_Call_to_HDMI_module_init_to_register_driver.patch @@ -0,0 +1,43 @@ +calling the platform registration of HDMI driver from core +during initialization. + +Signed-off-by: Mythri P K +--- + drivers/video/omap2/dss/core.c | 9 +++++++++ + 1 files changed, 9 insertions(+), 0 deletions(-) + +diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c +index c2f930b..1aa2ed1 100644 +--- a/drivers/video/omap2/dss/core.c ++++ b/drivers/video/omap2/dss/core.c +@@ -209,6 +209,12 @@ static int omap_dss_probe(struct platform_device *pdev) + goto err_dsi; + } + ++ r = hdmi_init_platform_driver(); ++ if (r) { ++ DSSERR("Failed to initialize hdmi\n"); ++ goto err_hdmi; ++ } ++ + r = dss_initialize_debugfs(); + if (r) + goto err_debugfs; +@@ -238,6 +244,8 @@ static int omap_dss_probe(struct platform_device *pdev) + err_register: + dss_uninitialize_debugfs(); + err_debugfs: ++ hdmi_uninit_platform_driver(); ++err_hdmi: + dsi_uninit_platform_driver(); + err_dsi: + venc_uninit_platform_driver(); +@@ -263,6 +271,7 @@ static int omap_dss_remove(struct platform_device *pdev) + dispc_uninit_platform_driver(); + rfbi_uninit_platform_driver(); + dsi_uninit_platform_driver(); ++ hdmi_uninit_platform_driver(); + dss_uninit_platform_driver(); + + dss_uninit_overlays(pdev); +-- 1.5.6.3 diff --git a/packages/linux/patches/linux-2.6.38-rc8-309-V5_Add_HDMI_structure_in_the_board_file_for_OMAP4_SDP.patch b/packages/linux/patches/linux-2.6.38-rc8-309-V5_Add_HDMI_structure_in_the_board_file_for_OMAP4_SDP.patch new file mode 100644 index 0000000000..491cc89a66 --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-309-V5_Add_HDMI_structure_in_the_board_file_for_OMAP4_SDP.patch @@ -0,0 +1,118 @@ +Adding board file structure for display which adds the display +structure with HDMI as the default driver when the display init +is called. +HDMI GPIO configurations are also done in this file. + +Signed-off-by: Mythri P K +--- + arch/arm/mach-omap2/board-4430sdp.c | 75 +++++++++++++++++++++++++++++++++++ + 1 files changed, 75 insertions(+), 0 deletions(-) + +diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c +index 85805d4..f5fcc5f 100644 +--- a/arch/arm/mach-omap2/board-4430sdp.c ++++ b/arch/arm/mach-omap2/board-4430sdp.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include "mux.h" + #include "hsmmc.h" +@@ -47,6 +48,8 @@ + #define ETH_KS8851_QUART 138 + #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO 184 + #define OMAP4_SFH7741_ENABLE_GPIO 188 ++#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ ++#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ + + static const int sdp4430_keymap[] = { + KEY(0, 0, KEY_E), +@@ -620,6 +623,76 @@ static void __init omap_sfh7741prox_init(void) + } + } + ++static void sdp4430_hdmi_mux_init(void) ++{ ++ /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */ ++ omap_mux_init_signal("hdmi_hpd", ++ OMAP_PIN_INPUT_PULLUP); ++ omap_mux_init_signal("hdmi_cec", ++ OMAP_PIN_INPUT_PULLUP); ++ /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */ ++ omap_mux_init_signal("hdmi_ddc_scl", ++ OMAP_PIN_INPUT_PULLUP); ++ omap_mux_init_signal("hdmi_ddc_sda", ++ OMAP_PIN_INPUT_PULLUP); ++} ++ ++static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev) ++{ ++ int status; ++ ++ status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, ++ "hdmi_gpio_hpd"); ++ if (status) { ++ pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD); ++ return status; ++ } ++ status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, ++ "hdmi_gpio_ls_oe"); ++ if (status) { ++ pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE); ++ goto error1; ++ } ++ ++ return 0; ++ ++error1: ++ gpio_free(HDMI_GPIO_HPD); ++ ++ return status; ++} ++ ++static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev) ++{ ++ gpio_free(HDMI_GPIO_LS_OE); ++ gpio_free(HDMI_GPIO_HPD); ++} ++ ++static struct omap_dss_device sdp4430_hdmi_device = { ++ .name = "hdmi", ++ .driver_name = "hdmi_panel", ++ .type = OMAP_DISPLAY_TYPE_HDMI, ++ .platform_enable = sdp4430_panel_enable_hdmi, ++ .platform_disable = sdp4430_panel_disable_hdmi, ++ .channel = OMAP_DSS_CHANNEL_DIGIT, ++}; ++ ++static struct omap_dss_device *sdp4430_dss_devices[] = { ++ &sdp4430_hdmi_device, ++}; ++ ++static struct omap_dss_board_info sdp4430_dss_data = { ++ .num_devices = ARRAY_SIZE(sdp4430_dss_devices), ++ .devices = sdp4430_dss_devices, ++ .default_device = &sdp4430_hdmi_device, ++}; ++ ++void omap_4430sdp_display_init(void) ++{ ++ sdp4430_hdmi_mux_init(); ++ omap_display_init(&sdp4430_dss_data); ++} ++ + #ifdef CONFIG_OMAP_MUX + static struct omap_board_mux board_mux[] __initdata = { + OMAP4_MUX(USBB2_ULPITLL_CLK, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT), +@@ -661,6 +734,8 @@ static void __init omap_4430sdp_init(void) + status = omap4_keyboard_init(&sdp4430_keypad_data); + if (status) + pr_err("Keypad initialization failed: %d\n", status); ++ ++ omap_4430sdp_display_init(); + } + + static void __init omap_4430sdp_map_io(void) +-- 1.5.6.3 diff --git a/packages/linux/patches/linux-2.6.38-rc8-310-V5_Add_HDMI_structure_in_the_board_file_for_OMAP4__PANDA.patch b/packages/linux/patches/linux-2.6.38-rc8-310-V5_Add_HDMI_structure_in_the_board_file_for_OMAP4__PANDA.patch new file mode 100644 index 0000000000..9c4b26ec9e --- /dev/null +++ b/packages/linux/patches/linux-2.6.38-rc8-310-V5_Add_HDMI_structure_in_the_board_file_for_OMAP4__PANDA.patch @@ -0,0 +1,117 @@ +Adding board file structure for display which adds the display +structure with HDMI as the default driver when the display init +is called. +HDMI GPIO configurations are also done in this file. + +Signed-off-by: Mythri P K +--- + arch/arm/mach-omap2/board-omap4panda.c | 74 ++++++++++++++++++++++++++++++++ + 1 files changed, 74 insertions(+), 0 deletions(-) + +diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c +index a94ce07..4869c0f 100644 +--- a/arch/arm/mach-omap2/board-omap4panda.c ++++ b/arch/arm/mach-omap2/board-omap4panda.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -49,6 +50,8 @@ + #define GPIO_HUB_NRESET 62 + #define GPIO_WIFI_PMENA 43 + #define GPIO_WIFI_IRQ 53 ++#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ ++#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ + + /* wl127x BT, FM, GPS connectivity chip */ + static int wl1271_gpios[] = {46, -1, -1}; +@@ -467,6 +470,76 @@ static struct omap_board_mux board_mux[] __initdata = { + #define board_mux NULL + #endif + ++static void sdp4430_hdmi_mux_init(void) ++{ ++ /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */ ++ omap_mux_init_signal("hdmi_hpd", ++ OMAP_PIN_INPUT_PULLUP); ++ omap_mux_init_signal("hdmi_cec", ++ OMAP_PIN_INPUT_PULLUP); ++ /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */ ++ omap_mux_init_signal("hdmi_ddc_scl", ++ OMAP_PIN_INPUT_PULLUP); ++ omap_mux_init_signal("hdmi_ddc_sda", ++ OMAP_PIN_INPUT_PULLUP); ++} ++ ++static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev) ++{ ++ int status; ++ ++ status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, ++ "hdmi_gpio_hpd"); ++ if (status) { ++ pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD); ++ return status; ++ } ++ status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, ++ "hdmi_gpio_ls_oe"); ++ if (status) { ++ pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE); ++ goto error1; ++ } ++ ++ return 0; ++ ++error1: ++ gpio_free(HDMI_GPIO_HPD); ++ ++ return status; ++} ++ ++static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev) ++{ ++ gpio_free(HDMI_GPIO_LS_OE); ++ gpio_free(HDMI_GPIO_HPD); ++} ++ ++static struct omap_dss_device sdp4430_hdmi_device = { ++ .name = "hdmi", ++ .driver_name = "hdmi_panel", ++ .type = OMAP_DISPLAY_TYPE_HDMI, ++ .platform_enable = sdp4430_panel_enable_hdmi, ++ .platform_disable = sdp4430_panel_disable_hdmi, ++ .channel = OMAP_DSS_CHANNEL_DIGIT, ++}; ++ ++static struct omap_dss_device *sdp4430_dss_devices[] = { ++ &sdp4430_hdmi_device, ++}; ++ ++static struct omap_dss_board_info sdp4430_dss_data = { ++ .num_devices = ARRAY_SIZE(sdp4430_dss_devices), ++ .devices = sdp4430_dss_devices, ++ .default_device = &sdp4430_hdmi_device, ++}; ++ ++void omap_panda_display_init(void) ++{ ++ sdp4430_hdmi_mux_init(); ++ omap_display_init(&sdp4430_dss_data); ++} ++ + static void __init omap4_panda_init(void) + { + int package = OMAP_PACKAGE_CBS; +@@ -485,6 +558,7 @@ static void __init omap4_panda_init(void) + omap4_twl6030_hsmmc_init(mmc); + omap4_ehci_init(); + usb_musb_init(&musb_board_data); ++ omap_panda_display_init(); + } + + static void __init omap4_panda_map_io(void) +-- 1.5.6.3