From bd2baf5d9a4453c8c1db409915ec466b5969b5cf Mon Sep 17 00:00:00 2001 From: Randy Xu Date: Sun, 11 Dec 2011 19:17:20 +0800 Subject: [PATCH] [Graphics/Display]: Port a bunch of patches from R2 BZ: 17008 This patch includes below bug fixing 0002-GFX-3D-2D-using-private-queue-instead-of-common-work.patch:BZ:4306 0003-GFX-Display-fix-V_1P22_VCCAON_DSI-rail-high.patch:BZ: 6670 0004-GFX-PM-Enable-GL3-attributes-including-auto-clock-g.patch:BZ: 6371, 8403, 8405, 8406, 8407 & 8408 0005-GFX-Display-Added-ULPS-support-to-DPI-driver.patch:BZ: 9284 0006-GFX-Display-replaced-busy-waits-20ms-with-mslee.patch:BZ: 9440 0007--PORT-FROM-R1-GFX-Display-update-pr2-cabc-control.patch:BZ: 8544 0008--PORT-FROM-R1-Graphics-Display-SGX-HW-recovery-ca.patch:BZ: 10106 0009--GFX-Display-Not-change-the-panel-devInfo-when-cre.patch:BZ: 11873 0010-Gfx-Display-Refined-scaling-setting-to-support-Cent.patch:BZ: 11093 0011-GFX-Improve-HDMI-rotation-mechanism-kernel.patch:BZ: 10804, 11517, 10736 0012-Gfx-Display-Fix-vblank-enable-disable-defect-in-HDM.patch:BZ: 11434 0013-psb_drm-obsolet-fields-can-be-deleted-in-psb_drm.h.patch:BZ: 9354 0014-Graphics-restore-the-BCD-reference-count-in-case-of.patch:BZ: 11670 0015-Gfx-Display-sending-HDMI-audio-suspended-resumed-ue.patch:BZ: 12415 0016-GFX-Display-add-code-to-support-HDMI-compliance.patch:BZ: 5876, 5879 0017-GFX-display-update-HDMI-AVI-info-support-kernel.patch:BZ: 5877 0018-Gfx-Display-Modify-DPMS-to-just-turn-off-HDMI-plane.patch:BZ: 12541 0019-GFX-display-Add-a-ioctl-interface-for-HDMIpipe-enabl.patch:BZ: 12881, 12949 0020-GFX-Display-fix-mimic-mode-will-be-changed-during-m.patch:BZ: 5876 0021-Graphic-Solve-klocwork-review-defects-for-pvr.patch:BZ: 13836 0022-Gfx-Display-fix-issue-of-HDMI-could-not-get-i2c-ada.patch:BZ: 14013 0023-GFX-Display-fix-refresh-info-not-right-of-MIPI-mode.patch:BZ: 13941 0024-Gfx-Display-fix-the-issue-of-HDMI-hotplug-could-not.patch:BZ: 13917 0025-GFX-HDCP-port-I2C-address-change-to-0x3A-without-re.patch:BZ: 14427 0026-GFX-display-add-code-to-support-HDMI-set-power-stat.patch:BZ: 13944 0027-Gfx-Display-Fix-issue-of-music-does-not-restart-on.patch:BZ: 13987 0028-GFX-Display-enhancement-HDMI-compliance-test-support.patch:BZ: 14104, 14617, 14627 0029-GFX-HDMI-HDCP-Fix-HDCP-cann-t-be-enabled-disabled.patch:BZ: 13724 0030-GFX-Display-Fix-call-issue-when-connect-HDMI.patch:BZ: 13468 0031-GFX-display-fix-HDMI-corrupted-after-resume-from-r.patch:BZ: 13067 0032-Gfx-Display-fix-issue-of-incoming-call-display-on-H.patch:BZ: 14113 0033-Gfx-Display-Ensure-HDMI-clock-is-enabled-before-HDM.patch:BZ: 14156 0034-GFX-display-update-hdmi_state-usage.patch:BZ: 14097 0035-GFX-display-flush-the-plane-changes-when-disable-e.patch:BZ: 15146 0036-GFX-display-fix-hdmi-dpms-fabric-error.-for-R2.patch:BZ: 14884, 14091, 12933 0037-GFX-Display-fix-OVADD-fabric-error-hdmi-resume-fail.patch:BZ: 15667 0038-GFX-Display-fix-lost-video-when-upplug-HDMI.patch:BZ: 15527 Change-Id: I35d6304f3cd84c6f45d3ef4c23637e4e41a68f83 Signed-off-by: Randy Xu Reviewed-on: http://android.intel.com:8080/26914 Reviewed-by: Hu, Austin Reviewed-by: buildbot Tested-by: buildbot --- drivers/gpu/drm/drm_edid.c | 2 +- drivers/i2c/busses/i2c-gpio.c | 2 +- drivers/staging/mrst/drv/mdfld_dsi_dpi.c | 78 +- drivers/staging/mrst/drv/mdfld_dsi_output.c | 6 +- drivers/staging/mrst/drv/mdfld_dsi_output.h | 4 +- drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.c | 5 + drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.h | 2 +- drivers/staging/mrst/drv/mdfld_gl3.c | 3 + drivers/staging/mrst/drv/mdfld_gl3.h | 25 + drivers/staging/mrst/drv/mdfld_hdcp.h | 2 +- drivers/staging/mrst/drv/mdfld_hdmi_audio.c | 42 +- drivers/staging/mrst/drv/mdfld_intel_hdcp.c | 33 +- drivers/staging/mrst/drv/mdfld_msic.c | 11 +- drivers/staging/mrst/drv/mdfld_msic.h | 1 + drivers/staging/mrst/drv/psb_drm.h | 21 +- drivers/staging/mrst/drv/psb_drv.c | 76 +- drivers/staging/mrst/drv/psb_drv.h | 8 +- drivers/staging/mrst/drv/psb_fb.c | 28 +- drivers/staging/mrst/drv/psb_intel_display2.c | 308 ++++---- drivers/staging/mrst/drv/psb_intel_drv.h | 3 + drivers/staging/mrst/drv/psb_intel_dsi.c | 3 + drivers/staging/mrst/drv/psb_intel_hdmi.c | 790 +++++++++++++++------ drivers/staging/mrst/drv/psb_intel_hdmi.h | 51 +- drivers/staging/mrst/drv/psb_intel_reg.h | 8 +- drivers/staging/mrst/drv/psb_irq.c | 8 +- drivers/staging/mrst/drv/psb_powermgmt.c | 77 +- drivers/staging/mrst/drv/psb_umevents.c | 7 + drivers/staging/mrst/drv/psb_umevents.h | 2 + drivers/staging/mrst/drv/tmd_6x10_vid.c | 56 +- drivers/staging/mrst/drv/tmd_vid.c | 4 +- drivers/staging/mrst/imgv/psb_msvdx.c | 14 +- drivers/staging/mrst/medfield/Makefile | 2 +- .../mrst/pvr/services4/srvkm/common/deviceclass.c | 4 +- 33 files changed, 1142 insertions(+), 544 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 1bbb85b..3330bc4 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -841,7 +841,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo; unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo; - unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; + unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 2 | pt->vsync_offset_pulse_width_lo >> 4; unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf); /* ignore tiny modes */ diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index a651779..369b056 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -211,7 +211,7 @@ static int __init i2c_gpio_init(void) return ret; } -subsys_initcall(i2c_gpio_init); +device_initcall(i2c_gpio_init); static void __exit i2c_gpio_exit(void) { diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dpi.c b/drivers/staging/mrst/drv/mdfld_dsi_dpi.c index 137d9b8..015974c 100755 --- a/drivers/staging/mrst/drv/mdfld_dsi_dpi.c +++ b/drivers/staging/mrst/drv/mdfld_dsi_dpi.c @@ -1179,6 +1179,54 @@ void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output * output, int pipe) /* dev_priv->dpi_panel_on = true; */ } +static int __dpi_enter_ulps_locked(struct mdfld_dsi_config *dsi_config) +{ + struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; + struct mdfld_dsi_hw_context *ctx = &dsi_config->dsi_hw_context; + struct drm_device *dev = dsi_config->dev; + struct mdfld_dsi_pkg_sender *sender + = mdfld_dsi_get_pkg_sender(dsi_config); + + ctx->device_ready = REG_READ(regs->device_ready_reg); + + if (ctx->device_ready & DSI_POWER_STATE_ULPS_MASK) { + DRM_ERROR("Broken ULPS states\n"); + return -EINVAL; + } + + /*wait for all FIFOs empty*/ + mdfld_dsi_wait_for_fifos_empty(sender); + + /*inform DSI host is to be put on ULPS*/ + ctx->device_ready |= DSI_POWER_STATE_ULPS_ENTER; + REG_WRITE(regs->device_ready_reg, ctx->device_ready); + + DRM_INFO("%s: entered ULPS state\n", __func__); + return 0; +} + +static int __dpi_exit_ulps_locked(struct mdfld_dsi_config *dsi_config) +{ + struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; + struct mdfld_dsi_hw_context *ctx = &dsi_config->dsi_hw_context; + struct drm_device *dev = dsi_config->dev; + + ctx->device_ready = REG_READ(regs->device_ready_reg); + + /*enter ULPS EXIT state*/ + ctx->device_ready &= ~DSI_POWER_STATE_ULPS_MASK; + ctx->device_ready |= DSI_POWER_STATE_ULPS_EXIT; + REG_WRITE(regs->device_ready_reg, ctx->device_ready); + + /*wait for 1ms as spec suggests*/ + mdelay(1); + + /*clear ULPS state*/ + ctx->device_ready &= ~DSI_POWER_STATE_ULPS_MASK; + REG_WRITE(regs->device_ready_reg, ctx->device_ready); + return 0; +} + /** * Power on sequence for video mode MIPI panel. * NOTE: do NOT modify this function @@ -1296,8 +1344,12 @@ static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config, REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff); REG_WRITE(regs->vgacntr_reg, ctx->vgacntr); + /*exit ULPS state*/ + __dpi_exit_ulps_locked(dsi_config); + /*Enable DSI Controller*/ REG_WRITE(regs->device_ready_reg, ctx->device_ready | BIT0); + /*set low power output hold*/ REG_WRITE(regs->mipi_reg, (ctx->mipi | BIT16)); @@ -1347,7 +1399,6 @@ static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config, if (p_funcs->set_brightness(dsi_config, ctx->lastbrightnesslevel)) DRM_ERROR("Failed to set panel brightness\n"); - power_on_err: ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return err; @@ -1427,11 +1478,16 @@ static int __dpi_panel_power_off(struct mdfld_dsi_config *dsi_config, /*Disable MIPI port*/ REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT31)); + /*clear Low power output hold*/ REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT16)); + /*Disable DSI controller*/ REG_WRITE(regs->device_ready_reg, (ctx->device_ready & ~BIT0)); + /*enter ULPS*/ + __dpi_enter_ulps_locked(dsi_config); + /*Disable DSI PLL*/ pipe0_enabled = (REG_READ(PIPEACONF) & BIT31) ? 1 : 0; pipe2_enabled = (REG_READ(PIPECCONF) & BIT31) ? 1 : 0; @@ -1483,7 +1539,7 @@ static int __mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) if (dsi_connector->status != connector_status_connected) return 0; - spin_lock(&dsi_config->context_lock); + mutex_lock(&dsi_config->context_lock); if (on && !dsi_config->dsi_hw_context.panel_on) { if (__dpi_panel_power_on(dsi_config, p_funcs)) { @@ -1495,12 +1551,6 @@ static int __mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) let panel in full color*/ mdfld_dsi_dpi_set_color_mode(dsi_config, false); } else if (!on && dsi_config->dsi_hw_context.panel_on) { - if (dpi_output->first_boot) { - PSB_DEBUG_ENTRY( - " Skip turn off, if first time boot and panel have enabled\n"); - dpi_output->first_boot = 0; - goto fun_exit; - } if (__dpi_panel_power_off(dsi_config, p_funcs)) { DRM_ERROR("Failed to power off\n"); goto set_power_err; @@ -1508,11 +1558,11 @@ static int __mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) dsi_config->dsi_hw_context.panel_on = 0; } fun_exit: - spin_unlock(&dsi_config->context_lock); + mutex_unlock(&dsi_config->context_lock); PSB_DEBUG_ENTRY("successfully\n"); return 0; set_power_err: - spin_unlock(&dsi_config->context_lock); + mutex_unlock(&dsi_config->context_lock); PSB_DEBUG_ENTRY("unsuccessfully!!!!\n"); return -EAGAIN; } @@ -1540,12 +1590,12 @@ void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) pipeconf_reg = PIPECCONF; } -#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY /*start up display island if it was shutdown*/ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) return; +#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY if(on) { if (get_panel_type(dev, pipe) == TMD_VID){ if(dsi_device_ready) { @@ -1597,7 +1647,6 @@ void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) } - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); #else /** * if TMD panel call new power on/off sequences instead. @@ -1606,6 +1655,7 @@ void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) __mdfld_dsi_dpi_set_power(encoder, on); #endif + ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); } void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) @@ -1775,7 +1825,7 @@ static void __mdfld_dsi_dpi_set_timing(struct mdfld_dsi_config *config, mode = adjusted_mode; ctx = &config->dsi_hw_context; - spin_lock(&config->context_lock); + mutex_lock(&config->context_lock); /*dpi resolution*/ ctx->dpi_resolution = (mode->vdisplay << 16 | mode->hdisplay); @@ -1798,7 +1848,7 @@ static void __mdfld_dsi_dpi_set_timing(struct mdfld_dsi_config *config, if (config->pipe == 0) ctx->mipi = PASS_FROM_SPHY_TO_AFE | config->lane_config; - spin_unlock(&config->context_lock); + mutex_unlock(&config->context_lock); } void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, diff --git a/drivers/staging/mrst/drv/mdfld_dsi_output.c b/drivers/staging/mrst/drv/mdfld_dsi_output.c index 340147e..a644c20 100755 --- a/drivers/staging/mrst/drv/mdfld_dsi_output.c +++ b/drivers/staging/mrst/drv/mdfld_dsi_output.c @@ -345,7 +345,7 @@ void mdfld_dsi_brightness_control (struct drm_device *dev, int pipe, int level) OSPM_UHB_ONLY_IF_ON)) return; - spin_lock(&dsi_config->context_lock); + mutex_lock(&dsi_config->context_lock); if (!dsi_config->dsi_hw_context.panel_on) goto set_brightness_out; @@ -354,7 +354,7 @@ void mdfld_dsi_brightness_control (struct drm_device *dev, int pipe, int level) DRM_ERROR("Failed to set panel brightness\n"); set_brightness_out: - spin_unlock(&dsi_config->context_lock); + mutex_unlock(&dsi_config->context_lock); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); #endif } @@ -1037,7 +1037,7 @@ int mdfld_dsi_output_init(struct drm_device *dev, mdfld_dsi_regs_init(dsi_config, pipe); /*init DSI HW context lock*/ - spin_lock_init(&dsi_config->context_lock); + mutex_init(&dsi_config->context_lock); dsi_connector->private = dsi_config; diff --git a/drivers/staging/mrst/drv/mdfld_dsi_output.h b/drivers/staging/mrst/drv/mdfld_dsi_output.h index f8bfc39..d41caa9 100755 --- a/drivers/staging/mrst/drv/mdfld_dsi_output.h +++ b/drivers/staging/mrst/drv/mdfld_dsi_output.h @@ -84,7 +84,7 @@ #define DSI_DEVICE_READY (0x1) #define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1) #define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1) -#define DSI_POWER_STATE_ULPS_OFFSET (0x1) +#define DSI_POWER_STATE_ULPS_MASK (0x3 << 1) #define DSI_ONE_DATA_LANE (0x1) @@ -395,7 +395,7 @@ struct mdfld_dsi_config { struct mdfld_dsi_hw_registers regs; /*DSI hw context*/ - spinlock_t context_lock; + struct mutex context_lock; struct mdfld_dsi_hw_context dsi_hw_context; int pipe; diff --git a/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.c b/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.c index bb6f467..b61e220 100755 --- a/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.c +++ b/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.c @@ -1441,6 +1441,11 @@ int mdfld_dsi_send_dpi_spk_pkg_lp(struct mdfld_dsi_pkg_sender *sender, MDFLD_DSI_LP_TRANSMISSION); } +int mdfld_dsi_wait_for_fifos_empty(struct mdfld_dsi_pkg_sender *sender) +{ + return wait_for_all_fifos_empty(sender); +} + int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector * dsi_connector, int pipe) { int ret; diff --git a/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.h b/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.h index 26be3de..87afb13 100644 --- a/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.h +++ b/drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.h @@ -209,5 +209,5 @@ extern int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender, u8 cmd, u32 *data, u16 len); - +extern int mdfld_dsi_wait_for_fifos_empty(struct mdfld_dsi_pkg_sender *sender); #endif diff --git a/drivers/staging/mrst/drv/mdfld_gl3.c b/drivers/staging/mrst/drv/mdfld_gl3.c index e336262..8b77663 100644 --- a/drivers/staging/mrst/drv/mdfld_gl3.c +++ b/drivers/staging/mrst/drv/mdfld_gl3.c @@ -38,6 +38,9 @@ void gl3_enable(void) if (!ospm_power_using_hw_begin(OSPM_GL3_CACHE_ISLAND, true)) return; MDFLD_GL3_WRITE(MDFLD_GL3_ENABLE_CACHE, MDFLD_GL3_CONTROL); + /* set gl3 attributes */ + MDFLD_GL3_WRITE(GCL_CR_CTL2_ATTRIBUTES, MDFLD_GCL_CR_CTL2); + MDFLD_GL3_WRITE(MDFLD_GCL_CR_ECO_EVICT_INVAL, MDFLD_GCL_CR_ECO); PSB_DEBUG_GENERAL("gl3 cache enabled with mask %x\n", MDFLD_GL3_ENABLE_CACHE); ospm_power_using_hw_end(OSPM_GL3_CACHE_ISLAND); } diff --git a/drivers/staging/mrst/drv/mdfld_gl3.h b/drivers/staging/mrst/drv/mdfld_gl3.h index b170f2a..142852d 100644 --- a/drivers/staging/mrst/drv/mdfld_gl3.h +++ b/drivers/staging/mrst/drv/mdfld_gl3.h @@ -51,6 +51,7 @@ #define MDFLD_GCL_CR_CTL2 0xB0000 #define MDFLD_GCL_ERR_ADDR 0xB0004 /* address at location is the address that had the error */ +#define MDFLD_GCL_CR_ECO 0xB0030 /*GL3 ECO Register*/ #define MDFLD_GCL_ERR_STATUS 0xB0008 #define MDFLD_IMG_MASK 0x20A8 /* unmask bit 21 to get GL3 interrupts */ @@ -112,6 +113,30 @@ #define MDFLD_GL3_DISABLE_CACHE (MDFLD_GL3_ENABLE_CACHE | MDFLD_GL3_DISABLE) +/* + GL3 attributes controlled via GCL_CR_CTL2 +*/ +#define GCL_CR_CTL2_WRTHRU_ENA (1) +#define GCL_CR_CTL2_TAG_ECC_CHECK_ENABLE (1<<2) +#define GCL_CR_CTL2_GL3_GL3Q_GATING_DISABLE (1<<8) +#define GCL_CR_CTL2_GL3_GCL_GATING_DISABLE (1<<9) +#define GCL_CR_CTL2_GL3_L3_GATING_DISABLE (1<<10) +#define GCL_CR_CTL2_DATA_ECC_CHECK_ENABLE (1<<19) +#define GCL_CR_CTL2_L2_SLEEP_TRANSISTOR_STRENGTH_ENABLE (1<<20) + +#define GCL_CR_CTL2_ATTRIBUTES (GCL_CR_CTL2_WRTHRU_ENA | \ + GCL_CR_CTL2_TAG_ECC_CHECK_ENABLE | \ + GCL_CR_CTL2_GL3_GL3Q_GATING_DISABLE | \ + GCL_CR_CTL2_GL3_GCL_GATING_DISABLE | \ + GCL_CR_CTL2_GL3_L3_GATING_DISABLE | \ + GCL_CR_CTL2_DATA_ECC_CHECK_ENABLE | \ + GCL_CR_CTL2_L2_SLEEP_TRANSISTOR_STRENGTH_ENABLE) + +/* + GL3 attributes controlled via GCL_CR_ECO +*/ +#define MDFLD_GCL_CR_ECO_EVICT_INVAL (1) + // GL3 #define MDFLD_GL3_WRITE(_val, _offs ) \ iowrite32(_val, dev_priv->gl3_reg + (_offs)) diff --git a/drivers/staging/mrst/drv/mdfld_hdcp.h b/drivers/staging/mrst/drv/mdfld_hdcp.h index 5852823..808d2bc 100644 --- a/drivers/staging/mrst/drv/mdfld_hdcp.h +++ b/drivers/staging/mrst/drv/mdfld_hdcp.h @@ -191,7 +191,7 @@ typedef struct _aksv_get { int hdcp_init(void **data, int drmFD, int output_id); int hdcp_uninit(void * data); -int hdcp_query(); +int hdcp_query(void); int hdcp_is_valid_bksv(uint8_t *buffer, uint32_t size); int hdcp_is_enabled(void); int hdcp_enable(int enable); diff --git a/drivers/staging/mrst/drv/mdfld_hdmi_audio.c b/drivers/staging/mrst/drv/mdfld_hdmi_audio.c index 82909e3..575d4f7 100644 --- a/drivers/staging/mrst/drv/mdfld_hdmi_audio.c +++ b/drivers/staging/mrst/drv/mdfld_hdmi_audio.c @@ -50,16 +50,21 @@ void mdfld_hdmi_audio_init(struct mid_intel_hdmi_priv *p_hdmi_priv) */ static int mdfld_hdmi_audio_write (uint32_t reg, uint32_t val) { - struct drm_device *dev = hdmi_priv->dev; - int ret = 0; + struct drm_device *dev = hdmi_priv->dev; + int ret = 0; + struct drm_psb_private *dev_priv = + (struct drm_psb_private *) dev->dev_private; - if (IS_HDMI_AUDIO_REG(reg)) { - REG_WRITE(reg, val); - } else { - ret = -EINVAL; - } + if (dev_priv->bDVIport) { + return 0; + } - return ret; + if (IS_HDMI_AUDIO_REG(reg)) + REG_WRITE(reg, val); + else + ret = -EINVAL; + + return ret; } /** @@ -69,16 +74,21 @@ static int mdfld_hdmi_audio_write (uint32_t reg, uint32_t val) */ static int mdfld_hdmi_audio_read (uint32_t reg, uint32_t *val) { - struct drm_device *dev = hdmi_priv->dev; - int ret = 0; + struct drm_device *dev = hdmi_priv->dev; + struct drm_psb_private *dev_priv = + (struct drm_psb_private *) dev->dev_private; + int ret = 0; - if (IS_HDMI_AUDIO_REG(reg)) { - *val = REG_READ(reg); - } else { - ret = -EINVAL; - } + if (dev_priv->bDVIport) { + return 0; + } - return ret; + if (IS_HDMI_AUDIO_REG(reg)) + *val = REG_READ(reg); + else + ret = -EINVAL; + + return ret; } /** diff --git a/drivers/staging/mrst/drv/mdfld_intel_hdcp.c b/drivers/staging/mrst/drv/mdfld_intel_hdcp.c index b4bfa56..54aa719 100644 --- a/drivers/staging/mrst/drv/mdfld_intel_hdcp.c +++ b/drivers/staging/mrst/drv/mdfld_intel_hdcp.c @@ -78,7 +78,7 @@ int hdcp_is_valid_bksv(uint8_t *buffer, uint32_t size) * Checks if HDCP is supported * */ -int hdcp_query() +int hdcp_query(void) { return hdmi_priv->is_hdcp_supported; } @@ -102,7 +102,7 @@ int hdcp_is_enabled(void) return ret; } -#define HDCP_PRIMARY_I2C_ADDR 0x74 +#define HDCP_PRIMARY_I2C_ADDR 0x3A // w/o read/write bit /* * * Read HDCP device data from i2c link @@ -213,7 +213,7 @@ static int write_hdcp_port(uint8_t offset, uint8_t *buffer, int size) .buf = &offset, }, { .addr = HDCP_PRIMARY_I2C_ADDR, - .flags = 0, + .flags = I2C_M_NOSTART, .len = size, .buf = buffer, } @@ -255,7 +255,7 @@ int hdcp_enable(int enable) mdfld_hdcp_rep_t hdcp_repeater; uint32_t max_retry = 0; sqword_t hw_an; - sqword_t hw_aksv; + static sqword_t hw_aksv = {{0}}; //read-once only after reset, subsequent read will return zero sqword_t hw_bksv; uint8_t bcaps=0; uint32_t rx_ri = 0; @@ -305,7 +305,7 @@ int hdcp_enable(int enable) } // Check for cipher time out - if(max_retry == 0) + if(max_retry == -1) { ret = 0; return 0; @@ -351,18 +351,17 @@ int hdcp_enable(int enable) } } - config.hdcp_config = HDCP_Off; - REG_WRITE(MDFLD_HDCP_CONFIG_REG, config.value); - - if(max_retry == 0) + if(max_retry == -1) return 0;//Cipher timeout, was not able to generate An :( //Read An hw_an.u.low_part = REG_READ(MDFLD_HDCP_AN_LOW_REG); hw_an.u.high_part = REG_READ(MDFLD_HDCP_AN_HI_REG); - hw_aksv.u.low_part = REG_READ(MDFLD_HDCP_AKSV_LOW_REG); - hw_aksv.u.high_part = REG_READ(MDFLD_HDCP_AKSV_HI_REG); + if(hw_aksv.quad_part == 0){ + hw_aksv.u.low_part = REG_READ(MDFLD_HDCP_AKSV_LOW_REG); + hw_aksv.u.high_part = REG_READ(MDFLD_HDCP_AKSV_HI_REG); + } //stHdcpParams.hwAksv.MajorPart_Low = 0x0361f714;//test data //stHdcpParams.hwAksv.MajorPart_High = 0xb7; @@ -375,6 +374,7 @@ int hdcp_enable(int enable) ret = write_hdcp_port(RX_AKSV_0, hw_aksv.byte, 5); if(!ret) return 0; + //Read the Bksv from receiver ret =read_hdcp_port(RX_TYPE_BKSV_DATA, &hw_bksv.byte[0], 5); @@ -414,6 +414,10 @@ int hdcp_enable(int enable) //At this point of time the Km is created + //TBD:Have some delay before reading the Ri' + //Right now using 100 ms, as per the HDCP spec(Refer HDCP SAS for details) + mdelay(HDCP_100MS_DELAY); + //Wait for Ri ready max_retry = HDCP_MAX_RETRY_STATUS;//TBD: Not yet finalized while(max_retry--) @@ -423,7 +427,7 @@ int hdcp_enable(int enable) break; } - if(max_retry == 0) + if(max_retry == -1) return 0;//Cipher timeout, was not able to generate An :( //Compare the R0 and Ri @@ -432,10 +436,6 @@ int hdcp_enable(int enable) if(!ret) return 0; - //TBD:Have some delay before reading the Ri' - //Right now using 100 ms, as per the HDCP spec(Refer HDCP SAS for details) - mdelay(HDCP_100MS_DELAY); - //update the HDCP_Ri' register and read the status reg for confrmation receivers_ri.value = REG_READ(MDFLD_HDCP_RECEIVER_RI_REG); receivers_ri.ri = rx_ri; @@ -446,6 +446,7 @@ int hdcp_enable(int enable) //SoftbiosDebugMessage(DBG_CRITICAL,"R Prime = %x\n",dwRxRi); //SoftbiosDebugMessage(DBG_CRITICAL,"HDCP_STATUS = %x\n",stStatus.value); ret = status.cipher_ri_match_status; + printk("%s: cipher ri %s\n",__func__,(ret==1)?"MATCH":"UNMATCH!"); /*if(GEN4INTHDCPCONTROLLER_HasInterruptOccured(pThis,ePort) == TRUE) { bRet = 0; diff --git a/drivers/staging/mrst/drv/mdfld_msic.c b/drivers/staging/mrst/drv/mdfld_msic.c index 9b8316d..b24b7fc 100644 --- a/drivers/staging/mrst/drv/mdfld_msic.c +++ b/drivers/staging/mrst/drv/mdfld_msic.c @@ -34,6 +34,7 @@ #define SRAM_MSIC_VRINT_ADDR 0xFFFF7FCB static u8 *sram_vreg_addr = 0; +unsigned char vrint_dat; /* * */ @@ -107,26 +108,26 @@ irqreturn_t msic_vreg_handler(int irq, void *dev_id) { struct drm_device *dev = hdmi_priv ? hdmi_priv->dev : NULL; struct drm_psb_private *dev_priv = NULL; - u8 data = 0; + vrint_dat = 0; /* Need to add lock later.*/ /* Read VREG interrupt status register */ if (sram_vreg_addr) - data = readb(sram_vreg_addr); + vrint_dat = readb(sram_vreg_addr); else DRM_ERROR("%s: sram_vreg_addr = 0x%x.\n", __func__, (u32) sram_vreg_addr); if (dev) { - PSB_DEBUG_ENTRY("data = 0x%x.\n", data); + PSB_DEBUG_ENTRY("vrint data = 0x%x.\n", vrint_dat); dev_priv = psb_priv(dev); /* handle HDMI HPD interrupts. */ - if (data & HDMI_HPD_STATUS) + if (vrint_dat & (HDMI_HPD_STATUS | HDMI_OCP_STATUS)) { - DRM_INFO("%s: HPD interrupt. data = 0x%x.\n", __func__, data); + DRM_INFO("%s: HPD interrupt.vrint data = 0x%x.\n", __func__, vrint_dat); if (dev_priv->um_start) hpd_notify_um(); diff --git a/drivers/staging/mrst/drv/mdfld_msic.h b/drivers/staging/mrst/drv/mdfld_msic.h index e60f992..7c15865 100644 --- a/drivers/staging/mrst/drv/mdfld_msic.h +++ b/drivers/staging/mrst/drv/mdfld_msic.h @@ -29,3 +29,4 @@ int msic_regsiter_driver(void); int msic_unregister_driver(void); extern void hpd_notify_um (void); +extern unsigned char vrint_dat; diff --git a/drivers/staging/mrst/drv/psb_drm.h b/drivers/staging/mrst/drv/psb_drm.h index b13f774..c7cf015 100644 --- a/drivers/staging/mrst/drv/psb_drm.h +++ b/drivers/staging/mrst/drv/psb_drm.h @@ -234,14 +234,8 @@ struct psb_ttm_fence_rep { typedef struct drm_psb_cmdbuf_arg { uint64_t buffer_list; /* List of buffers to validate */ uint64_t clip_rects; /* See i915 counterpart */ - uint64_t scene_arg; uint64_t fence_arg; - uint32_t ta_flags; - - uint32_t ta_handle; /* TA reg-value pairs */ - uint32_t ta_offset; - uint32_t ta_size; uint32_t oom_handle; uint32_t oom_offset; @@ -255,20 +249,10 @@ typedef struct drm_psb_cmdbuf_arg { uint32_t reloc_offset; uint32_t num_relocs; - int32_t damage; /* Damage front buffer with cliprects */ /* Not implemented yet */ uint32_t fence_flags; uint32_t engine; - /* - * Feedback; - */ - - uint32_t feedback_ops; - uint32_t feedback_handle; - uint32_t feedback_offset; - uint32_t feedback_breakpoints; - uint32_t feedback_size; } drm_psb_cmdbuf_arg_t; typedef struct drm_psb_pageflip_arg { @@ -779,8 +763,9 @@ struct drm_psb_get_pipe_from_crtc_id_arg { #define DRM_PSB_DISP_INIT_HDMI_FLIP_CHAIN 1 #define DRM_PSB_DISP_QUEUE_BUFFER 2 #define DRM_PSB_DISP_DEQUEUE_BUFFER 3 -#define DRM_PSB_DISP_HDMI_FLIP_STOP 4 -#define DRM_PSB_DISP_HDMI_FLIP_START 5 +#define DRM_PSB_DISP_PLANEB_DISABLE 4 +#define DRM_PSB_DISP_PLANEB_ENABLE 5 +#define DRM_PSB_HDMI_OSPM_ISLAND_DOWN 6 struct drm_psb_buffer_data { void* h_buffer; diff --git a/drivers/staging/mrst/drv/psb_drv.c b/drivers/staging/mrst/drv/psb_drv.c index e893df2..278cac5 100755 --- a/drivers/staging/mrst/drv/psb_drv.c +++ b/drivers/staging/mrst/drv/psb_drv.c @@ -97,6 +97,7 @@ int drm_psb_te_timer_delay = (DRM_HZ / 40); static int PanelID = GCT_DETECT; char HDMI_EDID[HDMI_MONITOR_NAME_LENGTH]; int hdmi_state; +extern u32 DISP_PLANEB_STATUS; static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -1103,19 +1104,32 @@ void hdmi_do_hotplug_wq(struct work_struct *work) #ifdef CONFIG_X86_MDFLD intel_scu_ipc_iowrite8(MSIC_VCC330CNT, VCC330_ON); + if (vrint_dat & HDMI_OCP_STATUS) { + /* when there occurs overcurrent in msic hdmi hdp, + need to reset VHDMIEN by clearing to 0 then set to 1*/ + intel_scu_ipc_iowrite8(MSIC_VHDMICNT, VHDMI_OFF); + + /* MSIC documentation requires that there be a 500us delay + after enabling VCC330 before you can enable VHDMI */ + usleep_range(500, 1000); + intel_scu_ipc_iowrite8(MSIC_VHDMICNT, VHDMI_ON | VHDMI_DB_30MS); + } + intel_scu_ipc_ioread8(MSIC_HDMI_STATUS, &data); if (data & HPD_SIGNAL_STATUS) { - PSB_DEBUG_ENTRY("hdmi_do_hotplug_wq: HDMI plugged in\n"); - hdmi_state = 1; + PSB_DEBUG_ENTRY( "hdmi_do_hotplug_wq: HDMI plugged in\n"); + dev_priv->bhdmiconnected = true; if (dev_priv->mdfld_had_event_callbacks) (*dev_priv->mdfld_had_event_callbacks) (HAD_EVENT_HOT_PLUG, dev_priv->had_pvt_data); drm_sysfs_hotplug_event(dev_priv->dev); } else { - PSB_DEBUG_ENTRY("hdmi_do_hotplug_wq: HDMI unplugged\n"); + PSB_DEBUG_ENTRY( "hdmi_do_hotplug_wq: HDMI unplugged\n"); + dev_priv->bhdmiconnected = false; hdmi_state = 0; + drm_sysfs_hotplug_event(dev_priv->dev); if (dev_priv->mdfld_had_event_callbacks) @@ -1433,6 +1447,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) bdev = &dev_priv->bdev; hdmi_state = 0; + dev_priv->bhdmiconnected = false; #ifdef CONFIG_MDFD_VIDEO_DECODE ret = psb_ttm_global_init(dev_priv); @@ -1904,8 +1919,10 @@ static int psb_flip_hdmi(struct drm_device *dev, uint32_t pipe) unsigned long irqflags; struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private; - if (!dev_priv->flip_start || dev_priv->head_fliped) + if (dev_priv->head_fliped) { + printk(KERN_INFO "HDMI flipped already!"); return 0; + } if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, false)) { switch (pipe){ case 1: @@ -1938,6 +1955,9 @@ static int psb_disp_ioctl(struct drm_device *dev, void *data, unsigned long irqflags; int ret = 0; unsigned int i = 0; + int dspcntr_reg = DSPBCNTR; + int dspbase_reg = MRST_DSPBBASE; + u32 temp; /*DRM_COPY_FROM_USER(&dp_ctrl, data, sizeof(struct drm_psb_disp_ctrl));*/ /*DRM_INFO("disp cmd:%d \n",dp_ctrl->cmd);*/ if (dp_ctrl->cmd == DRM_PSB_DISP_INIT_HDMI_FLIP_CHAIN) { @@ -1958,27 +1978,49 @@ static int psb_disp_ioctl(struct drm_device *dev, void *data, } dev_priv->flip_valid_size = flip_data->size; dev_priv->flip_inited = 1; - } - else if (dp_ctrl->cmd == DRM_PSB_DISP_QUEUE_BUFFER) { + } else if (dp_ctrl->cmd == DRM_PSB_DISP_QUEUE_BUFFER) { spin_lock_irqsave(&dev_priv->flip_lock, irqflags); dev_priv->flip_head = (unsigned int)dp_ctrl->u.buf_data.h_buffer; dev_priv->head_fliped = 0; - /*DRM_INFO("head:%d \n",dev_priv->flip_head);*/ spin_unlock_irqrestore(&dev_priv->flip_lock, irqflags); - psb_flip_hdmi(dev, 1); - } - else if (dp_ctrl->cmd == DRM_PSB_DISP_DEQUEUE_BUFFER) { + psb_flip_hdmi(dev, 1); + } else if (dp_ctrl->cmd == DRM_PSB_DISP_DEQUEUE_BUFFER) { i = (dev_priv->flip_tail + 1) % dev_priv->flip_valid_size; if (i != dev_priv->flip_head) dev_priv->flip_tail = i; dp_ctrl->u.buf_data.h_buffer = (void *)dev_priv->flip_tail; - /*DRM_INFO("tail:%d \n",dev_priv->flip_tail);*/ - } - else if (dp_ctrl->cmd == DRM_PSB_DISP_HDMI_FLIP_STOP) { - dev_priv->flip_start = 0; - } - else if (dp_ctrl->cmd == DRM_PSB_DISP_HDMI_FLIP_START) { - dev_priv->flip_start = 1; + } else if (dp_ctrl->cmd == DRM_PSB_DISP_PLANEB_DISABLE) { + if (DISP_PLANEB_STATUS == DISPLAY_PLANE_DISABLE) + ret = -1; + else { + /*Use Disable pipeB plane to turn off HDMI screen*/ + temp = REG_READ(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) != 0) { + REG_WRITE(dspcntr_reg, + temp & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); + } + } + } else if (dp_ctrl->cmd == DRM_PSB_DISP_PLANEB_ENABLE) { + if (DISP_PLANEB_STATUS == DISPLAY_PLANE_DISABLE) + ret = -1; + else { + /*Restore pipe B plane to turn on HDMI screen*/ + temp = REG_READ(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) == 0) { + REG_WRITE(dspcntr_reg, + temp | DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); + } + } + } else if (dp_ctrl->cmd == DRM_PSB_HDMI_OSPM_ISLAND_DOWN) { + /*Set power state island down when hdmi disconnected */ + if (pmu_nc_set_power_state(OSPM_DISPLAY_B_ISLAND, + OSPM_ISLAND_DOWN, OSPM_REG_TYPE)) + BUG(); + dev_priv->panel_desc &= ~DISPLAY_B; } exit: return ret; diff --git a/drivers/staging/mrst/drv/psb_drv.h b/drivers/staging/mrst/drv/psb_drv.h index 4b52059..02792fb 100755 --- a/drivers/staging/mrst/drv/psb_drv.h +++ b/drivers/staging/mrst/drv/psb_drv.h @@ -1045,8 +1045,14 @@ struct drm_psb_private { unsigned int flip_tail; unsigned int flip_inited; unsigned int head_fliped; - unsigned int flip_start; spinlock_t flip_lock; + /*whether is DVI port*/ + bool bDVIport; + unsigned int drm_psb_widi; + + /*hdmi connected status */ + bool bhdmiconnected; + }; struct psb_fpriv { diff --git a/drivers/staging/mrst/drv/psb_fb.c b/drivers/staging/mrst/drv/psb_fb.c index 7c3116a..5fd7b92 100644 --- a/drivers/staging/mrst/drv/psb_fb.c +++ b/drivers/staging/mrst/drv/psb_fb.c @@ -949,7 +949,6 @@ static struct drm_framebuffer *psb_user_framebuffer_create fbdev->psb_fb_helper.fb = fb; fbdev->psb_fb_helper.fbdev = info; - MRSTLFBHandleChangeFB(dev, psbfb); #endif return fb; @@ -1088,24 +1087,24 @@ static int psbfb_create(struct psb_fbdev * fbdev, struct drm_fb_helper_surface_s struct device * device = &dev->pdev->dev; int size, aligned_size; int ret; + struct mdfld_dsi_encoder *dsi_encoder = + MDFLD_DSI_ENCODER(dev_priv->encoder0); + struct mdfld_dsi_config *dsi_config = + mdfld_dsi_encoder_get_config(dsi_encoder); + struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; + /* PR2 panel must have 200 pixel dummy clocks, * So the display timing should be 800x1024, and surface * is 608x1024(64 bits align), or the information between android * and Linux frame buffer is not consistent. */ - -// if (get_panel_type(dev, 0) == TMD_6X10_VID) -// mode_cmd.width = sizes->surface_width - 200; -// else -// mode_cmd.width = sizes->surface_width; -// mode_cmd.height = sizes->surface_height; - - if (get_panel_type(dev, 0) == TMD_6X10_VID) - mode_cmd.width = sizes->fb_width - 200; - else - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->fb_height; - + if (get_panel_type(dev, 0) == TMD_6X10_VID) { + mode_cmd.width = fixed_mode->hdisplay - 200; + mode_cmd.height = fixed_mode->vdisplay; + } else { + mode_cmd.width = fixed_mode->hdisplay; + mode_cmd.height = fixed_mode->vdisplay; + } mode_cmd.bpp = 32; //HW requires pitch to be 64 byte aligned @@ -1573,7 +1572,6 @@ int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) info = psbfb->fbdev; psbfb->pvrBO = NULL; - MRSTLFBHandleChangeFB(dev, psbfb); #else info = fb->fbdev; #endif diff --git a/drivers/staging/mrst/drv/psb_intel_display2.c b/drivers/staging/mrst/drv/psb_intel_display2.c index 51d29ef..22f87ca 100755 --- a/drivers/staging/mrst/drv/psb_intel_display2.c +++ b/drivers/staging/mrst/drv/psb_intel_display2.c @@ -35,7 +35,7 @@ #include #include "psb_intel_display.h" -#include "psb_intel_hdmi.h" + #ifdef MIN #undef MIN #endif @@ -335,6 +335,170 @@ void mdfld__intel_plane_set_alpha(int enable) REG_WRITE(dspcntr_reg, dspcntr); } +static int mdfld_intel_set_scaling_property(struct drm_crtc *crtc, int x, int y, int pipe) +{ + struct drm_device *dev = crtc->dev; + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); + struct drm_framebuffer *fb = crtc->fb; + struct drm_display_mode *adjusted_mode = & psb_intel_crtc->saved_adjusted_mode; + uint64_t scalingType = psb_intel_crtc->scaling_type; + int pipesrc_reg = PIPEASRC; + int dspsize_reg = DSPASIZE; + int dsppos_reg = DSPAPOS; + int sprite_pos_x = 0, sprite_pos_y = 0; + int sprite_width = 0, sprite_height = 0; + int src_image_hor = 0, src_image_vert = 0; + + switch (pipe) { + case 0: + break; + case 1: + pipesrc_reg = PIPEBSRC; + dspsize_reg = DSPBSIZE; + dsppos_reg = DSPBPOS; + break; + case 2: + pipesrc_reg = PIPECSRC; + dspsize_reg = DSPCSIZE; + dsppos_reg = DSPCPOS; + break; + default: + DRM_ERROR("Illegal Pipe Number. \n"); + return -EINVAL; + } + + PSB_DEBUG_ENTRY("scalingType %llu\n", scalingType); + /* pipesrc and dspsize control the size that is scaled from, + * which should always be the user's requested size. + */ + if (pipe == 1) { + /* + * Frame buffer size may beyond active region in case of + * panning mode. + */ + sprite_width = MIN(fb->width, adjusted_mode->hdisplay); + sprite_height = MIN(fb->height, adjusted_mode->vdisplay); + + switch (scalingType) { + case DRM_MODE_SCALE_NONE: + case DRM_MODE_SCALE_CENTER: + /* This mode is used to support centering the screen by setting reg + * in DISPLAY controller */ + src_image_hor = adjusted_mode->hdisplay; + src_image_vert = adjusted_mode->vdisplay; + sprite_pos_x = (src_image_hor - sprite_width) / 2; + sprite_pos_y = (src_image_vert - sprite_height) / 2; + + REG_WRITE(PFIT_CONTROL, + REG_READ(PFIT_CONTROL) & ~PFIT_ENABLE); + + break; + + case DRM_MODE_SCALE_FULLSCREEN: + src_image_hor = sprite_width; + src_image_vert = sprite_height; + sprite_pos_x = 0; + sprite_pos_y = 0; + + if ((adjusted_mode->hdisplay > sprite_width) || + (adjusted_mode->vdisplay > sprite_height)) + REG_WRITE(PFIT_CONTROL, + PFIT_ENABLE | + PFIT_PIPE_SELECT_B | + PFIT_SCALING_MODE_AUTO); + break; + + case DRM_MODE_SCALE_ASPECT: + if ((adjusted_mode->hdisplay - sprite_width) >= + (adjusted_mode->vdisplay -sprite_height)) { + src_image_hor = adjusted_mode->hdisplay * + sprite_height /adjusted_mode->vdisplay; + src_image_vert = sprite_height; + sprite_pos_x = + (adjusted_mode->hdisplay - sprite_width) * + sprite_height /adjusted_mode->vdisplay /2; + sprite_pos_y = 0; + } else { + src_image_hor = sprite_width; + src_image_vert = adjusted_mode->vdisplay * + sprite_width / + adjusted_mode->hdisplay; + sprite_pos_x = 0; + sprite_pos_y = + (adjusted_mode->vdisplay - sprite_height) * + sprite_width /adjusted_mode->hdisplay /2; + } + + /* In case of rotation to landscape mode or hdmi timing + * setting is less than framebuffer size, it scales to + * hdmi display timing size automatically. + */ + if ((fb->width > fb->height) || + (fb->width > adjusted_mode->hdisplay) || + (fb->height > adjusted_mode->vdisplay)) { + sprite_pos_x = 0; + sprite_pos_y = 0; + sprite_height = fb->height; + sprite_width = fb->width; + src_image_hor = fb->width; + src_image_vert = fb->height; + } + + if ((adjusted_mode->hdisplay != fb->width) || + (adjusted_mode->vdisplay != + fb->height)) + REG_WRITE(PFIT_CONTROL, + PFIT_ENABLE | + PFIT_PIPE_SELECT_B | + PFIT_SCALING_MODE_AUTO); + break; + + default: + /* Android will not change mode, however ,we have tools + to change HDMI timing so there is some cases frame + buffer no change ,but timing changed mode setting, in + this case. mode information for source size is not + right, so here use fb information for source/sprite + size*/ + + /* The defined sprite rectangle must always be + completely contained within the displayable area of the + screen image (frame buffer). */ + sprite_pos_x = 0; + sprite_pos_y = 0; + sprite_height = fb->height; + sprite_width = fb->width; + src_image_hor = fb->width; + src_image_vert = fb->height; + if ((adjusted_mode->hdisplay != fb->width) || + (adjusted_mode->vdisplay != fb->height)) + REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | + PFIT_PIPE_SELECT_B); + + break; + } + + PSB_DEBUG_ENTRY("Sprite position: (%d, %d)\n", sprite_pos_x, + sprite_pos_y); + PSB_DEBUG_ENTRY("Sprite size: %d x %d\n", sprite_width, + sprite_height); + PSB_DEBUG_ENTRY("Pipe source image size: %d x %d\n", + src_image_hor, src_image_vert); + + REG_WRITE(dsppos_reg, (sprite_pos_y << 16) | sprite_pos_x); + REG_WRITE(dspsize_reg, ((sprite_height - 1) << 16) | + (sprite_width - 1)); + REG_WRITE(pipesrc_reg, ((src_image_hor - 1) << 16) | + (src_image_vert - 1)); + } else { + REG_WRITE(dspsize_reg, ((adjusted_mode->vdisplay - 1) << 16) | (adjusted_mode->hdisplay - 1)); + REG_WRITE(pipesrc_reg, ((adjusted_mode->hdisplay - 1) << 16) | (adjusted_mode->vdisplay - 1)); + REG_WRITE(dsppos_reg, 0); + } + + return 0; +} + int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; @@ -388,6 +552,8 @@ int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_f OSPM_UHB_FORCE_POWER_ON)) return 0; + mdfld_intel_set_scaling_property(crtc, x, y, pipe); + Start = mode_dev->bo_offset(dev, psbfb); Size = mode_dev->bo_size(dev, psbfb); Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); @@ -1017,6 +1183,7 @@ mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk, } static int mdfld_crtc_dsi_pll_calc(struct drm_crtc *crtc, + struct mdfld_dsi_config *dsi_config, struct drm_device *dev, struct mdfld_dsi_hw_context *ctx, struct drm_display_mode *adjusted_mode) @@ -1049,7 +1216,11 @@ static int mdfld_crtc_dsi_pll_calc(struct drm_crtc *crtc, dev_priv->bpp = 24; clk_byte = dev_priv->bpp / 8; - clk = adjusted_mode->clock; + + if (dsi_config->lane_count) + clk = adjusted_mode->clock / dsi_config->lane_count; + else + clk = adjusted_mode->clock; clk_tmp = clk * clk_n * clk_p2 * clk_byte; @@ -1119,12 +1290,12 @@ static int mdfld_crtc_dsi_mode_set(struct drm_crtc *crtc, fb_depth = crtc->fb->depth; dev = crtc->dev; - spin_lock(&dsi_config->context_lock); + mutex_lock(&dsi_config->context_lock); ctx->vgacntr = 0x80000000; /*setup pll*/ - mdfld_crtc_dsi_pll_calc(crtc, dev, ctx, adjusted_mode); + mdfld_crtc_dsi_pll_calc(crtc, dsi_config, dev, ctx, adjusted_mode); /*set up pipe timings*/ ctx->htotal = (mode->crtc_hdisplay - 1) | @@ -1178,7 +1349,7 @@ static int mdfld_crtc_dsi_mode_set(struct drm_crtc *crtc, break; default: DRM_ERROR("Unknown color depth\n"); - spin_unlock(&dsi_config->context_lock); + mutex_unlock(&dsi_config->context_lock); return -EINVAL; } @@ -1208,9 +1379,10 @@ static int mdfld_crtc_dsi_mode_set(struct drm_crtc *crtc, ctx->pipeconf |= ((hdelay-1) << 27); - spin_unlock(&dsi_config->context_lock); + mutex_unlock(&dsi_config->context_lock); return 0; } + static int mdfld_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -1339,12 +1511,12 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc, adjusted_mode->vtotal); PSB_DEBUG_ENTRY("adjusted_clock = %d\n", adjusted_mode->clock); + PSB_DEBUG_ENTRY("adjusted_refresh = %d\n", + adjusted_mode->vrefresh); PSB_DEBUG_ENTRY("hdisplay = %d\n", mode->hdisplay); PSB_DEBUG_ENTRY("vdisplay = %d\n", mode->vdisplay); - PSB_DEBUG_ENTRY("vrefresh = %d\n", - mode->vrefresh); if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) return 0; @@ -1401,122 +1573,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc, drm_connector_property_get_value(&psb_intel_output->base, dev->mode_config.scaling_mode_property, &scalingType); - PSB_DEBUG_ENTRY("scalingType %llu\n", scalingType); - /* pipesrc and dspsize control the size that is scaled from, - * which should always be the user's requested size. - */ - if (pipe == 1) { - /* - * Frame buffer size may beyond active region in case of - * panning mode. - */ - sprite_width = MIN(fb->width, adjusted_mode->crtc_hdisplay); - sprite_height = MIN(fb->height, adjusted_mode->crtc_vdisplay); - - switch (scalingType) { - case DRM_MODE_SCALE_NONE: - case DRM_MODE_SCALE_CENTER: - /* This mode is used to support centering the screen by setting reg - * in DISPLAY controller */ - src_image_hor = adjusted_mode->crtc_hdisplay; - src_image_vert = adjusted_mode->crtc_vdisplay; - sprite_pos_x = (src_image_hor - sprite_width) / 2; - sprite_pos_y = (src_image_vert - sprite_height) / 2; - - REG_WRITE(PFIT_CONTROL, - REG_READ(PFIT_CONTROL) & ~PFIT_ENABLE); - - break; - - case DRM_MODE_SCALE_FULLSCREEN: - src_image_hor = sprite_width; - src_image_vert = sprite_height; - sprite_pos_x = 0; - sprite_pos_y = 0; - - if ((adjusted_mode->hdisplay > sprite_width) || - (adjusted_mode->vdisplay > - sprite_height)) - REG_WRITE(PFIT_CONTROL, - PFIT_ENABLE | - PFIT_PIPE_SELECT_B | - PFIT_SCALING_MODE_AUTO); - break; - - case DRM_MODE_SCALE_ASPECT: - if ((adjusted_mode->crtc_hdisplay - sprite_width) >= - (adjusted_mode->crtc_vdisplay - - sprite_height)) { - src_image_hor = adjusted_mode->crtc_hdisplay * - sprite_height / - adjusted_mode->crtc_vdisplay; - src_image_vert = sprite_height; - sprite_pos_x = - (src_image_hor - sprite_width) / 2; - sprite_pos_y = 0; - } else { - src_image_hor = sprite_width; - src_image_vert = adjusted_mode->crtc_vdisplay * - sprite_width / - adjusted_mode->crtc_hdisplay; - sprite_pos_x = 0; - sprite_pos_y = - (src_image_vert - sprite_height) / 2; - } - - if ((adjusted_mode->hdisplay > sprite_width) || - (adjusted_mode->vdisplay > - sprite_height)) - REG_WRITE(PFIT_CONTROL, - PFIT_ENABLE | - PFIT_PIPE_SELECT_B | - PFIT_SCALING_MODE_AUTO); - break; - - default: - /* Android will not change mode, however ,we have tools - to change HDMI timing so there is some cases frame - buffer no change ,but timing changed mode setting, in - this case. mode information for source size is not - right, so here use fb information for source/sprite - size*/ - - /* The defined sprite rectangle must always be - completely contained within the displayable area of the - screen image (frame buffer). */ - REG_WRITE(dspsize_reg, - ((fb->height - 1) << 16) | - (fb->width - 1)); - /* Set the CRTC with encoder mode. */ - REG_WRITE(pipesrc_reg, - ((fb->width - 1) << 16) | - (fb->height - 1)); - if ((adjusted_mode->hdisplay != fb->width) || - (adjusted_mode->vdisplay != fb->height)) - REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | - PFIT_PIPE_SELECT_B); - - REG_WRITE(dsppos_reg, 0); - break; - } - - PSB_DEBUG_ENTRY("Sprite position: (%d, %d)\n", sprite_pos_x, - sprite_pos_y); - PSB_DEBUG_ENTRY("Sprite size: %d x %d\n", sprite_width, - sprite_height); - PSB_DEBUG_ENTRY("Pipe source image size: %d x %d\n", - src_image_hor, src_image_vert); - - REG_WRITE(dsppos_reg, (sprite_pos_y << 16) | sprite_pos_x); - REG_WRITE(dspsize_reg, ((sprite_height - 1) << 16) | - (sprite_width - 1)); - REG_WRITE(pipesrc_reg, ((src_image_hor - 1) << 16) | - (src_image_vert - 1)); - } else { - REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1)); - REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1)); - REG_WRITE(dsppos_reg, 0); - } + psb_intel_crtc->scaling_type = scalingType; if (scalingType == DRM_MODE_SCALE_NO_SCALE) { /*Moorestown doesn't have register support for centering so we need to @@ -1728,8 +1785,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc, REG_WRITE(dspcntr_reg, *dspcntr); psb_intel_wait_for_vblank(dev); - /*set hdmi avi information*/ - mdfld_hdmi_set_avi_information(dev, adjusted_mode); + mrst_crtc_mode_set_exit: ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); diff --git a/drivers/staging/mrst/drv/psb_intel_drv.h b/drivers/staging/mrst/drv/psb_intel_drv.h index 91d587a..d31a5b3 100644 --- a/drivers/staging/mrst/drv/psb_intel_drv.h +++ b/drivers/staging/mrst/drv/psb_intel_drv.h @@ -186,6 +186,9 @@ struct psb_intel_crtc { /*crtc mode setting flags*/ u32 mode_flags; + /* crtc scaling type */ + u32 scaling_type; + /*FIXME: Workaround to avoid MRST block.*/ #ifndef CONFIG_X86_MDFLD /* Saved Crtc HW states */ diff --git a/drivers/staging/mrst/drv/psb_intel_dsi.c b/drivers/staging/mrst/drv/psb_intel_dsi.c index 4f0fa53..bfc9c7d 100644 --- a/drivers/staging/mrst/drv/psb_intel_dsi.c +++ b/drivers/staging/mrst/drv/psb_intel_dsi.c @@ -2047,6 +2047,9 @@ static bool mrstDSI_clockInit(DRM_DRIVER_PRIVATE_T *dev_priv) case 200: p_mipi_2xclk = sku_100_mipi_2xclk; break; + default: + PSB_DEBUG_ENTRY("mrstDSI_clockInit, core_freq = %d\n", dev_priv->core_freq); + return false; } for (; i < MIPI_2XCLK_COUNT; i++) { diff --git a/drivers/staging/mrst/drv/psb_intel_hdmi.c b/drivers/staging/mrst/drv/psb_intel_hdmi.c index 21a1227..b33ecd4 100644 --- a/drivers/staging/mrst/drv/psb_intel_hdmi.c +++ b/drivers/staging/mrst/drv/psb_intel_hdmi.c @@ -30,6 +30,7 @@ #include #include "psb_intel_drv.h" #include "psb_drv.h" +#include "psb_irq.h" #include "psb_intel_reg.h" #include "psb_intel_hdmi_reg.h" #include "psb_intel_hdmi_edid.h" @@ -43,6 +44,8 @@ #include #endif +u32 DISP_PLANEB_STATUS = ~DISPLAY_PLANE_ENABLE; + /* FIXME_MDFLD HDMI EDID supports */ char EDID_Samsung[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] = { @@ -148,6 +151,7 @@ char EDID_Toshiba_Regza[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] = 0x43, 0x00, 0x13, 0x8e, 0x21, 0x00, 0x00, 0x98, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c, 0x25, 0x00, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3 }; + static struct hdmi_edid_info mdfld_hdmi_edid[] = { { HDMI_EDID_INFO("SAMSUNG", EDID_Samsung) }, { HDMI_EDID_INFO("SAMSUNG_2493HM", EDID_Samsung_2493HM) }, @@ -156,116 +160,317 @@ static struct hdmi_edid_info mdfld_hdmi_edid[] = { { HDMI_EDID_INFO("TOSHIBA_32RV525RZ", EDID_Toshiba_32RV525RZ) }, { HDMI_EDID_INFO("TOSHIBA_REGZA", EDID_Toshiba_Regza) }, }; -/*video code according CEA-861-E.pdf*/ -static struct hdmi_video_code mdfld_hdmi_video_code[] = { - /*640*480p@60hz*/ - {1, 640, 480, 60, 0}, - /*720*480p@60hz*/ - {2, 720, 480, 60, 0}, - /*1280*720p@60hz*/ - {4, 1280, 720, 60, 0}, - /*1920*1080i@60*/ - {5, 1920, 1080, 60, 1}, - /*1920*1080p@60hz*/ - {16, 1920, 1080, 60, 0}, - /*1920*1080p@30hz*/ - {34, 1920, 1080, 30, 0}, - /*1920*1080i@50hz*/ - {20, 1920, 1080, 50, 1}, +/* +*VIC for AVI InfoFrame Data Byte 4 and CEA Short Descriptors +*/ +struct hdmi_video_format_timing mdfld_hdmi_video_format_timing[] = { + /*NULL*/ + {0, 0, 0, 60, 0, 1, 1, 0}, + /*640*480p@60hz 4:3*/ + {1, 640, 480, 60, 0, 0, 0, HDMI_AVI_PAR_4_3}, + /*720*480p@60hz 4:3*/ + {2, 720, 480, 60, 0, 0, 0, HDMI_AVI_PAR_4_3}, + /*720*480p@60hz 16:9*/ + {3, 720, 480, 60, 0, 0, 0, HDMI_AVI_PAR_16_9}, + /*1280*720p@60hz 16:9*/ + {4, 1280, 720, 60, 0, 1, 1, HDMI_AVI_PAR_16_9}, + /*1920*1080i@60hz 16:9*/ + {5, 1920, 1080, 60, 1, 1, 1, HDMI_AVI_PAR_16_9}, + /*720*480i@60hz 4:3*/ + {6, 720, 480, 60, 1, 0, 0, HDMI_AVI_PAR_4_3}, + /*720*480i@60hz 16:9*/ + {7, 720, 480, 60, 1, 0, 0, HDMI_AVI_PAR_16_9}, + /*720*240p@60hz 4:3*/ + {8, 720, 240, 60, 0, 0, 0, HDMI_AVI_PAR_4_3}, + /*720*240p@60hz 16:9*/ + {9, 720, 240, 60, 0, 0, 0, HDMI_AVI_PAR_16_9}, + /*2880*480i@60hz 4:3*/ + {10, 2880, 480, 60, 1, 0, 0, HDMI_AVI_PAR_4_3}, + /*2880*480i@60hz 16:9*/ + {11, 2880, 480, 60, 1, 0, 0, HDMI_AVI_PAR_16_9}, + /*2880*240p@60hz 4:3*/ + {12, 2880, 240, 60, 0, 0, 0, HDMI_AVI_PAR_4_3}, + /*2880*240p@60hz 16:9*/ + {13, 2880, 240, 60, 0, 0, 0, HDMI_AVI_PAR_16_9}, + /*1440*480p@60hz 4:3*/ + {14, 1440, 480, 60, 0, 0, 0, HDMI_AVI_PAR_4_3}, + /*1440*480p@60hz 16:9*/ + {15, 1440, 480, 60, 0, 0, 0, HDMI_AVI_PAR_16_9}, + /*1920*1080p@60hz 16:9*/ + {16, 1920, 1080, 60, 0, 1, 1, HDMI_AVI_PAR_16_9}, + /*720*5760p@50hz 4:3*/ + {17, 720, 576, 50, 0, 0, 0, HDMI_AVI_PAR_4_3}, + /*720*5760p@50hz 16:9*/ + {18, 720, 576, 50, 0, 0, 0, HDMI_AVI_PAR_16_9}, + /*1280*720p@50hz 16:9*/ + {19, 1280, 720, 50, 0, 1, 1, HDMI_AVI_PAR_16_9}, + /*1920*1080i@50hz 16:9*/ + {20, 1920, 1080, 50, 1, 1, 1, HDMI_AVI_PAR_16_9}, + /*720*576i@50hz 4:3*/ + {21, 720, 576, 50, 1, 0, 0, HDMI_AVI_PAR_4_3}, + /*720*576i@50hz 16:9*/ + {22, 720, 576, 50, 1, 0, 0, HDMI_AVI_PAR_16_9}, + /*720*288p@50hz 4:3*/ + {23, 720, 288, 50, 0, 0, 0, HDMI_AVI_PAR_4_3}, + /*720*288p@50hz 16:9*/ + {24, 720, 288, 50, 0, 0, 0, HDMI_AVI_PAR_16_9}, + /*2880*576i@50hz 4:3*/ + {25, 2880, 576, 50, 1, 0, 0, HDMI_AVI_PAR_4_3}, + /*2880*576i@50hz 16:9*/ + {26, 2880, 576, 50, 1, 0, 0, HDMI_AVI_PAR_16_9}, + /*2880*288p@50hz 4:3*/ + {27, 2880, 288, 50, 0, 0, 0, HDMI_AVI_PAR_4_3}, + /*2880*288p@50hz 16:9*/ + {28, 2880, 288, 50, 0, 0, 0, HDMI_AVI_PAR_16_9}, + /*1440*576p@50hz 4:3*/ + {29, 1440, 576, 50, 0, 0, 0, HDMI_AVI_PAR_4_3}, + /*1440*576p@50hz 16:9*/ + {30, 1440, 576, 50, 0, 0, 0, HDMI_AVI_PAR_16_9}, + /*1920*1080p@50hz 16:9 */ + {31, 1920, 1080, 50, 0, 1, 1, HDMI_AVI_PAR_16_9}, + /*1920*1080p@24hz 16:9 */ + {32, 1920, 1080, 24, 0, 1, 1, HDMI_AVI_PAR_16_9}, + /*1920*1080p@25hz 16:9 */ + {33, 1920, 1080, 25, 0, 1, 1, HDMI_AVI_PAR_16_9}, + /*1920*1080p@30hz 16:9 */ + {34, 1920, 1080, 30, 0, 1, 1, HDMI_AVI_PAR_16_9}, }; -static int _get_hdmi_video_code(struct drm_display_mode *mode) + +static int mdfld_hdmi_get_cached_edid_block(struct drm_connector *connector, + uint32_t num_block, uint8_t *edid_block, uint32_t size); + +static int mdfld_hdmi_timing_get_vic(struct drm_display_mode *mode) { - /*default set to 1920*1080p@60hz*/ - int video_code = 16; int i = 0; - u32 video_code_count = - sizeof(mdfld_hdmi_video_code)/sizeof(struct hdmi_video_code); - bool bInterlace = false; - struct hdmi_video_code video_code_info = {0}; + int vic = 0; + u32 video_code_count = sizeof(mdfld_hdmi_video_format_timing) / + sizeof(struct hdmi_video_format_timing); + struct hdmi_video_format_timing vft_table_entry = {0}; PSB_DEBUG_ENTRY("%s\n", __func__); - bInterlace = mode->flags & DRM_MODE_FLAG_INTERLACE; /*find video code for this mode*/ for (i = 0; i < video_code_count; i++) { - video_code_info = mdfld_hdmi_video_code[i]; - if (mode->hdisplay == video_code_info.hdisplay && - mode->vdisplay == video_code_info.vdisplay && - mode->vrefresh == video_code_info.refresh && - bInterlace == video_code_info.bInterlace){ - video_code = video_code_info.video_code; + vft_table_entry = mdfld_hdmi_video_format_timing[i]; + + if (mode->hdisplay == vft_table_entry.hdisplay && + mode->vdisplay == vft_table_entry.vdisplay && + mode->vrefresh == vft_table_entry.refresh && + ((mode->flags & DRM_MODE_FLAG_INTERLACE) >> 4) + == vft_table_entry.bInterlace) { + vic = vft_table_entry.video_code; PSB_DEBUG_ENTRY( - "find hdmi mode video code %d\n", video_code); + "find hdmi mode video code= %d hpolar=%d vpolar= %d\n", + vft_table_entry.video_code, + vft_table_entry.hpolarity, + vft_table_entry.vpolarity); break; } } - if (i == video_code_count) + + if (i == video_code_count) { PSB_DEBUG_ENTRY( - "no find !please add this mode into video code array\n."); - return video_code; + "Not supported HDMI mode: width= %d height = %d, vrefresh %d\n.", + mode->hdisplay, mode->vdisplay, mode->vrefresh); + } + + return vic; } -int mdfld_hdmi_set_avi_information(struct drm_device *dev, - struct drm_display_mode *mode) + +static int mdfld_hdmi_get_aspect_ratio(int h_active, int v_active) +{ + unsigned char aspect_ratio = 0xFF; + if (!v_active) + return aspect_ratio; + + if ((h_active * 10) / v_active == 16 * 10 / 10) + /* 16:10 aspect ratio for EDID 1.3 */ + aspect_ratio = EDID_STD_ASPECT_RATIO_16_10; + else if ((h_active * 10) / v_active == 4 * 10 / 3) + /* 4:3 aspect ratio */ + aspect_ratio = EDID_STD_ASPECT_RATIO_4_3; + else if ((h_active * 10) / v_active == 5 * 10 / 4) + /* 5:4 aspect ratio*/ + aspect_ratio = EDID_STD_ASPECT_RATIO_5_4; + else if ((h_active * 10) / v_active == 16 * 10 / 9) + /* 16:9 aspect ratio*/ + aspect_ratio = EDID_STD_ASPECT_RATIO_16_9; + else if (v_active == h_active) + /*1:1 aspect ratio for EDID prior to EDID 1.3*/ + aspect_ratio = EDID_STD_ASPECT_RATIO_16_10; + + PSB_DEBUG_ENTRY("%s fb_width= %d fb_height= %d aspect_ratio %d\n", + __func__, h_active, v_active, aspect_ratio); + + return aspect_ratio; +} + +static uint8_t mdfld_hdmi_calc_hbuf_csum(uint8_t *data, uint8_t size) +{ + uint8_t csum = 0; + int i; + + for (i = 0; i < size; i++) + csum += data[i]; + + return 0x100 - csum; +} + +static int mdfld_hdmi_set_avi_infoframe(struct drm_device *dev, + struct drm_connector *connector, struct drm_display_mode *mode) { - struct _if_header avi_if_header; - u8 checksum = 0; u32 buf_size = 0; u32 viddipctl_val = 0; int i = 0; + int picture_aspect_ratio = 0xFF, active_aspect_ratio = 0xFF; + char *edid_block = connector->edid_blob_ptr->data; + baseedid_1_4_t *base_edid_block = NULL; + ce_edid_t *cea_edid_block = NULL; + int vic = 0; /*initialization avi_infoframe*/ + avi_if_t avi_if = {0}; + /* union _avi_if avi_if = { { - 0x82, 0x02, 0x0d, 0x00, 0x10, 0x18, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00 - } }; + 0x82, 0x02, 0x0d, 0x00, 0x00, 0x10, 0x18, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 + } }; + */ u32 *p_vsif = (u32 *)&avi_if; PSB_DEBUG_ENTRY("%s\n", __func__); - - avi_if_header.type = HDMI_AVI_TYPE; - avi_if_header.version = HDMI_AVI_VERSION2; - avi_if_header.length = HDMI_AVI_LENGTH; - avi_if_header.chksum = 0; - + /*get edid infomation*/ + cea_edid_block = (ce_edid_t *)(edid_block + EDID_BLOCK_SIZE); + base_edid_block = (baseedid_1_4_t *)edid_block; + + /*set header information*/ + avi_if.avi_info.avi_if_header.type = HDMI_AVI_TYPE; + avi_if.avi_info.avi_if_header.version = HDMI_AVI_VERSION2; + avi_if.avi_info.avi_if_header.length = + HDMI_AVI_LENGTH - HDMI_AVI_RESERVED_LENGTH - 1; + avi_if.avi_info.avi_if_header.ecc = 0; + avi_if.avi_info.chksum = 0; + + /* Data Byte 1 */ avi_if.avi_info.byte1_bits.scan_info = HDMI_AVI_SCAN_NODATA; avi_if.avi_info.byte1_bits.bar_info = HDMI_AVI_BAR_INVALID; avi_if.avi_info.byte1_bits.format = HDMI_AVI_AFI_VALID; avi_if.avi_info.byte1_bits.enc_mode = HDMI_AVI_RGB_MODE; + if (cea_edid_block) { + if (cea_edid_block->ucCapabilty & BIT7) + avi_if.avi_info.byte1_bits.scan_info = + HDMI_AVI_SCAN_UNDERSCAN; + /* if set YCbCr, should prepare YUV buffer + if (cea_edid_block->ucCapabilty & BIT5) + avi_if.avi_info.byte1_bits.enc_mode = + HDMI_AVI_YCRCB444_MODE; + else if (cea_edid_block->ucCapabilty & BIT4) + avi_if.avi_info.byte1_bits.enc_mode = + HDMI_AVI_YCRCB422_MODE; + */ + } + avi_if.avi_info.byte1_bits.b1rsvd = 0; + + /* Data Byte 2 + * Set aspect ratio + */ avi_if.avi_info.byte2_bits.afar = HDMI_AVI_AFAR_SAME; - avi_if.avi_info.byte2_bits.par = HDMI_AVI_PAR_NODATA; + avi_if.avi_info.byte2_bits.par = HDMI_AVI_PAR_NODATA; + + if (mode->width_mm && mode->height_mm) { + picture_aspect_ratio = mdfld_hdmi_get_aspect_ratio( + mode->width_mm, mode->height_mm); + PSB_DEBUG_ENTRY("PAR caculate by width_mm.\n"); + } else if (base_edid_block->ucMaxHIS && + base_edid_block->ucMaxVIS) { + picture_aspect_ratio = mdfld_hdmi_get_aspect_ratio( + base_edid_block->ucMaxHIS, + base_edid_block->ucMaxVIS); + PSB_DEBUG_ENTRY("PAR caculate by ucMaxHIS.\n"); + } else { + picture_aspect_ratio = mdfld_hdmi_get_aspect_ratio( + mode->hdisplay, mode->vdisplay); + PSB_DEBUG_ENTRY("PAR caculate by hdisplay.\n"); + } + if (picture_aspect_ratio != 0xFF) { + switch (picture_aspect_ratio) { + case EDID_STD_ASPECT_RATIO_4_3: + avi_if.avi_info.byte2_bits.par = + HDMI_AVI_PAR_4_3; + PSB_DEBUG_ENTRY("picture aspect ratio 4:3\n"); + break; + case EDID_STD_ASPECT_RATIO_16_9: + avi_if.avi_info.byte2_bits.par = + HDMI_AVI_PAR_16_9; + PSB_DEBUG_ENTRY("picture aspect ratio 16:9\n"); + break; + default: + avi_if.avi_info.byte2_bits.par = + HDMI_AVI_PAR_NODATA; + PSB_DEBUG_ENTRY("picture aspect ratio no data\n"); + break; + } + } else + PSB_DEBUG_ENTRY("picture aspect ratio no data\n"); + avi_if.avi_info.byte2_bits.colorimetry = HDMI_AVI_COLOR_NODATA; + if (avi_if.avi_info.byte1_bits.enc_mode != HDMI_AVI_RGB_MODE) { + if (mode->hdisplay <= 720) + avi_if.avi_info.byte2_bits.colorimetry = + HDMI_AVI_COLOR_ITU601; + else + avi_if.avi_info.byte2_bits.colorimetry = + HDMI_AVI_COLOR_ITU709; + } + /* Data Byte 3 */ avi_if.avi_info.byte3_bits.scaling_info = HDMI_AVI_SCALING_NODATA; avi_if.avi_info.byte3_bits.rgbquant_range = HDMI_AVI_RGBQUANT_DEFAULT; avi_if.avi_info.byte3_bits.ext_colorimetry = HDMI_COLORIMETRY_RGB256; avi_if.avi_info.byte3_bits.it_content = HDMI_AVI_ITC_NODATA; - /*get hdmi mode video code*/ - avi_if.avi_info.byte4_bits.vic = _get_hdmi_video_code(mode) ; + /* Data Byte 4 */ + /*get hdmi mode video code*/ + vic = mdfld_hdmi_timing_get_vic(mode); + if (mode->hdisplay == 720 && vic && + avi_if.avi_info.byte2_bits.par == HDMI_AVI_PAR_16_9) + vic += 1; + + avi_if.avi_info.byte4_bits.vic = vic; + if (avi_if.avi_info.byte4_bits.vic) { + /*sync the par here with the vic*/ + avi_if.avi_info.byte2_bits.par = + mdfld_hdmi_video_format_timing[vic].par; + } + PSB_DEBUG_ENTRY("set HDMI avi info.vic= %d\n", vic); + /* Data Byte 5 */ avi_if.avi_info.byte5_bits.pr = HDMI_PR_ONE; + /* Other Data Bytes */ avi_if.avi_info.byte6 = 0x00; avi_if.avi_info.byte7 = 0x00; - avi_if.avi_info.byte8 = 0x00; avi_if.avi_info.byte9 = 0x00; - avi_if.avi_info.byte10 = 0x00; avi_if.avi_info.byte11 = 0x00; - avi_if.avi_info.byte12 = 0x00; avi_if.avi_info.byte13 = 0x00; - for (i = 0; i < HDMI_AVI_TOTAL_LENGTH; i++) - checksum += avi_if.avi_buf[i]; - checksum = 0xff - checksum + 1; - avi_if_header.chksum = checksum; + /* clear PB14-PB27 reserved data to zero*/ + for (i = 0; i < HDMI_AVI_RESERVED_LENGTH; i++) + avi_if.avi_info.byte_reserved[i] = 0x00; - avi_if.avi_info.avi_if_header = avi_if_header; + avi_if.avi_info.chksum = + mdfld_hdmi_calc_hbuf_csum( + (uint8_t *)avi_if.avi_buf, HDMI_AVI_TOTAL_LENGTH); if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_FORCE_POWER_ON)) - return 0; + OSPM_UHB_FORCE_POWER_ON)) + return 0; + + /*clear DIP buffer firstly*/ + for (i = 0; i <= DIP_RAM_ADDR_INDEX_MAX; i++) + REG_WRITE(VIDEO_DIP_DATA, 0x0); /* Wait for 2 VSyncs. */ mdelay(20); /* msleep(20); */ @@ -275,8 +480,8 @@ int mdfld_hdmi_set_avi_information(struct drm_device *dev, /* Disable the DIP type . */ viddipctl_val = REG_READ(VIDEO_DIP_CTL); viddipctl_val &= ~(DIP_TYPE_MASK | DIP_BUFF_INDX_MASK | - DIP_RAM_ADDR_MASK | DIP_TX_FREQ_MASK); - viddipctl_val |= DIP_BUFF_INDX_VS | EN_DIP; + DIP_RAM_ADDR_MASK | DIP_TX_FREQ_MASK); + viddipctl_val |= DIP_BUFF_INDX_AVI | PORT_B_SELECT; REG_WRITE(VIDEO_DIP_CTL, viddipctl_val); /* Get the buffer size in DWORD. */ @@ -286,14 +491,22 @@ int mdfld_hdmi_set_avi_information(struct drm_device *dev, for (i = 0; i < buf_size; i++) REG_WRITE(VIDEO_DIP_DATA, *(p_vsif++)); + /*Write default DIF data so that Index pointer come back*/ + for (i = buf_size; i <= DIP_RAM_ADDR_INDEX_MAX; i++) + REG_WRITE(VIDEO_DIP_DATA, 0x00); + /* Enable the DIP type and transmission frequency. */ - viddipctl_val |= DIP_TYPE_AVI | DIP_TX_FREQ_2VSNC; - REG_WRITE(VIDEO_DIP_CTL, viddipctl_val); + viddipctl_val |= DIP_TYPE_AVI | DIP_TX_FREQ_1VSNC; + REG_WRITE(VIDEO_DIP_CTL, viddipctl_val); + + viddipctl_val |= EN_DIP; + REG_WRITE(VIDEO_DIP_CTL, viddipctl_val); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return 0; - } + + static void mdfld_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -302,25 +515,84 @@ static void mdfld_hdmi_mode_set(struct drm_encoder *encoder, struct psb_intel_output *output = enc_to_psb_intel_output(encoder); struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; u32 hdmib, hdmi_phy_misc; -#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO + int vic = 0; + u32 hpolarity = 0, vpolarity = 0; struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private; +#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO void *had_pvt_data = dev_priv->had_pvt_data; enum had_event_type event_type = HAD_EVENT_MODE_CHANGING; #endif PSB_DEBUG_ENTRY("\n"); - hdmib = REG_READ(hdmi_priv->hdmib_reg) | HDMIB_PORT_EN | HDMIB_PIPE_B_SELECT | HDMIB_NULL_PACKET; hdmi_phy_misc = REG_READ(HDMIPHYMISCCTL) & ~HDMI_PHY_POWER_DOWN; - REG_WRITE(HDMIPHYMISCCTL, hdmi_phy_misc); + + hdmib = REG_READ(hdmi_priv->hdmib_reg) | HDMIB_PORT_EN | + HDMIB_PIPE_B_SELECT; + + if (dev_priv->bDVIport) { + hdmib &= ~(HDMIB_NULL_PACKET | HDMI_AUDIO_ENABLE) ; + REG_WRITE(VIDEO_DIP_CTL, 0x0); + REG_WRITE(AUDIO_DIP_CTL, 0x0); + } else { + hdmib |= (HDMIB_NULL_PACKET | HDMI_AUDIO_ENABLE); + mdfld_hdmi_set_avi_infoframe(dev, &output->base, adjusted_mode); + } + + vic = mdfld_hdmi_timing_get_vic(adjusted_mode); + + /*Get mode hpolarity vpolarity*/ + if (adjusted_mode->flags & (DRM_MODE_FLAG_PHSYNC | + DRM_MODE_FLAG_PVSYNC)) { + hpolarity = 1; + vpolarity = 1; + PSB_DEBUG_ENTRY("polarity get from flag P\n"); + } else if (adjusted_mode->flags & (DRM_MODE_FLAG_NHSYNC | + DRM_MODE_FLAG_NVSYNC)) { + hpolarity = 0; + vpolarity = 0; + PSB_DEBUG_ENTRY("polarity get from flag N\n"); + } else if (vic) { + hpolarity = mdfld_hdmi_video_format_timing[vic].hpolarity; + vpolarity = mdfld_hdmi_video_format_timing[vic].vpolarity; + PSB_DEBUG_ENTRY("polarity get from table\n"); + } else { + if (adjusted_mode->vdisplay <= 576) { + hpolarity = 0; + vpolarity = 0; + } else { + hpolarity = 1; + vpolarity = 1; + } + } + + /* Update hpolarity */ + if (hpolarity == 1) + hdmib |= BIT3; + else + hdmib &= ~BIT3; + + /* Update vpolarity */ + if (vpolarity == 1) + hdmib |= BIT4; + else + hdmib &= ~BIT4; + REG_WRITE(hdmi_priv->hdmib_reg, hdmib); REG_READ(hdmi_priv->hdmib_reg); + /*save current set mode*/ + if (hdmi_priv->current_mode) + drm_mode_destroy(dev, + hdmi_priv->current_mode); + hdmi_priv->current_mode = + drm_mode_duplicate(dev, adjusted_mode); + #ifdef CONFIG_SND_INTELMID_HDMI_AUDIO /* Send MODE_CHANGE event to Audio driver */ - if (dev_priv->mdfld_had_event_callbacks) + if (dev_priv->mdfld_had_event_callbacks && !dev_priv->bDVIport) (*dev_priv->mdfld_had_event_callbacks)(event_type, had_pvt_data); #endif @@ -335,7 +607,11 @@ static bool mdfld_hdmi_mode_fixup(struct drm_encoder *encoder, struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(encoder->crtc); struct psb_intel_output *output = enc_to_psb_intel_output(encoder); + struct drm_connector *connector = &output->base; struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; + uint32_t adjusted_mode_id = 0; + struct drm_display_mode *temp_mode = NULL, *t = NULL; + PSB_DEBUG_ENTRY("hdisplay = %d, vdisplay = %d. a_hdisplay = %d," "a_vdisplay = %d.\n", mode->hdisplay, mode->vdisplay, adjusted_mode->hdisplay, adjusted_mode->vdisplay); @@ -346,33 +622,14 @@ static bool mdfld_hdmi_mode_fixup(struct drm_encoder *encoder, "Only support HDMI on pipe B on MID\n"); } - /* FIXME: To make HDMI display with 1920x1080, - * in 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD) fixed mode. */ - if ((hdmi_priv->mimic_mode != NULL) && - (hdmi_priv->edid_preferred_mode != NULL)) { - if (drm_mode_equal(mode, hdmi_priv->mimic_mode)) { - adjusted_mode->hdisplay = - hdmi_priv->edid_preferred_mode->hdisplay; - adjusted_mode->htotal = - hdmi_priv->edid_preferred_mode->htotal; - adjusted_mode->hsync_start = - hdmi_priv->edid_preferred_mode->hsync_start; - adjusted_mode->hsync_end = - hdmi_priv->edid_preferred_mode->hsync_end; - adjusted_mode->hskew = - hdmi_priv->edid_preferred_mode->hskew; - adjusted_mode->vdisplay = - hdmi_priv->edid_preferred_mode->vdisplay; - adjusted_mode->vtotal = - hdmi_priv->edid_preferred_mode->vtotal; - adjusted_mode->vsync_start = - hdmi_priv->edid_preferred_mode->vsync_start; - adjusted_mode->vsync_end = - hdmi_priv->edid_preferred_mode->vsync_end; - adjusted_mode->vscan = - hdmi_priv->edid_preferred_mode->vscan; - adjusted_mode->clock = - hdmi_priv->edid_preferred_mode->clock; + list_for_each_entry_safe(temp_mode, t, &connector->modes, head) { + if (drm_mode_equal(temp_mode, mode)) { + /*update adjusted mode with kernel mode info, + such as width_mm height_mm*/ + PSB_DEBUG_ENTRY("fix up enter.\n"); + adjusted_mode_id = adjusted_mode->base.id; + *adjusted_mode = *temp_mode; + adjusted_mode->base.id = adjusted_mode_id; /* Apply the adjusted mode to CRTC mode setting * parameters.*/ @@ -445,36 +702,47 @@ static void mdfld_hdmi_dpms(struct drm_encoder *encoder, int mode) (struct drm_psb_private *)dev->dev_private; struct psb_intel_output *output = enc_to_psb_intel_output(encoder); struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; - u32 hdmib, hdmi_phy_misc, pipebstat; + u32 hdmib, hdmi_phy_misc; - PSB_DEBUG_ENTRY("%s \n", mode == DRM_MODE_DPMS_ON ? "on" : "off"); + PSB_DEBUG_ENTRY("%s\n", mode == DRM_MODE_DPMS_ON ? + "on" : "off"); + + hdmib = REG_READ(hdmi_priv->hdmib_reg) | HDMIB_PIPE_B_SELECT; + + if (dev_priv->bDVIport) { + hdmib &= ~(HDMIB_NULL_PACKET | HDMI_AUDIO_ENABLE); + REG_WRITE(VIDEO_DIP_CTL, 0x0); + REG_WRITE(AUDIO_DIP_CTL, 0x0); + } else + hdmib |= (HDMIB_NULL_PACKET | HDMI_AUDIO_ENABLE); - hdmib = REG_READ(hdmi_priv->hdmib_reg) | HDMIB_PIPE_B_SELECT | HDMIB_NULL_PACKET; - pipebstat = REG_READ(PIPEBSTAT); hdmi_phy_misc = REG_READ(HDMIPHYMISCCTL); if (mode != DRM_MODE_DPMS_ON) { - if (dev_priv->mdfld_had_event_callbacks) + if (dev_priv->mdfld_had_event_callbacks + && !dev_priv->bDVIport) (*dev_priv->mdfld_had_event_callbacks) (HAD_EVENT_HOT_UNPLUG, dev_priv->had_pvt_data); REG_WRITE(hdmi_priv->hdmib_reg, hdmib & ~HDMIB_PORT_EN & ~HDMI_AUDIO_ENABLE); - REG_WRITE(PIPEBSTAT, pipebstat & ~PIPE_VBLANK_INTERRUPT_ENABLE); + psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); REG_WRITE(HDMIPHYMISCCTL, hdmi_phy_misc | HDMI_PHY_POWER_DOWN); + REG_WRITE(VIDEO_DIP_CTL, 0x0); + REG_WRITE(AUDIO_DIP_CTL, 0x0); } else { REG_WRITE(HDMIPHYMISCCTL, hdmi_phy_misc & ~HDMI_PHY_POWER_DOWN); - REG_WRITE(PIPEBSTAT, pipebstat | PIPE_VBLANK_INTERRUPT_ENABLE); + psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); REG_WRITE(hdmi_priv->hdmib_reg, - hdmib | HDMIB_PORT_EN | HDMI_AUDIO_ENABLE); + hdmib | HDMIB_PORT_EN); - if (dev_priv->mdfld_had_event_callbacks) + if (dev_priv->mdfld_had_event_callbacks + && !dev_priv->bDVIport) (*dev_priv->mdfld_had_event_callbacks) (HAD_EVENT_HOT_PLUG, dev_priv->had_pvt_data); } REG_READ(hdmi_priv->hdmib_reg); } -int lastpipebbase; static void mdfld_hdmi_encoder_save(struct drm_encoder *encoder) { @@ -491,9 +759,7 @@ static void mdfld_hdmi_encoder_save(struct drm_encoder *encoder) REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); /* Flush the plane changes */ - lastpipebbase = REG_READ(dspbase_reg); REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - REG_READ(dspbase_reg); } } @@ -502,6 +768,10 @@ static void mdfld_hdmi_encoder_restore(struct drm_encoder *encoder) int dspcntr_reg = DSPBCNTR; int dspbase_reg = MRST_DSPBBASE; struct drm_device *dev = encoder->dev; + struct drm_psb_private *dev_priv = + (struct drm_psb_private *)dev->dev_private; + struct psb_intel_output *output = enc_to_psb_intel_output(encoder); + struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; u32 temp; PSB_DEBUG_ENTRY("\n"); @@ -512,8 +782,15 @@ static void mdfld_hdmi_encoder_restore(struct drm_encoder *encoder) REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); /* Flush the plane changes */ - REG_WRITE(dspbase_reg, lastpipebbase); - REG_READ(dspbase_reg); + REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); + } + /*restore avi infomation*/ + if (!dev_priv->bDVIport) + mdfld_hdmi_set_avi_infoframe(dev, + &output->base, hdmi_priv->current_mode); + else { + REG_WRITE(VIDEO_DIP_CTL, 0x0); + REG_WRITE(AUDIO_DIP_CTL, 0x0); } } @@ -548,6 +825,7 @@ static int mdfld_hdmi_get_cached_edid_block(struct drm_connector *connector, uin DRM_ERROR("mdfld_hdmi_get_cached_edid_block() - Invalid EDID block\n"); return 0; } + edid_block = &displayinfo->raw_edid[EDID_BLOCK_SIZE*num_block]; return 1; } @@ -857,7 +1135,40 @@ static int mdfld_hdmi_create_eeld_packet(struct drm_connector *connector) pCurrentSADBlocks = NULL; return 1; } +bool isHDMI(struct drm_connector *connector) +{ + int i = 0, n = 0; + bool ret = false; + baseedid_1_4_t *base_edid_block = NULL; + char *edid_block = NULL; + + base_edid_block = (baseedid_1_4_t *)connector->edid_blob_ptr->data; + edid_block = (char *)connector->edid_blob_ptr->data; + if (!base_edid_block) { + PSB_DEBUG_ENTRY("base_edid_block = NULL\n"); + return false; + } + + if (base_edid_block->ucNumExtBlocks == 0) { + PSB_DEBUG_ENTRY("ucNumExtBlocks = 0\n"); + /*print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, + edid_block, EDID_LENGTH);*/ + return false; + } + /*search VSDB in extend edid */ + for (i = 0; i <= EDID_BLOCK_SIZE - 3; i++) { + n = EDID_BLOCK_SIZE + i; + if (edid_block[n] == 0x03 && + edid_block[n+1] == 0x0c && + edid_block[n+2] == 0x00) + ret = true; + } + /*print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, + edid_block, 2*EDID_LENGTH);*/ + + return ret; +} static enum drm_connector_status mdfld_hdmi_edid_detect(struct drm_connector *connector) { @@ -897,11 +1208,10 @@ mdfld_hdmi_edid_detect(struct drm_connector *connector) hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); mdfld_hdmi_create_eeld_packet(connector); } - drm_mode_connector_update_edid_property(connector, edid); - output->base.display_info.raw_edid = NULL; kfree(edid); dev_priv->hdmi_done_reading_edid = true; + hdmi_priv->is_hardcode_edid = false; } else { /* Failed to read a valid EDID, so we're using a hardcoded one */ if ((HDMI_EDID == NULL) || (strlen(HDMI_EDID) > HDMI_MONITOR_NAME_LENGTH)) @@ -917,9 +1227,21 @@ mdfld_hdmi_edid_detect(struct drm_connector *connector) } } - if (i == monitor_number) - /* Use Toshiba Regza HDMI EDID as default data. */ - edid = (struct edid *)mdfld_hdmi_edid[i - 1].edid_info; + if (i == monitor_number) { + if (dev_priv->platform_rev_id > MDFLD_PNW_C0) { + PSB_DEBUG_ENTRY( + "hard code fix to DVI!\n"); + /*EDID_Samsung_2493HM*/ + edid = + (struct edid *)mdfld_hdmi_edid[1].edid_info; + } else { + PSB_DEBUG_ENTRY( + "hard code fix to HDMI!\n"); + /*Use Toshiba Regza HDMI EDID as default data.*/ + edid = + (struct edid *)mdfld_hdmi_edid[i - 1].edid_info; + } + } hdmi_priv->has_hdmi_sink = false; if (edid) { @@ -930,10 +1252,34 @@ mdfld_hdmi_edid_detect(struct drm_connector *connector) } dev_priv->hdmi_done_reading_edid = true; + hdmi_priv->is_hardcode_edid = true; } + /* Check whether it's DVI port or HDMI. */ + if (isHDMI(connector)) + dev_priv->bDVIport = false; + else + dev_priv->bDVIport = true; + PSB_DEBUG_ENTRY("is DVI port ? %s", dev_priv->bDVIport ? "yes" : "no"); return status; } +void hdmi_unplug_prepare(struct drm_psb_private *dev_priv) +{ + int wait_count = 0; + + if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, false)) { + /*wait for overlay switch back to pipeA*/ + while ((PSB_RVDC32(OV_OVADD) & 0xc0) && wait_count < 5) { + PSB_DEBUG_ENTRY( + "wait for overlay switch to mipi 0x%x.\n", + PSB_RVDC32(OV_OVADD)); + msleep(20); + wait_count++; + }; + ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + } else + PSB_DEBUG_ENTRY("display controller is power off.\n"); +} static enum drm_connector_status mdfld_hdmi_detect(struct drm_connector *connector) @@ -947,6 +1293,10 @@ static enum drm_connector_status mdfld_hdmi_detect(struct drm_connector struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_output->dev_priv; struct mdfld_dsi_config *dsi_config = dev_priv->dsi_configs[0]; u8 data = 0; + enum drm_connector_status connect_status = + connector_status_disconnected; + static bool first_time_boot_detect = true; + /* Check if monitor is attached to HDMI connector. */ intel_scu_ipc_ioread8(MSIC_HDMI_STATUS, &data); @@ -954,20 +1304,13 @@ static enum drm_connector_status mdfld_hdmi_detect(struct drm_connector if (data & HPD_SIGNAL_STATUS) { DRM_DEBUG("%s: HPD connected data = 0x%x.\n", __func__, data); - if (dsi_config) { - hdmi_priv->mimic_mode = - drm_mode_duplicate(dev, dsi_config->fixed_mode); - drm_mode_set_name(hdmi_priv->mimic_mode); - } - if (connector->status == connector_status_connected) { /* * Don't un-gate Display B if HDMI is connected and in * D0i3 state. */ - if (hdmi_state == 0) - hdmi_state = 1; - return connector_status_connected; + connect_status = connector_status_connected; + goto fun_exit; } dev_priv->panel_desc |= DISPLAY_B; /* @@ -987,36 +1330,46 @@ static enum drm_connector_status mdfld_hdmi_detect(struct drm_connector if (dev_priv->hdmi_done_reading_edid || (mdfld_hdmi_edid_detect(connector) == connector_status_connected)) { - if (hdmi_state == 0) - hdmi_state = 1; - return connector_status_connected; + connect_status = connector_status_connected; } else { - hdmi_state = 0; - return connector_status_disconnected; + connect_status = connector_status_disconnected; } } else { DRM_DEBUG("%s: HPD disconnected data = 0x%x.\n", __func__, data); - /* - * Clean up the HDMI connector attached encoder, to make - * drm_crtc_helper_set_config() do mode setting each time, - * especially when plug out HDMI from a sink device and plug it - * in to another one with different EDID. - */ - drm_helper_disable_unused_functions(dev); + if (dev_priv->panel_desc & DISPLAY_B) { + hdmi_unplug_prepare(dev_priv); + /* + * Clean up the HDMI connector attached encoder, to make + * drm_crtc_helper_set_config() do mode setting + *each time, especially when plug out HDMI from + *a sink device and plug it + * in to another one with different EDID. + */ + drm_helper_disable_unused_functions(dev); + } + connect_status = connector_status_disconnected; - /* FIXME: Need to power gate Display B sub-system. - * Currently HDMI sometimes couldn't display after plugging - * in cable. */ - hdmi_state = 0; - return connector_status_disconnected; } #else - return mdfld_hdmi_edid_detect(connector); + connect_status = mdfld_hdmi_edid_detect(connector); #endif + +fun_exit: + if (first_time_boot_detect) { + if (connect_status == connector_status_connected) { + hdmi_state = 1; + dev_priv->bhdmiconnected = true; + } + first_time_boot_detect = false; + PSB_DEBUG_ENTRY("first time boot detect state 0x%d.\n", + connect_status); + } + + return connect_status; } static int mdfld_hdmi_set_property(struct drm_connector *connector, @@ -1036,6 +1389,7 @@ static int mdfld_hdmi_set_property(struct drm_connector *connector, if (!strcmp(property->name, "scaling mode") && pEncoder) { struct psb_intel_crtc *pPsbCrtc = to_psb_intel_crtc(pEncoder->crtc); bool bTransitionFromToCentered; + bool bTransitionFromToAspect; uint64_t curValue; if (!pPsbCrtc) @@ -1065,10 +1419,12 @@ static int mdfld_hdmi_set_property(struct drm_connector *connector, bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) || (value == DRM_MODE_SCALE_NO_SCALE) || (curValue == DRM_MODE_SCALE_CENTER) || (value == DRM_MODE_SCALE_CENTER); + bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_ASPECT) || + (value == DRM_MODE_SCALE_ASPECT); if (pPsbCrtc->saved_mode.hdisplay != 0 && pPsbCrtc->saved_mode.vdisplay != 0) { - if (bTransitionFromToCentered) { + if (bTransitionFromToCentered || bTransitionFromToAspect) { if (!drm_crtc_helper_set_mode(pEncoder->crtc, &pPsbCrtc->saved_mode, pEncoder->crtc->x, pEncoder->crtc->y, pEncoder->crtc->fb)) goto set_prop_error; @@ -1133,25 +1489,6 @@ static int mdfld_hdmi_get_modes(struct drm_connector *connector) PSB_DEBUG_ENTRY("\n"); - if (dsi_config) { - /* - * In case that the HDMI mimic mode's status is reset to - * MODE_UNVERIFIED when getting the complete set of display - * modes. - */ - if ((hdmi_priv->mimic_mode) && - (hdmi_priv->mimic_mode->status != - dsi_config->fixed_mode->status)) - hdmi_priv->mimic_mode->status = - dsi_config->fixed_mode->status; - } - - /* - * Insert MIPI's mode into HDMI connector's mode list as the mimic mode. - */ - if (hdmi_priv->mimic_mode) - drm_mode_probed_add(connector, hdmi_priv->mimic_mode); - /* * Probe more modes from EDID data. */ @@ -1210,38 +1547,50 @@ static int mdfld_hdmi_get_modes(struct drm_connector *connector) return ret; } - if ((!hdmi_priv->mimic_mode) || ((hdmi_priv->mimic_mode) && - (!(hdmi_priv->mimic_mode->type & - DRM_MODE_TYPE_PREFERRED)))) - return ret; - - list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { - /* - * Don't set the mode (from EDID) such as 1920x1200 as - * preferred, to avoid creating the frame buffer which doesn't - * match MIPI panel's resolution. Otherwise MIPI couldn't - * display the whole UI region. - */ - if ((!drm_mode_equal(mode, hdmi_priv->mimic_mode)) && - (mode->type & DRM_MODE_TYPE_PREFERRED)) { - mode->type &= ~DRM_MODE_TYPE_PREFERRED; - - if ((!hdmi_priv->edid_preferred_mode) || - /* - * In case that the HDMI EDID data has - * changed due to connecting to another - * HDMI device. - */ - ((hdmi_priv->edid_preferred_mode) && - (!drm_mode_equal(mode, - hdmi_priv->edid_preferred_mode)))) { - if (hdmi_priv->edid_preferred_mode) - drm_mode_destroy(dev, + /*reset preferred mode if NULL EDID got when detect*/ + if (hdmi_priv->is_hardcode_edid) { + if (dev_priv->platform_rev_id > MDFLD_PNW_C0) { + /*from C1, driver can get edid right + if not right,set prefer mode to 640*480p + it is required by HDMI compliance test.*/ + PSB_DEBUG_ENTRY( + " set hardcode edid prefer to 640*480p\n"); + list_for_each_entry_safe(mode, t, + &connector->probed_modes, head) { + if (mode->hdisplay == 640 + && mode->vdisplay == 480) + mode->type + |= DRM_MODE_TYPE_PREFERRED; + else if (mode->type & DRM_MODE_TYPE_PREFERRED) + mode->type + &= ~DRM_MODE_TYPE_PREFERRED; + } + } + } + /*record the preferred mode*/ + list_for_each_entry_safe(mode, t, + &connector->probed_modes, head) { + if ((mode->type & DRM_MODE_TYPE_PREFERRED)) { + drm_mode_debug_printmodeline(mode); + if (hdmi_priv->edid_preferred_mode) + drm_mode_destroy(dev, hdmi_priv->edid_preferred_mode); - hdmi_priv->edid_preferred_mode = - drm_mode_duplicate(dev, mode); - } + hdmi_priv->edid_preferred_mode = + drm_mode_duplicate(dev, mode); + } + } + /*clear the mode ,which the same as preferred mode + otherwise the preferred mode will be updated by + the same mode in DRM */ + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { + if ((!(mode->type & DRM_MODE_TYPE_PREFERRED)) && + drm_mode_equal(mode, + hdmi_priv->edid_preferred_mode)) { + PSB_DEBUG_ENTRY( + "clear the same mode as preferred.\n"); + list_del(&mode->head); + drm_mode_destroy(dev, mode); } } @@ -1258,19 +1607,6 @@ static int mdfld_hdmi_mode_valid(struct drm_connector *connector, PSB_DEBUG_ENTRY("display info. hdisplay = %d, vdisplay = %d.\n", mode->hdisplay, mode->vdisplay); - /* - * Skip the mimic mode (such as 480 x 854) valid checking with pixel - * clock. - */ - if ((hdmi_priv->mimic_mode == NULL) || - ((hdmi_priv->mimic_mode != NULL) && - (!drm_mode_equal(mode, hdmi_priv->mimic_mode)))) { - if (mode->clock > 165000) - return MODE_CLOCK_HIGH; - if (mode->clock < 20000) - return MODE_CLOCK_HIGH; - } - if (mode->type == DRM_MODE_TYPE_USERDEF) return MODE_OK; @@ -1287,14 +1623,49 @@ static int mdfld_hdmi_mode_valid(struct drm_connector *connector, static void mdfld_hdmi_connector_dpms(struct drm_connector *connector, int mode) { -#ifdef CONFIG_PM_RUNTIME struct drm_device * dev = connector->dev; struct drm_psb_private * dev_priv = dev->dev_private; + int hdmi_audio_busy = 0; + pm_event_t hdmi_audio_event; + u32 dspcntr_val; +#ifdef CONFIG_PM_RUNTIME bool panel_on, panel_on2; #endif /*first, execute dpms*/ + /* using suspend to judge whether hdmi audio is playing */ + if (dev_priv->had_interface && dev_priv->had_pvt_data) + hdmi_audio_busy = + dev_priv->had_interface->suspend(dev_priv->had_pvt_data, + hdmi_audio_event); + + PSB_DEBUG_ENTRY("[DPMS] audio busy: 0x%x\n", hdmi_audio_busy); + + /* if hdmi audio is busy, just turn off hdmi display plane */ + if (hdmi_audio_busy) { + dspcntr_val = PSB_RVDC32(DSPBCNTR); + connector->dpms = mode; + + if (mode != DRM_MODE_DPMS_ON) { + PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, DSPBCNTR); + DISP_PLANEB_STATUS = DISPLAY_PLANE_DISABLE; + } + else { + PSB_WVDC32(dspcntr_val | DISPLAY_PLANE_ENABLE, DSPBCNTR); + DISP_PLANEB_STATUS = DISPLAY_PLANE_ENABLE; + } + } else { + /* Resume audio if audio is suspended */ + if (dev_priv->had_interface && dev_priv->had_pvt_data) + dev_priv->had_interface->resume(dev_priv->had_pvt_data); + + drm_helper_connector_dpms(connector, mode); - drm_helper_connector_dpms(connector, mode); + if (mode != DRM_MODE_DPMS_ON) + DISP_PLANEB_STATUS = DISPLAY_PLANE_DISABLE; + else + DISP_PLANEB_STATUS = DISPLAY_PLANE_ENABLE; + + } #ifdef CONFIG_PM_RUNTIME if(is_panel_vid_or_cmd(dev)) { @@ -1396,7 +1767,7 @@ void mdfld_hdmi_init(struct drm_device *dev, connector->interlace_allowed = false; connector->doublescan_allowed = false; - drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_CENTER); + drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_ASPECT); /* hard-coded the HDMI_I2C_ADAPTER_ID to be 3, Should get from GCT*/ psb_intel_output->hdmi_i2c_adapter = i2c_get_adapter(3); @@ -1411,7 +1782,6 @@ void mdfld_hdmi_init(struct drm_device *dev, hdmi_priv->is_hdcp_supported = true; hdmi_priv->hdmi_i2c_adapter = psb_intel_output->hdmi_i2c_adapter; hdmi_priv->dev = dev; - hdmi_priv->mimic_mode = NULL; hdmi_priv->edid_preferred_mode = NULL; mdfld_hdcp_init(hdmi_priv); mdfld_hdmi_audio_init(hdmi_priv); diff --git a/drivers/staging/mrst/drv/psb_intel_hdmi.h b/drivers/staging/mrst/drv/psb_intel_hdmi.h index 9cde5dc..5025973 100644 --- a/drivers/staging/mrst/drv/psb_intel_hdmi.h +++ b/drivers/staging/mrst/drv/psb_intel_hdmi.h @@ -43,6 +43,8 @@ #define HDMI_MONITOR_NAME_LENGTH 20 +#define HDMI_VSDB_FLG "030c00" + // BaseLineDataLength. // Total size is in multiple of 4 bytes. i.e, 80/4 = 20 #define HDMI_EELD_BASELINE_DATA_LENGTH 0x14 @@ -55,9 +57,6 @@ struct mid_intel_hdmi_priv; extern void mdfld_hdcp_init(struct mid_intel_hdmi_priv *p_hdmi_priv); extern void mdfld_hdmi_audio_init(struct mid_intel_hdmi_priv *p_hdmi_priv); extern void mdfld_msic_init(struct mid_intel_hdmi_priv *p_hdmi_priv); -extern int mdfld_hdmi_set_avi_information(struct drm_device *dev, - struct drm_display_mode *mode); - // // HDMI command types // @@ -128,13 +127,14 @@ typedef enum { // InfoFrame Payload Length in bytes // typedef enum { - HDMI_VS_MAX_LENGTH = 27, // Vendor-Specific InfoFrame Payload Length, including IEEE reg ID - HDMI_AVI_LENGTH = 13, // AVI InfoFrame Payload Length - HDMI_SPD_LENGTH = 25, // SPD InfoFrame Payload Length - HDMI_AUDIO_LENGTH = 10, // Audio InfoFrame Payload Length - HDMI_MS_LENGTH = 10, // MPEG Source InfoFrame Payload Length - HDMI_PR_PE_LENGTH = 4, // Length of PR_PE_TYPE - HDMI_AUDIO_CAPS_LENGTH = 4 // Length of AUDIO_CAPS_TYPE + HDMI_VS_MAX_LENGTH = 27, // Vendor-Specific InfoFrame Payload Length, including IEEE reg ID + HDMI_AVI_LENGTH = 28, // AVI InfoFrame Payload Length + HDMI_AVI_RESERVED_LENGTH = 14, // AVI InfoFrame Reserved Length + HDMI_SPD_LENGTH = 25, // SPD InfoFrame Payload Length + HDMI_AUDIO_LENGTH = 10, // Audio InfoFrame Payload Length + HDMI_MS_LENGTH = 10, // MPEG Source InfoFrame Payload Length + HDMI_PR_PE_LENGTH = 4, // Length of PR_PE_TYPE + HDMI_AUDIO_CAPS_LENGTH = 4 // Length of AUDIO_CAPS_TYPE } infoframe_length_t; // @@ -142,7 +142,7 @@ typedef enum { // typedef enum { HDMI_VS_MAX_TOTAL_LENGTH = HDMI_VS_MAX_LENGTH + 4, // Max Total size of Vendor-Specific InfoFrame - HDMI_AVI_TOTAL_LENGTH = HDMI_AVI_LENGTH + 4, // Total size of AVI InfoFrame + HDMI_AVI_TOTAL_LENGTH = HDMI_AVI_LENGTH + 4, //Total size of AVI InfoFrame HDMI_SPD_TOTAL_LENGTH = HDMI_SPD_LENGTH + 4, // Total size of SPD InfoFrame HDMI_AUDIO_TOTAL_LENGTH = HDMI_AUDIO_LENGTH + 4, // Total size of Audio InfoFrame HDMI_MS_TOTAL_LENGTH = HDMI_MS_LENGTH + 4, // Total size of MPEG Source InfoFrame @@ -302,7 +302,7 @@ typedef struct _if_header { uint8_t type; // InfoFrame Type uint8_t version; // InfoFrame Version uint8_t length; // InfoFrame Length - uint8_t chksum; // Checksum of the InfoFrame + uint8_t ecc; } if_header_t; // @@ -314,6 +314,7 @@ typedef union _avi_if { struct { if_header_t avi_if_header; // AVI header data + uint8_t chksum; //check sum union { uint8_t byte1; @@ -373,10 +374,25 @@ typedef union _avi_if { uint8_t byte11; // end of left bar(upper), set to "00" uint8_t byte12; // start of right bar(lower), set to "00" uint8_t byte13; // start of right bar(upper), set to "00" + uint8_t byte_reserved[HDMI_AVI_RESERVED_LENGTH]; // reserved 14-27 } avi_info; #pragma pack() } avi_if_t; +/* +* HDMI Video Timing +*/ +struct hdmi_video_format_timing { + u32 video_code; + u32 hdisplay; + u32 vdisplay; + u32 refresh; + bool bInterlace; + u32 hpolarity; + u32 vpolarity; + avi_par_info_t par; +}; + // // SPD InfoFrame structure // @@ -885,16 +901,11 @@ struct mid_intel_hdmi_priv { bool is_hdcp_supported; struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */ struct drm_device *dev; - struct drm_display_mode *mimic_mode; struct drm_display_mode *edid_preferred_mode; + bool is_hardcode_edid; + struct drm_display_mode *current_mode; }; -struct hdmi_video_code { - u32 video_code; - u32 hdisplay; - u32 vdisplay; - u32 refresh; - bool bInterlace; -}; + struct hdmi_edid_info { char monitor_name[HDMI_MONITOR_NAME_LENGTH]; char *edid_info; diff --git a/drivers/staging/mrst/drv/psb_intel_reg.h b/drivers/staging/mrst/drv/psb_intel_reg.h index fc5eeb9..dca00f8 100644 --- a/drivers/staging/mrst/drv/psb_intel_reg.h +++ b/drivers/staging/mrst/drv/psb_intel_reg.h @@ -723,9 +723,9 @@ struct dpst_guardband { # define HDMIB_NULL_PACKET (1 << 9) #define HDMIB_HDCP_PORT (1 << 5) - #define VIDEO_DIP_CTL 0x61170 -#define EN_DIP (1 << 31) +#define EN_DIP (1 << 31) +#define PORT_B_SELECT (1 << 29) #define DIP_TYPE_MASK (0xf << 21) #define DIP_TYPE_AVI (1 << 21) #define DIP_TYPE_VS (2 << 21) @@ -739,7 +739,11 @@ struct dpst_guardband { #define DIP_TX_FREQ_1VSNC (1 << 16) #define DIP_TX_FREQ_2VSNC (2 << 16) #define DIP_RAM_ADDR_MASK 0xf +#define DIP_RAM_ADDR_INDEX_MAX 0xf #define VIDEO_DIP_DATA 0x61178 + +#define AUDIO_DIP_CTL 0x69060 + /* MEDFIELD HDMI audio unit registers */ #define AUD_CONFIG 0x69000 #define AUD_CONF_AUDIO_ENABLE (1 << 0) diff --git a/drivers/staging/mrst/drv/psb_irq.c b/drivers/staging/mrst/drv/psb_irq.c index 899509f..b031c2d 100644 --- a/drivers/staging/mrst/drv/psb_irq.c +++ b/drivers/staging/mrst/drv/psb_irq.c @@ -160,7 +160,7 @@ static int mipi_hdmi_vsync_check(struct drm_device *dev, uint32_t pipe) (struct drm_psb_private *) dev->dev_private; struct mdfld_dsi_config *dsi_config = dev_priv->dsi_configs[0]; static int pipe_surf[2]; - int pipea_stat, pipeb_stat; + int pipea_stat, pipeb_stat, pipeb_ctl, pipeb_cntr; unsigned long irqflags; spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); @@ -168,18 +168,23 @@ static int mipi_hdmi_vsync_check(struct drm_device *dev, uint32_t pipe) if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) { pipea_stat = REG_READ(psb_pipestat(0)); pipeb_stat = REG_READ(psb_pipestat(1)); + pipeb_ctl = REG_READ(HDMIB_CONTROL); + pipeb_cntr = REG_READ(DSPBCNTR); pipe_surf[pipe] = REG_READ(DSPASURF); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); } /* PSB_DEBUG_ENTRY("[vsync irq] pipe : 0x%x, regsurf: 0x%x !\n", pipe, pipe_surf[pipe]); */ if ((pipea_stat & PIPE_VBLANK_INTERRUPT_ENABLE) + && (pipeb_ctl & HDMIB_PORT_EN) + && (pipeb_cntr & DISPLAY_PLANE_ENABLE) && (pipeb_stat & PIPE_VBLANK_INTERRUPT_ENABLE)) { if (pipe_surf[0] == pipe_surf[1]) { pipe_surf[0] = MAX_NUM; pipe_surf[1] = MAX_NUM; } else { spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); + /*PSB_DEBUG_ENTRY("Probable Display Buffer LOCK!\n");*/ return 0; } } @@ -219,7 +224,6 @@ static void mid_check_vblank(struct drm_device *dev, uint32_t pipe) spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); } - /** * Display controller interrupt handler for vsync/vblank. * diff --git a/drivers/staging/mrst/drv/psb_powermgmt.c b/drivers/staging/mrst/drv/psb_powermgmt.c index 661fb9b..9bbf7f1 100755 --- a/drivers/staging/mrst/drv/psb_powermgmt.c +++ b/drivers/staging/mrst/drv/psb_powermgmt.c @@ -57,6 +57,7 @@ static atomic_t g_display_access_count; static atomic_t g_graphics_access_count; static atomic_t g_videoenc_access_count; static atomic_t g_videodec_access_count; +extern u32 DISP_PLANEB_STATUS; static bool gbSuspended = false; bool gbgfxsuspended = false; @@ -1116,7 +1117,7 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe) dspsize_val = dev_priv->saveDSPBSIZE; dsppos_val = dev_priv->saveDSPBPOS; dspsurf_val = dev_priv->saveDSPBSURF; - dspcntr_val = dev_priv->saveDSPBCNTR; + dspcntr_val = dev_priv->saveDSPBCNTR & ~DISPLAY_PLANE_ENABLE; dspstatus_val = dev_priv->saveDSPBSTATUS; palette_val = dev_priv->save_palette_b; break; @@ -1482,6 +1483,9 @@ void ospm_resume_display(struct pci_dev *pdev) struct drm_device *dev = pci_get_drvdata(pdev); struct drm_psb_private *dev_priv = dev->dev_private; struct psb_gtt *pg = dev_priv->pg; +#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO + char *uevent_string = NULL; +#endif #ifdef OSPM_GFX_DPK printk(KERN_ALERT "%s\n", __func__); @@ -1493,15 +1497,18 @@ void ospm_resume_display(struct pci_dev *pdev) return; } + if (IS_MDFLD(dev)) { + /*restore performance mode*/ + PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE); + PSB_WVDC32(dev_priv->saveVED_CG_DIS, PSB_MSVDX_CLOCKGATING); +#ifdef CONFIG_MDFD_GL3 + PSB_WVDC32(dev_priv->saveGL3_CTL, MDFLD_GL3_CONTROL); + PSB_WVDC32(dev_priv->saveGL3_USE_WRT_INVAL, MDFLD_GL3_USE_WRT_INVAL); +#endif + } + /* turn on the display power island */ ospm_power_island_up(OSPM_DISPLAY_ISLAND); - /* - Workaround to handle MIPI display not - resuming back correctly. This should be - removed once driver MIPI init sequence is - addressed. - */ - mdelay(50); PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); pci_write_config_word(pdev, PSB_GMCH_CTRL, @@ -1524,17 +1531,18 @@ void ospm_resume_display(struct pci_dev *pdev) * isn't turned on before suspending. */ if ((dev_priv->panel_desc & DISPLAY_B) && - (dev_priv->saveHDMIB_CONTROL & HDMIB_PORT_EN)) + (dev_priv->saveHDMIB_CONTROL & HDMIB_PORT_EN)) { mdfld_restore_display_registers(dev, 1); - mdfld_restore_cursor_overlay_registers(dev); - - /*restore performance mode*/ - PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE); - PSB_WVDC32(dev_priv->saveVED_CG_DIS, PSB_MSVDX_CLOCKGATING); -#ifdef CONFIG_MDFD_GL3 - PSB_WVDC32(dev_priv->saveGL3_CTL, MDFLD_GL3_CONTROL); - PSB_WVDC32(dev_priv->saveGL3_USE_WRT_INVAL, MDFLD_GL3_USE_WRT_INVAL); +#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO + if (dev_priv->had_pvt_data && hdmi_state) { + if (!dev_priv->had_interface->resume(dev_priv->had_pvt_data)) { + uevent_string = "HDMI_AUDIO_PM_RESUMED=1"; + psb_sysfs_uevent(dev_priv->dev, uevent_string); + } + } #endif + } + mdfld_restore_cursor_overlay_registers(dev); }else{ if (!dev_priv->iLVDS_enable) { @@ -1725,6 +1733,7 @@ static void gfx_late_resume(struct early_suspend *h) struct drm_device *dev = dev_priv->dev; struct drm_encoder *encoder; struct drm_encoder_helper_funcs *enc_funcs; + u32 dspcntr_val; #ifdef OSPM_GFX_DPK printk(KERN_ALERT "\ngfx_late_resume\n"); #endif @@ -1777,6 +1786,14 @@ static void gfx_late_resume(struct early_suspend *h) } } + if (dev_priv->panel_desc & DISPLAY_B) { + dspcntr_val = PSB_RVDC32(DSPBCNTR); + /* comply the status with HDMI DPMS */ + if (DISP_PLANEB_STATUS == DISPLAY_PLANE_DISABLE) + PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, DSPBCNTR); + else + PSB_WVDC32(dspcntr_val | DISPLAY_PLANE_ENABLE, DSPBCNTR); + } gbdispstatus = true; @@ -2379,12 +2396,6 @@ int psb_runtime_suspend(struct device *dev) int psb_runtime_resume(struct device *dev) { /* Notify HDMI Audio sub-system about the resume. */ -#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO - struct drm_psb_private* dev_priv = gpDrmDevice->dev_private; - - if(dev_priv->had_pvt_data) - dev_priv->had_interface->resume(dev_priv->had_pvt_data); -#endif #ifdef OSPM_GFX_DPK printk(KERN_ALERT "%s\n", __func__); @@ -2397,15 +2408,21 @@ int psb_runtime_idle(struct device *dev) { #ifdef CONFIG_SND_INTELMID_HDMI_AUDIO struct drm_psb_private* dev_priv = gpDrmDevice->dev_private; + struct snd_intel_had_interface *had_interface = dev_priv->had_interface; int hdmi_audio_busy = 0; pm_event_t hdmi_audio_event; -#endif - -#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO - if(dev_priv->had_pvt_data){ - hdmi_audio_event.event = 0; - hdmi_audio_busy = dev_priv->had_interface->suspend(dev_priv->had_pvt_data, hdmi_audio_event); - } + char *uevent_string = NULL; + + if (dev_priv->had_pvt_data && hdmi_state) { + hdmi_audio_event.event = 0; + hdmi_audio_busy = + had_interface->suspend(dev_priv->had_pvt_data, + hdmi_audio_event); + if (!hdmi_audio_busy) { + uevent_string = "HDMI_AUDIO_PM_SUSPENDED=1"; + psb_sysfs_uevent(dev_priv->dev, uevent_string); + } + } #endif if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count) || atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count) diff --git a/drivers/staging/mrst/drv/psb_umevents.c b/drivers/staging/mrst/drv/psb_umevents.c index 43ba430..b71a839 100644 --- a/drivers/staging/mrst/drv/psb_umevents.c +++ b/drivers/staging/mrst/drv/psb_umevents.c @@ -490,3 +490,10 @@ void psb_umevent_debug_dump_list(struct umevent_list *list) } spin_unlock_irqrestore(&list->list_lock, flags); } + +void psb_sysfs_uevent(struct drm_device *dev, char *event_string) +{ + char *envp[] = { event_string, NULL }; + + kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp); +} diff --git a/drivers/staging/mrst/drv/psb_umevents.h b/drivers/staging/mrst/drv/psb_umevents.h index 80651a2..6c4eed6 100644 --- a/drivers/staging/mrst/drv/psb_umevents.h +++ b/drivers/staging/mrst/drv/psb_umevents.h @@ -154,6 +154,8 @@ int psb_add_uevent_var(struct kobj_uevent_env *env, int psb_kobject_action_type(const char *buf, size_t count, enum kobject_action *type); +extern void psb_sysfs_uevent(struct drm_device *dev, char *event_string); + #if defined(CONFIG_NET) int psb_kobject_uevent_init(void); #endif diff --git a/drivers/staging/mrst/drv/tmd_6x10_vid.c b/drivers/staging/mrst/drv/tmd_6x10_vid.c index fcad067..ad2b98d 100755 --- a/drivers/staging/mrst/drv/tmd_6x10_vid.c +++ b/drivers/staging/mrst/drv/tmd_6x10_vid.c @@ -208,7 +208,7 @@ static int mdfld_dsi_pr2_detect(struct mdfld_dsi_config *dsi_config, if (pipe == 0) { /*reconfig lane configuration*/ dsi_config->lane_count = 3; - dsi_config->lane_config = MDFLD_DSI_DATA_LANE_4_0; + dsi_config->lane_config = MDFLD_DSI_DATA_LANE_3_1; dsi_config->dsi_hw_context.pll_bypass_mode = 1; /* This is for 400 mhz. Set it to 0 for 800mhz */ dsi_config->dsi_hw_context.cck_div = 1; @@ -261,7 +261,6 @@ static int mdfld_dsi_pr2_power_on(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); - unsigned long wait_timeout; int err; PSB_DEBUG_ENTRY("Turn on video mode TMD panel...\n"); @@ -272,11 +271,10 @@ static int mdfld_dsi_pr2_power_on(struct mdfld_dsi_config *dsi_config) } mdfld_dsi_send_gen_long_hs(sender, pr2_mcs_protect_off, 1, 0); - /*FIXME: change power state*/ + /*change power state*/ mdfld_dsi_send_mcs_long_hs(sender, pr2_exit_sleep_mode, 1, 0); - wait_timeout = jiffies + (120 * HZ / 1000); - while (time_before_eq(jiffies, wait_timeout)) - cpu_relax(); + + msleep(120); /*enable PWMON*/ pr2_backlight_control_2[0] |= BIT8; @@ -285,15 +283,14 @@ static int mdfld_dsi_pr2_power_on(struct mdfld_dsi_config *dsi_config) /*set display on*/ mdfld_dsi_send_mcs_long_hs(sender, pr2_set_display_on, 1, 0); - wait_timeout = jiffies + (21 * HZ / 1000); - while (time_before_eq(jiffies, wait_timeout)) - cpu_relax(); + msleep(21); /*Enable BLON , CABC*/ - pr2_backlight_control_1[0] |= BIT8; - mdfld_dsi_send_gen_long_hs(sender, pr2_backlight_control_1, 6, 0); - PSB_DEBUG_ENTRY("enable pr2 cabc\n"); - drm_psb_enable_pr2_cabc = 1; + if (drm_psb_enable_pr2_cabc) { + pr2_backlight_control_1[0] |= BIT8; + mdfld_dsi_send_gen_long_hs(sender, pr2_backlight_control_1, 6, 0); + printk(KERN_ALERT "enable pr2 cabc\n"); + } /*send TURN_ON packet*/ err = mdfld_dsi_send_dpi_spk_pkg_hs(sender, @@ -310,7 +307,6 @@ static int mdfld_dsi_pr2_power_off(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); - unsigned long wait_timeout; int err; PSB_DEBUG_ENTRY("Turn off video mode TMD panel...\n"); @@ -330,27 +326,22 @@ static int mdfld_dsi_pr2_power_off(struct mdfld_dsi_config *dsi_config) mdfld_dsi_send_gen_long_hs(sender, pr2_mcs_protect_off, 1, 0); - /*FIXME: change power state here*/ + /*change power state here*/ mdfld_dsi_send_mcs_long_hs(sender, pr2_set_display_off, 1, 0); /*disable BLCON, disable CABC*/ pr2_backlight_control_1[0] &= (~BIT8); mdfld_dsi_send_gen_long_hs(sender, pr2_backlight_control_1, 6, 0); - PSB_DEBUG_ENTRY("disable pr2 cabc\n"); - drm_psb_enable_pr2_cabc = 0; + printk(KERN_ALERT "disable pr2 cabc\n"); - wait_timeout = jiffies + (21 * HZ / 1000); - while (time_before_eq(jiffies, wait_timeout)) - cpu_relax(); + msleep(21); mdfld_dsi_send_mcs_long_hs(sender, pr2_enter_sleep_mode, 1, 0); /*disable PWMON*/ pr2_backlight_control_2[0] &= (~BIT8); mdfld_dsi_send_gen_long_hs(sender, pr2_backlight_control_2, 2, 0); - wait_timeout = jiffies + (120 * HZ / 1000); - while (time_before_eq(jiffies, wait_timeout)) - cpu_relax(); + msleep(120); /*put panel into deep standby mode*/ mdfld_dsi_send_gen_long_hs(sender, pr2_enter_low_power_mode, 1, 0); @@ -365,7 +356,6 @@ static int mdfld_dsi_pr2_set_brightness(struct mdfld_dsi_config *dsi_config, struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int duty_val = 0; - static int cabc_enable = 1; PSB_DEBUG_ENTRY("Set brightness level %d...\n", level); @@ -383,20 +373,6 @@ static int mdfld_dsi_pr2_set_brightness(struct mdfld_dsi_config *dsi_config, mdfld_dsi_send_gen_long_hs(sender, pr2_backlight_control_2, 2, 0); - if (drm_psb_enable_pr2_cabc != cabc_enable) { - - if (drm_psb_enable_pr2_cabc == 1) { - pr2_backlight_control_1[0] = 0x0f0f01b8; - PSB_DEBUG_ENTRY("Enable pr2 cabc.\n"); - } else if (drm_psb_enable_pr2_cabc == 0) { - pr2_backlight_control_1[0] = 0x0f0f00b8; - PSB_DEBUG_ENTRY("Disable pr2 cabc.\n"); - } - mdfld_dsi_send_gen_long_hs(sender, - pr2_backlight_control_1, 6, 0); - cabc_enable = drm_psb_enable_pr2_cabc; - } - mdfld_dsi_send_gen_long_hs(sender, pr2_mcs_protect_on, 1, 0); return 0; @@ -521,7 +497,9 @@ struct drm_display_mode *pr2_vid_get_config_mode(struct drm_device *dev) mode->vsync_start = 1031; mode->vsync_end = 1033; mode->vtotal = 1035; - mode->clock = 16500; + mode->vrefresh = 60; + mode->clock = mode->vrefresh * (mode->vtotal + 1) * + (mode->htotal + 1) / 1000; } drm_mode_set_name(mode); diff --git a/drivers/staging/mrst/drv/tmd_vid.c b/drivers/staging/mrst/drv/tmd_vid.c index 4231e3c..a0580ee 100644 --- a/drivers/staging/mrst/drv/tmd_vid.c +++ b/drivers/staging/mrst/drv/tmd_vid.c @@ -108,7 +108,9 @@ tmd_vid_get_config_mode(struct drm_device* dev) mode->vsync_start = 861; mode->vsync_end = 865; mode->vtotal = 873; - mode->clock = 13080; /* 60(refresh rate) * (873 + 1) * (499+1) / 1000 / 2 */ + mode->vrefresh = 60; + mode->clock = mode->vrefresh * (mode->vtotal + 1) * + (mode->htotal + 1) / 1000; } #endif drm_mode_set_name(mode); diff --git a/drivers/staging/mrst/imgv/psb_msvdx.c b/drivers/staging/mrst/imgv/psb_msvdx.c index b6ddc4a..dca1c9f 100644 --- a/drivers/staging/mrst/imgv/psb_msvdx.c +++ b/drivers/staging/mrst/imgv/psb_msvdx.c @@ -1515,7 +1515,19 @@ int lnc_video_getparam(struct drm_device *dev, void *data, } break; case IMG_VIDEO_SET_HDMI_STATE: - hdmi_state = (int)arg->value; + if (!hdmi_state) { + PSB_DEBUG_ENTRY( + "wait 100ms for kernel hdmi pipe ready.\n"); + msleep(100); + } + if (dev_priv->bhdmiconnected) + hdmi_state = (int)arg->value; + else + PSB_DEBUG_ENTRY( + "skip hdmi_state setting, for unplugged.\n"); + + PSB_DEBUG_ENTRY("%s, set hdmi_state = %d\n", + __func__, hdmi_state); break; case PNW_VIDEO_QUERY_ENTRY: ret = copy_from_user(&handle, diff --git a/drivers/staging/mrst/medfield/Makefile b/drivers/staging/mrst/medfield/Makefile index f3e56c9..f926a72 100644 --- a/drivers/staging/mrst/medfield/Makefile +++ b/drivers/staging/mrst/medfield/Makefile @@ -45,7 +45,6 @@ ccflags-y += \ -DLINUX \ -DPVRSRV_MODNAME="\"pvrsrvkm\"" \ -DPVR_BUILD_DIR="\"pc_i686_medfield_linux\"" \ - -DPVR_LINUX_MISR_USING_WORKQUEUE \ -DSERVICES4 \ -D_XOPEN_SOURCE=600 \ -DPVR2D_VALIDATE_INPUT_PARAMS \ @@ -55,6 +54,7 @@ ccflags-y += \ -DOPK_FALLBACK="" \ -DSUPPORT_ANDROID_PLATFORM \ -DPROFILE_COMM \ + -DPVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE\ -DSUPPORT_ANDROID_PLATFORM \ -DSUPPORT_GRAPHICS_HAL \ -DPVR_SECURE_FD_EXPORT \ diff --git a/drivers/staging/mrst/pvr/services4/srvkm/common/deviceclass.c b/drivers/staging/mrst/pvr/services4/srvkm/common/deviceclass.c index 9f2b2a57..bd9b8c1 100755 --- a/drivers/staging/mrst/pvr/services4/srvkm/common/deviceclass.c +++ b/drivers/staging/mrst/pvr/services4/srvkm/common/deviceclass.c @@ -2363,7 +2363,9 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, ErrorExit: - + if(psBCInfo->ui32RefCount) + psBCInfo->ui32RefCount--; + for(i=0; iui32BufferCount; i++) { if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) -- 2.7.4