Back to home page

OSCL-LXR

 
 

    


0001 /**************************************************************************
0002 
0003  Copyright 2006 Dave Airlie <airlied@linux.ie>
0004 
0005 All Rights Reserved.
0006 
0007 Permission is hereby granted, free of charge, to any person obtaining a
0008 copy of this software and associated documentation files (the "Software"),
0009 to deal in the Software without restriction, including without limitation
0010 on the rights to use, copy, modify, merge, publish, distribute, sub
0011 license, and/or sell copies of the Software, and to permit persons to whom
0012 the Software is furnished to do so, subject to the following conditions:
0013 
0014 The above copyright notice and this permission notice (including the next
0015 paragraph) shall be included in all copies or substantial portions of the
0016 Software.
0017 
0018 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0019 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0020 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
0021 THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
0022 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
0023 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
0024 USE OR OTHER DEALINGS IN THE SOFTWARE.
0025 
0026 **************************************************************************/
0027 
0028 #include <linux/module.h>
0029 #include <linux/kernel.h>
0030 #include <linux/delay.h>
0031 #include <linux/pci.h>
0032 #include <linux/fb.h>
0033 
0034 #include <linux/i2c.h>
0035 #include <linux/i2c-algo-bit.h>
0036 
0037 #include <asm/io.h>
0038 
0039 #include "intelfb.h"
0040 #include "intelfbhw.h"
0041 
0042 /* bit locations in the registers */
0043 #define SCL_DIR_MASK        0x0001
0044 #define SCL_DIR         0x0002
0045 #define SCL_VAL_MASK        0x0004
0046 #define SCL_VAL_OUT     0x0008
0047 #define SCL_VAL_IN      0x0010
0048 #define SDA_DIR_MASK        0x0100
0049 #define SDA_DIR         0x0200
0050 #define SDA_VAL_MASK        0x0400
0051 #define SDA_VAL_OUT     0x0800
0052 #define SDA_VAL_IN      0x1000
0053 
0054 static void intelfb_gpio_setscl(void *data, int state)
0055 {
0056     struct intelfb_i2c_chan *chan = data;
0057     struct intelfb_info *dinfo = chan->dinfo;
0058     u32 val;
0059 
0060     OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) |
0061            SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
0062     val = INREG(chan->reg);
0063 }
0064 
0065 static void intelfb_gpio_setsda(void *data, int state)
0066 {
0067     struct intelfb_i2c_chan *chan = data;
0068     struct intelfb_info *dinfo = chan->dinfo;
0069     u32 val;
0070 
0071     OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) |
0072            SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
0073     val = INREG(chan->reg);
0074 }
0075 
0076 static int intelfb_gpio_getscl(void *data)
0077 {
0078     struct intelfb_i2c_chan *chan = data;
0079     struct intelfb_info *dinfo = chan->dinfo;
0080     u32 val;
0081 
0082     OUTREG(chan->reg, SCL_DIR_MASK);
0083     OUTREG(chan->reg, 0);
0084     val = INREG(chan->reg);
0085     return ((val & SCL_VAL_IN) != 0);
0086 }
0087 
0088 static int intelfb_gpio_getsda(void *data)
0089 {
0090     struct intelfb_i2c_chan *chan = data;
0091     struct intelfb_info *dinfo = chan->dinfo;
0092     u32 val;
0093 
0094     OUTREG(chan->reg, SDA_DIR_MASK);
0095     OUTREG(chan->reg, 0);
0096     val = INREG(chan->reg);
0097     return ((val & SDA_VAL_IN) != 0);
0098 }
0099 
0100 static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
0101                  struct intelfb_i2c_chan *chan,
0102                  const u32 reg, const char *name,
0103                  int class)
0104 {
0105     int rc;
0106 
0107     chan->dinfo         = dinfo;
0108     chan->reg           = reg;
0109     snprintf(chan->adapter.name, sizeof(chan->adapter.name),
0110          "intelfb %s", name);
0111     chan->adapter.class     = class;
0112     chan->adapter.owner     = THIS_MODULE;
0113     chan->adapter.algo_data     = &chan->algo;
0114     chan->adapter.dev.parent    = &chan->dinfo->pdev->dev;
0115     chan->algo.setsda       = intelfb_gpio_setsda;
0116     chan->algo.setscl       = intelfb_gpio_setscl;
0117     chan->algo.getsda       = intelfb_gpio_getsda;
0118     chan->algo.getscl       = intelfb_gpio_getscl;
0119     chan->algo.udelay       = 40;
0120     chan->algo.timeout      = 20;
0121     chan->algo.data         = chan;
0122 
0123     i2c_set_adapdata(&chan->adapter, chan);
0124 
0125     /* Raise SCL and SDA */
0126     intelfb_gpio_setsda(chan, 1);
0127     intelfb_gpio_setscl(chan, 1);
0128     udelay(20);
0129 
0130     rc = i2c_bit_add_bus(&chan->adapter);
0131     if (rc == 0)
0132         DBG_MSG("I2C bus %s registered.\n", name);
0133     else
0134         WRN_MSG("Failed to register I2C bus %s.\n", name);
0135     return rc;
0136 }
0137 
0138 void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
0139 {
0140     int i = 0;
0141 
0142     /* everyone has at least a single analog output */
0143     dinfo->num_outputs = 1;
0144     dinfo->output[i].type = INTELFB_OUTPUT_ANALOG;
0145 
0146     /* setup the DDC bus for analog output */
0147     intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA,
0148                   "CRTDDC_A", I2C_CLASS_DDC);
0149     i++;
0150 
0151     /* need to add the output busses for each device
0152        - this function is very incomplete
0153        - i915GM has LVDS and TVOUT for example
0154     */
0155     switch(dinfo->chipset) {
0156     case INTEL_830M:
0157     case INTEL_845G:
0158     case INTEL_854:
0159     case INTEL_855GM:
0160     case INTEL_865G:
0161         dinfo->output[i].type = INTELFB_OUTPUT_DVO;
0162         intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus,
0163                       GPIOD, "DVODDC_D", I2C_CLASS_DDC);
0164         intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
0165                       GPIOE, "DVOI2C_E", 0);
0166         i++;
0167         break;
0168     case INTEL_915G:
0169     case INTEL_915GM:
0170         /* has some LVDS + tv-out */
0171     case INTEL_945G:
0172     case INTEL_945GM:
0173     case INTEL_945GME:
0174     case INTEL_965G:
0175     case INTEL_965GM:
0176         /* SDVO ports have a single control bus - 2 devices */
0177         dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
0178         intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
0179                       GPIOE, "SDVOCTRL_E", 0);
0180         /* TODO: initialize the SDVO */
0181         /* I830SDVOInit(pScrn, i, DVOB); */
0182         i++;
0183 
0184         /* set up SDVOC */
0185         dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
0186         dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus;
0187         /* TODO: initialize the SDVO */
0188         /* I830SDVOInit(pScrn, i, DVOC); */
0189         i++;
0190         break;
0191     }
0192     dinfo->num_outputs = i;
0193 }
0194 
0195 void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
0196 {
0197     int i;
0198 
0199     for (i = 0; i < MAX_OUTPUTS; i++) {
0200         if (dinfo->output[i].i2c_bus.dinfo) {
0201             i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter);
0202             dinfo->output[i].i2c_bus.dinfo = NULL;
0203         }
0204         if (dinfo->output[i].ddc_bus.dinfo) {
0205             i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter);
0206             dinfo->output[i].ddc_bus.dinfo = NULL;
0207         }
0208     }
0209 }