@@ -1014,6 +1014,13 @@ static void dcpep_cb_hotplug(struct apple_dcp *dcp, u64 *connected)
10141014 if (dcp -> main_display )
10151015 return ;
10161016
1017+ if (dcp -> during_modeset ) {
1018+ dev_info (dcp -> dev ,
1019+ "cb_hotplug() ignored during modeset connected:%llu\n" ,
1020+ * connected );
1021+ return ;
1022+ }
1023+
10171024 dev_info (dcp -> dev , "cb_hotplug() connected:%llu, valid_mode:%d\n" ,
10181025 * connected , dcp -> valid_mode );
10191026
@@ -1178,6 +1185,75 @@ static void complete_set_digital_out_mode(struct apple_dcp *dcp, void *data,
11781185 }
11791186}
11801187
1188+ int DCP_FW_NAME (iomfb_modeset )(struct apple_dcp * dcp ,
1189+ struct drm_crtc_state * crtc_state )
1190+ {
1191+ struct dcp_display_mode * mode ;
1192+ struct dcp_wait_cookie * cookie ;
1193+ int ret ;
1194+
1195+ mode = lookup_mode (dcp , & crtc_state -> mode );
1196+ if (!mode ) {
1197+ dev_err (dcp -> dev , "no match for " DRM_MODE_FMT "\n" ,
1198+ DRM_MODE_ARG (& crtc_state -> mode ));
1199+ return - EIO ;
1200+ }
1201+
1202+ dev_info (dcp -> dev ,
1203+ "set_digital_out_mode(color:%d timing:%d) " DRM_MODE_FMT "\n" ,
1204+ mode -> color_mode_id , mode -> timing_mode_id ,
1205+ DRM_MODE_ARG (& crtc_state -> mode ));
1206+ dcp -> mode = (struct dcp_set_digital_out_mode_req ){
1207+ .color_mode_id = mode -> color_mode_id ,
1208+ .timing_mode_id = mode -> timing_mode_id
1209+ };
1210+
1211+ cookie = kzalloc (sizeof (* cookie ), GFP_KERNEL );
1212+ if (!cookie ) {
1213+ return - ENOMEM ;
1214+ }
1215+
1216+ init_completion (& cookie -> done );
1217+ kref_init (& cookie -> refcount );
1218+ /* increase refcount to ensure the receiver has a reference */
1219+ kref_get (& cookie -> refcount );
1220+
1221+ dcp -> during_modeset = true;
1222+
1223+ dcp_set_digital_out_mode (dcp , false, & dcp -> mode ,
1224+ complete_set_digital_out_mode , cookie );
1225+
1226+ /*
1227+ * The DCP firmware has an internal timeout of ~8 seconds for
1228+ * modesets. Add an extra 500ms to safe side that the modeset
1229+ * call has returned.
1230+ */
1231+ dev_dbg (dcp -> dev , "%s - wait for modeset" , __func__ );
1232+ ret = wait_for_completion_timeout (& cookie -> done ,
1233+ msecs_to_jiffies (8500 ));
1234+
1235+ kref_put (& cookie -> refcount , release_wait_cookie );
1236+ dcp -> during_modeset = false;
1237+ dev_info (dcp -> dev , "set_digital_out_mode finished:%d\n" , ret );
1238+
1239+ if (ret == 0 ) {
1240+ dev_info (dcp -> dev , "set_digital_out_mode timed out\n" );
1241+ return - EIO ;
1242+ } else if (ret < 0 ) {
1243+ dev_info (dcp -> dev ,
1244+ "waiting on set_digital_out_mode failed:%d\n" , ret );
1245+ return - EIO ;
1246+
1247+ } else if (ret > 0 ) {
1248+ dev_dbg (dcp -> dev ,
1249+ "set_digital_out_mode finished with %d to spare\n" ,
1250+ jiffies_to_msecs (ret ));
1251+ }
1252+ dcp -> valid_mode = true;
1253+
1254+ return 0 ;
1255+ }
1256+
11811257void DCP_FW_NAME (iomfb_flush )(struct apple_dcp * dcp , struct drm_crtc * crtc , struct drm_atomic_state * state )
11821258{
11831259 struct drm_plane * plane ;
@@ -1186,13 +1262,10 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru
11861262 struct DCP_FW_NAME (dcp_swap_submit_req ) * req = & DCP_FW_UNION (dcp -> swap );
11871263 int plane_idx , l ;
11881264 int has_surface = 0 ;
1189- bool modeset ;
11901265 dev_dbg (dcp -> dev , "%s" , __func__ );
11911266
11921267 crtc_state = drm_atomic_get_new_crtc_state (state , crtc );
11931268
1194- modeset = drm_atomic_crtc_needs_modeset (crtc_state ) || !dcp -> valid_mode ;
1195-
11961269 /* Reset to defaults */
11971270 memset (req , 0 , sizeof (* req ));
11981271 for (l = 0 ; l < SWAP_SURFACES ; l ++ )
@@ -1305,64 +1378,6 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru
13051378 l += 1 ;
13061379 }
13071380
1308- if (modeset ) {
1309- struct dcp_display_mode * mode ;
1310- struct dcp_wait_cookie * cookie ;
1311- int ret ;
1312-
1313- mode = lookup_mode (dcp , & crtc_state -> mode );
1314- if (!mode ) {
1315- dev_warn (dcp -> dev , "no match for " DRM_MODE_FMT ,
1316- DRM_MODE_ARG (& crtc_state -> mode ));
1317- schedule_work (& dcp -> vblank_wq );
1318- return ;
1319- }
1320-
1321- dev_info (dcp -> dev , "set_digital_out_mode(color:%d timing:%d)" ,
1322- mode -> color_mode_id , mode -> timing_mode_id );
1323- dcp -> mode = (struct dcp_set_digital_out_mode_req ){
1324- .color_mode_id = mode -> color_mode_id ,
1325- .timing_mode_id = mode -> timing_mode_id
1326- };
1327-
1328- cookie = kzalloc (sizeof (* cookie ), GFP_KERNEL );
1329- if (!cookie ) {
1330- schedule_work (& dcp -> vblank_wq );
1331- return ;
1332- }
1333-
1334- init_completion (& cookie -> done );
1335- kref_init (& cookie -> refcount );
1336- /* increase refcount to ensure the receiver has a reference */
1337- kref_get (& cookie -> refcount );
1338-
1339- dcp_set_digital_out_mode (dcp , false, & dcp -> mode ,
1340- complete_set_digital_out_mode , cookie );
1341-
1342- /*
1343- * The DCP firmware has an internal timeout of ~8 seconds for
1344- * modesets. Add an extra 500ms to safe side that the modeset
1345- * call has returned.
1346- */
1347- dev_dbg (dcp -> dev , "%s - wait for modeset" , __func__ );
1348- ret = wait_for_completion_timeout (& cookie -> done ,
1349- msecs_to_jiffies (8500 ));
1350-
1351- kref_put (& cookie -> refcount , release_wait_cookie );
1352-
1353- if (ret == 0 ) {
1354- dev_info (dcp -> dev , "set_digital_out_mode timed out" );
1355- schedule_work (& dcp -> vblank_wq );
1356- return ;
1357- } else if (ret > 0 ) {
1358- dev_dbg (dcp -> dev ,
1359- "set_digital_out_mode finished with %d to spare" ,
1360- jiffies_to_msecs (ret ));
1361- }
1362-
1363- dcp -> valid_mode = true;
1364- }
1365-
13661381 if (!has_surface && !crtc_state -> color_mgmt_changed ) {
13671382 if (crtc_state -> enable && crtc_state -> active &&
13681383 !crtc_state -> planes_changed ) {
0 commit comments