Implement generic ASoC HDMI codec and use it in tda998x
Subsystems (7)
v9 cover Implement generic ASoC HDMI codec and use it in tda998x
Couple of minor changes since v8 to ALSA/ASoC side patches. The series is based on top of drm-next. However, it does not look like there is enough attention to the DRM side so that the tda998x patches would get in any time soon. So I am happy to rebase the first ALSA-side patches on top of Mark Brown's for-next tree, for instance, if they would have a change to go in on their own. The first two IEC958 helper patches should apply as such.
There is currently two other patch series[2][3] that depend on the first three (ALSA-) patches of this series. The third ("ASoC:
hdmi-codec: Add audio abort() callback for video side to use") is currently not used and can be dropped if so decided. The rest depends on those the first patches and adds hdmi-audio support for Beaglebone-black.
Best regards,
Jyri
[1] "[PATCH v6 0/6] Implement generic ASoC HDMI codec and use it in tda998x"
http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105524.html [2] "[PATCH v6 00/10] ASoC: Add mediatek HDMI codec support" by Philipp Zabel http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105509.html
[3] "[RFC v2 0/6] sti: add audio interface to the hdmi driver"
http://mailman.alsa-project.org/pipermail/alsa-devel/2016-January/103374.html
and "[PATCH v4 0/6] add IEC958 channel status control helpers"
http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105502.html
by Arnaud Pouliquen
Changes since v8
* "ALSA: pcm: add IEC958 channel status helper for hw_params"
- Split out the 32 bit support
- add: "ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper"
* "ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders"
- Set hw_params->msbits to 24 in hw_params() callback if sample width is greater than 24 bits
Changes since v7
* "drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding"
- Remove the unused "int ret" variable from tda998x_configure_audio()
Changes since v6
* "ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders"
- Add "Acked-by: Arnaud Pouliquen <[email protected]>" and "Tested-by: Philipp Zabel <[email protected]>", no other changes
* "ALSA: pcm: add IEC958 channel status helper for hw_param"
- Added kernel-doc for snd_pcm_create_iec958_consumer_hw_params()
* "drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding"
- Use PTR_ERR_OR_ZERO() in tda998x_audio_codec_init()
- Fix possible uninitialized use of 'size' in tda998x_get_audio_ports()
- Store audio configuration in tda998x_audio_hw_params() instead of tda998x_configure_audio().
Changes since v5
- Rebased on top of the latest drm-next branch
- Allow 32 bit samplewidth in snd_pcm_create_iec958_consumer() and snd_pcm_create_iec958_consumer_hw_params()
- Propose new simpler DT binding for tda998x audio
- Squash tda998x audio DT binding together with hdmi-codec integration
Changes since RFC v4,
- Rebased on top of the latest drm-next branch
- Split the hdmi-codec abort functionality into a separate patch for better visibility of what it is all about
- This does not affect the tda998x patches as the abort functionality is not used
- Drop S18_3* formats from I2S_FORMATS and add a comment about formats not supported by HDMI
Changes since RFC v3,
ASoC side:
- Add "ALSA: pcm: add IEC958 channel status helper for hw_params"
- Add "tda998x: Improve tda998x_configure_audio() audio related pdata"
- use snd_pcm_create_iec958_consumer_hw_params() to construct the stream header
- Remove set_clk() callback from hdmi-codec. It is not needed for now.
- Refer to stream header in AIF as specified in HDMI standard
- Set current_stream to NULL only after video side audio_shutdown() has been called. Avoid potential race if video side attempts to abort audio at the same time.
- No need to have video side device pointer in the hdmi codec's pdata as it is found from dev->parent.
- Fix hdmi-codec enum: DAI_ID_I2C > DAI_ID_I2S
- Improve audio_startup API comment
- Make improved checkpatch happy
- BUG_ON > WARN_ON
- put */ ending the block comment to a separate line
DRM side:
- Fix tda998x get_eld() locking
- Change tda998x audio parameters in pdata to more generic, that can be readily used in tda998x_audio_config()
- Rename and restructure audio port related private data members to be more descriptive
- Require audio configuration trough ASoC hdmi-codec if HDMI audio is configured trough DT binding.
DTS:
- Increase McASP fifo usage form 1 to 32
Jyri Sarha (7):
ALSA: pcm: add IEC958 channel status helper for hw_params
ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper
ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
ASoC: hdmi-codec: Add audio abort() callback for video side to use drm/i2c: tda998x: Improve tda998x_configure_audio() audio related
pdata
drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
ARM: dts: am335x-boneblack: Add HDMI audio support
.../devicetree/bindings/display/bridge/tda998x.txt | 18 + arch/arm/boot/dts/am335x-boneblack.dts | 71 +++- drivers/gpu/drm/i2c/Kconfig | 1 + drivers/gpu/drm/i2c/tda998x_drv.c | 275 ++++++++++++-- include/drm/i2c/tda998x.h | 24 +- include/dt-bindings/display/tda998x.h | 7 + include/sound/hdmi-codec.h | 104 ++++++ include/sound/pcm_iec958.h | 2 + sound/core/pcm_iec958.c | 65 +++- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/hdmi-codec.c | 414 +++++++++++++++++++++ 12 files changed, 917 insertions(+), 72 deletions(-) create mode 100644 include/dt-bindings/display/tda998x.h create mode 100644 include/sound/hdmi-codec.h create mode 100644 sound/soc/codecs/hdmi-codec.c
Signature · 1 line
1.9.1
PATCH v9 1/7 ALSA: pcm: add IEC958 channel status helper for hw_params
Add IEC958 channel status helper that gets the audio properties from snd_pcm_hw_params instead of snd_pcm_runtime. This is needed to produce the channel status bits already in audio stream configuration phase.
--- include/sound/pcm_iec958.h | 2 ++ sound/core/pcm_iec958.c | 64 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 17 deletions(-)
include/sound/pcm_iec958.h +2 -0
@@ -6,4 +6,6 @@int snd_pcm_create_iec958_consumer (struct snd_pcm_runtime *runtime,u8 *cs,size_t len); +int snd_pcm_create_iec958_consumer_hw_params (struct snd_pcm_hw_params *params, +u8 *cs,size_t len);#endif
sound/core/pcm_iec958.c +47 -17
88 lines not on this page · raw message
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v9 1/7] ALSA: pcm: add IEC958 channel status helper for hw_params
Quoted 7 lines · Jyri Sarha
Add IEC958 channel status helper that gets the audio properties from
snd_pcm_hw_paramsinstead ofsnd_pcm_runtime. This is needed to produce the channel status bits already in audio stream configuration phase.Signed-off-by Jyri Sarha <[email protected]>
Takashi
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Mark Brown
maintainerApplied "ALSA: pcm: add IEC958 channel status helper for hw_params" to the asoc tree
In reply to Jyri SarhaThe patch
ALSA: pcm: add IEC958 channel status helper for hw_params
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
From 4a4436573a6669516f73bac25016683d396ed4c4 Mon Sep 17 00:00:00 2001
From: Jyri Sarha <[email protected]>
Date: Thu, 31 Mar 2016 16:35:58 +0300
Subject: [PATCH] ALSA: pcm: add IEC958 channel status helper for hw_params
Add IEC958 channel status helper that gets the audio properties from snd_pcm_hw_params instead of snd_pcm_runtime. This is needed to produce the channel status bits already in audio stream configuration phase.
--- include/sound/pcm_iec958.h | 2 ++ sound/core/pcm_iec958.c | 64 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 17 deletions(-)
include/sound/pcm_iec958.h +2 -0
@@ -6,4 +6,6 @@int snd_pcm_create_iec958_consumer (struct snd_pcm_runtime *runtime,u8 *cs,size_t len); +int snd_pcm_create_iec958_consumer_hw_params (struct snd_pcm_hw_params *params, +u8 *cs,size_t len);#endif
sound/core/pcm_iec958.c +47 -17
88 lines not on this page · raw message
Signature · 6 lines
2.8.0.rc3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v9 2/7 ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper
In reply to Jyri SarhaTreat 32 bit sample width as if it was 24 bits when generating IEC958 channel status bits. On some platforms 24 sample width is problematic and to get full 24 bit precision a 32 bit format, using only the 24 most significant bits, may have to be used.
--- sound/core/pcm_iec958.c | 1 + 1 file changed, 1 insertion(+)
sound/core/pcm_iec958.c +1 -0
@@ -59,6 +59,7 @@ static int create_iec958_consumer(uint rate, uint sample_width,IEC958_AES4_CON_MAX_WORDLEN_24 ;break ;case 24 : +case 32 :/* Assume 24-bit width for 32-bit samples. */ ws =IEC958_AES4_CON_WORDLEN_24_20 |IEC958_AES4_CON_MAX_WORDLEN_24 ;break ;
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
A message that is not in the archive (sent off-list or not yet received): 44ee7ac5c0ddb4d25ac1bd4f189d328f8205e4a0.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org
Takashi Iwai
Reviewed-byRe: [PATCH v9 2/7] ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper
Quoted 7 lines · Jyri Sarha
Treat 32 bit sample width as if it was 24 bits when generating IEC958 channel status bits. On some platforms 24 sample width is problematic and to get full 24 bit precision a 32 bit format, using only the 24 most significant bits, may have to be used.
Signed-off-by Jyri Sarha <[email protected]>
Takashi
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Mark Brown
maintainerApplied "ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper" to the asoc tree
In reply to Jyri SarhaThe patch
ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
From 4a462ce084d5beb92cfc68f53f88c035c82e6b59 Mon Sep 17 00:00:00 2001
From: Jyri Sarha <[email protected]>
Date: Thu, 31 Mar 2016 16:35:59 +0300
Subject: [PATCH] ALSA: pcm: Allow 32 bit sample format in IEC958 channel
status helper
Treat 32 bit sample width as if it was 24 bits when generating IEC958 channel status bits. On some platforms 24 sample width is problematic and to get full 24 bit precision a 32 bit format, using only the 24 most significant bits, may have to be used.
--- sound/core/pcm_iec958.c | 1 + 1 file changed, 1 insertion(+)
sound/core/pcm_iec958.c +1 -0
@@ -59,6 +59,7 @@ static int create_iec958_consumer(uint rate, uint sample_width,IEC958_AES4_CON_MAX_WORDLEN_24 ;break ;case 24 : +case 32 :/* Assume 24-bit width for 32-bit samples. */ ws =IEC958_AES4_CON_WORDLEN_24_20 |IEC958_AES4_CON_MAX_WORDLEN_24 ;break ;
Signature · 6 lines
2.8.0.rc3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v9 3/7 ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
In reply to Jyri SarhaThe hdmi-codec is a platform device driver to be registered from drivers of external HDMI encoders with I2S and/or spdif interface. The driver in turn registers an ASoC codec for the HDMI encoder's audio functionality.
The structures and definitions in the API header are mostly redundant copies of similar structures in ASoC headers. This is on purpose to avoid direct dependencies to ASoC structures in video side driver.
--- include/sound/hdmi-codec.h | 100 +++++++++++ sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/hdmi-codec.c | 396 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 504 insertions(+) create mode 100644 include/sound/hdmi-codec.h create mode 100644 sound/soc/codecs/hdmi-codec.c
include/sound/hdmi-codec.h new file +100 -0
@@ -0,0 +1,100 @@ +/* +* hdmi-codec.h - HDMI Codec driver API +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com +* +* Author: Jyri Sarha <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +*/ + +#ifndef __HDMI_CODEC_H__ +#define __HDMI_CODEC_H__ + +#include <linux/hdmi.h> +#include <drm/drm_edid.h> +#include <sound/asoundef.h> +#include <uapi/sound/asound.h> + +/* +* Protocol between ASoC cpu-dai and HDMI-encoder +*/ +struct hdmi_codec_daifmt { +enum { +HDMI_I2S , +HDMI_RIGHT_J , +HDMI_LEFT_J , +HDMI_DSP_A , +HDMI_DSP_B , +HDMI_AC97 , +HDMI_SPDIF , + } fmt; +int bit_clk_inv:1 ; +int frame_clk_inv:1 ; +int bit_clk_master:1 ; +int frame_clk_master:1 ; +}; + +/* +* HDMI audio parameters +*/ +struct hdmi_codec_params { +struct hdmi_audio_infoframe cea; +struct snd_aes_iec958 iec; +int sample_rate; +int sample_width; +int channels; +}; + +struct hdmi_codec_ops { +/* +* Called when ASoC starts an audio stream setup. +* Optional +*/ +int (*audio_startup)(struct device *dev); + +/* +* Configures HDMI-encoder for audio stream. +* Mandatory +*/ +int (*hw_params)(struct device *dev, +struct hdmi_codec_daifmt *fmt, +struct hdmi_codec_params *hparms); + +/* +* Shuts down the audio stream. +* Mandatory +*/ +void (*audio_shutdown)(struct device *dev); + +/* +* Mute/unmute HDMI audio stream. +* Optional +*/ +int (*digital_mute)(struct device *dev,bool enable); + +/* +* Provides EDID-Like-Data from connected HDMI device. +* Optional +*/ +int (*get_eld)(struct device *dev,uint8_t *buf,size_t len); +}; + +/* HDMI codec initalization data */ +struct hdmi_codec_pdata { +const struct hdmi_codec_ops *ops; +uint i2s:1 ; +uint spdif:1 ; +int max_i2s_channels; +}; + +#define HDMI_CODEC_DRV_NAME "hdmi-audio-codec" + +#endif /* __HDMI_CODEC_H__ */
sound/soc/codecs/Kconfig +6 -0
@@ -86,6 +86,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MC13783 if MFD_MC13XXX select SND_SOC_ML26124 if I2C select SND_SOC_NAU8825 if I2C + select SND_SOC_HDMI_CODEC select SND_SOC_PCM1681 if I2C select SND_SOC_PCM179X if SPI_MASTER select SND_SOC_PCM3008
@@ -473,6 +474,11 @@ config SND_SOC_BT_SCO config SND_SOC_DMIC tristate +config SND_SOC_HDMI_CODEC + tristate + select SND_PCM_ELD + select SND_PCM_IEC958 + config SND_SOC_ES8328 tristate "Everest Semi ES8328 CODEC"
sound/soc/codecs/Makefile +2 -0
@@ -79,6 +79,7 @@ snd-soc-max9850-objs := max9850.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o snd-soc-nau8825-objs := nau8825.o +snd-soc-hdmi-codec-objs := hdmi-codec.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm179x-codec-objs := pcm179x.o snd-soc-pcm3008-objs := pcm3008.o
@@ -283,6 +284,7 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o +obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
sound/soc/codecs/hdmi-codec.c new file +396 -0
396 lines not on this page · raw message
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
New version Tested with success on sti platform
Regards
Arnaud
Quoted 572 lines · Jyri Sarha
The hdmi-codec is a platform device driver to be registered from drivers of external HDMI encoders with I2S and/or spdif interface. The driver in turn registers an ASoC codec for the HDMI encoder's audio functionality.
The structures and definitions in the API header are mostly redundant copies of similar structures in ASoC headers. This is on purpose to avoid direct dependencies to ASoC structures in video side driver.
Signed-off-by Jyri Sarha <[email protected]>--- include/sound/hdmi-codec.h | 100 +++++++++++ sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/hdmi-codec.c | 396 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 504 insertions(+) create mode 100644 include/sound/hdmi-codec.h create mode 100644 sound/soc/codecs/hdmi-codec.cinclude/sound/hdmi-codec.h new file +100
-0@@ -0,0 +1,100 @@ +/* +* hdmi-codec.h - HDMI Codec driver API +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com +* +* Author: Jyri Sarha <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +*/ + +#ifndef __HDMI_CODEC_H__ +#define __HDMI_CODEC_H__ + +#include <linux/hdmi.h> +#include <drm/drm_edid.h> +#include <sound/asoundef.h> +#include <uapi/sound/asound.h> + +/* +* Protocol between ASoC cpu-dai and HDMI-encoder +*/ +struct hdmi_codec_daifmt { +enum { +HDMI_I2S , +HDMI_RIGHT_J , +HDMI_LEFT_J , +HDMI_DSP_A , +HDMI_DSP_B , +HDMI_AC97 , +HDMI_SPDIF , + } fmt; +int bit_clk_inv:1 ; +int frame_clk_inv:1 ; +int bit_clk_master:1 ; +int frame_clk_master:1 ; +}; + +/* +* HDMI audio parameters +*/ +struct hdmi_codec_params { +struct hdmi_audio_infoframe cea; +struct snd_aes_iec958 iec; +int sample_rate; +int sample_width; +int channels; +}; + +struct hdmi_codec_ops { +/* +* Called when ASoC starts an audio stream setup. +* Optional +*/ +int (*audio_startup)(struct device *dev); + +/* +* Configures HDMI-encoder for audio stream. +* Mandatory +*/ +int (*hw_params)(struct device *dev, +struct hdmi_codec_daifmt *fmt, +struct hdmi_codec_params *hparms); + +/* +* Shuts down the audio stream. +* Mandatory +*/ +void (*audio_shutdown)(struct device *dev); + +/* +* Mute/unmute HDMI audio stream. +* Optional +*/ +int (*digital_mute)(struct device *dev,bool enable); + +/* +* Provides EDID-Like-Data from connected HDMI device. +* Optional +*/ +int (*get_eld)(struct device *dev,uint8_t *buf,size_t len); +}; + +/* HDMI codec initalization data */ +struct hdmi_codec_pdata { +const struct hdmi_codec_ops *ops; +uint i2s:1 ; +uint spdif:1 ; +int max_i2s_channels; +}; + +#define HDMI_CODEC_DRV_NAME "hdmi-audio-codec" + +#endif /* __HDMI_CODEC_H__ */ sound/soc/codecs/Kconfig +6
-0@@ -86,6 +86,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MC13783 if MFD_MC13XXX select SND_SOC_ML26124 if I2C select SND_SOC_NAU8825 if I2C + select SND_SOC_HDMI_CODEC select SND_SOC_PCM1681 if I2C select SND_SOC_PCM179X if SPI_MASTER select SND_SOC_PCM3008@@ -473,6 +474,11 @@ config SND_SOC_BT_SCO config SND_SOC_DMIC tristate +config SND_SOC_HDMI_CODEC + tristate + select SND_PCM_ELD + select SND_PCM_IEC958 + config SND_SOC_ES8328 tristate "Everest Semi ES8328 CODEC"sound/soc/codecs/Makefile +2
-0@@ -79,6 +79,7 @@ snd-soc-max9850-objs := max9850.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o snd-soc-nau8825-objs := nau8825.o +snd-soc-hdmi-codec-objs := hdmi-codec.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm179x-codec-objs := pcm179x.o snd-soc-pcm3008-objs := pcm3008.o@@ -283,6 +284,7 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o +obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.osound/soc/codecs/hdmi-codec.c new file +396
-0@@ -0,0 +1,396 @@ +/* +* ALSA SoC codec for HDMI encoder drivers +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* Author: Jyri Sarha <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +*/ +#include <linux/module.h> +#include <linux/string.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/pcm_drm_eld.h> +#include <sound/hdmi-codec.h> +#include <sound/pcm_iec958.h> + +#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */ + +struct hdmi_codec_priv { +struct hdmi_codec_pdata hcd; +struct snd_soc_dai_driver *daidrv; +struct hdmi_codec_daifmt daifmt[2 ]; +struct mutex current_stream_lock; +struct snd_pcm_substream *current_stream; +struct snd_pcm_hw_constraint_list ratec; +uint8_t eld[MAX_ELD_BYTES ]; +}; + +static const struct snd_soc_dapm_widget hdmi_widgets[] = { +SND_SOC_DAPM_OUTPUT ("TX" ), +}; + +static const struct snd_soc_dapm_route hdmi_routes[] = { + {"TX" ,NULL ,"Playback" }, +}; + +enum { +DAI_ID_I2S =0 , +DAI_ID_SPDIF , +}; + +static int hdmi_codec_new_stream (struct snd_pcm_substream *substream, +struct snd_soc_dai *dai) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); +int ret =0 ; + +mutex_lock (&hcp->current_stream_lock); +if (!hcp->current_stream) { + hcp->current_stream = substream; + }else if (hcp->current_stream != substream) { +dev_err (dai->dev,"Only one simultaneous stream supported!\n" ); + ret = -EINVAL ; + } +mutex_unlock (&hcp->current_stream_lock); + +return ret; +} + +static int hdmi_codec_startup (struct snd_pcm_substream *substream, +struct snd_soc_dai *dai) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); +int ret =0 ; + +dev_dbg (dai->dev,"%s()\n" , __func__); + + ret =hdmi_codec_new_stream (substream, dai); +if (ret) +return ret; + +if (hcp->hcd.ops->audio_startup) { + ret = hcp->hcd.ops->audio_startup (dai->dev->parent); +if (ret) { +mutex_lock (&hcp->current_stream_lock); + hcp->current_stream =NULL ; +mutex_unlock (&hcp->current_stream_lock); +return ret; + } + } + +if (hcp->hcd.ops->get_eld) { + ret = hcp->hcd.ops->get_eld (dai->dev->parent, hcp->eld, +sizeof (hcp->eld)); + +if (!ret) { + ret =snd_pcm_hw_constraint_eld (substream->runtime, + hcp->eld); +if (ret) +return ret; + } + } +return 0 ; +} + +static void hdmi_codec_shutdown (struct snd_pcm_substream *substream, +struct snd_soc_dai *dai) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); + +dev_dbg (dai->dev,"%s()\n" , __func__); + +WARN_ON (hcp->current_stream != substream); + + hcp->hcd.ops->audio_shutdown (dai->dev->parent); + +mutex_lock (&hcp->current_stream_lock); + hcp->current_stream =NULL ; +mutex_unlock (&hcp->current_stream_lock); +} + +static int hdmi_codec_hw_params (struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params, +struct snd_soc_dai *dai) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); +struct hdmi_codec_params hp = { + .iec = { + .status = {0 }, + .subcode = {0 }, + .pad =0 , + .dig_subframe = {0 }, + } + }; +int ret; + +dev_dbg (dai->dev,"%s() width %d rate %d channels %d\n" , __func__, +params_width (params),params_rate (params), +params_channels (params)); + +if (params_width (params) >24 ) + params->msbits =24 ; + + ret =snd_pcm_create_iec958_consumer_hw_params (params, hp.iec.status, +sizeof (hp.iec.status)); +if (ret <0 ) { +dev_err (dai->dev,"Creating IEC958 channel status failed %d\n" , + ret); +return ret; + } + + ret =hdmi_codec_new_stream (substream, dai); +if (ret) +return ret; + +hdmi_audio_infoframe_init (&hp.cea); + hp.cea.channels =params_channels (params); + hp.cea.coding_type =HDMI_AUDIO_CODING_TYPE_STREAM ; + hp.cea.sample_size =HDMI_AUDIO_SAMPLE_SIZE_STREAM ; + hp.cea.sample_frequency =HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM ; + + hp.sample_width =params_width (params); + hp.sample_rate =params_rate (params); + hp.channels =params_channels (params); + +return hcp->hcd.ops->hw_params (dai->dev->parent, &hcp->daifmt[dai->id], + &hp); +} + +static int hdmi_codec_set_fmt (struct snd_soc_dai *dai, +unsigned int fmt) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); +struct hdmi_codec_daifmt cf = {0 }; +int ret =0 ; + +dev_dbg (dai->dev,"%s()\n" , __func__); + +if (dai->id ==DAI_ID_SPDIF ) { + cf.fmt =HDMI_SPDIF ; + }else { +switch (fmt &SND_SOC_DAIFMT_MASTER_MASK ) { +case SND_SOC_DAIFMT_CBM_CFM : + cf.bit_clk_master =1 ; + cf.frame_clk_master =1 ; +break ; +case SND_SOC_DAIFMT_CBS_CFM : + cf.frame_clk_master =1 ; +break ; +case SND_SOC_DAIFMT_CBM_CFS : + cf.bit_clk_master =1 ; +break ; +case SND_SOC_DAIFMT_CBS_CFS : +break ; +default : +return -EINVAL ; + } + +switch (fmt &SND_SOC_DAIFMT_INV_MASK ) { +case SND_SOC_DAIFMT_NB_NF : +break ; +case SND_SOC_DAIFMT_NB_IF : + cf.frame_clk_inv =1 ; +break ; +case SND_SOC_DAIFMT_IB_NF : + cf.bit_clk_inv =1 ; +break ; +case SND_SOC_DAIFMT_IB_IF : + cf.frame_clk_inv =1 ; + cf.bit_clk_inv =1 ; +break ; + } + +switch (fmt &SND_SOC_DAIFMT_FORMAT_MASK ) { +case SND_SOC_DAIFMT_I2S : + cf.fmt =HDMI_I2S ; +break ; +case SND_SOC_DAIFMT_DSP_A : + cf.fmt =HDMI_DSP_A ; +break ; +case SND_SOC_DAIFMT_DSP_B : + cf.fmt =HDMI_DSP_B ; +break ; +case SND_SOC_DAIFMT_RIGHT_J : + cf.fmt =HDMI_RIGHT_J ; +break ; +case SND_SOC_DAIFMT_LEFT_J : + cf.fmt =HDMI_LEFT_J ; +break ; +case SND_SOC_DAIFMT_AC97 : + cf.fmt =HDMI_AC97 ; +break ; +default : +dev_err (dai->dev,"Invalid DAI interface format\n" ); +return -EINVAL ; + } + } + + hcp->daifmt[dai->id] = cf; + +return ret; +} + +static int hdmi_codec_digital_mute (struct snd_soc_dai *dai,int mute) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); + +dev_dbg (dai->dev,"%s()\n" , __func__); + +if (hcp->hcd.ops->digital_mute) +return hcp->hcd.ops->digital_mute (dai->dev->parent, mute); + +return 0 ; +} + +static const struct snd_soc_dai_ops hdmi_dai_ops = { + .startup = hdmi_codec_startup, + .shutdown = hdmi_codec_shutdown, + .hw_params = hdmi_codec_hw_params, + .set_fmt = hdmi_codec_set_fmt, + .digital_mute = hdmi_codec_digital_mute, +}; + + +#define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define SPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) + +/* +* This list is only for formats allowed on the I2S bus. So there is +* some formats listed that are not supported by HDMI interface. For +* instance allowing the 32-bit formats enables 24-precision with CPU +* DAIs that do not support 24-bit formats. If the extra formats cause +* problems, we should add the video side driver an option to disable +* them. +*/ +#define I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) + +static struct snd_soc_dai_driver hdmi_i2s_dai = { + .name ="i2s-hifi" , + .id =DAI_ID_I2S , + .playback = { + .stream_name ="Playback" , + .channels_min =2 , + .channels_max =8 , + .rates =HDMI_RATES , + .formats =I2S_FORMATS , + .sig_bits =24 , + }, + .ops = &hdmi_dai_ops, +}; + +static const struct snd_soc_dai_driver hdmi_spdif_dai = { + .name ="spdif-hifi" , + .id =DAI_ID_SPDIF , + .playback = { + .stream_name ="Playback" , + .channels_min =2 , + .channels_max =2 , + .rates =HDMI_RATES , + .formats =SPDIF_FORMATS , + }, + .ops = &hdmi_dai_ops, +}; + +static struct snd_soc_codec_driver hdmi_codec = { + .dapm_widgets = hdmi_widgets, + .num_dapm_widgets =ARRAY_SIZE (hdmi_widgets), + .dapm_routes = hdmi_routes, + .num_dapm_routes =ARRAY_SIZE (hdmi_routes), +}; + +static int hdmi_codec_probe (struct platform_device *pdev) +{ +struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; +struct device *dev = &pdev->dev; +struct hdmi_codec_priv *hcp; +int dai_count, i =0 ; +int ret; + +dev_dbg (dev,"%s()\n" , __func__); + +if (!hcd) { +dev_err (dev,"%s: No plalform data\n" , __func__); +return -EINVAL ; + } + + dai_count = hcd->i2s + hcd->spdif; +if (dai_count <1 || !hcd->ops || !hcd->ops->hw_params || + !hcd->ops->audio_shutdown) { +dev_err (dev,"%s: Invalid parameters\n" , __func__); +return -EINVAL ; + } + + hcp =devm_kzalloc (dev,sizeof (*hcp),GFP_KERNEL ); +if (!hcp) +return -ENOMEM ; + + hcp->hcd = *hcd; +mutex_init (&hcp->current_stream_lock); + + hcp->daidrv =devm_kzalloc (dev, dai_count *sizeof (*hcp->daidrv), +GFP_KERNEL ); +if (!hcp->daidrv) +return -ENOMEM ; + +if (hcd->i2s) { + hcp->daidrv[i] = hdmi_i2s_dai; + hcp->daidrv[i].playback.channels_max = + hcd->max_i2s_channels; + i++; + } + +if (hcd->spdif) + hcp->daidrv[i] = hdmi_spdif_dai; + + ret =snd_soc_register_codec (dev, &hdmi_codec, hcp->daidrv, + dai_count); +if (ret) { +dev_err (dev,"%s: snd_soc_register_codec() failed (%d)\n" , + __func__, ret); +return ret; + } + +dev_set_drvdata (dev, hcp); +return 0 ; +} + +static int hdmi_codec_remove (struct platform_device *pdev) +{ +snd_soc_unregister_codec (&pdev->dev); +return 0 ; +} + +static struct platform_driver hdmi_codec_driver = { + .driver = { + .name =HDMI_CODEC_DRV_NAME , + }, + .probe = hdmi_codec_probe, + .remove = hdmi_codec_remove, +}; + +module_platform_driver (hdmi_codec_driver); + +MODULE_AUTHOR ("Jyri Sarha <[email protected]>" ); +MODULE_DESCRIPTION ("HDMI Audio Codec Driver" ); +MODULE_LICENSE ("GPL" ); +MODULE_ALIAS ("platform:" HDMI_CODEC_DRV_NAME );
A message that is not in the archive (sent off-list or not yet received): 636486b25db48fa13ae640516cdebe7bcfea0d23.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org
PC Liao
Acked-byRe: [alsa-devel] [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
Hi Jyri,
Quoted 10 lines · Jyri Sarha
The hdmi-codec is a platform device driver to be registered from drivers of external HDMI encoders with I2S and/or spdif interface. The driver in turn registers an ASoC codec for the HDMI encoder's audio functionality.
The structures and definitions in the API header are mostly redundant copies of similar structures in ASoC headers. This is on purpose to avoid direct dependencies to ASoC structures in video side driver.
Signed-off-by Jyri Sarha <[email protected]>
I successfully tested new version on mt8173.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
In reply to Jyri SarhaQuoted 9 lines · Jyri Sarha
The hdmi-codec is a platform device driver to be registered from drivers of external HDMI encoders with I2S and/or spdif interface. The driver in turn registers an ASoC codec for the HDMI encoder's audio functionality.
The structures and definitions in the API header are mostly redundant copies of similar structures in ASoC headers. This is on purpose to avoid direct dependencies to ASoC structures in video side driver.
Mark,
There is now two acks (and a tested-by?) to this patch and reviewed-by to an earlier version (with very small change this this one). I think it would make sense to apply this one now, even if there are no users to the driver just yet. Then all the video side users could (at least in theory) implement the HW specific hdmi audio support with video side patches only.
What do you think?
Best regards,
Jyri
Quoted 563 lines
Signed-off-by Jyri Sarha <[email protected]>--- include/sound/hdmi-codec.h | 100 +++++++++++ sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/hdmi-codec.c | 396 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 504 insertions(+) create mode 100644 include/sound/hdmi-codec.h create mode 100644 sound/soc/codecs/hdmi-codec.cinclude/sound/hdmi-codec.h new file +100
-0@@ -0,0 +1,100 @@ +/* +* hdmi-codec.h - HDMI Codec driver API +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com +* +* Author: Jyri Sarha <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +*/ + +#ifndef __HDMI_CODEC_H__ +#define __HDMI_CODEC_H__ + +#include <linux/hdmi.h> +#include <drm/drm_edid.h> +#include <sound/asoundef.h> +#include <uapi/sound/asound.h> + +/* +* Protocol between ASoC cpu-dai and HDMI-encoder +*/ +struct hdmi_codec_daifmt { +enum { +HDMI_I2S , +HDMI_RIGHT_J , +HDMI_LEFT_J , +HDMI_DSP_A , +HDMI_DSP_B , +HDMI_AC97 , +HDMI_SPDIF , + } fmt; +int bit_clk_inv:1 ; +int frame_clk_inv:1 ; +int bit_clk_master:1 ; +int frame_clk_master:1 ; +}; + +/* +* HDMI audio parameters +*/ +struct hdmi_codec_params { +struct hdmi_audio_infoframe cea; +struct snd_aes_iec958 iec; +int sample_rate; +int sample_width; +int channels; +}; + +struct hdmi_codec_ops { +/* +* Called when ASoC starts an audio stream setup. +* Optional +*/ +int (*audio_startup)(struct device *dev); + +/* +* Configures HDMI-encoder for audio stream. +* Mandatory +*/ +int (*hw_params)(struct device *dev, +struct hdmi_codec_daifmt *fmt, +struct hdmi_codec_params *hparms); + +/* +* Shuts down the audio stream. +* Mandatory +*/ +void (*audio_shutdown)(struct device *dev); + +/* +* Mute/unmute HDMI audio stream. +* Optional +*/ +int (*digital_mute)(struct device *dev,bool enable); + +/* +* Provides EDID-Like-Data from connected HDMI device. +* Optional +*/ +int (*get_eld)(struct device *dev,uint8_t *buf,size_t len); +}; + +/* HDMI codec initalization data */ +struct hdmi_codec_pdata { +const struct hdmi_codec_ops *ops; +uint i2s:1 ; +uint spdif:1 ; +int max_i2s_channels; +}; + +#define HDMI_CODEC_DRV_NAME "hdmi-audio-codec" + +#endif /* __HDMI_CODEC_H__ */ sound/soc/codecs/Kconfig +6
-0@@ -86,6 +86,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MC13783 if MFD_MC13XXX select SND_SOC_ML26124 if I2C select SND_SOC_NAU8825 if I2C + select SND_SOC_HDMI_CODEC select SND_SOC_PCM1681 if I2C select SND_SOC_PCM179X if SPI_MASTER select SND_SOC_PCM3008@@ -473,6 +474,11 @@ config SND_SOC_BT_SCO config SND_SOC_DMIC tristate +config SND_SOC_HDMI_CODEC + tristate + select SND_PCM_ELD + select SND_PCM_IEC958 + config SND_SOC_ES8328 tristate "Everest Semi ES8328 CODEC"sound/soc/codecs/Makefile +2
-0@@ -79,6 +79,7 @@ snd-soc-max9850-objs := max9850.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o snd-soc-nau8825-objs := nau8825.o +snd-soc-hdmi-codec-objs := hdmi-codec.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm179x-codec-objs := pcm179x.o snd-soc-pcm3008-objs := pcm3008.o@@ -283,6 +284,7 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o +obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.osound/soc/codecs/hdmi-codec.c new file +396
-0@@ -0,0 +1,396 @@ +/* +* ALSA SoC codec for HDMI encoder drivers +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* Author: Jyri Sarha <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +*/ +#include <linux/module.h> +#include <linux/string.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/pcm_drm_eld.h> +#include <sound/hdmi-codec.h> +#include <sound/pcm_iec958.h> + +#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */ + +struct hdmi_codec_priv { +struct hdmi_codec_pdata hcd; +struct snd_soc_dai_driver *daidrv; +struct hdmi_codec_daifmt daifmt[2 ]; +struct mutex current_stream_lock; +struct snd_pcm_substream *current_stream; +struct snd_pcm_hw_constraint_list ratec; +uint8_t eld[MAX_ELD_BYTES ]; +}; + +static const struct snd_soc_dapm_widget hdmi_widgets[] = { +SND_SOC_DAPM_OUTPUT ("TX" ), +}; + +static const struct snd_soc_dapm_route hdmi_routes[] = { + {"TX" ,NULL ,"Playback" }, +}; + +enum { +DAI_ID_I2S =0 , +DAI_ID_SPDIF , +}; + +static int hdmi_codec_new_stream (struct snd_pcm_substream *substream, +struct snd_soc_dai *dai) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); +int ret =0 ; + +mutex_lock (&hcp->current_stream_lock); +if (!hcp->current_stream) { + hcp->current_stream = substream; + }else if (hcp->current_stream != substream) { +dev_err (dai->dev,"Only one simultaneous stream supported!\n" ); + ret = -EINVAL ; + } +mutex_unlock (&hcp->current_stream_lock); + +return ret; +} + +static int hdmi_codec_startup (struct snd_pcm_substream *substream, +struct snd_soc_dai *dai) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); +int ret =0 ; + +dev_dbg (dai->dev,"%s()\n" , __func__); + + ret =hdmi_codec_new_stream (substream, dai); +if (ret) +return ret; + +if (hcp->hcd.ops->audio_startup) { + ret = hcp->hcd.ops->audio_startup (dai->dev->parent); +if (ret) { +mutex_lock (&hcp->current_stream_lock); + hcp->current_stream =NULL ; +mutex_unlock (&hcp->current_stream_lock); +return ret; + } + } + +if (hcp->hcd.ops->get_eld) { + ret = hcp->hcd.ops->get_eld (dai->dev->parent, hcp->eld, +sizeof (hcp->eld)); + +if (!ret) { + ret =snd_pcm_hw_constraint_eld (substream->runtime, + hcp->eld); +if (ret) +return ret; + } + } +return 0 ; +} + +static void hdmi_codec_shutdown (struct snd_pcm_substream *substream, +struct snd_soc_dai *dai) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); + +dev_dbg (dai->dev,"%s()\n" , __func__); + +WARN_ON (hcp->current_stream != substream); + + hcp->hcd.ops->audio_shutdown (dai->dev->parent); + +mutex_lock (&hcp->current_stream_lock); + hcp->current_stream =NULL ; +mutex_unlock (&hcp->current_stream_lock); +} + +static int hdmi_codec_hw_params (struct snd_pcm_substream *substream, +struct snd_pcm_hw_params *params, +struct snd_soc_dai *dai) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); +struct hdmi_codec_params hp = { + .iec = { + .status = {0 }, + .subcode = {0 }, + .pad =0 , + .dig_subframe = {0 }, + } + }; +int ret; + +dev_dbg (dai->dev,"%s() width %d rate %d channels %d\n" , __func__, +params_width (params),params_rate (params), +params_channels (params)); + +if (params_width (params) >24 ) + params->msbits =24 ; + + ret =snd_pcm_create_iec958_consumer_hw_params (params, hp.iec.status, +sizeof (hp.iec.status)); +if (ret <0 ) { +dev_err (dai->dev,"Creating IEC958 channel status failed %d\n" , + ret); +return ret; + } + + ret =hdmi_codec_new_stream (substream, dai); +if (ret) +return ret; + +hdmi_audio_infoframe_init (&hp.cea); + hp.cea.channels =params_channels (params); + hp.cea.coding_type =HDMI_AUDIO_CODING_TYPE_STREAM ; + hp.cea.sample_size =HDMI_AUDIO_SAMPLE_SIZE_STREAM ; + hp.cea.sample_frequency =HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM ; + + hp.sample_width =params_width (params); + hp.sample_rate =params_rate (params); + hp.channels =params_channels (params); + +return hcp->hcd.ops->hw_params (dai->dev->parent, &hcp->daifmt[dai->id], + &hp); +} + +static int hdmi_codec_set_fmt (struct snd_soc_dai *dai, +unsigned int fmt) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); +struct hdmi_codec_daifmt cf = {0 }; +int ret =0 ; + +dev_dbg (dai->dev,"%s()\n" , __func__); + +if (dai->id ==DAI_ID_SPDIF ) { + cf.fmt =HDMI_SPDIF ; + }else { +switch (fmt &SND_SOC_DAIFMT_MASTER_MASK ) { +case SND_SOC_DAIFMT_CBM_CFM : + cf.bit_clk_master =1 ; + cf.frame_clk_master =1 ; +break ; +case SND_SOC_DAIFMT_CBS_CFM : + cf.frame_clk_master =1 ; +break ; +case SND_SOC_DAIFMT_CBM_CFS : + cf.bit_clk_master =1 ; +break ; +case SND_SOC_DAIFMT_CBS_CFS : +break ; +default : +return -EINVAL ; + } + +switch (fmt &SND_SOC_DAIFMT_INV_MASK ) { +case SND_SOC_DAIFMT_NB_NF : +break ; +case SND_SOC_DAIFMT_NB_IF : + cf.frame_clk_inv =1 ; +break ; +case SND_SOC_DAIFMT_IB_NF : + cf.bit_clk_inv =1 ; +break ; +case SND_SOC_DAIFMT_IB_IF : + cf.frame_clk_inv =1 ; + cf.bit_clk_inv =1 ; +break ; + } + +switch (fmt &SND_SOC_DAIFMT_FORMAT_MASK ) { +case SND_SOC_DAIFMT_I2S : + cf.fmt =HDMI_I2S ; +break ; +case SND_SOC_DAIFMT_DSP_A : + cf.fmt =HDMI_DSP_A ; +break ; +case SND_SOC_DAIFMT_DSP_B : + cf.fmt =HDMI_DSP_B ; +break ; +case SND_SOC_DAIFMT_RIGHT_J : + cf.fmt =HDMI_RIGHT_J ; +break ; +case SND_SOC_DAIFMT_LEFT_J : + cf.fmt =HDMI_LEFT_J ; +break ; +case SND_SOC_DAIFMT_AC97 : + cf.fmt =HDMI_AC97 ; +break ; +default : +dev_err (dai->dev,"Invalid DAI interface format\n" ); +return -EINVAL ; + } + } + + hcp->daifmt[dai->id] = cf; + +return ret; +} + +static int hdmi_codec_digital_mute (struct snd_soc_dai *dai,int mute) +{ +struct hdmi_codec_priv *hcp =snd_soc_dai_get_drvdata (dai); + +dev_dbg (dai->dev,"%s()\n" , __func__); + +if (hcp->hcd.ops->digital_mute) +return hcp->hcd.ops->digital_mute (dai->dev->parent, mute); + +return 0 ; +} + +static const struct snd_soc_dai_ops hdmi_dai_ops = { + .startup = hdmi_codec_startup, + .shutdown = hdmi_codec_shutdown, + .hw_params = hdmi_codec_hw_params, + .set_fmt = hdmi_codec_set_fmt, + .digital_mute = hdmi_codec_digital_mute, +}; + + +#define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define SPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) + +/* +* This list is only for formats allowed on the I2S bus. So there is +* some formats listed that are not supported by HDMI interface. For +* instance allowing the 32-bit formats enables 24-precision with CPU +* DAIs that do not support 24-bit formats. If the extra formats cause +* problems, we should add the video side driver an option to disable +* them. +*/ +#define I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) + +static struct snd_soc_dai_driver hdmi_i2s_dai = { + .name ="i2s-hifi" , + .id =DAI_ID_I2S , + .playback = { + .stream_name ="Playback" , + .channels_min =2 , + .channels_max =8 , + .rates =HDMI_RATES , + .formats =I2S_FORMATS , + .sig_bits =24 , + }, + .ops = &hdmi_dai_ops, +}; + +static const struct snd_soc_dai_driver hdmi_spdif_dai = { + .name ="spdif-hifi" , + .id =DAI_ID_SPDIF , + .playback = { + .stream_name ="Playback" , + .channels_min =2 , + .channels_max =2 , + .rates =HDMI_RATES , + .formats =SPDIF_FORMATS , + }, + .ops = &hdmi_dai_ops, +}; + +static struct snd_soc_codec_driver hdmi_codec = { + .dapm_widgets = hdmi_widgets, + .num_dapm_widgets =ARRAY_SIZE (hdmi_widgets), + .dapm_routes = hdmi_routes, + .num_dapm_routes =ARRAY_SIZE (hdmi_routes), +}; + +static int hdmi_codec_probe (struct platform_device *pdev) +{ +struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; +struct device *dev = &pdev->dev; +struct hdmi_codec_priv *hcp; +int dai_count, i =0 ; +int ret; + +dev_dbg (dev,"%s()\n" , __func__); + +if (!hcd) { +dev_err (dev,"%s: No plalform data\n" , __func__); +return -EINVAL ; + } + + dai_count = hcd->i2s + hcd->spdif; +if (dai_count <1 || !hcd->ops || !hcd->ops->hw_params || + !hcd->ops->audio_shutdown) { +dev_err (dev,"%s: Invalid parameters\n" , __func__); +return -EINVAL ; + } + + hcp =devm_kzalloc (dev,sizeof (*hcp),GFP_KERNEL ); +if (!hcp) +return -ENOMEM ; + + hcp->hcd = *hcd; +mutex_init (&hcp->current_stream_lock); + + hcp->daidrv =devm_kzalloc (dev, dai_count *sizeof (*hcp->daidrv), +GFP_KERNEL ); +if (!hcp->daidrv) +return -ENOMEM ; + +if (hcd->i2s) { + hcp->daidrv[i] = hdmi_i2s_dai; + hcp->daidrv[i].playback.channels_max = + hcd->max_i2s_channels; + i++; + } + +if (hcd->spdif) + hcp->daidrv[i] = hdmi_spdif_dai; + + ret =snd_soc_register_codec (dev, &hdmi_codec, hcp->daidrv, + dai_count); +if (ret) { +dev_err (dev,"%s: snd_soc_register_codec() failed (%d)\n" , + __func__, ret); +return ret; + } + +dev_set_drvdata (dev, hcp); +return 0 ; +} + +static int hdmi_codec_remove (struct platform_device *pdev) +{ +snd_soc_unregister_codec (&pdev->dev); +return 0 ; +} + +static struct platform_driver hdmi_codec_driver = { + .driver = { + .name =HDMI_CODEC_DRV_NAME , + }, + .probe = hdmi_codec_probe, + .remove = hdmi_codec_remove, +}; + +module_platform_driver (hdmi_codec_driver); + +MODULE_AUTHOR ("Jyri Sarha <[email protected]>" ); +MODULE_DESCRIPTION ("HDMI Audio Codec Driver" ); +MODULE_LICENSE ("GPL" ); +MODULE_ALIAS ("platform:" HDMI_CODEC_DRV_NAME );
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
Quoted 8 lines · Jyri Sarha
There is now two acks (and a tested-by?) to this patch and reviewed-by to an earlier version (with very small change this this one). I think it would make sense to apply this one now, even if there are no users to the driver just yet. Then all the video side users could (at least in theory) implement the HW specific hdmi audio support with video side patches only.
What do you think?
I applied it yesterday.
PATCH v9 4/7 ASoC: hdmi-codec: Add audio abort() callback for video side to use
In reply to Jyri SarhaAdd audio abort() callback, that is provided at audio stream start, for video side. This is for video side to use in case there is a pressing need to tear down the audio playback for some reason.
--- include/sound/hdmi-codec.h | 8 ++++++-- sound/soc/codecs/hdmi-codec.c | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-)
include/sound/hdmi-codec.h +6 -2
@@ -55,10 +55,14 @@ struct hdmi_codec_params {struct hdmi_codec_ops {/* -* Called when ASoC starts an audio stream setup. +* Called when ASoC starts an audio stream setup. The call +* provides an audio abort callback for stoping an ongoing +* stream from video side driver if the HDMI audio becomes +* unavailable. * Optional */ -int (*audio_startup)(struct device *dev); +int (*audio_startup)(struct device *dev, +void (*abort_cb)(struct device *dev));/* * Configures HDMI-encoder for audio stream.
sound/soc/codecs/hdmi-codec.c +19 -1
@@ -47,6 +47,23 @@ enum { DAI_ID_SPDIF, }; +static void hdmi_codec_abort (struct device *dev) +{ +struct hdmi_codec_priv *hcp =dev_get_drvdata (dev); + +dev_dbg (dev,"%s()\n" , __func__); + +mutex_lock (&hcp->current_stream_lock); +if (hcp->current_stream && hcp->current_stream->runtime && +snd_pcm_running (hcp->current_stream)) { +dev_info (dev,"HDMI audio playback aborted\n" ); +snd_pcm_stream_lock_irq (hcp->current_stream); +snd_pcm_stop (hcp->current_stream,SNDRV_PCM_STATE_DISCONNECTED ); +snd_pcm_stream_unlock_irq (hcp->current_stream); + } +mutex_unlock (&hcp->current_stream_lock); +} +static int hdmi_codec_new_stream (struct snd_pcm_substream *substream,struct snd_soc_dai *dai) {
@@ -78,7 +95,8 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,return ret;if (hcp->hcd.ops->audio_startup) { - ret = hcp->hcd.ops->audio_startup (dai->dev->parent); + ret = hcp->hcd.ops->audio_startup (dai->dev->parent, + hdmi_codec_abort);if (ret) {mutex_lock (&hcp->current_stream_lock); hcp->current_stream =NULL ;
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use
Quoted 15 lines · Jyri Sarha
Add audio
abort()callback, that is provided at audio stream start, for video side. This is for video side to use in case there is a pressing need to tear down the audio playback for some reason.Signed-off-by Jyri Sarha <[email protected]>--- include/sound/hdmi-codec.h | 8 ++++++-- sound/soc/codecs/hdmi-codec.c | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-)include/sound/hdmi-codec.h +0
-0
include/sound/hdmi-codec.h struct hdmi_codec_params { · line 59
Quoted 6 lines
include/sound/hdmi-codec.h +2
-1@@ -55,10 +55,14 @@ struct hdmi_codec_params {struct hdmi_codec_ops {/* -* Called when ASoC starts an audio stream setup. +* Called when ASoC starts an audio stream setup. The call +* provides an audio abort callback for stoping an ongoing
stopping
Quoted 25 lines
include/sound/hdmi-codec.h +4
-1+* stream from video side driver if the HDMI audio becomes +* unavailable. * Optional */ -int (*audio_startup)(struct device *dev); +int (*audio_startup)(struct device *dev, +void (*abort_cb)(struct device *dev));/* * Configures HDMI-encoder for audio stream. sound/soc/codecs/hdmi-codec.c +7
-0@@ -47,6 +47,23 @@ enum { DAI_ID_SPDIF, }; +static void hdmi_codec_abort (struct device *dev) +{ +struct hdmi_codec_priv *hcp =dev_get_drvdata (dev); + +dev_dbg (dev,"%s()\n" , __func__); + +mutex_lock (&hcp->current_stream_lock);
sound/soc/codecs/hdmi-codec.c enum { · line 66
Quoted 10 lines
sound/soc/codecs/hdmi-codec.c +10
-0+if (hcp->current_stream && hcp->current_stream->runtime && +snd_pcm_running (hcp->current_stream)) { +dev_info (dev,"HDMI audio playback aborted\n" ); +snd_pcm_stream_lock_irq (hcp->current_stream); +snd_pcm_stop (hcp->current_stream,SNDRV_PCM_STATE_DISCONNECTED ); +snd_pcm_stream_unlock_irq (hcp->current_stream); + } +mutex_unlock (&hcp->current_stream_lock); +} +
still not understand the need... i can not find a use case that justifies it.
As example, in case of HDMI plug/unplug i would not want that audio stream is stopped (live playback). From my point of view this should be a decision from user.
But as it is optional, I'm ok if need is justified.
Quoted 14 lines
sound/soc/codecs/hdmi-codec.c +2
-1static int hdmi_codec_new_stream (struct snd_pcm_substream *substream,struct snd_soc_dai *dai) {@@ -78,7 +95,8 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,return ret;if (hcp->hcd.ops->audio_startup) { - ret = hcp->hcd.ops->audio_startup (dai->dev->parent); + ret = hcp->hcd.ops->audio_startup (dai->dev->parent, + hdmi_codec_abort);if (ret) {mutex_lock (&hcp->current_stream_lock); hcp->current_stream =NULL ;
Re: [PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use
Quoted 58 lines · Arnaud Pouliquen
Quoted 15 lines · Jyri Sarha
Add audio
abort()callback, that is provided at audio stream start, for video side. This is for video side to use in case there is a pressing need to tear down the audio playback for some reason.Signed-off-by Jyri Sarha <[email protected]>--- include/sound/hdmi-codec.h | 8 ++++++-- sound/soc/codecs/hdmi-codec.c | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-)include/sound/hdmi-codec.h +0
-0include/sound/hdmi-codec.h struct hdmi_codec_params { · line 59
Quoted 6 lines
include/sound/hdmi-codec.h +2
-1@@ -55,10 +55,14 @@ struct hdmi_codec_params {struct hdmi_codec_ops {/* -* Called when ASoC starts an audio stream setup. +* Called when ASoC starts an audio stream setup. The call +* provides an audio abort callback for stoping an ongoing stopping
Quoted 33 lines
include/sound/hdmi-codec.h +4
-1+* stream from video side driver if the HDMI audio becomes +* unavailable. * Optional */ -int (*audio_startup)(struct device *dev); +int (*audio_startup)(struct device *dev, +void (*abort_cb)(struct device *dev));/* * Configures HDMI-encoder for audio stream. sound/soc/codecs/hdmi-codec.c +15
-0@@ -47,6 +47,23 @@ enum { DAI_ID_SPDIF, }; +static void hdmi_codec_abort (struct device *dev) +{ +struct hdmi_codec_priv *hcp =dev_get_drvdata (dev); + +dev_dbg (dev,"%s()\n" , __func__); + +mutex_lock (&hcp->current_stream_lock); +if (hcp->current_stream && hcp->current_stream->runtime && +snd_pcm_running (hcp->current_stream)) { +dev_info (dev,"HDMI audio playback aborted\n" ); +snd_pcm_stream_lock_irq (hcp->current_stream); +snd_pcm_stop (hcp->current_stream,SNDRV_PCM_STATE_DISCONNECTED ); +snd_pcm_stream_unlock_irq (hcp->current_stream); + } +mutex_unlock (&hcp->current_stream_lock);
Quoted 9 lines
sound/soc/codecs/hdmi-codec.c enum { · line 66
Quoted 2 lines
sound/soc/codecs/hdmi-codec.c +2
-0+} +still not understand the need... i can not find a use case that justifies it.
As example, in case of HDMI plug/unplug i would not want that audio stream is stopped (live playback). From my point of view this should be a decision from user.
But as it is optional, I'm ok if need is justified.
Well, I think we can drop this as there is no use for it ATM.
I copied this feature from my omap-hdmi-audio driver, where the display module on the SoC implements ASoC CPU-DAI itself. In that setup the DMA simply stops if the display is turned off, which eventually causes the audio stream to time out. However, it is unlikely to have a similar situation here, since the purpose is to implement ASoC codec DAI for an external HDMI encoder sitting behind i2s and/or spdif wires and the CPU-DAI can keep on playing the audio even if the whole encoder powered down. That is if the HDMI encoder does not provide the clocks for the DAI link. Anyway, we can add this feature later if there ever is a need for it.
Quoted 6 lines
Quoted 6 lines
sound/soc/codecs/hdmi-codec.c +0
-0static int hdmi_codec_new_stream (struct snd_pcm_substream *substream,struct snd_soc_dai *dai) {@@ -78,7 +95,8 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,return ret;
Quoted 8 lines
sound/soc/codecs/hdmi-codec.c static int hdmi_codec_startup(struct snd_pcm_substream *substream, · line 102
Quoted 8 lines
sound/soc/codecs/hdmi-codec.c +2
-1if (hcp->hcd.ops->audio_startup) { - ret = hcp->hcd.ops->audio_startup (dai->dev->parent); + ret = hcp->hcd.ops->audio_startup (dai->dev->parent, + hdmi_codec_abort);if (ret) {mutex_lock (&hcp->current_stream_lock); hcp->current_stream =NULL ;
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v9 5/7 drm/i2c: tda998x: Improve tda998x_configure_audio() audio related pdata
In reply to Jyri SarhaDefine struct tda998x_audio_params in include/drm/i2c/tda998x.h and use it in pdata and for tda998x_configure_audio() parameters. Also updates tda998x_write_aif() to take struct hdmi_audio_infoframe * directly as a parameter.
--- drivers/gpu/drm/i2c/tda998x_drv.c | 77 ++++++++++++++++++++------------------- include/drm/i2c/tda998x.h | 24 +++++++----- 2 files changed, 53 insertions(+), 48 deletions(-)
drivers/gpu/drm/i2c/tda998x_drv.c +39 -38
@@ -41,7 +41,7 @@ struct tda998x_priv {u8 vip_cntrl_0;u8 vip_cntrl_1;u8 vip_cntrl_2; -struct tda998x_encoder_params params; +struct tda998x_audio_params audio_params;wait_queue_head_t wq_edid;volatile int wq_edid_wait;
@@ -666,26 +666,16 @@ tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr,reg_set (priv,REG_DIP_IF_FLAGS , bit); } -static void -tda998x_write_aif (struct tda998x_priv *priv,struct tda998x_encoder_params *p) +static int tda998x_write_aif (struct tda998x_priv *priv, +struct hdmi_audio_infoframe *cea) {union hdmi_infoframe frame; -hdmi_audio_infoframe_init (&frame.audio); - - frame.audio.channels = p->audio_frame[1 ] &0x07 ; - frame.audio.channel_allocation = p->audio_frame[4 ]; - frame.audio.level_shift_value = (p->audio_frame[5 ] &0x78 ) >>3 ; - frame.audio.downmix_inhibit = (p->audio_frame[5 ] &0x80 ) >>7 ; - -/* -* L-PCM and IEC61937 compressed audio shall always set sample -* frequency to "refer to stream". For others, see the HDMI -* specification. -*/ - frame.audio.sample_frequency = (p->audio_frame[2 ] &0x1c ) >>2 ; + frame.audio = *cea;tda998x_write_if (priv,DIP_IF_FLAGS_IF4 ,REG_IF4_HB0 , &frame); + +return 0 ; } static void
@@ -710,20 +700,21 @@ static void tda998x_audio_mute(struct tda998x_priv *priv, bool on) } } -static void +static int tda998x_configure_audio (struct tda998x_priv *priv, -struct drm_display_mode *mode,struct tda998x_encoder_params *p) +struct tda998x_audio_params *params, +unsigned mode_clock) {u8 buf[6 ], clksel_aip, clksel_fs, cts_n, adiv;u32 n;/* Enable audio ports */ -reg_write (priv,REG_ENA_AP , p->audio_cfg); -reg_write (priv,REG_ENA_ACLK , p->audio_clk_cfg); +reg_write (priv,REG_ENA_AP , params->config);/* Set audio input source */ -switch (p->audio_format) { +switch (params->format) {case AFMT_SPDIF : +reg_write (priv,REG_ENA_ACLK ,0 );reg_write (priv,REG_MUX_AP ,MUX_AP_SELECT_SPDIF ); clksel_aip =AIP_CLKSEL_AIP_SPDIF ; clksel_fs =AIP_CLKSEL_FS_FS64SPDIF ;
@@ -731,15 +722,29 @@ tda998x_configure_audio(struct tda998x_priv *priv,break ;case AFMT_I2S : +reg_write (priv,REG_ENA_ACLK ,1 );reg_write (priv,REG_MUX_AP ,MUX_AP_SELECT_I2S ); clksel_aip =AIP_CLKSEL_AIP_I2S ; clksel_fs =AIP_CLKSEL_FS_ACLK ; - cts_n =CTS_N_M (3 ) |CTS_N_K (3 ); +switch (params->sample_width) { +case 16 : + cts_n =CTS_N_M (3 ) |CTS_N_K (1 ); +break ; +case 18 : +case 20 : +case 24 : + cts_n =CTS_N_M (3 ) |CTS_N_K (2 ); +break ; +default : +case 32 : + cts_n =CTS_N_M (3 ) |CTS_N_K (3 ); +break ; + }break ;default :BUG (); -return ; +return -EINVAL ; }reg_write (priv,REG_AIP_CLKSEL , clksel_aip);
@@ -755,11 +760,11 @@ tda998x_configure_audio(struct tda998x_priv *priv,* assume 100MHz requires larger divider. */ adiv =AUDIO_DIV_SERCLK_8 ; -if (mode->clock >100000 ) +if (mode_clock >100000 ) adiv++;/* AUDIO_DIV_SERCLK_16 */ /* S/PDIF asks for a larger divider */ -if (p->audio_format ==AFMT_SPDIF ) +if (params->format ==AFMT_SPDIF ) adiv++;/* AUDIO_DIV_SERCLK_16 or _32 */ reg_write (priv,REG_AUDIO_DIV , adiv);
@@ -768,7 +773,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,* This is the approximate value of N, which happens to be * the recommended values for non-coherent clocks. */ - n =128 * p->audio_sample_rate /1000 ; + n =128 * params->sample_rate /1000 ;/* Write the CTS and N values */ buf[0 ] =0x44 ;
@@ -787,19 +792,13 @@ tda998x_configure_audio(struct tda998x_priv *priv,reg_clear (priv,REG_AIP_CNTRL_0 ,AIP_CNTRL_0_RST_CTS );/* Write the channel status */ - buf[0 ] =IEC958_AES0_CON_NOT_COPYRIGHT ; - buf[1 ] =0x00 ; - buf[2 ] =IEC958_AES3_CON_FS_NOTID ; - buf[3 ] =IEC958_AES4_CON_ORIGFS_NOTID | -IEC958_AES4_CON_MAX_WORDLEN_24 ; -reg_write_range (priv,REG_CH_STAT_B (0 ), buf,4 ); +reg_write_range (priv,REG_CH_STAT_B (0 ), params->status,4 );tda998x_audio_mute (priv, true);msleep (20 );tda998x_audio_mute (priv, false); -/* Write the audio information packet */ -tda998x_write_aif (priv, p); +return tda998x_write_aif (priv, ¶ms->cea); }/* DRM encoder functions */
@@ -820,7 +819,7 @@ static void tda998x_encoder_set_config(struct tda998x_priv *priv,VIP_CNTRL_2_SWAP_F (p->swap_f) | (p->mirr_f ?VIP_CNTRL_2_MIRR_F :0 ); - priv->params = *p; + priv->audio_params = p->audio; }static void tda998x_encoder_dpms (struct drm_encoder *encoder,int mode)
@@ -1057,9 +1056,11 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,tda998x_write_avi (priv, adjusted_mode); -if (priv->params.audio_cfg) -tda998x_configure_audio (priv, adjusted_mode, - &priv->params); +if (priv->audio_params.format !=AFMT_UNUSED ) { +tda998x_configure_audio (priv, + &priv->audio_params, + adjusted_mode->clock); + } } }
include/drm/i2c/tda998x.h +14 -10
@@ -1,6 +1,19 @@ #ifndef __DRM_I2C_TDA998X_H__ #define __DRM_I2C_TDA998X_H__ +#define AFMT_UNUSED 0 +#define AFMT_SPDIF 1 +#define AFMT_I2S 2 + +struct tda998x_audio_params { + u8 config; + u8 format; + unsigned sample_width; + unsigned sample_rate; + struct hdmi_audio_infoframe cea; + u8 status[4]; +}; + struct tda998x_encoder_params { u8 swap_b:3; u8 mirr_b:1;
@@ -15,16 +28,7 @@ struct tda998x_encoder_params { u8 swap_e:3; u8 mirr_e:1; -u8 audio_cfg; -u8 audio_clk_cfg; -u8 audio_frame[6 ]; - -enum { -AFMT_SPDIF , -AFMT_I2S - } audio_format; - - unsigned audio_sample_rate; + struct tda998x_audio_params audio; };#endif
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v9 6/7 drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
In reply to Jyri SarhaRegister ASoC HDMI codec for audio functionality and adds device tree binding for audio configuration.
With the registered HDMI codec the tda998x node can be used like a regular codec node in ASoC card configurations. HDMI audio info-frame and audio stream header is generated by the ASoC HDMI codec. The codec also applies constraints for available sample-rates based on Edid Like Data from the display. The device tree binding document has been updated [1].
Part of this patch has been inspired by Jean Francoise's "drm/i2c: tda998x:
Add support of a DT graph of ports"-patch [2]. There may still be some identical lines left from the original patch and some of the ideas have come from there.
[1] Documentation/devicetree/bindings/display/bridge/tda998x.txt
[2] http://mailman.alsa-project.org/pipermail/alsa-devel/2015-July/095255.html
--- .../devicetree/bindings/display/bridge/tda998x.txt | 18 ++ drivers/gpu/drm/i2c/Kconfig | 1 + drivers/gpu/drm/i2c/tda998x_drv.c | 198 ++++++++++++++++++++- include/drm/i2c/tda998x.h | 4 +- include/dt-bindings/display/tda998x.h | 7 + 5 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 include/dt-bindings/display/tda998x.h
Documentation/devicetree/bindings/display/bridge/tda998x.txt +18 -0
@@ -21,8 +21,19 @@ Optional properties: - video-ports: 24 bits value which defines how the video controller output is wired to the TDA998x input - default: <0x230145> + - audio-ports: array of 8-bit values, 2 values per one DAI[1]. + The first value defines the DAI type: TDA998x_SPDIF or TDA998x_I2S[2]. + The second value defines the tda998x AP_ENA reg content when the DAI + in question is used. The implementation allows one or two DAIs. If two + DAIs are defined, they must be of different type. + +[1] Documentation/sound/alsa/soc/DAI.txt +[2] include/dt-bindings/display/tda998x.h + Example: +#include <dt-bindings/display/tda998x.h> + tda998x: hdmi-encoder { compatible = "nxp,tda998x"; reg = <0x70>;
@@ -30,4 +41,11 @@ Example: interrupts = <27 2>; /* falling edge */ pinctrl-0 = <&pmx_camera>; pinctrl-names = "default"; + video-ports = <0x230145>; + + #sound-dai-cells = <2>; + /* DAI-format AP_ENA reg value */ + audio-ports = < TDA998x_SPDIF 0x04 + TDA998x_I2S 0x03>; + };
drivers/gpu/drm/i2c/Kconfig +1 -0
@@ -28,6 +28,7 @@ config DRM_I2C_SIL164 config DRM_I2C_NXP_TDA998X tristate "NXP Semiconductors TDA998X HDMI encoder" default m if DRM_TILCDC + select SND_SOC_HDMI_CODEC if SND_SOC help Support for NXP Semiconductors TDA998X HDMI encoders.
drivers/gpu/drm/i2c/tda998x_drv.c +195 -3
261 lines not on this page · raw message
include/drm/i2c/tda998x.h +2 -2
@@ -1,9 +1,9 @@ #ifndef __DRM_I2C_TDA998X_H__ #define __DRM_I2C_TDA998X_H__ +#include <dt-bindings/display/tda998x.h> + #define AFMT_UNUSED 0 -#define AFMT_SPDIF 1 -#define AFMT_I2S 2 struct tda998x_audio_params { u8 config;
include/dt-bindings/display/tda998x.h new file +7 -0
@@ -0,0 +1,7 @@ +#ifndef _DT_BINDINGS_TDA998X_H +#define _DT_BINDINGS_TDA998X_H + +#define AFMT_SPDIF 1 +#define AFMT_I2S 2 + +#endif /*_DT_BINDINGS_TDA998X_H */
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v9 6/7] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
Quoted 33 lines · Jyri Sarha
Register ASoC HDMI codec for audio functionality and adds device tree binding for audio configuration.
With the registered HDMI codec the tda998x node can be used like a regular codec node in ASoC card configurations. HDMI audio info-frame and audio stream header is generated by the ASoC HDMI codec. The codec also applies constraints for available sample-rates based on Edid Like Data from the display. The device tree binding document has been updated [1].
Part of this patch has been inspired by Jean Francoise's "drm/i2c: tda998x:
Add support of a DT graph of ports"-patch [2]. There may still be some identical lines left from the original patch and some of the ideas have come from there.[1]
Documentation/devicetree/bindings/display/bridge/tda998x.txt
[2] http://mailman.alsa-project.org/pipermail/alsa-devel/2015-July/095255.htmlSigned-off-by Jyri Sarha <[email protected]>--- .../devicetree/bindings/display/bridge/tda998x.txt | 18 ++ drivers/gpu/drm/i2c/Kconfig | 1 + drivers/gpu/drm/i2c/tda998x_drv.c | 198 ++++++++++++++++++++- include/drm/i2c/tda998x.h | 4 +- include/dt-bindings/display/tda998x.h | 7 + 5 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 include/dt-bindings/display/tda998x.hDocumentation/devicetree/bindings/display/bridge/tda998x.txt +0
-0
Documentation/devicetree/bindings/display/bridge/tda998x.txt Optional properties: · line 24
Quoted 4 lines
Documentation/devicetree/bindings/display/bridge/tda998x.txt +1
-0@@ -21,8 +21,19 @@ Optional properties: - video-ports: 24 bits value which defines how the video controller output is wired to the TDA998x input - default: <0x230145> + - audio-ports: array of 8-bit values, 2 values per one DAI[1].
This should have nxp prefix. With that,
Quoted 17 lines
Documentation/devicetree/bindings/display/bridge/tda998x.txt +10
-0+ The first value defines the DAI type: TDA998x_SPDIF or TDA998x_I2S[2]. + The second value defines the tda998x AP_ENA reg content when the DAI + in question is used. The implementation allows one or two DAIs. If two + DAIs are defined, they must be of different type. + +[1] Documentation/sound/alsa/soc/DAI.txt +[2] include/dt-bindings/display/tda998x.h + Example: +#include <dt-bindings/display/tda998x.h> + tda998x: hdmi-encoder { compatible = "nxp,tda998x"; reg = <0x70>;@@ -30,4 +41,11 @@ Example: interrupts = <27 2>; /* falling edge */
Documentation/devicetree/bindings/display/bridge/tda998x.txt Example: · line 51
Quoted 10 lines
Documentation/devicetree/bindings/display/bridge/tda998x.txt +7
-0pinctrl-0 = <&pmx_camera>; pinctrl-names = "default"; + video-ports = <0x230145>; + + #sound-dai-cells = <2>; + /* DAI-format AP_ENA reg value */ + audio-ports = < TDA998x_SPDIF 0x04 + TDA998x_I2S 0x03>; + };
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v9 7/7 ARM: dts: am335x-boneblack: Add HDMI audio support
In reply to Jyri SarhaAdd HDMI audio support. Adds mcasp0_pins, clk_mcasp0_fixed, clk_mcasp0, mcasp0, sound node, and updates the tda19988 node to follow the new binding.
--- arch/arm/boot/dts/am335x-boneblack.dts | 71 ++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 4 deletions(-)
arch/arm/boot/dts/am335x-boneblack.dts +67 -4
@@ -9,6 +9,7 @@ #include "am33xx.dtsi" #include "am335x-bone-common.dtsi" +#include <dt-bindings/display/tda998x.h> / { model = "TI AM335x BeagleBone Black";
@@ -64,6 +65,16 @@ AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */ >; }; + + mcasp0_pins: mcasp0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */ + AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/ + AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */ + AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */ + AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */ + >; + }; }; &lcdc {
@@ -76,16 +87,22 @@ }; &i2c0 { - tda19988 { + tda19988: tda19988 { compatible = "nxp,tda998x"; reg = <0x70>; + pinctrl-names = "default", "off"; pinctrl-0 = <&nxp_hdmi_bonelt_pins>; pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; - port { - hdmi_0: endpoint@0 { - remote-endpoint = <&lcdc_0>; + #sound-dai-cells = <0>; + audio-ports = < AFMT_I2S 0x03>; + + ports { + port@0 { + hdmi_0: endpoint@0 { + remote-endpoint = <&lcdc_0>; + }; }; }; };
@@ -94,3 +111,49 @@ &rtc { system-power-controller; }; + +&mcasp0 { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcasp0_pins>; + status = "okay"; + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 0 0 1 0 + >; + tx-num-evt = <32>; + rx-num-evt = <32>; +}; + +/ { + clk_mcasp0_fixed: clk_mcasp0_fixed { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24576000>; + }; + + clk_mcasp0: clk_mcasp0 { + #clock-cells = <0>; + compatible = "gpio-gate-clock"; + clocks = <&clk_mcasp0_fixed>; + enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */ + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "TI BeagleBone Black"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&dailink0_master>; + simple-audio-card,frame-master = <&dailink0_master>; + + dailink0_master: simple-audio-card,cpu { + sound-dai = <&mcasp0>; + clocks = <&clk_mcasp0>; + }; + + simple-audio-card,codec { + sound-dai = <&tda19988>; + }; + }; +};
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Mark Brown
maintainerQuoted 7 lines · Jyri Sarha
Couple of minor changes since v8 to ALSA/ASoC side patches. The series is based on top of drm-next. However, it does not look like there is enough attention to the DRM side so that the tda998x patches would get in any time soon. So I am happy to rebase the first ALSA-side patches on top of Mark Brown's for-next tree, for instance, if they would have a change to go in on their own. The first two IEC958 helper patches should apply as such.
None of the ASoC specific patches here have had any review from other HDMI users?
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 9 lines · Mark Brown
Quoted 7 lines · Jyri Sarha
Couple of minor changes since v8 to ALSA/ASoC side patches. The series is based on top of drm-next. However, it does not look like there is enough attention to the DRM side so that the tda998x patches would get in any time soon. So I am happy to rebase the first ALSA-side patches on top of Mark Brown's for-next tree, for instance, if they would have a change to go in on their own. The first two IEC958 helper patches should apply as such.
Quoted 3 lines
None of the ASoC specific patches here have had any review from other HDMI users?
I got ack from Arnaud Pouliquen and tested-by from Philipp Zabel for "ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders" in previous version of the series. Since then there is one minimal change, but because I touched the patch I removed the ack and tested-by tags.
The change is setting hw_params->msbits to 24 in hw_params() callback if sample width is greater than 24 bits.
Best regards,
Jyri
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Mark Brown
maintainerQuoted 9 lines · Jyri Sarha
Quoted 2 lines · Mark Brown
None of the ASoC specific patches here have had any review from other HDMI users?
I got ack from Arnaud Pouliquen and tested-by from Philipp Zabel for "ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders" in previous version of the series. Since then there is one minimal change, but because I touched the patch I removed the ack and tested-by tags.
Yes, I remember but if you think the change is big enough to warrant removing the tags I'm hoping to see some interest in review!
Quoted 2 lines
The change is setting
hw_params->msbitsto 24 inhw_params()callback if sample width is greater than 24 bits.
That is reasonably small though...
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel