drm: xlnx: zynqmp_dpsub: Move audio clk from zynqmp_disp to zynqmp_dpsub
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 6 Aug 2021 11:29:52 +0000 (14:29 +0300)
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Wed, 19 Oct 2022 13:51:04 +0000 (16:51 +0300)
The audio 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.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
drivers/gpu/drm/xlnx/zynqmp_disp.c
drivers/gpu/drm/xlnx/zynqmp_disp.h
drivers/gpu/drm/xlnx/zynqmp_dp.c
drivers/gpu/drm/xlnx/zynqmp_dpsub.c
drivers/gpu/drm/xlnx/zynqmp_dpsub.h

index d030665..a6e7ccf 100644 (file)
@@ -166,8 +166,6 @@ struct zynqmp_disp_layer {
  * @blend.base: Register I/O base address for the blender
  * @avbuf.base: Register I/O base address for the audio/video buffer manager
  * @audio.base: Registers I/O base address for the audio mixer
- * @audio.clk: Audio clock
- * @audio.clk_from_ps: True of the audio clock comes from PS, false from PL
  * @layers: Layers (planes)
  */
 struct zynqmp_disp {
@@ -185,8 +183,6 @@ struct zynqmp_disp {
        } avbuf;
        struct {
                void __iomem *base;
-               struct clk *clk;
-               bool clk_from_ps;
        } audio;
 
        struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
@@ -892,25 +888,6 @@ static void zynqmp_disp_audio_disable(struct zynqmp_disp *disp)
                                ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
 }
 
-static void zynqmp_disp_audio_init(struct zynqmp_disp *disp)
-{
-       /* Try the live PL audio clock. */
-       disp->audio.clk = devm_clk_get(disp->dev, "dp_live_audio_aclk");
-       if (!IS_ERR(disp->audio.clk)) {
-               disp->audio.clk_from_ps = false;
-               return;
-       }
-
-       /* If the live PL audio clock is not valid, fall back to PS clock. */
-       disp->audio.clk = devm_clk_get(disp->dev, "dp_aud_clk");
-       if (!IS_ERR(disp->audio.clk)) {
-               disp->audio.clk_from_ps = true;
-               return;
-       }
-
-       dev_err(disp->dev, "audio disabled due to missing clock\n");
-}
-
 /* -----------------------------------------------------------------------------
  * ZynqMP Display external functions for zynqmp_dp
  */
@@ -930,32 +907,6 @@ void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp)
 }
 
 /**
- * zynqmp_disp_audio_enabled - If the audio is enabled
- * @disp: Display controller
- *
- * Return if the audio is enabled depending on the audio clock.
- *
- * Return: true if audio is enabled, or false.
- */
-bool zynqmp_disp_audio_enabled(struct zynqmp_disp *disp)
-{
-       return !!disp->audio.clk;
-}
-
-/**
- * zynqmp_disp_get_audio_clk_rate - Get the current audio clock rate
- * @disp: Display controller
- *
- * Return: the current audio clock rate.
- */
-unsigned int zynqmp_disp_get_audio_clk_rate(struct zynqmp_disp *disp)
-{
-       if (zynqmp_disp_audio_enabled(disp))
-               return 0;
-       return clk_get_rate(disp->audio.clk);
-}
-
-/**
  * zynqmp_disp_get_crtc_mask - Return the CRTC bit mask
  * @disp: Display controller
  *
@@ -1408,7 +1359,8 @@ static void zynqmp_disp_enable(struct zynqmp_disp *disp)
        zynqmp_disp_avbuf_enable(disp);
        /* Choose clock source based on the DT clock handle. */
        zynqmp_disp_avbuf_set_clocks_sources(disp, disp->dpsub->vid_clk_from_ps,
-                                            disp->audio.clk_from_ps, true);
+                                            disp->dpsub->aud_clk_from_ps,
+                                            true);
        zynqmp_disp_avbuf_enable_channels(disp);
        zynqmp_disp_avbuf_enable_audio(disp);
 
@@ -1669,8 +1621,6 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
        if (IS_ERR(disp->audio.base))
                return PTR_ERR(disp->audio.base);
 
-       zynqmp_disp_audio_init(disp);
-
        ret = zynqmp_disp_create_layers(disp);
        if (ret)
                return ret;
index f402901..1b7f90a 100644 (file)
@@ -31,8 +31,6 @@ struct zynqmp_disp;
 struct zynqmp_dpsub;
 
 void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp);
-bool zynqmp_disp_audio_enabled(struct zynqmp_disp *disp);
-unsigned int zynqmp_disp_get_audio_clk_rate(struct zynqmp_disp *disp);
 uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp);
 
 int zynqmp_disp_drm_init(struct zynqmp_dpsub *dpsub);
index 33fd69e..3e4d164 100644 (file)
@@ -1252,7 +1252,7 @@ static void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
                reg = drm_dp_bw_code_to_link_rate(dp->mode.bw_code);
                zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_N_VID, reg);
                zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_M_VID, mode->clock);
-               rate = zynqmp_disp_get_audio_clk_rate(dp->dpsub->disp);
+               rate = zynqmp_dpsub_get_audio_clk_rate(dp->dpsub);
                if (rate) {
                        dev_dbg(dp->dev, "Audio rate: %d\n", rate / 512);
                        zynqmp_dp_write(dp, ZYNQMP_DP_TX_N_AUD, reg);
@@ -1261,7 +1261,7 @@ static void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
        }
 
        /* Only 2 channel audio is supported now */
-       if (zynqmp_disp_audio_enabled(dp->dpsub->disp))
+       if (zynqmp_dpsub_audio_enabled(dp->dpsub))
                zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CHANNELS, 1);
 
        zynqmp_dp_write(dp, ZYNQMP_DP_USER_PIX_WIDTH, 1);
@@ -1372,7 +1372,7 @@ static void zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge,
        /* Enable the encoder */
        dp->enabled = true;
        zynqmp_dp_update_misc(dp);
-       if (zynqmp_disp_audio_enabled(dp->dpsub->disp))
+       if (zynqmp_dpsub_audio_enabled(dp->dpsub))
                zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 1);
        zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN, 0);
        if (dp->status == connector_status_connected) {
@@ -1406,7 +1406,7 @@ static void zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge,
        drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
        zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN,
                        ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL);
-       if (zynqmp_disp_audio_enabled(dp->dpsub->disp))
+       if (zynqmp_dpsub_audio_enabled(dp->dpsub))
                zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 0);
        pm_runtime_put_sync(dp->dev);
 }
index 7d6c30a..6d60efb 100644 (file)
@@ -197,6 +197,36 @@ static const struct dev_pm_ops zynqmp_dpsub_pm_ops = {
 };
 
 /* -----------------------------------------------------------------------------
+ * DPSUB Configuration
+ */
+
+/**
+ * zynqmp_dpsub_audio_enabled - If the audio is enabled
+ * @dpsub: DisplayPort subsystem
+ *
+ * Return if the audio is enabled depending on the audio clock.
+ *
+ * Return: true if audio is enabled, or false.
+ */
+bool zynqmp_dpsub_audio_enabled(struct zynqmp_dpsub *dpsub)
+{
+       return !!dpsub->aud_clk;
+}
+
+/**
+ * zynqmp_dpsub_get_audio_clk_rate - Get the current audio clock rate
+ * @dpsub: DisplayPort subsystem
+ *
+ * Return: the current audio clock rate.
+ */
+unsigned int zynqmp_dpsub_get_audio_clk_rate(struct zynqmp_dpsub *dpsub)
+{
+       if (zynqmp_dpsub_audio_enabled(dpsub))
+               return 0;
+       return clk_get_rate(dpsub->aud_clk);
+}
+
+/* -----------------------------------------------------------------------------
  * Probe & Remove
  */
 
@@ -214,14 +244,16 @@ static int zynqmp_dpsub_init_clocks(struct zynqmp_dpsub *dpsub)
                return ret;
        }
 
-       /* Try the live PL video clock */
+       /*
+        * Try the live PL video clock, and fall back to the PS clock if the
+        * live PL video clock isn't valid.
+        */
        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)) {
@@ -231,6 +263,24 @@ static int zynqmp_dpsub_init_clocks(struct zynqmp_dpsub *dpsub)
                dpsub->vid_clk_from_ps = true;
        }
 
+       /*
+        * Try the live PL audio clock, and fall back to the PS clock if the
+        * live PL audio clock isn't valid. Missing audio clock disables audio
+        * but isn't an error.
+        */
+       dpsub->aud_clk = devm_clk_get(dpsub->dev, "dp_live_audio_aclk");
+       if (!IS_ERR(dpsub->aud_clk)) {
+               dpsub->aud_clk_from_ps = false;
+               return 0;
+       }
+
+       dpsub->aud_clk = devm_clk_get(dpsub->dev, "dp_aud_clk");
+       if (!IS_ERR(dpsub->aud_clk)) {
+               dpsub->aud_clk_from_ps = true;
+               return 0;
+       }
+
+       dev_info(dpsub->dev, "audio disabled due to missing clock\n");
        return 0;
 }
 
index bcb119b..5bd42e1 100644 (file)
@@ -35,6 +35,8 @@ enum zynqmp_dpsub_format {
  * @apb_clk: The APB clock
  * @vid_clk: Video clock
  * @vid_clk_from_ps: True of the video clock comes from PS, false from PL
+ * @aud_clk: Audio clock
+ * @aud_clk_from_ps: True of the audio clock comes from PS, false from PL
  * @encoder: The dummy DRM encoder
  * @bridge: The DP encoder bridge
  * @disp: The display controller
@@ -48,6 +50,8 @@ struct zynqmp_dpsub {
        struct clk *apb_clk;
        struct clk *vid_clk;
        bool vid_clk_from_ps;
+       struct clk *aud_clk;
+       bool aud_clk_from_ps;
 
        struct drm_encoder encoder;
        struct drm_bridge *bridge;
@@ -63,4 +67,7 @@ static inline struct zynqmp_dpsub *to_zynqmp_dpsub(struct drm_device *drm)
        return container_of(drm, struct zynqmp_dpsub, drm);
 }
 
+bool zynqmp_dpsub_audio_enabled(struct zynqmp_dpsub *dpsub);
+unsigned int zynqmp_dpsub_get_audio_clk_rate(struct zynqmp_dpsub *dpsub);
+
 #endif /* _ZYNQMP_DPSUB_H_ */