|
@@ -788,6 +788,95 @@ static void sti_hdmi_disable(struct drm_bridge *bridge)
|
|
|
hdmi->enabled = false;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * sti_hdmi_audio_get_non_coherent_n() - get N parameter for non-coherent
|
|
|
+ * clocks. None-coherent clocks means that audio and TMDS clocks have not the
|
|
|
+ * same source (drifts between clocks). In this case assumption is that CTS is
|
|
|
+ * automatically calculated by hardware.
|
|
|
+ *
|
|
|
+ * @audio_fs: audio frame clock frequency in Hz
|
|
|
+ *
|
|
|
+ * Values computed are based on table described in HDMI specification 1.4b
|
|
|
+ *
|
|
|
+ * Returns n value.
|
|
|
+ */
|
|
|
+static int sti_hdmi_audio_get_non_coherent_n(unsigned int audio_fs)
|
|
|
+{
|
|
|
+ unsigned int n;
|
|
|
+
|
|
|
+ switch (audio_fs) {
|
|
|
+ case 32000:
|
|
|
+ n = 4096;
|
|
|
+ break;
|
|
|
+ case 44100:
|
|
|
+ n = 6272;
|
|
|
+ break;
|
|
|
+ case 48000:
|
|
|
+ n = 6144;
|
|
|
+ break;
|
|
|
+ case 88200:
|
|
|
+ n = 6272 * 2;
|
|
|
+ break;
|
|
|
+ case 96000:
|
|
|
+ n = 6144 * 2;
|
|
|
+ break;
|
|
|
+ case 176400:
|
|
|
+ n = 6272 * 4;
|
|
|
+ break;
|
|
|
+ case 192000:
|
|
|
+ n = 6144 * 4;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* Not pre-defined, recommended value: 128 * fs / 1000 */
|
|
|
+ n = (audio_fs * 128) / 1000;
|
|
|
+ }
|
|
|
+
|
|
|
+ return n;
|
|
|
+}
|
|
|
+
|
|
|
+static int hdmi_audio_configure(struct sti_hdmi *hdmi)
|
|
|
+{
|
|
|
+ int audio_cfg, n;
|
|
|
+ struct hdmi_audio_params *params = &hdmi->audio;
|
|
|
+ struct hdmi_audio_infoframe *info = ¶ms->cea;
|
|
|
+
|
|
|
+ DRM_DEBUG_DRIVER("\n");
|
|
|
+
|
|
|
+ if (!hdmi->enabled)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* update N parameter */
|
|
|
+ n = sti_hdmi_audio_get_non_coherent_n(params->sample_rate);
|
|
|
+
|
|
|
+ DRM_DEBUG_DRIVER("Audio rate = %d Hz, TMDS clock = %d Hz, n = %d\n",
|
|
|
+ params->sample_rate, hdmi->mode.clock * 1000, n);
|
|
|
+ hdmi_write(hdmi, n, HDMI_AUDN);
|
|
|
+
|
|
|
+ /* update HDMI registers according to configuration */
|
|
|
+ audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID |
|
|
|
+ HDMI_AUD_CFG_ONE_BIT_INVALID;
|
|
|
+
|
|
|
+ switch (info->channels) {
|
|
|
+ case 8:
|
|
|
+ audio_cfg |= HDMI_AUD_CFG_CH78_VALID;
|
|
|
+ case 6:
|
|
|
+ audio_cfg |= HDMI_AUD_CFG_CH56_VALID;
|
|
|
+ case 4:
|
|
|
+ audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH;
|
|
|
+ case 2:
|
|
|
+ audio_cfg |= HDMI_AUD_CFG_CH12_VALID;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ DRM_ERROR("ERROR: Unsupported number of channels (%d)!\n",
|
|
|
+ info->channels);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG);
|
|
|
+
|
|
|
+ return hdmi_audio_infoframe_config(hdmi);
|
|
|
+}
|
|
|
+
|
|
|
static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
|
|
|
{
|
|
|
struct sti_hdmi *hdmi = bridge->driver_private;
|
|
@@ -826,9 +915,12 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
|
|
|
if (hdmi_avi_infoframe_config(hdmi))
|
|
|
DRM_ERROR("Unable to configure AVI infoframe\n");
|
|
|
|
|
|
- /* Program AUDIO infoframe */
|
|
|
- if (hdmi_audio_infoframe_config(hdmi))
|
|
|
- DRM_ERROR("Unable to configure AUDIO infoframe\n");
|
|
|
+ if (hdmi->audio.enabled) {
|
|
|
+ if (hdmi_audio_configure(hdmi))
|
|
|
+ DRM_ERROR("Unable to configure audio\n");
|
|
|
+ } else {
|
|
|
+ hdmi_audio_infoframe_config(hdmi);
|
|
|
+ }
|
|
|
|
|
|
/* Program VS infoframe */
|
|
|
if (hdmi_vendor_infoframe_config(hdmi))
|
|
@@ -1078,97 +1170,6 @@ static struct drm_encoder *sti_hdmi_find_encoder(struct drm_device *dev)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * sti_hdmi_audio_get_non_coherent_n() - get N parameter for non-coherent
|
|
|
- * clocks. None-coherent clocks means that audio and TMDS clocks have not the
|
|
|
- * same source (drifts between clocks). In this case assumption is that CTS is
|
|
|
- * automatically calculated by hardware.
|
|
|
- *
|
|
|
- * @audio_fs: audio frame clock frequency in Hz
|
|
|
- *
|
|
|
- * Values computed are based on table described in HDMI specification 1.4b
|
|
|
- *
|
|
|
- * Returns n value.
|
|
|
- */
|
|
|
-static int sti_hdmi_audio_get_non_coherent_n(unsigned int audio_fs)
|
|
|
-{
|
|
|
- unsigned int n;
|
|
|
-
|
|
|
- switch (audio_fs) {
|
|
|
- case 32000:
|
|
|
- n = 4096;
|
|
|
- break;
|
|
|
- case 44100:
|
|
|
- n = 6272;
|
|
|
- break;
|
|
|
- case 48000:
|
|
|
- n = 6144;
|
|
|
- break;
|
|
|
- case 88200:
|
|
|
- n = 6272 * 2;
|
|
|
- break;
|
|
|
- case 96000:
|
|
|
- n = 6144 * 2;
|
|
|
- break;
|
|
|
- case 176400:
|
|
|
- n = 6272 * 4;
|
|
|
- break;
|
|
|
- case 192000:
|
|
|
- n = 6144 * 4;
|
|
|
- break;
|
|
|
- default:
|
|
|
- /* Not pre-defined, recommended value: 128 * fs / 1000 */
|
|
|
- n = (audio_fs * 128) / 1000;
|
|
|
- }
|
|
|
-
|
|
|
- return n;
|
|
|
-}
|
|
|
-
|
|
|
-static int hdmi_audio_configure(struct sti_hdmi *hdmi,
|
|
|
- struct hdmi_audio_params *params)
|
|
|
-{
|
|
|
- int audio_cfg, n;
|
|
|
- struct hdmi_audio_infoframe *info = ¶ms->cea;
|
|
|
-
|
|
|
- DRM_DEBUG_DRIVER("\n");
|
|
|
-
|
|
|
- if (!hdmi->enabled)
|
|
|
- return 0;
|
|
|
-
|
|
|
- /* update N parameter */
|
|
|
- n = sti_hdmi_audio_get_non_coherent_n(params->sample_rate);
|
|
|
-
|
|
|
- DRM_DEBUG_DRIVER("Audio rate = %d Hz, TMDS clock = %d Hz, n = %d\n",
|
|
|
- params->sample_rate, hdmi->mode.clock * 1000, n);
|
|
|
- hdmi_write(hdmi, n, HDMI_AUDN);
|
|
|
-
|
|
|
- /* update HDMI registers according to configuration */
|
|
|
- audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID |
|
|
|
- HDMI_AUD_CFG_ONE_BIT_INVALID;
|
|
|
-
|
|
|
- switch (info->channels) {
|
|
|
- case 8:
|
|
|
- audio_cfg |= HDMI_AUD_CFG_CH78_VALID;
|
|
|
- case 6:
|
|
|
- audio_cfg |= HDMI_AUD_CFG_CH56_VALID;
|
|
|
- case 4:
|
|
|
- audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH;
|
|
|
- case 2:
|
|
|
- audio_cfg |= HDMI_AUD_CFG_CH12_VALID;
|
|
|
- break;
|
|
|
- default:
|
|
|
- DRM_ERROR("ERROR: Unsupported number of channels (%d)!\n",
|
|
|
- info->channels);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG);
|
|
|
-
|
|
|
- hdmi->audio = *params;
|
|
|
-
|
|
|
- return hdmi_audio_infoframe_config(hdmi);
|
|
|
-}
|
|
|
-
|
|
|
static void hdmi_audio_shutdown(struct device *dev, void *data)
|
|
|
{
|
|
|
struct sti_hdmi *hdmi = dev_get_drvdata(dev);
|
|
@@ -1192,17 +1193,9 @@ static int hdmi_audio_hw_params(struct device *dev,
|
|
|
{
|
|
|
struct sti_hdmi *hdmi = dev_get_drvdata(dev);
|
|
|
int ret;
|
|
|
- struct hdmi_audio_params audio = {
|
|
|
- .sample_width = params->sample_width,
|
|
|
- .sample_rate = params->sample_rate,
|
|
|
- .cea = params->cea,
|
|
|
- };
|
|
|
|
|
|
DRM_DEBUG_DRIVER("\n");
|
|
|
|
|
|
- if (!hdmi->enabled)
|
|
|
- return 0;
|
|
|
-
|
|
|
if ((daifmt->fmt != HDMI_I2S) || daifmt->bit_clk_inv ||
|
|
|
daifmt->frame_clk_inv || daifmt->bit_clk_master ||
|
|
|
daifmt->frame_clk_master) {
|
|
@@ -1213,9 +1206,13 @@ static int hdmi_audio_hw_params(struct device *dev,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- audio.enabled = true;
|
|
|
+ hdmi->audio.sample_width = params->sample_width;
|
|
|
+ hdmi->audio.sample_rate = params->sample_rate;
|
|
|
+ hdmi->audio.cea = params->cea;
|
|
|
+
|
|
|
+ hdmi->audio.enabled = true;
|
|
|
|
|
|
- ret = hdmi_audio_configure(hdmi, &audio);
|
|
|
+ ret = hdmi_audio_configure(hdmi);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|