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