Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5059 → Rev 5060

/drivers/video/drm/i915/intel_dsi.c
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;
}