Re: [PATCH] dt-bindings: Improve phandle-array schemas

2022-01-19 Thread Arnaud POULIQUEN
Hello Rob,

On 1/19/22 2:50 AM, Rob Herring wrote:
> The 'phandle-array' type is a bit ambiguous. It can be either just an
> array of phandles or an array of phandles plus args. Many schemas for
> phandle-array properties aren't clear in the schema which case applies
> though the description usually describes it.
> 
> The array of phandles case boils down to needing:
> 
> items:
>   maxItems: 1
> 
> The phandle plus args cases should typically take this form:
> 
> items:
>   - items:
>   - description: A phandle
>   - description: 1st arg cell
>   - description: 2nd arg cell
> 
> With this change, some examples need updating so that the bracketing of
> property values matches the schema.
> 
> Cc: Damien Le Moal 
> Cc: Herbert Xu 
> Cc: "David S. Miller" 
> Cc: Chun-Kuang Hu 
> Cc: Philipp Zabel 
> Cc: Laurent Pinchart 
> Cc: Kieran Bingham 
> Cc: Vinod Koul 
> Cc: Georgi Djakov 
> Cc: Thomas Gleixner 
> Cc: Marc Zyngier 
> Cc: Joerg Roedel 
> Cc: Lee Jones 
> Cc: Daniel Thompson 
> Cc: Jingoo Han 
> Cc: Pavel Machek 
> Cc: Mauro Carvalho Chehab 
> Cc: Krzysztof Kozlowski 
> Cc: Jakub Kicinski 
> Cc: Wolfgang Grandegger 
> Cc: Marc Kleine-Budde 
> Cc: Andrew Lunn 
> Cc: Vivien Didelot 
> Cc: Florian Fainelli 
> Cc: Vladimir Oltean 
> Cc: Kalle Valo 
> Cc: Viresh Kumar 
> Cc: Stephen Boyd 
> Cc: Kishon Vijay Abraham I 
> Cc: Linus Walleij 
> Cc: "Rafael J. Wysocki" 
> Cc: Kevin Hilman 
> Cc: Ulf Hansson 
> Cc: Sebastian Reichel 
> Cc: Mark Brown 
> Cc: Mathieu Poirier 
> Cc: Daniel Lezcano 
> Cc: Zhang Rui 
> Cc: Greg Kroah-Hartman 
> Cc: Thierry Reding 
> Cc: Jonathan Hunter 
> Cc: Sudeep Holla 
> Cc: Geert Uytterhoeven 
> Cc: linux-...@vger.kernel.org
> Cc: linux-cry...@vger.kernel.org
> Cc: dri-devel@lists.freedesktop.org
> Cc: dmaeng...@vger.kernel.org
> Cc: linux...@vger.kernel.org
> Cc: io...@lists.linux-foundation.org
> Cc: linux-l...@vger.kernel.org
> Cc: linux-me...@vger.kernel.org
> Cc: net...@vger.kernel.org
> Cc: linux-...@vger.kernel.org
> Cc: linux-wirel...@vger.kernel.org
> Cc: linux-...@lists.infradead.org
> Cc: linux-g...@vger.kernel.org
> Cc: linux-ri...@lists.infradead.org
> Cc: linux-remotep...@vger.kernel.org
> Cc: alsa-de...@alsa-project.org
> Cc: linux-...@vger.kernel.org
> Signed-off-by: Rob Herring 
> ---

[...]

>  .../bindings/remoteproc/st,stm32-rproc.yaml   | 33 ++--

[...]

> diff --git a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml 
> b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
> index b587c97c282b..be3d9b0e876b 100644
> --- a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
> +++ b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
> @@ -29,17 +29,22 @@ properties:
>  
>st,syscfg-holdboot:
>  description: remote processor reset hold boot
> -  - Phandle of syscon block.
> -  - The offset of the hold boot setting register.
> -  - The field mask of the hold boot.
>  $ref: "/schemas/types.yaml#/definitions/phandle-array"
> -maxItems: 1
> +items:
> +  - items:
> +  - description: Phandle of syscon block
> +  - description: The offset of the hold boot setting register
> +  - description: The field mask of the hold boot
>  
>st,syscfg-tz:
>  description:
>Reference to the system configuration which holds the RCC trust zone 
> mode
>  $ref: "/schemas/types.yaml#/definitions/phandle-array"
> -maxItems: 1
> +items:
> +  - items:
> +  - description: Phandle of syscon block
> +  - description: FIXME
> +  - description: FIXME

 - description: The offset of the trust zone setting register
 - description: The field mask of the trust zone state

>  
>interrupts:
>  description: Should contain the WWDG1 watchdog reset interrupt
> @@ -93,20 +98,32 @@ properties:
>  $ref: "/schemas/types.yaml#/definitions/phandle-array"
>  description: |
>Reference to the system configuration which holds the remote
> -maxItems: 1
> +items:
> +  - items:
> +  - description: Phandle of syscon block
> +  - description: FIXME
> +  - description: FIXME

 - description: The offset of the power setting register
 - description: The field mask of the PDDS selection

>  
>st,syscfg-m4-state:
>  $ref: "/schemas/types.yaml#/definitions/phandle-array"
>  description: |
>Reference to the tamp register which exposes the Cortex-M4 state.
> -maxItems: 1
> +items:
> +  - items:
> +  - description: Phandle of syscon block with the tamp register
> +  - description: FIXME
> +  - description: FIXME

 - description: The offset of the tamp register
 - description: The field mask of the Cortex-M4 state

>  
>st,syscfg-rsc-tbl:
>  $ref: "/schemas/types.yaml#/definitions/phandle-array"
>  description: |
>Reference to the tamp register which references the 

Re: [PATCH] dt-bindings: Drop redundant minItems/maxItems

2021-06-19 Thread Arnaud POULIQUEN
Hello ROb,

On 6/15/21 9:15 PM, Rob Herring wrote:
> If a property has an 'items' list, then a 'minItems' or 'maxItems' with the
> same size as the list is redundant and can be dropped. Note that is DT
> schema specific behavior and not standard json-schema behavior. The tooling
> will fixup the final schema adding any unspecified minItems/maxItems.
> 
> This condition is partially checked with the meta-schema already, but
> only if both 'minItems' and 'maxItems' are equal to the 'items' length.
> An improved meta-schema is pending.
> 
[...]
>  .../devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml | 2 --
[...]
>  .../devicetree/bindings/mailbox/st,stm32-ipcc.yaml  | 2 --
[...]
>  .../devicetree/bindings/remoteproc/st,stm32-rproc.yaml  | 2 --
[...]
>  Documentation/devicetree/bindings/sound/st,stm32-sai.yaml   | 3 ---
Reviewed-by: Arnaud Pouliquen 

Thanks,
Arnaud


Re: [alsa-devel] [PATCH v2 2/2] drm/bridge: adv7511: restrict audio sample sizes

2017-08-01 Thread Arnaud Pouliquen
Hello Srinivas,

On 08/01/2017 12:49 AM, srinivas.kandaga...@linaro.org wrote:
> From: Srinivas Kandagatla 
> 
> ADV7533 only supports audio samples word width from 16-24 bits.
> This patch restricts the audio sample sizes to the supported ones,
> so that sound card does not report wrong list of supported hwparms.
> 
> Without this patch aplay would fail when playing a 32 bit audio.
> 
> Signed-off-by: Srinivas Kandagatla 
> ---
>  drivers/gpu/drm/bridge/adv7511/adv7511_audio.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c 
> b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
> index 67469c26bae8..d01d0aa0eef7 100644
> --- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
> +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
> @@ -214,6 +214,8 @@ static struct hdmi_codec_pdata codec_data = {
>   .ops = _codec_ops,
>   .max_i2s_channels = 2,
>   .i2s = 1,
> + .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
> + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE),
>  };

I'm not sure that this limitation is needed.
I already used ADV7513 and i did not observe this limitation.

I had a look to ADV7533 data-sheet. it should support 32 and 64 bits I2S
format bus, with 16 or 24 bits precision sample. So it should support
SNDRV_PCM_FMTBIT_S32_LE and SNDRV_PCM_FMTBIT_S32_BE

As example, if you configure bus in Left justified format with 24 bits
sample length, 32 bits application samples should be truncated to 24
bits samples at ADV7533 I2S interface level (LSB dropped).

Perhaps i missed something... but look like more an I2S bus
configuration issue in your DT card description, that that a miss in the
drivers.

Regards
Arnaud
>  
>  int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [alsa-devel] [PATCH v2 2/2] drm/bridge: adv7511: restrict audio sample sizes

2017-08-01 Thread Arnaud Pouliquen
Hello Srinivas,

On 08/01/2017 02:52 PM, Srinivas Kandagatla wrote:
 As example, if you configure bus in Left justified format with 24 bits
 sample length, 32 bits application samples should be truncated to 24
 bits samples at ADV7533 I2S interface level (LSB dropped).
>>
>>> May be we can do that to make the user happy but isn't this just truncate
>>> the resolution to 24Bit then?
>>
>>> And it's a false indication that we are supporting 32bit samples.
>>> Which am not very happy with.
>>
>> This is what the sample_bits field in the DAI structure is for.ya.
> But still reporting that driver supports 32 bit samples when it does not 
> really support all 32 bits, is kinda misleading to user.
> Isn't it?
> 
> And the driver would be end up with hacked up code for each case.

By experience, this is usual. As example, if you have a look to codec
ad193x (i take one randomly) it support 16, 20, 24 and 32 bits frames.
But if you have a look to AD1939 data-sheet it supports 24-bits conversion.
Some other examples could be 13-bits DAC/ADC with 16 bits samples.

In term of audio quality, truncation to a 24 bits sample should generate
an negligible additional error equal to the LSB bit: -20log(2^24)= -144dB.

It is just a personal opinion, but if have the choice between do
truncation in software (application or alsa-lib) and in hardware, i
would prefer the second one.

Regards
arnaud
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v4 1/3] DRM: add help to get ELD speaker allocation

2017-01-19 Thread Arnaud Pouliquen


On 01/19/2017 11:29 AM, Mark Brown wrote:
> On Wed, Jan 18, 2017 at 07:38:53AM +1100, Eric Anholt wrote:
>> Mark Brown  writes:
> 
>>> You don't appear to have sent this to any of the DRM
>>> maintainers - it does need review from them.
> 
>> It was sent to dri-devel.  That's us.  And the patch already has
>> a r-b From DRM on it.
> 
> I see.  For most subsystems you need to actually copy a human to
> make sure that things are seen - just the list isn't enough.  In
> terms of it being reviewed one of the problems with DRM not listing
> the reviwers in the MAINTAINERS file or anything is that it's very
> hard for anyone to tell if something is considered a good enough
> review or if it's just a review from someone who happens to
> contribute to DRM sometimes.
> 
I limited diffusion to ASoC, as Daniel Vetter and Takashi Iwai
discussed the topic here:
http://www.spinics.net/lists/alsa-devel/msg58114.html
Seems that is was not a good strategy as it leads to discussions..
Sorry for this.

Regards
Arnaud
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v4 0/3] Generic HDMI codec: Add channel mapping control

2017-01-16 Thread Arnaud Pouliquen
Hello,

Any comments on this patch-set?
what about the introduction of pcm new callback in DAI ops to use chmap
helpers?
Is it something reasonable, or should i come back on V1?

Regards
Arnaud

> 2017-01-03 16:52 GMT+01:00 Arnaud Pouliquen <arnaud.pouliq...@st.com>:
> Aim of this patch is to add  'Playback Channel Map' control to export
> audio capabilities in term of HDMI sink speakers allocation.
>
> V4:
> Abandon "Generic HDMI codec: Add channel mapping control" patch as it 
> generates warnings during compilation.
>
> Workaround is to define 2 constant tables in hdmi-codec.c to declare channel 
> mapping.
> One for stereo and one for multichannel.
> Consequence is that the behaviour is changed:
>The chmap multichannel table export the HDMI CA configuration (tlv) and 
> not only the one suuported by HDMI sink.
> Furthermore the chmap control .get handler is overwritten to allow to export 
> to user the selected configuration.
>
>  - "ASoC: hdmi-codec: add channel mapping control":
> - add hdmi_codec_stereo_chmaps and hdmi_codec_8ch_chmaps tables.
> - implement chmap control get handler.
>  - "DRM: add help to get ELD speaker allocation"
>  => No delta vs V2.
>  - "ALSA pcm: allow non constant snd_pcm_chmap_elem"
>  => abandonned
>  - "ASoC: core: add optional pcm_new callback for DAI driver"
>  => No delta vs V2.
>
> V3:
>  - "ASoC: hdmi-codec: add channel mapping control":
>  => Minor fixes:
>  - select stereo speaker config by default if HDMI cable unplugged
>  - fix compilation warning.
>  - "DRM: add help to get ELD speaker allocation"
>  => No delta vs V2.
>  - "ALSA pcm: allow non constant snd_pcm_chmap_elem"
>  => No delta vs V2.
>  - "ASoC: core: add optional pcm_new callback for DAI driver"
>  => No delta vs V2.
>
> V2:
> In this version I use chmap helper functions from pcm_lib.c.
> It is quite tricky to use it from ASoC due to the relation chip of the 
> controls
> with the pcm runtime.
> After several tries, my conclusion is that it must be handled in ASoC DAI 
> driver.
> Main reason is that the DAI driver can not provide snd_pcm_chmap struct
> through kcontrol structure. But this induces that soc-core provides pcm 
> runtime
> structure to DAI driver during probe.
>
> Base on this conclusion. I reworked my patches by adding 2
> new patches in patch-set
> 1)  ALSA pcm: allow non constant snd_pcm_chmap_elem
>This patch allows to handle non constant channel mapping. As ELD
>information can change during runtime it is mandatory to properly
>handle the feature.
>In term of compatibility with legacy it should be straightforward,
>as update just consists in suppressing the 'const' constraint.
>
> 2)  ASoC: core: add optional pcm_new callback for DAI driver
> This is the only way i found to be able to use
> snd_pcm_add_chmap_ctls and associated controls helper functions.
> From my point of view, this is the more simple way to add relationship
> between DAI and associated pcm devices.
>Notice that this patch, if accepted, makes the following one obsolete,
>as it also answer to the associated topic:
>   [PATCH v5 0/2] ALSA controls management using index/device/sub-devices 
> fields
>   (http://www.spinics.net/lists/alsa-devel/msg57639.html).
>
> If you estimate that this it not reasonable i will come back to my first 
> version.
>
> V1:
> This patch follows discussion initiate here:
> [RFC] ASOC: HDMI audio info frame speaker allocation
> http://www.spinics.net/lists/alsa-devel/msg57363.html
>
> The code is fully inspired from HDA driver.
> On hw_param, HDMI sink speaker capabilities are exported via TLV ops
> and  a CEA allocation is choson, based on ELD information and the number of
> channels requested by user.
>
> Mains differences with HDA implementation are:
>  - Control is read only
>  - Channel swap is not supported. Consequence is that unused channel in
>the mid of CEA audio infoframe channel mapping are considered as
>active.
>example for channel allocation 0x02: FL, FR, 0, FC)
> This configuration is only available for a 4 channels stream.
>   - Channel allocation table has been reordered and HDMI 2.0 is not
> supported.
>
> Arnaud Pouliquen (4):
>   DRM: add help to get ELD speaker allocation
>   ASoC: core: add optional pcm_new callback for DAI driver
>   ASoC: hdmi-codec: add channel mapping control
>
>  include/drm/drm_edid.h|  13 ++
>  include/sound/soc-dai.h   |   3 +
>  sound/soc/codecs/hdmi-codec.c | 380 
> +-
>  sound/soc/soc-core.c  |  28 
>  4 files changed, 423 insertions(+), 1 deletion(-)
>
> --
> 1.9.1
>
> 

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 3/3] ASoC: hdmi-codec: add channel mapping control

2017-01-03 Thread Arnaud Pouliquen
Add user interface to provide channel mapping.
In a first step this control is read only.

As TLV type, the control provides all configuration available for
HDMI sink(ELD), and provides current channel mapping selected by codec
based on ELD and number of channels specified by user on open.
When control is called before the number of the channel is specified
(i.e. hw_params is set), it returns all channels set to UNKNOWN.

Signed-off-by: Arnaud Pouliquen 
---
 sound/soc/codecs/hdmi-codec.c | 380 +-
 1 file changed, 379 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 90b5948..dc6715a 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,6 +34,258 @@ struct hdmi_device {
 LIST_HEAD(hdmi_device_list);

 #define DAI_NAME_SIZE 16
+
+#define HDMI_CODEC_CHMAP_IDX_UNKNOWN  -1
+
+struct hdmi_codec_channel_map_table {
+   unsigned char map;  /* ALSA API channel map position */
+   unsigned long spk_mask; /* speaker position bit mask */
+};
+
+/*
+ * CEA speaker placement for HDMI 1.4:
+ *
+ *  FL  FLC   FC   FRC   FR   FRW
+ *
+ *  LFE
+ *
+ *  RL  RLC   RC   RRC   RR
+ *
+ *  Speaker placement has to be extended to support HDMI 2.0
+ */
+enum hdmi_codec_cea_spk_placement {
+   FL  = BIT(0),   /* Front Left   */
+   FC  = BIT(1),   /* Front Center */
+   FR  = BIT(2),   /* Front Right  */
+   FLC = BIT(3),   /* Front Left Center*/
+   FRC = BIT(4),   /* Front Right Center   */
+   RL  = BIT(5),   /* Rear Left*/
+   RC  = BIT(6),   /* Rear Center  */
+   RR  = BIT(7),   /* Rear Right   */
+   RLC = BIT(8),   /* Rear Left Center */
+   RRC = BIT(9),   /* Rear Right Center*/
+   LFE = BIT(10),  /* Low Frequency Effect */
+};
+
+/*
+ * cea Speaker allocation structure
+ */
+struct hdmi_codec_cea_spk_alloc {
+   const int ca_id;
+   unsigned int n_ch;
+   unsigned long mask;
+};
+
+/* Channel maps  stereo HDMI */
+const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = {
+   { .channels = 2,
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+   { }
+};
+
+/* Channel maps for multi-channel playbacks, up to 8 n_ch */
+const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = {
+   { .channels = 2, /* CA_ID 0x00 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+   { .channels = 4, /* CA_ID 0x01 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
+  SNDRV_CHMAP_NA } },
+   { .channels = 4, /* CA_ID 0x02 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
+  SNDRV_CHMAP_FC } },
+   { .channels = 4, /* CA_ID 0x03 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
+  SNDRV_CHMAP_FC } },
+   { .channels = 6, /* CA_ID 0x04 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
+  SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
+   { .channels = 6, /* CA_ID 0x05 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
+  SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
+   { .channels = 6, /* CA_ID 0x06 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
+  SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
+   { .channels = 6, /* CA_ID 0x07 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
+  SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
+   { .channels = 6, /* CA_ID 0x08 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
+  SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
+   { .channels = 6, /* CA_ID 0x09 */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
+  SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
+   { .channels = 6, /* CA_ID 0x0A */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
+  SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
+   { .channels = 6, /* CA_ID 0x0B */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
+  SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
+   { .channels = 8, /* CA_ID 0x0C */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
+  SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
+  SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
+   { .channels = 8, /* CA_ID 0x0D */
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
+  SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
+  SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
+   { .channels = 8

[PATCH v4 2/3] ASoC: core: add optional pcm_new callback for DAI driver

2017-01-03 Thread Arnaud Pouliquen
During probe, DAIs can need to perform some actions that requests
the knowledge of the pcm runtime handle.
The callback is called during DAIs linking, after PCM device creation.
For instance this can be used to add relationship between a DAI pcm
control and the pcm device.

Signed-off-by: Arnaud Pouliquen 
---
 include/sound/soc-dai.h |  3 +++
 sound/soc/soc-core.c| 28 
 2 files changed, 31 insertions(+)

diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 964b7de..1c8b579 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -231,6 +231,9 @@ struct snd_soc_dai_driver {
int (*resume)(struct snd_soc_dai *dai);
/* compress dai */
int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num);
+   /* Optional Callback used at pcm creation*/
+   int (*pcm_new)(struct snd_soc_pcm_runtime *rtd,
+  struct snd_soc_dai *dai);
/* DAI is also used for the control bus */
bool bus_control;

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c0bbcd9..b8c5813 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1552,6 +1552,27 @@ static int soc_probe_dai(struct snd_soc_dai *dai, int 
order)
return 0;
 }

+static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais,
+   struct snd_soc_pcm_runtime *rtd)
+{
+   int i, ret = 0;
+
+   for (i = 0; i < num_dais; ++i) {
+   struct snd_soc_dai_driver *drv = dais[i]->driver;
+
+   if (!rtd->dai_link->no_pcm && drv->pcm_new)
+   ret = drv->pcm_new(rtd, dais[i]);
+   if (ret < 0) {
+   dev_err(dais[i]->dev,
+   "ASoC: Failed to bind %s with pcm device\n",
+   dais[i]->name);
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
 static int soc_link_dai_widgets(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link,
struct snd_soc_pcm_runtime *rtd)
@@ -1663,6 +1684,13 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
   dai_link->stream_name, ret);
return ret;
}
+   ret = soc_link_dai_pcm_new(_dai, 1, rtd);
+   if (ret < 0)
+   return ret;
+   ret = soc_link_dai_pcm_new(rtd->codec_dais,
+  rtd->num_codecs, rtd);
+   if (ret < 0)
+   return ret;
} else {
INIT_DELAYED_WORK(>delayed_work,
codec2codec_close_delayed_work);
-- 
1.9.1



[PATCH v4 1/3] DRM: add help to get ELD speaker allocation

2017-01-03 Thread Arnaud Pouliquen
Add helper to allow users to retrieve the speaker allocations without
knowledge of the ELD structure.

Signed-off-by: Arnaud Pouliquen 
Reviewed-by: Jani Nikula 
---
 include/drm/drm_edid.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index c3a7d44..de93543 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -248,6 +248,7 @@ struct detailed_timing {
 # define DRM_ELD_AUD_SYNCH_DELAY_MAX   0xfa/* 500 ms */

 #define DRM_ELD_SPEAKER7
+# define DRM_ELD_SPEAKER_MASK  0x7f
 # define DRM_ELD_SPEAKER_RLRC  (1 << 6)
 # define DRM_ELD_SPEAKER_FLRC  (1 << 5)
 # define DRM_ELD_SPEAKER_RC(1 << 4)
@@ -415,6 +416,18 @@ static inline int drm_eld_size(const uint8_t *eld)
 }

 /**
+ * drm_eld_get_spk_alloc - Get speaker allocation
+ * @eld: pointer to an ELD memory structure
+ *
+ * The returned value is the speakers mask. User has to use %DRM_ELD_SPEAKER
+ * field definitions to identify speakers.
+ */
+static inline u8 drm_eld_get_spk_alloc(const uint8_t *eld)
+{
+   return eld[DRM_ELD_SPEAKER] & DRM_ELD_SPEAKER_MASK;
+}
+
+/**
  * drm_eld_get_conn_type - Get device type hdmi/dp connected
  * @eld: pointer to an ELD memory structure
  *
-- 
1.9.1



[PATCH v4 0/3] Generic HDMI codec: Add channel mapping control

2017-01-03 Thread Arnaud Pouliquen
Aim of this patch is to add  'Playback Channel Map' control to export 
audio capabilities in term of HDMI sink speakers allocation.

V4:
Abandon "Generic HDMI codec: Add channel mapping control" patch as it generates 
warnings during compilation.

Workaround is to define 2 constant tables in hdmi-codec.c to declare channel 
mapping.
One for stereo and one for multichannel.
Consequence is that the behaviour is changed: 
   The chmap multichannel table export the HDMI CA configuration (tlv) and not 
only the one suuported by HDMI sink.
Furthermore the chmap control .get handler is overwritten to allow to export to 
user the selected configuration. 

 - "ASoC: hdmi-codec: add channel mapping control":
- add hdmi_codec_stereo_chmaps and hdmi_codec_8ch_chmaps tables.
- implement chmap control get handler. 
 - "DRM: add help to get ELD speaker allocation"
 => No delta vs V2.
 - "ALSA pcm: allow non constant snd_pcm_chmap_elem"
 => abandonned
 - "ASoC: core: add optional pcm_new callback for DAI driver"
 => No delta vs V2.

V3:
 - "ASoC: hdmi-codec: add channel mapping control":
 => Minor fixes:
 - select stereo speaker config by default if HDMI cable unplugged
 - fix compilation warning. 
 - "DRM: add help to get ELD speaker allocation"
 => No delta vs V2.
 - "ALSA pcm: allow non constant snd_pcm_chmap_elem"
 => No delta vs V2.
 - "ASoC: core: add optional pcm_new callback for DAI driver"
 => No delta vs V2.

V2:
In this version I use chmap helper functions from pcm_lib.c. 
It is quite tricky to use it from ASoC due to the relation chip of the controls
with the pcm runtime.
After several tries, my conclusion is that it must be handled in ASoC DAI 
driver.
Main reason is that the DAI driver can not provide snd_pcm_chmap struct
through kcontrol structure. But this induces that soc-core provides pcm runtime
structure to DAI driver during probe.

Base on this conclusion. I reworked my patches by adding 2 
new patches in patch-set
1)  ALSA pcm: allow non constant snd_pcm_chmap_elem
   This patch allows to handle non constant channel mapping. As ELD
   information can change during runtime it is mandatory to properly 
   handle the feature.
   In term of compatibility with legacy it should be straightforward,
   as update just consists in suppressing the 'const' constraint.

2)  ASoC: core: add optional pcm_new callback for DAI driver
This is the only way i found to be able to use 
snd_pcm_add_chmap_ctls and associated controls helper functions.
From my point of view, this is the more simple way to add relationship
between DAI and associated pcm devices.
   Notice that this patch, if accepted, makes the following one obsolete,
   as it also answer to the associated topic:
  [PATCH v5 0/2] ALSA controls management using index/device/sub-devices fields
  (http://www.spinics.net/lists/alsa-devel/msg57639.html).

If you estimate that this it not reasonable i will come back to my first 
version.

V1:
This patch follows discussion initiate here: 
[RFC] ASOC: HDMI audio info frame speaker allocation
http://www.spinics.net/lists/alsa-devel/msg57363.html

The code is fully inspired from HDA driver.
On hw_param, HDMI sink speaker capabilities are exported via TLV ops
and  a CEA allocation is choson, based on ELD information and the number of
channels requested by user.

Mains differences with HDA implementation are:
 - Control is read only
 - Channel swap is not supported. Consequence is that unused channel in
   the mid of CEA audio infoframe channel mapping are considered as
   active.
   example for channel allocation 0x02: FL, FR, 0, FC)
This configuration is only available for a 4 channels stream.
  - Channel allocation table has been reordered and HDMI 2.0 is not
supported.

Arnaud Pouliquen (4):
  DRM: add help to get ELD speaker allocation
  ASoC: core: add optional pcm_new callback for DAI driver
  ASoC: hdmi-codec: add channel mapping control

 include/drm/drm_edid.h|  13 ++
 include/sound/soc-dai.h   |   3 +
 sound/soc/codecs/hdmi-codec.c | 380 +-
 sound/soc/soc-core.c  |  28 
 4 files changed, 423 insertions(+), 1 deletion(-)

-- 
1.9.1



[alsa-devel] [PATCH v3 2/4] ALSA pcm: allow non constant snd_pcm_chmap_elem

2016-12-19 Thread Arnaud Pouliquen

I had a doubt...this confirms that my arm compiler is too permissive :(
This patch in pcm_lib has to be abandoned.
I will propose a V4 with one/some constant table(s) defined in hdmi-codec...

Regards
Arnaud


On 12/19/2016 05:31 PM, kbuild test robot wrote:
> Hi Arnaud,
> 
> [auto build test WARNING on asoc/for-next]
> [also build test WARNING on v4.9 next-20161219]
> [if your patch is applied to the wrong git tree, please drop us a note to 
> help improve the system]
> 
> url:
> https://github.com/0day-ci/linux/commits/Arnaud-Pouliquen/Generic-HDMI-codec-Add-channel-mapping-control/20161219-235923
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 
> for-next
> config: x86_64-acpi-redef (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
> # save the attached .config to linux build tree
> make ARCH=x86_64 
> 
> All warnings (new ones prefixed by >>):
> 
>sound/pci/atiixp.c: In function 'snd_atiixp_pcm_new':
>>> sound/pci/atiixp.c:1298:10: warning: passing argument 3 of 
>>> 'snd_pcm_add_chmap_ctls' discards 'const' qualifier from pointer target 
>>> type [-Wdiscarded-qualifiers]
>  snd_pcm_alt_chmaps, chip->max_channels, 0,
>  ^~
>In file included from sound/pci/atiixp.c:31:0:
>include/sound/pcm.h:1389:5: note: expected 'struct snd_pcm_chmap_elem *' 
> but argument is of type 'const struct snd_pcm_chmap_elem *'
> int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
> ^~
> --
>sound/pci/cmipci.c: In function 'snd_cmipci_pcm_spdif_new':
>>> sound/pci/cmipci.c:1966:10: warning: passing argument 3 of 
>>> 'snd_pcm_add_chmap_ctls' discards 'const' qualifier from pointer target 
>>> type [-Wdiscarded-qualifiers]
>  snd_pcm_alt_chmaps, cm->max_channels, 0,
>  ^~
>In file included from sound/pci/cmipci.c:35:0:
>include/sound/pcm.h:1389:5: note: expected 'struct snd_pcm_chmap_elem *' 
> but argument is of type 'const struct snd_pcm_chmap_elem *'
> int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
> ^~
> --
>sound/pci/ens1370.c: In function 'snd_ensoniq_pcm':
>>> sound/pci/ens1370.c:1297:10: warning: passing argument 3 of 
>>> 'snd_pcm_add_chmap_ctls' discards 'const' qualifier from pointer target 
>>> type [-Wdiscarded-qualifiers]
>  surround_map, 2, 0, NULL);
>  ^~~~
>In file included from sound/pci/ens1370.c:41:0:
>include/sound/pcm.h:1389:5: note: expected 'struct snd_pcm_chmap_elem *' 
> but argument is of type 'const struct snd_pcm_chmap_elem *'
> int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
> ^~
>sound/pci/ens1370.c: In function 'snd_ensoniq_pcm2':
>sound/pci/ens1370.c:1329:10: warning: passing argument 3 of 
> 'snd_pcm_add_chmap_ctls' discards 'const' qualifier from pointer target type 
> [-Wdiscarded-qualifiers]
>  snd_pcm_std_chmaps, 2, 0, NULL);
>  ^~
>In file included from sound/pci/ens1370.c:41:0:
>include/sound/pcm.h:1389:5: note: expected 'struct snd_pcm_chmap_elem *' 
> but argument is of type 'const struct snd_pcm_chmap_elem *'
> int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
> ^~
> --
>In file included from sound/pci/au88x0/au8810.c:9:0:
>sound/pci/au88x0/au88x0_pcm.c: In function 'snd_vortex_new_pcm':
>>> sound/pci/au88x0/au88x0_pcm.c:659:11: warning: passing argument 3 of 
>>> 'snd_pcm_add_chmap_ctls' discards 'const' qualifier from pointer target 
>>> type [-Wdiscarded-qualifiers]
>   snd_pcm_std_chmaps,
>   ^~
>In file included from sound/pci/au88x0/au88x0.h:23:0,
> from sound/pci/au88x0/au8810.c:2:
>include/sound/pcm.h:1389:5: note: expected 'struct snd_pcm_chmap_elem *' 
> but argument is of type 'const struct snd_pcm_chmap_elem *'
> int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
> ^~
>In file included from sound/pci/au88x0/au8810.c:9:0:
>sound/pci/au88x0/au88x0_pcm.c:665:11: warning: passing argument 3 of 
> 'snd_pcm_add_chmap_ctls' discards 'const' qualifier from pointer target type 
> [-Wdiscarded-qualifiers]
>   snd_pcm_std_chmaps, 2, 0, NULL);
>   ^~
>In file included from sound/pci/au88x0/au88x0.h:23:0,
> from sound/pci/au88x0/au8810.c:2:
>include/sound/pcm.h:1389:5: note: expected 'struct snd_pcm_chm

[PATCH v3 4/4] ASoC: hdmi-codec: add channel mapping control

2016-12-19 Thread Arnaud Pouliquen
Add user interface to provide channel mapping.
In a first step this control is read only.

As TLV type, the control provides all configuration available for
HDMI sink(ELD), and provides current channel mapping selected by codec
based on ELD and number of channels specified by user on open.
When control is called before the number of the channel is specified
(i.e. hw_params is set), it returns all channels set to UNKNOWN.

Signed-off-by: Arnaud Pouliquen 
---
 sound/soc/codecs/hdmi-codec.c | 313 +-
 1 file changed, 312 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 90b5948..e2ccc2b 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,6 +34,124 @@ struct hdmi_device {
 LIST_HEAD(hdmi_device_list);

 #define DAI_NAME_SIZE 16
+#define HDMI_MAX_SPEAKERS  8
+
+struct hdmi_codec_channel_map_table {
+   unsigned char map;  /* ALSA API channel map position */
+   unsigned long spk_mask; /* speaker position bit mask */
+};
+
+/*
+ * CEA speaker placement for HDMI 1.4:
+ *
+ *  FL  FLC   FC   FRC   FR   FRW
+ *
+ *  LFE
+ *
+ *  RL  RLC   RC   RRC   RR
+ *
+ *  Speaker placement has to be extended to support HDMI 2.0
+ */
+enum hdmi_codec_cea_spk_placement {
+   FL  = BIT(0),   /* Front Left   */
+   FC  = BIT(1),   /* Front Center */
+   FR  = BIT(2),   /* Front Right  */
+   FLC = BIT(3),   /* Front Left Center*/
+   FRC = BIT(4),   /* Front Right Center   */
+   RL  = BIT(5),   /* Rear Left*/
+   RC  = BIT(6),   /* Rear Center  */
+   RR  = BIT(7),   /* Rear Right   */
+   RLC = BIT(8),   /* Rear Left Center */
+   RRC = BIT(9),   /* Rear Right Center*/
+   LFE = BIT(10),  /* Low Frequency Effect */
+};
+
+static const struct hdmi_codec_channel_map_table hdmi_codec_map_table[] = {
+   { SNDRV_CHMAP_FL,   FL },
+   { SNDRV_CHMAP_FR,   FR },
+   { SNDRV_CHMAP_RL,   RL },
+   { SNDRV_CHMAP_RR,   RR },
+   { SNDRV_CHMAP_LFE,  LFE },
+   { SNDRV_CHMAP_FC,   FC },
+   { SNDRV_CHMAP_RLC,  RLC },
+   { SNDRV_CHMAP_RRC,  RRC },
+   { SNDRV_CHMAP_RC,   RC },
+   { SNDRV_CHMAP_FLC,  FLC },
+   { SNDRV_CHMAP_FRC,  FRC },
+   {} /* terminator */
+};
+
+/*
+ * cea Speaker allocation structure
+ */
+struct hdmi_codec_cea_spk_alloc {
+   const int ca_id;
+   const unsigned long speakers[HDMI_MAX_SPEAKERS];
+
+   /* Derived values, computed during init */
+   unsigned int channels;
+   unsigned long spks_mask;
+   unsigned long spk_na_mask;
+};
+
+/* default HDMI channel maps is stereo */
+const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = {
+   { .channels = 2,
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+   { }
+};
+
+/*
+ * hdmi_codec_channel_alloc: speaker configuration available for CEA
+ *
+ * This is an ordered list!
+ * The preceding ones have better chances to be selected by
+ * hdmi_codec_get_ch_alloc_table_idx().
+ */
+static struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
+{ .ca_id = 0x00,  .speakers = {   0,0,   0,   0,   0,0,  FR,  FL } },
+/* 2.1 */
+{ .ca_id = 0x01,  .speakers = {   0,0,   0,   0,   0,  LFE,  FR,  FL } },
+/* Dolby Surround */
+{ .ca_id = 0x02,  .speakers = {   0,0,   0,   0,  FC,0,  FR,  FL } },
+/* surround51 */
+{ .ca_id = 0x0b,  .speakers = {   0,0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+/* surround40 */
+{ .ca_id = 0x08,  .speakers = {   0,0,  RR,  RL,   0,0,  FR,  FL } },
+/* surround41 */
+{ .ca_id = 0x09,  .speakers = {   0,0,  RR,  RL,   0,  LFE,  FR,  FL } },
+/* surround50 */
+{ .ca_id = 0x0a,  .speakers = {   0,0,  RR,  RL,  FC,0,  FR,  FL } },
+/* 6.1 */
+{ .ca_id = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+/* surround71 */
+{ .ca_id = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+
+{ .ca_id = 0x03,  .speakers = {   0,0,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_id = 0x04,  .speakers = {   0,0,   0,  RC,   0,0,  FR,  FL } },
+{ .ca_id = 0x05,  .speakers = {   0,0,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_id = 0x06,  .speakers = {   0,0,   0,  RC,  FC,0,  FR,  FL } },
+{ .ca_id = 0x07,  .speakers = {   0,0,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_id = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,0,  FR,  FL } },
+{ .ca_id = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_id = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,0,  FR,  FL } },
+{ .ca_id = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,0,  FR,  FL } },
+{ .ca_id = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL

[PATCH v3 3/4] ASoC: core: add optional pcm_new callback for DAI driver

2016-12-19 Thread Arnaud Pouliquen
During probe, DAIs can need to perform some actions that request
the knowledge of the pcm runtime handle.
The callback is called during DAIs linking, after PCM device creation.
For instance this can be used to add relationship between a DAI pcm
control and the pcm device.

Signed-off-by: Arnaud Pouliquen 
---
 include/sound/soc-dai.h |  3 +++
 sound/soc/soc-core.c| 28 
 2 files changed, 31 insertions(+)

diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 964b7de..1c8b579 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -231,6 +231,9 @@ struct snd_soc_dai_driver {
int (*resume)(struct snd_soc_dai *dai);
/* compress dai */
int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num);
+   /* Optional Callback used at pcm creation*/
+   int (*pcm_new)(struct snd_soc_pcm_runtime *rtd,
+  struct snd_soc_dai *dai);
/* DAI is also used for the control bus */
bool bus_control;

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c0bbcd9..b8c5813 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1552,6 +1552,27 @@ static int soc_probe_dai(struct snd_soc_dai *dai, int 
order)
return 0;
 }

+static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais,
+   struct snd_soc_pcm_runtime *rtd)
+{
+   int i, ret = 0;
+
+   for (i = 0; i < num_dais; ++i) {
+   struct snd_soc_dai_driver *drv = dais[i]->driver;
+
+   if (!rtd->dai_link->no_pcm && drv->pcm_new)
+   ret = drv->pcm_new(rtd, dais[i]);
+   if (ret < 0) {
+   dev_err(dais[i]->dev,
+   "ASoC: Failed to bind %s with pcm device\n",
+   dais[i]->name);
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
 static int soc_link_dai_widgets(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link,
struct snd_soc_pcm_runtime *rtd)
@@ -1663,6 +1684,13 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
   dai_link->stream_name, ret);
return ret;
}
+   ret = soc_link_dai_pcm_new(_dai, 1, rtd);
+   if (ret < 0)
+   return ret;
+   ret = soc_link_dai_pcm_new(rtd->codec_dais,
+  rtd->num_codecs, rtd);
+   if (ret < 0)
+   return ret;
} else {
INIT_DELAYED_WORK(>delayed_work,
codec2codec_close_delayed_work);
-- 
1.9.1



[PATCH v3 2/4] ALSA pcm: allow non constant snd_pcm_chmap_elem

2016-12-19 Thread Arnaud Pouliquen
For HDMI, channel mapping can be retrieved from ELD. In this case mapping
can change during runtime (plug/unplug).
This patch removes the 'const' property of the struct chmap.

Signed-off-by: Arnaud Pouliquen 
---
 include/sound/pcm.h  | 4 ++--
 sound/core/pcm_lib.c | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index af1fb37..3b459a3 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1355,7 +1355,7 @@ struct snd_pcm_chmap {
struct snd_pcm *pcm;/* assigned PCM instance */
int stream; /* PLAYBACK or CAPTURE */
struct snd_kcontrol *kctl;
-   const struct snd_pcm_chmap_elem *chmap;
+   struct snd_pcm_chmap_elem *chmap;
unsigned int max_channels;
unsigned int channel_mask;  /* optional: active channels bitmask */
void *private_data; /* optional: private data pointer */
@@ -1387,7 +1387,7 @@ struct snd_pcm_chmap {
 #define SND_PCM_CHMAP_MASK_2468(SND_PCM_CHMAP_MASK_246 | (1U << 8))

 int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
-  const struct snd_pcm_chmap_elem *chmap,
+  struct snd_pcm_chmap_elem *chmap,
   int max_channels,
   unsigned long private_value,
   struct snd_pcm_chmap **info_ret);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index bb12615..252a498 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2489,7 +2489,7 @@ static int pcm_chmap_ctl_get(struct snd_kcontrol 
*kcontrol,
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, >id);
struct snd_pcm_substream *substream;
-   const struct snd_pcm_chmap_elem *map;
+   struct snd_pcm_chmap_elem *map;

if (snd_BUG_ON(!info->chmap))
return -EINVAL;
@@ -2519,7 +2519,7 @@ static int pcm_chmap_ctl_tlv(struct snd_kcontrol 
*kcontrol, int op_flag,
 unsigned int size, unsigned int __user *tlv)
 {
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
-   const struct snd_pcm_chmap_elem *map;
+   struct snd_pcm_chmap_elem *map;
unsigned int __user *dst;
int c, count = 0;

@@ -2578,7 +2578,7 @@ static void pcm_chmap_ctl_private_free(struct 
snd_kcontrol *kcontrol)
  * Return: Zero if successful, or a negative error value.
  */
 int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
-  const struct snd_pcm_chmap_elem *chmap,
+  struct snd_pcm_chmap_elem *chmap,
   int max_channels,
   unsigned long private_value,
   struct snd_pcm_chmap **info_ret)
-- 
1.9.1



[PATCH v3 1/4] DRM: add help to get ELD speaker allocation

2016-12-19 Thread Arnaud Pouliquen
Add helper to allow users to retrieve the speaker allocations without
knowledge of the ELD structure.

Signed-off-by: Arnaud Pouliquen 
---
 include/drm/drm_edid.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index c3a7d44..de93543 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -248,6 +248,7 @@ struct detailed_timing {
 # define DRM_ELD_AUD_SYNCH_DELAY_MAX   0xfa/* 500 ms */

 #define DRM_ELD_SPEAKER7
+# define DRM_ELD_SPEAKER_MASK  0x7f
 # define DRM_ELD_SPEAKER_RLRC  (1 << 6)
 # define DRM_ELD_SPEAKER_FLRC  (1 << 5)
 # define DRM_ELD_SPEAKER_RC(1 << 4)
@@ -415,6 +416,18 @@ static inline int drm_eld_size(const uint8_t *eld)
 }

 /**
+ * drm_eld_get_spk_alloc - Get speaker allocation
+ * @eld: pointer to an ELD memory structure
+ *
+ * The returned value is the speakers mask. User has to use %DRM_ELD_SPEAKER
+ * field definitions to identify speakers.
+ */
+static inline u8 drm_eld_get_spk_alloc(const uint8_t *eld)
+{
+   return eld[DRM_ELD_SPEAKER] & DRM_ELD_SPEAKER_MASK;
+}
+
+/**
  * drm_eld_get_conn_type - Get device type hdmi/dp connected
  * @eld: pointer to an ELD memory structure
  *
-- 
1.9.1



[PATCH v3 0/4] Generic HDMI codec: Add channel mapping control

2016-12-19 Thread Arnaud Pouliquen
Aim of this patch is to add  'Playback Channel Map' control to export 
audio capabilities in term of HDMI sink speakers allocation.

V3:
 - "ASoC: hdmi-codec: add channel mapping control":
 => Minor fixes:
 - select stereo speaker config by default if HDMI cable unplugged
 - fix compilation warning. 
 - "DRM: add help to get ELD speaker allocation"
 => No delta vs V2.
 - "ALSA pcm: allow non constant snd_pcm_chmap_elem"
 => No delta vs V2.
 - "ASoC: core: add optional pcm_new callback for DAI driver"
 => No delta vs V2.

V2:
In this version I use chmap helper functions from pcm_lib.c. 
It is quite tricky to use it from ASoC due to the relation chip of the controls
with the pcm runtime.
After several tries, my conclusion is that it must be handled in ASoC DAI 
driver.
Main reason is that the DAI driver can not provide snd_pcm_chmap struct
through kcontrol structure. But this induces that soc-core provides pcm runtime
structure to DAI driver during probe.

Base on this conclusion. I reworked my patches by adding 2 
new patches in patch-set
1)  ALSA pcm: allow non constant snd_pcm_chmap_elem
   This patch allows to handle non constant channel mapping. As ELD
   information can change during runtime it is mandatory to properly 
   handle the feature.
   In term of compatibility with legacy it should be straightforward,
   as update just consists in suppressing the 'const' constraint.

2)  ASoC: core: add optional pcm_new callback for DAI driver
This is the only way i found to be able to use 
snd_pcm_add_chmap_ctls and associated controls helper functions.
From my point of view, this is the more simple way to add relationship
between DAI and associated pcm devices.
   Notice that this patch, if accepted, makes the following one obsolete,
   as it also answer to the associated topic:
  [PATCH v5 0/2] ALSA controls management using index/device/sub-devices fields
  (http://www.spinics.net/lists/alsa-devel/msg57639.html).

If you estimate that this it not reasonable i will come back to my first 
version.

V1:
This patch follows discussion initiate here: 
[RFC] ASOC: HDMI audio info frame speaker allocation
http://www.spinics.net/lists/alsa-devel/msg57363.html

The code is fully inspired from HDA driver.
On hw_param, HDMI sink speaker capabilities are exported via TLV ops
and  a CEA allocation is choson, based on ELD information and the number of
channels requested by user.

Mains differences with HDA implementation are:
 - Control is read only
 - Channel swap is not supported. Consequence is that unused channel in
   the mid of CEA audio infoframe channel mapping are considered as
   active.
   example for channel allocation 0x02: FL, FR, 0, FC)
This configuration is only available for a 4 channels stream.
  - Channel allocation table has been reordered and HDMI 2.0 is not
supported.

Arnaud Pouliquen (4):
  DRM: add help to get ELD speaker allocation
  ALSA pcm: allow non constant snd_pcm_chmap_elem
  ASoC: core: add optional pcm_new callback for DAI driver
  ASoC: hdmi-codec: add channel mapping control

 include/drm/drm_edid.h|  13 ++
 include/sound/pcm.h   |   4 +-
 include/sound/soc-dai.h   |   3 +
 sound/core/pcm_lib.c  |   6 +-
 sound/soc/codecs/hdmi-codec.c | 313 +-
 sound/soc/soc-core.c  |  28 
 6 files changed, 361 insertions(+), 6 deletions(-)

-- 
1.9.1



[STLinux Kernel] [PATCH v2 4/4] ASoC: hdmi-codec: add channel mapping control

2016-12-19 Thread Arnaud Pouliquen

I detected 2 issues in this version, details below.

V3 is following.
Sorry for the inconvenience...

Regards
Arnaud

On 12/14/2016 04:16 PM, Arnaud Pouliquen wrote:
> +static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc)
> +{
> + int i;
> + const unsigned long hdmi_codec_eld_spk_alloc_bits[] = {
> + [0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR,
> + [4] = RC, [5] = FLC | FRC, [6] = RLC | RRC,
> + };
> + unsigned long spk_mask;
Missing initialization that generates warning during compilation
> +
> + for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) {
> + if (spk_alloc & (1 << i))
> + spk_mask |= hdmi_codec_eld_spk_alloc_bits[i];
> + }
> +
> + return spk_mask;
> +}
> +
> +/* From speaker bit mask to ALSA API channel position */
> +static int snd_hdac_spk_to_chmap(int spk)
> +{
> + const struct hdmi_codec_channel_map_table *t = hdmi_codec_map_table;
> +
> + for (; t->map; t++) {
> + if (t->spk_mask == spk)
> + return t->map;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * hdmi_codec_cea_init_channel_alloc:
> + * Compute derived values in hdmi_codec_channel_alloc[].
> + * spk_na_mask is used to store unused channels in mid of the channel
> + * allocations. These particular channels are then considered as active 
> channels
> + * For instance:
> + *CA_ID 0x02: CA =  (FL, FR, 0, FC) => spk_na_mask = 0x04, channels = 4
> + *CA_ID 0x04: CA =  (FL, FR, 0, 0, RC) => spk_na_mask = 0x03C, channels 
> = 5
> + */
> +static void hdmi_codec_cea_init_channel_alloc(void)
> +{
> + int i, j, k, last;
> + struct hdmi_codec_cea_spk_alloc *p;
> +
> + /* Test if not already done by another instance */
> + if (hdmi_codec_channel_alloc[0].channels)
> + return;
> +
> + for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++) {
> + p = hdmi_codec_channel_alloc + i;
> + p->spks_mask = 0;
> + p->spk_na_mask = 0;
> + last = HDMI_MAX_SPEAKERS;
> + for (j = 0, k = 7; j < HDMI_MAX_SPEAKERS; j++, k--) {
> + if (p->speakers[j]) {
> + p->spks_mask |= p->speakers[j];
> + if (last == HDMI_MAX_SPEAKERS)
> + last = j;
> + } else if (last != HDMI_MAX_SPEAKERS) {
> + p->spk_na_mask |= 1 << k;
> + }
> + }
> + p->channels = 8 - last;
> + }
> +}
> +
> +static int hdmi_codec_get_ch_alloc_table_idx(struct hdmi_codec_priv *hcp,
> +  unsigned char channels)
> +{
> + int i;
> + u8 spk_alloc;
> + unsigned long spk_mask;
> + struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc;
> +
> + spk_alloc = drm_eld_get_spk_alloc(hcp->eld);
> + spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);
> +
> + for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) {
> + if (cap->channels != channels)
> + continue;
> + if (!(cap->spks_mask == (spk_mask & cap->spks_mask)))
> + continue;
> + return i;
> + }
> +
If HDMI cable not plugged, ELD is empty. In this case this function
returns an error. For backward compatible, it should not return an error
but a default allocation that should be stereo.

> + return -EINVAL;
> +}
> +
> +static void hdmi_cea_alloc_to_tlv_spks(struct hdmi_codec_cea_spk_alloc *cap,
> +unsigned char *chmap)
> +{
> + int count = 0;
> + int c, spk;
> +
> + /* Detect unused channels in cea caps, tag them as N/A channel in TLV */
> + for (c = 0; c < HDMI_MAX_SPEAKERS; c++) {
> + spk = cap->speakers[7 - c];
> + if (cap->spk_na_mask & BIT(c))
> + chmap[count++] = SNDRV_CHMAP_NA;
> + else
> + chmap[count++] = snd_hdac_spk_to_chmap(spk);
> + }
> +}
> +
> +static void hdmi_cea_alloc_to_tlv_chmap(struct hdmi_codec_priv *hcp,
> + struct hdmi_codec_cea_spk_alloc *cap)
> +{
> + unsigned int chs, count = 0;
> + struct snd_pcm_chmap *info = hcp->chmap_info;
> + struct snd_pcm_chmap_elem *chmap = info->chmap;
> + unsigned long max_chs = info->max_channels;
> + int num_ca = ARRAY_SIZE(hdmi_codec_channe

[alsa-lib][PATCH] ASoC: hdmi-codec: use unsigned type to structure members with bit-field instead of signed type

2016-12-16 Thread Arnaud Pouliquen
Hi Takashi,

Reviewed and tested for sti machine.

Acked-by: Arnaud Pouliquen 

Regards
Arnaud

On 12/16/2016 10:26 AM, Takashi Sakamoto wrote:
> This is a fix for Linux 4.10-rc1.
> 
> In C language specification, a bit-field is interpreted as a signed or
> unsigned integer type consisting of the specified number of bits.
> 
> In GCC manual, the range of a signed bit field of N bits is from
> -(2^N) / 2 to ((2^N) / 2) - 1
> https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Bit-Fields
> 
> Therefore, when defined as 1 bit-field with signed type, variables can
> represents -1 and 0.
> 
> The snd-soc-hdmi-codec module includes a structure which has signed type
> members with bit-fields. Codes of this module assign 0 and 1 to the
> members. This seems to result in implementation-dependent behaviours.
> 
> As of v4.10-rc1 merge window, outside of sound subsystem, this structure
> is referred by below GPU modules.
>  - tda998x
>  - sti-drm
>  - mediatek-drm-hdmi
>  - msm
> 
> As long as I review their codes relevant to the structure, the structure
> members are used just for condition statements and printk formats.
> My proposal of change is a bit intrusive to the printk formats but this
> may be acceptable.
> 
> Totally, it's reasonable to use unsigned type for the structure members.
> This bug is detected by Sparse, static code analyzer with below warnings.
> 
> ./include/sound/hdmi-codec.h:39:26: error: dubious one-bit signed bitfield
> ./include/sound/hdmi-codec.h:40:28: error: dubious one-bit signed bitfield
> ./include/sound/hdmi-codec.h:41:29: error: dubious one-bit signed bitfield
> ./include/sound/hdmi-codec.h:42:31: error: dubious one-bit signed bitfield
> 
> CC: Jyri Sarha 
> CC: Jie Qiu 
> CC: Arnaud Pouliquen 
> CC: Srinivas Kandagatla 
> CC: dri-devel at lists.freedesktop.org
> CC: stable at vger.kernel.org
> Fixes: 09184118a8ab ("ASoC: hdmi-codec: Add hdmi-codec for external 
> HDMI-encoders")
> Signed-off-by: Takashi Sakamoto 
> ---
>  include/sound/hdmi-codec.h | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> index 530c57b..915c435 100644
> --- a/include/sound/hdmi-codec.h
> +++ b/include/sound/hdmi-codec.h
> @@ -36,10 +36,10 @@ struct hdmi_codec_daifmt {
>   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;
> + unsigned int bit_clk_inv:1;
> + unsigned int frame_clk_inv:1;
> + unsigned int bit_clk_master:1;
> + unsigned int frame_clk_master:1;
>  };
>  
>  /*
> 


[PATCH v2 4/4] ASoC: hdmi-codec: add channel mapping control

2016-12-14 Thread Arnaud Pouliquen
Add user interface to provide channel mapping.
In a first step this control is read only.

As TLV type, the control provides all configuration available for
HDMI sink(ELD), and provides current channel mapping selected by codec
based on ELD and number of channels specified by user on open.
When control is called before the number of the channel is specified
(i.e. hw_params is set), it returns all channels set to UNKNOWN.

Signed-off-by: Arnaud Pouliquen 
---
 sound/soc/codecs/hdmi-codec.c | 310 +-
 1 file changed, 309 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index f27d115..01c837c 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -18,12 +18,131 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 

 #include  /* This is only to get MAX_ELD_BYTES */

+#define HDMI_MAX_SPEAKERS  8
+
+struct hdmi_codec_channel_map_table {
+   unsigned char map;  /* ALSA API channel map position */
+   unsigned long spk_mask; /* speaker position bit mask */
+};
+
+/*
+ * CEA speaker placement for HDMI 1.4:
+ *
+ *  FL  FLC   FC   FRC   FR   FRW
+ *
+ *  LFE
+ *
+ *  RL  RLC   RC   RRC   RR
+ *
+ *  Speaker placement has to be extended to support HDMI 2.0
+ */
+enum hdmi_codec_cea_spk_placement {
+   FL  = BIT(0),   /* Front Left   */
+   FC  = BIT(1),   /* Front Center */
+   FR  = BIT(2),   /* Front Right  */
+   FLC = BIT(3),   /* Front Left Center*/
+   FRC = BIT(4),   /* Front Right Center   */
+   RL  = BIT(5),   /* Rear Left*/
+   RC  = BIT(6),   /* Rear Center  */
+   RR  = BIT(7),   /* Rear Right   */
+   RLC = BIT(8),   /* Rear Left Center */
+   RRC = BIT(9),   /* Rear Right Center*/
+   LFE = BIT(10),  /* Low Frequency Effect */
+};
+
+static const struct hdmi_codec_channel_map_table hdmi_codec_map_table[] = {
+   { SNDRV_CHMAP_FL,   FL },
+   { SNDRV_CHMAP_FR,   FR },
+   { SNDRV_CHMAP_RL,   RL },
+   { SNDRV_CHMAP_RR,   RR },
+   { SNDRV_CHMAP_LFE,  LFE },
+   { SNDRV_CHMAP_FC,   FC },
+   { SNDRV_CHMAP_RLC,  RLC },
+   { SNDRV_CHMAP_RRC,  RRC },
+   { SNDRV_CHMAP_RC,   RC },
+   { SNDRV_CHMAP_FLC,  FLC },
+   { SNDRV_CHMAP_FRC,  FRC },
+   {} /* terminator */
+};
+
+/*
+ * cea Speaker allocation structure
+ */
+struct hdmi_codec_cea_spk_alloc {
+   const int ca_id;
+   const unsigned long speakers[HDMI_MAX_SPEAKERS];
+
+   /* Derived values, computed during init */
+   unsigned int channels;
+   unsigned long spks_mask;
+   unsigned long spk_na_mask;
+};
+
+/* default HDMI channel maps is stereo */
+const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = {
+   { .channels = 2,
+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+   { }
+};
+
+/*
+ * hdmi_codec_channel_alloc: speaker configuration available for CEA
+ *
+ * This is an ordered list!
+ * The preceding ones have better chances to be selected by
+ * hdmi_codec_get_ch_alloc_table_idx().
+ */
+static struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
+{ .ca_id = 0x00,  .speakers = {   0,0,   0,   0,   0,0,  FR,  FL } },
+/* 2.1 */
+{ .ca_id = 0x01,  .speakers = {   0,0,   0,   0,   0,  LFE,  FR,  FL } },
+/* Dolby Surround */
+{ .ca_id = 0x02,  .speakers = {   0,0,   0,   0,  FC,0,  FR,  FL } },
+/* surround51 */
+{ .ca_id = 0x0b,  .speakers = {   0,0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+/* surround40 */
+{ .ca_id = 0x08,  .speakers = {   0,0,  RR,  RL,   0,0,  FR,  FL } },
+/* surround41 */
+{ .ca_id = 0x09,  .speakers = {   0,0,  RR,  RL,   0,  LFE,  FR,  FL } },
+/* surround50 */
+{ .ca_id = 0x0a,  .speakers = {   0,0,  RR,  RL,  FC,0,  FR,  FL } },
+/* 6.1 */
+{ .ca_id = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+/* surround71 */
+{ .ca_id = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+
+{ .ca_id = 0x03,  .speakers = {   0,0,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_id = 0x04,  .speakers = {   0,0,   0,  RC,   0,0,  FR,  FL } },
+{ .ca_id = 0x05,  .speakers = {   0,0,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_id = 0x06,  .speakers = {   0,0,   0,  RC,  FC,0,  FR,  FL } },
+{ .ca_id = 0x07,  .speakers = {   0,0,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_id = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,0,  FR,  FL } },
+{ .ca_id = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_id = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,0,  FR,  FL } },
+{ .ca_id = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,0,  FR,  FL } },
+{ .ca_id = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_id = 0x12,  .speakers = { RRC

[PATCH v2 3/4] ASoC: core: add optional pcm_new callback for DAI driver

2016-12-14 Thread Arnaud Pouliquen
During probe, DAIs can need to perform some actions that requests
the knowledge of the pcm runtime handle.
The callback is called during DAIs linking, after PCM device creation.
For instance this can be used to add relation ship between a DAI pcm
control and the pcm device.

Signed-off-by: Arnaud Pouliquen 
---
 include/sound/soc-dai.h |  3 +++
 sound/soc/soc-core.c| 28 
 2 files changed, 31 insertions(+)

diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 964b7de..960990e 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -231,6 +231,9 @@ struct snd_soc_dai_driver {
int (*resume)(struct snd_soc_dai *dai);
/* compress dai */
int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num);
+   /* Optional Callback used at pcm creation*/
+   int (*pcm_new)(struct snd_soc_pcm_runtime *rtd,
+  struct snd_soc_dai *dai);
/* DAI is also used for the control bus */
bool bus_control;

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4afa8db..d3a6c22 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1552,6 +1552,27 @@ static int soc_probe_dai(struct snd_soc_dai *dai, int 
order)
return 0;
 }

+static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais,
+   struct snd_soc_pcm_runtime *rtd)
+{
+   int i, ret = 0;
+
+   for (i = 0; i < num_dais; ++i) {
+   struct snd_soc_dai_driver *drv = dais[i]->driver;
+
+   if (!rtd->dai_link->no_pcm && drv->pcm_new)
+   ret = drv->pcm_new(rtd, dais[i]);
+   if (ret < 0) {
+   dev_err(dais[i]->dev,
+   "ASoC: Failed to bind %s with pcm device\n",
+   dais[i]->name);
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
 static int soc_link_dai_widgets(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link,
struct snd_soc_pcm_runtime *rtd)
@@ -1663,6 +1684,13 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
   dai_link->stream_name, ret);
return ret;
}
+   ret = soc_link_dai_pcm_new(_dai, 1, rtd);
+   if (ret < 0)
+   return ret;
+   ret = soc_link_dai_pcm_new(rtd->codec_dais,
+  rtd->num_codecs, rtd);
+   if (ret < 0)
+   return ret;
} else {
INIT_DELAYED_WORK(>delayed_work,
codec2codec_close_delayed_work);
-- 
1.9.1



[PATCH v2 2/4] ALSA pcm: allow non constant snd_pcm_chmap_elem

2016-12-14 Thread Arnaud Pouliquen
For HDMI, channel mapping can be retrieved from ELD. In this case mapping
can change during runtime (plug/unplug).
This patch suppresses the 'const' property of the struct chmap.

Signed-off-by: Arnaud Pouliquen 
---
 include/sound/pcm.h  | 4 ++--
 sound/core/pcm_lib.c | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index af1fb37..3b459a3 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1355,7 +1355,7 @@ struct snd_pcm_chmap {
struct snd_pcm *pcm;/* assigned PCM instance */
int stream; /* PLAYBACK or CAPTURE */
struct snd_kcontrol *kctl;
-   const struct snd_pcm_chmap_elem *chmap;
+   struct snd_pcm_chmap_elem *chmap;
unsigned int max_channels;
unsigned int channel_mask;  /* optional: active channels bitmask */
void *private_data; /* optional: private data pointer */
@@ -1387,7 +1387,7 @@ extern const struct snd_pcm_chmap_elem 
snd_pcm_alt_chmaps[];
 #define SND_PCM_CHMAP_MASK_2468(SND_PCM_CHMAP_MASK_246 | (1U << 8))

 int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
-  const struct snd_pcm_chmap_elem *chmap,
+  struct snd_pcm_chmap_elem *chmap,
   int max_channels,
   unsigned long private_value,
   struct snd_pcm_chmap **info_ret);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index bb12615..252a498 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2489,7 +2489,7 @@ static int pcm_chmap_ctl_get(struct snd_kcontrol 
*kcontrol,
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, >id);
struct snd_pcm_substream *substream;
-   const struct snd_pcm_chmap_elem *map;
+   struct snd_pcm_chmap_elem *map;

if (snd_BUG_ON(!info->chmap))
return -EINVAL;
@@ -2519,7 +2519,7 @@ static int pcm_chmap_ctl_tlv(struct snd_kcontrol 
*kcontrol, int op_flag,
 unsigned int size, unsigned int __user *tlv)
 {
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
-   const struct snd_pcm_chmap_elem *map;
+   struct snd_pcm_chmap_elem *map;
unsigned int __user *dst;
int c, count = 0;

@@ -2578,7 +2578,7 @@ static void pcm_chmap_ctl_private_free(struct 
snd_kcontrol *kcontrol)
  * Return: Zero if successful, or a negative error value.
  */
 int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
-  const struct snd_pcm_chmap_elem *chmap,
+  struct snd_pcm_chmap_elem *chmap,
   int max_channels,
   unsigned long private_value,
   struct snd_pcm_chmap **info_ret)
-- 
1.9.1



[PATCH v2 1/4] DRM: add help to get ELD speaker allocation

2016-12-14 Thread Arnaud Pouliquen
Add helper to allow users to retrieve the speaker allocations without
knowledge of the ELD structure.

Signed-off-by: Arnaud Pouliquen 
---
 include/drm/drm_edid.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 919933d..0706cc6 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -245,6 +245,7 @@ struct detailed_timing {
 # define DRM_ELD_AUD_SYNCH_DELAY_MAX   0xfa/* 500 ms */

 #define DRM_ELD_SPEAKER7
+# define DRM_ELD_SPEAKER_MASK  0x7f
 # define DRM_ELD_SPEAKER_RLRC  (1 << 6)
 # define DRM_ELD_SPEAKER_FLRC  (1 << 5)
 # define DRM_ELD_SPEAKER_RC(1 << 4)
@@ -412,6 +413,18 @@ static inline int drm_eld_size(const uint8_t *eld)
 }

 /**
+ * drm_eld_get_spk_alloc - Get speaker allocation
+ * @eld: pointer to an ELD memory structure
+ *
+ * The returned value is the speakers mask. User has to use %DRM_ELD_SPEAKER
+ * field definitions to identify speakers.
+ */
+static inline u8 drm_eld_get_spk_alloc(const uint8_t *eld)
+{
+   return eld[DRM_ELD_SPEAKER] & DRM_ELD_SPEAKER_MASK;
+}
+
+/**
  * drm_eld_get_conn_type - Get device type hdmi/dp connected
  * @eld: pointer to an ELD memory structure
  *
-- 
1.9.1



[PATCH v2 0/4] Generic HDMI codec: Add channel mapping control

2016-12-14 Thread Arnaud Pouliquen
Aim of this patch is to add  'Playback Channel Map' control to export 
audio capabilities in term of HDMI sink speakers allocation.

V2:
In this version I use chmap helper functions from pcm_lib.c. 
It is quite tricky to use it from ASoC due to the relation chip of the controls
with the pcm runtime.
After several tries, my conclusion is that it must be handled in ASoC DAI 
driver.
Main reason is that the DAI driver can not provide snd_pcm_chmap struct
through kcontrol structure. But this induces that soc-core provides pcm runtime
structure to DAI driver during probe.

Base on this conclusion. I reworked my patches by adding 2 
new patches in patch-set
1)  ALSA pcm: allow non constant snd_pcm_chmap_elem
   This patch allows to handle non constant channel mapping. As ELD
   information can change during runtime it is mandatory to properly 
   handle the feature.
   In term of compatibility with legacy it should be straightforward,
   as update just consists in suppressing the 'const' constraint.

2)  ASoC: core: add optional pcm_new callback for DAI driver
This is the only way i found to be able to use 
snd_pcm_add_chmap_ctls and associated controls helper functions.
From my point of view, this is the more simple way to add relationship
between DAI and associated pcm devices.
   Notice that this patch, if accepted, makes the following one obsolete,
   as it also answer to the associated topic:
  [PATCH v5 0/2] ALSA controls management using index/device/sub-devices fields
  (http://www.spinics.net/lists/alsa-devel/msg57639.html).

If you estimate that this it not reasonable i will come back to my first 
version.

V1:
This patch follow discussion initiates here: 
[RFC] ASOC: HDMI audio info frame speaker allocation
http://www.spinics.net/lists/alsa-devel/msg57363.html

The code is fully inspired from HDA driver.
On hw_param, HDMI sink speaker capabilities are exported via TLV ops
and  a CEA allocation is choson, based on ELD information and the number of
channels requested by user.

Mains differences with HDA implementation are:
 - Control is read only
 - Channel swap is not supported. Consequence is that unused channel in
   the mid of CEA audio infoframe channel mapping are considered as
   active.
   example for channel allocation 0x02: FL, FR, 0, FC)
This configuration is only available for a 4 channels stream.
  - Channel allocation table has been reordered and HDMI 2.0 is not
supported.

Arnaud Pouliquen (4):
  DRM: add help to get ELD speaker allocation
  ALSA pcm: allow non constant snd_pcm_chmap_elem
  ASoC: core: add optional pcm_new callback for DAI driver
  ASoC: hdmi-codec: add channel mapping control

 include/drm/drm_edid.h|  13 ++
 include/sound/pcm.h   |   4 +-
 include/sound/soc-dai.h   |   3 +
 sound/core/pcm_lib.c  |   6 +-
 sound/soc/codecs/hdmi-codec.c | 310 +-
 sound/soc/soc-core.c  |  28 
 6 files changed, 358 insertions(+), 6 deletions(-)

-- 
1.9.1



[PATCH 2/2] ASoC: hdmi-codec: add channel mapping control

2016-12-13 Thread Arnaud Pouliquen


On 12/13/2016 02:58 PM, Takashi Sakamoto wrote:
> On 2016年12月13日 22:23, Takashi Sakamoto wrote:
>> Hi Arnaud,
 This table is invariant in lifetime of the storage object, as well.
 Let's put into .rodata section, too.

>>> This table is updated in hdmi_codec_cea_init_channel_alloc so can not be
>>> constant. In theory i could declare all field instead of computing some.
>>> But for lisibility, i would prefer to just declare ca_index  and
>>> speakers allocation field in this table (i will declared both as const)
>>
>> You should pay enough attention to a case that one system has several
>> GPUs to which relevant GPU drivers register HDMI_CODEC_DRV_NAME platform
>> device. The 'static' modifier has an effect to keep just one storage
>> object, thus your code causes bugs in the case.
> 
> Oops, the bug is unrelated to the static modifier. The modifier is for 
> reference scope. I'll correct as the file local symbol has just one 
> storage object.
> 
> (I might be tired tonight...)
> 
i understood in this way :-)
As 'ca_index' and "speakers" fiel are constants
the fields computed in hdmi_codec_cea_init_channel_alloc will
not change if the functions is called several time ( multi-instances).
but agree that it is not very clean, but this should work.
To avoid to compute several time, i can also add a test in
hdmi_codec_cea_init_channel_alloc to do it only one time (by testing
hdmi_codec_channel_alloc[0].channels), or perhaps better an atomic local
variable to avoid side effect for Multiprocessor archs.

Now the second approach is to define all the field. This indeeds a big
table (around 256 lines instead of 32 lines):

static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
{
.ca_index = 0x00,
.speakers = {   0,0,   0,   0,   0,0,  FR,  FL } },
.channels = 2,
.spk_mask = FR | FL,
.spk_na_mask = 0x00,
},
{ /* 2.1 */
.ca_index = 0x01,
.speakers = {   0,0,   0,   0,   0,  LFE,  FR,  FL } },
.channels = 3,
.spk_mask = FR | FL | LFE,
.spk_na_mask = 0x00,
},
{ /* Dolby Surround */
.ca_index = 0x02,
.speakers = {   0,0,   0,   0,  FC,0,  FR,  FL } },
.channels = 4,
.spk_mask = FR | FL | FC,
.spk_na_mask = BIT(2),
},
[...]

{
.ca_index = 0x1f,
.speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
.channels = 8,
.spk_mask = FRC | FLC | RR | RL | FC | LFE | FR | FL,
.spk_na_mask = 0x0,
},

I would prefer the first one to save lines, but i can implement the
second one (or another one if you have an alternative to propose).

Regards
Arnaud


[PATCH 2/2] ASoC: hdmi-codec: add channel mapping control

2016-12-12 Thread Arnaud Pouliquen
  static const struct snd_kcontrol_new hdmi_controls[] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ |
 @@ -79,6 +400,17 @@ static const struct snd_kcontrol_new hdmi_controls[] = 
 {
.info = hdmi_eld_ctl_info,
.get = hdmi_eld_ctl_get,
},
 +  {
 +  .access = SNDRV_CTL_ELEM_ACCESS_READ |
 +SNDRV_CTL_ELEM_ACCESS_TLV_READ |
 +SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK |
 +SNDRV_CTL_ELEM_ACCESS_VOLATILE,
 +  .iface = SNDRV_CTL_ELEM_IFACE_PCM,
 +  .name = "Playback Channel Map",
 +  .info = hdmi_codec_chmap_ctl_info,
 +  .get = hdmi_codec_chmap_ctl_get,
 +  .tlv.c = hdmi_codec_chmap_ctl_tlv,
 +  },
  };
>>>
>>> If you can keep the same interface for applications as
>>> 'snd_pcm_add_chmap_ctls()' have, it's better to integrate the function
>>> to have different tables/callbacks depending on drivers.
>>>
>> I had a look before define it. Unfortunately i cannot use
>> snd_pcm_add_chmap_ctls. snd_pcm_add_chmap_ctls requests "snd_pcm"
>> structure as input param. ASoC codec not aware of it.
>> i could add an helper for ASoC, but hdmi-codec should be used for HDMI
>> drivers and i'm not sure that there is another need in ASoC.
> 
> For example, splitting the function to two parts; one gets the parameter 
> for pcm instance, another deal with adding control element sets. Symbols 
> of both functions are going to be exported and your code can reuse the 
> latter.
> 
> My motivation for this idea is to use the same code for control element 
> sets with the same name of 'Playback Channel Map'. In this case, usage 
> of the same code brings us an merit. We can produce the consist way for 
> applications to handle the control element sets, even if long term 
> development brings much code changes. It has an advantage to reduce 
> maintaining effort.
> 
> This is merely my initial idea. If it's impossible, your idea is preferable.
> 

I checked you proposal. I see 2 blocking points:
- ASoC core set the control private_data field to snd_soc_component so
it is not possible to reuse pcm_chmap_ctl_get/set/tlv that request
snd_pcm_chmap type for the private_data

- The control is a PCM control, so for multi instances it could have to
migrate to the pcm_controls field if following patch is accepted:
[PATCH v5 0/2] ALSA controls management using index/device/sub-devices
fields (http://www.spinics.net/lists/alsa-devel/msg57639.html)
in this case it must be created by the ASoC core and not the driver itself

Alternative could be to treat the control in soc-core:
In soc_link_dai_pcm_controls that is created in patch-set mentioned above.

I have to improve and test it(dirty code for concept...) but this would
be something like that :

static int soc_link_dai_pcm_controls(struct snd_soc_dai **dais, int
num_dais,
 struct snd_soc_pcm_runtime *rtd)
{
struct snd_kcontrol_new kctl;
int i, j, ret;

for (i = 0; i < num_dais; ++i) {
for (j = 0; j < dais[i]->driver->num_pcm_controls; j++) {
kctl = dais[i]->driver->pcm_controls[j];

+   /* TODO test also capture */
+   if(!strcmp(kctl->name, "Playback Channel Map") {
+   ret = snd_pcm_add_chmap_ctls(rtd->pcm,
+ SNDRV_PCM_STREAM_PLAYBACK,
+ /* Not very clean: chmap pointer is stored in 
private_value */
+ (const struct snd_pcm_chmap_elem *) 
kctl.private_value,
+ dai->driver->playback.max_channels,
+ 0, NULL);
+   continue;
+   }
if (kctl.iface != SNDRV_CTL_ELEM_IFACE_PCM ||
rtd->dai_link->no_pcm) {
dev_err(dais[i]->dev,
"ASoC: Failed to bind %s control: %s\n",
dais[i]->name, kctl.name);
return -EINVAL;
}
Regards
Arnaud


[PATCH 2/2] ASoC: hdmi-codec: add channel mapping control

2016-12-12 Thread Arnaud Pouliquen


On 12/12/2016 03:05 PM, Takashi Sakamoto wrote:
> On Dec 12 2016 21:55, Takashi Iwai wrote:
>> On Mon, 12 Dec 2016 13:12:16 +0100,
>> Takashi Sakamoto wrote:
>>>
>>> On Dec 12 2016 18:54, Takashi Iwai wrote:
>>> +enum hdmi_codec_cea_spk_placement {
>>> +   FL  = (1 <<  0),/* Front Left   */
>>> +   FC  = (1 <<  1),/* Front Center */
>>> +   FR  = (1 <<  2),/* Front Right  */
>>> +   FLC = (1 <<  3),/* Front Left Center*/
>>> +   FRC = (1 <<  4),/* Front Right Center   */
>>> +   RL  = (1 <<  5),/* Rear Left*/
>>> +   RC  = (1 <<  6),/* Rear Center  */
>>> +   RR  = (1 <<  7),/* Rear Right   */
>>> +   RLC = (1 <<  8),/* Rear Left Center */
>>> +   RRC = (1 <<  9),/* Rear Right Center*/
>>> +   LFE = (1 << 10),/* Low Frequency Effect */
>>> +};
>>
>> BIT() macro in "linux/bitops.h" is available.
> will be corrected in a v2

 One slight caution: BIT() expands to an unsigned long type.
>>>
>>> Mmm, indeed. This is my wrong indication, sorry.
>>> Thanks for your correction.
>>
>> Well, it's not necessarily wrong.  My point is that it requires
>> caution sometimes, as it's not blindly convertible.
>> In short: it depends on the code.
> 
> Hm. Here, I prefer to avoiding needless type-coversions, especially 
> between 'signed' and 'unsigned'. In C semantics of enumerator 
> specifiers, these values are handled as 'int' type. On the other hand, 
> the BIT() macro has 'UL' suffix.
> 
> In short: carefulness.
I will have a look if reasonable or not to integrate use of BIT ...

Arnaud


[PATCH 2/2] ASoC: hdmi-codec: add channel mapping control

2016-12-12 Thread Arnaud Pouliquen


On 12/12/2016 01:03 PM, Takashi Sakamoto wrote:
> On 2016年12月12日 18:38, Arnaud Pouliquen wrote:
>>>> + */
>>>> +static struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
>>>> +/*  channel:   7 6543 21  
>>>>   0  */
>>>> +{ .ca_index = 0x00,  .speakers = {   0,0,   0,   0,   0,0,  FR,  
>>>> FL } },
>>>> +   /* 2.1 */
>>>> +{ .ca_index = 0x01,  .speakers = {   0,0,   0,   0,   0,  LFE,  FR,  
>>>> FL } },
>>>> +   /* Dolby Surround */
>>>> +{ .ca_index = 0x02,  .speakers = {   0,0,   0,   0,  FC,0,  FR,  
>>>> FL } },
>>>> +   /* surround51 */
>>>> +{ .ca_index = 0x0b,  .speakers = {   0,0,  RR,  RL,  FC,  LFE,  FR,  
>>>> FL } },
>>>> +   /* surround40 */
>>>> +{ .ca_index = 0x08,  .speakers = {   0,0,  RR,  RL,   0,0,  FR,  
>>>> FL } },
>>>> +   /* surround41 */
>>>> +{ .ca_index = 0x09,  .speakers = {   0,0,  RR,  RL,   0,  LFE,  FR,  
>>>> FL } },
>>>> +   /* surround50 */
>>>> +{ .ca_index = 0x0a,  .speakers = {   0,0,  RR,  RL,  FC,0,  FR,  
>>>> FL } },
>>>> +   /* 6.1 */
>>>> +{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  
>>>> FL } },
>>>> +   /* surround71 */
>>>> +{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  
>>>> FL } },
>>>> +
>>>> +{ .ca_index = 0x03,  .speakers = {   0,0,   0,   0,  FC,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x04,  .speakers = {   0,0,   0,  RC,   0,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x05,  .speakers = {   0,0,   0,  RC,   0,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x06,  .speakers = {   0,0,   0,  RC,  FC,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x07,  .speakers = {   0,0,   0,  RC,  FC,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,0,  FR,  
>>>> FL } },
>>>> +{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  
>>>> FL } },
>>>> +};
>>>
>>> Ditto.
>> Sorry not understand this comment vs the previous one, could you please
>> clarify?
> 
> This table is invariant in lifetime of the storage object, as well. 
> Let's put into .rodata section, too.
>
This table is updated in hdmi_codec_cea_init_channel_alloc so can not be
constant. In theory i could declare all field instead of computing some.
But for lisibility, i would prefer to just declare ca_index  and
speakers allocation field in this table (i will declared both as const)

Regards,

Arnaud



[PATCH 2/2] ASoC: hdmi-codec: add channel mapping control

2016-12-12 Thread Arnaud Pouliquen


On 12/11/2016 07:09 AM, Takashi Sakamoto wrote:
> On Dec 9 2016 01:37, Arnaud Pouliquen wrote:
>> Add user interface to provide channel mapping.
>> In a first step this control is read only.
>>
>> As TLV type, the control provides all configurations available for
>> HDMI sink(ELD), and provides current channel mapping selected by codec
>> based on ELD and number of channels specified by user on open.
>> When control is called before the number of the channel is specified
>> (i.e. hw_params is set), it returns all channels set to UNKNOWN.
>>
>> Notice that SNDRV_CTL_TLVT_CHMAP_FIXED is used for all mappings,
>> as no information is available from HDMI driver to allow channel swapping.
>>
>> Signed-off-by: Arnaud Pouliquen 
>> ---
>>  sound/soc/codecs/hdmi-codec.c | 346 
>> +-
>>  1 file changed, 345 insertions(+), 1 deletion(-)
>>
>> diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
>> index f27d115..0cb83a3 100644
>> --- a/sound/soc/codecs/hdmi-codec.c
>> +++ b/sound/soc/codecs/hdmi-codec.c
>> @@ -18,12 +18,137 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  #include 
>>  #include 
>>  #include 
>>
>>  #include  /* This is only to get MAX_ELD_BYTES */
>>
>> +#define HDMI_MAX_SPEAKERS  8
>> +
>> +/*
>> + * CEA speaker placement for HDMI 1.4:
>> + *
>> + *  FL  FLC   FC   FRC   FR   FRW
>> + *
>> + *  LFE
>> + *
>> + *  RL  RLC   RC   RRC   RR
>> + *
>> + *  Speaker placement has to be extended to support HDMI 2.0
>> + */
>> +enum hdmi_codec_cea_spk_placement {
>> +FL  = (1 <<  0),/* Front Left   */
>> +FC  = (1 <<  1),/* Front Center */
>> +FR  = (1 <<  2),/* Front Right  */
>> +FLC = (1 <<  3),/* Front Left Center*/
>> +FRC = (1 <<  4),/* Front Right Center   */
>> +RL  = (1 <<  5),/* Rear Left*/
>> +RC  = (1 <<  6),/* Rear Center  */
>> +RR  = (1 <<  7),/* Rear Right   */
>> +RLC = (1 <<  8),/* Rear Left Center */
>> +RRC = (1 <<  9),/* Rear Right Center*/
>> +LFE = (1 << 10),/* Low Frequency Effect */
>> +};
> 
> BIT() macro in "linux/bitops.h" is available.
will be corrected in a v2
> 
>> +
>> +/*
>> + * ELD Speaker allocation bits in the CEA Speaker Allocation data block
>> + */
>> +static int hdmi_codec_eld_spk_alloc_bits[] = {
>> +[0] = FL | FR,
>> +[1] = LFE,
>> +[2] = FC,
>> +[3] = RL | RR,
>> +[4] = RC,
>> +[5] = FLC | FRC,
>> +[6] = RLC | RRC,
>> +};
> 
> Please put this kind of invariant table into .rodata section with 
> 'const' modifier.
will be corrected in a v2

> 
>> +
>> +struct hdmi_codec_channel_map_table {
>> +unsigned char map;  /* ALSA API channel map position */
>> +int spk_mask;   /* speaker position bit mask */
>> +};
>> +
>> +static struct hdmi_codec_channel_map_table hdmi_codec_map_table[] = {
>> +{ SNDRV_CHMAP_FL,   FL },
>> +{ SNDRV_CHMAP_FR,   FR },
>> +{ SNDRV_CHMAP_RL,   RL },
>> +{ SNDRV_CHMAP_RR,   RR },
>> +{ SNDRV_CHMAP_LFE,  LFE },
>> +{ SNDRV_CHMAP_FC,   FC },
>> +{ SNDRV_CHMAP_RLC,  RLC },
>> +{ SNDRV_CHMAP_RRC,  RRC },
>> +{ SNDRV_CHMAP_RC,   RC },
>> +{ SNDRV_CHMAP_FLC,  FLC },
>> +{ SNDRV_CHMAP_FRC,  FRC },
>> +{} /* terminator */
>> +};
> 
> In this case, the table can be put into snd_hdac_spk_to_chmap().
will be corrected in a v2
> 
>> +
>> +/*
>> + * cea Speaker allocation structure
>> + */
>> +struct hdmi_codec_cea_spk_alloc {
>> +int ca_index;
>> +int speakers[HDMI_MAX_SPEAKERS];
>> +
>> +/* Derived values, computed during init */
>> +int channels;
>> +int spk_mask;
>> +int spk_na_mask;
>> +};
>> +
>> +/*
>> + * This is an ordered list!
>> + *
>> + * The preceding ones have better chances to be selected by
>> + * hdmi_channel_allocation().
> 
> The function is not defined and implemented. It takes developers to be 
> puzzled.
will be corrected in a v2

> 
>> + */
>> +static struct hdmi_codec_cea_spk_alloc 

[PATCH 0/2] Generic HDMI codec: Add channel mapping control

2016-12-09 Thread Arnaud Pouliquen
Hi,

On 12/08/2016 10:13 PM, Takashi Sakamoto wrote:
> On Dec 9 2016 05:52, Takashi Sakamoto wrote:
>> On Dec 9 2016 01:37, Arnaud Pouliquen wrote:
>>> Aim of this patch is to add  'Playback Channel Map' control to export
>>> audio capabilities in term of HDMI sink speakers allocation.
>>> This patch follow discussion initiates here:
>>> [RFC] ASOC: HDMI audio info frame speaker allocation
>>> http://www.spinics.net/lists/alsa-devel/msg57363.html
>>>
>>> The code is fully inspired from HDA driver.
>>> On hw_param, HDMI sink speaker capabilities are exported via TLV ops
>>> and  a CEA allocation is choson, based on ELD information and the
>>> number of
>>> channels requested by user.
>>>
>>> Mains differences with HDA implementation are:
>>>  - Control is read only
>>>  - Channel swap is not supported. Consequence is that unused channel in
>>>the mid of CEA audio infoframe channel mapping are considered as
>>>active.
>>>example for channel allocation 0x02: FL, FR, 0, FC)
>>>     This configuration is only available for a 4 channels stream.
>>>   - Channel allocation table has been reordered and HDMI 2.0 is not
>>> supported.
>>>
>>> Arnaud Pouliquen (2):
>>>   DRM: add help to get ELD speaker allocation
>>>   ASoC: hdmi-codec: add channel mapping control
>>>
>>>  include/drm/drm_edid.h|  13 ++
>>>  sound/soc/codecs/hdmi-codec.c | 346
>>> +-
>>>  2 files changed, 358 insertions(+), 1 deletion(-)
>>
>> Please pay enough attention to development cycle for Linux kernel.
>>
>> We're mostly on the end of development for 4.9 cycle, and review process
>> for new feature might be delay for next cycle, till 4.9 release, two
>> weeks later.
> 
> Oops. I was stupid just after awakening...
> 
> Anyway, we're mostly on the end of development for 4.10 cycle, and the
> review process for new feature might be delay till 4.10-rc1 release, two
> weeks later. During the weeks. bug fixes are preferable to be applied.

Thank you for warning me. No problem for the delay, i fully understand
that focus is on bug fixes.
Notice that it is quite difficult for developers to find the best timing
to address this kind of patch, as integration process is not always
simple to follow... this probably come with experience.

So if i well understand your remark the best windows to integrate a
feature for the version N+1, is to propose patch from N-rc1 tag.
(expecting that patch-set is enough mature to be integrated in N+1...)

Regards
Arnaud


[PATCH 2/2] ASoC: hdmi-codec: add channel mapping control

2016-12-08 Thread Arnaud Pouliquen
Add user interface to provide channel mapping.
In a first step this control is read only.

As TLV type, the control provides all configurations available for
HDMI sink(ELD), and provides current channel mapping selected by codec
based on ELD and number of channels specified by user on open.
When control is called before the number of the channel is specified
(i.e. hw_params is set), it returns all channels set to UNKNOWN.

Notice that SNDRV_CTL_TLVT_CHMAP_FIXED is used for all mappings,
as no information is available from HDMI driver to allow channel swapping.

Signed-off-by: Arnaud Pouliquen 
---
 sound/soc/codecs/hdmi-codec.c | 346 +-
 1 file changed, 345 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index f27d115..0cb83a3 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -18,12 +18,137 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 

 #include  /* This is only to get MAX_ELD_BYTES */

+#define HDMI_MAX_SPEAKERS  8
+
+/*
+ * CEA speaker placement for HDMI 1.4:
+ *
+ *  FL  FLC   FC   FRC   FR   FRW
+ *
+ *  LFE
+ *
+ *  RL  RLC   RC   RRC   RR
+ *
+ *  Speaker placement has to be extended to support HDMI 2.0
+ */
+enum hdmi_codec_cea_spk_placement {
+   FL  = (1 <<  0),/* Front Left   */
+   FC  = (1 <<  1),/* Front Center */
+   FR  = (1 <<  2),/* Front Right  */
+   FLC = (1 <<  3),/* Front Left Center*/
+   FRC = (1 <<  4),/* Front Right Center   */
+   RL  = (1 <<  5),/* Rear Left*/
+   RC  = (1 <<  6),/* Rear Center  */
+   RR  = (1 <<  7),/* Rear Right   */
+   RLC = (1 <<  8),/* Rear Left Center */
+   RRC = (1 <<  9),/* Rear Right Center*/
+   LFE = (1 << 10),/* Low Frequency Effect */
+};
+
+/*
+ * ELD Speaker allocation bits in the CEA Speaker Allocation data block
+ */
+static int hdmi_codec_eld_spk_alloc_bits[] = {
+   [0] = FL | FR,
+   [1] = LFE,
+   [2] = FC,
+   [3] = RL | RR,
+   [4] = RC,
+   [5] = FLC | FRC,
+   [6] = RLC | RRC,
+};
+
+struct hdmi_codec_channel_map_table {
+   unsigned char map;  /* ALSA API channel map position */
+   int spk_mask;   /* speaker position bit mask */
+};
+
+static struct hdmi_codec_channel_map_table hdmi_codec_map_table[] = {
+   { SNDRV_CHMAP_FL,   FL },
+   { SNDRV_CHMAP_FR,   FR },
+   { SNDRV_CHMAP_RL,   RL },
+   { SNDRV_CHMAP_RR,   RR },
+   { SNDRV_CHMAP_LFE,  LFE },
+   { SNDRV_CHMAP_FC,   FC },
+   { SNDRV_CHMAP_RLC,  RLC },
+   { SNDRV_CHMAP_RRC,  RRC },
+   { SNDRV_CHMAP_RC,   RC },
+   { SNDRV_CHMAP_FLC,  FLC },
+   { SNDRV_CHMAP_FRC,  FRC },
+   {} /* terminator */
+};
+
+/*
+ * cea Speaker allocation structure
+ */
+struct hdmi_codec_cea_spk_alloc {
+   int ca_index;
+   int speakers[HDMI_MAX_SPEAKERS];
+
+   /* Derived values, computed during init */
+   int channels;
+   int spk_mask;
+   int spk_na_mask;
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_channel_allocation().
+ */
+static struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
+/*   channel:   7 6543 210  */
+{ .ca_index = 0x00,  .speakers = {   0,0,   0,   0,   0,0,  FR,  FL } 
},
+/* 2.1 */
+{ .ca_index = 0x01,  .speakers = {   0,0,   0,   0,   0,  LFE,  FR,  FL } 
},
+/* Dolby Surround */
+{ .ca_index = 0x02,  .speakers = {   0,0,   0,   0,  FC,0,  FR,  FL } 
},
+/* surround51 */
+{ .ca_index = 0x0b,  .speakers = {   0,0,  RR,  RL,  FC,  LFE,  FR,  FL } 
},
+/* surround40 */
+{ .ca_index = 0x08,  .speakers = {   0,0,  RR,  RL,   0,0,  FR,  FL } 
},
+/* surround41 */
+{ .ca_index = 0x09,  .speakers = {   0,0,  RR,  RL,   0,  LFE,  FR,  FL } 
},
+/* surround50 */
+{ .ca_index = 0x0a,  .speakers = {   0,0,  RR,  RL,  FC,0,  FR,  FL } 
},
+/* 6.1 */
+{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } 
},
+/* surround71 */
+{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } 
},
+
+{ .ca_index = 0x03,  .speakers = {   0,0,   0,   0,  FC,  LFE,  FR,  FL } 
},
+{ .ca_index = 0x04,  .speakers = {   0,0,   0,  RC,   0,0,  FR,  FL } 
},
+{ .ca_index = 0x05,  .speakers = {   0,0,   0,  RC,

[PATCH 1/2] DRM: add help to get ELD speaker allocation

2016-12-08 Thread Arnaud Pouliquen
Add helper to allow users to retrieve the speaker allocations without
knowledge of the ELD structure.

Signed-off-by: Arnaud Pouliquen 
---
 include/drm/drm_edid.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 919933d..0706cc6 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -245,6 +245,7 @@ struct detailed_timing {
 # define DRM_ELD_AUD_SYNCH_DELAY_MAX   0xfa/* 500 ms */

 #define DRM_ELD_SPEAKER7
+# define DRM_ELD_SPEAKER_MASK  0x7f
 # define DRM_ELD_SPEAKER_RLRC  (1 << 6)
 # define DRM_ELD_SPEAKER_FLRC  (1 << 5)
 # define DRM_ELD_SPEAKER_RC(1 << 4)
@@ -412,6 +413,18 @@ static inline int drm_eld_size(const uint8_t *eld)
 }

 /**
+ * drm_eld_get_spk_alloc - Get speaker allocation
+ * @eld: pointer to an ELD memory structure
+ *
+ * The returned value is the speakers mask. User has to use %DRM_ELD_SPEAKER
+ * field definitions to identify speakers.
+ */
+static inline u8 drm_eld_get_spk_alloc(const uint8_t *eld)
+{
+   return eld[DRM_ELD_SPEAKER] & DRM_ELD_SPEAKER_MASK;
+}
+
+/**
  * drm_eld_get_conn_type - Get device type hdmi/dp connected
  * @eld: pointer to an ELD memory structure
  *
-- 
1.9.1



[PATCH 0/2] Generic HDMI codec: Add channel mapping control

2016-12-08 Thread Arnaud Pouliquen
Aim of this patch is to add  'Playback Channel Map' control to export 
audio capabilities in term of HDMI sink speakers allocation.
This patch follow discussion initiates here: 
[RFC] ASOC: HDMI audio info frame speaker allocation
http://www.spinics.net/lists/alsa-devel/msg57363.html

The code is fully inspired from HDA driver.
On hw_param, HDMI sink speaker capabilities are exported via TLV ops
and  a CEA allocation is choson, based on ELD information and the number of
channels requested by user.

Mains differences with HDA implementation are:
 - Control is read only
 - Channel swap is not supported. Consequence is that unused channel in
   the mid of CEA audio infoframe channel mapping are considered as
   active.
   example for channel allocation 0x02: FL, FR, 0, FC)
This configuration is only available for a 4 channels stream.
  - Channel allocation table has been reordered and HDMI 2.0 is not
supported.

Arnaud Pouliquen (2):
  DRM: add help to get ELD speaker allocation
  ASoC: hdmi-codec: add channel mapping control

 include/drm/drm_edid.h|  13 ++
 sound/soc/codecs/hdmi-codec.c | 346 +-
 2 files changed, 358 insertions(+), 1 deletion(-)

-- 
1.9.1



[PATCH] drm: sti: allow audio playback on HDMI even if disabled.

2016-09-30 Thread Arnaud Pouliquen
This fix allows to play audio while HDMI is disconnected.
When HDMI is disable, audio configuration is stored and samples
are dropped (by HDMI IP).
When HDMI is enabled, audio HDMI configuration is applied and samples
are outputted on HDMI wire.

Signed-off-by: Arnaud Pouliquen 
---
 drivers/gpu/drm/sti/sti_hdmi.c | 205 -
 1 file changed, 101 insertions(+), 104 deletions(-)

diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 376b076..9c0025e 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -788,6 +788,95 @@ static void sti_hdmi_disable(struct drm_bridge *bridge)
hdmi->enabled = false;
 }

+/**
+ * sti_hdmi_audio_get_non_coherent_n() - get N parameter for non-coherent
+ * clocks. None-coherent clocks means that audio and TMDS clocks have not the
+ * same source (drifts between clocks). In this case assumption is that CTS is
+ * automatically calculated by hardware.
+ *
+ * @audio_fs: audio frame clock frequency in Hz
+ *
+ * Values computed are based on table described in HDMI specification 1.4b
+ *
+ * Returns n value.
+ */
+static int sti_hdmi_audio_get_non_coherent_n(unsigned int audio_fs)
+{
+   unsigned int n;
+
+   switch (audio_fs) {
+   case 32000:
+   n = 4096;
+   break;
+   case 44100:
+   n = 6272;
+   break;
+   case 48000:
+   n = 6144;
+   break;
+   case 88200:
+   n = 6272 * 2;
+   break;
+   case 96000:
+   n = 6144 * 2;
+   break;
+   case 176400:
+   n = 6272 * 4;
+   break;
+   case 192000:
+   n = 6144 * 4;
+   break;
+   default:
+   /* Not pre-defined, recommended value: 128 * fs / 1000 */
+   n = (audio_fs * 128) / 1000;
+   }
+
+   return n;
+}
+
+static int hdmi_audio_configure(struct sti_hdmi *hdmi)
+{
+   int audio_cfg, n;
+   struct hdmi_audio_params *params = >audio;
+   struct hdmi_audio_infoframe *info = >cea;
+
+   DRM_DEBUG_DRIVER("\n");
+
+   if (!hdmi->enabled)
+   return 0;
+
+   /* update N parameter */
+   n = sti_hdmi_audio_get_non_coherent_n(params->sample_rate);
+
+   DRM_DEBUG_DRIVER("Audio rate = %d Hz, TMDS clock = %d Hz, n = %d\n",
+params->sample_rate, hdmi->mode.clock * 1000, n);
+   hdmi_write(hdmi, n, HDMI_AUDN);
+
+   /* update HDMI registers according to configuration */
+   audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID |
+   HDMI_AUD_CFG_ONE_BIT_INVALID;
+
+   switch (info->channels) {
+   case 8:
+   audio_cfg |= HDMI_AUD_CFG_CH78_VALID;
+   case 6:
+   audio_cfg |= HDMI_AUD_CFG_CH56_VALID;
+   case 4:
+   audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH;
+   case 2:
+   audio_cfg |= HDMI_AUD_CFG_CH12_VALID;
+   break;
+   default:
+   DRM_ERROR("ERROR: Unsupported number of channels (%d)!\n",
+ info->channels);
+   return -EINVAL;
+   }
+
+   hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG);
+
+   return hdmi_audio_infoframe_config(hdmi);
+}
+
 static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
 {
struct sti_hdmi *hdmi = bridge->driver_private;
@@ -826,9 +915,12 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
if (hdmi_avi_infoframe_config(hdmi))
DRM_ERROR("Unable to configure AVI infoframe\n");

-   /* Program AUDIO infoframe */
-   if (hdmi_audio_infoframe_config(hdmi))
-   DRM_ERROR("Unable to configure AUDIO infoframe\n");
+   if (hdmi->audio.enabled) {
+   if (hdmi_audio_configure(hdmi))
+   DRM_ERROR("Unable to configure audio\n");
+   } else {
+   hdmi_audio_infoframe_config(hdmi);
+   }

/* Program VS infoframe */
if (hdmi_vendor_infoframe_config(hdmi))
@@ -1078,97 +1170,6 @@ static struct drm_encoder *sti_hdmi_find_encoder(struct 
drm_device *dev)
return NULL;
 }

-/**
- * sti_hdmi_audio_get_non_coherent_n() - get N parameter for non-coherent
- * clocks. None-coherent clocks means that audio and TMDS clocks have not the
- * same source (drifts between clocks). In this case assumption is that CTS is
- * automatically calculated by hardware.
- *
- * @audio_fs: audio frame clock frequency in Hz
- *
- * Values computed are based on table described in HDMI specification 1.4b
- *
- * Returns n value.
- */
-static int sti_hdmi_audio_get_non_coherent_n(unsigned int audio_fs)
-{
-   unsigned int n;
-
-   switch (audio_fs) {
-   case 32000:
-   n = 4096;
-   b

[PATCH v8 15/18] ARM: STi: DT: STiH407: Add uniperif reader dt nodes

2016-09-05 Thread Arnaud Pouliquen
Hello ptere, Lee,

Thanks for your remarks,

Regards
Arnaud
On 08/31/2016 01:28 PM, Lee Jones wrote:
> On Tue, 30 Aug 2016, Peter Griffin wrote:
>> Thanks for reviewing and your very valuable feedback.
>> On Tue, 30 Aug 2016, Lee Jones wrote:
>>> On Fri, 26 Aug 2016, Peter Griffin wrote:
>>>
>>>> This patch adds the DT node for the uniperif reader
>>>> IP block found on STiH407 family silicon.
>>>>
>>>> Signed-off-by: Arnaud Pouliquen 
>>>> Signed-off-by: Peter Griffin 
>>>> ---
>>>>  arch/arm/boot/dts/stih407-family.dtsi | 26 ++
>>>>  1 file changed, 26 insertions(+)
>>>>
>>>> diff --git a/arch/arm/boot/dts/stih407-family.dtsi 
>>>> b/arch/arm/boot/dts/stih407-family.dtsi
>>>> index d263c96..bdddf2c 100644
>>>> --- a/arch/arm/boot/dts/stih407-family.dtsi
>>>> +++ b/arch/arm/boot/dts/stih407-family.dtsi
>>>> @@ -956,5 +956,31 @@
>>>>st,version = <5>;
>>>>st,mode = "SPDIF";
>>>>};
>>>> +
>>>> +  sti_uni_reader0: sti-uni-reader at 0 {
>>>> +  compatible = "st,sti-uni-reader";
>>>> +  status = "disabled";
>>>
>>> I find it's normally nicer to place the status of the node at the
>>> bottom, separated by a '\n'.
>>
>> Ok I'll add a superflous '\n' in the next version.
> 
> Everyone loves a smart arse!
> 
> In this case I believe the '\n' to be a functional separator and not
> superfluous at all.
> 
>>>> +  dai-name = "Uni Reader #0 (PCM IN)";
>>>
>>> Oooo, not seen something like this before.
>>>
>>> If it does not already have one, it would require a DT Ack.
>>
>> No idea, the driver got merged 1 year ago.
This field could be suppressed and handled in source code, using
st,uniperiph-id to retreive it.
>>
>> Arnaud did you get a DT ack when you merged this driver & binding? i if i 
>> remember well, i had  sent to Alsa mailing list only, I missed
this obvious...
>>>
>>>> +  st,version = <3>;
>>>
>>> This will likely need a DT Ack too.  We usually encode this sort of
>>> information in the compatible string.
yes, better to use compatibility
>>
>> See 05c1b4480e86a871b18030d6f3d532dc0ecdf38c
> 
> Well Rob's the boss.  We certainly never used to take 'device ID' or
> 'version' attributes.  I guess something must have changed.

I will try to provide patches for code and bindings rework this week.



[v4,1/2] video: hdmi: add helper functions for N and CTS

2016-06-07 Thread Arnaud Pouliquen
hi Doug,

Thanks for this very interesting feed back.

On my side i'm quite busy on some other topics, and on my platform,
CTS is hardware computed.
So if you have the experience and the hardware for coherent N and CTS
calculations, you are welcome to improve my patch.

On 06/06/2016 06:34 PM, Doug Anderson wrote:
> Hi,
> 
> On Thu, Apr 21, 2016 at 8:29 AM, Arnaud Pouliquen  
> wrote:
>> Add helper functions to compute HDMI CTS and N parameters.
>> Implementation is based on HDMI 1.4b specification.
> 
> It would be super nice to have this somewhere common.  Any idea who
> would land this?
I discussed with Daniel Vetter on DRM IRC, he requests more
adherence/commitment on it. So if you are interested in using helpers in
your driver that should help :-)

> 
> 
>> +static const struct hdmi_audio_acr hdmi_audio_standard_acr[3][13] = {
>> +   [HDMI_AUDIO_N_CTS_32KHZ] = {
>> +   /* N and CTS values for 32 kHz rate*/
>> +   {  25174825, {  4576,  28125, 0 } }, /* 25.20/1.001  MHz */
>> +   {  2520, {  4096,  25200, 0 } }, /* 25.20MHz */
>> +   {  2700, {  4096,  27000, 0 } }, /* 27.00MHz */
>> +   {  27027000, {  4096,  27027, 0 } }, /* 27.00*1.001  MHz */
>> +   {  5400, {  4096,  54000, 0 } }, /* 54.00MHz */
>> +   {  54054000, {  4096,  54054, 0 } }, /* 54.00*1.001  MHz */
>> +   {  74175824, { 11648, 210937, 50 } }, /* 74.25/1.001 MHz */
>> +   {  7425, {  4096,  74250, 0 } }, /* 74.25MHz */
>> +   { 148351648, { 11648, 421875, 0 } }, /* 148.50/1.001 MHz */
>> +   { 14850, {  4096, 148500, 0 } }, /* 148.50   MHz */
>> +   { 296703296, {  5824, 421875, 0 } }, /* 297/1.001 MHz 
>> (truncated)*/
>> +   { 296703297, {  5824, 421875, 0 } }, /* 297/1.001 MHz 
>> (rounded)*/
>> +   { 29700, {  3072, 222750, 0 } }, /* 297  MHz */
> 
> One thing to note is that for all but the non-integral clock rates and
> the rates >= ~297MHz, all of this can be done programmatically.
> ...the function I came up with to do that is pretty slow, so a table
> is still useful in general unless you want to try to optimize things,
> but it might be nice to have the function available as a fallback?
> Specifically many TVs will allow audio to work with rates other than
> the ones in the HDMI spec.
> 
> You can see the full implementation we used on some devices I worked
> on at 
> <https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14/drivers/gpu/drm/bridge/dw_hdmi.c>.
> Specifically the function for computing N:
> 
> static unsigned int hdmi_compute_n(struct dw_hdmi *hdmi,
>unsigned long pixel_clk)
> {
>   unsigned int freq = hdmi->sample_rate;
>   unsigned int min_n = DIV_ROUND_UP((128 * freq), 1500);
>   unsigned int max_n = (128 * freq) / 300;
>   unsigned int ideal_n = (128 * freq) / 1000;
>   unsigned int best_n_distance = ideal_n;
>   unsigned int best_n = 0;
>   u64 best_diff = U64_MAX;
>   int n;
>   /* If the ideal N could satisfy the audio math, then just take it */
>   if (hdmi_audio_math_diff(freq, ideal_n, pixel_clk) == 0)
> return ideal_n;
>   for (n = min_n; n <= max_n; n++) {
> u64 diff = hdmi_audio_math_diff(freq, n, pixel_clk);
> if (diff < best_diff || (diff == best_diff &&
> abs(n - ideal_n) < best_n_distance)) {
>   best_n = n;
>   best_diff = diff;
>   best_n_distance = abs(best_n - ideal_n);
> }
> /*
>  * The best N already satisfy the audio math, and also be
>  * the closest value to ideal N, so just cut the loop.
>  */
> if ((best_diff == 0) && (abs(n - ideal_n) > best_n_distance))
>   break;
>   }
>   return best_n;
> }
Right, I have based my default case algorithm, on HDMI recommendation,
> +   val = (u64)tmds_clk * n_cts->n;
> +   n_cts->cts = div64_u64(val, 128UL * audio_fs);
but yours seems more accurate. if too slow, a parameter could allows to
select between accurate and fast calculation...
> 
> I believe this function written by Yakir Yang based on a bit of python
> I had coded up.  The python has the advantage that it will come up
> with the right N/CTS even for fractional clock rates, like
> 25.20/1.001:
> 
> def DIV_ROUND_UP(x, y): return (x + y - 1) / y
> def calc(freq, tmds):
>   min_n = DIV_ROUND_UP((128 * freq), 1500)
>   max_n = (128 * freq) / 300
>   ideal_n = (128 * freq) / 1000
>   best = 0x
>   for n in xrange(min_n, max_n + 1):
> cts = int(round((tmds * n / (128. 

[PATCH v5 1/1] drm: sti: Add ASoC generic hdmi codec support.

2016-05-30 Thread Arnaud Pouliquen
Add the interface needed by audio hdmi-codec driver.

Signed-off-by: Arnaud Pouliquen 
---
 drivers/gpu/drm/sti/Kconfig|   1 +
 drivers/gpu/drm/sti/sti_hdmi.c | 294 ++---
 drivers/gpu/drm/sti/sti_hdmi.h |  13 ++
 3 files changed, 291 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
index 5ad43a1..494ab25 100644
--- a/drivers/gpu/drm/sti/Kconfig
+++ b/drivers/gpu/drm/sti/Kconfig
@@ -7,5 +7,6 @@ config DRM_STI
select DRM_KMS_CMA_HELPER
select DRM_PANEL
select FW_LOADER
+   select SND_SOC_HDMI_CODEC if SND_SOC
help
  Choose this option to enable DRM on STM stiH41x chipset
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 6ef0715..f345c2d 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -18,6 +18,8 @@
 #include 
 #include 

+#include 
+
 #include "sti_hdmi.h"
 #include "sti_hdmi_tx3g4c28phy.h"
 #include "sti_hdmi_tx3g0c55phy.h"
@@ -35,6 +37,8 @@
 #define HDMI_DFLT_CHL0_DAT  0x0110
 #define HDMI_DFLT_CHL1_DAT  0x0114
 #define HDMI_DFLT_CHL2_DAT  0x0118
+#define HDMI_AUDIO_CFG  0x0200
+#define HDMI_SPDIF_FIFO_STATUS  0x0204
 #define HDMI_SW_DI_1_HEAD_WORD  0x0210
 #define HDMI_SW_DI_1_PKT_WORD0  0x0214
 #define HDMI_SW_DI_1_PKT_WORD1  0x0218
@@ -44,6 +48,9 @@
 #define HDMI_SW_DI_1_PKT_WORD5  0x0228
 #define HDMI_SW_DI_1_PKT_WORD6  0x022C
 #define HDMI_SW_DI_CFG  0x0230
+#define HDMI_SAMPLE_FLAT_MASK   0x0244
+#define HDMI_AUDN   0x0400
+#define HDMI_AUD_CTS0x0404
 #define HDMI_SW_DI_2_HEAD_WORD  0x0600
 #define HDMI_SW_DI_2_PKT_WORD0  0x0604
 #define HDMI_SW_DI_2_PKT_WORD1  0x0608
@@ -103,6 +110,7 @@
 #define HDMI_INT_DLL_LCKBIT(5)
 #define HDMI_INT_NEW_FRAME  BIT(6)
 #define HDMI_INT_GENCTRL_PKTBIT(7)
+#define HDMI_INT_AUDIO_FIFO_XRUNBIT(8)
 #define HDMI_INT_SINK_TERM_PRESENT  BIT(11)

 #define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \
@@ -111,6 +119,7 @@
| HDMI_INT_GLOBAL)

 #define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \
+   | HDMI_INT_AUDIO_FIFO_XRUN \
| HDMI_INT_GENCTRL_PKT \
| HDMI_INT_NEW_FRAME \
| HDMI_INT_DLL_LCK \
@@ -121,6 +130,27 @@

 #define HDMI_STA_SW_RST BIT(1)

+#define HDMI_AUD_CFG_8CH   BIT(0)
+#define HDMI_AUD_CFG_SPDIF_DIV_2   BIT(1)
+#define HDMI_AUD_CFG_SPDIF_DIV_3   BIT(2)
+#define HDMI_AUD_CFG_SPDIF_CLK_DIV_4   (BIT(1) | BIT(2))
+#define HDMI_AUD_CFG_CTS_CLK_256FS BIT(12)
+#define HDMI_AUD_CFG_DTS_INVALID   BIT(16)
+#define HDMI_AUD_CFG_ONE_BIT_INVALID   (BIT(18) | BIT(19) | BIT(20) |  BIT(21))
+#define HDMI_AUD_CFG_CH12_VALIDBIT(28)
+#define HDMI_AUD_CFG_CH34_VALIDBIT(29)
+#define HDMI_AUD_CFG_CH56_VALIDBIT(30)
+#define HDMI_AUD_CFG_CH78_VALIDBIT(31)
+
+/* sample flat mask */
+#define HDMI_SAMPLE_FLAT_NO 0
+#define HDMI_SAMPLE_FLAT_SP0 BIT(0)
+#define HDMI_SAMPLE_FLAT_SP1 BIT(1)
+#define HDMI_SAMPLE_FLAT_SP2 BIT(2)
+#define HDMI_SAMPLE_FLAT_SP3 BIT(3)
+#define HDMI_SAMPLE_FLAT_ALL (HDMI_SAMPLE_FLAT_SP0 | HDMI_SAMPLE_FLAT_SP1 |\
+ HDMI_SAMPLE_FLAT_SP2 | HDMI_SAMPLE_FLAT_SP3)
+
 #define HDMI_INFOFRAME_HEADER_TYPE(x)(((x) & 0xff) <<  0)
 #define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
 #define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
@@ -171,6 +201,10 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
wake_up_interruptible(>wait_event);
}

+   /* Audio FIFO underrun IRQ */
+   if (hdmi->irq_status & HDMI_INT_AUDIO_FIFO_XRUN)
+   DRM_INFO("Warning: audio FIFO underrun occurs!");
+
return IRQ_HANDLED;
 }

@@ -441,26 +475,29 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi 
*hdmi)
  */
 static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
 {
-   struct hdmi_audio_infoframe infofame;
+   struct hdmi_audio_params *audio = >audio;
u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
-   int ret;
-
-   ret = hdmi_audio_infoframe_init();
-   if (ret < 0) {
-   DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
-   return ret;
-   }
-
-   infofame.channels = 2;
-
-   ret = hdmi_audio_infoframe_pack(, buffer, sizeof(buffer));
-   if (ret < 0) {
-   DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
-   return ret;
+   int ret, val;
+
+   DRM_DEBUG_DRIVER("enter %s, AIF %s\n", __func__,
+ 

[PATCH v5 0/1] sti: add audio interface to the hdmi driver

2016-05-30 Thread Arnaud Pouliquen
This patchset implements audio interface in HDMI drm driver. Implementation is 
based on 
ASoC generic hdmi codec driver( https://patchwork.kernel.org/patch/8713141/). 

V5:
Helper functions are suppressed, following dicussion on IRC with Daniel 
Vetter.
request is that other drivers that can use helper are also updated
helper function patch will be proposed  in a next, separed patchset.
for this track, hdmi_audio_get_non_coherent_n is integrated in sti 
driver.

V4:
 fixes for "video: hdmi: add helper functions for N and CTS"
- typo error and additional comments
- cts_1_ratio computation
- warning reported by kbuild test robot
- add rounded value for 297/1.001 MHz

V3: 
 - video: hdmi: add helper function for N and CTS
  Also used on Mediatek platform 
(https://patchwork.kernel.org/patch/8887341)
  delta vs V2:
  - typo fixes
  - if/else code optimisation
 - drm: sti: Add ASoC generic hdmi codec support.
  - typo fixes
  - add audio registers in debugfs information

V2: RFC
https://patchwork.kernel.org/patch/8091531/("video: hdmi: add helper function 
for N and CTS")
https://patchwork.kernel.org/patch/8091561/("ASoC: hdmi-codec: Add hdmi-codec 
for external HDMI-encoders")
 - patch: video: hdmi: add helper function for N and CTS
 Fixes based on Russel King remarks
 - Duplicate function to have a separte treatment for coherent and
   non-coherent clocks
 - Add ratio field for alternate CTS value
 - Clock frequency in Hz for TMDS and audio clocks
 - Add information concerning clocks and CTS calculation. 

V1: 
This RFC is the implementation of audio HDMI on sti platform based on generic 
hdmi-codec driver:
https://patchwork.kernel.org/patch/7215271/ ("ASoC: hdmi-codec: Add 
hdmi-codec for external HDMI-encoders")
https://patchwork.kernel.org/patch/8062611/ ("video: hdmi: add helper 
function for N and CTS")

Arnaud Pouliquen (1):
  drm: sti: Add ASoC generic hdmi codec support.

 drivers/gpu/drm/sti/Kconfig|   1 +
 drivers/gpu/drm/sti/sti_hdmi.c | 294 ++---
 drivers/gpu/drm/sti/sti_hdmi.h |  13 ++
 3 files changed, 291 insertions(+), 17 deletions(-)

-- 
1.9.1



[PATCH v4 1/2] video: hdmi: add helper functions for N and CTS

2016-05-09 Thread Arnaud Pouliquen
Hello,

As there is no more feedback on this patch, should i suppose that I need
to abandon it?

I can integrate it in my driver... but as, N and CTS calculation is not
platform dependent, this would make sense to add it in a generic part.
(Example of another platform that could use it:
https://patchwork.kernel.org/patch/8887341)

Thanks and regards
Arnaud

On 04/28/2016 02:13 PM, Arnaud Pouliquen wrote:
> Add linux-fbdev diffusion list in loop for patch-set review.
> 
> On 04/21/2016 05:29 PM, Arnaud POULIQUEN wrote:
>> Add helper functions to compute HDMI CTS and N parameters.
>> Implementation is based on HDMI 1.4b specification.
>>
>> Signed-off-by: Arnaud Pouliquen 
>> Acked-by: Benjamin Gaignard 
>> Acked-by: Vincent ABRIOU 
>> ---
>>  drivers/video/hdmi.c | 208 
>> +++
>>  include/linux/hdmi.h |  24 ++
>>  2 files changed, 232 insertions(+)
>>
>> diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
>> index 1626892..5d124ef 100644
>> --- a/drivers/video/hdmi.c
>> +++ b/drivers/video/hdmi.c
>> @@ -1242,3 +1242,211 @@ int hdmi_infoframe_unpack(union hdmi_infoframe 
>> *frame, void *buffer)
>>  return ret;
>>  }
>>  EXPORT_SYMBOL(hdmi_infoframe_unpack);
>> +
>> +/*
>> + * audio clock regeneration (acr) parameters
>> + * N and CTS computation are based on HDMI specification 1.4b
>> + */
>> +enum hdmi_audio_rate {
>> +HDMI_AUDIO_N_CTS_32KHZ,
>> +HDMI_AUDIO_N_CTS_44_1KHZ,
>> +HDMI_AUDIO_N_CTS_48KHZ,
>> +};
>> +
>> +struct hdmi_audio_acr {
>> +unsigned int tmds_clk;
>> +struct hdmi_audio_n_cts n_cts;
>> +};
>> +
>> +static const struct hdmi_audio_acr hdmi_audio_standard_acr[3][13] = {
>> +[HDMI_AUDIO_N_CTS_32KHZ] = {
>> +/* N and CTS values for 32 kHz rate*/
>> +{  25174825, {  4576,  28125, 0 } }, /* 25.20/1.001  MHz */
>> +{  2520, {  4096,  25200, 0 } }, /* 25.20MHz */
>> +{  2700, {  4096,  27000, 0 } }, /* 27.00MHz */
>> +{  27027000, {  4096,  27027, 0 } }, /* 27.00*1.001  MHz */
>> +{  5400, {  4096,  54000, 0 } }, /* 54.00MHz */
>> +{  54054000, {  4096,  54054, 0 } }, /* 54.00*1.001  MHz */
>> +{  74175824, { 11648, 210937, 50 } }, /* 74.25/1.001 MHz */
>> +{  7425, {  4096,  74250, 0 } }, /* 74.25MHz */
>> +{ 148351648, { 11648, 421875, 0 } }, /* 148.50/1.001 MHz */
>> +{ 14850, {  4096, 148500, 0 } }, /* 148.50   MHz */
>> +{ 296703296, {  5824, 421875, 0 } }, /* 297/1.001 MHz 
>> (truncated)*/
>> +{ 296703297, {  5824, 421875, 0 } }, /* 297/1.001 MHz 
>> (rounded)*/
>> +{ 29700, {  3072, 222750, 0 } }, /* 297  MHz */
>> +},
>> +[HDMI_AUDIO_N_CTS_44_1KHZ] = {
>> +/* N and CTS values for 44.1 kHz, 88.2 kHz and 176.4 kHz rates*/
>> +{  25174825, {  7007,  31250, 0 } }, /* 25.20/1.001  MHz */
>> +{  2520, {  6272,  28000, 0 } }, /* 25.20MHz */
>> +{  2700, {  6272,  3, 0 } }, /* 27.00MHz */
>> +{  27027000, {  6272,  30030, 0 } }, /* 27.00*1.001  MHz */
>> +{  5400, {  6272,  6, 0 } }, /* 54.00MHz */
>> +{  54054000, {  6272,  60060, 0 } }, /* 54.00*1.001  MHz */
>> +{  74175824, { 17836, 234375, 0 } }, /* 74.25/1.001  MHz */
>> +{  7425, {  6272,  82500, 0 } }, /* 74.25MHz */
>> +{ 148351648, {  8918, 234375, 0 } }, /* 148.50/1.001 MHz */
>> +{ 14850, {  6272, 165000, 0 } }, /* 148.50   MHz */
>> +{ 296703296, {  4459, 234375, 0 } }, /* 297/1.001 MHz 
>> (truncated) */
>> +{ 296703297, {  4459, 234375, 0 } }, /* 297/1.001 MHz (rounded) 
>> */
>> +{ 29700, {  4704, 247500, 0 } }, /* 297  MHz */
>> +},
>> +[HDMI_AUDIO_N_CTS_48KHZ] = {
>> +/* N and CTS values for 48 kHz, 96 kHz and 192 kHz rates*/
>> +{  25174825, {  6864,  28125, 0 } }, /* 25.20/1.001  MHz */
>> +{  2520, {  6144,  25200, 0 } }, /* 25.20MHz */
>> +{  2700, {  6144,  27000, 0 } }, /* 27.00MHz */
>> +{  27027000, {  6144,  27027, 0 } }, /* 27.00*1.001  MHz */
>> +{  5400, {  6144,  54000, 0 } }, /* 54.00MHz */
>> +{  54054000, {  6144,  54054, 

[PATCH v4 2/2] drm: sti: Add ASoC generic hdmi codec support.

2016-04-28 Thread Arnaud Pouliquen
Add linux-fbdev diffusion list in loop for patch-set review.

On 04/21/2016 05:29 PM, Arnaud POULIQUEN wrote:
> Add the interface needed by audio hdmi-codec driver.
> 
> Signed-off-by: Arnaud Pouliquen 
> Acked-by: Benjamin Gaignard 
> Acked-by: Vincent ABRIOU 
> ---
>  drivers/gpu/drm/sti/Kconfig|   1 +
>  drivers/gpu/drm/sti/sti_hdmi.c | 248 
> ++---
>  drivers/gpu/drm/sti/sti_hdmi.h |  13 +++
>  3 files changed, 245 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
> index 5ad43a1..494ab25 100644
> --- a/drivers/gpu/drm/sti/Kconfig
> +++ b/drivers/gpu/drm/sti/Kconfig
> @@ -7,5 +7,6 @@ config DRM_STI
>   select DRM_KMS_CMA_HELPER
>   select DRM_PANEL
>   select FW_LOADER
> + select SND_SOC_HDMI_CODEC if SND_SOC
>   help
> Choose this option to enable DRM on STM stiH41x chipset
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 6ef0715..3a8bd47 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -18,6 +18,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  #include "sti_hdmi.h"
>  #include "sti_hdmi_tx3g4c28phy.h"
>  #include "sti_hdmi_tx3g0c55phy.h"
> @@ -35,6 +37,8 @@
>  #define HDMI_DFLT_CHL0_DAT  0x0110
>  #define HDMI_DFLT_CHL1_DAT  0x0114
>  #define HDMI_DFLT_CHL2_DAT  0x0118
> +#define HDMI_AUDIO_CFG  0x0200
> +#define HDMI_SPDIF_FIFO_STATUS  0x0204
>  #define HDMI_SW_DI_1_HEAD_WORD  0x0210
>  #define HDMI_SW_DI_1_PKT_WORD0  0x0214
>  #define HDMI_SW_DI_1_PKT_WORD1  0x0218
> @@ -44,6 +48,9 @@
>  #define HDMI_SW_DI_1_PKT_WORD5  0x0228
>  #define HDMI_SW_DI_1_PKT_WORD6  0x022C
>  #define HDMI_SW_DI_CFG  0x0230
> +#define HDMI_SAMPLE_FLAT_MASK   0x0244
> +#define HDMI_AUDN   0x0400
> +#define HDMI_AUD_CTS0x0404
>  #define HDMI_SW_DI_2_HEAD_WORD  0x0600
>  #define HDMI_SW_DI_2_PKT_WORD0  0x0604
>  #define HDMI_SW_DI_2_PKT_WORD1  0x0608
> @@ -103,6 +110,7 @@
>  #define HDMI_INT_DLL_LCKBIT(5)
>  #define HDMI_INT_NEW_FRAME  BIT(6)
>  #define HDMI_INT_GENCTRL_PKTBIT(7)
> +#define HDMI_INT_AUDIO_FIFO_XRUNBIT(8)
>  #define HDMI_INT_SINK_TERM_PRESENT  BIT(11)
>  
>  #define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \
> @@ -111,6 +119,7 @@
>   | HDMI_INT_GLOBAL)
>  
>  #define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \
> + | HDMI_INT_AUDIO_FIFO_XRUN \
>   | HDMI_INT_GENCTRL_PKT \
>   | HDMI_INT_NEW_FRAME \
>   | HDMI_INT_DLL_LCK \
> @@ -121,6 +130,27 @@
>  
>  #define HDMI_STA_SW_RST BIT(1)
>  
> +#define HDMI_AUD_CFG_8CH BIT(0)
> +#define HDMI_AUD_CFG_SPDIF_DIV_2 BIT(1)
> +#define HDMI_AUD_CFG_SPDIF_DIV_3 BIT(2)
> +#define HDMI_AUD_CFG_SPDIF_CLK_DIV_4 (BIT(1) | BIT(2))
> +#define HDMI_AUD_CFG_CTS_CLK_256FS   BIT(12)
> +#define HDMI_AUD_CFG_DTS_INVALID BIT(16)
> +#define HDMI_AUD_CFG_ONE_BIT_INVALID (BIT(18) | BIT(19) | BIT(20) |  BIT(21))
> +#define HDMI_AUD_CFG_CH12_VALID  BIT(28)
> +#define HDMI_AUD_CFG_CH34_VALID  BIT(29)
> +#define HDMI_AUD_CFG_CH56_VALID  BIT(30)
> +#define HDMI_AUD_CFG_CH78_VALID  BIT(31)
> +
> +/* sample flat mask */
> +#define HDMI_SAMPLE_FLAT_NO   0
> +#define HDMI_SAMPLE_FLAT_SP0 BIT(0)
> +#define HDMI_SAMPLE_FLAT_SP1 BIT(1)
> +#define HDMI_SAMPLE_FLAT_SP2 BIT(2)
> +#define HDMI_SAMPLE_FLAT_SP3 BIT(3)
> +#define HDMI_SAMPLE_FLAT_ALL (HDMI_SAMPLE_FLAT_SP0 | HDMI_SAMPLE_FLAT_SP1 |\
> +   HDMI_SAMPLE_FLAT_SP2 | HDMI_SAMPLE_FLAT_SP3)
> +
>  #define HDMI_INFOFRAME_HEADER_TYPE(x)(((x) & 0xff) <<  0)
>  #define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
>  #define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
> @@ -171,6 +201,10 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
>   wake_up_interruptible(>wait_event);
>   }
>  
> + /* Audio FIFO underrun IRQ */
> + if (hdmi->irq_status & HDMI_INT_AUDIO_FIFO_XRUN)
> + DRM_INFO("Warning: audio FIFO underrun occurs!");
> +
>   return IRQ_HANDLED;
>  }
>  
> @@ -441,26 +475,29 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi 
> *hdmi)
>   */
>  static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
>  {
> - struct 

[PATCH v4 1/2] video: hdmi: add helper functions for N and CTS

2016-04-28 Thread Arnaud Pouliquen
Add linux-fbdev diffusion list in loop for patch-set review.

On 04/21/2016 05:29 PM, Arnaud POULIQUEN wrote:
> Add helper functions to compute HDMI CTS and N parameters.
> Implementation is based on HDMI 1.4b specification.
> 
> Signed-off-by: Arnaud Pouliquen 
> Acked-by: Benjamin Gaignard 
> Acked-by: Vincent ABRIOU 
> ---
>  drivers/video/hdmi.c | 208 
> +++
>  include/linux/hdmi.h |  24 ++
>  2 files changed, 232 insertions(+)
> 
> diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
> index 1626892..5d124ef 100644
> --- a/drivers/video/hdmi.c
> +++ b/drivers/video/hdmi.c
> @@ -1242,3 +1242,211 @@ int hdmi_infoframe_unpack(union hdmi_infoframe 
> *frame, void *buffer)
>   return ret;
>  }
>  EXPORT_SYMBOL(hdmi_infoframe_unpack);
> +
> +/*
> + * audio clock regeneration (acr) parameters
> + * N and CTS computation are based on HDMI specification 1.4b
> + */
> +enum hdmi_audio_rate {
> + HDMI_AUDIO_N_CTS_32KHZ,
> + HDMI_AUDIO_N_CTS_44_1KHZ,
> + HDMI_AUDIO_N_CTS_48KHZ,
> +};
> +
> +struct hdmi_audio_acr {
> + unsigned int tmds_clk;
> + struct hdmi_audio_n_cts n_cts;
> +};
> +
> +static const struct hdmi_audio_acr hdmi_audio_standard_acr[3][13] = {
> + [HDMI_AUDIO_N_CTS_32KHZ] = {
> + /* N and CTS values for 32 kHz rate*/
> + {  25174825, {  4576,  28125, 0 } }, /* 25.20/1.001  MHz */
> + {  2520, {  4096,  25200, 0 } }, /* 25.20MHz */
> + {  2700, {  4096,  27000, 0 } }, /* 27.00MHz */
> + {  27027000, {  4096,  27027, 0 } }, /* 27.00*1.001  MHz */
> + {  5400, {  4096,  54000, 0 } }, /* 54.00MHz */
> + {  54054000, {  4096,  54054, 0 } }, /* 54.00*1.001  MHz */
> + {  74175824, { 11648, 210937, 50 } }, /* 74.25/1.001 MHz */
> + {  7425, {  4096,  74250, 0 } }, /* 74.25MHz */
> + { 148351648, { 11648, 421875, 0 } }, /* 148.50/1.001 MHz */
> + { 14850, {  4096, 148500, 0 } }, /* 148.50   MHz */
> + { 296703296, {  5824, 421875, 0 } }, /* 297/1.001 MHz 
> (truncated)*/
> + { 296703297, {  5824, 421875, 0 } }, /* 297/1.001 MHz 
> (rounded)*/
> + { 29700, {  3072, 222750, 0 } }, /* 297  MHz */
> + },
> + [HDMI_AUDIO_N_CTS_44_1KHZ] = {
> + /* N and CTS values for 44.1 kHz, 88.2 kHz and 176.4 kHz rates*/
> + {  25174825, {  7007,  31250, 0 } }, /* 25.20/1.001  MHz */
> + {  2520, {  6272,  28000, 0 } }, /* 25.20MHz */
> + {  2700, {  6272,  3, 0 } }, /* 27.00MHz */
> + {  27027000, {  6272,  30030, 0 } }, /* 27.00*1.001  MHz */
> + {  5400, {  6272,  6, 0 } }, /* 54.00MHz */
> + {  54054000, {  6272,  60060, 0 } }, /* 54.00*1.001  MHz */
> + {  74175824, { 17836, 234375, 0 } }, /* 74.25/1.001  MHz */
> + {  7425, {  6272,  82500, 0 } }, /* 74.25MHz */
> + { 148351648, {  8918, 234375, 0 } }, /* 148.50/1.001 MHz */
> + { 14850, {  6272, 165000, 0 } }, /* 148.50   MHz */
> + { 296703296, {  4459, 234375, 0 } }, /* 297/1.001 MHz 
> (truncated) */
> + { 296703297, {  4459, 234375, 0 } }, /* 297/1.001 MHz (rounded) 
> */
> + { 29700, {  4704, 247500, 0 } }, /* 297  MHz */
> + },
> + [HDMI_AUDIO_N_CTS_48KHZ] = {
> + /* N and CTS values for 48 kHz, 96 kHz and 192 kHz rates*/
> + {  25174825, {  6864,  28125, 0 } }, /* 25.20/1.001  MHz */
> + {  2520, {  6144,  25200, 0 } }, /* 25.20MHz */
> + {  2700, {  6144,  27000, 0 } }, /* 27.00MHz */
> + {  27027000, {  6144,  27027, 0 } }, /* 27.00*1.001  MHz */
> + {  5400, {  6144,  54000, 0 } }, /* 54.00MHz */
> + {  54054000, {  6144,  54054, 0 } }, /* 54.00*1.001  MHz */
> + {  74175824, { 11648, 140625, 0 } }, /* 74.25/1.001  MHz */
> + {  7425, {  6144,  74250, 0 } }, /* 74.25MHz */
> + { 148351648, {  5824, 140625, 0 } }, /* 148.50/1.001 MHz */
> + { 14850, {  6144, 148500, 0 } }, /* 148.50   MHz */
> + { 296703296, {  5824, 281250, 0 } }, /* 297/1.001 MHz 
> (truncated) */
> + { 296703297, {  5824, 281250, 0 } }, /* 297/1.001 MHz (rounded) 
> */
> + { 29700, {  5120, 247500, 0 } }, /* 297  MHz */
> + }
> +};
> +
> +/**
> + * hdmi_audio_get_coherent_n_cts() - compute N and CTS para

[PATCH v4 0/2] sti: add audio interface to the hdmi driver

2016-04-28 Thread Arnaud Pouliquen
Add linux-fbdev diffusion list in loop for patch-set review.

On 04/21/2016 05:29 PM, Arnaud POULIQUEN wrote:
> This patchset implements audio interface in HDMI drm driver. Implementation 
> is based on 
> ASoC generic hdmi codec driver( https://patchwork.kernel.org/patch/8713141/). 
> It also proposes helper functions to compute N and CTS parameters
> according to HDMI 1.4b specification. 
> 
> V4:
>  fixes for "video: hdmi: add helper functions for N and CTS"
> - typo error and additional comments
> - cts_1_ratio computation
> - warning reported by kbuild test robot
> - add rounded value for 297/1.001 MHz
> 
> V3: 
>  - video: hdmi: add helper function for N and CTS
> Also used on Mediatek platform 
> (https://patchwork.kernel.org/patch/8887341)
> delta vs V2:
>   - typo fixes
>   - if/else code optimisation
>  - drm: sti: Add ASoC generic hdmi codec support.
> - typo fixes
>   - add audio registers in debugfs information
> 
> V2: RFC
> https://patchwork.kernel.org/patch/8091531/("video: hdmi: add helper function 
> for N and CTS")
> https://patchwork.kernel.org/patch/8091561/("ASoC: hdmi-codec: Add hdmi-codec 
> for external HDMI-encoders")
>  - patch: video: hdmi: add helper function for N and CTS
>  Fixes based on Russel King remarks
>  - Duplicate function to have a separte treatment for coherent and
>non-coherent clocks
>  - Add ratio field for alternate CTS value
>  - Clock frequency in Hz for TMDS and audio clocks
>  - Add information concerning clocks and CTS calculation. 
> 
> V1: 
> This RFC is the implementation of audio HDMI on sti platform based on generic 
> hdmi-codec driver:
>   https://patchwork.kernel.org/patch/7215271/ ("ASoC: hdmi-codec: Add 
> hdmi-codec for external HDMI-encoders")
>   https://patchwork.kernel.org/patch/8062611/ ("video: hdmi: add helper 
> function for N and CTS")
> Arnaud Pouliquen (2):
>   video: hdmi: add helper functions for N and CTS
>   drm: sti: Add ASoC generic hdmi codec support.
> 
>  drivers/gpu/drm/sti/Kconfig|   1 +
>  drivers/gpu/drm/sti/sti_hdmi.c | 248 
> ++---
>  drivers/gpu/drm/sti/sti_hdmi.h |  13 +++
>  drivers/video/hdmi.c   | 208 ++
>  include/linux/hdmi.h   |  24 
>  5 files changed, 477 insertions(+), 17 deletions(-)
> 


[PATCH v4 2/2] drm: sti: Add ASoC generic hdmi codec support.

2016-04-21 Thread Arnaud Pouliquen
Add the interface needed by audio hdmi-codec driver.

Signed-off-by: Arnaud Pouliquen 
Acked-by: Benjamin Gaignard 
Acked-by: Vincent ABRIOU 
---
 drivers/gpu/drm/sti/Kconfig|   1 +
 drivers/gpu/drm/sti/sti_hdmi.c | 248 ++---
 drivers/gpu/drm/sti/sti_hdmi.h |  13 +++
 3 files changed, 245 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
index 5ad43a1..494ab25 100644
--- a/drivers/gpu/drm/sti/Kconfig
+++ b/drivers/gpu/drm/sti/Kconfig
@@ -7,5 +7,6 @@ config DRM_STI
select DRM_KMS_CMA_HELPER
select DRM_PANEL
select FW_LOADER
+   select SND_SOC_HDMI_CODEC if SND_SOC
help
  Choose this option to enable DRM on STM stiH41x chipset
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 6ef0715..3a8bd47 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -18,6 +18,8 @@
 #include 
 #include 

+#include 
+
 #include "sti_hdmi.h"
 #include "sti_hdmi_tx3g4c28phy.h"
 #include "sti_hdmi_tx3g0c55phy.h"
@@ -35,6 +37,8 @@
 #define HDMI_DFLT_CHL0_DAT  0x0110
 #define HDMI_DFLT_CHL1_DAT  0x0114
 #define HDMI_DFLT_CHL2_DAT  0x0118
+#define HDMI_AUDIO_CFG  0x0200
+#define HDMI_SPDIF_FIFO_STATUS  0x0204
 #define HDMI_SW_DI_1_HEAD_WORD  0x0210
 #define HDMI_SW_DI_1_PKT_WORD0  0x0214
 #define HDMI_SW_DI_1_PKT_WORD1  0x0218
@@ -44,6 +48,9 @@
 #define HDMI_SW_DI_1_PKT_WORD5  0x0228
 #define HDMI_SW_DI_1_PKT_WORD6  0x022C
 #define HDMI_SW_DI_CFG  0x0230
+#define HDMI_SAMPLE_FLAT_MASK   0x0244
+#define HDMI_AUDN   0x0400
+#define HDMI_AUD_CTS0x0404
 #define HDMI_SW_DI_2_HEAD_WORD  0x0600
 #define HDMI_SW_DI_2_PKT_WORD0  0x0604
 #define HDMI_SW_DI_2_PKT_WORD1  0x0608
@@ -103,6 +110,7 @@
 #define HDMI_INT_DLL_LCKBIT(5)
 #define HDMI_INT_NEW_FRAME  BIT(6)
 #define HDMI_INT_GENCTRL_PKTBIT(7)
+#define HDMI_INT_AUDIO_FIFO_XRUNBIT(8)
 #define HDMI_INT_SINK_TERM_PRESENT  BIT(11)

 #define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \
@@ -111,6 +119,7 @@
| HDMI_INT_GLOBAL)

 #define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \
+   | HDMI_INT_AUDIO_FIFO_XRUN \
| HDMI_INT_GENCTRL_PKT \
| HDMI_INT_NEW_FRAME \
| HDMI_INT_DLL_LCK \
@@ -121,6 +130,27 @@

 #define HDMI_STA_SW_RST BIT(1)

+#define HDMI_AUD_CFG_8CH   BIT(0)
+#define HDMI_AUD_CFG_SPDIF_DIV_2   BIT(1)
+#define HDMI_AUD_CFG_SPDIF_DIV_3   BIT(2)
+#define HDMI_AUD_CFG_SPDIF_CLK_DIV_4   (BIT(1) | BIT(2))
+#define HDMI_AUD_CFG_CTS_CLK_256FS BIT(12)
+#define HDMI_AUD_CFG_DTS_INVALID   BIT(16)
+#define HDMI_AUD_CFG_ONE_BIT_INVALID   (BIT(18) | BIT(19) | BIT(20) |  BIT(21))
+#define HDMI_AUD_CFG_CH12_VALIDBIT(28)
+#define HDMI_AUD_CFG_CH34_VALIDBIT(29)
+#define HDMI_AUD_CFG_CH56_VALIDBIT(30)
+#define HDMI_AUD_CFG_CH78_VALIDBIT(31)
+
+/* sample flat mask */
+#define HDMI_SAMPLE_FLAT_NO 0
+#define HDMI_SAMPLE_FLAT_SP0 BIT(0)
+#define HDMI_SAMPLE_FLAT_SP1 BIT(1)
+#define HDMI_SAMPLE_FLAT_SP2 BIT(2)
+#define HDMI_SAMPLE_FLAT_SP3 BIT(3)
+#define HDMI_SAMPLE_FLAT_ALL (HDMI_SAMPLE_FLAT_SP0 | HDMI_SAMPLE_FLAT_SP1 |\
+ HDMI_SAMPLE_FLAT_SP2 | HDMI_SAMPLE_FLAT_SP3)
+
 #define HDMI_INFOFRAME_HEADER_TYPE(x)(((x) & 0xff) <<  0)
 #define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
 #define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
@@ -171,6 +201,10 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
wake_up_interruptible(>wait_event);
}

+   /* Audio FIFO underrun IRQ */
+   if (hdmi->irq_status & HDMI_INT_AUDIO_FIFO_XRUN)
+   DRM_INFO("Warning: audio FIFO underrun occurs!");
+
return IRQ_HANDLED;
 }

@@ -441,26 +475,29 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi 
*hdmi)
  */
 static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
 {
-   struct hdmi_audio_infoframe infofame;
+   struct hdmi_audio_params *audio = >audio;
u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
-   int ret;
-
-   ret = hdmi_audio_infoframe_init();
-   if (ret < 0) {
-   DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
-   return ret;
-   }
-
-   infofame.channels = 2;
-
-   ret = hdmi_audio_infoframe_pack(, buffer, sizeof(buffer));
-   if (ret < 0) {
-   DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
-   return ret;
+   int ret, val;
+
+   DRM_DEBUG_DRIVER("enter %s

[PATCH v4 1/2] video: hdmi: add helper functions for N and CTS

2016-04-21 Thread Arnaud Pouliquen
Add helper functions to compute HDMI CTS and N parameters.
Implementation is based on HDMI 1.4b specification.

Signed-off-by: Arnaud Pouliquen 
Acked-by: Benjamin Gaignard 
Acked-by: Vincent ABRIOU 
---
 drivers/video/hdmi.c | 208 +++
 include/linux/hdmi.h |  24 ++
 2 files changed, 232 insertions(+)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1626892..5d124ef 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -1242,3 +1242,211 @@ int hdmi_infoframe_unpack(union hdmi_infoframe *frame, 
void *buffer)
return ret;
 }
 EXPORT_SYMBOL(hdmi_infoframe_unpack);
+
+/*
+ * audio clock regeneration (acr) parameters
+ * N and CTS computation are based on HDMI specification 1.4b
+ */
+enum hdmi_audio_rate {
+   HDMI_AUDIO_N_CTS_32KHZ,
+   HDMI_AUDIO_N_CTS_44_1KHZ,
+   HDMI_AUDIO_N_CTS_48KHZ,
+};
+
+struct hdmi_audio_acr {
+   unsigned int tmds_clk;
+   struct hdmi_audio_n_cts n_cts;
+};
+
+static const struct hdmi_audio_acr hdmi_audio_standard_acr[3][13] = {
+   [HDMI_AUDIO_N_CTS_32KHZ] = {
+   /* N and CTS values for 32 kHz rate*/
+   {  25174825, {  4576,  28125, 0 } }, /* 25.20/1.001  MHz */
+   {  2520, {  4096,  25200, 0 } }, /* 25.20MHz */
+   {  2700, {  4096,  27000, 0 } }, /* 27.00MHz */
+   {  27027000, {  4096,  27027, 0 } }, /* 27.00*1.001  MHz */
+   {  5400, {  4096,  54000, 0 } }, /* 54.00MHz */
+   {  54054000, {  4096,  54054, 0 } }, /* 54.00*1.001  MHz */
+   {  74175824, { 11648, 210937, 50 } }, /* 74.25/1.001 MHz */
+   {  7425, {  4096,  74250, 0 } }, /* 74.25MHz */
+   { 148351648, { 11648, 421875, 0 } }, /* 148.50/1.001 MHz */
+   { 14850, {  4096, 148500, 0 } }, /* 148.50   MHz */
+   { 296703296, {  5824, 421875, 0 } }, /* 297/1.001 MHz 
(truncated)*/
+   { 296703297, {  5824, 421875, 0 } }, /* 297/1.001 MHz 
(rounded)*/
+   { 29700, {  3072, 222750, 0 } }, /* 297  MHz */
+   },
+   [HDMI_AUDIO_N_CTS_44_1KHZ] = {
+   /* N and CTS values for 44.1 kHz, 88.2 kHz and 176.4 kHz rates*/
+   {  25174825, {  7007,  31250, 0 } }, /* 25.20/1.001  MHz */
+   {  2520, {  6272,  28000, 0 } }, /* 25.20MHz */
+   {  2700, {  6272,  3, 0 } }, /* 27.00MHz */
+   {  27027000, {  6272,  30030, 0 } }, /* 27.00*1.001  MHz */
+   {  5400, {  6272,  6, 0 } }, /* 54.00MHz */
+   {  54054000, {  6272,  60060, 0 } }, /* 54.00*1.001  MHz */
+   {  74175824, { 17836, 234375, 0 } }, /* 74.25/1.001  MHz */
+   {  7425, {  6272,  82500, 0 } }, /* 74.25MHz */
+   { 148351648, {  8918, 234375, 0 } }, /* 148.50/1.001 MHz */
+   { 14850, {  6272, 165000, 0 } }, /* 148.50   MHz */
+   { 296703296, {  4459, 234375, 0 } }, /* 297/1.001 MHz 
(truncated) */
+   { 296703297, {  4459, 234375, 0 } }, /* 297/1.001 MHz (rounded) 
*/
+   { 29700, {  4704, 247500, 0 } }, /* 297  MHz */
+   },
+   [HDMI_AUDIO_N_CTS_48KHZ] = {
+   /* N and CTS values for 48 kHz, 96 kHz and 192 kHz rates*/
+   {  25174825, {  6864,  28125, 0 } }, /* 25.20/1.001  MHz */
+   {  2520, {  6144,  25200, 0 } }, /* 25.20MHz */
+   {  2700, {  6144,  27000, 0 } }, /* 27.00MHz */
+   {  27027000, {  6144,  27027, 0 } }, /* 27.00*1.001  MHz */
+   {  5400, {  6144,  54000, 0 } }, /* 54.00MHz */
+   {  54054000, {  6144,  54054, 0 } }, /* 54.00*1.001  MHz */
+   {  74175824, { 11648, 140625, 0 } }, /* 74.25/1.001  MHz */
+   {  7425, {  6144,  74250, 0 } }, /* 74.25MHz */
+   { 148351648, {  5824, 140625, 0 } }, /* 148.50/1.001 MHz */
+   { 14850, {  6144, 148500, 0 } }, /* 148.50   MHz */
+   { 296703296, {  5824, 281250, 0 } }, /* 297/1.001 MHz 
(truncated) */
+   { 296703297, {  5824, 281250, 0 } }, /* 297/1.001 MHz (rounded) 
*/
+   { 29700, {  5120, 247500, 0 } }, /* 297  MHz */
+   }
+};
+
+/**
+ * hdmi_audio_get_coherent_n_cts() - compute N and CTS parameters for coherent
+ * clocks. Coherent clock means that audio and TMDS clocks have the same
+ * source (no drifts between clocks).
+ *
+ * @audio_fs: audio frame clock frequency in Hz
+ * @tmds_clk: HDMI TMDS clock frequency in Hz
+ * @n_cts: N and CTS parameter returned to user
+ *
+ * Values computed are based on table described in HDMI specification 1.4b
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_audio_get_coherent_n_cts(unsigned int

[PATCH v4 0/2] sti: add audio interface to the hdmi driver

2016-04-21 Thread Arnaud Pouliquen
This patchset implements audio interface in HDMI drm driver. Implementation is 
based on 
ASoC generic hdmi codec driver( https://patchwork.kernel.org/patch/8713141/). 
It also proposes helper functions to compute N and CTS parameters
according to HDMI 1.4b specification. 

V4:
 fixes for "video: hdmi: add helper functions for N and CTS"
- typo error and additional comments
- cts_1_ratio computation
- warning reported by kbuild test robot
- add rounded value for 297/1.001 MHz

V3: 
 - video: hdmi: add helper function for N and CTS
  Also used on Mediatek platform 
(https://patchwork.kernel.org/patch/8887341)
  delta vs V2:
  - typo fixes
  - if/else code optimisation
 - drm: sti: Add ASoC generic hdmi codec support.
  - typo fixes
  - add audio registers in debugfs information

V2: RFC
https://patchwork.kernel.org/patch/8091531/("video: hdmi: add helper function 
for N and CTS")
https://patchwork.kernel.org/patch/8091561/("ASoC: hdmi-codec: Add hdmi-codec 
for external HDMI-encoders")
 - patch: video: hdmi: add helper function for N and CTS
 Fixes based on Russel King remarks
 - Duplicate function to have a separte treatment for coherent and
   non-coherent clocks
 - Add ratio field for alternate CTS value
 - Clock frequency in Hz for TMDS and audio clocks
 - Add information concerning clocks and CTS calculation. 

V1: 
This RFC is the implementation of audio HDMI on sti platform based on generic 
hdmi-codec driver:
https://patchwork.kernel.org/patch/7215271/ ("ASoC: hdmi-codec: Add 
hdmi-codec for external HDMI-encoders")
https://patchwork.kernel.org/patch/8062611/ ("video: hdmi: add helper 
function for N and CTS")
Arnaud Pouliquen (2):
  video: hdmi: add helper functions for N and CTS
  drm: sti: Add ASoC generic hdmi codec support.

 drivers/gpu/drm/sti/Kconfig|   1 +
 drivers/gpu/drm/sti/sti_hdmi.c | 248 ++---
 drivers/gpu/drm/sti/sti_hdmi.h |  13 +++
 drivers/video/hdmi.c   | 208 ++
 include/linux/hdmi.h   |  24 
 5 files changed, 477 insertions(+), 17 deletions(-)

-- 
1.9.1



[PATCH v3 1/2] video: hdmi: add helper function for N and CTS

2016-04-21 Thread Arnaud Pouliquen


On 04/21/2016 02:39 PM, Philipp Zabel wrote:
> Hi Arnaud,
> 
> Am Donnerstag, den 21.04.2016, 10:07 +0200 schrieb Arnaud Pouliquen:
>> Add helper function to compute HDMI CTS and N parameters
>> Implementation is based on HDMI 1.4b specification.
>>
>> Signed-off-by: Arnaud Pouliquen 
>> Acked-by: Benjamin Gaignard 
>> Acked-by: Vincent ABRIOU 
> 
> Reviewed-by: Philipp Zabel 
> 
>> ---
>>  drivers/video/hdmi.c | 202 
>> +++
>>  include/linux/hdmi.h |  22 ++
>>  2 files changed, 224 insertions(+)
>>
>> diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
>> index 1626892..6381ce0 100644
>> --- a/drivers/video/hdmi.c
>> +++ b/drivers/video/hdmi.c
>> @@ -1242,3 +1242,205 @@ int hdmi_infoframe_unpack(union hdmi_infoframe 
>> *frame, void *buffer)
>>  return ret;
>>  }
>>  EXPORT_SYMBOL(hdmi_infoframe_unpack);
>> +
>> +/**
>> + * audio clock regeneration (acr) parameters
>> + * N and CTS computation are based on HDMI specification 1.4b
>> + */
>> +enum audio_rate {
>> +HDMI_AUDIO_N_CTS_32KHZ,
>> +HDMI_AUDIO_N_CTS_44_1KHZ,
>> +HDMI_AUDIO_N_CTS_48KHZ,
>> +};
>> +
>> +struct hdmi_audio_acr {
>> +unsigned int tmds_clk;
>> +struct hdmi_audio_n_cts n_cts;
>> +};
>> +
>> +static const struct hdmi_audio_acr hdmi_audio_standard_acr[3][12] = {
>> +{ /*32 kHz*/
> 
> If you used
> 
>   [HDMI_AUDIO_N_CTS_32KHZ] = {
> 
> instead, that would mirror how the array is indexed via audio_freq_id in
> hdmi_audio_get_coherent_n_cts below.
> 
>> +{  25174825, {  4576,  28125, 0 } }, /* 25,20/1.001  MHz */
>^
> s/,/./
> 
>> +{  2520, {  4096,  25200, 0 } }, /* 25.20MHz */
>> +{  2700, {  4096,  27000, 0 } }, /* 27.00MHz */
>> +{  27027000, {  4096,  27027, 0 } }, /* 27.00*1.001  MHz */
>> +{  5400, {  4096,  54000, 0 } }, /* 54.00MHz */
>> +{  54054000, {  4096,  54054, 0 } }, /* 54.00*1.001  MHz */
>> +{  74175824, { 11648, 210937, 50 } }, /* 74.25/1.001  MHz */
>> +{  7425, {  4096,  74250, 0 } }, /* 74.25MHz */
>> +{ 148351648, { 11648, 421875, 0 } }, /* 148.50/1.001 MHz */
>> +{ 14850, {  4096, 148500, 0 } }, /* 148.50   MHz */
>> +{ 296703296, {  5824, 421875, 0 } }, /* 297/1.001MHz */
>^
> Maybe add a comment above that tmds_clk is rounded down?
My apologize, I have forgotten to add 296703297 value to take into
account truncated and rounded values as discussed in V2:
{ 296703296, {  5824, 421875, 0 } }, /* 297/1.001MHz 
(truncated) */
{ 296703297, { 5824, 421875, 0 } }, /* 297/1.001 MHz (rounded) 
*/

> 
>> +{ 29700, {  3072, 222750, 0 } }, /* 297  MHz */
>> +},
>> +{ /*44.1 kHz, 88.2 kHz  176.4 kHz*/
>> +{  25174825, {  7007,  31250, 0 } }, /* 25,20/1.001  MHz */
>> +{  2520, {  6272,  28000, 0 } }, /* 25.20MHz */
>> +{  2700, {  6272,  3, 0 } }, /* 27.00MHz */
>> +{  27027000, {  6272,  30030, 0 } }, /* 27.00*1.001  MHz */
>> +{  5400, {  6272,  6, 0 } }, /* 54.00MHz */
>> +{  54054000, {  6272,  60060, 0 } }, /* 54.00*1.001  MHz */
>> +{  74175824, { 17836, 234375, 0 } }, /* 74.25/1.001  MHz */
>> +{  7425, {  6272,  82500, 0 } }, /* 74.25MHz */
>> +{ 148351648, {  8918, 234375, 0 } }, /* 148.50/1.001 MHz */
>> +{ 14850, {  6272, 165000, 0 } }, /* 148.50   MHz */
>> +{ 296703296, {  4459, 234375, 0 } }, /* 297/1.001MHz */
>> +{ 29700, {  4704, 247500, 0 } }, /* 297  MHz */
>> +},
>> +{ /*48 kHz, 96 kHz  192 kHz*/
>> +{  25174825, {  6864,  28125, 0 } }, /* 25,20/1.001  MHz */
>> +{  2520, {  6144,  25200, 0 } }, /* 25.20MHz */
>> +{  2700, {  6144,  27000, 0 } }, /* 27.00MHz */
>> +{  27027000, {  6144,  27027, 0 } }, /* 27.00*1.001  MHz */
>> +{  5400, {  6144,  54000, 0 } }, /* 54.00MHz */
>> +{  54054000, {  6144,  54054, 0 } }, /* 54.00*1.001  MHz */
>> +{  74175824, { 11648, 140625, 0 } }, /* 74.25/1.001  MHz */
>> +{  742

[PATCH v3 2/2] drm: sti: Add ASoC generic hdmi codec support.

2016-04-21 Thread Arnaud Pouliquen
Add the interface needed by audio hdmi-codec driver.

Signed-off-by: Arnaud Pouliquen 
Acked-by: Benjamin Gaignard 
Acked-by: Vincent ABRIOU 
---
 drivers/gpu/drm/sti/Kconfig|   1 +
 drivers/gpu/drm/sti/sti_hdmi.c | 248 ++---
 drivers/gpu/drm/sti/sti_hdmi.h |  13 +++
 3 files changed, 245 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
index 5ad43a1..494ab25 100644
--- a/drivers/gpu/drm/sti/Kconfig
+++ b/drivers/gpu/drm/sti/Kconfig
@@ -7,5 +7,6 @@ config DRM_STI
select DRM_KMS_CMA_HELPER
select DRM_PANEL
select FW_LOADER
+   select SND_SOC_HDMI_CODEC if SND_SOC
help
  Choose this option to enable DRM on STM stiH41x chipset
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 6ef0715..3a8bd47 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -18,6 +18,8 @@
 #include 
 #include 

+#include 
+
 #include "sti_hdmi.h"
 #include "sti_hdmi_tx3g4c28phy.h"
 #include "sti_hdmi_tx3g0c55phy.h"
@@ -35,6 +37,8 @@
 #define HDMI_DFLT_CHL0_DAT  0x0110
 #define HDMI_DFLT_CHL1_DAT  0x0114
 #define HDMI_DFLT_CHL2_DAT  0x0118
+#define HDMI_AUDIO_CFG  0x0200
+#define HDMI_SPDIF_FIFO_STATUS  0x0204
 #define HDMI_SW_DI_1_HEAD_WORD  0x0210
 #define HDMI_SW_DI_1_PKT_WORD0  0x0214
 #define HDMI_SW_DI_1_PKT_WORD1  0x0218
@@ -44,6 +48,9 @@
 #define HDMI_SW_DI_1_PKT_WORD5  0x0228
 #define HDMI_SW_DI_1_PKT_WORD6  0x022C
 #define HDMI_SW_DI_CFG  0x0230
+#define HDMI_SAMPLE_FLAT_MASK   0x0244
+#define HDMI_AUDN   0x0400
+#define HDMI_AUD_CTS0x0404
 #define HDMI_SW_DI_2_HEAD_WORD  0x0600
 #define HDMI_SW_DI_2_PKT_WORD0  0x0604
 #define HDMI_SW_DI_2_PKT_WORD1  0x0608
@@ -103,6 +110,7 @@
 #define HDMI_INT_DLL_LCKBIT(5)
 #define HDMI_INT_NEW_FRAME  BIT(6)
 #define HDMI_INT_GENCTRL_PKTBIT(7)
+#define HDMI_INT_AUDIO_FIFO_XRUNBIT(8)
 #define HDMI_INT_SINK_TERM_PRESENT  BIT(11)

 #define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \
@@ -111,6 +119,7 @@
| HDMI_INT_GLOBAL)

 #define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \
+   | HDMI_INT_AUDIO_FIFO_XRUN \
| HDMI_INT_GENCTRL_PKT \
| HDMI_INT_NEW_FRAME \
| HDMI_INT_DLL_LCK \
@@ -121,6 +130,27 @@

 #define HDMI_STA_SW_RST BIT(1)

+#define HDMI_AUD_CFG_8CH   BIT(0)
+#define HDMI_AUD_CFG_SPDIF_DIV_2   BIT(1)
+#define HDMI_AUD_CFG_SPDIF_DIV_3   BIT(2)
+#define HDMI_AUD_CFG_SPDIF_CLK_DIV_4   (BIT(1) | BIT(2))
+#define HDMI_AUD_CFG_CTS_CLK_256FS BIT(12)
+#define HDMI_AUD_CFG_DTS_INVALID   BIT(16)
+#define HDMI_AUD_CFG_ONE_BIT_INVALID   (BIT(18) | BIT(19) | BIT(20) |  BIT(21))
+#define HDMI_AUD_CFG_CH12_VALIDBIT(28)
+#define HDMI_AUD_CFG_CH34_VALIDBIT(29)
+#define HDMI_AUD_CFG_CH56_VALIDBIT(30)
+#define HDMI_AUD_CFG_CH78_VALIDBIT(31)
+
+/* sample flat mask */
+#define HDMI_SAMPLE_FLAT_NO 0
+#define HDMI_SAMPLE_FLAT_SP0 BIT(0)
+#define HDMI_SAMPLE_FLAT_SP1 BIT(1)
+#define HDMI_SAMPLE_FLAT_SP2 BIT(2)
+#define HDMI_SAMPLE_FLAT_SP3 BIT(3)
+#define HDMI_SAMPLE_FLAT_ALL (HDMI_SAMPLE_FLAT_SP0 | HDMI_SAMPLE_FLAT_SP1 |\
+ HDMI_SAMPLE_FLAT_SP2 | HDMI_SAMPLE_FLAT_SP3)
+
 #define HDMI_INFOFRAME_HEADER_TYPE(x)(((x) & 0xff) <<  0)
 #define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
 #define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
@@ -171,6 +201,10 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
wake_up_interruptible(>wait_event);
}

+   /* Audio FIFO underrun IRQ */
+   if (hdmi->irq_status & HDMI_INT_AUDIO_FIFO_XRUN)
+   DRM_INFO("Warning: audio FIFO underrun occurs!");
+
return IRQ_HANDLED;
 }

@@ -441,26 +475,29 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi 
*hdmi)
  */
 static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
 {
-   struct hdmi_audio_infoframe infofame;
+   struct hdmi_audio_params *audio = >audio;
u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
-   int ret;
-
-   ret = hdmi_audio_infoframe_init();
-   if (ret < 0) {
-   DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
-   return ret;
-   }
-
-   infofame.channels = 2;
-
-   ret = hdmi_audio_infoframe_pack(, buffer, sizeof(buffer));
-   if (ret < 0) {
-   DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
-   return ret;
+   int ret, val;
+
+   DRM_DEBUG_DRIVER("enter %s

[PATCH v3 1/2] video: hdmi: add helper function for N and CTS

2016-04-21 Thread Arnaud Pouliquen
Add helper function to compute HDMI CTS and N parameters
Implementation is based on HDMI 1.4b specification.

Signed-off-by: Arnaud Pouliquen 
Acked-by: Benjamin Gaignard 
Acked-by: Vincent ABRIOU 
---
 drivers/video/hdmi.c | 202 +++
 include/linux/hdmi.h |  22 ++
 2 files changed, 224 insertions(+)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1626892..6381ce0 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -1242,3 +1242,205 @@ int hdmi_infoframe_unpack(union hdmi_infoframe *frame, 
void *buffer)
return ret;
 }
 EXPORT_SYMBOL(hdmi_infoframe_unpack);
+
+/**
+ * audio clock regeneration (acr) parameters
+ * N and CTS computation are based on HDMI specification 1.4b
+ */
+enum audio_rate {
+   HDMI_AUDIO_N_CTS_32KHZ,
+   HDMI_AUDIO_N_CTS_44_1KHZ,
+   HDMI_AUDIO_N_CTS_48KHZ,
+};
+
+struct hdmi_audio_acr {
+   unsigned int tmds_clk;
+   struct hdmi_audio_n_cts n_cts;
+};
+
+static const struct hdmi_audio_acr hdmi_audio_standard_acr[3][12] = {
+   { /*32 kHz*/
+   {  25174825, {  4576,  28125, 0 } }, /* 25,20/1.001  MHz */
+   {  2520, {  4096,  25200, 0 } }, /* 25.20MHz */
+   {  2700, {  4096,  27000, 0 } }, /* 27.00MHz */
+   {  27027000, {  4096,  27027, 0 } }, /* 27.00*1.001  MHz */
+   {  5400, {  4096,  54000, 0 } }, /* 54.00MHz */
+   {  54054000, {  4096,  54054, 0 } }, /* 54.00*1.001  MHz */
+   {  74175824, { 11648, 210937, 50 } }, /* 74.25/1.001  MHz */
+   {  7425, {  4096,  74250, 0 } }, /* 74.25MHz */
+   { 148351648, { 11648, 421875, 0 } }, /* 148.50/1.001 MHz */
+   { 14850, {  4096, 148500, 0 } }, /* 148.50   MHz */
+   { 296703296, {  5824, 421875, 0 } }, /* 297/1.001MHz */
+   { 29700, {  3072, 222750, 0 } }, /* 297  MHz */
+   },
+   { /*44.1 kHz, 88.2 kHz  176.4 kHz*/
+   {  25174825, {  7007,  31250, 0 } }, /* 25,20/1.001  MHz */
+   {  2520, {  6272,  28000, 0 } }, /* 25.20MHz */
+   {  2700, {  6272,  3, 0 } }, /* 27.00MHz */
+   {  27027000, {  6272,  30030, 0 } }, /* 27.00*1.001  MHz */
+   {  5400, {  6272,  6, 0 } }, /* 54.00MHz */
+   {  54054000, {  6272,  60060, 0 } }, /* 54.00*1.001  MHz */
+   {  74175824, { 17836, 234375, 0 } }, /* 74.25/1.001  MHz */
+   {  7425, {  6272,  82500, 0 } }, /* 74.25MHz */
+   { 148351648, {  8918, 234375, 0 } }, /* 148.50/1.001 MHz */
+   { 14850, {  6272, 165000, 0 } }, /* 148.50   MHz */
+   { 296703296, {  4459, 234375, 0 } }, /* 297/1.001MHz */
+   { 29700, {  4704, 247500, 0 } }, /* 297  MHz */
+   },
+   { /*48 kHz, 96 kHz  192 kHz*/
+   {  25174825, {  6864,  28125, 0 } }, /* 25,20/1.001  MHz */
+   {  2520, {  6144,  25200, 0 } }, /* 25.20MHz */
+   {  2700, {  6144,  27000, 0 } }, /* 27.00MHz */
+   {  27027000, {  6144,  27027, 0 } }, /* 27.00*1.001  MHz */
+   {  5400, {  6144,  54000, 0 } }, /* 54.00MHz */
+   {  54054000, {  6144,  54054, 0 } }, /* 54.00*1.001  MHz */
+   {  74175824, { 11648, 140625, 0 } }, /* 74.25/1.001  MHz */
+   {  7425, {  6144,  74250, 0 } }, /* 74.25MHz */
+   { 148351648, {  5824, 140625, 0 } }, /* 148.50/1.001 MHz */
+   { 14850, {  6144, 148500, 0 } }, /* 148.50   MHz */
+   { 296703296, {  5824, 281250, 0 } }, /* 297/1.001MHz */
+   { 29700, {  5120, 247500, 0 } }, /* 297  MHz */
+   }
+};
+
+/**
+ * hdmi_audio_get_coherent_n_cts() - compute N and CTS parameters for coherent
+ * clocks. Coherent clock means that audio and TMDS clocks have the same
+ * source (no drifts between clocks).
+ *
+ * @audio_fs: audio frame clock frequency in Hz
+ * @tmds_clk: HDMI TMDS clock frequency in Hz
+ * @n_cts: N and CTS parameter returned to user
+ *
+ * Values computed are based on table described in HDMI specification 1.4b
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_audio_get_coherent_n_cts(unsigned int audio_fs,
+ unsigned int tmds_clk,
+ struct hdmi_audio_n_cts *n_cts)
+{
+   int audio_freq_id, i;
+   int rate_coeff = 1;
+   u64 val, min;
+   const struct hdmi_audio_acr  *acr_table;
+   const struct hdmi_audio_n_cts *predef_n_cts = NULL;
+
+   switch (audio_fs) {
+   case 32000:
+   audio_freq_id = HDMI_AUDIO_N_CTS_32KHZ;
+   n_cts->n = 4096;
+   break;
+   case 44

[PATCH v3 0/2] sti: add audio interface to the hdmi driver

2016-04-21 Thread Arnaud Pouliquen
This patchset implements audio interface in HDMI drm driver. Implementation is 
based on 
ASoC generic hdmi codec driver( https://patchwork.kernel.org/patch/8713141/). 
It also proposes helper functions to compute N and CTS parameters
according to HDMI 1.4b specification. 

V3: 
 - video: hdmi: add helper function for N and CTS
  Also used on Mediatek platform 
(https://patchwork.kernel.org/patch/8887341)
  delta vs V2:
  - typo fixes
  - if/else code optimisation
 - drm: sti: Add ASoC generic hdmi codec support.
  - typo fixes
  - add audio registers in debugfs information

V2: RFC
https://patchwork.kernel.org/patch/8091531/("video: hdmi: add helper function 
for N and CTS")
https://patchwork.kernel.org/patch/8091561/("ASoC: hdmi-codec: Add hdmi-codec 
for external HDMI-encoders")
 - patch: video: hdmi: add helper function for N and CTS
 Fixes based on Russel King remarks
 - Duplicate function to have a separte treatment for coherent and
   non-coherent clocks
 - Add ratio field for alternate CTS value
 - Clock frequency in Hz for TMDS and audio clocks
 - Add information concerning clocks and CTS calculation. 

V1: 
This RFC is the implementation of audio HDMI on sti platform based on generic 
hdmi-codec driver:
https://patchwork.kernel.org/patch/7215271/ ("ASoC: hdmi-codec: Add 
hdmi-codec for external HDMI-encoders")
https://patchwork.kernel.org/patch/8062611/ ("video: hdmi: add helper 
function for N and CTS")
Arnaud Pouliquen (2):
  drm: sti: Add ASoC generic hdmi codec support.
  video: hdmi: add helper function for N and CTS

 drivers/gpu/drm/sti/Kconfig|   1 +
 drivers/gpu/drm/sti/sti_hdmi.c | 248 ++---
 drivers/gpu/drm/sti/sti_hdmi.h |  13 +++
 drivers/video/hdmi.c   | 202 +
 include/linux/hdmi.h   |  22 
 5 files changed, 469 insertions(+), 17 deletions(-)

-- 
1.9.1



[PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use

2016-04-13 Thread Arnaud Pouliquen


On 03/31/2016 03:36 PM, Jyri Sarha wrote:
> 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 
> ---
>  include/sound/hdmi-codec.h|  8 ++--
>  sound/soc/codecs/hdmi-codec.c | 20 +++-
>  2 files changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> index fc3a481..15fe70f 100644
> --- a/include/sound/hdmi-codec.h
> +++ b/include/sound/hdmi-codec.h
> @@ -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
> +  * 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.
> diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
> index b46b8ed..35151a4 100644
> --- a/sound/soc/codecs/hdmi-codec.c
> +++ b/sound/soc/codecs/hdmi-codec.c
> @@ -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(>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(>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.

>  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(>current_stream_lock);
>   hcp->current_stream = NULL;
> 


[PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders

2016-04-13 Thread Arnaud Pouliquen
New version Tested with success on sti platform

Acked-by: Arnaud Pouliquen 

Regards
Arnaud


On 03/31/2016 03:36 PM, Jyri Sarha wrote:
> 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 
> ---
>  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
> 
> diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> new file mode 100644
> index 000..fc3a481
> --- /dev/null
> +++ b/include/sound/hdmi-codec.h
> @@ -0,0 +1,100 @@
> +/*
> + * hdmi-codec.h - HDMI Codec driver API
> + *
> + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
> + *
> + * Author: Jyri Sarha 
> + *
> + * 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 
> +#include 
> +#include 
> +#include 
> +
> +/*
> + * 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__ */
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 50693c8..62b62fe 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -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

[PATCH v6 2/6] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders

2016-03-09 Thread Arnaud Pouliquen
Hello Jyri,

Tested with success on sti platform

Acked-by: Arnaud Pouliquen 

Regards
Arnaud

On 03/08/2016 09:14 PM, Jyri Sarha wrote:
> 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 
> ---
>  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
> 
> diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> new file mode 100644
> index 000..fc3a481
> --- /dev/null
> +++ b/include/sound/hdmi-codec.h
> @@ -0,0 +1,100 @@
> +/*
> + * hdmi-codec.h - HDMI Codec driver API
> + *
> + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
> + *
> + * Author: Jyri Sarha 
> + *
> + * 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 
> +#include 
> +#include 
> +#include 
> +
> +/*
> + * 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__ */
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 50693c8..62b62fe 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -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

[PATCH v6 1/6] ALSA: pcm: add IEC958 channel status helper for hw_params

2016-03-09 Thread Arnaud Pouliquen
Hello Jyri,

Acked-by: Arnaud Pouliquen 

With few nitpicking remarks on form.

Regards
Arnaud

On 03/08/2016 09:14 PM, Jyri Sarha wrote:
> 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.
> 
> Signed-off-by: Jyri Sarha 
> ---
>  include/sound/pcm_iec958.h |  2 ++
>  sound/core/pcm_iec958.c| 53 
> +++---
>  2 files changed, 38 insertions(+), 17 deletions(-)
> 
> diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h
> index 0eed397..36f023a 100644
> --- a/include/sound/pcm_iec958.h
> +++ b/include/sound/pcm_iec958.h
> @@ -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
> diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
> index 36b2d7a..27e0981 100644
> --- a/sound/core/pcm_iec958.c
> +++ b/sound/core/pcm_iec958.c
> @@ -9,30 +9,18 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  
> -/**
> - * 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
> + *
> + * 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
> +{
> + 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?
> +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
> +  u8 *cs, size_t len)
should be aligned on parenthesis
> +{
> + return create_iec958_consumer(params_rate(params), params_width(params),
> +   cs, len);
> +}
> +EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);
> 


[PATCH RFC v5 2/8] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders

2016-03-08 Thread Arnaud Pouliquen
Hello Jyri,

> +
> +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));
I ran into an issue during my test.
For I2S, an error is returned by create_iec958_consumer for 32-bits
stream (SNDRV_PCM_FMTBIT_S32_LE).
I suppose that it makes sense to handle 32-bits configuration for I2S
(but also SPDIF), to support software IEC958 formating/pre-formating...
To fix issue, just need to add 32-bits with 24-bits case in
create_iec958_consumer

Regards
Arnaud


[PATCH RFC v5 2/8] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders

2016-02-22 Thread Arnaud Pouliquen
Hello Jyri,

Integrated and tested on sti platform with success.

I will re-submit patch-set associated to sti platform, when (if) patches
accepted.

Regards
Arnaud

On 02/17/2016 03:49 PM, Jyri Sarha wrote:
> 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 
> ---
>  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
> 
> diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> new file mode 100644
> index 000..fc3a481
> --- /dev/null
> +++ b/include/sound/hdmi-codec.h
> @@ -0,0 +1,100 @@
> +/*
> + * hdmi-codec.h - HDMI Codec driver API
> + *
> + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
> + *
> + * Author: Jyri Sarha 
> + *
> + * 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 
> +#include 
> +#include 
> +#include 
> +
> +/*
> + * 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__ */
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index cfdafc4..4d5915e 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -82,6 +82,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_PCM1792A if SPI_MASTER
>   select SND_SOC_PCM3008
> @@ -454,6 +455,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"
>  
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index f632fc4..49c1824 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -75,6 +75,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, way forward?

2015-10-16 Thread Arnaud Pouliquen
> After reading the ELCE Audio mini conf minutes [1] I gather that HDMI
> audio was not discussed after all.
>
> My conclusion from the Lars-Peter's latest mail [2] related to the
> subject is that the wind is currently blowing slightly in favour of my
> version of the hdmi codec [3], or at least not in favour of Arnaud's
> version [4].
Based on previous discussions and lack of feedback from DRM community,
This make sens for me.

>
> So how should we proceed? Are we still waiting for some feedback from
> DRM/video side?
>
> There was not too many clear suggestions to my latest patch series
> [3], so I do not see too much point in sending yet another version of
> that series.
  For me, some points need to be clarified:
- Do we need the abort callback. Is there a uses cases that makes it 
mandatory (some timeout mechanism already exists to stop audio...)

- Does trigger is needed when CPU-DAI is master on bus?
Otherwise how to inform HDMI that I2S bus is no more clocked? I'm not
sure that mute is sufficient for all hardwares... For instance for my
hardware CTS parameter is hardware computed based on I2S L/R clock.

- IEC controls to support compress mode. This should be handled by codec 
driver in I2S mode, but not in SPDIF mode.

>
> Arnaud, if I'd try to make a patch series that would implement sti
> HDMI audio with my HDMI codec, would you be willing try that out?
hmm...more simple that i do the stuff for sti platform as some pieces of 
code are missing today in kernel (Device tree part).
I will try to find time next week to make a prototype for test and give 
you a feedback.

Additional point: We should also define some new helper functions:

- For N and CTS HDMI parameters: In my RFC i have proposed helper 
function, don't know if that matches with other platforms need...

- For IEC standard controls (could be added in core/pcm_iec958.c)

BR,
Arnaud



[alsa-devel] [PATCH RFC V2 0/5] another generic audio hdmi codec proposal

2015-10-07 Thread Arnaud Pouliquen


>> My approach is the reverse: DRM driver does not need to know anything
>> about audio side. As ALSA is the client of DRM, seems more logical from
>> my point of view ...
>> Now if a generic solution must be found for all video drivers, sure,
>> your solution is more flexible.
>> But if i well understood fbdev drivers are no more accepted for upstream
>> (please correct me if I'm wrong).
>> So i don't know we have to keep fbdev in picture...
>>
>
> I am not promoting fbdev support. I am merely asking if we want to force
> all HDMI drivers to implement a drm_bridge if they want to support audio.
>
Yes this is a good point... My implementation is based on hypothesis 
that HDMI drivers are now upstreamed as DRM drivers.

>>> - HDMI encoder driver implementations that do not use DRM bridge
>>>  abstraction do not need add an extra DRM object just to get the
>>>  audio working.
>>>
>>> Short comings I see in the current HDMI audio bridge approach:
>>>
>>> In its current from the DRM audio bridge abstraction pretends to be a
>>> generic audio abstraction for DRM devices, but the implementation is
>>> quite specific to external HDMI encoders with spdif and/or i2s
>>> interface. There is a lot of HDMI video devices that provide the
>>> digital audio interface (ASoC DAI) directly and there is no need for
>>> anything but dummy codec implementation (if following ASoC
>>> paradigm). Before going forward I think we should at least consider
>>> how this abstraction would serve those devices.
>> Sorry, but i don't see any difference between both implementations for
>> this point.In both implementations, ops are called only if defined.
>> Could you give me name of the drivers you have in mind?
>
> I am not talking about Beaglebone-Black or tda998x here. There are
> platforms where video HW provides the digital audio interface for HDMI
> audio directly. For instance OMAP4 and OMAP5 (see
> sound/soc/omap/omap-hdmi-audio.c and drivers/video/fbdev/omap2/dss/) are
> like that.
Not checked in details but seems similar to your approach except ops 
used by cpu_dai.

>
>>>
>>> Also, I am not entirely happy how the drm_audio_bridge_funcs are used
>>> at the moment. The do not map too well to ASoC DAI callbacks and I do
>>> not see too much point in creating a completely new audio-callback
>>> abstraction, that is sligtly incompatible with ALSA, and then
>>> translating alsa callbacks to these new callbacks. I think the
>>> callbacks should map more or less directly ALSA callbacks.
>>
>> As API is defined in DRM, it seems more logical to match it with the one
>> defined for video. From my windows, i didn't see any blocking point to
>> connect codec callback with this API.
>> But anyway, this API is not freezed, it could be improved with your help.
>
> The most usual things can be made to work with your API too, but the
> translation is not the most efficient one and some features are missing,
> for instance muting.
Could be added but is it necessary if trigger is implemented?( see my 
next comments)

> Also, in ALSA side the prepare and trigger
> callbacks are meant to be used only for starting and stopping the audio
> stream.
Yes but for me, it is required. Otherwise how to manage CPU-DAI master 
configuration?
if stream is stopped, cpu_dai can be stopped as there is no more stream 
to sent on bus. If no information is sent to HDMI, This generates HDMI 
codec or protocol issue...
Use startup/shutdown/digital_mute seems not sufficient.

The stream is configured before either one of those are called.
> With your API each pause+resume from a video client will reconfigure the
> audio from the scratch.
Configuration is sent using pre_enable operation. So no reconfiguration 
should be re-applied.

Best Regards
Arnaud


[alsa-devel] [PATCH RFC V2 0/5] another generic audio hdmi codec proposal

2015-10-07 Thread Arnaud Pouliquen

On 10/06/2015 04:33 PM, Jean-Francois Moine wrote:
> On Tue, 6 Oct 2015 11:23:03 +0200
> Arnaud Pouliquen  wrote:
>   [snip]
>> As API is defined in DRM, it seems more logical to match it with the one
>> defined for video. From my windows, i didn't see any blocking point to
>> connect codec callback with this API.
>> But anyway, this API is not freezed, it could be improved with your help.
>
> Arnaud, your implementation seems more heavy than Jyri's, and I don't
> feel the DRM bridge.
>
> For HDMI, the exchanges between DRM and ALSA are only:
> - DRM -> ALSA
>- device connection with the audio constraints
>- device disconnection
> - ALSA -> DRM
>- start audio with the chosen audio parameters
>- stop audio
>
> and, in the system, the HDMI devices are seen as DRM connectors (video
> view) and as ASoC CODECs (audio view).
>
> We just need a link between these entities.
> I don't think that the bridge offers this.
Not so heavy...
In fact another way to differentiate the twice approaches could be to
answer to this question:
Should ALSA bypasses or not the DRM core/API to access to DRM HDMI 
connector?

Concerning bridge usage, I tried to found a link to address DRM driver 
trough DRM API. Bridge seemed a good candidate. Perhaps the DRM encoder 
API could be an other option to study...

Ken ar wech all/ best Regards
Arnaud


[alsa-devel] [PATCH RFC V2 0/5] another generic audio hdmi codec proposal

2015-10-06 Thread Arnaud Pouliquen
Hello Jyri,

Thanks your feedback, my answers in line


On 10/05/2015 03:27 PM, Jyri Sarha wrote:
> On 10/01/15 19:50, Arnaud Pouliquen wrote:
>>
>> Version 2:
>> This version integrates missing features upgraded to be aligned when possible
>> with patch set:
>> [PATCH RFC v4 0/8] Implement generic ASoC HDMI codec and use it in tda998x
>>
>
> There are still some details I would like to change if we decide to go
> the drm audio bridge way. But before all that, I would like to ask,
> why should we go forward with your approach? Is there anything that
> can be done with your approach, but can not be done with mine?
>
> Don't take me wrong, I do not see anything fundamentally wrong with
> your approach. I would just like hear some justification why we should
> abandon my approach - that I've been working on for some time - and go
> forward with yours.

Both implementations are similar in term of feature. And i think both 
have advantages and drawbacks...
The main difference, is that my approach is based on a standard service 
client-provider model.
Means that ops are defined by code in charge of providing the service 
(DRM) and not by the client (ALSA).
I don't want to impose my implementation but just propose an alternative
that makes sense for me.

In a first step, before going deep in discussion on the approach, it 
should be interesting to have maintainers feedback, to be sure that my 
approach could make sense from DRM and ALSA point of view.

@DRM (and ALSA) maintainers:
Please, could you give a first feedback on such implementation based on 
DRM API extension?
Is it something that could be acceptable (or not) from your point of view?

>
> Here is couple of benefits I can name in my approach:
> ­ Video side agnostic implementation
>  The ASoC side does not need to know anything about video side
>  implementation. There is no real exposure ASoC side internals in
>  video side either. Even fbdev driver, or some other non DRM video
>  driver, could use my implementation.
My approach is the reverse: DRM driver does not need to know anything 
about audio side. As ALSA is the client of DRM, seems more logical from 
my point of view ...
Now if a generic solution must be found for all video drivers, sure, 
your solution is more flexible.
But if i well understood fbdev drivers are no more accepted for upstream
(please correct me if I'm wrong).
So i don't know we have to keep fbdev in picture...

> - HDMI encoder driver implementations that do not use DRM bridge
> abstraction do not need add an extra DRM object just to get the
> audio working.
>
> Short comings I see in the current HDMI audio bridge approach:
>
> In its current from the DRM audio bridge abstraction pretends to be a
> generic audio abstraction for DRM devices, but the implementation is
> quite specific to external HDMI encoders with spdif and/or i2s
> interface. There is a lot of HDMI video devices that provide the
> digital audio interface (ASoC DAI) directly and there is no need for
> anything but dummy codec implementation (if following ASoC
> paradigm). Before going forward I think we should at least consider
> how this abstraction would serve those devices.
Sorry, but i don't see any difference between both implementations for 
this point.In both implementations, ops are called only if defined.
Could you give me name of the drivers you have in mind?
>
> Also, I am not entirely happy how the drm_audio_bridge_funcs are used
> at the moment. The do not map too well to ASoC DAI callbacks and I do
> not see too much point in creating a completely new audio-callback
> abstraction, that is sligtly incompatible with ALSA, and then
> translating alsa callbacks to these new callbacks. I think the
> callbacks should map more or less directly ALSA callbacks.

As API is defined in DRM, it seems more logical to match it with the one
defined for video. From my windows, i didn't see any blocking point to
connect codec callback with this API.
But anyway, this API is not freezed, it could be improved with your help.

Best Regards,
Arnaud


[PATCH RFC V2 5/5] DT: sti: add audio HDMI dai link in audio card

2015-10-01 Thread Arnaud Pouliquen
Add the HDMI dai link to support audio for HDMi output

Signed-off-by: Arnaud Pouliquen 
---
 arch/arm/boot/dts/stih410.dtsi   |  6 +-
 arch/arm/boot/dts/stihxxx-b2120.dtsi | 21 +
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi
index 7ee7dc0..dfc61a9 100644
--- a/arch/arm/boot/dts/stih410.dtsi
+++ b/arch/arm/boot/dts/stih410.dtsi
@@ -186,8 +186,9 @@
 <_s_d2_quadfs 0>;
};

-   sti-hdmi at 8d04000 {
+   sti_hdmi: sti-hdmi at 8d04000 {
compatible = "st,stih407-hdmi";
+   #sound-dai-cells = <0>;
reg = <0x8d04000 0x1000>;
reg-names = "hdmi-reg";
interrupts = ;
@@ -211,6 +212,9 @@
resets = < 
STIH407_HDMI_TX_PHY_SOFTRESET>;
ddc = <>;

+   sound-dai {
+   format = "spdif";
+   };
};

sti-hda at 8d02000 {
diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi 
b/arch/arm/boot/dts/stihxxx-b2120.dtsi
index 3ad9c82..80fed19 100644
--- a/arch/arm/boot/dts/stihxxx-b2120.dtsi
+++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi
@@ -81,6 +81,9 @@
audio_controller: sti-asoc-platform {
status = "okay";
};
+   sti_uni_player0: sti-uni-player at 0 {
+   status = "okay";
+   };
sti_uni_player2: sti-uni-player at 2 {
status = "okay";
};
@@ -93,6 +96,12 @@
sti_uni_reader1: sti-uni-reader at 1 {
status = "okay";
};
+
+   sti-display-subsystem {
+   sti_hdmi: sti-hdmi at 8d04000 {
+   status = "okay";
+   };
+   };
};

sound {
@@ -125,6 +134,18 @@
sound-dai = <_sasg_codec 0>;
};
};
+   simple-audio-card,dai-link at 2 {
+   /* HDMI */
+   format = "i2s";
+   mclk-fs = <128>;
+   cpu {
+   sound-dai = <_uni_player0>;
+   };
+
+   codec {
+   sound-dai = <_hdmi>;
+   };
+   };
};

 };
-- 
1.9.1



[PATCH RFC V2 4/5] drm: sti: connect audio driver

2015-10-01 Thread Arnaud Pouliquen
Registeur Asoc codec and implement audio bridge ops.

Signed-off-by: Arnaud Pouliquen 
---
 drivers/gpu/drm/sti/sti_hdmi.c | 184 ++---
 drivers/gpu/drm/sti/sti_hdmi.h |   3 +
 2 files changed, 176 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 06595e9..cf0e307 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -17,6 +17,8 @@
 #include 
 #include 

+#include 
+
 #include "sti_hdmi.h"
 #include "sti_hdmi_tx3g4c28phy.h"
 #include "sti_hdmi_tx3g0c55phy.h"
@@ -34,6 +36,8 @@
 #define HDMI_DFLT_CHL0_DAT  0x0110
 #define HDMI_DFLT_CHL1_DAT  0x0114
 #define HDMI_DFLT_CHL2_DAT  0x0118
+#define HDMI_AUDIO_CFG  0x0200
+#define HDMI_SPDIF_FIFO_STATUS  0x0204
 #define HDMI_SW_DI_1_HEAD_WORD  0x0210
 #define HDMI_SW_DI_1_PKT_WORD0  0x0214
 #define HDMI_SW_DI_1_PKT_WORD1  0x0218
@@ -43,6 +47,9 @@
 #define HDMI_SW_DI_1_PKT_WORD5  0x0228
 #define HDMI_SW_DI_1_PKT_WORD6  0x022C
 #define HDMI_SW_DI_CFG  0x0230
+#define HDMI_SAMPLE_FLAT_MASK   0x0244
+#define HDMI_AUDN   0x0400
+#define HDMI_AUD_CTS0x0404
 #define HDMI_SW_DI_2_HEAD_WORD  0x0600
 #define HDMI_SW_DI_2_PKT_WORD0  0x0604
 #define HDMI_SW_DI_2_PKT_WORD1  0x0608
@@ -109,6 +116,29 @@

 #define HDMI_STA_SW_RST BIT(1)

+#define HDMI_AUD_CFG_8CH   BIT(0)
+#define HDMI_AUD_CFG_SPDIF_DIV_2   BIT(1)
+#define HDMI_AUD_CFG_SPDIF_DIV_3   BIT(2)
+#define HDMI_AUD_CFG_SPDIF_CLK_DIV_4   (BIT(1) | BIT(2))
+#define HDMI_AUD_CFG_CTS_CLK_256FS BIT(12)
+#define HDMI_AUD_CFG_DTS_INVALID   BIT(16)
+#define HDMI_AUD_CFG_ONE_BIT_INVALID   (BIT(18) | BIT(19) | BIT(20) |  BIT(21))
+#define HDMI_AUD_CFG_CH12_VALIDBIT(28)
+#define HDMI_AUD_CFG_CH34_VALIDBIT(29)
+#define HDMI_AUD_CFG_CH56_VALIDBIT(30)
+#define HDMI_AUD_CFG_CH78_VALIDBIT(31)
+
+/* sample flat mask */
+#define HDMI_SAMPLE_FLAT_NO 0
+#define HDMI_SAMPLE_FLAT_SP0 BIT(0)
+#define HDMI_SAMPLE_FLAT_SP1 BIT(1)
+#define HDMI_SAMPLE_FLAT_SP2 BIT(2)
+#define HDMI_SAMPLE_FLAT_SP3 BIT(3)
+#define HDMI_SAMPLE_FLAT_ALL (HDMI_SAMPLE_FLAT_SP0 \
+ | HDMI_SAMPLE_FLAT_SP1 \
+ | HDMI_SAMPLE_FLAT_SP2 \
+ | HDMI_SAMPLE_FLAT_SP3)
+
 #define HDMI_INFOFRAME_HEADER_TYPE(x)(((x) & 0xff) <<  0)
 #define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
 #define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
@@ -380,19 +410,15 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi 
*hdmi)
  */
 static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
 {
-   struct hdmi_audio_infoframe infofame;
+   struct hdmi_audio_infoframe *infoframe;
u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
int ret;

-   ret = hdmi_audio_infoframe_init();
-   if (ret < 0) {
-   DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
-   return ret;
-   }
+   DRM_DEBUG_DRIVER("enter %s\n", __func__);

-   infofame.channels = 2;
+   infoframe = >audio.infoframe;

-   ret = hdmi_audio_infoframe_pack(, buffer, sizeof(buffer));
+   ret = hdmi_audio_infoframe_pack(infoframe, buffer, sizeof(buffer));
if (ret < 0) {
DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
return ret;
@@ -404,6 +430,60 @@ static int hdmi_audio_infoframe_config(struct sti_hdmi 
*hdmi)
 }

 /**
+ * set audio frame rate
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ */
+static int hdmi_audio_set_infoframe(struct sti_hdmi *hdmi,
+   struct hdmi_audio_infoframe *info)
+{
+   struct hdmi_audio_n_cts n_cts;
+   int ret, audio_cfg;
+
+   DRM_DEBUG_DRIVER("enter %s\n", __func__);
+
+   hdmi->audio.infoframe = *info;
+
+   if (!hdmi->enabled)
+   return 0;
+
+   /* update HDMI registers according to configuration */
+   audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID |
+   HDMI_AUD_CFG_ONE_BIT_INVALID;
+
+   switch (info->channels) {
+   case 8:
+   audio_cfg |= HDMI_AUD_CFG_CH78_VALID;
+   case 6:
+   audio_cfg |= HDMI_AUD_CFG_CH56_VALID;
+   case 4:
+   audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH;
+   case 2:
+   audio_cfg |= HDMI_AUD_CFG_CH12_VALID;
+   break;
+   default:
+   DRM_ERROR("ERROR: Unsupported number of channels (%d)!\n",
+ info->channels);
+   

[PATCH RFC V2 3/5] ASoC: codec: hdmi drm codec driver

2015-10-01 Thread Arnaud Pouliquen
Add a generic codec to interface audio with DRM drivers

Signed-off-by: Arnaud Pouliquen 
---
 include/sound/hdmi_drm.h|  15 ++
 sound/soc/codecs/Kconfig|   8 +-
 sound/soc/codecs/Makefile   |   2 +
 sound/soc/codecs/hdmi_drm.c | 358 
 4 files changed, 380 insertions(+), 3 deletions(-)
 create mode 100644 include/sound/hdmi_drm.h
 create mode 100644 sound/soc/codecs/hdmi_drm.c

diff --git a/include/sound/hdmi_drm.h b/include/sound/hdmi_drm.h
new file mode 100644
index 000..411acee
--- /dev/null
+++ b/include/sound/hdmi_drm.h
@@ -0,0 +1,15 @@
+/*
+ * Interface for HDMI DRM  codec
+ *
+ * Author: Arnaud Pouliquen 
+ *
+ * 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.
+ */
+#ifndef __HDMI_DRM__H__
+#define __HDMI_DRM__H__
+
+#define HDMI_DRM_CODEC_DRV_NAME "hdmi-drm-audio-codec"
+
+#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 395ef5d..fe5b0c8 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -80,6 +80,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_MC13783 if MFD_MC13XXX
select SND_SOC_ML26124 if I2C
select SND_SOC_HDMI_CODEC
+   select SND_SOC_HDMI_DRM_CODEC
select SND_SOC_PCM1681 if I2C
select SND_SOC_PCM1792A if SPI_MASTER
select SND_SOC_PCM3008
@@ -445,9 +446,10 @@ config SND_SOC_DMIC
 config SND_SOC_HDMI_CODEC
tristate "HDMI stub CODEC"

-   tristate
-   select SND_PCM_ELD
-   select SND_PCM_IEC958
+config SND_SOC_HDMI_DRM_CODEC
+   tristate "HDMI DRM CODEC"
+   select SND_PCM_ELD
+   select SND_PCM_IEC958

 config SND_SOC_ES8328
tristate "Everest Semi ES8328 CODEC"
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index f683b33..41b2dcb 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -73,6 +73,7 @@ snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
 snd-soc-hdmi-codec-objs := hdmi-codec.o
+snd-soc-hdmi-drm-codec-objs := hdmi_drm.o
 snd-soc-pcm1681-objs := pcm1681.o
 snd-soc-pcm1792a-codec-objs := pcm1792a.o
 snd-soc-pcm3008-objs := pcm3008.o
@@ -265,6 +266,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_HDMI_CODEC) += snd-soc-hdmi-codec.o
+obj-$(CONFIG_SND_SOC_HDMI_DRM_CODEC) += snd-soc-hdmi-drm-codec.o
 obj-$(CONFIG_SND_SOC_PCM1681)  += snd-soc-pcm1681.o
 obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o
 obj-$(CONFIG_SND_SOC_PCM3008)  += snd-soc-pcm3008.o
diff --git a/sound/soc/codecs/hdmi_drm.c b/sound/soc/codecs/hdmi_drm.c
new file mode 100644
index 000..1176d3b
--- /dev/null
+++ b/sound/soc/codecs/hdmi_drm.c
@@ -0,0 +1,358 @@
+/*
+ * ALSA SoC codec driver for DRM HDMI device.
+ * Copyright (C) STMicroelectronics SA 2015
+ * Authors: Arnaud Pouliquen 
+ *  for STMicroelectronics.
+ * Inspirate from hdmi-codec (Jyri Sarha )
+
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct hdmi_drm_dai_data {
+   struct drm_bridge *bridge;
+   struct hdmi_audio_mode mode;
+   struct drm_audio_bridge_cfg cfg;
+   enum {
+   HDMI_DRM_I2S,
+   HDMI_DRM_SPDIF
+   } hai;
+};
+
+static const struct snd_soc_dapm_widget hdmi_drm_widgets[] = {
+   SND_SOC_DAPM_OUTPUT("TX"),
+};
+
+static const struct snd_soc_dapm_route hdmi_drm_routes[] = {
+   { "TX", NULL, "Playback" },
+};
+
+int hdmi_drm_dai_startup(struct snd_pcm_substream *substream,
+struct snd_soc_dai *dai)
+{
+   struct hdmi_drm_dai_data *priv = snd_soc_dai_get_drvdata(dai);
+   uint8_t *eld;
+
+   dev_dbg(dai->dev, "%s: enter for bridge %p\n", __func__, priv->bridge);
+
+   eld = drm_audio_bridge_mode_get(priv->bridge);
+   if (!eld)
+   return 0;
+
+   return snd_pcm_hw_constraint_eld(substream->runtime, eld);
+}
+
+static void hdmi_drm_dai_shutdown(struct snd_pcm_substream *substream,
+  struct snd_soc_dai *dai)
+{
+   struct hdmi_drm_dai_data *priv = snd_soc_dai_get_drvdata(dai);
+
+   drm_audio_bridge_post_disable(priv->bridge);
+}
+
+static int hdmi_drm_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+   struct hdmi_drm_dai_data *priv = snd_soc_dai_get_drvdata(dai);
+   struct hdmi_audio_infoframe *iframe = >mode.infoframe;
+   unsigned c

[PATCH RFC V2 2/5] drm: add helper functions to add audio capabilities for bridge

2015-10-01 Thread Arnaud Pouliquen
Extend bridge capabilities for audio to enable to connect an audio driver to a
DRM driver with audio capabilities

Signed-off-by: Arnaud Pouliquen 
---
 drivers/gpu/drm/drm_bridge.c | 137 ++-
 include/drm/drm_crtc.h   |  62 
 include/drm/drm_modes.h  |  12 
 3 files changed, 210 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 6b8f721..d1a437e 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -194,7 +194,7 @@ EXPORT_SYMBOL(drm_bridge_mode_fixup);
  * chain, starting from the last bridge to the first. These are called before
  * calling the encoder's prepare op.
  *
- * Note: the bridge passed should be the one closest to the encoder
+ * Note: the bridge passed should be the othingsne closest to the encoder
  */
 void drm_bridge_disable(struct drm_bridge *bridge)
 {
@@ -328,6 +328,141 @@ struct drm_bridge *of_drm_find_bridge(struct device_node 
*np)
 EXPORT_SYMBOL(of_drm_find_bridge);
 #endif

+/**
+ * DOC: audio bridge callbacks
+ *
+ * The drm_audio_bridge_funcs ops are populated by the bridge driver that has
+ * audio capabilities (e.g. HDMI)
+ * The alsa driver (or asoc codec) uses the defined helpers.
+ * These helpers call a specific drm_audio_bridge_funcs ops defined by
+ * bridges with audio capabilities during encoder configuration.
+ *
+ * pre_enable: this contains actions needed to be done by the bridge before
+ * audio is enabled by its source.
+ *
+ * enable: this contains actions needed to be done by the audio bridge once its
+ * source is enabled. In other words, enable is called once the source is
+ * ready to start stream rendering.
+ *
+ * disable: this contains actions needed to be done by audio bridge when
+ * disable the audio part, assuming that its source is still enabled.
+ *
+ * post_disable: this contains actions needed to be done by the bridge once
+ * its source is disabled.
+ *
+ * mode_set: this sets up the mode by the audio bridge. It assumes that its
+ * audio source is aligned on this mode.
+ *
+ * mode_get: this get the supported modes based on ELD table. this can be use
+ * by audio source to fix audio constraints according to mode.
+ */
+
+/**
+ * drm_audio_bridge_pre_enable - calls 'pre_enable' drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ */
+int drm_audio_bridge_pre_enable(struct drm_bridge *bridge,
+struct drm_audio_bridge_cfg *cfg)
+{
+   if (!bridge)
+   return -EINVAL;
+
+   if (bridge->audio_funcs->pre_enable)
+   return bridge->audio_funcs->pre_enable(bridge, cfg);
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_pre_enable);
+
+/**
+ * drm_audio_bridge_disable - calls 'disable' drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ */
+int drm_audio_bridge_disable(struct drm_bridge *bridge)
+{
+   if (!bridge)
+   return -EINVAL;
+
+   if (bridge->audio_funcs->disable)
+   return bridge->audio_funcs->disable(bridge);
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_disable);
+
+/**
+ * drm_audio_bridge_enable - calls 'enable' drm_audio_bridge_funcs audio
+ * bridge in the encoder chain.
+ * @bridge: bridge control structure
+ */
+int drm_audio_bridge_enable(struct drm_bridge *bridge)
+{
+   if (!bridge)
+   return -EINVAL;
+
+   if (bridge->audio_funcs->enable)
+   return bridge->audio_funcs->enable(bridge);
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_enable);
+
+/**
+ * drm_audio_bridge_post_disable - calls 'disable' drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ */
+int drm_audio_bridge_post_disable(struct drm_bridge *bridge)
+{
+   if (!bridge)
+   return -EINVAL;
+
+   if (bridge->audio_funcs->post_disable)
+   return bridge->audio_funcs->post_disable(bridge);
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_post_disable);
+
+/**
+ * drm_audio_bridge_mode_set - calls 'mode_set' drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ * @mode: desired audio mode to be set for the audio bridge
+ */
+int drm_audio_bridge_mode_set(struct drm_bridge *bridge,
+  struct hdmi_audio_mode *mode)
+{
+   if (!bridge)
+   return -EINVAL;
+
+   if (bridge->audio_funcs->mode_set)
+   return bridge->audio_funcs->mode_set(bridge, mode);
+
+   return 0;
+}
+EXPORT_SYMBOL(drm_audio_bridge_mode_set);
+
+/**
+ * drm_audio_bridge_mode_get - calls 'enable'drm_audio_bridge_funcs op
+ * for audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ * Note: The ret

[PATCH RFC V2 1/5] video: hdmi: add helper function for N and CTS

2015-10-01 Thread Arnaud Pouliquen
Add helper function to compute HDMI CTS and N parameters
Implementation is based on HDMI 1.4b specification.

Signed-off-by: Arnaud Pouliquen 
Cc: linux-fbdev at vger.kernel.org
Cc: Jean-Christophe Plagniol-Villard 
Cc: Tomi Valkeinen 
---
 drivers/video/hdmi.c | 147 +++
 include/linux/hdmi.h |  12 +
 2 files changed, 159 insertions(+)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1626892..93e2fdf 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -1242,3 +1242,150 @@ int hdmi_infoframe_unpack(union hdmi_infoframe *frame, 
void *buffer)
return ret;
 }
 EXPORT_SYMBOL(hdmi_infoframe_unpack);
+
+/**
+ * audio clock regeneration (acr) parameters
+ * N and CTS computation are based on HDMI specification 1.4b
+ */
+enum audio_rate {
+   HDMI_AUDIO_N_CTS_32KHZ,
+   HDMI_AUDIO_N_CTS_44_1KHZ,
+   HDMI_AUDIO_N_CTS_48KHZ,
+};
+
+struct hdmi_audio_acr {
+   unsigned long pixel_clk;
+   struct hdmi_audio_n_cts n_cts;
+};
+
+static const struct hdmi_audio_acr hdmi_audio_standard_acr[3][12] = {
+   { /*32 kHz*/
+   {  25175, {  4576,  28125 } }, /* 25,20/1.001  MHz */
+   {  25200, {  4096,  25200 } }, /* 25.20MHz */
+   {  27000, {  4096,  27000 } }, /* 27.00MHz */
+   {  27027, {  4096,  27027 } }, /* 27.00*1.001  MHz */
+   {  54000, {  4096,  54000 } }, /* 54.00MHz */
+   {  54054, {  4096,  54054 } }, /* 54.00*1.001  MHz */
+   {  74176, { 11648, 310938 } }, /* 74.25/1.001  MHz */
+   {  74250, {  4096,  74250 } }, /* 74.25MHz */
+   { 148352, { 11648, 421875 } }, /* 148.50/1.001 MHz */
+   { 148500, {  4096, 148500 } }, /* 148.50   MHz */
+   { 296703, {  5824, 421875 } }, /* 297/1.001MHz */
+   { 297000, {  3072, 222750 } }, /* 297  MHz */
+   },
+   { /*44.1 kHz, 88.2 kHz  176.4 kHz*/
+   {  25175, {  7007,  31250 } }, /* 25,20/1.001  MHz */
+   {  25200, {  6272,  28000 } }, /* 25.20MHz */
+   {  27000, {  6272,  3 } }, /* 27.00MHz */
+   {  27027, {  6272,  30030 } }, /* 27.00*1.001  MHz */
+   {  54000, {  6272,  6 } }, /* 54.00MHz */
+   {  54054, {  6272,  60060 } }, /* 54.00*1.001  MHz */
+   {  74176, { 17836, 234375 } }, /* 74.25/1.001  MHz */
+   {  74250, {  6272,  82500 } }, /* 74.25MHz */
+   { 148352, {  8918, 234375 } }, /* 148.50/1.001 MHz */
+   { 148500, {  6272, 165000 } }, /* 148.50   MHz */
+   { 296703, {  4459, 234375 } }, /* 297/1.001MHz */
+   { 297000, {  4704, 247500 } }, /* 297  MHz */
+   },
+   { /*48 kHz, 96 kHz  192 kHz*/
+   {  25175, {  6864,  28125 } }, /* 25,20/1.001  MHz */
+   {  25200, {  6144,  25200 } }, /* 25.20MHz */
+   {  27000, {  6144,  27000 } }, /* 27.00MHz */
+   {  27027, {  6144,  27027 } }, /* 27.00*1.001  MHz */
+   {  54000, {  6144,  54000 } }, /* 54.00MHz */
+   {  54054, {  6144,  54054 } }, /* 54.00*1.001  MHz */
+   {  74176, { 11648, 140625 } }, /* 74.25/1.001  MHz */
+   {  74250, {  6144,  74250 } }, /* 74.25MHz */
+   { 148352, {  5824, 140625 } }, /* 148.50/1.001 MHz */
+   { 148500, {  6144, 148500 } }, /* 148.50   MHz */
+   { 296703, {  5824, 281250 } }, /* 297/1.001MHz */
+   { 297000, {  5120, 247500 } }, /* 297  MHz */
+   }
+};
+
+/**
+ * hdmi_compute_n_cts() - compute N and CTS parameters
+ * @audio_fs: audio frame clock frequency in KHz
+ * @pixel_clk: pixel cloack frequency in kHz
+ * @n_cts: N and CTS parameter returned to user
+ *
+ * Values computed are based on table described in HDMI specification 1.4b
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_audio_compute_n_cts(enum hdmi_audio_sample_frequency audio_fs,
+unsigned long pixel_clk,
+struct hdmi_audio_n_cts *n_cts)
+{
+   int audio_freq_id, i;
+   int ratio = 1;
+   const struct hdmi_audio_acr  *acr_table;
+   const struct hdmi_audio_n_cts *predef_n_cts = NULL;
+
+   switch (audio_fs) {
+   case HDMI_AUDIO_SAMPLE_FREQUENCY_32000:
+   audio_freq_id = HDMI_AUDIO_N_CTS_32KHZ;
+   n_cts->n = 4096;
+   break;
+
+   case HDMI_AUDIO_SAMPLE_FREQUENCY_44100:
+   audio_freq_id = HDMI_AUDIO_N_CTS_44_1KHZ;
+   n_cts->n = 6272;
+   break;
+
+   case HDMI_AUDIO_SAMPLE_FREQUENCY_48000:
+   audio_freq_id = HDMI_AUDIO_N_CTS_48KHZ;
+   n_cts->n = 6144;
+   

[PATCH RFC V2 0/5] another generic audio hdmi codec proposal

2015-10-01 Thread Arnaud Pouliquen

Version 2:
This version integrates missing features upgraded to be aligned when possible 
with patch set:
[PATCH RFC v4 0/8] Implement generic ASoC HDMI codec and use it in tda998x

It does not support the abort callback, the mute and syclk ops. 
This could be added in V3 or separate patch if justified.  

  [RFC 1/5]video: hdmi: add help function for N and CTS
- Replace real frequency value by enum in switch case
Notice that this patch is independant from the rest of the implentation
  [RFC 2/5]drm: add helper functions to add audio capabilities for bridge
- extend audio bridge ops
  [RFC 3/5]ASoC: codec:  hdmi drm codec driver
aligned when possible with hdmi-codec.c implementation
. ELD management for alsa contraints
. Support of SPDIF and I2S mode
. hwparam ond set_fmt functions implemented
  [RFC 4/5]drm: sti: connect audio driver
=> Implementation for STI platform
  [RFC 5/5]DT: sti: add audio HDMI dai link in audio card
=> Devicetree example

Version 1:

This patch set is a tentative to implement a generic code for the HDMI audio.
Main concept are aligned with solution proposeded for TI platform. 
 -  ASoC codec driver registered by DRM driver
 -  ASOC driver is a generic driver.
 -  compatible with simple card

 Difference is that i propose a DRM generic interface based on bridge structure.
 Advantage is that all data exchanges are done through the DRM API.

 I think also that some helper functions could been used for N and CTS 
parameters calculation,
 as suggested by Russell King in a previous mail.

 I full aware that some features (like ELD and info frame) are partially or not 
implemented in my patches. 
 This patch set is more a skeleton than a full implementation...
 I just post it to suggest a possible DRM API.

Arnaud Pouliquen (5):
  video: hdmi: add helper function for N and CTS
  drm: add helper function to add audio capabilities for bridge
  ASoC: codec:  hdmi drm codec driver
  drm: sti: connect audio driver
  DT: sti: add audio HDMI dai link in audio card

 arch/arm/boot/dts/stih410.dtsi   |   6 +-
 arch/arm/boot/dts/stihxxx-b2120.dtsi |  21 ++
 drivers/gpu/drm/drm_bridge.c | 137 +-
 drivers/gpu/drm/sti/sti_hdmi.c   | 184 --
 drivers/gpu/drm/sti/sti_hdmi.h   |   3 +
 drivers/video/hdmi.c | 147 ++
 include/drm/drm_crtc.h   |  62 ++
 include/drm/drm_modes.h  |  12 ++
 include/linux/hdmi.h |  12 ++
 include/sound/hdmi_drm.h |  15 ++
 sound/soc/codecs/Kconfig |   8 +-
 sound/soc/codecs/Makefile|   2 +
 sound/soc/codecs/hdmi_drm.c  | 358 +++
 13 files changed, 951 insertions(+), 16 deletions(-)
 create mode 100644 include/sound/hdmi_drm.h
 create mode 100644 sound/soc/codecs/hdmi_drm.c

-- 
1.9.1



[PATCH RFC v4 3/8] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders

2015-09-28 Thread Arnaud Pouliquen
few questions/remarks
BR,
Arnaud

> +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(>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(>current_stream_lock);
> +}
Does driver should stop the stream in case of unplug?
This could generate unexpected behavior at application level.
Perhaps should be better if this part is managed in DRM driver. if HDMI 
master, I2S bus should be maintained ON to consume the audio stream 
until application action.

> +
> +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));
Tell me if i am wrong, but in case of SPDIF format, IEC status is 
managed by cpu_dai not by the codec.
To manage IEC61937 a control should be needed to update IEC status bits...

> +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.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,
> >daifmt[dai->id],
> +   );
> +}
> +


[RFC 3/5] ASoC: codec: hdmi drm codec driver

2015-09-25 Thread Arnaud Pouliquen
Hello Jyri,

Yes using or not DRM bridge we should be able to have a common 
implementation

Please find,my answer belows

BR,
Arnaud

On 09/25/2015 04:11 PM, Jyri Sarha wrote:
> Despite my earlier comment this implementation and the related HW is
> quite similar in all significant aspects to the patch set posted couple
> of days ago [1] for Beaglebone-Black HDMI audio.
>
> [1] http://permalink.gmane.org/gmane.linux.alsa.devel/144144
yes i trying to align my dev on it. to match with your development.
Aim for me is to reuse it and adapt it using a DRM bridge interface.
i hope to provide a V2 next week.
>
> I have not yet gotten to bottom of drm-side audio bride part, but I am
> working on it. Bellow is couple of early comments to the ASoC part.
>
> Best regards,
> Jyri
>
> On 09/21/15 16:19, Arnaud Pouliquen wrote:
>> +
>> +static int st_hdmi_dai_probe(struct snd_soc_dai *dai)
>> +{
>> +struct hdmi_drm_dai_data *priv;
>> +
>> +dev_err(dai->dev, "%s: enter\n", __func__);
>> +priv = devm_kzalloc(dai->dev, sizeof(*priv), GFP_KERNEL);
>> +
>> +priv->bridge = of_drm_find_bridge(dai->dev->of_node);
>> +
>> +dev_err(dai->dev, "%s: bridge %p\n", __func__, priv->bridge);
>> +
>> +snd_soc_dai_set_drvdata(dai, priv);
>> +
>
> The call above overwrites the private data pointer of the drivers that
> registering the codec. This hardly works in general.
>
> A separate platform driver - with this already merged patch [2] - that I
> use with my patch-set solves this issue quite nicely.
>
> [2] http://lists.freedesktop.org/archives/dri-devel/2015-May/083517.html
Yes same dev,(but no crash...?).i need to define sub node.
>> +return 0;
>> +}here are several important callbacks missing here
>> +
>> +static const struct snd_soc_dai_ops hdmi_drm_codec_ops = {
>> +.prepare =  hdmi_drm_dai_prepare,
>> +.trigger = hdmi_drm_dai_trigger,
>> +};
>
>
> At least set_daifmt() and hw_params() callbacks should be defined before
> this could be generally usable. HDMI encoders do not usually support too
> many daifmts, but the driver should be able the check that the selected
> format is supported. But as you said this not complete code yet.
I'm trying to match codec ops with following DRM audio bridge ops,
that is similar to the existing drm_bridge_funcs structure.
struct drm_audio_bridge_funcs {
void (*disable)(struct drm_bridge *bridge);
void (*post_disable)(struct drm_bridge *bridge);
void (*pre_enable)(struct drm_bridge *bridge);
void (*enable)(struct drm_bridge *bridge);
int  (*mode_set)(struct drm_bridge *bridge,
struct hdmi_audio_mode *mode);
uint8_t *(*mode_get)(struct drm_bridge *bridge); /*return eld*/
};
audio parameters should be part of struct hdmi_audio_mode that contains 
audio configurations ( info frame,iec, format, clk...)




[RFC 5/5] DT: sti: add audio HDMI dai link in audio card

2015-09-21 Thread Arnaud Pouliquen
Add the HDMI dai link to support audio for HDMi output

Signed-off-by: Arnaud Pouliquen 
---
 arch/arm/boot/dts/stih410.dtsi   |  4 ++--
 arch/arm/boot/dts/stihxxx-b2120.dtsi | 21 +
 arch/arm/configs/multi_v7_defconfig  |  1 +
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi
index 7ee7dc0..3881016 100644
--- a/arch/arm/boot/dts/stih410.dtsi
+++ b/arch/arm/boot/dts/stih410.dtsi
@@ -186,8 +186,9 @@
 <_s_d2_quadfs 0>;
};

-   sti-hdmi at 8d04000 {
+   sti_hdmi: sti-hdmi at 8d04000 {
compatible = "st,stih407-hdmi";
+   #sound-dai-cells = <0>;
reg = <0x8d04000 0x1000>;
reg-names = "hdmi-reg";
interrupts = ;
@@ -210,7 +211,6 @@
reset-names = "hdmi";
resets = < 
STIH407_HDMI_TX_PHY_SOFTRESET>;
ddc = <>;
-
};

sti-hda at 8d02000 {
diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi 
b/arch/arm/boot/dts/stihxxx-b2120.dtsi
index 3ad9c82..80fed19 100644
--- a/arch/arm/boot/dts/stihxxx-b2120.dtsi
+++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi
@@ -81,6 +81,9 @@
audio_controller: sti-asoc-platform {
status = "okay";
};
+   sti_uni_player0: sti-uni-player at 0 {
+   status = "okay";
+   };
sti_uni_player2: sti-uni-player at 2 {
status = "okay";
};
@@ -93,6 +96,12 @@
sti_uni_reader1: sti-uni-reader at 1 {
status = "okay";
};
+
+   sti-display-subsystem {
+   sti_hdmi: sti-hdmi at 8d04000 {
+   status = "okay";
+   };
+   };
};

sound {
@@ -125,6 +134,18 @@
sound-dai = <_sasg_codec 0>;
};
};
+   simple-audio-card,dai-link at 2 {
+   /* HDMI */
+   format = "i2s";
+   mclk-fs = <128>;
+   cpu {
+   sound-dai = <_uni_player0>;
+   };
+
+   codec {
+   sound-dai = <_hdmi>;
+   };
+   };
};

 };
diff --git a/arch/arm/configs/multi_v7_defconfig 
b/arch/arm/configs/multi_v7_defconfig
index 2a44694..6f43666 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -461,6 +461,7 @@ CONFIG_SND_ATMEL_SOC=m
 CONFIG_SND_ATMEL_SOC_WM8904=m
 CONFIG_SND_SOC_SH4_FSI=m
 CONFIG_SND_SOC_RCAR=m
+CONFIG_SND_SOC_HDMI_DRM_CODEC=y
 CONFIG_SND_SOC_STI=y
 CONFIG_SND_SOC_STI_SAS=y
 CONFIG_SND_SOC_TEGRA=m
-- 
1.9.1



[RFC 4/5] drm: sti: connect audio driver

2015-09-21 Thread Arnaud Pouliquen
Add management of the audio bridge

Signed-off-by: Arnaud Pouliquen 
---
 drivers/gpu/drm/sti/sti_hdmi.c | 146 +
 drivers/gpu/drm/sti/sti_hdmi.h |   3 +
 2 files changed, 137 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 06595e9..d324e0a 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -17,6 +17,8 @@
 #include 
 #include 

+#include 
+
 #include "sti_hdmi.h"
 #include "sti_hdmi_tx3g4c28phy.h"
 #include "sti_hdmi_tx3g0c55phy.h"
@@ -34,6 +36,8 @@
 #define HDMI_DFLT_CHL0_DAT  0x0110
 #define HDMI_DFLT_CHL1_DAT  0x0114
 #define HDMI_DFLT_CHL2_DAT  0x0118
+#define HDMI_AUDIO_CFG  0x0200
+#define HDMI_SPDIF_FIFO_STATUS  0x0204
 #define HDMI_SW_DI_1_HEAD_WORD  0x0210
 #define HDMI_SW_DI_1_PKT_WORD0  0x0214
 #define HDMI_SW_DI_1_PKT_WORD1  0x0218
@@ -43,6 +47,9 @@
 #define HDMI_SW_DI_1_PKT_WORD5  0x0228
 #define HDMI_SW_DI_1_PKT_WORD6  0x022C
 #define HDMI_SW_DI_CFG  0x0230
+#define HDMI_SAMPLE_FLAT_MASK   0x0244
+#define HDMI_AUDN   0x0400
+#define HDMI_AUD_CTS0x0404
 #define HDMI_SW_DI_2_HEAD_WORD  0x0600
 #define HDMI_SW_DI_2_PKT_WORD0  0x0604
 #define HDMI_SW_DI_2_PKT_WORD1  0x0608
@@ -52,6 +59,7 @@
 #define HDMI_SW_DI_2_PKT_WORD5  0x0618
 #define HDMI_SW_DI_2_PKT_WORD6  0x061C

+
 #define HDMI_IFRAME_SLOT_AVI1
 #define HDMI_IFRAME_SLOT_AUDIO  2

@@ -109,6 +117,27 @@

 #define HDMI_STA_SW_RST BIT(1)

+#define HDMI_AUD_CFG_8CHBIT(0)
+#define HDMI_AUD_CFG_SPDIF_DIV_2  BIT(1)
+#define HDMI_AUD_CFG_SPDIF_DIV_3  BIT(2)
+#define HDMI_AUD_CFG_SPDIF_CLK_DIV_4 (BIT(1) | BIT(1))
+#define HDMI_AUD_CFG_CTS_CLK_128FS  BIT(17)
+#define HDMI_AUD_CFG_CH12_VALID BIT(28)
+#define HDMI_AUD_CFG_CH34_VALID BIT(29)
+#define HDMI_AUD_CFG_CH56_VALID BIT(30)
+#define HDMI_AUD_CFG_CH78_VALID BIT(31)
+
+/* sample flat mask */
+#define HDMI_SAMPLE_FLAT_NO 0
+#define HDMI_SAMPLE_FLAT_SP0 BIT(0)
+#define HDMI_SAMPLE_FLAT_SP1 BIT(1)
+#define HDMI_SAMPLE_FLAT_SP2 BIT(2)
+#define HDMI_SAMPLE_FLAT_SP3 BIT(3)
+#define HDMI_SAMPLE_FLAT_ALL (HDMI_SAMPLE_FLAT_SP0 \
+ | HDMI_SAMPLE_FLAT_SP1 \
+ | HDMI_SAMPLE_FLAT_SP2 \
+ | HDMI_SAMPLE_FLAT_SP3)
+
 #define HDMI_INFOFRAME_HEADER_TYPE(x)(((x) & 0xff) <<  0)
 #define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
 #define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
@@ -380,19 +409,13 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi 
*hdmi)
  */
 static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
 {
-   struct hdmi_audio_infoframe infofame;
+   struct hdmi_audio_infoframe *infoframe;
u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
int ret;

-   ret = hdmi_audio_infoframe_init();
-   if (ret < 0) {
-   DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
-   return ret;
-   }
-
-   infofame.channels = 2;
+   infoframe = >audio.infoframe;

-   ret = hdmi_audio_infoframe_pack(, buffer, sizeof(buffer));
+   ret = hdmi_audio_infoframe_pack(infoframe, buffer, sizeof(buffer));
if (ret < 0) {
DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
return ret;
@@ -404,6 +427,56 @@ static int hdmi_audio_infoframe_config(struct sti_hdmi 
*hdmi)
 }

 /**
+ * set audio frame rate
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ */
+static int hdmi_audio_set_infoframe(struct sti_hdmi *hdmi,
+   struct hdmi_audio_infoframe *info)
+{
+   struct hdmi_audio_n_cts n_cts;
+   int ret, audio_cfg;
+
+   hdmi->audio.infoframe = *info;
+
+   if (!hdmi->enabled)
+   return 0;
+
+   /* update HDMI registers according to configuration */
+   audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_3 | HDMI_AUD_CFG_CTS_CLK_128FS;
+
+   switch (info->channels) {
+   case 8:
+   audio_cfg |= HDMI_AUD_CFG_CH78_VALID;
+   case 6:
+   audio_cfg |= HDMI_AUD_CFG_CH56_VALID;
+   case 4:
+   audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH;
+   case 2:
+   audio_cfg = HDMI_AUD_CFG_CH12_VALID;
+   break;
+   default:
+   DRM_ERROR("ERROR: Unsupported number of channels (%d)!\n",
+ info->channels);
+   return -EINVAL;
+   }
+
+   hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG);
+
+   /* update N parameter */
+   ret = hdmi_audio_compute_n_cts(info->sample_frequency,
+  

[RFC 3/5] ASoC: codec: hdmi drm codec driver

2015-09-21 Thread Arnaud Pouliquen
Add a generic codec to interface audio with DRM drivers

Signed-off-by: Arnaud Pouliquen 
---
 include/sound/hdmi_drm.h|  16 ++
 sound/soc/codecs/Kconfig|   4 ++
 sound/soc/codecs/Makefile   |   2 +
 sound/soc/codecs/hdmi_drm.c | 125 
 4 files changed, 147 insertions(+)
 create mode 100644 include/sound/hdmi_drm.h
 create mode 100644 sound/soc/codecs/hdmi_drm.c

diff --git a/include/sound/hdmi_drm.h b/include/sound/hdmi_drm.h
new file mode 100644
index 000..0146b88
--- /dev/null
+++ b/include/sound/hdmi_drm.h
@@ -0,0 +1,16 @@
+/*
+ * Interface for HDMI DRM  codec
+ *
+ * Author: Arnaud Pouliquen 
+ *
+ * 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.
+ */
+#ifndef __HDMI_DRM__H__
+#define __HDMI_DRM__H__
+
+int hdmi_drm_codec_register(struct device *dev);
+void hdmi_drm_codec_unregister(struct device *dev);
+
+#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0c9733e..922af30 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -80,6 +80,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_MC13783 if MFD_MC13XXX
select SND_SOC_ML26124 if I2C
select SND_SOC_HDMI_CODEC
+   select SND_SOC_HDMI_DRM_CODEC
select SND_SOC_PCM1681 if I2C
select SND_SOC_PCM1792A if SPI_MASTER
select SND_SOC_PCM3008
@@ -445,6 +446,9 @@ config SND_SOC_DMIC
 config SND_SOC_HDMI_CODEC
tristate "HDMI stub CODEC"

+config SND_SOC_HDMI_DRM_CODEC
+   tristate "HDMI DRM CODEC"
+
 config SND_SOC_ES8328
tristate "Everest Semi ES8328 CODEC"

diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 4a32077..c92aaf7 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -73,6 +73,7 @@ snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
 snd-soc-hdmi-codec-objs := hdmi.o
+snd-soc-hdmi-drm-codec-objs := hdmi_drm.o
 snd-soc-pcm1681-objs := pcm1681.o
 snd-soc-pcm1792a-codec-objs := pcm1792a.o
 snd-soc-pcm3008-objs := pcm3008.o
@@ -265,6 +266,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_HDMI_CODEC) += snd-soc-hdmi-codec.o
+obj-$(CONFIG_SND_SOC_HDMI_DRM_CODEC) += snd-soc-hdmi-drm-codec.o
 obj-$(CONFIG_SND_SOC_PCM1681)  += snd-soc-pcm1681.o
 obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o
 obj-$(CONFIG_SND_SOC_PCM3008)  += snd-soc-pcm3008.o
diff --git a/sound/soc/codecs/hdmi_drm.c b/sound/soc/codecs/hdmi_drm.c
new file mode 100644
index 000..2df9a8f
--- /dev/null
+++ b/sound/soc/codecs/hdmi_drm.c
@@ -0,0 +1,125 @@
+/*
+ * ALSA SoC codec driver for DRM HDMI device.
+ * Copyright (C) STMicroelectronics SA 2015
+ * Authors: Arnaud Pouliquen 
+ *  for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct hdmi_drm_dai_data {
+   struct drm_bridge *bridge;
+};
+
+static const struct snd_soc_dapm_widget hdmi_drm_widgets[] = {
+   SND_SOC_DAPM_OUTPUT("TX"),
+};
+
+static const struct snd_soc_dapm_route hdmi_drm_routes[] = {
+   { "TX", NULL, "Playback" },
+};
+
+int hdmi_drm_dai_prepare(struct snd_pcm_substream *substream,
+struct snd_soc_dai *dai)
+{
+   struct hdmi_drm_dai_data *priv = snd_soc_dai_get_drvdata(dai);
+
+   dev_err(dai->dev, "%s: enter for bridge %p\n", __func__, priv->bridge);
+   drm_audio_bridge_pre_enable(priv->bridge);
+   return 0;
+}
+
+int hdmi_drm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+struct snd_soc_dai *dai)
+{
+   struct hdmi_drm_dai_data *priv = snd_soc_dai_get_drvdata(dai);
+
+   dev_err(dai->dev, "%s: enter\n", __func__);
+   switch (cmd) {
+   case SNDRV_PCM_TRIGGER_START:
+   case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+   case SNDRV_PCM_TRIGGER_RESUME:
+   drm_audio_bridge_enable(priv->bridge);
+   break;
+
+   case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+   case SNDRV_PCM_TRIGGER_STOP:
+   case SNDRV_PCM_TRIGGER_SUSPEND:
+   drm_audio_bridge_disable(priv->bridge);
+   break;
+   }
+
+   return 0;
+}
+
+static int st_hdmi_dai_probe(struct snd_soc_dai *dai)
+{
+   struct hdmi_drm_dai_data *priv;
+
+   dev_err(dai->dev, "%s: enter\n", __func__);
+   priv = devm_kzalloc(dai->dev, sizeof(*priv), GFP_KERNEL);
+
+   priv->bridge = of_drm_find_bridge(dai->dev->of_node);
+
+   dev_err(dai->dev, "%s: bridge %p\n", __func__, priv-

[RFC 2/5] drm: add helper functions to add bridge audio capabilities

2015-09-21 Thread Arnaud Pouliquen
Extend bridge capabilities for audio to enable to connect an audio driver to a
DRM driver with audio capabilities

Signed-off-by: Arnaud Pouliquen 
---
 drivers/gpu/drm/drm_bridge.c | 114 +++
 include/drm/drm_crtc.h   |  31 
 include/linux/hdmi.h |  16 ++
 3 files changed, 161 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 6b8f721..2284ac9 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -328,6 +328,120 @@ struct drm_bridge *of_drm_find_bridge(struct device_node 
*np)
 EXPORT_SYMBOL(of_drm_find_bridge);
 #endif

+/**
+ * DOC: audio bridge callbacks
+ *
+ * The drm_audio_bridge_funcs ops are populated by the bridge driver that have
+ * audio capabilities (a.e HDMI)
+ * The drm internals(atomic and crtc helpers) use the helpers defined in
+ * drm_bridge.c
+ * These helpers call a specific drm_audio_bridge_funcs ops for all the bridges
+ * during encoder configuration.
+ *
+ * When creating a bridge driver, one can implement drm_audio_bridge_funcs op
+ * with the help of these rough rules:
+ *
+ * pre_enable: this contains things needed to be done for the bridge before
+ * audio is enabled by its source.
+ *
+ * enable: this contains things needed to be done for the audio bridge once its
+ * source is enabled. In other words, enable is called once the source is
+ * ready to start stream rendering.
+ *
+ * disable: this contains things needed to be done for audio bridge when to
+ * disable the audio part for the bridge, assuming that its source is still
+ * enabled.
+ *
+ * post_disable: this contains things needed to be done for the bridge once
+ * its source is disabled.
+ *
+ * mode_set: this sets up the mode for the audio bridge. It assumes that its
+ * source (an encoder or a bridge) has set the mode too.
+ */
+
+/**
+ * drm_audio_bridge_pre_enable - calls 'pre_enable' drm_audio_bridge_funcs ops
+ *   for audio bridges in the encoder chain.
+ * @bridge: bridge control structure
+ *
+ * Calls 'pre_enable' drm_audio_bridge_funcs op for  audio bridge in the
+ * encoder chain.
+ *
+ */
+
+void drm_audio_bridge_pre_enable(struct drm_bridge *bridge)
+{
+   if (!bridge)
+   return;
+
+   if (bridge->audio_funcs->pre_enable)
+   bridge->audio_funcs->pre_enable(bridge);
+}
+EXPORT_SYMBOL(drm_audio_bridge_pre_enable);
+
+/**
+ * drm_audio_bridge_disable - calls 'disable' drm_audio_bridge_funcs op for
+ *audio bridge in the encoder chain.
+ * @bridge: bridge control structure
+ *
+ * Calls 'disable' drm_audio_bridge_funcs op for bridges with audio in the
+ * encoder chain.
+ *
+ */
+void drm_audio_bridge_disable(struct drm_bridge *bridge)
+{
+   if (!bridge)
+   return;
+
+   if (bridge->audio_funcs->disable)
+   bridge->audio_funcs->disable(bridge);
+}
+EXPORT_SYMBOL(drm_audio_bridge_disable);
+
+/**
+ * drm_audio_bridge_mode_set - set audio mode for audio bridge in the
+ *  encoder chain
+ * @bridge: bridge control structure
+ * @mode: desired audio mode to be set for the audio bridge
+ *
+ * Calls 'mode_set' drm_audio_bridge_funcs op for audio bridge in the
+ * encoder chain.
+ *
+ */
+void drm_audio_bridge_mode_set(struct drm_bridge *bridge,
+  struct hdmi_audio_mode *mode)
+{
+   if (!bridge)
+   return;
+
+   if (bridge->audio_funcs->mode_set)
+   bridge->audio_funcs->mode_set(bridge, mode);
+}
+EXPORT_SYMBOL(drm_audio_bridge_mode_set);
+
+/**
+ * drm_audio_bridge_enable - calls 'enable' drm_audio_bridge_funcs op for all 
bridges
+ *in the encoder chain.
+ * @bridge: bridge control structure
+ *
+ * Calls 'enable' drm_audio_bridge_funcs op for all the bridges in the encoder
+ * chain, starting from the first bridge to the last. These are called
+ * after completing the encoder's commit op.
+ *
+ * Note that the bridge passed should be the one closest to the encoder
+ */
+void drm_audio_bridge_enable(struct drm_bridge *bridge)
+{
+   if (!bridge)
+   return;
+
+   if (bridge->audio_funcs->mode_set)
+   bridge->audio_funcs->enable(bridge);
+
+}
+EXPORT_SYMBOL(drm_audio_bridge_enable);
+
+
 MODULE_AUTHOR("Ajay Kumar ");
 MODULE_DESCRIPTION("DRM bridge infrastructure");
 MODULE_LICENSE("GPL and additional rights");
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3b4d8a4..5074019 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -583,6 +583,7 @@ struct drm_encoder_funcs {
  * @possible_clones: bitmask of potential sibling encoders for cloning
  * @crtc: currently bound CRTC
  * @bridge: bridge associated to the encoder
+ * @abridge: optional audio bridge associated to the encoder (HDMI)
  * @funcs: cont

[RFC 1/5] video: hdmi: add help function for N and CTS

2015-09-21 Thread Arnaud Pouliquen
Add helper function to compute CTS and N parameters base on 
table described in HDMI specification 1.4b

Signed-off-by: Arnaud Pouliquen 
---
 drivers/video/hdmi.c | 148 +++
 include/linux/hdmi.h |   8 +++
 2 files changed, 156 insertions(+)

diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 1626892..9c487fb 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -1242,3 +1242,151 @@ int hdmi_infoframe_unpack(union hdmi_infoframe *frame, 
void *buffer)
return ret;
 }
 EXPORT_SYMBOL(hdmi_infoframe_unpack);
+
+/*
+ * audio clock regeneration (acr) parameters
+ * N and CTS computation are based on HDMI specification 1.4b
+ */
+
+enum audio_rate {
+   HDMI_AUDIO_N_CTS_32KHZ,
+   HDMI_AUDIO_N_CTS_44_1KHZ,
+   HDMI_AUDIO_N_CTS_48KHZ,
+};
+
+struct hdmi_audio_acr {
+   unsigned long pixel_clk;
+   struct hdmi_audio_n_cts n_cts;
+};
+
+static const struct hdmi_audio_acr hdmi_audio_standard_acr[3][12] = {
+   { /*32 kHz*/
+   {  25175, {  4576,  28125 } }, /* 25,20/1.001  MHz */
+   {  25200, {  4096,  25200 } }, /* 25.20MHz */
+   {  27000, {  4096,  27000 } }, /* 27.00MHz */
+   {  27027, {  4096,  27027 } }, /* 27.00*1.001  MHz */
+   {  54000, {  4096,  54000 } }, /* 54.00MHz */
+   {  54054, {  4096,  54054 } }, /* 54.00*1.001  MHz */
+   {  74176, { 11648, 310938 } }, /* 74.25/1.001  MHz */
+   {  74250, {  4096,  74250 } }, /* 74.25MHz */
+   { 148352, { 11648, 421875 } }, /* 148.50/1.001 MHz */
+   { 148500, {  4096, 148500 } }, /* 148.50   MHz */
+   { 296703, {  5824, 421875 } }, /* 297/1.001MHz */
+   { 297000, {  3072, 222750 } }, /* 297  MHz */
+   },
+   { /*44.1 kHz, 88.2 kHz  176.4 kHz*/
+   {  25175, {  7007,  31250 } }, /* 25,20/1.001  MHz */
+   {  25200, {  6272,  28000 } }, /* 25.20MHz */
+   {  27000, {  6272,  3 } }, /* 27.00MHz */
+   {  27027, {  6272,  30030 } }, /* 27.00*1.001  MHz */
+   {  54000, {  6272,  6 } }, /* 54.00MHz */
+   {  54054, {  6272,  60060 } }, /* 54.00*1.001  MHz */
+   {  74176, { 17836, 234375 } }, /* 74.25/1.001  MHz */
+   {  74250, {  6272,  82500 } }, /* 74.25MHz */
+   { 148352, {  8918, 234375 } }, /* 148.50/1.001 MHz */
+   { 148500, {  6272, 165000 } }, /* 148.50   MHz */
+   { 296703, {  4459, 234375 } }, /* 297/1.001MHz */
+   { 297000, {  4704, 247500 } }, /* 297  MHz */
+   },
+   { /*48 kHz, 96 kHz  192 kHz*/
+   {  25175, {  6864,  28125 } }, /* 25,20/1.001  MHz */
+   {  25200, {  6144,  25200 } }, /* 25.20MHz */
+   {  27000, {  6144,  27000 } }, /* 27.00MHz */
+   {  27027, {  6144,  27027 } }, /* 27.00*1.001  MHz */
+   {  54000, {  6144,  54000 } }, /* 54.00MHz */
+   {  54054, {  6144,  54054 } }, /* 54.00*1.001  MHz */
+   {  74176, { 11648, 140625 } }, /* 74.25/1.001  MHz */
+   {  74250, {  6144,  74250 } }, /* 74.25MHz */
+   { 148352, {  5824, 140625 } }, /* 148.50/1.001 MHz */
+   { 148500, {  6144, 148500 } }, /* 148.50   MHz */
+   { 296703, {  5824, 281250 } }, /* 297/1.001MHz */
+   { 297000, {  5120, 247500 } }, /* 297  MHz */
+   }
+};
+
+/**
+ * hdmi_compute_n_cts() - compute N and CTS parameters
+ * @audio_clk: audio frame clock frequency in KHz
+ * @pixel_clk: pixel cloack frequency in kHz
+ * @n_cts: N and CTS parameter returned to user
+ *
+ * Values computed are based on table described in HDMI specification 1.4b
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+
+int hdmi_audio_compute_n_cts(unsigned int audio_fs, unsigned long pixel_clk,
+struct hdmi_audio_n_cts *n_cts)
+{
+   int audio_freq_id, i;
+   int ratio = 1;
+   const struct hdmi_audio_acr  *acr_table;
+   const struct hdmi_audio_n_cts *predef_n_cts = NULL;
+
+   switch (audio_fs) {
+   case 32000:
+   audio_freq_id = HDMI_AUDIO_N_CTS_32KHZ;
+   n_cts->n = 4096;
+   break;
+
+   case 44100:
+   audio_freq_id = HDMI_AUDIO_N_CTS_44_1KHZ;
+   n_cts->n = 6272;
+   break;
+
+   case 48000:
+   audio_freq_id = HDMI_AUDIO_N_CTS_48KHZ;
+   n_cts->n = 6144;
+   break;
+
+   case 88200:
+   audio_freq_id = HDMI_AUDIO_N_CTS_44_1KHZ;
+   ratio = 2;
+   n_cts->n = 6272 * 2;
+   break;
+
+   case 96000:
+   a

[RFC 0/5] another generic audio hdmi codec proposal

2015-09-21 Thread Arnaud Pouliquen
I 'm working on HDMI implementation for sti platform. 
As some discussions are on going for audio on HDMI. Here is the begin of my 
work...

This patch set is a tentative to implement a generic code for the HDMI audio.
Main concept are aligned with solution proposeded for TI platform. 
 -  ASoC codec driver registered by DRM driver
 -  ASOC driver is a generic driver.
 -  compatible with simple card

 Difference is that i propose a DRM generic interface based on bridge structure.
 Advantage is that all data exchanges are done through the DRM API.

 I think also that some helper functions could been used for N and CTS 
parameters calculation,
 as suggested by Russell King in a previous mail.

 I full aware that some features (like ELD and info frame) are partially or not 
implemented in my patches. 
 This patch set is more a skeleton than a full implementation...
 I just post it to suggest a possible DRM API.

Arnaud Pouliquen (5):
  video: hdmi: add help function for N and cts
  drm: add helper functionto add audio capabilities for bridge
  ASoC: codec:  hdmi drm codec driver
  drm: sti: connect audio driver
  DT: sti: add audio HDMI dai link in audio card

 arch/arm/boot/dts/stih410.dtsi   |   4 +-
 arch/arm/boot/dts/stihxxx-b2120.dtsi |  21 +
 arch/arm/configs/multi_v7_defconfig  |   1 +
 drivers/gpu/drm/drm_bridge.c | 114 +++
 drivers/gpu/drm/sti/sti_hdmi.c   | 146 +++---
 drivers/gpu/drm/sti/sti_hdmi.h   |   3 +
 drivers/video/hdmi.c | 148 +++
 include/drm/drm_crtc.h   |  31 
 include/linux/hdmi.h |  24 ++
 include/sound/hdmi_drm.h |  16 
 sound/soc/codecs/Kconfig |   4 +
 sound/soc/codecs/Makefile|   2 +
 sound/soc/codecs/hdmi_drm.c  | 125 +
 13 files changed, 625 insertions(+), 14 deletions(-)
 create mode 100644 include/sound/hdmi_drm.h
 create mode 100644 sound/soc/codecs/hdmi_drm.c

-- 
1.9.1