linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] follow up: aty128fb and EDID
@ 2003-02-21  1:12 Magnus Damm
  0 siblings, 0 replies; only message in thread
From: Magnus Damm @ 2003-02-21  1:12 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: brad

[-- Attachment #1: Type: text/plain, Size: 353 bytes --]

Hi,

Here comes a quick hack that adds EDID support to aty128fb.
I took the EDID code from the radeon driver and modified it.
It's not pretty, but it might be useful for someone.

So consider it a quick fix.
The 2.5-tree has a file called fbmon.c that has EDID
functionallity broken out, that should probably be the
long term solution.

thanks /

magnus

[-- Attachment #2: linuxppc_2_4-aty128fb_edid.patch --]
[-- Type: application/octet-stream, Size: 4739 bytes --]

--- linuxppc_2_4/drivers/video/aty128fb.c	2003-02-20 20:12:35.000000000 +0000
+++ linuxppc_2_4-aty128fb_edid/drivers/video/aty128fb.c	2003-02-21 01:06:21.000000000 +0000
@@ -329,10 +329,17 @@
     int crt_on, lcd_on;
     u32 save_lcd_gen_cntl;
 #endif
+    unsigned char *EDID;
 };
 
 static struct fb_info_aty128 *board_list = NULL;
 
+static void aty128_get_EDID(struct fb_info_aty128 *rinfo);
+static int aty128_dfp_parse_EDID(struct fb_info_aty128 *rinfo);
+#ifdef CONFIG_ALL_PPC
+static int aty128_get_EDID_OF(struct fb_info_aty128 *rinfo);
+extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev);
+
 #ifdef CONFIG_PMAC_PBOOK
   int aty128_sleep_notify(struct pmu_sleep_notifier *self, int when);
   static struct pmu_sleep_notifier aty128_sleep_notifier = {
@@ -340,6 +347,8 @@
   };
 #endif
 
+#endif
+
 #define round_div(n, d) ((n+(d/2))/d)
 
     /*
@@ -1858,6 +1867,7 @@
 #endif
     
     var = default_var;
+    aty128_get_EDID(info);
 #ifdef CONFIG_PPC
     if (_machine == _MACH_Pmac) {
         if (mode_option) {
@@ -1893,8 +1903,14 @@
             if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
                 default_cmode = CMODE_8;
 
-            if (mac_vmode_to_var(default_vmode, default_cmode, &var))
+ 	    if (mac_vmode_to_var(default_vmode, default_cmode, &var))
                 var = default_var;
+	    
+	    if (aty128_dfp_parse_EDID(info)) {
+	        default_var = var;
+		aty128_dfp_parse_EDID(info);
+                var = default_var;
+	    }
         }
     } else
 #endif /* CONFIG_PPC */
@@ -2220,6 +2236,116 @@
 }           
 #endif /* !CONFIG_PPC */
 
+static void aty128_get_EDID(struct fb_info_aty128 *rinfo)
+{
+#ifdef CONFIG_ALL_PPC
+	if (!aty128_get_EDID_OF(rinfo))
+		DBG("could not retrieve EDID from OF\n");
+#else
+	/* XXX use other methods later */
+#endif
+}
+
+static int aty128_dfp_parse_EDID(struct fb_info_aty128 *rinfo)
+{
+	unsigned char *block = rinfo->EDID;
+	unsigned int hblank, vblank;
+	unsigned int hOver_plus, vOver_plus;
+	unsigned int hSync_width, vSync_width;
+	unsigned int interlaced, synct, misc;
+	unsigned int hAct_high, vAct_high;
+	int k;
+
+	if (!block)
+		return 0;
+
+	/* jump to the detailed timing block section */
+	block += 54;
+
+	for (k = 0; k < 4; k++) {
+	  block = &rinfo->EDID[0x36 + (k*18)];
+
+	  if ((block[0] == 0) && (block[1] == 0) && 
+	      (block[2] == 0) && (block[4] == 0)) {
+	    continue;
+	  }
+
+
+	  default_var.pixclock = 100000000 / (block[0] + (block[1] << 8));
+	  default_var.xres = (block[2] + ((block[4] & 0xf0) << 4));
+	  default_var.xres_virtual = default_var.xres;
+	  hblank = (block[3] + ((block[4] & 0x0f) << 8));
+	  default_var.yres = (block[5] + ((block[7] & 0xf0) << 4));
+	  default_var.yres_virtual = default_var.yres;
+	  vblank = (block[6] + ((block[7] & 0x0f) << 8));
+	  hOver_plus = (block[8] + ((block[11] & 0xc0) << 2));
+	  hSync_width = (block[9] + ((block[11] & 0x30) << 4));
+	  vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2));
+	  vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4));
+
+	  default_var.xoffset = default_var.yoffset = 0;
+
+	  default_var.left_margin = (hblank - hOver_plus - hSync_width);
+	  default_var.right_margin = hOver_plus;
+	  default_var.upper_margin = (vblank - vOver_plus - vSync_width);
+	  default_var.lower_margin = vOver_plus;
+	  default_var.hsync_len = hSync_width;
+	  default_var.vsync_len = vSync_width;
+	  default_var.sync = 0;
+	  
+	  interlaced = ((block[17] & 0x80) >> 7);
+	  synct = ((block[17] & 0x18) >> 3);
+	  misc = ((block[17] & 0x06) >> 1);
+	  hAct_high = vAct_high = 0;
+	  if (synct == 3) {
+	    if (misc & 2)
+	      hAct_high = 1;
+	    if (misc & 1)
+	      vAct_high = 1;
+	  }
+	  
+	  if (synct == 3) {
+	    if (hAct_high)
+	      default_var.sync |= FB_SYNC_HOR_HIGH_ACT;
+	    if (vAct_high)
+	      default_var.sync |= FB_SYNC_VERT_HIGH_ACT;
+	  }
+	  
+	  default_var.vmode = 0;
+	  if (interlaced)
+	    default_var.vmode |= FB_VMODE_INTERLACED;
+
+	  DBG("detected panel size from EDID: %dx%d\n",
+	      default_var.xres, default_var.yres);
+
+	  return 1;
+	}
+	return 0;
+}
+
+
+
+#ifdef CONFIG_ALL_PPC
+static int aty128_get_EDID_OF(struct fb_info_aty128 *rinfo)
+{
+	struct device_node *dp;
+	unsigned char *pedid = NULL;
+
+	dp = pci_device_to_OF_node(rinfo->pdev);
+	pedid = (unsigned char *) get_property(dp, "DFP,EDID", 0);
+	if (!pedid)
+		pedid = (unsigned char *) get_property(dp, "LCD,EDID", 0);
+	if (!pedid)
+		pedid = (unsigned char *) get_property(dp, "EDID", 0);
+
+	if (pedid) {
+		rinfo->EDID = pedid;
+		return 1;
+	} else
+		return 0;
+}
+#endif /* CONFIG_ALL_PPC */
+
 
 /* fill in known card constants if pll_block is not available */
 static void __init

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-02-21  1:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-02-21  1:12 [PATCH] follow up: aty128fb and EDID Magnus Damm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).