brintos

brintos / linux-shallow public Read only

0
0
Text · 1.7 KiB · 9791381 Raw
86 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>4 */5/*6 * generic EDID driver7 */8 9#include <linux/slab.h>10#include <linux/fb.h>11#include "via_aux.h"12#include "../edid.h"13 14 15static const char *name = "EDID";16 17 18static void query_edid(struct via_aux_drv *drv)19{20	struct fb_monspecs *spec = drv->data;21	unsigned char edid[EDID_LENGTH];22	bool valid = false;23 24	if (spec) {25		fb_destroy_modedb(spec->modedb);26	} else {27		spec = kmalloc(sizeof(*spec), GFP_KERNEL);28		if (!spec)29			return;30	}31 32	spec->version = spec->revision = 0;33	if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {34		fb_edid_to_monspecs(edid, spec);35		valid = spec->version || spec->revision;36	}37 38	if (!valid) {39		kfree(spec);40		spec = NULL;41	} else42		printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor);43 44	drv->data = spec;45}46 47static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv)48{49	struct fb_monspecs *spec = drv->data;50	int i;51 52	if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL))53		return NULL;54 55	for (i = 0; i < spec->modedb_len; i++) {56		if (spec->modedb[i].flag & FB_MODE_IS_FIRST &&57			spec->modedb[i].flag & FB_MODE_IS_DETAILED)58			return &spec->modedb[i];59	}60 61	return NULL;62}63 64static void cleanup(struct via_aux_drv *drv)65{66	struct fb_monspecs *spec = drv->data;67 68	if (spec)69		fb_destroy_modedb(spec->modedb);70}71 72void via_aux_edid_probe(struct via_aux_bus *bus)73{74	struct via_aux_drv drv = {75		.bus	=	bus,76		.addr	=	0x50,77		.name	=	name,78		.cleanup	=	cleanup,79		.get_preferred_mode	=	get_preferred_mode};80 81	query_edid(&drv);82 83	/* as EDID devices can be connected/disconnected just add the driver */84	via_aux_add(&drv);85}86