Implement generic ASoC HDMI codec and use it in tda998x
Subsystems (7)
v6 cover Implement generic ASoC HDMI codec and use it in tda998x
There is currently two other patch series[1][2] that depend on the three first (ALSA-) patches of this series. It would be nice to get at least those three applied sooner rather than later, so please tell me if I can do anything to get those in.
BTW, I applied the relevant patches from the two series to on top of this one. Obviously the two series conflicted with each other a bit and also the IEC958 helper patch from [2] conflicted with the IEC958 patch from my series (which is weird since Arnaud's series depends on my series...). After resolving the conflicts everything compiled fine, but for some reason neither the 'ELD' or IEC958 Playback Default' appeared on my BBB. I'll try to find time to debug this further at some point.
[1] http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105509.html
[2] http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105502.html
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 (6):
ALSA: pcm: add IEC958 channel status helper for hw_params
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 | 271 ++++++++++++-- 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 | 53 ++- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/hdmi-codec.c | 411 +++++++++++++++++++++ 12 files changed, 898 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 v6 1/6 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 | 53 +++++++++++++++++++++++++++++++--------------- 2 files changed, 38 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 +36 -17
83 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 v6 1/6] ALSA: pcm: add IEC958 channel status helper for hw_params
Hello Jyri,
With few nitpicking remarks on form.
Regards
Arnaud
Quoted 88 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]>--- include/sound/pcm_iec958.h | 2 ++ sound/core/pcm_iec958.c | 53 +++++++++++++++++++++++++++++++--------------- 2 files changed, 38 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 +12
-17@@ -9,30 +9,18 @@#include <linux/types.h> #include <sound/asoundef.h> #include <sound/pcm.h> +#include <sound/pcm_params.h> #include <sound/pcm_iec958.h> -/** -* snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status -* @runtime: pcm runtime structure with ->rate filled in -* @cs: channel status buffer, at least four bytes -* @len: length of channel status buffer -* -* Create the consumer format channel status data in @cs of maximum size -* @len corresponding to the parameters of the PCM runtime @runtime. -* -* Drivers may wish to tweak the contents of the buffer after creation. -* -* Returns: length of buffer, or negative error code if something failed. -*/ -int snd_pcm_create_iec958_consumer (struct snd_pcm_runtime *runtime,u8 *cs, -size_t len) +static int create_iec958_consumer (uint rate,uint sample_width, +u8 *cs,size_t len) {unsigned int fs, ws;if (len <4 )return -EINVAL ; -switch (runtime->rate) { +switch (rate) {case 32000 : fs =IEC958_AES3_CON_FS_32000 ;break ;@@ -59,7 +47,7 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, }if (len >4 ) { -switch (snd_pcm_format_width (runtime->format)) { +switch (sample_width) {case 16 : ws =IEC958_AES4_CON_WORDLEN_20_16 ;break ;@@ -71,6 +59,7 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,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 ;@@ -92,4 +81,34 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,return len; } + +/** +* snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status +* @runtime: pcm runtime structure with ->rate filled in +* @cs: channel status buffer, at least four bytes +* @len: length of channel status buffer
sound/core/pcm_iec958.c int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, · line 99
Quoted 10 lines
sound/core/pcm_iec958.c +10
-0+* +* Create the consumer format channel status data in @cs of maximum size +* @len corresponding to the parameters of the PCM runtime @runtime. +* +* Drivers may wish to tweak the contents of the buffer after creation. +* +* Returns: length of buffer, or negative error code if something failed. +*/ +int snd_pcm_create_iec958_consumer (struct snd_pcm_runtime *runtime,u8 *cs, +size_t len)
should be aligned on parenthesis
sound/core/pcm_iec958.c int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, · line 107
Quoted 8 lines
sound/core/pcm_iec958.c +7
-0+{ +return create_iec958_consumer (runtime->rate, +snd_pcm_format_width (runtime->format), + cs, len); +}EXPORT_SYMBOL (snd_pcm_create_iec958_consumer); + +
No kernel-doc comment?
sound/core/pcm_iec958.c int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, · line 108
Quoted 1 line
sound/core/pcm_iec958.c +1
-0+int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
Could be snd_pcm_hw_params_create_iec958_consumer to be coherent with functions declared in pcm.h
sound/core/pcm_iec958.c int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, · line 109
Quoted 1 line
sound/core/pcm_iec958.c +1
-0+ u8 *cs, size_t len)
should be aligned on parenthesis
Quoted 6 lines
sound/core/pcm_iec958.c +5
-0+{ +return create_iec958_consumer (params_rate (params),params_width (params), + cs, len); +} +EXPORT_SYMBOL (snd_pcm_create_iec958_consumer_hw_params);
Re: [PATCH v6 1/6] ALSA: pcm: add IEC958 channel status helper for hw_params
Quoted 109 lines · Arnaud Pouliquen
Hello Jyri,
Acked-by Arnaud Pouliquen <[email protected]>With few nitpicking remarks on form.
Regards
ArnaudQuoted 88 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]>--- include/sound/pcm_iec958.h | 2 ++ sound/core/pcm_iec958.c | 53 +++++++++++++++++++++++++++++++--------------- 2 files changed, 38 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 +12
-17@@ -9,30 +9,18 @@#include <linux/types.h> #include <sound/asoundef.h> #include <sound/pcm.h> +#include <sound/pcm_params.h> #include <sound/pcm_iec958.h> -/** -* snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status -* @runtime: pcm runtime structure with ->rate filled in -* @cs: channel status buffer, at least four bytes -* @len: length of channel status buffer -* -* Create the consumer format channel status data in @cs of maximum size -* @len corresponding to the parameters of the PCM runtime @runtime. -* -* Drivers may wish to tweak the contents of the buffer after creation. -* -* Returns: length of buffer, or negative error code if something failed. -*/ -int snd_pcm_create_iec958_consumer (struct snd_pcm_runtime *runtime,u8 *cs, -size_t len) +static int create_iec958_consumer (uint rate,uint sample_width, +u8 *cs,size_t len) {unsigned int fs, ws;if (len <4 )return -EINVAL ; -switch (runtime->rate) { +switch (rate) {case 32000 : fs =IEC958_AES3_CON_FS_32000 ;break ;@@ -59,7 +47,7 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, }if (len >4 ) { -switch (snd_pcm_format_width (runtime->format)) { +switch (sample_width) {case 16 : ws =IEC958_AES4_CON_WORDLEN_20_16 ;break ;@@ -71,6 +59,7 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,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 ;@@ -92,4 +81,34 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,return len; } + +/** +* snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status +* @runtime: pcm runtime structure with ->rate filled in +* @cs: channel status buffer, at least four bytes +* @len: length of channel status buffer sound/core/pcm_iec958.c int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, · line 99
Quoted 10 lines
sound/core/pcm_iec958.c +10
-0+* +* Create the consumer format channel status data in @cs of maximum size +* @len corresponding to the parameters of the PCM runtime @runtime. +* +* Drivers may wish to tweak the contents of the buffer after creation. +* +* Returns: length of buffer, or negative error code if something failed. +*/ +int snd_pcm_create_iec958_consumer (struct snd_pcm_runtime *runtime,u8 *cs, +size_t len)should be aligned on parenthesis
Quoted 9 lines
sound/core/pcm_iec958.c int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, · line 107
Quoted 8 lines
sound/core/pcm_iec958.c +7
-0+{ +return create_iec958_consumer (runtime->rate, +snd_pcm_format_width (runtime->format), + cs, len); +}EXPORT_SYMBOL (snd_pcm_create_iec958_consumer); + +No kernel-doc comment?
Oh yes. It'll be mostly redundant with snd_pcm_create_iec958_consumer() but still it should be there.
Quoted 3 lines
sound/core/pcm_iec958.c int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, · line 108
Quoted 1 line
sound/core/pcm_iec958.c +1
-0+int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,Could be
snd_pcm_hw_params_create_iec958_consumerto be coherent with functions declared inpcm.h
I feel that iec958 should be earlier in the name because it is the common denominator in this c-file. Then again I have no strong opinions about this.
Quoted 2 lines
sound/core/pcm_iec958.c int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, · line 109
Quoted 1 line
sound/core/pcm_iec958.c +1
-0+ u8 *cs, size_t len)should be aligned on parenthesis
But it is. It just that the diff '+'-sign pushes the line above one char right, but the line bellow is not pushed because it indented with tabs (like it should be).
Quoted 6 lines
sound/core/pcm_iec958.c int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, · line 114
Quoted 6 lines
sound/core/pcm_iec958.c +5
-0+{ +return create_iec958_consumer (params_rate (params),params_width (params), + cs, len); +} +EXPORT_SYMBOL (snd_pcm_create_iec958_consumer_hw_params);
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Mark Brown
maintainerRe: [PATCH v6 1/6] ALSA: pcm: add IEC958 channel status helper for hw_params
In reply to Jyri SarhaQuoted 4 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.
Takashi, are you OK with this one?
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v6 2/6 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 | 393 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 501 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 +393 -0
393 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 v6 2/6] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
Hello Jyri,
Tested with success on sti platform
Regards
Arnaud
Quoted 569 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 | 393 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 501 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 +393
-0@@ -0,0 +1,393 @@ +/* +* 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)); + + 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 );
Re: [PATCH v6 2/6] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
In reply to Jyri SarhaHi Jyri,
Am Dienstag, den 08.03.2016, 22:14 +0200 schrieb Jyri Sarha:
Quoted 10 lines
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]>
on mt8173
regards
Philipp
_______________________________________________
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): 6269edecc567c7b1431b023bc812f0309db99273.1457465383.git.jsarha-l0cyMroinI0@public.gmane.org
Philipp Zabel
Acked-byRe: [PATCH v6 2/6] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
Hi Jyri,
Am Dienstag, den 08.03.2016, 22:14 +0200 schrieb Jyri Sarha:
Quoted 10 lines
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]>
Tested on mt8173,
regards
Philipp
--
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
PATCH v6 3/6 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
PATCH v6 4/6 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 v6 5/6 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 | 194 ++++++++++++++++++++- include/drm/i2c/tda998x.h | 4 +- include/dt-bindings/display/tda998x.h | 7 + 5 files changed, 219 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 +191 -3
257 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
A message that is not in the archive (sent off-list or not yet received): 7e2cd007e1ea3217c817fb4e7782b0bfe11ea56c.1457465383.git.jsarha-l0cyMroinI0@public.gmane.org
kbuild test robot
build bot[PATCH] drm/i2c: tda998x: fix ptr_ret.cocci warnings
drivers/gpu/drm/i2c/tda998x_drv.c:1329:1-3: WARNING: PTR_ERR_OR_ZERO can be used
drivers/gpu/drm/i2c/tda998x_drv.c:1329:1-3: WARNING: PTR_ERR_OR_ZERO can be used
Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR
Generated by: scripts/coccinelle/api/ptr_ret.cocci
---
tda998x_drv.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/gpu/drm/i2c/tda998x_drv.c +1 -4
@@ -1326,10 +1326,7 @@ static int tda998x_audio_codec_init(stru dev,HDMI_CODEC_DRV_NAME ,PLATFORM_DEVID_AUTO , &codec_data, sizeof(codec_data)); -if (IS_ERR (priv->audio_pdev)) -return PTR_ERR (priv->audio_pdev); - -return 0 ; +return PTR_ERR_OR_ZERO (priv->audio_pdev); }/* I2C driver functions */
--
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
kbuild test robot
build botRe: [PATCH v6 5/6] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
In reply to a message not in the archivecoccinelle warnings: (new ones prefixed by >>)
Hi Jyri,
[auto build test WARNING on drm/drm-next]
[also build test WARNING on v4.5-rc7 next-20160308]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
url: https://github.com/0day-ci/linux/commits/Jyri-Sarha/Implement-generic-ASoC-HDMI-codec-and-use-it-in-tda998x/20160309-041821 base: git://people.freedesktop.org/~airlied/linux.git drm-next
coccinelle warnings: (new ones prefixed by >>)
>> drivers/gpu/drm/i2c/tda998x_drv.c:1329:1-3: WARNING: PTR_ERR_OR_ZERO can be used
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
--
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
kbuild test robot
build botRe: [PATCH v6 5/6] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
In reply to a message not in the archivereproduce:
Hi Jyri,
[auto build test WARNING on drm/drm-next]
[also build test WARNING on v4.5-rc7 next-20160309]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
url: https://github.com/0day-ci/linux/commits/Jyri-Sarha/Implement-generic-ASoC-HDMI-codec-and-use-it-in-tda998x/20160309-041821 base: git://people.freedesktop.org/~airlied/linux.git drm-next config: x86_64-rhel (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64
All warnings (new ones prefixed by >>):
drivers/gpu/drm/i2c/tda998x_drv.c: In function 'tda998x_get_audio_ports':
>> drivers/gpu/drm/i2c/tda998x_drv.c:1345:7: warning: 'size' is used uninitialized in this function [-Wuninitialized]
size /= sizeof(u32);
^vim +/size +1345 drivers/gpu/drm/i2c/tda998x_drv.c
1329 if (IS_ERR(priv->audio_pdev))
1330 return PTR_ERR(priv->audio_pdev);
1331
1332 return 0;
1333 }
1334
1335 /* I2C driver functions */
1336
1337 static int tda998x_get_audio_ports(struct tda998x_priv *priv,
1338 struct device_node *np)
1339 {
1340 const u32 *port_data;
1341 u32 size;
1342 int i;
1343
1344 port_data = of_get_property(np, "audio-ports", &size);
> 1345 size /= sizeof(u32);
1346
1347 if (size > 2 * ARRAY_SIZE(priv->audio_port) || size % 2 != 0) {
1348 dev_err(&priv->hdmi->dev,
1349 "Bad number of elements in audio-ports dt-property\n");
1350 return -EINVAL;
1351 }
1352
1353 size /= 2;
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Re: [PATCH v6 5/6] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
Quoted 22 lines · kbuild test robot
Hi Jyri,
[auto build test WARNING on drm/drm-next]
[also build test WARNING on v4.5-rc7 next-20160309]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]url: https://github.com/0day-ci/linux/commits/Jyri-Sarha/Implement-generic-ASoC-HDMI-codec-and-use-it-in-tda998x/20160309-041821 base: git://people.freedesktop.org/~airlied/linux.git drm-next config: x86_64-rhel (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64All warnings (new ones prefixed by >>):
drivers/gpu/drm/i2c/tda998x_drv.c: In function 'tda998x_get_audio_ports':Quoted 1 line
Quoted 1 line
drivers/gpu/drm/i2c/tda998x_drv.c:1345:7: warning: 'size' is used uninitialized in this function [-Wuninitialized]size /= sizeof(u32); ^vim +/size +1345
drivers/gpu/drm/i2c/tda998x_drv.c
Quoted 17 lines
1329 if (IS_ERR(priv->audio_pdev)) 1330 return PTR_ERR(priv->audio_pdev); 1331 1332 return 0; 1333 } 1334 1335 /* I2C driver functions */ 1336 1337 static int tda998x_get_audio_ports(struct tda998x_priv *priv, 1338 struct device_node *np) 1339 { 1340 const u32 *port_data; 1341 u32 size; 1342 int i; 1343 1344 port_data = of_get_property(np, "audio-ports", &size);Quoted 1 line
1345 size /= sizeof(u32);
Oops, that is a real bug. I should test if port_data is not null before assuming that the size has been set (/me thinks that he had that line there at some point but then it vanished). Actually initializing size to 0 would be enough, but I think I'll do the both just to be more explicit.
And I'll start using PTR_ERR_OR_ZERO() while I am at it.
Quoted 9 lines
1346
1347 if (size > 2 * ARRAY_SIZE(priv->audio_port) || size % 2 != 0) {
1348 dev_err(&priv->hdmi->dev,
1349 "Bad number of elements in audio-ports dt-property\n");
1350 return -EINVAL;
1351 }
1352
1353 size /= 2;Quoted 4 lines
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v6 6/6 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 4 lines · Jyri Sarha
There is currently two other patch series[1][2] that depend on the three first (ALSA-) patches of this series. It would be nice to get at least those three applied sooner rather than later, so please tell me if I can do anything to get those in.
It would be good if the people working on those other series could review this code then - there's no Reviwed-by or Acked-by on those patches or anything like that. This is what I mean about a lack of visible collaboration, there is no real enagagment that can be seen here.
_______________________________________________
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): [email protected]
Quoted 4 lines · Jyri Sarha
There is currently two other patch series[1][2] that depend on the
[1] http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105509.html
[2] http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105502.html
Oh, and as usual please provide human readable descriptions of things especially for the benefit of those working offline or with spotty network connections.