From patchwork Thu Oct 1 16:50:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud POULIQUEN X-Patchwork-Id: 7310151 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E9FB79F314 for ; Thu, 1 Oct 2015 16:52:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B4C7C206AB for ; Thu, 1 Oct 2015 16:52:46 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 816F120689 for ; Thu, 1 Oct 2015 16:52:44 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 1B1A32668AC; Thu, 1 Oct 2015 18:52:43 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 13E33266800; Thu, 1 Oct 2015 18:51:14 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 418352667FC; Thu, 1 Oct 2015 18:51:12 +0200 (CEST) Received: from mx07-00178001.pphosted.com (mx07-00178001.pphosted.com [62.209.51.94]) by alsa0.perex.cz (Postfix) with ESMTP id D43702667E4 for ; Thu, 1 Oct 2015 18:51:01 +0200 (CEST) Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.14.5/8.14.5) with SMTP id t91GjtcM006051; Thu, 1 Oct 2015 18:51:01 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 1x8edrnwx0-1 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT); Thu, 01 Oct 2015 18:51:01 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 3727E31; Thu, 1 Oct 2015 16:50:41 +0000 (GMT) Received: from Webmail-eu.st.com (Safex1hubcas21.st.com [10.75.90.44]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 6136DA81E; Thu, 1 Oct 2015 16:50:59 +0000 (GMT) Received: from localhost (10.201.23.162) by Webmail-ga.st.com (10.75.90.48) with Microsoft SMTP Server (TLS) id 14.3.224.2; Thu, 1 Oct 2015 18:50:58 +0200 From: Arnaud Pouliquen To: , Date: Thu, 1 Oct 2015 18:50:18 +0200 Message-ID: <1443718221-5120-3-git-send-email-arnaud.pouliquen@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1443718221-5120-1-git-send-email-arnaud.pouliquen@st.com> References: <1443718221-5120-1-git-send-email-arnaud.pouliquen@st.com> MIME-Version: 1.0 X-Originating-IP: [10.201.23.162] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.14.151, 1.0.33, 0.0.0000 definitions=2015-10-01_06:2015-10-01, 2015-10-01, 1970-01-01 signatures=0 Cc: moinejf@free.fr, linux@arm.linux.org.uk, bcousson@baylibre.com, David Airlie , tomi.valkeinen@ti.com, arnaud.pouliquen@st.com, lgirdwood@gmail.com, Jyri Sarha , peter.ujfalusi@ti.com, Takashi Iwai , tony@atomide.com, broonie@kernel.org, Benjamin Gaignard Subject: [alsa-devel] [PATCH RFC V2 2/5] drm: add helper functions to add audio capabilities for bridge X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Extend bridge capabilities for audio to enable to connect an audio driver to a DRM driver with audio capabilities Signed-off-by: Arnaud Pouliquen --- 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 "); 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