[alsa-devel] [PATCH RFC V2 2/5] drm: add helper functions to add audio capabilities for bridge
Arnaud Pouliquen
arnaud.pouliquen at st.com
Thu Oct 1 18:50:18 CEST 2015
Extend bridge capabilities for audio to enable to connect an audio driver to a
DRM driver with audio capabilities
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen at st.com>
---
drivers/gpu/drm/drm_bridge.c | 137 ++++++++++++++++++++++++++++++++++++++++++-
include/drm/drm_crtc.h | 62 ++++++++++++++++++++
include/drm/drm_modes.h | 12 ++++
3 files changed, 210 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 6b8f721..d1a437e 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -194,7 +194,7 @@ EXPORT_SYMBOL(drm_bridge_mode_fixup);
* chain, starting from the last bridge to the first. These are called before
* calling the encoder's prepare op.
*
- * Note: the bridge passed should be the one closest to the encoder
+ * Note: the bridge passed should be the othingsne closest to the encoder
*/
void drm_bridge_disable(struct drm_bridge *bridge)
{
@@ -328,6 +328,141 @@ struct drm_bridge *of_drm_find_bridge(struct device_node *np)
EXPORT_SYMBOL(of_drm_find_bridge);
#endif
+/**
+ * DOC: audio bridge callbacks
+ *
+ * The drm_audio_bridge_funcs ops are populated by the bridge driver that has
+ * audio capabilities (e.g. HDMI)
+ * The alsa driver (or asoc codec) uses the defined helpers.
+ * These helpers call a specific drm_audio_bridge_funcs ops defined by
+ * bridges with audio capabilities during encoder configuration.
+ *
+ * pre_enable: this contains actions needed to be done by the bridge before
+ * audio is enabled by its source.
+ *
+ * enable: this contains actions needed to be done by the audio bridge once its
+ * source is enabled. In other words, enable is called once the source is
+ * ready to start stream rendering.
+ *
+ * disable: this contains actions needed to be done by audio bridge when
+ * disable the audio part, assuming that its source is still enabled.
+ *
+ * post_disable: this contains actions needed to be done by the bridge once
+ * its source is disabled.
+ *
+ * mode_set: this sets up the mode by the audio bridge. It assumes that its
+ * audio source is aligned on this mode.
+ *
+ * mode_get: this get the supported modes based on ELD table. this can be use
+ * by audio source to fix audio constraints according to mode.
+ */
+
+/**
+ * drm_audio_bridge_pre_enable - calls 'pre_enable' drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ */
+int drm_audio_bridge_pre_enable(struct drm_bridge *bridge,
+ struct drm_audio_bridge_cfg *cfg)
+{
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->audio_funcs->pre_enable)
+ return bridge->audio_funcs->pre_enable(bridge, cfg);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_pre_enable);
+
+/**
+ * drm_audio_bridge_disable - calls 'disable' drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ */
+int drm_audio_bridge_disable(struct drm_bridge *bridge)
+{
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->audio_funcs->disable)
+ return bridge->audio_funcs->disable(bridge);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_disable);
+
+/**
+ * drm_audio_bridge_enable - calls 'enable' drm_audio_bridge_funcs audio
+ * bridge in the encoder chain.
+ * @bridge: bridge control structure
+ */
+int drm_audio_bridge_enable(struct drm_bridge *bridge)
+{
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->audio_funcs->enable)
+ return bridge->audio_funcs->enable(bridge);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_enable);
+
+/**
+ * drm_audio_bridge_post_disable - calls 'disable' drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ */
+int drm_audio_bridge_post_disable(struct drm_bridge *bridge)
+{
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->audio_funcs->post_disable)
+ return bridge->audio_funcs->post_disable(bridge);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_post_disable);
+
+/**
+ * drm_audio_bridge_mode_set - calls 'mode_set' drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ * @mode: desired audio mode to be set for the audio bridge
+ */
+int drm_audio_bridge_mode_set(struct drm_bridge *bridge,
+ struct hdmi_audio_mode *mode)
+{
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->audio_funcs->mode_set)
+ return bridge->audio_funcs->mode_set(bridge, mode);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_mode_set);
+
+/**
+ * drm_audio_bridge_mode_get - calls 'enable'drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ * Note: The returned pointer needs to be freed using kfree().
+ */
+uint8_t *drm_audio_bridge_mode_get(struct drm_bridge *bridge)
+{
+ if (!bridge)
+ return NULL;
+
+ if (bridge->audio_funcs->mode_get)
+ return bridge->audio_funcs->mode_get(bridge);
+
+ return NULL;
+}
+EXPORT_SYMBOL(drm_audio_bridge_mode_get);
+
MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs at samsung.com>");
MODULE_DESCRIPTION("DRM bridge infrastructure");
MODULE_LICENSE("GPL and additional rights");
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3b4d8a4..f13626a 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -583,6 +583,7 @@ struct drm_encoder_funcs {
* @possible_clones: bitmask of potential sibling encoders for cloning
* @crtc: currently bound CRTC
* @bridge: bridge associated to the encoder
+ * @abridge: optional audio bridge associated to the encoder (HDMI)
* @funcs: control functions
* @helper_private: mid-layer private data
*
@@ -601,6 +602,7 @@ struct drm_encoder {
struct drm_crtc *crtc;
struct drm_bridge *bridge;
+ struct drm_bridge *abridge;
const struct drm_encoder_funcs *funcs;
const void *helper_private;
};
@@ -905,6 +907,56 @@ struct drm_bridge_funcs {
};
/**
+ * struct drm_audio_bridge_cfg - audio interface configuration
+ * @fmt: bus format
+ * @sample_rate: sampling frequency
+ * @sample_width: sample size
+ * @channels: number of channels
+ * @frame_clk_master: frame synchro master
+ * @frame_clk_inv: frame clock inverted
+ * @bit_clk_master: bit clock master
+ * @bit_clk_inv: bit clock inverted
+ */
+struct drm_audio_bridge_cfg {
+ enum {
+ HDMI_I2S,
+ HDMI_RIGHT_J,
+ HDMI_LEFT_J,
+ HDMI_DSP_A,
+ HDMI_DSP_B,
+ HDMI_AC97,
+ HDMI_SPDIF,
+ } fmt;
+ int sample_rate;
+ int sample_width;
+ int channels;
+ int frame_clk_master:1;
+ int frame_clk_inv:1;
+ int bit_clk_master:1;
+ int bit_clk_inv:1;
+};
+
+/**
+ * struct drm_audio_bridge_funcs - audio drm_bridge control functions
+ * @disable: Called to disable the audio bridge
+ * @post_disable: Called for post disable actions
+ * @pre_enable: Called to configure the audio bridge
+ * @enable: Called to enable the audio bridge
+ * @mode_set: Set the audio bridge mode
+ * @mode_get: Get ELD buffer for audio mode supported.
+ */
+struct drm_audio_bridge_funcs {
+ int (*disable)(struct drm_bridge *bridge);
+ int (*post_disable)(struct drm_bridge *bridge);
+ int (*pre_enable)(struct drm_bridge *bridge,
+ struct drm_audio_bridge_cfg *cfg);
+ int (*enable)(struct drm_bridge *bridge);
+ int (*mode_set)(struct drm_bridge *bridge,
+ struct hdmi_audio_mode *mode);
+ uint8_t *(*mode_get)(struct drm_bridge *bridge);
+};
+
+/**
* struct drm_bridge - central DRM bridge control structure
* @dev: DRM device this bridge belongs to
* @encoder: encoder to which this bridge is connected
@@ -925,6 +977,7 @@ struct drm_bridge {
struct list_head list;
const struct drm_bridge_funcs *funcs;
+ const struct drm_audio_bridge_funcs *audio_funcs;
void *driver_private;
};
@@ -1266,6 +1319,15 @@ void drm_bridge_mode_set(struct drm_bridge *bridge,
void drm_bridge_pre_enable(struct drm_bridge *bridge);
void drm_bridge_enable(struct drm_bridge *bridge);
+int drm_audio_bridge_pre_enable(struct drm_bridge *bridge,
+ struct drm_audio_bridge_cfg *cfg);
+int drm_audio_bridge_enable(struct drm_bridge *bridge);
+int drm_audio_bridge_disable(struct drm_bridge *bridge);
+int drm_audio_bridge_post_disable(struct drm_bridge *bridge);
+int drm_audio_bridge_mode_set(struct drm_bridge *bridge,
+ struct hdmi_audio_mode *mode);
+uint8_t *drm_audio_bridge_mode_get(struct drm_bridge *bridge);
+
extern int drm_encoder_init(struct drm_device *dev,
struct drm_encoder *encoder,
const struct drm_encoder_funcs *funcs,
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 08a8cac..e923e32 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -164,6 +164,18 @@ struct drm_cmdline_mode {
enum drm_connector_force force;
};
+/*
+ * struct hdmi_audio_mode - hdmi audio structure for audio configuration
+ * @infoframe: audio info frame
+ * @iec_status: iec60958 channel status bytes
+ *
+ * This is used by audio driver to configure the HDMI audio part
+ */
+struct hdmi_audio_mode {
+ struct hdmi_audio_infoframe infoframe;
+ unsigned char iec_status[24];
+};
+
/**
* drm_mode_is_stereo - check for stereo mode flags
* @mode: drm_display_mode to check
--
1.9.1
More information about the Alsa-devel
mailing list