Lines Matching +full:zynqmp +full:- +full:reset
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>
27 #include <linux/media-bus-format.h>
32 #include <linux/reset.h>
249 * struct zynqmp_dp_link_config - Common link config between source and sink
259 * struct zynqmp_dp_mode - Configured mode of DisplayPort
273 * struct zynqmp_dp_config - Configuration of DisplayPort from DTS
285 * enum test_pattern - Test patterns for test testing
289 * @TEST_80BIT_CUSTOM: A custom 80-bit pattern
311 [TEST_SYMBOL_ERROR] = "symbol-error",
313 [TEST_80BIT_CUSTOM] = "80bit-custom",
318 * struct zynqmp_dp_test - Configuration for test mode
338 * struct zynqmp_dp_train_set_priv - Private data for train_set debugfs files
348 * struct zynqmp_dp - Xilinx DisplayPort core
352 * @reset: reset controller
392 struct reset_control *reset; member
418 writel(val, dp->iomem + offset); in zynqmp_dp_write()
423 return readl(dp->iomem + offset); in zynqmp_dp_read()
436 /* -----------------------------------------------------------------------------
447 reset_control_assert(dp->reset); in zynqmp_dp_reset()
449 reset_control_deassert(dp->reset); in zynqmp_dp_reset()
454 bool status = !!reset_control_status(dp->reset); in zynqmp_dp_reset()
462 dev_err(dp->dev, "reset %s timeout\n", assert ? "assert" : "deassert"); in zynqmp_dp_reset()
463 return -ETIMEDOUT; in zynqmp_dp_reset()
467 * zynqmp_dp_phy_init - Initialize the phy
480 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_phy_init()
481 ret = phy_init(dp->phy[i]); in zynqmp_dp_phy_init()
483 dev_err(dp->dev, "failed to init phy lane %d\n", i); in zynqmp_dp_phy_init()
494 for (i = dp->num_lanes - 1; i >= 0; i--) { in zynqmp_dp_phy_init()
495 ret = phy_power_on(dp->phy[i]); in zynqmp_dp_phy_init()
497 dev_err(dp->dev, "failed to power on phy lane %d\n", i); in zynqmp_dp_phy_init()
506 * zynqmp_dp_phy_exit - Exit the phy
516 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_phy_exit()
517 ret = phy_power_off(dp->phy[i]); in zynqmp_dp_phy_exit()
519 dev_err(dp->dev, "failed to power off phy(%d) %d\n", i, in zynqmp_dp_phy_exit()
523 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_phy_exit()
524 ret = phy_exit(dp->phy[i]); in zynqmp_dp_phy_exit()
526 dev_err(dp->dev, "failed to exit phy(%d) %d\n", i, ret); in zynqmp_dp_phy_exit()
531 * zynqmp_dp_phy_probe - Probe the PHYs
536 * found. The caller can check dp->num_lanes to check how many PHYs were found.
539 * * 0 - Success
540 * * -ENXIO - No PHY found
541 * * -EPROBE_DEFER - Probe deferral requested
542 * * Other negative value - PHY retrieval failure
552 snprintf(phy_name, sizeof(phy_name), "dp-phy%d", i); in zynqmp_dp_phy_probe()
553 phy = devm_phy_get(dp->dev, phy_name); in zynqmp_dp_phy_probe()
557 case -ENODEV: in zynqmp_dp_phy_probe()
558 if (dp->num_lanes) in zynqmp_dp_phy_probe()
561 dev_err(dp->dev, "no PHY found\n"); in zynqmp_dp_phy_probe()
562 return -ENXIO; in zynqmp_dp_phy_probe()
564 case -EPROBE_DEFER: in zynqmp_dp_phy_probe()
565 return -EPROBE_DEFER; in zynqmp_dp_phy_probe()
568 dev_err(dp->dev, "failed to get PHY lane %u\n", in zynqmp_dp_phy_probe()
574 dp->phy[i] = phy; in zynqmp_dp_phy_probe()
575 dp->num_lanes++; in zynqmp_dp_phy_probe()
582 * zynqmp_dp_phy_ready - Check if PHY is ready
588 * Return: 0 if PHY is ready, or -ENODEV if PHY is not ready.
594 ready = (1 << dp->num_lanes) - 1; in zynqmp_dp_phy_ready()
603 dev_err(dp->dev, "PHY isn't ready\n"); in zynqmp_dp_phy_ready()
604 return -ENODEV; in zynqmp_dp_phy_ready()
613 /* -----------------------------------------------------------------------------
618 * zynqmp_dp_max_rate - Calculate and return available max pixel clock
619 * @link_rate: link rate (Kilo-bytes / sec)
631 * zynqmp_dp_mode_configure - Configure the link values
641 * Return: Current link rate code, or -EINVAL.
646 int max_rate = dp->link_config.max_rate; in zynqmp_dp_mode_configure()
648 u8 max_lanes = dp->link_config.max_lanes; in zynqmp_dp_mode_configure()
650 u8 bpp = dp->config.bpp; in zynqmp_dp_mode_configure()
662 dev_err(dp->dev, "can't downshift. already lowest link rate\n"); in zynqmp_dp_mode_configure()
663 return -EINVAL; in zynqmp_dp_mode_configure()
677 dp->mode.bw_code = bw_code; in zynqmp_dp_mode_configure()
678 dp->mode.lane_cnt = lane_cnt; in zynqmp_dp_mode_configure()
679 dp->mode.pclock = pclock; in zynqmp_dp_mode_configure()
680 return dp->mode.bw_code; in zynqmp_dp_mode_configure()
684 dev_err(dp->dev, "failed to configure link values\n"); in zynqmp_dp_mode_configure()
686 return -EINVAL; in zynqmp_dp_mode_configure()
690 * zynqmp_dp_adjust_train - Adjust train values
697 u8 *train_set = dp->train_set; in zynqmp_dp_adjust_train()
700 for (i = 0; i < dp->mode.lane_cnt; i++) { in zynqmp_dp_adjust_train()
716 * zynqmp_dp_update_vs_emph - Update the training values
731 ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, train_set, in zynqmp_dp_update_vs_emph()
732 dp->mode.lane_cnt); in zynqmp_dp_update_vs_emph()
736 for (i = 0; i < dp->mode.lane_cnt; i++) { in zynqmp_dp_update_vs_emph()
746 phy_configure(dp->phy[i], &opts); in zynqmp_dp_update_vs_emph()
755 * zynqmp_dp_link_train_cr - Train clock recovery
764 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_link_train_cr()
772 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in zynqmp_dp_link_train_cr()
783 ret = zynqmp_dp_update_vs_emph(dp, dp->train_set); in zynqmp_dp_link_train_cr()
787 drm_dp_link_train_clock_recovery_delay(&dp->aux, dp->dpcd); in zynqmp_dp_link_train_cr()
788 ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status); in zynqmp_dp_link_train_cr()
797 if (!(dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED)) in zynqmp_dp_link_train_cr()
802 if ((dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == vs) in zynqmp_dp_link_train_cr()
810 vs = dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; in zynqmp_dp_link_train_cr()
815 return -EIO; in zynqmp_dp_link_train_cr()
821 * zynqmp_dp_link_train_ce - Train channel equalization
830 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_link_train_ce()
835 if (dp->dpcd[DP_DPCD_REV] >= DP_V1_2 && in zynqmp_dp_link_train_ce()
836 dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED) in zynqmp_dp_link_train_ce()
842 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in zynqmp_dp_link_train_ce()
848 ret = zynqmp_dp_update_vs_emph(dp, dp->train_set); in zynqmp_dp_link_train_ce()
852 drm_dp_link_train_channel_eq_delay(&dp->aux, dp->dpcd); in zynqmp_dp_link_train_ce()
853 ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status); in zynqmp_dp_link_train_ce()
865 return -EIO; in zynqmp_dp_link_train_ce()
871 * zynqmp_dp_setup() - Set up major link parameters
876 * @downspread: Enable spread-spectrum clocking
878 * Return: 0 on success, or -errno on failure
895 drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, in zynqmp_dp_setup()
899 drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, 0); in zynqmp_dp_setup()
902 ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET, aux_lane_cnt); in zynqmp_dp_setup()
904 dev_err(dp->dev, "failed to set lane count\n"); in zynqmp_dp_setup()
908 ret = drm_dp_dpcd_writeb(&dp->aux, DP_MAIN_LINK_CHANNEL_CODING_SET, in zynqmp_dp_setup()
911 dev_err(dp->dev, "failed to set ANSI 8B/10B encoding\n"); in zynqmp_dp_setup()
915 ret = drm_dp_dpcd_writeb(&dp->aux, DP_LINK_BW_SET, bw_code); in zynqmp_dp_setup()
917 dev_err(dp->dev, "failed to set DP bandwidth\n"); in zynqmp_dp_setup()
940 * zynqmp_dp_train - Train the link
949 ret = zynqmp_dp_setup(dp, dp->mode.bw_code, dp->mode.lane_cnt, in zynqmp_dp_train()
950 drm_dp_enhanced_frame_cap(dp->dpcd), in zynqmp_dp_train()
951 dp->dpcd[DP_MAX_DOWNSPREAD] & in zynqmp_dp_train()
957 memset(dp->train_set, 0, sizeof(dp->train_set)); in zynqmp_dp_train()
966 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in zynqmp_dp_train()
969 dev_err(dp->dev, "failed to disable training pattern\n"); in zynqmp_dp_train()
981 * zynqmp_dp_train_loop - Downshift the link rate during training
988 struct zynqmp_dp_mode *mode = &dp->mode; in zynqmp_dp_train_loop()
989 u8 bw = mode->bw_code; in zynqmp_dp_train_loop()
993 if (dp->status == connector_status_disconnected || in zynqmp_dp_train_loop()
994 !dp->enabled) in zynqmp_dp_train_loop()
1001 ret = zynqmp_dp_mode_configure(dp, mode->pclock, bw); in zynqmp_dp_train_loop()
1009 dev_err(dp->dev, "failed to train the DP link\n"); in zynqmp_dp_train_loop()
1012 /* -----------------------------------------------------------------------------
1019 * zynqmp_dp_aux_cmd_submit - Submit aux command
1036 * -EBUSY when there is any request already being processed
1037 * -ETIMEDOUT when receiving reply is timed out
1038 * -EIO when received bytes are less than requested
1049 return -EBUSY; in zynqmp_dp_aux_cmd_submit()
1051 reinit_completion(&dp->aux_done); in zynqmp_dp_aux_cmd_submit()
1063 reg |= (bytes - 1) << ZYNQMP_DP_AUX_COMMAND_BYTES_SHIFT; in zynqmp_dp_aux_cmd_submit()
1067 time_left = wait_for_completion_timeout(&dp->aux_done, in zynqmp_dp_aux_cmd_submit()
1070 return -ETIMEDOUT; in zynqmp_dp_aux_cmd_submit()
1074 return -ETIMEDOUT; in zynqmp_dp_aux_cmd_submit()
1085 return -EIO; in zynqmp_dp_aux_cmd_submit()
1106 ret = zynqmp_dp_aux_cmd_submit(dp, msg->request, msg->address, in zynqmp_dp_aux_transfer()
1107 msg->buffer, msg->size, in zynqmp_dp_aux_transfer()
1108 &msg->reply); in zynqmp_dp_aux_transfer()
1110 dev_vdbg(dp->dev, "aux %d retries\n", i); in zynqmp_dp_aux_transfer()
1111 return msg->size; in zynqmp_dp_aux_transfer()
1114 if (dp->status == connector_status_disconnected) { in zynqmp_dp_aux_transfer()
1115 dev_dbg(dp->dev, "no connected aux device\n"); in zynqmp_dp_aux_transfer()
1116 if (dp->ignore_aux_errors) in zynqmp_dp_aux_transfer()
1118 return -ENODEV; in zynqmp_dp_aux_transfer()
1124 dev_dbg(dp->dev, "failed to do aux transfer (%d)\n", ret); in zynqmp_dp_aux_transfer()
1126 if (!dp->ignore_aux_errors) in zynqmp_dp_aux_transfer()
1130 msg->reply = DP_AUX_NATIVE_REPLY_ACK; in zynqmp_dp_aux_transfer()
1131 memset(msg->buffer, 0, msg->size); in zynqmp_dp_aux_transfer()
1132 return msg->size; in zynqmp_dp_aux_transfer()
1136 * zynqmp_dp_aux_init - Initialize and register the DP AUX
1155 rate = clk_get_rate(dp->dpsub->apb_clk); in zynqmp_dp_aux_init()
1158 dev_err(dp->dev, "aclk frequency too high\n"); in zynqmp_dp_aux_init()
1159 return -EINVAL; in zynqmp_dp_aux_init()
1169 dp->aux.name = "ZynqMP DP AUX"; in zynqmp_dp_aux_init()
1170 dp->aux.dev = dp->dev; in zynqmp_dp_aux_init()
1171 dp->aux.drm_dev = dp->bridge.dev; in zynqmp_dp_aux_init()
1172 dp->aux.transfer = zynqmp_dp_aux_transfer; in zynqmp_dp_aux_init()
1174 return drm_dp_aux_register(&dp->aux); in zynqmp_dp_aux_init()
1178 * zynqmp_dp_aux_cleanup - Cleanup the DP AUX
1185 drm_dp_aux_unregister(&dp->aux); in zynqmp_dp_aux_cleanup()
1191 /* -----------------------------------------------------------------------------
1196 * zynqmp_dp_update_misc - Write the misc registers
1204 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_MISC0, dp->config.misc0); in zynqmp_dp_update_misc()
1205 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_MISC1, dp->config.misc1); in zynqmp_dp_update_misc()
1209 * zynqmp_dp_set_format - Set the input format
1217 * Return: 0 on success, or -EINVAL.
1224 struct zynqmp_dp_config *config = &dp->config; in zynqmp_dp_set_format()
1227 config->misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_MASK; in zynqmp_dp_set_format()
1228 config->misc1 &= ~ZYNQMP_DP_MAIN_STREAM_MISC1_Y_ONLY_EN; in zynqmp_dp_set_format()
1232 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_RGB; in zynqmp_dp_set_format()
1237 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_444; in zynqmp_dp_set_format()
1242 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_COMP_FORMAT_YCRCB_422; in zynqmp_dp_set_format()
1247 config->misc1 |= ZYNQMP_DP_MAIN_STREAM_MISC1_Y_ONLY_EN; in zynqmp_dp_set_format()
1252 dev_err(dp->dev, "Invalid colormetry in DT\n"); in zynqmp_dp_set_format()
1253 return -EINVAL; in zynqmp_dp_set_format()
1256 if (info && info->bpc && bpc > info->bpc) { in zynqmp_dp_set_format()
1257 dev_warn(dp->dev, in zynqmp_dp_set_format()
1259 bpc, info->bpc); in zynqmp_dp_set_format()
1260 bpc = info->bpc; in zynqmp_dp_set_format()
1263 config->misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_MASK; in zynqmp_dp_set_format()
1267 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_6; in zynqmp_dp_set_format()
1270 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8; in zynqmp_dp_set_format()
1273 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_10; in zynqmp_dp_set_format()
1276 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_12; in zynqmp_dp_set_format()
1279 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_16; in zynqmp_dp_set_format()
1282 dev_warn(dp->dev, "Not supported bpc (%u). fall back to 8bpc\n", in zynqmp_dp_set_format()
1284 config->misc0 |= ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_8; in zynqmp_dp_set_format()
1290 config->bpp = bpc * num_colors; in zynqmp_dp_set_format()
1296 * zynqmp_dp_encoder_mode_set_transfer_unit - Set the transfer unit values
1313 vid_kbytes = mode->clock * (dp->config.bpp / 8); in zynqmp_dp_encoder_mode_set_transfer_unit()
1314 bw = drm_dp_bw_code_to_link_rate(dp->mode.bw_code); in zynqmp_dp_encoder_mode_set_transfer_unit()
1315 avg_bytes_per_tu = vid_kbytes * tu / (dp->mode.lane_cnt * bw / 1000); in zynqmp_dp_encoder_mode_set_transfer_unit()
1327 init_wait = tu - avg_bytes_per_tu / 1000; in zynqmp_dp_encoder_mode_set_transfer_unit()
1333 * zynqmp_dp_encoder_mode_set_stream - Configure the main stream
1343 u8 lane_cnt = dp->mode.lane_cnt; in zynqmp_dp_encoder_mode_set_stream()
1346 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HTOTAL, mode->htotal); in zynqmp_dp_encoder_mode_set_stream()
1347 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VTOTAL, mode->vtotal); in zynqmp_dp_encoder_mode_set_stream()
1349 (!!(mode->flags & DRM_MODE_FLAG_PVSYNC) << in zynqmp_dp_encoder_mode_set_stream()
1351 (!!(mode->flags & DRM_MODE_FLAG_PHSYNC) << in zynqmp_dp_encoder_mode_set_stream()
1354 mode->hsync_end - mode->hsync_start); in zynqmp_dp_encoder_mode_set_stream()
1356 mode->vsync_end - mode->vsync_start); in zynqmp_dp_encoder_mode_set_stream()
1357 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_HRES, mode->hdisplay); in zynqmp_dp_encoder_mode_set_stream()
1358 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VRES, mode->vdisplay); in zynqmp_dp_encoder_mode_set_stream()
1360 mode->htotal - mode->hsync_start); in zynqmp_dp_encoder_mode_set_stream()
1362 mode->vtotal - mode->vsync_start); in zynqmp_dp_encoder_mode_set_stream()
1365 if (dp->config.misc0 & ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK) { in zynqmp_dp_encoder_mode_set_stream()
1366 reg = drm_dp_bw_code_to_link_rate(dp->mode.bw_code); in zynqmp_dp_encoder_mode_set_stream()
1368 zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_M_VID, mode->clock); in zynqmp_dp_encoder_mode_set_stream()
1374 wpl = (mode->hdisplay * dp->config.bpp + 15) / 16; in zynqmp_dp_encoder_mode_set_stream()
1375 reg = wpl + wpl % lane_cnt - lane_cnt; in zynqmp_dp_encoder_mode_set_stream()
1379 /* -----------------------------------------------------------------------------
1386 zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CHANNELS, num_channels - 1); in zynqmp_dp_audio_set_channels()
1404 if (!(dp->config.misc0 & ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK)) in zynqmp_dp_audio_write_n_m()
1407 link_rate = drm_dp_bw_code_to_link_rate(dp->mode.bw_code); in zynqmp_dp_audio_write_n_m()
1409 rate = clk_get_rate(dp->dpsub->aud_clk); in zynqmp_dp_audio_write_n_m()
1411 dev_dbg(dp->dev, "Audio rate: %d\n", rate / 512); in zynqmp_dp_audio_write_n_m()
1417 /* -----------------------------------------------------------------------------
1422 * zynqmp_dp_disp_connected_live_layer - Return the first connected live layer
1431 if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) in zynqmp_dp_disp_connected_live_layer()
1432 return dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_VID]; in zynqmp_dp_disp_connected_live_layer()
1433 else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX)) in zynqmp_dp_disp_connected_live_layer()
1434 return dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX]; in zynqmp_dp_disp_connected_live_layer()
1450 bridge_state = drm_atomic_get_new_bridge_state(state, &dp->bridge); in zynqmp_dp_disp_enable()
1454 bus_fmt = bridge_state->input_bus_cfg.format; in zynqmp_dp_disp_enable()
1458 if (layer == dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX]) in zynqmp_dp_disp_enable()
1459 zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, true, 255); in zynqmp_dp_disp_enable()
1461 zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, false, 0); in zynqmp_dp_disp_enable()
1463 zynqmp_disp_enable(dp->dpsub->disp); in zynqmp_dp_disp_enable()
1475 zynqmp_disp_disable(dp->dpsub->disp); in zynqmp_dp_disp_disable()
1479 /* -----------------------------------------------------------------------------
1493 dev_err(dp->dev, "failed to initialize DP aux\n"); in zynqmp_dp_bridge_attach()
1497 if (dp->next_bridge) { in zynqmp_dp_bridge_attach()
1498 ret = drm_bridge_attach(encoder, dp->next_bridge, in zynqmp_dp_bridge_attach()
1529 if (mode->clock > ZYNQMP_MAX_FREQ) { in zynqmp_dp_bridge_mode_valid()
1530 dev_dbg(dp->dev, "filtered mode %s for high pixel rate\n", in zynqmp_dp_bridge_mode_valid()
1531 mode->name); in zynqmp_dp_bridge_mode_valid()
1537 scoped_guard(mutex, &dp->lock) in zynqmp_dp_bridge_mode_valid()
1538 rate = zynqmp_dp_max_rate(dp->link_config.max_rate, in zynqmp_dp_bridge_mode_valid()
1539 dp->link_config.max_lanes, in zynqmp_dp_bridge_mode_valid()
1540 dp->config.bpp); in zynqmp_dp_bridge_mode_valid()
1541 if (mode->clock > rate) { in zynqmp_dp_bridge_mode_valid()
1542 dev_dbg(dp->dev, "filtered mode %s for high pixel rate\n", in zynqmp_dp_bridge_mode_valid()
1543 mode->name); in zynqmp_dp_bridge_mode_valid()
1564 pm_runtime_get_sync(dp->dev); in zynqmp_dp_bridge_atomic_enable()
1566 guard(mutex)(&dp->lock); in zynqmp_dp_bridge_atomic_enable()
1575 bridge->encoder); in zynqmp_dp_bridge_atomic_enable()
1576 crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; in zynqmp_dp_bridge_atomic_enable()
1578 adjusted_mode = &crtc_state->adjusted_mode; in zynqmp_dp_bridge_atomic_enable()
1579 mode = &crtc_state->mode; in zynqmp_dp_bridge_atomic_enable()
1581 zynqmp_dp_set_format(dp, &connector->display_info, in zynqmp_dp_bridge_atomic_enable()
1585 rate = zynqmp_dp_max_rate(dp->link_config.max_rate, in zynqmp_dp_bridge_atomic_enable()
1586 dp->link_config.max_lanes, dp->config.bpp); in zynqmp_dp_bridge_atomic_enable()
1587 if (mode->clock > rate) { in zynqmp_dp_bridge_atomic_enable()
1588 dev_err(dp->dev, "mode %s has too high pixel rate\n", in zynqmp_dp_bridge_atomic_enable()
1589 mode->name); in zynqmp_dp_bridge_atomic_enable()
1594 ret = zynqmp_dp_mode_configure(dp, adjusted_mode->clock, 0); in zynqmp_dp_bridge_atomic_enable()
1596 pm_runtime_put_sync(dp->dev); in zynqmp_dp_bridge_atomic_enable()
1604 dp->enabled = true; in zynqmp_dp_bridge_atomic_enable()
1608 if (dp->status == connector_status_connected) { in zynqmp_dp_bridge_atomic_enable()
1610 ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, in zynqmp_dp_bridge_atomic_enable()
1620 dev_dbg(dp->dev, "DP aux failed\n"); in zynqmp_dp_bridge_atomic_enable()
1635 mutex_lock(&dp->lock); in zynqmp_dp_bridge_atomic_disable()
1636 dp->enabled = false; in zynqmp_dp_bridge_atomic_disable()
1637 cancel_work(&dp->hpd_work); in zynqmp_dp_bridge_atomic_disable()
1639 drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3); in zynqmp_dp_bridge_atomic_disable()
1644 mutex_unlock(&dp->lock); in zynqmp_dp_bridge_atomic_disable()
1646 pm_runtime_put_sync(dp->dev); in zynqmp_dp_bridge_atomic_disable()
1657 struct drm_display_mode *mode = &crtc_state->mode; in zynqmp_dp_bridge_atomic_check()
1658 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; in zynqmp_dp_bridge_atomic_check()
1659 int diff = mode->htotal - mode->hsync_end; in zynqmp_dp_bridge_atomic_check()
1662 * ZynqMP DP requires horizontal backporch to be greater than 12. in zynqmp_dp_bridge_atomic_check()
1666 int vrefresh = (adjusted_mode->clock * 1000) / in zynqmp_dp_bridge_atomic_check()
1667 (adjusted_mode->vtotal * adjusted_mode->htotal); in zynqmp_dp_bridge_atomic_check()
1669 dev_dbg(dp->dev, "hbackporch adjusted: %d to %d", in zynqmp_dp_bridge_atomic_check()
1670 diff, ZYNQMP_DP_MIN_H_BACKPORCH - diff); in zynqmp_dp_bridge_atomic_check()
1671 diff = ZYNQMP_DP_MIN_H_BACKPORCH - diff; in zynqmp_dp_bridge_atomic_check()
1672 adjusted_mode->htotal += diff; in zynqmp_dp_bridge_atomic_check()
1673 adjusted_mode->clock = adjusted_mode->vtotal * in zynqmp_dp_bridge_atomic_check()
1674 adjusted_mode->htotal * vrefresh / 1000; in zynqmp_dp_bridge_atomic_check()
1682 struct zynqmp_dp_link_config *link_config = &dp->link_config; in __zynqmp_dp_bridge_detect()
1686 lockdep_assert_held(&dp->lock); in __zynqmp_dp_bridge_detect()
1700 ret = drm_dp_dpcd_read(&dp->aux, 0x0, dp->dpcd, in __zynqmp_dp_bridge_detect()
1701 sizeof(dp->dpcd)); in __zynqmp_dp_bridge_detect()
1703 dev_dbg(dp->dev, "DPCD read failed"); in __zynqmp_dp_bridge_detect()
1707 link_config->max_rate = min_t(int, in __zynqmp_dp_bridge_detect()
1708 drm_dp_max_link_rate(dp->dpcd), in __zynqmp_dp_bridge_detect()
1710 link_config->max_lanes = min_t(u8, in __zynqmp_dp_bridge_detect()
1711 drm_dp_max_lane_count(dp->dpcd), in __zynqmp_dp_bridge_detect()
1712 dp->num_lanes); in __zynqmp_dp_bridge_detect()
1714 dp->status = connector_status_connected; in __zynqmp_dp_bridge_detect()
1719 dp->status = connector_status_disconnected; in __zynqmp_dp_bridge_detect()
1728 guard(mutex)(&dp->lock); in zynqmp_dp_bridge_detect()
1737 return drm_edid_read_ddc(connector, &dp->aux.ddc); in zynqmp_dp_bridge_edid_read()
1769 /* -----------------------------------------------------------------------------
1774 * zynqmp_dp_set_test_pattern() - Configure the link for a test pattern
1843 if (dp->dpcd[DP_DPCD_REV] < 0x12) { in zynqmp_dp_set_test_pattern()
1845 dev_warn(dp->dev, in zynqmp_dp_set_test_pattern()
1854 ret = drm_dp_dpcd_write(&dp->aux, DP_LINK_QUAL_LANE0_SET, in zynqmp_dp_set_test_pattern()
1860 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, dpcd_train); in zynqmp_dp_set_test_pattern()
1866 return zynqmp_dp_setup(dp, dp->test.bw_code, dp->test.link_cnt, in zynqmp_dp_test_setup()
1867 dp->test.enhanced, dp->test.downspread); in zynqmp_dp_test_setup()
1873 struct zynqmp_dp *dp = file->private_data; in zynqmp_dp_pattern_read()
1877 scoped_guard(mutex, &dp->lock) in zynqmp_dp_pattern_read()
1879 test_pattern_str[dp->test.pattern]); in zynqmp_dp_pattern_read()
1888 struct zynqmp_dp *dp = file->private_data; in zynqmp_dp_pattern_write()
1893 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, in zynqmp_dp_pattern_write()
1901 return -EINVAL; in zynqmp_dp_pattern_write()
1903 mutex_lock(&dp->lock); in zynqmp_dp_pattern_write()
1904 dp->test.pattern = pattern; in zynqmp_dp_pattern_write()
1905 if (dp->test.active) in zynqmp_dp_pattern_write()
1906 ret = zynqmp_dp_set_test_pattern(dp, dp->test.pattern, in zynqmp_dp_pattern_write()
1907 dp->test.custom) ?: ret; in zynqmp_dp_pattern_write()
1908 mutex_unlock(&dp->lock); in zynqmp_dp_pattern_write()
1924 guard(mutex)(&dp->lock); in zynqmp_dp_enhanced_get()
1925 *val = dp->test.enhanced; in zynqmp_dp_enhanced_get()
1933 guard(mutex)(&dp->lock); in zynqmp_dp_enhanced_set()
1934 dp->test.enhanced = val; in zynqmp_dp_enhanced_set()
1935 return dp->test.active ? zynqmp_dp_test_setup(dp) : 0; in zynqmp_dp_enhanced_set()
1945 guard(mutex)(&dp->lock); in zynqmp_dp_downspread_get()
1946 *val = dp->test.downspread; in zynqmp_dp_downspread_get()
1954 guard(mutex)(&dp->lock); in zynqmp_dp_downspread_set()
1955 dp->test.downspread = val; in zynqmp_dp_downspread_set()
1957 return dp->test.active ? zynqmp_dp_test_setup(dp) : 0; in zynqmp_dp_downspread_set()
1967 guard(mutex)(&dp->lock); in zynqmp_dp_active_get()
1968 *val = dp->test.active; in zynqmp_dp_active_get()
1977 guard(mutex)(&dp->lock); in zynqmp_dp_active_set()
1985 ret = zynqmp_dp_set_test_pattern(dp, dp->test.pattern, in zynqmp_dp_active_set()
1986 dp->test.custom); in zynqmp_dp_active_set()
1990 ret = zynqmp_dp_update_vs_emph(dp, dp->test.train_set); in zynqmp_dp_active_set()
1994 dp->test.active = true; in zynqmp_dp_active_set()
1998 dp->test.active = false; in zynqmp_dp_active_set()
2001 dev_warn(dp->dev, "could not clear test pattern: %d\n", in zynqmp_dp_active_set()
2015 struct zynqmp_dp *dp = file->private_data; in zynqmp_dp_custom_read()
2018 mutex_lock(&dp->lock); in zynqmp_dp_custom_read()
2019 ret = simple_read_from_buffer(user_buf, count, ppos, &dp->test.custom, in zynqmp_dp_custom_read()
2020 sizeof(dp->test.custom)); in zynqmp_dp_custom_read()
2021 mutex_unlock(&dp->lock); in zynqmp_dp_custom_read()
2029 struct zynqmp_dp *dp = file->private_data; in zynqmp_dp_custom_write()
2031 char buf[sizeof(dp->test.custom)]; in zynqmp_dp_custom_write()
2037 mutex_lock(&dp->lock); in zynqmp_dp_custom_write()
2038 memcpy(dp->test.custom, buf, ret); in zynqmp_dp_custom_write()
2039 if (dp->test.active) in zynqmp_dp_custom_write()
2040 ret = zynqmp_dp_set_test_pattern(dp, dp->test.pattern, in zynqmp_dp_custom_write()
2041 dp->test.custom) ?: ret; in zynqmp_dp_custom_write()
2042 mutex_unlock(&dp->lock); in zynqmp_dp_custom_write()
2056 struct zynqmp_dp *dp = priv->dp; in zynqmp_dp_swing_get()
2058 guard(mutex)(&dp->lock); in zynqmp_dp_swing_get()
2059 *val = dp->test.train_set[priv->lane] & DP_TRAIN_VOLTAGE_SWING_MASK; in zynqmp_dp_swing_get()
2066 struct zynqmp_dp *dp = priv->dp; in zynqmp_dp_swing_set()
2067 u8 *train_set = &dp->test.train_set[priv->lane]; in zynqmp_dp_swing_set()
2070 return -EINVAL; in zynqmp_dp_swing_set()
2072 guard(mutex)(&dp->lock); in zynqmp_dp_swing_set()
2079 if (dp->test.active) in zynqmp_dp_swing_set()
2080 return zynqmp_dp_update_vs_emph(dp, dp->test.train_set); in zynqmp_dp_swing_set()
2091 struct zynqmp_dp *dp = priv->dp; in zynqmp_dp_preemphasis_get()
2093 guard(mutex)(&dp->lock); in zynqmp_dp_preemphasis_get()
2095 dp->test.train_set[priv->lane]); in zynqmp_dp_preemphasis_get()
2102 struct zynqmp_dp *dp = priv->dp; in zynqmp_dp_preemphasis_set()
2103 u8 *train_set = &dp->test.train_set[priv->lane]; in zynqmp_dp_preemphasis_set()
2106 return -EINVAL; in zynqmp_dp_preemphasis_set()
2108 guard(mutex)(&dp->lock); in zynqmp_dp_preemphasis_set()
2115 if (dp->test.active) in zynqmp_dp_preemphasis_set()
2116 return zynqmp_dp_update_vs_emph(dp, dp->test.train_set); in zynqmp_dp_preemphasis_set()
2128 guard(mutex)(&dp->lock); in zynqmp_dp_lanes_get()
2129 *val = dp->test.link_cnt; in zynqmp_dp_lanes_get()
2138 return -EINVAL; in zynqmp_dp_lanes_set()
2140 guard(mutex)(&dp->lock); in zynqmp_dp_lanes_set()
2141 if (val > dp->num_lanes) in zynqmp_dp_lanes_set()
2142 return -EINVAL; in zynqmp_dp_lanes_set()
2144 dp->test.link_cnt = val; in zynqmp_dp_lanes_set()
2145 return dp->test.active ? zynqmp_dp_test_setup(dp) : 0; in zynqmp_dp_lanes_set()
2155 guard(mutex)(&dp->lock); in zynqmp_dp_rate_get()
2156 *val = drm_dp_bw_code_to_link_rate(dp->test.bw_code) * 10000ULL; in zynqmp_dp_rate_get()
2167 return -EINVAL; in zynqmp_dp_rate_set()
2172 return -EINVAL; in zynqmp_dp_rate_set()
2176 return -EINVAL; in zynqmp_dp_rate_set()
2178 guard(mutex)(&dp->lock); in zynqmp_dp_rate_set()
2179 dp->test.bw_code = bw_code; in zynqmp_dp_rate_set()
2180 return dp->test.active ? zynqmp_dp_test_setup(dp) : 0; in zynqmp_dp_rate_set()
2190 guard(mutex)(&dp->lock); in zynqmp_dp_ignore_aux_errors_get()
2191 *val = dp->ignore_aux_errors; in zynqmp_dp_ignore_aux_errors_get()
2200 return -EINVAL; in zynqmp_dp_ignore_aux_errors_set()
2202 guard(mutex)(&dp->lock); in zynqmp_dp_ignore_aux_errors_set()
2203 dp->ignore_aux_errors = val; in zynqmp_dp_ignore_aux_errors_set()
2215 guard(mutex)(&dp->lock); in zynqmp_dp_ignore_hpd_get()
2216 *val = dp->ignore_hpd; in zynqmp_dp_ignore_hpd_get()
2225 return -EINVAL; in zynqmp_dp_ignore_hpd_set()
2227 guard(mutex)(&dp->lock); in zynqmp_dp_ignore_hpd_set()
2228 dp->ignore_hpd = val; in zynqmp_dp_ignore_hpd_set()
2242 dp->test.bw_code = DP_LINK_BW_5_4; in zynqmp_dp_bridge_debugfs_init()
2243 dp->test.link_cnt = dp->num_lanes; in zynqmp_dp_bridge_debugfs_init()
2258 for (i = 0; i < dp->num_lanes; i++) { in zynqmp_dp_bridge_debugfs_init()
2262 dp->debugfs_train_set[i].dp = dp; in zynqmp_dp_bridge_debugfs_init()
2263 dp->debugfs_train_set[i].lane = i; in zynqmp_dp_bridge_debugfs_init()
2267 &dp->debugfs_train_set[i], in zynqmp_dp_bridge_debugfs_init()
2272 &dp->debugfs_train_set[i], in zynqmp_dp_bridge_debugfs_init()
2293 /* -----------------------------------------------------------------------------
2298 * zynqmp_dp_enable_vblank - Enable vblank
2309 * zynqmp_dp_disable_vblank - Disable vblank
2324 scoped_guard(mutex, &dp->lock) { in zynqmp_dp_hpd_work_func()
2325 if (dp->ignore_hpd) in zynqmp_dp_hpd_work_func()
2331 drm_bridge_hpd_notify(&dp->bridge, status); in zynqmp_dp_hpd_work_func()
2341 guard(mutex)(&dp->lock); in zynqmp_dp_hpd_irq_work_func()
2342 if (dp->ignore_hpd) in zynqmp_dp_hpd_irq_work_func()
2345 err = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, status, in zynqmp_dp_hpd_irq_work_func()
2348 dev_dbg_ratelimited(dp->dev, in zynqmp_dp_hpd_irq_work_func()
2352 !drm_dp_clock_recovery_ok(&status[2], dp->mode.lane_cnt) || in zynqmp_dp_hpd_irq_work_func()
2353 !drm_dp_channel_eq_ok(&status[2], dp->mode.lane_cnt)) { in zynqmp_dp_hpd_irq_work_func()
2380 dev_dbg_ratelimited(dp->dev, "underflow interrupt\n"); in zynqmp_dp_irq_handler()
2382 dev_dbg_ratelimited(dp->dev, "overflow interrupt\n"); in zynqmp_dp_irq_handler()
2385 zynqmp_dpsub_drm_handle_vblank(dp->dpsub); in zynqmp_dp_irq_handler()
2388 schedule_work(&dp->hpd_work); in zynqmp_dp_irq_handler()
2391 schedule_work(&dp->hpd_irq_work); in zynqmp_dp_irq_handler()
2394 complete(&dp->aux_done); in zynqmp_dp_irq_handler()
2397 complete(&dp->aux_done); in zynqmp_dp_irq_handler()
2402 /* -----------------------------------------------------------------------------
2408 struct platform_device *pdev = to_platform_device(dpsub->dev); in zynqmp_dp_probe()
2413 dp = devm_drm_bridge_alloc(&pdev->dev, struct zynqmp_dp, bridge, &zynqmp_dp_bridge_funcs); in zynqmp_dp_probe()
2417 dp->dev = &pdev->dev; in zynqmp_dp_probe()
2418 dp->dpsub = dpsub; in zynqmp_dp_probe()
2419 dp->status = connector_status_disconnected; in zynqmp_dp_probe()
2420 mutex_init(&dp->lock); in zynqmp_dp_probe()
2421 init_completion(&dp->aux_done); in zynqmp_dp_probe()
2423 INIT_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func); in zynqmp_dp_probe()
2424 INIT_WORK(&dp->hpd_irq_work, zynqmp_dp_hpd_irq_work_func); in zynqmp_dp_probe()
2427 dp->iomem = devm_platform_ioremap_resource_byname(pdev, "dp"); in zynqmp_dp_probe()
2428 if (IS_ERR(dp->iomem)) in zynqmp_dp_probe()
2429 return PTR_ERR(dp->iomem); in zynqmp_dp_probe()
2431 dp->irq = platform_get_irq(pdev, 0); in zynqmp_dp_probe()
2432 if (dp->irq < 0) in zynqmp_dp_probe()
2433 return dp->irq; in zynqmp_dp_probe()
2435 dp->reset = devm_reset_control_get(dp->dev, NULL); in zynqmp_dp_probe()
2436 if (IS_ERR(dp->reset)) in zynqmp_dp_probe()
2437 return dev_err_probe(dp->dev, PTR_ERR(dp->reset), in zynqmp_dp_probe()
2438 "failed to get reset\n"); in zynqmp_dp_probe()
2453 bridge = &dp->bridge; in zynqmp_dp_probe()
2454 bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID in zynqmp_dp_probe()
2456 bridge->type = DRM_MODE_CONNECTOR_DisplayPort; in zynqmp_dp_probe()
2457 bridge->of_node = dp->dev->of_node; in zynqmp_dp_probe()
2458 dpsub->bridge = bridge; in zynqmp_dp_probe()
2462 * not being connected for backward-compatibility with older DTs. in zynqmp_dp_probe()
2464 ret = drm_of_find_panel_or_bridge(dp->dev->of_node, 5, 0, NULL, in zynqmp_dp_probe()
2465 &dp->next_bridge); in zynqmp_dp_probe()
2466 if (ret < 0 && ret != -ENODEV) in zynqmp_dp_probe()
2470 dp->config.misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK; in zynqmp_dp_probe()
2490 ret = devm_request_irq(dp->dev, dp->irq, zynqmp_dp_irq_handler, in zynqmp_dp_probe()
2491 IRQF_SHARED, dev_name(dp->dev), dp); in zynqmp_dp_probe()
2495 dpsub->dp = dp; in zynqmp_dp_probe()
2497 dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n", in zynqmp_dp_probe()
2498 dp->num_lanes); in zynqmp_dp_probe()
2511 struct zynqmp_dp *dp = dpsub->dp; in zynqmp_dp_remove()
2514 devm_free_irq(dp->dev, dp->irq, dp); in zynqmp_dp_remove()
2516 cancel_work_sync(&dp->hpd_irq_work); in zynqmp_dp_remove()
2517 cancel_work_sync(&dp->hpd_work); in zynqmp_dp_remove()
2524 mutex_destroy(&dp->lock); in zynqmp_dp_remove()