18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * linux/drivers/video/nvidia/nv_of.c
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Based on rivafb-i2c.c
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
98c2ecf20Sopenharmony_ci * License.  See the file COPYING in the main directory of this archive
108c2ecf20Sopenharmony_ci * for more details.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/kernel.h>
158c2ecf20Sopenharmony_ci#include <linux/delay.h>
168c2ecf20Sopenharmony_ci#include <linux/gfp.h>
178c2ecf20Sopenharmony_ci#include <linux/pci.h>
188c2ecf20Sopenharmony_ci#include <linux/fb.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <asm/io.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "nv_type.h"
238c2ecf20Sopenharmony_ci#include "nv_local.h"
248c2ecf20Sopenharmony_ci#include "nv_proto.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#include "../edid.h"
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciint nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	struct nvidia_par *par = info->par;
318c2ecf20Sopenharmony_ci	struct device_node *parent, *dp;
328c2ecf20Sopenharmony_ci	const unsigned char *pedid = NULL;
338c2ecf20Sopenharmony_ci	static char *propnames[] = {
348c2ecf20Sopenharmony_ci		"DFP,EDID", "LCD,EDID", "EDID", "EDID1",
358c2ecf20Sopenharmony_ci		"EDID,B", "EDID,A", NULL };
368c2ecf20Sopenharmony_ci	int i;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	parent = pci_device_to_OF_node(par->pci_dev);
398c2ecf20Sopenharmony_ci	if (parent == NULL)
408c2ecf20Sopenharmony_ci		return -1;
418c2ecf20Sopenharmony_ci	if (par->twoHeads) {
428c2ecf20Sopenharmony_ci		const char *pname;
438c2ecf20Sopenharmony_ci		int len;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci		for (dp = NULL;
468c2ecf20Sopenharmony_ci		     (dp = of_get_next_child(parent, dp)) != NULL;) {
478c2ecf20Sopenharmony_ci			pname = of_get_property(dp, "name", NULL);
488c2ecf20Sopenharmony_ci			if (!pname)
498c2ecf20Sopenharmony_ci				continue;
508c2ecf20Sopenharmony_ci			len = strlen(pname);
518c2ecf20Sopenharmony_ci			if ((pname[len-1] == 'A' && conn == 1) ||
528c2ecf20Sopenharmony_ci			    (pname[len-1] == 'B' && conn == 2)) {
538c2ecf20Sopenharmony_ci				for (i = 0; propnames[i] != NULL; ++i) {
548c2ecf20Sopenharmony_ci					pedid = of_get_property(dp,
558c2ecf20Sopenharmony_ci							propnames[i], NULL);
568c2ecf20Sopenharmony_ci					if (pedid != NULL)
578c2ecf20Sopenharmony_ci						break;
588c2ecf20Sopenharmony_ci				}
598c2ecf20Sopenharmony_ci				of_node_put(dp);
608c2ecf20Sopenharmony_ci				break;
618c2ecf20Sopenharmony_ci			}
628c2ecf20Sopenharmony_ci		}
638c2ecf20Sopenharmony_ci	}
648c2ecf20Sopenharmony_ci	if (pedid == NULL) {
658c2ecf20Sopenharmony_ci		for (i = 0; propnames[i] != NULL; ++i) {
668c2ecf20Sopenharmony_ci			pedid = of_get_property(parent, propnames[i], NULL);
678c2ecf20Sopenharmony_ci			if (pedid != NULL)
688c2ecf20Sopenharmony_ci				break;
698c2ecf20Sopenharmony_ci		}
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci	if (pedid) {
728c2ecf20Sopenharmony_ci		*out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
738c2ecf20Sopenharmony_ci		if (*out_edid == NULL)
748c2ecf20Sopenharmony_ci			return -1;
758c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn);
768c2ecf20Sopenharmony_ci		return 0;
778c2ecf20Sopenharmony_ci	}
788c2ecf20Sopenharmony_ci	return -1;
798c2ecf20Sopenharmony_ci}
80