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

intelfb: add preliminary i2c support

[06/07] intelfb: adds intelfb_i2c.c which contains the infrastructure needed to
enumerate the i2c busses on the intelfb.

Signed-off-by: Dennis Munsie <dmunsie@cecropia.com>

authored by

Dennis Munsie and committed by
Dave Airlie
41c9480a dd696ec8

+193
+4
drivers/video/intelfb/intelfb.h
··· 365 365 366 366 extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var); 367 367 368 + #ifdef CONFIG_FB_INTEL_I2C 369 + extern void intelfb_create_i2c_busses(struct intelfb_info *dinfo); 370 + #endif 371 + 368 372 #endif /* _INTELFB_H */
+184
drivers/video/intelfb/intelfb_i2c.c
··· 1 + /************************************************************************** 2 + 3 + Copyright 2006 Dave Airlie <airlied@linux.ie> 4 + 5 + All Rights Reserved. 6 + 7 + Permission is hereby granted, free of charge, to any person obtaining a 8 + copy of this software and associated documentation files (the "Software"), 9 + to deal in the Software without restriction, including without limitation 10 + on the rights to use, copy, modify, merge, publish, distribute, sub 11 + license, and/or sell copies of the Software, and to permit persons to whom 12 + the Software is furnished to do so, subject to the following conditions: 13 + 14 + The above copyright notice and this permission notice (including the next 15 + paragraph) shall be included in all copies or substantial portions of the 16 + Software. 17 + 18 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 + FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21 + THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 22 + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 + USE OR OTHER DEALINGS IN THE SOFTWARE. 25 + 26 + **************************************************************************/ 27 + 28 + #include <linux/config.h> 29 + #include <linux/module.h> 30 + #include <linux/kernel.h> 31 + #include <linux/sched.h> 32 + #include <linux/delay.h> 33 + #include <linux/pci.h> 34 + #include <linux/fb.h> 35 + 36 + #include <linux/i2c.h> 37 + #include <linux/i2c-id.h> 38 + #include <linux/i2c-algo-bit.h> 39 + 40 + #include <asm/io.h> 41 + 42 + #include "intelfb.h" 43 + #include "intelfbhw.h" 44 + 45 + /* bit locations in the registers */ 46 + #define SCL_DIR_MASK 0x0001 47 + #define SCL_DIR 0x0002 48 + #define SCL_VAL_MASK 0x0004 49 + #define SCL_VAL_OUT 0x0008 50 + #define SCL_VAL_IN 0x0010 51 + #define SDA_DIR_MASK 0x0100 52 + #define SDA_DIR 0x0200 53 + #define SDA_VAL_MASK 0x0400 54 + #define SDA_VAL_OUT 0x0800 55 + #define SDA_VAL_IN 0x1000 56 + 57 + static void intelfb_gpio_setscl(void *data, int state) 58 + { 59 + struct intelfb_i2c_chan *chan = data; 60 + struct intelfb_info *dinfo = chan->dinfo; 61 + u32 val; 62 + 63 + OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK); 64 + val = INREG(chan->reg); 65 + } 66 + 67 + static void intelfb_gpio_setsda(void *data, int state) 68 + { 69 + struct intelfb_i2c_chan *chan = data; 70 + struct intelfb_info *dinfo = chan->dinfo; 71 + u32 val; 72 + 73 + OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK); 74 + val = INREG(chan->reg); 75 + } 76 + 77 + static int intelfb_gpio_getscl(void *data) 78 + { 79 + struct intelfb_i2c_chan *chan = data; 80 + struct intelfb_info *dinfo = chan->dinfo; 81 + u32 val; 82 + 83 + OUTREG(chan->reg, SCL_DIR_MASK); 84 + OUTREG(chan->reg, 0); 85 + val = INREG(chan->reg); 86 + return ((val & SCL_VAL_IN) != 0); 87 + } 88 + 89 + static int intelfb_gpio_getsda(void *data) 90 + { 91 + struct intelfb_i2c_chan *chan = data; 92 + struct intelfb_info *dinfo = chan->dinfo; 93 + u32 val; 94 + 95 + OUTREG(chan->reg, SDA_DIR_MASK); 96 + OUTREG(chan->reg, 0); 97 + val = INREG(chan->reg); 98 + return ((val & SDA_VAL_IN) != 0); 99 + } 100 + 101 + static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo, 102 + struct intelfb_i2c_chan *chan, 103 + const u32 reg, const char *name) 104 + { 105 + int rc; 106 + 107 + chan->dinfo = dinfo; 108 + chan->reg = reg; 109 + snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name); 110 + chan->adapter.owner = THIS_MODULE; 111 + chan->adapter.id = I2C_HW_B_INTELFB; 112 + chan->adapter.algo_data = &chan->algo; 113 + chan->adapter.dev.parent = &chan->dinfo->pdev->dev; 114 + chan->algo.setsda = intelfb_gpio_setsda; 115 + chan->algo.setscl = intelfb_gpio_setscl; 116 + chan->algo.getsda = intelfb_gpio_getsda; 117 + chan->algo.getscl = intelfb_gpio_getscl; 118 + chan->algo.udelay = 40; 119 + chan->algo.timeout = 20; 120 + chan->algo.data = chan; 121 + 122 + i2c_set_adapdata(&chan->adapter, chan); 123 + 124 + /* Raise SCL and SDA */ 125 + intelfb_gpio_setsda(chan, 1); 126 + intelfb_gpio_setscl(chan, 1); 127 + udelay(20); 128 + 129 + rc = i2c_bit_add_bus(&chan->adapter); 130 + if (rc == 0) 131 + DBG_MSG("I2C bus %s registered.\n", name); 132 + else 133 + WRN_MSG("Failed to register I2C bus %s.\n", name); 134 + return rc; 135 + } 136 + 137 + void intelfb_create_i2c_busses(struct intelfb_info *dinfo) 138 + { 139 + int i = 0; 140 + 141 + /* everyone has at least a single analog output */ 142 + dinfo->num_outputs = 1; 143 + dinfo->output[i].type = INTELFB_OUTPUT_ANALOG; 144 + 145 + /* setup the DDC bus for analog output */ 146 + intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA, "CRTDDC_A"); 147 + i++; 148 + 149 + /* need to add the output busses for each device 150 + - this function is very incomplete 151 + - i915GM has LVDS and TVOUT for example 152 + */ 153 + switch(dinfo->chipset) { 154 + case INTEL_830M: 155 + case INTEL_845G: 156 + case INTEL_855GM: 157 + case INTEL_865G: 158 + dinfo->output[i].type = INTELFB_OUTPUT_DVO; 159 + intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOD, "DVODDC_D"); 160 + intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "DVOI2C_E"); 161 + i++; 162 + break; 163 + case INTEL_915G: 164 + case INTEL_915GM: 165 + /* has some LVDS + tv-out */ 166 + case INTEL_945G: 167 + case INTEL_945GM: 168 + /* SDVO ports have a single control bus - 2 devices */ 169 + dinfo->output[i].type = INTELFB_OUTPUT_SDVO; 170 + intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "SDVOCTRL_E"); 171 + /* TODO: initialize the SDVO */ 172 + // I830SDVOInit(pScrn, i, DVOB); 173 + i++; 174 + 175 + /* set up SDVOC */ 176 + dinfo->output[i].type = INTELFB_OUTPUT_SDVO; 177 + dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus; 178 + /* TODO: initialize the SDVO */ 179 + // I830SDVOInit(pScrn, i, DVOC); 180 + i++; 181 + break; 182 + } 183 + dinfo->num_outputs = i; 184 + }
+5
drivers/video/intelfb/intelfbdrv.c
··· 851 851 if (bailearly == 5) 852 852 bailout(dinfo); 853 853 854 + #ifdef CONFIG_FB_INTEL_I2C 855 + /* register I2C bus */ 856 + intelfb_create_i2c_busses(dinfo); 857 + #endif 858 + 854 859 if (bailearly == 6) 855 860 bailout(dinfo); 856 861