Skip to content

Commit 542c6e5

Browse files
Venkateshwar Rao GannavarapuMichal Simek
authored andcommitted
drm: xlnx: hdmi: Add FRL mode support in mode set
This patch adds the FRL mode support in atomic mode set functionality. Signed-off-by: Venkateshwar Rao Gannavarapu <venkateshwar.rao.gannavarapu@xilinx.com>
1 parent 749a3a6 commit 542c6e5

File tree

1 file changed

+81
-33
lines changed

1 file changed

+81
-33
lines changed

drivers/gpu/drm/xlnx/xlnx_hdmi.c

Lines changed: 81 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,8 +2453,8 @@ xlnx_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
24532453
struct drm_display_mode *mode = &crtc_state->mode;
24542454
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
24552455
union phy_configure_opts phy_cfg = {0};
2456-
int ret;
2457-
u32 drm_fourcc;
2456+
int ret, i;
2457+
u32 drm_fourcc, lnk_clk, vid_clk;
24582458

24592459
dev_dbg(hdmi->dev, "mode->clock = %d\n", mode->clock * 1000);
24602460
dev_dbg(hdmi->dev, "mode->crtc_clock = %d\n", mode->crtc_clock * 1000);
@@ -2474,6 +2474,15 @@ xlnx_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
24742474
dev_dbg(hdmi->dev, "mode->flags = %d interlace = %d\n", mode->flags,
24752475
!!(mode->flags & DRM_MODE_FLAG_INTERLACE));
24762476

2477+
if (hdmi->stream.is_frl) {
2478+
xlnx_hdmi_frl_reset_deassert(hdmi);
2479+
xlnx_hdmi_frl_intr_enable(hdmi);
2480+
xlnx_hdmi_frl_execute(hdmi);
2481+
} else {
2482+
xlnx_hdmi_frl_ext_vidsrc(hdmi);
2483+
xlnx_hdmi_frl_sleep(hdmi);
2484+
}
2485+
24772486
drm_fourcc = encoder->crtc->primary->state->fb->format->format;
24782487
hdmi->xvidc_colorfmt = xlnx_hdmi_find_media_bus(hdmi, drm_fourcc);
24792488
dev_dbg(hdmi->dev, "xvidc_colorfmt = %d\n", hdmi->xvidc_colorfmt);
@@ -2482,34 +2491,65 @@ xlnx_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
24822491
hdmi->tmds_clk = adjusted_mode->clock * 1000;
24832492
dev_dbg(hdmi->dev, "tmds_clk = %u\n", hdmi->tmds_clk);
24842493

2485-
phy_cfg.hdmi.clkout1_obuftds = 1;
2486-
phy_cfg.hdmi.clkout1_obuftds_en = false;
2487-
ret = phy_configure(hdmi->phy[0], &phy_cfg);
2488-
if (ret)
2489-
dev_err(hdmi->dev, "phy_cfg:10bufds_en err\n");
2494+
if (hdmi->stream.is_frl) {
2495+
phy_cfg.hdmi.clkout1_obuftds = 1;
2496+
phy_cfg.hdmi.clkout1_obuftds_en = false;
2497+
for (i = 0; i < HDMI_MAX_LANES; i++) {
2498+
ret = phy_configure(hdmi->phy[i], &phy_cfg);
2499+
if (ret) {
2500+
dev_err(hdmi->dev, "phy_cfg:10bufds_en err\n");
2501+
return;
2502+
}
2503+
}
2504+
}
24902505

24912506
xlnx_hdmi_stream_start(hdmi);
2492-
xlnx_hdmi_clkratio(hdmi);
2493-
2494-
/* Assert VID_IN bridge resets */
2495-
xlnx_hdmi_ext_sysrst_assert(hdmi);
2496-
xlnx_hdmi_ext_vrst_assert(hdmi);
2497-
2498-
/* Assert HDMI TXCore resets */
2499-
xlnx_hdmi_int_lrst_assert(hdmi);
2500-
xlnx_hdmi_int_vrst_assert(hdmi);
2501-
25022507
/* get tmds clock from phy */
2503-
phy_cfg.hdmi.tx_params = 1;
2504-
phy_cfg.hdmi.ppc = config->ppc;
2505-
phy_cfg.hdmi.bpc = config->bpc;
2506-
phy_cfg.hdmi.fmt = hdmi->xvidc_colorfmt;
2507-
phy_cfg.hdmi.tx_tmdsclk = hdmi->tmds_clk;
2508-
ret = phy_configure(hdmi->phy[0], &phy_cfg);
2509-
if (ret)
2510-
dev_err(hdmi->dev, "phy_config: set txparams error %d\n", ret);
2508+
if (!hdmi->stream.is_frl) {
2509+
xlnx_hdmi_clkratio(hdmi);
2510+
2511+
/* Assert VID_IN bridge resets */
2512+
xlnx_hdmi_ext_sysrst_assert(hdmi);
2513+
xlnx_hdmi_ext_vrst_assert(hdmi);
2514+
2515+
/* Assert HDMI TXCore resets */
2516+
xlnx_hdmi_int_lrst_assert(hdmi);
2517+
xlnx_hdmi_int_vrst_assert(hdmi);
2518+
2519+
phy_cfg.hdmi.tx_params = 1;
2520+
phy_cfg.hdmi.ppc = config->ppc;
2521+
phy_cfg.hdmi.bpc = config->bpc;
2522+
phy_cfg.hdmi.fmt = hdmi->xvidc_colorfmt;
2523+
phy_cfg.hdmi.tx_tmdsclk = hdmi->tmds_clk;
2524+
for (i = 0; i < HDMI_MAX_LANES; i++) {
2525+
ret = phy_configure(hdmi->phy[i], &phy_cfg);
2526+
if (ret) {
2527+
dev_err(hdmi->dev, "phy_config: set txparams error %d\n", ret);
2528+
return;
2529+
}
2530+
}
2531+
} else {
2532+
lnk_clk = adjusted_mode->clock / config->ppc;
2533+
vid_clk = lnk_clk;
2534+
2535+
xlnx_set_frl_link_clk(hdmi, lnk_clk);
2536+
xlnx_set_frl_vid_clk(hdmi, vid_clk);
2537+
2538+
xlnx_hdmi_aux_enable(hdmi);
2539+
xlnx_hdmi_start_frl_train(hdmi, hdmi->config.max_frl_rate);
2540+
xlnx_hdmi_auxintr_enable(hdmi);
2541+
xlnx_hdmi_set_samplerate(hdmi, 1);
2542+
2543+
/* release vid_in bridge resets */
2544+
xlnx_hdmi_ext_sysrst_deassert(hdmi);
2545+
xlnx_hdmi_ext_vrst_deassert(hdmi);
2546+
/* release tx cor resets */
2547+
xlnx_hdmi_int_lrst_deassert(hdmi);
2548+
xlnx_hdmi_int_vrst_deassert(hdmi);
2549+
xlnx_pioout_bridge_yuv_clr(hdmi);
2550+
xlnx_pioout_bridge_pixel_clr(hdmi);
2551+
}
25112552

2512-
xlnx_hdmi_start_frl_train(hdmi, hdmi->config.max_frl_rate);
25132553
dev_dbg(hdmi->dev, "mode->clock = %u Hz\n", adjusted_mode->clock);
25142554

25152555
hdmi->wait_for_streamup = 0;
@@ -2523,11 +2563,18 @@ xlnx_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
25232563
dev_dbg(hdmi->dev, "TX: Video ready interrupt received\n");
25242564
if (!config->vid_interface)
25252565
xlnx_hdmi_vtc_set_timing(hdmi, adjusted_mode);
2566+
if (hdmi->stream.is_frl)
2567+
xlnx_hdmi_vtc_writel(hdmi, HDMI_TX_VTC_CTL,
2568+
HDMI_TX_VTC_CTL_GE);
25262569
} else {
25272570
dev_dbg(hdmi->dev, "video ready interrupt not received\n");
25282571
}
25292572

2530-
xlnx_hdmi_ext_sysrst_assert(hdmi);
2573+
if (hdmi->stream.is_frl)
2574+
xlnx_hdmi_set_frl_active(hdmi,
2575+
HDMI_TX_FRL_ACTIVE_MODE_FULL_STREAM);
2576+
else
2577+
xlnx_hdmi_ext_sysrst_assert(hdmi);
25312578
}
25322579

25332580
static const struct drm_encoder_funcs xlnx_hdmi_encoder_funcs = {
@@ -2668,7 +2715,7 @@ static void xlnx_hdmi_exit_phy(struct xlnx_hdmi *hdmi)
26682715
static int xlnx_hdmi_initialize(struct xlnx_hdmi *hdmi)
26692716
{
26702717
union phy_configure_opts phy_cfg = {0};
2671-
int ret;
2718+
int ret, i;
26722719
unsigned long val, clkrate;
26732720

26742721
/* mutex that protects against concurrent access */
@@ -2686,7 +2733,6 @@ static int xlnx_hdmi_initialize(struct xlnx_hdmi *hdmi)
26862733
xlnx_hdmi_aux_disable(hdmi);
26872734
xlnx_hdmi_frl_intr_disable(hdmi);
26882735
xlnx_hdmi_frl_clear(hdmi);
2689-
xlnx_hdmi_frl_ext_vidsrc(hdmi);
26902736
xlnx_hdmi_piointr_clear(hdmi);
26912737
xlnx_hdmi_ddc_intr_clear(hdmi);
26922738

@@ -2731,10 +2777,12 @@ static int xlnx_hdmi_initialize(struct xlnx_hdmi *hdmi)
27312777
xlnx_hdmi_reset(hdmi);
27322778

27332779
phy_cfg.hdmi.config_hdmi20 = 1;
2734-
ret = phy_configure(hdmi->phy[0], &phy_cfg);
2735-
if (ret) {
2736-
dev_err(hdmi->dev, "phy_cfg: hdmi20 err\n");
2737-
return ret;
2780+
for (i = 0; i < HDMI_MAX_LANES; i++) {
2781+
ret = phy_configure(hdmi->phy[i], &phy_cfg);
2782+
if (ret) {
2783+
dev_err(hdmi->dev, "phy_cfg: hdmi20 err\n");
2784+
return ret;
2785+
}
27382786
}
27392787

27402788
/* Enable Interrupts */

0 commit comments

Comments
 (0)