@@ -14,7 +14,6 @@
#include <drm/drm_of.h>
#include <drm/display/drm_hdmi_state_helper.h>
-#include <sound/hdmi-codec.h>
#include "hdmi.h"
void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
@@ -245,87 +244,6 @@ static const struct hdmi_platform_config hdmi_tx_8974_config = {
.hpd_freq = hpd_clk_freq_8x74,
};
-/*
- * HDMI audio codec callbacks
- */
-static int msm_hdmi_audio_hw_params(struct device *dev, void *data,
- struct hdmi_codec_daifmt *daifmt,
- struct hdmi_codec_params *params)
-{
- struct hdmi *hdmi = dev_get_drvdata(dev);
- unsigned int rate;
- int ret;
-
- DRM_DEV_DEBUG(dev, "%u Hz, %d bit, %d channels\n", params->sample_rate,
- params->sample_width, params->cea.channels);
-
- switch (params->sample_rate) {
- case 32000:
- rate = HDMI_SAMPLE_RATE_32KHZ;
- break;
- case 44100:
- rate = HDMI_SAMPLE_RATE_44_1KHZ;
- break;
- case 48000:
- rate = HDMI_SAMPLE_RATE_48KHZ;
- break;
- case 88200:
- rate = HDMI_SAMPLE_RATE_88_2KHZ;
- break;
- case 96000:
- rate = HDMI_SAMPLE_RATE_96KHZ;
- break;
- case 176400:
- rate = HDMI_SAMPLE_RATE_176_4KHZ;
- break;
- case 192000:
- rate = HDMI_SAMPLE_RATE_192KHZ;
- break;
- default:
- DRM_DEV_ERROR(dev, "rate[%d] not supported!\n",
- params->sample_rate);
- return -EINVAL;
- }
-
- ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(hdmi->connector,
- ¶ms->cea);
- if (ret)
- return ret;
-
- msm_hdmi_audio_info_setup(hdmi, rate, params->cea.channels);
-
- return 0;
-}
-
-static void msm_hdmi_audio_shutdown(struct device *dev, void *data)
-{
- struct hdmi *hdmi = dev_get_drvdata(dev);
-
- drm_atomic_helper_connector_hdmi_clear_audio_infoframe(hdmi->connector);
- msm_hdmi_audio_disable(hdmi);
-}
-
-static const struct hdmi_codec_ops msm_hdmi_audio_codec_ops = {
- .hw_params = msm_hdmi_audio_hw_params,
- .audio_shutdown = msm_hdmi_audio_shutdown,
-};
-
-static struct hdmi_codec_pdata codec_data = {
- .ops = &msm_hdmi_audio_codec_ops,
- .max_i2s_channels = 8,
- .i2s = 1,
-};
-
-static int msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev)
-{
- hdmi->audio_pdev = platform_device_register_data(dev,
- HDMI_CODEC_DRV_NAME,
- PLATFORM_DEVID_AUTO,
- &codec_data,
- sizeof(codec_data));
- return PTR_ERR_OR_ZERO(hdmi->audio_pdev);
-}
-
static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
{
struct msm_drm_private *priv = dev_get_drvdata(master);
@@ -337,12 +255,6 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
return err;
priv->hdmi = hdmi;
- err = msm_hdmi_register_audio_driver(hdmi, dev);
- if (err) {
- DRM_ERROR("Failed to attach an audio codec %d\n", err);
- hdmi->audio_pdev = NULL;
- }
-
return 0;
}
@@ -352,9 +264,6 @@ static void msm_hdmi_unbind(struct device *dev, struct device *master,
struct msm_drm_private *priv = dev_get_drvdata(master);
if (priv->hdmi) {
- if (priv->hdmi->audio_pdev)
- platform_device_unregister(priv->hdmi->audio_pdev);
-
if (priv->hdmi->bridge)
msm_hdmi_hpd_disable(priv->hdmi);
@@ -33,7 +33,6 @@ struct hdmi_hdcp_ctrl;
struct hdmi {
struct drm_device *dev;
struct platform_device *pdev;
- struct platform_device *audio_pdev;
const struct hdmi_platform_config *config;
@@ -205,16 +204,15 @@ static inline int msm_hdmi_pll_8998_init(struct platform_device *pdev)
/*
* audio:
*/
-#define HDMI_SAMPLE_RATE_32KHZ 0
-#define HDMI_SAMPLE_RATE_44_1KHZ 1
-#define HDMI_SAMPLE_RATE_48KHZ 2
-#define HDMI_SAMPLE_RATE_88_2KHZ 3
-#define HDMI_SAMPLE_RATE_96KHZ 4
-#define HDMI_SAMPLE_RATE_176_4KHZ 5
-#define HDMI_SAMPLE_RATE_192KHZ 6
-
-int msm_hdmi_audio_info_setup(struct hdmi *hdmi, int rate, int channels);
-int msm_hdmi_audio_disable(struct hdmi *hdmi);
+struct hdmi_codec_daifmt;
+struct hdmi_codec_params;
+
+int msm_hdmi_bridge_audio_prepare(struct drm_connector *connector,
+ struct drm_bridge *bridge,
+ struct hdmi_codec_daifmt *daifmt,
+ struct hdmi_codec_params *params);
+void msm_hdmi_bridge_audio_shutdown(struct drm_connector *connector,
+ struct drm_bridge *bridge);
/*
* hdmi bridge:
@@ -4,7 +4,12 @@
* Author: Rob Clark <robdclark@gmail.com>
*/
+#include <drm/display/drm_hdmi_state_helper.h>
+
#include <linux/hdmi.h>
+
+#include <sound/hdmi-codec.h>
+
#include "hdmi.h"
/* Supported HDMI Audio sample rates */
@@ -68,7 +73,8 @@ static const struct hdmi_msm_audio_arcs *get_arcs(unsigned long int pixclock)
return NULL;
}
-static int msm_hdmi_audio_update(struct hdmi *hdmi)
+static int msm_hdmi_audio_update(struct hdmi *hdmi,
+ struct drm_connector *connector)
{
struct hdmi_audio *audio = &hdmi->audio;
const struct hdmi_msm_audio_arcs *arcs = NULL;
@@ -76,7 +82,7 @@ static int msm_hdmi_audio_update(struct hdmi *hdmi)
uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl;
uint32_t audio_config;
- if (!hdmi->connector->display_info.is_hdmi)
+ if (!connector->display_info.is_hdmi)
return -EINVAL;
DBG("audio: enabled=%d, channels=%d, rate=%d",
@@ -192,29 +198,72 @@ static int msm_hdmi_audio_update(struct hdmi *hdmi)
return 0;
}
-int msm_hdmi_audio_info_setup(struct hdmi *hdmi, int rate, int channels)
+int msm_hdmi_bridge_audio_prepare(struct drm_connector *connector,
+ struct drm_bridge *bridge,
+ struct hdmi_codec_daifmt *daifmt,
+ struct hdmi_codec_params *params)
{
- if (!hdmi)
- return -ENXIO;
-
- if ((rate < 0) || (rate >= MSM_HDMI_SAMPLE_RATE_MAX))
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+ struct hdmi *hdmi = hdmi_bridge->hdmi;
+ unsigned int rate;
+ int ret;
+
+ drm_dbg_driver(bridge->dev, "%u Hz, %d bit, %d channels\n",
+ params->sample_rate,
+ params->sample_width,
+ params->cea.channels);
+
+ switch (params->sample_rate) {
+ case 32000:
+ rate = MSM_HDMI_SAMPLE_RATE_32KHZ;
+ break;
+ case 44100:
+ rate = MSM_HDMI_SAMPLE_RATE_44_1KHZ;
+ break;
+ case 48000:
+ rate = MSM_HDMI_SAMPLE_RATE_48KHZ;
+ break;
+ case 88200:
+ rate = MSM_HDMI_SAMPLE_RATE_88_2KHZ;
+ break;
+ case 96000:
+ rate = MSM_HDMI_SAMPLE_RATE_96KHZ;
+ break;
+ case 176400:
+ rate = MSM_HDMI_SAMPLE_RATE_176_4KHZ;
+ break;
+ case 192000:
+ rate = MSM_HDMI_SAMPLE_RATE_192KHZ;
+ break;
+ default:
+ drm_err(bridge->dev, "rate[%d] not supported!\n",
+ params->sample_rate);
return -EINVAL;
+ }
+
+ ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector,
+ ¶ms->cea);
+ if (ret)
+ return ret;
hdmi->audio.rate = rate;
- hdmi->audio.channels = channels;
+ hdmi->audio.channels = params->cea.channels;
hdmi->audio.enabled = true;
- return msm_hdmi_audio_update(hdmi);
+ return msm_hdmi_audio_update(hdmi, connector);
}
-int msm_hdmi_audio_disable(struct hdmi *hdmi)
+void msm_hdmi_bridge_audio_shutdown(struct drm_connector *connector,
+ struct drm_bridge *bridge)
{
- if (!hdmi)
- return -ENXIO;
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+ struct hdmi *hdmi = hdmi_bridge->hdmi;
+
+ drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector);
hdmi->audio.rate = 0;
hdmi->audio.channels = 2;
hdmi->audio.enabled = false;
- return msm_hdmi_audio_update(hdmi);
+ msm_hdmi_audio_update(hdmi, connector);
}
@@ -470,6 +470,8 @@ static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
.hdmi_tmds_char_rate_valid = msm_hdmi_bridge_tmds_char_rate_valid,
.hdmi_clear_infoframe = msm_hdmi_bridge_clear_infoframe,
.hdmi_write_infoframe = msm_hdmi_bridge_write_infoframe,
+ .hdmi_audio_prepare = msm_hdmi_bridge_audio_prepare,
+ .hdmi_audio_shutdown = msm_hdmi_bridge_audio_shutdown,
};
static void
@@ -507,6 +509,9 @@ int msm_hdmi_bridge_init(struct hdmi *hdmi)
DRM_BRIDGE_OP_DETECT |
DRM_BRIDGE_OP_HDMI |
DRM_BRIDGE_OP_EDID;
+ bridge->hdmi_audio_max_i2s_playback_channels = 8;
+ bridge->hdmi_audio_dev = &hdmi->pdev->dev;
+ bridge->hdmi_audio_dai_port = -1;
ret = devm_drm_bridge_add(hdmi->dev->dev, bridge);
if (ret)
In order to simplify the driver even further and to remove the boilerplate code, rewrite the audio interface to use the DRM HDMI Audio framework. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> --- drivers/gpu/drm/msm/hdmi/hdmi.c | 91 ---------------------------------- drivers/gpu/drm/msm/hdmi/hdmi.h | 20 ++++---- drivers/gpu/drm/msm/hdmi/hdmi_audio.c | 75 +++++++++++++++++++++++----- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 5 ++ 4 files changed, 76 insertions(+), 115 deletions(-)