[coreboot-gerrit] Patch set updated for coreboot: cf24acd FUI: Fill in link_m and link_n values

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Thu Dec 12 22:16:13 CET 2013


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4381

-gerrit

commit cf24acdf8375e69dc1059c2736e76acd2725279b
Author: Furquan Shaikh <furquan at google.com>
Date:   Mon Jul 22 16:18:31 2013 -0700

    FUI: Fill in link_m and link_n values
    
    ... based on the EDID detailed timing values for
    pixel_clock and link_clock.
    
    Two undocumented registers 0x6f040 and 0x6f044 correspond to link_m and link_n
    respectively.  Other two undocumented registers 0x6f030 and 0x6f034 correspond
    to data_m and data_n respectively.
    
    Calculations are based on the intel_link_compute_m_n from linux kernel.
    
    Currently, the value for 0x6f030 does not come up right with our calculations.
    Hence, set to hard-coded value.
    
    Change-Id: I40ff411729d0a61759164c3c1098504973f9cf5e
    Reviewed-on: https://gerrit.chromium.org/gerrit/62915
    Reviewed-by: Ronald G. Minnich <rminnich at chromium.org>
    Tested-by: Furquan Shaikh <furquan at chromium.org>
    Commit-Queue: Furquan Shaikh <furquan at chromium.org>
---
 src/drivers/intel/gma/i915.h         | 14 +++++++++
 src/drivers/intel/gma/i915_reg.h     |  4 +++
 src/drivers/intel/gma/intel_dp.c     | 58 ++++++++++++++++++++++--------------
 src/include/edid.h                   |  2 ++
 src/lib/edid.c                       |  6 ++--
 src/mainboard/google/slippy/gma.c    | 30 +++++++++++++++++++
 src/mainboard/google/slippy/i915io.c | 11 +++++--
 7 files changed, 98 insertions(+), 27 deletions(-)

diff --git a/src/drivers/intel/gma/i915.h b/src/drivers/intel/gma/i915.h
index e976f91..62fe023 100644
--- a/src/drivers/intel/gma/i915.h
+++ b/src/drivers/intel/gma/i915.h
@@ -65,6 +65,14 @@ void io_i915_write32(unsigned long val, unsigned long addr);
 
 #define DP_LINK_CONFIGURATION_SIZE	9
 
+struct intel_dp_m_n {
+	uint32_t	tu;
+	uint32_t	gmch_m;
+	uint32_t	gmch_n;
+	uint32_t	link_m;
+	uint32_t	link_n;
+};
+
 struct intel_dp {
 	int gen; // 6 for link, 7 for wtm2
 	int has_pch_split; // 1 for link and wtm2
@@ -134,6 +142,7 @@ struct intel_dp {
 	u32 pfa_ctl;
 	u32 pipesrc;
 	u32 stride;
+	struct intel_dp_m_n m_n;
 };
 
 /* we may yet need these. */
@@ -183,3 +192,8 @@ void intel_dp_wait_reg(unsigned long addr,
 
 void intel_dp_wait_panel_power_control(unsigned long val);
 
+void intel_dp_compute_m_n(unsigned int bits_per_pixel,
+                          unsigned int nlanes,
+                          unsigned int pixel_clock,
+                          unsigned int link_clock,
+                          struct intel_dp_m_n *m_n);
diff --git a/src/drivers/intel/gma/i915_reg.h b/src/drivers/intel/gma/i915_reg.h
index d947f1a..27a3d2b 100644
--- a/src/drivers/intel/gma/i915_reg.h
+++ b/src/drivers/intel/gma/i915_reg.h
@@ -3321,6 +3321,10 @@
 #define _PIPEA_DATA_M1           0x60030
 #define  TU_SIZE(x)             (((x)-1) << 25) /* default size 64 */
 #define  TU_SIZE_MASK           0x7e000000
+
+#define  DATA_LINK_M_N_MASK     (0xffffff)
+#define  DATA_LINK_N_MAX        (0x800000)
+
 #define  PIPE_DATA_M1_OFFSET    0
 #define _PIPEA_DATA_N1           0x60034
 #define  PIPE_DATA_N1_OFFSET    0
diff --git a/src/drivers/intel/gma/intel_dp.c b/src/drivers/intel/gma/intel_dp.c
index 8097c6a..0def771 100644
--- a/src/drivers/intel/gma/intel_dp.c
+++ b/src/drivers/intel/gma/intel_dp.c
@@ -393,37 +393,51 @@ intel_dp_i2c_init(struct intel_dp *intel_dp)
 	return ret;
 }
 
-struct intel_dp_m_n {
-	uint32_t	tu;
-	uint32_t	gmch_m;
-	uint32_t	gmch_n;
-	uint32_t	link_m;
-	uint32_t	link_n;
-};
-
 static void
-intel_reduce_ratio(uint32_t *num, uint32_t *den)
+intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
 {
-	while (*num > 0xffffff || *den > 0xffffff) {
+	while (*num > DATA_LINK_M_N_MASK || *den > DATA_LINK_M_N_MASK) {
 		*num >>= 1;
 		*den >>= 1;
 	}
 }
 
-static void
-intel_dp_compute_m_n(int bpp,
-		     int nlanes,
-		     int pixel_clock,
-		     int link_clock,
-		     struct intel_dp_m_n *m_n)
+unsigned int roundup_power_of_two(unsigned int n);
+
+unsigned int roundup_power_of_two(unsigned int n)
+{
+	n--;
+	n |= n >> 1;
+	n |= n >> 2;
+	n |= n >> 4;
+	n |= n >> 8;
+	n |= n >> 16;
+	n++;
+	return n;
+}
+
+static void compute_m_n(unsigned int m, unsigned int n,
+			unsigned int *ret_m, unsigned int *ret_n)
+{
+	*ret_n = MIN(roundup_power_of_two(n), DATA_LINK_N_MAX);
+	*ret_m = ( (unsigned long long)m * *ret_n) / n;
+	intel_reduce_m_n_ratio(ret_m, ret_n);
+}
+
+void intel_dp_compute_m_n(unsigned int bits_per_pixel,
+			  unsigned int nlanes,
+			  unsigned int pixel_clock,
+			  unsigned int link_clock,
+			  struct intel_dp_m_n *m_n)
 {
 	m_n->tu = 64;
-	m_n->gmch_m = (pixel_clock * bpp) >> 3;
-	m_n->gmch_n = link_clock * nlanes;
-	intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
-	m_n->link_m = pixel_clock;
-	m_n->link_n = link_clock;
-	intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
+
+	compute_m_n(bits_per_pixel * pixel_clock,
+		    link_clock * nlanes * 8,
+		    &m_n->gmch_m, &m_n->gmch_n);
+
+	compute_m_n(pixel_clock, link_clock,
+		    &m_n->link_m, &m_n->link_n);
 }
 
 /* not sure. */
diff --git a/src/include/edid.h b/src/include/edid.h
index 7d4736d..ca92852 100644
--- a/src/include/edid.h
+++ b/src/include/edid.h
@@ -45,6 +45,8 @@ struct edid {
 	/* used to compute timing for graphics chips. */
 	unsigned char phsync;
 	unsigned char pvsync;
+	unsigned int pixel_clock;
+	unsigned int link_clock;
 	unsigned int ha;
 	unsigned int hbl;
 	unsigned int hso;
diff --git a/src/lib/edid.c b/src/lib/edid.c
index d0e8b98..d7ffbfc 100644
--- a/src/lib/edid.c
+++ b/src/lib/edid.c
@@ -447,6 +447,8 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension)
 	}
 
 	if (! did_detailed_timing){
+		/* Edid contains pixel clock in terms of 10KHz */
+		out->pixel_clock = (x[0] + (x[1] << 8)) * 10;
 		out->ha = (x[2] + ((x[4] & 0xF0) << 4));
 		out->hbl = (x[3] + ((x[4] & 0x0F) << 8));
 		out->hso = (x[8] + ((x[11] & 0xC0) << 2));
@@ -500,11 +502,11 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension)
 		break;
 	}
 
-	printk(BIOS_SPEW, "Detailed mode (IN HEX): Clock %d0 KHz, %x mm x %x mm\n"
+	printk(BIOS_SPEW, "Detailed mode (IN HEX): Clock %d KHz, %x mm x %x mm\n"
 	       "               %04x %04x %04x %04x hborder %x\n"
 	       "               %04x %04x %04x %04x vborder %x\n"
 	       "               %chsync %cvsync%s%s %s\n",
-	       (x[0] + (x[1] << 8)),
+	       out->pixel_clock,
 	       (x[12] + ((x[14] & 0xF0) << 4)),
 	       (x[13] + ((x[14] & 0x0F) << 8)),
 	       out->ha, out->ha + out->hso, out->ha + out->hso + out->hspw,
diff --git a/src/mainboard/google/slippy/gma.c b/src/mainboard/google/slippy/gma.c
index 3907218..52a7b0b 100644
--- a/src/mainboard/google/slippy/gma.c
+++ b/src/mainboard/google/slippy/gma.c
@@ -288,6 +288,12 @@ void dp_init_dim_regs(struct intel_dp *dp)
 
 	dp->pfa_sz = (edid->ha << 16) | (edid->va);
 
+	intel_dp_compute_m_n(dp->bpp,
+			     dp->lane_count,
+			     dp->edid.pixel_clock,
+			     dp->edid.link_clock,
+			     &dp->m_n);
+
 	printk(BIOS_SPEW, "dp->stride  = 0x%08x\n",dp->stride);
 	printk(BIOS_SPEW, "dp->htotal  = 0x%08x\n", dp->htotal);
 	printk(BIOS_SPEW, "dp->hblank  = 0x%08x\n", dp->hblank);
@@ -299,6 +305,26 @@ void dp_init_dim_regs(struct intel_dp *dp)
 	printk(BIOS_SPEW, "dp->pfa_pos = 0x%08x\n", dp->pfa_pos);
 	printk(BIOS_SPEW, "dp->pfa_ctl = 0x%08x\n", dp->pfa_ctl);
 	printk(BIOS_SPEW, "dp->pfa_sz  = 0x%08x\n", dp->pfa_sz);
+	printk(BIOS_SPEW, "dp->link_m  = 0x%08x\n", dp->m_n.link_m);
+	printk(BIOS_SPEW, "dp->link_n  = 0x%08x\n", dp->m_n.link_n);
+	printk(BIOS_SPEW, "0x6f030     = 0x%08x\n", TU_SIZE(dp->m_n.tu) | dp->m_n.gmch_m);
+	printk(BIOS_SPEW, "0x6f030     = 0x%08x\n", dp->m_n.gmch_m);
+	printk(BIOS_SPEW, "0x6f034     = 0x%08x\n", dp->m_n.gmch_n);
+}
+
+int intel_dp_bw_code_to_link_rate(u8 link_bw);
+
+int intel_dp_bw_code_to_link_rate(u8 link_bw)
+{
+	switch (link_bw) {
+        case DP_LINK_BW_1_62:
+        default:
+		return 162000;
+        case DP_LINK_BW_2_7:
+		return 270000;
+        case DP_LINK_BW_5_4:
+                return 540000;
+	}
 }
 
 int i915lightup(unsigned int physbase, unsigned int iobase, unsigned int mmio,
@@ -366,6 +392,10 @@ int i915lightup(unsigned int pphysbase, unsigned int piobase,
 	edid_ok = decode_edid(dp->rawedid, dp->edidlen, &dp->edid);
 	printk(BIOS_SPEW, "decode edid returns %d\n", edid_ok);
 
+	dp->edid.link_clock = intel_dp_bw_code_to_link_rate(dp->link_bw);
+
+	printk(BIOS_SPEW, "pixel_clock is %i, link_clock is %i\n",dp->edid.pixel_clock, dp->edid.link_clock);
+
 	dp_init_dim_regs(dp);
 
 	/* more undocumented stuff. */
diff --git a/src/mainboard/google/slippy/i915io.c b/src/mainboard/google/slippy/i915io.c
index 18e0480..c1e0547 100644
--- a/src/mainboard/google/slippy/i915io.c
+++ b/src/mainboard/google/slippy/i915io.c
@@ -117,9 +117,14 @@ printk(BIOS_SPEW, "DP_MAX_DOWNSPREAD");
 
 	/* undocumented. */
 	io_i915_write32(0x7e4a0000,0x6f030);
-	io_i915_write32(0x00800000,0x6f034);
-	io_i915_write32(0x00021000,0x6f040);
-	io_i915_write32(0x00080000,0x6f044);
+	/* io_i915_write32(0x00800000,0x6f034); */
+	/* Write to 0x6f030 has to be 0x7e4ayyyy -- First four hex digits are important.
+	   However, with our formula we always see values 0x7e43yyyy (1366 panel) and
+	   0x7e42yyy (1280 panel) */
+	/* io_i915_write32(TU_SIZE(dp->m_n.tu) | dp->m_n.gmch_m,0x6f030); */
+	io_i915_write32(dp->m_n.gmch_n,0x6f034);
+	io_i915_write32(dp->m_n.link_m,0x6f040);
+	io_i915_write32(dp->m_n.link_n,0x6f044);
 
 	/* leave as is for now. */
 	io_i915_write32(dp->htotal,0x6f000);



More information about the coreboot-gerrit mailing list