35,6 → 35,11 |
|
/* the sub-encoders aka panel drivers */ |
static const struct intel_dsi_device intel_dsi_devices[] = { |
{ |
.panel_id = MIPI_DSI_GENERIC_PANEL_ID, |
.name = "vbt-generic-dsi-vid-mode-display", |
.dev_ops = &vbt_generic_dsi_display_ops, |
}, |
}; |
|
static void band_gap_reset(struct drm_i915_private *dev_priv) |
59,12 → 64,12 |
|
static inline bool is_vid_mode(struct intel_dsi *intel_dsi) |
{ |
return intel_dsi->dev.type == INTEL_DSI_VIDEO_MODE; |
return intel_dsi->operation_mode == INTEL_DSI_VIDEO_MODE; |
} |
|
static inline bool is_cmd_mode(struct intel_dsi *intel_dsi) |
{ |
return intel_dsi->dev.type == INTEL_DSI_COMMAND_MODE; |
return intel_dsi->operation_mode == INTEL_DSI_COMMAND_MODE; |
} |
|
static void intel_dsi_hot_plug(struct intel_encoder *encoder) |
87,6 → 92,9 |
if (fixed_mode) |
intel_fixed_panel_mode(fixed_mode, adjusted_mode); |
|
/* DSI uses short packets for sync events, so clear mode flags for DSI */ |
adjusted_mode->flags = 0; |
|
if (intel_dsi->dev.dev_ops->mode_fixup) |
return intel_dsi->dev.dev_ops->mode_fixup(&intel_dsi->dev, |
mode, adjusted_mode); |
94,13 → 102,6 |
return true; |
} |
|
static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) |
{ |
DRM_DEBUG_KMS("\n"); |
|
vlv_enable_dsi_pll(encoder); |
} |
|
static void intel_dsi_device_ready(struct intel_encoder *encoder) |
{ |
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
110,32 → 111,27 |
|
DRM_DEBUG_KMS("\n"); |
|
mutex_lock(&dev_priv->dpio_lock); |
/* program rcomp for compliance, reduce from 50 ohms to 45 ohms |
* needed everytime after power gate */ |
vlv_flisdsi_write(dev_priv, 0x04, 0x0004); |
mutex_unlock(&dev_priv->dpio_lock); |
|
/* bandgap reset is needed after everytime we do power gate */ |
band_gap_reset(dev_priv); |
|
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER); |
usleep_range(2500, 3000); |
|
val = I915_READ(MIPI_PORT_CTRL(pipe)); |
I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD); |
usleep_range(1000, 1500); |
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT); |
usleep_range(2000, 2500); |
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY); |
usleep_range(2000, 2500); |
I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00); |
usleep_range(2000, 2500); |
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY); |
usleep_range(2000, 2500); |
} |
static void intel_dsi_pre_enable(struct intel_encoder *encoder) |
{ |
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
|
DRM_DEBUG_KMS("\n"); |
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT); |
usleep_range(2500, 3000); |
|
if (intel_dsi->dev.dev_ops->panel_reset) |
intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev); |
|
/* put device in ready state */ |
intel_dsi_device_ready(encoder); |
|
if (intel_dsi->dev.dev_ops->send_otp_cmds) |
intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev); |
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY); |
usleep_range(2500, 3000); |
} |
|
static void intel_dsi_enable(struct intel_encoder *encoder) |
153,9 → 149,14 |
I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4); |
else { |
msleep(20); /* XXX */ |
dpi_send_cmd(intel_dsi, TURN_ON); |
dpi_send_cmd(intel_dsi, TURN_ON, DPI_LP_MODE_EN); |
msleep(100); |
|
if (intel_dsi->dev.dev_ops->enable) |
intel_dsi->dev.dev_ops->enable(&intel_dsi->dev); |
|
wait_for_dsi_fifo_empty(intel_dsi); |
|
/* assert ip_tg_enable signal */ |
temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK; |
temp = temp | intel_dsi->port_bits; |
162,11 → 163,74 |
I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE); |
POSTING_READ(MIPI_PORT_CTRL(pipe)); |
} |
} |
|
if (intel_dsi->dev.dev_ops->enable) |
intel_dsi->dev.dev_ops->enable(&intel_dsi->dev); |
static void intel_dsi_pre_enable(struct intel_encoder *encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
enum pipe pipe = intel_crtc->pipe; |
u32 tmp; |
|
DRM_DEBUG_KMS("\n"); |
|
/* Disable DPOunit clock gating, can stall pipe |
* and we need DPLL REFA always enabled */ |
tmp = I915_READ(DPLL(pipe)); |
tmp |= DPLL_REFA_CLK_ENABLE_VLV; |
I915_WRITE(DPLL(pipe), tmp); |
|
/* update the hw state for DPLL */ |
intel_crtc->config.dpll_hw_state.dpll = DPLL_INTEGRATED_CLOCK_VLV | |
DPLL_REFA_CLK_ENABLE_VLV; |
|
tmp = I915_READ(DSPCLK_GATE_D); |
tmp |= DPOUNIT_CLOCK_GATE_DISABLE; |
I915_WRITE(DSPCLK_GATE_D, tmp); |
|
/* put device in ready state */ |
intel_dsi_device_ready(encoder); |
|
msleep(intel_dsi->panel_on_delay); |
|
if (intel_dsi->dev.dev_ops->panel_reset) |
intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev); |
|
if (intel_dsi->dev.dev_ops->send_otp_cmds) |
intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev); |
|
wait_for_dsi_fifo_empty(intel_dsi); |
|
/* Enable port in pre-enable phase itself because as per hw team |
* recommendation, port should be enabled befor plane & pipe */ |
intel_dsi_enable(encoder); |
} |
|
static void intel_dsi_enable_nop(struct intel_encoder *encoder) |
{ |
DRM_DEBUG_KMS("\n"); |
|
/* for DSI port enable has to be done before pipe |
* and plane enable, so port enable is done in |
* pre_enable phase itself unlike other encoders |
*/ |
} |
|
static void intel_dsi_pre_disable(struct intel_encoder *encoder) |
{ |
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
|
DRM_DEBUG_KMS("\n"); |
|
if (is_vid_mode(intel_dsi)) { |
/* Send Shutdown command to the panel in LP mode */ |
dpi_send_cmd(intel_dsi, SHUTDOWN, DPI_LP_MODE_EN); |
msleep(10); |
} |
} |
|
static void intel_dsi_disable(struct intel_encoder *encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
179,8 → 243,7 |
DRM_DEBUG_KMS("\n"); |
|
if (is_vid_mode(intel_dsi)) { |
dpi_send_cmd(intel_dsi, SHUTDOWN); |
msleep(10); |
wait_for_dsi_fifo_empty(intel_dsi); |
|
/* de-assert ip_tg_enable signal */ |
temp = I915_READ(MIPI_PORT_CTRL(pipe)); |
190,10 → 253,29 |
msleep(2); |
} |
|
/* Panel commands can be sent when clock is in LP11 */ |
I915_WRITE(MIPI_DEVICE_READY(pipe), 0x0); |
|
temp = I915_READ(MIPI_CTRL(pipe)); |
temp &= ~ESCAPE_CLOCK_DIVIDER_MASK; |
I915_WRITE(MIPI_CTRL(pipe), temp | |
intel_dsi->escape_clk_div << |
ESCAPE_CLOCK_DIVIDER_SHIFT); |
|
I915_WRITE(MIPI_EOT_DISABLE(pipe), CLOCKSTOP); |
|
temp = I915_READ(MIPI_DSI_FUNC_PRG(pipe)); |
temp &= ~VID_MODE_FORMAT_MASK; |
I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), temp); |
|
I915_WRITE(MIPI_DEVICE_READY(pipe), 0x1); |
|
/* if disable packets are sent before sending shutdown packet then in |
* some next enable sequence send turn on packet error is observed */ |
if (intel_dsi->dev.dev_ops->disable) |
intel_dsi->dev.dev_ops->disable(&intel_dsi->dev); |
|
wait_for_dsi_fifo_empty(intel_dsi); |
} |
|
static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) |
205,38 → 287,50 |
|
DRM_DEBUG_KMS("\n"); |
|
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER); |
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_ENTER); |
usleep_range(2000, 2500); |
|
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT); |
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT); |
usleep_range(2000, 2500); |
|
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER); |
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_ENTER); |
usleep_range(2000, 2500); |
|
if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT) |
== 0x00000), 30)) |
DRM_ERROR("DSI LP not going Low\n"); |
|
val = I915_READ(MIPI_PORT_CTRL(pipe)); |
I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD); |
usleep_range(1000, 1500); |
|
if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT) |
== 0x00000), 30)) |
DRM_ERROR("DSI LP not going Low\n"); |
|
I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00); |
usleep_range(2000, 2500); |
|
vlv_disable_dsi_pll(encoder); |
} |
|
static void intel_dsi_post_disable(struct intel_encoder *encoder) |
{ |
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
u32 val; |
|
DRM_DEBUG_KMS("\n"); |
|
intel_dsi_disable(encoder); |
|
intel_dsi_clear_device_ready(encoder); |
|
val = I915_READ(DSPCLK_GATE_D); |
val &= ~DPOUNIT_CLOCK_GATE_DISABLE; |
I915_WRITE(DSPCLK_GATE_D, val); |
|
if (intel_dsi->dev.dev_ops->disable_panel_power) |
intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev); |
|
msleep(intel_dsi->panel_off_delay); |
msleep(intel_dsi->panel_pwr_cycle_delay); |
} |
|
static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, |
243,11 → 337,16 |
enum pipe *pipe) |
{ |
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
enum intel_display_power_domain power_domain; |
u32 port, func; |
enum pipe p; |
|
DRM_DEBUG_KMS("\n"); |
|
power_domain = intel_display_port_power_domain(encoder); |
if (!intel_display_power_enabled(dev_priv, power_domain)) |
return false; |
|
/* XXX: this only works for one DSI output */ |
for (p = PIPE_A; p <= PIPE_B; p++) { |
port = I915_READ(MIPI_PORT_CTRL(p)); |
267,9 → 366,21 |
static void intel_dsi_get_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
{ |
u32 pclk; |
DRM_DEBUG_KMS("\n"); |
|
/* XXX: read flags, set to adjusted_mode */ |
/* |
* DPLL_MD is not used in case of DSI, reading will get some default value |
* set dpll_md = 0 |
*/ |
pipe_config->dpll_hw_state.dpll_md = 0; |
|
pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp); |
if (!pclk) |
return; |
|
pipe_config->adjusted_mode.crtc_clock = pclk; |
pipe_config->port_clock = pclk; |
} |
|
static enum drm_mode_status |
359,7 → 470,7 |
I915_WRITE(MIPI_VBP_COUNT(pipe), vbp); |
} |
|
static void intel_dsi_mode_set(struct intel_encoder *intel_encoder) |
static void intel_dsi_prepare(struct intel_encoder *intel_encoder) |
{ |
struct drm_encoder *encoder = &intel_encoder->base; |
struct drm_device *dev = encoder->dev; |
374,9 → 485,6 |
|
DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); |
|
/* XXX: Location of the call */ |
band_gap_reset(dev_priv); |
|
/* escape clock divider, 20MHz, shared for A and C. device ready must be |
* off when doing this! txclkesc? */ |
tmp = I915_READ(MIPI_CTRL(0)); |
447,11 → 555,21 |
/* dphy stuff */ |
|
/* in terms of low power clock */ |
I915_WRITE(MIPI_INIT_COUNT(pipe), txclkesc(ESCAPE_CLOCK_DIVIDER_1, 100)); |
I915_WRITE(MIPI_INIT_COUNT(pipe), txclkesc(intel_dsi->escape_clk_div, 100)); |
|
val = 0; |
if (intel_dsi->eotp_pkt == 0) |
val |= EOT_DISABLE; |
|
if (intel_dsi->clock_stop) |
val |= CLOCKSTOP; |
|
/* recovery disables */ |
I915_WRITE(MIPI_EOT_DISABLE(pipe), intel_dsi->eot_disable); |
I915_WRITE(MIPI_EOT_DISABLE(pipe), val); |
|
/* in terms of low power clock */ |
I915_WRITE(MIPI_INIT_COUNT(pipe), intel_dsi->init_count); |
|
/* in terms of txbyteclkhs. actual high to low switch + |
* MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK. |
* |
479,17 → 597,42 |
intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT); |
|
if (is_vid_mode(intel_dsi)) |
/* Some panels might have resolution which is not a multiple of |
* 64 like 1366 x 768. Enable RANDOM resolution support for such |
* panels by default */ |
I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe), |
intel_dsi->video_frmt_cfg_bits | |
intel_dsi->video_mode_format); |
intel_dsi->video_mode_format | |
IP_TG_CONFIG | |
RANDOM_DPI_DISPLAY_RESOLUTION); |
} |
|
static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) |
{ |
DRM_DEBUG_KMS("\n"); |
|
intel_dsi_prepare(encoder); |
|
vlv_enable_dsi_pll(encoder); |
} |
|
static enum drm_connector_status |
intel_dsi_detect(struct drm_connector *connector, bool force) |
{ |
struct intel_dsi *intel_dsi = intel_attached_dsi(connector); |
struct intel_encoder *intel_encoder = &intel_dsi->base; |
enum intel_display_power_domain power_domain; |
enum drm_connector_status connector_status; |
struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private; |
|
DRM_DEBUG_KMS("\n"); |
return intel_dsi->dev.dev_ops->detect(&intel_dsi->dev); |
power_domain = intel_display_port_power_domain(intel_encoder); |
|
intel_display_power_get(dev_priv, power_domain); |
connector_status = intel_dsi->dev.dev_ops->detect(&intel_dsi->dev); |
intel_display_power_put(dev_priv, power_domain); |
|
return connector_status; |
} |
|
static int intel_dsi_get_modes(struct drm_connector *connector) |
542,7 → 685,7 |
.fill_modes = drm_helper_probe_single_connector_modes, |
}; |
|
bool intel_dsi_init(struct drm_device *dev) |
void intel_dsi_init(struct drm_device *dev) |
{ |
struct intel_dsi *intel_dsi; |
struct intel_encoder *intel_encoder; |
550,19 → 693,31 |
struct intel_connector *intel_connector; |
struct drm_connector *connector; |
struct drm_display_mode *fixed_mode = NULL; |
struct drm_i915_private *dev_priv = dev->dev_private; |
const struct intel_dsi_device *dsi; |
unsigned int i; |
|
DRM_DEBUG_KMS("\n"); |
|
/* There is no detection method for MIPI so rely on VBT */ |
if (!dev_priv->vbt.has_mipi) |
return; |
|
if (IS_VALLEYVIEW(dev)) { |
dev_priv->mipi_mmio_base = VLV_MIPI_BASE; |
} else { |
DRM_ERROR("Unsupported Mipi device to reg base"); |
return; |
} |
|
intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL); |
if (!intel_dsi) |
return false; |
return; |
|
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); |
if (!intel_connector) { |
kfree(intel_dsi); |
return false; |
return; |
} |
|
intel_encoder = &intel_dsi->base; |
578,14 → 733,14 |
intel_encoder->compute_config = intel_dsi_compute_config; |
intel_encoder->pre_pll_enable = intel_dsi_pre_pll_enable; |
intel_encoder->pre_enable = intel_dsi_pre_enable; |
intel_encoder->enable = intel_dsi_enable; |
intel_encoder->mode_set = intel_dsi_mode_set; |
intel_encoder->disable = intel_dsi_disable; |
intel_encoder->enable = intel_dsi_enable_nop; |
intel_encoder->disable = intel_dsi_pre_disable; |
intel_encoder->post_disable = intel_dsi_post_disable; |
intel_encoder->get_hw_state = intel_dsi_get_hw_state; |
intel_encoder->get_config = intel_dsi_get_config; |
|
intel_connector->get_hw_state = intel_connector_get_hw_state; |
intel_connector->unregister = intel_connector_unregister; |
|
for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) { |
dsi = &intel_dsi_devices[i]; |
603,7 → 758,7 |
intel_encoder->type = INTEL_OUTPUT_DSI; |
intel_encoder->crtc_mask = (1 << 0); /* XXX */ |
|
intel_encoder->cloneable = false; |
intel_encoder->cloneable = 0; |
drm_connector_init(dev, connector, &intel_dsi_connector_funcs, |
DRM_MODE_CONNECTOR_DSI); |
|
615,7 → 770,7 |
|
intel_connector_attach_encoder(intel_connector, intel_encoder); |
|
drm_sysfs_connector_add(connector); |
drm_connector_register(connector); |
|
fixed_mode = dsi->dev_ops->get_modes(&intel_dsi->dev); |
if (!fixed_mode) { |
624,14 → 779,12 |
} |
|
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; |
intel_panel_init(&intel_connector->panel, fixed_mode); |
intel_panel_init(&intel_connector->panel, fixed_mode, NULL); |
|
return true; |
return; |
|
err: |
drm_encoder_cleanup(&intel_encoder->base); |
kfree(intel_dsi); |
kfree(intel_connector); |
|
return false; |
} |