Skip to contentSkip to conversation

video: Add / fix videomodes modes, use for sunxi, enable EDID on sunxi

PATCH New Hans de Goede 3 participants 29 messages Dec 19, 2014 – Jan 8, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v2 cover video: Add / fix videomodes modes, use for sunxi, enable EDID on sunxi

Hi Anatolij & Ian,

Here is v2 of my patch-series to make the video-mode configurable on sunxi and use EDID where available.

In version 2 I've switched to using the existing infra in videomodes.c as much as possible, including using the standard video-mode env. variable, and the existing functions to parse it.

Anatolij this series starts with a bunch of fixes / additions to videomodes.c, can you please review (and ack :) these ? Since the only user of the new functionality is sunxi code I would like to take these upstream through u-boot-sunxi/next if that is ok with you, but I do need your ack for them before merging them there.

Ian, can you review the sunxi specific patches ?

Thanks & Regards,

Hans

#1 lore raw

PATCH v2 1/11 videomodes: Add pixelclock_khz and refresh fields to ctfb_res_modes

Add pixelclock_khz and refresh fields to ctfb_res_modes:

1) pixelclocks are usually referred to in hz, not picoseconds, and e.g pll-s are also typically programmed in hz, not ps. Converting between the 2 leads to rounding differences, add a pixelclock_khz field to directly store the *exact* pixelclock for a mode, so that drivers do not need to resort to rounding tricks to try and guess the exact pixelclock;

2) The video-mode environment variable, as parsed by video_get_video_mode also contains the vertical refresh rate, add a refresh field, so that the refresh-rate can be matched when parsing the video-mode environment variable.

---
 drivers/video/videomodes.c | 14 +++++++-------
 drivers/video/videomodes.h |  2 ++
 2 files changed, 9 insertions(+), 7 deletions(-)
drivers/video/videomodes.c +7 -7
index 18c1f3d..8f8a919 100644
@@ -84,13 +84,13 @@ const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
 	{0x31B, RES_MODE_1280x1024, 24},
 };
 const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
-	/* x	 y pixclk   le	ri  up	lo   hs vs  s  vmode */
-	{640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED},
-	{800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},
-	{1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED},
-	{960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED},
-	{1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED},
-	{1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED},
+	/*  x     y  hz  pixclk ps/kHz   le   ri  up  lo   hs vs  s  vmode */
+	{ 640,  480, 60, 39721,  25180,  40,  24, 32, 11,  96, 2, 0, FB_VMODE_NONINTERLACED},
+	{ 800,  600, 60, 27778,  36000,  64,  24, 22,  1,  72, 2, 0, FB_VMODE_NONINTERLACED},
+	{1024,  768, 60, 15384,  65000, 168,   8, 29,  3, 144, 4, 0, FB_VMODE_NONINTERLACED},
+	{ 960,  720, 80, 13100,  76335, 160,  40, 32,  8,  80, 4, 0, FB_VMODE_NONINTERLACED},
+	{1152,  864, 60, 12004,  83300, 200,  64, 32, 16,  80, 4, 0, FB_VMODE_NONINTERLACED},
+	{1280, 1024, 60,  9090, 110000, 200,  48, 26,  1, 184, 3, 0, FB_VMODE_NONINTERLACED},
 };
 
 /************************************************************************
drivers/video/videomodes.h +2 -0
index d83993a..94b13e6 100644
@@ -35,8 +35,10 @@
 struct ctfb_res_modes {
 	int xres;		/* visible resolution		*/
 	int yres;
+	int refresh;		/* vertical refresh rate in hz  */
 	/* Timing: All values in pixclocks, except pixclock (of course) */
 	int pixclock;		/* pixel clock in ps (pico seconds) */
+	int pixclock_khz;	/* pixel clock in kHz           */
 	int left_margin;	/* time from sync to picture	*/
 	int right_margin;	/* time from picture to sync	*/
 	int upper_margin;	/* time from sync to picture	*/
Signature · 1 line
2.1.0
#2 lore raw

PATCH v2 1/11 videomodes: Add pixelclock_khz and refresh fields to ctfb_res_modes

Quoted 8 lines · On Fri, 19 Dec 2014 18:10:31 +0100 Hans de Goede <[email protected]> wrote:

Add pixelclock_khz and refresh fields to ctfb_res_modes:

1) pixelclocks are usually referred to in hz, not picoseconds, and e.g pll-s are also typically programmed in hz, not ps. Converting between the 2 leads to rounding differences, add a pixelclock_khz field to directly store the *exact* pixelclock for a mode, so that drivers do not need to resort to rounding tricks to try and guess the exact pixelclock;

Quoted 6 lines

2) The video-mode environment variable, as parsed by video_get_video_mode also contains the vertical refresh rate, add a refresh field, so that the refresh-rate can be matched when parsing the video-mode environment variable.

#3 lore raw

PATCH v2 2/11 videomodes: Add (vesa) standard timings

In reply to Hans de Goede

The timings for the modes defined in videomodes.c differ (significantly) from vesa standard timings for these modes.

This commit adds a version with the proper std timings for these modes, since I do not want to cause regressions, boards which want to use the standard timings need to define CONFIG_VIDEO_STD_TIMINGS to get the new correct timings.

Since there is no std timing for 960x720 this commit uses the timing used by the nvidia video drivers for 960x720, which uses a standard pixelclock of 74.25 MHz rather then the weird 76.335... clock used by the old modes.

---
 drivers/video/videomodes.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/video/videomodes.c +9 -0
index 8f8a919..a363482 100644
@@ -85,12 +85,21 @@ const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
 };
 const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
 	/*  x     y  hz  pixclk ps/kHz   le   ri  up  lo   hs vs  s  vmode */
+#ifndef CONFIG_VIDEO_STD_TIMINGS
 	{ 640,  480, 60, 39721,  25180,  40,  24, 32, 11,  96, 2, 0, FB_VMODE_NONINTERLACED},
 	{ 800,  600, 60, 27778,  36000,  64,  24, 22,  1,  72, 2, 0, FB_VMODE_NONINTERLACED},
 	{1024,  768, 60, 15384,  65000, 168,   8, 29,  3, 144, 4, 0, FB_VMODE_NONINTERLACED},
 	{ 960,  720, 80, 13100,  76335, 160,  40, 32,  8,  80, 4, 0, FB_VMODE_NONINTERLACED},
 	{1152,  864, 60, 12004,  83300, 200,  64, 32, 16,  80, 4, 0, FB_VMODE_NONINTERLACED},
 	{1280, 1024, 60,  9090, 110000, 200,  48, 26,  1, 184, 3, 0, FB_VMODE_NONINTERLACED},
+#else
+	{ 640,  480, 60, 39683,  25200,  48,  16, 33, 10,  96, 2, 0, FB_VMODE_NONINTERLACED},
+	{ 800,  600, 60, 25000,  40000,  88,  40, 23,  1, 128, 4, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
+	{1024,  768, 60, 15384,  65000, 160,  24, 29,  3, 136, 6, 0, FB_VMODE_NONINTERLACED},
+	{ 960,  720, 75, 13468,  74250, 176,  72, 27,  1, 112, 2, 0, FB_VMODE_NONINTERLACED},
+	{1152,  864, 75,  9259, 108000, 256,  64, 32,  1, 128, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
+	{1280, 1024, 60,  9259, 108000, 248,  48, 38,  1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
+#endif
 };
 
 /************************************************************************
Signature · 1 line
2.1.0
#4 lore raw

PATCH v2 2/11 videomodes: Add (vesa) standard timings

Quoted 7 lines · On Fri, 19 Dec 2014 18:10:32 +0100 Hans de Goede <[email protected]> wrote:

The timings for the modes defined in videomodes.c differ (significantly) from vesa standard timings for these modes.

This commit adds a version with the proper std timings for these modes, since I do not want to cause regressions, boards which want to use the standard timings need to define CONFIG_VIDEO_STD_TIMINGS to get the new correct timings.

Quoted 5 lines

Since there is no std timing for 960x720 this commit uses the timing used by the nvidia video drivers for 960x720, which uses a standard pixelclock of 74.25 MHz rather then the weird 76.335... clock used by the old modes.

#5 lore raw

PATCH v2 3/11 videomodes: Add a bunch of high res modes

In reply to Hans de Goede

Add modes useful for hd-tvs and modern monitors.

---
 drivers/video/videomodes.c | 4 ++++
 drivers/video/videomodes.h | 6 +++++-
 2 files changed, 9 insertions(+), 1 deletion(-)
drivers/video/videomodes.c +4 -0
index a363482..595ea3f 100644
@@ -100,6 +100,10 @@ const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
 	{1152,  864, 75,  9259, 108000, 256,  64, 32,  1, 128, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
 	{1280, 1024, 60,  9259, 108000, 248,  48, 38,  1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
 #endif
+	{1280,  720, 60, 13468,  74250, 220, 110, 20,  5,  40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
+	{1360,  768, 60, 11696,  85500, 256,  64, 17,  3, 112, 7, 0, FB_VMODE_NONINTERLACED},
+	{1920, 1080, 60,  6734, 148500, 148,  88, 36,  4,  44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
+	{1920, 1200, 60,  6494, 154000,  80,  48, 26,  3,  32, 6, FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED},
 };
 
 /************************************************************************
drivers/video/videomodes.h +5 -1
index 94b13e6..579c685 100644
@@ -64,7 +64,11 @@ struct ctfb_vesa_modes {
 #define RES_MODE_960_720	3
 #define RES_MODE_1152x864	4
 #define RES_MODE_1280x1024	5
-#define RES_MODES_COUNT		6
+#define RES_MODE_1280x720	6
+#define RES_MODE_1360x768	7
+#define RES_MODE_1920x1080	8
+#define RES_MODE_1920x1200	9
+#define RES_MODES_COUNT		10
 
 #define VESA_MODES_COUNT 19
 
Signature · 1 line
2.1.0
#7 lore raw

PATCH v2 4/11 videomodes: Add video_get_ctfb_res_modes helper function

In reply to Hans de Goede

Add a video_get_ctfb_res_modes() helper function, which uses video_get_video_mode() to parse the 'video-mode' environment variable and then looks up the matching mode in res_mode_init and returns the matching mode.

---
 drivers/video/videomodes.c | 40 ++++++++++++++++++++++++++++++++++++++++
 drivers/video/videomodes.h |  5 +++++
 2 files changed, 45 insertions(+)
drivers/video/videomodes.c +40 -0
index 595ea3f..72841fd 100644
@@ -273,3 +273,43 @@ int video_get_video_mode(unsigned int *xres, unsigned int *yres,
 
 	return 1;
 }
+
+/*
+ * Parse the 'video-mode' environment variable using video_get_video_mode()
+ * and lookup the matching ctfb_res_modes in res_mode_init.
+ *
+ * @default_mode: RES_MODE_##x## define for the mode to store in mode_ret
+ *   when 'video-mode' is not set or does not contain a valid mode
+ * @default_depth: depth to set when 'video-mode' is not set
+ * @mode_ret: pointer where the mode will be stored
+ * @depth_ret: pointer where the depth will be stored
+ * @options: pointer to any remaining options, or NULL
+ */
+void video_get_ctfb_res_modes(int default_mode, unsigned int default_depth,
+			      const struct ctfb_res_modes **mode_ret,
+			      unsigned int *depth_ret,
+			      const char **options)
+{
+	unsigned int i, xres, yres, depth, refresh;
+
+	*mode_ret = &res_mode_init[default_mode];
+	*depth_ret = default_depth;
+	*options = NULL;
+
+	if (!video_get_video_mode(&xres, &yres, &depth, &refresh, options))
+		return;
+
+	for (i = 0; i < RES_MODES_COUNT; i++) {
+		if (res_mode_init[i].xres == xres &&
+		    res_mode_init[i].yres == yres &&
+		    res_mode_init[i].refresh == refresh) {
+			*mode_ret = &res_mode_init[i];
+			*depth_ret = depth;
+			return;
+		}
+	}
+
+	printf("video-mode %dx%d-%d@%d not available, falling back to %dx%d-%d@%d\n",
+	       xres, yres, depth, refresh, (*mode_ret)->xres,
+	       (*mode_ret)->yres, *depth_ret, (*mode_ret)->refresh);
+}
drivers/video/videomodes.h +5 -0
index 579c685..02419cd 100644
@@ -79,3 +79,8 @@ int video_get_params (struct ctfb_res_modes *pPar, char *penv);
 
 int video_get_video_mode(unsigned int *xres, unsigned int *yres,
 	unsigned int *depth, unsigned int *freq, const char **options);
+
+void video_get_ctfb_res_modes(int default_mode, unsigned int default_depth,
+			      const struct ctfb_res_modes **mode_ret,
+			      unsigned int *depth_ret,
+			      const char **options);
Signature · 1 line
2.1.0
#8 lore raw

PATCH v2 4/11 videomodes: Add video_get_ctfb_res_modes helper function

Quoted 5 lines · On Fri, 19 Dec 2014 18:10:34 +0100 Hans de Goede <[email protected]> wrote:

Add a video_get_ctfb_res_modes() helper function, which uses video_get_video_mode() to parse the 'video-mode' environment variable and then looks up the matching mode in res_mode_init and returns the matching mode.

#9 lore raw

PATCH v2 5/11 videomodes: Add helper functions to parse video-mode env-var extra options

In reply to Hans de Goede

Add 2 helper functions to get strings, reps. ints from the options value returned by video_get_video_mode() / video_get_ctfb_res_modes().

---
 drivers/video/videomodes.c | 60 +++++++++++++++++++++++++++++++++++++++++++++-
 drivers/video/videomodes.h |  5 ++++
 2 files changed, 64 insertions(+), 1 deletion(-)
drivers/video/videomodes.c +59 -1
index 72841fd..1f79d5f 100644
@@ -113,7 +113,7 @@ const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
  * returns the length to the next seperator
  */
 static int
-video_get_param_len (char *start, char sep)
+video_get_param_len (const char *start, char sep)
 {
 	int i = 0;
 	while ((*start != 0) && (*start != sep)) {
@@ -313,3 +313,61 @@ void video_get_ctfb_res_modes(int default_mode, unsigned int default_depth,
 	       xres, yres, depth, refresh, (*mode_ret)->xres,
 	       (*mode_ret)->yres, *depth_ret, (*mode_ret)->refresh);
 }
+
+/*
+ * Find the named string option within the ',' seperated options string, and
+ * store its value in dest.
+ *
+ * @options: ',' seperated options string
+ * @name: name of the option to look for
+ * @dest: destination buffer to store the value of the option in
+ * @dest_len: length of dest
+ * @def: value to store in dest if the option is not present in options
+ */
+void video_get_option_string(const char *options, const char *name,
+			     char *dest, int dest_len, const char *def)
+{
+	const char *p = options;
+	const int name_len = strlen(name);
+	int i, len;
+
+	while (p && (i = video_get_param_len (p, ',')) != 0) {
+		if (strncmp(p, name, name_len) == 0 && p[name_len] == '=') {
+			len = i - (name_len + 1);
+			if (len >= dest_len)
+				len = dest_len - 1;
+			memcpy(dest, &p[name_len + 1], len);
+			dest[len] = 0;
+			return;
+		}
+		p += i;
+		if (*p != 0)
+			p++;	/* skip ',' */
+	}
+	strcpy(dest, def);
+}
+
+/*
+ * Find the named integer option within the ',' seperated options string, and
+ * return its value.
+ *
+ * @options: ',' seperated options string
+ * @name: name of the option to look for
+ * @def: value to return if the option is not present in options
+ */
+int video_get_option_int(const char *options, const char *name, int def)
+{
+	const char *p = options;
+	const int name_len = strlen(name);
+	int i;
+
+	while (p && (i = video_get_param_len (p, ',')) != 0) {
+		if (strncmp(p, name, name_len) == 0 && p[name_len] == '=')
+			return simple_strtoul(&p[name_len + 1], NULL, 10);
+
+		p += i;
+		if (*p != 0)
+			p++;	/* skip ',' */
+	}
+	return def;
+}
drivers/video/videomodes.h +5 -0
index 02419cd..047b8a9 100644
@@ -84,3 +84,8 @@ void video_get_ctfb_res_modes(int default_mode, unsigned int default_depth,
 			      const struct ctfb_res_modes **mode_ret,
 			      unsigned int *depth_ret,
 			      const char **options);
+
+void video_get_option_string(const char *options, const char *name,
+			     char *dest, int dest_len, const char *def);
+
+int video_get_option_int(const char *options, const char *name, int def);
Signature · 1 line
2.1.0
#10 lore raw

PATCH v2 5/11 videomodes: Add helper functions to parse video-mode env-var extra options

Quoted 2 lines · Hans de Goede

Add 2 helper functions to get strings, reps. ints from the options value returned by video_get_video_mode() / video_get_ctfb_res_modes().

I can't quite parse this, what is "reps. ints"?

Also, it's "separated" not "seperated" (throughout).

Quoted 95 lines
---
 drivers/video/videomodes.c | 60 +++++++++++++++++++++++++++++++++++++++++++++-
 drivers/video/videomodes.h |  5 ++++
 2 files changed, 64 insertions(+), 1 deletion(-)
drivers/video/videomodes.c +59 -1
index 72841fd..1f79d5f 100644
@@ -113,7 +113,7 @@ const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
  * returns the length to the next seperator
  */
 static int
-video_get_param_len (char *start, char sep)
+video_get_param_len (const char *start, char sep)
 {
 	int i = 0;
 	while ((*start != 0) && (*start != sep)) {
@@ -313,3 +313,61 @@ void video_get_ctfb_res_modes(int default_mode, unsigned int default_depth,
 	       xres, yres, depth, refresh, (*mode_ret)->xres,
 	       (*mode_ret)->yres, *depth_ret, (*mode_ret)->refresh);
 }
+
+/*
+ * Find the named string option within the ',' seperated options string, and
+ * store its value in dest.
+ *
+ * @options: ',' seperated options string
+ * @name: name of the option to look for
+ * @dest: destination buffer to store the value of the option in
+ * @dest_len: length of dest
+ * @def: value to store in dest if the option is not present in options
+ */
+void video_get_option_string(const char *options, const char *name,
+			     char *dest, int dest_len, const char *def)
+{
+	const char *p = options;
+	const int name_len = strlen(name);
+	int i, len;
+
+	while (p && (i = video_get_param_len (p, ',')) != 0) {
+		if (strncmp(p, name, name_len) == 0 && p[name_len] == '=') {
+			len = i - (name_len + 1);
+			if (len >= dest_len)
+				len = dest_len - 1;
+			memcpy(dest, &p[name_len + 1], len);
+			dest[len] = 0;
+			return;
+		}
+		p += i;
+		if (*p != 0)
+			p++;	/* skip ',' */
+	}
+	strcpy(dest, def);
+}
+
+/*
+ * Find the named integer option within the ',' seperated options string, and
+ * return its value.
+ *
+ * @options: ',' seperated options string
+ * @name: name of the option to look for
+ * @def: value to return if the option is not present in options
+ */
+int video_get_option_int(const char *options, const char *name, int def)
+{
+	const char *p = options;
+	const int name_len = strlen(name);
+	int i;
+
+	while (p && (i = video_get_param_len (p, ',')) != 0) {
+		if (strncmp(p, name, name_len) == 0 && p[name_len] == '=')
+			return simple_strtoul(&p[name_len + 1], NULL, 10);
+
+		p += i;
+		if (*p != 0)
+			p++;	/* skip ',' */
+	}
+	return def;
+}
drivers/video/videomodes.h +5 -0
index 02419cd..047b8a9 100644
@@ -84,3 +84,8 @@ void video_get_ctfb_res_modes(int default_mode, unsigned int default_depth,
 			      const struct ctfb_res_modes **mode_ret,
 			      unsigned int *depth_ret,
 			      const char **options);
+
+void video_get_option_string(const char *options, const char *name,
+			     char *dest, int dest_len, const char *def);
+
+int video_get_option_int(const char *options, const char *name, int def);
#11 lore raw

PATCH v2 5/11 videomodes: Add helper functions to parse video-mode env-var extra options

Hi,

Quoted 5 lines · Ian Campbell
Quoted 2 lines · Hans de Goede

Add 2 helper functions to get strings, reps. ints from the options value returned by video_get_video_mode() / video_get_ctfb_res_modes().

I can't quite parse this, what is "reps. ints"?

Oops sorry, that should be resp. for respectively, so with the abbreviations dropped it should read:

"Add 2 helper functions to get strings, respectively integers from the options value returned by video_get_video_mode() / video_get_ctfb_res_modes()."

Which hopefully is more clear, I've fixed this in my personal tree.

Quoted 1 line

Also, it's "separated" not "seperated" (throughout).

I've also fixed this in my personal tree.

Thanks & Regards,

Hans

Quoted 98 lines
Quoted 96 lines
---
  drivers/video/videomodes.c | 60 +++++++++++++++++++++++++++++++++++++++++++++-
  drivers/video/videomodes.h |  5 ++++
  2 files changed, 64 insertions(+), 1 deletion(-)
drivers/video/videomodes.c +59 -1
index 72841fd..1f79d5f 100644
@@ -113,7 +113,7 @@ const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
   * returns the length to the next seperator
   */
  static int
-video_get_param_len (char *start, char sep)
+video_get_param_len (const char *start, char sep)
  {
  	int i = 0;
  	while ((*start != 0) && (*start != sep)) {
@@ -313,3 +313,61 @@ void video_get_ctfb_res_modes(int default_mode, unsigned int default_depth,
  	       xres, yres, depth, refresh, (*mode_ret)->xres,
  	       (*mode_ret)->yres, *depth_ret, (*mode_ret)->refresh);
  }
+
+/*
+ * Find the named string option within the ',' seperated options string, and
+ * store its value in dest.
+ *
+ * @options: ',' seperated options string
+ * @name: name of the option to look for
+ * @dest: destination buffer to store the value of the option in
+ * @dest_len: length of dest
+ * @def: value to store in dest if the option is not present in options
+ */
+void video_get_option_string(const char *options, const char *name,
+			     char *dest, int dest_len, const char *def)
+{
+	const char *p = options;
+	const int name_len = strlen(name);
+	int i, len;
+
+	while (p && (i = video_get_param_len (p, ',')) != 0) {
+		if (strncmp(p, name, name_len) == 0 && p[name_len] == '=') {
+			len = i - (name_len + 1);
+			if (len >= dest_len)
+				len = dest_len - 1;
+			memcpy(dest, &p[name_len + 1], len);
+			dest[len] = 0;
+			return;
+		}
+		p += i;
+		if (*p != 0)
+			p++;	/* skip ',' */
+	}
+	strcpy(dest, def);
+}
+
+/*
+ * Find the named integer option within the ',' seperated options string, and
+ * return its value.
+ *
+ * @options: ',' seperated options string
+ * @name: name of the option to look for
+ * @def: value to return if the option is not present in options
+ */
+int video_get_option_int(const char *options, const char *name, int def)
+{
+	const char *p = options;
+	const int name_len = strlen(name);
+	int i;
+
+	while (p && (i = video_get_param_len (p, ',')) != 0) {
+		if (strncmp(p, name, name_len) == 0 && p[name_len] == '=')
+			return simple_strtoul(&p[name_len + 1], NULL, 10);
+
+		p += i;
+		if (*p != 0)
+			p++;	/* skip ',' */
+	}
+	return def;
+}
drivers/video/videomodes.h +5 -0
index 02419cd..047b8a9 100644
@@ -84,3 +84,8 @@ void video_get_ctfb_res_modes(int default_mode, unsigned int default_depth,
  			      const struct ctfb_res_modes **mode_ret,
  			      unsigned int *depth_ret,
  			      const char **options);
+
+void video_get_option_string(const char *options, const char *name,
+			     char *dest, int dest_len, const char *def);
+
+int video_get_option_int(const char *options, const char *name, int def);
#12 lore raw

PATCH v2 5/11 videomodes: Add helper functions to parse video-mode env-var extra options

In reply to Hans de Goede
Quoted 4 lines · On Fri, 19 Dec 2014 18:10:35 +0100 Hans de Goede <[email protected]> wrote:

Add 2 helper functions to get strings, reps. ints from the options value returned by video_get_video_mode() / video_get_ctfb_res_modes().

before applying please fix these checkpatch warnings:

WARNING: space prohibited between function name and open parenthesis '(' #32: FILE: drivers/video/videomodes.c:116:
+video_get_param_len (const char *start, char sep)

WARNING: space prohibited between function name and open parenthesis '(' #58: FILE: drivers/video/videomodes.c:334:
+ while (p && (i = video_get_param_len (p, ',')) != 0) {

WARNING: space prohibited between function name and open parenthesis '(' #88: FILE: drivers/video/videomodes.c:364:
+ while (p && (i = video_get_param_len (p, ',')) != 0) {

total: 0 errors, 3 warnings, 0 checks, 77 lines checked

With these warnings fixed,

#13 lore raw

PATCH v2 6/11 videomodes: Add video_edid_dtd_to_ctfb_res_modes helper function

In reply to Hans de Goede

Add a video_edid_dtd_to_ctfb_res_modes helper function to convert an EDID detailed timing to a struct ctfb_res_modes.

---
 drivers/video/videomodes.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/video/videomodes.h |  4 +++
 include/edid.h             |  4 +++
 3 files changed, 81 insertions(+)
drivers/video/videomodes.c +73 -0
index 1f79d5f..9a4f0af 100644
@@ -58,6 +58,8 @@
 ****************************************************************************/
 
 #include <common.h>
+#include <edid.h>
+#include <errno.h>
 #include <linux/ctype.h>
 
 #include "videomodes.h"
@@ -371,3 +373,74 @@ int video_get_option_int(const char *options, const char *name, int def)
 	}
 	return def;
 }
+
+/**
+ * Convert an EDID detailed timing to a struct ctfb_res_modes
+ *
+ * @param t		The EDID detailed timing to be converted
+ * @param mode		Returns the converted timing
+ *
+ * @return 0 on success, or a negative errno on error
+ */
+int video_edid_dtd_to_ctfb_res_modes(struct edid_detailed_timing *t,
+				     struct ctfb_res_modes *mode)
+{
+	int margin, h_total, v_total;
+
+	/* Check all timings are non 0 */
+	if (EDID_DETAILED_TIMING_PIXEL_CLOCK(*t) == 0 ||
+	    EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*t) == 0 ||
+	    EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*t) == 0 ||
+	    EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*t) == 0 ||
+	    EDID_DETAILED_TIMING_VERTICAL_BLANKING(*t) == 0 ||
+	    EDID_DETAILED_TIMING_HSYNC_OFFSET(*t) == 0 ||
+	    EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(*t) == 0 ||
+	    EDID_DETAILED_TIMING_VSYNC_OFFSET(*t) == 0 ||
+	    EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(*t) == 0 ||
+	    /* 3d formats are not supported*/
+	    EDID_DETAILED_TIMING_FLAG_STEREO(*t) != 0)
+		return -EINVAL;
+
+	mode->xres = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*t);
+	mode->yres = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*t);
+
+	h_total = mode->xres + EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*t);
+	v_total = mode->yres + EDID_DETAILED_TIMING_VERTICAL_BLANKING(*t);
+	mode->refresh = EDID_DETAILED_TIMING_PIXEL_CLOCK(*t) /
+			(h_total * v_total);
+
+	mode->pixclock = 1000000000000LL / EDID_DETAILED_TIMING_PIXEL_CLOCK(*t);
+	mode->pixclock_khz = (EDID_DETAILED_TIMING_PIXEL_CLOCK(*t) + 500) /
+				1000;
+
+	mode->right_margin = EDID_DETAILED_TIMING_HSYNC_OFFSET(*t);
+	mode->hsync_len = EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(*t);
+	margin = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*t) -
+			(mode->right_margin + mode->hsync_len);
+	if (margin <= 0)
+		return -EINVAL;
+
+	mode->left_margin = margin;
+
+	mode->lower_margin = EDID_DETAILED_TIMING_VSYNC_OFFSET(*t);
+	mode->vsync_len = EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(*t);
+	margin = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*t) -
+			(mode->lower_margin + mode->vsync_len);
+	if (margin <= 0)
+		return -EINVAL;
+
+	mode->upper_margin = margin;
+
+	mode->sync = 0;
+	if (EDID_DETAILED_TIMING_FLAG_HSYNC_POLARITY(*t))
+		mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (EDID_DETAILED_TIMING_FLAG_VSYNC_POLARITY(*t))
+		mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+	if (EDID_DETAILED_TIMING_FLAG_INTERLACED(*t))
+		mode->vmode = FB_VMODE_INTERLACED;
+	else
+		mode->vmode = FB_VMODE_NONINTERLACED;
+
+	return 0;
+}
drivers/video/videomodes.h +4 -0
index 047b8a9..82190a2 100644
@@ -5,6 +5,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <edid.h>
 
 #ifndef CONFIG_SYS_DEFAULT_VIDEO_MODE
 #define CONFIG_SYS_DEFAULT_VIDEO_MODE	0x301
@@ -89,3 +90,6 @@ void video_get_option_string(const char *options, const char *name,
 			     char *dest, int dest_len, const char *def);
 
 int video_get_option_int(const char *options, const char *name, int def);
+
+int video_edid_dtd_to_ctfb_res_modes(struct edid_detailed_timing *t,
+				     struct ctfb_res_modes *mode);
include/edid.h +4 -0
index 480a773..d3cc523 100644
@@ -86,6 +86,10 @@ struct edid_detailed_timing {
 	GET_BITS((_x).flags, 4, 3)
 #define EDID_DETAILED_TIMING_FLAG_POLARITY(_x) \
 	GET_BITS((_x).flags, 2, 1)
+#define EDID_DETAILED_TIMING_FLAG_VSYNC_POLARITY(_x) \
+	GET_BIT((_x).flags, 2)
+#define EDID_DETAILED_TIMING_FLAG_HSYNC_POLARITY(_x) \
+	GET_BIT((_x).flags, 1)
 #define EDID_DETAILED_TIMING_FLAG_INTERLEAVED(_x) \
 	GET_BIT((_x).flags, 0)
 } __attribute__ ((__packed__));
Signature · 1 line
2.1.0
#15 lore raw

PATCH v2 7/11 edid: Add an edid_check_checksum() helper function

In reply to Hans de Goede

Add a helper function to check the checksum of an EDID data block.

---
 common/edid.c  | 12 ++++++++++++
 include/edid.h |  9 +++++++++
 2 files changed, 21 insertions(+)
common/edid.c +12 -0
index e66108f..df797fc 100644
@@ -12,6 +12,7 @@
 
 #include <common.h>
 #include <edid.h>
+#include <errno.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
 
@@ -29,6 +30,17 @@ int edid_check_info(struct edid1_info *edid_info)
 	return 0;
 }
 
+int edid_check_checksum(u8 *edid_block)
+{
+	u8 checksum = 0;
+	int i;
+
+	for (i = 0; i < 128; i++)
+		checksum += edid_block[i];
+
+	return (checksum == 0) ? 0 : -EINVAL;
+}
+
 int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin,
 		    unsigned int *hmax, unsigned int *vmin,
 		    unsigned int *vmax)
include/edid.h +9 -0
index d3cc523..a69f43a 100644
@@ -246,6 +246,15 @@ void edid_print_info(struct edid1_info *edid_info);
 int edid_check_info(struct edid1_info *info);
 
 /**
+ * Check checksum of a 128 bytes EDID data block
+ *
+ * @param edid_block	EDID block data
+ *
+ * @return 0 on success, or a negative errno on error
+ */
+int edid_check_checksum(u8 *edid_block);
+
+/**
  * Get the horizontal and vertical rate ranges of the monitor.
  *
  * @param edid	The EDID info
Signature · 1 line
2.1.0
#17 lore raw

PATCH v2 8/11 sunxi: video: Use video-mode/-timing from videomodes

In reply to Hans de Goede

Switch from fb_videomode to ctfb_res_modes and use the predefined videotimings from videomodes.c, rather then defining our own.

---
 drivers/video/Makefile         |  2 +-
 drivers/video/sunxi_display.c  | 41 +++++++++++------------------------------
 include/configs/sunxi-common.h |  1 +
 3 files changed, 13 insertions(+), 31 deletions(-)
drivers/video/Makefile +1 -1
index 00b563f..42b1eaa 100644
@@ -39,7 +39,7 @@ obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o
 obj-$(CONFIG_VIDEO_SED13806) += sed13806.o
 obj-$(CONFIG_VIDEO_SM501) += sm501.o
 obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o
-obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o
+obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o videomodes.o
 obj-$(CONFIG_VIDEO_TEGRA) += tegra.o
 obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
 obj-$(CONFIG_VIDEO_X86) += x86_fb.o
drivers/video/sunxi_display.c +11 -30

97 lines not on this page · raw message

include/configs/sunxi-common.h +1 -0
index 7b958f8..727f446 100644
@@ -212,6 +212,7 @@
 #define CONFIG_CFB_CONSOLE
 #define CONFIG_VIDEO_SW_CURSOR
 #define CONFIG_VIDEO_LOGO
+#define CONFIG_VIDEO_STD_TIMINGS
 
 /* allow both serial and cfb console. */
 #define CONFIG_CONSOLE_MUX
Signature · 1 line
2.1.0
#20 lore raw

PATCH v2 9/11 sunxi: video: Add support for video-mode environment variable

In reply to Hans de Goede

Add support for the standard video-mode environment variable using the videomodes.c video_get_ctfb_res_modes() helper function.

This will allow users to specify the resolution e.g. :

setenv video-mode sunxi:video-mode=1280x1024-24 at 60 saveenv

Also make the reserved fb mem slightly larger to allow 1920x1200 to work.

---
 drivers/video/sunxi_display.c  | 16 +++++++++++++---
 include/configs/sunxi-common.h |  2 +-
 2 files changed, 14 insertions(+), 4 deletions(-)
drivers/video/sunxi_display.c +13 -3
index cedb56e..cf81e45 100644
@@ -358,7 +358,9 @@ retry:
 void *video_hw_init(void)
 {
 	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
-	const struct ctfb_res_modes *mode = &res_mode_init[RES_MODE_1024x768];
+	const struct ctfb_res_modes *mode;
+	const char *options;
+	unsigned int depth;
 	int ret;
 
 	memset(&sunxi_display, 0, sizeof(struct sunxi_display));
@@ -367,14 +369,22 @@ void *video_hw_init(void)
 	       CONFIG_SUNXI_FB_SIZE >> 10);
 	gd->fb_base = gd->ram_top;
 
+	video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode, &depth, &options);
+
 	ret = sunxi_hdmi_hpd_detect();
 	if (!ret)
 		return NULL;
 
 	printf("HDMI connected.\n");
-	sunxi_display.enabled = true;
 
-	printf("Setting up a %dx%d console.\n", mode->xres, mode->yres);
+	if (mode->vmode != FB_VMODE_NONINTERLACED) {
+		printf("Only non-interlaced modes supported, falling back to 1024x768\n");
+		mode = &res_mode_init[RES_MODE_1024x768];
+	} else {
+		printf("Setting up a %dx%d console\n", mode->xres, mode->yres);
+	}
+
+	sunxi_display.enabled = true;
 	sunxi_engines_init();
 	sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
 
include/configs/sunxi-common.h +1 -1
index 727f446..77965f7 100644
@@ -202,7 +202,7 @@
  * The amount of RAM that is reserved for the FB. This will not show up as
  * RAM to the kernel, but will be reclaimed by a KMS driver in future.
  */
-#define CONFIG_SUNXI_FB_SIZE (8 << 20)
+#define CONFIG_SUNXI_FB_SIZE (9 << 20)
 
 /* Do we want to initialize a simple FB? */
 #define CONFIG_VIDEO_DT_SIMPLEFB
Signature · 1 line
2.1.0
#21 lore raw

PATCH v2 9/11 sunxi: video: Add support for video-mode environment variable

Quoted 11 lines · Hans de Goede

Add support for the standard video-mode environment variable using the videomodes.c video_get_ctfb_res_modes() helper function.

This will allow users to specify the resolution e.g. :

setenv video-mode sunxi:video-mode=1280x1024-24 at 60 saveenv

Also make the reserved fb mem slightly larger to allow 1920x1200 to work.

#22 lore raw

PATCH v2 9/11 sunxi: video: Add support for video-mode environment variable

In reply to Hans de Goede
Quoted 11 lines · On Fri, 19 Dec 2014 18:10:39 +0100 Hans de Goede <[email protected]> wrote:

Add support for the standard video-mode environment variable using the videomodes.c video_get_ctfb_res_modes() helper function.

This will allow users to specify the resolution e.g. :

setenv video-mode sunxi:video-mode=1280x1024-24 at 60 saveenv

Also make the reserved fb mem slightly larger to allow 1920x1200 to work.

#23 lore raw

PATCH v2 10/11 sunxi: video: Add hpd option

In reply to Hans de Goede

Allow the user to specify hpd=0 as option in the video-mode env. variable, if hpd is set to 0 then the hdmi output will be brought up even if no cable is connected.

---
 drivers/video/sunxi_display.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)
drivers/video/sunxi_display.c +17 -9
index cf81e45..18fa83d 100644
@@ -53,10 +53,16 @@ static int sunxi_hdmi_hpd_detect(void)
 
 	udelay(1000);
 
-	if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT)
-		return 1;
+	return (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT) ? 1 : 0;
+}
+
+static void sunxi_hdmi_shutdown(void)
+{
+	struct sunxi_ccm_reg * const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	struct sunxi_hdmi_reg * const hdmi =
+		(struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
 
-	/* No need to keep these running */
 	clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE);
 	clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
 	clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
@@ -64,8 +70,6 @@ static int sunxi_hdmi_hpd_detect(void)
 	clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
 #endif
 	clock_set_pll3(0);
-
-	return 0;
 }
 
 /*
@@ -361,7 +365,7 @@ void *video_hw_init(void)
 	const struct ctfb_res_modes *mode;
 	const char *options;
 	unsigned int depth;
-	int ret;
+	int ret, hpd;
 
 	memset(&sunxi_display, 0, sizeof(struct sunxi_display));
 
@@ -370,12 +374,16 @@ void *video_hw_init(void)
 	gd->fb_base = gd->ram_top;
 
 	video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode, &depth, &options);
+	hpd = video_get_option_int(options, "hpd", 1);
 
+	/* Always call hdp_detect, as it also enables various clocks, etc. */
 	ret = sunxi_hdmi_hpd_detect();
-	if (!ret)
+	if (hpd && !ret) {
+		sunxi_hdmi_shutdown();
 		return NULL;
-
-	printf("HDMI connected.\n");
+	}
+	if (ret)
+		printf("HDMI connected: ");
 
 	if (mode->vmode != FB_VMODE_NONINTERLACED) {
 		printf("Only non-interlaced modes supported, falling back to 1024x768\n");
Signature · 1 line
2.1.0
#26 lore raw

PATCH v2 11/11 sunxi: video: Add DDC & EDID support

In reply to Hans de Goede

Add DDC & EDID support and use it to automatically select the native mode of the attached monitor. This can be disabled by adding edid=0 as option to the video-mode env. variable.

---
 arch/arm/include/asm/arch-sunxi/display.h |  85 +++++++++++++++++
 drivers/video/sunxi_display.c             | 154 +++++++++++++++++++++++++++++-
 include/configs/sunxi-common.h            |   1 +
 3 files changed, 239 insertions(+), 1 deletion(-)
arch/arm/include/asm/arch-sunxi/display.h +85 -0
index ddb71c1..8c4835e 100644
@@ -107,6 +107,48 @@ struct sunxi_hdmi_reg {
 	u32 pad_ctrl1;			/* 0x204 */
 	u32 pll_ctrl;			/* 0x208 */
 	u32 pll_dbg0;			/* 0x20c */
+	u32 pll_dbg1;			/* 0x210 */
+	u32 hpd_cec;			/* 0x214 */
+	u8 res1[0x28];			/* 0x218 */
+	u32 spd_pkt;			/* 0x240 */
+	u8 res2[0xac];			/* 0x244 */
+	u32 pkt_ctrl0;			/* 0x2f0 */
+	u32 pkt_ctrl1;			/* 0x2f4 */
+	u8 res3[0x18];			/* 0x2f8 */
+	u32 audio_sample_count;		/* 0x310 */
+	u8 res4[0xec];			/* 0x314 */
+	u32 audio_tx_fifo;		/* 0x400 */
+	u8 res5[0xfc];			/* 0x404 */
+#ifndef CONFIG_MACH_SUN6I
+	u32 ddc_ctrl;			/* 0x500 */
+	u32 ddc_addr;			/* 0x504 */
+	u32 ddc_int_mask;		/* 0x508 */
+	u32 ddc_int_status;		/* 0x50c */
+	u32 ddc_fifo_ctrl;		/* 0x510 */
+	u32 ddc_fifo_status;		/* 0x514 */
+	u32 ddc_fifo_data;		/* 0x518 */
+	u32 ddc_byte_count;		/* 0x51c */
+	u32 ddc_cmnd;			/* 0x520 */
+	u32 ddc_exreg;			/* 0x524 */
+	u32 ddc_clock;			/* 0x528 */
+	u8 res6[0x14];			/* 0x52c */
+	u32 ddc_line_ctrl;		/* 0x540 */
+#else
+	u32 ddc_ctrl;			/* 0x500 */
+	u32 ddc_exreg;			/* 0x504 */
+	u32 ddc_cmnd;			/* 0x508 */
+	u32 ddc_addr;			/* 0x50c */
+	u32 ddc_int_mask;		/* 0x510 */
+	u32 ddc_int_status;		/* 0x514 */
+	u32 ddc_fifo_ctrl;		/* 0x518 */
+	u32 ddc_fifo_status;		/* 0x51c */
+	u32 ddc_clock;			/* 0x520 */
+	u32 ddc_timeout;		/* 0x524 */
+	u8 res6[0x18];			/* 0x528 */
+	u32 ddc_dbg;			/* 0x540 */
+	u8 res7[0x3c];			/* 0x544 */
+	u32 ddc_fifo_data;		/* 0x580 */
+#endif
 };
 
 /*
@@ -182,6 +224,49 @@ struct sunxi_hdmi_reg {
 #define SUNXI_HDMI_PLL_DBG0_PLL3		(0 << 21)
 #define SUNXI_HDMI_PLL_DBG0_PLL7		(1 << 21)
 
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HMDI_DDC_CTRL_ENABLE		(1 << 0)
+#define SUNXI_HMDI_DDC_CTRL_SCL_ENABLE		(1 << 4)
+#define SUNXI_HMDI_DDC_CTRL_SDA_ENABLE		(1 << 6)
+#define SUNXI_HMDI_DDC_CTRL_START		(1 << 27)
+#define SUNXI_HMDI_DDC_CTRL_RESET		(1 << 31)
+#else
+#define SUNXI_HMDI_DDC_CTRL_RESET		(1 << 0)
+/* sun4i / sun5i / sun7i do not have a separate line_ctrl reg */
+#define SUNXI_HMDI_DDC_CTRL_SDA_ENABLE		0
+#define SUNXI_HMDI_DDC_CTRL_SCL_ENABLE		0
+#define SUNXI_HMDI_DDC_CTRL_START		(1 << 30)
+#define SUNXI_HMDI_DDC_CTRL_ENABLE		(1 << 31)
+#endif
+
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HMDI_DDC_ADDR_SLAVE_ADDR		(0xa0 << 0)
+#else
+#define SUNXI_HMDI_DDC_ADDR_SLAVE_ADDR		(0x50 << 0)
+#endif
+#define SUNXI_HMDI_DDC_ADDR_OFFSET(n)		(((n) & 0xff) << 8)
+#define SUNXI_HMDI_DDC_ADDR_EDDC_ADDR		(0x60 << 16)
+#define SUNXI_HMDI_DDC_ADDR_EDDC_SEGMENT(n)	((n) << 24)
+
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HDMI_DDC_FIFO_CTRL_CLEAR		(1 << 15)
+#else
+#define SUNXI_HDMI_DDC_FIFO_CTRL_CLEAR		(1 << 31)
+#endif
+
+#define SUNXI_HDMI_DDC_CMND_EXPLICIT_EDDC_READ	6
+#define SUNXI_HDMI_DDC_CMND_IMPLICIT_EDDC_READ	7
+
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HDMI_DDC_CLOCK			0x61
+#else
+/* N = 5,M=1 Fscl= Ftmds/2/10/2^N/(M+1) */
+#define SUNXI_HDMI_DDC_CLOCK			0x0d
+#endif
+
+#define SUNXI_HMDI_DDC_LINE_CTRL_SCL_ENABLE	(1 << 8)
+#define SUNXI_HMDI_DDC_LINE_CTRL_SDA_ENABLE	(1 << 9)
+
 int sunxi_simplefb_setup(void *blob);
 
 #endif /* _SUNXI_DISPLAY_H */
drivers/video/sunxi_display.c +153 -1

192 lines not on this page · raw message

include/configs/sunxi-common.h +1 -0
index 77965f7..30b7ee4 100644
@@ -213,6 +213,7 @@
 #define CONFIG_VIDEO_SW_CURSOR
 #define CONFIG_VIDEO_LOGO
 #define CONFIG_VIDEO_STD_TIMINGS
+#define CONFIG_I2C_EDID
 
 /* allow both serial and cfb console. */
 #define CONFIG_CONSOLE_MUX
Signature · 1 line
2.1.0
#28 lore raw

PATCH v2 11/11 sunxi: video: Add DDC & EDID support

In reply to Hans de Goede
Quoted 5 lines · On Fri, 19 Dec 2014 18:10:41 +0100 Hans de Goede <[email protected]> wrote:

Add DDC & EDID support and use it to automatically select the native mode of the attached monitor. This can be disabled by adding edid=0 as option to the video-mode env. variable.