File Index
Files and directories
Sign in
FILE

fb_ddc.c

File preview with syntax highlighting.

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