2 * Copyright (c) 2010 Intel Corporation
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, sublicensen
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:
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
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.
24 * Thomas Eaton <thomas.g.eaton@intel.com>
25 * Scott Rowe <scott.m.rowe@intel.com>
28 #include "mdfld_dsi_dbi.h"
29 #include "mdfld_dsi_dpi.h"
30 #include "mdfld_dsi_output.h"
31 #include "mdfld_output.h"
33 #include "mdfld_dsi_pkg_sender.h"
35 #include "displays/tpo_cmd.h"
37 static struct drm_display_mode
*tpo_cmd_get_config_mode(struct drm_device
*dev
)
39 struct drm_display_mode
*mode
;
40 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
41 struct mrst_timing_info
*ti
= &dev_priv
->gct_data
.DTD
;
44 mode
= kzalloc(sizeof(*mode
), GFP_KERNEL
);
49 dev_dbg(dev
->dev
, "gct find MIPI panel.\n");
51 mode
->hdisplay
= (ti
->hactive_hi
<< 8) | ti
->hactive_lo
;
52 mode
->vdisplay
= (ti
->vactive_hi
<< 8) | ti
->vactive_lo
;
53 mode
->hsync_start
= mode
->hdisplay
+ \
54 ((ti
->hsync_offset_hi
<< 8) | \
56 mode
->hsync_end
= mode
->hsync_start
+ \
57 ((ti
->hsync_pulse_width_hi
<< 8) | \
58 ti
->hsync_pulse_width_lo
);
59 mode
->htotal
= mode
->hdisplay
+ ((ti
->hblank_hi
<< 8) | \
62 mode
->vdisplay
+ ((ti
->vsync_offset_hi
<< 8) | \
65 mode
->vsync_start
+ ((ti
->vsync_pulse_width_hi
<< 8) | \
66 ti
->vsync_pulse_width_lo
);
67 mode
->vtotal
= mode
->vdisplay
+ \
68 ((ti
->vblank_hi
<< 8) | ti
->vblank_lo
);
69 mode
->clock
= ti
->pixel_clock
* 10;
71 dev_dbg(dev
->dev
, "hdisplay is %d\n", mode
->hdisplay
);
72 dev_dbg(dev
->dev
, "vdisplay is %d\n", mode
->vdisplay
);
73 dev_dbg(dev
->dev
, "HSS is %d\n", mode
->hsync_start
);
74 dev_dbg(dev
->dev
, "HSE is %d\n", mode
->hsync_end
);
75 dev_dbg(dev
->dev
, "htotal is %d\n", mode
->htotal
);
76 dev_dbg(dev
->dev
, "VSS is %d\n", mode
->vsync_start
);
77 dev_dbg(dev
->dev
, "VSE is %d\n", mode
->vsync_end
);
78 dev_dbg(dev
->dev
, "vtotal is %d\n", mode
->vtotal
);
79 dev_dbg(dev
->dev
, "clock is %d\n", mode
->clock
);
83 mode
->hsync_start
= 872;
84 mode
->hsync_end
= 876;
86 mode
->vsync_start
= 482;
87 mode
->vsync_end
= 494;
92 drm_mode_set_name(mode
);
93 drm_mode_set_crtcinfo(mode
, 0);
95 mode
->type
|= DRM_MODE_TYPE_PREFERRED
;
100 static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder
*encoder
,
101 struct drm_display_mode
*mode
,
102 struct drm_display_mode
*adjusted_mode
)
104 struct drm_device
*dev
= encoder
->dev
;
105 struct drm_display_mode
*fixed_mode
= tpo_cmd_get_config_mode(dev
);
108 adjusted_mode
->hdisplay
= fixed_mode
->hdisplay
;
109 adjusted_mode
->hsync_start
= fixed_mode
->hsync_start
;
110 adjusted_mode
->hsync_end
= fixed_mode
->hsync_end
;
111 adjusted_mode
->htotal
= fixed_mode
->htotal
;
112 adjusted_mode
->vdisplay
= fixed_mode
->vdisplay
;
113 adjusted_mode
->vsync_start
= fixed_mode
->vsync_start
;
114 adjusted_mode
->vsync_end
= fixed_mode
->vsync_end
;
115 adjusted_mode
->vtotal
= fixed_mode
->vtotal
;
116 adjusted_mode
->clock
= fixed_mode
->clock
;
117 drm_mode_set_crtcinfo(adjusted_mode
, CRTC_INTERLACE_HALVE_V
);
123 static void mdfld_dsi_dbi_set_power(struct drm_encoder
*encoder
, bool on
)
126 struct mdfld_dsi_encoder
*dsi_encoder
= MDFLD_DSI_ENCODER(encoder
);
127 struct mdfld_dsi_dbi_output
*dbi_output
=
128 MDFLD_DSI_DBI_OUTPUT(dsi_encoder
);
129 /*struct drm_device *dev = dbi_output->dev;*/
130 struct drm_device
*dev
= encoder
->dev
;
131 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
133 int pipe
= (dbi_output
->channel_num
== 0) ? 0 : 2;
135 dev_dbg(dev
->dev
, "pipe %d : %s, panel on: %s\n",
136 pipe
, on
? "On" : "Off",
137 dbi_output
->dbi_panel_on
? "True" : "False");
141 dev_priv
->dual_mipi
= true;
143 dev_priv
->dual_mipi
= false;
144 reg_offset
= MIPIC_REG_OFFSET
;
147 dev_priv
->dual_mipi
= false;
150 if (!gma_power_begin(dev
, true)) {
151 dev_err(dev
->dev
, "hw begin failed\n");
156 if (dbi_output
->dbi_panel_on
)
159 ret
= mdfld_dsi_dbi_update_power(dbi_output
, DRM_MODE_DPMS_ON
);
161 dev_err(dev
->dev
, "power on error\n");
165 dbi_output
->dbi_panel_on
= true;
168 dev_priv
->dbi_panel_on2
= true;
170 dev_priv
->dbi_panel_on
= true;
171 mdfld_enable_te(dev
, pipe
);
173 if (!dbi_output
->dbi_panel_on
&& !dbi_output
->first_boot
)
176 dbi_output
->dbi_panel_on
= false;
177 dbi_output
->first_boot
= false;
180 dev_priv
->dbi_panel_on2
= false;
182 dev_priv
->dbi_panel_on
= false;
184 mdfld_disable_te(dev
, pipe
);
186 ret
= mdfld_dsi_dbi_update_power(dbi_output
, DRM_MODE_DPMS_OFF
);
188 dev_err(dev
->dev
, "power on error\n");
197 dev_err(dev
->dev
, "failed\n");
201 static void mdfld_dsi_dbi_mode_set(struct drm_encoder
*encoder
,
202 struct drm_display_mode
*mode
,
203 struct drm_display_mode
*adjusted_mode
)
206 struct drm_device
*dev
= encoder
->dev
;
207 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
208 struct mdfld_dsi_encoder
*dsi_encoder
= MDFLD_DSI_ENCODER(encoder
);
209 struct mdfld_dsi_dbi_output
*dsi_output
=
210 MDFLD_DSI_DBI_OUTPUT(dsi_encoder
);
211 struct mdfld_dsi_config
*dsi_config
=
212 mdfld_dsi_encoder_get_config(dsi_encoder
);
213 struct mdfld_dsi_connector
*dsi_connector
= dsi_config
->connector
;
214 int pipe
= dsi_connector
->pipe
;
219 u32 dspcntr_reg
= DSPACNTR
;
220 u32 pipeconf_reg
= PIPEACONF
;
224 u32 dspcntr_val
= dev_priv
->dspcntr
;
225 u32 pipeconf_val
= dev_priv
->pipeconf
;
226 u32 h_active_area
= mode
->hdisplay
;
227 u32 v_active_area
= mode
->vdisplay
;
230 mipi_val
= (PASS_FROM_SPHY_TO_AFE
| SEL_FLOPPED_HSTX
|
231 TE_TRIGGER_GPIO_PIN
);
233 dev_dbg(dev
->dev
, "mipi_val =0x%x\n", mipi_val
);
235 dev_dbg(dev
->dev
, "type %s\n", (pipe
== 2) ? "MIPI2" : "MIPI");
236 dev_dbg(dev
->dev
, "h %d v %d\n", mode
->hdisplay
, mode
->vdisplay
);
240 dspcntr_reg
= DSPCCNTR
;
241 pipeconf_reg
= PIPECCONF
;
243 reg_offset
= MIPIC_REG_OFFSET
;
245 dspcntr_val
= dev_priv
->dspcntr2
;
246 pipeconf_val
= dev_priv
->pipeconf2
;
248 mipi_val
|= 0x2; /*two lanes for port A and C respectively*/
251 if (!gma_power_begin(dev
, true)) {
252 dev_err(dev
->dev
, "hw begin failed\n");
256 /* Set up pipe related registers */
257 REG_WRITE(mipi_reg
, mipi_val
);
260 mdfld_dsi_controller_dbi_init(dsi_config
, pipe
);
264 REG_WRITE(dspcntr_reg
, dspcntr_val
);
265 REG_READ(dspcntr_reg
);
267 /* 20ms delay before sending exit_sleep_mode */
270 /* Send exit_sleep_mode DCS */
271 ret
= mdfld_dsi_dbi_send_dcs(dsi_output
, exit_sleep_mode
,
272 NULL
, 0, CMD_DATA_SRC_SYSTEM_MEM
);
274 dev_err(dev
->dev
, "sent exit_sleep_mode faild\n");
278 /* Send set_tear_on DCS */
279 ret
= mdfld_dsi_dbi_send_dcs(dsi_output
, set_tear_on
,
280 ¶m
, 1, CMD_DATA_SRC_SYSTEM_MEM
);
282 dev_err(dev
->dev
, "%s - sent set_tear_on faild\n", __func__
);
286 /* Do some init stuff */
287 mdfld_dsi_brightness_init(dsi_config
, pipe
);
289 mdfld_dsi_gen_fifo_ready(dev
, (MIPIA_GEN_FIFO_STAT_REG
+ reg_offset
),
290 HS_CTRL_FIFO_EMPTY
| HS_DATA_FIFO_EMPTY
);
292 REG_WRITE(pipeconf_reg
, pipeconf_val
| PIPEACONF_DSR
);
293 REG_READ(pipeconf_reg
);
295 /* TODO: this looks ugly, try to move it to CRTC mode setting*/
297 dev_priv
->pipeconf2
|= PIPEACONF_DSR
;
299 dev_priv
->pipeconf
|= PIPEACONF_DSR
;
301 dev_dbg(dev
->dev
, "pipeconf %x\n", REG_READ(pipeconf_reg
));
303 ret
= mdfld_dsi_dbi_update_area(dsi_output
, 0, 0,
304 h_active_area
- 1, v_active_area
- 1);
306 dev_err(dev
->dev
, "update area failed\n");
314 dev_err(dev
->dev
, "mode set failed\n");
317 static void mdfld_dsi_dbi_prepare(struct drm_encoder
*encoder
)
319 struct mdfld_dsi_encoder
*dsi_encoder
= MDFLD_DSI_ENCODER(encoder
);
320 struct mdfld_dsi_dbi_output
*dbi_output
321 = MDFLD_DSI_DBI_OUTPUT(dsi_encoder
);
323 dbi_output
->mode_flags
|= MODE_SETTING_IN_ENCODER
;
324 dbi_output
->mode_flags
&= ~MODE_SETTING_ENCODER_DONE
;
326 mdfld_dsi_dbi_set_power(encoder
, false);
329 static void mdfld_dsi_dbi_commit(struct drm_encoder
*encoder
)
331 struct mdfld_dsi_encoder
*dsi_encoder
= MDFLD_DSI_ENCODER(encoder
);
332 struct mdfld_dsi_dbi_output
*dbi_output
=
333 MDFLD_DSI_DBI_OUTPUT(dsi_encoder
);
334 struct drm_device
*dev
= dbi_output
->dev
;
335 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
336 struct psb_drm_dpu_rect rect
;
338 mdfld_dsi_dbi_set_power(encoder
, true);
339 dbi_output
->mode_flags
&= ~MODE_SETTING_IN_ENCODER
;
345 if (dbi_output
->channel_num
== 1) {
346 dev_priv
->dsr_fb_update
|= MDFLD_DSR_2D_3D_2
;
347 #ifdef CONFIG_MDFLD_DSI_DPU
348 /*if dpu enabled report a fullscreen damage*/
349 mdfld_dbi_dpu_report_damage(dev
, MDFLD_PLANEC
, &rect
);
352 dev_priv
->dsr_fb_update
|= MDFLD_DSR_2D_3D_0
;
353 #ifdef CONFIG_MDFLD_DSI_DPU
354 mdfld_dbi_dpu_report_damage(dev
, MDFLD_PLANEA
, &rect
);
357 dbi_output
->mode_flags
|= MODE_SETTING_ENCODER_DONE
;
360 static void mdfld_dsi_dbi_dpms(struct drm_encoder
*encoder
, int mode
)
362 struct mdfld_dsi_encoder
*dsi_encoder
= MDFLD_DSI_ENCODER(encoder
);
363 struct mdfld_dsi_dbi_output
*dbi_output
364 = MDFLD_DSI_DBI_OUTPUT(dsi_encoder
);
365 struct drm_device
*dev
= dbi_output
->dev
;
366 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
367 static bool bdispoff
;
369 dev_dbg(dev
->dev
, "%s\n", (mode
== DRM_MODE_DPMS_ON
? "on" : "off"));
371 if (mode
== DRM_MODE_DPMS_ON
) {
373 * FIXME: in case I am wrong!
374 * we don't need to exit dsr here to wake up plane/pipe/pll
375 * if everything goes right, hw_begin will resume them all
379 mdfld_dsi_dbi_exit_dsr(dev
, MDFLD_DSR_2D_3D
, 0, 0);
381 mdfld_dsi_dbi_set_power(encoder
, true);
382 /* FIXME if (gbgfxsuspended)
383 gbgfxsuspended = false; */
385 dev_priv
->dispstatus
= true;
388 * I am not sure whether this is the perfect place to
389 * turn rpm on since we still have a lot of CRTC turnning
392 mdfld_dsi_dbi_set_power(encoder
, false);
394 dev_priv
->dispstatus
= false;
400 * Update the DBI MIPI Panel Frame Buffer.
402 static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output
*dbi_output
,
405 struct mdfld_dsi_pkg_sender
*sender
=
406 mdfld_dsi_encoder_get_pkg_sender(&dbi_output
->base
);
407 struct drm_device
*dev
= dbi_output
->dev
;
408 struct drm_crtc
*crtc
= dbi_output
->base
.base
.crtc
;
409 struct psb_intel_crtc
*psb_crtc
= (crtc
) ?
410 to_psb_intel_crtc(crtc
) : NULL
;
411 u32 dpll_reg
= MRST_DPLL_A
;
412 u32 dspcntr_reg
= DSPACNTR
;
413 u32 pipeconf_reg
= PIPEACONF
;
414 u32 dsplinoff_reg
= DSPALINOFF
;
415 u32 dspsurf_reg
= DSPASURF
;
418 /* If mode setting on-going, back off */
419 if ((dbi_output
->mode_flags
& MODE_SETTING_ON_GOING
) ||
420 (psb_crtc
&& psb_crtc
->mode_flags
& MODE_SETTING_ON_GOING
) ||
421 !(dbi_output
->mode_flags
& MODE_SETTING_ENCODER_DONE
))
425 dspcntr_reg
= DSPCCNTR
;
426 pipeconf_reg
= PIPECCONF
;
427 dsplinoff_reg
= DSPCLINOFF
;
428 dspsurf_reg
= DSPCSURF
;
429 reg_offset
= MIPIC_REG_OFFSET
;
432 if (!gma_power_begin(dev
, true)) {
433 dev_err(dev
->dev
, "hw begin failed\n");
437 /* Check DBI FIFO status */
438 if (!(REG_READ(dpll_reg
) & DPLL_VCO_ENABLE
) ||
439 !(REG_READ(dspcntr_reg
) & DISPLAY_PLANE_ENABLE
) ||
440 !(REG_READ(pipeconf_reg
) & DISPLAY_PLANE_ENABLE
))
443 /* Refresh plane changes */
444 REG_WRITE(dsplinoff_reg
, REG_READ(dsplinoff_reg
));
445 REG_WRITE(dspsurf_reg
, REG_READ(dspsurf_reg
));
446 REG_READ(dspsurf_reg
);
448 mdfld_dsi_send_dcs(sender
,
453 MDFLD_DSI_SEND_PACKAGE
);
455 dbi_output
->dsr_fb_update_done
= true;
460 static int tpo_cmd_get_panel_info(struct drm_device
*dev
,
462 struct panel_info
*pi
)
467 pi
->width_mm
= TPO_PANEL_WIDTH
;
468 pi
->height_mm
= TPO_PANEL_HEIGHT
;
474 /* TPO DBI encoder helper funcs */
475 static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs
= {
476 .dpms
= mdfld_dsi_dbi_dpms
,
477 .mode_fixup
= mdfld_dsi_dbi_mode_fixup
,
478 .prepare
= mdfld_dsi_dbi_prepare
,
479 .mode_set
= mdfld_dsi_dbi_mode_set
,
480 .commit
= mdfld_dsi_dbi_commit
,
483 /* TPO DBI encoder funcs */
484 static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs
= {
485 .destroy
= drm_encoder_cleanup
,
488 void tpo_cmd_init(struct drm_device
*dev
, struct panel_funcs
*p_funcs
)
490 p_funcs
->encoder_funcs
= &mdfld_dsi_dbi_encoder_funcs
;
491 p_funcs
->encoder_helper_funcs
= &mdfld_dsi_dbi_helper_funcs
;
492 p_funcs
->get_config_mode
= &tpo_cmd_get_config_mode
;
493 p_funcs
->update_fb
= mdfld_dsi_dbi_update_fb
;
494 p_funcs
->get_panel_info
= tpo_cmd_get_panel_info
;