Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* Hisilicon Hibmc SoC drm driver
0003  *
0004  * Based on the bochs drm driver.
0005  *
0006  * Copyright (c) 2016 Huawei Limited.
0007  *
0008  * Author:
0009  *      Tian Tao <tiantao6@hisilicon.com>
0010  */
0011 
0012 #include <linux/delay.h>
0013 #include <linux/pci.h>
0014 
0015 #include <drm/drm_atomic_helper.h>
0016 #include <drm/drm_probe_helper.h>
0017 
0018 #include "hibmc_drm_drv.h"
0019 
0020 #define GPIO_DATA       0x0802A0
0021 #define GPIO_DATA_DIRECTION 0x0802A4
0022 
0023 #define I2C_SCL_MASK        BIT(0)
0024 #define I2C_SDA_MASK        BIT(1)
0025 
0026 static void hibmc_set_i2c_signal(void *data, u32 mask, int value)
0027 {
0028     struct hibmc_connector *hibmc_connector = data;
0029     struct hibmc_drm_private *priv = to_hibmc_drm_private(hibmc_connector->base.dev);
0030     u32 tmp_dir = readl(priv->mmio + GPIO_DATA_DIRECTION);
0031 
0032     if (value) {
0033         tmp_dir &= ~mask;
0034         writel(tmp_dir, priv->mmio + GPIO_DATA_DIRECTION);
0035     } else {
0036         u32 tmp_data = readl(priv->mmio + GPIO_DATA);
0037 
0038         tmp_data &= ~mask;
0039         writel(tmp_data, priv->mmio + GPIO_DATA);
0040 
0041         tmp_dir |= mask;
0042         writel(tmp_dir, priv->mmio + GPIO_DATA_DIRECTION);
0043     }
0044 }
0045 
0046 static int hibmc_get_i2c_signal(void *data, u32 mask)
0047 {
0048     struct hibmc_connector *hibmc_connector = data;
0049     struct hibmc_drm_private *priv = to_hibmc_drm_private(hibmc_connector->base.dev);
0050     u32 tmp_dir = readl(priv->mmio + GPIO_DATA_DIRECTION);
0051 
0052     if ((tmp_dir & mask) != mask) {
0053         tmp_dir &= ~mask;
0054         writel(tmp_dir, priv->mmio + GPIO_DATA_DIRECTION);
0055     }
0056 
0057     return (readl(priv->mmio + GPIO_DATA) & mask) ? 1 : 0;
0058 }
0059 
0060 static void hibmc_ddc_setsda(void *data, int state)
0061 {
0062     hibmc_set_i2c_signal(data, I2C_SDA_MASK, state);
0063 }
0064 
0065 static void hibmc_ddc_setscl(void *data, int state)
0066 {
0067     hibmc_set_i2c_signal(data, I2C_SCL_MASK, state);
0068 }
0069 
0070 static int hibmc_ddc_getsda(void *data)
0071 {
0072     return hibmc_get_i2c_signal(data, I2C_SDA_MASK);
0073 }
0074 
0075 static int hibmc_ddc_getscl(void *data)
0076 {
0077     return hibmc_get_i2c_signal(data, I2C_SCL_MASK);
0078 }
0079 
0080 int hibmc_ddc_create(struct drm_device *drm_dev,
0081              struct hibmc_connector *connector)
0082 {
0083     connector->adapter.owner = THIS_MODULE;
0084     connector->adapter.class = I2C_CLASS_DDC;
0085     snprintf(connector->adapter.name, I2C_NAME_SIZE, "HIS i2c bit bus");
0086     connector->adapter.dev.parent = drm_dev->dev;
0087     i2c_set_adapdata(&connector->adapter, connector);
0088     connector->adapter.algo_data = &connector->bit_data;
0089 
0090     connector->bit_data.udelay = 20;
0091     connector->bit_data.timeout = usecs_to_jiffies(2000);
0092     connector->bit_data.data = connector;
0093     connector->bit_data.setsda = hibmc_ddc_setsda;
0094     connector->bit_data.setscl = hibmc_ddc_setscl;
0095     connector->bit_data.getsda = hibmc_ddc_getsda;
0096     connector->bit_data.getscl = hibmc_ddc_getscl;
0097 
0098     return i2c_bit_add_bus(&connector->adapter);
0099 }