^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*-*- linux-c -*-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * All Rights Reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * License. See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "i810.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "i810_regs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "i810_main.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "../edid.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* bit locations in the registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define SCL_DIR_MASK 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SCL_DIR 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SCL_VAL_MASK 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define SCL_VAL_OUT 0x0008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SCL_VAL_IN 0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SDA_DIR_MASK 0x0100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SDA_DIR 0x0200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define SDA_VAL_MASK 0x0400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SDA_VAL_OUT 0x0800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SDA_VAL_IN 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define DEBUG /* define this for verbose EDID parsing output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define DPRINTK(fmt, args...) printk(fmt,## args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define DPRINTK(fmt, args...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static void i810i2c_setscl(void *data, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct i810fb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct i810fb_par *par = chan->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u8 __iomem *mmio = par->mmio_start_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK | SCL_VAL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) i810_writel(mmio, chan->ddc_base, SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) i810_readl(mmio, chan->ddc_base); /* flush posted write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static void i810i2c_setsda(void *data, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct i810fb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct i810fb_par *par = chan->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u8 __iomem *mmio = par->mmio_start_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK | SDA_VAL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) i810_writel(mmio, chan->ddc_base, SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) i810_readl(mmio, chan->ddc_base); /* flush posted write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int i810i2c_getscl(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct i810fb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct i810fb_par *par = chan->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u8 __iomem *mmio = par->mmio_start_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) i810_writel(mmio, chan->ddc_base, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int i810i2c_getsda(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct i810fb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct i810fb_par *par = chan->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u8 __iomem *mmio = par->mmio_start_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) i810_writel(mmio, chan->ddc_base, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) strcpy(chan->adapter.name, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) chan->adapter.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) chan->adapter.algo_data = &chan->algo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) chan->adapter.dev.parent = &chan->par->dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) chan->algo.setsda = i810i2c_setsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) chan->algo.setscl = i810i2c_setscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) chan->algo.getsda = i810i2c_getsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) chan->algo.getscl = i810i2c_getscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) chan->algo.udelay = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) chan->algo.timeout = (HZ/2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) chan->algo.data = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) i2c_set_adapdata(&chan->adapter, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* Raise SCL and SDA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) chan->algo.setsda(chan, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) chan->algo.setscl(chan, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) udelay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) rc = i2c_bit_add_bus(&chan->adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) dev_warn(&chan->par->dev->dev, "Failed to register I2C bus "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) "%s.\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) chan->par = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) void i810_create_i2c_busses(struct i810fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) par->chan[0].par = par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) par->chan[1].par = par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) par->chan[2].par = par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) par->chan[0].ddc_base = GPIOA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) i810_setup_i2c_bus(&par->chan[0], "I810-DDC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) par->chan[1].ddc_base = GPIOB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) i810_setup_i2c_bus(&par->chan[1], "I810-I2C");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) par->chan[2].ddc_base = GPIOC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) void i810_delete_i2c_busses(struct i810fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (par->chan[0].par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) i2c_del_adapter(&par->chan[0].adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) par->chan[0].par = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (par->chan[1].par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) i2c_del_adapter(&par->chan[1].adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) par->chan[1].par = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (par->chan[2].par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) i2c_del_adapter(&par->chan[2].adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) par->chan[2].par = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct i810fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u8 *edid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (conn < par->ddc_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) edid = fb_ddc_read(&par->chan[conn].adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) const u8 *e = fb_firmware_edid(info->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (e != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) DPRINTK("i810-i2c: Getting EDID from BIOS\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *out_edid = edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return (edid) ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }