1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/delay.h>
27#include <linux/slab.h>
28
29#include "dm_services.h"
30
31#include "include/gpio_types.h"
32#include "hw_gpio.h"
33#include "hw_ddc.h"
34
35#include "reg_helper.h"
36#include "gpio_regs.h"
37
38
39#undef FN
40#define FN(reg_name, field_name) \
41 ddc->shifts->field_name, ddc->masks->field_name
42
43#define CTX \
44 ddc->base.base.ctx
45#define REG(reg)\
46 (ddc->regs->reg)
47
48static void destruct(
49 struct hw_ddc *pin)
50{
51 dal_hw_gpio_destruct(&pin->base);
52}
53
54static void destroy(
55 struct hw_gpio_pin **ptr)
56{
57 struct hw_ddc *pin = HW_DDC_FROM_BASE(*ptr);
58
59 destruct(pin);
60
61 kfree(pin);
62
63 *ptr = NULL;
64}
65
66static enum gpio_result set_config(
67 struct hw_gpio_pin *ptr,
68 const struct gpio_config_data *config_data)
69{
70 struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
71 struct hw_gpio *hw_gpio = NULL;
72 uint32_t regval;
73 uint32_t ddc_data_pd_en = 0;
74 uint32_t ddc_clk_pd_en = 0;
75 uint32_t aux_pad_mode = 0;
76
77 hw_gpio = &ddc->base;
78
79 if (hw_gpio == NULL) {
80 ASSERT_CRITICAL(false);
81 return GPIO_RESULT_NULL_HANDLE;
82 }
83
84 regval = REG_GET_3(gpio.MASK_reg,
85 DC_GPIO_DDC1DATA_PD_EN, &ddc_data_pd_en,
86 DC_GPIO_DDC1CLK_PD_EN, &ddc_clk_pd_en,
87 AUX_PAD1_MODE, &aux_pad_mode);
88
89 switch (config_data->config.ddc.type) {
90 case GPIO_DDC_CONFIG_TYPE_MODE_I2C:
91
92
93
94
95 if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) {
96 if (!ddc_data_pd_en || !ddc_clk_pd_en) {
97
98 REG_SET_2(gpio.MASK_reg, regval,
99 DC_GPIO_DDC1DATA_PD_EN, 1,
100 DC_GPIO_DDC1CLK_PD_EN, 1);
101
102 if (config_data->type ==
103 GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
104 msleep(3);
105 }
106 } else {
107 uint32_t reg2;
108 uint32_t sda_pd_dis = 0;
109 uint32_t scl_pd_dis = 0;
110
111 reg2 = REG_GET_2(gpio.MASK_reg,
112 DC_GPIO_SDA_PD_DIS, &sda_pd_dis,
113 DC_GPIO_SCL_PD_DIS, &scl_pd_dis);
114
115 if (sda_pd_dis) {
116 REG_SET(gpio.MASK_reg, regval,
117 DC_GPIO_SDA_PD_DIS, 0);
118
119 if (config_data->type ==
120 GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
121 msleep(3);
122 }
123
124 if (!scl_pd_dis) {
125 REG_SET(gpio.MASK_reg, regval,
126 DC_GPIO_SCL_PD_DIS, 1);
127
128 if (config_data->type ==
129 GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
130 msleep(3);
131 }
132 }
133
134 if (aux_pad_mode) {
135
136
137 if (config_data->config.ddc.data_en_bit_present ||
138 config_data->config.ddc.clock_en_bit_present)
139
140
141 msleep(2);
142
143
144
145
146 REG_UPDATE(gpio.MASK_reg,
147 AUX_PAD1_MODE, 0);
148 }
149
150#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
151 if (ddc->regs->dc_gpio_aux_ctrl_5 != 0) {
152 REG_UPDATE(dc_gpio_aux_ctrl_5, DDC_PAD_I2CMODE, 1);
153 }
154
155 if (ddc->regs->phy_aux_cntl != 0) {
156 REG_UPDATE(phy_aux_cntl, AUX_PAD_RXSEL, 1);
157 }
158#endif
159 return GPIO_RESULT_OK;
160 case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
161
162 if (!aux_pad_mode) {
163 REG_SET(gpio.MASK_reg, regval,
164 AUX_PAD1_MODE, 1);
165 }
166#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
167 if (ddc->regs->dc_gpio_aux_ctrl_5 != 0) {
168 REG_UPDATE(dc_gpio_aux_ctrl_5,
169 DDC_PAD_I2CMODE, 0);
170 }
171#endif
172
173 return GPIO_RESULT_OK;
174 case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
175 if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
176 (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
177 REG_UPDATE_3(ddc_setup,
178 DC_I2C_DDC1_ENABLE, 1,
179 DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
180 DC_I2C_DDC1_EDID_DETECT_MODE, 0);
181 return GPIO_RESULT_OK;
182 }
183 break;
184 case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
185 if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
186 (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
187 REG_UPDATE_3(ddc_setup,
188 DC_I2C_DDC1_ENABLE, 1,
189 DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
190 DC_I2C_DDC1_EDID_DETECT_MODE, 1);
191 return GPIO_RESULT_OK;
192 }
193 break;
194 case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
195 if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
196 (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
197 REG_UPDATE_2(ddc_setup,
198 DC_I2C_DDC1_ENABLE, 0,
199 DC_I2C_DDC1_EDID_DETECT_ENABLE, 0);
200 return GPIO_RESULT_OK;
201 }
202 break;
203 }
204
205 BREAK_TO_DEBUGGER();
206
207 return GPIO_RESULT_NON_SPECIFIC_ERROR;
208}
209
210static const struct hw_gpio_pin_funcs funcs = {
211 .destroy = destroy,
212 .open = dal_hw_gpio_open,
213 .get_value = dal_hw_gpio_get_value,
214 .set_value = dal_hw_gpio_set_value,
215 .set_config = set_config,
216 .change_mode = dal_hw_gpio_change_mode,
217 .close = dal_hw_gpio_close,
218};
219
220static void construct(
221 struct hw_ddc *ddc,
222 enum gpio_id id,
223 uint32_t en,
224 struct dc_context *ctx)
225{
226 dal_hw_gpio_construct(&ddc->base, id, en, ctx);
227 ddc->base.base.funcs = &funcs;
228}
229
230struct hw_gpio_pin *dal_hw_ddc_create(
231 struct dc_context *ctx,
232 enum gpio_id id,
233 uint32_t en)
234{
235 struct hw_ddc *pin;
236
237 if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) {
238 ASSERT_CRITICAL(false);
239 return NULL;
240 }
241
242 pin = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL);
243 if (!pin) {
244 ASSERT_CRITICAL(false);
245 return NULL;
246 }
247
248 construct(pin, id, en, ctx);
249 return &pin->base.base;
250}
251