162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * linux/drivers/video/nvidia/nv_of.c
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Based on rivafb-i2c.c
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
962306a36Sopenharmony_ci * License.  See the file COPYING in the main directory of this archive
1062306a36Sopenharmony_ci * for more details.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/kernel.h>
1562306a36Sopenharmony_ci#include <linux/delay.h>
1662306a36Sopenharmony_ci#include <linux/gfp.h>
1762306a36Sopenharmony_ci#include <linux/pci.h>
1862306a36Sopenharmony_ci#include <linux/fb.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <asm/io.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include "nv_type.h"
2362306a36Sopenharmony_ci#include "nv_local.h"
2462306a36Sopenharmony_ci#include "nv_proto.h"
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include "../edid.h"
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ciint nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	struct nvidia_par *par = info->par;
3162306a36Sopenharmony_ci	struct device_node *parent, *dp;
3262306a36Sopenharmony_ci	const unsigned char *pedid = NULL;
3362306a36Sopenharmony_ci	static char *propnames[] = {
3462306a36Sopenharmony_ci		"DFP,EDID", "LCD,EDID", "EDID", "EDID1",
3562306a36Sopenharmony_ci		"EDID,B", "EDID,A", NULL };
3662306a36Sopenharmony_ci	int i;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	parent = pci_device_to_OF_node(par->pci_dev);
3962306a36Sopenharmony_ci	if (parent == NULL)
4062306a36Sopenharmony_ci		return -1;
4162306a36Sopenharmony_ci	if (par->twoHeads) {
4262306a36Sopenharmony_ci		const char *pname;
4362306a36Sopenharmony_ci		int len;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci		for_each_child_of_node(parent, dp) {
4662306a36Sopenharmony_ci			pname = of_get_property(dp, "name", NULL);
4762306a36Sopenharmony_ci			if (!pname)
4862306a36Sopenharmony_ci				continue;
4962306a36Sopenharmony_ci			len = strlen(pname);
5062306a36Sopenharmony_ci			if ((pname[len-1] == 'A' && conn == 1) ||
5162306a36Sopenharmony_ci			    (pname[len-1] == 'B' && conn == 2)) {
5262306a36Sopenharmony_ci				for (i = 0; propnames[i] != NULL; ++i) {
5362306a36Sopenharmony_ci					pedid = of_get_property(dp,
5462306a36Sopenharmony_ci							propnames[i], NULL);
5562306a36Sopenharmony_ci					if (pedid != NULL)
5662306a36Sopenharmony_ci						break;
5762306a36Sopenharmony_ci				}
5862306a36Sopenharmony_ci				of_node_put(dp);
5962306a36Sopenharmony_ci				break;
6062306a36Sopenharmony_ci			}
6162306a36Sopenharmony_ci		}
6262306a36Sopenharmony_ci	}
6362306a36Sopenharmony_ci	if (pedid == NULL) {
6462306a36Sopenharmony_ci		for (i = 0; propnames[i] != NULL; ++i) {
6562306a36Sopenharmony_ci			pedid = of_get_property(parent, propnames[i], NULL);
6662306a36Sopenharmony_ci			if (pedid != NULL)
6762306a36Sopenharmony_ci				break;
6862306a36Sopenharmony_ci		}
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci	if (pedid) {
7162306a36Sopenharmony_ci		*out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
7262306a36Sopenharmony_ci		if (*out_edid == NULL)
7362306a36Sopenharmony_ci			return -1;
7462306a36Sopenharmony_ci		printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn);
7562306a36Sopenharmony_ci		return 0;
7662306a36Sopenharmony_ci	}
7762306a36Sopenharmony_ci	return -1;
7862306a36Sopenharmony_ci}
79