Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Antonino A. Daplas and committed by
Linus Torvalds
5fab851e 8a0934f2

+51 -90
+47 -88
drivers/video/i810/i810-i2c.c
··· 46 46 struct i810fb_par *par = chan->par; 47 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 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 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 57 struct i810fb_par *par = chan->par; 58 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 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 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 68 struct i810fb_par *par = chan->par; 69 69 u8 __iomem *mmio = par->mmio_start_virtual; 70 70 71 - i810_writel(mmio, GPIOB, SCL_DIR_MASK); 72 - i810_writel(mmio, GPIOB, 0); 73 - return (0 != (i810_readl(mmio, GPIOB) & SCL_VAL_IN)); 71 + i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK); 72 + i810_writel(mmio, chan->ddc_base, 0); 73 + return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0); 74 74 } 75 75 76 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 79 struct i810fb_par *par = chan->par; 80 80 u8 __iomem *mmio = par->mmio_start_virtual; 81 81 82 - i810_writel(mmio, GPIOB, SDA_DIR_MASK); 83 - i810_writel(mmio, GPIOB, 0); 84 - return (0 != (i810_readl(mmio, GPIOB) & SDA_VAL_IN)); 82 + i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK); 83 + i810_writel(mmio, chan->ddc_base, 0); 84 + return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0); 85 85 } 86 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 - } 130 - 131 - #define I2C_ALGO_DDC_I810 0x0e0000 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) 87 + static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) 135 88 { 136 89 int rc; 137 90 ··· 92 139 chan->adapter.owner = THIS_MODULE; 93 140 chan->adapter.algo_data = &chan->algo; 94 141 chan->adapter.dev.parent = &chan->par->dev->dev; 95 - switch (conn) { 96 - case 1: 97 - chan->adapter.id = I2C_ALGO_DDC_I810; 98 - chan->algo.setsda = i810ddc_setsda; 99 - chan->algo.setscl = i810ddc_setscl; 100 - chan->algo.getsda = i810ddc_getsda; 101 - chan->algo.getscl = i810ddc_getscl; 102 - break; 103 - case 2: 104 - chan->adapter.id = I2C_ALGO_I2C_I810; 105 - chan->algo.setsda = i810i2c_setsda; 106 - chan->algo.setscl = i810i2c_setscl; 107 - chan->algo.getsda = i810i2c_getsda; 108 - chan->algo.getscl = i810i2c_getscl; 109 - break; 110 - } 142 + chan->adapter.id = I2C_HW_B_I810; 143 + chan->algo.setsda = i810i2c_setsda; 144 + chan->algo.setscl = i810i2c_setscl; 145 + chan->algo.getsda = i810i2c_getsda; 146 + chan->algo.getscl = i810i2c_getscl; 111 147 chan->algo.udelay = 10; 112 148 chan->algo.mdelay = 10; 113 149 chan->algo.timeout = (HZ/2); ··· 110 168 udelay(20); 111 169 112 170 rc = i2c_bit_add_bus(&chan->adapter); 171 + 113 172 if (rc == 0) 114 173 dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name); 115 - else 174 + else { 116 175 dev_warn(&chan->par->dev->dev, "Failed to register I2C bus " 117 176 "%s.\n", name); 177 + chan->par = NULL; 178 + } 179 + 118 180 return rc; 119 181 } 120 182 ··· 126 180 { 127 181 par->chan[0].par = par; 128 182 par->chan[1].par = par; 129 - i810_setup_i2c_bus(&par->chan[0], "I810-DDC", 1); 130 - i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 2); 183 + par->chan[2].par = par; 184 + 185 + par->chan[0].ddc_base = GPIOA; 186 + i810_setup_i2c_bus(&par->chan[0], "I810-DDC"); 187 + par->chan[1].ddc_base = GPIOB; 188 + i810_setup_i2c_bus(&par->chan[1], "I810-I2C"); 189 + par->chan[2].ddc_base = GPIOC; 190 + i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC"); 131 191 } 132 192 133 193 void i810_delete_i2c_busses(struct i810fb_par *par) ··· 141 189 if (par->chan[0].par) 142 190 i2c_bit_del_bus(&par->chan[0].adapter); 143 191 par->chan[0].par = NULL; 192 + 144 193 if (par->chan[1].par) 145 194 i2c_bit_del_bus(&par->chan[1].adapter); 146 195 par->chan[1].par = NULL; 196 + 197 + if (par->chan[2].par) 198 + i2c_bit_del_bus(&par->chan[2].adapter); 199 + par->chan[2].par = NULL; 147 200 } 148 201 149 202 static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan) ··· 178 221 DPRINTK("i810-i2c: I2C Transfer successful\n"); 179 222 return buf; 180 223 } 224 + 181 225 DPRINTK("i810-i2c: Unable to read EDID block.\n"); 182 226 kfree(buf); 183 227 return NULL; ··· 191 233 int i; 192 234 193 235 DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn); 194 - if (conn < 3) { 236 + if (conn < 4) { 195 237 for (i = 0; i < 3; i++) { 196 238 /* Do the real work */ 197 239 edid = i810_do_probe_i2c_edid(&par->chan[conn-1]); ··· 199 241 break; 200 242 } 201 243 } else { 202 - DPRINTK("i810-i2c: Getting EDID from BIOS\n"); 203 - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); 204 - if (edid) 205 - memcpy(edid, fb_firmware_edid(info->device), 206 - EDID_LENGTH); 244 + const u8 *e = fb_firmware_edid(info->device); 245 + 246 + if (e != NULL) { 247 + DPRINTK("i810-i2c: Getting EDID from BIOS\n"); 248 + edid = kmalloc(EDID_LENGTH, GFP_KERNEL); 249 + if (edid) 250 + memcpy(edid, e, EDID_LENGTH); 251 + } 207 252 } 208 253 209 254 if (out_edid) ··· 214 253 215 254 return (edid) ? 0 : 1; 216 255 } 217 - 218 -
+2 -1
drivers/video/i810/i810.h
··· 249 249 struct i810fb_par *par; 250 250 struct i2c_adapter adapter; 251 251 struct i2c_algo_bit_data algo; 252 + unsigned long ddc_base; 252 253 }; 253 254 254 255 struct i810fb_par { ··· 263 262 struct heap_data iring; 264 263 struct heap_data cursor_heap; 265 264 struct vgastate state; 266 - struct i810fb_i2c_chan chan[2]; 265 + struct i810fb_i2c_chan chan[3]; 267 266 atomic_t use_count; 268 267 u32 pseudo_palette[17]; 269 268 unsigned long mmio_start_phys;
+1 -1
drivers/video/i810/i810_main.c
··· 1854 1854 #ifdef CONFIG_FB_I810_I2C 1855 1855 i810_create_i2c_busses(par); 1856 1856 1857 - for (i = 0; i < 3; i++) { 1857 + for (i = 0; i < 4; i++) { 1858 1858 err = i810_probe_i2c_connector(info, &par->edid, i+1); 1859 1859 if (!err) 1860 1860 break;
+1
drivers/video/i810/i810_regs.h
··· 70 70 #define HVSYNC 0x05000 71 71 #define GPIOA 0x05010 72 72 #define GPIOB 0x05014 73 + #define GPIOC 0x0501C 73 74 74 75 /* Clock Control and Power Management Registers (06000h 06FFFh) */ 75 76 #define DCLK_0D 0x06000