]>
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 | ||
89ae3d3b | 376 | ctrl->panel_hpd_gpio = devm_gpiod_get(dev, "panel-hpd", GPIOD_IN); |
ab5b0107 HL |
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 | ||
89ae3d3b | 384 | ctrl->panel_en_gpio = devm_gpiod_get(dev, "panel-en", GPIOD_OUT_LOW); |
ab5b0107 HL |
385 | if (IS_ERR(ctrl->panel_en_gpio)) { |
386 | ret = PTR_ERR(ctrl->panel_en_gpio); | |
387 | ctrl->panel_en_gpio = NULL; | |
388 | pr_err("%s: cannot get panel-en-gpios, %d\n", __func__, ret); | |
389 | return ret; | |
390 | } | |
391 | ||
ab5b0107 HL |
392 | DBG("gpio on"); |
393 | ||
394 | return 0; | |
395 | } | |
396 | ||
397 | static void edp_ctrl_irq_enable(struct edp_ctrl *ctrl, int enable) | |
398 | { | |
399 | unsigned long flags; | |
400 | ||
401 | DBG("%d", enable); | |
402 | spin_lock_irqsave(&ctrl->irq_lock, flags); | |
403 | if (enable) { | |
404 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, EDP_INTR_MASK1); | |
405 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, EDP_INTR_MASK2); | |
406 | } else { | |
407 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, 0x0); | |
408 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, 0x0); | |
409 | } | |
410 | spin_unlock_irqrestore(&ctrl->irq_lock, flags); | |
411 | DBG("exit"); | |
412 | } | |
413 | ||
414 | static void edp_fill_link_cfg(struct edp_ctrl *ctrl) | |
415 | { | |
416 | u32 prate; | |
417 | u32 lrate; | |
418 | u32 bpp; | |
419 | u8 max_lane = ctrl->dp_link.num_lanes; | |
420 | u8 lane; | |
421 | ||
422 | prate = ctrl->pixel_rate; | |
423 | bpp = ctrl->color_depth * 3; | |
424 | ||
425 | /* | |
426 | * By default, use the maximum link rate and minimum lane count, | |
427 | * so that we can do rate down shift during link training. | |
428 | */ | |
429 | ctrl->link_rate = drm_dp_link_rate_to_bw_code(ctrl->dp_link.rate); | |
430 | ||
431 | prate *= bpp; | |
432 | prate /= 8; /* in kByte */ | |
433 | ||
434 | lrate = 270000; /* in kHz */ | |
435 | lrate *= ctrl->link_rate; | |
436 | lrate /= 10; /* in kByte, 10 bits --> 8 bits */ | |
437 | ||
438 | for (lane = 1; lane <= max_lane; lane <<= 1) { | |
439 | if (lrate >= prate) | |
440 | break; | |
441 | lrate <<= 1; | |
442 | } | |
443 | ||
444 | ctrl->lane_cnt = lane; | |
445 | DBG("rate=%d lane=%d", ctrl->link_rate, ctrl->lane_cnt); | |
446 | } | |
447 | ||
ab5b0107 HL |
448 | static void edp_config_ctrl(struct edp_ctrl *ctrl) |
449 | { | |
450 | u32 data; | |
451 | enum edp_color_depth depth; | |
452 | ||
453 | data = EDP_CONFIGURATION_CTRL_LANES(ctrl->lane_cnt - 1); | |
454 | ||
455 | if (ctrl->dp_link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) | |
456 | data |= EDP_CONFIGURATION_CTRL_ENHANCED_FRAMING; | |
457 | ||
458 | depth = EDP_6BIT; | |
459 | if (ctrl->color_depth == 8) | |
460 | depth = EDP_8BIT; | |
461 | ||
462 | data |= EDP_CONFIGURATION_CTRL_COLOR(depth); | |
463 | ||
464 | if (!ctrl->interlaced) /* progressive */ | |
465 | data |= EDP_CONFIGURATION_CTRL_PROGRESSIVE; | |
466 | ||
467 | data |= (EDP_CONFIGURATION_CTRL_SYNC_CLK | | |
468 | EDP_CONFIGURATION_CTRL_STATIC_MVID); | |
469 | ||
470 | edp_write(ctrl->base + REG_EDP_CONFIGURATION_CTRL, data); | |
471 | } | |
472 | ||
473 | static void edp_state_ctrl(struct edp_ctrl *ctrl, u32 state) | |
474 | { | |
475 | edp_write(ctrl->base + REG_EDP_STATE_CTRL, state); | |
476 | /* Make sure H/W status is set */ | |
477 | wmb(); | |
478 | } | |
479 | ||
480 | static int edp_lane_set_write(struct edp_ctrl *ctrl, | |
481 | u8 voltage_level, u8 pre_emphasis_level) | |
482 | { | |
483 | int i; | |
484 | u8 buf[4]; | |
485 | ||
486 | if (voltage_level >= DPCD_LINK_VOLTAGE_MAX) | |
487 | voltage_level |= 0x04; | |
488 | ||
489 | if (pre_emphasis_level >= DPCD_LINK_PRE_EMPHASIS_MAX) | |
490 | pre_emphasis_level |= 0x04; | |
491 | ||
492 | pre_emphasis_level <<= 3; | |
493 | ||
494 | for (i = 0; i < 4; i++) | |
495 | buf[i] = voltage_level | pre_emphasis_level; | |
496 | ||
497 | DBG("%s: p|v=0x%x", __func__, voltage_level | pre_emphasis_level); | |
498 | if (drm_dp_dpcd_write(ctrl->drm_aux, 0x103, buf, 4) < 4) { | |
499 | pr_err("%s: Set sw/pe to panel failed\n", __func__); | |
500 | return -ENOLINK; | |
501 | } | |
502 | ||
503 | return 0; | |
504 | } | |
505 | ||
506 | static int edp_train_pattern_set_write(struct edp_ctrl *ctrl, u8 pattern) | |
507 | { | |
508 | u8 p = pattern; | |
509 | ||
510 | DBG("pattern=%x", p); | |
511 | if (drm_dp_dpcd_write(ctrl->drm_aux, | |
512 | DP_TRAINING_PATTERN_SET, &p, 1) < 1) { | |
513 | pr_err("%s: Set training pattern to panel failed\n", __func__); | |
514 | return -ENOLINK; | |
515 | } | |
516 | ||
517 | return 0; | |
518 | } | |
519 | ||
520 | static void edp_sink_train_set_adjust(struct edp_ctrl *ctrl, | |
521 | const u8 *link_status) | |
522 | { | |
523 | int i; | |
524 | u8 max = 0; | |
525 | u8 data; | |
526 | ||
527 | /* use the max level across lanes */ | |
528 | for (i = 0; i < ctrl->lane_cnt; i++) { | |
529 | data = drm_dp_get_adjust_request_voltage(link_status, i); | |
530 | DBG("lane=%d req_voltage_swing=0x%x", i, data); | |
531 | if (max < data) | |
532 | max = data; | |
533 | } | |
534 | ||
535 | ctrl->v_level = max >> DP_TRAIN_VOLTAGE_SWING_SHIFT; | |
536 | ||
537 | /* use the max level across lanes */ | |
538 | max = 0; | |
539 | for (i = 0; i < ctrl->lane_cnt; i++) { | |
540 | data = drm_dp_get_adjust_request_pre_emphasis(link_status, i); | |
541 | DBG("lane=%d req_pre_emphasis=0x%x", i, data); | |
542 | if (max < data) | |
543 | max = data; | |
544 | } | |
545 | ||
546 | ctrl->p_level = max >> DP_TRAIN_PRE_EMPHASIS_SHIFT; | |
547 | DBG("v_level=%d, p_level=%d", ctrl->v_level, ctrl->p_level); | |
548 | } | |
549 | ||
550 | static void edp_host_train_set(struct edp_ctrl *ctrl, u32 train) | |
551 | { | |
552 | int cnt = 10; | |
553 | u32 data; | |
554 | u32 shift = train - 1; | |
555 | ||
556 | DBG("train=%d", train); | |
557 | ||
558 | edp_state_ctrl(ctrl, EDP_STATE_CTRL_TRAIN_PATTERN_1 << shift); | |
559 | while (--cnt) { | |
560 | data = edp_read(ctrl->base + REG_EDP_MAINLINK_READY); | |
561 | if (data & (EDP_MAINLINK_READY_TRAIN_PATTERN_1_READY << shift)) | |
562 | break; | |
563 | } | |
564 | ||
565 | if (cnt == 0) | |
566 | pr_err("%s: set link_train=%d failed\n", __func__, train); | |
567 | } | |
568 | ||
569 | static const u8 vm_pre_emphasis[4][4] = { | |
570 | {0x03, 0x06, 0x09, 0x0C}, /* pe0, 0 db */ | |
571 | {0x03, 0x06, 0x09, 0xFF}, /* pe1, 3.5 db */ | |
572 | {0x03, 0x06, 0xFF, 0xFF}, /* pe2, 6.0 db */ | |
573 | {0x03, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */ | |
574 | }; | |
575 | ||
576 | /* voltage swing, 0.2v and 1.0v are not support */ | |
577 | static const u8 vm_voltage_swing[4][4] = { | |
578 | {0x14, 0x18, 0x1A, 0x1E}, /* sw0, 0.4v */ | |
579 | {0x18, 0x1A, 0x1E, 0xFF}, /* sw1, 0.6 v */ | |
580 | {0x1A, 0x1E, 0xFF, 0xFF}, /* sw1, 0.8 v */ | |
581 | {0x1E, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */ | |
582 | }; | |
583 | ||
584 | static int edp_voltage_pre_emphasise_set(struct edp_ctrl *ctrl) | |
585 | { | |
586 | u32 value0; | |
587 | u32 value1; | |
588 | ||
589 | DBG("v=%d p=%d", ctrl->v_level, ctrl->p_level); | |
590 | ||
591 | value0 = vm_pre_emphasis[(int)(ctrl->v_level)][(int)(ctrl->p_level)]; | |
592 | value1 = vm_voltage_swing[(int)(ctrl->v_level)][(int)(ctrl->p_level)]; | |
593 | ||
594 | /* Configure host and panel only if both values are allowed */ | |
595 | if (value0 != 0xFF && value1 != 0xFF) { | |
596 | msm_edp_phy_vm_pe_cfg(ctrl->phy, value0, value1); | |
597 | return edp_lane_set_write(ctrl, ctrl->v_level, ctrl->p_level); | |
598 | } | |
599 | ||
600 | return -EINVAL; | |
601 | } | |
602 | ||
603 | static int edp_start_link_train_1(struct edp_ctrl *ctrl) | |
604 | { | |
605 | u8 link_status[DP_LINK_STATUS_SIZE]; | |
606 | u8 old_v_level; | |
607 | int tries; | |
608 | int ret; | |
609 | int rlen; | |
610 | ||
611 | DBG(""); | |
612 | ||
613 | edp_host_train_set(ctrl, DP_TRAINING_PATTERN_1); | |
614 | ret = edp_voltage_pre_emphasise_set(ctrl); | |
615 | if (ret) | |
616 | return ret; | |
617 | ret = edp_train_pattern_set_write(ctrl, | |
618 | DP_TRAINING_PATTERN_1 | DP_RECOVERED_CLOCK_OUT_EN); | |
619 | if (ret) | |
620 | return ret; | |
621 | ||
622 | tries = 0; | |
623 | old_v_level = ctrl->v_level; | |
624 | while (1) { | |
625 | drm_dp_link_train_clock_recovery_delay(ctrl->dpcd); | |
626 | ||
627 | rlen = drm_dp_dpcd_read_link_status(ctrl->drm_aux, link_status); | |
628 | if (rlen < DP_LINK_STATUS_SIZE) { | |
629 | pr_err("%s: read link status failed\n", __func__); | |
630 | return -ENOLINK; | |
631 | } | |
632 | if (drm_dp_clock_recovery_ok(link_status, ctrl->lane_cnt)) { | |
633 | ret = 0; | |
634 | break; | |
635 | } | |
636 | ||
637 | if (ctrl->v_level == DPCD_LINK_VOLTAGE_MAX) { | |
638 | ret = -1; | |
639 | break; | |
640 | } | |
641 | ||
642 | if (old_v_level == ctrl->v_level) { | |
643 | tries++; | |
644 | if (tries >= 5) { | |
645 | ret = -1; | |
646 | break; | |
647 | } | |
648 | } else { | |
649 | tries = 0; | |
650 | old_v_level = ctrl->v_level; | |
651 | } | |
652 | ||
653 | edp_sink_train_set_adjust(ctrl, link_status); | |
654 | ret = edp_voltage_pre_emphasise_set(ctrl); | |
655 | if (ret) | |
656 | return ret; | |
657 | } | |
658 | ||
659 | return ret; | |
660 | } | |
661 | ||
662 | static int edp_start_link_train_2(struct edp_ctrl *ctrl) | |
663 | { | |
664 | u8 link_status[DP_LINK_STATUS_SIZE]; | |
665 | int tries = 0; | |
666 | int ret; | |
667 | int rlen; | |
668 | ||
669 | DBG(""); | |
670 | ||
671 | edp_host_train_set(ctrl, DP_TRAINING_PATTERN_2); | |
672 | ret = edp_voltage_pre_emphasise_set(ctrl); | |
673 | if (ret) | |
674 | return ret; | |
675 | ||
676 | ret = edp_train_pattern_set_write(ctrl, | |
677 | DP_TRAINING_PATTERN_2 | DP_RECOVERED_CLOCK_OUT_EN); | |
678 | if (ret) | |
679 | return ret; | |
680 | ||
681 | while (1) { | |
682 | drm_dp_link_train_channel_eq_delay(ctrl->dpcd); | |
683 | ||
684 | rlen = drm_dp_dpcd_read_link_status(ctrl->drm_aux, link_status); | |
685 | if (rlen < DP_LINK_STATUS_SIZE) { | |
686 | pr_err("%s: read link status failed\n", __func__); | |
687 | return -ENOLINK; | |
688 | } | |
689 | if (drm_dp_channel_eq_ok(link_status, ctrl->lane_cnt)) { | |
690 | ret = 0; | |
691 | break; | |
692 | } | |
693 | ||
694 | tries++; | |
695 | if (tries > 10) { | |
696 | ret = -1; | |
697 | break; | |
698 | } | |
699 | ||
700 | edp_sink_train_set_adjust(ctrl, link_status); | |
701 | ret = edp_voltage_pre_emphasise_set(ctrl); | |
702 | if (ret) | |
703 | return ret; | |
704 | } | |
705 | ||
706 | return ret; | |
707 | } | |
708 | ||
709 | static int edp_link_rate_down_shift(struct edp_ctrl *ctrl) | |
710 | { | |
711 | u32 prate, lrate, bpp; | |
712 | u8 rate, lane, max_lane; | |
713 | int changed = 0; | |
714 | ||
715 | rate = ctrl->link_rate; | |
716 | lane = ctrl->lane_cnt; | |
717 | max_lane = ctrl->dp_link.num_lanes; | |
718 | ||
719 | bpp = ctrl->color_depth * 3; | |
720 | prate = ctrl->pixel_rate; | |
721 | prate *= bpp; | |
722 | prate /= 8; /* in kByte */ | |
723 | ||
724 | if (rate > DP_LINK_BW_1_62 && rate <= EDP_LINK_BW_MAX) { | |
725 | rate -= 4; /* reduce rate */ | |
726 | changed++; | |
727 | } | |
728 | ||
729 | if (changed) { | |
730 | if (lane >= 1 && lane < max_lane) | |
731 | lane <<= 1; /* increase lane */ | |
732 | ||
733 | lrate = 270000; /* in kHz */ | |
734 | lrate *= rate; | |
735 | lrate /= 10; /* kByte, 10 bits --> 8 bits */ | |
736 | lrate *= lane; | |
737 | ||
738 | DBG("new lrate=%u prate=%u(kHz) rate=%d lane=%d p=%u b=%d", | |
739 | lrate, prate, rate, lane, | |
740 | ctrl->pixel_rate, | |
741 | bpp); | |
742 | ||
743 | if (lrate > prate) { | |
744 | ctrl->link_rate = rate; | |
745 | ctrl->lane_cnt = lane; | |
746 | DBG("new rate=%d %d", rate, lane); | |
747 | return 0; | |
748 | } | |
749 | } | |
750 | ||
751 | return -EINVAL; | |
752 | } | |
753 | ||
754 | static int edp_clear_training_pattern(struct edp_ctrl *ctrl) | |
755 | { | |
756 | int ret; | |
757 | ||
758 | ret = edp_train_pattern_set_write(ctrl, 0); | |
759 | ||
760 | drm_dp_link_train_channel_eq_delay(ctrl->dpcd); | |
761 | ||
762 | return ret; | |
763 | } | |
764 | ||
765 | static int edp_do_link_train(struct edp_ctrl *ctrl) | |
766 | { | |
767 | int ret; | |
768 | struct drm_dp_link dp_link; | |
769 | ||
770 | DBG(""); | |
771 | /* | |
772 | * Set the current link rate and lane cnt to panel. They may have been | |
773 | * adjusted and the values are different from them in DPCD CAP | |
774 | */ | |
775 | dp_link.num_lanes = ctrl->lane_cnt; | |
776 | dp_link.rate = drm_dp_bw_code_to_link_rate(ctrl->link_rate); | |
777 | dp_link.capabilities = ctrl->dp_link.capabilities; | |
778 | if (drm_dp_link_configure(ctrl->drm_aux, &dp_link) < 0) | |
779 | return EDP_TRAIN_FAIL; | |
780 | ||
781 | ctrl->v_level = 0; /* start from default level */ | |
782 | ctrl->p_level = 0; | |
783 | ||
784 | edp_state_ctrl(ctrl, 0); | |
785 | if (edp_clear_training_pattern(ctrl)) | |
786 | return EDP_TRAIN_FAIL; | |
787 | ||
788 | ret = edp_start_link_train_1(ctrl); | |
789 | if (ret < 0) { | |
790 | if (edp_link_rate_down_shift(ctrl) == 0) { | |
791 | DBG("link reconfig"); | |
792 | ret = EDP_TRAIN_RECONFIG; | |
793 | goto clear; | |
794 | } else { | |
795 | pr_err("%s: Training 1 failed", __func__); | |
796 | ret = EDP_TRAIN_FAIL; | |
797 | goto clear; | |
798 | } | |
799 | } | |
800 | DBG("Training 1 completed successfully"); | |
801 | ||
802 | edp_state_ctrl(ctrl, 0); | |
803 | if (edp_clear_training_pattern(ctrl)) | |
804 | return EDP_TRAIN_FAIL; | |
805 | ||
806 | ret = edp_start_link_train_2(ctrl); | |
807 | if (ret < 0) { | |
808 | if (edp_link_rate_down_shift(ctrl) == 0) { | |
809 | DBG("link reconfig"); | |
810 | ret = EDP_TRAIN_RECONFIG; | |
811 | goto clear; | |
812 | } else { | |
813 | pr_err("%s: Training 2 failed", __func__); | |
814 | ret = EDP_TRAIN_FAIL; | |
815 | goto clear; | |
816 | } | |
817 | } | |
818 | DBG("Training 2 completed successfully"); | |
819 | ||
820 | edp_state_ctrl(ctrl, EDP_STATE_CTRL_SEND_VIDEO); | |
821 | clear: | |
822 | edp_clear_training_pattern(ctrl); | |
823 | ||
824 | return ret; | |
825 | } | |
826 | ||
827 | static void edp_clock_synchrous(struct edp_ctrl *ctrl, int sync) | |
828 | { | |
829 | u32 data; | |
830 | enum edp_color_depth depth; | |
831 | ||
832 | data = edp_read(ctrl->base + REG_EDP_MISC1_MISC0); | |
833 | ||
834 | if (sync) | |
835 | data |= EDP_MISC1_MISC0_SYNC; | |
836 | else | |
837 | data &= ~EDP_MISC1_MISC0_SYNC; | |
838 | ||
839 | /* only legacy rgb mode supported */ | |
840 | depth = EDP_6BIT; /* Default */ | |
841 | if (ctrl->color_depth == 8) | |
842 | depth = EDP_8BIT; | |
843 | else if (ctrl->color_depth == 10) | |
844 | depth = EDP_10BIT; | |
845 | else if (ctrl->color_depth == 12) | |
846 | depth = EDP_12BIT; | |
847 | else if (ctrl->color_depth == 16) | |
848 | depth = EDP_16BIT; | |
849 | ||
850 | data |= EDP_MISC1_MISC0_COLOR(depth); | |
851 | ||
852 | edp_write(ctrl->base + REG_EDP_MISC1_MISC0, data); | |
853 | } | |
854 | ||
855 | static int edp_sw_mvid_nvid(struct edp_ctrl *ctrl, u32 m, u32 n) | |
856 | { | |
857 | u32 n_multi, m_multi = 5; | |
858 | ||
859 | if (ctrl->link_rate == DP_LINK_BW_1_62) { | |
860 | n_multi = 1; | |
861 | } else if (ctrl->link_rate == DP_LINK_BW_2_7) { | |
862 | n_multi = 2; | |
863 | } else { | |
864 | pr_err("%s: Invalid link rate, %d\n", __func__, | |
865 | ctrl->link_rate); | |
866 | return -EINVAL; | |
867 | } | |
868 | ||
869 | edp_write(ctrl->base + REG_EDP_SOFTWARE_MVID, m * m_multi); | |
870 | edp_write(ctrl->base + REG_EDP_SOFTWARE_NVID, n * n_multi); | |
871 | ||
872 | return 0; | |
873 | } | |
874 | ||
875 | static void edp_mainlink_ctrl(struct edp_ctrl *ctrl, int enable) | |
876 | { | |
877 | u32 data = 0; | |
878 | ||
879 | edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, EDP_MAINLINK_CTRL_RESET); | |
880 | /* Make sure fully reset */ | |
881 | wmb(); | |
882 | usleep_range(500, 1000); | |
883 | ||
884 | if (enable) | |
885 | data |= EDP_MAINLINK_CTRL_ENABLE; | |
886 | ||
887 | edp_write(ctrl->base + REG_EDP_MAINLINK_CTRL, data); | |
888 | } | |
889 | ||
890 | static void edp_ctrl_phy_aux_enable(struct edp_ctrl *ctrl, int enable) | |
891 | { | |
892 | if (enable) { | |
893 | edp_regulator_enable(ctrl); | |
894 | edp_clk_enable(ctrl, EDP_CLK_MASK_AUX_CHAN); | |
895 | msm_edp_phy_ctrl(ctrl->phy, 1); | |
896 | msm_edp_aux_ctrl(ctrl->aux, 1); | |
897 | gpiod_set_value(ctrl->panel_en_gpio, 1); | |
898 | } else { | |
899 | gpiod_set_value(ctrl->panel_en_gpio, 0); | |
900 | msm_edp_aux_ctrl(ctrl->aux, 0); | |
901 | msm_edp_phy_ctrl(ctrl->phy, 0); | |
902 | edp_clk_disable(ctrl, EDP_CLK_MASK_AUX_CHAN); | |
903 | edp_regulator_disable(ctrl); | |
904 | } | |
905 | } | |
906 | ||
907 | static void edp_ctrl_link_enable(struct edp_ctrl *ctrl, int enable) | |
908 | { | |
909 | u32 m, n; | |
910 | ||
911 | if (enable) { | |
912 | /* Enable link channel clocks */ | |
913 | edp_clk_enable(ctrl, EDP_CLK_MASK_LINK_CHAN); | |
914 | ||
915 | msm_edp_phy_lane_power_ctrl(ctrl->phy, true, ctrl->lane_cnt); | |
916 | ||
917 | msm_edp_phy_vm_pe_init(ctrl->phy); | |
918 | ||
919 | /* Make sure phy is programed */ | |
920 | wmb(); | |
921 | msm_edp_phy_ready(ctrl->phy); | |
922 | ||
923 | edp_config_ctrl(ctrl); | |
924 | msm_edp_ctrl_pixel_clock_valid(ctrl, ctrl->pixel_rate, &m, &n); | |
925 | edp_sw_mvid_nvid(ctrl, m, n); | |
926 | edp_mainlink_ctrl(ctrl, 1); | |
927 | } else { | |
928 | edp_mainlink_ctrl(ctrl, 0); | |
929 | ||
930 | msm_edp_phy_lane_power_ctrl(ctrl->phy, false, 0); | |
931 | edp_clk_disable(ctrl, EDP_CLK_MASK_LINK_CHAN); | |
932 | } | |
933 | } | |
934 | ||
935 | static int edp_ctrl_training(struct edp_ctrl *ctrl) | |
936 | { | |
937 | int ret; | |
938 | ||
939 | /* Do link training only when power is on */ | |
940 | if (!ctrl->power_on) | |
941 | return -EINVAL; | |
942 | ||
943 | train_start: | |
944 | ret = edp_do_link_train(ctrl); | |
945 | if (ret == EDP_TRAIN_RECONFIG) { | |
946 | /* Re-configure main link */ | |
947 | edp_ctrl_irq_enable(ctrl, 0); | |
948 | edp_ctrl_link_enable(ctrl, 0); | |
949 | msm_edp_phy_ctrl(ctrl->phy, 0); | |
950 | ||
951 | /* Make sure link is fully disabled */ | |
952 | wmb(); | |
953 | usleep_range(500, 1000); | |
954 | ||
955 | msm_edp_phy_ctrl(ctrl->phy, 1); | |
956 | edp_ctrl_link_enable(ctrl, 1); | |
957 | edp_ctrl_irq_enable(ctrl, 1); | |
958 | goto train_start; | |
959 | } | |
960 | ||
961 | return ret; | |
962 | } | |
963 | ||
964 | static void edp_ctrl_on_worker(struct work_struct *work) | |
965 | { | |
966 | struct edp_ctrl *ctrl = container_of( | |
967 | work, struct edp_ctrl, on_work); | |
968 | int ret; | |
969 | ||
970 | mutex_lock(&ctrl->dev_mutex); | |
971 | ||
972 | if (ctrl->power_on) { | |
973 | DBG("already on"); | |
974 | goto unlock_ret; | |
975 | } | |
976 | ||
977 | edp_ctrl_phy_aux_enable(ctrl, 1); | |
978 | edp_ctrl_link_enable(ctrl, 1); | |
979 | ||
980 | edp_ctrl_irq_enable(ctrl, 1); | |
a5ec308a | 981 | ret = drm_dp_link_power_up(ctrl->drm_aux, &ctrl->dp_link); |
ab5b0107 HL |
982 | if (ret) |
983 | goto fail; | |
984 | ||
985 | ctrl->power_on = true; | |
986 | ||
987 | /* Start link training */ | |
988 | ret = edp_ctrl_training(ctrl); | |
989 | if (ret != EDP_TRAIN_SUCCESS) | |
990 | goto fail; | |
991 | ||
992 | DBG("DONE"); | |
993 | goto unlock_ret; | |
994 | ||
995 | fail: | |
996 | edp_ctrl_irq_enable(ctrl, 0); | |
997 | edp_ctrl_link_enable(ctrl, 0); | |
998 | edp_ctrl_phy_aux_enable(ctrl, 0); | |
999 | ctrl->power_on = false; | |
1000 | unlock_ret: | |
1001 | mutex_unlock(&ctrl->dev_mutex); | |
1002 | } | |
1003 | ||
1004 | static void edp_ctrl_off_worker(struct work_struct *work) | |
1005 | { | |
1006 | struct edp_ctrl *ctrl = container_of( | |
1007 | work, struct edp_ctrl, off_work); | |
a51d01f0 | 1008 | unsigned long time_left; |
ab5b0107 HL |
1009 | |
1010 | mutex_lock(&ctrl->dev_mutex); | |
1011 | ||
1012 | if (!ctrl->power_on) { | |
1013 | DBG("already off"); | |
1014 | goto unlock_ret; | |
1015 | } | |
1016 | ||
1017 | reinit_completion(&ctrl->idle_comp); | |
1018 | edp_state_ctrl(ctrl, EDP_STATE_CTRL_PUSH_IDLE); | |
1019 | ||
a51d01f0 | 1020 | time_left = wait_for_completion_timeout(&ctrl->idle_comp, |
ab5b0107 | 1021 | msecs_to_jiffies(500)); |
c6d0baf1 | 1022 | if (!time_left) |
0c076bff | 1023 | DBG("%s: idle pattern timedout\n", __func__); |
ab5b0107 HL |
1024 | |
1025 | edp_state_ctrl(ctrl, 0); | |
1026 | ||
a5ec308a | 1027 | drm_dp_link_power_down(ctrl->drm_aux, &ctrl->dp_link); |
ab5b0107 HL |
1028 | |
1029 | edp_ctrl_irq_enable(ctrl, 0); | |
1030 | ||
1031 | edp_ctrl_link_enable(ctrl, 0); | |
1032 | ||
1033 | edp_ctrl_phy_aux_enable(ctrl, 0); | |
1034 | ||
1035 | ctrl->power_on = false; | |
1036 | ||
1037 | unlock_ret: | |
1038 | mutex_unlock(&ctrl->dev_mutex); | |
1039 | } | |
1040 | ||
1041 | irqreturn_t msm_edp_ctrl_irq(struct edp_ctrl *ctrl) | |
1042 | { | |
1043 | u32 isr1, isr2, mask1, mask2; | |
1044 | u32 ack; | |
1045 | ||
1046 | DBG(""); | |
1047 | spin_lock(&ctrl->irq_lock); | |
1048 | isr1 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_1); | |
1049 | isr2 = edp_read(ctrl->base + REG_EDP_INTERRUPT_REG_2); | |
1050 | ||
1051 | mask1 = isr1 & EDP_INTR_MASK1; | |
1052 | mask2 = isr2 & EDP_INTR_MASK2; | |
1053 | ||
1054 | isr1 &= ~mask1; /* remove masks bit */ | |
1055 | isr2 &= ~mask2; | |
1056 | ||
1057 | DBG("isr=%x mask=%x isr2=%x mask2=%x", | |
1058 | isr1, mask1, isr2, mask2); | |
1059 | ||
1060 | ack = isr1 & EDP_INTR_STATUS1; | |
1061 | ack <<= 1; /* ack bits */ | |
1062 | ack |= mask1; | |
1063 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_1, ack); | |
1064 | ||
1065 | ack = isr2 & EDP_INTR_STATUS2; | |
1066 | ack <<= 1; /* ack bits */ | |
1067 | ack |= mask2; | |
1068 | edp_write(ctrl->base + REG_EDP_INTERRUPT_REG_2, ack); | |
1069 | spin_unlock(&ctrl->irq_lock); | |
1070 | ||
1071 | if (isr1 & EDP_INTERRUPT_REG_1_HPD) | |
1072 | DBG("edp_hpd"); | |
1073 | ||
1074 | if (isr2 & EDP_INTERRUPT_REG_2_READY_FOR_VIDEO) | |
1075 | DBG("edp_video_ready"); | |
1076 | ||
1077 | if (isr2 & EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT) { | |
1078 | DBG("idle_patterns_sent"); | |
1079 | complete(&ctrl->idle_comp); | |
1080 | } | |
1081 | ||
1082 | msm_edp_aux_irq(ctrl->aux, isr1); | |
1083 | ||
1084 | return IRQ_HANDLED; | |
1085 | } | |
1086 | ||
1087 | void msm_edp_ctrl_power(struct edp_ctrl *ctrl, bool on) | |
1088 | { | |
1089 | if (on) | |
1090 | queue_work(ctrl->workqueue, &ctrl->on_work); | |
1091 | else | |
1092 | queue_work(ctrl->workqueue, &ctrl->off_work); | |
1093 | } | |
1094 | ||
1095 | int msm_edp_ctrl_init(struct msm_edp *edp) | |
1096 | { | |
1097 | struct edp_ctrl *ctrl = NULL; | |
1098 | struct device *dev = &edp->pdev->dev; | |
1099 | int ret; | |
1100 | ||
1101 | if (!edp) { | |
1102 | pr_err("%s: edp is NULL!\n", __func__); | |
1103 | return -EINVAL; | |
1104 | } | |
1105 | ||
1106 | ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); | |
1107 | if (!ctrl) | |
1108 | return -ENOMEM; | |
1109 | ||
1110 | edp->ctrl = ctrl; | |
1111 | ctrl->pdev = edp->pdev; | |
1112 | ||
1113 | ctrl->base = msm_ioremap(ctrl->pdev, "edp", "eDP"); | |
1114 | if (IS_ERR(ctrl->base)) | |
1115 | return PTR_ERR(ctrl->base); | |
1116 | ||
1117 | /* Get regulator, clock, gpio, pwm */ | |
1118 | ret = edp_regulator_init(ctrl); | |
1119 | if (ret) { | |
1120 | pr_err("%s:regulator init fail\n", __func__); | |
1121 | return ret; | |
1122 | } | |
1123 | ret = edp_clk_init(ctrl); | |
1124 | if (ret) { | |
1125 | pr_err("%s:clk init fail\n", __func__); | |
1126 | return ret; | |
1127 | } | |
1128 | ret = edp_gpio_config(ctrl); | |
1129 | if (ret) { | |
1130 | pr_err("%s:failed to configure GPIOs: %d", __func__, ret); | |
1131 | return ret; | |
1132 | } | |
1133 | ||
1134 | /* Init aux and phy */ | |
1135 | ctrl->aux = msm_edp_aux_init(dev, ctrl->base, &ctrl->drm_aux); | |
1136 | if (!ctrl->aux || !ctrl->drm_aux) { | |
1137 | pr_err("%s:failed to init aux\n", __func__); | |
6128f1be | 1138 | return -ENOMEM; |
ab5b0107 HL |
1139 | } |
1140 | ||
1141 | ctrl->phy = msm_edp_phy_init(dev, ctrl->base); | |
1142 | if (!ctrl->phy) { | |
1143 | pr_err("%s:failed to init phy\n", __func__); | |
6128f1be | 1144 | ret = -ENOMEM; |
ab5b0107 HL |
1145 | goto err_destory_aux; |
1146 | } | |
1147 | ||
1148 | spin_lock_init(&ctrl->irq_lock); | |
1149 | mutex_init(&ctrl->dev_mutex); | |
1150 | init_completion(&ctrl->idle_comp); | |
1151 | ||
1152 | /* setup workqueue */ | |
1153 | ctrl->workqueue = alloc_ordered_workqueue("edp_drm_work", 0); | |
1154 | INIT_WORK(&ctrl->on_work, edp_ctrl_on_worker); | |
1155 | INIT_WORK(&ctrl->off_work, edp_ctrl_off_worker); | |
1156 | ||
1157 | return 0; | |
1158 | ||
1159 | err_destory_aux: | |
1160 | msm_edp_aux_destroy(dev, ctrl->aux); | |
1161 | ctrl->aux = NULL; | |
1162 | return ret; | |
1163 | } | |
1164 | ||
1165 | void msm_edp_ctrl_destroy(struct edp_ctrl *ctrl) | |
1166 | { | |
1167 | if (!ctrl) | |
1168 | return; | |
1169 | ||
1170 | if (ctrl->workqueue) { | |
1171 | flush_workqueue(ctrl->workqueue); | |
1172 | destroy_workqueue(ctrl->workqueue); | |
1173 | ctrl->workqueue = NULL; | |
1174 | } | |
1175 | ||
1176 | if (ctrl->aux) { | |
1177 | msm_edp_aux_destroy(&ctrl->pdev->dev, ctrl->aux); | |
1178 | ctrl->aux = NULL; | |
1179 | } | |
1180 | ||
1181 | kfree(ctrl->edid); | |
1182 | ctrl->edid = NULL; | |
1183 | ||
1184 | mutex_destroy(&ctrl->dev_mutex); | |
1185 | } | |
1186 | ||
1187 | bool msm_edp_ctrl_panel_connected(struct edp_ctrl *ctrl) | |
1188 | { | |
1189 | mutex_lock(&ctrl->dev_mutex); | |
1190 | DBG("connect status = %d", ctrl->edp_connected); | |
1191 | if (ctrl->edp_connected) { | |
1192 | mutex_unlock(&ctrl->dev_mutex); | |
1193 | return true; | |
1194 | } | |
1195 | ||
1196 | if (!ctrl->power_on) { | |
1197 | edp_ctrl_phy_aux_enable(ctrl, 1); | |
1198 | edp_ctrl_irq_enable(ctrl, 1); | |
1199 | } | |
1200 | ||
1201 | if (drm_dp_dpcd_read(ctrl->drm_aux, DP_DPCD_REV, ctrl->dpcd, | |
1202 | DP_RECEIVER_CAP_SIZE) < DP_RECEIVER_CAP_SIZE) { | |
1203 | pr_err("%s: AUX channel is NOT ready\n", __func__); | |
1204 | memset(ctrl->dpcd, 0, DP_RECEIVER_CAP_SIZE); | |
1205 | } else { | |
1206 | ctrl->edp_connected = true; | |
1207 | } | |
1208 | ||
1209 | if (!ctrl->power_on) { | |
1210 | edp_ctrl_irq_enable(ctrl, 0); | |
1211 | edp_ctrl_phy_aux_enable(ctrl, 0); | |
1212 | } | |
1213 | ||
1214 | DBG("exit: connect status=%d", ctrl->edp_connected); | |
1215 | ||
1216 | mutex_unlock(&ctrl->dev_mutex); | |
1217 | ||
1218 | return ctrl->edp_connected; | |
1219 | } | |
1220 | ||
1221 | int msm_edp_ctrl_get_panel_info(struct edp_ctrl *ctrl, | |
1222 | struct drm_connector *connector, struct edid **edid) | |
1223 | { | |
1224 | int ret = 0; | |
1225 | ||
1226 | mutex_lock(&ctrl->dev_mutex); | |
1227 | ||
1228 | if (ctrl->edid) { | |
1229 | if (edid) { | |
1230 | DBG("Just return edid buffer"); | |
1231 | *edid = ctrl->edid; | |
1232 | } | |
1233 | goto unlock_ret; | |
1234 | } | |
1235 | ||
1236 | if (!ctrl->power_on) { | |
1237 | edp_ctrl_phy_aux_enable(ctrl, 1); | |
1238 | edp_ctrl_irq_enable(ctrl, 1); | |
1239 | } | |
1240 | ||
1241 | ret = drm_dp_link_probe(ctrl->drm_aux, &ctrl->dp_link); | |
1242 | if (ret) { | |
1243 | pr_err("%s: read dpcd cap failed, %d\n", __func__, ret); | |
1244 | goto disable_ret; | |
1245 | } | |
1246 | ||
1247 | /* Initialize link rate as panel max link rate */ | |
1248 | ctrl->link_rate = drm_dp_link_rate_to_bw_code(ctrl->dp_link.rate); | |
1249 | ||
1250 | ctrl->edid = drm_get_edid(connector, &ctrl->drm_aux->ddc); | |
1251 | if (!ctrl->edid) { | |
1252 | pr_err("%s: edid read fail\n", __func__); | |
1253 | goto disable_ret; | |
1254 | } | |
1255 | ||
1256 | if (edid) | |
1257 | *edid = ctrl->edid; | |
1258 | ||
1259 | disable_ret: | |
1260 | if (!ctrl->power_on) { | |
1261 | edp_ctrl_irq_enable(ctrl, 0); | |
1262 | edp_ctrl_phy_aux_enable(ctrl, 0); | |
1263 | } | |
1264 | unlock_ret: | |
1265 | mutex_unlock(&ctrl->dev_mutex); | |
1266 | return ret; | |
1267 | } | |
1268 | ||
1269 | int msm_edp_ctrl_timing_cfg(struct edp_ctrl *ctrl, | |
1270 | const struct drm_display_mode *mode, | |
1271 | const struct drm_display_info *info) | |
1272 | { | |
1273 | u32 hstart_from_sync, vstart_from_sync; | |
1274 | u32 data; | |
1275 | int ret = 0; | |
1276 | ||
1277 | mutex_lock(&ctrl->dev_mutex); | |
1278 | /* | |
1279 | * Need to keep color depth, pixel rate and | |
1280 | * interlaced information in ctrl context | |
1281 | */ | |
1282 | ctrl->color_depth = info->bpc; | |
1283 | ctrl->pixel_rate = mode->clock; | |
1284 | ctrl->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); | |
1285 | ||
1286 | /* Fill initial link config based on passed in timing */ | |
1287 | edp_fill_link_cfg(ctrl); | |
1288 | ||
1289 | if (edp_clk_enable(ctrl, EDP_CLK_MASK_AHB)) { | |
1290 | pr_err("%s, fail to prepare enable ahb clk\n", __func__); | |
1291 | ret = -EINVAL; | |
1292 | goto unlock_ret; | |
1293 | } | |
1294 | edp_clock_synchrous(ctrl, 1); | |
1295 | ||
1296 | /* Configure eDP timing to HW */ | |
1297 | edp_write(ctrl->base + REG_EDP_TOTAL_HOR_VER, | |
1298 | EDP_TOTAL_HOR_VER_HORIZ(mode->htotal) | | |
1299 | EDP_TOTAL_HOR_VER_VERT(mode->vtotal)); | |
1300 | ||
1301 | vstart_from_sync = mode->vtotal - mode->vsync_start; | |
1302 | hstart_from_sync = mode->htotal - mode->hsync_start; | |
1303 | edp_write(ctrl->base + REG_EDP_START_HOR_VER_FROM_SYNC, | |
1304 | EDP_START_HOR_VER_FROM_SYNC_HORIZ(hstart_from_sync) | | |
1305 | EDP_START_HOR_VER_FROM_SYNC_VERT(vstart_from_sync)); | |
1306 | ||
1307 | data = EDP_HSYNC_VSYNC_WIDTH_POLARITY_VERT( | |
1308 | mode->vsync_end - mode->vsync_start); | |
1309 | data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_HORIZ( | |
1310 | mode->hsync_end - mode->hsync_start); | |
1311 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | |
1312 | data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_NVSYNC; | |
1313 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | |
1314 | data |= EDP_HSYNC_VSYNC_WIDTH_POLARITY_NHSYNC; | |
1315 | edp_write(ctrl->base + REG_EDP_HSYNC_VSYNC_WIDTH_POLARITY, data); | |
1316 | ||
1317 | edp_write(ctrl->base + REG_EDP_ACTIVE_HOR_VER, | |
1318 | EDP_ACTIVE_HOR_VER_HORIZ(mode->hdisplay) | | |
1319 | EDP_ACTIVE_HOR_VER_VERT(mode->vdisplay)); | |
1320 | ||
1321 | edp_clk_disable(ctrl, EDP_CLK_MASK_AHB); | |
1322 | ||
1323 | unlock_ret: | |
1324 | mutex_unlock(&ctrl->dev_mutex); | |
1325 | return ret; | |
1326 | } | |
1327 | ||
1328 | bool msm_edp_ctrl_pixel_clock_valid(struct edp_ctrl *ctrl, | |
1329 | u32 pixel_rate, u32 *pm, u32 *pn) | |
1330 | { | |
1331 | const struct edp_pixel_clk_div *divs; | |
1332 | u32 err = 1; /* 1% error tolerance */ | |
1333 | u32 clk_err; | |
1334 | int i; | |
1335 | ||
1336 | if (ctrl->link_rate == DP_LINK_BW_1_62) { | |
1337 | divs = clk_divs[0]; | |
1338 | } else if (ctrl->link_rate == DP_LINK_BW_2_7) { | |
1339 | divs = clk_divs[1]; | |
1340 | } else { | |
1341 | pr_err("%s: Invalid link rate,%d\n", __func__, ctrl->link_rate); | |
1342 | return false; | |
1343 | } | |
1344 | ||
1345 | for (i = 0; i < EDP_PIXEL_CLK_NUM; i++) { | |
1346 | clk_err = abs(divs[i].rate - pixel_rate); | |
1347 | if ((divs[i].rate * err / 100) >= clk_err) { | |
1348 | if (pm) | |
1349 | *pm = divs[i].m; | |
1350 | if (pn) | |
1351 | *pn = divs[i].n; | |
1352 | return true; | |
1353 | } | |
1354 | } | |
1355 | ||
1356 | DBG("pixel clock %d(kHz) not supported", pixel_rate); | |
1357 | ||
1358 | return false; | |
1359 | } | |
1360 |