diff options
Diffstat (limited to 'drivers/staging/gma500/mrst_hdmi_i2c.c')
-rw-r--r-- | drivers/staging/gma500/mrst_hdmi_i2c.c | 328 |
1 files changed, 0 insertions, 328 deletions
diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c deleted file mode 100644 index 36e7edc4d14c..000000000000 --- a/drivers/staging/gma500/mrst_hdmi_i2c.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Li Peng <peng.li@intel.com> - */ - -#include <linux/mutex.h> -#include <linux/pci.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/export.h> -#include "psb_drv.h" - -#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg)) -#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg)) - -#define HDMI_HCR 0x1000 -#define HCR_DETECT_HDP (1 << 6) -#define HCR_ENABLE_HDCP (1 << 5) -#define HCR_ENABLE_AUDIO (1 << 2) -#define HCR_ENABLE_PIXEL (1 << 1) -#define HCR_ENABLE_TMDS (1 << 0) -#define HDMI_HICR 0x1004 -#define HDMI_INTR_I2C_ERROR (1 << 4) -#define HDMI_INTR_I2C_FULL (1 << 3) -#define HDMI_INTR_I2C_DONE (1 << 2) -#define HDMI_INTR_HPD (1 << 0) -#define HDMI_HSR 0x1008 -#define HDMI_HISR 0x100C -#define HDMI_HI2CRDB0 0x1200 -#define HDMI_HI2CHCR 0x1240 -#define HI2C_HDCP_WRITE (0 << 2) -#define HI2C_HDCP_RI_READ (1 << 2) -#define HI2C_HDCP_READ (2 << 2) -#define HI2C_EDID_READ (3 << 2) -#define HI2C_READ_CONTINUE (1 << 1) -#define HI2C_ENABLE_TRANSACTION (1 << 0) - -#define HDMI_ICRH 0x1100 -#define HDMI_HI2CTDR0 0x1244 -#define HDMI_HI2CTDR1 0x1248 - -#define I2C_STAT_INIT 0 -#define I2C_READ_DONE 1 -#define I2C_TRANSACTION_DONE 2 - -struct hdmi_i2c_dev { - struct i2c_adapter *adap; - struct mutex i2c_lock; - struct completion complete; - int status; - struct i2c_msg *msg; - int buf_offset; -}; - -static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev) -{ - u32 temp; - - temp = HDMI_READ(HDMI_HICR); - temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE); - HDMI_WRITE(HDMI_HICR, temp); - HDMI_READ(HDMI_HICR); -} - -static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev) -{ - HDMI_WRITE(HDMI_HICR, 0x0); - HDMI_READ(HDMI_HICR); -} - -static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg) -{ - struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - u32 temp; - - i2c_dev->status = I2C_STAT_INIT; - i2c_dev->msg = pmsg; - i2c_dev->buf_offset = 0; - INIT_COMPLETION(i2c_dev->complete); - - /* Enable I2C transaction */ - temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION; - HDMI_WRITE(HDMI_HI2CHCR, temp); - HDMI_READ(HDMI_HI2CHCR); - - while (i2c_dev->status != I2C_TRANSACTION_DONE) - wait_for_completion_interruptible_timeout(&i2c_dev->complete, - 10 * HZ); - - return 0; -} - -static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg) -{ - /* - * XXX: i2c write seems isn't useful for EDID probe, don't do anything - */ - return 0; -} - -static int mrst_hdmi_i2c_access(struct i2c_adapter *adap, - struct i2c_msg *pmsg, - int num) -{ - struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - int i, err = 0; - - mutex_lock(&i2c_dev->i2c_lock); - - /* Enable i2c unit */ - HDMI_WRITE(HDMI_ICRH, 0x00008760); - - /* Enable irq */ - hdmi_i2c_irq_enable(hdmi_dev); - for (i = 0; i < num; i++) { - if (pmsg->len && pmsg->buf) { - if (pmsg->flags & I2C_M_RD) - err = xfer_read(adap, pmsg); - else - err = xfer_write(adap, pmsg); - } - pmsg++; /* next message */ - } - - /* Disable irq */ - hdmi_i2c_irq_disable(hdmi_dev); - - mutex_unlock(&i2c_dev->i2c_lock); - - return i; -} - -static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; -} - -static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = { - .master_xfer = mrst_hdmi_i2c_access, - .functionality = mrst_hdmi_i2c_func, -}; - -static struct i2c_adapter mrst_hdmi_i2c_adapter = { - .name = "mrst_hdmi_i2c", - .nr = 3, - .owner = THIS_MODULE, - .class = I2C_CLASS_DDC, - .algo = &mrst_hdmi_i2c_algorithm, -}; - -static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev) -{ - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - struct i2c_msg *msg = i2c_dev->msg; - u8 *buf = msg->buf; - u32 temp; - int i, offset; - - offset = i2c_dev->buf_offset; - for (i = 0; i < 0x10; i++) { - temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4)); - memcpy(buf + (offset + i * 4), &temp, 4); - } - i2c_dev->buf_offset += (0x10 * 4); - - /* clearing read buffer full intr */ - temp = HDMI_READ(HDMI_HISR); - HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL); - HDMI_READ(HDMI_HISR); - - /* continue read transaction */ - temp = HDMI_READ(HDMI_HI2CHCR); - HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE); - HDMI_READ(HDMI_HI2CHCR); - - i2c_dev->status = I2C_READ_DONE; - return; -} - -static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev) -{ - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - u32 temp; - - /* clear transaction done intr */ - temp = HDMI_READ(HDMI_HISR); - HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE); - HDMI_READ(HDMI_HISR); - - - temp = HDMI_READ(HDMI_HI2CHCR); - HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION); - HDMI_READ(HDMI_HI2CHCR); - - i2c_dev->status = I2C_TRANSACTION_DONE; - return; -} - -static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev) -{ - struct mrst_hdmi_dev *hdmi_dev = dev; - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - u32 stat; - - stat = HDMI_READ(HDMI_HISR); - - if (stat & HDMI_INTR_HPD) { - HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD); - HDMI_READ(HDMI_HISR); - } - - if (stat & HDMI_INTR_I2C_FULL) - hdmi_i2c_read(hdmi_dev); - - if (stat & HDMI_INTR_I2C_DONE) - hdmi_i2c_transaction_done(hdmi_dev); - - complete(&i2c_dev->complete); - - return IRQ_HANDLED; -} - -/* - * choose alternate function 2 of GPIO pin 52, 53, - * which is used by HDMI I2C logic - */ -static void mrst_hdmi_i2c_gpio_fix(void) -{ - void *base; - unsigned int gpio_base = 0xff12c000; - int gpio_len = 0x1000; - u32 temp; - - base = ioremap((resource_size_t)gpio_base, gpio_len); - if (base == NULL) { - DRM_ERROR("gpio ioremap fail\n"); - return; - } - - temp = readl(base + 0x44); - DRM_DEBUG_DRIVER("old gpio val %x\n", temp); - writel((temp | 0x00000a00), (base + 0x44)); - temp = readl(base + 0x44); - DRM_DEBUG_DRIVER("new gpio val %x\n", temp); - - iounmap(base); -} - -int mrst_hdmi_i2c_init(struct pci_dev *dev) -{ - struct mrst_hdmi_dev *hdmi_dev; - struct hdmi_i2c_dev *i2c_dev; - int ret; - - hdmi_dev = pci_get_drvdata(dev); - - i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL); - if (i2c_dev == NULL) { - DRM_ERROR("Can't allocate interface\n"); - ret = -ENOMEM; - goto exit; - } - - i2c_dev->adap = &mrst_hdmi_i2c_adapter; - i2c_dev->status = I2C_STAT_INIT; - init_completion(&i2c_dev->complete); - mutex_init(&i2c_dev->i2c_lock); - i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev); - hdmi_dev->i2c_dev = i2c_dev; - - /* Enable HDMI I2C function on gpio */ - mrst_hdmi_i2c_gpio_fix(); - - /* request irq */ - ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED, - mrst_hdmi_i2c_adapter.name, hdmi_dev); - if (ret) { - DRM_ERROR("Failed to request IRQ for I2C controller\n"); - goto err; - } - - /* Adapter registration */ - ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter); - return ret; - -err: - kfree(i2c_dev); -exit: - return ret; -} - -void mrst_hdmi_i2c_exit(struct pci_dev *dev) -{ - struct mrst_hdmi_dev *hdmi_dev; - struct hdmi_i2c_dev *i2c_dev; - - hdmi_dev = pci_get_drvdata(dev); - if (i2c_del_adapter(&mrst_hdmi_i2c_adapter)) - DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n"); - - i2c_dev = hdmi_dev->i2c_dev; - kfree(i2c_dev); - free_irq(dev->irq, hdmi_dev); -} |