diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2005-11-07 04:00:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 10:53:52 -0500 |
commit | 5fab851ea15206cc375582ad0db79f7827325098 (patch) | |
tree | bc7e3dd1e15d147c1aa482df69f433ff37246641 | |
parent | 8a0934f2969df4cdea81cf48fde4c8626b32325d (diff) |
[PATCH] i810fb: Cleanup I2C code
- The functions for reading the 1st and 2nd bus are essentially the same,
except for the register. Consolidate them all.
- According to Nicolas Boichat, there is an undocumented 3rd i2c bus for
attaching daughter cards. Add support for this.
Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/video/i810/i810-i2c.c | 135 | ||||
-rw-r--r-- | drivers/video/i810/i810.h | 3 | ||||
-rw-r--r-- | drivers/video/i810/i810_main.c | 2 | ||||
-rw-r--r-- | drivers/video/i810/i810_regs.h | 1 |
4 files changed, 51 insertions, 90 deletions
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index 689d2586366d..c61bad0da20f 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c | |||
@@ -46,92 +46,45 @@ static void i810i2c_setscl(void *data, int state) | |||
46 | struct i810fb_par *par = chan->par; | 46 | struct i810fb_par *par = chan->par; |
47 | u8 __iomem *mmio = par->mmio_start_virtual; | 47 | u8 __iomem *mmio = par->mmio_start_virtual; |
48 | 48 | ||
49 | i810_writel(mmio, GPIOB, (state ? SCL_VAL_OUT : 0) | SCL_DIR | | 49 | i810_writel(mmio, chan->ddc_base, (state ? SCL_VAL_OUT : 0) | SCL_DIR | |
50 | SCL_DIR_MASK | SCL_VAL_MASK); | 50 | SCL_DIR_MASK | SCL_VAL_MASK); |
51 | i810_readl(mmio, GPIOB); /* flush posted write */ | 51 | i810_readl(mmio, chan->ddc_base); /* flush posted write */ |
52 | } | 52 | } |
53 | 53 | ||
54 | static void i810i2c_setsda(void *data, int state) | 54 | static void i810i2c_setsda(void *data, int state) |
55 | { | 55 | { |
56 | struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; | 56 | struct i810fb_i2c_chan *chan = data; |
57 | struct i810fb_par *par = chan->par; | 57 | struct i810fb_par *par = chan->par; |
58 | u8 __iomem *mmio = par->mmio_start_virtual; | 58 | u8 __iomem *mmio = par->mmio_start_virtual; |
59 | 59 | ||
60 | i810_writel(mmio, GPIOB, (state ? SDA_VAL_OUT : 0) | SDA_DIR | | 60 | i810_writel(mmio, chan->ddc_base, (state ? SDA_VAL_OUT : 0) | SDA_DIR | |
61 | SDA_DIR_MASK | SDA_VAL_MASK); | 61 | SDA_DIR_MASK | SDA_VAL_MASK); |
62 | i810_readl(mmio, GPIOB); /* flush posted write */ | 62 | i810_readl(mmio, chan->ddc_base); /* flush posted write */ |
63 | } | 63 | } |
64 | 64 | ||
65 | static int i810i2c_getscl(void *data) | 65 | static int i810i2c_getscl(void *data) |
66 | { | 66 | { |
67 | struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; | 67 | struct i810fb_i2c_chan *chan = data; |
68 | struct i810fb_par *par = chan->par; | 68 | struct i810fb_par *par = chan->par; |
69 | u8 __iomem *mmio = par->mmio_start_virtual; | 69 | u8 __iomem *mmio = par->mmio_start_virtual; |
70 | 70 | ||
71 | i810_writel(mmio, GPIOB, SCL_DIR_MASK); | 71 | i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK); |
72 | i810_writel(mmio, GPIOB, 0); | 72 | i810_writel(mmio, chan->ddc_base, 0); |
73 | return (0 != (i810_readl(mmio, GPIOB) & SCL_VAL_IN)); | 73 | return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0); |
74 | } | 74 | } |
75 | 75 | ||
76 | static int i810i2c_getsda(void *data) | 76 | static int i810i2c_getsda(void *data) |
77 | { | 77 | { |
78 | struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; | 78 | struct i810fb_i2c_chan *chan = data; |
79 | struct i810fb_par *par = chan->par; | 79 | struct i810fb_par *par = chan->par; |
80 | u8 __iomem *mmio = par->mmio_start_virtual; | 80 | u8 __iomem *mmio = par->mmio_start_virtual; |
81 | 81 | ||
82 | i810_writel(mmio, GPIOB, SDA_DIR_MASK); | 82 | i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK); |
83 | i810_writel(mmio, GPIOB, 0); | 83 | i810_writel(mmio, chan->ddc_base, 0); |
84 | return (0 != (i810_readl(mmio, GPIOB) & SDA_VAL_IN)); | 84 | return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0); |
85 | } | ||
86 | |||
87 | static void i810ddc_setscl(void *data, int state) | ||
88 | { | ||
89 | struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; | ||
90 | struct i810fb_par *par = chan->par; | ||
91 | u8 __iomem *mmio = par->mmio_start_virtual; | ||
92 | |||
93 | i810_writel(mmio, GPIOA, (state ? SCL_VAL_OUT : 0) | SCL_DIR | | ||
94 | SCL_DIR_MASK | SCL_VAL_MASK); | ||
95 | i810_readl(mmio, GPIOA); /* flush posted write */ | ||
96 | } | ||
97 | |||
98 | static void i810ddc_setsda(void *data, int state) | ||
99 | { | ||
100 | struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; | ||
101 | struct i810fb_par *par = chan->par; | ||
102 | u8 __iomem *mmio = par->mmio_start_virtual; | ||
103 | |||
104 | i810_writel(mmio, GPIOA, (state ? SDA_VAL_OUT : 0) | SDA_DIR | | ||
105 | SDA_DIR_MASK | SDA_VAL_MASK); | ||
106 | i810_readl(mmio, GPIOA); /* flush posted write */ | ||
107 | } | ||
108 | |||
109 | static int i810ddc_getscl(void *data) | ||
110 | { | ||
111 | struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; | ||
112 | struct i810fb_par *par = chan->par; | ||
113 | u8 __iomem *mmio = par->mmio_start_virtual; | ||
114 | |||
115 | i810_writel(mmio, GPIOA, SCL_DIR_MASK); | ||
116 | i810_writel(mmio, GPIOA, 0); | ||
117 | return (0 != (i810_readl(mmio, GPIOA) & SCL_VAL_IN)); | ||
118 | } | ||
119 | |||
120 | static int i810ddc_getsda(void *data) | ||
121 | { | ||
122 | struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; | ||
123 | struct i810fb_par *par = chan->par; | ||
124 | u8 __iomem *mmio = par->mmio_start_virtual; | ||
125 | |||
126 | i810_writel(mmio, GPIOA, SDA_DIR_MASK); | ||
127 | i810_writel(mmio, GPIOA, 0); | ||
128 | return (0 != (i810_readl(mmio, GPIOA) & SDA_VAL_IN)); | ||
129 | } | 85 | } |
130 | 86 | ||
131 | #define I2C_ALGO_DDC_I810 0x0e0000 | 87 | static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) |
132 | #define I2C_ALGO_I2C_I810 0x0f0000 | ||
133 | static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, | ||
134 | int conn) | ||
135 | { | 88 | { |
136 | int rc; | 89 | int rc; |
137 | 90 | ||
@@ -139,22 +92,11 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, | |||
139 | chan->adapter.owner = THIS_MODULE; | 92 | chan->adapter.owner = THIS_MODULE; |
140 | chan->adapter.algo_data = &chan->algo; | 93 | chan->adapter.algo_data = &chan->algo; |
141 | chan->adapter.dev.parent = &chan->par->dev->dev; | 94 | chan->adapter.dev.parent = &chan->par->dev->dev; |
142 | switch (conn) { | 95 | chan->adapter.id = I2C_HW_B_I810; |
143 | case 1: | 96 | chan->algo.setsda = i810i2c_setsda; |
144 | chan->adapter.id = I2C_ALGO_DDC_I810; | 97 | chan->algo.setscl = i810i2c_setscl; |
145 | chan->algo.setsda = i810ddc_setsda; | 98 | chan->algo.getsda = i810i2c_getsda; |
146 | chan->algo.setscl = i810ddc_setscl; | 99 | chan->algo.getscl = i810i2c_getscl; |
147 | chan->algo.getsda = i810ddc_getsda; | ||
148 | chan->algo.getscl = i810ddc_getscl; | ||
149 | break; | ||
150 | case 2: | ||
151 | chan->adapter.id = I2C_ALGO_I2C_I810; | ||
152 | chan->algo.setsda = i810i2c_setsda; | ||
153 | chan->algo.setscl = i810i2c_setscl; | ||
154 | chan->algo.getsda = i810i2c_getsda; | ||
155 | chan->algo.getscl = i810i2c_getscl; | ||
156 | break; | ||
157 | } | ||
158 | chan->algo.udelay = 10; | 100 | chan->algo.udelay = 10; |
159 | chan->algo.mdelay = 10; | 101 | chan->algo.mdelay = 10; |
160 | chan->algo.timeout = (HZ/2); | 102 | chan->algo.timeout = (HZ/2); |
@@ -168,11 +110,15 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, | |||
168 | udelay(20); | 110 | udelay(20); |
169 | 111 | ||
170 | rc = i2c_bit_add_bus(&chan->adapter); | 112 | rc = i2c_bit_add_bus(&chan->adapter); |
113 | |||
171 | if (rc == 0) | 114 | if (rc == 0) |
172 | dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name); | 115 | dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name); |
173 | else | 116 | else { |
174 | dev_warn(&chan->par->dev->dev, "Failed to register I2C bus " | 117 | dev_warn(&chan->par->dev->dev, "Failed to register I2C bus " |
175 | "%s.\n", name); | 118 | "%s.\n", name); |
119 | chan->par = NULL; | ||
120 | } | ||
121 | |||
176 | return rc; | 122 | return rc; |
177 | } | 123 | } |
178 | 124 | ||
@@ -180,8 +126,14 @@ void i810_create_i2c_busses(struct i810fb_par *par) | |||
180 | { | 126 | { |
181 | par->chan[0].par = par; | 127 | par->chan[0].par = par; |
182 | par->chan[1].par = par; | 128 | par->chan[1].par = par; |
183 | i810_setup_i2c_bus(&par->chan[0], "I810-DDC", 1); | 129 | par->chan[2].par = par; |
184 | i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 2); | 130 | |
131 | par->chan[0].ddc_base = GPIOA; | ||
132 | i810_setup_i2c_bus(&par->chan[0], "I810-DDC"); | ||
133 | par->chan[1].ddc_base = GPIOB; | ||
134 | i810_setup_i2c_bus(&par->chan[1], "I810-I2C"); | ||
135 | par->chan[2].ddc_base = GPIOC; | ||
136 | i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC"); | ||
185 | } | 137 | } |
186 | 138 | ||
187 | void i810_delete_i2c_busses(struct i810fb_par *par) | 139 | void i810_delete_i2c_busses(struct i810fb_par *par) |
@@ -189,9 +141,14 @@ void i810_delete_i2c_busses(struct i810fb_par *par) | |||
189 | if (par->chan[0].par) | 141 | if (par->chan[0].par) |
190 | i2c_bit_del_bus(&par->chan[0].adapter); | 142 | i2c_bit_del_bus(&par->chan[0].adapter); |
191 | par->chan[0].par = NULL; | 143 | par->chan[0].par = NULL; |
144 | |||
192 | if (par->chan[1].par) | 145 | if (par->chan[1].par) |
193 | i2c_bit_del_bus(&par->chan[1].adapter); | 146 | i2c_bit_del_bus(&par->chan[1].adapter); |
194 | par->chan[1].par = NULL; | 147 | par->chan[1].par = NULL; |
148 | |||
149 | if (par->chan[2].par) | ||
150 | i2c_bit_del_bus(&par->chan[2].adapter); | ||
151 | par->chan[2].par = NULL; | ||
195 | } | 152 | } |
196 | 153 | ||
197 | static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan) | 154 | static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan) |
@@ -221,6 +178,7 @@ static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan) | |||
221 | DPRINTK("i810-i2c: I2C Transfer successful\n"); | 178 | DPRINTK("i810-i2c: I2C Transfer successful\n"); |
222 | return buf; | 179 | return buf; |
223 | } | 180 | } |
181 | |||
224 | DPRINTK("i810-i2c: Unable to read EDID block.\n"); | 182 | DPRINTK("i810-i2c: Unable to read EDID block.\n"); |
225 | kfree(buf); | 183 | kfree(buf); |
226 | return NULL; | 184 | return NULL; |
@@ -233,7 +191,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) | |||
233 | int i; | 191 | int i; |
234 | 192 | ||
235 | DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn); | 193 | DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn); |
236 | if (conn < 3) { | 194 | if (conn < 4) { |
237 | for (i = 0; i < 3; i++) { | 195 | for (i = 0; i < 3; i++) { |
238 | /* Do the real work */ | 196 | /* Do the real work */ |
239 | edid = i810_do_probe_i2c_edid(&par->chan[conn-1]); | 197 | edid = i810_do_probe_i2c_edid(&par->chan[conn-1]); |
@@ -241,11 +199,14 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) | |||
241 | break; | 199 | break; |
242 | } | 200 | } |
243 | } else { | 201 | } else { |
244 | DPRINTK("i810-i2c: Getting EDID from BIOS\n"); | 202 | const u8 *e = fb_firmware_edid(info->device); |
245 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | 203 | |
246 | if (edid) | 204 | if (e != NULL) { |
247 | memcpy(edid, fb_firmware_edid(info->device), | 205 | DPRINTK("i810-i2c: Getting EDID from BIOS\n"); |
248 | EDID_LENGTH); | 206 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); |
207 | if (edid) | ||
208 | memcpy(edid, e, EDID_LENGTH); | ||
209 | } | ||
249 | } | 210 | } |
250 | 211 | ||
251 | if (out_edid) | 212 | if (out_edid) |
@@ -253,5 +214,3 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) | |||
253 | 214 | ||
254 | return (edid) ? 0 : 1; | 215 | return (edid) ? 0 : 1; |
255 | } | 216 | } |
256 | |||
257 | |||
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h index d48949ceaacc..6c187d5fe951 100644 --- a/drivers/video/i810/i810.h +++ b/drivers/video/i810/i810.h | |||
@@ -249,6 +249,7 @@ struct i810fb_i2c_chan { | |||
249 | struct i810fb_par *par; | 249 | struct i810fb_par *par; |
250 | struct i2c_adapter adapter; | 250 | struct i2c_adapter adapter; |
251 | struct i2c_algo_bit_data algo; | 251 | struct i2c_algo_bit_data algo; |
252 | unsigned long ddc_base; | ||
252 | }; | 253 | }; |
253 | 254 | ||
254 | struct i810fb_par { | 255 | struct i810fb_par { |
@@ -262,7 +263,7 @@ struct i810fb_par { | |||
262 | struct heap_data iring; | 263 | struct heap_data iring; |
263 | struct heap_data cursor_heap; | 264 | struct heap_data cursor_heap; |
264 | struct vgastate state; | 265 | struct vgastate state; |
265 | struct i810fb_i2c_chan chan[2]; | 266 | struct i810fb_i2c_chan chan[3]; |
266 | atomic_t use_count; | 267 | atomic_t use_count; |
267 | u32 pseudo_palette[17]; | 268 | u32 pseudo_palette[17]; |
268 | unsigned long mmio_start_phys; | 269 | unsigned long mmio_start_phys; |
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 0dbc9ddb6766..4175b2d8513c 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
@@ -1854,7 +1854,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info) | |||
1854 | #ifdef CONFIG_FB_I810_I2C | 1854 | #ifdef CONFIG_FB_I810_I2C |
1855 | i810_create_i2c_busses(par); | 1855 | i810_create_i2c_busses(par); |
1856 | 1856 | ||
1857 | for (i = 0; i < 3; i++) { | 1857 | for (i = 0; i < 4; i++) { |
1858 | err = i810_probe_i2c_connector(info, &par->edid, i+1); | 1858 | err = i810_probe_i2c_connector(info, &par->edid, i+1); |
1859 | if (!err) | 1859 | if (!err) |
1860 | break; | 1860 | break; |
diff --git a/drivers/video/i810/i810_regs.h b/drivers/video/i810/i810_regs.h index 6e4b9afa4d98..91c6bd9d0d0d 100644 --- a/drivers/video/i810/i810_regs.h +++ b/drivers/video/i810/i810_regs.h | |||
@@ -70,6 +70,7 @@ | |||
70 | #define HVSYNC 0x05000 | 70 | #define HVSYNC 0x05000 |
71 | #define GPIOA 0x05010 | 71 | #define GPIOA 0x05010 |
72 | #define GPIOB 0x05014 | 72 | #define GPIOB 0x05014 |
73 | #define GPIOC 0x0501C | ||
73 | 74 | ||
74 | /* Clock Control and Power Management Registers (06000h 06FFFh) */ | 75 | /* Clock Control and Power Management Registers (06000h 06FFFh) */ |
75 | #define DCLK_0D 0x06000 | 76 | #define DCLK_0D 0x06000 |