Lines Matching +full:zynqmp +full:- +full:dpsub +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0
3 * ZynqMP DisplayPort Driver
5 * Copyright (C) 2017 - 2020 Xilinx, Inc.
8 * - Hyun Woo Kwon <hyun.kwon@xilinx.com>
9 * - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
57 #define ZYNQMP_DP_SOFTWARE_RESET_STREAM2 BIT(1)
91 #define ZYNQMP_DP_CORE_ID_DIRECTION GENMASK(1)
104 #define ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_REQUEST BIT(1)
111 #define ZYNQMP_DP_AUX_REPLY_CODE_AUX_DEFER BIT(1)
123 #define ZYNQMP_DP_INT_HPD_EVENT BIT(1)
148 #define ZYNQMP_DP_MAIN_STREAM_POLARITY_VSYNC_SHIFT 1
157 #define ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_RGB (0 << 1)
158 #define ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_422 (5 << 1)
159 #define ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_444 (6 << 1)
160 #define ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_MASK (7 << 1)
164 #define ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8 (1 << 5)
184 #define ZYNQMP_DP_PHY_RESET_GTTX_RESET BIT(1)
205 #define ZYNQMP_DP_TX_PHY_POWER_DOWN_LANE_1 BIT(1)
241 * struct zynqmp_dp_link_config - Common link config between source and sink
251 * struct zynqmp_dp_mode - Configured mode of DisplayPort
265 * struct zynqmp_dp_config - Configuration of DisplayPort from DTS
277 * struct zynqmp_dp - Xilinx DisplayPort core
279 * @dpsub: Display subsystem
299 struct zynqmp_dpsub *dpsub; member
328 writel(val, dp->iomem + offset); in zynqmp_dp_write()
333 return readl(dp->iomem + offset); in zynqmp_dp_read()
346 /* -----------------------------------------------------------------------------
357 reset_control_assert(dp->reset); in zynqmp_dp_reset()
359 reset_control_deassert(dp->reset); in zynqmp_dp_reset()
364 bool status = !!reset_control_status(dp->reset); in zynqmp_dp_reset()
372 dev_err(dp->dev, "reset %s timeout\n", assert ? "assert" : "deassert"); in zynqmp_dp_reset()
373 return -ETIMEDOUT; in zynqmp_dp_reset()
377 * zynqmp_dp_phy_init - Initialize the phy
390 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_phy_init()
391 ret = phy_init(dp->phy[i]); in zynqmp_dp_phy_init()
393 dev_err(dp->dev, "failed to init phy lane %d\n", i); in zynqmp_dp_phy_init()
404 for (i = dp->num_lanes - 1; i >= 0; i--) { in zynqmp_dp_phy_init()
405 ret = phy_power_on(dp->phy[i]); in zynqmp_dp_phy_init()
407 dev_err(dp->dev, "failed to power on phy lane %d\n", i); in zynqmp_dp_phy_init()
416 * zynqmp_dp_phy_exit - Exit the phy
426 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_phy_exit()
427 ret = phy_power_off(dp->phy[i]); in zynqmp_dp_phy_exit()
429 dev_err(dp->dev, "failed to power off phy(%d) %d\n", i, in zynqmp_dp_phy_exit()
433 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_phy_exit()
434 ret = phy_exit(dp->phy[i]); in zynqmp_dp_phy_exit()
436 dev_err(dp->dev, "failed to exit phy(%d) %d\n", i, ret); in zynqmp_dp_phy_exit()
441 * zynqmp_dp_phy_probe - Probe the PHYs
446 * found. The caller can check dp->num_lanes to check how many PHYs were found.
449 * * 0 - Success
450 * * -ENXIO - No PHY found
451 * * -EPROBE_DEFER - Probe deferral requested
452 * * Other negative value - PHY retrieval failure
462 snprintf(phy_name, sizeof(phy_name), "dp-phy%d", i); in zynqmp_dp_phy_probe()
463 phy = devm_phy_get(dp->dev, phy_name); in zynqmp_dp_phy_probe()
467 case -ENODEV: in zynqmp_dp_phy_probe()
468 if (dp->num_lanes) in zynqmp_dp_phy_probe()
471 dev_err(dp->dev, "no PHY found\n"); in zynqmp_dp_phy_probe()
472 return -ENXIO; in zynqmp_dp_phy_probe()
474 case -EPROBE_DEFER: in zynqmp_dp_phy_probe()
475 return -EPROBE_DEFER; in zynqmp_dp_phy_probe()
478 dev_err(dp->dev, "failed to get PHY lane %u\n", in zynqmp_dp_phy_probe()
484 dp->phy[i] = phy; in zynqmp_dp_phy_probe()
485 dp->num_lanes++; in zynqmp_dp_phy_probe()
492 * zynqmp_dp_phy_ready - Check if PHY is ready
495 * Check if PHY is ready. If PHY is not ready, wait 1ms to check for 100 times.
498 * Return: 0 if PHY is ready, or -ENODEV if PHY is not ready.
504 ready = (1 << dp->num_lanes) - 1; in zynqmp_dp_phy_ready()
506 /* Wait for 100 * 1ms. This should be enough time for PHY to be ready */ in zynqmp_dp_phy_ready()
513 dev_err(dp->dev, "PHY isn't ready\n"); in zynqmp_dp_phy_ready()
514 return -ENODEV; in zynqmp_dp_phy_ready()
523 /* -----------------------------------------------------------------------------
528 * zynqmp_dp_max_rate - Calculate and return available max pixel clock
529 * @link_rate: link rate (Kilo-bytes / sec)
541 * zynqmp_dp_mode_configure - Configure the link values
551 * Return: Current link rate code, or -EINVAL.
556 int max_rate = dp->link_config.max_rate; in zynqmp_dp_mode_configure()
558 u8 max_lanes = dp->link_config.max_lanes; in zynqmp_dp_mode_configure()
560 u8 bpp = dp->config.bpp; in zynqmp_dp_mode_configure()
572 dev_err(dp->dev, "can't downshift. already lowest link rate\n"); in zynqmp_dp_mode_configure()
573 return -EINVAL; in zynqmp_dp_mode_configure()
580 for (lane_cnt = 1; lane_cnt <= max_lanes; lane_cnt <<= 1) { in zynqmp_dp_mode_configure()
587 dp->mode.bw_code = bw_code; in zynqmp_dp_mode_configure()
588 dp->mode.lane_cnt = lane_cnt; in zynqmp_dp_mode_configure()
589 dp->mode.pclock = pclock; in zynqmp_dp_mode_configure()
590 return dp->mode.bw_code; in zynqmp_dp_mode_configure()
594 dev_err(dp->dev, "failed to configure link values\n"); in zynqmp_dp_mode_configure()
596 return -EINVAL; in zynqmp_dp_mode_configure()
600 * zynqmp_dp_adjust_train - Adjust train values
607 u8 *train_set = dp->train_set; in zynqmp_dp_adjust_train()
611 for (i = 0; i < dp->mode.lane_cnt; i++) { in zynqmp_dp_adjust_train()
628 for (i = 0; i < dp->mode.lane_cnt; i++) in zynqmp_dp_adjust_train()
633 * zynqmp_dp_update_vs_emph - Update the training values
647 ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, dp->train_set, in zynqmp_dp_update_vs_emph()
648 dp->mode.lane_cnt); in zynqmp_dp_update_vs_emph()
652 for (i = 0; i < dp->mode.lane_cnt; i++) { in zynqmp_dp_update_vs_emph()
655 u8 train = dp->train_set[i]; in zynqmp_dp_update_vs_emph()
662 phy_configure(dp->phy[i], &opts); in zynqmp_dp_update_vs_emph()
671 * zynqmp_dp_link_train_cr - Train clock recovery
680 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_link_train_cr()
688 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in zynqmp_dp_link_train_cr()
703 drm_dp_link_train_clock_recovery_delay(&dp->aux, dp->dpcd); in zynqmp_dp_link_train_cr()
704 ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status); in zynqmp_dp_link_train_cr()
713 if (!(dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED)) in zynqmp_dp_link_train_cr()
718 if ((dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == vs) in zynqmp_dp_link_train_cr()
726 vs = dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; in zynqmp_dp_link_train_cr()
731 return -EIO; in zynqmp_dp_link_train_cr()
737 * zynqmp_dp_link_train_ce - Train channel equalization
746 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_link_train_ce()
751 if (dp->dpcd[DP_DPCD_REV] >= DP_V1_2 && in zynqmp_dp_link_train_ce()
752 dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED) in zynqmp_dp_link_train_ce()
758 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in zynqmp_dp_link_train_ce()
768 drm_dp_link_train_channel_eq_delay(&dp->aux, dp->dpcd); in zynqmp_dp_link_train_ce()
769 ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status); in zynqmp_dp_link_train_ce()
781 return -EIO; in zynqmp_dp_link_train_ce()
787 * zynqmp_dp_train - Train the link
795 u8 bw_code = dp->mode.bw_code; in zynqmp_dp_train()
796 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_train()
802 enhanced = drm_dp_enhanced_frame_cap(dp->dpcd); in zynqmp_dp_train()
804 zynqmp_dp_write(dp, ZYNQMP_DP_ENHANCED_FRAME_EN, 1); in zynqmp_dp_train()
808 if (dp->dpcd[3] & 0x1) { in zynqmp_dp_train()
809 zynqmp_dp_write(dp, ZYNQMP_DP_DOWNSPREAD_CTL, 1); in zynqmp_dp_train()
810 drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, in zynqmp_dp_train()
814 drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, 0); in zynqmp_dp_train()
817 ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET, aux_lane_cnt); in zynqmp_dp_train()
819 dev_err(dp->dev, "failed to set lane count\n"); in zynqmp_dp_train()
823 ret = drm_dp_dpcd_writeb(&dp->aux, DP_MAIN_LINK_CHANNEL_CODING_SET, in zynqmp_dp_train()
826 dev_err(dp->dev, "failed to set ANSI 8B/10B encoding\n"); in zynqmp_dp_train()
830 ret = drm_dp_dpcd_writeb(&dp->aux, DP_LINK_BW_SET, bw_code); in zynqmp_dp_train()
832 dev_err(dp->dev, "failed to set DP bandwidth\n"); in zynqmp_dp_train()
855 zynqmp_dp_write(dp, ZYNQMP_DP_SCRAMBLING_DISABLE, 1); in zynqmp_dp_train()
856 memset(dp->train_set, 0, sizeof(dp->train_set)); in zynqmp_dp_train()
865 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in zynqmp_dp_train()
868 dev_err(dp->dev, "failed to disable training pattern\n"); in zynqmp_dp_train()
880 * zynqmp_dp_train_loop - Downshift the link rate during training
887 struct zynqmp_dp_mode *mode = &dp->mode; in zynqmp_dp_train_loop()
888 u8 bw = mode->bw_code; in zynqmp_dp_train_loop()
892 if (dp->status == connector_status_disconnected || in zynqmp_dp_train_loop()
893 !dp->enabled) in zynqmp_dp_train_loop()
900 ret = zynqmp_dp_mode_configure(dp, mode->pclock, bw); in zynqmp_dp_train_loop()
908 dev_err(dp->dev, "failed to train the DP link\n"); in zynqmp_dp_train_loop()
911 /* -----------------------------------------------------------------------------
918 * zynqmp_dp_aux_cmd_submit - Submit aux command
935 * -EBUSY when there is any request already being processed
936 * -ETIMEDOUT when receiving reply is timed out
937 * -EIO when received bytes are less than requested
947 return -EBUSY; in zynqmp_dp_aux_cmd_submit()
959 reg |= (bytes - 1) << ZYNQMP_DP_AUX_COMMAND_BYTES_SHIFT; in zynqmp_dp_aux_cmd_submit()
970 return -ETIMEDOUT; in zynqmp_dp_aux_cmd_submit()
984 return -EIO; in zynqmp_dp_aux_cmd_submit()
1002 iter = iter ? iter : 1; in zynqmp_dp_aux_transfer()
1005 ret = zynqmp_dp_aux_cmd_submit(dp, msg->request, msg->address, in zynqmp_dp_aux_transfer()
1006 msg->buffer, msg->size, in zynqmp_dp_aux_transfer()
1007 &msg->reply); in zynqmp_dp_aux_transfer()
1009 dev_dbg(dp->dev, "aux %d retries\n", i); in zynqmp_dp_aux_transfer()
1010 return msg->size; in zynqmp_dp_aux_transfer()
1013 if (dp->status == connector_status_disconnected) { in zynqmp_dp_aux_transfer()
1014 dev_dbg(dp->dev, "no connected aux device\n"); in zynqmp_dp_aux_transfer()
1015 return -ENODEV; in zynqmp_dp_aux_transfer()
1021 dev_dbg(dp->dev, "failed to do aux transfer (%d)\n", ret); in zynqmp_dp_aux_transfer()
1027 * zynqmp_dp_aux_init - Initialize and register the DP AUX
1046 rate = clk_get_rate(dp->dpsub->apb_clk); in zynqmp_dp_aux_init()
1049 dev_err(dp->dev, "aclk frequency too high\n"); in zynqmp_dp_aux_init()
1050 return -EINVAL; in zynqmp_dp_aux_init()
1057 dp->aux.name = "ZynqMP DP AUX"; in zynqmp_dp_aux_init()
1058 dp->aux.dev = dp->dev; in zynqmp_dp_aux_init()
1059 dp->aux.drm_dev = dp->bridge.dev; in zynqmp_dp_aux_init()
1060 dp->aux.transfer = zynqmp_dp_aux_transfer; in zynqmp_dp_aux_init()
1062 return drm_dp_aux_register(&dp->aux); in zynqmp_dp_aux_init()
1066 * zynqmp_dp_aux_cleanup - Cleanup the DP AUX
1073 drm_dp_aux_unregister(&dp->aux); in zynqmp_dp_aux_cleanup()
1076 /* -----------------------------------------------------------------------------
1081 * zynqmp_dp_update_misc - Write the misc registers
1089 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_MISC0, dp->config.misc0); in zynqmp_dp_update_misc()
1090 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_MISC1, dp->config.misc1); in zynqmp_dp_update_misc()
1094 * zynqmp_dp_set_format - Set the input format
1102 * Return: 0 on success, or -EINVAL.
1109 struct zynqmp_dp_config *config = &dp->config; in zynqmp_dp_set_format()
1112 config->misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_MASK; in zynqmp_dp_set_format()
1113 config->misc1 &= ~ZYNQMP_DP_MAIN_STREAM_MISC1_Y_ONLY_EN; in zynqmp_dp_set_format()
1117 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_RGB; in zynqmp_dp_set_format()
1122 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_444; in zynqmp_dp_set_format()
1127 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_422; in zynqmp_dp_set_format()
1132 config->misc1 |= ZYNQMP_DP_MAIN_STREAM_MISC1_Y_ONLY_EN; in zynqmp_dp_set_format()
1133 num_colors = 1; in zynqmp_dp_set_format()
1137 dev_err(dp->dev, "Invalid colormetry in DT\n"); in zynqmp_dp_set_format()
1138 return -EINVAL; in zynqmp_dp_set_format()
1141 if (info && info->bpc && bpc > info->bpc) { in zynqmp_dp_set_format()
1142 dev_warn(dp->dev, in zynqmp_dp_set_format()
1144 bpc, info->bpc); in zynqmp_dp_set_format()
1145 bpc = info->bpc; in zynqmp_dp_set_format()
1148 config->misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_MASK; in zynqmp_dp_set_format()
1152 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_6; in zynqmp_dp_set_format()
1155 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8; in zynqmp_dp_set_format()
1158 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_10; in zynqmp_dp_set_format()
1161 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_12; in zynqmp_dp_set_format()
1164 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_16; in zynqmp_dp_set_format()
1167 dev_warn(dp->dev, "Not supported bpc (%u). fall back to 8bpc\n", in zynqmp_dp_set_format()
1169 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8; in zynqmp_dp_set_format()
1175 config->bpp = bpc * num_colors; in zynqmp_dp_set_format()
1181 * zynqmp_dp_encoder_mode_set_transfer_unit - Set the transfer unit values
1198 vid_kbytes = mode->clock * (dp->config.bpp / 8); in zynqmp_dp_encoder_mode_set_transfer_unit()
1199 bw = drm_dp_bw_code_to_link_rate(dp->mode.bw_code); in zynqmp_dp_encoder_mode_set_transfer_unit()
1200 avg_bytes_per_tu = vid_kbytes * tu / (dp->mode.lane_cnt * bw / 1000); in zynqmp_dp_encoder_mode_set_transfer_unit()
1212 init_wait = tu - avg_bytes_per_tu / 1000; in zynqmp_dp_encoder_mode_set_transfer_unit()
1218 * zynqmp_dp_encoder_mode_set_stream - Configure the main stream
1228 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_encoder_mode_set_stream()
1232 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HTOTAL, mode->htotal); in zynqmp_dp_encoder_mode_set_stream()
1233 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VTOTAL, mode->vtotal); in zynqmp_dp_encoder_mode_set_stream()
1235 (!!(mode->flags & DRM_MODE_FLAG_PVSYNC) << in zynqmp_dp_encoder_mode_set_stream()
1237 (!!(mode->flags & DRM_MODE_FLAG_PHSYNC) << in zynqmp_dp_encoder_mode_set_stream()
1240 mode->hsync_end - mode->hsync_start); in zynqmp_dp_encoder_mode_set_stream()
1242 mode->vsync_end - mode->vsync_start); in zynqmp_dp_encoder_mode_set_stream()
1243 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HRES, mode->hdisplay); in zynqmp_dp_encoder_mode_set_stream()
1244 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VRES, mode->vdisplay); in zynqmp_dp_encoder_mode_set_stream()
1246 mode->htotal - mode->hsync_start); in zynqmp_dp_encoder_mode_set_stream()
1248 mode->vtotal - mode->vsync_start); in zynqmp_dp_encoder_mode_set_stream()
1251 if (dp->config.misc0 & ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK) { in zynqmp_dp_encoder_mode_set_stream()
1252 reg = drm_dp_bw_code_to_link_rate(dp->mode.bw_code); in zynqmp_dp_encoder_mode_set_stream()
1254 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_M_VID, mode->clock); in zynqmp_dp_encoder_mode_set_stream()
1255 rate = zynqmp_dpsub_get_audio_clk_rate(dp->dpsub); in zynqmp_dp_encoder_mode_set_stream()
1257 dev_dbg(dp->dev, "Audio rate: %d\n", rate / 512); in zynqmp_dp_encoder_mode_set_stream()
1264 if (zynqmp_dpsub_audio_enabled(dp->dpsub)) in zynqmp_dp_encoder_mode_set_stream()
1265 zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CHANNELS, 1); in zynqmp_dp_encoder_mode_set_stream()
1267 zynqmp_dp_write(dp, ZYNQMP_DP_USER_PIX_WIDTH, 1); in zynqmp_dp_encoder_mode_set_stream()
1270 wpl = (mode->hdisplay * dp->config.bpp + 15) / 16; in zynqmp_dp_encoder_mode_set_stream()
1271 reg = wpl + wpl % lane_cnt - lane_cnt; in zynqmp_dp_encoder_mode_set_stream()
1275 /* -----------------------------------------------------------------------------
1286 if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) in zynqmp_dp_disp_enable()
1288 else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) in zynqmp_dp_disp_enable()
1293 layer = dp->dpsub->layers[layer_id]; in zynqmp_dp_disp_enable()
1301 zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, true, 255); in zynqmp_dp_disp_enable()
1303 zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, false, 0); in zynqmp_dp_disp_enable()
1305 zynqmp_disp_enable(dp->dpsub->disp); in zynqmp_dp_disp_enable()
1313 if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) in zynqmp_dp_disp_disable()
1314 layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_VID]; in zynqmp_dp_disp_disable()
1315 else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) in zynqmp_dp_disp_disable()
1316 layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX]; in zynqmp_dp_disp_disable()
1320 zynqmp_disp_disable(dp->dpsub->disp); in zynqmp_dp_disp_disable()
1324 /* -----------------------------------------------------------------------------
1337 dev_err(dp->dev, "failed to initialize DP aux\n"); in zynqmp_dp_bridge_attach()
1341 if (dp->next_bridge) { in zynqmp_dp_bridge_attach()
1342 ret = drm_bridge_attach(bridge->encoder, dp->next_bridge, in zynqmp_dp_bridge_attach()
1373 if (mode->clock > ZYNQMP_MAX_FREQ) { in zynqmp_dp_bridge_mode_valid()
1374 dev_dbg(dp->dev, "filtered mode %s for high pixel rate\n", in zynqmp_dp_bridge_mode_valid()
1375 mode->name); in zynqmp_dp_bridge_mode_valid()
1381 rate = zynqmp_dp_max_rate(dp->link_config.max_rate, in zynqmp_dp_bridge_mode_valid()
1382 dp->link_config.max_lanes, dp->config.bpp); in zynqmp_dp_bridge_mode_valid()
1383 if (mode->clock > rate) { in zynqmp_dp_bridge_mode_valid()
1384 dev_dbg(dp->dev, "filtered mode %s for high pixel rate\n", in zynqmp_dp_bridge_mode_valid()
1385 mode->name); in zynqmp_dp_bridge_mode_valid()
1397 struct drm_atomic_state *state = old_bridge_state->base.state; in zynqmp_dp_bridge_atomic_enable()
1407 pm_runtime_get_sync(dp->dev); in zynqmp_dp_bridge_atomic_enable()
1417 bridge->encoder); in zynqmp_dp_bridge_atomic_enable()
1418 crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; in zynqmp_dp_bridge_atomic_enable()
1420 adjusted_mode = &crtc_state->adjusted_mode; in zynqmp_dp_bridge_atomic_enable()
1421 mode = &crtc_state->mode; in zynqmp_dp_bridge_atomic_enable()
1423 zynqmp_dp_set_format(dp, &connector->display_info, in zynqmp_dp_bridge_atomic_enable()
1427 rate = zynqmp_dp_max_rate(dp->link_config.max_rate, in zynqmp_dp_bridge_atomic_enable()
1428 dp->link_config.max_lanes, dp->config.bpp); in zynqmp_dp_bridge_atomic_enable()
1429 if (mode->clock > rate) { in zynqmp_dp_bridge_atomic_enable()
1430 dev_err(dp->dev, "mode %s has too high pixel rate\n", in zynqmp_dp_bridge_atomic_enable()
1431 mode->name); in zynqmp_dp_bridge_atomic_enable()
1436 ret = zynqmp_dp_mode_configure(dp, adjusted_mode->clock, 0); in zynqmp_dp_bridge_atomic_enable()
1438 pm_runtime_put_sync(dp->dev); in zynqmp_dp_bridge_atomic_enable()
1446 dp->enabled = true; in zynqmp_dp_bridge_atomic_enable()
1448 if (zynqmp_dpsub_audio_enabled(dp->dpsub)) in zynqmp_dp_bridge_atomic_enable()
1449 zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 1); in zynqmp_dp_bridge_atomic_enable()
1451 if (dp->status == connector_status_connected) { in zynqmp_dp_bridge_atomic_enable()
1453 ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, in zynqmp_dp_bridge_atomic_enable()
1455 if (ret == 1) in zynqmp_dp_bridge_atomic_enable()
1462 if (ret != 1) in zynqmp_dp_bridge_atomic_enable()
1463 dev_dbg(dp->dev, "DP aux failed\n"); in zynqmp_dp_bridge_atomic_enable()
1468 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_ENABLE, 1); in zynqmp_dp_bridge_atomic_enable()
1476 dp->enabled = false; in zynqmp_dp_bridge_atomic_disable()
1477 cancel_delayed_work(&dp->hpd_work); in zynqmp_dp_bridge_atomic_disable()
1479 drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3); in zynqmp_dp_bridge_atomic_disable()
1482 if (zynqmp_dpsub_audio_enabled(dp->dpsub)) in zynqmp_dp_bridge_atomic_disable()
1487 pm_runtime_put_sync(dp->dev); in zynqmp_dp_bridge_atomic_disable()
1498 struct drm_display_mode *mode = &crtc_state->mode; in zynqmp_dp_bridge_atomic_check()
1499 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; in zynqmp_dp_bridge_atomic_check()
1500 int diff = mode->htotal - mode->hsync_end; in zynqmp_dp_bridge_atomic_check()
1503 * ZynqMP DP requires horizontal backporch to be greater than 12. in zynqmp_dp_bridge_atomic_check()
1507 int vrefresh = (adjusted_mode->clock * 1000) / in zynqmp_dp_bridge_atomic_check()
1508 (adjusted_mode->vtotal * adjusted_mode->htotal); in zynqmp_dp_bridge_atomic_check()
1510 dev_dbg(dp->dev, "hbackporch adjusted: %d to %d", in zynqmp_dp_bridge_atomic_check()
1511 diff, ZYNQMP_DP_MIN_H_BACKPORCH - diff); in zynqmp_dp_bridge_atomic_check()
1512 diff = ZYNQMP_DP_MIN_H_BACKPORCH - diff; in zynqmp_dp_bridge_atomic_check()
1513 adjusted_mode->htotal += diff; in zynqmp_dp_bridge_atomic_check()
1514 adjusted_mode->clock = adjusted_mode->vtotal * in zynqmp_dp_bridge_atomic_check()
1515 adjusted_mode->htotal * vrefresh / 1000; in zynqmp_dp_bridge_atomic_check()
1524 struct zynqmp_dp_link_config *link_config = &dp->link_config; in zynqmp_dp_bridge_detect()
1540 ret = drm_dp_dpcd_read(&dp->aux, 0x0, dp->dpcd, in zynqmp_dp_bridge_detect()
1541 sizeof(dp->dpcd)); in zynqmp_dp_bridge_detect()
1543 dev_dbg(dp->dev, "DPCD read failed"); in zynqmp_dp_bridge_detect()
1547 link_config->max_rate = min_t(int, in zynqmp_dp_bridge_detect()
1548 drm_dp_max_link_rate(dp->dpcd), in zynqmp_dp_bridge_detect()
1550 link_config->max_lanes = min_t(u8, in zynqmp_dp_bridge_detect()
1551 drm_dp_max_lane_count(dp->dpcd), in zynqmp_dp_bridge_detect()
1552 dp->num_lanes); in zynqmp_dp_bridge_detect()
1554 dp->status = connector_status_connected; in zynqmp_dp_bridge_detect()
1559 dp->status = connector_status_disconnected; in zynqmp_dp_bridge_detect()
1568 return drm_get_edid(connector, &dp->aux.ddc); in zynqmp_dp_bridge_get_edid()
1585 /* -----------------------------------------------------------------------------
1590 * zynqmp_dp_enable_vblank - Enable vblank
1601 * zynqmp_dp_disable_vblank - Disable vblank
1617 status = zynqmp_dp_bridge_detect(&dp->bridge); in zynqmp_dp_hpd_work_func()
1618 drm_bridge_hpd_notify(&dp->bridge, status); in zynqmp_dp_hpd_work_func()
1633 dev_dbg_ratelimited(dp->dev, "underflow interrupt\n"); in zynqmp_dp_irq_handler()
1635 dev_dbg_ratelimited(dp->dev, "overflow interrupt\n"); in zynqmp_dp_irq_handler()
1640 zynqmp_dpsub_drm_handle_vblank(dp->dpsub); in zynqmp_dp_irq_handler()
1643 schedule_delayed_work(&dp->hpd_work, 0); in zynqmp_dp_irq_handler()
1649 ret = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, status, in zynqmp_dp_irq_handler()
1655 !drm_dp_clock_recovery_ok(&status[2], dp->mode.lane_cnt) || in zynqmp_dp_irq_handler()
1656 !drm_dp_channel_eq_ok(&status[2], dp->mode.lane_cnt)) { in zynqmp_dp_irq_handler()
1665 /* -----------------------------------------------------------------------------
1669 int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) in zynqmp_dp_probe() argument
1671 struct platform_device *pdev = to_platform_device(dpsub->dev); in zynqmp_dp_probe()
1679 return -ENOMEM; in zynqmp_dp_probe()
1681 dp->dev = &pdev->dev; in zynqmp_dp_probe()
1682 dp->dpsub = dpsub; in zynqmp_dp_probe()
1683 dp->status = connector_status_disconnected; in zynqmp_dp_probe()
1685 INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func); in zynqmp_dp_probe()
1689 dp->iomem = devm_ioremap_resource(dp->dev, res); in zynqmp_dp_probe()
1690 if (IS_ERR(dp->iomem)) { in zynqmp_dp_probe()
1691 ret = PTR_ERR(dp->iomem); in zynqmp_dp_probe()
1695 dp->irq = platform_get_irq(pdev, 0); in zynqmp_dp_probe()
1696 if (dp->irq < 0) { in zynqmp_dp_probe()
1697 ret = dp->irq; in zynqmp_dp_probe()
1701 dp->reset = devm_reset_control_get(dp->dev, NULL); in zynqmp_dp_probe()
1702 if (IS_ERR(dp->reset)) { in zynqmp_dp_probe()
1703 if (PTR_ERR(dp->reset) != -EPROBE_DEFER) in zynqmp_dp_probe()
1704 dev_err(dp->dev, "failed to get reset: %ld\n", in zynqmp_dp_probe()
1705 PTR_ERR(dp->reset)); in zynqmp_dp_probe()
1706 ret = PTR_ERR(dp->reset); in zynqmp_dp_probe()
1719 bridge = &dp->bridge; in zynqmp_dp_probe()
1720 bridge->funcs = &zynqmp_dp_bridge_funcs; in zynqmp_dp_probe()
1721 bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID in zynqmp_dp_probe()
1723 bridge->type = DRM_MODE_CONNECTOR_DisplayPort; in zynqmp_dp_probe()
1724 dpsub->bridge = bridge; in zynqmp_dp_probe()
1728 * not being connected for backward-compatibility with older DTs. in zynqmp_dp_probe()
1730 ret = drm_of_find_panel_or_bridge(dp->dev->of_node, 5, 0, NULL, in zynqmp_dp_probe()
1731 &dp->next_bridge); in zynqmp_dp_probe()
1732 if (ret < 0 && ret != -ENODEV) in zynqmp_dp_probe()
1736 dp->config.misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK; in zynqmp_dp_probe()
1742 zynqmp_dp_write(dp, ZYNQMP_DP_FORCE_SCRAMBLER_RESET, 1); in zynqmp_dp_probe()
1750 zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, 1); in zynqmp_dp_probe()
1756 ret = devm_request_threaded_irq(dp->dev, dp->irq, NULL, in zynqmp_dp_probe()
1758 dev_name(dp->dev), dp); in zynqmp_dp_probe()
1762 dpsub->dp = dp; in zynqmp_dp_probe()
1764 dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n", in zynqmp_dp_probe()
1765 dp->num_lanes); in zynqmp_dp_probe()
1778 void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub) in zynqmp_dp_remove() argument
1780 struct zynqmp_dp *dp = dpsub->dp; in zynqmp_dp_remove()
1783 disable_irq(dp->irq); in zynqmp_dp_remove()
1785 cancel_delayed_work_sync(&dp->hpd_work); in zynqmp_dp_remove()