follow up: aty128fb and EDID
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