Lines Matching +full:displayport +full:- +full:controller
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>
242 * struct zynqmp_dp_link_config - Common link config between source and sink
252 * struct zynqmp_dp_mode - Configured mode of DisplayPort
266 * struct zynqmp_dp_config - Configuration of DisplayPort from DTS
278 * struct zynqmp_dp - Xilinx DisplayPort core
285 * @reset: reset controller
335 writel(val, dp->iomem + offset); in zynqmp_dp_write()
340 return readl(dp->iomem + offset); in zynqmp_dp_read()
353 /* -----------------------------------------------------------------------------
364 reset_control_assert(dp->reset); in zynqmp_dp_reset()
366 reset_control_deassert(dp->reset); in zynqmp_dp_reset()
371 bool status = !!reset_control_status(dp->reset); in zynqmp_dp_reset()
379 dev_err(dp->dev, "reset %s timeout\n", assert ? "assert" : "deassert"); in zynqmp_dp_reset()
380 return -ETIMEDOUT; in zynqmp_dp_reset()
384 * zynqmp_dp_phy_init - Initialize the phy
385 * @dp: DisplayPort IP core structure
397 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_phy_init()
398 ret = phy_init(dp->phy[i]); in zynqmp_dp_phy_init()
400 dev_err(dp->dev, "failed to init phy lane %d\n", i); in zynqmp_dp_phy_init()
411 for (i = dp->num_lanes - 1; i >= 0; i--) { in zynqmp_dp_phy_init()
412 ret = phy_power_on(dp->phy[i]); in zynqmp_dp_phy_init()
414 dev_err(dp->dev, "failed to power on phy lane %d\n", i); in zynqmp_dp_phy_init()
423 * zynqmp_dp_phy_exit - Exit the phy
424 * @dp: DisplayPort IP core structure
433 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_phy_exit()
434 ret = phy_power_off(dp->phy[i]); in zynqmp_dp_phy_exit()
436 dev_err(dp->dev, "failed to power off phy(%d) %d\n", i, in zynqmp_dp_phy_exit()
440 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_phy_exit()
441 ret = phy_exit(dp->phy[i]); in zynqmp_dp_phy_exit()
443 dev_err(dp->dev, "failed to exit phy(%d) %d\n", i, ret); in zynqmp_dp_phy_exit()
448 * zynqmp_dp_phy_probe - Probe the PHYs
449 * @dp: DisplayPort IP core structure
453 * found. The caller can check dp->num_lanes to check how many PHYs were found.
456 * * 0 - Success
457 * * -ENXIO - No PHY found
458 * * -EPROBE_DEFER - Probe deferral requested
459 * * Other negative value - PHY retrieval failure
469 snprintf(phy_name, sizeof(phy_name), "dp-phy%d", i); in zynqmp_dp_phy_probe()
470 phy = devm_phy_get(dp->dev, phy_name); in zynqmp_dp_phy_probe()
474 case -ENODEV: in zynqmp_dp_phy_probe()
475 if (dp->num_lanes) in zynqmp_dp_phy_probe()
478 dev_err(dp->dev, "no PHY found\n"); in zynqmp_dp_phy_probe()
479 return -ENXIO; in zynqmp_dp_phy_probe()
481 case -EPROBE_DEFER: in zynqmp_dp_phy_probe()
482 return -EPROBE_DEFER; in zynqmp_dp_phy_probe()
485 dev_err(dp->dev, "failed to get PHY lane %u\n", in zynqmp_dp_phy_probe()
491 dp->phy[i] = phy; in zynqmp_dp_phy_probe()
492 dp->num_lanes++; in zynqmp_dp_phy_probe()
499 * zynqmp_dp_phy_ready - Check if PHY is ready
500 * @dp: DisplayPort IP core structure
505 * Return: 0 if PHY is ready, or -ENODEV if PHY is not ready.
511 ready = (1 << dp->num_lanes) - 1; in zynqmp_dp_phy_ready()
520 dev_err(dp->dev, "PHY isn't ready\n"); in zynqmp_dp_phy_ready()
521 return -ENODEV; in zynqmp_dp_phy_ready()
530 /* -----------------------------------------------------------------------------
531 * DisplayPort Link Training
535 * zynqmp_dp_max_rate - Calculate and return available max pixel clock
536 * @link_rate: link rate (Kilo-bytes / sec)
548 * zynqmp_dp_mode_configure - Configure the link values
549 * @dp: DisplayPort IP core structure
558 * Return: Current link rate code, or -EINVAL.
563 int max_rate = dp->link_config.max_rate; in zynqmp_dp_mode_configure()
565 u8 max_lanes = dp->link_config.max_lanes; in zynqmp_dp_mode_configure()
567 u8 bpp = dp->config.bpp; in zynqmp_dp_mode_configure()
579 dev_err(dp->dev, "can't downshift. already lowest link rate\n"); in zynqmp_dp_mode_configure()
580 return -EINVAL; in zynqmp_dp_mode_configure()
594 dp->mode.bw_code = bw_code; in zynqmp_dp_mode_configure()
595 dp->mode.lane_cnt = lane_cnt; in zynqmp_dp_mode_configure()
596 dp->mode.pclock = pclock; in zynqmp_dp_mode_configure()
597 return dp->mode.bw_code; in zynqmp_dp_mode_configure()
601 dev_err(dp->dev, "failed to configure link values\n"); in zynqmp_dp_mode_configure()
603 return -EINVAL; in zynqmp_dp_mode_configure()
607 * zynqmp_dp_adjust_train - Adjust train values
608 * @dp: DisplayPort IP core structure
614 u8 *train_set = dp->train_set; in zynqmp_dp_adjust_train()
618 for (i = 0; i < dp->mode.lane_cnt; i++) { in zynqmp_dp_adjust_train()
635 for (i = 0; i < dp->mode.lane_cnt; i++) in zynqmp_dp_adjust_train()
640 * zynqmp_dp_update_vs_emph - Update the training values
641 * @dp: DisplayPort IP core structure
654 ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, dp->train_set, in zynqmp_dp_update_vs_emph()
655 dp->mode.lane_cnt); in zynqmp_dp_update_vs_emph()
659 for (i = 0; i < dp->mode.lane_cnt; i++) { in zynqmp_dp_update_vs_emph()
662 u8 train = dp->train_set[i]; in zynqmp_dp_update_vs_emph()
669 phy_configure(dp->phy[i], &opts); in zynqmp_dp_update_vs_emph()
678 * zynqmp_dp_link_train_cr - Train clock recovery
679 * @dp: DisplayPort IP core structure
687 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_link_train_cr()
695 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in zynqmp_dp_link_train_cr()
710 drm_dp_link_train_clock_recovery_delay(&dp->aux, dp->dpcd); in zynqmp_dp_link_train_cr()
711 ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status); in zynqmp_dp_link_train_cr()
720 if (!(dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED)) in zynqmp_dp_link_train_cr()
725 if ((dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == vs) in zynqmp_dp_link_train_cr()
733 vs = dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; in zynqmp_dp_link_train_cr()
738 return -EIO; in zynqmp_dp_link_train_cr()
744 * zynqmp_dp_link_train_ce - Train channel equalization
745 * @dp: DisplayPort IP core structure
753 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_link_train_ce()
758 if (dp->dpcd[DP_DPCD_REV] >= DP_V1_2 && in zynqmp_dp_link_train_ce()
759 dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED) in zynqmp_dp_link_train_ce()
765 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in zynqmp_dp_link_train_ce()
775 drm_dp_link_train_channel_eq_delay(&dp->aux, dp->dpcd); in zynqmp_dp_link_train_ce()
776 ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status); in zynqmp_dp_link_train_ce()
788 return -EIO; in zynqmp_dp_link_train_ce()
794 * zynqmp_dp_link_train - Train the link
795 * @dp: DisplayPort IP core structure
802 u8 bw_code = dp->mode.bw_code; in zynqmp_dp_train()
803 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_train()
809 enhanced = drm_dp_enhanced_frame_cap(dp->dpcd); in zynqmp_dp_train()
815 if (dp->dpcd[3] & 0x1) { in zynqmp_dp_train()
817 drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, in zynqmp_dp_train()
821 drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, 0); in zynqmp_dp_train()
824 ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET, aux_lane_cnt); in zynqmp_dp_train()
826 dev_err(dp->dev, "failed to set lane count\n"); in zynqmp_dp_train()
830 ret = drm_dp_dpcd_writeb(&dp->aux, DP_MAIN_LINK_CHANNEL_CODING_SET, in zynqmp_dp_train()
833 dev_err(dp->dev, "failed to set ANSI 8B/10B encoding\n"); in zynqmp_dp_train()
837 ret = drm_dp_dpcd_writeb(&dp->aux, DP_LINK_BW_SET, bw_code); in zynqmp_dp_train()
839 dev_err(dp->dev, "failed to set DP bandwidth\n"); in zynqmp_dp_train()
863 memset(dp->train_set, 0, sizeof(dp->train_set)); in zynqmp_dp_train()
872 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in zynqmp_dp_train()
875 dev_err(dp->dev, "failed to disable training pattern\n"); in zynqmp_dp_train()
887 * zynqmp_dp_train_loop - Downshift the link rate during training
888 * @dp: DisplayPort IP core structure
894 struct zynqmp_dp_mode *mode = &dp->mode; in zynqmp_dp_train_loop()
895 u8 bw = mode->bw_code; in zynqmp_dp_train_loop()
899 if (dp->status == connector_status_disconnected || in zynqmp_dp_train_loop()
900 !dp->enabled) in zynqmp_dp_train_loop()
907 ret = zynqmp_dp_mode_configure(dp, mode->pclock, bw); in zynqmp_dp_train_loop()
915 dev_err(dp->dev, "failed to train the DP link\n"); in zynqmp_dp_train_loop()
918 /* -----------------------------------------------------------------------------
919 * DisplayPort AUX
925 * zynqmp_dp_aux_cmd_submit - Submit aux command
926 * @dp: DisplayPort IP core structure
942 * -EBUSY when there is any request already being processed
943 * -ETIMEDOUT when receiving reply is timed out
944 * -EIO when received bytes are less than requested
954 return -EBUSY; in zynqmp_dp_aux_cmd_submit()
966 reg |= (bytes - 1) << ZYNQMP_DP_AUX_COMMAND_BYTES_SHIFT; in zynqmp_dp_aux_cmd_submit()
977 return -ETIMEDOUT; in zynqmp_dp_aux_cmd_submit()
991 return -EIO; in zynqmp_dp_aux_cmd_submit()
1012 ret = zynqmp_dp_aux_cmd_submit(dp, msg->request, msg->address, in zynqmp_dp_aux_transfer()
1013 msg->buffer, msg->size, in zynqmp_dp_aux_transfer()
1014 &msg->reply); in zynqmp_dp_aux_transfer()
1016 dev_dbg(dp->dev, "aux %d retries\n", i); in zynqmp_dp_aux_transfer()
1017 return msg->size; in zynqmp_dp_aux_transfer()
1020 if (dp->status == connector_status_disconnected) { in zynqmp_dp_aux_transfer()
1021 dev_dbg(dp->dev, "no connected aux device\n"); in zynqmp_dp_aux_transfer()
1022 return -ENODEV; in zynqmp_dp_aux_transfer()
1028 dev_dbg(dp->dev, "failed to do aux transfer (%d)\n", ret); in zynqmp_dp_aux_transfer()
1034 * zynqmp_dp_aux_init - Initialize and register the DP AUX
1035 * @dp: DisplayPort IP core structure
1053 rate = clk_get_rate(dp->dpsub->apb_clk); in zynqmp_dp_aux_init()
1056 dev_err(dp->dev, "aclk frequency too high\n"); in zynqmp_dp_aux_init()
1057 return -EINVAL; in zynqmp_dp_aux_init()
1064 dp->aux.name = "ZynqMP DP AUX"; in zynqmp_dp_aux_init()
1065 dp->aux.dev = dp->dev; in zynqmp_dp_aux_init()
1066 dp->aux.drm_dev = dp->drm; in zynqmp_dp_aux_init()
1067 dp->aux.transfer = zynqmp_dp_aux_transfer; in zynqmp_dp_aux_init()
1069 return drm_dp_aux_register(&dp->aux); in zynqmp_dp_aux_init()
1073 * zynqmp_dp_aux_cleanup - Cleanup the DP AUX
1074 * @dp: DisplayPort IP core structure
1080 drm_dp_aux_unregister(&dp->aux); in zynqmp_dp_aux_cleanup()
1083 /* -----------------------------------------------------------------------------
1084 * DisplayPort Generic Support
1088 * zynqmp_dp_update_misc - Write the misc registers
1089 * @dp: DisplayPort IP core structure
1096 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_MISC0, dp->config.misc0); in zynqmp_dp_update_misc()
1097 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_MISC1, dp->config.misc1); in zynqmp_dp_update_misc()
1101 * zynqmp_dp_set_format - Set the input format
1102 * @dp: DisplayPort IP core structure
1108 * Return: 0 on success, or -EINVAL.
1115 struct zynqmp_dp_config *config = &dp->config; in zynqmp_dp_set_format()
1118 config->misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_MASK; in zynqmp_dp_set_format()
1119 config->misc1 &= ~ZYNQMP_DP_MAIN_STREAM_MISC1_Y_ONLY_EN; in zynqmp_dp_set_format()
1123 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_RGB; in zynqmp_dp_set_format()
1128 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_444; in zynqmp_dp_set_format()
1133 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_422; in zynqmp_dp_set_format()
1138 config->misc1 |= ZYNQMP_DP_MAIN_STREAM_MISC1_Y_ONLY_EN; in zynqmp_dp_set_format()
1143 dev_err(dp->dev, "Invalid colormetry in DT\n"); in zynqmp_dp_set_format()
1144 return -EINVAL; in zynqmp_dp_set_format()
1147 display = &dp->connector.display_info; in zynqmp_dp_set_format()
1148 if (display->bpc && bpc > display->bpc) { in zynqmp_dp_set_format()
1149 dev_warn(dp->dev, in zynqmp_dp_set_format()
1151 bpc, display->bpc); in zynqmp_dp_set_format()
1152 bpc = display->bpc; in zynqmp_dp_set_format()
1155 config->misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_MASK; in zynqmp_dp_set_format()
1159 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_6; in zynqmp_dp_set_format()
1162 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8; in zynqmp_dp_set_format()
1165 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_10; in zynqmp_dp_set_format()
1168 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_12; in zynqmp_dp_set_format()
1171 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_16; in zynqmp_dp_set_format()
1174 dev_warn(dp->dev, "Not supported bpc (%u). fall back to 8bpc\n", in zynqmp_dp_set_format()
1176 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8; in zynqmp_dp_set_format()
1182 config->bpp = bpc * num_colors; in zynqmp_dp_set_format()
1188 * zynqmp_dp_encoder_mode_set_transfer_unit - Set the transfer unit values
1189 * @dp: DisplayPort IP core structure
1205 vid_kbytes = mode->clock * (dp->config.bpp / 8); in zynqmp_dp_encoder_mode_set_transfer_unit()
1206 bw = drm_dp_bw_code_to_link_rate(dp->mode.bw_code); in zynqmp_dp_encoder_mode_set_transfer_unit()
1207 avg_bytes_per_tu = vid_kbytes * tu / (dp->mode.lane_cnt * bw / 1000); in zynqmp_dp_encoder_mode_set_transfer_unit()
1219 init_wait = tu - avg_bytes_per_tu / 1000; in zynqmp_dp_encoder_mode_set_transfer_unit()
1225 * zynqmp_dp_encoder_mode_set_stream - Configure the main stream
1226 * @dp: DisplayPort IP core structure
1235 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_encoder_mode_set_stream()
1239 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HTOTAL, mode->htotal); in zynqmp_dp_encoder_mode_set_stream()
1240 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VTOTAL, mode->vtotal); in zynqmp_dp_encoder_mode_set_stream()
1242 (!!(mode->flags & DRM_MODE_FLAG_PVSYNC) << in zynqmp_dp_encoder_mode_set_stream()
1244 (!!(mode->flags & DRM_MODE_FLAG_PHSYNC) << in zynqmp_dp_encoder_mode_set_stream()
1247 mode->hsync_end - mode->hsync_start); in zynqmp_dp_encoder_mode_set_stream()
1249 mode->vsync_end - mode->vsync_start); in zynqmp_dp_encoder_mode_set_stream()
1250 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HRES, mode->hdisplay); in zynqmp_dp_encoder_mode_set_stream()
1251 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VRES, mode->vdisplay); in zynqmp_dp_encoder_mode_set_stream()
1253 mode->htotal - mode->hsync_start); in zynqmp_dp_encoder_mode_set_stream()
1255 mode->vtotal - mode->vsync_start); in zynqmp_dp_encoder_mode_set_stream()
1258 if (dp->config.misc0 & ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK) { in zynqmp_dp_encoder_mode_set_stream()
1259 reg = drm_dp_bw_code_to_link_rate(dp->mode.bw_code); in zynqmp_dp_encoder_mode_set_stream()
1261 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_M_VID, mode->clock); in zynqmp_dp_encoder_mode_set_stream()
1262 rate = zynqmp_disp_get_audio_clk_rate(dp->dpsub->disp); in zynqmp_dp_encoder_mode_set_stream()
1264 dev_dbg(dp->dev, "Audio rate: %d\n", rate / 512); in zynqmp_dp_encoder_mode_set_stream()
1271 if (zynqmp_disp_audio_enabled(dp->dpsub->disp)) in zynqmp_dp_encoder_mode_set_stream()
1277 wpl = (mode->hdisplay * dp->config.bpp + 15) / 16; in zynqmp_dp_encoder_mode_set_stream()
1278 reg = wpl + wpl % lane_cnt - lane_cnt; in zynqmp_dp_encoder_mode_set_stream()
1282 /* -----------------------------------------------------------------------------
1290 struct zynqmp_dp_link_config *link_config = &dp->link_config; in zynqmp_dp_connector_detect()
1306 ret = drm_dp_dpcd_read(&dp->aux, 0x0, dp->dpcd, in zynqmp_dp_connector_detect()
1307 sizeof(dp->dpcd)); in zynqmp_dp_connector_detect()
1309 dev_dbg(dp->dev, "DPCD read failed"); in zynqmp_dp_connector_detect()
1313 link_config->max_rate = min_t(int, in zynqmp_dp_connector_detect()
1314 drm_dp_max_link_rate(dp->dpcd), in zynqmp_dp_connector_detect()
1316 link_config->max_lanes = min_t(u8, in zynqmp_dp_connector_detect()
1317 drm_dp_max_lane_count(dp->dpcd), in zynqmp_dp_connector_detect()
1318 dp->num_lanes); in zynqmp_dp_connector_detect()
1320 dp->status = connector_status_connected; in zynqmp_dp_connector_detect()
1325 dp->status = connector_status_disconnected; in zynqmp_dp_connector_detect()
1335 edid = drm_get_edid(connector, &dp->aux.ddc); in zynqmp_dp_connector_get_modes()
1351 return &dp->encoder; in zynqmp_dp_connector_best_encoder()
1358 u8 max_lanes = dp->link_config.max_lanes; in zynqmp_dp_connector_mode_valid()
1359 u8 bpp = dp->config.bpp; in zynqmp_dp_connector_mode_valid()
1360 int max_rate = dp->link_config.max_rate; in zynqmp_dp_connector_mode_valid()
1363 if (mode->clock > ZYNQMP_MAX_FREQ) { in zynqmp_dp_connector_mode_valid()
1364 dev_dbg(dp->dev, "filtered the mode, %s,for high pixel rate\n", in zynqmp_dp_connector_mode_valid()
1365 mode->name); in zynqmp_dp_connector_mode_valid()
1372 if (mode->clock > rate) { in zynqmp_dp_connector_mode_valid()
1373 dev_dbg(dp->dev, "filtered the mode, %s,for high pixel rate\n", in zynqmp_dp_connector_mode_valid()
1374 mode->name); in zynqmp_dp_connector_mode_valid()
1398 /* -----------------------------------------------------------------------------
1408 pm_runtime_get_sync(dp->dev); in zynqmp_dp_encoder_enable()
1409 dp->enabled = true; in zynqmp_dp_encoder_enable()
1411 if (zynqmp_disp_audio_enabled(dp->dpsub->disp)) in zynqmp_dp_encoder_enable()
1414 if (dp->status == connector_status_connected) { in zynqmp_dp_encoder_enable()
1416 ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, in zynqmp_dp_encoder_enable()
1426 dev_dbg(dp->dev, "DP aux failed\n"); in zynqmp_dp_encoder_enable()
1438 dp->enabled = false; in zynqmp_dp_encoder_disable()
1439 cancel_delayed_work(&dp->hpd_work); in zynqmp_dp_encoder_disable()
1441 drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3); in zynqmp_dp_encoder_disable()
1444 if (zynqmp_disp_audio_enabled(dp->dpsub->disp)) in zynqmp_dp_encoder_disable()
1446 pm_runtime_put_sync(dp->dev); in zynqmp_dp_encoder_disable()
1455 struct drm_display_mode *mode = &crtc_state->mode; in zynqmp_dp_encoder_atomic_mode_set()
1456 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; in zynqmp_dp_encoder_atomic_mode_set()
1457 u8 max_lanes = dp->link_config.max_lanes; in zynqmp_dp_encoder_atomic_mode_set()
1458 u8 bpp = dp->config.bpp; in zynqmp_dp_encoder_atomic_mode_set()
1459 int rate, max_rate = dp->link_config.max_rate; in zynqmp_dp_encoder_atomic_mode_set()
1466 if (mode->clock > rate) { in zynqmp_dp_encoder_atomic_mode_set()
1467 dev_err(dp->dev, "the mode, %s,has too high pixel rate\n", in zynqmp_dp_encoder_atomic_mode_set()
1468 mode->name); in zynqmp_dp_encoder_atomic_mode_set()
1472 ret = zynqmp_dp_mode_configure(dp, adjusted_mode->clock, 0); in zynqmp_dp_encoder_atomic_mode_set()
1487 struct drm_display_mode *mode = &crtc_state->mode; in zynqmp_dp_encoder_atomic_check()
1488 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; in zynqmp_dp_encoder_atomic_check()
1489 int diff = mode->htotal - mode->hsync_end; in zynqmp_dp_encoder_atomic_check()
1496 int vrefresh = (adjusted_mode->clock * 1000) / in zynqmp_dp_encoder_atomic_check()
1497 (adjusted_mode->vtotal * adjusted_mode->htotal); in zynqmp_dp_encoder_atomic_check()
1499 dev_dbg(encoder->dev->dev, "hbackporch adjusted: %d to %d", in zynqmp_dp_encoder_atomic_check()
1500 diff, ZYNQMP_DP_MIN_H_BACKPORCH - diff); in zynqmp_dp_encoder_atomic_check()
1501 diff = ZYNQMP_DP_MIN_H_BACKPORCH - diff; in zynqmp_dp_encoder_atomic_check()
1502 adjusted_mode->htotal += diff; in zynqmp_dp_encoder_atomic_check()
1503 adjusted_mode->clock = adjusted_mode->vtotal * in zynqmp_dp_encoder_atomic_check()
1504 adjusted_mode->htotal * vrefresh / 1000; in zynqmp_dp_encoder_atomic_check()
1517 /* -----------------------------------------------------------------------------
1522 * zynqmp_dp_enable_vblank - Enable vblank
1523 * @dp: DisplayPort IP core structure
1533 * zynqmp_dp_disable_vblank - Disable vblank
1534 * @dp: DisplayPort IP core structure
1549 if (dp->drm) in zynqmp_dp_hpd_work_func()
1550 drm_helper_hpd_irq_event(dp->drm); in zynqmp_dp_hpd_work_func()
1565 dev_dbg_ratelimited(dp->dev, "underflow interrupt\n"); in zynqmp_dp_irq_handler()
1567 dev_dbg_ratelimited(dp->dev, "overflow interrupt\n"); in zynqmp_dp_irq_handler()
1572 zynqmp_disp_handle_vblank(dp->dpsub->disp); in zynqmp_dp_irq_handler()
1575 schedule_delayed_work(&dp->hpd_work, 0); in zynqmp_dp_irq_handler()
1581 ret = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, status, in zynqmp_dp_irq_handler()
1587 !drm_dp_clock_recovery_ok(&status[2], dp->mode.lane_cnt) || in zynqmp_dp_irq_handler()
1588 !drm_dp_channel_eq_ok(&status[2], dp->mode.lane_cnt)) { in zynqmp_dp_irq_handler()
1597 /* -----------------------------------------------------------------------------
1603 struct zynqmp_dp *dp = dpsub->dp; in zynqmp_dp_drm_init()
1604 struct drm_encoder *encoder = &dp->encoder; in zynqmp_dp_drm_init()
1605 struct drm_connector *connector = &dp->connector; in zynqmp_dp_drm_init()
1608 dp->config.misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK; in zynqmp_dp_drm_init()
1612 encoder->possible_crtcs |= zynqmp_disp_get_crtc_mask(dpsub->disp); in zynqmp_dp_drm_init()
1613 drm_simple_encoder_init(dp->drm, encoder, DRM_MODE_ENCODER_TMDS); in zynqmp_dp_drm_init()
1616 connector->polled = DRM_CONNECTOR_POLL_HPD; in zynqmp_dp_drm_init()
1617 ret = drm_connector_init(encoder->dev, connector, in zynqmp_dp_drm_init()
1621 dev_err(dp->dev, "failed to create the DRM connector\n"); in zynqmp_dp_drm_init()
1632 dev_err(dp->dev, "failed to initialize DP aux\n"); in zynqmp_dp_drm_init()
1644 struct platform_device *pdev = to_platform_device(dpsub->dev); in zynqmp_dp_probe()
1651 return -ENOMEM; in zynqmp_dp_probe()
1653 dp->dev = &pdev->dev; in zynqmp_dp_probe()
1654 dp->dpsub = dpsub; in zynqmp_dp_probe()
1655 dp->status = connector_status_disconnected; in zynqmp_dp_probe()
1656 dp->drm = drm; in zynqmp_dp_probe()
1658 INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func); in zynqmp_dp_probe()
1660 dpsub->dp = dp; in zynqmp_dp_probe()
1664 dp->iomem = devm_ioremap_resource(dp->dev, res); in zynqmp_dp_probe()
1665 if (IS_ERR(dp->iomem)) in zynqmp_dp_probe()
1666 return PTR_ERR(dp->iomem); in zynqmp_dp_probe()
1668 dp->irq = platform_get_irq(pdev, 0); in zynqmp_dp_probe()
1669 if (dp->irq < 0) in zynqmp_dp_probe()
1670 return dp->irq; in zynqmp_dp_probe()
1672 dp->reset = devm_reset_control_get(dp->dev, NULL); in zynqmp_dp_probe()
1673 if (IS_ERR(dp->reset)) { in zynqmp_dp_probe()
1674 if (PTR_ERR(dp->reset) != -EPROBE_DEFER) in zynqmp_dp_probe()
1675 dev_err(dp->dev, "failed to get reset: %ld\n", in zynqmp_dp_probe()
1676 PTR_ERR(dp->reset)); in zynqmp_dp_probe()
1677 return PTR_ERR(dp->reset); in zynqmp_dp_probe()
1706 ret = devm_request_threaded_irq(dp->dev, dp->irq, NULL, in zynqmp_dp_probe()
1708 dev_name(dp->dev), dp); in zynqmp_dp_probe()
1712 dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n", in zynqmp_dp_probe()
1713 dp->num_lanes); in zynqmp_dp_probe()
1727 struct zynqmp_dp *dp = dpsub->dp; in zynqmp_dp_remove()
1730 disable_irq(dp->irq); in zynqmp_dp_remove()
1732 cancel_delayed_work_sync(&dp->hpd_work); in zynqmp_dp_remove()