diff options
Diffstat (limited to 'drivers/gpu/drm/i915/vlv_dsi.c')
-rw-r--r-- | drivers/gpu/drm/i915/vlv_dsi.c | 190 |
1 files changed, 51 insertions, 139 deletions
diff --git a/drivers/gpu/drm/i915/vlv_dsi.c b/drivers/gpu/drm/i915/vlv_dsi.c index 435a2c35ee8c..361e962a7969 100644 --- a/drivers/gpu/drm/i915/vlv_dsi.c +++ b/drivers/gpu/drm/i915/vlv_dsi.c | |||
@@ -206,39 +206,6 @@ static const struct mipi_dsi_host_ops intel_dsi_host_ops = { | |||
206 | .transfer = intel_dsi_host_transfer, | 206 | .transfer = intel_dsi_host_transfer, |
207 | }; | 207 | }; |
208 | 208 | ||
209 | static struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi, | ||
210 | enum port port) | ||
211 | { | ||
212 | struct intel_dsi_host *host; | ||
213 | struct mipi_dsi_device *device; | ||
214 | |||
215 | host = kzalloc(sizeof(*host), GFP_KERNEL); | ||
216 | if (!host) | ||
217 | return NULL; | ||
218 | |||
219 | host->base.ops = &intel_dsi_host_ops; | ||
220 | host->intel_dsi = intel_dsi; | ||
221 | host->port = port; | ||
222 | |||
223 | /* | ||
224 | * We should call mipi_dsi_host_register(&host->base) here, but we don't | ||
225 | * have a host->dev, and we don't have OF stuff either. So just use the | ||
226 | * dsi framework as a library and hope for the best. Create the dsi | ||
227 | * devices by ourselves here too. Need to be careful though, because we | ||
228 | * don't initialize any of the driver model devices here. | ||
229 | */ | ||
230 | device = kzalloc(sizeof(*device), GFP_KERNEL); | ||
231 | if (!device) { | ||
232 | kfree(host); | ||
233 | return NULL; | ||
234 | } | ||
235 | |||
236 | device->host = &host->base; | ||
237 | host->device = device; | ||
238 | |||
239 | return host; | ||
240 | } | ||
241 | |||
242 | /* | 209 | /* |
243 | * send a video mode command | 210 | * send a video mode command |
244 | * | 211 | * |
@@ -290,16 +257,6 @@ static void band_gap_reset(struct drm_i915_private *dev_priv) | |||
290 | mutex_unlock(&dev_priv->sb_lock); | 257 | mutex_unlock(&dev_priv->sb_lock); |
291 | } | 258 | } |
292 | 259 | ||
293 | static inline bool is_vid_mode(struct intel_dsi *intel_dsi) | ||
294 | { | ||
295 | return intel_dsi->operation_mode == INTEL_DSI_VIDEO_MODE; | ||
296 | } | ||
297 | |||
298 | static inline bool is_cmd_mode(struct intel_dsi *intel_dsi) | ||
299 | { | ||
300 | return intel_dsi->operation_mode == INTEL_DSI_COMMAND_MODE; | ||
301 | } | ||
302 | |||
303 | static bool intel_dsi_compute_config(struct intel_encoder *encoder, | 260 | static bool intel_dsi_compute_config(struct intel_encoder *encoder, |
304 | struct intel_crtc_state *pipe_config, | 261 | struct intel_crtc_state *pipe_config, |
305 | struct drm_connector_state *conn_state) | 262 | struct drm_connector_state *conn_state) |
@@ -314,6 +271,7 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder, | |||
314 | int ret; | 271 | int ret; |
315 | 272 | ||
316 | DRM_DEBUG_KMS("\n"); | 273 | DRM_DEBUG_KMS("\n"); |
274 | pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; | ||
317 | 275 | ||
318 | if (fixed_mode) { | 276 | if (fixed_mode) { |
319 | intel_fixed_panel_mode(fixed_mode, adjusted_mode); | 277 | intel_fixed_panel_mode(fixed_mode, adjusted_mode); |
@@ -745,17 +703,6 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, | |||
745 | const struct intel_crtc_state *pipe_config); | 703 | const struct intel_crtc_state *pipe_config); |
746 | static void intel_dsi_unprepare(struct intel_encoder *encoder); | 704 | static void intel_dsi_unprepare(struct intel_encoder *encoder); |
747 | 705 | ||
748 | static void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec) | ||
749 | { | ||
750 | struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); | ||
751 | |||
752 | /* For v3 VBTs in vid-mode the delays are part of the VBT sequences */ | ||
753 | if (is_vid_mode(intel_dsi) && dev_priv->vbt.dsi.seq_version >= 3) | ||
754 | return; | ||
755 | |||
756 | msleep(msec); | ||
757 | } | ||
758 | |||
759 | /* | 706 | /* |
760 | * Panel enable/disable sequences from the VBT spec. | 707 | * Panel enable/disable sequences from the VBT spec. |
761 | * | 708 | * |
@@ -793,6 +740,10 @@ static void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec) | |||
793 | * - wait t4 - wait t4 | 740 | * - wait t4 - wait t4 |
794 | */ | 741 | */ |
795 | 742 | ||
743 | /* | ||
744 | * DSI port enable has to be done before pipe and plane enable, so we do it in | ||
745 | * the pre_enable hook instead of the enable hook. | ||
746 | */ | ||
796 | static void intel_dsi_pre_enable(struct intel_encoder *encoder, | 747 | static void intel_dsi_pre_enable(struct intel_encoder *encoder, |
797 | const struct intel_crtc_state *pipe_config, | 748 | const struct intel_crtc_state *pipe_config, |
798 | const struct drm_connector_state *conn_state) | 749 | const struct drm_connector_state *conn_state) |
@@ -895,17 +846,6 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder, | |||
895 | } | 846 | } |
896 | 847 | ||
897 | /* | 848 | /* |
898 | * DSI port enable has to be done before pipe and plane enable, so we do it in | ||
899 | * the pre_enable hook. | ||
900 | */ | ||
901 | static void intel_dsi_enable_nop(struct intel_encoder *encoder, | ||
902 | const struct intel_crtc_state *pipe_config, | ||
903 | const struct drm_connector_state *conn_state) | ||
904 | { | ||
905 | DRM_DEBUG_KMS("\n"); | ||
906 | } | ||
907 | |||
908 | /* | ||
909 | * DSI port disable has to be done after pipe and plane disable, so we do it in | 849 | * DSI port disable has to be done after pipe and plane disable, so we do it in |
910 | * the post_disable hook. | 850 | * the post_disable hook. |
911 | */ | 851 | */ |
@@ -1272,31 +1212,6 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, | |||
1272 | } | 1212 | } |
1273 | } | 1213 | } |
1274 | 1214 | ||
1275 | static enum drm_mode_status | ||
1276 | intel_dsi_mode_valid(struct drm_connector *connector, | ||
1277 | struct drm_display_mode *mode) | ||
1278 | { | ||
1279 | struct intel_connector *intel_connector = to_intel_connector(connector); | ||
1280 | const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; | ||
1281 | int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; | ||
1282 | |||
1283 | DRM_DEBUG_KMS("\n"); | ||
1284 | |||
1285 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
1286 | return MODE_NO_DBLESCAN; | ||
1287 | |||
1288 | if (fixed_mode) { | ||
1289 | if (mode->hdisplay > fixed_mode->hdisplay) | ||
1290 | return MODE_PANEL; | ||
1291 | if (mode->vdisplay > fixed_mode->vdisplay) | ||
1292 | return MODE_PANEL; | ||
1293 | if (fixed_mode->clock > max_dotclk) | ||
1294 | return MODE_CLOCK_HIGH; | ||
1295 | } | ||
1296 | |||
1297 | return MODE_OK; | ||
1298 | } | ||
1299 | |||
1300 | /* return txclkesc cycles in terms of divider and duration in us */ | 1215 | /* return txclkesc cycles in terms of divider and duration in us */ |
1301 | static u16 txclkesc(u32 divider, unsigned int us) | 1216 | static u16 txclkesc(u32 divider, unsigned int us) |
1302 | { | 1217 | { |
@@ -1619,39 +1534,6 @@ static void intel_dsi_unprepare(struct intel_encoder *encoder) | |||
1619 | } | 1534 | } |
1620 | } | 1535 | } |
1621 | 1536 | ||
1622 | static int intel_dsi_get_modes(struct drm_connector *connector) | ||
1623 | { | ||
1624 | struct intel_connector *intel_connector = to_intel_connector(connector); | ||
1625 | struct drm_display_mode *mode; | ||
1626 | |||
1627 | DRM_DEBUG_KMS("\n"); | ||
1628 | |||
1629 | if (!intel_connector->panel.fixed_mode) { | ||
1630 | DRM_DEBUG_KMS("no fixed mode\n"); | ||
1631 | return 0; | ||
1632 | } | ||
1633 | |||
1634 | mode = drm_mode_duplicate(connector->dev, | ||
1635 | intel_connector->panel.fixed_mode); | ||
1636 | if (!mode) { | ||
1637 | DRM_DEBUG_KMS("drm_mode_duplicate failed\n"); | ||
1638 | return 0; | ||
1639 | } | ||
1640 | |||
1641 | drm_mode_probed_add(connector, mode); | ||
1642 | return 1; | ||
1643 | } | ||
1644 | |||
1645 | static void intel_dsi_connector_destroy(struct drm_connector *connector) | ||
1646 | { | ||
1647 | struct intel_connector *intel_connector = to_intel_connector(connector); | ||
1648 | |||
1649 | DRM_DEBUG_KMS("\n"); | ||
1650 | intel_panel_fini(&intel_connector->panel); | ||
1651 | drm_connector_cleanup(connector); | ||
1652 | kfree(connector); | ||
1653 | } | ||
1654 | |||
1655 | static void intel_dsi_encoder_destroy(struct drm_encoder *encoder) | 1537 | static void intel_dsi_encoder_destroy(struct drm_encoder *encoder) |
1656 | { | 1538 | { |
1657 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); | 1539 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); |
@@ -1676,7 +1558,7 @@ static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs | |||
1676 | static const struct drm_connector_funcs intel_dsi_connector_funcs = { | 1558 | static const struct drm_connector_funcs intel_dsi_connector_funcs = { |
1677 | .late_register = intel_connector_register, | 1559 | .late_register = intel_connector_register, |
1678 | .early_unregister = intel_connector_unregister, | 1560 | .early_unregister = intel_connector_unregister, |
1679 | .destroy = intel_dsi_connector_destroy, | 1561 | .destroy = intel_connector_destroy, |
1680 | .fill_modes = drm_helper_probe_single_connector_modes, | 1562 | .fill_modes = drm_helper_probe_single_connector_modes, |
1681 | .atomic_get_property = intel_digital_connector_atomic_get_property, | 1563 | .atomic_get_property = intel_digital_connector_atomic_get_property, |
1682 | .atomic_set_property = intel_digital_connector_atomic_set_property, | 1564 | .atomic_set_property = intel_digital_connector_atomic_set_property, |
@@ -1684,27 +1566,57 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = { | |||
1684 | .atomic_duplicate_state = intel_digital_connector_duplicate_state, | 1566 | .atomic_duplicate_state = intel_digital_connector_duplicate_state, |
1685 | }; | 1567 | }; |
1686 | 1568 | ||
1687 | static int intel_dsi_get_panel_orientation(struct intel_connector *connector) | 1569 | static enum drm_panel_orientation |
1570 | vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector) | ||
1688 | { | 1571 | { |
1689 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | 1572 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1690 | int orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; | 1573 | struct intel_encoder *encoder = connector->encoder; |
1691 | enum i9xx_plane_id i9xx_plane; | 1574 | enum intel_display_power_domain power_domain; |
1575 | enum drm_panel_orientation orientation; | ||
1576 | struct intel_plane *plane; | ||
1577 | struct intel_crtc *crtc; | ||
1578 | enum pipe pipe; | ||
1692 | u32 val; | 1579 | u32 val; |
1693 | 1580 | ||
1694 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | 1581 | if (!encoder->get_hw_state(encoder, &pipe)) |
1695 | if (connector->encoder->crtc_mask == BIT(PIPE_B)) | 1582 | return DRM_MODE_PANEL_ORIENTATION_UNKNOWN; |
1696 | i9xx_plane = PLANE_B; | ||
1697 | else | ||
1698 | i9xx_plane = PLANE_A; | ||
1699 | 1583 | ||
1700 | val = I915_READ(DSPCNTR(i9xx_plane)); | 1584 | crtc = intel_get_crtc_for_pipe(dev_priv, pipe); |
1701 | if (val & DISPPLANE_ROTATE_180) | 1585 | plane = to_intel_plane(crtc->base.primary); |
1702 | orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; | 1586 | |
1703 | } | 1587 | power_domain = POWER_DOMAIN_PIPE(pipe); |
1588 | if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) | ||
1589 | return DRM_MODE_PANEL_ORIENTATION_UNKNOWN; | ||
1590 | |||
1591 | val = I915_READ(DSPCNTR(plane->i9xx_plane)); | ||
1592 | |||
1593 | if (!(val & DISPLAY_PLANE_ENABLE)) | ||
1594 | orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; | ||
1595 | else if (val & DISPPLANE_ROTATE_180) | ||
1596 | orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; | ||
1597 | else | ||
1598 | orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; | ||
1599 | |||
1600 | intel_display_power_put(dev_priv, power_domain); | ||
1704 | 1601 | ||
1705 | return orientation; | 1602 | return orientation; |
1706 | } | 1603 | } |
1707 | 1604 | ||
1605 | static enum drm_panel_orientation | ||
1606 | vlv_dsi_get_panel_orientation(struct intel_connector *connector) | ||
1607 | { | ||
1608 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | ||
1609 | enum drm_panel_orientation orientation; | ||
1610 | |||
1611 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | ||
1612 | orientation = vlv_dsi_get_hw_panel_orientation(connector); | ||
1613 | if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) | ||
1614 | return orientation; | ||
1615 | } | ||
1616 | |||
1617 | return intel_dsi_get_panel_orientation(connector); | ||
1618 | } | ||
1619 | |||
1708 | static void intel_dsi_add_properties(struct intel_connector *connector) | 1620 | static void intel_dsi_add_properties(struct intel_connector *connector) |
1709 | { | 1621 | { |
1710 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | 1622 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
@@ -1722,7 +1634,7 @@ static void intel_dsi_add_properties(struct intel_connector *connector) | |||
1722 | connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; | 1634 | connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; |
1723 | 1635 | ||
1724 | connector->base.display_info.panel_orientation = | 1636 | connector->base.display_info.panel_orientation = |
1725 | intel_dsi_get_panel_orientation(connector); | 1637 | vlv_dsi_get_panel_orientation(connector); |
1726 | drm_connector_init_panel_orientation_property( | 1638 | drm_connector_init_panel_orientation_property( |
1727 | &connector->base, | 1639 | &connector->base, |
1728 | connector->panel.fixed_mode->hdisplay, | 1640 | connector->panel.fixed_mode->hdisplay, |
@@ -1773,7 +1685,6 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) | |||
1773 | 1685 | ||
1774 | intel_encoder->compute_config = intel_dsi_compute_config; | 1686 | intel_encoder->compute_config = intel_dsi_compute_config; |
1775 | intel_encoder->pre_enable = intel_dsi_pre_enable; | 1687 | intel_encoder->pre_enable = intel_dsi_pre_enable; |
1776 | intel_encoder->enable = intel_dsi_enable_nop; | ||
1777 | intel_encoder->disable = intel_dsi_disable; | 1688 | intel_encoder->disable = intel_dsi_disable; |
1778 | intel_encoder->post_disable = intel_dsi_post_disable; | 1689 | intel_encoder->post_disable = intel_dsi_post_disable; |
1779 | intel_encoder->get_hw_state = intel_dsi_get_hw_state; | 1690 | intel_encoder->get_hw_state = intel_dsi_get_hw_state; |
@@ -1806,7 +1717,8 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) | |||
1806 | for_each_dsi_port(port, intel_dsi->ports) { | 1717 | for_each_dsi_port(port, intel_dsi->ports) { |
1807 | struct intel_dsi_host *host; | 1718 | struct intel_dsi_host *host; |
1808 | 1719 | ||
1809 | host = intel_dsi_host_init(intel_dsi, port); | 1720 | host = intel_dsi_host_init(intel_dsi, &intel_dsi_host_ops, |
1721 | port); | ||
1810 | if (!host) | 1722 | if (!host) |
1811 | goto err; | 1723 | goto err; |
1812 | 1724 | ||