brintos

brintos / linux-shallow public Read only

0
0
Text · 2.7 KiB · e251432 Raw
127 lines · c
1/*2 * drivers/video/fb_ddc.c - DDC/EDID read support.3 *4 *  Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>5 *6 * This file is subject to the terms and conditions of the GNU General Public7 * License.  See the file COPYING in the main directory of this archive8 * for more details.9 */10 11#include <linux/delay.h>12#include <linux/device.h>13#include <linux/module.h>14#include <linux/fb.h>15#include <linux/i2c-algo-bit.h>16#include <linux/slab.h>17 18#include "../edid.h"19 20#define DDC_ADDR	0x5021 22static unsigned char *fb_do_probe_ddc_edid(struct i2c_adapter *adapter)23{24	unsigned char start = 0x0;25	unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);26	struct i2c_msg msgs[] = {27		{28			.addr	= DDC_ADDR,29			.flags	= 0,30			.len	= 1,31			.buf	= &start,32		}, {33			.addr	= DDC_ADDR,34			.flags	= I2C_M_RD,35			.len	= EDID_LENGTH,36			.buf	= buf,37		}38	};39 40	if (!buf) {41		dev_warn(&adapter->dev, "unable to allocate memory for EDID "42			 "block.\n");43		return NULL;44	}45 46	if (i2c_transfer(adapter, msgs, 2) == 2)47		return buf;48 49	dev_warn(&adapter->dev, "unable to read EDID block.\n");50	kfree(buf);51	return NULL;52}53 54unsigned char *fb_ddc_read(struct i2c_adapter *adapter)55{56	struct i2c_algo_bit_data *algo_data = adapter->algo_data;57	unsigned char *edid = NULL;58	int i, j;59 60	algo_data->setscl(algo_data->data, 1);61 62	for (i = 0; i < 3; i++) {63		/* For some old monitors we need the64		 * following process to initialize/stop DDC65		 */66		algo_data->setsda(algo_data->data, 1);67		msleep(13);68 69		algo_data->setscl(algo_data->data, 1);70		if (algo_data->getscl) {71			for (j = 0; j < 5; j++) {72				msleep(10);73				if (algo_data->getscl(algo_data->data))74					break;75			}76			if (j == 5)77				continue;78		} else {79			udelay(algo_data->udelay);80		}81 82		algo_data->setsda(algo_data->data, 0);83		msleep(15);84		algo_data->setscl(algo_data->data, 0);85		msleep(15);86		algo_data->setsda(algo_data->data, 1);87		msleep(15);88 89		/* Do the real work */90		edid = fb_do_probe_ddc_edid(adapter);91		algo_data->setsda(algo_data->data, 0);92		algo_data->setscl(algo_data->data, 0);93		msleep(15);94 95		algo_data->setscl(algo_data->data, 1);96		if (algo_data->getscl) {97			for (j = 0; j < 10; j++) {98				msleep(10);99				if (algo_data->getscl(algo_data->data))100					break;101			}102		} else {103			udelay(algo_data->udelay);104		}105 106		algo_data->setsda(algo_data->data, 1);107		msleep(15);108		algo_data->setscl(algo_data->data, 0);109		algo_data->setsda(algo_data->data, 0);110		if (edid)111			break;112	}113	/* Release the DDC lines when done or the Apple Cinema HD display114	 * will switch off115	 */116	algo_data->setsda(algo_data->data, 1);117	algo_data->setscl(algo_data->data, 1);118 119	return edid;120}121 122EXPORT_SYMBOL_GPL(fb_ddc_read);123 124MODULE_AUTHOR("Dennis Munsie <dmunsie@cecropia.com>");125MODULE_DESCRIPTION("DDC/EDID reading support");126MODULE_LICENSE("GPL");127