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