]>
Commit | Line | Data |
---|---|---|
97fb5e8d | 1 | // SPDX-License-Identifier: GPL-2.0-only |
ab5b0107 HL |
2 | /* |
3 | * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. | |
ab5b0107 HL |
4 | */ |
5 | ||
6 | #include <linux/clk.h> | |
7 | #include <linux/gpio/consumer.h> | |
8 | #include <linux/regulator/consumer.h> | |
78f27b1c MY |
9 | #include <drm/drm_crtc.h> |
10 | #include <drm/drm_dp_helper.h> | |
11 | #include <drm/drm_edid.h> | |
ab5b0107 | 12 | |
ab5b0107 HL |
13 | #include "edp.h" |
14 | #include "edp.xml.h" | |
15 | ||
ab5b0107 HL |
16 | #define VDDA_UA_ON_LOAD 100000 /* uA units */ |
17 | #define VDDA_UA_OFF_LOAD 100 /* uA units */ | |
18 | ||
19 | #define DPCD_LINK_VOLTAGE_MAX 4 | |
20 | #define DPCD_LINK_PRE_EMPHASIS_MAX 4 | |
21 | ||
22 | #define EDP_LINK_BW_MAX DP_LINK_BW_2_7 | |
23 | ||
24 | /* Link training return value */ | |
25 | #define EDP_TRAIN_FAIL -1 | |
26 | #define EDP_TRAIN_SUCCESS 0 | |
27 | #define EDP_TRAIN_RECONFIG 1 | |
28 | ||
29 | #define EDP_CLK_MASK_AHB BIT(0) | |
30 | #define EDP_CLK_MASK_AUX BIT(1) | |
31 | #define EDP_CLK_MASK_LINK BIT(2) | |
32 | #define EDP_CLK_MASK_PIXEL BIT(3) | |
33 | #define EDP_CLK_MASK_MDP_CORE BIT(4) | |
34 | #define EDP_CLK_MASK_LINK_CHAN (EDP_CLK_MASK_LINK | EDP_CLK_MASK_PIXEL) | |
35 | #define EDP_CLK_MASK_AUX_CHAN \ | |
36 | (EDP_CLK_MASK_AHB | EDP_CLK_MASK_AUX | EDP_CLK_MASK_MDP_CORE) | |
37 | #define EDP_CLK_MASK_ALL (EDP_CLK_MASK_AUX_CHAN | EDP_CLK_MASK_LINK_CHAN) | |
38 | ||
39 | #define EDP_BACKLIGHT_MAX 255 | |
40 | ||
41 | #define EDP_INTR_STATUS1 \ | |
42 | (EDP_INTERRUPT_REG_1_HPD | EDP_INTERRUPT_REG_1_AUX_I2C_DONE | \ | |
43 | EDP_INTERRUPT_REG_1_WRONG_ADDR | EDP_INTERRUPT_REG_1_TIMEOUT | \ | |
44 | EDP_INTERRUPT_REG_1_NACK_DEFER | EDP_INTERRUPT_REG_1_WRONG_DATA_CNT | \ | |
45 | EDP_INTERRUPT_REG_1_I2C_NACK | EDP_INTERRUPT_REG_1_I2C_DEFER | \ | |
46 | EDP_INTERRUPT_REG_1_PLL_UNLOCK | EDP_INTERRUPT_REG_1_AUX_ERROR) | |
47 | #define EDP_INTR_MASK1 (EDP_INTR_STATUS1 << 2) | |
48 | #define EDP_INTR_STATUS2 \ | |
49 | (EDP_INTERRUPT_REG_2_READY_FOR_VIDEO | \ | |
50 | EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT | \ | |
51 | EDP_INTERRUPT_REG_2_FRAME_END | EDP_INTERRUPT_REG_2_CRC_UPDATED) | |
52 | #define EDP_INTR_MASK2 (EDP_INTR_STATUS2 << 2) | |
53 | ||
54 | struct edp_ctrl { | |
55 | struct platform_device *pdev; | |
56 | ||
57 | void __iomem *base; | |
58 | ||
59 | /* regulators */ | |
1d15c165 | 60 | struct regulator *vdda_vreg; /* 1.8 V */ |
ab5b0107 HL |
61 | struct regulator *lvl_vreg; |
62 | ||
63 | /* clocks */ | |
64 | struct clk *aux_clk; | |
65 | struct clk *pixel_clk; | |
66 | struct clk *ahb_clk; | |
67 | struct clk *link_clk; | |
68 | struct clk *mdp_core_clk; | |
69 | ||
70 | /* gpios */ | |
71 | struct gpio_desc *panel_en_gpio; | |
72 | struct gpio_desc *panel_hpd_gpio; | |
73 | ||
74 | /* completion and mutex */ | |
75 | struct completion idle_comp; | |
76 | struct mutex dev_mutex; /* To protect device power status */ | |
77 | ||
78 | /* work queue */ | |
79 | struct work_struct on_work; | |
80 | struct work_struct off_work; | |
81 | struct workqueue_struct *workqueue; | |
82 | ||
83 | /* Interrupt register lock */ | |
84 | spinlock_t irq_lock; | |
85 | ||
86 | bool edp_connected; | |
87 | bool power_on; | |
88 | ||
89 | /* edid raw data */ | |
90 | struct edid *edid; | |
91 | ||
92 | struct drm_dp_link dp_link; | |
93 | struct drm_dp_aux *drm_aux; | |
94 | ||
95 | /* dpcd raw data */ | |
96 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; | |
97 | ||
98 | /* Link status */ | |
99 | u8 link_rate; | |
100 | u8 lane_cnt; | |
101 | u8 v_level; | |
102 | u8 p_level; | |
103 | ||
104 | /* Timing status */ | |
105 | u8 interlaced; | |
106 | u32 pixel_rate; /* in kHz */ | |
107 | u32 color_depth; | |
108 | ||
109 | struct edp_aux *aux; | |
110 | struct edp_phy *phy; | |
111 | }; | |
112 | ||
113 | struct edp_pixel_clk_div { | |
114 | u32 rate; /* in kHz */ | |
115 | u32 m; | |
116 | u32 n; | |
117 | }; | |
118 | ||
119 | #define EDP_PIXEL_CLK_NUM 8 | |
120 | static const struct edp_pixel_clk_div clk_divs[2][EDP_PIXEL_CLK_NUM] = { | |
121 | { /* Link clock = 162MHz, source clock = 810MHz */ | |
122 | {119000, 31, 211}, /* WSXGA+ 1680x1050@60Hz CVT */ | |
123 | {130250, 32, 199}, /* UXGA 1600x1200@60Hz CVT */ | |
124 | {148500, 11, 60}, /* FHD 1920x1080@60Hz */ | |
125 | {154000, 50, 263}, /* WUXGA 1920x1200@60Hz CVT */ | |
126 | {209250, 31, 120}, /* QXGA 2048x1536@60Hz CVT */ | |
127 | {268500, 119, 359}, /* WQXGA 2560x1600@60Hz CVT */ | |
128 | {138530, 33, 193}, /* AUO B116HAN03.0 Panel */ | |
129 | {141400, 48, 275}, /* AUO B133HTN01.2 Panel */ | |
130 | }, | |
131 | { /* Link clock = 270MHz, source clock = 675MHz */ | |
132 | {119000, 52, 295}, /* WSXGA+ 1680x1050@60Hz CVT */ | |
133 | {130250, 11, 57}, /* UXGA 1600x1200@60Hz CVT */ | |
134 | {148500, 11, 50}, /* FHD 1920x1080@60Hz */ | |
135 | {154000, 47, 206}, /* WUXGA 1920x1200@60Hz CVT */ | |
136 | {209250, 31, 100}, /* QXGA 2048x1536@60Hz CVT */ | |
137 | {268500, 107, 269}, /* WQXGA 2560x1600@60Hz CVT */ | |
138 | {138530, 63, 307}, /* AUO B116HAN03.0 Panel */ | |
139 | {141400, 53, 253}, /* AUO B133HTN01.2 Panel */ | |
140 | }, | |
141 | }; | |
142 | ||
143 | static int edp_clk_init(struct edp_ctrl *ctrl) | |
144 | { | |
cf52ec24 | 145 | struct platform_device *pdev = ctrl->pdev; |
ab5b0107 HL |
146 | int ret; |
147 | ||
cf52ec24 | 148 | ctrl->aux_clk = msm_clk_get(pdev, "core"); |
ab5b0107 HL |
149 | if (IS_ERR(ctrl->aux_clk)) { |
150 | ret = PTR_ERR(ctrl->aux_clk); | |
cf52ec24 | 151 | pr_err("%s: Can't find core clock, %d\n", __func__, ret); |
ab5b0107 HL |
152 | ctrl->aux_clk = NULL; |
153 | return ret; | |
154 | } | |
155 | ||
cf52ec24 | 156 | ctrl->pixel_clk = msm_clk_get(pdev, "pixel"); |
ab5b0107 HL |
157 | if (IS_ERR(ctrl->pixel_clk)) { |
158 | ret = PTR_ERR(ctrl->pixel_clk); | |
cf52ec24 | 159 | pr_err("%s: Can't find pixel clock, %d\n", __func__, ret); |
ab5b0107 HL |
160 | ctrl->pixel_clk = NULL; |
161 | return ret; | |
162 | } | |
163 | ||
cf52ec24 | 164 | ctrl->ahb_clk = msm_clk_get(pdev, "iface"); |
ab5b0107 HL |
165 | if (IS_ERR(ctrl->ahb_clk)) { |
166 | ret = PTR_ERR(ctrl->ahb_clk); | |
cf52ec24 | 167 | pr_err("%s: Can't find iface clock, %d\n", __func__, ret); |
ab5b0107 HL |
168 | ctrl->ahb_clk = NULL; |
169 | return ret; | |
170 | } | |
171 | ||
cf52ec24 | 172 | ctrl->link_clk = msm_clk_get(pdev, "link"); |
ab5b0107 HL |
173 | if (IS_ERR(ctrl->link_clk)) { |
174 | ret = PTR_ERR(ctrl->link_clk); | |
cf52ec24 | 175 | pr_err("%s: Can't find link clock, %d\n", __func__, ret); |
ab5b0107 HL |
176 | ctrl->link_clk = NULL; |
177 | return ret; | |
178 | } | |
179 | ||
180 | /* need mdp core clock to receive irq */ | |
cf52ec24 | 181 | ctrl->mdp_core_clk = msm_clk_get(pdev, "mdp_core"); |
ab5b0107 HL |
182 | if (IS_ERR(ctrl->mdp_core_clk)) { |
183 | ret = PTR_ERR(ctrl->mdp_core_clk); | |
cf52ec24 | 184 | pr_err("%s: Can't find mdp_core clock, %d\n", __func__, ret); |
ab5b0107 HL |
185 | ctrl->mdp_core_clk = NULL; |
186 | return ret; | |
187 | } | |
188 | ||
189 | return 0; | |
190 | } | |
191 | ||
192 | static int edp_clk_enable(struct edp_ctrl *ctrl, u32 clk_mask) | |
193 | { | |
194 | int ret; | |
195 | ||
196 | DBG("mask=%x", clk_mask); | |
197 | /* ahb_clk should be enabled first */ | |
198 | if (clk_mask & EDP_CLK_MASK_AHB) { | |
199 | ret = clk_prepare_enable(ctrl->ahb_clk); | |
200 | if (ret) { | |
201 | pr_err("%s: Failed to enable ahb clk\n", __func__); | |
202 | goto f0; | |
203 | } | |
204 | } | |
205 | if (clk_mask & EDP_CLK_MASK_AUX) { | |
206 | ret = clk_set_rate(ctrl->aux_clk, 19200000); | |
207 | if (ret) { | |
208 | pr_err("%s: Failed to set rate aux clk\n", __func__); | |
209 | goto f1; | |
210 | } | |
211 | ret = clk_prepare_enable(ctrl->aux_clk); | |
212 | if (ret) { | |
213 | pr_err("%s: Failed to enable aux clk\n", __func__); | |
214 | goto f1; | |
215 | } | |
216 | } | |
217 | /* Need to set rate and enable link_clk prior to pixel_clk */ | |
218 | if (clk_mask & EDP_CLK_MASK_LINK) { | |
219 | DBG("edp->link_clk, set_rate %ld", | |
220 | (unsigned long)ctrl->link_rate * 27000000); | |
221 | ret = clk_set_rate(ctrl->link_clk, | |
222 | (unsigned long)ctrl->link_rate * 27000000); | |
223 | if (ret) { | |
224 | pr_err("%s: Failed to set rate to link clk\n", | |
225 | __func__); | |
226 | goto f2; | |
227 | } | |
228 | ||
229 | ret = clk_prepare_enable(ctrl->link_clk); | |
230 | if (ret) { | |
231 | pr_err("%s: Failed to enable link clk\n", __func__); | |
232 | goto f2; | |
233 | } | |
234 | } | |
235 | if (clk_mask & EDP_CLK_MASK_PIXEL) { | |
236 | DBG("edp->pixel_clk, set_rate %ld", | |
237 | (unsigned long)ctrl->pixel_rate * 1000); | |
238 | ret = clk_set_rate(ctrl->pixel_clk, | |
239 | (unsigned long)ctrl->pixel_rate * 1000); | |
240 | if (ret) { | |
241 | pr_err("%s: Failed to set rate to pixel clk\n", | |
242 | __func__); | |
243 | goto f3; | |
244 | } | |
245 | ||
246 | ret = clk_prepare_enable(ctrl->pixel_clk); | |
247 | if (ret) { | |
248 | pr_err("%s: Failed to enable pixel clk\n", __func__); | |
249 | goto f3; | |
250 | } | |
251 | } | |
252 | if (clk_mask & EDP_CLK_MASK_MDP_CORE) { | |
253 | ret = clk_prepare_enable(ctrl->mdp_core_clk); | |
254 | if (ret) { | |
255 | pr_err("%s: Failed to enable mdp core clk\n", __func__); | |
256 | goto f4; | |
257 | } | |
258 | } | |
259 | ||
260 | return 0; | |
261 | ||
262 | f4: | |
263 | if (clk_mask & EDP_CLK_MASK_PIXEL) | |
264 | clk_disable_unprepare(ctrl->pixel_clk); | |
265 | f3: | |
266 | if (clk_mask & EDP_CLK_MASK_LINK) | |
267 | clk_disable_unprepare(ctrl->link_clk); | |
268 | f2: | |
269 | if (clk_mask & EDP_CLK_MASK_AUX) | |
270 | clk_disable_unprepare(ctrl->aux_clk); | |
271 | f1: | |
272 | if (clk_mask & EDP_CLK_MASK_AHB) | |
273 | clk_disable_unprepare(ctrl->ahb_clk); | |
274 | f0: | |
275 | return ret; | |
276 | } | |
277 | ||
278 | static void edp_clk_disable(struct edp_ctrl *ctrl, u32 clk_mask) | |
279 | { | |
280 | if (clk_mask & EDP_CLK_MASK_MDP_CORE) | |
281 | clk_disable_unprepare(ctrl->mdp_core_clk); | |
282 | if (clk_mask & EDP_CLK_MASK_PIXEL) | |
283 | clk_disable_unprepare(ctrl->pixel_clk); | |
284 | if (clk_mask & EDP_CLK_MASK_LINK) | |
285 | clk_disable_unprepare(ctrl->link_clk); | |
286 | if (clk_mask & EDP_CLK_MASK_AUX) | |
287 | clk_disable_unprepare(ctrl->aux_clk); | |
288 | if (clk_mask & EDP_CLK_MASK_AHB) | |
289 | clk_disable_unprepare(ctrl->ahb_clk); | |
290 | } | |
291 | ||
292 | static int edp_regulator_init(struct edp_ctrl *ctrl) | |
293 | { | |
294 | struct device *dev = &ctrl->pdev->dev; | |
d6c925ca | 295 | int ret; |
ab5b0107 HL |
296 | |
297 | DBG(""); | |
298 | ctrl->vdda_vreg = devm_regulator_get(dev, "vdda"); | |
d6c925ca VT |
299 | ret = PTR_ERR_OR_ZERO(ctrl->vdda_vreg); |
300 | if (ret) { | |
301 | pr_err("%s: Could not get vdda reg, ret = %d\n", __func__, | |
302 | ret); | |
ab5b0107 | 303 | ctrl->vdda_vreg = NULL; |
d6c925ca | 304 | return ret; |
ab5b0107 HL |
305 | } |
306 | ctrl->lvl_vreg = devm_regulator_get(dev, "lvl-vdd"); | |
d6c925ca VT |
307 | ret = PTR_ERR_OR_ZERO(ctrl->lvl_vreg); |
308 | if (ret) { | |
309 | pr_err("%s: Could not get lvl-vdd reg, ret = %d\n", __func__, | |
310 | ret); | |
ab5b0107 | 311 | ctrl->lvl_vreg = NULL; |
d6c925ca | 312 | return ret; |
ab5b0107 HL |
313 | } |
314 | ||
315 | return 0; | |
316 | } | |
317 | ||
318 | static int edp_regulator_enable(struct edp_ctrl *ctrl) | |
319 | { | |
320 | int ret; | |
321 | ||
7e476c7d | 322 | ret = regulator_set_load(ctrl->vdda_vreg, VDDA_UA_ON_LOAD); |
ab5b0107 HL |
323 | if (ret < 0) { |
324 | pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__); | |
325 | goto vdda_set_fail; | |
326 | } | |
327 | ||
328 | ret = regulator_enable(ctrl->vdda_vreg); | |
329 | if (ret) { | |
330 | pr_err("%s: Failed to enable vdda_vreg regulator.\n", __func__); | |
331 | goto vdda_enable_fail; | |
332 | } | |
333 | ||
334 | ret = regulator_enable(ctrl->lvl_vreg); | |
335 | if (ret) { | |
336 | pr_err("Failed to enable lvl-vdd reg regulator, %d", ret); | |
337 | goto lvl_enable_fail; | |
338 | } | |
339 | ||
340 | DBG("exit"); | |
341 | return 0; | |
342 | ||
343 | lvl_enable_fail: | |
344 | regulator_disable(ctrl->vdda_vreg); | |
345 | vdda_enable_fail: | |
7e476c7d | 346 | regulator_set_load(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD); |
ab5b0107 HL |
347 | vdda_set_fail: |
348 | return ret; | |
349 | } | |
350 | ||
351 | static void edp_regulator_disable(struct edp_ctrl *ctrl) | |
352 | { | |
353 | regulator_disable(ctrl->lvl_vreg); | |
354 | regulator_disable(ctrl->vdda_vreg); | |
7e476c7d | 355 | regulator_set_load(ctrl->vdda_vreg, VDDA_UA_OFF_LOAD); |
ab5b0107 HL |
356 | } |
357 | ||
358 | static int edp_gpio_config(struct edp_ctrl *ctrl) | |
359 | { | |
360 | struct device *dev = &ctrl->pdev->dev; | |
361 | int ret; | |
362 | ||
89ae3d3b | 363 | ctrl->panel_hpd_gpio = devm_gpiod_get(dev, "panel-hpd", GPIOD_IN); |
ab5b0107 HL |
364 | if (IS_ERR(ctrl->panel_hpd_gpio)) { |
365 | ret = PTR_ERR(ctrl->panel_hpd_gpio); | |
366 | ctrl->panel_hpd_gpio = NULL; | |
367 | pr_err("%s: cannot get panel-hpd-gpios, %d\n", __func__, ret); | |
368 | return ret; | |
369 | } | |
370 | ||
89ae3d3b | 371 | ctrl->panel_en_gpio = devm_gpiod_get(dev, "panel-en", GPIOD_OUT_LOW); |
ab5b0107 HL |
372 | if (IS_ERR(ctrl->panel_en_gpio)) { |
373 | ret = PTR_ERR(ctrl->panel_en_gpio); | |
374 | ctrl->panel_en_gpio = NULL; | |
375 | pr_err("%s: cannot get panel-en-gpios, %d\n", __func__, ret); | |
376 | return ret; | |
377 | } | |
378 | ||
ab5b0107 HL |
379 | DBG("gpio on"); |
380 | ||
381 | return 0; | |
382 | } | |
383 | ||
384 | static void edp_ctrl_irq_enable(struct edp_ctrl *ctrl, int enable) | |
385 | { | |
386 | unsigned long flags; | |
387 | ||
388 | DBG("%d", enable); | |
389 | spin_lock_irqsave(&ctrl->irq_lock, flags); | |
390 | if (enable) { | |
391 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, EDP_INTR_MASK1); | |
392 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, EDP_INTR_MASK2); | |
393 | } else { | |
394 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, 0x0); | |
395 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, 0x0); | |
396 | } | |
397 | spin_unlock_irqrestore(&ctrl->irq_lock, flags); | |
398 | DBG("exit"); | |
399 | } | |
400 | ||
401 | static void edp_fill_link_cfg(struct edp_ctrl *ctrl) | |
402 | { | |
403 | u32 prate; | |
404 | u32 lrate; | |
405 | u32 bpp; | |
406 | u8 max_lane = ctrl->dp_link.num_lanes; | |
407 | u8 lane; | |
408 | ||
409 | prate = ctrl->pixel_rate; | |
410 | bpp = ctrl->color_depth * 3; | |
411 | ||
412 | /* | |
413 | * By default, use the maximum link rate and minimum lane count, | |
414 | * so that we can do rate down shift during link training. | |
415 | */ | |
416 | ctrl->link_rate = drm_dp_link_rate_to_bw_code(ctrl->dp_link.rate); | |
417 | ||
418 | prate *= bpp; | |
419 | prate /= 8; /* in kByte */ | |
420 | ||
421 | lrate = 270000; /* in kHz */ | |
422 | lrate *= ctrl->link_rate; | |
423 | lrate /= 10; /* in kByte, 10 bits --> 8 bits */ | |
424 | ||
425 | for (lane = 1; lane <= max_lane; lane <<= 1) { | |
426 | if (lrate >= prate) | |
427 | break; | |
428 | lrate <<= 1; | |
429 | } | |
430 | ||
431 | ctrl->lane_cnt = lane; | |
432 | DBG("rate=%d lane=%d", ctrl->link_rate, ctrl->lane_cnt); | |
433 | } | |
434 | ||
ab5b0107 HL |
435 | static void edp_config_ctrl(struct edp_ctrl *ctrl) |
436 | { | |
437 | u32 data; | |
438 | enum edp_color_depth depth; | |
439 | ||
440 | data = EDP_CONFIGURATION_CTRL_LANES(ctrl->lane_cnt - 1); | |
441 | ||
442 | if (ctrl->dp_link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) | |
443 | data |= EDP_CONFIGURATION_CTRL_ENHANCED_FRAMING; | |
444 | ||
445 | depth = EDP_6BIT; | |
446 | if (ctrl->color_depth == 8) | |
447 | depth = EDP_8BIT; | |
448 | ||
449 | data |= EDP_CONFIGURATION_CTRL_COLOR(depth); | |
450 | ||
451 | if (!ctrl->interlaced) /* progressive */ | |
452 | data |= EDP_CONFIGURATION_CTRL_PROGRESSIVE; | |
453 | ||
454 | data |= (EDP_CONFIGURATION_CTRL_SYNC_CLK | | |
455 | EDP_CONFIGURATION_CTRL_STATIC_MVID); | |
456 | ||
457 | edp_write(ctrl->base + REG_EDP_CONFIGURATION_CTRL, data); | |
458 | } | |
459 | ||
460 | static void edp_state_ctrl(struct edp_ctrl *ctrl, u32 state) | |
461 | { | |
462 | edp_write(ctrl->base + REG_EDP_STATE_CTRL, state); | |
463 | /* Make sure H/W status is set */ | |
464 | wmb(); | |
465 | } | |
466 | ||
467 | static int edp_lane_set_write(struct edp_ctrl *ctrl, | |
468 | u8 voltage_level, u8 pre_emphasis_level) | |
469 | { | |
470 | int i; | |
471 | u8 buf[4]; | |
472 | ||
473 | if (voltage_level >= DPCD_LINK_VOLTAGE_MAX) | |
474 | voltage_level |= 0x04; | |
475 | ||
476 | if (pre_emphasis_level >= DPCD_LINK_PRE_EMPHASIS_MAX) | |
477 | pre_emphasis_level |= 0x04; | |
478 | ||
479 | pre_emphasis_level <<= 3; | |
480 | ||
481 | for (i = 0; i < 4; i++) | |
482 | buf[i] = voltage_level | pre_emphasis_level; | |
483 | ||
484 | DBG("%s: p|v=0x%x", __func__, voltage_level | pre_emphasis_level); | |
485 | if (drm_dp_dpcd_write(ctrl->drm_aux, 0x103, buf, 4) < 4) { | |
486 | pr_err("%s: Set sw/pe to panel failed\n", __func__); | |
487 | return -ENOLINK; | |
488 | } | |
489 | ||
490 | return 0; | |
491 | } | |
492 | ||
493 | static int edp_train_pattern_set_write(struct edp_ctrl *ctrl, u8 pattern) | |
494 | { | |
495 | u8 p = pattern; | |
496 | ||
497 | DBG("pattern=%x", p); | |
498 | if (drm_dp_dpcd_write(ctrl->drm_aux, | |
499 | DP_TRAINING_PATTERN_SET, &p, 1) < 1) { | |
500 | pr_err("%s: Set training pattern to panel failed\n", __func__); | |
501 | return -ENOLINK; | |
502 | } | |
503 | ||
504 | return 0; | |
505 | } | |
506 | ||
507 | static void edp_sink_train_set_adjust(struct edp_ctrl *ctrl, | |
508 | const u8 *link_status) | |
509 | { | |
510 | int i; | |
511 | u8 max = 0; | |
512 | u8 data; | |
513 | ||
514 | /* use the max level across lanes */ | |
515 | for (i = 0; i < ctrl->lane_cnt; i++) { | |
516 | data = drm_dp_get_adjust_request_voltage(link_status, i); | |
517 | DBG("lane=%d req_voltage_swing=0x%x", i, data); | |
518 | if (max < data) | |
519 | max = data; | |
520 | } | |
521 | ||
522 | ctrl->v_level = max >> DP_TRAIN_VOLTAGE_SWING_SHIFT; | |
523 | ||
524 | /* use the max level across lanes */ | |
525 | max = 0; | |
526 | for (i = 0; i < ctrl->lane_cnt; i++) { | |
527 | data = drm_dp_get_adjust_request_pre_emphasis(link_status, i); | |
528 | DBG("lane=%d req_pre_emphasis=0x%x", i, data); | |
529 | if (max < data) | |
530 | max = data; | |
531 | } | |
532 | ||
533 | ctrl->p_level = max >> DP_TRAIN_PRE_EMPHASIS_SHIFT; | |
534 | DBG("v_level=%d, p_level=%d", ctrl->v_level, ctrl->p_level); | |
535 | } | |
536 | ||
537 | static void edp_host_train_set(struct edp_ctrl *ctrl, u32 train) | |
538 | { | |
539 | int cnt = 10; | |
540 | u32 data; | |
541 | u32 shift = train - 1; | |
542 | ||
543 | DBG("train=%d", train); | |
544 | ||
545 | edp_state_ctrl(ctrl, EDP_STATE_CTRL_TRAIN_PATTERN_1 << shift); | |
546 | while (--cnt) { | |
547 | data = edp_read(ctrl->base + REG_EDP_MAINLINK_READY); | |
548 | if (data & (EDP_MAINLINK_READY_TRAIN_PATTERN_1_READY << shift)) | |
549 | break; | |
550 | } | |
551 | ||
552 | if (cnt == 0) | |
553 | pr_err("%s: set link_train=%d failed\n", __func__, train); | |
554 | } | |
555 | ||
556 | static const u8 vm_pre_emphasis[4][4] = { | |
557 | {0x03, 0x06, 0x09, 0x0C}, /* pe0, 0 db */ | |
558 | {0x03, 0x06, 0x09, 0xFF}, /* pe1, 3.5 db */ | |
559 | {0x03, 0x06, 0xFF, 0xFF}, /* pe2, 6.0 db */ | |
560 | {0x03, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */ | |
561 | }; | |
562 | ||
563 | /* voltage swing, 0.2v and 1.0v are not support */ | |
564 | static const u8 vm_voltage_swing[4][4] = { | |
565 | {0x14, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v */ | |
566 | {0x18, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */ | |
567 | {0x1A, 0x1E, 0xFF, 0xFF}, /* sw1, 0.8 v */ | |
568 | {0x1E, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */ | |
569 | }; | |
570 | ||
571 | static int edp_voltage_pre_emphasise_set(struct edp_ctrl *ctrl) | |
572 | { | |
573 | u32 value0; | |
574 | u32 value1; | |
575 | ||
576 | DBG("v=%d p=%d", ctrl->v_level, ctrl->p_level); | |
577 | ||
578 | value0 = vm_pre_emphasis[(int)(ctrl->v_level)][(int)(ctrl->p_level)]; | |
579 | value1 = vm_voltage_swing[(int)(ctrl->v_level)][(int)(ctrl->p_level)]; | |
580 | ||
581 | /* Configure host and panel only if both values are allowed */ | |
582 | if (value0 != 0xFF && value1 != 0xFF) { | |
583 | msm_edp_phy_vm_pe_cfg(ctrl->phy, value0, value1); | |
584 | return edp_lane_set_write(ctrl, ctrl->v_level, ctrl->p_level); | |
585 | } | |
586 | ||
587 | return -EINVAL; | |
588 | } | |
589 | ||
590 | static int edp_start_link_train_1(struct edp_ctrl *ctrl) | |
591 | { | |
592 | u8 link_status[DP_LINK_STATUS_SIZE]; | |
593 | u8 old_v_level; | |
594 | int tries; | |
595 | int ret; | |
596 | int rlen; | |
597 | ||
598 | DBG(""); | |
599 | ||
600 | edp_host_train_set(ctrl, DP_TRAINING_PATTERN_1); | |
601 | ret = edp_voltage_pre_emphasise_set(ctrl); | |
602 | if (ret) | |
603 | return ret; | |
604 | ret = edp_train_pattern_set_write(ctrl, | |
605 | DP_TRAINING_PATTERN_1 | DP_RECOVERED_CLOCK_OUT_EN); | |
606 | if (ret) | |
607 | return ret; | |
608 | ||
609 | tries = 0; | |
610 | old_v_level = ctrl->v_level; | |
611 | while (1) { | |
612 | drm_dp_link_train_clock_recovery_delay(ctrl->dpcd); | |
613 | ||
614 | rlen = drm_dp_dpcd_read_link_status(ctrl->drm_aux, link_status); | |
615 | if (rlen < DP_LINK_STATUS_SIZE) { | |
616 | pr_err("%s: read link status failed\n", __func__); | |
617 | return -ENOLINK; | |
618 | } | |
619 | if (drm_dp_clock_recovery_ok(link_status, ctrl->lane_cnt)) { | |
620 | ret = 0; | |
621 | break; | |
622 | } | |
623 | ||
624 | if (ctrl->v_level == DPCD_LINK_VOLTAGE_MAX) { | |
625 | ret = -1; | |
626 | break; | |
627 | } | |
628 | ||
629 | if (old_v_level == ctrl->v_level) { | |
630 | tries++; | |
631 | if (tries >= 5) { | |
632 | ret = -1; | |
633 | break; | |
634 | } | |
635 | } else { | |
636 | tries = 0; | |
637 | old_v_level = ctrl->v_level; | |
638 | } | |
639 | ||
640 | edp_sink_train_set_adjust(ctrl, link_status); | |
641 | ret = edp_voltage_pre_emphasise_set(ctrl); | |
642 | if (ret) | |
643 | return ret; | |
644 | } | |
645 | ||
646 | return ret; | |
647 | } | |
648 | ||
649 | static int edp_start_link_train_2(struct edp_ctrl *ctrl) | |
650 | { | |
651 | u8 link_status[DP_LINK_STATUS_SIZE]; | |
652 | int tries = 0; | |
653 | int ret; | |
654 | int rlen; | |
655 | ||
656 | DBG(""); | |
657 | ||
658 | edp_host_train_set(ctrl, DP_TRAINING_PATTERN_2); | |
659 | ret = edp_voltage_pre_emphasise_set(ctrl); | |
660 | if (ret) | |
661 | return ret; | |
662 | ||
663 | ret = edp_train_pattern_set_write(ctrl, | |
664 | DP_TRAINING_PATTERN_2 | DP_RECOVERED_CLOCK_OUT_EN); | |
665 | if (ret) | |
666 | return ret; | |
667 | ||
668 | while (1) { | |
669 | drm_dp_link_train_channel_eq_delay(ctrl->dpcd); | |
670 | ||
671 | rlen = drm_dp_dpcd_read_link_status(ctrl->drm_aux, link_status); | |
672 | if (rlen < DP_LINK_STATUS_SIZE) { | |
673 | pr_err("%s: read link status failed\n", __func__); | |
674 | return -ENOLINK; | |
675 | } | |
676 | if (drm_dp_channel_eq_ok(link_status, ctrl->lane_cnt)) { | |
677 | ret = 0; | |
678 | break; | |
679 | } | |
680 | ||
681 | tries++; | |
682 | if (tries > 10) { | |
683 | ret = -1; | |
684 | break; | |
685 | } | |
686 | ||
687 | edp_sink_train_set_adjust(ctrl, link_status); | |
688 | ret = edp_voltage_pre_emphasise_set(ctrl); | |
689 | if (ret) | |
690 | return ret; | |
691 | } | |
692 | ||
693 | return ret; | |
694 | } | |
695 | ||
696 | static int edp_link_rate_down_shift(struct edp_ctrl *ctrl) | |
697 | { | |
698 | u32 prate, lrate, bpp; | |
699 | u8 rate, lane, max_lane; | |
700 | int changed = 0; | |
701 | ||
702 | rate = ctrl->link_rate; | |
703 | lane = ctrl->lane_cnt; | |
704 | max_lane = ctrl->dp_link.num_lanes; | |
705 | ||
706 | bpp = ctrl->color_depth * 3; | |
707 | prate = ctrl->pixel_rate; | |
708 | prate *= bpp; | |
709 | prate /= 8; /* in kByte */ | |
710 | ||
711 | if (rate > DP_LINK_BW_1_62 && rate <= EDP_LINK_BW_MAX) { | |
712 | rate -= 4; /* reduce rate */ | |
713 | changed++; | |
714 | } | |
715 | ||
716 | if (changed) { | |
717 | if (lane >= 1 && lane < max_lane) | |
718 | lane <<= 1; /* increase lane */ | |
719 | ||
720 | lrate = 270000; /* in kHz */ | |
721 | lrate *= rate; | |
722 | lrate /= 10; /* kByte, 10 bits --> 8 bits */ | |
723 | lrate *= lane; | |
724 | ||
725 | DBG("new lrate=%u prate=%u(kHz) rate=%d lane=%d p=%u b=%d", | |
726 | lrate, prate, rate, lane, | |
727 | ctrl->pixel_rate, | |
728 | bpp); | |
729 | ||
730 | if (lrate > prate) { | |
731 | ctrl->link_rate = rate; | |
732 | ctrl->lane_cnt = lane; | |
733 | DBG("new rate=%d %d", rate, lane); | |
734 | return 0; | |
735 | } | |
736 | } | |
737 | ||
738 | return -EINVAL; | |
739 | } | |
740 | ||
741 | static int edp_clear_training_pattern(struct edp_ctrl *ctrl) | |
742 | { | |
743 | int ret; | |
744 | ||
745 | ret = edp_train_pattern_set_write(ctrl, 0); | |
746 | ||
747 | drm_dp_link_train_channel_eq_delay(ctrl->dpcd); | |
748 | ||
749 | return ret; | |
750 | } | |
751 | ||
752 | static int edp_do_link_train(struct edp_ctrl *ctrl) | |
753 | { | |
754 | int ret; | |
755 | struct drm_dp_link dp_link; | |
756 | ||
757 | DBG(""); | |
758 | /* | |
759 | * Set the current link rate and lane cnt to panel. They may have been | |
760 | * adjusted and the values are different from them in DPCD CAP | |
761 | */ | |
762 | dp_link.num_lanes = ctrl->lane_cnt; | |
763 | dp_link.rate = drm_dp_bw_code_to_link_rate(ctrl->link_rate); | |
764 | dp_link.capabilities = ctrl->dp_link.capabilities; | |
765 | if (drm_dp_link_configure(ctrl->drm_aux, &dp_link) < 0) | |
766 | return EDP_TRAIN_FAIL; | |
767 | ||
768 | ctrl->v_level = 0; /* start from default level */ | |
769 | ctrl->p_level = 0; | |
770 | ||
771 | edp_state_ctrl(ctrl, 0); | |
772 | if (edp_clear_training_pattern(ctrl)) | |
773 | return EDP_TRAIN_FAIL; | |
774 | ||
775 | ret = edp_start_link_train_1(ctrl); | |
776 | if (ret < 0) { | |
777 | if (edp_link_rate_down_shift(ctrl) == 0) { | |
778 | DBG("link reconfig"); | |
779 | ret = EDP_TRAIN_RECONFIG; | |
780 | goto clear; | |
781 | } else { | |
782 | pr_err("%s: Training 1 failed", __func__); | |
783 | ret = EDP_TRAIN_FAIL; | |
784 | goto clear; | |
785 | } | |
786 | } | |
787 | DBG("Training 1 completed successfully"); | |
788 | ||
789 | edp_state_ctrl(ctrl, 0); | |
790 | if (edp_clear_training_pattern(ctrl)) | |
791 | return EDP_TRAIN_FAIL; | |
792 | ||
793 | ret = edp_start_link_train_2(ctrl); | |
794 | if (ret < 0) { | |
795 | if (edp_link_rate_down_shift(ctrl) == 0) { | |
796 | DBG("link reconfig"); | |
797 | ret = EDP_TRAIN_RECONFIG; | |
798 | goto clear; | |
799 | } else { | |
800 | pr_err("%s: Training 2 failed", __func__); | |
801 | ret = EDP_TRAIN_FAIL; | |
802 | goto clear; | |
803 | } | |
804 | } | |
805 | DBG("Training 2 completed successfully"); | |
806 | ||
807 | edp_state_ctrl(ctrl, EDP_STATE_CTRL_SEND_VIDEO); | |
808 | clear: | |
809 | edp_clear_training_pattern(ctrl); | |
810 | ||
811 | return ret; | |
812 | } | |
813 | ||
814 | static void edp_clock_synchrous(struct edp_ctrl *ctrl, int sync) | |
815 | { | |
816 | u32 data; | |
817 | enum edp_color_depth depth; | |
818 | ||
819 | data = edp_read(ctrl->base + REG_EDP_MISC1_MISC0); | |
820 | ||
821 | if (sync) | |
822 | data |= EDP_MISC1_MISC0_SYNC; | |
823 | else | |
824 | data &= ~EDP_MISC1_MISC0_SYNC; | |
825 | ||
826 | /* only legacy rgb mode supported */ | |
827 | depth = EDP_6BIT; /* Default */ | |
828 | if (ctrl->color_depth == 8) | |
829 | depth = EDP_8BIT; | |
830 | else if (ctrl->color_depth == 10) | |
831 | depth = EDP_10BIT; | |
832 | else if (ctrl->color_depth == 12) | |
833 | depth = EDP_12BIT; | |
834 | else if (ctrl->color_depth == 16) | |
835 | depth = EDP_16BIT; | |
836 | ||
837 | data |= EDP_MISC1_MISC0_COLOR(depth); | |
838 | ||
839 | edp_write(ctrl->base + REG_EDP_MISC1_MISC0, data); | |
840 | } | |
841 | ||
842 | static int edp_sw_mvid_nvid(struct edp_ctrl *ctrl, u32 m, u32 n) | |
843 | { | |
844 | u32 n_multi, m_multi = 5; | |
845 | ||
846 | if (ctrl->link_rate == DP_LINK_BW_1_62) { | |
847 | n_multi = 1; | |
848 | } else if (ctrl->link_rate == DP_LINK_BW_2_7) { | |
849 | n_multi = 2; | |
850 | } else { | |
851 | pr_err("%s: Invalid link rate, %d\n", __func__, | |
852 | ctrl->link_rate); | |
853 | return -EINVAL; | |
854 | } | |
855 | ||
856 | edp_write(ctrl->base + REG_EDP_SOFTWARE_MVID, m * m_multi); | |
857 | edp_write(ctrl->base + REG_EDP_SOFTWARE_NVID, n * n_multi); | |
858 | ||
859 | return 0; | |
860 | } | |
861 | ||
862 | static void edp_mainlink_ctrl(struct edp_ctrl *ctrl, int enable) | |
863 | { | |
864 | u32 data = 0; | |
865 | ||
866 | edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, EDP_MAINLINK_CTRL_RESET); | |
867 | /* Make sure fully reset */ | |
868 | wmb(); | |
869 | usleep_range(500, 1000); | |
870 | ||
871 | if (enable) | |
872 | data |= EDP_MAINLINK_CTRL_ENABLE; | |
873 | ||
874 | edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, data); | |
875 | } | |
876 | ||
877 | static void edp_ctrl_phy_aux_enable(struct edp_ctrl *ctrl, int enable) | |
878 | { | |
879 | if (enable) { | |
880 | edp_regulator_enable(ctrl); | |
881 | edp_clk_enable(ctrl, EDP_CLK_MASK_AUX_CHAN); | |
882 | msm_edp_phy_ctrl(ctrl->phy, 1); | |
883 | msm_edp_aux_ctrl(ctrl->aux, 1); | |
884 | gpiod_set_value(ctrl->panel_en_gpio, 1); | |
885 | } else { | |
886 | gpiod_set_value(ctrl->panel_en_gpio, 0); | |
887 | msm_edp_aux_ctrl(ctrl->aux, 0); | |
888 | msm_edp_phy_ctrl(ctrl->phy, 0); | |
889 | edp_clk_disable(ctrl, EDP_CLK_MASK_AUX_CHAN); | |
890 | edp_regulator_disable(ctrl); | |
891 | } | |
892 | } | |
893 | ||
894 | static void edp_ctrl_link_enable(struct edp_ctrl *ctrl, int enable) | |
895 | { | |
896 | u32 m, n; | |
897 | ||
898 | if (enable) { | |
899 | /* Enable link channel clocks */ | |
900 | edp_clk_enable(ctrl, EDP_CLK_MASK_LINK_CHAN); | |
901 | ||
902 | msm_edp_phy_lane_power_ctrl(ctrl->phy, true, ctrl->lane_cnt); | |
903 | ||
904 | msm_edp_phy_vm_pe_init(ctrl->phy); | |
905 | ||
906 | /* Make sure phy is programed */ | |
907 | wmb(); | |
908 | msm_edp_phy_ready(ctrl->phy); | |
909 | ||
910 | edp_config_ctrl(ctrl); | |
911 | msm_edp_ctrl_pixel_clock_valid(ctrl, ctrl->pixel_rate, &m, &n); | |
912 | edp_sw_mvid_nvid(ctrl, m, n); | |
913 | edp_mainlink_ctrl(ctrl, 1); | |
914 | } else { | |
915 | edp_mainlink_ctrl(ctrl, 0); | |
916 | ||
917 | msm_edp_phy_lane_power_ctrl(ctrl->phy, false, 0); | |
918 | edp_clk_disable(ctrl, EDP_CLK_MASK_LINK_CHAN); | |
919 | } | |
920 | } | |
921 | ||
922 | static int edp_ctrl_training(struct edp_ctrl *ctrl) | |
923 | { | |
924 | int ret; | |
925 | ||
926 | /* Do link training only when power is on */ | |
927 | if (!ctrl->power_on) | |
928 | return -EINVAL; | |
929 | ||
930 | train_start: | |
931 | ret = edp_do_link_train(ctrl); | |
932 | if (ret == EDP_TRAIN_RECONFIG) { | |
933 | /* Re-configure main link */ | |
934 | edp_ctrl_irq_enable(ctrl, 0); | |
935 | edp_ctrl_link_enable(ctrl, 0); | |
936 | msm_edp_phy_ctrl(ctrl->phy, 0); | |
937 | ||
938 | /* Make sure link is fully disabled */ | |
939 | wmb(); | |
940 | usleep_range(500, 1000); | |
941 | ||
942 | msm_edp_phy_ctrl(ctrl->phy, 1); | |
943 | edp_ctrl_link_enable(ctrl, 1); | |
944 | edp_ctrl_irq_enable(ctrl, 1); | |
945 | goto train_start; | |
946 | } | |
947 | ||
948 | return ret; | |
949 | } | |
950 | ||
951 | static void edp_ctrl_on_worker(struct work_struct *work) | |
952 | { | |
953 | struct edp_ctrl *ctrl = container_of( | |
954 | work, struct edp_ctrl, on_work); | |
955 | int ret; | |
956 | ||
957 | mutex_lock(&ctrl->dev_mutex); | |
958 | ||
959 | if (ctrl->power_on) { | |
960 | DBG("already on"); | |
961 | goto unlock_ret; | |
962 | } | |
963 | ||
964 | edp_ctrl_phy_aux_enable(ctrl, 1); | |
965 | edp_ctrl_link_enable(ctrl, 1); | |
966 | ||
967 | edp_ctrl_irq_enable(ctrl, 1); | |
a5ec308a | 968 | ret = drm_dp_link_power_up(ctrl->drm_aux, &ctrl->dp_link); |
ab5b0107 HL |
969 | if (ret) |
970 | goto fail; | |
971 | ||
972 | ctrl->power_on = true; | |
973 | ||
974 | /* Start link training */ | |
975 | ret = edp_ctrl_training(ctrl); | |
976 | if (ret != EDP_TRAIN_SUCCESS) | |
977 | goto fail; | |
978 | ||
979 | DBG("DONE"); | |
980 | goto unlock_ret; | |
981 | ||
982 | fail: | |
983 | edp_ctrl_irq_enable(ctrl, 0); | |
984 | edp_ctrl_link_enable(ctrl, 0); | |
985 | edp_ctrl_phy_aux_enable(ctrl, 0); | |
986 | ctrl->power_on = false; | |
987 | unlock_ret: | |
988 | mutex_unlock(&ctrl->dev_mutex); | |
989 | } | |
990 | ||
991 | static void edp_ctrl_off_worker(struct work_struct *work) | |
992 | { | |
993 | struct edp_ctrl *ctrl = container_of( | |
994 | work, struct edp_ctrl, off_work); | |
a51d01f0 | 995 | unsigned long time_left; |
ab5b0107 HL |
996 | |
997 | mutex_lock(&ctrl->dev_mutex); | |
998 | ||
999 | if (!ctrl->power_on) { | |
1000 | DBG("already off"); | |
1001 | goto unlock_ret; | |
1002 | } | |
1003 | ||
1004 | reinit_completion(&ctrl->idle_comp); | |
1005 | edp_state_ctrl(ctrl, EDP_STATE_CTRL_PUSH_IDLE); | |
1006 | ||
a51d01f0 | 1007 | time_left = wait_for_completion_timeout(&ctrl->idle_comp, |
ab5b0107 | 1008 | msecs_to_jiffies(500)); |
c6d0baf1 | 1009 | if (!time_left) |
0c076bff | 1010 | DBG("%s: idle pattern timedout\n", __func__); |
ab5b0107 HL |
1011 | |
1012 | edp_state_ctrl(ctrl, 0); | |
1013 | ||
a5ec308a | 1014 | drm_dp_link_power_down(ctrl->drm_aux, &ctrl->dp_link); |
ab5b0107 HL |
1015 | |
1016 | edp_ctrl_irq_enable(ctrl, 0); | |
1017 | ||
1018 | edp_ctrl_link_enable(ctrl, 0); | |
1019 | ||
1020 | edp_ctrl_phy_aux_enable(ctrl, 0); | |
1021 | ||
1022 | ctrl->power_on = false; | |
1023 | ||
1024 | unlock_ret: | |
1025 | mutex_unlock(&ctrl->dev_mutex); | |
1026 | } | |
1027 | ||
1028 | irqreturn_t msm_edp_ctrl_irq(struct edp_ctrl *ctrl) | |
1029 | { | |
1030 | u32 isr1, isr2, mask1, mask2; | |
1031 | u32 ack; | |
1032 | ||
1033 | DBG(""); | |
1034 | spin_lock(&ctrl->irq_lock); | |
1035 | isr1 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_1); | |
1036 | isr2 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_2); | |
1037 | ||
1038 | mask1 = isr1 & EDP_INTR_MASK1; | |
1039 | mask2 = isr2 & EDP_INTR_MASK2; | |
1040 | ||
1041 | isr1 &= ~mask1; /* remove masks bit */ | |
1042 | isr2 &= ~mask2; | |
1043 | ||
1044 | DBG("isr=%x mask=%x isr2=%x mask2=%x", | |
1045 | isr1, mask1, isr2, mask2); | |
1046 | ||
1047 | ack = isr1 & EDP_INTR_STATUS1; | |
1048 | ack <<= 1; /* ack bits */ | |
1049 | ack |= mask1; | |
1050 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, ack); | |
1051 | ||
1052 | ack = isr2 & EDP_INTR_STATUS2; | |
1053 | ack <<= 1; /* ack bits */ | |
1054 | ack |= mask2; | |
1055 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, ack); | |
1056 | spin_unlock(&ctrl->irq_lock); | |
1057 | ||
1058 | if (isr1 & EDP_INTERRUPT_REG_1_HPD) | |
1059 | DBG("edp_hpd"); | |
1060 | ||
1061 | if (isr2 & EDP_INTERRUPT_REG_2_READY_FOR_VIDEO) | |
1062 | DBG("edp_video_ready"); | |
1063 | ||
1064 | if (isr2 & EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT) { | |
1065 | DBG("idle_patterns_sent"); | |
1066 | complete(&ctrl->idle_comp); | |
1067 | } | |
1068 | ||
1069 | msm_edp_aux_irq(ctrl->aux, isr1); | |
1070 | ||
1071 | return IRQ_HANDLED; | |
1072 | } | |
1073 | ||
1074 | void msm_edp_ctrl_power(struct edp_ctrl *ctrl, bool on) | |
1075 | { | |
1076 | if (on) | |
1077 | queue_work(ctrl->workqueue, &ctrl->on_work); | |
1078 | else | |
1079 | queue_work(ctrl->workqueue, &ctrl->off_work); | |
1080 | } | |
1081 | ||
1082 | int msm_edp_ctrl_init(struct msm_edp *edp) | |
1083 | { | |
1084 | struct edp_ctrl *ctrl = NULL; | |
1085 | struct device *dev = &edp->pdev->dev; | |
1086 | int ret; | |
1087 | ||
1088 | if (!edp) { | |
1089 | pr_err("%s: edp is NULL!\n", __func__); | |
1090 | return -EINVAL; | |
1091 | } | |
1092 | ||
1093 | ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); | |
1094 | if (!ctrl) | |
1095 | return -ENOMEM; | |
1096 | ||
1097 | edp->ctrl = ctrl; | |
1098 | ctrl->pdev = edp->pdev; | |
1099 | ||
1100 | ctrl->base = msm_ioremap(ctrl->pdev, "edp", "eDP"); | |
1101 | if (IS_ERR(ctrl->base)) | |
1102 | return PTR_ERR(ctrl->base); | |
1103 | ||
1104 | /* Get regulator, clock, gpio, pwm */ | |
1105 | ret = edp_regulator_init(ctrl); | |
1106 | if (ret) { | |
1107 | pr_err("%s:regulator init fail\n", __func__); | |
1108 | return ret; | |
1109 | } | |
1110 | ret = edp_clk_init(ctrl); | |
1111 | if (ret) { | |
1112 | pr_err("%s:clk init fail\n", __func__); | |
1113 | return ret; | |
1114 | } | |
1115 | ret = edp_gpio_config(ctrl); | |
1116 | if (ret) { | |
1117 | pr_err("%s:failed to configure GPIOs: %d", __func__, ret); | |
1118 | return ret; | |
1119 | } | |
1120 | ||
1121 | /* Init aux and phy */ | |
1122 | ctrl->aux = msm_edp_aux_init(dev, ctrl->base, &ctrl->drm_aux); | |
1123 | if (!ctrl->aux || !ctrl->drm_aux) { | |
1124 | pr_err("%s:failed to init aux\n", __func__); | |
6128f1be | 1125 | return -ENOMEM; |
ab5b0107 HL |
1126 | } |
1127 | ||
1128 | ctrl->phy = msm_edp_phy_init(dev, ctrl->base); | |
1129 | if (!ctrl->phy) { | |
1130 | pr_err("%s:failed to init phy\n", __func__); | |
6128f1be | 1131 | ret = -ENOMEM; |
ab5b0107 HL |
1132 | goto err_destory_aux; |
1133 | } | |
1134 | ||
1135 | spin_lock_init(&ctrl->irq_lock); | |
1136 | mutex_init(&ctrl->dev_mutex); | |
1137 | init_completion(&ctrl->idle_comp); | |
1138 | ||
1139 | /* setup workqueue */ | |
1140 | ctrl->workqueue = alloc_ordered_workqueue("edp_drm_work", 0); | |
1141 | INIT_WORK(&ctrl->on_work, edp_ctrl_on_worker); | |
1142 | INIT_WORK(&ctrl->off_work, edp_ctrl_off_worker); | |
1143 | ||
1144 | return 0; | |
1145 | ||
1146 | err_destory_aux: | |
1147 | msm_edp_aux_destroy(dev, ctrl->aux); | |
1148 | ctrl->aux = NULL; | |
1149 | return ret; | |
1150 | } | |
1151 | ||
1152 | void msm_edp_ctrl_destroy(struct edp_ctrl *ctrl) | |
1153 | { | |
1154 | if (!ctrl) | |
1155 | return; | |
1156 | ||
1157 | if (ctrl->workqueue) { | |
1158 | flush_workqueue(ctrl->workqueue); | |
1159 | destroy_workqueue(ctrl->workqueue); | |
1160 | ctrl->workqueue = NULL; | |
1161 | } | |
1162 | ||
1163 | if (ctrl->aux) { | |
1164 | msm_edp_aux_destroy(&ctrl->pdev->dev, ctrl->aux); | |
1165 | ctrl->aux = NULL; | |
1166 | } | |
1167 | ||
1168 | kfree(ctrl->edid); | |
1169 | ctrl->edid = NULL; | |
1170 | ||
1171 | mutex_destroy(&ctrl->dev_mutex); | |
1172 | } | |
1173 | ||
1174 | bool msm_edp_ctrl_panel_connected(struct edp_ctrl *ctrl) | |
1175 | { | |
1176 | mutex_lock(&ctrl->dev_mutex); | |
1177 | DBG("connect status = %d", ctrl->edp_connected); | |
1178 | if (ctrl->edp_connected) { | |
1179 | mutex_unlock(&ctrl->dev_mutex); | |
1180 | return true; | |
1181 | } | |
1182 | ||
1183 | if (!ctrl->power_on) { | |
1184 | edp_ctrl_phy_aux_enable(ctrl, 1); | |
1185 | edp_ctrl_irq_enable(ctrl, 1); | |
1186 | } | |
1187 | ||
1188 | if (drm_dp_dpcd_read(ctrl->drm_aux, DP_DPCD_REV, ctrl->dpcd, | |
1189 | DP_RECEIVER_CAP_SIZE) < DP_RECEIVER_CAP_SIZE) { | |
1190 | pr_err("%s: AUX channel is NOT ready\n", __func__); | |
1191 | memset(ctrl->dpcd, 0, DP_RECEIVER_CAP_SIZE); | |
1192 | } else { | |
1193 | ctrl->edp_connected = true; | |
1194 | } | |
1195 | ||
1196 | if (!ctrl->power_on) { | |
1197 | edp_ctrl_irq_enable(ctrl, 0); | |
1198 | edp_ctrl_phy_aux_enable(ctrl, 0); | |
1199 | } | |
1200 | ||
1201 | DBG("exit: connect status=%d", ctrl->edp_connected); | |
1202 | ||
1203 | mutex_unlock(&ctrl->dev_mutex); | |
1204 | ||
1205 | return ctrl->edp_connected; | |
1206 | } | |
1207 | ||
1208 | int msm_edp_ctrl_get_panel_info(struct edp_ctrl *ctrl, | |
1209 | struct drm_connector *connector, struct edid **edid) | |
1210 | { | |
1211 | int ret = 0; | |
1212 | ||
1213 | mutex_lock(&ctrl->dev_mutex); | |
1214 | ||
1215 | if (ctrl->edid) { | |
1216 | if (edid) { | |
1217 | DBG("Just return edid buffer"); | |
1218 | *edid = ctrl->edid; | |
1219 | } | |
1220 | goto unlock_ret; | |
1221 | } | |
1222 | ||
1223 | if (!ctrl->power_on) { | |
1224 | edp_ctrl_phy_aux_enable(ctrl, 1); | |
1225 | edp_ctrl_irq_enable(ctrl, 1); | |
1226 | } | |
1227 | ||
1228 | ret = drm_dp_link_probe(ctrl->drm_aux, &ctrl->dp_link); | |
1229 | if (ret) { | |
1230 | pr_err("%s: read dpcd cap failed, %d\n", __func__, ret); | |
1231 | goto disable_ret; | |
1232 | } | |
1233 | ||
1234 | /* Initialize link rate as panel max link rate */ | |
1235 | ctrl->link_rate = drm_dp_link_rate_to_bw_code(ctrl->dp_link.rate); | |
1236 | ||
1237 | ctrl->edid = drm_get_edid(connector, &ctrl->drm_aux->ddc); | |
1238 | if (!ctrl->edid) { | |
1239 | pr_err("%s: edid read fail\n", __func__); | |
1240 | goto disable_ret; | |
1241 | } | |
1242 | ||
1243 | if (edid) | |
1244 | *edid = ctrl->edid; | |
1245 | ||
1246 | disable_ret: | |
1247 | if (!ctrl->power_on) { | |
1248 | edp_ctrl_irq_enable(ctrl, 0); | |
1249 | edp_ctrl_phy_aux_enable(ctrl, 0); | |
1250 | } | |
1251 | unlock_ret: | |
1252 | mutex_unlock(&ctrl->dev_mutex); | |
1253 | return ret; | |
1254 | } | |
1255 | ||
1256 | int msm_edp_ctrl_timing_cfg(struct edp_ctrl *ctrl, | |
1257 | const struct drm_display_mode *mode, | |
1258 | const struct drm_display_info *info) | |
1259 | { | |
1260 | u32 hstart_from_sync, vstart_from_sync; | |
1261 | u32 data; | |
1262 | int ret = 0; | |
1263 | ||
1264 | mutex_lock(&ctrl->dev_mutex); | |
1265 | /* | |
1266 | * Need to keep color depth, pixel rate and | |
1267 | * interlaced information in ctrl context | |
1268 | */ | |
1269 | ctrl->color_depth = info->bpc; | |
1270 | ctrl->pixel_rate = mode->clock; | |
1271 | ctrl->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); | |
1272 | ||
1273 | /* Fill initial link config based on passed in timing */ | |
1274 | edp_fill_link_cfg(ctrl); | |
1275 | ||
1276 | if (edp_clk_enable(ctrl, EDP_CLK_MASK_AHB)) { | |
1277 | pr_err("%s, fail to prepare enable ahb clk\n", __func__); | |
1278 | ret = -EINVAL; | |
1279 | goto unlock_ret; | |
1280 | } | |
1281 | edp_clock_synchrous(ctrl, 1); | |
1282 | ||
1283 | /* Configure eDP timing to HW */ | |
1284 | edp_write(ctrl->base + REG_EDP_TOTAL_HOR_VER, | |
1285 | EDP_TOTAL_HOR_VER_HORIZ(mode->htotal) | | |
1286 | EDP_TOTAL_HOR_VER_VERT(mode->vtotal)); | |
1287 | ||
1288 | vstart_from_sync = mode->vtotal - mode->vsync_start; | |
1289 | hstart_from_sync = mode->htotal - mode->hsync_start; | |
1290 | edp_write(ctrl->base + REG_EDP_START_HOR_VER_FROM_SYNC, | |
1291 | EDP_START_HOR_VER_FROM_SYNC_HORIZ(hstart_from_sync) | | |
1292 | EDP_START_HOR_VER_FROM_SYNC_VERT(vstart_from_sync)); | |
1293 | ||
1294 | data = EDP_HSYNC_VSYNC_WIDTH_POLARITY_VERT( | |
1295 | mode->vsync_end - mode->vsync_start); | |
1296 | data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_HORIZ( | |
1297 | mode->hsync_end - mode->hsync_start); | |
1298 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | |
1299 | data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_NVSYNC; | |
1300 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | |
1301 | data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_NHSYNC; | |
1302 | edp_write(ctrl->base + REG_EDP_HSYNC_VSYNC_WIDTH_POLARITY, data); | |
1303 | ||
1304 | edp_write(ctrl->base + REG_EDP_ACTIVE_HOR_VER, | |
1305 | EDP_ACTIVE_HOR_VER_HORIZ(mode->hdisplay) | | |
1306 | EDP_ACTIVE_HOR_VER_VERT(mode->vdisplay)); | |
1307 | ||
1308 | edp_clk_disable(ctrl, EDP_CLK_MASK_AHB); | |
1309 | ||
1310 | unlock_ret: | |
1311 | mutex_unlock(&ctrl->dev_mutex); | |
1312 | return ret; | |
1313 | } | |
1314 | ||
1315 | bool msm_edp_ctrl_pixel_clock_valid(struct edp_ctrl *ctrl, | |
1316 | u32 pixel_rate, u32 *pm, u32 *pn) | |
1317 | { | |
1318 | const struct edp_pixel_clk_div *divs; | |
1319 | u32 err = 1; /* 1% error tolerance */ | |
1320 | u32 clk_err; | |
1321 | int i; | |
1322 | ||
1323 | if (ctrl->link_rate == DP_LINK_BW_1_62) { | |
1324 | divs = clk_divs[0]; | |
1325 | } else if (ctrl->link_rate == DP_LINK_BW_2_7) { | |
1326 | divs = clk_divs[1]; | |
1327 | } else { | |
1328 | pr_err("%s: Invalid link rate,%d\n", __func__, ctrl->link_rate); | |
1329 | return false; | |
1330 | } | |
1331 | ||
1332 | for (i = 0; i < EDP_PIXEL_CLK_NUM; i++) { | |
1333 | clk_err = abs(divs[i].rate - pixel_rate); | |
1334 | if ((divs[i].rate * err / 100) >= clk_err) { | |
1335 | if (pm) | |
1336 | *pm = divs[i].m; | |
1337 | if (pn) | |
1338 | *pn = divs[i].n; | |
1339 | return true; | |
1340 | } | |
1341 | } | |
1342 | ||
1343 | DBG("pixel clock %d(kHz) not supported", pixel_rate); | |
1344 | ||
1345 | return false; | |
1346 | } | |
1347 |