[bootlin/training-materials updates] master: audio: checkpoint (e480fd16)

Alexandre Belloni alexandre.belloni at bootlin.com
Wed Apr 26 02:17:44 CEST 2023


Repository : https://github.com/bootlin/training-materials
On branch  : master
Link       : https://github.com/bootlin/training-materials/commit/e480fd166b31a977d8fd44df9325d1c50b806c17

>---------------------------------------------------------------

commit e480fd166b31a977d8fd44df9325d1c50b806c17
Author: Alexandre Belloni <alexandre.belloni at bootlin.com>
Date:   Wed Apr 26 02:17:44 2023 +0200

    audio: checkpoint
    
    Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>


>---------------------------------------------------------------

e480fd166b31a977d8fd44df9325d1c50b806c17
 common/audio-title.tex                             |   2 +-
 mk/audio.mk                                        |   3 +
 slides/audio-alsa-lib/audio-alsa-lib.tex           | 344 +++++++++++++++++++++
 slides/audio-alsa-utils/audio-alsa-utils.tex       | 344 +++++++++++++++++++++
 slides/audio-asoc-codec/audio-asoc-codec.tex       |   2 +-
 .../audio-asoc-component-callbacks.tex             |  14 +-
 slides/audio-asoc-cpu/audio-asoc-cpu.tex           |  92 ++++++
 7 files changed, 792 insertions(+), 9 deletions(-)

diff --git a/common/audio-title.tex b/common/audio-title.tex
index f4686abf..1a942d7c 100644
--- a/common/audio-title.tex
+++ b/common/audio-title.tex
@@ -1,2 +1,2 @@
 \def \trainingurl{https://bootlin.com/training/graphics}
-\def \trainingtitle{Audio with embedded Linux training}
+\def \trainingtitle{Audio with embedded Linux}
diff --git a/mk/audio.mk b/mk/audio.mk
index 051cb6bc..b238b303 100644
--- a/mk/audio.mk
+++ b/mk/audio.mk
@@ -11,5 +11,8 @@ AUDIO_SLIDES = \
 	audio-asoc-component-callbacks \
 	audio-auxiliary \
 	audio-asoc-DAPM \
+	audio-asoc-cpu \
+	audio-alsa-lib \
+	audio-alsa-utils \
 	audio-debugging \
 	last-slides
diff --git a/slides/audio-alsa-lib/audio-alsa-lib.tex b/slides/audio-alsa-lib/audio-alsa-lib.tex
new file mode 100644
index 00000000..1985e768
--- /dev/null
+++ b/slides/audio-alsa-lib/audio-alsa-lib.tex
@@ -0,0 +1,344 @@
+\section{Userspace ALSA}
+
+\subsection{alsa-lib}
+
+\begin{frame}{alsa-lib}
+  \begin{itemize}
+  \item The main way to interact with ALSA devices is to use alsa-lib.
+  \item \url{https://github.com/alsa-project/alsa-lib.git}
+  \item It provides mainly access to the devices but also goes further
+    and allows handling audio in userspace
+  \item The library itself is actually named \code{libasound}
+  \item The include file is \code{alsa/asoundlib.h}
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API}
+  \begin{itemize}
+  \item 
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_open(snd_pcm_t ** pcmp, const char * name, snd_pcm_stream_t stream, int mode)
+      \end{minted}
+    \end{block}
+  \item \code{name} is the name of the PCM to be opened.
+  \item \code{stream} can be either \code{SND_PCM_STREAM_PLAYBACK} or
+    \code{SND_PCM_STREAM_CAPTURE}
+  \item \code{mode} can be a combination of \code{SND_PCM_NONBLOCK}
+    and \code{SND_PCM_ASYNC}
+  \item 
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_close(snd_pcm_t *pcm)
+      \end{minted}
+    \end{block}
+  \item Closes the PCM.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}{PCM name}
+  \begin{itemize}
+  \item This can be specified as a hardware device. The three
+    arguments (in order: CARD,DEV,SUBDEV) specify card number or
+    identifier, device number and subdevice number (-1 means any). For
+    example: \code{hw:0} or \code{hw:1,0}
+  \item Or through the \code{plug} plugin: \code{plug:mypcmdef},
+    \code{plug:hw:0,0}
+  \item The list of available names can be generated using
+    \code{snd_card_next} to iterate over all the physical cards. See
+    \code{device_list} in \code{aplay}.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - PCM}
+  \begin{itemize}
+  \item The next step is to handle the PCM stream parameters
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+snd_pcm_hw_params_t *hw_params;
+int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t ** ptr)
+int snd_pcm_hw_params_any(snd_pcm_t * pcm, snd_pcm_hw_params_t * params)
+      \end{minted}
+      \end{block}
+    \item This will allocate a \code{snd_pcm_hw_params_t} and fill it
+      with the range of parameters supported by \code{pcm}.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                 snd_pcm_access_t _access)
+      \end{minted}
+    \end{block}
+    \item This set the proper access type: interleaved or
+      non-interleaved, mmap or not.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                 snd_pcm_format_t val)
+      \end{minted}
+    \end{block}
+    \item This set the format, using a \code{SND_PCM_FORMAT_} macro.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - PCM}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_channels(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                   unsigned int val)
+      \end{minted}
+    \end{block}
+    \item Sets the number of channels.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_rate_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                    unsigned int *val, int *dir)
+      \end{minted}
+    \end{block}
+    \item Sets the sample rate, setting \code{dir} to 0 will require
+      the exact rate.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_periods(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                  unsigned int val, int dir)
+int snd_pcm_hw_params_set_period_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                      snd_pcm_uframes_t val, int dir)
+int snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                      snd_pcm_uframes_t val)
+      \end{minted}
+    \end{block}
+  \item Sets the number of periods and the period size in the
+      buffer or the buffer size.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - PCM}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params(snd_pcm_t * pcm, snd_pcm_hw_params_t * params)
+       \end{minted}
+    \end{block}
+  \item Installs the parameters and calls \code{snd_pcm_prepare} on
+    the stream.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_pcm_hw_params_free(snd_pcm_hw_params_t * obj)
+      \end{minted}
+    \end{block}
+  \item Frees the allocated \code{snd_pcm_hw_params_t}.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_prepare(snd_pcm_t * pcm)
+      \end{minted}
+    \end{block}
+  \item Prepares the stream.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_wait(snd_pcm_t * pcm, int timeout)
+      \end{minted}
+    \end{block}
+  \item Waits for the PCM to be ready.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - PCM}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+      \end{minted}
+    \end{block}
+  \item Write or read from an interleaved or non-interleaved buffer.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
+                       snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
+snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset,
+                                      snd_pcm_uframes_t frames)
+snd_pcm_sframes_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer,
+                                      snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+      \end{minted}
+    \end{block}
+  \item Write or read from an interleaved or non-interleaved mmap buffer.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - controls}
+  \begin{itemize}
+  \item It is possible to set controls programatically.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+snd_ctl_t *handle;
+int snd_ctl_open (snd_ctl_t **ctl, const char *name, int mode)
+      \end{minted}
+    \end{block}
+    \item Opens the sound card to be controlled.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+snd_ctl_elem_id_t *id;
+#define snd_ctl_elem_id_alloca(ptr)
+snd_ctl_elem_value_t *value;
+#define snd_ctl_elem_value_alloca(ptr)
+      \end{minted}
+    \end{block}
+  \item Allocate a \code{snd_ctl_elem_id_t}, referring to a particular
+    control and a \code{snd_ctl_elem_value_t} to be set for this
+    control.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_id_set_interface(snd_ctl_elem_id_t *obj, snd_ctl_elem_iface_t val)
+void snd_ctl_elem_id_set_name(snd_ctl_elem_id_t *obj, const char *val)
+      \end{minted}
+    \end{block}
+    \item Set the interface and name of the control to be set.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - controls}
+  \begin{itemize}
+  \item A lookup is needed to fill the \code{snd_ctl_elem_id_t}
+    completely
+  \end{itemize}
+  \begin{block}{}
+    \fontsize{9}{9}\selectfont
+    \begin{minted}{c}
+int lookup_id(snd_ctl_elem_id_t *id, snd_ctl_t *handle)
+{
+    int err;
+    snd_ctl_elem_info_t *info;
+    snd_ctl_elem_info_alloca(&info);
+
+    snd_ctl_elem_info_set_id(info, id);
+    if ((err = snd_ctl_elem_info(handle, info)) < 0) {
+        return err;
+    }
+    snd_ctl_elem_info_get_id(info, id);
+
+    return 0;
+}
+    \end{minted}
+  \end{block}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - controls}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_value_set_id(snd_ctl_elem_value_t *obj, const snd_ctl_elem_id_t *ptr)
+      \end{minted}
+    \end{block}
+    \item Links the value with the control id.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_value_set_boolean(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_value_set_integer(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_value_set_integer64(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                      long long val)
+void snd_ctl_elem_value_set_enumerated(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                       unsigned int val)
+void snd_ctl_elem_value_set_byte(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                 unsigned char val)
+void snd_ctl_elem_set_bytes(snd_ctl_elem_value_t *obj, void *data, size_t size)
+      \end{minted}
+    \end{block}
+  \item Set the value in \code{snd_ctl_elem_value_t}.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_ctl_elem_write(snd_ctl_t *ctl, snd_ctl_elem_value_t *data)
+      \end{minted}
+    \end{block}
+  \item Actually set the control.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - controls}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_value_set_id(snd_ctl_elem_value_t *obj, const snd_ctl_elem_id_t *ptr)
+      \end{minted}
+    \end{block}
+    \item Links the value with the control id.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_value_set_boolean(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_value_set_integer(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_value_set_integer64(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                      long long val)
+void snd_ctl_elem_value_set_enumerated(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                       unsigned int val)
+void snd_ctl_elem_value_set_byte(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                 unsigned char val)
+void snd_ctl_elem_set_bytes(snd_ctl_elem_value_t *obj, void *data, size_t size)
+      \end{minted}
+    \end{block}
+  \item Set the value in \code{snd_ctl_elem_value_t}.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_ctl_elem_write(snd_ctl_t *ctl, snd_ctl_elem_value_t *data)
+      \end{minted}
+    \end{block}
+  \item Actually set the control.
+  \end{itemize}
+\end{frame}
+
+
+\begin{frame}{Going further}
+  \begin{itemize}
+  \item UCM: The ALSA Use Case Configuration:
+    \url{https://www.alsa-project.org/alsa-doc/alsa-lib/group__ucm__conf.html}
+  \item ALSA topology:
+    \url{https://www.alsa-project.org/wiki/ALSA_topology}
+  \end{itemize}
+\end{frame}
diff --git a/slides/audio-alsa-utils/audio-alsa-utils.tex b/slides/audio-alsa-utils/audio-alsa-utils.tex
new file mode 100644
index 00000000..1985e768
--- /dev/null
+++ b/slides/audio-alsa-utils/audio-alsa-utils.tex
@@ -0,0 +1,344 @@
+\section{Userspace ALSA}
+
+\subsection{alsa-lib}
+
+\begin{frame}{alsa-lib}
+  \begin{itemize}
+  \item The main way to interact with ALSA devices is to use alsa-lib.
+  \item \url{https://github.com/alsa-project/alsa-lib.git}
+  \item It provides mainly access to the devices but also goes further
+    and allows handling audio in userspace
+  \item The library itself is actually named \code{libasound}
+  \item The include file is \code{alsa/asoundlib.h}
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API}
+  \begin{itemize}
+  \item 
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_open(snd_pcm_t ** pcmp, const char * name, snd_pcm_stream_t stream, int mode)
+      \end{minted}
+    \end{block}
+  \item \code{name} is the name of the PCM to be opened.
+  \item \code{stream} can be either \code{SND_PCM_STREAM_PLAYBACK} or
+    \code{SND_PCM_STREAM_CAPTURE}
+  \item \code{mode} can be a combination of \code{SND_PCM_NONBLOCK}
+    and \code{SND_PCM_ASYNC}
+  \item 
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_close(snd_pcm_t *pcm)
+      \end{minted}
+    \end{block}
+  \item Closes the PCM.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}{PCM name}
+  \begin{itemize}
+  \item This can be specified as a hardware device. The three
+    arguments (in order: CARD,DEV,SUBDEV) specify card number or
+    identifier, device number and subdevice number (-1 means any). For
+    example: \code{hw:0} or \code{hw:1,0}
+  \item Or through the \code{plug} plugin: \code{plug:mypcmdef},
+    \code{plug:hw:0,0}
+  \item The list of available names can be generated using
+    \code{snd_card_next} to iterate over all the physical cards. See
+    \code{device_list} in \code{aplay}.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - PCM}
+  \begin{itemize}
+  \item The next step is to handle the PCM stream parameters
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+snd_pcm_hw_params_t *hw_params;
+int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t ** ptr)
+int snd_pcm_hw_params_any(snd_pcm_t * pcm, snd_pcm_hw_params_t * params)
+      \end{minted}
+      \end{block}
+    \item This will allocate a \code{snd_pcm_hw_params_t} and fill it
+      with the range of parameters supported by \code{pcm}.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                 snd_pcm_access_t _access)
+      \end{minted}
+    \end{block}
+    \item This set the proper access type: interleaved or
+      non-interleaved, mmap or not.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                 snd_pcm_format_t val)
+      \end{minted}
+    \end{block}
+    \item This set the format, using a \code{SND_PCM_FORMAT_} macro.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - PCM}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_channels(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                   unsigned int val)
+      \end{minted}
+    \end{block}
+    \item Sets the number of channels.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_rate_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                    unsigned int *val, int *dir)
+      \end{minted}
+    \end{block}
+    \item Sets the sample rate, setting \code{dir} to 0 will require
+      the exact rate.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params_set_periods(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                  unsigned int val, int dir)
+int snd_pcm_hw_params_set_period_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                      snd_pcm_uframes_t val, int dir)
+int snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+                                      snd_pcm_uframes_t val)
+      \end{minted}
+    \end{block}
+  \item Sets the number of periods and the period size in the
+      buffer or the buffer size.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - PCM}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_hw_params(snd_pcm_t * pcm, snd_pcm_hw_params_t * params)
+       \end{minted}
+    \end{block}
+  \item Installs the parameters and calls \code{snd_pcm_prepare} on
+    the stream.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_pcm_hw_params_free(snd_pcm_hw_params_t * obj)
+      \end{minted}
+    \end{block}
+  \item Frees the allocated \code{snd_pcm_hw_params_t}.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_prepare(snd_pcm_t * pcm)
+      \end{minted}
+    \end{block}
+  \item Prepares the stream.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_wait(snd_pcm_t * pcm, int timeout)
+      \end{minted}
+    \end{block}
+  \item Waits for the PCM to be ready.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - PCM}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+      \end{minted}
+    \end{block}
+  \item Write or read from an interleaved or non-interleaved buffer.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
+                       snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
+snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset,
+                                      snd_pcm_uframes_t frames)
+snd_pcm_sframes_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer,
+                                      snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+      \end{minted}
+    \end{block}
+  \item Write or read from an interleaved or non-interleaved mmap buffer.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - controls}
+  \begin{itemize}
+  \item It is possible to set controls programatically.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+snd_ctl_t *handle;
+int snd_ctl_open (snd_ctl_t **ctl, const char *name, int mode)
+      \end{minted}
+    \end{block}
+    \item Opens the sound card to be controlled.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+snd_ctl_elem_id_t *id;
+#define snd_ctl_elem_id_alloca(ptr)
+snd_ctl_elem_value_t *value;
+#define snd_ctl_elem_value_alloca(ptr)
+      \end{minted}
+    \end{block}
+  \item Allocate a \code{snd_ctl_elem_id_t}, referring to a particular
+    control and a \code{snd_ctl_elem_value_t} to be set for this
+    control.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_id_set_interface(snd_ctl_elem_id_t *obj, snd_ctl_elem_iface_t val)
+void snd_ctl_elem_id_set_name(snd_ctl_elem_id_t *obj, const char *val)
+      \end{minted}
+    \end{block}
+    \item Set the interface and name of the control to be set.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - controls}
+  \begin{itemize}
+  \item A lookup is needed to fill the \code{snd_ctl_elem_id_t}
+    completely
+  \end{itemize}
+  \begin{block}{}
+    \fontsize{9}{9}\selectfont
+    \begin{minted}{c}
+int lookup_id(snd_ctl_elem_id_t *id, snd_ctl_t *handle)
+{
+    int err;
+    snd_ctl_elem_info_t *info;
+    snd_ctl_elem_info_alloca(&info);
+
+    snd_ctl_elem_info_set_id(info, id);
+    if ((err = snd_ctl_elem_info(handle, info)) < 0) {
+        return err;
+    }
+    snd_ctl_elem_info_get_id(info, id);
+
+    return 0;
+}
+    \end{minted}
+  \end{block}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - controls}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_value_set_id(snd_ctl_elem_value_t *obj, const snd_ctl_elem_id_t *ptr)
+      \end{minted}
+    \end{block}
+    \item Links the value with the control id.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_value_set_boolean(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_value_set_integer(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_value_set_integer64(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                      long long val)
+void snd_ctl_elem_value_set_enumerated(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                       unsigned int val)
+void snd_ctl_elem_value_set_byte(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                 unsigned char val)
+void snd_ctl_elem_set_bytes(snd_ctl_elem_value_t *obj, void *data, size_t size)
+      \end{minted}
+    \end{block}
+  \item Set the value in \code{snd_ctl_elem_value_t}.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_ctl_elem_write(snd_ctl_t *ctl, snd_ctl_elem_value_t *data)
+      \end{minted}
+    \end{block}
+  \item Actually set the control.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{alsa-lib API - controls}
+  \begin{itemize}
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_value_set_id(snd_ctl_elem_value_t *obj, const snd_ctl_elem_id_t *ptr)
+      \end{minted}
+    \end{block}
+    \item Links the value with the control id.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+void snd_ctl_elem_value_set_boolean(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_value_set_integer(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_value_set_integer64(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                      long long val)
+void snd_ctl_elem_value_set_enumerated(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                       unsigned int val)
+void snd_ctl_elem_value_set_byte(snd_ctl_elem_value_t *obj, unsigned int idx,
+                                 unsigned char val)
+void snd_ctl_elem_set_bytes(snd_ctl_elem_value_t *obj, void *data, size_t size)
+      \end{minted}
+    \end{block}
+  \item Set the value in \code{snd_ctl_elem_value_t}.
+  \item
+    \begin{block}{}
+    \fontsize{9}{9}\selectfont
+      \begin{minted}{c}
+int snd_ctl_elem_write(snd_ctl_t *ctl, snd_ctl_elem_value_t *data)
+      \end{minted}
+    \end{block}
+  \item Actually set the control.
+  \end{itemize}
+\end{frame}
+
+
+\begin{frame}{Going further}
+  \begin{itemize}
+  \item UCM: The ALSA Use Case Configuration:
+    \url{https://www.alsa-project.org/alsa-doc/alsa-lib/group__ucm__conf.html}
+  \item ALSA topology:
+    \url{https://www.alsa-project.org/wiki/ALSA_topology}
+  \end{itemize}
+\end{frame}
diff --git a/slides/audio-asoc-codec/audio-asoc-codec.tex b/slides/audio-asoc-codec/audio-asoc-codec.tex
index fddefa94..7d04976a 100644
--- a/slides/audio-asoc-codec/audio-asoc-codec.tex
+++ b/slides/audio-asoc-codec/audio-asoc-codec.tex
@@ -86,7 +86,7 @@ struct snd_soc_component_driver {
     When called, all the parameters of the stream are known so it is
     possible to configure the component to handle the stream
     correctly.
-  \item Those are mostyl not used, the DAI specific callbacks are used
+  \item Those are mostly not used, the DAI specific callbacks are used
     instead.
   \end{itemize}
 \end{frame}
diff --git a/slides/audio-asoc-component-callbacks/audio-asoc-component-callbacks.tex b/slides/audio-asoc-component-callbacks/audio-asoc-component-callbacks.tex
index 51dc3f07..061c8dd2 100644
--- a/slides/audio-asoc-component-callbacks/audio-asoc-component-callbacks.tex
+++ b/slides/audio-asoc-component-callbacks/audio-asoc-component-callbacks.tex
@@ -226,10 +226,10 @@ static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
     \end{itemize}
   \item Also the polarity can be changed:
     \begin{itemize}
-    \item \ksym{SND_SOC_DAIFMT_NB_NF}: normal bit clock + frame
+    \item \ksym{SND_SOC_DAIFMT_NB_NF}: normal bit clock + normal frame
     \item \ksym{SND_SOC_DAIFMT_NB_IF}: normal bit clock + invert frame
     \item \ksym{SND_SOC_DAIFMT_IB_NF}: invert bit clock + normal frame
-    \item \ksym{SND_SOC_DAIFMT_IB_IF}: invert bit clock + frame
+    \item \ksym{SND_SOC_DAIFMT_IB_IF}: invert bit clock + invert frame
     \end{itemize}
   \end{itemize}
 \end{frame}
@@ -248,10 +248,10 @@ static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
     \fontsize{9}{9}\selectfont
     \begin{minted}{c}
 /* previous definitions kept for backwards-compatibility, do not use in new contributions */
-#define SND_SOC_DAIFMT_CBM_CFM		SND_SOC_DAIFMT_CBP_CFP
-#define SND_SOC_DAIFMT_CBS_CFM		SND_SOC_DAIFMT_CBC_CFP
-#define SND_SOC_DAIFMT_CBM_CFS		SND_SOC_DAIFMT_CBP_CFC
-#define SND_SOC_DAIFMT_CBS_CFS		SND_SOC_DAIFMT_CBC_CFC
+#define SND_SOC_DAIFMT_CBM_CFM                SND_SOC_DAIFMT_CBP_CFP
+#define SND_SOC_DAIFMT_CBS_CFM                SND_SOC_DAIFMT_CBC_CFP
+#define SND_SOC_DAIFMT_CBM_CFS                SND_SOC_DAIFMT_CBP_CFC
+#define SND_SOC_DAIFMT_CBS_CFS                SND_SOC_DAIFMT_CBC_CFC
     \end{minted}
   \end{block}
   \end{itemize}
@@ -299,7 +299,7 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
   \begin{itemize}
   \item This callback configures the DAI for TDM operation.
   \item \code{slot} is the total number of slots of the TDM stream and
-    \code{slot_with} the width of each slot in bit clock cycles.
+    \code{slot_width} the width of each slot in bit clock cycles.
   \item \code{tx_mask} and \code{rx_mask} are bitmasks specifying the
     active slots of the TDM stream for the specified DAI, i.e. which slots the
     DAI should write to or read from. A set bit means the channel is
diff --git a/slides/audio-asoc-cpu/audio-asoc-cpu.tex b/slides/audio-asoc-cpu/audio-asoc-cpu.tex
new file mode 100644
index 00000000..81cdbd0d
--- /dev/null
+++ b/slides/audio-asoc-cpu/audio-asoc-cpu.tex
@@ -0,0 +1,92 @@
+\subsection{CPU DAI driver}
+
+\begin{frame}{CPU DAI driver}
+  \begin{itemize}
+  \item The CPU DAI driver is now a component driver, like the codec
+    ones.
+  \item However, it is usually more complex as it need to handle IRQs
+    and take care of pinmuxing, clocks and DMA.
+  \item Also, the list of supported format and rates is usually very
+    large.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}{DMA handling}
+  \begin{itemize}
+  \item When a DMA controller is available, handling DMA in ALSA is
+    done almost completely in the core, through \code{dmaengine_pcm}.
+  \item The DMA is simply registered using
+    \kfunc{devm_snd_dmaengine_pcm_register}. This handles parsing the
+    device tree if necessary.
+  \item In the DAI driver probe callback, the DMA engine is simply
+    configured using \kfunc{snd_soc_dai_init_dma_data} which takes the
+    DMA configuration for playback and capture.
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{DMA handling example}
+  \begin{block}{\code{sound/soc/atmel/atmel-i2s.c}}
+    \fontsize{8}{7}\selectfont
+    \begin{minted}{c}
+struct atmel_i2s_dev {
+        struct device                           *dev;
+        struct regmap                           *regmap;
+        struct clk                              *pclk;
+        struct clk                              *gclk;
+        struct snd_dmaengine_dai_dma_data       playback;
+        struct snd_dmaengine_dai_dma_data       capture;
+        unsigned int                            fmt;
+        const struct atmel_i2s_gck_param        *gck_param;
+        const struct atmel_i2s_caps             *caps;
+        int                                     clk_use_no;
+};
+[...]
+static int atmel_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+        struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+        snd_soc_dai_init_dma_data(dai, &dev->playback, &dev->capture);
+        return 0;
+}
+    \end{minted}
+  \end{block}
+\end{frame}
+
+\begin{frame}[fragile]{DMA handling example}
+  \begin{block}{\code{sound/soc/atmel/atmel-i2s.c}}
+    \fontsize{8}{8}\selectfont
+    \begin{minted}{c}
+static int atmel_i2s_probe(struct platform_device *pdev)
+{
+[...]
+        /* Prepare DMA config. */
+        dev->playback.addr        = (dma_addr_t)mem->start + ATMEL_I2SC_THR;
+        dev->playback.maxburst        = 1;
+        dev->capture.addr        = (dma_addr_t)mem->start + ATMEL_I2SC_RHR;
+        dev->capture.maxburst        = 1;
+
+        if (of_property_match_string(np, "dma-names", "rx-tx") == 0)
+                pcm_flags |= SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX;
+        err = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, pcm_flags);
+        if (err) {
+                dev_err(&pdev->dev, "failed to register PCM: %d\n", err);
+                clk_disable_unprepare(dev->pclk);
+                return err;
+        }
+[...]
+}
+    \end{minted}
+  \end{block}
+\end{frame}
+
+\begin{frame}{DMA handling}
+  \begin{itemize}
+  \item When a peripheral DMA controller is used, this is more
+    complex.
+  \item The driver will have to handle all th aspects of the PCM
+    stream life cycle
+  \item Understandable example in \kfile{sound/soc/atmel/atmel-pcm-pdc.c}
+  \end{itemize}
+\end{frame}
+
+




More information about the training-materials-updates mailing list