]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drm/bridge: dw-hdmi: set channel count in the infoframes
[linux.git] / drivers / gpu / drm / bridge / synopsys / dw-hdmi.c
index c6490949d9db33ba88c027987fecdd0b774163a6..4e57b984b244074c9c322639444d69899acc6a4e 100644 (file)
@@ -508,8 +508,14 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
        /* nshift factor = 0 */
        hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
 
-       hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
-                   HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+       /* Use automatic CTS generation mode when CTS is not set */
+       if (cts)
+               hdmi_writeb(hdmi, ((cts >> 16) &
+                                  HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
+                                 HDMI_AUD_CTS3_CTS_MANUAL,
+                           HDMI_AUD_CTS3);
+       else
+               hdmi_writeb(hdmi, 0, HDMI_AUD_CTS3);
        hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
        hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
 
@@ -579,24 +585,33 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
 {
        unsigned long ftdms = pixel_clk;
        unsigned int n, cts;
+       u8 config3;
        u64 tmp;
 
        n = hdmi_compute_n(sample_rate, pixel_clk);
 
-       /*
-        * Compute the CTS value from the N value.  Note that CTS and N
-        * can be up to 20 bits in total, so we need 64-bit math.  Also
-        * note that our TDMS clock is not fully accurate; it is accurate
-        * to kHz.  This can introduce an unnecessary remainder in the
-        * calculation below, so we don't try to warn about that.
-        */
-       tmp = (u64)ftdms * n;
-       do_div(tmp, 128 * sample_rate);
-       cts = tmp;
+       config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
 
-       dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
-               __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000,
-               n, cts);
+       /* Only compute CTS when using internal AHB audio */
+       if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
+               /*
+                * Compute the CTS value from the N value.  Note that CTS and N
+                * can be up to 20 bits in total, so we need 64-bit math.  Also
+                * note that our TDMS clock is not fully accurate; it is
+                * accurate to kHz.  This can introduce an unnecessary remainder
+                * in the calculation below, so we don't try to warn about that.
+                */
+               tmp = (u64)ftdms * n;
+               do_div(tmp, 128 * sample_rate);
+               cts = tmp;
+
+               dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
+                       __func__, sample_rate,
+                       ftdms / 1000000, (ftdms / 1000) % 1000,
+                       n, cts);
+       } else {
+               cts = 0;
+       }
 
        spin_lock_irq(&hdmi->audio_lock);
        hdmi->audio_n = n;
@@ -630,6 +645,42 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
 
+void dw_hdmi_set_channel_count(struct dw_hdmi *hdmi, unsigned int cnt)
+{
+       u8 layout;
+
+       mutex_lock(&hdmi->audio_mutex);
+
+       /*
+        * For >2 channel PCM audio, we need to select layout 1
+        * and set an appropriate channel map.
+        */
+       if (cnt > 2)
+               layout = HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1;
+       else
+               layout = HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0;
+
+       hdmi_modb(hdmi, layout, HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK,
+                 HDMI_FC_AUDSCONF);
+
+       /* Set the audio infoframes channel count */
+       hdmi_modb(hdmi, (cnt - 1) << HDMI_FC_AUDICONF0_CC_OFFSET,
+                 HDMI_FC_AUDICONF0_CC_MASK, HDMI_FC_AUDICONF0);
+
+       mutex_unlock(&hdmi->audio_mutex);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_channel_count);
+
+void dw_hdmi_set_channel_allocation(struct dw_hdmi *hdmi, unsigned int ca)
+{
+       mutex_lock(&hdmi->audio_mutex);
+
+       hdmi_writeb(hdmi, ca, HDMI_FC_AUDICONF2);
+
+       mutex_unlock(&hdmi->audio_mutex);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_channel_allocation);
+
 static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable)
 {
        if (enable)
@@ -2185,8 +2236,10 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
 
        drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);
 
-       drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
-                          DRM_MODE_CONNECTOR_HDMIA);
+       drm_connector_init_with_ddc(bridge->dev, connector,
+                                   &dw_hdmi_connector_funcs,
+                                   DRM_MODE_CONNECTOR_HDMIA,
+                                   hdmi->ddc);
 
        drm_connector_attach_encoder(connector, encoder);