diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dsi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dsi.c | 620 |
1 files changed, 620 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c new file mode 100644 index 000000000000..d257b093ca68 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dsi.c | |||
@@ -0,0 +1,620 @@ | |||
1 | /* | ||
2 | * Copyright © 2013 Intel Corporation | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | * DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | * Author: Jani Nikula <jani.nikula@intel.com> | ||
24 | */ | ||
25 | |||
26 | #include <drm/drmP.h> | ||
27 | #include <drm/drm_crtc.h> | ||
28 | #include <drm/drm_edid.h> | ||
29 | #include <drm/i915_drm.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include "i915_drv.h" | ||
32 | #include "intel_drv.h" | ||
33 | #include "intel_dsi.h" | ||
34 | #include "intel_dsi_cmd.h" | ||
35 | |||
36 | /* the sub-encoders aka panel drivers */ | ||
37 | static const struct intel_dsi_device intel_dsi_devices[] = { | ||
38 | }; | ||
39 | |||
40 | |||
41 | static void vlv_cck_modify(struct drm_i915_private *dev_priv, u32 reg, u32 val, | ||
42 | u32 mask) | ||
43 | { | ||
44 | u32 tmp = vlv_cck_read(dev_priv, reg); | ||
45 | tmp &= ~mask; | ||
46 | tmp |= val; | ||
47 | vlv_cck_write(dev_priv, reg, tmp); | ||
48 | } | ||
49 | |||
50 | static void band_gap_wa(struct drm_i915_private *dev_priv) | ||
51 | { | ||
52 | mutex_lock(&dev_priv->dpio_lock); | ||
53 | |||
54 | /* Enable bandgap fix in GOP driver */ | ||
55 | vlv_cck_modify(dev_priv, 0x6D, 0x00010000, 0x00030000); | ||
56 | msleep(20); | ||
57 | vlv_cck_modify(dev_priv, 0x6E, 0x00010000, 0x00030000); | ||
58 | msleep(20); | ||
59 | vlv_cck_modify(dev_priv, 0x6F, 0x00010000, 0x00030000); | ||
60 | msleep(20); | ||
61 | vlv_cck_modify(dev_priv, 0x00, 0x00008000, 0x00008000); | ||
62 | msleep(20); | ||
63 | vlv_cck_modify(dev_priv, 0x00, 0x00000000, 0x00008000); | ||
64 | msleep(20); | ||
65 | |||
66 | /* Turn Display Trunk on */ | ||
67 | vlv_cck_modify(dev_priv, 0x6B, 0x00020000, 0x00030000); | ||
68 | msleep(20); | ||
69 | |||
70 | vlv_cck_modify(dev_priv, 0x6C, 0x00020000, 0x00030000); | ||
71 | msleep(20); | ||
72 | |||
73 | vlv_cck_modify(dev_priv, 0x6D, 0x00020000, 0x00030000); | ||
74 | msleep(20); | ||
75 | vlv_cck_modify(dev_priv, 0x6E, 0x00020000, 0x00030000); | ||
76 | msleep(20); | ||
77 | vlv_cck_modify(dev_priv, 0x6F, 0x00020000, 0x00030000); | ||
78 | |||
79 | mutex_unlock(&dev_priv->dpio_lock); | ||
80 | |||
81 | /* Need huge delay, otherwise clock is not stable */ | ||
82 | msleep(100); | ||
83 | } | ||
84 | |||
85 | static struct intel_dsi *intel_attached_dsi(struct drm_connector *connector) | ||
86 | { | ||
87 | return container_of(intel_attached_encoder(connector), | ||
88 | struct intel_dsi, base); | ||
89 | } | ||
90 | |||
91 | static inline bool is_vid_mode(struct intel_dsi *intel_dsi) | ||
92 | { | ||
93 | return intel_dsi->dev.type == INTEL_DSI_VIDEO_MODE; | ||
94 | } | ||
95 | |||
96 | static inline bool is_cmd_mode(struct intel_dsi *intel_dsi) | ||
97 | { | ||
98 | return intel_dsi->dev.type == INTEL_DSI_COMMAND_MODE; | ||
99 | } | ||
100 | |||
101 | static void intel_dsi_hot_plug(struct intel_encoder *encoder) | ||
102 | { | ||
103 | DRM_DEBUG_KMS("\n"); | ||
104 | } | ||
105 | |||
106 | static bool intel_dsi_compute_config(struct intel_encoder *encoder, | ||
107 | struct intel_crtc_config *config) | ||
108 | { | ||
109 | struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi, | ||
110 | base); | ||
111 | struct intel_connector *intel_connector = intel_dsi->attached_connector; | ||
112 | struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; | ||
113 | struct drm_display_mode *adjusted_mode = &config->adjusted_mode; | ||
114 | struct drm_display_mode *mode = &config->requested_mode; | ||
115 | |||
116 | DRM_DEBUG_KMS("\n"); | ||
117 | |||
118 | if (fixed_mode) | ||
119 | intel_fixed_panel_mode(fixed_mode, adjusted_mode); | ||
120 | |||
121 | if (intel_dsi->dev.dev_ops->mode_fixup) | ||
122 | return intel_dsi->dev.dev_ops->mode_fixup(&intel_dsi->dev, | ||
123 | mode, adjusted_mode); | ||
124 | |||
125 | return true; | ||
126 | } | ||
127 | |||
128 | static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) | ||
129 | { | ||
130 | DRM_DEBUG_KMS("\n"); | ||
131 | |||
132 | vlv_enable_dsi_pll(encoder); | ||
133 | } | ||
134 | |||
135 | static void intel_dsi_pre_enable(struct intel_encoder *encoder) | ||
136 | { | ||
137 | DRM_DEBUG_KMS("\n"); | ||
138 | } | ||
139 | |||
140 | static void intel_dsi_enable(struct intel_encoder *encoder) | ||
141 | { | ||
142 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; | ||
143 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | ||
144 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
145 | int pipe = intel_crtc->pipe; | ||
146 | u32 temp; | ||
147 | |||
148 | DRM_DEBUG_KMS("\n"); | ||
149 | |||
150 | temp = I915_READ(MIPI_DEVICE_READY(pipe)); | ||
151 | if ((temp & DEVICE_READY) == 0) { | ||
152 | temp &= ~ULPS_STATE_MASK; | ||
153 | I915_WRITE(MIPI_DEVICE_READY(pipe), temp | DEVICE_READY); | ||
154 | } else if (temp & ULPS_STATE_MASK) { | ||
155 | temp &= ~ULPS_STATE_MASK; | ||
156 | I915_WRITE(MIPI_DEVICE_READY(pipe), temp | ULPS_STATE_EXIT); | ||
157 | /* | ||
158 | * We need to ensure that there is a minimum of 1 ms time | ||
159 | * available before clearing the UPLS exit state. | ||
160 | */ | ||
161 | msleep(2); | ||
162 | I915_WRITE(MIPI_DEVICE_READY(pipe), temp); | ||
163 | } | ||
164 | |||
165 | if (is_cmd_mode(intel_dsi)) | ||
166 | I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4); | ||
167 | |||
168 | if (is_vid_mode(intel_dsi)) { | ||
169 | msleep(20); /* XXX */ | ||
170 | dpi_send_cmd(intel_dsi, TURN_ON); | ||
171 | msleep(100); | ||
172 | |||
173 | /* assert ip_tg_enable signal */ | ||
174 | temp = I915_READ(MIPI_PORT_CTRL(pipe)); | ||
175 | I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE); | ||
176 | POSTING_READ(MIPI_PORT_CTRL(pipe)); | ||
177 | } | ||
178 | |||
179 | intel_dsi->dev.dev_ops->enable(&intel_dsi->dev); | ||
180 | } | ||
181 | |||
182 | static void intel_dsi_disable(struct intel_encoder *encoder) | ||
183 | { | ||
184 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; | ||
185 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | ||
186 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
187 | int pipe = intel_crtc->pipe; | ||
188 | u32 temp; | ||
189 | |||
190 | DRM_DEBUG_KMS("\n"); | ||
191 | |||
192 | intel_dsi->dev.dev_ops->disable(&intel_dsi->dev); | ||
193 | |||
194 | if (is_vid_mode(intel_dsi)) { | ||
195 | dpi_send_cmd(intel_dsi, SHUTDOWN); | ||
196 | msleep(10); | ||
197 | |||
198 | /* de-assert ip_tg_enable signal */ | ||
199 | temp = I915_READ(MIPI_PORT_CTRL(pipe)); | ||
200 | I915_WRITE(MIPI_PORT_CTRL(pipe), temp & ~DPI_ENABLE); | ||
201 | POSTING_READ(MIPI_PORT_CTRL(pipe)); | ||
202 | |||
203 | msleep(2); | ||
204 | } | ||
205 | |||
206 | temp = I915_READ(MIPI_DEVICE_READY(pipe)); | ||
207 | if (temp & DEVICE_READY) { | ||
208 | temp &= ~DEVICE_READY; | ||
209 | temp &= ~ULPS_STATE_MASK; | ||
210 | I915_WRITE(MIPI_DEVICE_READY(pipe), temp); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | static void intel_dsi_post_disable(struct intel_encoder *encoder) | ||
215 | { | ||
216 | DRM_DEBUG_KMS("\n"); | ||
217 | |||
218 | vlv_disable_dsi_pll(encoder); | ||
219 | } | ||
220 | |||
221 | static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, | ||
222 | enum pipe *pipe) | ||
223 | { | ||
224 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; | ||
225 | u32 port, func; | ||
226 | enum pipe p; | ||
227 | |||
228 | DRM_DEBUG_KMS("\n"); | ||
229 | |||
230 | /* XXX: this only works for one DSI output */ | ||
231 | for (p = PIPE_A; p <= PIPE_B; p++) { | ||
232 | port = I915_READ(MIPI_PORT_CTRL(p)); | ||
233 | func = I915_READ(MIPI_DSI_FUNC_PRG(p)); | ||
234 | |||
235 | if ((port & DPI_ENABLE) || (func & CMD_MODE_DATA_WIDTH_MASK)) { | ||
236 | if (I915_READ(MIPI_DEVICE_READY(p)) & DEVICE_READY) { | ||
237 | *pipe = p; | ||
238 | return true; | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
243 | return false; | ||
244 | } | ||
245 | |||
246 | static void intel_dsi_get_config(struct intel_encoder *encoder, | ||
247 | struct intel_crtc_config *pipe_config) | ||
248 | { | ||
249 | DRM_DEBUG_KMS("\n"); | ||
250 | |||
251 | /* XXX: read flags, set to adjusted_mode */ | ||
252 | } | ||
253 | |||
254 | static int intel_dsi_mode_valid(struct drm_connector *connector, | ||
255 | struct drm_display_mode *mode) | ||
256 | { | ||
257 | struct intel_connector *intel_connector = to_intel_connector(connector); | ||
258 | struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; | ||
259 | struct intel_dsi *intel_dsi = intel_attached_dsi(connector); | ||
260 | |||
261 | DRM_DEBUG_KMS("\n"); | ||
262 | |||
263 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { | ||
264 | DRM_DEBUG_KMS("MODE_NO_DBLESCAN\n"); | ||
265 | return MODE_NO_DBLESCAN; | ||
266 | } | ||
267 | |||
268 | if (fixed_mode) { | ||
269 | if (mode->hdisplay > fixed_mode->hdisplay) | ||
270 | return MODE_PANEL; | ||
271 | if (mode->vdisplay > fixed_mode->vdisplay) | ||
272 | return MODE_PANEL; | ||
273 | } | ||
274 | |||
275 | return intel_dsi->dev.dev_ops->mode_valid(&intel_dsi->dev, mode); | ||
276 | } | ||
277 | |||
278 | /* return txclkesc cycles in terms of divider and duration in us */ | ||
279 | static u16 txclkesc(u32 divider, unsigned int us) | ||
280 | { | ||
281 | switch (divider) { | ||
282 | case ESCAPE_CLOCK_DIVIDER_1: | ||
283 | default: | ||
284 | return 20 * us; | ||
285 | case ESCAPE_CLOCK_DIVIDER_2: | ||
286 | return 10 * us; | ||
287 | case ESCAPE_CLOCK_DIVIDER_4: | ||
288 | return 5 * us; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | /* return pixels in terms of txbyteclkhs */ | ||
293 | static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count) | ||
294 | { | ||
295 | return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp, 8), lane_count); | ||
296 | } | ||
297 | |||
298 | static void set_dsi_timings(struct drm_encoder *encoder, | ||
299 | const struct drm_display_mode *mode) | ||
300 | { | ||
301 | struct drm_device *dev = encoder->dev; | ||
302 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
303 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
304 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); | ||
305 | int pipe = intel_crtc->pipe; | ||
306 | unsigned int bpp = intel_crtc->config.pipe_bpp; | ||
307 | unsigned int lane_count = intel_dsi->lane_count; | ||
308 | |||
309 | u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp; | ||
310 | |||
311 | hactive = mode->hdisplay; | ||
312 | hfp = mode->hsync_start - mode->hdisplay; | ||
313 | hsync = mode->hsync_end - mode->hsync_start; | ||
314 | hbp = mode->htotal - mode->hsync_end; | ||
315 | |||
316 | vfp = mode->vsync_start - mode->vdisplay; | ||
317 | vsync = mode->vsync_end - mode->vsync_start; | ||
318 | vbp = mode->vtotal - mode->vsync_end; | ||
319 | |||
320 | /* horizontal values are in terms of high speed byte clock */ | ||
321 | hactive = txbyteclkhs(hactive, bpp, lane_count); | ||
322 | hfp = txbyteclkhs(hfp, bpp, lane_count); | ||
323 | hsync = txbyteclkhs(hsync, bpp, lane_count); | ||
324 | hbp = txbyteclkhs(hbp, bpp, lane_count); | ||
325 | |||
326 | I915_WRITE(MIPI_HACTIVE_AREA_COUNT(pipe), hactive); | ||
327 | I915_WRITE(MIPI_HFP_COUNT(pipe), hfp); | ||
328 | |||
329 | /* meaningful for video mode non-burst sync pulse mode only, can be zero | ||
330 | * for non-burst sync events and burst modes */ | ||
331 | I915_WRITE(MIPI_HSYNC_PADDING_COUNT(pipe), hsync); | ||
332 | I915_WRITE(MIPI_HBP_COUNT(pipe), hbp); | ||
333 | |||
334 | /* vertical values are in terms of lines */ | ||
335 | I915_WRITE(MIPI_VFP_COUNT(pipe), vfp); | ||
336 | I915_WRITE(MIPI_VSYNC_PADDING_COUNT(pipe), vsync); | ||
337 | I915_WRITE(MIPI_VBP_COUNT(pipe), vbp); | ||
338 | } | ||
339 | |||
340 | static void intel_dsi_mode_set(struct intel_encoder *intel_encoder) | ||
341 | { | ||
342 | struct drm_encoder *encoder = &intel_encoder->base; | ||
343 | struct drm_device *dev = encoder->dev; | ||
344 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
345 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
346 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); | ||
347 | struct drm_display_mode *adjusted_mode = | ||
348 | &intel_crtc->config.adjusted_mode; | ||
349 | int pipe = intel_crtc->pipe; | ||
350 | unsigned int bpp = intel_crtc->config.pipe_bpp; | ||
351 | u32 val, tmp; | ||
352 | |||
353 | DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); | ||
354 | |||
355 | /* Update the DSI PLL */ | ||
356 | vlv_enable_dsi_pll(intel_encoder); | ||
357 | |||
358 | /* XXX: Location of the call */ | ||
359 | band_gap_wa(dev_priv); | ||
360 | |||
361 | /* escape clock divider, 20MHz, shared for A and C. device ready must be | ||
362 | * off when doing this! txclkesc? */ | ||
363 | tmp = I915_READ(MIPI_CTRL(0)); | ||
364 | tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; | ||
365 | I915_WRITE(MIPI_CTRL(0), tmp | ESCAPE_CLOCK_DIVIDER_1); | ||
366 | |||
367 | /* read request priority is per pipe */ | ||
368 | tmp = I915_READ(MIPI_CTRL(pipe)); | ||
369 | tmp &= ~READ_REQUEST_PRIORITY_MASK; | ||
370 | I915_WRITE(MIPI_CTRL(pipe), tmp | READ_REQUEST_PRIORITY_HIGH); | ||
371 | |||
372 | /* XXX: why here, why like this? handling in irq handler?! */ | ||
373 | I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff); | ||
374 | I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff); | ||
375 | |||
376 | I915_WRITE(MIPI_DPHY_PARAM(pipe), | ||
377 | 0x3c << EXIT_ZERO_COUNT_SHIFT | | ||
378 | 0x1f << TRAIL_COUNT_SHIFT | | ||
379 | 0xc5 << CLK_ZERO_COUNT_SHIFT | | ||
380 | 0x1f << PREPARE_COUNT_SHIFT); | ||
381 | |||
382 | I915_WRITE(MIPI_DPI_RESOLUTION(pipe), | ||
383 | adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT | | ||
384 | adjusted_mode->hdisplay << HORIZONTAL_ADDRESS_SHIFT); | ||
385 | |||
386 | set_dsi_timings(encoder, adjusted_mode); | ||
387 | |||
388 | val = intel_dsi->lane_count << DATA_LANES_PRG_REG_SHIFT; | ||
389 | if (is_cmd_mode(intel_dsi)) { | ||
390 | val |= intel_dsi->channel << CMD_MODE_CHANNEL_NUMBER_SHIFT; | ||
391 | val |= CMD_MODE_DATA_WIDTH_8_BIT; /* XXX */ | ||
392 | } else { | ||
393 | val |= intel_dsi->channel << VID_MODE_CHANNEL_NUMBER_SHIFT; | ||
394 | |||
395 | /* XXX: cross-check bpp vs. pixel format? */ | ||
396 | val |= intel_dsi->pixel_format; | ||
397 | } | ||
398 | I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), val); | ||
399 | |||
400 | /* timeouts for recovery. one frame IIUC. if counter expires, EOT and | ||
401 | * stop state. */ | ||
402 | |||
403 | /* | ||
404 | * In burst mode, value greater than one DPI line Time in byte clock | ||
405 | * (txbyteclkhs) To timeout this timer 1+ of the above said value is | ||
406 | * recommended. | ||
407 | * | ||
408 | * In non-burst mode, Value greater than one DPI frame time in byte | ||
409 | * clock(txbyteclkhs) To timeout this timer 1+ of the above said value | ||
410 | * is recommended. | ||
411 | * | ||
412 | * In DBI only mode, value greater than one DBI frame time in byte | ||
413 | * clock(txbyteclkhs) To timeout this timer 1+ of the above said value | ||
414 | * is recommended. | ||
415 | */ | ||
416 | |||
417 | if (is_vid_mode(intel_dsi) && | ||
418 | intel_dsi->video_mode_format == VIDEO_MODE_BURST) { | ||
419 | I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), | ||
420 | txbyteclkhs(adjusted_mode->htotal, bpp, | ||
421 | intel_dsi->lane_count) + 1); | ||
422 | } else { | ||
423 | I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), | ||
424 | txbyteclkhs(adjusted_mode->vtotal * | ||
425 | adjusted_mode->htotal, | ||
426 | bpp, intel_dsi->lane_count) + 1); | ||
427 | } | ||
428 | I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), 8309); /* max */ | ||
429 | I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), 0x14); /* max */ | ||
430 | I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), 0xffff); /* max */ | ||
431 | |||
432 | /* dphy stuff */ | ||
433 | |||
434 | /* in terms of low power clock */ | ||
435 | I915_WRITE(MIPI_INIT_COUNT(pipe), txclkesc(ESCAPE_CLOCK_DIVIDER_1, 100)); | ||
436 | |||
437 | /* recovery disables */ | ||
438 | I915_WRITE(MIPI_EOT_DISABLE(pipe), intel_dsi->eot_disable); | ||
439 | |||
440 | /* in terms of txbyteclkhs. actual high to low switch + | ||
441 | * MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK. | ||
442 | * | ||
443 | * XXX: write MIPI_STOP_STATE_STALL? | ||
444 | */ | ||
445 | I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), 0x46); | ||
446 | |||
447 | /* XXX: low power clock equivalence in terms of byte clock. the number | ||
448 | * of byte clocks occupied in one low power clock. based on txbyteclkhs | ||
449 | * and txclkesc. txclkesc time / txbyteclk time * (105 + | ||
450 | * MIPI_STOP_STATE_STALL) / 105.??? | ||
451 | */ | ||
452 | I915_WRITE(MIPI_LP_BYTECLK(pipe), 4); | ||
453 | |||
454 | /* the bw essential for transmitting 16 long packets containing 252 | ||
455 | * bytes meant for dcs write memory command is programmed in this | ||
456 | * register in terms of byte clocks. based on dsi transfer rate and the | ||
457 | * number of lanes configured the time taken to transmit 16 long packets | ||
458 | * in a dsi stream varies. */ | ||
459 | I915_WRITE(MIPI_DBI_BW_CTRL(pipe), 0x820); | ||
460 | |||
461 | I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe), | ||
462 | 0xa << LP_HS_SSW_CNT_SHIFT | | ||
463 | 0x14 << HS_LP_PWR_SW_CNT_SHIFT); | ||
464 | |||
465 | if (is_vid_mode(intel_dsi)) | ||
466 | I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe), | ||
467 | intel_dsi->video_mode_format); | ||
468 | } | ||
469 | |||
470 | static enum drm_connector_status | ||
471 | intel_dsi_detect(struct drm_connector *connector, bool force) | ||
472 | { | ||
473 | struct intel_dsi *intel_dsi = intel_attached_dsi(connector); | ||
474 | DRM_DEBUG_KMS("\n"); | ||
475 | return intel_dsi->dev.dev_ops->detect(&intel_dsi->dev); | ||
476 | } | ||
477 | |||
478 | static int intel_dsi_get_modes(struct drm_connector *connector) | ||
479 | { | ||
480 | struct intel_connector *intel_connector = to_intel_connector(connector); | ||
481 | struct drm_display_mode *mode; | ||
482 | |||
483 | DRM_DEBUG_KMS("\n"); | ||
484 | |||
485 | if (!intel_connector->panel.fixed_mode) { | ||
486 | DRM_DEBUG_KMS("no fixed mode\n"); | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | mode = drm_mode_duplicate(connector->dev, | ||
491 | intel_connector->panel.fixed_mode); | ||
492 | if (!mode) { | ||
493 | DRM_DEBUG_KMS("drm_mode_duplicate failed\n"); | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | drm_mode_probed_add(connector, mode); | ||
498 | return 1; | ||
499 | } | ||
500 | |||
501 | static void intel_dsi_destroy(struct drm_connector *connector) | ||
502 | { | ||
503 | struct intel_connector *intel_connector = to_intel_connector(connector); | ||
504 | |||
505 | DRM_DEBUG_KMS("\n"); | ||
506 | intel_panel_fini(&intel_connector->panel); | ||
507 | drm_connector_cleanup(connector); | ||
508 | kfree(connector); | ||
509 | } | ||
510 | |||
511 | static const struct drm_encoder_funcs intel_dsi_funcs = { | ||
512 | .destroy = intel_encoder_destroy, | ||
513 | }; | ||
514 | |||
515 | static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs = { | ||
516 | .get_modes = intel_dsi_get_modes, | ||
517 | .mode_valid = intel_dsi_mode_valid, | ||
518 | .best_encoder = intel_best_encoder, | ||
519 | }; | ||
520 | |||
521 | static const struct drm_connector_funcs intel_dsi_connector_funcs = { | ||
522 | .dpms = intel_connector_dpms, | ||
523 | .detect = intel_dsi_detect, | ||
524 | .destroy = intel_dsi_destroy, | ||
525 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
526 | }; | ||
527 | |||
528 | bool intel_dsi_init(struct drm_device *dev) | ||
529 | { | ||
530 | struct intel_dsi *intel_dsi; | ||
531 | struct intel_encoder *intel_encoder; | ||
532 | struct drm_encoder *encoder; | ||
533 | struct intel_connector *intel_connector; | ||
534 | struct drm_connector *connector; | ||
535 | struct drm_display_mode *fixed_mode = NULL; | ||
536 | const struct intel_dsi_device *dsi; | ||
537 | unsigned int i; | ||
538 | |||
539 | DRM_DEBUG_KMS("\n"); | ||
540 | |||
541 | intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL); | ||
542 | if (!intel_dsi) | ||
543 | return false; | ||
544 | |||
545 | intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); | ||
546 | if (!intel_connector) { | ||
547 | kfree(intel_dsi); | ||
548 | return false; | ||
549 | } | ||
550 | |||
551 | intel_encoder = &intel_dsi->base; | ||
552 | encoder = &intel_encoder->base; | ||
553 | intel_dsi->attached_connector = intel_connector; | ||
554 | |||
555 | connector = &intel_connector->base; | ||
556 | |||
557 | drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI); | ||
558 | |||
559 | /* XXX: very likely not all of these are needed */ | ||
560 | intel_encoder->hot_plug = intel_dsi_hot_plug; | ||
561 | intel_encoder->compute_config = intel_dsi_compute_config; | ||
562 | intel_encoder->pre_pll_enable = intel_dsi_pre_pll_enable; | ||
563 | intel_encoder->pre_enable = intel_dsi_pre_enable; | ||
564 | intel_encoder->enable = intel_dsi_enable; | ||
565 | intel_encoder->mode_set = intel_dsi_mode_set; | ||
566 | intel_encoder->disable = intel_dsi_disable; | ||
567 | intel_encoder->post_disable = intel_dsi_post_disable; | ||
568 | intel_encoder->get_hw_state = intel_dsi_get_hw_state; | ||
569 | intel_encoder->get_config = intel_dsi_get_config; | ||
570 | |||
571 | intel_connector->get_hw_state = intel_connector_get_hw_state; | ||
572 | |||
573 | for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) { | ||
574 | dsi = &intel_dsi_devices[i]; | ||
575 | intel_dsi->dev = *dsi; | ||
576 | |||
577 | if (dsi->dev_ops->init(&intel_dsi->dev)) | ||
578 | break; | ||
579 | } | ||
580 | |||
581 | if (i == ARRAY_SIZE(intel_dsi_devices)) { | ||
582 | DRM_DEBUG_KMS("no device found\n"); | ||
583 | goto err; | ||
584 | } | ||
585 | |||
586 | intel_encoder->type = INTEL_OUTPUT_DSI; | ||
587 | intel_encoder->crtc_mask = (1 << 0); /* XXX */ | ||
588 | |||
589 | intel_encoder->cloneable = false; | ||
590 | drm_connector_init(dev, connector, &intel_dsi_connector_funcs, | ||
591 | DRM_MODE_CONNECTOR_DSI); | ||
592 | |||
593 | drm_connector_helper_add(connector, &intel_dsi_connector_helper_funcs); | ||
594 | |||
595 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; /*XXX*/ | ||
596 | connector->interlace_allowed = false; | ||
597 | connector->doublescan_allowed = false; | ||
598 | |||
599 | intel_connector_attach_encoder(intel_connector, intel_encoder); | ||
600 | |||
601 | drm_sysfs_connector_add(connector); | ||
602 | |||
603 | fixed_mode = dsi->dev_ops->get_modes(&intel_dsi->dev); | ||
604 | if (!fixed_mode) { | ||
605 | DRM_DEBUG_KMS("no fixed mode\n"); | ||
606 | goto err; | ||
607 | } | ||
608 | |||
609 | fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
610 | intel_panel_init(&intel_connector->panel, fixed_mode); | ||
611 | |||
612 | return true; | ||
613 | |||
614 | err: | ||
615 | drm_encoder_cleanup(&intel_encoder->base); | ||
616 | kfree(intel_dsi); | ||
617 | kfree(intel_connector); | ||
618 | |||
619 | return false; | ||
620 | } | ||