diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-18 10:55:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-18 10:55:05 -0400 |
commit | f4566ed08d34ba299412d0bb1a6909ec9af0ed35 (patch) | |
tree | 812dad9c22b81c5f9de899afbe61696c5463ef2d | |
parent | bf6740281ed599f98ba13eb3f017ca83deb6277f (diff) | |
parent | 7945dc5885c51d05d9368fd0066755adca73f009 (diff) |
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie:
"These came in late last week, I wanted to look over the mst one before
forwarding, but it seems good.
Just three i915 and one MST fix"
* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
drm/i915: Commit planes on each crtc separately.
drm/i915: calculate primary visibility changes instead of calling from set_config
drm/i915: Only dither on 6bpc panels
drm/dp/mst: Remove port after removing connector.
-rw-r--r-- | drivers/gpu/drm/drm_dp_mst_topology.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_atomic.c | 45 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 59 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 2 |
4 files changed, 36 insertions, 89 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index b0487c9f018c..eb603f1defc2 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c | |||
@@ -873,9 +873,10 @@ static void drm_dp_destroy_port(struct kref *kref) | |||
873 | from an EDID retrieval */ | 873 | from an EDID retrieval */ |
874 | if (port->connector) { | 874 | if (port->connector) { |
875 | mutex_lock(&mgr->destroy_connector_lock); | 875 | mutex_lock(&mgr->destroy_connector_lock); |
876 | list_add(&port->connector->destroy_list, &mgr->destroy_connector_list); | 876 | list_add(&port->next, &mgr->destroy_connector_list); |
877 | mutex_unlock(&mgr->destroy_connector_lock); | 877 | mutex_unlock(&mgr->destroy_connector_lock); |
878 | schedule_work(&mgr->destroy_connector_work); | 878 | schedule_work(&mgr->destroy_connector_work); |
879 | return; | ||
879 | } | 880 | } |
880 | drm_dp_port_teardown_pdt(port, port->pdt); | 881 | drm_dp_port_teardown_pdt(port, port->pdt); |
881 | 882 | ||
@@ -2659,7 +2660,7 @@ static void drm_dp_tx_work(struct work_struct *work) | |||
2659 | static void drm_dp_destroy_connector_work(struct work_struct *work) | 2660 | static void drm_dp_destroy_connector_work(struct work_struct *work) |
2660 | { | 2661 | { |
2661 | struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work); | 2662 | struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work); |
2662 | struct drm_connector *connector; | 2663 | struct drm_dp_mst_port *port; |
2663 | 2664 | ||
2664 | /* | 2665 | /* |
2665 | * Not a regular list traverse as we have to drop the destroy | 2666 | * Not a regular list traverse as we have to drop the destroy |
@@ -2668,15 +2669,21 @@ static void drm_dp_destroy_connector_work(struct work_struct *work) | |||
2668 | */ | 2669 | */ |
2669 | for (;;) { | 2670 | for (;;) { |
2670 | mutex_lock(&mgr->destroy_connector_lock); | 2671 | mutex_lock(&mgr->destroy_connector_lock); |
2671 | connector = list_first_entry_or_null(&mgr->destroy_connector_list, struct drm_connector, destroy_list); | 2672 | port = list_first_entry_or_null(&mgr->destroy_connector_list, struct drm_dp_mst_port, next); |
2672 | if (!connector) { | 2673 | if (!port) { |
2673 | mutex_unlock(&mgr->destroy_connector_lock); | 2674 | mutex_unlock(&mgr->destroy_connector_lock); |
2674 | break; | 2675 | break; |
2675 | } | 2676 | } |
2676 | list_del(&connector->destroy_list); | 2677 | list_del(&port->next); |
2677 | mutex_unlock(&mgr->destroy_connector_lock); | 2678 | mutex_unlock(&mgr->destroy_connector_lock); |
2678 | 2679 | ||
2679 | mgr->cbs->destroy_connector(mgr, connector); | 2680 | mgr->cbs->destroy_connector(mgr, port->connector); |
2681 | |||
2682 | drm_dp_port_teardown_pdt(port, port->pdt); | ||
2683 | |||
2684 | if (!port->input && port->vcpi.vcpi > 0) | ||
2685 | drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); | ||
2686 | kfree(port); | ||
2680 | } | 2687 | } |
2681 | } | 2688 | } |
2682 | 2689 | ||
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 7ed8033aae60..8e35e0d013df 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c | |||
@@ -129,8 +129,9 @@ int intel_atomic_commit(struct drm_device *dev, | |||
129 | struct drm_atomic_state *state, | 129 | struct drm_atomic_state *state, |
130 | bool async) | 130 | bool async) |
131 | { | 131 | { |
132 | int ret; | 132 | struct drm_crtc_state *crtc_state; |
133 | int i; | 133 | struct drm_crtc *crtc; |
134 | int ret, i; | ||
134 | 135 | ||
135 | if (async) { | 136 | if (async) { |
136 | DRM_DEBUG_KMS("i915 does not yet support async commit\n"); | 137 | DRM_DEBUG_KMS("i915 does not yet support async commit\n"); |
@@ -142,48 +143,18 @@ int intel_atomic_commit(struct drm_device *dev, | |||
142 | return ret; | 143 | return ret; |
143 | 144 | ||
144 | /* Point of no return */ | 145 | /* Point of no return */ |
145 | 146 | drm_atomic_helper_swap_state(dev, state); | |
146 | /* | ||
147 | * FIXME: The proper sequence here will eventually be: | ||
148 | * | ||
149 | * drm_atomic_helper_swap_state(dev, state) | ||
150 | * drm_atomic_helper_commit_modeset_disables(dev, state); | ||
151 | * drm_atomic_helper_commit_planes(dev, state); | ||
152 | * drm_atomic_helper_commit_modeset_enables(dev, state); | ||
153 | * drm_atomic_helper_wait_for_vblanks(dev, state); | ||
154 | * drm_atomic_helper_cleanup_planes(dev, state); | ||
155 | * drm_atomic_state_free(state); | ||
156 | * | ||
157 | * once we have full atomic modeset. For now, just manually update | ||
158 | * plane states to avoid clobbering good states with dummy states | ||
159 | * while nuclear pageflipping. | ||
160 | */ | ||
161 | for (i = 0; i < dev->mode_config.num_total_plane; i++) { | ||
162 | struct drm_plane *plane = state->planes[i]; | ||
163 | |||
164 | if (!plane) | ||
165 | continue; | ||
166 | |||
167 | plane->state->state = state; | ||
168 | swap(state->plane_states[i], plane->state); | ||
169 | plane->state->state = NULL; | ||
170 | } | ||
171 | 147 | ||
172 | /* swap crtc_scaler_state */ | 148 | /* swap crtc_scaler_state */ |
173 | for (i = 0; i < dev->mode_config.num_crtc; i++) { | 149 | for_each_crtc_in_state(state, crtc, crtc_state, i) { |
174 | struct drm_crtc *crtc = state->crtcs[i]; | 150 | to_intel_crtc(crtc)->config = to_intel_crtc_state(crtc->state); |
175 | if (!crtc) { | ||
176 | continue; | ||
177 | } | ||
178 | |||
179 | to_intel_crtc(crtc)->config->scaler_state = | ||
180 | to_intel_crtc_state(state->crtc_states[i])->scaler_state; | ||
181 | 151 | ||
182 | if (INTEL_INFO(dev)->gen >= 9) | 152 | if (INTEL_INFO(dev)->gen >= 9) |
183 | skl_detach_scalers(to_intel_crtc(crtc)); | 153 | skl_detach_scalers(to_intel_crtc(crtc)); |
154 | |||
155 | drm_atomic_helper_commit_planes_on_crtc(crtc_state); | ||
184 | } | 156 | } |
185 | 157 | ||
186 | drm_atomic_helper_commit_planes(dev, state); | ||
187 | drm_atomic_helper_wait_for_vblanks(dev, state); | 158 | drm_atomic_helper_wait_for_vblanks(dev, state); |
188 | drm_atomic_helper_cleanup_planes(dev, state); | 159 | drm_atomic_helper_cleanup_planes(dev, state); |
189 | drm_atomic_state_free(state); | 160 | drm_atomic_state_free(state); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 30e0f54ba19d..87476ff181dd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -11826,7 +11826,9 @@ encoder_retry: | |||
11826 | goto encoder_retry; | 11826 | goto encoder_retry; |
11827 | } | 11827 | } |
11828 | 11828 | ||
11829 | pipe_config->dither = pipe_config->pipe_bpp != base_bpp; | 11829 | /* Dithering seems to not pass-through bits correctly when it should, so |
11830 | * only enable it on 6bpc panels. */ | ||
11831 | pipe_config->dither = pipe_config->pipe_bpp == 6*3; | ||
11830 | DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n", | 11832 | DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n", |
11831 | base_bpp, pipe_config->pipe_bpp, pipe_config->dither); | 11833 | base_bpp, pipe_config->pipe_bpp, pipe_config->dither); |
11832 | 11834 | ||
@@ -12624,17 +12626,17 @@ static int __intel_set_mode(struct drm_crtc *modeset_crtc, | |||
12624 | 12626 | ||
12625 | modeset_update_crtc_power_domains(state); | 12627 | modeset_update_crtc_power_domains(state); |
12626 | 12628 | ||
12627 | drm_atomic_helper_commit_planes(dev, state); | ||
12628 | |||
12629 | /* Now enable the clocks, plane, pipe, and connectors that we set up. */ | 12629 | /* Now enable the clocks, plane, pipe, and connectors that we set up. */ |
12630 | for_each_crtc_in_state(state, crtc, crtc_state, i) { | 12630 | for_each_crtc_in_state(state, crtc, crtc_state, i) { |
12631 | if (!needs_modeset(crtc->state) || !crtc->state->enable) | 12631 | if (!needs_modeset(crtc->state) || !crtc->state->enable) { |
12632 | drm_atomic_helper_commit_planes_on_crtc(crtc_state); | ||
12632 | continue; | 12633 | continue; |
12634 | } | ||
12633 | 12635 | ||
12634 | update_scanline_offset(to_intel_crtc(crtc)); | 12636 | update_scanline_offset(to_intel_crtc(crtc)); |
12635 | 12637 | ||
12636 | dev_priv->display.crtc_enable(crtc); | 12638 | dev_priv->display.crtc_enable(crtc); |
12637 | intel_crtc_enable_planes(crtc); | 12639 | drm_atomic_helper_commit_planes_on_crtc(crtc_state); |
12638 | } | 12640 | } |
12639 | 12641 | ||
12640 | /* FIXME: add subpixel order */ | 12642 | /* FIXME: add subpixel order */ |
@@ -12891,20 +12893,11 @@ intel_modeset_stage_output_state(struct drm_device *dev, | |||
12891 | return 0; | 12893 | return 0; |
12892 | } | 12894 | } |
12893 | 12895 | ||
12894 | static bool primary_plane_visible(struct drm_crtc *crtc) | ||
12895 | { | ||
12896 | struct intel_plane_state *plane_state = | ||
12897 | to_intel_plane_state(crtc->primary->state); | ||
12898 | |||
12899 | return plane_state->visible; | ||
12900 | } | ||
12901 | |||
12902 | static int intel_crtc_set_config(struct drm_mode_set *set) | 12896 | static int intel_crtc_set_config(struct drm_mode_set *set) |
12903 | { | 12897 | { |
12904 | struct drm_device *dev; | 12898 | struct drm_device *dev; |
12905 | struct drm_atomic_state *state = NULL; | 12899 | struct drm_atomic_state *state = NULL; |
12906 | struct intel_crtc_state *pipe_config; | 12900 | struct intel_crtc_state *pipe_config; |
12907 | bool primary_plane_was_visible; | ||
12908 | int ret; | 12901 | int ret; |
12909 | 12902 | ||
12910 | BUG_ON(!set); | 12903 | BUG_ON(!set); |
@@ -12943,38 +12936,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set) | |||
12943 | 12936 | ||
12944 | intel_update_pipe_size(to_intel_crtc(set->crtc)); | 12937 | intel_update_pipe_size(to_intel_crtc(set->crtc)); |
12945 | 12938 | ||
12946 | primary_plane_was_visible = primary_plane_visible(set->crtc); | ||
12947 | |||
12948 | ret = intel_set_mode_with_config(set->crtc, pipe_config, true); | 12939 | ret = intel_set_mode_with_config(set->crtc, pipe_config, true); |
12949 | 12940 | ||
12950 | if (ret == 0 && | ||
12951 | pipe_config->base.enable && | ||
12952 | pipe_config->base.planes_changed && | ||
12953 | !needs_modeset(&pipe_config->base)) { | ||
12954 | struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc); | ||
12955 | |||
12956 | /* | ||
12957 | * We need to make sure the primary plane is re-enabled if it | ||
12958 | * has previously been turned off. | ||
12959 | */ | ||
12960 | if (ret == 0 && !primary_plane_was_visible && | ||
12961 | primary_plane_visible(set->crtc)) { | ||
12962 | WARN_ON(!intel_crtc->active); | ||
12963 | intel_post_enable_primary(set->crtc); | ||
12964 | } | ||
12965 | |||
12966 | /* | ||
12967 | * In the fastboot case this may be our only check of the | ||
12968 | * state after boot. It would be better to only do it on | ||
12969 | * the first update, but we don't have a nice way of doing that | ||
12970 | * (and really, set_config isn't used much for high freq page | ||
12971 | * flipping, so increasing its cost here shouldn't be a big | ||
12972 | * deal). | ||
12973 | */ | ||
12974 | if (i915.fastboot && ret == 0) | ||
12975 | intel_modeset_check_state(set->crtc->dev); | ||
12976 | } | ||
12977 | |||
12978 | if (ret) { | 12941 | if (ret) { |
12979 | DRM_DEBUG_KMS("failed to set mode on [CRTC:%d], err = %d\n", | 12942 | DRM_DEBUG_KMS("failed to set mode on [CRTC:%d], err = %d\n", |
12980 | set->crtc->base.id, ret); | 12943 | set->crtc->base.id, ret); |
@@ -13305,6 +13268,9 @@ intel_check_primary_plane(struct drm_plane *plane, | |||
13305 | */ | 13268 | */ |
13306 | if (IS_BROADWELL(dev)) | 13269 | if (IS_BROADWELL(dev)) |
13307 | intel_crtc->atomic.wait_vblank = true; | 13270 | intel_crtc->atomic.wait_vblank = true; |
13271 | |||
13272 | if (crtc_state) | ||
13273 | intel_crtc->atomic.post_enable_primary = true; | ||
13308 | } | 13274 | } |
13309 | 13275 | ||
13310 | /* | 13276 | /* |
@@ -13317,6 +13283,10 @@ intel_check_primary_plane(struct drm_plane *plane, | |||
13317 | if (!state->visible || !fb) | 13283 | if (!state->visible || !fb) |
13318 | intel_crtc->atomic.disable_ips = true; | 13284 | intel_crtc->atomic.disable_ips = true; |
13319 | 13285 | ||
13286 | if (!state->visible && old_state->visible && | ||
13287 | crtc_state && !needs_modeset(&crtc_state->base)) | ||
13288 | intel_crtc->atomic.pre_disable_primary = true; | ||
13289 | |||
13320 | intel_crtc->atomic.fb_bits |= | 13290 | intel_crtc->atomic.fb_bits |= |
13321 | INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); | 13291 | INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); |
13322 | 13292 | ||
@@ -15034,6 +15004,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) | |||
15034 | struct intel_plane_state *plane_state; | 15004 | struct intel_plane_state *plane_state; |
15035 | 15005 | ||
15036 | memset(crtc->config, 0, sizeof(*crtc->config)); | 15006 | memset(crtc->config, 0, sizeof(*crtc->config)); |
15007 | crtc->config->base.crtc = &crtc->base; | ||
15037 | 15008 | ||
15038 | crtc->config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE; | 15009 | crtc->config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE; |
15039 | 15010 | ||
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 57ca8cc383a6..3b4d8a4a23fb 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -743,8 +743,6 @@ struct drm_connector { | |||
743 | uint8_t num_h_tile, num_v_tile; | 743 | uint8_t num_h_tile, num_v_tile; |
744 | uint8_t tile_h_loc, tile_v_loc; | 744 | uint8_t tile_h_loc, tile_v_loc; |
745 | uint16_t tile_h_size, tile_v_size; | 745 | uint16_t tile_h_size, tile_v_size; |
746 | |||
747 | struct list_head destroy_list; | ||
748 | }; | 746 | }; |
749 | 747 | ||
750 | /** | 748 | /** |