aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/Kconfig5
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/fb_ddc.c116
-rw-r--r--include/linux/fb.h2
4 files changed, 124 insertions, 0 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 652d202adf75..d498e908f4b7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -53,6 +53,11 @@ config FB
53 (e.g. an accelerated X server) and that are not frame buffer 53 (e.g. an accelerated X server) and that are not frame buffer
54 device-aware may cause unexpected results. If unsure, say N. 54 device-aware may cause unexpected results. If unsure, say N.
55 55
56config FB_DDC
57 tristate
58 depends on FB && I2C && I2C_ALGOBIT
59 default n
60
56config FB_CFB_FILLRECT 61config FB_CFB_FILLRECT
57 tristate 62 tristate
58 depends on FB 63 depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 481c6c9695f8..a6980e9a2481 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
18obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o 18obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
19obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o 19obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
20obj-$(CONFIG_FB_MACMODES) += macmodes.o 20obj-$(CONFIG_FB_MACMODES) += macmodes.o
21obj-$(CONFIG_FB_DDC) += fb_ddc.o
21 22
22# Hardware specific drivers go first 23# Hardware specific drivers go first
23obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o 24obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o
diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c
new file mode 100644
index 000000000000..3aa6ebf68f17
--- /dev/null
+++ b/drivers/video/fb_ddc.c
@@ -0,0 +1,116 @@
1/*
2 * driver/vide/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/fb.h>
14#include <linux/i2c-algo-bit.h>
15
16#include "edid.h"
17
18#define DDC_ADDR 0x50
19
20static unsigned char *fb_do_probe_ddc_edid(struct i2c_adapter *adapter)
21{
22 unsigned char start = 0x0;
23 struct i2c_msg msgs[] = {
24 {
25 .addr = DDC_ADDR,
26 .len = 1,
27 .buf = &start,
28 }, {
29 .addr = DDC_ADDR,
30 .flags = I2C_M_RD,
31 .len = EDID_LENGTH,
32 }
33 };
34 unsigned char *buf;
35
36 buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
37 if (!buf) {
38 dev_warn(&adapter->dev, "unable to allocate memory for EDID "
39 "block.\n");
40 return NULL;
41 }
42 msgs[1].buf = buf;
43
44 if (i2c_transfer(adapter, msgs, 2) == 2)
45 return buf;
46
47 dev_warn(&adapter->dev, "unable to read EDID block.\n");
48 kfree(buf);
49 return NULL;
50}
51
52unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
53{
54 struct i2c_algo_bit_data *algo_data = adapter->algo_data;
55 unsigned char *edid = NULL;
56 int i, j;
57
58 algo_data->setscl(algo_data->data, 1);
59 algo_data->setscl(algo_data->data, 0);
60
61 for (i = 0; i < 3; i++) {
62 /* For some old monitors we need the
63 * following process to initialize/stop DDC
64 */
65 algo_data->setsda(algo_data->data, 0);
66 msleep(13);
67
68 algo_data->setscl(algo_data->data, 1);
69 for (j = 0; j < 5; j++) {
70 msleep(10);
71 if (algo_data->getscl(algo_data->data))
72 break;
73 }
74 if (j == 5)
75 continue;
76
77 algo_data->setsda(algo_data->data, 0);
78 msleep(15);
79 algo_data->setscl(algo_data->data, 0);
80 msleep(15);
81 algo_data->setsda(algo_data->data, 1);
82 msleep(15);
83
84 /* Do the real work */
85 edid = fb_do_probe_ddc_edid(adapter);
86 algo_data->setsda(algo_data->data, 0);
87 algo_data->setscl(algo_data->data, 0);
88 msleep(15);
89
90 algo_data->setscl(algo_data->data, 1);
91 for (j = 0; j < 10; j++) {
92 msleep(10);
93 if (algo_data->getscl(algo_data->data))
94 break;
95 }
96
97 algo_data->setsda(algo_data->data, 1);
98 msleep(15);
99 algo_data->setscl(algo_data->data, 0);
100 if (edid)
101 break;
102 }
103 /* Release the DDC lines when done or the Apple Cinema HD display
104 * will switch off
105 */
106 algo_data->setsda(algo_data->data, 0);
107 algo_data->setscl(algo_data->data, 0);
108
109 return edid;
110}
111
112EXPORT_SYMBOL_GPL(fb_ddc_read);
113
114MODULE_AUTHOR("Dennis Munsie <dmunsie@cecropia.com>");
115MODULE_DESCRIPTION("DDC/EDID reading support");
116MODULE_LICENSE("GPL");
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 2f335e966011..37aab314f0c4 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -2,6 +2,7 @@
2#define _LINUX_FB_H 2#define _LINUX_FB_H
3 3
4#include <asm/types.h> 4#include <asm/types.h>
5#include <linux/i2c.h>
5 6
6/* Definitions of frame buffers */ 7/* Definitions of frame buffers */
7 8
@@ -940,6 +941,7 @@ extern void fb_edid_to_monspecs(unsigned char *edid,
940 struct fb_monspecs *specs); 941 struct fb_monspecs *specs);
941extern void fb_destroy_modedb(struct fb_videomode *modedb); 942extern void fb_destroy_modedb(struct fb_videomode *modedb);
942extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb); 943extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
944extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
943 945
944/* drivers/video/modedb.c */ 946/* drivers/video/modedb.c */
945#define VESA_MODEDB_SIZE 34 947#define VESA_MODEDB_SIZE 34