2 * Copyright © 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, 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:
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 * jim liu <jim.liu@intel.com>
25 * Jackie Li<yaodong.li@intel.com>
28 #include "mdfld_dsi_output.h"
29 #include "mdfld_dsi_dbi.h"
30 #include "mdfld_dsi_dpi.h"
31 #include "mdfld_output.h"
32 #include <asm/intel_scu_ipc.h>
33 #include "mdfld_dsi_pkg_sender.h"
34 #include <linux/pm_runtime.h>
36 #define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
38 static int CABC_control
= 1;
39 static int LABC_control
= 1;
41 module_param (CABC_control
, int, 0644);
42 module_param (LABC_control
, int, 0644);
45 * make these MCS command global
46 * we don't need 'movl' everytime we send them.
47 * FIXME: these datas were provided by OEM, we should get them from GCT.
49 static u32 mdfld_dbi_mcs_hysteresis
[] = {
50 0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
51 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
52 0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
53 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
57 static u32 mdfld_dbi_mcs_display_profile
[] = {
58 0x50281450, 0x0000c882, 0x00000000, 0x00000000,
62 static u32 mdfld_dbi_mcs_kbbc_profile
[] = {
63 0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
66 static u32 mdfld_dbi_mcs_gamma_profile
[] = {
67 0x81111158, 0x88888888, 0x88888888,
71 * write hysteresis values.
73 static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config
*dsi_config
,
76 struct mdfld_dsi_pkg_sender
*sender
= mdfld_dsi_get_pkg_sender(dsi_config
);
82 mdfld_dsi_send_mcs_long_hs(sender
,
83 mdfld_dbi_mcs_hysteresis
,
85 MDFLD_DSI_SEND_PACKAGE
);
89 * write display profile values.
91 static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config
*dsi_config
, int pipe
)
93 struct mdfld_dsi_pkg_sender
*sender
= mdfld_dsi_get_pkg_sender(dsi_config
);
99 mdfld_dsi_send_mcs_long_hs(sender
,
100 mdfld_dbi_mcs_display_profile
,
102 MDFLD_DSI_SEND_PACKAGE
);
106 * write KBBC profile values.
108 static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config
* dsi_config
, int pipe
)
110 struct mdfld_dsi_pkg_sender
*sender
= mdfld_dsi_get_pkg_sender(dsi_config
);
116 mdfld_dsi_send_mcs_long_hs(sender
,
117 mdfld_dbi_mcs_kbbc_profile
,
119 MDFLD_DSI_SEND_PACKAGE
);
123 * write gamma setting.
125 static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config
*dsi_config
, int pipe
)
127 struct mdfld_dsi_pkg_sender
*sender
= mdfld_dsi_get_pkg_sender(dsi_config
);
133 mdfld_dsi_send_mcs_long_hs(sender
,
134 mdfld_dbi_mcs_gamma_profile
,
136 MDFLD_DSI_SEND_PACKAGE
);
140 * Check and see if the generic control or data buffer is empty and ready.
142 void mdfld_dsi_gen_fifo_ready (struct drm_device
*dev
, u32 gen_fifo_stat_reg
, u32 fifo_stat
)
144 u32 GEN_BF_time_out_count
= 0;
146 /* Check MIPI Adatper command registers */
147 for (GEN_BF_time_out_count
= 0; GEN_BF_time_out_count
< GEN_FB_TIME_OUT
; GEN_BF_time_out_count
++)
149 if ((REG_READ(gen_fifo_stat_reg
) & fifo_stat
) == fifo_stat
)
154 if (GEN_BF_time_out_count
== GEN_FB_TIME_OUT
)
156 "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n",
161 * Manage the DSI MIPI keyboard and display brightness.
162 * FIXME: this is exported to OSPM code. should work out an specific
163 * display interface to OSPM.
165 void mdfld_dsi_brightness_init(struct mdfld_dsi_config
*dsi_config
, int pipe
)
167 struct mdfld_dsi_pkg_sender
*sender
= mdfld_dsi_get_pkg_sender(dsi_config
);
168 struct drm_device
*dev
= sender
->dev
;
169 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
176 /* Set default display backlight value to 85% (0xd8)*/
177 mdfld_dsi_send_mcs_short_hs(sender
,
178 write_display_brightness
,
181 MDFLD_DSI_SEND_PACKAGE
);
183 /* Set minimum brightness setting of CABC function to 20% (0x33)*/
184 mdfld_dsi_send_mcs_short_hs(sender
,
185 write_cabc_min_bright
,
188 MDFLD_DSI_SEND_PACKAGE
);
190 mdfld_dsi_write_hysteresis(dsi_config
, pipe
);
191 mdfld_dsi_write_display_profile (dsi_config
, pipe
);
192 mdfld_dsi_write_kbbc_profile (dsi_config
, pipe
);
193 mdfld_dsi_write_gamma_setting (dsi_config
, pipe
);
195 /* Enable backlight or/and LABC */
196 gen_ctrl_val
= BRIGHT_CNTL_BLOCK_ON
| DISPLAY_DIMMING_ON
| BACKLIGHT_ON
;
197 if (LABC_control
== 1 || CABC_control
== 1)
198 gen_ctrl_val
|= DISPLAY_DIMMING_ON
| DISPLAY_BRIGHTNESS_AUTO
| GAMMA_AUTO
;
200 if (LABC_control
== 1)
201 gen_ctrl_val
|= AMBIENT_LIGHT_SENSE_ON
;
203 dev_priv
->mipi_ctrl_display
= gen_ctrl_val
;
205 mdfld_dsi_send_mcs_short_hs(sender
,
209 MDFLD_DSI_SEND_PACKAGE
);
211 if (CABC_control
== 0)
213 mdfld_dsi_send_mcs_short_hs(sender
,
217 MDFLD_DSI_SEND_PACKAGE
);
221 * Manage the mipi display brightness.
222 * TODO: refine this interface later
224 void mdfld_dsi_brightness_control(struct drm_device
*dev
, int pipe
, int level
)
226 struct mdfld_dsi_pkg_sender
*sender
;
227 struct drm_psb_private
*dev_priv
;
228 struct mdfld_dsi_config
*dsi_config
;
232 if (!dev
|| (pipe
!= 0 && pipe
!= 2)) {
233 dev_err(dev
->dev
, "Invalid parameter\n");
237 p_type
= mdfld_get_panel_type(dev
, 0);
239 dev_priv
= dev
->dev_private
;
242 dsi_config
= dev_priv
->dsi_configs
[1];
244 dsi_config
= dev_priv
->dsi_configs
[0];
246 sender
= mdfld_dsi_get_pkg_sender(dsi_config
);
253 gen_ctrl_val
= ((level
* 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL
) & 0xff;
256 "pipe = %d, gen_ctrl_val = %d. \n", pipe
, gen_ctrl_val
);
258 if(p_type
== TMD_VID
|| p_type
== TMD_CMD
){
259 /* Set display backlight value */
260 mdfld_dsi_send_mcs_short_hs(sender
,
261 tmd_write_display_brightness
,
264 MDFLD_DSI_SEND_PACKAGE
);
266 /* Set display backlight value */
267 mdfld_dsi_send_mcs_short_hs(sender
,
268 write_display_brightness
,
271 MDFLD_DSI_SEND_PACKAGE
);
274 /* Enable backlight control */
278 gen_ctrl_val
= dev_priv
->mipi_ctrl_display
;
280 mdfld_dsi_send_mcs_short_hs(sender
,
284 MDFLD_DSI_SEND_PACKAGE
);
289 * shut down DSI controller
291 void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config
* dsi_config
, int pipe
)
293 struct drm_device
* dev
;
294 u32 reg_offset
= pipe
? MIPIC_REG_OFFSET
: 0;
302 dev
= dsi_config
->dev
;
304 if (!gma_power_begin(dev
, true)) {
305 dev_err(dev
->dev
, "hw begin failed\n");
309 if(!(REG_READ(MIPIA_DEVICE_READY_REG
+ reg_offset
) & DSI_DEVICE_READY
))
312 /* Send shut down package, clean packet send bit first */
313 if(REG_READ(MIPIA_INTR_STAT_REG
+ reg_offset
) & DSI_INTR_STATE_SPL_PKG_SENT
) {
314 REG_WRITE((MIPIA_INTR_STAT_REG
+ reg_offset
),
315 (REG_READ(MIPIA_INTR_STAT_REG
+ reg_offset
) | DSI_INTR_STATE_SPL_PKG_SENT
));
318 /*send shut down package in HS*/
319 REG_WRITE((MIPIA_DPI_CONTROL_REG
+ reg_offset
), DSI_DPI_CTRL_HS_SHUTDOWN
);
323 * make sure shut down is sent.
324 * FIXME: add max retry counter
326 while(!(REG_READ(MIPIA_INTR_STAT_REG
+ reg_offset
) & DSI_INTR_STATE_SPL_PKG_SENT
)) {
330 dev_err(dev
->dev
, "timeout\n");
335 /*sleep 1 ms to ensure shutdown finished*/
339 REG_WRITE((MIPIA_DEVICE_READY_REG
+ reg_offset
),
340 (REG_READ(MIPIA_DEVICE_READY_REG
+ reg_offset
) & ~DSI_DEVICE_READY
));
346 void mdfld_dsi_controller_startup(struct mdfld_dsi_config
* dsi_config
, int pipe
)
348 struct drm_device
* dev
;
349 u32 reg_offset
= pipe
? MIPIC_REG_OFFSET
: 0;
358 dev
= dsi_config
->dev
;
359 dev_dbg(dev
->dev
, "starting up DSI controller on pipe %d...\n", pipe
);
361 if (!gma_power_begin(dev
, true)) {
362 dev_err(dev
->dev
, "hw begin failed\n");
366 if((REG_READ(MIPIA_DEVICE_READY_REG
+ reg_offset
) & DSI_DEVICE_READY
))
369 /*if config DPI, turn on DPI interface*/
370 if(dsi_config
->type
== MDFLD_DSI_ENCODER_DPI
) {
371 if(REG_READ(MIPIA_INTR_STAT_REG
+ reg_offset
) & DSI_INTR_STATE_SPL_PKG_SENT
) {
372 REG_WRITE((MIPIA_INTR_STAT_REG
+ reg_offset
), DSI_INTR_STATE_SPL_PKG_SENT
);
375 REG_WRITE((MIPIA_DPI_CONTROL_REG
+ reg_offset
), DSI_DPI_CTRL_HS_TURN_ON
);
378 * make sure shut down is sent.
379 * FIXME: add max retry counter
381 while(!(REG_READ(MIPIA_INTR_STAT_REG
+ reg_offset
) & DSI_INTR_STATE_SPL_PKG_SENT
)) {
384 dev_err(dev
->dev
, "timeout\n");
393 REG_WRITE((MIPIA_DEVICE_READY_REG
+ reg_offset
),
394 (REG_READ(MIPIA_DEVICE_READY_REG
+ reg_offset
) | DSI_DEVICE_READY
));
401 static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config
*dsi_config
,
406 struct mdfld_dsi_pkg_sender
*sender
407 = mdfld_dsi_get_pkg_sender(dsi_config
);
409 if (!sender
|| !data
) {
410 DRM_ERROR("Invalid parameter\n");
414 if (transmission
== MDFLD_DSI_HS_TRANSMISSION
)
415 return mdfld_dsi_read_mcs_hs(sender
, dcs
, data
, 1);
416 else if (transmission
== MDFLD_DSI_LP_TRANSMISSION
)
417 return mdfld_dsi_read_mcs_lp(sender
, dcs
, data
, 1);
422 int mdfld_dsi_get_power_mode(struct mdfld_dsi_config
*dsi_config
,
426 if (!dsi_config
|| !mode
) {
427 DRM_ERROR("Invalid parameter\n");
431 return mdfld_dsi_get_panel_status(dsi_config
, 0x0a, mode
, transmission
);
434 int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config
*dsi_config
,
438 if (!dsi_config
|| !result
) {
439 DRM_ERROR("Invalid parameter\n");
443 return mdfld_dsi_get_panel_status(dsi_config
, 0x0f, result
,
448 * NOTE: this function was used by OSPM.
449 * TODO: will be removed later, should work out display interfaces for OSPM
451 void mdfld_dsi_controller_init(struct mdfld_dsi_config
* dsi_config
, int pipe
)
453 if(!dsi_config
|| ((pipe
!= 0) && (pipe
!= 2))) {
459 mdfld_dsi_dpi_controller_init(dsi_config
, pipe
);
461 mdfld_dsi_controller_dbi_init(dsi_config
, pipe
);
464 static void mdfld_dsi_connector_save(struct drm_connector
* connector
)
468 static void mdfld_dsi_connector_restore(struct drm_connector
* connector
)
472 static enum drm_connector_status
mdfld_dsi_connector_detect(struct drm_connector
* connector
, bool force
)
474 struct psb_intel_output
*psb_output
475 = to_psb_intel_output(connector
);
476 struct mdfld_dsi_connector
*dsi_connector
477 = MDFLD_DSI_CONNECTOR(psb_output
);
478 return dsi_connector
->status
;
481 static int mdfld_dsi_connector_set_property(struct drm_connector
*connector
,
482 struct drm_property
*property
,
485 struct drm_encoder
*encoder
= connector
->encoder
;
487 if (!strcmp(property
->name
, "scaling mode") && encoder
) {
488 struct psb_intel_crtc
* psb_crtc
= to_psb_intel_crtc(encoder
->crtc
);
489 bool bTransitionFromToCentered
;
496 case DRM_MODE_SCALE_FULLSCREEN
:
498 case DRM_MODE_SCALE_NO_SCALE
:
500 case DRM_MODE_SCALE_ASPECT
:
506 if (drm_connector_property_get_value(connector
, property
, &curValue
))
509 if (curValue
== value
)
512 if (drm_connector_property_set_value(connector
, property
, value
))
515 bTransitionFromToCentered
= (curValue
== DRM_MODE_SCALE_NO_SCALE
) ||
516 (value
== DRM_MODE_SCALE_NO_SCALE
);
518 if (psb_crtc
->saved_mode
.hdisplay
!= 0 &&
519 psb_crtc
->saved_mode
.vdisplay
!= 0) {
520 if (bTransitionFromToCentered
) {
521 if (!drm_crtc_helper_set_mode(encoder
->crtc
, &psb_crtc
->saved_mode
,
522 encoder
->crtc
->x
, encoder
->crtc
->y
, encoder
->crtc
->fb
))
525 struct drm_encoder_helper_funcs
*pEncHFuncs
= encoder
->helper_private
;
526 pEncHFuncs
->mode_set(encoder
, &psb_crtc
->saved_mode
,
527 &psb_crtc
->saved_adjusted_mode
);
530 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
531 } else if (!strcmp(property
->name
, "backlight") && encoder
) {
532 struct drm_psb_private
*dev_priv
= encoder
->dev
->dev_private
;
533 struct backlight_device
*psb_bd
= dev_priv
->backlight_device
;
534 dev_dbg(encoder
->dev
->dev
, "backlight level = %d\n", (int)value
);
535 if (drm_connector_property_set_value(connector
, property
, value
))
538 dev_dbg(encoder
->dev
->dev
,
539 "set brightness to %d", (int)value
);
541 psb_bd
->props
.brightness
= value
;
542 backlight_update_status(psb_bd
);
553 static void mdfld_dsi_connector_destroy(struct drm_connector
*connector
)
555 struct psb_intel_output
* psb_output
= to_psb_intel_output(connector
);
556 struct mdfld_dsi_connector
* dsi_connector
= MDFLD_DSI_CONNECTOR(psb_output
);
557 struct mdfld_dsi_pkg_sender
* sender
;
562 drm_sysfs_connector_remove(connector
);
563 drm_connector_cleanup(connector
);
565 sender
= dsi_connector
->pkg_sender
;
567 mdfld_dsi_pkg_sender_destroy(sender
);
569 kfree(dsi_connector
);
572 static int mdfld_dsi_connector_get_modes(struct drm_connector
* connector
)
574 struct psb_intel_output
* psb_output
= to_psb_intel_output(connector
);
575 struct mdfld_dsi_connector
* dsi_connector
= MDFLD_DSI_CONNECTOR(psb_output
);
576 struct mdfld_dsi_config
* dsi_config
= mdfld_dsi_get_config(dsi_connector
);
577 struct drm_display_mode
* fixed_mode
= dsi_config
->fixed_mode
;
578 struct drm_display_mode
* dup_mode
= NULL
;
579 struct drm_device
* dev
= connector
->dev
;
581 connector
->display_info
.min_vfreq
= 0;
582 connector
->display_info
.max_vfreq
= 200;
583 connector
->display_info
.min_hfreq
= 0;
584 connector
->display_info
.max_hfreq
= 200;
587 dev_dbg(dev
->dev
, "fixed_mode %dx%d\n",
588 fixed_mode
->hdisplay
, fixed_mode
->vdisplay
);
590 dup_mode
= drm_mode_duplicate(dev
, fixed_mode
);
591 drm_mode_probed_add(connector
, dup_mode
);
594 dev_err(dev
->dev
, "Didn't get any modes!\n");
598 static int mdfld_dsi_connector_mode_valid(struct drm_connector
* connector
, struct drm_display_mode
* mode
)
600 struct psb_intel_output
* psb_output
= to_psb_intel_output(connector
);
601 struct mdfld_dsi_connector
* dsi_connector
= MDFLD_DSI_CONNECTOR(psb_output
);
602 struct mdfld_dsi_config
* dsi_config
= mdfld_dsi_get_config(dsi_connector
);
603 struct drm_display_mode
* fixed_mode
= dsi_config
->fixed_mode
;
605 dev_dbg(connector
->dev
->dev
, "mode %p, fixed mode %p\n",
608 if(mode
->flags
& DRM_MODE_FLAG_DBLSCAN
)
609 return MODE_NO_DBLESCAN
;
611 if(mode
->flags
& DRM_MODE_FLAG_INTERLACE
)
612 return MODE_NO_INTERLACE
;
615 * FIXME: current DC has no fitting unit, reject any mode setting request
616 * will figure out a way to do up-scaling(pannel fitting) later.
619 if(mode
->hdisplay
!= fixed_mode
->hdisplay
)
622 if(mode
->vdisplay
!= fixed_mode
->vdisplay
)
625 dev_dbg(connector
->dev
->dev
, "mode ok\n");
630 static void mdfld_dsi_connector_dpms(struct drm_connector
*connector
, int mode
)
632 #ifdef CONFIG_PM_RUNTIME
633 struct drm_device
* dev
= connector
->dev
;
634 struct drm_psb_private
* dev_priv
= dev
->dev_private
;
635 bool panel_on
, panel_on2
;
637 /* First, execute DPMS */
638 drm_helper_connector_dpms(connector
, mode
);
640 #ifdef CONFIG_PM_RUNTIME
641 if(mdfld_panel_dpi(dev
)) {
643 panel_on
= dev_priv
->dpi_panel_on
;
644 panel_on2
= dev_priv
->dpi_panel_on2
;
647 panel_on
= dev_priv
->dbi_panel_on
;
648 panel_on2
= dev_priv
->dbi_panel_on2
;
651 /* Then check all display panels + monitors status */
652 /* Make sure that the Display (B) sub-system status isn't i3 when
653 * R/W the DC register, otherwise "Fabric error" issue would occur
654 * during S0i3 state. */
655 if(!panel_on
&& !panel_on2
&& !(REG_READ(HDMIB_CONTROL
)
657 /* Request rpm idle */
658 if(dev_priv
->rpm_enabled
)
659 pm_request_idle(&dev
->pdev
->dev
);
662 * if rpm wasn't enabled yet, try to allow it
663 * FIXME: won't enable rpm for DPI since DPI
664 * CRTC setting is a little messy now.
668 if(!dev_priv
->rpm_enabled
&& !mdfld_panel_dpi(dev
))
669 ospm_runtime_pm_allow(dev
);
674 static struct drm_encoder
*mdfld_dsi_connector_best_encoder(
675 struct drm_connector
*connector
)
677 struct psb_intel_output
* psb_output
= to_psb_intel_output(connector
);
678 struct mdfld_dsi_connector
* dsi_connector
= MDFLD_DSI_CONNECTOR(psb_output
);
679 struct mdfld_dsi_config
* dsi_config
= mdfld_dsi_get_config(dsi_connector
);
680 struct mdfld_dsi_encoder
* encoder
= NULL
;
682 if(dsi_config
->type
== MDFLD_DSI_ENCODER_DBI
)
683 encoder
= dsi_config
->encoders
[MDFLD_DSI_ENCODER_DBI
];
684 else if (dsi_config
->type
== MDFLD_DSI_ENCODER_DPI
)
685 encoder
= dsi_config
->encoders
[MDFLD_DSI_ENCODER_DPI
];
687 dev_dbg(connector
->dev
->dev
, "get encoder %p\n", encoder
);
690 dev_err(connector
->dev
->dev
,
691 "Invalid encoder for type %d\n", dsi_config
->type
);
694 dsi_config
->encoder
= encoder
;
695 return &encoder
->base
;
698 /* DSI connector funcs */
699 static const struct drm_connector_funcs mdfld_dsi_connector_funcs
= {
700 .dpms
= /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms
,
701 .save
= mdfld_dsi_connector_save
,
702 .restore
= mdfld_dsi_connector_restore
,
703 .detect
= mdfld_dsi_connector_detect
,
704 .fill_modes
= drm_helper_probe_single_connector_modes
,
705 .set_property
= mdfld_dsi_connector_set_property
,
706 .destroy
= mdfld_dsi_connector_destroy
,
709 /* DSI connector helper funcs */
710 static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs
= {
711 .get_modes
= mdfld_dsi_connector_get_modes
,
712 .mode_valid
= mdfld_dsi_connector_mode_valid
,
713 .best_encoder
= mdfld_dsi_connector_best_encoder
,
716 static int mdfld_dsi_get_default_config(struct drm_device
* dev
,
717 struct mdfld_dsi_config
* config
, int pipe
)
719 if(!dev
|| !config
) {
725 config
->type
= mdfld_panel_dpi(dev
);
726 config
->lane_count
= 2;
727 config
->channel_num
= 0;
728 /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
729 if (mdfld_get_panel_type(dev
, pipe
) == TMD_VID
) {
730 config
->video_mode
= MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE
;
732 config
->video_mode
= MDFLD_DSI_VIDEO_BURST_MODE
;
739 * Returns the panel fixed mode from configuration.
741 struct drm_display_mode
*
742 mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config
* dsi_config
, int pipe
)
744 struct drm_device
*dev
= dsi_config
->dev
;
745 struct drm_display_mode
*mode
;
746 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
747 struct mrst_timing_info
*ti
= &dev_priv
->gct_data
.DTD
;
748 bool use_gct
= false;
750 mode
= kzalloc(sizeof(*mode
), GFP_KERNEL
);
752 dev_err(dev
->dev
, "Out of memory for mode\n");
756 dev_dbg(dev
->dev
, "gct find MIPI panel.\n");
758 mode
->hdisplay
= (ti
->hactive_hi
<< 8) | ti
->hactive_lo
;
759 mode
->vdisplay
= (ti
->vactive_hi
<< 8) | ti
->vactive_lo
;
760 mode
->hsync_start
= mode
->hdisplay
+ \
761 ((ti
->hsync_offset_hi
<< 8) | \
762 ti
->hsync_offset_lo
);
763 mode
->hsync_end
= mode
->hsync_start
+ \
764 ((ti
->hsync_pulse_width_hi
<< 8) | \
765 ti
->hsync_pulse_width_lo
);
766 mode
->htotal
= mode
->hdisplay
+ ((ti
->hblank_hi
<< 8) | \
768 mode
->vsync_start
= \
769 mode
->vdisplay
+ ((ti
->vsync_offset_hi
<< 8) | \
770 ti
->vsync_offset_lo
);
772 mode
->vsync_start
+ ((ti
->vsync_pulse_width_hi
<< 8) | \
773 ti
->vsync_pulse_width_lo
);
774 mode
->vtotal
= mode
->vdisplay
+ \
775 ((ti
->vblank_hi
<< 8) | ti
->vblank_lo
);
776 mode
->clock
= ti
->pixel_clock
* 10;
778 if(dsi_config
->type
== MDFLD_DSI_ENCODER_DPI
) {
779 if (mdfld_get_panel_type(dev
, pipe
) == TMD_VID
) {
780 mode
->hdisplay
= 480;
781 mode
->vdisplay
= 854;
782 mode
->hsync_start
= 487;
783 mode
->hsync_end
= 490;
785 mode
->vsync_start
= 861;
786 mode
->vsync_end
= 865;
790 mode
->hdisplay
= 864;
791 mode
->vdisplay
= 480;
792 mode
->hsync_start
= 873;
793 mode
->hsync_end
= 876;
795 mode
->vsync_start
= 487;
796 mode
->vsync_end
= 490;
800 } else if(dsi_config
->type
== MDFLD_DSI_ENCODER_DBI
) {
801 mode
->hdisplay
= 864;
802 mode
->vdisplay
= 480;
803 mode
->hsync_start
= 872;
804 mode
->hsync_end
= 876;
806 mode
->vsync_start
= 482;
807 mode
->vsync_end
= 494;
814 drm_mode_set_name(mode
);
815 drm_mode_set_crtcinfo(mode
, 0);
817 mode
->type
|= DRM_MODE_TYPE_PREFERRED
;
822 int mdfld_dsi_panel_reset(int pipe
)
835 DRM_ERROR("Invalid output\n");
839 ret
= gpio_request(gpio
, "gfx");
841 DRM_ERROR("gpio_rqueset failed\n");
845 ret
= gpio_direction_output(gpio
, 1);
847 DRM_ERROR("gpio_direction_output failed\n");
854 if (gpio_is_valid(gpio
))
863 * @pipe pipe number. 0 or 2
866 * Do the initialization of a MIPI output, including create DRM mode objects
867 * initialization of DSI output on @pipe
869 void mdfld_dsi_output_init(struct drm_device
*dev
,
871 struct mdfld_dsi_config
*config
,
872 struct panel_funcs
* p_cmd_funcs
,
873 struct panel_funcs
* p_vid_funcs
)
875 struct mdfld_dsi_config
* dsi_config
;
876 struct mdfld_dsi_connector
* dsi_connector
;
877 struct psb_intel_output
* psb_output
;
878 struct drm_connector
* connector
;
879 struct mdfld_dsi_encoder
* encoder
;
880 struct drm_psb_private
* dev_priv
= dev
->dev_private
;
881 struct panel_info dsi_panel_info
;
882 u32 width_mm
, height_mm
;
884 dev_dbg(dev
->dev
, "init DSI output on pipe %d\n", pipe
);
886 if(!dev
|| ((pipe
!= 0) && (pipe
!= 2))) {
891 /*create a new connetor*/
892 dsi_connector
= kzalloc(sizeof(struct mdfld_dsi_connector
), GFP_KERNEL
);
894 DRM_ERROR("No memory");
898 dsi_connector
->pipe
= pipe
;
904 dsi_config
= kzalloc(sizeof(struct mdfld_dsi_config
), GFP_KERNEL
);
907 "cannot allocate memory for DSI config\n");
911 mdfld_dsi_get_default_config(dev
, dsi_config
, pipe
);
914 dsi_connector
->private = dsi_config
;
916 dsi_config
->changed
= 1;
917 dsi_config
->dev
= dev
;
919 /* Init fixed mode basing on DSI config type */
920 if(dsi_config
->type
== MDFLD_DSI_ENCODER_DBI
) {
921 dsi_config
->fixed_mode
= p_cmd_funcs
->get_config_mode(dev
);
922 if(p_cmd_funcs
->get_panel_info(dev
, pipe
, &dsi_panel_info
))
924 } else if(dsi_config
->type
== MDFLD_DSI_ENCODER_DPI
) {
925 dsi_config
->fixed_mode
= p_vid_funcs
->get_config_mode(dev
);
926 if(p_vid_funcs
->get_panel_info(dev
, pipe
, &dsi_panel_info
))
930 width_mm
= dsi_panel_info
.width_mm
;
931 height_mm
= dsi_panel_info
.height_mm
;
933 dsi_config
->mode
= dsi_config
->fixed_mode
;
934 dsi_config
->connector
= dsi_connector
;
936 if(!dsi_config
->fixed_mode
) {
937 dev_err(dev
->dev
, "No pannel fixed mode was found\n");
941 if(pipe
&& dev_priv
->dsi_configs
[0]) {
942 dsi_config
->dvr_ic_inited
= 0;
943 dev_priv
->dsi_configs
[1] = dsi_config
;
944 } else if(pipe
== 0) {
945 dsi_config
->dvr_ic_inited
= 1;
946 dev_priv
->dsi_configs
[0] = dsi_config
;
948 dev_err(dev
->dev
, "Trying to init MIPI1 before MIPI0\n");
952 /*init drm connector object*/
953 psb_output
= &dsi_connector
->base
;
955 psb_output
->type
= (pipe
== 0) ? INTEL_OUTPUT_MIPI
: INTEL_OUTPUT_MIPI2
;
957 connector
= &psb_output
->base
;
958 /* Revisit type if MIPI/HDMI bridges ever appear on Medfield */
959 drm_connector_init(dev
, connector
, &mdfld_dsi_connector_funcs
,
960 DRM_MODE_CONNECTOR_LVDS
);
961 drm_connector_helper_add(connector
, &mdfld_dsi_connector_helper_funcs
);
963 connector
->display_info
.subpixel_order
= SubPixelHorizontalRGB
;
964 connector
->display_info
.width_mm
= width_mm
;
965 connector
->display_info
.height_mm
= height_mm
;
966 connector
->interlace_allowed
= false;
967 connector
->doublescan_allowed
= false;
969 /* Attach properties */
970 drm_connector_attach_property(connector
, dev
->mode_config
.scaling_mode_property
, DRM_MODE_SCALE_FULLSCREEN
);
971 drm_connector_attach_property(connector
, dev_priv
->backlight_property
, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL
);
973 /* Init DSI package sender on this output */
974 if (mdfld_dsi_pkg_sender_init(dsi_connector
, pipe
)) {
975 DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe
);
979 /* Init DBI & DPI encoders */
981 encoder
= mdfld_dsi_dbi_init(dev
, dsi_connector
, p_cmd_funcs
);
983 dev_err(dev
->dev
, "Create DBI encoder failed\n");
986 encoder
->private = dsi_config
;
987 dsi_config
->encoders
[MDFLD_DSI_ENCODER_DBI
] = encoder
;
991 encoder
= mdfld_dsi_dpi_init(dev
, dsi_connector
, p_vid_funcs
);
993 dev_err(dev
->dev
, "Create DPI encoder failed\n");
996 encoder
->private = dsi_config
;
997 dsi_config
->encoders
[MDFLD_DSI_ENCODER_DPI
] = encoder
;
1000 drm_sysfs_connector_add(connector
);
1003 /*TODO: add code to destroy outputs on error*/
1006 mdfld_dsi_pkg_sender_destroy(dsi_connector
->pkg_sender
);
1008 drm_connector_cleanup(connector
);
1009 kfree(dsi_config
->fixed_mode
);
1012 kfree(dsi_connector
);