All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] OMAP: DSS2: EDID & detect support
@ 2011-08-31 13:23 ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Implement EDID reading and monitor detection support for HDMI and DVI outputs.

This set is based on the previously sent "OMAP: DSS2: misc improvements" set.

 Tomi

Tomi Valkeinen (12):
  OMAP: DSS2: add read_edid() to omap_dss_driver struct
  OMAP: DSS2: add detect() to omap_dss_driver struct
  OMAP: DSS2: HDMI: make set_timing saner
  OMAP: DSS2: HDMI: implement read_edid()
  OMAP: DSS2: HDMI: remove edid parsing
  OMAP: DSS2: HDMI: split hdmi_core_ddc_edid
  OMAP: DSS2: HDMI: clean up edid reading & fix checksum
  OMAP: DSS2: HDMI: remove error prints in check_timings
  OMAP: DSS2: HDMI: implement detect()
  OMAP: DSS2: Generic-dpi: add detect & read_edid support
  OMAP: Panda & Beagle: DVI: Add i2c_bus_num
  OMAPFB: find best mode from edid

 arch/arm/mach-omap2/board-omap3beagle.c          |    1 +
 arch/arm/mach-omap2/board-omap4panda.c           |    1 +
 drivers/video/omap2/displays/panel-generic-dpi.c |   92 ++++++
 drivers/video/omap2/dss/dss.h                    |    2 +
 drivers/video/omap2/dss/hdmi.c                   |  323 +++++++++-------------
 drivers/video/omap2/dss/hdmi_omap4_panel.c       |   66 ++++-
 drivers/video/omap2/omapfb/omapfb-main.c         |  109 +++++++-
 include/video/omap-panel-generic-dpi.h           |    2 +
 include/video/omapdss.h                          |    3 +
 9 files changed, 378 insertions(+), 221 deletions(-)

-- 
1.7.4.1


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 00/12] OMAP: DSS2: EDID & detect support
@ 2011-08-31 13:23 ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Implement EDID reading and monitor detection support for HDMI and DVI outputs.

This set is based on the previously sent "OMAP: DSS2: misc improvements" set.

 Tomi

Tomi Valkeinen (12):
  OMAP: DSS2: add read_edid() to omap_dss_driver struct
  OMAP: DSS2: add detect() to omap_dss_driver struct
  OMAP: DSS2: HDMI: make set_timing saner
  OMAP: DSS2: HDMI: implement read_edid()
  OMAP: DSS2: HDMI: remove edid parsing
  OMAP: DSS2: HDMI: split hdmi_core_ddc_edid
  OMAP: DSS2: HDMI: clean up edid reading & fix checksum
  OMAP: DSS2: HDMI: remove error prints in check_timings
  OMAP: DSS2: HDMI: implement detect()
  OMAP: DSS2: Generic-dpi: add detect & read_edid support
  OMAP: Panda & Beagle: DVI: Add i2c_bus_num
  OMAPFB: find best mode from edid

 arch/arm/mach-omap2/board-omap3beagle.c          |    1 +
 arch/arm/mach-omap2/board-omap4panda.c           |    1 +
 drivers/video/omap2/displays/panel-generic-dpi.c |   92 ++++++
 drivers/video/omap2/dss/dss.h                    |    2 +
 drivers/video/omap2/dss/hdmi.c                   |  323 +++++++++-------------
 drivers/video/omap2/dss/hdmi_omap4_panel.c       |   66 ++++-
 drivers/video/omap2/omapfb/omapfb-main.c         |  109 +++++++-
 include/video/omap-panel-generic-dpi.h           |    2 +
 include/video/omapdss.h                          |    3 +
 9 files changed, 378 insertions(+), 221 deletions(-)

-- 
1.7.4.1


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 01/12] OMAP: DSS2: add read_edid() to omap_dss_driver struct
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

read_edid() can be used to get the EDID information from the display.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 include/video/omapdss.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index f8385ae..8ed5a6c 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -558,6 +558,8 @@ struct omap_dss_driver {
 
 	int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
 	u32 (*get_wss)(struct omap_dss_device *dssdev);
+
+	int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
 };
 
 int omap_dss_register_driver(struct omap_dss_driver *);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 01/12] OMAP: DSS2: add read_edid() to omap_dss_driver struct
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

read_edid() can be used to get the EDID information from the display.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 include/video/omapdss.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index f8385ae..8ed5a6c 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -558,6 +558,8 @@ struct omap_dss_driver {
 
 	int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
 	u32 (*get_wss)(struct omap_dss_device *dssdev);
+
+	int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
 };
 
 int omap_dss_register_driver(struct omap_dss_driver *);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 02/12] OMAP: DSS2: add detect() to omap_dss_driver struct
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

detect() can be used to probe if the display is connected.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 include/video/omapdss.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 8ed5a6c..a62f49a 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -560,6 +560,7 @@ struct omap_dss_driver {
 	u32 (*get_wss)(struct omap_dss_device *dssdev);
 
 	int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+	bool (*detect)(struct omap_dss_device *dssdev);
 };
 
 int omap_dss_register_driver(struct omap_dss_driver *);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 02/12] OMAP: DSS2: add detect() to omap_dss_driver struct
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

detect() can be used to probe if the display is connected.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 include/video/omapdss.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 8ed5a6c..a62f49a 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -560,6 +560,7 @@ struct omap_dss_driver {
 	u32 (*get_wss)(struct omap_dss_device *dssdev);
 
 	int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+	bool (*detect)(struct omap_dss_device *dssdev);
 };
 
 int omap_dss_register_driver(struct omap_dss_driver *);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 03/12] OMAP: DSS2: HDMI: make set_timing saner
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Currently the set_timings code for hdmi is quite strange. The display is
disabled in hdmi_omap4_panel.c before setting timings, and enabled in
hdmi.c after setting the timings. Furthermore, the timings were not
permanent, and disabling and enabling the display would lose them.

This patch makes the set_timings handling a bit better.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c             |   13 +++++++++++--
 drivers/video/omap2/dss/hdmi_omap4_panel.c |    7 +------
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index d08096b..8f8ae0e 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1226,11 +1226,20 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 	struct hdmi_cm cm;
 
 	hdmi.custom_set = 1;
+
 	cm = hdmi_get_code(&dssdev->panel.timings);
 	hdmi.code = cm.code;
 	hdmi.mode = cm.mode;
-	omapdss_hdmi_display_enable(dssdev);
-	hdmi.custom_set = 0;
+
+	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
+		int r;
+
+		hdmi_power_off(dssdev);
+
+		r = hdmi_power_on(dssdev);
+		if (r)
+			DSSERR("failed to power on device\n");
+	}
 }
 
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 7d4f2bd..25d5fb2 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -161,12 +161,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
 	mutex_lock(&hdmi.hdmi_lock);
 
 	dssdev->panel.timings = *timings;
-
-	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
-		/* turn the hdmi off and on to get new timings to use */
-		omapdss_hdmi_display_disable(dssdev);
-		omapdss_hdmi_display_set_timing(dssdev);
-	}
+	omapdss_hdmi_display_set_timing(dssdev);
 
 	mutex_unlock(&hdmi.hdmi_lock);
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 03/12] OMAP: DSS2: HDMI: make set_timing saner
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Currently the set_timings code for hdmi is quite strange. The display is
disabled in hdmi_omap4_panel.c before setting timings, and enabled in
hdmi.c after setting the timings. Furthermore, the timings were not
permanent, and disabling and enabling the display would lose them.

This patch makes the set_timings handling a bit better.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c             |   13 +++++++++++--
 drivers/video/omap2/dss/hdmi_omap4_panel.c |    7 +------
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index d08096b..8f8ae0e 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1226,11 +1226,20 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 	struct hdmi_cm cm;
 
 	hdmi.custom_set = 1;
+
 	cm = hdmi_get_code(&dssdev->panel.timings);
 	hdmi.code = cm.code;
 	hdmi.mode = cm.mode;
-	omapdss_hdmi_display_enable(dssdev);
-	hdmi.custom_set = 0;
+
+	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+		int r;
+
+		hdmi_power_off(dssdev);
+
+		r = hdmi_power_on(dssdev);
+		if (r)
+			DSSERR("failed to power on device\n");
+	}
 }
 
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 7d4f2bd..25d5fb2 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -161,12 +161,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
 	mutex_lock(&hdmi.hdmi_lock);
 
 	dssdev->panel.timings = *timings;
-
-	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-		/* turn the hdmi off and on to get new timings to use */
-		omapdss_hdmi_display_disable(dssdev);
-		omapdss_hdmi_display_set_timing(dssdev);
-	}
+	omapdss_hdmi_display_set_timing(dssdev);
 
 	mutex_unlock(&hdmi.hdmi_lock);
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 04/12] OMAP: DSS2: HDMI: implement read_edid()
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Implement read_edid() for HDMI by implementing necessary functions to
hdmi.c and to hdmi_omap4_panel.c.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.h              |    1 +
 drivers/video/omap2/dss/hdmi.c             |   60 ++++++++++++++++++---------
 drivers/video/omap2/dss/hdmi_omap4_panel.c |   24 +++++++++++
 3 files changed, 65 insertions(+), 20 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 57b1a01..6102b80 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -492,6 +492,7 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 					struct omap_video_timings *timings);
+int omapdss_hdmi_read_edid(u8 *buf, int len);
 int hdmi_panel_init(void);
 void hdmi_panel_exit(void);
 
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 8f8ae0e..5e66cb8 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -471,29 +471,32 @@ static int read_edid(u8 *pedid, u16 max_length)
 {
 	int r = 0, n = 0, i = 0;
 	int max_ext_blocks = (max_length / 128) - 1;
+	int len;
 
 	r = hdmi_core_ddc_edid(pedid, 0);
-	if (r) {
+	if (r)
 		return r;
-	} else {
-		n = pedid[0x7e];
 
-		/*
-		 * README: need to comply with max_length set by the caller.
-		 * Better implementation should be to allocate necessary
-		 * memory to store EDID according to nb_block field found
-		 * in first block
-		 */
-		if (n > max_ext_blocks)
-			n = max_ext_blocks;
+	len = 128;
+	n = pedid[0x7e];
 
-		for (i = 1; i <= n; i++) {
-			r = hdmi_core_ddc_edid(pedid, i);
-			if (r)
-				return r;
-		}
+	/*
+	 * README: need to comply with max_length set by the caller.
+	 * Better implementation should be to allocate necessary
+	 * memory to store EDID according to nb_block field found
+	 * in first block
+	 */
+	if (n > max_ext_blocks)
+		n = max_ext_blocks;
+
+	for (i = 1; i <= n; i++) {
+		r = hdmi_core_ddc_edid(pedid, i);
+		if (r)
+			return r;
+		len += 128;
 	}
-	return 0;
+
+	return len;
 }
 
 static int get_timings_index(void)
@@ -660,7 +663,7 @@ static void hdmi_read_edid(struct omap_video_timings *dp)
 	if (!hdmi.edid_set)
 		ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
 
-	if (!ret) {
+	if (ret > 0) {
 		if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
 			/* search for timings of default resolution */
 			get_edid_timing_data(hdmi.edid);
@@ -1242,6 +1245,23 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 	}
 }
 
+int omapdss_hdmi_read_edid(u8 *buf, int len)
+{
+	int r;
+
+	mutex_lock(&hdmi.lock);
+
+	r = hdmi_runtime_get();
+	BUG_ON(r);
+
+	r = read_edid(buf, len);
+
+	hdmi_runtime_put();
+	mutex_unlock(&hdmi.lock);
+
+	return r;
+}
+
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 {
 	int r = 0;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 25d5fb2..7adaf7a 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -185,6 +185,29 @@ err:
 	return r;
 }
 
+static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
+{
+	int r;
+
+	mutex_lock(&hdmi.hdmi_lock);
+
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+		r = omapdss_hdmi_display_enable(dssdev);
+		if (r)
+			goto err;
+	}
+
+	r = omapdss_hdmi_read_edid(buf, len);
+
+	if (dssdev->state = OMAP_DSS_DISPLAY_DISABLED ||
+			dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED)
+		omapdss_hdmi_display_disable(dssdev);
+err:
+	mutex_unlock(&hdmi.hdmi_lock);
+
+	return r;
+}
+
 static struct omap_dss_driver hdmi_driver = {
 	.probe		= hdmi_panel_probe,
 	.remove		= hdmi_panel_remove,
@@ -195,6 +218,7 @@ static struct omap_dss_driver hdmi_driver = {
 	.get_timings	= hdmi_get_timings,
 	.set_timings	= hdmi_set_timings,
 	.check_timings	= hdmi_check_timings,
+	.read_edid	= hdmi_read_edid,
 	.driver			= {
 		.name   = "hdmi_panel",
 		.owner  = THIS_MODULE,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 04/12] OMAP: DSS2: HDMI: implement read_edid()
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Implement read_edid() for HDMI by implementing necessary functions to
hdmi.c and to hdmi_omap4_panel.c.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.h              |    1 +
 drivers/video/omap2/dss/hdmi.c             |   60 ++++++++++++++++++---------
 drivers/video/omap2/dss/hdmi_omap4_panel.c |   24 +++++++++++
 3 files changed, 65 insertions(+), 20 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 57b1a01..6102b80 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -492,6 +492,7 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 					struct omap_video_timings *timings);
+int omapdss_hdmi_read_edid(u8 *buf, int len);
 int hdmi_panel_init(void);
 void hdmi_panel_exit(void);
 
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 8f8ae0e..5e66cb8 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -471,29 +471,32 @@ static int read_edid(u8 *pedid, u16 max_length)
 {
 	int r = 0, n = 0, i = 0;
 	int max_ext_blocks = (max_length / 128) - 1;
+	int len;
 
 	r = hdmi_core_ddc_edid(pedid, 0);
-	if (r) {
+	if (r)
 		return r;
-	} else {
-		n = pedid[0x7e];
 
-		/*
-		 * README: need to comply with max_length set by the caller.
-		 * Better implementation should be to allocate necessary
-		 * memory to store EDID according to nb_block field found
-		 * in first block
-		 */
-		if (n > max_ext_blocks)
-			n = max_ext_blocks;
+	len = 128;
+	n = pedid[0x7e];
 
-		for (i = 1; i <= n; i++) {
-			r = hdmi_core_ddc_edid(pedid, i);
-			if (r)
-				return r;
-		}
+	/*
+	 * README: need to comply with max_length set by the caller.
+	 * Better implementation should be to allocate necessary
+	 * memory to store EDID according to nb_block field found
+	 * in first block
+	 */
+	if (n > max_ext_blocks)
+		n = max_ext_blocks;
+
+	for (i = 1; i <= n; i++) {
+		r = hdmi_core_ddc_edid(pedid, i);
+		if (r)
+			return r;
+		len += 128;
 	}
-	return 0;
+
+	return len;
 }
 
 static int get_timings_index(void)
@@ -660,7 +663,7 @@ static void hdmi_read_edid(struct omap_video_timings *dp)
 	if (!hdmi.edid_set)
 		ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
 
-	if (!ret) {
+	if (ret > 0) {
 		if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
 			/* search for timings of default resolution */
 			get_edid_timing_data(hdmi.edid);
@@ -1242,6 +1245,23 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 	}
 }
 
+int omapdss_hdmi_read_edid(u8 *buf, int len)
+{
+	int r;
+
+	mutex_lock(&hdmi.lock);
+
+	r = hdmi_runtime_get();
+	BUG_ON(r);
+
+	r = read_edid(buf, len);
+
+	hdmi_runtime_put();
+	mutex_unlock(&hdmi.lock);
+
+	return r;
+}
+
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 {
 	int r = 0;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 25d5fb2..7adaf7a 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -185,6 +185,29 @@ err:
 	return r;
 }
 
+static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
+{
+	int r;
+
+	mutex_lock(&hdmi.hdmi_lock);
+
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+		r = omapdss_hdmi_display_enable(dssdev);
+		if (r)
+			goto err;
+	}
+
+	r = omapdss_hdmi_read_edid(buf, len);
+
+	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+			dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+		omapdss_hdmi_display_disable(dssdev);
+err:
+	mutex_unlock(&hdmi.hdmi_lock);
+
+	return r;
+}
+
 static struct omap_dss_driver hdmi_driver = {
 	.probe		= hdmi_panel_probe,
 	.remove		= hdmi_panel_remove,
@@ -195,6 +218,7 @@ static struct omap_dss_driver hdmi_driver = {
 	.get_timings	= hdmi_get_timings,
 	.set_timings	= hdmi_set_timings,
 	.check_timings	= hdmi_check_timings,
+	.read_edid	= hdmi_read_edid,
 	.driver			= {
 		.name   = "hdmi_panel",
 		.owner  = THIS_MODULE,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 05/12] OMAP: DSS2: HDMI: remove edid parsing
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

OMAPFB handles EDID parsing now, using the common helper functions in
fbdev. We can remove the EDID parsing from HDMI driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c             |  137 ----------------------------
 drivers/video/omap2/dss/hdmi_omap4_panel.c |    8 +--
 2 files changed, 1 insertions(+), 144 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 5e66cb8..b5aca64 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -53,9 +53,6 @@ static struct {
 	void __iomem *base_wp;	/* HDMI wrapper */
 	int code;
 	int mode;
-	u8 edid[HDMI_EDID_MAX_LENGTH];
-	u8 edid_set;
-	bool custom_set;
 	struct hdmi_config cfg;
 
 	struct clk *sys_clk;
@@ -146,8 +143,6 @@ static const int code_vesa[85] = {
 	-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);
@@ -561,129 +556,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
 	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;
-
-	/* search block 0, there are 4 DTDs arranged in priority order */
-	for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
-		current_descriptor_addrs -			EDID_DESCRIPTOR_BLOCK0_ADDRESS +
-			count * EDID_TIMING_DESCRIPTOR_SIZE;
-		get_horz_vert_timing_info(current_descriptor_addrs,
-				edid, &edid_timings);
-		cm = hdmi_get_code(&edid_timings);
-		DSSDBG("Block0[%d] value matches code = %d , mode = %d\n",
-			count, cm.code, cm.mode);
-		if (cm.code = -1) {
-			continue;
-		} else {
-			hdmi.code = cm.code;
-			hdmi.mode = cm.mode;
-			DSSDBG("code = %d , mode = %d\n",
-				hdmi.code, hdmi.mode);
-			return;
-		}
-	}
-	if (edid[0x7e] != 0x00) {
-		for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
-			count++) {
-			current_descriptor_addrs -			EDID_DESCRIPTOR_BLOCK1_ADDRESS +
-			count * EDID_TIMING_DESCRIPTOR_SIZE;
-			get_horz_vert_timing_info(current_descriptor_addrs,
-						edid, &edid_timings);
-			cm = hdmi_get_code(&edid_timings);
-			DSSDBG("Block1[%d] value matches code = %d, mode = %d",
-				count, cm.code, cm.mode);
-			if (cm.code = -1) {
-				continue;
-			} else {
-				hdmi.code = cm.code;
-				hdmi.mode = cm.mode;
-				DSSDBG("code = %d , mode = %d\n",
-					hdmi.code, hdmi.mode);
-				return;
-			}
-		}
-	}
-
-	DSSINFO("no valid timing found , falling back to VGA\n");
-	hdmi.code = 4; /* setting default value of 640 480 VGA */
-	hdmi.mode = HDMI_DVI;
-}
-
-static void hdmi_read_edid(struct omap_video_timings *dp)
-{
-	int ret = 0, code;
-
-	memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
-
-	if (!hdmi.edid_set)
-		ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
-
-	if (ret > 0) {
-		if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
-			/* search for timings of default resolution */
-			get_edid_timing_data(hdmi.edid);
-			hdmi.edid_set = true;
-		}
-	} else {
-		DSSWARN("failed to read E-EDID\n");
-	}
-
-	if (!hdmi.edid_set) {
-		DSSINFO("fallback to VGA\n");
-		hdmi.code = 4; /* setting default value of 640 480 VGA */
-		hdmi.mode = HDMI_DVI;
-	}
-
-	code = get_timings_index();
-
-	*dp = cea_vesa_timings[code].timings;
-}
-
 static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
 			struct hdmi_core_infoframe_avi *avi_cfg,
 			struct hdmi_core_packet_enable_repeat *repeat_cfg)
@@ -1138,12 +1010,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 		dssdev->panel.timings.x_res,
 		dssdev->panel.timings.y_res);
 
-	if (!hdmi.custom_set) {
-		DSSDBG("Read EDID as no EDID is not set on poweron\n");
-		hdmi_read_edid(p);
-	}
 	code = get_timings_index();
-	dssdev->panel.timings = cea_vesa_timings[code].timings;
 	update_hdmi_timings(&hdmi.cfg, p, code);
 
 	phy = p->pixel_clock;
@@ -1205,8 +1072,6 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 	hdmi_phy_off();
 	hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
 	hdmi_runtime_put();
-
-	hdmi.edid_set = 0;
 }
 
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -1228,8 +1093,6 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 {
 	struct hdmi_cm cm;
 
-	hdmi.custom_set = 1;
-
 	cm = hdmi_get_code(&dssdev->panel.timings);
 	hdmi.code = cm.code;
 	hdmi.mode = cm.mode;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 7adaf7a..5e314e8 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -40,13 +40,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev)
 	dssdev->panel.config = OMAP_DSS_LCD_TFT |
 			OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
 
-	/*
-	 * Initialize the timings to 640 * 480
-	 * This is only for framebuffer update not for TV timing setting
-	 * Setting TV timing will be done only on enable
-	 */
-	dssdev->panel.timings.x_res = 640;
-	dssdev->panel.timings.y_res = 480;
+	dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31};
 
 	DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
 		dssdev->panel.timings.x_res,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 05/12] OMAP: DSS2: HDMI: remove edid parsing
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

OMAPFB handles EDID parsing now, using the common helper functions in
fbdev. We can remove the EDID parsing from HDMI driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c             |  137 ----------------------------
 drivers/video/omap2/dss/hdmi_omap4_panel.c |    8 +--
 2 files changed, 1 insertions(+), 144 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 5e66cb8..b5aca64 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -53,9 +53,6 @@ static struct {
 	void __iomem *base_wp;	/* HDMI wrapper */
 	int code;
 	int mode;
-	u8 edid[HDMI_EDID_MAX_LENGTH];
-	u8 edid_set;
-	bool custom_set;
 	struct hdmi_config cfg;
 
 	struct clk *sys_clk;
@@ -146,8 +143,6 @@ static const int code_vesa[85] = {
 	-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);
@@ -561,129 +556,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
 	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;
-
-	/* search block 0, there are 4 DTDs arranged in priority order */
-	for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
-		current_descriptor_addrs =
-			EDID_DESCRIPTOR_BLOCK0_ADDRESS +
-			count * EDID_TIMING_DESCRIPTOR_SIZE;
-		get_horz_vert_timing_info(current_descriptor_addrs,
-				edid, &edid_timings);
-		cm = hdmi_get_code(&edid_timings);
-		DSSDBG("Block0[%d] value matches code = %d , mode = %d\n",
-			count, cm.code, cm.mode);
-		if (cm.code == -1) {
-			continue;
-		} else {
-			hdmi.code = cm.code;
-			hdmi.mode = cm.mode;
-			DSSDBG("code = %d , mode = %d\n",
-				hdmi.code, hdmi.mode);
-			return;
-		}
-	}
-	if (edid[0x7e] != 0x00) {
-		for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
-			count++) {
-			current_descriptor_addrs =
-			EDID_DESCRIPTOR_BLOCK1_ADDRESS +
-			count * EDID_TIMING_DESCRIPTOR_SIZE;
-			get_horz_vert_timing_info(current_descriptor_addrs,
-						edid, &edid_timings);
-			cm = hdmi_get_code(&edid_timings);
-			DSSDBG("Block1[%d] value matches code = %d, mode = %d",
-				count, cm.code, cm.mode);
-			if (cm.code == -1) {
-				continue;
-			} else {
-				hdmi.code = cm.code;
-				hdmi.mode = cm.mode;
-				DSSDBG("code = %d , mode = %d\n",
-					hdmi.code, hdmi.mode);
-				return;
-			}
-		}
-	}
-
-	DSSINFO("no valid timing found , falling back to VGA\n");
-	hdmi.code = 4; /* setting default value of 640 480 VGA */
-	hdmi.mode = HDMI_DVI;
-}
-
-static void hdmi_read_edid(struct omap_video_timings *dp)
-{
-	int ret = 0, code;
-
-	memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
-
-	if (!hdmi.edid_set)
-		ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
-
-	if (ret > 0) {
-		if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
-			/* search for timings of default resolution */
-			get_edid_timing_data(hdmi.edid);
-			hdmi.edid_set = true;
-		}
-	} else {
-		DSSWARN("failed to read E-EDID\n");
-	}
-
-	if (!hdmi.edid_set) {
-		DSSINFO("fallback to VGA\n");
-		hdmi.code = 4; /* setting default value of 640 480 VGA */
-		hdmi.mode = HDMI_DVI;
-	}
-
-	code = get_timings_index();
-
-	*dp = cea_vesa_timings[code].timings;
-}
-
 static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
 			struct hdmi_core_infoframe_avi *avi_cfg,
 			struct hdmi_core_packet_enable_repeat *repeat_cfg)
@@ -1138,12 +1010,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 		dssdev->panel.timings.x_res,
 		dssdev->panel.timings.y_res);
 
-	if (!hdmi.custom_set) {
-		DSSDBG("Read EDID as no EDID is not set on poweron\n");
-		hdmi_read_edid(p);
-	}
 	code = get_timings_index();
-	dssdev->panel.timings = cea_vesa_timings[code].timings;
 	update_hdmi_timings(&hdmi.cfg, p, code);
 
 	phy = p->pixel_clock;
@@ -1205,8 +1072,6 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 	hdmi_phy_off();
 	hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
 	hdmi_runtime_put();
-
-	hdmi.edid_set = 0;
 }
 
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -1228,8 +1093,6 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 {
 	struct hdmi_cm cm;
 
-	hdmi.custom_set = 1;
-
 	cm = hdmi_get_code(&dssdev->panel.timings);
 	hdmi.code = cm.code;
 	hdmi.mode = cm.mode;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 7adaf7a..5e314e8 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -40,13 +40,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev)
 	dssdev->panel.config = OMAP_DSS_LCD_TFT |
 			OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
 
-	/*
-	 * Initialize the timings to 640 * 480
-	 * This is only for framebuffer update not for TV timing setting
-	 * Setting TV timing will be done only on enable
-	 */
-	dssdev->panel.timings.x_res = 640;
-	dssdev->panel.timings.y_res = 480;
+	dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31};
 
 	DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
 		dssdev->panel.timings.x_res,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 06/12] OMAP: DSS2: HDMI: split hdmi_core_ddc_edid
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Split the DDC initialization off from hdmi_core_ddc_edid() into a
separate function hdmi_core_ddc_init().

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |   67 +++++++++++++++++++++++++++-------------
 1 files changed, 45 insertions(+), 22 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index b5aca64..04ce105 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -366,12 +366,8 @@ static void hdmi_phy_off(void)
 	hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
 }
 
-static int hdmi_core_ddc_edid(u8 *pedid, int ext)
+static int hdmi_core_ddc_init(void)
 {
-	u32 i, j;
-	char checksum = 0;
-	u32 offset = 0;
-
 	/* Turn on CLK for DDC */
 	REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0);
 
@@ -382,32 +378,55 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 	 */
 	usleep_range(800, 1000);
 
-	if (!ext) {
-		/* Clk SCL Devices */
-		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
+	/* IN_PROG */
+	if (REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) = 1) {
+		/* Abort transaction */
+		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xf, 3, 0);
 
-		/* HDMI_CORE_DDC_STATUS_IN_PROG */
+		/* IN_PROG */
 		if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
-						4, 4, 0) != 0) {
-			DSSERR("Failed to program DDC\n");
+					4, 4, 0) != 0) {
+			DSSERR("Timeout aborting DDC transaction\n");
 			return -ETIMEDOUT;
 		}
+	}
 
-		/* Clear FIFO */
-		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+	/* Clk SCL Devices */
+	REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
 
-		/* HDMI_CORE_DDC_STATUS_IN_PROG */
-		if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
-						4, 4, 0) != 0) {
-			DSSERR("Failed to program DDC\n");
-			return -ETIMEDOUT;
-		}
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
+		DSSERR("Timeout starting SCL clock\n");
+		return -ETIMEDOUT;
+	}
 
-	} else {
-		if (ext % 2 != 0)
-			offset = 0x80;
+	/* 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("Timeout clearing DDC fifo\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int hdmi_core_ddc_edid(u8 *pedid, int ext)
+{
+	u32 i, j;
+	char checksum = 0;
+	u32 offset = 0;
+
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
+		DSSERR("Timeout waiting DDC to be ready\n");
+		return -ETIMEDOUT;
 	}
 
+	if (ext % 2 != 0)
+		offset = 0x80;
+
 	/* Load Segment Address Register */
 	REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
 
@@ -468,6 +487,10 @@ static int read_edid(u8 *pedid, u16 max_length)
 	int max_ext_blocks = (max_length / 128) - 1;
 	int len;
 
+	r = hdmi_core_ddc_init();
+	if (r)
+		return r;
+
 	r = hdmi_core_ddc_edid(pedid, 0);
 	if (r)
 		return r;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 06/12] OMAP: DSS2: HDMI: split hdmi_core_ddc_edid
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Split the DDC initialization off from hdmi_core_ddc_edid() into a
separate function hdmi_core_ddc_init().

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |   67 +++++++++++++++++++++++++++-------------
 1 files changed, 45 insertions(+), 22 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index b5aca64..04ce105 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -366,12 +366,8 @@ static void hdmi_phy_off(void)
 	hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
 }
 
-static int hdmi_core_ddc_edid(u8 *pedid, int ext)
+static int hdmi_core_ddc_init(void)
 {
-	u32 i, j;
-	char checksum = 0;
-	u32 offset = 0;
-
 	/* Turn on CLK for DDC */
 	REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0);
 
@@ -382,32 +378,55 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 	 */
 	usleep_range(800, 1000);
 
-	if (!ext) {
-		/* Clk SCL Devices */
-		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
+	/* IN_PROG */
+	if (REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) {
+		/* Abort transaction */
+		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xf, 3, 0);
 
-		/* HDMI_CORE_DDC_STATUS_IN_PROG */
+		/* IN_PROG */
 		if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
-						4, 4, 0) != 0) {
-			DSSERR("Failed to program DDC\n");
+					4, 4, 0) != 0) {
+			DSSERR("Timeout aborting DDC transaction\n");
 			return -ETIMEDOUT;
 		}
+	}
 
-		/* Clear FIFO */
-		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+	/* Clk SCL Devices */
+	REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
 
-		/* HDMI_CORE_DDC_STATUS_IN_PROG */
-		if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
-						4, 4, 0) != 0) {
-			DSSERR("Failed to program DDC\n");
-			return -ETIMEDOUT;
-		}
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
+		DSSERR("Timeout starting SCL clock\n");
+		return -ETIMEDOUT;
+	}
 
-	} else {
-		if (ext % 2 != 0)
-			offset = 0x80;
+	/* 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("Timeout clearing DDC fifo\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int hdmi_core_ddc_edid(u8 *pedid, int ext)
+{
+	u32 i, j;
+	char checksum = 0;
+	u32 offset = 0;
+
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
+		DSSERR("Timeout waiting DDC to be ready\n");
+		return -ETIMEDOUT;
 	}
 
+	if (ext % 2 != 0)
+		offset = 0x80;
+
 	/* Load Segment Address Register */
 	REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
 
@@ -468,6 +487,10 @@ static int read_edid(u8 *pedid, u16 max_length)
 	int max_ext_blocks = (max_length / 128) - 1;
 	int len;
 
+	r = hdmi_core_ddc_init();
+	if (r)
+		return r;
+
 	r = hdmi_core_ddc_edid(pedid, 0);
 	if (r)
 		return r;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 07/12] OMAP: DSS2: HDMI: clean up edid reading & fix checksum
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Clean up reading of EDID by passing direct address to the block being
read, instead of start address of the whole EDID memory area. Rewrite
the loop which reads the EDID.

This also fixes the checksum calculation, which used to calculate the
checksum only for the first block.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |   67 ++++++++++++++++++++-------------------
 1 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 04ce105..34e05ee 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -414,8 +414,8 @@ static int hdmi_core_ddc_init(void)
 
 static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 {
-	u32 i, j;
-	char checksum = 0;
+	u32 i;
+	char checksum;
 	u32 offset = 0;
 
 	/* HDMI_CORE_DDC_STATUS_IN_PROG */
@@ -457,21 +457,31 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 		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) {
+	for (i = 0; i < 0x80; ++i) {
+		int t;
 
-		if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) = 0) {
-			/* FIFO not empty */
-			pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
-			j++;
+		/* IN_PROG */
+		if (REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) = 0) {
+			DSSERR("operation stopped when reading edid\n");
+			return -EIO;
+		}
+
+		t = 0;
+		/* FIFO_EMPTY */
+		while (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) = 1) {
+			if (t++ > 10000) {
+				DSSERR("timeout reading edid\n");
+				return -ETIMEDOUT;
+			}
+			udelay(1);
 		}
+
+		pedid[i] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
 	}
 
-	for (j = 0; j < 128; j++)
-		checksum += pedid[j];
+	checksum = 0;
+	for (i = 0; i < 0x80; ++i)
+		checksum += pedid[i];
 
 	if (checksum != 0) {
 		DSSERR("E-EDID checksum failed!!\n");
@@ -481,40 +491,31 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 	return 0;
 }
 
-static int read_edid(u8 *pedid, u16 max_length)
+static int read_edid(u8 *edid, int len)
 {
-	int r = 0, n = 0, i = 0;
-	int max_ext_blocks = (max_length / 128) - 1;
-	int len;
+	int r, l;
+
+	if (len < 128)
+		return -EINVAL;
 
 	r = hdmi_core_ddc_init();
 	if (r)
 		return r;
 
-	r = hdmi_core_ddc_edid(pedid, 0);
+	r = hdmi_core_ddc_edid(edid, 0);
 	if (r)
 		return r;
 
-	len = 128;
-	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;
+	l = 128;
 
-	for (i = 1; i <= n; i++) {
-		r = hdmi_core_ddc_edid(pedid, i);
+	if (len >= 128 * 2 && edid[0x7e] > 0) {
+		r = hdmi_core_ddc_edid(edid + 0x80, 1);
 		if (r)
 			return r;
-		len += 128;
+		l += 128;
 	}
 
-	return len;
+	return l;
 }
 
 static int get_timings_index(void)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 07/12] OMAP: DSS2: HDMI: clean up edid reading & fix checksum
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Clean up reading of EDID by passing direct address to the block being
read, instead of start address of the whole EDID memory area. Rewrite
the loop which reads the EDID.

This also fixes the checksum calculation, which used to calculate the
checksum only for the first block.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |   67 ++++++++++++++++++++-------------------
 1 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 04ce105..34e05ee 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -414,8 +414,8 @@ static int hdmi_core_ddc_init(void)
 
 static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 {
-	u32 i, j;
-	char checksum = 0;
+	u32 i;
+	char checksum;
 	u32 offset = 0;
 
 	/* HDMI_CORE_DDC_STATUS_IN_PROG */
@@ -457,21 +457,31 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 		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) {
+	for (i = 0; i < 0x80; ++i) {
+		int t;
 
-		if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) {
-			/* FIFO not empty */
-			pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
-			j++;
+		/* IN_PROG */
+		if (REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 0) {
+			DSSERR("operation stopped when reading edid\n");
+			return -EIO;
+		}
+
+		t = 0;
+		/* FIFO_EMPTY */
+		while (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 1) {
+			if (t++ > 10000) {
+				DSSERR("timeout reading edid\n");
+				return -ETIMEDOUT;
+			}
+			udelay(1);
 		}
+
+		pedid[i] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
 	}
 
-	for (j = 0; j < 128; j++)
-		checksum += pedid[j];
+	checksum = 0;
+	for (i = 0; i < 0x80; ++i)
+		checksum += pedid[i];
 
 	if (checksum != 0) {
 		DSSERR("E-EDID checksum failed!!\n");
@@ -481,40 +491,31 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 	return 0;
 }
 
-static int read_edid(u8 *pedid, u16 max_length)
+static int read_edid(u8 *edid, int len)
 {
-	int r = 0, n = 0, i = 0;
-	int max_ext_blocks = (max_length / 128) - 1;
-	int len;
+	int r, l;
+
+	if (len < 128)
+		return -EINVAL;
 
 	r = hdmi_core_ddc_init();
 	if (r)
 		return r;
 
-	r = hdmi_core_ddc_edid(pedid, 0);
+	r = hdmi_core_ddc_edid(edid, 0);
 	if (r)
 		return r;
 
-	len = 128;
-	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;
+	l = 128;
 
-	for (i = 1; i <= n; i++) {
-		r = hdmi_core_ddc_edid(pedid, i);
+	if (len >= 128 * 2 && edid[0x7e] > 0) {
+		r = hdmi_core_ddc_edid(edid + 0x80, 1);
 		if (r)
 			return r;
-		len += 128;
+		l += 128;
 	}
 
-	return len;
+	return l;
 }
 
 static int get_timings_index(void)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 08/12] OMAP: DSS2: HDMI: remove error prints in check_timings
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

check_timings() is supposed to be used to verify if timings are ok or
not. Currently the HDMI driver prints error messages if the timings are
not ok. This is not right, as it is no error to give invalid timings to
check_timings().

Remove the error prints.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c             |    1 -
 drivers/video/omap2/dss/hdmi_omap4_panel.c |    6 +-----
 2 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 34e05ee..55edbd2 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1105,7 +1105,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 
 	cm = hdmi_get_code(timings);
 	if (cm.code = -1) {
-		DSSERR("Invalid timing entered\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 5e314e8..ffea8d3 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -170,11 +170,7 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
 	mutex_lock(&hdmi.hdmi_lock);
 
 	r = omapdss_hdmi_display_check_timing(dssdev, timings);
-	if (r) {
-		DSSERR("Timing cannot be applied\n");
-		goto err;
-	}
-err:
+
 	mutex_unlock(&hdmi.hdmi_lock);
 	return r;
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 08/12] OMAP: DSS2: HDMI: remove error prints in check_timings
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

check_timings() is supposed to be used to verify if timings are ok or
not. Currently the HDMI driver prints error messages if the timings are
not ok. This is not right, as it is no error to give invalid timings to
check_timings().

Remove the error prints.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c             |    1 -
 drivers/video/omap2/dss/hdmi_omap4_panel.c |    6 +-----
 2 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 34e05ee..55edbd2 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1105,7 +1105,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 
 	cm = hdmi_get_code(timings);
 	if (cm.code == -1) {
-		DSSERR("Invalid timing entered\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 5e314e8..ffea8d3 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -170,11 +170,7 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
 	mutex_lock(&hdmi.hdmi_lock);
 
 	r = omapdss_hdmi_display_check_timing(dssdev, timings);
-	if (r) {
-		DSSERR("Timing cannot be applied\n");
-		goto err;
-	}
-err:
+
 	mutex_unlock(&hdmi.hdmi_lock);
 	return r;
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 09/12] OMAP: DSS2: HDMI: implement detect()
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Implement detect() by checking the hot plug detect status.

The implementation is not very good, as it always turns on the HDMI
output to get the detection working. HDMI driver needs improvements so
that we could enable only core parts of it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.h              |    1 +
 drivers/video/omap2/dss/hdmi.c             |   18 ++++++++++++++++++
 drivers/video/omap2/dss/hdmi_omap4_panel.c |   25 +++++++++++++++++++++++++
 3 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6102b80..dd7dc19 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -493,6 +493,7 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 					struct omap_video_timings *timings);
 int omapdss_hdmi_read_edid(u8 *buf, int len);
+bool omapdss_hdmi_detect(void);
 int hdmi_panel_init(void);
 void hdmi_panel_exit(void);
 
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 55edbd2..e8a977e 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1148,6 +1148,24 @@ int omapdss_hdmi_read_edid(u8 *buf, int len)
 	return r;
 }
 
+bool omapdss_hdmi_detect(void)
+{
+	int r;
+
+	mutex_lock(&hdmi.lock);
+
+	r = hdmi_runtime_get();
+	BUG_ON(r);
+
+	/* HPD */
+	r = REG_GET(HDMI_CORE_SYS_SYS_STAT, 1, 1);
+
+	hdmi_runtime_put();
+	mutex_unlock(&hdmi.lock);
+
+	return r = 1;
+}
+
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 {
 	int r = 0;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index ffea8d3..c859421 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -25,6 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <video/omapdss.h>
+#include <linux/slab.h>
 
 #include "dss.h"
 
@@ -198,6 +199,29 @@ err:
 	return r;
 }
 
+static bool hdmi_detect(struct omap_dss_device *dssdev)
+{
+	int r;
+
+	mutex_lock(&hdmi.hdmi_lock);
+
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+		r = omapdss_hdmi_display_enable(dssdev);
+		if (r)
+			goto err;
+	}
+
+	r = omapdss_hdmi_detect();
+
+	if (dssdev->state = OMAP_DSS_DISPLAY_DISABLED ||
+			dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED)
+		omapdss_hdmi_display_disable(dssdev);
+err:
+	mutex_unlock(&hdmi.hdmi_lock);
+
+	return r;
+}
+
 static struct omap_dss_driver hdmi_driver = {
 	.probe		= hdmi_panel_probe,
 	.remove		= hdmi_panel_remove,
@@ -209,6 +233,7 @@ static struct omap_dss_driver hdmi_driver = {
 	.set_timings	= hdmi_set_timings,
 	.check_timings	= hdmi_check_timings,
 	.read_edid	= hdmi_read_edid,
+	.detect		= hdmi_detect,
 	.driver			= {
 		.name   = "hdmi_panel",
 		.owner  = THIS_MODULE,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 09/12] OMAP: DSS2: HDMI: implement detect()
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Implement detect() by checking the hot plug detect status.

The implementation is not very good, as it always turns on the HDMI
output to get the detection working. HDMI driver needs improvements so
that we could enable only core parts of it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.h              |    1 +
 drivers/video/omap2/dss/hdmi.c             |   18 ++++++++++++++++++
 drivers/video/omap2/dss/hdmi_omap4_panel.c |   25 +++++++++++++++++++++++++
 3 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6102b80..dd7dc19 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -493,6 +493,7 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 					struct omap_video_timings *timings);
 int omapdss_hdmi_read_edid(u8 *buf, int len);
+bool omapdss_hdmi_detect(void);
 int hdmi_panel_init(void);
 void hdmi_panel_exit(void);
 
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 55edbd2..e8a977e 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1148,6 +1148,24 @@ int omapdss_hdmi_read_edid(u8 *buf, int len)
 	return r;
 }
 
+bool omapdss_hdmi_detect(void)
+{
+	int r;
+
+	mutex_lock(&hdmi.lock);
+
+	r = hdmi_runtime_get();
+	BUG_ON(r);
+
+	/* HPD */
+	r = REG_GET(HDMI_CORE_SYS_SYS_STAT, 1, 1);
+
+	hdmi_runtime_put();
+	mutex_unlock(&hdmi.lock);
+
+	return r == 1;
+}
+
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 {
 	int r = 0;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index ffea8d3..c859421 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -25,6 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <video/omapdss.h>
+#include <linux/slab.h>
 
 #include "dss.h"
 
@@ -198,6 +199,29 @@ err:
 	return r;
 }
 
+static bool hdmi_detect(struct omap_dss_device *dssdev)
+{
+	int r;
+
+	mutex_lock(&hdmi.hdmi_lock);
+
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+		r = omapdss_hdmi_display_enable(dssdev);
+		if (r)
+			goto err;
+	}
+
+	r = omapdss_hdmi_detect();
+
+	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+			dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+		omapdss_hdmi_display_disable(dssdev);
+err:
+	mutex_unlock(&hdmi.hdmi_lock);
+
+	return r;
+}
+
 static struct omap_dss_driver hdmi_driver = {
 	.probe		= hdmi_panel_probe,
 	.remove		= hdmi_panel_remove,
@@ -209,6 +233,7 @@ static struct omap_dss_driver hdmi_driver = {
 	.set_timings	= hdmi_set_timings,
 	.check_timings	= hdmi_check_timings,
 	.read_edid	= hdmi_read_edid,
+	.detect		= hdmi_detect,
 	.driver			= {
 		.name   = "hdmi_panel",
 		.owner  = THIS_MODULE,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 10/12] OMAP: DSS2: Generic-dpi: add detect & read_edid support
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Add i2c_bus_num field to panel_generic_dpi_data, and use it in the
panel-generic-dpi.c to detect if a panel is connected and to read EDID
from the panel.

Original by: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-generic-dpi.c |   92 ++++++++++++++++++++++
 include/video/omap-panel-generic-dpi.h           |    2 +
 2 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 9c90f75..6ef36ad 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -34,6 +34,8 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <video/omapdss.h>
+#include <linux/i2c.h>
+#include <drm/drm_edid.h>
 
 #include <video/omap-panel-generic-dpi.h>
 
@@ -407,6 +409,93 @@ static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
 	return dpi_check_timings(dssdev, timings);
 }
 
+
+static int generic_dpi_ddc_read(struct i2c_adapter *adapter,
+		unsigned char *buf, u16 count, u8 offset)
+{
+	int r, retries;
+
+	for (retries = 3; retries > 0; retries--) {
+		struct i2c_msg msgs[] = {
+			{
+				.addr   = DDC_ADDR,
+				.flags  = 0,
+				.len    = 1,
+				.buf    = &offset,
+			}, {
+				.addr   = DDC_ADDR,
+				.flags  = I2C_M_RD,
+				.len    = count,
+				.buf    = buf,
+			}
+		};
+
+		r = i2c_transfer(adapter, msgs, 2);
+		if (r = 2)
+			return 0;
+
+		if (r != -EAGAIN)
+			break;
+	}
+
+	return r < 0 ? r : -EIO;
+}
+
+static int generic_dpi_panel_read_edid(struct omap_dss_device *dssdev,
+		u8 *edid, int len)
+{
+	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
+	struct i2c_adapter *adapter;
+	int r, l, bytes_read;
+
+	if (panel_data->i2c_bus_num = 0)
+		return -ENODEV;
+
+	adapter = i2c_get_adapter(panel_data->i2c_bus_num);
+	if (!adapter) {
+		dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
+				panel_data->i2c_bus_num);
+		return -EINVAL;
+	}
+
+	l = min(EDID_LENGTH, len);
+	r = generic_dpi_ddc_read(adapter, edid, l, 0);
+	if (r)
+		return r;
+
+	bytes_read = l;
+
+	/* if there are extensions, read second block */
+	if (len > EDID_LENGTH && edid[0x7e] > 0) {
+		l = min(EDID_LENGTH, len - EDID_LENGTH);
+
+		r = generic_dpi_ddc_read(adapter, edid + EDID_LENGTH,
+				l, EDID_LENGTH);
+		if (r)
+			return r;
+
+		bytes_read += l;
+	}
+
+	return bytes_read;
+}
+
+static bool generic_dpi_panel_detect(struct omap_dss_device *dssdev)
+{
+	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
+	struct i2c_adapter *adapter;
+	unsigned char out;
+
+	if (panel_data->i2c_bus_num = 0)
+		return true;
+
+	adapter = i2c_get_adapter(panel_data->i2c_bus_num);
+	if (!adapter)
+		return true;
+
+	return generic_dpi_ddc_read(adapter, &out, 1, 0) = 0;
+}
+
 static struct omap_dss_driver dpi_driver = {
 	.probe		= generic_dpi_panel_probe,
 	.remove		= __exit_p(generic_dpi_panel_remove),
@@ -420,6 +509,9 @@ static struct omap_dss_driver dpi_driver = {
 	.get_timings	= generic_dpi_panel_get_timings,
 	.check_timings	= generic_dpi_panel_check_timings,
 
+	.read_edid	= generic_dpi_panel_read_edid,
+	.detect		= generic_dpi_panel_detect,
+
 	.driver         = {
 		.name   = "generic_dpi_panel",
 		.owner  = THIS_MODULE,
diff --git a/include/video/omap-panel-generic-dpi.h b/include/video/omap-panel-generic-dpi.h
index 127e3f2..3ab023a 100644
--- a/include/video/omap-panel-generic-dpi.h
+++ b/include/video/omap-panel-generic-dpi.h
@@ -27,11 +27,13 @@ struct omap_dss_device;
  * @name: panel name
  * @platform_enable: platform specific panel enable function
  * @platform_disable: platform specific panel disable function
+ * @i2c_bus_num: i2c bus id for the panel
  */
 struct panel_generic_dpi_data {
 	const char *name;
 	int (*platform_enable)(struct omap_dss_device *dssdev);
 	void (*platform_disable)(struct omap_dss_device *dssdev);
+	u16 i2c_bus_num;
 };
 
 #endif /* __OMAP_PANEL_GENERIC_DPI_H */
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 10/12] OMAP: DSS2: Generic-dpi: add detect & read_edid support
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Add i2c_bus_num field to panel_generic_dpi_data, and use it in the
panel-generic-dpi.c to detect if a panel is connected and to read EDID
from the panel.

Original by: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-generic-dpi.c |   92 ++++++++++++++++++++++
 include/video/omap-panel-generic-dpi.h           |    2 +
 2 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 9c90f75..6ef36ad 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -34,6 +34,8 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <video/omapdss.h>
+#include <linux/i2c.h>
+#include <drm/drm_edid.h>
 
 #include <video/omap-panel-generic-dpi.h>
 
@@ -407,6 +409,93 @@ static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
 	return dpi_check_timings(dssdev, timings);
 }
 
+
+static int generic_dpi_ddc_read(struct i2c_adapter *adapter,
+		unsigned char *buf, u16 count, u8 offset)
+{
+	int r, retries;
+
+	for (retries = 3; retries > 0; retries--) {
+		struct i2c_msg msgs[] = {
+			{
+				.addr   = DDC_ADDR,
+				.flags  = 0,
+				.len    = 1,
+				.buf    = &offset,
+			}, {
+				.addr   = DDC_ADDR,
+				.flags  = I2C_M_RD,
+				.len    = count,
+				.buf    = buf,
+			}
+		};
+
+		r = i2c_transfer(adapter, msgs, 2);
+		if (r == 2)
+			return 0;
+
+		if (r != -EAGAIN)
+			break;
+	}
+
+	return r < 0 ? r : -EIO;
+}
+
+static int generic_dpi_panel_read_edid(struct omap_dss_device *dssdev,
+		u8 *edid, int len)
+{
+	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
+	struct i2c_adapter *adapter;
+	int r, l, bytes_read;
+
+	if (panel_data->i2c_bus_num == 0)
+		return -ENODEV;
+
+	adapter = i2c_get_adapter(panel_data->i2c_bus_num);
+	if (!adapter) {
+		dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
+				panel_data->i2c_bus_num);
+		return -EINVAL;
+	}
+
+	l = min(EDID_LENGTH, len);
+	r = generic_dpi_ddc_read(adapter, edid, l, 0);
+	if (r)
+		return r;
+
+	bytes_read = l;
+
+	/* if there are extensions, read second block */
+	if (len > EDID_LENGTH && edid[0x7e] > 0) {
+		l = min(EDID_LENGTH, len - EDID_LENGTH);
+
+		r = generic_dpi_ddc_read(adapter, edid + EDID_LENGTH,
+				l, EDID_LENGTH);
+		if (r)
+			return r;
+
+		bytes_read += l;
+	}
+
+	return bytes_read;
+}
+
+static bool generic_dpi_panel_detect(struct omap_dss_device *dssdev)
+{
+	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
+	struct i2c_adapter *adapter;
+	unsigned char out;
+
+	if (panel_data->i2c_bus_num == 0)
+		return true;
+
+	adapter = i2c_get_adapter(panel_data->i2c_bus_num);
+	if (!adapter)
+		return true;
+
+	return generic_dpi_ddc_read(adapter, &out, 1, 0) == 0;
+}
+
 static struct omap_dss_driver dpi_driver = {
 	.probe		= generic_dpi_panel_probe,
 	.remove		= __exit_p(generic_dpi_panel_remove),
@@ -420,6 +509,9 @@ static struct omap_dss_driver dpi_driver = {
 	.get_timings	= generic_dpi_panel_get_timings,
 	.check_timings	= generic_dpi_panel_check_timings,
 
+	.read_edid	= generic_dpi_panel_read_edid,
+	.detect		= generic_dpi_panel_detect,
+
 	.driver         = {
 		.name   = "generic_dpi_panel",
 		.owner  = THIS_MODULE,
diff --git a/include/video/omap-panel-generic-dpi.h b/include/video/omap-panel-generic-dpi.h
index 127e3f2..3ab023a 100644
--- a/include/video/omap-panel-generic-dpi.h
+++ b/include/video/omap-panel-generic-dpi.h
@@ -27,11 +27,13 @@ struct omap_dss_device;
  * @name: panel name
  * @platform_enable: platform specific panel enable function
  * @platform_disable: platform specific panel disable function
+ * @i2c_bus_num: i2c bus id for the panel
  */
 struct panel_generic_dpi_data {
 	const char *name;
 	int (*platform_enable)(struct omap_dss_device *dssdev);
 	void (*platform_disable)(struct omap_dss_device *dssdev);
+	u16 i2c_bus_num;
 };
 
 #endif /* __OMAP_PANEL_GENERIC_DPI_H */
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Add i2c bus number for DVI output. The driver uses this to detect if a
panel is connected and to read EDID.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/board-omap3beagle.c |    1 +
 arch/arm/mach-omap2/board-omap4panda.c  |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 3ae16b4..13244e9 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
 	.name = "generic",
 	.platform_enable = beagle_enable_dvi,
 	.platform_disable = beagle_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 static struct omap_dss_device beagle_dvi_device = {
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 9aaa960..d5760e3 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
 	.name			= "generic",
 	.platform_enable	= omap4_panda_enable_dvi,
 	.platform_disable	= omap4_panda_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 struct omap_dss_device omap4_panda_dvi_device = {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Add i2c bus number for DVI output. The driver uses this to detect if a
panel is connected and to read EDID.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/board-omap3beagle.c |    1 +
 arch/arm/mach-omap2/board-omap4panda.c  |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 3ae16b4..13244e9 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
 	.name = "generic",
 	.platform_enable = beagle_enable_dvi,
 	.platform_disable = beagle_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 static struct omap_dss_device beagle_dvi_device = {
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 9aaa960..d5760e3 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
 	.name			= "generic",
 	.platform_enable	= omap4_panda_enable_dvi,
 	.platform_disable	= omap4_panda_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 struct omap_dss_device omap4_panda_dvi_device = {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 12/12] OMAPFB: find best mode from edid
  2011-08-31 13:23 ` Tomi Valkeinen
@ 2011-08-31 13:23   ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Use the new read_edid() function to get EDID information from the
display (when available), and use the information to use a suitable mode
at initialization time.

Hot-plug is not yet supported, so the timings selected at init time will
stay even if the monitor would be changed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/omapfb/omapfb-main.c |  109 +++++++++++++++++++++++++++---
 1 files changed, 99 insertions(+), 10 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index cd2cae8e..c84cc29 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2276,6 +2276,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
 	return r;
 }
 
+static void fb_videomode_to_omap_timings(struct fb_videomode *m,
+		struct omap_video_timings *t)
+{
+	t->x_res = m->xres;
+	t->y_res = m->yres;
+	t->pixel_clock = PICOS2KHZ(m->pixclock);
+	t->hsw = m->hsync_len;
+	t->hfp = m->right_margin;
+	t->hbp = m->left_margin;
+	t->vsw = m->vsync_len;
+	t->vfp = m->lower_margin;
+	t->vbp = m->upper_margin;
+}
+
+static int omapfb_find_best_mode(struct omap_dss_device *display,
+		struct omap_video_timings *timings)
+{
+	struct fb_monspecs *specs;
+	u8 *edid;
+	int r, i, best_xres, best_idx, len;
+
+	if (!display->driver->read_edid)
+		return -ENODEV;
+
+	len = 0x80 * 2;
+	edid = kmalloc(len, GFP_KERNEL);
+
+	r = display->driver->read_edid(display, edid, len);
+	if (r < 0)
+		goto err1;
+
+	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+
+	fb_edid_to_monspecs(edid, specs);
+
+	if (edid[126] > 0)
+		fb_edid_add_monspecs(edid + 0x80, specs);
+
+	best_xres = 0;
+	best_idx = -1;
+
+	for (i = 0; i < specs->modedb_len; ++i) {
+		struct fb_videomode *m;
+		struct omap_video_timings t;
+
+		m = &specs->modedb[i];
+
+		if (m->pixclock = 0)
+			continue;
+
+		/* skip repeated pixel modes */
+		if (m->xres = 2880 || m->xres = 1440)
+			continue;
+
+		fb_videomode_to_omap_timings(m, &t);
+
+		r = display->driver->check_timings(display, &t);
+		if (r = 0 && best_xres < m->xres) {
+			best_xres = m->xres;
+			best_idx = i;
+		}
+	}
+
+	if (best_xres = 0) {
+		r = -ENOENT;
+		goto err2;
+	}
+
+	fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
+
+	r = 0;
+
+err2:
+	fb_destroy_modedb(specs->modedb);
+	kfree(specs);
+err1:
+	kfree(edid);
+
+	return r;
+}
+
 static int omapfb_init_display(struct omapfb2_device *fbdev,
 		struct omap_dss_device *dssdev)
 {
@@ -2404,9 +2485,27 @@ static int omapfb_probe(struct platform_device *pdev)
 	for (i = 0; i < fbdev->num_managers; i++)
 		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
 
+	/* gfx overlay should be the default one. find a display
+	 * connected to that, and use it as default display */
+	ovl = omap_dss_get_overlay(0);
+	if (ovl->manager && ovl->manager->device) {
+		def_display = ovl->manager->device;
+	} else {
+		dev_warn(&pdev->dev, "cannot find default display\n");
+		def_display = NULL;
+	}
+
 	if (def_mode && strlen(def_mode) > 0) {
 		if (omapfb_parse_def_modes(fbdev))
 			dev_warn(&pdev->dev, "cannot parse default modes\n");
+	} else if (def_display && def_display->driver->set_timings &&
+			def_display->driver->check_timings) {
+		struct omap_video_timings t;
+
+		r = omapfb_find_best_mode(def_display, &t);
+
+		if (r = 0)
+			def_display->driver->set_timings(def_display, &t);
 	}
 
 	r = omapfb_create_framebuffers(fbdev);
@@ -2423,16 +2522,6 @@ static int omapfb_probe(struct platform_device *pdev)
 
 	DBG("mgr->apply'ed\n");
 
-	/* gfx overlay should be the default one. find a display
-	 * connected to that, and use it as default display */
-	ovl = omap_dss_get_overlay(0);
-	if (ovl->manager && ovl->manager->device) {
-		def_display = ovl->manager->device;
-	} else {
-		dev_warn(&pdev->dev, "cannot find default display\n");
-		def_display = NULL;
-	}
-
 	if (def_display) {
 		r = omapfb_init_display(fbdev, def_display);
 		if (r) {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 12/12] OMAPFB: find best mode from edid
@ 2011-08-31 13:23   ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Use the new read_edid() function to get EDID information from the
display (when available), and use the information to use a suitable mode
at initialization time.

Hot-plug is not yet supported, so the timings selected at init time will
stay even if the monitor would be changed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/omapfb/omapfb-main.c |  109 +++++++++++++++++++++++++++---
 1 files changed, 99 insertions(+), 10 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index cd2cae8e..c84cc29 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2276,6 +2276,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
 	return r;
 }
 
+static void fb_videomode_to_omap_timings(struct fb_videomode *m,
+		struct omap_video_timings *t)
+{
+	t->x_res = m->xres;
+	t->y_res = m->yres;
+	t->pixel_clock = PICOS2KHZ(m->pixclock);
+	t->hsw = m->hsync_len;
+	t->hfp = m->right_margin;
+	t->hbp = m->left_margin;
+	t->vsw = m->vsync_len;
+	t->vfp = m->lower_margin;
+	t->vbp = m->upper_margin;
+}
+
+static int omapfb_find_best_mode(struct omap_dss_device *display,
+		struct omap_video_timings *timings)
+{
+	struct fb_monspecs *specs;
+	u8 *edid;
+	int r, i, best_xres, best_idx, len;
+
+	if (!display->driver->read_edid)
+		return -ENODEV;
+
+	len = 0x80 * 2;
+	edid = kmalloc(len, GFP_KERNEL);
+
+	r = display->driver->read_edid(display, edid, len);
+	if (r < 0)
+		goto err1;
+
+	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+
+	fb_edid_to_monspecs(edid, specs);
+
+	if (edid[126] > 0)
+		fb_edid_add_monspecs(edid + 0x80, specs);
+
+	best_xres = 0;
+	best_idx = -1;
+
+	for (i = 0; i < specs->modedb_len; ++i) {
+		struct fb_videomode *m;
+		struct omap_video_timings t;
+
+		m = &specs->modedb[i];
+
+		if (m->pixclock == 0)
+			continue;
+
+		/* skip repeated pixel modes */
+		if (m->xres == 2880 || m->xres == 1440)
+			continue;
+
+		fb_videomode_to_omap_timings(m, &t);
+
+		r = display->driver->check_timings(display, &t);
+		if (r == 0 && best_xres < m->xres) {
+			best_xres = m->xres;
+			best_idx = i;
+		}
+	}
+
+	if (best_xres == 0) {
+		r = -ENOENT;
+		goto err2;
+	}
+
+	fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
+
+	r = 0;
+
+err2:
+	fb_destroy_modedb(specs->modedb);
+	kfree(specs);
+err1:
+	kfree(edid);
+
+	return r;
+}
+
 static int omapfb_init_display(struct omapfb2_device *fbdev,
 		struct omap_dss_device *dssdev)
 {
@@ -2404,9 +2485,27 @@ static int omapfb_probe(struct platform_device *pdev)
 	for (i = 0; i < fbdev->num_managers; i++)
 		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
 
+	/* gfx overlay should be the default one. find a display
+	 * connected to that, and use it as default display */
+	ovl = omap_dss_get_overlay(0);
+	if (ovl->manager && ovl->manager->device) {
+		def_display = ovl->manager->device;
+	} else {
+		dev_warn(&pdev->dev, "cannot find default display\n");
+		def_display = NULL;
+	}
+
 	if (def_mode && strlen(def_mode) > 0) {
 		if (omapfb_parse_def_modes(fbdev))
 			dev_warn(&pdev->dev, "cannot parse default modes\n");
+	} else if (def_display && def_display->driver->set_timings &&
+			def_display->driver->check_timings) {
+		struct omap_video_timings t;
+
+		r = omapfb_find_best_mode(def_display, &t);
+
+		if (r == 0)
+			def_display->driver->set_timings(def_display, &t);
 	}
 
 	r = omapfb_create_framebuffers(fbdev);
@@ -2423,16 +2522,6 @@ static int omapfb_probe(struct platform_device *pdev)
 
 	DBG("mgr->apply'ed\n");
 
-	/* gfx overlay should be the default one. find a display
-	 * connected to that, and use it as default display */
-	ovl = omap_dss_get_overlay(0);
-	if (ovl->manager && ovl->manager->device) {
-		def_display = ovl->manager->device;
-	} else {
-		dev_warn(&pdev->dev, "cannot find default display\n");
-		def_display = NULL;
-	}
-
 	if (def_display) {
 		r = omapfb_init_display(fbdev, def_display);
 		if (r) {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
  2011-08-31 13:23   ` Tomi Valkeinen
@ 2011-08-31 15:00     ` Andy Doan
  -1 siblings, 0 replies; 30+ messages in thread
From: Andy Doan @ 2011-08-31 15:00 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, archit, mythripk

On 08/31/2011 08:23 AM, Tomi Valkeinen wrote:
> Add i2c bus number for DVI output. The driver uses this to detect if a
> panel is connected and to read EDID.
>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>   arch/arm/mach-omap2/board-omap4panda.c  |    1 +
>   2 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> index 3ae16b4..13244e9 100644
> --- a/arch/arm/mach-omap2/board-omap3beagle.c
> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> @@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
>   	.name = "generic",
>   	.platform_enable = beagle_enable_dvi,
>   	.platform_disable = beagle_disable_dvi,
> +	.i2c_bus_num = 3,
>   };
>
>   static struct omap_dss_device beagle_dvi_device = {
> diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
> index 9aaa960..d5760e3 100644
> --- a/arch/arm/mach-omap2/board-omap4panda.c
> +++ b/arch/arm/mach-omap2/board-omap4panda.c
> @@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
>   	.name			= "generic",
>   	.platform_enable	= omap4_panda_enable_dvi,
>   	.platform_disable	= omap4_panda_disable_dvi,
> +	.i2c_bus_num = 3,
>   };
>
>   struct omap_dss_device omap4_panda_dvi_device = {

Can you add a similar patch for board-overo.c? I've tested earlier 
versions of this patch series on a Tide+Tobi successfully. Here's a copy 
of my patch:

   http://tinyurl.com/3cek5m7


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
@ 2011-08-31 15:00     ` Andy Doan
  0 siblings, 0 replies; 30+ messages in thread
From: Andy Doan @ 2011-08-31 15:00 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, archit, mythripk

On 08/31/2011 08:23 AM, Tomi Valkeinen wrote:
> Add i2c bus number for DVI output. The driver uses this to detect if a
> panel is connected and to read EDID.
>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>   arch/arm/mach-omap2/board-omap4panda.c  |    1 +
>   2 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> index 3ae16b4..13244e9 100644
> --- a/arch/arm/mach-omap2/board-omap3beagle.c
> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> @@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
>   	.name = "generic",
>   	.platform_enable = beagle_enable_dvi,
>   	.platform_disable = beagle_disable_dvi,
> +	.i2c_bus_num = 3,
>   };
>
>   static struct omap_dss_device beagle_dvi_device = {
> diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
> index 9aaa960..d5760e3 100644
> --- a/arch/arm/mach-omap2/board-omap4panda.c
> +++ b/arch/arm/mach-omap2/board-omap4panda.c
> @@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
>   	.name			= "generic",
>   	.platform_enable	= omap4_panda_enable_dvi,
>   	.platform_disable	= omap4_panda_disable_dvi,
> +	.i2c_bus_num = 3,
>   };
>
>   struct omap_dss_device omap4_panda_dvi_device = {

Can you add a similar patch for board-overo.c? I've tested earlier 
versions of this patch series on a Tide+Tobi successfully. Here's a copy 
of my patch:

   http://tinyurl.com/3cek5m7


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
  2011-08-31 15:00     ` Andy Doan
@ 2011-08-31 18:09       ` Tomi Valkeinen
  -1 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 18:09 UTC (permalink / raw)
  To: Andy Doan; +Cc: linux-omap, linux-fbdev, archit, mythripk

On Wed, 2011-08-31 at 10:00 -0500, Andy Doan wrote:
> On 08/31/2011 08:23 AM, Tomi Valkeinen wrote:
> > Add i2c bus number for DVI output. The driver uses this to detect if a
> > panel is connected and to read EDID.
> >
> > Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> > ---
> >   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
> >   arch/arm/mach-omap2/board-omap4panda.c  |    1 +
> >   2 files changed, 2 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> > index 3ae16b4..13244e9 100644
> > --- a/arch/arm/mach-omap2/board-omap3beagle.c
> > +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> > @@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
> >   	.name = "generic",
> >   	.platform_enable = beagle_enable_dvi,
> >   	.platform_disable = beagle_disable_dvi,
> > +	.i2c_bus_num = 3,
> >   };
> >
> >   static struct omap_dss_device beagle_dvi_device = {
> > diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
> > index 9aaa960..d5760e3 100644
> > --- a/arch/arm/mach-omap2/board-omap4panda.c
> > +++ b/arch/arm/mach-omap2/board-omap4panda.c
> > @@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
> >   	.name			= "generic",
> >   	.platform_enable	= omap4_panda_enable_dvi,
> >   	.platform_disable	= omap4_panda_disable_dvi,
> > +	.i2c_bus_num = 3,
> >   };
> >
> >   struct omap_dss_device omap4_panda_dvi_device = {
> 
> Can you add a similar patch for board-overo.c? I've tested earlier 
> versions of this patch series on a Tide+Tobi successfully. Here's a copy 
> of my patch:
> 
>    http://tinyurl.com/3cek5m7

Sure. I only added the boards I know have the ddc i2c on bus 3 (i.e.
those I was able to test).

 Tomi



^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
@ 2011-08-31 18:09       ` Tomi Valkeinen
  0 siblings, 0 replies; 30+ messages in thread
From: Tomi Valkeinen @ 2011-08-31 18:09 UTC (permalink / raw)
  To: Andy Doan; +Cc: linux-omap, linux-fbdev, archit, mythripk

On Wed, 2011-08-31 at 10:00 -0500, Andy Doan wrote:
> On 08/31/2011 08:23 AM, Tomi Valkeinen wrote:
> > Add i2c bus number for DVI output. The driver uses this to detect if a
> > panel is connected and to read EDID.
> >
> > Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> > ---
> >   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
> >   arch/arm/mach-omap2/board-omap4panda.c  |    1 +
> >   2 files changed, 2 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> > index 3ae16b4..13244e9 100644
> > --- a/arch/arm/mach-omap2/board-omap3beagle.c
> > +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> > @@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
> >   	.name = "generic",
> >   	.platform_enable = beagle_enable_dvi,
> >   	.platform_disable = beagle_disable_dvi,
> > +	.i2c_bus_num = 3,
> >   };
> >
> >   static struct omap_dss_device beagle_dvi_device = {
> > diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
> > index 9aaa960..d5760e3 100644
> > --- a/arch/arm/mach-omap2/board-omap4panda.c
> > +++ b/arch/arm/mach-omap2/board-omap4panda.c
> > @@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
> >   	.name			= "generic",
> >   	.platform_enable	= omap4_panda_enable_dvi,
> >   	.platform_disable	= omap4_panda_disable_dvi,
> > +	.i2c_bus_num = 3,
> >   };
> >
> >   struct omap_dss_device omap4_panda_dvi_device = {
> 
> Can you add a similar patch for board-overo.c? I've tested earlier 
> versions of this patch series on a Tide+Tobi successfully. Here's a copy 
> of my patch:
> 
>    http://tinyurl.com/3cek5m7

Sure. I only added the boards I know have the ddc i2c on bus 3 (i.e.
those I was able to test).

 Tomi



^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2011-08-31 18:09 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-31 13:23 [PATCH 00/12] OMAP: DSS2: EDID & detect support Tomi Valkeinen
2011-08-31 13:23 ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 01/12] OMAP: DSS2: add read_edid() to omap_dss_driver struct Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 02/12] OMAP: DSS2: add detect() " Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 03/12] OMAP: DSS2: HDMI: make set_timing saner Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 04/12] OMAP: DSS2: HDMI: implement read_edid() Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 05/12] OMAP: DSS2: HDMI: remove edid parsing Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 06/12] OMAP: DSS2: HDMI: split hdmi_core_ddc_edid Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 07/12] OMAP: DSS2: HDMI: clean up edid reading & fix checksum Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 08/12] OMAP: DSS2: HDMI: remove error prints in check_timings Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 09/12] OMAP: DSS2: HDMI: implement detect() Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 10/12] OMAP: DSS2: Generic-dpi: add detect & read_edid support Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen
2011-08-31 15:00   ` Andy Doan
2011-08-31 15:00     ` Andy Doan
2011-08-31 18:09     ` Tomi Valkeinen
2011-08-31 18:09       ` Tomi Valkeinen
2011-08-31 13:23 ` [PATCH 12/12] OMAPFB: find best mode from edid Tomi Valkeinen
2011-08-31 13:23   ` Tomi Valkeinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.