1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2014 Red Hat
4 * Author: Rob Clark <robdclark@gmail.com>
5 * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
6 */
7
8 #include <linux/delay.h>
9
10 #include <drm/drm_crtc.h>
11 #include <drm/drm_probe_helper.h>
12
13 #include "mdp4_kms.h"
14
15 struct mdp4_lcdc_encoder {
16 struct drm_encoder base;
17 struct device_node *panel_node;
18 struct drm_panel *panel;
19 struct clk *lcdc_clk;
20 unsigned long int pixclock;
21 struct regulator *regs[3];
22 bool enabled;
23 uint32_t bsc;
24 };
25 #define to_mdp4_lcdc_encoder(x) container_of(x, struct mdp4_lcdc_encoder, base)
26
get_kms(struct drm_encoder * encoder)27 static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
28 {
29 struct msm_drm_private *priv = encoder->dev->dev_private;
30 return to_mdp4_kms(to_mdp_kms(priv->kms));
31 }
32
33 #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
34 #include <mach/board.h>
bs_init(struct mdp4_lcdc_encoder * mdp4_lcdc_encoder)35 static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder)
36 {
37 struct drm_device *dev = mdp4_lcdc_encoder->base.dev;
38 struct lcdc_platform_data *lcdc_pdata = mdp4_find_pdata("lvds.0");
39
40 if (!lcdc_pdata) {
41 DRM_DEV_ERROR(dev->dev, "could not find lvds pdata\n");
42 return;
43 }
44
45 if (lcdc_pdata->bus_scale_table) {
46 mdp4_lcdc_encoder->bsc = msm_bus_scale_register_client(
47 lcdc_pdata->bus_scale_table);
48 DBG("lvds : bus scale client: %08x", mdp4_lcdc_encoder->bsc);
49 }
50 }
51
bs_fini(struct mdp4_lcdc_encoder * mdp4_lcdc_encoder)52 static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder)
53 {
54 if (mdp4_lcdc_encoder->bsc) {
55 msm_bus_scale_unregister_client(mdp4_lcdc_encoder->bsc);
56 mdp4_lcdc_encoder->bsc = 0;
57 }
58 }
59
bs_set(struct mdp4_lcdc_encoder * mdp4_lcdc_encoder,int idx)60 static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx)
61 {
62 if (mdp4_lcdc_encoder->bsc) {
63 DBG("set bus scaling: %d", idx);
64 msm_bus_scale_client_update_request(mdp4_lcdc_encoder->bsc, idx);
65 }
66 }
67 #else
bs_init(struct mdp4_lcdc_encoder * mdp4_lcdc_encoder)68 static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {}
bs_fini(struct mdp4_lcdc_encoder * mdp4_lcdc_encoder)69 static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {}
bs_set(struct mdp4_lcdc_encoder * mdp4_lcdc_encoder,int idx)70 static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx) {}
71 #endif
72
mdp4_lcdc_encoder_destroy(struct drm_encoder * encoder)73 static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder)
74 {
75 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
76 to_mdp4_lcdc_encoder(encoder);
77 bs_fini(mdp4_lcdc_encoder);
78 drm_encoder_cleanup(encoder);
79 kfree(mdp4_lcdc_encoder);
80 }
81
82 static const struct drm_encoder_funcs mdp4_lcdc_encoder_funcs = {
83 .destroy = mdp4_lcdc_encoder_destroy,
84 };
85
86 /* this should probably be a helper: */
get_connector(struct drm_encoder * encoder)87 static struct drm_connector *get_connector(struct drm_encoder *encoder)
88 {
89 struct drm_device *dev = encoder->dev;
90 struct drm_connector *connector;
91
92 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
93 if (connector->encoder == encoder)
94 return connector;
95
96 return NULL;
97 }
98
setup_phy(struct drm_encoder * encoder)99 static void setup_phy(struct drm_encoder *encoder)
100 {
101 struct drm_device *dev = encoder->dev;
102 struct drm_connector *connector = get_connector(encoder);
103 struct mdp4_kms *mdp4_kms = get_kms(encoder);
104 uint32_t lvds_intf = 0, lvds_phy_cfg0 = 0;
105 int bpp, nchan, swap;
106
107 if (!connector)
108 return;
109
110 bpp = 3 * connector->display_info.bpc;
111
112 if (!bpp)
113 bpp = 18;
114
115 /* TODO, these should come from panel somehow: */
116 nchan = 1;
117 swap = 0;
118
119 switch (bpp) {
120 case 24:
121 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0),
122 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x08) |
123 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x05) |
124 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x04) |
125 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x03));
126 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0),
127 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x02) |
128 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x01) |
129 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x00));
130 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1),
131 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x11) |
132 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x10) |
133 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0d) |
134 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0c));
135 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1),
136 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0b) |
137 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0a) |
138 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x09));
139 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2),
140 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) |
141 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) |
142 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) |
143 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x15));
144 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2),
145 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x14) |
146 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x13) |
147 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x12));
148 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(3),
149 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1b) |
150 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x17) |
151 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x16) |
152 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0f));
153 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(3),
154 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0e) |
155 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x07) |
156 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x06));
157 if (nchan == 2) {
158 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE3_EN |
159 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN |
160 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN |
161 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN |
162 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN |
163 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
164 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
165 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
166 } else {
167 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE3_EN |
168 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
169 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
170 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
171 }
172 break;
173
174 case 18:
175 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(0),
176 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x0a) |
177 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x07) |
178 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x06) |
179 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x05));
180 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(0),
181 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x04) |
182 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x03) |
183 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x02));
184 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(1),
185 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x13) |
186 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x12) |
187 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x0f) |
188 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x0e));
189 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(1),
190 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x0d) |
191 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x0c) |
192 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x0b));
193 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_3_TO_0(2),
194 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT0(0x1a) |
195 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT1(0x19) |
196 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT2(0x18) |
197 MDP4_LCDC_LVDS_MUX_CTL_3_TO_0_BIT3(0x17));
198 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_MUX_CTL_6_TO_4(2),
199 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT4(0x16) |
200 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT5(0x15) |
201 MDP4_LCDC_LVDS_MUX_CTL_6_TO_4_BIT6(0x14));
202 if (nchan == 2) {
203 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE2_EN |
204 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE1_EN |
205 MDP4_LCDC_LVDS_INTF_CTL_CH2_DATA_LANE0_EN |
206 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
207 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
208 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
209 } else {
210 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE2_EN |
211 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE1_EN |
212 MDP4_LCDC_LVDS_INTF_CTL_CH1_DATA_LANE0_EN;
213 }
214 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_RGB_OUT;
215 break;
216
217 default:
218 DRM_DEV_ERROR(dev->dev, "unknown bpp: %d\n", bpp);
219 return;
220 }
221
222 switch (nchan) {
223 case 1:
224 lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0;
225 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN |
226 MDP4_LCDC_LVDS_INTF_CTL_MODE_SEL;
227 break;
228 case 2:
229 lvds_phy_cfg0 = MDP4_LVDS_PHY_CFG0_CHANNEL0 |
230 MDP4_LVDS_PHY_CFG0_CHANNEL1;
231 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH2_CLK_LANE_EN |
232 MDP4_LCDC_LVDS_INTF_CTL_CH1_CLK_LANE_EN;
233 break;
234 default:
235 DRM_DEV_ERROR(dev->dev, "unknown # of channels: %d\n", nchan);
236 return;
237 }
238
239 if (swap)
240 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_CH_SWAP;
241
242 lvds_intf |= MDP4_LCDC_LVDS_INTF_CTL_ENABLE;
243
244 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0);
245 mdp4_write(mdp4_kms, REG_MDP4_LCDC_LVDS_INTF_CTL, lvds_intf);
246 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG2, 0x30);
247
248 mb();
249 udelay(1);
250 lvds_phy_cfg0 |= MDP4_LVDS_PHY_CFG0_SERIALIZATION_ENBLE;
251 mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0);
252 }
253
mdp4_lcdc_encoder_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)254 static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder,
255 struct drm_display_mode *mode,
256 struct drm_display_mode *adjusted_mode)
257 {
258 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
259 to_mdp4_lcdc_encoder(encoder);
260 struct mdp4_kms *mdp4_kms = get_kms(encoder);
261 uint32_t lcdc_hsync_skew, vsync_period, vsync_len, ctrl_pol;
262 uint32_t display_v_start, display_v_end;
263 uint32_t hsync_start_x, hsync_end_x;
264
265 mode = adjusted_mode;
266
267 DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
268
269 mdp4_lcdc_encoder->pixclock = mode->clock * 1000;
270
271 DBG("pixclock=%lu", mdp4_lcdc_encoder->pixclock);
272
273 ctrl_pol = 0;
274 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
275 ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_HSYNC_LOW;
276 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
277 ctrl_pol |= MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW;
278 /* probably need to get DATA_EN polarity from panel.. */
279
280 lcdc_hsync_skew = 0; /* get this from panel? */
281
282 hsync_start_x = (mode->htotal - mode->hsync_start);
283 hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
284
285 vsync_period = mode->vtotal * mode->htotal;
286 vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
287 display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + lcdc_hsync_skew;
288 display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + lcdc_hsync_skew - 1;
289
290 mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_CTRL,
291 MDP4_LCDC_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) |
292 MDP4_LCDC_HSYNC_CTRL_PERIOD(mode->htotal));
293 mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_PERIOD, vsync_period);
294 mdp4_write(mdp4_kms, REG_MDP4_LCDC_VSYNC_LEN, vsync_len);
295 mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_HCTRL,
296 MDP4_LCDC_DISPLAY_HCTRL_START(hsync_start_x) |
297 MDP4_LCDC_DISPLAY_HCTRL_END(hsync_end_x));
298 mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VSTART, display_v_start);
299 mdp4_write(mdp4_kms, REG_MDP4_LCDC_DISPLAY_VEND, display_v_end);
300 mdp4_write(mdp4_kms, REG_MDP4_LCDC_BORDER_CLR, 0);
301 mdp4_write(mdp4_kms, REG_MDP4_LCDC_UNDERFLOW_CLR,
302 MDP4_LCDC_UNDERFLOW_CLR_ENABLE_RECOVERY |
303 MDP4_LCDC_UNDERFLOW_CLR_COLOR(0xff));
304 mdp4_write(mdp4_kms, REG_MDP4_LCDC_HSYNC_SKEW, lcdc_hsync_skew);
305 mdp4_write(mdp4_kms, REG_MDP4_LCDC_CTRL_POLARITY, ctrl_pol);
306 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_HCTL,
307 MDP4_LCDC_ACTIVE_HCTL_START(0) |
308 MDP4_LCDC_ACTIVE_HCTL_END(0));
309 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VSTART, 0);
310 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0);
311 }
312
mdp4_lcdc_encoder_disable(struct drm_encoder * encoder)313 static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder)
314 {
315 struct drm_device *dev = encoder->dev;
316 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
317 to_mdp4_lcdc_encoder(encoder);
318 struct mdp4_kms *mdp4_kms = get_kms(encoder);
319 struct drm_panel *panel;
320 int i, ret;
321
322 if (WARN_ON(!mdp4_lcdc_encoder->enabled))
323 return;
324
325 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0);
326
327 panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node);
328 if (!IS_ERR(panel)) {
329 drm_panel_disable(panel);
330 drm_panel_unprepare(panel);
331 }
332
333 /*
334 * Wait for a vsync so we know the ENABLE=0 latched before
335 * the (connector) source of the vsync's gets disabled,
336 * otherwise we end up in a funny state if we re-enable
337 * before the disable latches, which results that some of
338 * the settings changes for the new modeset (like new
339 * scanout buffer) don't latch properly..
340 */
341 mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC);
342
343 clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk);
344
345 for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
346 ret = regulator_disable(mdp4_lcdc_encoder->regs[i]);
347 if (ret)
348 DRM_DEV_ERROR(dev->dev, "failed to disable regulator: %d\n", ret);
349 }
350
351 bs_set(mdp4_lcdc_encoder, 0);
352
353 mdp4_lcdc_encoder->enabled = false;
354 }
355
mdp4_lcdc_encoder_enable(struct drm_encoder * encoder)356 static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder)
357 {
358 struct drm_device *dev = encoder->dev;
359 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
360 to_mdp4_lcdc_encoder(encoder);
361 unsigned long pc = mdp4_lcdc_encoder->pixclock;
362 struct mdp4_kms *mdp4_kms = get_kms(encoder);
363 struct drm_panel *panel;
364 uint32_t config;
365 int i, ret;
366
367 if (WARN_ON(mdp4_lcdc_encoder->enabled))
368 return;
369
370 /* TODO: hard-coded for 18bpp: */
371 config =
372 MDP4_DMA_CONFIG_R_BPC(BPC6) |
373 MDP4_DMA_CONFIG_G_BPC(BPC6) |
374 MDP4_DMA_CONFIG_B_BPC(BPC6) |
375 MDP4_DMA_CONFIG_PACK(0x21) |
376 MDP4_DMA_CONFIG_DEFLKR_EN |
377 MDP4_DMA_CONFIG_DITHER_EN;
378
379 if (!of_property_read_bool(dev->dev->of_node, "qcom,lcdc-align-lsb"))
380 config |= MDP4_DMA_CONFIG_PACK_ALIGN_MSB;
381
382 mdp4_crtc_set_config(encoder->crtc, config);
383 mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0);
384
385 bs_set(mdp4_lcdc_encoder, 1);
386
387 for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
388 ret = regulator_enable(mdp4_lcdc_encoder->regs[i]);
389 if (ret)
390 DRM_DEV_ERROR(dev->dev, "failed to enable regulator: %d\n", ret);
391 }
392
393 DBG("setting lcdc_clk=%lu", pc);
394 ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc);
395 if (ret)
396 DRM_DEV_ERROR(dev->dev, "failed to configure lcdc_clk: %d\n", ret);
397 ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk);
398 if (ret)
399 DRM_DEV_ERROR(dev->dev, "failed to enable lcdc_clk: %d\n", ret);
400
401 panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node);
402 if (!IS_ERR(panel)) {
403 drm_panel_prepare(panel);
404 drm_panel_enable(panel);
405 }
406
407 setup_phy(encoder);
408
409 mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1);
410
411 mdp4_lcdc_encoder->enabled = true;
412 }
413
414 static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = {
415 .mode_set = mdp4_lcdc_encoder_mode_set,
416 .disable = mdp4_lcdc_encoder_disable,
417 .enable = mdp4_lcdc_encoder_enable,
418 };
419
mdp4_lcdc_round_pixclk(struct drm_encoder * encoder,unsigned long rate)420 long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate)
421 {
422 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
423 to_mdp4_lcdc_encoder(encoder);
424 return clk_round_rate(mdp4_lcdc_encoder->lcdc_clk, rate);
425 }
426
427 /* initialize encoder */
mdp4_lcdc_encoder_init(struct drm_device * dev,struct device_node * panel_node)428 struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
429 struct device_node *panel_node)
430 {
431 struct drm_encoder *encoder = NULL;
432 struct mdp4_lcdc_encoder *mdp4_lcdc_encoder;
433 struct regulator *reg;
434 int ret;
435
436 mdp4_lcdc_encoder = kzalloc(sizeof(*mdp4_lcdc_encoder), GFP_KERNEL);
437 if (!mdp4_lcdc_encoder) {
438 ret = -ENOMEM;
439 goto fail;
440 }
441
442 mdp4_lcdc_encoder->panel_node = panel_node;
443
444 encoder = &mdp4_lcdc_encoder->base;
445
446 drm_encoder_init(dev, encoder, &mdp4_lcdc_encoder_funcs,
447 DRM_MODE_ENCODER_LVDS, NULL);
448 drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs);
449
450 /* TODO: do we need different pll in other cases? */
451 mdp4_lcdc_encoder->lcdc_clk = mpd4_lvds_pll_init(dev);
452 if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) {
453 DRM_DEV_ERROR(dev->dev, "failed to get lvds_clk\n");
454 ret = PTR_ERR(mdp4_lcdc_encoder->lcdc_clk);
455 goto fail;
456 }
457
458 /* TODO: different regulators in other cases? */
459 reg = devm_regulator_get(dev->dev, "lvds-vccs-3p3v");
460 if (IS_ERR(reg)) {
461 ret = PTR_ERR(reg);
462 DRM_DEV_ERROR(dev->dev, "failed to get lvds-vccs-3p3v: %d\n", ret);
463 goto fail;
464 }
465 mdp4_lcdc_encoder->regs[0] = reg;
466
467 reg = devm_regulator_get(dev->dev, "lvds-pll-vdda");
468 if (IS_ERR(reg)) {
469 ret = PTR_ERR(reg);
470 DRM_DEV_ERROR(dev->dev, "failed to get lvds-pll-vdda: %d\n", ret);
471 goto fail;
472 }
473 mdp4_lcdc_encoder->regs[1] = reg;
474
475 reg = devm_regulator_get(dev->dev, "lvds-vdda");
476 if (IS_ERR(reg)) {
477 ret = PTR_ERR(reg);
478 DRM_DEV_ERROR(dev->dev, "failed to get lvds-vdda: %d\n", ret);
479 goto fail;
480 }
481 mdp4_lcdc_encoder->regs[2] = reg;
482
483 bs_init(mdp4_lcdc_encoder);
484
485 return encoder;
486
487 fail:
488 if (encoder)
489 mdp4_lcdc_encoder_destroy(encoder);
490
491 return ERR_PTR(ret);
492 }
493