0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/delay.h>
0012 #include <linux/device.h>
0013 #include <linux/module.h>
0014 #include <linux/fb.h>
0015 #include <linux/i2c-algo-bit.h>
0016 #include <linux/slab.h>
0017
0018 #include "../edid.h"
0019
0020 #define DDC_ADDR 0x50
0021
0022 static unsigned char *fb_do_probe_ddc_edid(struct i2c_adapter *adapter)
0023 {
0024 unsigned char start = 0x0;
0025 unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
0026 struct i2c_msg msgs[] = {
0027 {
0028 .addr = DDC_ADDR,
0029 .flags = 0,
0030 .len = 1,
0031 .buf = &start,
0032 }, {
0033 .addr = DDC_ADDR,
0034 .flags = I2C_M_RD,
0035 .len = EDID_LENGTH,
0036 .buf = buf,
0037 }
0038 };
0039
0040 if (!buf) {
0041 dev_warn(&adapter->dev, "unable to allocate memory for EDID "
0042 "block.\n");
0043 return NULL;
0044 }
0045
0046 if (i2c_transfer(adapter, msgs, 2) == 2)
0047 return buf;
0048
0049 dev_warn(&adapter->dev, "unable to read EDID block.\n");
0050 kfree(buf);
0051 return NULL;
0052 }
0053
0054 unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
0055 {
0056 struct i2c_algo_bit_data *algo_data = adapter->algo_data;
0057 unsigned char *edid = NULL;
0058 int i, j;
0059
0060 algo_data->setscl(algo_data->data, 1);
0061
0062 for (i = 0; i < 3; i++) {
0063
0064
0065
0066 algo_data->setsda(algo_data->data, 1);
0067 msleep(13);
0068
0069 algo_data->setscl(algo_data->data, 1);
0070 if (algo_data->getscl) {
0071 for (j = 0; j < 5; j++) {
0072 msleep(10);
0073 if (algo_data->getscl(algo_data->data))
0074 break;
0075 }
0076 if (j == 5)
0077 continue;
0078 } else {
0079 udelay(algo_data->udelay);
0080 }
0081
0082 algo_data->setsda(algo_data->data, 0);
0083 msleep(15);
0084 algo_data->setscl(algo_data->data, 0);
0085 msleep(15);
0086 algo_data->setsda(algo_data->data, 1);
0087 msleep(15);
0088
0089
0090 edid = fb_do_probe_ddc_edid(adapter);
0091 algo_data->setsda(algo_data->data, 0);
0092 algo_data->setscl(algo_data->data, 0);
0093 msleep(15);
0094
0095 algo_data->setscl(algo_data->data, 1);
0096 if (algo_data->getscl) {
0097 for (j = 0; j < 10; j++) {
0098 msleep(10);
0099 if (algo_data->getscl(algo_data->data))
0100 break;
0101 }
0102 } else {
0103 udelay(algo_data->udelay);
0104 }
0105
0106 algo_data->setsda(algo_data->data, 1);
0107 msleep(15);
0108 algo_data->setscl(algo_data->data, 0);
0109 algo_data->setsda(algo_data->data, 0);
0110 if (edid)
0111 break;
0112 }
0113
0114
0115
0116 algo_data->setsda(algo_data->data, 1);
0117 algo_data->setscl(algo_data->data, 1);
0118
0119 adapter->class |= I2C_CLASS_DDC;
0120 return edid;
0121 }
0122
0123 EXPORT_SYMBOL_GPL(fb_ddc_read);
0124
0125 MODULE_AUTHOR("Dennis Munsie <dmunsie@cecropia.com>");
0126 MODULE_DESCRIPTION("DDC/EDID reading support");
0127 MODULE_LICENSE("GPL");