[PATCH RFC 0/4] Add HDMI support for Intel KeemBay I2S
The below patch series are to support Audio over HDMI. The modification in this patch series shall allow I2S driver to playback standard PCM format and IEC958 encoded format to the ADV7511 HDMI chip.
ALSA IEC958 plugin will be used to compose the IEC958 format.
Existing hdmi-codec driver only support standard pcm format. Support of IEC958 encoded format passdown from ALSA IEC958 plugin is needed so that the IEC958 encoded data can be streamed to the HDMI chip.
Sia Jee Heng (4): ASoC: codec: hdmi-codec: Support IEC958 encoded PCM format drm: bridge: adv7511: Support I2S IEC958 encoded PCM format dt-bindings: sound: Intel, Keembay-i2s: Add hdmi-i2s compatible string ASoC: Intel: KMB: Support IEC958 encoded PCM format
.../bindings/sound/intel,keembay-i2s.yaml | 1 + drivers/gpu/drm/bridge/adv7511/adv7511.h | 1 + .../gpu/drm/bridge/adv7511/adv7511_audio.c | 6 ++ include/sound/hdmi-codec.h | 5 ++ sound/soc/codecs/hdmi-codec.c | 4 +- sound/soc/intel/keembay/kmb_platform.c | 73 ++++++++++++++++++- sound/soc/intel/keembay/kmb_platform.h | 1 + 7 files changed, 89 insertions(+), 2 deletions(-)
base-commit: 2557c711b87cd42bb22be9ca6ff3fce038624f30
Existing hdmi-codec driver only support standard pcm format. Support of IEC958 encoded format pass from ALSA IEC958 plugin is needed so that the IEC958 encoded data can be streamed to the HDMI chip.
Signed-off-by: Sia Jee Heng jee.heng.sia@intel.com --- include/sound/hdmi-codec.h | 5 +++++ sound/soc/codecs/hdmi-codec.c | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h index b55970859a13..4b3a1d374b90 100644 --- a/include/sound/hdmi-codec.h +++ b/include/sound/hdmi-codec.h @@ -34,6 +34,11 @@ struct hdmi_codec_daifmt { unsigned int frame_clk_inv:1; unsigned int bit_clk_master:1; unsigned int frame_clk_master:1; + /* bit_fmt could be standard PCM format or + * IEC958 encoded format. ALSA IEC958 plugin will pass + * IEC958_SUBFRAME format to the underneath driver. + */ + snd_pcm_format_t bit_fmt; };
/* diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 0f3ac22f2cf8..422539f933de 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -489,6 +489,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, hp.sample_rate = params_rate(params); hp.channels = params_channels(params);
+ cf->bit_fmt = params_format(params); return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data, cf, &hp); } @@ -617,7 +618,8 @@ static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = { 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) + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\ + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
Support IEC958 encoded PCM format for ADV7511 so that ADV7511 HDMI audio driver can accept the IEC958 data from the I2S input.
Signed-off-by: Sia Jee Heng jee.heng.sia@intel.com --- drivers/gpu/drm/bridge/adv7511/adv7511.h | 1 + drivers/gpu/drm/bridge/adv7511/adv7511_audio.c | 6 ++++++ 2 files changed, 7 insertions(+)
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h index a9bb734366ae..05e3abb5a0c9 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511.h +++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h @@ -191,6 +191,7 @@ #define ADV7511_I2S_FORMAT_I2S 0 #define ADV7511_I2S_FORMAT_RIGHT_J 1 #define ADV7511_I2S_FORMAT_LEFT_J 2 +#define ADV7511_I2S_IEC958_DIRECT 3
#define ADV7511_PACKET(p, x) ((p) * 0x20 + (x)) #define ADV7511_PACKET_SDP(x) ADV7511_PACKET(0, x) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c index 45838bd08d37..61f4a38e7d2b 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c @@ -101,6 +101,10 @@ static int adv7511_hdmi_hw_params(struct device *dev, void *data, case 20: len = ADV7511_I2S_SAMPLE_LEN_20; break; + case 32: + if (fmt->bit_fmt != SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE) + return -EINVAL; + fallthrough; case 24: len = ADV7511_I2S_SAMPLE_LEN_24; break; @@ -112,6 +116,8 @@ static int adv7511_hdmi_hw_params(struct device *dev, void *data, case HDMI_I2S: audio_source = ADV7511_AUDIO_SOURCE_I2S; i2s_format = ADV7511_I2S_FORMAT_I2S; + if (fmt->bit_fmt == SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE) + i2s_format = ADV7511_I2S_IEC958_DIRECT; break; case HDMI_RIGHT_J: audio_source = ADV7511_AUDIO_SOURCE_I2S;
Add intel,keembay-hdmi-i2s compatible string to support the HDMI interface.
Signed-off-by: Sia Jee Heng jee.heng.sia@intel.com --- Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml | 1 + 1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml index dba25c33f0b0..6f71294909a5 100644 --- a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml @@ -18,6 +18,7 @@ properties: enum: - intel,keembay-i2s - intel,keembay-tdm + - intel,keembay-hdmi-i2s
"#sound-dai-cells": const: 0
Support ALSA IEC958 plugin for KeemBay I2S driver. Bit manipulation needed as IEC958 format supported by ADV7511 HDMI chip is not compatible with the ALSA IEC958 plugin format.
Signed-off-by: Sia Jee Heng jee.heng.sia@intel.com --- sound/soc/intel/keembay/kmb_platform.c | 73 +++++++++++++++++++++++++- sound/soc/intel/keembay/kmb_platform.h | 1 + 2 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index 4961ba89c110..0fd1e8f62c89 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -5,6 +5,7 @@ // Intel KeemBay Platform driver. //
+#include <linux/bitrev.h> #include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/io.h> @@ -39,7 +40,8 @@ static const struct snd_pcm_hardware kmb_pcm_hardware = { .rate_max = 48000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, .channels_min = 2, .channels_max = 2, .buffer_bytes_max = BUFFER_BYTES_MAX, @@ -50,6 +52,50 @@ static const struct snd_pcm_hardware kmb_pcm_hardware = { .fifo_size = 16, };
+/* + * Convert to ADV7511 HDMI hardware format. + * ADV7511 HDMI chip need parity bit replaced by block start bit and + * with the preamble bits left out. + * ALSA IEC958 subframe format: + * bit 0-3 = preamble (0x8 = block start) + * 4-7 = AUX (=0) + * 8-27 = audio data (without AUX if 24bit sample) + * 28 = validity + * 29 = user data + * 30 = channel status + * 31 = parity + * + * ADV7511 IEC958 subframe format: + * bit 0-23 = audio data + * 24 = validity + * 25 = user data + * 26 = channel status + * 27 = block start + * 28-31 = 0 + * MSB to LSB bit reverse by software as hardware not supporting it. + */ +static void hdmi_reformat_iec958(struct snd_pcm_runtime *runtime, + struct kmb_i2s_info *kmb_i2s, + unsigned int tx_ptr) +{ + u32(*buf)[2] = (void *)runtime->dma_area; + unsigned long temp; + u32 i, j, sample; + + for (i = 0; i < kmb_i2s->fifo_th; i++) { + j = 0; + do { + temp = buf[tx_ptr][j]; + /* Replace parity with block start*/ + assign_bit(31, &temp, (BIT(3) & temp)); + sample = bitrev32(temp); + buf[tx_ptr][j] = sample << 4; + j++; + } while (j < 2); + tx_ptr++; + } +} + static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s, struct snd_pcm_runtime *runtime, unsigned int tx_ptr, bool *period_elapsed) @@ -65,6 +111,8 @@ static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s, writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); } else { + if (kmb_i2s->iec958_fmt) + hdmi_reformat_iec958(runtime, kmb_i2s, tx_ptr); writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); } @@ -235,6 +283,7 @@ static int kmb_pcm_trigger(struct snd_soc_component *component, kmb_i2s->tx_substream = NULL; else kmb_i2s->rx_substream = NULL; + kmb_i2s->iec958_fmt = false; break; default: return -EINVAL; @@ -549,6 +598,9 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream, kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; + case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: + kmb_i2s->iec958_fmt = true; + fallthrough; case SNDRV_PCM_FORMAT_S32_LE: config->data_width = 32; kmb_i2s->ccr = 0x10; @@ -686,6 +738,24 @@ static struct snd_soc_dai_ops kmb_dai_ops = { .set_fmt = kmb_set_dai_fmt, };
+static struct snd_soc_dai_driver intel_kmb_hdmi_dai[] = { + { + .name = "intel_kmb_hdmi_i2s", + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE), + }, + .ops = &kmb_dai_ops, + .probe = kmb_probe, + }, +}; + static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = { { .name = "intel_kmb_i2s", @@ -740,6 +810,7 @@ static struct snd_soc_dai_driver intel_kmb_tdm_dai[] = {
static const struct of_device_id kmb_plat_of_match[] = { { .compatible = "intel,keembay-i2s", .data = &intel_kmb_i2s_dai}, + { .compatible = "intel,keembay-hdmi-i2s", .data = &intel_kmb_hdmi_dai}, { .compatible = "intel,keembay-tdm", .data = &intel_kmb_tdm_dai}, {} }; diff --git a/sound/soc/intel/keembay/kmb_platform.h b/sound/soc/intel/keembay/kmb_platform.h index 67234caee814..29be2cd84ddb 100644 --- a/sound/soc/intel/keembay/kmb_platform.h +++ b/sound/soc/intel/keembay/kmb_platform.h @@ -150,6 +150,7 @@ struct kmb_i2s_info { struct snd_pcm_substream *rx_substream; unsigned int tx_ptr; unsigned int rx_ptr; + bool iec958_fmt; };
#endif /* KMB_PLATFORM_H_ */
On Thu, Feb 04, 2021 at 09:42:54AM +0800, Sia Jee Heng wrote:
The below patch series are to support Audio over HDMI. The modification in this patch series shall allow I2S driver to playback standard PCM format and IEC958 encoded format to the ADV7511 HDMI chip.
This seems fine - what's the plan for getting the DRM patch merged? I can apply it if that's best for people.
-----Original Message----- From: Mark Brown broonie@kernel.org Sent: 06 February 2021 12:35 AM To: Sia, Jee Heng jee.heng.sia@intel.com Cc: alsa-devel@alsa-project.org; tiwai@suse.com; pierre- louis.bossart@linux.intel.com Subject: Re: [PATCH RFC 0/4] Add HDMI support for Intel KeemBay I2S
On Thu, Feb 04, 2021 at 09:42:54AM +0800, Sia Jee Heng wrote:
The below patch series are to support Audio over HDMI. The modification in this patch series shall allow I2S driver to playback standard PCM format and IEC958 encoded format to the
ADV7511
HDMI chip.
This seems fine - what's the plan for getting the DRM patch merged? I can apply it if that's best for people.
[>>] Hi Mark, if there is no issue to the flows and no concern from the rest, I think the changes to the Sound can be merged first. I shall submit the DRM patch to the DRM community later.
On Thu, 4 Feb 2021 09:42:54 +0800, Sia Jee Heng wrote:
The below patch series are to support Audio over HDMI. The modification in this patch series shall allow I2S driver to playback standard PCM format and IEC958 encoded format to the ADV7511 HDMI chip.
ALSA IEC958 plugin will be used to compose the IEC958 format.
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/4] ASoC: codec: hdmi-codec: Support IEC958 encoded PCM format commit: 28785f548d18e6d52785a1172e5c176784ce74cd [3/4] dt-bindings: sound: Intel, Keembay-i2s: Add hdmi-i2s compatible string commit: d5e16dc5fdad09d7b3133b6aaea7848bfb518e04 [4/4] ASoC: Intel: KMB: Support IEC958 encoded PCM format commit: 1c5f6e0714c16e3ad8732e49e07082772dcc6f87
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
participants (3)
-
Mark Brown
-
Sia Jee Heng
-
Sia, Jee Heng