Commit 1682ade6 authored by Laurent Pinchart's avatar Laurent Pinchart

drm: xlnx: zynqmp_dpsub: Move pclk from zynqmp_disp to zynqmp_dpsub

The video clock is an external resource from the DPSUB point of view,
not a resource internal to the display controller. Move it to the
zynqmp_dpsub structure, to allow accessing it from outside the disp
code.

While at it, rename the fields from pclk and pclk_from_ps to vid_clk and
vid_clk_from_ps, to better reflect their purpose and match the
documentation.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
parent 96e0e3e3
...@@ -169,8 +169,6 @@ struct zynqmp_disp_layer { ...@@ -169,8 +169,6 @@ struct zynqmp_disp_layer {
* @audio.clk: Audio clock * @audio.clk: Audio clock
* @audio.clk_from_ps: True of the audio clock comes from PS, false from PL * @audio.clk_from_ps: True of the audio clock comes from PS, false from PL
* @layers: Layers (planes) * @layers: Layers (planes)
* @pclk: Pixel clock
* @pclk_from_ps: True of the video clock comes from PS, false from PL
*/ */
struct zynqmp_disp { struct zynqmp_disp {
struct device *dev; struct device *dev;
...@@ -192,9 +190,6 @@ struct zynqmp_disp { ...@@ -192,9 +190,6 @@ struct zynqmp_disp {
} audio; } audio;
struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS]; struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
struct clk *pclk;
bool pclk_from_ps;
}; };
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
...@@ -1412,7 +1407,7 @@ static void zynqmp_disp_enable(struct zynqmp_disp *disp) ...@@ -1412,7 +1407,7 @@ static void zynqmp_disp_enable(struct zynqmp_disp *disp)
zynqmp_disp_avbuf_enable(disp); zynqmp_disp_avbuf_enable(disp);
/* Choose clock source based on the DT clock handle. */ /* Choose clock source based on the DT clock handle. */
zynqmp_disp_avbuf_set_clocks_sources(disp, disp->pclk_from_ps, zynqmp_disp_avbuf_set_clocks_sources(disp, disp->dpsub->vid_clk_from_ps,
disp->audio.clk_from_ps, true); disp->audio.clk_from_ps, true);
zynqmp_disp_avbuf_enable_channels(disp); zynqmp_disp_avbuf_enable_channels(disp);
zynqmp_disp_avbuf_enable_audio(disp); zynqmp_disp_avbuf_enable_audio(disp);
...@@ -1440,13 +1435,13 @@ static int zynqmp_disp_setup_clock(struct zynqmp_disp *disp, ...@@ -1440,13 +1435,13 @@ static int zynqmp_disp_setup_clock(struct zynqmp_disp *disp,
long diff; long diff;
int ret; int ret;
ret = clk_set_rate(disp->pclk, mode_clock); ret = clk_set_rate(disp->dpsub->vid_clk, mode_clock);
if (ret) { if (ret) {
dev_err(disp->dev, "failed to set a pixel clock\n"); dev_err(disp->dev, "failed to set the video clock\n");
return ret; return ret;
} }
rate = clk_get_rate(disp->pclk); rate = clk_get_rate(disp->dpsub->vid_clk);
diff = rate - mode_clock; diff = rate - mode_clock;
if (abs(diff) > mode_clock / 20) if (abs(diff) > mode_clock / 20)
dev_info(disp->dev, dev_info(disp->dev,
...@@ -1477,9 +1472,9 @@ zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc, ...@@ -1477,9 +1472,9 @@ zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
zynqmp_disp_setup_clock(disp, adjusted_mode->clock * 1000); zynqmp_disp_setup_clock(disp, adjusted_mode->clock * 1000);
ret = clk_prepare_enable(disp->pclk); ret = clk_prepare_enable(disp->dpsub->vid_clk);
if (ret) { if (ret) {
dev_err(disp->dev, "failed to enable a pixel clock\n"); dev_err(disp->dev, "failed to enable the video clock\n");
pm_runtime_put_sync(disp->dev); pm_runtime_put_sync(disp->dev);
return; return;
} }
...@@ -1519,7 +1514,7 @@ zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc, ...@@ -1519,7 +1514,7 @@ zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc,
} }
spin_unlock_irq(&crtc->dev->event_lock); spin_unlock_irq(&crtc->dev->event_lock);
clk_disable_unprepare(disp->pclk); clk_disable_unprepare(disp->dpsub->vid_clk);
pm_runtime_put_sync(disp->dev); pm_runtime_put_sync(disp->dev);
} }
...@@ -1674,23 +1669,6 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm) ...@@ -1674,23 +1669,6 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
if (IS_ERR(disp->audio.base)) if (IS_ERR(disp->audio.base))
return PTR_ERR(disp->audio.base); return PTR_ERR(disp->audio.base);
/* Try the live PL video clock */
disp->pclk = devm_clk_get(disp->dev, "dp_live_video_in_clk");
if (!IS_ERR(disp->pclk))
disp->pclk_from_ps = false;
else if (PTR_ERR(disp->pclk) == -EPROBE_DEFER)
return PTR_ERR(disp->pclk);
/* If the live PL video clock is not valid, fall back to PS clock */
if (IS_ERR_OR_NULL(disp->pclk)) {
disp->pclk = devm_clk_get(disp->dev, "dp_vtc_pixel_clk_in");
if (IS_ERR(disp->pclk)) {
dev_err(disp->dev, "failed to init any video clock\n");
return PTR_ERR(disp->pclk);
}
disp->pclk_from_ps = true;
}
zynqmp_disp_audio_init(disp); zynqmp_disp_audio_init(disp);
ret = zynqmp_disp_create_layers(disp); ret = zynqmp_disp_create_layers(disp);
......
...@@ -214,6 +214,23 @@ static int zynqmp_dpsub_init_clocks(struct zynqmp_dpsub *dpsub) ...@@ -214,6 +214,23 @@ static int zynqmp_dpsub_init_clocks(struct zynqmp_dpsub *dpsub)
return ret; return ret;
} }
/* Try the live PL video clock */
dpsub->vid_clk = devm_clk_get(dpsub->dev, "dp_live_video_in_clk");
if (!IS_ERR(dpsub->vid_clk))
dpsub->vid_clk_from_ps = false;
else if (PTR_ERR(dpsub->vid_clk) == -EPROBE_DEFER)
return PTR_ERR(dpsub->vid_clk);
/* If the live PL video clock is not valid, fall back to PS clock */
if (IS_ERR_OR_NULL(dpsub->vid_clk)) {
dpsub->vid_clk = devm_clk_get(dpsub->dev, "dp_vtc_pixel_clk_in");
if (IS_ERR(dpsub->vid_clk)) {
dev_err(dpsub->dev, "failed to init any video clock\n");
return PTR_ERR(dpsub->vid_clk);
}
dpsub->vid_clk_from_ps = true;
}
return 0; return 0;
} }
......
...@@ -33,6 +33,8 @@ enum zynqmp_dpsub_format { ...@@ -33,6 +33,8 @@ enum zynqmp_dpsub_format {
* @drm: The DRM/KMS device * @drm: The DRM/KMS device
* @dev: The physical device * @dev: The physical device
* @apb_clk: The APB clock * @apb_clk: The APB clock
* @vid_clk: Video clock
* @vid_clk_from_ps: True of the video clock comes from PS, false from PL
* @encoder: The dummy DRM encoder * @encoder: The dummy DRM encoder
* @bridge: The DP encoder bridge * @bridge: The DP encoder bridge
* @disp: The display controller * @disp: The display controller
...@@ -44,6 +46,8 @@ struct zynqmp_dpsub { ...@@ -44,6 +46,8 @@ struct zynqmp_dpsub {
struct device *dev; struct device *dev;
struct clk *apb_clk; struct clk *apb_clk;
struct clk *vid_clk;
bool vid_clk_from_ps;
struct drm_encoder encoder; struct drm_encoder encoder;
struct drm_bridge *bridge; struct drm_bridge *bridge;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment