150472Speter/*
27130Srgrimes * linux/drivers/video/nvidia/nv_of.c
350203Srgrimes *
450203Srgrimes * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
57130Srgrimes *
639161Sobrien * Based on rivafb-i2c.c
78571Srgrimes *
88571Srgrimes * This file is subject to the terms and conditions of the GNU General Public
97130Srgrimes * License.  See the file COPYING in the main directory of this archive
1039250Sgibbs * for more details.
1139250Sgibbs */
1239250Sgibbs
1339250Sgibbs#include <linux/module.h>
1456583Sn_hibma#include <linux/kernel.h>
1560724Speter#include <linux/delay.h>
1660724Speter#include <linux/gfp.h>
1756583Sn_hibma#include <linux/pci.h>
1856583Sn_hibma#include <linux/fb.h>
1956583Sn_hibma
208571Srgrimes#include <asm/io.h>
2123271Sbde
2223271Sbde#include "nv_type.h"
237130Srgrimes#include "nv_local.h"
2426453Sache#include "nv_proto.h"
2526453Sache
2626453Sache#include "../edid.h"
2726453Sache
2826453Sacheint nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
2926453Sache{
3026453Sache	struct nvidia_par *par = info->par;
3126453Sache	struct device_node *parent, *dp;
3226453Sache	const unsigned char *pedid = NULL;
3326453Sache	static char *propnames[] = {
3426453Sache		"DFP,EDID", "LCD,EDID", "EDID", "EDID1",
3526453Sache		"EDID,B", "EDID,A", NULL };
3639271Sphk	int i;
3739271Sphk
3852419Sjulian	parent = pci_device_to_OF_node(par->pci_dev);
3952419Sjulian	if (parent == NULL)
4026453Sache		return -1;
4126453Sache	if (par->twoHeads) {
4252905Sjlemon		const char *pname;
4352905Sjlemon		int len;
4426453Sache
4526453Sache		for_each_child_of_node(parent, dp) {
4626453Sache			pname = of_get_property(dp, "name", NULL);
4726453Sache			if (!pname)
4852228Sbp				continue;
4952228Sbp			len = strlen(pname);
5026453Sache			if ((pname[len-1] == 'A' && conn == 1) ||
5126453Sache			    (pname[len-1] == 'B' && conn == 2)) {
5226453Sache				for (i = 0; propnames[i] != NULL; ++i) {
5326453Sache					pedid = of_get_property(dp,
5454091Ssemenu							propnames[i], NULL);
5554091Ssemenu					if (pedid != NULL)
5652228Sbp						break;
5752228Sbp				}
588571Srgrimes				of_node_put(dp);
597130Srgrimes				break;
6055097Skris			}
6155097Skris		}
6226453Sache	}
6326453Sache	if (pedid == NULL) {
6434030Sdufault		for (i = 0; propnames[i] != NULL; ++i) {
6534030Sdufault			pedid = of_get_property(parent, propnames[i], NULL);
668571Srgrimes			if (pedid != NULL)
677130Srgrimes				break;
688571Srgrimes		}
697130Srgrimes	}
708571Srgrimes	if (pedid) {
717130Srgrimes		*out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
728571Srgrimes		if (*out_edid == NULL)
737130Srgrimes			return -1;
7441230Sjdp		printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn);
7541230Sjdp		return 0;
768571Srgrimes	}
777130Srgrimes	return -1;
7826453Sache}
7926453Sache