* [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 @ 2011-03-09 11:45 Mythri P K 2011-03-09 11:45 ` [PATCH v4 1/9] OMAP4 : DSS2 : Add display type HDMI to DSS2 Mythri P K 2011-03-09 14:15 ` [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 Tomi Valkeinen 0 siblings, 2 replies; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K Adding HDMI support on OMAP4. HDMI is a driver that is similar to the VENC or the DSI driver to support HDMI/DVI sink device. The current design adheres to the DSS2 architecture. It is split into the HDMI DSS driver and HDMI panel driver. HDMI DSS driver (hdmi.c) is responsible for 1.OMAP related configuration such as 1.Listening to the DSS_HDMI irq which signals changes such as hot-plug detect,physical attach/detach. 2.calculate the PLL values based on the TV resolution that is selected 3.configuration of the Mux/GPIO settings. 2.HDMI configuration based on the parameters read from the EDID of the sink device such as: 1. Configuration of the PHY registers. 2. Configuration of the PLL registers and setting of the TMDS clock. 3. Configuration of the DDC to read the EDID data when available. 4. Configuration of the core registers to set: a. set the video registers to the timing and format that is selected. b. set the audio registers based on the EDID value read and user selected parameters. c. Set the AVI info frame registers to configure the auxilary info frame which are repeated. HDMI Panel Driver (hdmi_omap4_panel.c) . This is a panel driver which acts as the controlling device which synchronizes the audio and video portion of the driver.[enable ,disable , notification to audio on suspend etc]. It registers hdmi driver to the omap_dss bus and calls the functionality of the HDMI DSS driver. It is also provides the interface for users 1.To read the EDID contents and also confiure the timings based on EDID. 2.To configure AVI Inforframe based on the the EDID(sink capability). Note : Mux handling with hwmod is dependent on pm_runtime_sync ,so mux with hwmod will be posted once patch series with pm_runtime_sync is done. verified on 4430 SDP ES2.1 - Penguins on HDMI and DVI TV. verified on PANDA ES2.1 - Penguins on HDMI and DVI TV. Changes from V3: 1. compile hdmi_omap4_panel.c as part of OMAPDSS , for OMAPDSS to work as module. 2. Function cleanup to take enum as parameter. 3. Rebased on Tomi's master branch Tree. Changes from V2: 1. separated the gamma function from venc/hdmi clock source switch function. 2. Mutex lock fixed. 3. Removed some enum to be used later from the header file. 4. global variables in hdmi.c moved to hdmi structure. Changes from V1: 1. HDMI to call dss_get_dispc_clock_source instead of directly setting register. 2. All HDMI enumerators are added HDMI prefix. 3. Fixed the mutex position. Mythri P K (9): OMAP4 : DSS2 : Add display type HDMI to DSS2 OMAP4 : DSS2 : HDMI: Select between HDMI VENC clock source. OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable. OMAP4 : DSS2 : HDMI: HDMI driver header file addition OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS OMAP4 : DSS : HDMI: Call to HDMI module init to register driver. OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 SDP OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 PANDA arch/arm/mach-omap2/board-4430sdp.c | 75 ++ arch/arm/mach-omap2/board-omap4panda.c | 74 ++ arch/arm/plat-omap/include/plat/display.h | 1 + drivers/video/omap2/dss/Kconfig | 16 + drivers/video/omap2/dss/Makefile | 2 + drivers/video/omap2/dss/core.c | 9 + drivers/video/omap2/dss/dispc.c | 10 + drivers/video/omap2/dss/display.c | 5 + drivers/video/omap2/dss/dss.c | 5 + drivers/video/omap2/dss/dss.h | 51 +- drivers/video/omap2/dss/dss_features.c | 2 +- drivers/video/omap2/dss/hdmi.c | 1335 ++++++++++++++++++++++++++++ drivers/video/omap2/dss/hdmi.h | 415 +++++++++ drivers/video/omap2/dss/hdmi_omap4_panel.c | 209 +++++ drivers/video/omap2/dss/manager.c | 9 +- drivers/video/omap2/dss/overlay.c | 6 +- 16 files changed, 2218 insertions(+), 6 deletions(-) create mode 100644 drivers/video/omap2/dss/hdmi.c create mode 100644 drivers/video/omap2/dss/hdmi.h create mode 100644 drivers/video/omap2/dss/hdmi_omap4_panel.c ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v4 1/9] OMAP4 : DSS2 : Add display type HDMI to DSS2 2011-03-09 11:45 [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 Mythri P K @ 2011-03-09 11:45 ` Mythri P K 2011-03-09 11:45 ` [PATCH v4 2/9] OMAP4 : DSS2 : HDMI: Select between HDMI VENC clock source Mythri P K 2011-03-09 14:15 ` [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 Tomi Valkeinen 1 sibling, 1 reply; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K 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 <mythripk@ti.com> --- 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 dc170ad..f4a4ca9 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -112,7 +112,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 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v4 2/9] OMAP4 : DSS2 : HDMI: Select between HDMI VENC clock source. 2011-03-09 11:45 ` [PATCH v4 1/9] OMAP4 : DSS2 : Add display type HDMI to DSS2 Mythri P K @ 2011-03-09 11:45 ` Mythri P K 2011-03-09 11:45 ` [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable Mythri P K 0 siblings, 1 reply; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K Signed-off-by: Mythri P K <mythripk@ti.com> --- 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 2be4d03..1d91b0a 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -559,6 +559,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 85d4141..29f31fd 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -129,6 +129,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; @@ -215,6 +220,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 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable. 2011-03-09 11:45 ` [PATCH v4 2/9] OMAP4 : DSS2 : HDMI: Select between HDMI VENC clock source Mythri P K @ 2011-03-09 11:45 ` Mythri P K 2011-03-09 11:45 ` [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition Mythri P K 2011-03-09 14:49 ` [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable Premi, Sanjeev 0 siblings, 2 replies; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K Adding changes to set gamma table bit for TV interface to make sure it is disabled Signed-off-by: Mythri P K <mythripk@ti.com> --- drivers/video/omap2/dss/dispc.c | 10 ++++++++++ drivers/video/omap2/dss/dss.h | 1 + 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 4a368c4..0defe16 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1008,6 +1008,16 @@ 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. + */ + BUG_ON(enable); + + 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 29f31fd..008cbf4 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -363,6 +363,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 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition 2011-03-09 11:45 ` [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable Mythri P K @ 2011-03-09 11:45 ` Mythri P K 2011-03-09 11:45 ` [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS Mythri P K 2011-03-09 15:56 ` [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition Premi, Sanjeev 2011-03-09 14:49 ` [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable Premi, Sanjeev 1 sibling, 2 replies; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K 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 <mythripk@ti.com> --- 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef _OMAP4_DSS_HDMI_H_ +#define _OMAP4_DSS_HDMI_H_ + +#include <linux/string.h> +#include <plat/display.h> + +#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 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS 2011-03-09 11:45 ` [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition Mythri P K @ 2011-03-09 11:45 ` Mythri P K 2011-03-09 11:45 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel " Mythri P K 2011-03-09 15:50 ` [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI " Premi, Sanjeev 2011-03-09 15:56 ` [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition Premi, Sanjeev 1 sibling, 2 replies; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K 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 <mythripk@ti.com> Yong Zhi <y-zhi@ti.com> --- drivers/video/omap2/dss/Kconfig | 8 + drivers/video/omap2/dss/Makefile | 1 + drivers/video/omap2/dss/display.c | 3 + drivers/video/omap2/dss/dss.h | 43 ++ drivers/video/omap2/dss/hdmi.c | 1315 +++++++++++++++++++++++++++++++++++++ 5 files changed, 1370 insertions(+), 0 deletions(-) create mode 100644 drivers/video/omap2/dss/hdmi.c diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index db01473..7749ddb 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 OMAP2_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..5998b69 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -5,3 +5,4 @@ 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_OMAP2_DSS_HDMI) += hdmi.o 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 008cbf4..3eb2661 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -174,6 +174,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; @@ -437,6 +447,39 @@ static inline void venc_uninit_platform_driver(void) } #endif +/* HDMI */ +#ifdef CONFIG_OMAP2_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); +#ifdef CONFIG_OMAP4_PANEL_HDMI +int hdmi_panel_init(void); +void hdmi_panel_exit(void); +#else +static inline int hdmi_panel_init(void) +{ + return 0; +} +static inline void hdmi_panel_exit(void) +{ +} +#endif + /* 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..6852843 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.c @@ -0,0 +1,1315 @@ +/* + * 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 <mythripk@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 <http://www.gnu.org/licenses/>. + */ + +#define DSS_SUBSYS_NAME "HDMI" + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/mutex.h> +#include <linux/delay.h> +#include <linux/string.h> +#include <plat/display.h> + +#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; + struct hdmi_config cfg; +} hdmi; + +/* + * Logic for the below structure + * user enters the CEA or VESA timings by specifying + * the hdmicode which corresponds to CEA/VESA timings + * please refer to section 6.3 in HDMI 1.3 specification for timing code. + * There is a correspondence between CEA/VESA timing and code. + * In the below structure, cea_vesa_timings corresponds to all + * The OMAP4 supported timing CEA and VESA timing values. + * code_cea corresponds to the CEA code entered by the user, + * The use of it is to get the timing from the cea_vesa_timing array. + * Similarly for code_vesa. + * code_index is backmapping, Once EDID is read from the TV + * EDID is parsed to find the timing values to map it back to the + * corresponding CEA or VESA index this structure is used. + */ + +/* + * This is the structure which has all supported timing + * values that OMAP4 supports + */ +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 -ENODEV; + } + + 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 -ENODEV; + } + + 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 -ENODEV; + } + + return 0; +} + +static int hdmi_pll_program(struct hdmi_pll_info *fmt) +{ + u16 r = 0; + enum hdmi_clk_refsel refsel; + + /* wait for wrapper reset */ + hdmi_wait_softreset(); + + 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; + + hdmi_pll_reset(); + + 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 No timer needed */ + 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); + + /* + * Do not optimize this part of the code, seems + * DDC bus needs some time to get stabilized + */ + + /* 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 -EIO; + } 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 -EIO; + } + } + 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) { + code = 9; + /* HDMI code 16 corresponds to 1920 * 1080 */ + hdmi.code = 16; + /* HDMI mode 1 corresponds to HDMI 0 to DVI */ + hdmi.mode = HDMI_HDMI; + } + 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 int 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 != 0) { + DSSWARN("failed to read E-EDID\n"); + } else { + 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; + } + } + + 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; + + return 0; +} + +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 2^18(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); + + DSSDBG("Read EDID as no EDID is not set on poweron\n"); + r = hdmi_read_edid(p); + if (r) + goto err; + + 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_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 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-09 11:45 ` [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS Mythri P K @ 2011-03-09 11:45 ` Mythri P K 2011-03-09 11:45 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Mythri P K ` (2 more replies) 2011-03-09 15:50 ` [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI " Premi, Sanjeev 1 sibling, 3 replies; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K 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 <mythripk@ti.com> --- drivers/video/omap2/dss/Kconfig | 8 + drivers/video/omap2/dss/Makefile | 1 + drivers/video/omap2/dss/hdmi_omap4_panel.c | 209 ++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+), 0 deletions(-) create mode 100644 drivers/video/omap2/dss/hdmi_omap4_panel.c diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 7749ddb..f66043f 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -125,4 +125,12 @@ config OMAP2_DSS_MIN_FCK_PER_PCK Max FCK is 173MHz, so this doesn't work if your PCK is very high. +config OMAP4_PANEL_HDMI + bool "HDMI panel support" + depends on OMAP2_DSS_HDMI + default n + help + HDMI panel. This adds the High Definition Multimedia panel. + See http://www.hdmi.org/ for HDMI specification. + endif diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 5998b69..7ee4093 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -6,3 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o omapdss-$(CONFIG_OMAP2_DSS_HDMI) += hdmi.o +omapdss-$(CONFIG_OMAP4_PANEL_HDMI) += hdmi_omap4_panel.o 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..fda14ff --- /dev/null +++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c @@ -0,0 +1,209 @@ +/* + * 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 <mythripk@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 <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/mutex.h> +#include <linux/module.h> +#include <plat/display.h> + +#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 1920 * 1080 + * 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 = 1920; + dssdev->panel.timings.y_res = 1080; + + 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) +{ + int r = 0; + + 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); + r = omapdss_hdmi_display_enable(dssdev); + if (r) { + DSSERR("failed to set timings and power on\n"); + goto err; + } + } + +err: + mutex_unlock(&hdmi.hdmi_lock); +} + +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, + .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 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver. 2011-03-09 11:45 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel " Mythri P K @ 2011-03-09 11:45 ` Mythri P K 2011-03-09 11:45 ` [PATCH v4 8/9] OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 SDP Mythri P K 2011-03-09 15:54 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Premi, Sanjeev 2011-03-09 14:23 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS Tomi Valkeinen 2011-03-10 7:52 ` Tomi Valkeinen 2 siblings, 2 replies; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K calling the platform registration of HDMI driver from core during initialization. Signed-off-by: Mythri P K <mythripk@ti.com> --- 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 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v4 8/9] OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 SDP 2011-03-09 11:45 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Mythri P K @ 2011-03-09 11:45 ` Mythri P K 2011-03-09 11:45 ` [PATCH v4 9/9] OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 PANDA Mythri P K 2011-03-09 15:54 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Premi, Sanjeev 1 sibling, 1 reply; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K 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 <mythripk@ti.com> --- 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 <plat/usb.h> #include <plat/mmc.h> #include <plat/omap4-keypad.h> +#include <plat/display.h> #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 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v4 9/9] OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 PANDA 2011-03-09 11:45 ` [PATCH v4 8/9] OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 SDP Mythri P K @ 2011-03-09 11:45 ` Mythri P K 0 siblings, 0 replies; 33+ messages in thread From: Mythri P K @ 2011-03-09 11:45 UTC (permalink / raw) To: linux-omap, tomi.valkeinen; +Cc: Mythri P K 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 <mythripk@ti.com> --- 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 <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <plat/display.h> #include <plat/board.h> #include <plat/common.h> @@ -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 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* RE: [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver. 2011-03-09 11:45 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Mythri P K 2011-03-09 11:45 ` [PATCH v4 8/9] OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 SDP Mythri P K @ 2011-03-09 15:54 ` Premi, Sanjeev 2011-03-10 5:24 ` K, Mythri P 1 sibling, 1 reply; 33+ messages in thread From: Premi, Sanjeev @ 2011-03-09 15:54 UTC (permalink / raw) To: K, Mythri P, linux-omap@vger.kernel.org, Valkeinen, Tomi > -----Original Message----- > From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- > owner@vger.kernel.org] On Behalf Of K, Mythri P > Sent: Wednesday, March 09, 2011 5:15 PM > To: linux-omap@vger.kernel.org; Valkeinen, Tomi > Cc: K, Mythri P > Subject: [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to > register driver. > > calling the platform registration of HDMI driver from core > during initialization. [sp] Contrary to the subject, patch adds calls for both init and uninit functions. Shouldn't this be included in same patch where init and uninit are being defined? [snip]...[snip] ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver. 2011-03-09 15:54 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Premi, Sanjeev @ 2011-03-10 5:24 ` K, Mythri P 0 siblings, 0 replies; 33+ messages in thread From: K, Mythri P @ 2011-03-10 5:24 UTC (permalink / raw) To: Premi, Sanjeev; +Cc: linux-omap@vger.kernel.org, Valkeinen, Tomi Hi Sanjeev, On Wed, Mar 9, 2011 at 9:24 PM, Premi, Sanjeev <premi@ti.com> wrote: >> -----Original Message----- >> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- >> owner@vger.kernel.org] On Behalf Of K, Mythri P >> Sent: Wednesday, March 09, 2011 5:15 PM >> To: linux-omap@vger.kernel.org; Valkeinen, Tomi >> Cc: K, Mythri P >> Subject: [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to >> register driver. >> >> calling the platform registration of HDMI driver from core >> during initialization. > > [sp] Contrary to the subject, patch adds calls for both init and uninit > functions. Subject says calling of the registration function. > > Shouldn't this be included in same patch where init and uninit are > being defined? Again i would prefer to keep the hdmi.c separate , do you see any issue in splitting ? I have made sure every patch compiles. > > [snip]...[snip] > Thanks and regards, Mythri. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-09 11:45 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel " Mythri P K 2011-03-09 11:45 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Mythri P K @ 2011-03-09 14:23 ` Tomi Valkeinen 2011-03-10 5:27 ` K, Mythri P 2011-03-10 7:52 ` Tomi Valkeinen 2 siblings, 1 reply; 33+ messages in thread From: Tomi Valkeinen @ 2011-03-09 14:23 UTC (permalink / raw) To: K, Mythri P; +Cc: linux-omap@vger.kernel.org On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: > 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 <mythripk@ti.com> > --- > drivers/video/omap2/dss/Kconfig | 8 + > drivers/video/omap2/dss/Makefile | 1 + > drivers/video/omap2/dss/hdmi_omap4_panel.c | 209 ++++++++++++++++++++++++++++ > 3 files changed, 218 insertions(+), 0 deletions(-) > create mode 100644 drivers/video/omap2/dss/hdmi_omap4_panel.c > > diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig > index 7749ddb..f66043f 100644 > --- a/drivers/video/omap2/dss/Kconfig > +++ b/drivers/video/omap2/dss/Kconfig > @@ -125,4 +125,12 @@ config OMAP2_DSS_MIN_FCK_PER_PCK > Max FCK is 173MHz, so this doesn't work if your PCK > is very high. > > +config OMAP4_PANEL_HDMI > + bool "HDMI panel support" > + depends on OMAP2_DSS_HDMI > + default n > + help > + HDMI panel. This adds the High Definition Multimedia panel. > + See http://www.hdmi.org/ for HDMI specification. > + > endif > diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile > index 5998b69..7ee4093 100644 > --- a/drivers/video/omap2/dss/Makefile > +++ b/drivers/video/omap2/dss/Makefile > @@ -6,3 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o > omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o > omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o > omapdss-$(CONFIG_OMAP2_DSS_HDMI) += hdmi.o > +omapdss-$(CONFIG_OMAP4_PANEL_HDMI) += hdmi_omap4_panel.o You don't need CONFIG_OMAP4_PANEL_HDMI. In fact, you cannot have it: hdmi.c calls the panel driver, so they must be compiled in or out together. Also, as they depend on each other, adding them in patches like this breaks compilation. Do it so that first add hdmi.c in a patch. Then hdmi_omap4_panel.c. After those, add Kconfig and Makefile changes. This way the kernel stays compilable, and you can still have the additions divided into separate patches. Tomi ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-09 14:23 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS Tomi Valkeinen @ 2011-03-10 5:27 ` K, Mythri P 0 siblings, 0 replies; 33+ messages in thread From: K, Mythri P @ 2011-03-10 5:27 UTC (permalink / raw) To: Tomi Valkeinen; +Cc: linux-omap@vger.kernel.org Hi Tomi, On Wed, Mar 9, 2011 at 7:53 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote: > On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: >> 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 <mythripk@ti.com> >> --- >> drivers/video/omap2/dss/Kconfig | 8 + >> drivers/video/omap2/dss/Makefile | 1 + >> drivers/video/omap2/dss/hdmi_omap4_panel.c | 209 ++++++++++++++++++++++++++++ >> 3 files changed, 218 insertions(+), 0 deletions(-) >> create mode 100644 drivers/video/omap2/dss/hdmi_omap4_panel.c >> >> diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig >> index 7749ddb..f66043f 100644 >> --- a/drivers/video/omap2/dss/Kconfig >> +++ b/drivers/video/omap2/dss/Kconfig >> @@ -125,4 +125,12 @@ config OMAP2_DSS_MIN_FCK_PER_PCK >> Max FCK is 173MHz, so this doesn't work if your PCK >> is very high. >> >> +config OMAP4_PANEL_HDMI >> + bool "HDMI panel support" >> + depends on OMAP2_DSS_HDMI >> + default n >> + help >> + HDMI panel. This adds the High Definition Multimedia panel. >> + See http://www.hdmi.org/ for HDMI specification. >> + >> endif >> diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile >> index 5998b69..7ee4093 100644 >> --- a/drivers/video/omap2/dss/Makefile >> +++ b/drivers/video/omap2/dss/Makefile >> @@ -6,3 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o >> omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o >> omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o >> omapdss-$(CONFIG_OMAP2_DSS_HDMI) += hdmi.o >> +omapdss-$(CONFIG_OMAP4_PANEL_HDMI) += hdmi_omap4_panel.o > > You don't need CONFIG_OMAP4_PANEL_HDMI. In fact, you cannot have it: > hdmi.c calls the panel driver, so they must be compiled in or out > together. > > Also, as they depend on each other, adding them in patches like this > breaks compilation. Do it so that first add hdmi.c in a patch. Then > hdmi_omap4_panel.c. After those, add Kconfig and Makefile changes. This > way the kernel stays compilable, and you can still have the additions > divided into separate patches. Sure i will do that. > > Tomi > Thanks and regards, Mythri. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-09 11:45 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel " Mythri P K 2011-03-09 11:45 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Mythri P K 2011-03-09 14:23 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS Tomi Valkeinen @ 2011-03-10 7:52 ` Tomi Valkeinen 2011-03-10 9:00 ` K, Mythri P 2 siblings, 1 reply; 33+ messages in thread From: Tomi Valkeinen @ 2011-03-10 7:52 UTC (permalink / raw) To: K, Mythri P; +Cc: linux-omap@vger.kernel.org On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: > 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 <mythripk@ti.com> <snip> > +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 1920 * 1080 > + * 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 = 1920; > + dssdev->panel.timings.y_res = 1080; This will cause the framebuffer to be initialized to 1920x1080, regardless of the timings the hdmi driver will select. I think you should either probe the display here to find what it supports, and initialize the size accordingly, or if the display is not connected, use some safe resolution most of the displays should support. VGA probably. And the timings selected here should also be used by the hdmi driver. What happens now with my monitor is that I get a fb of 1920x1028, but the hdmi driver doesn't like the modes my monitor gives via EDID, and falls back to VGA -> messed up display. Also, I'm getting "timeout waiting for EVSYNC" when I load or unload the driver. Tomi ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-10 7:52 ` Tomi Valkeinen @ 2011-03-10 9:00 ` K, Mythri P 2011-03-10 9:19 ` Tomi Valkeinen 0 siblings, 1 reply; 33+ messages in thread From: K, Mythri P @ 2011-03-10 9:00 UTC (permalink / raw) To: Tomi Valkeinen; +Cc: linux-omap@vger.kernel.org Hi Tomi, On Thu, Mar 10, 2011 at 1:22 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote: > On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: >> 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 <mythripk@ti.com> > > <snip> > >> +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 1920 * 1080 >> + * 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 = 1920; >> + dssdev->panel.timings.y_res = 1080; > > This will cause the framebuffer to be initialized to 1920x1080, > regardless of the timings the hdmi driver will select. I have set it to VGA , But anyways we need to fix FB to take the feedback from the driver for the timing , atleast when you disable the overlay set manager and enable it again. > > I think you should either probe the display here to find what it > supports, and initialize the size accordingly, or if the display is not > connected, use some safe resolution most of the displays should support. > VGA probably. > > And the timings selected here should also be used by the hdmi driver. > What happens now with my monitor is that I get a fb of 1920x1028, but > the hdmi driver doesn't like the modes my monitor gives via EDID, and > falls back to VGA -> messed up display. > > Also, I'm getting "timeout waiting for EVSYNC" when I load or unload the > driver. > This is ok, I have not seen any issue because of this warning, Also we need to understand the rationale as to why the wait_timeout was added in the code "dispc_enable_digit_out", It seems more like a hack, and not necessarily needed? > Tomi > > > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-10 9:00 ` K, Mythri P @ 2011-03-10 9:19 ` Tomi Valkeinen 2011-03-10 9:33 ` K, Mythri P 0 siblings, 1 reply; 33+ messages in thread From: Tomi Valkeinen @ 2011-03-10 9:19 UTC (permalink / raw) To: K, Mythri P; +Cc: linux-omap@vger.kernel.org On Thu, 2011-03-10 at 03:00 -0600, K, Mythri P wrote: > Hi Tomi, > > On Thu, Mar 10, 2011 at 1:22 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote: > > On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: > >> 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 <mythripk@ti.com> > > > > <snip> > > > >> +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 1920 * 1080 > >> + * 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 = 1920; > >> + dssdev->panel.timings.y_res = 1080; > > > > This will cause the framebuffer to be initialized to 1920x1080, > > regardless of the timings the hdmi driver will select. > > I have set it to VGA , But anyways we need to fix FB to take the > feedback from the driver > for the timing , atleast when you disable the overlay set manager and > enable it again. No, the FB cannot do anything with that information. FB driver can't change the resolution by itself. It has to happen on some upper level, in the user space. The only case when the FB can select the resolution is when the driver is loading. At that point nobody is using the framebuffer, as it didn't even exist earlier. That's why I suggested reading the EDID in the probe. > > I think you should either probe the display here to find what it > > supports, and initialize the size accordingly, or if the display is not > > connected, use some safe resolution most of the displays should support. > > VGA probably. > > > > And the timings selected here should also be used by the hdmi driver. > > What happens now with my monitor is that I get a fb of 1920x1028, but > > the hdmi driver doesn't like the modes my monitor gives via EDID, and > > falls back to VGA -> messed up display. > > > > Also, I'm getting "timeout waiting for EVSYNC" when I load or unload the > > driver. > > > This is ok, I have not seen any issue because of this warning, It's an error, it's not ok =). > Also we need to understand the rationale as to why the wait_timeout was added > in the code "dispc_enable_digit_out", It seems more like a hack, and > not necessarily needed? When disabling, the point is to wait until the DISPC has really turned off the output. For VENC this needed waiting for EVSYNC_EVEN and ODD. I don't remember why the same code is ran when enabling. HDMI may work differently, so it is possible that the function needs to be fixed. But I wonder why it gives timeouts when enabling HDMI also... Shouldn't the EVSYNCs happen with HDMI too? We can look at that later, presuming the timeout doesn't cause any problems. Tomi ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-10 9:19 ` Tomi Valkeinen @ 2011-03-10 9:33 ` K, Mythri P 2011-03-10 9:39 ` Hiremath, Vaibhav 2011-03-10 9:49 ` Tomi Valkeinen 0 siblings, 2 replies; 33+ messages in thread From: K, Mythri P @ 2011-03-10 9:33 UTC (permalink / raw) To: Tomi Valkeinen; +Cc: linux-omap@vger.kernel.org Hi Tomi, On Thu, Mar 10, 2011 at 2:49 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote: > On Thu, 2011-03-10 at 03:00 -0600, K, Mythri P wrote: >> Hi Tomi, >> >> On Thu, Mar 10, 2011 at 1:22 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote: >> > On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: >> >> 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 <mythripk@ti.com> >> > >> > <snip> >> > >> >> +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 1920 * 1080 >> >> + * 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 = 1920; >> >> + dssdev->panel.timings.y_res = 1080; >> > >> > This will cause the framebuffer to be initialized to 1920x1080, >> > regardless of the timings the hdmi driver will select. >> >> I have set it to VGA , But anyways we need to fix FB to take the >> feedback from the driver >> for the timing , atleast when you disable the overlay set manager and >> enable it again. > > No, the FB cannot do anything with that information. FB driver can't > change the resolution by itself. It has to happen on some upper level, > in the user space. > > The only case when the FB can select the resolution is when the driver > is loading. At that point nobody is using the framebuffer, as it didn't > even exist earlier. That's why I suggested reading the EDID in the > probe. Reading the EDID during probe is not feasible , 1. To read EDID we have to enable clocks and configure HDMI , which may not be intended - as probe does not mean that the user would want to enable HDMI. 2. If HDMI is not connected at boot up , but the cable is plugged in later on we will run into issues. There are mechanisms in v4l2 to reconfigure the overlay size and its own parameters , Even if a notification is sent there is no mechanism today in FB to do it. What happens if FB is switched from one manager to other with resolution ? There is not neat way to do it today, So i think a more reasonable way is to find a way to atleast let the user space change the virtual size of FB dynamically given there is enough VRAM allocated. > >> > I think you should either probe the display here to find what it >> > supports, and initialize the size accordingly, or if the display is not >> > connected, use some safe resolution most of the displays should support. >> > VGA probably. >> > >> > And the timings selected here should also be used by the hdmi driver. >> > What happens now with my monitor is that I get a fb of 1920x1028, but >> > the hdmi driver doesn't like the modes my monitor gives via EDID, and >> > falls back to VGA -> messed up display. >> > >> > Also, I'm getting "timeout waiting for EVSYNC" when I load or unload the >> > driver. >> > >> This is ok, I have not seen any issue because of this warning, > > It's an error, it's not ok =). > >> Also we need to understand the rationale as to why the wait_timeout was added >> in the code "dispc_enable_digit_out", It seems more like a hack, and >> not necessarily needed? > > When disabling, the point is to wait until the DISPC has really turned > off the output. For VENC this needed waiting for EVSYNC_EVEN and ODD. I > don't remember why the same code is ran when enabling. > > HDMI may work differently, so it is possible that the function needs to > be fixed. But I wonder why it gives timeouts when enabling HDMI also... > Shouldn't the EVSYNCs happen with HDMI too? > > We can look at that later, presuming the timeout doesn't cause any > problems. > HDMI is not dependent on the EVSYNC_ODD , but on EVSYNC EVEN, it has never needed to wait and has not caused any issue for last 8-10 months it is being used :). Why the same function was used ? Because it is a generic digit_out function to do a TVENABLE. > Tomi > > > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* RE: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-10 9:33 ` K, Mythri P @ 2011-03-10 9:39 ` Hiremath, Vaibhav 2011-03-10 9:47 ` K, Mythri P 2011-03-10 9:49 ` Tomi Valkeinen 1 sibling, 1 reply; 33+ messages in thread From: Hiremath, Vaibhav @ 2011-03-10 9:39 UTC (permalink / raw) To: K, Mythri P, Valkeinen, Tomi; +Cc: linux-omap@vger.kernel.org > -----Original Message----- > From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- > owner@vger.kernel.org] On Behalf Of K, Mythri P > Sent: Thursday, March 10, 2011 3:03 PM > To: Valkeinen, Tomi > Cc: linux-omap@vger.kernel.org > Subject: Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver > addition in the DSS > > Hi Tomi, > > On Thu, Mar 10, 2011 at 2:49 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> > wrote: > > On Thu, 2011-03-10 at 03:00 -0600, K, Mythri P wrote: > >> Hi Tomi, > >> > >> On Thu, Mar 10, 2011 at 1:22 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> > wrote: > >> > On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: > >> >> 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 <mythripk@ti.com> > >> > > >> > <snip> > >> > <snip> > >> > >> I have set it to VGA , But anyways we need to fix FB to take the > >> feedback from the driver > >> for the timing , atleast when you disable the overlay set manager and > >> enable it again. > > > > No, the FB cannot do anything with that information. FB driver can't > > change the resolution by itself. It has to happen on some upper level, > > in the user space. > > > > The only case when the FB can select the resolution is when the driver > > is loading. At that point nobody is using the framebuffer, as it didn't > > even exist earlier. That's why I suggested reading the EDID in the > > probe. > > Reading the EDID during probe is not feasible , > 1. To read EDID we have to enable clocks and configure HDMI , which > may not be intended - as probe does not mean > that the user would want to enable HDMI. > 2. If HDMI is not connected at boot up , but the cable is plugged in > later on we will run into issues. > There are mechanisms in v4l2 to reconfigure the overlay size and its > own parameters , Even if a notification is sent there is no > mechanism today in FB to do it. > What happens if FB is switched from one manager to other with > resolution ? [Hiremath, Vaibhav] Isn't we get interrupt on HDMI connection back to CPU? > There is not neat way to do it today, So i think a more reasonable way > is to find a way to atleast > let the user space change the virtual size of FB dynamically given > there is enough VRAM allocated. > [Hiremath, Vaibhav] I think let default VRAM allocation be minimal and let user configure omapfb.vram using bootargs (or IOCTL) based on his requirement. Thanks, Vaibhav > > > > >> > I think you should either probe the display here to find what it > >> > supports, and initialize the size accordingly, or if the display is > not > >> > connected, use some safe resolution most of the displays should > support. > >> > VGA probably. > >> > > >> > And the timings selected here should also be used by the hdmi driver. > >> > What happens now with my monitor is that I get a fb of 1920x1028, but > >> > the hdmi driver doesn't like the modes my monitor gives via EDID, and > >> > falls back to VGA -> messed up display. > >> > > >> > Also, I'm getting "timeout waiting for EVSYNC" when I load or unload > the > >> > driver. > >> > > >> This is ok, I have not seen any issue because of this warning, > > > > It's an error, it's not ok =). > > > >> Also we need to understand the rationale as to why the wait_timeout was > added > >> in the code "dispc_enable_digit_out", It seems more like a hack, and > >> not necessarily needed? > > > > When disabling, the point is to wait until the DISPC has really turned > > off the output. For VENC this needed waiting for EVSYNC_EVEN and ODD. I > > don't remember why the same code is ran when enabling. > > > > HDMI may work differently, so it is possible that the function needs to > > be fixed. But I wonder why it gives timeouts when enabling HDMI also... > > Shouldn't the EVSYNCs happen with HDMI too? > > > > We can look at that later, presuming the timeout doesn't cause any > > problems. > > > HDMI is not dependent on the EVSYNC_ODD , but on EVSYNC EVEN, > it has never needed to wait and has not caused any issue for last 8-10 > months it is being used :). > Why the same function was used ? Because it is a generic digit_out > function to do a TVENABLE. > > > Tomi > > > > > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-10 9:39 ` Hiremath, Vaibhav @ 2011-03-10 9:47 ` K, Mythri P 0 siblings, 0 replies; 33+ messages in thread From: K, Mythri P @ 2011-03-10 9:47 UTC (permalink / raw) To: Hiremath, Vaibhav; +Cc: Valkeinen, Tomi, linux-omap@vger.kernel.org Hi Vaibhav, On Thu, Mar 10, 2011 at 3:09 PM, Hiremath, Vaibhav <hvaibhav@ti.com> wrote: > >> -----Original Message----- >> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- >> owner@vger.kernel.org] On Behalf Of K, Mythri P >> Sent: Thursday, March 10, 2011 3:03 PM >> To: Valkeinen, Tomi >> Cc: linux-omap@vger.kernel.org >> Subject: Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver >> addition in the DSS >> >> Hi Tomi, >> >> On Thu, Mar 10, 2011 at 2:49 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> >> wrote: >> > On Thu, 2011-03-10 at 03:00 -0600, K, Mythri P wrote: >> >> Hi Tomi, >> >> >> >> On Thu, Mar 10, 2011 at 1:22 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> >> wrote: >> >> > On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: >> >> >> 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 <mythripk@ti.com> >> >> > >> >> > <snip> >> >> > > <snip> >> >> >> >> I have set it to VGA , But anyways we need to fix FB to take the >> >> feedback from the driver >> >> for the timing , atleast when you disable the overlay set manager and >> >> enable it again. >> > >> > No, the FB cannot do anything with that information. FB driver can't >> > change the resolution by itself. It has to happen on some upper level, >> > in the user space. >> > >> > The only case when the FB can select the resolution is when the driver >> > is loading. At that point nobody is using the framebuffer, as it didn't >> > even exist earlier. That's why I suggested reading the EDID in the >> > probe. >> >> Reading the EDID during probe is not feasible , >> 1. To read EDID we have to enable clocks and configure HDMI , which >> may not be intended - as probe does not mean >> that the user would want to enable HDMI. >> 2. If HDMI is not connected at boot up , but the cable is plugged in >> later on we will run into issues. >> There are mechanisms in v4l2 to reconfigure the overlay size and its >> own parameters , Even if a notification is sent there is no >> mechanism today in FB to do it. >> What happens if FB is switched from one manager to other with >> resolution ? > [Hiremath, Vaibhav] Isn't we get interrupt on HDMI connection back to CPU? > >> There is not neat way to do it today, So i think a more reasonable way >> is to find a way to atleast >> let the user space change the virtual size of FB dynamically given >> there is enough VRAM allocated. >> > [Hiremath, Vaibhav] I think let default VRAM allocation be minimal and let user configure omapfb.vram using bootargs (or IOCTL) based on his requirement. > yes I agree , so as Tomi also suggested i'm now setting it to VGA FB , But it would be nice to have a sysfs to do the same, ie FB should be able to look for the resolution of the driver it is connected to and realloc if enough memory is present else default to original , if there is a change in the manager. Just a nice to have intelligence i would think. Thanks and regards, Mythri. > Thanks, > Vaibhav > >> >> > >> >> > I think you should either probe the display here to find what it >> >> > supports, and initialize the size accordingly, or if the display is >> not >> >> > connected, use some safe resolution most of the displays should >> support. >> >> > VGA probably. >> >> > >> >> > And the timings selected here should also be used by the hdmi driver. >> >> > What happens now with my monitor is that I get a fb of 1920x1028, but >> >> > the hdmi driver doesn't like the modes my monitor gives via EDID, and >> >> > falls back to VGA -> messed up display. >> >> > >> >> > Also, I'm getting "timeout waiting for EVSYNC" when I load or unload >> the >> >> > driver. >> >> > >> >> This is ok, I have not seen any issue because of this warning, >> > >> > It's an error, it's not ok =). >> > >> >> Also we need to understand the rationale as to why the wait_timeout was >> added >> >> in the code "dispc_enable_digit_out", It seems more like a hack, and >> >> not necessarily needed? >> > >> > When disabling, the point is to wait until the DISPC has really turned >> > off the output. For VENC this needed waiting for EVSYNC_EVEN and ODD. I >> > don't remember why the same code is ran when enabling. >> > >> > HDMI may work differently, so it is possible that the function needs to >> > be fixed. But I wonder why it gives timeouts when enabling HDMI also... >> > Shouldn't the EVSYNCs happen with HDMI too? >> > >> > We can look at that later, presuming the timeout doesn't cause any >> > problems. >> > >> HDMI is not dependent on the EVSYNC_ODD , but on EVSYNC EVEN, >> it has never needed to wait and has not caused any issue for last 8-10 >> months it is being used :). >> Why the same function was used ? Because it is a generic digit_out >> function to do a TVENABLE. >> >> > Tomi >> > >> > >> > >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-omap" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS 2011-03-10 9:33 ` K, Mythri P 2011-03-10 9:39 ` Hiremath, Vaibhav @ 2011-03-10 9:49 ` Tomi Valkeinen 1 sibling, 0 replies; 33+ messages in thread From: Tomi Valkeinen @ 2011-03-10 9:49 UTC (permalink / raw) To: K, Mythri P; +Cc: linux-omap@vger.kernel.org On Thu, 2011-03-10 at 03:33 -0600, K, Mythri P wrote: > Hi Tomi, > > On Thu, Mar 10, 2011 at 2:49 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote: > > On Thu, 2011-03-10 at 03:00 -0600, K, Mythri P wrote: > >> Hi Tomi, > >> > >> On Thu, Mar 10, 2011 at 1:22 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote: > >> > On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: > >> >> 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 <mythripk@ti.com> > >> > > >> > <snip> > >> > > >> >> +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 1920 * 1080 > >> >> + * 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 = 1920; > >> >> + dssdev->panel.timings.y_res = 1080; > >> > > >> > This will cause the framebuffer to be initialized to 1920x1080, > >> > regardless of the timings the hdmi driver will select. > >> > >> I have set it to VGA , But anyways we need to fix FB to take the > >> feedback from the driver > >> for the timing , atleast when you disable the overlay set manager and > >> enable it again. > > > > No, the FB cannot do anything with that information. FB driver can't > > change the resolution by itself. It has to happen on some upper level, > > in the user space. > > > > The only case when the FB can select the resolution is when the driver > > is loading. At that point nobody is using the framebuffer, as it didn't > > even exist earlier. That's why I suggested reading the EDID in the > > probe. > > Reading the EDID during probe is not feasible , > 1. To read EDID we have to enable clocks and configure HDMI , which > may not be intended - as probe does not mean > that the user would want to enable HDMI. Well, the function is called "probe" for a purpose =). It can probe the HW to find out what's there. I believe that for reading the EDID we don't need DISPC at all, but just a small subset of the HDMI hardware? > 2. If HDMI is not connected at boot up , but the cable is plugged in > later on we will run into issues. Not any more than currently, when we don't read EDID in the probe. Probing would just allow the driver to setup sane default if the monitor is connected when the driver is loaded. If we have the user space properly handling hotplugs etc, this probe is of course extra. But it wouldn't do any harm in that case either, would it? > There are mechanisms in v4l2 to reconfigure the overlay size and its > own parameters , Even if a notification is sent there is no I'm not familiar with v4l2, it may be possible there. But it doesn't mean it's possible in the framebuffer. > mechanism today in FB to do it. > What happens if FB is switched from one manager to other with resolution ? > There is not neat way to do it today, So i think a more reasonable way > is to find a way to atleast > let the user space change the virtual size of FB dynamically given > there is enough VRAM allocated. The userspace can do all the configuration it wants, sure. And that's how it should work. But the FB driver itself cannot do this. Well, to be exact, it could in some cases, but not always. If the framebuffer memory is ioremapped, the fb cannot go and change it. And even if it's not ioremapped, changing the fb resolution independently would easily mess up applications. They won't be expecting the fb to change suddenly when they are using it. > >> > I think you should either probe the display here to find what it > >> > supports, and initialize the size accordingly, or if the display is not > >> > connected, use some safe resolution most of the displays should support. > >> > VGA probably. > >> > > >> > And the timings selected here should also be used by the hdmi driver. > >> > What happens now with my monitor is that I get a fb of 1920x1028, but > >> > the hdmi driver doesn't like the modes my monitor gives via EDID, and > >> > falls back to VGA -> messed up display. > >> > > >> > Also, I'm getting "timeout waiting for EVSYNC" when I load or unload the > >> > driver. > >> > > >> This is ok, I have not seen any issue because of this warning, > > > > It's an error, it's not ok =). > > > >> Also we need to understand the rationale as to why the wait_timeout was added > >> in the code "dispc_enable_digit_out", It seems more like a hack, and > >> not necessarily needed? > > > > When disabling, the point is to wait until the DISPC has really turned > > off the output. For VENC this needed waiting for EVSYNC_EVEN and ODD. I > > don't remember why the same code is ran when enabling. > > > > HDMI may work differently, so it is possible that the function needs to > > be fixed. But I wonder why it gives timeouts when enabling HDMI also... > > Shouldn't the EVSYNCs happen with HDMI too? > > > > We can look at that later, presuming the timeout doesn't cause any > > problems. > > > HDMI is not dependent on the EVSYNC_ODD , but on EVSYNC EVEN, What do you mean dependent? When HDMI is enabled, we only get EVSYNC_EVENs? Even when using interlace mode? > it has never needed to wait and has not caused any issue for last 8-10 > months it is being used :). That doesn't mean it's not needed. VENC worked fine without the wait for years. Until it didn't, after some PM work if I recall right. Both VENC and LCD outputs need to wait until DISPC has really finished with the output, before disabling the clocks. At least on OMAP3. HDMI may be different, but I find it a bit difficult to believe, as the same digit output is used for both HDMI and VENC. Tomi ^ permalink raw reply [flat|nested] 33+ messages in thread
* RE: [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS 2011-03-09 11:45 ` [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS Mythri P K 2011-03-09 11:45 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel " Mythri P K @ 2011-03-09 15:50 ` Premi, Sanjeev 2011-03-10 5:22 ` K, Mythri P 1 sibling, 1 reply; 33+ messages in thread From: Premi, Sanjeev @ 2011-03-09 15:50 UTC (permalink / raw) To: K, Mythri P, linux-omap@vger.kernel.org, Valkeinen, Tomi > -----Original Message----- > From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- > owner@vger.kernel.org] On Behalf Of K, Mythri P > Sent: Wednesday, March 09, 2011 5:15 PM > To: linux-omap@vger.kernel.org; Valkeinen, Tomi > Cc: K, Mythri P > Subject: [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the > DSS > > 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 <mythripk@ti.com> > Yong Zhi <y-zhi@ti.com> > --- > drivers/video/omap2/dss/Kconfig | 8 + > drivers/video/omap2/dss/Makefile | 1 + > drivers/video/omap2/dss/display.c | 3 + > drivers/video/omap2/dss/dss.h | 43 ++ > drivers/video/omap2/dss/hdmi.c | 1315 > +++++++++++++++++++++++++++++++++++++ > 5 files changed, 1370 insertions(+), 0 deletions(-) > create mode 100644 drivers/video/omap2/dss/hdmi.c > > diff --git a/drivers/video/omap2/dss/Kconfig > b/drivers/video/omap2/dss/Kconfig > index db01473..7749ddb 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 OMAP2_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. > + [sp] This may have been discussed earlier... but if the interface is supported only on OMAP4, wouldn't it be better to rename OMAP2_DSS_HDMI as OMAP4_DSS_HDMI? Or, the implementation can be used by OMAP3 as well. If so, you may want to update the depends. > 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..5998b69 100644 > --- a/drivers/video/omap2/dss/Makefile > +++ b/drivers/video/omap2/dss/Makefile > @@ -5,3 +5,4 @@ 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_OMAP2_DSS_HDMI) += hdmi.o > 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 008cbf4..3eb2661 100644 > --- a/drivers/video/omap2/dss/dss.h > +++ b/drivers/video/omap2/dss/dss.h > @@ -174,6 +174,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; > > @@ -437,6 +447,39 @@ static inline void venc_uninit_platform_driver(void) > } > #endif > > +/* HDMI */ > +#ifdef CONFIG_OMAP2_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); > +#ifdef CONFIG_OMAP4_PANEL_HDMI > +int hdmi_panel_init(void); > +void hdmi_panel_exit(void); > +#else > +static inline int hdmi_panel_init(void) > +{ > + return 0; > +} > +static inline void hdmi_panel_exit(void) > +{ > +} > +#endif > + > /* 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..6852843 > --- /dev/null > +++ b/drivers/video/omap2/dss/hdmi.c > @@ -0,0 +1,1315 @@ > +/* > + * 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 <mythripk@ti.com> > + * > + * [sp] Extra blank lines here > + * 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 <http://www.gnu.org/licenses/>. > + */ > + > +#define DSS_SUBSYS_NAME "HDMI" > + > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/err.h> > +#include <linux/io.h> > +#include <linux/interrupt.h> > +#include <linux/mutex.h> > +#include <linux/delay.h> > +#include <linux/string.h> > +#include <plat/display.h> > + > +#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; > + struct hdmi_config cfg; > +} hdmi; > + > +/* > + * Logic for the below structure > + * user enters the CEA or VESA timings by specifying > + * the hdmicode which corresponds to CEA/VESA timings > + * please refer to section 6.3 in HDMI 1.3 specification for timing code. > + * There is a correspondence between CEA/VESA timing and code. > + * In the below structure, cea_vesa_timings corresponds to all > + * The OMAP4 supported timing CEA and VESA timing values. > + * code_cea corresponds to the CEA code entered by the user, > + * The use of it is to get the timing from the cea_vesa_timing array. > + * Similarly for code_vesa. > + * code_index is backmapping, Once EDID is read from the TV > + * EDID is parsed to find the timing values to map it back to the > + * corresponding CEA or VESA index this structure is used. > + */ [sp] Is the comment intentionally formatted as it is? There seems to be an opportunity to improve the text and readability here. > + > +/* > + * This is the structure which has all supported timing > + * values that OMAP4 supports > + */ [sp] Seems to be repeat of the comment just above. > +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); > +} [sp] Suggestion - reg.idx reads better than idx.idx esp since the argument type is "struct hdmi_reg". > + > +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; [sp] Just wanted to confirm that "!val" is really safe to return from here. > + } > + 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 -ENODEV; [sp] Is -ENODEV appropriate. Going by error message, function seems to be setting the power mode? > + } > + > + 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 -ENODEV; [sp] same comment here. > + } > + > + 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; [sp] When we return from here, HDMI_PHYPWRCMD_LDOON was successful. Is it okay to leave the state as is? > + > + /* > + * 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); [sp] Is this known behavior/feature - or a workaround? > + > + /* > + * 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); [sp] Can REG_FLD_MOD be used here as well? - comment suggests only 2 fields being updated. > + > + /* 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 -ENODEV; [sp] Is -ENODEV appropriate? > + } > + > + return 0; > +} > + > +static int hdmi_pll_program(struct hdmi_pll_info *fmt) > +{ > + u16 r = 0; > + enum hdmi_clk_refsel refsel; > + > + /* wait for wrapper reset */ > + hdmi_wait_softreset(); [sp] Return value isn;t being checked here. If -ENODEV was returned, is it safe to move ahead? > + > + 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; > + > + hdmi_pll_reset(); [sp] Return value is again ignored here. This function can return -ETIMEDOUT. Is it okay to ignore it? > + > + refsel = HDMI_REFSEL_SYSCLK; > + > + r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); > + if (r) > + return r; [sp] When we return from this error location, much of clock and power config seems to have been done. Can we leave them in same state? > + > + 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) [sp] Variable pEDID seems bit different. Suggest using lowercase for it. > +{ > + 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 No timer needed */ [sp] What is significance of "No timer needed"? > + 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); > + > + /* > + * Do not optimize this part of the code, seems > + * DDC bus needs some time to get stabilized > + */ > + > + /* 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; > + } > + [sp] Is -EIO appropriate error here? > + 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 -EIO; [sp] Same query on -EIO here. > + } 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 > + */ [sp] Shouldn't this info go to the function header instead? > + [sp] extra line > + 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 -EIO; > + } > + } > + 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) { > + code = 9; > + /* HDMI code 16 corresponds to 1920 * 1080 */ > + hdmi.code = 16; > + /* HDMI mode 1 corresponds to HDMI 0 to DVI */ > + hdmi.mode = HDMI_HDMI; > + } > + 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 > */ [sp] Suggest using kernel documentation style. > +static void get_edid_timing_data(u8 *edid) [sp] Contrast use of *edid vs *pEDID few functions above. > +{ > + 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 int 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 != 0) { [sp] Shouldn't we check for success case first? > + DSSWARN("failed to read E-EDID\n"); > + } else { > + 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; > + } > + } > + > + 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; > + > + return 0; [sp] Function will always return 0. Shouldn't it be void? > +} > + > +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 2^18(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); > + > + DSSDBG("Read EDID as no EDID is not set on poweron\n"); > + r = hdmi_read_edid(p); > + if (r) > + goto err; > + > + 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_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 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS 2011-03-09 15:50 ` [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI " Premi, Sanjeev @ 2011-03-10 5:22 ` K, Mythri P 2011-03-10 7:57 ` Tomi Valkeinen 0 siblings, 1 reply; 33+ messages in thread From: K, Mythri P @ 2011-03-10 5:22 UTC (permalink / raw) To: Premi, Sanjeev; +Cc: linux-omap@vger.kernel.org, Valkeinen, Tomi Hi Sanjeev, On Wed, Mar 9, 2011 at 9:20 PM, Premi, Sanjeev <premi@ti.com> wrote: >> -----Original Message----- >> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- >> owner@vger.kernel.org] On Behalf Of K, Mythri P >> Sent: Wednesday, March 09, 2011 5:15 PM >> To: linux-omap@vger.kernel.org; Valkeinen, Tomi >> Cc: K, Mythri P >> Subject: [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the >> DSS >> >> 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 <mythripk@ti.com> >> Yong Zhi <y-zhi@ti.com> >> --- >> drivers/video/omap2/dss/Kconfig | 8 + >> drivers/video/omap2/dss/Makefile | 1 + >> drivers/video/omap2/dss/display.c | 3 + >> drivers/video/omap2/dss/dss.h | 43 ++ >> drivers/video/omap2/dss/hdmi.c | 1315 >> +++++++++++++++++++++++++++++++++++++ >> 5 files changed, 1370 insertions(+), 0 deletions(-) >> create mode 100644 drivers/video/omap2/dss/hdmi.c >> >> diff --git a/drivers/video/omap2/dss/Kconfig >> b/drivers/video/omap2/dss/Kconfig >> index db01473..7749ddb 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 OMAP2_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. >> + > [sp] This may have been discussed earlier... but if the interface is > supported only on OMAP4, wouldn't it be better to rename > OMAP2_DSS_HDMI as OMAP4_DSS_HDMI? > Or, the implementation can be used by OMAP3 as well. If so, you > may want to update the depends. I shall change it to OMAP4. > >> 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..5998b69 100644 >> --- a/drivers/video/omap2/dss/Makefile >> +++ b/drivers/video/omap2/dss/Makefile >> @@ -5,3 +5,4 @@ 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_OMAP2_DSS_HDMI) += hdmi.o >> 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 008cbf4..3eb2661 100644 >> --- a/drivers/video/omap2/dss/dss.h >> +++ b/drivers/video/omap2/dss/dss.h >> @@ -174,6 +174,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; >> >> @@ -437,6 +447,39 @@ static inline void venc_uninit_platform_driver(void) >> } >> #endif >> >> +/* HDMI */ >> +#ifdef CONFIG_OMAP2_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); >> +#ifdef CONFIG_OMAP4_PANEL_HDMI >> +int hdmi_panel_init(void); >> +void hdmi_panel_exit(void); >> +#else >> +static inline int hdmi_panel_init(void) >> +{ >> + return 0; >> +} >> +static inline void hdmi_panel_exit(void) >> +{ >> +} >> +#endif >> + >> /* 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..6852843 >> --- /dev/null >> +++ b/drivers/video/omap2/dss/hdmi.c >> @@ -0,0 +1,1315 @@ >> +/* >> + * 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 <mythripk@ti.com> >> + * >> + * > > [sp] Extra blank lines here > >> + * 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 <http://www.gnu.org/licenses/>. >> + */ >> + >> +#define DSS_SUBSYS_NAME "HDMI" >> + >> +#include <linux/kernel.h> >> +#include <linux/module.h> >> +#include <linux/err.h> >> +#include <linux/io.h> >> +#include <linux/interrupt.h> >> +#include <linux/mutex.h> >> +#include <linux/delay.h> >> +#include <linux/string.h> >> +#include <plat/display.h> >> + >> +#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; >> + struct hdmi_config cfg; >> +} hdmi; >> + >> +/* >> + * Logic for the below structure >> + * user enters the CEA or VESA timings by specifying >> + * the hdmicode which corresponds to CEA/VESA timings >> + * please refer to section 6.3 in HDMI 1.3 specification for timing code. >> + * There is a correspondence between CEA/VESA timing and code. >> + * In the below structure, cea_vesa_timings corresponds to all >> + * The OMAP4 supported timing CEA and VESA timing values. >> + * code_cea corresponds to the CEA code entered by the user, >> + * The use of it is to get the timing from the cea_vesa_timing array. >> + * Similarly for code_vesa. >> + * code_index is backmapping, Once EDID is read from the TV >> + * EDID is parsed to find the timing values to map it back to the >> + * corresponding CEA or VESA index this structure is used. >> + */ > > [sp] Is the comment intentionally formatted as it is? > There seems to be an opportunity to improve the text and > readability here. > I shall try to indent. >> + >> +/* >> + * This is the structure which has all supported timing >> + * values that OMAP4 supports >> + */ > > [sp] Seems to be repeat of the comment just above. > >> +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); >> +} > > [sp] Suggestion - reg.idx reads better than idx.idx esp since the argument > type is "struct hdmi_reg".\ I have named it similar to other DSS register read functions. > >> + >> +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; > > [sp] Just wanted to confirm that "!val" is really safe to return from here. yes , again similar to other DSS function. > >> + } >> + 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 -ENODEV; > > [sp] Is -ENODEV appropriate. Going by error message, function seems to be > setting the power mode? yes , but as we are waiting on device to set the status, probably i can set a TIMEDOUT. > >> + } >> + >> + 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 -ENODEV; > > [sp] same comment here. > >> + } >> + >> + 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; > > [sp] When we return from here, HDMI_PHYPWRCMD_LDOON was > successful. Is it okay to leave the state as is? yes > >> + >> + /* >> + * 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); > > [sp] Is this known behavior/feature - or a workaround? It is a known behavior. > >> + >> + /* >> + * 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); > > [sp] Can REG_FLD_MOD be used here as well? - comment suggests only > 2 fields being updated. It is used to configure TXVALID and TMDSCLKEN .2 other bits to say use the configured value. > >> + >> + /* 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 -ENODEV; > > [sp] Is -ENODEV appropriate? Will replace with TIMEDOUT. > >> + } >> + >> + return 0; >> +} >> + >> +static int hdmi_pll_program(struct hdmi_pll_info *fmt) >> +{ >> + u16 r = 0; >> + enum hdmi_clk_refsel refsel; >> + >> + /* wait for wrapper reset */ >> + hdmi_wait_softreset(); > > [sp] Return value isn;t being checked here. If -ENODEV was returned, > is it safe to move ahead? > >> + >> + 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; >> + >> + hdmi_pll_reset(); > > [sp] Return value is again ignored here. This function can return > -ETIMEDOUT. Is it okay to ignore it? > >> + >> + refsel = HDMI_REFSEL_SYSCLK; >> + >> + r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); >> + if (r) >> + return r; > > [sp] When we return from this error location, much of clock and > power config seems to have been done. Can we leave them in > same state? yes , because on error we would anyway be cutting clocks , and that would be over written while configuring next. > >> + >> + 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) > > [sp] Variable pEDID seems bit different. Suggest using lowercase for it. > >> +{ >> + 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 No timer needed */ > > [sp] What is significance of "No timer needed"? > >> + 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); >> + >> + /* >> + * Do not optimize this part of the code, seems >> + * DDC bus needs some time to get stabilized >> + */ >> + >> + /* 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; >> + } >> + > [sp] Is -EIO appropriate error here? I2c is not responding , so i think EIO would be appropriate, Do you have any other suggestions? > >> + 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 -EIO; > > [sp] Same query on -EIO here. Again it is because of i2c fail , so I think EIO is appropriate. > >> + } 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 >> + */ > [sp] Shouldn't this info go to the function header instead? It is for the parameter passed , so i added it while checking for the parameter. > >> + > [sp] extra line >> + 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 -EIO; >> + } >> + } >> + 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) { >> + code = 9; >> + /* HDMI code 16 corresponds to 1920 * 1080 */ >> + hdmi.code = 16; >> + /* HDMI mode 1 corresponds to HDMI 0 to DVI */ >> + hdmi.mode = HDMI_HDMI; >> + } >> + 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 >> */ > [sp] Suggest using kernel documentation style. > >> +static void get_edid_timing_data(u8 *edid) > > [sp] Contrast use of *edid vs *pEDID few functions above. > >> +{ >> + 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 int 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 != 0) { > > [sp] Shouldn't we check for success case first? > >> + DSSWARN("failed to read E-EDID\n"); >> + } else { >> + 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; >> + } >> + } >> + >> + 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; >> + >> + return 0; > > [sp] Function will always return 0. Shouldn't it be void? will change to void. > Thanks and regards, Mythri. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS 2011-03-10 5:22 ` K, Mythri P @ 2011-03-10 7:57 ` Tomi Valkeinen 0 siblings, 0 replies; 33+ messages in thread From: Tomi Valkeinen @ 2011-03-10 7:57 UTC (permalink / raw) To: K, Mythri P; +Cc: Premi, Sanjeev, linux-omap@vger.kernel.org On Wed, 2011-03-09 at 23:22 -0600, K, Mythri P wrote: > Hi Sanjeev, > > On Wed, Mar 9, 2011 at 9:20 PM, Premi, Sanjeev <premi@ti.com> wrote: > >> -----Original Message----- > >> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- > >> owner@vger.kernel.org] On Behalf Of K, Mythri P > >> Sent: Wednesday, March 09, 2011 5:15 PM > >> To: linux-omap@vger.kernel.org; Valkeinen, Tomi > >> Cc: K, Mythri P > >> Subject: [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the > >> DSS <snip> > >> +/* > >> + * Logic for the below structure > >> + * user enters the CEA or VESA timings by specifying > >> + * the hdmicode which corresponds to CEA/VESA timings > >> + * please refer to section 6.3 in HDMI 1.3 specification for timing code. > >> + * There is a correspondence between CEA/VESA timing and code. > >> + * In the below structure, cea_vesa_timings corresponds to all > >> + * The OMAP4 supported timing CEA and VESA timing values. > >> + * code_cea corresponds to the CEA code entered by the user, > >> + * The use of it is to get the timing from the cea_vesa_timing array. > >> + * Similarly for code_vesa. > >> + * code_index is backmapping, Once EDID is read from the TV > >> + * EDID is parsed to find the timing values to map it back to the > >> + * corresponding CEA or VESA index this structure is used. > >> + */ > > > > [sp] Is the comment intentionally formatted as it is? > > There seems to be an opportunity to improve the text and > > readability here. > > > I shall try to indent. You can just select the whole comment and press "gw", that will arrange the comment nicely. Presuming you use vim. And everybody does, don't they? =) Tomi ^ permalink raw reply [flat|nested] 33+ messages in thread
* RE: [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition 2011-03-09 11:45 ` [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition Mythri P K 2011-03-09 11:45 ` [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS Mythri P K @ 2011-03-09 15:56 ` Premi, Sanjeev 2011-03-10 5:02 ` K, Mythri P 1 sibling, 1 reply; 33+ messages in thread From: Premi, Sanjeev @ 2011-03-09 15:56 UTC (permalink / raw) To: K, Mythri P, linux-omap@vger.kernel.org, Valkeinen, Tomi > -----Original Message----- > From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- > owner@vger.kernel.org] On Behalf Of K, Mythri P > Sent: Wednesday, March 09, 2011 5:15 PM > To: linux-omap@vger.kernel.org; Valkeinen, Tomi > Cc: K, Mythri P > Subject: [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file > addition > > Adding the hdmi interface driver header file (hdmi.h) to the dss driver. > Register and structure declaration done here. [sp] Any specific reason to keep header file in separate patch? > [snip]...[snip] ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition 2011-03-09 15:56 ` [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition Premi, Sanjeev @ 2011-03-10 5:02 ` K, Mythri P 2011-03-10 8:52 ` Premi, Sanjeev 0 siblings, 1 reply; 33+ messages in thread From: K, Mythri P @ 2011-03-10 5:02 UTC (permalink / raw) To: Premi, Sanjeev; +Cc: linux-omap@vger.kernel.org, Valkeinen, Tomi Hi Sanjeev, On Wed, Mar 9, 2011 at 9:26 PM, Premi, Sanjeev <premi@ti.com> wrote: >> -----Original Message----- >> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- >> owner@vger.kernel.org] On Behalf Of K, Mythri P >> Sent: Wednesday, March 09, 2011 5:15 PM >> To: linux-omap@vger.kernel.org; Valkeinen, Tomi >> Cc: K, Mythri P >> Subject: [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file >> addition >> >> Adding the hdmi interface driver header file (hdmi.h) to the dss driver. >> Register and structure declaration done here. > > [sp] Any specific reason to keep header file in separate patch? > When i had posted it earlier there were several compliants that the patch is huge, if i include header file with the corresponding c file , and hence difficult to review. So it just to make reviewers job easy. >> > [snip]...[snip] > Thanks and regards, Mythri. ^ permalink raw reply [flat|nested] 33+ messages in thread
* RE: [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition 2011-03-10 5:02 ` K, Mythri P @ 2011-03-10 8:52 ` Premi, Sanjeev 2011-03-10 9:07 ` Tomi Valkeinen 0 siblings, 1 reply; 33+ messages in thread From: Premi, Sanjeev @ 2011-03-10 8:52 UTC (permalink / raw) To: K, Mythri P; +Cc: linux-omap@vger.kernel.org, Valkeinen, Tomi > -----Original Message----- > From: K, Mythri P > Sent: Thursday, March 10, 2011 10:32 AM > To: Premi, Sanjeev > Cc: linux-omap@vger.kernel.org; Valkeinen, Tomi > Subject: Re: [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file > addition > [snip]...[snip] > > > > [sp] Any specific reason to keep header file in separate patch? > > > When i had posted it earlier there were several compliants that the > patch is huge, > if i include header file with the corresponding c file , and hence > difficult to review. So it just to make > reviewers job easy. [sp] Final say on the issue rests with the maintainer. But it I found it difficult to review the .c file with when looking for structure definitions, members etc. If they were together, we wouldn't need this in a separate patch: [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to... ~sanjeev ^ permalink raw reply [flat|nested] 33+ messages in thread
* RE: [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition 2011-03-10 8:52 ` Premi, Sanjeev @ 2011-03-10 9:07 ` Tomi Valkeinen 0 siblings, 0 replies; 33+ messages in thread From: Tomi Valkeinen @ 2011-03-10 9:07 UTC (permalink / raw) To: Premi, Sanjeev; +Cc: K, Mythri P, linux-omap@vger.kernel.org On Thu, 2011-03-10 at 02:52 -0600, Premi, Sanjeev wrote: > > -----Original Message----- > > From: K, Mythri P > > Sent: Thursday, March 10, 2011 10:32 AM > > To: Premi, Sanjeev > > Cc: linux-omap@vger.kernel.org; Valkeinen, Tomi > > Subject: Re: [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file > > addition > > > > [snip]...[snip] > > > > > > > [sp] Any specific reason to keep header file in separate patch? > > > > > When i had posted it earlier there were several compliants that the > > patch is huge, > > if i include header file with the corresponding c file , and hence > > difficult to review. So it just to make > > reviewers job easy. > > [sp] Final say on the issue rests with the maintainer. But it I found it > difficult to review the .c file with when looking for structure > definitions, members etc. > > If they were together, we wouldn't need this in a separate patch: > [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to... It's not a clear thing, but I find it easier to review the patches, if new large files are added as separate patches. But it's true that that introduces the need to do some cross checking between patches, so it's a compromise. Tomi ^ permalink raw reply [flat|nested] 33+ messages in thread
* RE: [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable. 2011-03-09 11:45 ` [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable Mythri P K 2011-03-09 11:45 ` [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition Mythri P K @ 2011-03-09 14:49 ` Premi, Sanjeev 2011-03-10 5:55 ` K, Mythri P 1 sibling, 1 reply; 33+ messages in thread From: Premi, Sanjeev @ 2011-03-09 14:49 UTC (permalink / raw) To: K, Mythri P, linux-omap@vger.kernel.org, Valkeinen, Tomi > -----Original Message----- > From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- > owner@vger.kernel.org] On Behalf Of K, Mythri P > Sent: Wednesday, March 09, 2011 5:15 PM > To: linux-omap@vger.kernel.org; Valkeinen, Tomi > Cc: K, Mythri P > Subject: [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table > disable. [sp] HDMI seems repetitive in the subject in this and some of the subsequent Patches. > > Adding changes to set gamma table bit for TV interface to make sure it is > disabled [sp] Is this bit expected to be "enabled" by default? If no, how can/would this bit get enabled. The subject and description of the patch doesn't match the contents. The patch is adding a function that can *both* enable/disable gamma table - not just disable. > > Signed-off-by: Mythri P K <mythripk@ti.com> > --- > drivers/video/omap2/dss/dispc.c | 10 ++++++++++ > drivers/video/omap2/dss/dss.h | 1 + > 2 files changed, 11 insertions(+), 0 deletions(-) > > diff --git a/drivers/video/omap2/dss/dispc.c > b/drivers/video/omap2/dss/dispc.c > index 4a368c4..0defe16 100644 > --- a/drivers/video/omap2/dss/dispc.c > +++ b/drivers/video/omap2/dss/dispc.c > @@ -1008,6 +1008,16 @@ 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. > + */ > + BUG_ON(enable); [sp] Is BUG_ON really needed. Can't this be a WARN or equiv? > + > + REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); [sp] I don't understand HDMI much, but if enabling gamma causes BUG_ON, then why would we need implementation to disable it. Instead, shouldn't the function be empty - if it can't be avoided altogether? > +} > + > 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 29f31fd..008cbf4 100644 > --- a/drivers/video/omap2/dss/dss.h > +++ b/drivers/video/omap2/dss/dss.h > @@ -363,6 +363,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); [sp] Is this patch really standalone? I suggest merging it with the patch where the API is actually used. In effect, nothing gets disabled in this patch. > int dispc_setup_plane(enum omap_plane plane, > u32 paddr, u16 screen_width, > u16 pos_x, u16 pos_y, > -- > 1.5.6.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable. 2011-03-09 14:49 ` [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable Premi, Sanjeev @ 2011-03-10 5:55 ` K, Mythri P 0 siblings, 0 replies; 33+ messages in thread From: K, Mythri P @ 2011-03-10 5:55 UTC (permalink / raw) To: Premi, Sanjeev; +Cc: linux-omap@vger.kernel.org, Valkeinen, Tomi Hi Sanjeev, On Wed, Mar 9, 2011 at 8:19 PM, Premi, Sanjeev <premi@ti.com> wrote: >> -----Original Message----- >> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap- >> owner@vger.kernel.org] On Behalf Of K, Mythri P >> Sent: Wednesday, March 09, 2011 5:15 PM >> To: linux-omap@vger.kernel.org; Valkeinen, Tomi >> Cc: K, Mythri P >> Subject: [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table >> disable. > [sp] HDMI seems repetitive in the subject in this and some of the subsequent > Patches. >> >> Adding changes to set gamma table bit for TV interface to make sure it is >> disabled > > [sp] Is this bit expected to be "enabled" by default? If no, how can/would > this bit get enabled. > > The subject and description of the patch doesn't match the contents. > The patch is adding a function that can *both* enable/disable gamma > table - not just disable. >We have seen several examples of the reset bit being changed across Silicon versions , So this is to set the gamma enable to 0 Effectively a disable., so i have added a comment that this still needs to add enable functionality. >> >> Signed-off-by: Mythri P K <mythripk@ti.com> >> --- >> drivers/video/omap2/dss/dispc.c | 10 ++++++++++ >> drivers/video/omap2/dss/dss.h | 1 + >> 2 files changed, 11 insertions(+), 0 deletions(-) >> >> diff --git a/drivers/video/omap2/dss/dispc.c >> b/drivers/video/omap2/dss/dispc.c >> index 4a368c4..0defe16 100644 >> --- a/drivers/video/omap2/dss/dispc.c >> +++ b/drivers/video/omap2/dss/dispc.c >> @@ -1008,6 +1008,16 @@ 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. >> + */ >> + BUG_ON(enable); > [sp] Is BUG_ON really needed. Can't this be a WARN or equiv? > >> + >> + REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); > > [sp] I don't understand HDMI much, but if enabling gamma causes BUG_ON, > then why would we need implementation to disable it. > > Instead, shouldn't the function be empty - if it can't be avoided > altogether? > >> +} >> + >> 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 29f31fd..008cbf4 100644 >> --- a/drivers/video/omap2/dss/dss.h >> +++ b/drivers/video/omap2/dss/dss.h >> @@ -363,6 +363,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); > > [sp] Is this patch really standalone? I suggest merging it with the patch > where the API is actually used. > > In effect, nothing gets disabled in this patch. > >> int dispc_setup_plane(enum omap_plane plane, >> u32 paddr, u16 screen_width, >> u16 pos_x, u16 pos_y, >> -- >> 1.5.6.3 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-omap" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 2011-03-09 11:45 [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 Mythri P K 2011-03-09 11:45 ` [PATCH v4 1/9] OMAP4 : DSS2 : Add display type HDMI to DSS2 Mythri P K @ 2011-03-09 14:15 ` Tomi Valkeinen 2011-03-10 5:27 ` K, Mythri P 1 sibling, 1 reply; 33+ messages in thread From: Tomi Valkeinen @ 2011-03-09 14:15 UTC (permalink / raw) To: K, Mythri P; +Cc: linux-omap@vger.kernel.org On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: > Adding HDMI support on OMAP4. > > HDMI is a driver that is similar to the VENC or the DSI driver to support > HDMI/DVI sink device. > > The current design adheres to the DSS2 architecture. > > It is split into the HDMI DSS driver and HDMI panel driver. This doesn't apply to my tree. Are you sure it's based on DSS master branch? Applying: OMAP4 : DSS2 : Add display type HDMI to DSS2 Applying: OMAP4 : DSS2 : HDMI: Select between HDMI VENC clock source. Applying: OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable. Applying: OMAP4 : DSS2 : HDMI: HDMI driver header file addition Applying: OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS fatal: sha1 information is lacking or useless (drivers/video/omap2/dss/dss.h). Repository lacks necessary blobs to fall back on 3-way merge. Cannot fall back to three-way merge. Patch failed at 0005 OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS When you have resolved this problem run "git am -3 --resolved". If you would prefer to skip this patch, instead run "git am -3 --skip". To restore the original branch and stop patching run "git am -3 --abort". Tomi ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 2011-03-09 14:15 ` [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 Tomi Valkeinen @ 2011-03-10 5:27 ` K, Mythri P 2011-03-10 7:21 ` Tomi Valkeinen 0 siblings, 1 reply; 33+ messages in thread From: K, Mythri P @ 2011-03-10 5:27 UTC (permalink / raw) To: Tomi Valkeinen; +Cc: linux-omap@vger.kernel.org Hi Tomi, yes This is based off your tree. Thanks and regards, Mythri. On Wed, Mar 9, 2011 at 7:45 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote: > On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: >> Adding HDMI support on OMAP4. >> >> HDMI is a driver that is similar to the VENC or the DSI driver to support >> HDMI/DVI sink device. >> >> The current design adheres to the DSS2 architecture. >> >> It is split into the HDMI DSS driver and HDMI panel driver. > > This doesn't apply to my tree. Are you sure it's based on DSS master > branch? > > Applying: OMAP4 : DSS2 : Add display type HDMI to DSS2 > Applying: OMAP4 : DSS2 : HDMI: Select between HDMI VENC clock source. > Applying: OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable. > Applying: OMAP4 : DSS2 : HDMI: HDMI driver header file addition > Applying: OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS > fatal: sha1 information is lacking or useless (drivers/video/omap2/dss/dss.h). > Repository lacks necessary blobs to fall back on 3-way merge. > Cannot fall back to three-way merge. > Patch failed at 0005 OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS > When you have resolved this problem run "git am -3 --resolved". > If you would prefer to skip this patch, instead run "git am -3 --skip". > To restore the original branch and stop patching run "git am -3 --abort". > > Tomi > > > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 2011-03-10 5:27 ` K, Mythri P @ 2011-03-10 7:21 ` Tomi Valkeinen 0 siblings, 0 replies; 33+ messages in thread From: Tomi Valkeinen @ 2011-03-10 7:21 UTC (permalink / raw) To: K, Mythri P; +Cc: linux-omap@vger.kernel.org On Wed, 2011-03-09 at 23:27 -0600, K, Mythri P wrote: > Hi Tomi, > yes This is based off your tree. > > Thanks and regards, > Mythri. It looks like there were some whitespace issues. I don't know what caused them... Also, please don't top-post on public mailing lists. Tomi > > On Wed, Mar 9, 2011 at 7:45 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote: > > On Wed, 2011-03-09 at 05:45 -0600, K, Mythri P wrote: > >> Adding HDMI support on OMAP4. > >> > >> HDMI is a driver that is similar to the VENC or the DSI driver to support > >> HDMI/DVI sink device. > >> > >> The current design adheres to the DSS2 architecture. > >> > >> It is split into the HDMI DSS driver and HDMI panel driver. > > > > This doesn't apply to my tree. Are you sure it's based on DSS master > > branch? > > > > Applying: OMAP4 : DSS2 : Add display type HDMI to DSS2 > > Applying: OMAP4 : DSS2 : HDMI: Select between HDMI VENC clock source. > > Applying: OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable. > > Applying: OMAP4 : DSS2 : HDMI: HDMI driver header file addition > > Applying: OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS > > fatal: sha1 information is lacking or useless (drivers/video/omap2/dss/dss.h). > > Repository lacks necessary blobs to fall back on 3-way merge. > > Cannot fall back to three-way merge. > > Patch failed at 0005 OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS > > When you have resolved this problem run "git am -3 --resolved". > > If you would prefer to skip this patch, instead run "git am -3 --skip". > > To restore the original branch and stop patching run "git am -3 --abort". > > > > Tomi > > > > > > ^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2011-03-10 9:49 UTC | newest] Thread overview: 33+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-03-09 11:45 [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 Mythri P K 2011-03-09 11:45 ` [PATCH v4 1/9] OMAP4 : DSS2 : Add display type HDMI to DSS2 Mythri P K 2011-03-09 11:45 ` [PATCH v4 2/9] OMAP4 : DSS2 : HDMI: Select between HDMI VENC clock source Mythri P K 2011-03-09 11:45 ` [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable Mythri P K 2011-03-09 11:45 ` [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition Mythri P K 2011-03-09 11:45 ` [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI driver addition in the DSS Mythri P K 2011-03-09 11:45 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel " Mythri P K 2011-03-09 11:45 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Mythri P K 2011-03-09 11:45 ` [PATCH v4 8/9] OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 SDP Mythri P K 2011-03-09 11:45 ` [PATCH v4 9/9] OMAP4 : HDMI : Add HDMI structure in the board file for OMAP4 PANDA Mythri P K 2011-03-09 15:54 ` [PATCH v4 7/9] OMAP4 : DSS : HDMI: Call to HDMI module init to register driver Premi, Sanjeev 2011-03-10 5:24 ` K, Mythri P 2011-03-09 14:23 ` [PATCH v4 6/9] OMAP4 : DSS2 : HDMI: HDMI panel driver addition in the DSS Tomi Valkeinen 2011-03-10 5:27 ` K, Mythri P 2011-03-10 7:52 ` Tomi Valkeinen 2011-03-10 9:00 ` K, Mythri P 2011-03-10 9:19 ` Tomi Valkeinen 2011-03-10 9:33 ` K, Mythri P 2011-03-10 9:39 ` Hiremath, Vaibhav 2011-03-10 9:47 ` K, Mythri P 2011-03-10 9:49 ` Tomi Valkeinen 2011-03-09 15:50 ` [PATCH v4 5/9] OMAP4 : DSS2 : HDMI: HDMI " Premi, Sanjeev 2011-03-10 5:22 ` K, Mythri P 2011-03-10 7:57 ` Tomi Valkeinen 2011-03-09 15:56 ` [PATCH v4 4/9] OMAP4 : DSS2 : HDMI: HDMI driver header file addition Premi, Sanjeev 2011-03-10 5:02 ` K, Mythri P 2011-03-10 8:52 ` Premi, Sanjeev 2011-03-10 9:07 ` Tomi Valkeinen 2011-03-09 14:49 ` [PATCH v4 3/9] OMAP4 : DSS2 : HDMI: HDMI dispc gamma table disable Premi, Sanjeev 2011-03-10 5:55 ` K, Mythri P 2011-03-09 14:15 ` [PATCH v4 0/9] OMAP4 : DSS2 : HDMI support on OMAP4 Tomi Valkeinen 2011-03-10 5:27 ` K, Mythri P 2011-03-10 7:21 ` Tomi Valkeinen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox