1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Hisilicon Hibmc SoC drm driver
4 * Based on the bochs drm driver.
6 * Copyright (c) 2016 Huawei Limited.
9 * Tian Tao <tiantao6@hisilicon.com>
12 #include <linux/delay.h>
13 #include <linux/pci.h>
15 #include <drm/drm_atomic_helper.h>
16 #include <drm/drm_probe_helper.h>
18 #include "hibmc_drm_drv.h"
20 #define GPIO_DATA 0x0802A0
21 #define GPIO_DATA_DIRECTION 0x0802A4
23 #define I2C_SCL_MASK BIT(0)
24 #define I2C_SDA_MASK BIT(1)
26 static void hibmc_set_i2c_signal(void *data
, u32 mask
, int value
)
28 struct hibmc_connector
*hibmc_connector
= data
;
29 struct hibmc_drm_private
*priv
= to_hibmc_drm_private(hibmc_connector
->base
.dev
);
30 u32 tmp_dir
= readl(priv
->mmio
+ GPIO_DATA_DIRECTION
);
34 writel(tmp_dir
, priv
->mmio
+ GPIO_DATA_DIRECTION
);
36 u32 tmp_data
= readl(priv
->mmio
+ GPIO_DATA
);
39 writel(tmp_data
, priv
->mmio
+ GPIO_DATA
);
42 writel(tmp_dir
, priv
->mmio
+ GPIO_DATA_DIRECTION
);
46 static int hibmc_get_i2c_signal(void *data
, u32 mask
)
48 struct hibmc_connector
*hibmc_connector
= data
;
49 struct hibmc_drm_private
*priv
= to_hibmc_drm_private(hibmc_connector
->base
.dev
);
50 u32 tmp_dir
= readl(priv
->mmio
+ GPIO_DATA_DIRECTION
);
52 if ((tmp_dir
& mask
) != mask
) {
54 writel(tmp_dir
, priv
->mmio
+ GPIO_DATA_DIRECTION
);
57 return (readl(priv
->mmio
+ GPIO_DATA
) & mask
) ? 1 : 0;
60 static void hibmc_ddc_setsda(void *data
, int state
)
62 hibmc_set_i2c_signal(data
, I2C_SDA_MASK
, state
);
65 static void hibmc_ddc_setscl(void *data
, int state
)
67 hibmc_set_i2c_signal(data
, I2C_SCL_MASK
, state
);
70 static int hibmc_ddc_getsda(void *data
)
72 return hibmc_get_i2c_signal(data
, I2C_SDA_MASK
);
75 static int hibmc_ddc_getscl(void *data
)
77 return hibmc_get_i2c_signal(data
, I2C_SCL_MASK
);
80 int hibmc_ddc_create(struct drm_device
*drm_dev
,
81 struct hibmc_connector
*connector
)
83 connector
->adapter
.owner
= THIS_MODULE
;
84 connector
->adapter
.class = I2C_CLASS_DDC
;
85 snprintf(connector
->adapter
.name
, I2C_NAME_SIZE
, "HIS i2c bit bus");
86 connector
->adapter
.dev
.parent
= &drm_dev
->pdev
->dev
;
87 i2c_set_adapdata(&connector
->adapter
, connector
);
88 connector
->adapter
.algo_data
= &connector
->bit_data
;
90 connector
->bit_data
.udelay
= 20;
91 connector
->bit_data
.timeout
= usecs_to_jiffies(2000);
92 connector
->bit_data
.data
= connector
;
93 connector
->bit_data
.setsda
= hibmc_ddc_setsda
;
94 connector
->bit_data
.setscl
= hibmc_ddc_setscl
;
95 connector
->bit_data
.getsda
= hibmc_ddc_getsda
;
96 connector
->bit_data
.getscl
= hibmc_ddc_getscl
;
98 return i2c_bit_add_bus(&connector
->adapter
);