Skip to contentSkip to conversation

follow up: aty128fb and EDID

PATCH New Magnus Damm 1 participant 1 message Feb 21, 2003 Framebuffer layer

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 follow up: aty128fb and EDID

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

drivers/video/aty128fb.c +127 -1
@@ -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