aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/dispnv50/disp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/dispnv50/disp.c')
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c103
1 files changed, 74 insertions, 29 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 26af45785939..67107f0b1299 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -561,7 +561,7 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
561 u32 max_ac_packet; 561 u32 max_ac_packet;
562 union hdmi_infoframe avi_frame; 562 union hdmi_infoframe avi_frame;
563 union hdmi_infoframe vendor_frame; 563 union hdmi_infoframe vendor_frame;
564 bool scdc_supported, high_tmds_clock_ratio = false, scrambling = false; 564 bool high_tmds_clock_ratio = false, scrambling = false;
565 u8 config; 565 u8 config;
566 int ret; 566 int ret;
567 int size; 567 int size;
@@ -571,10 +571,9 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
571 return; 571 return;
572 572
573 hdmi = &nv_connector->base.display_info.hdmi; 573 hdmi = &nv_connector->base.display_info.hdmi;
574 scdc_supported = hdmi->scdc.supported;
575 574
576 ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode, 575 ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi,
577 scdc_supported); 576 &nv_connector->base, mode);
578 if (!ret) { 577 if (!ret) {
579 /* We have an AVI InfoFrame, populate it to the display */ 578 /* We have an AVI InfoFrame, populate it to the display */
580 args.pwr.avi_infoframe_length 579 args.pwr.avi_infoframe_length
@@ -680,6 +679,8 @@ nv50_msto_payload(struct nv50_msto *msto)
680 struct nv50_mstm *mstm = mstc->mstm; 679 struct nv50_mstm *mstm = mstc->mstm;
681 int vcpi = mstc->port->vcpi.vcpi, i; 680 int vcpi = mstc->port->vcpi.vcpi, i;
682 681
682 WARN_ON(!mutex_is_locked(&mstm->mgr.payload_lock));
683
683 NV_ATOMIC(drm, "%s: vcpi %d\n", msto->encoder.name, vcpi); 684 NV_ATOMIC(drm, "%s: vcpi %d\n", msto->encoder.name, vcpi);
684 for (i = 0; i < mstm->mgr.max_payloads; i++) { 685 for (i = 0; i < mstm->mgr.max_payloads; i++) {
685 struct drm_dp_payload *payload = &mstm->mgr.payloads[i]; 686 struct drm_dp_payload *payload = &mstm->mgr.payloads[i];
@@ -704,14 +705,16 @@ nv50_msto_cleanup(struct nv50_msto *msto)
704 struct nv50_mstc *mstc = msto->mstc; 705 struct nv50_mstc *mstc = msto->mstc;
705 struct nv50_mstm *mstm = mstc->mstm; 706 struct nv50_mstm *mstm = mstc->mstm;
706 707
708 if (!msto->disabled)
709 return;
710
707 NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name); 711 NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name);
708 if (mstc->port && mstc->port->vcpi.vcpi > 0 && !nv50_msto_payload(msto)) 712
709 drm_dp_mst_deallocate_vcpi(&mstm->mgr, mstc->port); 713 drm_dp_mst_deallocate_vcpi(&mstm->mgr, mstc->port);
710 if (msto->disabled) { 714
711 msto->mstc = NULL; 715 msto->mstc = NULL;
712 msto->head = NULL; 716 msto->head = NULL;
713 msto->disabled = false; 717 msto->disabled = false;
714 }
715} 718}
716 719
717static void 720static void
@@ -731,8 +734,10 @@ nv50_msto_prepare(struct nv50_msto *msto)
731 (0x0100 << msto->head->base.index), 734 (0x0100 << msto->head->base.index),
732 }; 735 };
733 736
737 mutex_lock(&mstm->mgr.payload_lock);
738
734 NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name); 739 NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
735 if (mstc->port && mstc->port->vcpi.vcpi > 0) { 740 if (mstc->port->vcpi.vcpi > 0) {
736 struct drm_dp_payload *payload = nv50_msto_payload(msto); 741 struct drm_dp_payload *payload = nv50_msto_payload(msto);
737 if (payload) { 742 if (payload) {
738 args.vcpi.start_slot = payload->start_slot; 743 args.vcpi.start_slot = payload->start_slot;
@@ -746,7 +751,9 @@ nv50_msto_prepare(struct nv50_msto *msto)
746 msto->encoder.name, msto->head->base.base.name, 751 msto->encoder.name, msto->head->base.base.name,
747 args.vcpi.start_slot, args.vcpi.num_slots, 752 args.vcpi.start_slot, args.vcpi.num_slots,
748 args.vcpi.pbn, args.vcpi.aligned_pbn); 753 args.vcpi.pbn, args.vcpi.aligned_pbn);
754
749 nvif_mthd(&drm->display->disp.object, 0, &args, sizeof(args)); 755 nvif_mthd(&drm->display->disp.object, 0, &args, sizeof(args));
756 mutex_unlock(&mstm->mgr.payload_lock);
750} 757}
751 758
752static int 759static int
@@ -754,16 +761,23 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
754 struct drm_crtc_state *crtc_state, 761 struct drm_crtc_state *crtc_state,
755 struct drm_connector_state *conn_state) 762 struct drm_connector_state *conn_state)
756{ 763{
757 struct nv50_mstc *mstc = nv50_mstc(conn_state->connector); 764 struct drm_atomic_state *state = crtc_state->state;
765 struct drm_connector *connector = conn_state->connector;
766 struct nv50_mstc *mstc = nv50_mstc(connector);
758 struct nv50_mstm *mstm = mstc->mstm; 767 struct nv50_mstm *mstm = mstc->mstm;
759 int bpp = conn_state->connector->display_info.bpc * 3; 768 int bpp = connector->display_info.bpc * 3;
760 int slots; 769 int slots;
761 770
762 mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock, bpp); 771 mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
772 bpp);
763 773
764 slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn); 774 if (drm_atomic_crtc_needs_modeset(crtc_state) &&
765 if (slots < 0) 775 !drm_connector_is_unregistered(connector)) {
766 return slots; 776 slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
777 mstc->port, mstc->pbn);
778 if (slots < 0)
779 return slots;
780 }
767 781
768 return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state, 782 return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
769 mstc->native); 783 mstc->native);
@@ -829,8 +843,7 @@ nv50_msto_disable(struct drm_encoder *encoder)
829 struct nv50_mstc *mstc = msto->mstc; 843 struct nv50_mstc *mstc = msto->mstc;
830 struct nv50_mstm *mstm = mstc->mstm; 844 struct nv50_mstm *mstm = mstc->mstm;
831 845
832 if (mstc->port) 846 drm_dp_mst_reset_vcpi_slots(&mstm->mgr, mstc->port);
833 drm_dp_mst_reset_vcpi_slots(&mstm->mgr, mstc->port);
834 847
835 mstm->outp->update(mstm->outp, msto->head->base.index, NULL, 0, 0); 848 mstm->outp->update(mstm->outp, msto->head->base.index, NULL, 0, 0);
836 mstm->modified = true; 849 mstm->modified = true;
@@ -927,12 +940,43 @@ nv50_mstc_get_modes(struct drm_connector *connector)
927 return ret; 940 return ret;
928} 941}
929 942
943static int
944nv50_mstc_atomic_check(struct drm_connector *connector,
945 struct drm_connector_state *new_conn_state)
946{
947 struct drm_atomic_state *state = new_conn_state->state;
948 struct nv50_mstc *mstc = nv50_mstc(connector);
949 struct drm_dp_mst_topology_mgr *mgr = &mstc->mstm->mgr;
950 struct drm_connector_state *old_conn_state =
951 drm_atomic_get_old_connector_state(state, connector);
952 struct drm_crtc_state *crtc_state;
953 struct drm_crtc *new_crtc = new_conn_state->crtc;
954
955 if (!old_conn_state->crtc)
956 return 0;
957
958 /* We only want to free VCPI if this state disables the CRTC on this
959 * connector
960 */
961 if (new_crtc) {
962 crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
963
964 if (!crtc_state ||
965 !drm_atomic_crtc_needs_modeset(crtc_state) ||
966 crtc_state->enable)
967 return 0;
968 }
969
970 return drm_dp_atomic_release_vcpi_slots(state, mgr, mstc->port);
971}
972
930static const struct drm_connector_helper_funcs 973static const struct drm_connector_helper_funcs
931nv50_mstc_help = { 974nv50_mstc_help = {
932 .get_modes = nv50_mstc_get_modes, 975 .get_modes = nv50_mstc_get_modes,
933 .mode_valid = nv50_mstc_mode_valid, 976 .mode_valid = nv50_mstc_mode_valid,
934 .best_encoder = nv50_mstc_best_encoder, 977 .best_encoder = nv50_mstc_best_encoder,
935 .atomic_best_encoder = nv50_mstc_atomic_best_encoder, 978 .atomic_best_encoder = nv50_mstc_atomic_best_encoder,
979 .atomic_check = nv50_mstc_atomic_check,
936}; 980};
937 981
938static enum drm_connector_status 982static enum drm_connector_status
@@ -942,7 +986,7 @@ nv50_mstc_detect(struct drm_connector *connector, bool force)
942 enum drm_connector_status conn_status; 986 enum drm_connector_status conn_status;
943 int ret; 987 int ret;
944 988
945 if (!mstc->port) 989 if (drm_connector_is_unregistered(connector))
946 return connector_status_disconnected; 990 return connector_status_disconnected;
947 991
948 ret = pm_runtime_get_sync(connector->dev->dev); 992 ret = pm_runtime_get_sync(connector->dev->dev);
@@ -961,7 +1005,10 @@ static void
961nv50_mstc_destroy(struct drm_connector *connector) 1005nv50_mstc_destroy(struct drm_connector *connector)
962{ 1006{
963 struct nv50_mstc *mstc = nv50_mstc(connector); 1007 struct nv50_mstc *mstc = nv50_mstc(connector);
1008
964 drm_connector_cleanup(&mstc->connector); 1009 drm_connector_cleanup(&mstc->connector);
1010 drm_dp_mst_put_port_malloc(mstc->port);
1011
965 kfree(mstc); 1012 kfree(mstc);
966} 1013}
967 1014
@@ -1009,6 +1056,7 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port,
1009 drm_object_attach_property(&mstc->connector.base, dev->mode_config.path_property, 0); 1056 drm_object_attach_property(&mstc->connector.base, dev->mode_config.path_property, 0);
1010 drm_object_attach_property(&mstc->connector.base, dev->mode_config.tile_property, 0); 1057 drm_object_attach_property(&mstc->connector.base, dev->mode_config.tile_property, 0);
1011 drm_connector_set_path_property(&mstc->connector, path); 1058 drm_connector_set_path_property(&mstc->connector, path);
1059 drm_dp_mst_get_port_malloc(port);
1012 return 0; 1060 return 0;
1013} 1061}
1014 1062
@@ -1073,10 +1121,6 @@ nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
1073 1121
1074 drm_fb_helper_remove_one_connector(&drm->fbcon->helper, &mstc->connector); 1122 drm_fb_helper_remove_one_connector(&drm->fbcon->helper, &mstc->connector);
1075 1123
1076 drm_modeset_lock(&drm->dev->mode_config.connection_mutex, NULL);
1077 mstc->port = NULL;
1078 drm_modeset_unlock(&drm->dev->mode_config.connection_mutex);
1079
1080 drm_connector_put(&mstc->connector); 1124 drm_connector_put(&mstc->connector);
1081} 1125}
1082 1126
@@ -1099,11 +1143,8 @@ nv50_mstm_add_connector(struct drm_dp_mst_topology_mgr *mgr,
1099 int ret; 1143 int ret;
1100 1144
1101 ret = nv50_mstc_new(mstm, port, path, &mstc); 1145 ret = nv50_mstc_new(mstm, port, path, &mstc);
1102 if (ret) { 1146 if (ret)
1103 if (mstc)
1104 mstc->connector.funcs->destroy(&mstc->connector);
1105 return NULL; 1147 return NULL;
1106 }
1107 1148
1108 return &mstc->connector; 1149 return &mstc->connector;
1109} 1150}
@@ -2117,6 +2158,10 @@ nv50_disp_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
2117 return ret; 2158 return ret;
2118 } 2159 }
2119 2160
2161 ret = drm_dp_mst_atomic_check(state);
2162 if (ret)
2163 return ret;
2164
2120 return 0; 2165 return 0;
2121} 2166}
2122 2167