All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/5] compress: add compress data API to ALSA kernel
@ 2011-09-02  6:06 Vinod Koul
  2011-09-02  6:06 ` [RFC 1/5] compress API documentation Vinod Koul
                   ` (12 more replies)
  0 siblings, 13 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-02  6:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg

As agreed during the ASoC workshop in May 2011, this set of patches are a
proposal from Intel to add a new compressed data interface to ALSA. This
proposal builds on the existing Intel solution and the experience gathered over
two years with Meego and Android solutions. This proposal is no longer
Intel-specific and was generalized with the addition of a basic core;
codec-related definitions are based on the vendor-neutral OpenMAX AL standard. 
The code as is isn't functional and will need low-level hardware-specific
drivers and a tighter integration with ALSA and ASoC. The main ideas will be
presented during the Linux Plumbers Conference on September 9. Feedback through
the mailing list would be greatly appreciated as well.
Future versions will include support for capture, mmap, integration with alsa,
asoc, dsp etc
Support for effects is beyond the scope of this interface.

Vinod Koul (5):
  compress API documentation
  compress: add compress parameter definations
  compress: add API header and driver header files
  compress: add the core file
  compress: add makefile and kconfig file

 .../sound/alsa/compress/snd_compress_data.txt      |  186 ++++++
 include/sound/compress_driver.h                    |  138 +++++
 include/sound/compress_offload.h                   |  137 +++++
 include/sound/snd_compress_params.h                |  396 ++++++++++++
 sound/Kconfig                                      |    2 +
 sound/Makefile                                     |    3 +-
 sound/compress_offload/Kconfig                     |   12 +
 sound/compress_offload/Makefile                    |    3 +
 sound/compress_offload/core.c                      |  632 ++++++++++++++++++++
 9 files changed, 1508 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/sound/alsa/compress/snd_compress_data.txt
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h
 create mode 100644 include/sound/snd_compress_params.h
 create mode 100644 sound/compress_offload/Kconfig
 create mode 100644 sound/compress_offload/Makefile
 create mode 100644 sound/compress_offload/core.c

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [RFC 1/5] compress API documentation
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
@ 2011-09-02  6:06 ` Vinod Koul
  2011-09-02  6:06 ` [RFC 2/5] compress: add compress parameter definations Vinod Koul
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-02  6:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

The patch adds the documentation file explaining the API

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 .../sound/alsa/compress/snd_compress_data.txt      |  186 ++++++++++++++++++++
 1 files changed, 186 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/sound/alsa/compress/snd_compress_data.txt

diff --git a/Documentation/sound/alsa/compress/snd_compress_data.txt b/Documentation/sound/alsa/compress/snd_compress_data.txt
new file mode 100644
index 0000000..a8e6762
--- /dev/null
+++ b/Documentation/sound/alsa/compress/snd_compress_data.txt
@@ -0,0 +1,186 @@
+		snd_compress_data.txt
+		=====================
+	Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+		Vinod Koul <vinod.koul@linux.intel.com>
+
+Overview
+
+Since its early days, the ALSA API was defined with PCM support or
+constant bitrates payloads such as IEC61937 in mind. Arguments and
+returned values in frames are the norm, making it a challenge to
+extend the existing API to compressed data streams.
+
+In recent years, audio digital signal processors (DSP) were integrated
+in system-on-chip designs, and DSPs are also integrated in audio
+codecs. Processing compressed data on such DSPs results in a dramatic
+reduction of power consumption compared to host-based
+processing. Support for such hardware has not been very good in Linux,
+mostly because of a lack of a generic API available in the mainline
+kernel.
+
+Rather than requiring a compability break with an API change of the
+ALSA PCM interface, a new 'Compressed Data' API is introduced to
+provide a control and data-streaming interface for audio DSPs.
+
+The design of this API was inspired by the 2-year experience with the
+Intel Moorestown SOC, with many corrections required to upstream the
+API in the mainline kernel instead of the staging tree and make it
+usable by others.
+
+Requirements
+
+The main requirements are:
+
+- separation between byte counts and time. Compressed formats may have
+  a header per file, per frame, or no header at all. The payload size
+  may vary from frame-to-frame. As a result, it is not possible to
+  estimate reliably the duration of audio buffers when handling
+  compressed data. Dedicated mechanisms are required to allow for
+  reliable audio-video synchronization, which requires precise
+  reporting of the number of samples rendered at any given time.
+
+- Handling of multiple formats. PCM data only requires a specification
+  of the sampling rate, number of channels and bits per sample. In
+  contrast, compressed data comes in a variety of formats. Audio DSPs
+  may also provide support for a limited number of audio encoders and
+  decoders embedded in firmware, or may support more choices through
+  dynamic download of libraries.
+
+- Focus on main formats. This API provides support for the most
+  popular formats used for audio and video capture and playback. It is
+  likely that as audio compression technology advances, new formats
+  will be added.
+
+- Handling of multiple configurations. Even for a given format like
+  AAC, some implementations may support AAC multichannel but HE-AAC
+  stereo. Likewise WMA10 level M3 may require too much memory and cpu
+  cycles. The new API needs to provide a generic way of listing these
+  formats.
+
+- Rendering/Grabbing only. This API does not provide any means of
+  hardware acceleration, where PCM samples are provided back to
+  user-space for additional processing. This API focuses instead on
+  streaming compressed data to a DSP, with the assumption that the
+  decoded samples are routed to a physical output or logical back-end.
+
+ - Complexity hiding. Existing user-space multimedia frameworks all
+  have existing enums/structures for each compressed format. This new
+  API assumes the existence of a platform-specific compatibility layer
+  to expose, translate and make use of the capabilities of the audio
+  DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
+  applications are not supposed to make use of this API.
+
+
+Design
+
+The new API shares a number of concepts with with the PCM API for flow
+control. Start, pause, resume, drain and stop commands have the same
+semantics no matter what the content is.
+
+The concept of memory ring buffer divided in a set of fragments is
+borrowed from the ALSA PCM API. However, only sizes in bytes can be
+specified.
+
+Seeks/trick modes are assumed to be handled by the host.
+
+The notion of rewinds/forwards is not supported. Data committed to the
+ring buffer cannot be invalidated, except when dropping all buffers.
+
+The Compressed Data API does not make any assumptions on how the data
+is transmitted to the audio DSP. DMA transfers from main memory to an
+embedded audio cluster or to a SPI interface for external DSPs are
+possible. As in the ALSA PCM case, a core set of routines is exposed;
+each driver implementer will have to write support for a set of
+mandatory routines and possibly make use of optional ones.
+
+The main additions are
+
+- get_codecs
+This routine returns the list of audio formats supported. Querying the
+codecs on a capture stream will return encoders, decoders will be
+listed for playback streams.
+
+- get_codec_caps
+For each codec, this routine returns a list of capabilities. The
+intent is to make sure all the capabilities correspond to valid
+settings, and to minimize the risks of configuration failures. For
+example, for a complex codec such as AAC, the number of channels
+supported may depend on a specific profile. If the capabilities were
+exposed with a single descriptor, it may happen that a specific
+combination of profiles/channels/formats may not be
+supported. Likewise, embedded DSPs have limited memory and cpu cycles,
+it is likely that some implementations make the list of capabilities
+dynamic and dependent on existing workloads.
+
+- set_params
+This routine sets the configuration chosen for a specific codec. The
+most important field in the parameters is the codec type; in most
+cases decoders will ignore other fields, while encoders will strictly
+comply to the settings
+
+- get_params
+This routines returns the actual settings used by the DSP. Changes to
+the settings should remain the exception.
+
+- get_timestamp
+The timestamp becomes a multiple field structure. It lists the number
+of bytes transferred, the number of samples processed and the number
+of samples rendered/grabbed. All these values can be used to determine
+the avarage bitrate, figure out if the ring buffer needs to be
+refilled or the delay due to decoding/encoding/io on the DSP.
+
+Note that the list of codecs/profiles/modes was derived from the
+OpenMAX AL specification instead of reinventing the wheel.
+Modifications include:
+- Addition of FLAC and IEC formats
+- Merge of encoder/decoder capabilities
+- Profiles/modes listed as bitmasks to make descriptors more compact
+- Addition of set_params for decoders (missing in OpenMAX AL)
+- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
+- Addition of format information for WMA
+- Addition of encoding options when required (derived from OpenMAX IL)
+- Addition of rateControlSupported (missing in OpenMAX AL)
+
+Not supported:
+
+- Support for VoIP/circuit-switched calls is not the target of this
+  API. Support for dynamic bit-rate changes would require a tight
+  coupling between the DSP and the host stack, limiting power savings.
+
+- Packet-loss concealment is not supported. This would require an
+  additional interface to let the decoder synthesize data when frames
+  are lost during transmission. This may be added in the future.
+
+- Volume control/routing is not handled by this API. Devices exposing a
+  compressed data interface will be considered as regular ALSA devices
+
+Instead,
+  offloaded processing will be considered as regular ALSA devices;
+  volume changes and routing information will be provided with regular
+  ALSA kcontrols.
+
+- Embedded audio effects. Such effects should be enabled in the same
+  manner, no matter if the input was PCM or compressed.
+
+- multichannel IEC encoding. Unclear if this is required.
+
+- Encoding/decoding acceleration is not supported as mentioned
+  above. It is possible to route the output of a decoder to a capture
+  stream, or even implement transcoding capabilities. This routing
+  would be enabled with ALSA kcontrols.
+
+- Audio policy/resource management. This API does not provide any
+  hooks to query the utilization of the audio DSP, nor any premption
+  mechanisms.
+
+- No notion of underun/overrun. Since the bytes written are compressed
+  in nature and data written/read doesn't translate directly to
+  rendered output in time, this does not deal with underrun/overun and
+  maybe dealt in user-library
+
+Credits:
+- Mark Brown and Liam Girdwood for discussions on the need for this API
+- Rakesh Ughreja for valuable feedback
+- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
+  demonstrating and quantifying the benefits of audio offload on a
+  real platform.
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [RFC 2/5] compress: add compress parameter definations
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
  2011-09-02  6:06 ` [RFC 1/5] compress API documentation Vinod Koul
@ 2011-09-02  6:06 ` Vinod Koul
  2011-09-02  6:49   ` Paul Menzel
  2011-09-02 14:19   ` Mark Brown
  2011-09-02  6:06 ` [RFC 3/5] compress: add API header and driver header files Vinod Koul
                   ` (10 subsequent siblings)
  12 siblings, 2 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-02  6:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

The patch adds the various definations used to define the encoder and decoder
parameters

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 include/sound/snd_compress_params.h |  396 +++++++++++++++++++++++++++++++++++
 1 files changed, 396 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/snd_compress_params.h

diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
new file mode 100644
index 0000000..7203e5f
--- /dev/null
+++ b/include/sound/snd_compress_params.h
@@ -0,0 +1,396 @@
+/*
+ *  snd_compress_params.h - codec types and parameters for compressed data
+ *  streaming interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+ *              Vinod Koul <vinod.koul@linux.intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The definitions in this file are derived from the OpenMAX AL version 1.1
+ * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
+ *
+ * Copyright (c) 2007-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and/or associated documentation files (the
+ * "Materials "), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+
+
+/* AUDIO CODECS SUPPORTED */
+#define MAX_NUM_CODECS 32
+#define MAX_NUM_CODEC_DESCRIPTORS 32
+#define MAX_NUM_RATES 32
+#define MAX_NUM_BITRATES 32
+
+/* Codecs are listed linearly to allow for extensibility */
+#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
+#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
+#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
+#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
+#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
+#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
+#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
+#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
+#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
+#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
+#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
+
+/*
+ * Profile and modes are listed with bit masks. This allows for a
+ * more compact representation of fields that will not evolve
+ * (in contrast to the list of codecs)
+ */
+
+#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
+
+/* MP3 modes are only useful for encoders */
+#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
+#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
+#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
+#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
+
+/* AMR modes are only useful for encoders */
+#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
+
+#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
+#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
+
+#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
+
+/* AMRWB modes are only useful for encoders */
+#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
+
+/* AAC modes are required for encoders and decoders */
+#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
+#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
+#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
+#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
+#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
+#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
+#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
+
+/* AAC formats are required for encoders and decoders */
+#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
+#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
+
+#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
+#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
+#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
+#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
+
+#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
+#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
+#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
+#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
+#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
+#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
+#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
+
+#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
+/*
+ * Some implementations strip the ASF header and only send ASF packets
+ * to the DSP
+ */
+#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
+
+#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
+#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
+
+/*
+ * Define quality levels for FLAC encoders, from LEVEL0 (fast)
+ * to LEVEL8 (best)
+ */
+#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
+#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
+#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
+#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
+#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
+#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
+#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
+
+#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
+
+/* IEC61937 payloads without CUVP and preambles */
+#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
+/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
+#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
+
+/*
+ * IEC modes are mandatory for decoders. Format autodetection
+ *  will only happen on the DSP side with mode 0. The PCM mode should
+ *  not be used, the PCM codec should be used instead
+ */
+#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
+#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
+#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
+#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
+#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
+#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
+#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
+#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
+#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
+#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
+#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
+#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
+#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
+#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
+#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
+#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
+#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
+#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
+#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
+
+/* <FIXME: multichannel encoders aren't supported for now. Would need
+   an additional definition of channel arrangement> */
+
+/* VBR/CBR definitions */
+#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
+#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
+
+/* Encoder options */
+
+struct wmaEncoderOptions {
+	__u32 super_block_align; /* WMA Type-specific data */
+};
+
+
+/**
+ * struct vorbisEncoderOptions
+ * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
+ * In the default mode of operation, the quality level is 3.
+ * Normal quality range is 0 - 10.
+ * @managed: Boolean. Set  bitrate  management  mode. This turns off the
+ * normal VBR encoding, but allows hard or soft bitrate constraints to be
+ * enforced by the encoder. This mode can be slower, and may also be
+ * lower quality. It is primarily useful for streaming.
+ * @maxBitrate: enabled only is managed is TRUE
+ * @minBitrate: enabled only is managed is TRUE
+ * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
+ * non-stereo streams). Useful for lower-bitrate encoding.
+ *
+ * These options were extracted from the OpenMAX IL spec and gstreamer vorbisenc
+ * properties
+ *
+ * For best quality users should specify VBR mode and set quality levels.
+ */
+
+struct vorbisEncoderOptions {
+	int quality;
+	__u32 managed;
+	__u32 maxBitrate;
+	__u32 minBirate;
+	__u32 downmix;
+};
+
+
+/**
+ * struct realEncoderOptions
+ * @coupling_quant_bits: is the number of coupling quantization bits in the stream
+ * @coupling_start_region: is the coupling start region in the stream
+ * @num_regions: is the number of regions value
+ *
+ * These options were extracted from the OpenMAX IL spec
+ */
+
+struct realEncoderOptions {
+	__u32 coupling_quant_bits;
+	__u32 coupling_start_region;
+	__u32 num_regions;
+};
+
+/**
+ * struct flacEncoderOptions
+ * @serialNumber: valid only for OGG formats, needs to be set by application
+ * @replayGain: Add ReplayGain tags
+ *
+ * These options were extracted from the FLAC online documentation
+ * at http://flac.sourceforge.net/documentation_tools_flac.html
+ *
+ * To make the API simpler, it is assumed that the user will select quality
+ * profiles. Additional options that affect encoding quality and speed can
+ * be added at a later stage if need be.
+ *
+ * By default the Subset format is used by encoders.
+ *
+ * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
+ * not supported in this API.
+ */
+
+struct flacEncoderOptions {
+	__u32 serialNumber;
+	__u32 replayGain;
+};
+
+struct genericEncoderOptions {
+	__u32 encoderBandwidth;
+	int reserved[15];
+};
+
+union AudioCodecOptions {
+	struct wmaEncoderOptions wmaSpecificOptions;
+	struct vorbisEncoderOptions vorbisSpecificOptions;
+	struct realEncoderOptions realSpecificOptions;
+	struct flacEncoderOptions flacEncoderOptions;
+	struct genericEncoderOptions genericOptions;
+};
+
+/** struct SndAudioCodecDescriptor - description of codec capabilities
+ * @maxChannels: maximum number of audio channels
+ * @minBitsPerSample: Minimum bits per sample of PCM data <FIXME: needed?>
+ * @maxBitsPerSample: Maximum bits per sample of PCM data <FIXME: needed?>
+ * @minSampleRate: Minimum sampling rate supported, unit is Hz
+ * @maxSampleRate: Minimum sampling rate supported, unit is Hz
+ * @isFreqRangeContinuous: TRUE if the device supports a continuous range of
+ *                         sampling rates between minSampleRate and maxSampleRate;
+ *                         otherwise FALSE <FIXME: needed?>
+ * @SampleRatesSupported: Indexed array containing supported sampling rates in Hz
+ * @numSampleRatesSupported: Size of the pSamplesRatesSupported array
+ * @minBitRate: Minimum bitrate in bits per second
+ * @maxBitRate: Max bitrate in bits per second
+ * @isBitrateRangeContinuous: TRUE if the device supports a continuous range of
+ *		      bitrates between minBitRate and maxBitRate; otherwise FALSE
+ * @BitratesSupported: Indexed array containing supported bit rates
+ * @numBitratesSupported: Size of the pBiratesSupported array
+ * @rateControlSupported: value is specified by SND_RATECONTROLMODE defines.
+ * @profileSetting: Profile supported. See SND_AUDIOPROFILE defines.
+ * @modeSetting: Mode supported. See SND_AUDIOMODE defines
+ * @streamFormat: Format supported. See SND_AUDIOSTREAMFORMAT defines
+ * @reserved: reserved for future use
+ *
+ * This structure provides a scalar value for profile, mode and stream format fields.
+ * If an implementation supports multiple combinations, they will be listed as codecs
+ * with different IDs, for example there would be 2 decoders for AAC-RAW and AAC-ADTS.
+ * This entails some redundancy but makes it easier to avoid invalid configurations.
+ *
+ */
+
+struct SndAudioCodecDescriptor {
+	__u32 maxChannels;
+	__u32 minBitsPerSample;
+	__u32 maxBitsPerSample;
+	__u32 minSampleRate;
+	__u32 maxSampleRate;
+	__u32 isFreqRangeContinuous;
+	__u32 sampleRatesSupported[MAX_NUM_RATES];
+	__u32 numSampleRatesSupported;
+	__u32 minBitRate;
+	__u32 maxBitRate;
+	__u32 isBitrateRangeContinuous;
+	__u32 bitratesSupported[MAX_NUM_BITRATES];
+	__u32 numBitratesSupported;
+	__u32 rateControlSupported;
+	__u32 profileSetting;
+	__u32 modeSetting;
+	__u32 streamFormat;
+	__u32 reserved[16];
+};
+
+/** struct SndAudioCodecSettings -
+ * @codecId: Identifies the supported audio encoder/decoder. See SND_AUDIOCODEC	macros.
+ * @channelsIn: Number of input audio channels
+ * @channelsOut: Number of output channels. In case of contradiction between this field and the
+ *		channelMode field, the channelMode field overrides
+ * @sampleRate: Audio sample rate of input data
+ * @bitRate: Bitrate of encoded data. May be ignored by decoders
+ * @bitsPerSample: <FIXME: Needed? DSP implementations can handle their own format>
+ * @rateControl: Encoding rate control. See SND_RATECONTROLMODE defines.
+ *               Encoders may rely on profiles for quality levels.
+ *		 May be ignored by decoders.
+ * @profileSetting: Mandatory for encoders, can be mandatory for specific decoders as well.
+ *		See SND_AUDIOPROFILE defines
+ * @levelSetting: Supported level (Only used by WMA at the moment)
+ * @channelMode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
+ * @streamFormat: Format of encoded bistream. Mandatory when defined. See SND_AUDIOSTREAMFORMAT
+ *		defines
+ * @blockAlignment: Block alignment in bytes of an audio sample. Only required for PCM or IEC formats
+ * @options: encoder-specific settings
+ * @reserved: reserved for future use
+ */
+
+struct SndAudioCodecSettings {
+	__u32 codecId;
+	__u32 channelsIn;
+	__u32 channelsOut;
+	__u32 sampleRate;
+	__u32 bitRate;
+	__u32 bitsPerSample;
+	__u32 rateControl;
+	__u32 profileSetting;
+	__u32 levelSetting;
+	__u32 channelMode;
+	__u32 streamFormat;
+	__u32 blockAlignment;
+	union AudioCodecOptions options;
+	__u32 reserved[3];
+};
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [RFC 3/5] compress: add API header and driver header files
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
  2011-09-02  6:06 ` [RFC 1/5] compress API documentation Vinod Koul
  2011-09-02  6:06 ` [RFC 2/5] compress: add compress parameter definations Vinod Koul
@ 2011-09-02  6:06 ` Vinod Koul
  2011-09-02 13:36   ` Clemens Ladisch
  2011-09-02  6:06 ` [RFC 4/5] compress: add the core file Vinod Koul
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-09-02  6:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

This patch adds the header files for ioctl definations and header file for
driver APIs for lower level device drivers to use

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 include/sound/compress_driver.h  |  138 ++++++++++++++++++++++++++++++++++++++
 include/sound/compress_offload.h |  137 +++++++++++++++++++++++++++++++++++++
 2 files changed, 275 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h

diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
new file mode 100644
index 0000000..e5fbbf1
--- /dev/null
+++ b/include/sound/compress_driver.h
@@ -0,0 +1,138 @@
+/*
+ *  compress_driver.h - compress offload driver definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_DRIVER_H
+#define __COMPRESS_DRIVER_H
+
+#include <sound/compress_offload.h>
+#include <sound/asound.h>
+#include <sound/pcm.h>
+
+struct snd_compr_ops;
+
+/**
+ * struct snd_compr_runtime: runtime stream description
+ * @state: stream state
+ * @ops: pointer to DSP callbacks
+ * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
+ *	DSP doesn't implement copy
+ * @buffer_size: size of the above buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @periods: number of such fragments
+ * @hw_pointer: offset of last location in buffer where DSP copied data
+ * @app_pointer: offset of last location in buffer where app wrote data
+ * @sleep: poll sleep
+ */
+struct snd_compr_runtime {
+	snd_pcm_state_t state;
+	struct snd_compr_ops *ops;
+	void *buffer;
+	size_t buffer_size;
+	size_t fragment_size;
+	unsigned int periods;
+	size_t hw_pointer;
+	size_t app_pointer;
+	wait_queue_head_t sleep;
+};
+
+/**
+ * struct snd_compr_stream: compressed stream
+ * @name: device name
+ * @ops: pointer to DSP callbacks
+ * @runtime: pointer to runtime structure
+ * @device: device pointer
+ * @direction: stream direction, playback/recording
+ * @private_data: pointer to DSP private data
+ */
+struct snd_compr_stream {
+	const char *name;
+	struct snd_compr_ops *ops;
+	struct snd_compr_runtime *runtime;
+	struct snd_compr *device;
+	unsigned int direction;
+	void *private_data;
+};
+
+/**
+ * struct snd_compr_ops: compressed path DSP operations
+ * @open: Open the compressed stream
+ * This callback is mandatory and shall keep dsp ready to receive the stream parameter
+ * @free: Close the compressed stream, mandatory
+ * @set_params: Sets the compressed stream parameters, mandatory
+ * This can be called in during stream creation only to set codec params
+ * and the stream properties
+ * @get_params: retrieve the codec parameters, mandatory
+ * @trigger: Trigger operations like start, pause, resume, drain, stop. Mandatory
+ * @pointer: Retrieve current h/w pointer information. Mandatory
+ * @copy: Copy the compressed data to/from userspace, Optional
+ * Can't be implemented if DSP supports mmap
+ * @mmap: DSP mmap method to mmap DSP memory
+ * @ack: Ack for DSP when data is written to audio buffer, Optional
+ * Not valid if copy is implemented
+ * @get_caps: Retrieve DSP capabilities, mandatory
+ * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory
+ */
+struct snd_compr_ops {
+	int (*open)(struct snd_compr_stream *stream);
+	int (*free)(struct snd_compr_stream *stream);
+	int (*set_params)(struct snd_compr_stream *stream,
+			struct snd_compr_params *params);
+	int (*get_params)(struct snd_compr_stream *stream,
+			struct snd_compr_params *params);
+	int (*trigger)(struct snd_compr_stream *stream, int cmd);
+	int (*pointer)(struct snd_compr_stream *stream,
+			struct snd_compr_tstamp *tstamp);
+	int (*copy)(struct snd_compr_stream *stream, const char __user *buf,
+		       size_t count);
+	int (*mmap)(struct snd_compr_stream *stream, struct vm_area_struct *vma);
+	int (*ack)(struct snd_compr_stream *stream);
+	int (*get_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_caps *caps);
+	int (*get_codec_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_codec_caps *codec);
+};
+
+/**
+ * struct snd_compr: Compressed device
+ * @name: DSP device name
+ * @dev: Device pointer
+ * @lock: device lock
+ * @ops: pointer to DSP callbacks
+ * @private_data: pointer to DSP pvt data
+ */
+struct snd_compr {
+	const char *name;
+	struct device *dev;
+	struct mutex lock;
+	struct snd_compr_ops *ops;
+	struct list_head list;
+	void *private_data;
+};
+
+
+int snd_compress_register(struct snd_compr *device);
+int snd_compress_deregister(struct snd_compr *device);
+void snd_compr_period_elapsed(struct snd_compr_stream *stream);
+
+#endif
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
new file mode 100644
index 0000000..48f816f
--- /dev/null
+++ b/include/sound/compress_offload.h
@@ -0,0 +1,137 @@
+/*
+ *  compress_offload.h - compress offload header definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_OFFLOAD_H
+#define __COMPRESS_OFFLOAD_H
+
+#include <linux/types.h>
+/**
+ * struct snd_compressed_buffer:compressed buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @periods: number of such fragments
+ */
+struct snd_compressed_buffer {
+	size_t fragment_size;
+	int periods;
+};
+
+/* */
+struct snd_compr_params {
+	struct snd_compressed_buffer buffer;
+	struct SndAudioCodecSettings codec;
+};
+
+/**
+ * struct snd_compr_tstamp: timestamp descriptor
+ * @copied_bytes: Number of bytes offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from ring buffer to DSP
+ * @decoded: Frames decoded by DSP
+ * @rendered: Frames rendered by DSP into a mixer or an audio output
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp {
+	size_t copied_bytes;
+	size_t copied_total;
+	size_t decoded;
+	size_t rendered;
+	__u32 sampling_rate;
+};
+
+/**
+ * struct snd_compr_avail: avail descriptor
+ * @avail: Number of bytes available in ring buffer for writing/reading
+ * @tstamp: timestamp infomation
+ */
+struct snd_compr_avail {
+	size_t avail;
+	struct snd_compr_tstamp tstamp;
+};
+
+/**
+ * struct snd_compr_caps: caps descriptor
+ * @codecs: pointer to array of codecs
+ * @min_fragment_size: minimum fragment supported by DSP
+ * @max_fragment_size: maximum fragment supported by DSP
+ * @min_periods: min periods supported by DSP
+ * @max_periods: max periods supported by DSP
+ * @num_codecs: number of codecs supported
+ * @reserved: reserved field
+ */
+struct snd_compr_caps {
+	__u32 num_codecs;
+	__u32 min_fragment_size;
+	__u32 max_fragment_size;
+	__u32 min_periods;
+	__u32 max_periods;
+	__u32 codecs[MAX_NUM_CODECS];
+	__u32 reserved[11];
+};
+
+/**
+ * struct snd_compr_codec_caps: query capability of codec
+ * @codec: codec for which capability is queried
+ * @num_descriptors: number of codec descriptors
+ * @descriptor: array of codec capability descriptor
+ */
+struct snd_compr_codec_caps {
+	__u32 codec;
+	__u32 num_descriptors;
+	struct SndAudioCodecDescriptor descriptor[MAX_NUM_CODEC_DESCRIPTORS];
+};
+
+/**
+ * compress path ioctl definitions
+ * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
+ * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
+ * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
+ * Note: only codec params can be changed runtime and stream params cant be
+ * SNDRV_COMPRESS_GET_PARAMS: Query codec and stream params
+ * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
+ * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
+ * This also queries the tstamp properties
+ * SNDRV_COMPRESS_PAUSE: Pause the running stream
+ * SNDRV_COMPRESS_RESUME: resume a paused stream
+ * SNDRV_COMPRESS_START: Start a stream
+ * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content and
+ * buffers current with DSP
+ * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
+ */
+#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x00, struct snd_compr_caps *)
+#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x01, struct snd_compr_codec_caps *)
+#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x02, struct snd_compr_params *)
+#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x03, struct snd_compr_params *)
+#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x10, struct snd_compr_tstamp *)
+#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x11, struct snd_compr_avail *)
+#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x20)
+#define SNDRV_COMPRESS_RESUME		_IO('C', 0x21)
+#define SNDRV_COMPRESS_START		_IO('C', 0x22)
+#define SNDRV_COMPRESS_STOP		_IO('C', 0x23)
+#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x24)
+/*
+ * TODO
+ * 1. add mmap support
+ *
+ */
+#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [RFC 4/5] compress: add the core file
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (2 preceding siblings ...)
  2011-09-02  6:06 ` [RFC 3/5] compress: add API header and driver header files Vinod Koul
@ 2011-09-02  6:06 ` Vinod Koul
  2011-09-02 14:36   ` Mark Brown
                     ` (4 more replies)
  2011-09-02  6:06 ` [RFC 5/5] compress: add makefile and kconfig file Vinod Koul
                   ` (8 subsequent siblings)
  12 siblings, 5 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-02  6:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

This patch ads core.c, the file which implements the ioctls and
registers the devices

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/compress_offload/core.c |  632 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 632 insertions(+), 0 deletions(-)
 create mode 100644 sound/compress_offload/core.c

diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
new file mode 100644
index 0000000..1797dba
--- /dev/null
+++ b/sound/compress_offload/core.c
@@ -0,0 +1,632 @@
+/*
+ *  core.c - compress offload core
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
+
+/* TODO:
+ * - Integrate with alsa, compressed devices should register as alsa devices
+ *	as /dev/snd_compr_xxx
+ * - Integrate with ASoC:
+ *	Opening compressed path should also start the codec dai
+ *   TBD how the cpu dai will be viewed and started.
+ *	ASoC should always be optional part
+ *	(we should be able to use this framework in non asoc systems
+ * - Multiple node representation
+ *	driver should be able to register multiple nodes
+ * - Version numbering for API
+ */
+
+static DEFINE_MUTEX(device_mutex);
+static LIST_HEAD(device_list);
+static LIST_HEAD(misc_list);
+
+/*
+ * currently we are using misc device for registration and exposing ioctls
+ * this is temporary and will be moved to snd
+ * the device should be registered as /dev/snd_compr.....
+ */
+
+struct snd_compr_misc {
+	struct miscdevice misc;
+	struct list_head list;
+	struct snd_compr *compr;
+};
+
+struct snd_ioctl_data {
+	struct snd_compr_misc *misc;
+	unsigned long caps;
+	unsigned int minor;
+	struct snd_compr_stream stream;
+};
+
+static struct snd_compr_misc *snd_compr_get_device(unsigned int minor)
+{
+	struct snd_compr_misc *misc;
+
+	list_for_each_entry(misc, &misc_list, list) {
+		if (minor == misc->misc.minor)
+			return misc;
+	}
+	return NULL;
+}
+
+static int snd_compr_open(struct inode *inode, struct file *f)
+{
+	unsigned int minor = iminor(inode);
+	struct snd_compr_misc *misc = snd_compr_get_device(minor);
+	struct snd_ioctl_data *data;
+	struct snd_compr_runtime *runtime;
+	unsigned int direction;
+	int ret;
+
+	mutex_lock(&device_mutex);
+	if (f->f_flags & O_WRONLY)
+		direction = SNDRV_PCM_STREAM_PLAYBACK;
+	else {
+		ret = -ENXIO;
+		goto out;
+	}
+	/* curently only encoded playback is supported, above needs to be removed
+	 * once we have recording support */
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	data->misc = misc;
+	data->minor = minor;
+	data->stream.ops = misc->compr->ops;
+	data->stream.direction = direction;
+	data->stream.private_data = misc->compr->private_data;
+	data->stream.device = misc->compr;
+	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+	if (!runtime) {
+		ret = -ENOMEM;
+		kfree(data);
+		goto out;
+	}
+	ret = misc->compr->ops->open(&data->stream);
+	if (ret) {
+		kfree(runtime);
+		kfree(data);
+		goto out;
+	}
+	runtime->state = SNDRV_PCM_STATE_OPEN;
+	init_waitqueue_head(&runtime->sleep);
+	data->stream.runtime = runtime;
+	f->private_data = (void *)data;
+out:
+	mutex_unlock(&device_mutex);
+	return ret;
+}
+
+static int snd_compr_free(struct inode *inode, struct file *f)
+{
+	struct snd_ioctl_data *data = f->private_data;
+	mutex_lock(&device_mutex);
+	data->stream.ops->free(&data->stream);
+	kfree(data->stream.runtime->buffer);
+	kfree(data->stream.runtime);
+	kfree(data);
+	mutex_unlock(&device_mutex);
+	return 0;
+}
+
+static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
+		struct snd_compr_tstamp *tstamp)
+{
+	stream->ops->pointer(stream, tstamp);
+	stream->runtime->hw_pointer = tstamp->copied_bytes;
+}
+
+static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
+		struct snd_compr_avail *avail)
+{
+	size_t avail_calc;
+
+	snd_compr_update_tstamp(stream, &avail->tstamp);
+	avail_calc = stream->runtime->app_pointer -  stream->runtime->hw_pointer;
+	if (avail_calc < 0)
+		avail_calc = stream->runtime->buffer_size + avail_calc;
+	avail->avail = avail_calc;
+	return avail_calc;
+}
+
+static size_t snd_compr_get_avail(struct snd_compr_stream *stream)
+{
+	struct snd_compr_avail avail;
+
+	return snd_compr_calc_avail(stream, &avail);
+}
+
+static int
+snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_avail ioctl_avail;
+
+	snd_compr_calc_avail(stream, &ioctl_avail);
+
+	if (copy_to_user((unsigned long __user *)arg, &ioctl_avail, sizeof(ioctl_avail)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_compr_write_data(struct snd_compr_stream *stream,
+	       const char __user *buf, size_t count)
+{
+	void *dstn;
+	size_t copy;
+
+	dstn = stream->runtime->buffer + stream->runtime->app_pointer;
+	if (count <  stream->runtime->buffer_size - stream->runtime->app_pointer) {
+		if (copy_from_user(dstn, buf, count))
+			return -EFAULT;
+		stream->runtime->app_pointer += count;
+	} else {
+		copy = stream->runtime->buffer_size - stream->runtime->app_pointer;
+		if (copy_from_user(dstn, buf, copy))
+			return -EFAULT;
+		if (copy_from_user(stream->runtime->buffer, buf + copy, count - copy))
+			return -EFAULT;
+		stream->runtime->app_pointer = count - copy;
+	}
+	/* if DSP cares, let it know data has been written */
+	if (stream->ops->ack)
+		stream->ops->ack(stream);
+	return count;
+}
+
+static int snd_compr_write(struct file *f, const char __user *buf,
+		size_t count, loff_t *offset)
+{
+	struct snd_ioctl_data *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	/* write is allowed when stream is running or has been steup */
+	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
+			stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+		return -EPERM;
+	mutex_lock(&stream->device->lock);
+
+	avail = snd_compr_get_avail(stream);
+	/* calculate how much we can write to buffer */
+	if (avail > count)
+		avail = count;
+
+	if (stream->ops->copy)
+		retval = stream->ops->copy(stream, buf, avail);
+	else
+		retval = snd_compr_write_data(stream, buf, avail);
+
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+
+static int snd_compr_read(struct file *f, char __user *buf,
+		size_t count, loff_t *offset)
+{
+	return -ENXIO;
+}
+
+static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
+{
+	return -ENXIO;
+}
+
+unsigned int snd_compr_poll(struct file *f, poll_table *wait)
+{
+	struct snd_ioctl_data *data = f->private_data;
+	struct snd_compr_stream *stream;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+		return -ENXIO;
+	poll_wait(f, &stream->runtime->sleep, wait);
+
+	/* this would change after read is implemented, we would need to
+	 * check for direction here */
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+		return POLLOUT | POLLWRNORM;
+
+	return 0;
+}
+
+void snd_compr_period_elapsed(struct snd_compr_stream *stream)
+{
+	size_t avail;
+
+	avail = snd_compr_get_avail(stream);
+	if (avail >= stream->runtime->fragment_size)
+		wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_period_elapsed);
+
+static int snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_caps caps;
+
+	if (!stream->ops->get_caps)
+		return -ENXIO;
+
+	retval = stream->ops->get_caps(stream, &caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
+		retval = -EFAULT;
+out:
+	return retval;
+}
+
+static int snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_codec_caps *caps;
+
+	if (!stream->ops->get_codec_caps)
+		return -ENXIO;
+
+	caps = kmalloc(sizeof(*caps), GFP_KERNEL);
+	if (!caps)
+		return -ENOMEM;
+
+	retval = stream->ops->get_codec_caps(stream, caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
+		retval = -EFAULT;
+
+out:
+	kfree(caps);
+	return retval;
+}
+
+/* revisit this with snd_pcm_preallocate_xxx */
+static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+		struct snd_compr_params *params)
+{
+	unsigned int buffer_size;
+	void *buffer;
+
+	buffer_size = params->buffer.fragment_size * params->buffer.periods;
+	if (stream->ops->copy) {
+		buffer = NULL;
+		/* if copy is defined the driver will be required to copy
+		 * the data from core
+		 */
+	} else {
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+	}
+	stream->runtime->fragment_size = params->buffer.fragment_size;
+	stream->runtime->periods = params->buffer.periods;
+	stream->runtime->buffer = buffer;
+	stream->runtime->buffer_size = buffer_size;
+	return 0;
+}
+
+static int snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_params *params;
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+		/*
+		 * we should allow parameter change only when stream has been
+		 * opened not in other cases
+		 */
+		params = kmalloc(sizeof(*params), GFP_KERNEL);
+		if (!params)
+			return -ENOMEM;
+		if (copy_from_user(&params, (void __user *)arg, sizeof(params)))
+			return -EFAULT;
+		retval = snd_compr_allocate_buffer(stream, params);
+		if (retval) {
+			kfree(params);
+			return -ENOMEM;
+		}
+		retval = stream->ops->set_params(stream, params);
+		if (retval)
+			goto out;
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+	} else
+		return -EPERM;
+out:
+	kfree(params);
+	return retval;
+}
+
+static int snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_params *params;
+	int retval;
+
+	if (!stream->ops->get_params)
+		return -ENXIO;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+	retval = stream->ops->get_params(stream, params);
+	if (retval)
+		goto out;
+	if (copy_to_user((char __user *)arg, params, sizeof(*params)))
+		retval = -EFAULT;
+
+out:
+	kfree(params);
+	return retval;
+}
+
+static int snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_tstamp tstamp;
+
+	snd_compr_update_tstamp(stream, &tstamp);
+	if (copy_to_user((struct snd_compr_tstamp __user *)arg, &tstamp, sizeof(tstamp)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_compr_pause(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED)
+		return 0;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_resume(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_start(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_stop(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_drain(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED ||
+			stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct snd_ioctl_data *data = f->private_data;
+	struct snd_compr_stream *stream;
+	int retval = -ENOTTY;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	mutex_lock(&stream->device->lock);
+	switch (_IOC_NR(cmd)) {
+	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+		retval = snd_compr_get_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+		retval = snd_compr_get_codec_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+		retval = snd_compr_set_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
+		retval = snd_compr_get_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
+		retval = snd_compr_tstamp(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
+		retval = snd_compr_ioctl_avail(stream, arg);
+	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
+		retval = snd_compr_pause(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_RESUME):
+		retval = snd_compr_resume(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_START):
+		retval = snd_compr_start(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_STOP):
+		retval = snd_compr_stop(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+		cmd = SND_COMPR_TRIGGER_DRAIN;
+		retval = snd_compr_drain(stream);
+		break;
+	}
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+static const struct file_operations snd_comp_file = {
+	.owner =	THIS_MODULE,
+	.open =		snd_compr_open,
+	.release =	snd_compr_free,
+	.read =		snd_compr_read,
+	.write =	snd_compr_write,
+	.unlocked_ioctl = snd_compr_ioctl,
+	.mmap =		snd_compr_mmap,
+	.poll =		snd_compr_poll,
+};
+
+static int snd_compress_add_device(struct snd_compr *device)
+{
+	int ret;
+
+	struct snd_compr_misc *misc = kzalloc(sizeof(*misc), GFP_KERNEL);
+
+	misc->misc.name = device->name;
+	misc->misc.fops = &snd_comp_file;
+	misc->misc.minor = MISC_DYNAMIC_MINOR;
+	misc->compr = device;
+	ret = misc_register(&misc->misc);
+	if (ret) {
+		pr_err("couldn't register misc device\n");
+		kfree(misc);
+	} else {
+		pr_debug("Got minor %d\n", misc->misc.minor);
+		list_add_tail(&misc->list, &misc_list);
+	}
+	return ret;
+}
+
+static int snd_compress_remove_device(struct snd_compr *device)
+{
+	struct snd_compr_misc *misc, *__misc;
+
+	list_for_each_entry_safe(misc, __misc, &misc_list, list) {
+		if (device == misc->compr) {
+			misc_deregister(&misc->misc);
+			list_del(&device->list);
+			kfree(misc);
+		}
+	}
+	return 0;
+}
+/**
+ * snd_compress_register - register compressed device
+ *
+ * @device: compressed device to register
+ */
+int snd_compress_register(struct snd_compr *device)
+{
+	int retval;
+
+	if (device->name == NULL || device->dev == NULL || device->ops == NULL)
+		return -EINVAL;
+	BUG_ON(!device->ops->open);
+	BUG_ON(!device->ops->free);
+	BUG_ON(!device->ops->set_params);
+	BUG_ON(!device->ops->get_params);
+	BUG_ON(!device->ops->trigger);
+	BUG_ON(!device->ops->pointer);
+	BUG_ON(!device->ops->get_caps);
+	BUG_ON(!device->ops->get_codec_caps);
+
+	INIT_LIST_HEAD(&device->list);
+	/* todo register the compressed streams */
+	/* todo integrate with asoc */
+
+	/* register a compressed card  TBD if this needs change */
+
+	pr_debug("Registering compressed device %s\n", device->name);
+	mutex_lock(&device_mutex);
+	/*  register a msic device for now */
+	retval = snd_compress_add_device(device);
+	if (!retval)
+		list_add_tail(&device->list, &device_list);
+	mutex_unlock(&device_mutex);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(snd_compress_register);
+
+int snd_compress_deregister(struct snd_compr *device)
+{
+	pr_debug("Removing compressed device %s\n", device->name);
+	mutex_lock(&device_mutex);
+	snd_compress_remove_device(device);
+	list_del(&device->list);
+	mutex_unlock(&device_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_compress_deregister);
+
+static int __init snd_compress_init(void)
+{
+	return 0;
+}
+
+static void __exit snd_compress_exit(void)
+{
+}
+
+module_init(snd_compress_init);
+module_exit(snd_compress_exit);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [RFC 5/5] compress: add makefile and kconfig file
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (3 preceding siblings ...)
  2011-09-02  6:06 ` [RFC 4/5] compress: add the core file Vinod Koul
@ 2011-09-02  6:06 ` Vinod Koul
  2011-09-02 11:30 ` [RFC 0/5] compress: add compress data API to ALSA kernel Mark Brown
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-02  6:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/Kconfig                   |    2 ++
 sound/Makefile                  |    3 ++-
 sound/compress_offload/Kconfig  |   12 ++++++++++++
 sound/compress_offload/Makefile |    3 +++
 4 files changed, 19 insertions(+), 1 deletions(-)
 create mode 100644 sound/compress_offload/Kconfig
 create mode 100644 sound/compress_offload/Makefile

diff --git a/sound/Kconfig b/sound/Kconfig
index 1fef141..9b09263 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -93,6 +93,8 @@ source "sound/mips/Kconfig"
 
 source "sound/sh/Kconfig"
 
+source "sound/compress_offload/Kconfig"
+
 # the following will depend on the order of config.
 # here assuming USB is defined before ALSA
 source "sound/usb/Kconfig"
diff --git a/sound/Makefile b/sound/Makefile
index ce9132b..5a54d6c 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -6,7 +6,8 @@ obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
-	firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
+	firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ \
+	compress_offload/
 obj-$(CONFIG_SND_AOA) += aoa/
 
 # This one must be compilable even if sound is configured out
diff --git a/sound/compress_offload/Kconfig b/sound/compress_offload/Kconfig
new file mode 100644
index 0000000..7ed2d04
--- /dev/null
+++ b/sound/compress_offload/Kconfig
@@ -0,0 +1,12 @@
+#
+# compressed offload config
+#
+
+menuconfig SND_COMPRESS_OFFLOAD
+	tristate "ALSA Compressed audio offload support"
+	default n
+	help
+	  If you want support for offloading compressed audio and have such
+	  a hardware, then you should say Y here and also to the DSP driver
+	  of your platform.
+
diff --git a/sound/compress_offload/Makefile b/sound/compress_offload/Makefile
new file mode 100644
index 0000000..f0f378f
--- /dev/null
+++ b/sound/compress_offload/Makefile
@@ -0,0 +1,3 @@
+snd-compress-objs := core.o
+
+obj-$(CONFIG_SND_COMPRESS_OFFLOAD)	+= snd-compress.o
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* Re: [RFC 2/5] compress: add compress parameter definations
  2011-09-02  6:06 ` [RFC 2/5] compress: add compress parameter definations Vinod Koul
@ 2011-09-02  6:49   ` Paul Menzel
  2011-09-02 19:54     ` Pierre-Louis Bossart
  2011-09-02 14:19   ` Mark Brown
  1 sibling, 1 reply; 133+ messages in thread
From: Paul Menzel @ 2011-09-02  6:49 UTC (permalink / raw)
  To: alsa-devel


[-- Attachment #1.1: Type: text/plain, Size: 20125 bytes --]

Am Freitag, den 02.09.2011, 11:36 +0530 schrieb Vinod Koul:
> The patch adds the various definations used to define the encoder and decoder
> parameters

There is a typo in the summary and message body: defin*i*tions.

I found some more things in the comments below.

> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> ---
>  include/sound/snd_compress_params.h |  396 +++++++++++++++++++++++++++++++++++
>  1 files changed, 396 insertions(+), 0 deletions(-)
>  create mode 100644 include/sound/snd_compress_params.h
> 
> diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
> new file mode 100644
> index 0000000..7203e5f
> --- /dev/null
> +++ b/include/sound/snd_compress_params.h
> @@ -0,0 +1,396 @@
> +/*
> + *  snd_compress_params.h - codec types and parameters for compressed data
> + *  streaming interface
> + *
> + *  Copyright (C) 2011 Intel Corporation
> + *  Authors:	Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>

No ».« between the names.

> + *              Vinod Koul <vinod.koul@linux.intel.com>
> + *
> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; version 2 of the License.
> + *
> + *  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.
> + *
> + *  You should have received a copy of the GNU General Public License along
> + *  with this program; if not, write to the Free Software Foundation, Inc.,
> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + * The definitions in this file are derived from the OpenMAX AL version 1.1
> + * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
> + *
> + * Copyright (c) 2007-2010 The Khronos Group Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining
> + * a copy of this software and/or associated documentation files (the
> + * "Materials "), to deal in the Materials without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sublicense, and/or sell copies of the Materials, and to
> + * permit persons to whom the Materials are furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included
> + * in all copies or substantial portions of the Materials.
> + *
> + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
> + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
> + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
> + *
> + */
> +
> +
> +/* AUDIO CODECS SUPPORTED */
> +#define MAX_NUM_CODECS 32
> +#define MAX_NUM_CODEC_DESCRIPTORS 32
> +#define MAX_NUM_RATES 32
> +#define MAX_NUM_BITRATES 32
> +
> +/* Codecs are listed linearly to allow for extensibility */
> +#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
> +#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
> +#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
> +#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
> +#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
> +#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
> +#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
> +#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
> +#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
> +#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
> +#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
> +
> +/*
> + * Profile and modes are listed with bit masks. This allows for a
> + * more compact representation of fields that will not evolve
> + * (in contrast to the list of codecs)
> + */
> +
> +#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
> +
> +/* MP3 modes are only useful for encoders */
> +#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
> +#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
> +#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
> +#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
> +
> +#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
> +
> +/* AMR modes are only useful for encoders */
> +#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
> +
> +#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
> +#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
> +#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
> +#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
> +#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
> +#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
> +#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
> +
> +#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
> +
> +/* AMRWB modes are only useful for encoders */
> +#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
> +
> +#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
> +
> +#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
> +
> +/* AAC modes are required for encoders and decoders */
> +#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
> +#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
> +#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
> +#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
> +#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
> +#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
> +#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
> +
> +/* AAC formats are required for encoders and decoders */
> +#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
> +#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
> +#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
> +#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
> +#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
> +#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
> +#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
> +
> +#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
> +#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
> +#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
> +#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
> +
> +#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
> +#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
> +#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
> +#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
> +#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
> +
> +#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
> +/*
> + * Some implementations strip the ASF header and only send ASF packets
> + * to the DSP
> + */
> +#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
> +
> +#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
> +
> +#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
> +
> +#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
> +
> +#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
> +
> +#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
> +
> +/*
> + * Define quality levels for FLAC encoders, from LEVEL0 (fast)
> + * to LEVEL8 (best)
> + */
> +#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
> +#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
> +#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
> +#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
> +#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
> +#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
> +
> +#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
> +#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
> +
> +/* IEC61937 payloads without CUVP and preambles */
> +#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
> +/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
> +#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
> +
> +/*
> + * IEC modes are mandatory for decoders. Format autodetection
> + *  will only happen on the DSP side with mode 0. The PCM mode should
> + *  not be used, the PCM codec should be used instead

The alignment should be fixed. Should a full stop ».« be added at the
end in all the comments?

> + */
> +#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
> +#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
> +#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
> +#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
> +#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
> +#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
> +#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
> +#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
> +#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
> +#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
> +#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
> +#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
> +#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
> +#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
> +#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
> +#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
> +
> +/* <FIXME: multichannel encoders aren't supported for now. Would need
> +   an additional definition of channel arrangement> */
> +
> +/* VBR/CBR definitions */
> +#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
> +#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
> +
> +/* Encoder options */
> +
> +struct wmaEncoderOptions {
> +	__u32 super_block_align; /* WMA Type-specific data */
> +};
> +
> +
> +/**
> + * struct vorbisEncoderOptions
> + * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
> + * In the default mode of operation, the quality level is 3.
> + * Normal quality range is 0 - 10.
> + * @managed: Boolean. Set  bitrate  management  mode. This turns off the
> + * normal VBR encoding, but allows hard or soft bitrate constraints to be
> + * enforced by the encoder. This mode can be slower, and may also be
> + * lower quality. It is primarily useful for streaming.
> + * @maxBitrate: enabled only is managed is TRUE
> + * @minBitrate: enabled only is managed is TRUE

s/is/if/

> + * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
> + * non-stereo streams). Useful for lower-bitrate encoding.
> + *
> + * These options were extracted from the OpenMAX IL spec and gstreamer vorbisenc
> + * properties

GStreamer, since the other words are also capitalized?

> + *
> + * For best quality users should specify VBR mode and set quality levels.
> + */
> +
> +struct vorbisEncoderOptions {
> +	int quality;
> +	__u32 managed;
> +	__u32 maxBitrate;
> +	__u32 minBirate;
> +	__u32 downmix;
> +};
> +
> +
> +/**
> + * struct realEncoderOptions
> + * @coupling_quant_bits: is the number of coupling quantization bits in the stream

Remove »is the«.

> + * @coupling_start_region: is the coupling start region in the stream

Dito.

> + * @num_regions: is the number of regions value

Dito.

> + *
> + * These options were extracted from the OpenMAX IL spec
> + */
> +
> +struct realEncoderOptions {
> +	__u32 coupling_quant_bits;
> +	__u32 coupling_start_region;
> +	__u32 num_regions;
> +};
> +
> +/**
> + * struct flacEncoderOptions
> + * @serialNumber: valid only for OGG formats, needs to be set by application
> + * @replayGain: Add ReplayGain tags
> + *
> + * These options were extracted from the FLAC online documentation
> + * at http://flac.sourceforge.net/documentation_tools_flac.html
> + *
> + * To make the API simpler, it is assumed that the user will select quality
> + * profiles. Additional options that affect encoding quality and speed can
> + * be added at a later stage if need be.

s/if need be/if needed/

> + *
> + * By default the Subset format is used by encoders.
> + *
> + * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
> + * not supported in this API.
> + */
> +
> +struct flacEncoderOptions {
> +	__u32 serialNumber;
> +	__u32 replayGain;
> +};
> +
> +struct genericEncoderOptions {
> +	__u32 encoderBandwidth;
> +	int reserved[15];
> +};
> +
> +union AudioCodecOptions {
> +	struct wmaEncoderOptions wmaSpecificOptions;
> +	struct vorbisEncoderOptions vorbisSpecificOptions;
> +	struct realEncoderOptions realSpecificOptions;
> +	struct flacEncoderOptions flacEncoderOptions;
> +	struct genericEncoderOptions genericOptions;
> +};
> +
> +/** struct SndAudioCodecDescriptor - description of codec capabilities
> + * @maxChannels: maximum number of audio channels
> + * @minBitsPerSample: Minimum bits per sample of PCM data <FIXME: needed?>
> + * @maxBitsPerSample: Maximum bits per sample of PCM data <FIXME: needed?>

More elaborate explanation for the FIXME (in the commit message)?

> + * @minSampleRate: Minimum sampling rate supported, unit is Hz
> + * @maxSampleRate: Minimum sampling rate supported, unit is Hz
> + * @isFreqRangeContinuous: TRUE if the device supports a continuous range of
> + *                         sampling rates between minSampleRate and maxSampleRate;
> + *                         otherwise FALSE <FIXME: needed?>

Dito.

> + * @SampleRatesSupported: Indexed array containing supported sampling rates in Hz
> + * @numSampleRatesSupported: Size of the pSamplesRatesSupported array
> + * @minBitRate: Minimum bitrate in bits per second
> + * @maxBitRate: Max bitrate in bits per second
> + * @isBitrateRangeContinuous: TRUE if the device supports a continuous range of
> + *		      bitrates between minBitRate and maxBitRate; otherwise FALSE
> + * @BitratesSupported: Indexed array containing supported bit rates
> + * @numBitratesSupported: Size of the pBiratesSupported array

Remove `p` in front of pBiratesSupported?

> + * @rateControlSupported: value is specified by SND_RATECONTROLMODE defines.

*V*alue.

> + * @profileSetting: Profile supported. See SND_AUDIOPROFILE defines.

Supported profile.

> + * @modeSetting: Mode supported. See SND_AUDIOMODE defines

Supported mod.

> + * @streamFormat: Format supported. See SND_AUDIOSTREAMFORMAT defines

Supported format.

> + * @reserved: reserved for future use
> + *
> + * This structure provides a scalar value for profile, mode and stream format fields.
> + * If an implementation supports multiple combinations, they will be listed as codecs
> + * with different IDs, for example there would be 2 decoders for AAC-RAW and AAC-ADTS.
> + * This entails some redundancy but makes it easier to avoid invalid configurations.
> + *
> + */
> +
> +struct SndAudioCodecDescriptor {
> +	__u32 maxChannels;
> +	__u32 minBitsPerSample;
> +	__u32 maxBitsPerSample;
> +	__u32 minSampleRate;
> +	__u32 maxSampleRate;
> +	__u32 isFreqRangeContinuous;
> +	__u32 sampleRatesSupported[MAX_NUM_RATES];
> +	__u32 numSampleRatesSupported;
> +	__u32 minBitRate;
> +	__u32 maxBitRate;
> +	__u32 isBitrateRangeContinuous;
> +	__u32 bitratesSupported[MAX_NUM_BITRATES];
> +	__u32 numBitratesSupported;
> +	__u32 rateControlSupported;
> +	__u32 profileSetting;
> +	__u32 modeSetting;
> +	__u32 streamFormat;
> +	__u32 reserved[16];
> +};
> +
> +/** struct SndAudioCodecSettings -
> + * @codecId: Identifies the supported audio encoder/decoder. See SND_AUDIOCODEC	macros.

White space before macros.

> + * @channelsIn: Number of input audio channels
> + * @channelsOut: Number of output channels. In case of contradiction between this field and the
> + *		channelMode field, the channelMode field overrides

Overrides what?

> + * @sampleRate: Audio sample rate of input data
> + * @bitRate: Bitrate of encoded data. May be ignored by decoders
> + * @bitsPerSample: <FIXME: Needed? DSP implementations can handle their own format>
> + * @rateControl: Encoding rate control. See SND_RATECONTROLMODE defines.
> + *               Encoders may rely on profiles for quality levels.
> + *		 May be ignored by decoders.

Alignment.

> + * @profileSetting: Mandatory for encoders, can be mandatory for specific decoders as well.
> + *		See SND_AUDIOPROFILE defines

Alignement?

> + * @levelSetting: Supported level (Only used by WMA at the moment)
> + * @channelMode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
> + * @streamFormat: Format of encoded bistream. Mandatory when defined. See SND_AUDIOSTREAMFORMAT
> + *		defines

Alignment?

> + * @blockAlignment: Block alignment in bytes of an audio sample. Only required for PCM or IEC formats
> + * @options: encoder-specific settings
> + * @reserved: reserved for future use
> + */
> +
> +struct SndAudioCodecSettings {
> +	__u32 codecId;
> +	__u32 channelsIn;
> +	__u32 channelsOut;
> +	__u32 sampleRate;
> +	__u32 bitRate;
> +	__u32 bitsPerSample;
> +	__u32 rateControl;
> +	__u32 profileSetting;
> +	__u32 levelSetting;
> +	__u32 channelMode;
> +	__u32 streamFormat;
> +	__u32 blockAlignment;
> +	union AudioCodecOptions options;
> +	__u32 reserved[3];
> +};


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 0/5] compress: add compress data API to ALSA kernel
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (4 preceding siblings ...)
  2011-09-02  6:06 ` [RFC 5/5] compress: add makefile and kconfig file Vinod Koul
@ 2011-09-02 11:30 ` Mark Brown
  2011-09-02 14:04   ` Pierre-Louis Bossart
       [not found]   ` <000601cc6979$437b11c0$ca713540$@bossart@linux.intel.com>
  2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
                   ` (6 subsequent siblings)
  12 siblings, 2 replies; 133+ messages in thread
From: Mark Brown @ 2011-09-02 11:30 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg

On Fri, Sep 02, 2011 at 11:36:20AM +0530, Vinod Koul wrote:
> As agreed during the ASoC workshop in May 2011, this set of patches are a
> proposal from Intel to add a new compressed data interface to ALSA. This
> proposal builds on the existing Intel solution and the experience gathered over
> two years with Meego and Android solutions. This proposal is no longer
> Intel-specific and was generalized with the addition of a basic core;
> codec-related definitions are based on the vendor-neutral OpenMAX AL standard. 

Excellent stuff, I'll have a look when I can.  Are there corresponding
patches to alsa-lib and alsa-utils?

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 3/5] compress: add API header and driver header files
  2011-09-02  6:06 ` [RFC 3/5] compress: add API header and driver header files Vinod Koul
@ 2011-09-02 13:36   ` Clemens Ladisch
  2011-09-03  2:59     ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Clemens Ladisch @ 2011-09-02 13:36 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

Vinod Koul wrote:
> +#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x00, struct snd_compr_caps *)
> +#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x01, struct snd_compr_codec_caps *)
> +#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x02, struct snd_compr_params *)
> +#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x03, struct snd_compr_params *)
> +#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x10, struct snd_compr_tstamp *)
> +#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x11, struct snd_compr_avail *)

The type whose size is made part of the ioctl number is supposed to be
the actual structure, not a pointer to it.

> +#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x20)
> +#define SNDRV_COMPRESS_RESUME		_IO('C', 0x21)
> +#define SNDRV_COMPRESS_START		_IO('C', 0x22)
> +#define SNDRV_COMPRESS_STOP		_IO('C', 0x23)
> +#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x24)

Please update Documentation/ioctl/ioctl-number.txt.
(This also makes it easier to pick codes without conflicts.)


Regards,
Clemens

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 0/5] compress: add compress data API to ALSA kernel
  2011-09-02 11:30 ` [RFC 0/5] compress: add compress data API to ALSA kernel Mark Brown
@ 2011-09-02 14:04   ` Pierre-Louis Bossart
       [not found]   ` <000601cc6979$437b11c0$ca713540$@bossart@linux.intel.com>
  1 sibling, 0 replies; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-09-02 14:04 UTC (permalink / raw)
  To: 'Mark Brown', 'Vinod Koul'; +Cc: tiwai, alsa-devel, lrg

> Excellent stuff, I'll have a look when I can.  Are there corresponding
> patches to alsa-lib and alsa-utils?

Not yet. I wanted to have more visibility into alsa-lib use for 
Android before doing into changes there.
Let's talk about it at LPC.
-Pierre

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 2/5] compress: add compress parameter definations
  2011-09-02  6:06 ` [RFC 2/5] compress: add compress parameter definations Vinod Koul
  2011-09-02  6:49   ` Paul Menzel
@ 2011-09-02 14:19   ` Mark Brown
  2011-09-02 19:26     ` Pierre-Louis Bossart
  1 sibling, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-09-02 14:19 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg, Pierre-Louis Bossart

On Fri, Sep 02, 2011 at 11:36:22AM +0530, Vinod Koul wrote:

> +/* AUDIO CODECS SUPPORTED */
> +#define MAX_NUM_CODECS 32
> +#define MAX_NUM_CODEC_DESCRIPTORS 32
> +#define MAX_NUM_RATES 32
> +#define MAX_NUM_BITRATES 32

Can we avoid these limitations?  The limit on the number of CODECs in
particular strikes me as not sufficiently high for me to be confident
we'd never run into it.  Consider a server side telephony system...

> +/* Codecs are listed linearly to allow for extensibility */
> +#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
> +#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
> +#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
> +#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
> +#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
> +#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
> +#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
> +#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
> +#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
> +#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
> +#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)

I'd be inclined to add:

+#define SND_AUDIOCODEC_G723_1                  ((__u32) 0x0000000C)
+#define SND_AUDIOCODEC_G729                    ((__u32) 0x0000000D)

for VoIP usage as part of the default set but obviously it doesn't
really matter as it's trivial to add new numbers.

> +	__u32 sampleRatesSupported[MAX_NUM_RATES];
> +	__u32 numSampleRatesSupported;
> +	__u32 minBitRate;
> +	__u32 maxBitRate;
> +	__u32 isBitrateRangeContinuous;

Should we use the existing ALSA rate constants and whatnot for the
sample rate here?

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 0/5] compress: add compress data API to ALSA kernel
       [not found]   ` <000601cc6979$437b11c0$ca713540$@bossart@linux.intel.com>
@ 2011-09-02 14:23     ` Mark Brown
  0 siblings, 0 replies; 133+ messages in thread
From: Mark Brown @ 2011-09-02 14:23 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: tiwai, 'Vinod Koul', alsa-devel, lrg

On Fri, Sep 02, 2011 at 09:04:42AM -0500, Pierre-Louis Bossart wrote:

> Not yet. I wanted to have more visibility into alsa-lib use for 
> Android before doing into changes there.
> Let's talk about it at LPC.

FWIW and the benefit of the list alsa-lib won't fly for adoption by
Google as part of the standard Android system unless it gets relicensed,
though obviously other people are happily using it in production and
there's systems other than Android out there.  tinyalsa is probably the
way forward for Google.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-02  6:06 ` [RFC 4/5] compress: add the core file Vinod Koul
@ 2011-09-02 14:36   ` Mark Brown
  2011-09-03  3:06     ` Vinod Koul
  2011-09-07 13:59   ` Dimitris Papastamos
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-09-02 14:36 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg, Pierre-Louis Bossart

On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:

> + * - Integrate with ASoC:
> + *	Opening compressed path should also start the codec dai
> + *   TBD how the cpu dai will be viewed and started.
> + *	ASoC should always be optional part
> + *	(we should be able to use this framework in non asoc systems

Just write an ALSA core API, ASoC is an ALSA driver so it can just use
the same interfaces as everything else gets.

> + * - Multiple node representation
> + *	driver should be able to register multiple nodes
> + * - Version numbering for API

I'd suggest doing this per ioctl rather than per API.

> +	ret = misc->compr->ops->open(&data->stream);
> +	if (ret) {
> +		kfree(runtime);
> +		kfree(data);
> +		goto out;
> +	}
> +	runtime->state = SNDRV_PCM_STATE_OPEN;
> +	init_waitqueue_head(&runtime->sleep);
> +	data->stream.runtime = runtime;
> +	f->private_data = (void *)data;

Should we hoist these before we call open(), especially the init of
runtime?  It seems likely to be more robusy.

> +static int snd_compr_write(struct file *f, const char __user *buf,
> +		size_t count, loff_t *offset)
> +{
> +	struct snd_ioctl_data *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +	size_t avail;
> +	int retval;
> +
> +	BUG_ON(!data);
> +	stream = &data->stream;
> +	/* write is allowed when stream is running or has been steup */
> +	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
> +			stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> +		return -EPERM;
> +	mutex_lock(&stream->device->lock);

Shouldn't we lock something before we check the stream state?

> +static int snd_compr_read(struct file *f, char __user *buf,
> +		size_t count, loff_t *offset)
> +{
> +	return -ENXIO;
> +}
> +
> +static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
> +{
> +	return -ENXIO;
> +}

Do we need to implement noops like these?

> +unsigned int snd_compr_poll(struct file *f, poll_table *wait)
> +{
> +	struct snd_ioctl_data *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +
> +	BUG_ON(!data);
> +	stream = &data->stream;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> +		return -ENXIO;
> +	poll_wait(f, &stream->runtime->sleep, wait);
> +
> +	/* this would change after read is implemented, we would need to
> +	 * check for direction here */
> +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> +		return POLLOUT | POLLWRNORM;
> +
> +	return 0;
> +}
> +
> +void snd_compr_period_elapsed(struct snd_compr_stream *stream)
> +{
> +	size_t avail;
> +
> +	avail = snd_compr_get_avail(stream);
> +	if (avail >= stream->runtime->fragment_size)
> +		wake_up(&stream->runtime->sleep);
> +}
> +EXPORT_SYMBOL_GPL(snd_compr_period_elapsed);

I can see why you picked period_elapsed() (for consistency) but it feels
wrong to have a time based name for something which is going to end up
being data size based.

> +static int snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
> +{
> +	struct snd_compr_params *params;
> +	int retval;
> +
> +	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {

It would be more legible to reverse the check I think?  Also shouldn't
there be more locking in this (and all the other stuff looking at
states)?

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 2/5] compress: add compress parameter definations
  2011-09-02 14:19   ` Mark Brown
@ 2011-09-02 19:26     ` Pierre-Louis Bossart
  2011-09-03  0:05       ` Mark Brown
  0 siblings, 1 reply; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-09-02 19:26 UTC (permalink / raw)
  To: Mark Brown; +Cc: tiwai, Vinod Koul, alsa-devel, lrg

Thanks Mark for your feedback.

> > +/* AUDIO CODECS SUPPORTED */
> > +#define MAX_NUM_CODECS 32
> > +#define MAX_NUM_CODEC_DESCRIPTORS 32
> > +#define MAX_NUM_RATES 32
> > +#define MAX_NUM_BITRATES 32
> 
> Can we avoid these limitations?  The limit on the number of CODECs in
> particular strikes me as not sufficiently high for me to be confident
> we'd never run into it.  Consider a server side telephony system...

The MAX_NUM_CODECS is actually the number of formats supported by your
firmware, it's not related to the number of streams supported in
parallel on your hardware. We could see support for 8 MP3 decoders, the
number of codecs would be 1. This was dynamic but we limited it to make
our life simpler. There's no problem to make it more flexible.
We can align the sampling rates to use the exising ALSA definitions.
The descriptors correspond to the number of variations for a given
format, we can probably restrict it to 32...

> I'd be inclined to add:
> 
> +#define SND_AUDIOCODEC_G723_1                  ((__u32) 0x0000000C)
> +#define SND_AUDIOCODEC_G729                    ((__u32) 0x0000000D)
> 
> for VoIP usage as part of the default set but obviously it doesn't
> really matter as it's trivial to add new numbers.

Yes we can add these codecs, but it's actually extremely difficult to do
any kind of hw acceleration for VoIP. G723.1 needs extra signaling for
bad/lost frames, and you may want coupling between jitter buffer
management, decoding and possibly a time-stretching solution to
compensate for timing issues or dropped frames. This is difficult to
implement if the speech encoding/decoding is done on the DSP, while the
jitter buffer management is done on the host. The data transfers based
on ringbuffers/DMAs makes it also difficult to handle frames of varying
sizes while limiting latency.
I'd rather push RTP packets down to the DSP and have the complete VoIP
stack handled there.

> Should we use the existing ALSA rate constants and whatnot for the
> sample rate here?

Yes. No issue on our side.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 2/5] compress: add compress parameter definations
  2011-09-02  6:49   ` Paul Menzel
@ 2011-09-02 19:54     ` Pierre-Louis Bossart
  2011-09-03  6:28       ` Mark Brown
  0 siblings, 1 reply; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-09-02 19:54 UTC (permalink / raw)
  To: Paul Menzel; +Cc: alsa-devel

Thank you Paul for your feedback. We will fix all the typos/formatting
issues. You flagged two important points, see my answers below.

> > +/** struct SndAudioCodecDescriptor - description of codec capabilities
> > + * @maxChannels: maximum number of audio channels
> > + * @minBitsPerSample: Minimum bits per sample of PCM data <FIXME: needed?>
> > + * @maxBitsPerSample: Maximum bits per sample of PCM data <FIXME: needed?>
> 
> More elaborate explanation for the FIXME (in the commit message)?

These fields were defined by OpenMAX AL and make sense for a software
implementation of encoders/decoders. In our case the DSP may be a 24-bit
CPU, or a 32-bit one, or a 16-bit one with double precision. I believe
it's useless to specify the internal PCM format to be used by the DSP,
this should be defined by the firmware implementers. 
We decided to leave these fields for now, and see if anyone had a good
reason to keep them. If no one speaks up they will be removed.

> > + * @isFreqRangeContinuous: TRUE if the device supports a continuous range of
> > + *                         sampling rates between minSampleRate and maxSampleRate;
> > + *                         otherwise FALSE <FIXME: needed?>

This also comes from OpenMAX AL. I don't know of any hardware
implementation where the audio rate can be specified with an arbitrary
value. Again if we don't see anyone needing this field, it'll be
removed.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 2/5] compress: add compress parameter definations
  2011-09-02 19:26     ` Pierre-Louis Bossart
@ 2011-09-03  0:05       ` Mark Brown
  0 siblings, 0 replies; 133+ messages in thread
From: Mark Brown @ 2011-09-03  0:05 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: tiwai, Vinod Koul, alsa-devel, lrg

On Fri, Sep 02, 2011 at 02:26:01PM -0500, Pierre-Louis Bossart wrote:

> > > +/* AUDIO CODECS SUPPORTED */
> > > +#define MAX_NUM_CODECS 32
> > > +#define MAX_NUM_CODEC_DESCRIPTORS 32
> > > +#define MAX_NUM_RATES 32
> > > +#define MAX_NUM_BITRATES 32

> > Can we avoid these limitations?  The limit on the number of CODECs in
> > particular strikes me as not sufficiently high for me to be confident
> > we'd never run into it.  Consider a server side telephony system...

> The MAX_NUM_CODECS is actually the number of formats supported by your
> firmware, it's not related to the number of streams supported in
> parallel on your hardware. We could see support for 8 MP3 decoders, the
> number of codecs would be 1. This was dynamic but we limited it to make
> our life simpler. There's no problem to make it more flexible.

Yeah, I know.  I can't think it'll be a practical issue right now but
it's near enough to actual numbers that it doesn't make me happy seeing
it hard coded into an ABI.  The issue with server side telephony stuff
is that you end up interoperating with all sorts of weird stuff, some of
the PSTN stuff I used to work on would be getting close to this limit
due to some of the funky file formats people liked to do records in.

> We can align the sampling rates to use the exising ALSA definitions.
> The descriptors correspond to the number of variations for a given
> format, we can probably restrict it to 32...

That one is probably reasonable, yes.

> > I'd be inclined to add:

> > +#define SND_AUDIOCODEC_G723_1                  ((__u32) 0x0000000C)
> > +#define SND_AUDIOCODEC_G729                    ((__u32) 0x0000000D)

> > for VoIP usage as part of the default set but obviously it doesn't
> > really matter as it's trivial to add new numbers.

> Yes we can add these codecs, but it's actually extremely difficult to do
> any kind of hw acceleration for VoIP. G723.1 needs extra signaling for
> bad/lost frames, and you may want coupling between jitter buffer
> management, decoding and possibly a time-stretching solution to
> compensate for timing issues or dropped frames. This is difficult to

It's really not that hard, and there's also also the answerphone use
case where you're not dealing with a live VoIP stream but rather the
recorded data from one.  That was actually my main thought here - an
answerphone type thing rather than calls.

The G.723.1 lost frame stuff is generally just totally ignored, I'd be
astonished if anyone ever implements it and I'm not convinced from
memory that there's even a place for it in the RTP encoding.

> implement if the speech encoding/decoding is done on the DSP, while the
> jitter buffer management is done on the host. The data transfers based
> on ringbuffers/DMAs makes it also difficult to handle frames of varying
> sizes while limiting latency.

Yes, you would be using a message based thing if it were live audio
(which might be DMAed obviously but nothing like a single audio stream
with a single buffer) - the sort of thing copy() is good for.  The DMA
ring buffers just don't make much sense with the low volume low latency
traffic a live VoIP call generates.

> I'd rather push RTP packets down to the DSP and have the complete VoIP
> stack handled there.

Better yet, have a network stack on the DSP and never bother the host
with the data in the first place.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 3/5] compress: add API header and driver header files
  2011-09-02 13:36   ` Clemens Ladisch
@ 2011-09-03  2:59     ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-03  2:59 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Fri, 2011-09-02 at 15:36 +0200, Clemens Ladisch wrote:
> Vinod Koul wrote:
> > +#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x00, struct snd_compr_caps *)
> > +#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x01, struct snd_compr_codec_caps *)
> > +#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x02, struct snd_compr_params *)
> > +#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x03, struct snd_compr_params *)
> > +#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x10, struct snd_compr_tstamp *)
> > +#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x11, struct snd_compr_avail *)
> 
> The type whose size is made part of the ioctl number is supposed to be
> the actual structure, not a pointer to it.
> 
> > +#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x20)
> > +#define SNDRV_COMPRESS_RESUME		_IO('C', 0x21)
> > +#define SNDRV_COMPRESS_START		_IO('C', 0x22)
> > +#define SNDRV_COMPRESS_STOP		_IO('C', 0x23)
> > +#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x24)
> 
> Please update Documentation/ioctl/ioctl-number.txt.
> (This also makes it easier to pick codes without conflicts.)
We are not using new ioctl major number here. Current piggy backed on
misc devices but this will for next rev be seen as using snd ioctl

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-02 14:36   ` Mark Brown
@ 2011-09-03  3:06     ` Vinod Koul
  2011-09-05 17:43       ` Mark Brown
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-09-03  3:06 UTC (permalink / raw)
  To: Mark Brown; +Cc: tiwai, alsa-devel, lrg, Pierre-Louis Bossart

On Fri, 2011-09-02 at 15:36 +0100, Mark Brown wrote:
> On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> 
> > + * - Integrate with ASoC:
> > + *	Opening compressed path should also start the codec dai
> > + *   TBD how the cpu dai will be viewed and started.
> > + *	ASoC should always be optional part
> > + *	(we should be able to use this framework in non asoc systems
> 
> Just write an ALSA core API, ASoC is an ALSA driver so it can just use
> the same interfaces as everything else gets.
Actually no. That way devices would get regsitered as /dev/snd_pcmCxDxy
which wont be corect.
Was thinking of making these appear as something
like /dev/snd/comprCxDxy.
ANy pointer for above change would be welcome
> 
> > + * - Multiple node representation
> > + *	driver should be able to register multiple nodes
> > + * - Version numbering for API
> 
> I'd suggest doing this per ioctl rather than per API.
OK
> 
> > +	ret = misc->compr->ops->open(&data->stream);
> > +	if (ret) {
> > +		kfree(runtime);
> > +		kfree(data);
> > +		goto out;
> > +	}
> > +	runtime->state = SNDRV_PCM_STATE_OPEN;
> > +	init_waitqueue_head(&runtime->sleep);
> > +	data->stream.runtime = runtime;
> > +	f->private_data = (void *)data;
> 
> Should we hoist these before we call open(), especially the init of
> runtime?  It seems likely to be more robusy.
Since open is just supposed to let the device know that stream is being
created with a particular direction. Event if I move this up, doesn't
serve a purpose as driver should touch these a t open.
But I agree this helps to make more robust 
> 
> > +static int snd_compr_write(struct file *f, const char __user *buf,
> > +		size_t count, loff_t *offset)
> > +{
> > +	struct snd_ioctl_data *data = f->private_data;
> > +	struct snd_compr_stream *stream;
> > +	size_t avail;
> > +	int retval;
> > +
> > +	BUG_ON(!data);
> > +	stream = &data->stream;
> > +	/* write is allowed when stream is running or has been steup */
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
> > +			stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> > +		return -EPERM;
> > +	mutex_lock(&stream->device->lock);
> 
> Shouldn't we lock something before we check the stream state?
Yesss...

> 
> > +static int snd_compr_read(struct file *f, char __user *buf,
> > +		size_t count, loff_t *offset)
> > +{
> > +	return -ENXIO;
> > +}
> > +
> > +static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
> > +{
> > +	return -ENXIO;
> > +}
> 
> Do we need to implement noops like these?
Well I kept them placeholder to remind me what else needs
implementation, I think I will keep them for a while as we need to
implement mmap and recording support as well. Recording is actually
trivial after playback.
> 
> > +unsigned int snd_compr_poll(struct file *f, poll_table *wait)
> > +{
> > +	struct snd_ioctl_data *data = f->private_data;
> > +	struct snd_compr_stream *stream;
> > +
> > +	BUG_ON(!data);
> > +	stream = &data->stream;
> > +
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> > +		return -ENXIO;
> > +	poll_wait(f, &stream->runtime->sleep, wait);
> > +
> > +	/* this would change after read is implemented, we would need to
> > +	 * check for direction here */
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> > +		return POLLOUT | POLLWRNORM;
> > +
> > +	return 0;
> > +}
> > +
> > +void snd_compr_period_elapsed(struct snd_compr_stream *stream)
> > +{
> > +	size_t avail;
> > +
> > +	avail = snd_compr_get_avail(stream);
> > +	if (avail >= stream->runtime->fragment_size)
> > +		wake_up(&stream->runtime->sleep);
> > +}
> > +EXPORT_SYMBOL_GPL(snd_compr_period_elapsed);
> 
> I can see why you picked period_elapsed() (for consistency) but it feels
> wrong to have a time based name for something which is going to end up
> being data size based.
Yes the notion of period here cannot be time it is in bytes.

> 
> > +static int snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
> > +{
> > +	struct snd_compr_params *params;
> > +	int retval;
> > +
> > +	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
> 
> It would be more legible to reverse the check I think?  Also shouldn't
> there be more locking in this (and all the other stuff looking at
> states)?
Ok, Thanks for review


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 2/5] compress: add compress parameter definations
  2011-09-02 19:54     ` Pierre-Louis Bossart
@ 2011-09-03  6:28       ` Mark Brown
  0 siblings, 0 replies; 133+ messages in thread
From: Mark Brown @ 2011-09-03  6:28 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: alsa-devel, Paul Menzel

On Fri, Sep 02, 2011 at 02:54:49PM -0500, Pierre-Louis Bossart wrote:

> > > + * @isFreqRangeContinuous: TRUE if the device supports a continuous range of
> > > + *                         sampling rates between minSampleRate and maxSampleRate;
> > > + *                         otherwise FALSE <FIXME: needed?>

> This also comes from OpenMAX AL. I don't know of any hardware
> implementation where the audio rate can be specified with an arbitrary
> value. Again if we don't see anyone needing this field, it'll be
> removed.

If you switch to ALSA rate specification you'll get this for free
anyway as ALSA supports it.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-03  3:06     ` Vinod Koul
@ 2011-09-05 17:43       ` Mark Brown
  2011-09-05 21:21         ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-09-05 17:43 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg, Pierre-Louis Bossart

On Sat, Sep 03, 2011 at 08:36:25AM +0530, Vinod Koul wrote:
> On Fri, 2011-09-02 at 15:36 +0100, Mark Brown wrote:
> > On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:

> > > + *   TBD how the cpu dai will be viewed and started.
> > > + *	ASoC should always be optional part
> > > + *	(we should be able to use this framework in non asoc systems

> > Just write an ALSA core API, ASoC is an ALSA driver so it can just use
> > the same interfaces as everything else gets.

> Actually no. That way devices would get regsitered as /dev/snd_pcmCxDxy
> which wont be corect.

I'm sorry, I can't understand why this would be the case?  ALSA already
has devices with several different names (control, hw, and pcm).

> > > +	runtime->state = SNDRV_PCM_STATE_OPEN;
> > > +	init_waitqueue_head(&runtime->sleep);
> > > +	data->stream.runtime = runtime;
> > > +	f->private_data = (void *)data;

> > Should we hoist these before we call open(), especially the init of
> > runtime?  It seems likely to be more robusy.

> Since open is just supposed to let the device know that stream is being
> created with a particular direction. Event if I move this up, doesn't
> serve a purpose as driver should touch these a t open.
> But I agree this helps to make more robust 

The most obvious ones were the runtime pointer and the state, I can
easily see some configuration being done on init that might also be done
at later and so want to check the state.

> Well I kept them placeholder to remind me what else needs
> implementation, I think I will keep them for a while as we need to
> implement mmap and recording support as well. Recording is actually
> trivial after playback.

It's generally preferred to omit this sort of stuff from actual
upstream submissions.

> > > +EXPORT_SYMBOL_GPL(snd_compr_period_elapsed);

> > I can see why you picked period_elapsed() (for consistency) but it feels
> > wrong to have a time based name for something which is going to end up
> > being data size based.

> Yes the notion of period here cannot be time it is in bytes.

Right, but the trouble is that "period" generally means a unit of time
so it doesn't read right.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-05 17:43       ` Mark Brown
@ 2011-09-05 21:21         ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-05 21:21 UTC (permalink / raw)
  To: Mark Brown; +Cc: tiwai, alsa-devel, lrg, Pierre-Louis Bossart

On Mon, 2011-09-05 at 10:43 -0700, Mark Brown wrote:
> On Sat, Sep 03, 2011 at 08:36:25AM +0530, Vinod Koul wrote:
> > On Fri, 2011-09-02 at 15:36 +0100, Mark Brown wrote:
> > > On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> 
> > > > + *   TBD how the cpu dai will be viewed and started.
> > > > + *	ASoC should always be optional part
> > > > + *	(we should be able to use this framework in non asoc systems
> 
> > > Just write an ALSA core API, ASoC is an ALSA driver so it can just use
> > > the same interfaces as everything else gets.
> 
> > Actually no. That way devices would get regsitered as /dev/snd_pcmCxDxy
> > which wont be corect.
> 
> I'm sorry, I can't understand why this would be the case?  ALSA already
> has devices with several different names (control, hw, and pcm).
Okay, I checked and looking at code, I think i should call
snd_register_device_for_dev with a new device type, like
SNDRV_DEVICE_TYPE_COMPRESSED.
> 
> > > > +	runtime->state = SNDRV_PCM_STATE_OPEN;
> > > > +	init_waitqueue_head(&runtime->sleep);
> > > > +	data->stream.runtime = runtime;
> > > > +	f->private_data = (void *)data;
> 
> > > Should we hoist these before we call open(), especially the init of
> > > runtime?  It seems likely to be more robusy.
> 
> > Since open is just supposed to let the device know that stream is being
> > created with a particular direction. Event if I move this up, doesn't
> > serve a purpose as driver should touch these a t open.
> > But I agree this helps to make more robust 
> 
> The most obvious ones were the runtime pointer and the state, I can
> easily see some configuration being done on init that might also be done
> at later and so want to check the state.
Okay will change this

> > Well I kept them placeholder to remind me what else needs
> > implementation, I think I will keep them for a while as we need to
> > implement mmap and recording support as well. Recording is actually
> > trivial after playback.
> 
> It's generally preferred to omit this sort of stuff from actual
> upstream submissions.
No issues, will remove all dead code.

> > > +EXPORT_SYMBOL_GPL(snd_compr_period_elapsed);
> 
> > > I can see why you picked period_elapsed() (for consistency) but it feels
> > > wrong to have a time based name for something which is going to end up
> > > being data size based.
> 
> > Yes the notion of period here cannot be time it is in bytes.
> 
> Right, but the trouble is that "period" generally means a unit of time
> so it doesn't read right.
Hmmm, I might then go for _fragment_elapsed or something :)


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-02  6:06 ` [RFC 4/5] compress: add the core file Vinod Koul
  2011-09-02 14:36   ` Mark Brown
@ 2011-09-07 13:59   ` Dimitris Papastamos
  2011-09-07 14:12     ` Dimitris Papastamos
  2011-09-07 15:20   ` Dimitris Papastamos
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 133+ messages in thread
From: Dimitris Papastamos @ 2011-09-07 13:59 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> This patch ads core.c, the file which implements the ioctls and
> registers the devices
> 
> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> ---
>  sound/compress_offload/core.c |  632 +++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 632 insertions(+), 0 deletions(-)
>  create mode 100644 sound/compress_offload/core.c
> 
> diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
> new file mode 100644
> index 0000000..1797dba
> --- /dev/null

> +static int snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
> +{
> +	struct snd_compr_params *params;
> +	int retval;
> +
> +	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
> +		/*
> +		 * we should allow parameter change only when stream has been
> +		 * opened not in other cases
> +		 */
> +		params = kmalloc(sizeof(*params), GFP_KERNEL);
> +		if (!params)
> +			return -ENOMEM;
> +		if (copy_from_user(&params, (void __user *)arg, sizeof(params)))
> +			return -EFAULT;

This should be copy_from_user(params, ...) and not &params.

Thanks,
Dimitris

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-07 13:59   ` Dimitris Papastamos
@ 2011-09-07 14:12     ` Dimitris Papastamos
  2011-09-07 18:00       ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Dimitris Papastamos @ 2011-09-07 14:12 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Wed, Sep 07, 2011 at 02:59:27PM +0100, Dimitris Papastamos wrote:
> On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> > This patch ads core.c, the file which implements the ioctls and
> > registers the devices
> > 
> > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> > ---
> >  sound/compress_offload/core.c |  632 +++++++++++++++++++++++++++++++++++++++++
> >  1 files changed, 632 insertions(+), 0 deletions(-)
> >  create mode 100644 sound/compress_offload/core.c
> > 
> > diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
> > new file mode 100644
> > index 0000000..1797dba
> > --- /dev/null
> 
> > +static int snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
> > +{
> > +	struct snd_compr_params *params;
> > +	int retval;
> > +
> > +	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
> > +		/*
> > +		 * we should allow parameter change only when stream has been
> > +		 * opened not in other cases
> > +		 */
> > +		params = kmalloc(sizeof(*params), GFP_KERNEL);
> > +		if (!params)
> > +			return -ENOMEM;
> > +		if (copy_from_user(&params, (void __user *)arg, sizeof(params)))
> > +			return -EFAULT;
> 
> This should be copy_from_user(params, ...) and not &params.

Aw and it should be sizeof(*params).

Thanks,
Dimitris

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-02  6:06 ` [RFC 4/5] compress: add the core file Vinod Koul
  2011-09-02 14:36   ` Mark Brown
  2011-09-07 13:59   ` Dimitris Papastamos
@ 2011-09-07 15:20   ` Dimitris Papastamos
  2011-09-07 18:05     ` Vinod Koul
  2011-09-08 10:38   ` Dimitris Papastamos
  2011-09-22 13:01   ` Dimitris Papastamos
  4 siblings, 1 reply; 133+ messages in thread
From: Dimitris Papastamos @ 2011-09-07 15:20 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> This patch ads core.c, the file which implements the ioctls and
> registers the devices
> 
> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> ---
>  sound/compress_offload/core.c |  632 +++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 632 insertions(+), 0 deletions(-)
>  create mode 100644 sound/compress_offload/core.c
> 
> diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
> new file mode 100644
> index 0000000..1797dba
> --- /dev/null
> +++ b/sound/compress_offload/core.c
> @@ -0,0 +1,632 @@

> +static int snd_compr_start(struct snd_compr_stream *stream)
> +{
> +	int retval;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
> +		return -EPERM;
> +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
> +	if (!retval)
> +		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
> +	return retval;
> +}
> +
> +static int snd_compr_stop(struct snd_compr_stream *stream)
> +{
> +	int retval;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
> +		return -EPERM;
> +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
> +	if (!retval) {
> +		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
> +		wake_up(&stream->runtime->sleep);
> +	}
> +	return retval;
> +}
> +
> +static int snd_compr_drain(struct snd_compr_stream *stream)
> +{
> +	int retval;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED ||
> +			stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
> +		return -EPERM;
> +	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
> +	if (!retval) {
> +		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
> +		wake_up(&stream->runtime->sleep);
> +	}
> +	return retval;
> +}

How is it expected to have stream->runtime->state ==
SNDRV_PCM_STATE_PREPARED?  This is not set anywhere in the core code.
Do we need to just add another ioctl for _PREPARE?

Thanks,
Dimitris

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-07 14:12     ` Dimitris Papastamos
@ 2011-09-07 18:00       ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-07 18:00 UTC (permalink / raw)
  To: Dimitris Papastamos; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Wed, 2011-09-07 at 15:12 +0100, Dimitris Papastamos wrote:
> On Wed, Sep 07, 2011 at 02:59:27PM +0100, Dimitris Papastamos wrote:
> > On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> > > This patch ads core.c, the file which implements the ioctls and
> > > registers the devices
> > > 
> > > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> > > ---
> > >  sound/compress_offload/core.c |  632 +++++++++++++++++++++++++++++++++++++++++
> > >  1 files changed, 632 insertions(+), 0 deletions(-)
> > >  create mode 100644 sound/compress_offload/core.c
> > > 
> > > diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
> > > new file mode 100644
> > > index 0000000..1797dba
> > > --- /dev/null
> > 
> > > +static int snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
> > > +{
> > > +	struct snd_compr_params *params;
> > > +	int retval;
> > > +
> > > +	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
> > > +		/*
> > > +		 * we should allow parameter change only when stream has been
> > > +		 * opened not in other cases
> > > +		 */
> > > +		params = kmalloc(sizeof(*params), GFP_KERNEL);
> > > +		if (!params)
> > > +			return -ENOMEM;
> > > +		if (copy_from_user(&params, (void __user *)arg, sizeof(params)))
> > > +			return -EFAULT;
> > 
> > This should be copy_from_user(params, ...) and not &params.
> 
> Aw and it should be sizeof(*params).
Rightly so, Thanks


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-07 15:20   ` Dimitris Papastamos
@ 2011-09-07 18:05     ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-07 18:05 UTC (permalink / raw)
  To: Dimitris Papastamos; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Wed, 2011-09-07 at 16:20 +0100, Dimitris Papastamos wrote:
> On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> > This patch ads core.c, the file which implements the ioctls and
> > registers the devices
> > 
> > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> > ---
> >  sound/compress_offload/core.c |  632 +++++++++++++++++++++++++++++++++++++++++
> >  1 files changed, 632 insertions(+), 0 deletions(-)
> >  create mode 100644 sound/compress_offload/core.c
> > 
> > diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
> > new file mode 100644
> > index 0000000..1797dba
> > --- /dev/null
> > +++ b/sound/compress_offload/core.c
> > @@ -0,0 +1,632 @@
> 
> > +static int snd_compr_start(struct snd_compr_stream *stream)
> > +{
> > +	int retval;
> > +
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
> > +		return -EPERM;
> > +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
> > +	if (!retval)
> > +		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
> > +	return retval;
> > +}
> > +
> > +static int snd_compr_stop(struct snd_compr_stream *stream)
> > +{
> > +	int retval;
> > +
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
> > +		return -EPERM;
> > +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
> > +	if (!retval) {
> > +		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
> > +		wake_up(&stream->runtime->sleep);
> > +	}
> > +	return retval;
> > +}
> > +
> > +static int snd_compr_drain(struct snd_compr_stream *stream)
> > +{
> > +	int retval;
> > +
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED ||
> > +			stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
> > +		return -EPERM;
> > +	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
> > +	if (!retval) {
> > +		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
> > +		wake_up(&stream->runtime->sleep);
> > +	}
> > +	return retval;
> > +}
> 
> How is it expected to have stream->runtime->state ==
> SNDRV_PCM_STATE_PREPARED?  This is not set anywhere in the core code.
> Do we need to just add another ioctl for _PREPARE?
Nope. My thoughts on this were that _TRIGGER_START should be called only
when first data has been written, i.e when we are in _SETUP state.
So write in _SETUP state should move this to _PREPARED, and obviously I
have missed that part, Thanks will fix this

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-02  6:06 ` [RFC 4/5] compress: add the core file Vinod Koul
                     ` (2 preceding siblings ...)
  2011-09-07 15:20   ` Dimitris Papastamos
@ 2011-09-08 10:38   ` Dimitris Papastamos
  2011-09-08 23:18     ` Vinod Koul
  2011-09-22 13:01   ` Dimitris Papastamos
  4 siblings, 1 reply; 133+ messages in thread
From: Dimitris Papastamos @ 2011-09-08 10:38 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> This patch ads core.c, the file which implements the ioctls and
> registers the devices
> 
> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> ---
>  sound/compress_offload/core.c |  632 +++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 632 insertions(+), 0 deletions(-)
>  create mode 100644 sound/compress_offload/core.c
> 
> diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
> new file mode 100644
> index 0000000..1797dba
> --- /dev/null
> +++ b/sound/compress_offload/core.c
> @@ -0,0 +1,632 @@

> +unsigned int snd_compr_poll(struct file *f, poll_table *wait)
> +{
> +	struct snd_ioctl_data *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +
> +	BUG_ON(!data);
> +	stream = &data->stream;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> +		return -ENXIO;
> +	poll_wait(f, &stream->runtime->sleep, wait);
> +
> +	/* this would change after read is implemented, we would need to
> +	 * check for direction here */
> +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> +		return POLLOUT | POLLWRNORM;
> +
> +	return 0;
> +}

Do we need to grab any locks here?  I'm also confused about checking for
!= SNDRV_PCM_STATE_RUNNING and only then returning POLLOUT | POLLWRNORM.
Shouldn't the normal cycle be write->start->poll->write->poll->...?  At
the moment, the state won't change and for this cycle to be effective we
have to call stop/drain in between.  Am I missing something?

Thanks,
Dimitris

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-08 10:38   ` Dimitris Papastamos
@ 2011-09-08 23:18     ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-08 23:18 UTC (permalink / raw)
  To: Dimitris Papastamos; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Thu, 2011-09-08 at 11:38 +0100, Dimitris Papastamos wrote:
> On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> > This patch ads core.c, the file which implements the ioctls and
> > registers the devices
> > 
> > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> > ---
> >  sound/compress_offload/core.c |  632 +++++++++++++++++++++++++++++++++++++++++
> >  1 files changed, 632 insertions(+), 0 deletions(-)
> >  create mode 100644 sound/compress_offload/core.c
> > 
> > diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
> > new file mode 100644
> > index 0000000..1797dba
> > --- /dev/null
> > +++ b/sound/compress_offload/core.c
> > @@ -0,0 +1,632 @@
> 
> > +unsigned int snd_compr_poll(struct file *f, poll_table *wait)
> > +{
> > +	struct snd_ioctl_data *data = f->private_data;
> > +	struct snd_compr_stream *stream;
> > +
> > +	BUG_ON(!data);
> > +	stream = &data->stream;
> > +
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> > +		return -ENXIO;
> > +	poll_wait(f, &stream->runtime->sleep, wait);
> > +
> > +	/* this would change after read is implemented, we would need to
> > +	 * check for direction here */
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> > +		return POLLOUT | POLLWRNORM;
> > +
> > +	return 0;
> > +}
> 
> Do we need to grab any locks here?  I'm also confused about checking for
> != SNDRV_PCM_STATE_RUNNING and only then returning POLLOUT | POLLWRNORM.
> Shouldn't the normal cycle be write->start->poll->write->poll->...?  At
> the moment, the state won't change and for this cycle to be effective we
> have to call stop/drain in between.  Am I missing something?
My original intention (and in staging sst driver), was state changes
when poll is woken up, but I agree in above case it is not true. I will
fix this

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-02  6:06 ` [RFC 4/5] compress: add the core file Vinod Koul
                     ` (3 preceding siblings ...)
  2011-09-08 10:38   ` Dimitris Papastamos
@ 2011-09-22 13:01   ` Dimitris Papastamos
  2011-09-23  5:41     ` Vinod Koul
  4 siblings, 1 reply; 133+ messages in thread
From: Dimitris Papastamos @ 2011-09-22 13:01 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Fri, Sep 02, 2011 at 11:36:24AM +0530, Vinod Koul wrote:
> This patch ads core.c, the file which implements the ioctls and
> registers the devices
> 
> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> ---
>  sound/compress_offload/core.c |  632 +++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 632 insertions(+), 0 deletions(-)
>  create mode 100644 sound/compress_offload/core.c
> 
> diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
> new file mode 100644
> index 0000000..1797dba
> --- /dev/null
> +++ b/sound/compress_offload/core.c
> @@ -0,0 +1,632 @@

Hi Vinod,

Any chance you could share your latest changes somehow?  It'd be worth
setting up a repository for further development on this.  I've got some
patches sitting locally, some of them are bug fixes, some others are
expected to mess with the API itself.

Thanks for your time,
Dimitris

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-22 13:01   ` Dimitris Papastamos
@ 2011-09-23  5:41     ` Vinod Koul
  2011-09-23 11:07       ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-09-23  5:41 UTC (permalink / raw)
  To: Dimitris Papastamos; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Thu, 2011-09-22 at 14:01 +0100, Dimitris Papastamos wrote:
> 
> Hi Vinod,
> 
> Any chance you could share your latest changes somehow?  It'd be worth
> setting up a repository for further development on this.  I've got some
> patches sitting locally, some of them are bug fixes, some others are
> expected to mess with the API itself.
> 
Sure, let me setup a repo with above patches and current changes.
Btw we have already fixed the comments you and other had given on this
RFC. 

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [RFC 4/5] compress: add the core file
  2011-09-23  5:41     ` Vinod Koul
@ 2011-09-23 11:07       ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-09-23 11:07 UTC (permalink / raw)
  To: Dimitris Papastamos; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Fri, 2011-09-23 at 11:11 +0530, Vinod Koul wrote:
> On Thu, 2011-09-22 at 14:01 +0100, Dimitris Papastamos wrote:
> > 
> > Hi Vinod,
> > 
> > Any chance you could share your latest changes somehow?  It'd be worth
> > setting up a repository for further development on this.  I've got some
> > patches sitting locally, some of them are bug fixes, some others are
> > expected to mess with the API itself.
> > 
> Sure, let me setup a repo with above patches and current changes.
> Btw we have already fixed the comments you and other had given on this
> RFC. 
All,

I am staging the current wip code for compressed path API at
git://git.infradead.org/users/vkoul/snd-compress.git snd_compress

Currently it contains the RFC posted sometime back, fixes identified on
RFC and few during discussion in LPC

Patches/comments are welcome!

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [PATCH 0/6] compress: add compress data API to ALSA kernel
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (5 preceding siblings ...)
  2011-09-02 11:30 ` [RFC 0/5] compress: add compress data API to ALSA kernel Mark Brown
@ 2011-11-22  8:51 ` Vinod Koul
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                     ` (6 more replies)
  2011-11-22  8:51 ` [PATCH 1/6] compress API documentation Vinod Koul
                   ` (5 subsequent siblings)
  12 siblings, 7 replies; 133+ messages in thread
From: Vinod Koul @ 2011-11-22  8:51 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, pierre-louis.bossart

As agreed during the ASoC workshop in May 2011, this set of patches are a
proposal from Intel to add a new compressed data interface to ALSA. This
proposal builds on the existing Intel solution and the experience gathered over
two years with Meego and Android solutions. This proposal is no longer
Intel-specific and was generalized with the addition of a basic core;
codec-related definitions are based on the vendor-neutral OpenMAX AL standard. 

These patches are also availble in git tree:
git://git.infradead.org/users/vkoul/snd-compress.git v2_patches

Changes in v2:
 Fixed the comments revived in v2
 Fixed the comments recieved during LPC discussions
 add support for alsa device registeration
 fix the bugs found in testing

Omair Mohammed Abdullah (1):
  core: add support for compressed devices

Vinod Koul (5):
  compress API documentation
  compress: add compress parameter definations
  compress: add API header and driver header files
  compress: add the core file
  compress: add makefile and kconfig file

 .../sound/alsa/compress/snd_compress_data.txt      |  187 +++++
 include/sound/compress_driver.h                    |  161 ++++
 include/sound/compress_offload.h                   |  150 ++++
 include/sound/core.h                               |    1 +
 include/sound/minors.h                             |    7 +-
 include/sound/snd_compress_params.h                |  395 +++++++++
 sound/Kconfig                                      |    2 +
 sound/Makefile                                     |    3 +-
 sound/compress_offload/Kconfig                     |   17 +
 sound/compress_offload/Makefile                    |    4 +
 sound/compress_offload/core.c                      |  839 ++++++++++++++++++++
 sound/core/sound.c                                 |    6 +
 12 files changed, 1770 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sound/alsa/compress/snd_compress_data.txt
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h
 create mode 100644 include/sound/snd_compress_params.h
 create mode 100644 sound/compress_offload/Kconfig
 create mode 100644 sound/compress_offload/Makefile
 create mode 100644 sound/compress_offload/core.c

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [PATCH 1/6] compress API documentation
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (6 preceding siblings ...)
  2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
@ 2011-11-22  8:51 ` Vinod Koul
  2011-11-22  8:51 ` [PATCH 2/6] core: add support for compressed devices Vinod Koul
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-11-22  8:51 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, pierre-louis.bossart

The patch adds the documentation file explaining the API

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 .../sound/alsa/compress/snd_compress_data.txt      |  187 ++++++++++++++++++++
 1 files changed, 187 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/sound/alsa/compress/snd_compress_data.txt

diff --git a/Documentation/sound/alsa/compress/snd_compress_data.txt b/Documentation/sound/alsa/compress/snd_compress_data.txt
new file mode 100644
index 0000000..98e2cc9
--- /dev/null
+++ b/Documentation/sound/alsa/compress/snd_compress_data.txt
@@ -0,0 +1,187 @@
+		snd_compress_data.txt
+		=====================
+	Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+		Vinod Koul <vinod.koul@linux.intel.com>
+
+Overview
+
+Since its early days, the ALSA API was defined with PCM support or
+constant bitrates payloads such as IEC61937 in mind. Arguments and
+returned values in frames are the norm, making it a challenge to
+extend the existing API to compressed data streams.
+
+In recent years, audio digital signal processors (DSP) were integrated
+in system-on-chip designs, and DSPs are also integrated in audio
+codecs. Processing compressed data on such DSPs results in a dramatic
+reduction of power consumption compared to host-based
+processing. Support for such hardware has not been very good in Linux,
+mostly because of a lack of a generic API available in the mainline
+kernel.
+
+Rather than requiring a compability break with an API change of the
+ALSA PCM interface, a new 'Compressed Data' API is introduced to
+provide a control and data-streaming interface for audio DSPs.
+
+The design of this API was inspired by the 2-year experience with the
+Intel Moorestown SOC, with many corrections required to upstream the
+API in the mainline kernel instead of the staging tree and make it
+usable by others.
+
+Requirements
+
+The main requirements are:
+
+- separation between byte counts and time. Compressed formats may have
+  a header per file, per frame, or no header at all. The payload size
+  may vary from frame-to-frame. As a result, it is not possible to
+  estimate reliably the duration of audio buffers when handling
+  compressed data. Dedicated mechanisms are required to allow for
+  reliable audio-video synchronization, which requires precise
+  reporting of the number of samples rendered at any given time.
+
+- Handling of multiple formats. PCM data only requires a specification
+  of the sampling rate, number of channels and bits per sample. In
+  contrast, compressed data comes in a variety of formats. Audio DSPs
+  may also provide support for a limited number of audio encoders and
+  decoders embedded in firmware, or may support more choices through
+  dynamic download of libraries.
+
+- Focus on main formats. This API provides support for the most
+  popular formats used for audio and video capture and playback. It is
+  likely that as audio compression technology advances, new formats
+  will be added.
+
+- Handling of multiple configurations. Even for a given format like
+  AAC, some implementations may support AAC multichannel but HE-AAC
+  stereo. Likewise WMA10 level M3 may require too much memory and cpu
+  cycles. The new API needs to provide a generic way of listing these
+  formats.
+
+- Rendering/Grabbing only. This API does not provide any means of
+  hardware acceleration, where PCM samples are provided back to
+  user-space for additional processing. This API focuses instead on
+  streaming compressed data to a DSP, with the assumption that the
+  decoded samples are routed to a physical output or logical back-end.
+
+ - Complexity hiding. Existing user-space multimedia frameworks all
+  have existing enums/structures for each compressed format. This new
+  API assumes the existence of a platform-specific compatibility layer
+  to expose, translate and make use of the capabilities of the audio
+  DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
+  applications are not supposed to make use of this API.
+
+
+Design
+
+The new API shares a number of concepts with with the PCM API for flow
+control. Start, pause, resume, drain and stop commands have the same
+semantics no matter what the content is.
+
+The concept of memory ring buffer divided in a set of fragments is
+borrowed from the ALSA PCM API. However, only sizes in bytes can be
+specified.
+
+Seeks/trick modes are assumed to be handled by the host.
+
+The notion of rewinds/forwards is not supported. Data committed to the
+ring buffer cannot be invalidated, except when dropping all buffers.
+
+The Compressed Data API does not make any assumptions on how the data
+is transmitted to the audio DSP. DMA transfers from main memory to an
+embedded audio cluster or to a SPI interface for external DSPs are
+possible. As in the ALSA PCM case, a core set of routines is exposed;
+each driver implementer will have to write support for a set of
+mandatory routines and possibly make use of optional ones.
+
+The main additions are
+
+- get_codecs
+This routine returns the list of audio formats supported. Querying the
+codecs on a capture stream will return encoders, decoders will be
+listed for playback streams.
+
+- get_codec_caps
+For each codec, this routine returns a list of capabilities. The
+intent is to make sure all the capabilities correspond to valid
+settings, and to minimize the risks of configuration failures. For
+example, for a complex codec such as AAC, the number of channels
+supported may depend on a specific profile. If the capabilities were
+exposed with a single descriptor, it may happen that a specific
+combination of profiles/channels/formats may not be
+supported. Likewise, embedded DSPs have limited memory and cpu cycles,
+it is likely that some implementations make the list of capabilities
+dynamic and dependent on existing workloads.
+
+- set_params
+This routine sets the configuration chosen for a specific codec. The
+most important field in the parameters is the codec type; in most
+cases decoders will ignore other fields, while encoders will strictly
+comply to the settings
+
+- get_params
+This routines returns the actual settings used by the DSP. Changes to
+the settings should remain the exception.
+
+- get_timestamp
+The timestamp becomes a multiple field structure. It lists the number
+of bytes transferred, the number of samples processed and the number
+of samples rendered/grabbed. All these values can be used to determine
+the avarage bitrate, figure out if the ring buffer needs to be
+refilled or the delay due to decoding/encoding/io on the DSP.
+
+Note that the list of codecs/profiles/modes was derived from the
+OpenMAX AL specification instead of reinventing the wheel.
+Modifications include:
+- Addition of FLAC and IEC formats
+- Merge of encoder/decoder capabilities
+- Profiles/modes listed as bitmasks to make descriptors more compact
+- Addition of set_params for decoders (missing in OpenMAX AL)
+- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
+- Addition of format information for WMA
+- Addition of encoding options when required (derived from OpenMAX IL)
+- Addition of rateControlSupported (missing in OpenMAX AL)
+
+Not supported:
+
+- Support for VoIP/circuit-switched calls is not the target of this
+  API. Support for dynamic bit-rate changes would require a tight
+  coupling between the DSP and the host stack, limiting power savings.
+
+- Packet-loss concealment is not supported. This would require an
+  additional interface to let the decoder synthesize data when frames
+  are lost during transmission. This may be added in the future.
+
+- Volume control/routing is not handled by this API. Devices exposing a
+  compressed data interface will be considered as regular ALSA devices
+
+Instead,
+  offloaded processing will be considered as regular ALSA devices;
+  volume changes and routing information will be provided with regular
+  ALSA kcontrols.
+
+- Embedded audio effects. Such effects should be enabled in the same
+  manner, no matter if the input was PCM or compressed.
+
+- multichannel IEC encoding. Unclear if this is required.
+
+- Encoding/decoding acceleration is not supported as mentioned
+  above. It is possible to route the output of a decoder to a capture
+  stream, or even implement transcoding capabilities. This routing
+  would be enabled with ALSA kcontrols.
+
+- Audio policy/resource management. This API does not provide any
+  hooks to query the utilization of the audio DSP, nor any premption
+  mechanisms.
+
+- No notion of underun/overrun. Since the bytes written are compressed
+  in nature and data written/read doesn't translate directly to
+  rendered output in time, this does not deal with underrun/overun and
+  maybe dealt in user-library
+
+Credits:
+- Mark Brown and Liam Girdwood for discussions on the need for this API
+- Harsha Priya for her work on intel_sst compressed API
+- Rakesh Ughreja for valuable feedback
+- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
+  demonstrating and quantifying the benefits of audio offload on a
+  real platform.
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH 2/6] core: add support for compressed devices
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (7 preceding siblings ...)
  2011-11-22  8:51 ` [PATCH 1/6] compress API documentation Vinod Koul
@ 2011-11-22  8:51 ` Vinod Koul
  2011-11-23 11:30   ` Mark Brown
  2011-11-22  8:51 ` [PATCH 3/6] compress: add compress parameter definations Vinod Koul
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-11-22  8:51 UTC (permalink / raw)
  To: alsa-devel
  Cc: Vinod Koul, tiwai, broonie, pierre-louis.bossart,
	Omair Mohammed Abdullah, lrg

From: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>

Use the two minor numbers 2 and 3 for audio compressed offload devices.
Also add support for these devices in core

Signed-off-by: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 include/sound/core.h   |    1 +
 include/sound/minors.h |    7 ++++++-
 sound/core/sound.c     |    6 ++++++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/include/sound/core.h b/include/sound/core.h
index 1fa2407..9d1e54b 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -62,6 +62,7 @@ typedef int __bitwise snd_device_type_t;
 #define	SNDRV_DEV_BUS		((__force snd_device_type_t) 0x1007)
 #define	SNDRV_DEV_CODEC		((__force snd_device_type_t) 0x1008)
 #define	SNDRV_DEV_JACK          ((__force snd_device_type_t) 0x1009)
+#define	SNDRV_DEV_COMPRESS	((__force snd_device_type_t) 0x100A)
 #define	SNDRV_DEV_LOWLEVEL	((__force snd_device_type_t) 0x2000)
 
 typedef int __bitwise snd_device_state_t;
diff --git a/include/sound/minors.h b/include/sound/minors.h
index 8f76420..faaeb64 100644
--- a/include/sound/minors.h
+++ b/include/sound/minors.h
@@ -35,7 +35,8 @@
 #define SNDRV_MINOR_TIMER		33	/* SNDRV_MINOR_GLOBAL + 1 * 32 */
 
 #ifndef CONFIG_SND_DYNAMIC_MINORS
-						/* 2 - 3 (reserved) */
+#define SNDRV_MINOR_COMPR_PLAYBACK	2
+#define SNDRV_MINOR_COMPR_CAPTURE	3
 #define SNDRV_MINOR_HWDEP		4	/* 4 - 7 */
 #define SNDRV_MINOR_RAWMIDI		8	/* 8 - 15 */
 #define SNDRV_MINOR_PCM_PLAYBACK	16	/* 16 - 23 */
@@ -49,6 +50,8 @@
 #define SNDRV_DEVICE_TYPE_PCM_CAPTURE	SNDRV_MINOR_PCM_CAPTURE
 #define SNDRV_DEVICE_TYPE_SEQUENCER	SNDRV_MINOR_SEQUENCER
 #define SNDRV_DEVICE_TYPE_TIMER		SNDRV_MINOR_TIMER
+#define SNDRV_DEVICE_TYPE_COMPR_PLAYBACK SNDRV_MINOR_COMPR_PLAYBACK
+#define SNDRV_DEVICE_TYPE_COMPR_CAPTURE	SNDRV_MINOR_COMPR_CAPTURE
 
 #else /* CONFIG_SND_DYNAMIC_MINORS */
 
@@ -60,6 +63,8 @@ enum {
 	SNDRV_DEVICE_TYPE_RAWMIDI,
 	SNDRV_DEVICE_TYPE_PCM_PLAYBACK,
 	SNDRV_DEVICE_TYPE_PCM_CAPTURE,
+	SNDRV_DEVICE_TYPE_COMPR_PLAYBACK,
+	SNDRV_DEVICE_TYPE_COMPR_CAPTURE,
 };
 
 #endif /* CONFIG_SND_DYNAMIC_MINORS */
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 1c7a3ef..9377807 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -233,6 +233,12 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
 			return -EINVAL;
 		minor = SNDRV_MINOR(card->number, type + dev);
 		break;
+	case SNDRV_DEVICE_TYPE_COMPR_PLAYBACK:
+	case SNDRV_DEVICE_TYPE_COMPR_CAPTURE:
+		if (snd_BUG_ON(!card))
+			return -EINVAL;
+		minor = SNDRV_MINOR(card->number, type);
+		break;
 	default:
 		return -EINVAL;
 	}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH 3/6] compress: add compress parameter definations
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (8 preceding siblings ...)
  2011-11-22  8:51 ` [PATCH 2/6] core: add support for compressed devices Vinod Koul
@ 2011-11-22  8:51 ` Vinod Koul
  2011-11-23 16:32   ` Mark Brown
  2011-11-22  8:51 ` [PATCH 4/6] compress: add API header and driver header files Vinod Koul
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-11-22  8:51 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, pierre-louis.bossart

The patch adds the various definations used to define the encoder and decoder
parameters

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 include/sound/snd_compress_params.h |  395 +++++++++++++++++++++++++++++++++++
 1 files changed, 395 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/snd_compress_params.h

diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
new file mode 100644
index 0000000..79b681d
--- /dev/null
+++ b/include/sound/snd_compress_params.h
@@ -0,0 +1,395 @@
+/*
+ *  snd_compress_params.h - codec types and parameters for compressed data
+ *  streaming interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *              Vinod Koul <vinod.koul@linux.intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The definitions in this file are derived from the OpenMAX AL version 1.1
+ * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
+ *
+ * Copyright (c) 2007-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and/or associated documentation files (the
+ * "Materials "), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+#ifndef __SND_COMPRESS_PARAMS_H
+#define __SND_COMPRESS_PARAMS_H
+
+/* AUDIO CODECS SUPPORTED */
+#define MAX_NUM_CODECS 32
+#define MAX_NUM_CODEC_DESCRIPTORS 32
+#define MAX_NUM_BITRATES 32
+
+/* Codecs are listed linearly to allow for extensibility */
+#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
+#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
+#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
+#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
+#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
+#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
+#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
+#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
+#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
+#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
+#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
+#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
+#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
+
+/*
+ * Profile and modes are listed with bit masks. This allows for a
+ * more compact representation of fields that will not evolve
+ * (in contrast to the list of codecs)
+ */
+
+#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
+
+/* MP3 modes are only useful for encoders */
+#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
+#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
+#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
+#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
+
+/* AMR modes are only useful for encoders */
+#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
+
+#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
+#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
+
+#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
+
+/* AMRWB modes are only useful for encoders */
+#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
+
+/* AAC modes are required for encoders and decoders */
+#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
+#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
+#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
+#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
+#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
+#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
+#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
+
+/* AAC formats are required for encoders and decoders */
+#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
+#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
+
+#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
+#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
+#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
+#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
+
+#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
+#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
+#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
+#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
+#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
+#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
+#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
+
+#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
+/*
+ * Some implementations strip the ASF header and only send ASF packets
+ * to the DSP
+ */
+#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
+
+#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
+#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
+
+/*
+ * Define quality levels for FLAC encoders, from LEVEL0 (fast)
+ * to LEVEL8 (best)
+ */
+#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
+#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
+#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
+#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
+#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
+#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
+#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
+
+#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
+
+/* IEC61937 payloads without CUVP and preambles */
+#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
+/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
+#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
+
+/*
+ * IEC modes are mandatory for decoders. Format autodetection
+ * will only happen on the DSP side with mode 0. The PCM mode should
+ * not be used, the PCM codec should be used instead.
+ */
+#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
+#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
+#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
+#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
+#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
+#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
+#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
+#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
+#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
+#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
+#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
+#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
+#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
+#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
+#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
+#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
+#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
+#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
+#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
+
+#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
+#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
+
+/* <FIXME: multichannel encoders aren't supported for now. Would need
+   an additional definition of channel arrangement> */
+
+/* VBR/CBR definitions */
+#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
+#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
+
+/* Encoder options */
+
+struct snd_enc_wma {
+	__u32 super_block_align; /* WMA Type-specific data */
+};
+
+
+/**
+ * struct snd_enc_vorbis
+ * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
+ * In the default mode of operation, the quality level is 3.
+ * Normal quality range is 0 - 10.
+ * @managed: Boolean. Set  bitrate  management  mode. This turns off the
+ * normal VBR encoding, but allows hard or soft bitrate constraints to be
+ * enforced by the encoder. This mode can be slower, and may also be
+ * lower quality. It is primarily useful for streaming.
+ * @max_bit_rate: Enabled only if managed is TRUE
+ * @min_bit_rate: Enabled only if managed is TRUE
+ * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
+ * non-stereo streams). Useful for lower-bitrate encoding.
+ *
+ * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
+ * properties
+ *
+ * For best quality users should specify VBR mode and set quality levels.
+ */
+
+struct snd_enc_vorbis {
+	int quality;
+	__u32 managed;
+	__u32 max_bit_rate;
+	__u32 min_bit_rate;
+	__u32 downmix;
+};
+
+
+/**
+ * struct snd_enc_real
+ * @quant_bits: number of coupling quantization bits in the stream
+ * @start_region: coupling start region in the stream
+ * @num_regions: number of regions value
+ *
+ * These options were extracted from the OpenMAX IL spec
+ */
+
+struct snd_enc_real {
+	__u32 quant_bits;
+	__u32 start_region;
+	__u32 num_regions;
+};
+
+/**
+ * struct snd_enc_flac
+ * @num: serial number, valid only for OGG formats
+ *	needs to be set by application
+ * @gain: Add replay gain tags
+ *
+ * These options were extracted from the FLAC online documentation
+ * at http://flac.sourceforge.net/documentation_tools_flac.html
+ *
+ * To make the API simpler, it is assumed that the user will select quality
+ * profiles. Additional options that affect encoding quality and speed can
+ * be added at a later stage if needed.
+ *
+ * By default the Subset format is used by encoders.
+ *
+ * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
+ * not supported in this API.
+ */
+
+struct snd_enc_flac {
+	__u32 num;
+	__u32 gain;
+};
+
+struct snd_enc_generic {
+	__u32 bw;	/* encoder bandwidth */
+	int reserved[15];
+};
+
+union snd_codec_options {
+	struct snd_enc_wma wma;
+	struct snd_enc_vorbis vorbis;
+	struct snd_enc_real real;
+	struct snd_enc_flac flac;
+	struct snd_enc_generic generic;
+};
+
+/** struct snd_codec_desc - description of codec capabilities
+ * @max_ch: Maximum number of audio channels
+ * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
+ * @bit_rate: Indexed array containing supported bit rates
+ * @num_bitrates: Number of valid values in bit_rate array
+ * @rate_control: value is specified by SND_RATECONTROLMODE defines.
+ * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
+ * @modes: Supported modes. See SND_AUDIOMODE defines
+ * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
+ * @reserved: reserved for future use
+ *
+ * This structure provides a scalar value for profiles, modes and stream
+ * format fields.
+ * If an implementation supports multiple combinations, they will be listed as
+ * codecs with different descriptors, for example there would be 2 descriptors
+ * for AAC-RAW and AAC-ADTS.
+ * This entails some redundancy but makes it easier to avoid invalid
+ * configurations.
+ *
+ */
+
+struct snd_codec_desc {
+	__u32 max_ch;
+	__u32 sample_rates;
+	__u32 bit_rate[MAX_NUM_BITRATES];
+	__u32 num_bitrates;
+	__u32 rate_control;
+	__u32 profiles;
+	__u32 modes;
+	__u32 formats;
+	__u32 reserved[16];
+};
+
+/** struct snd_codec
+ * @id: Identifies the supported audio encoder/decoder.
+ *		See SND_AUDIOCODEC macros.
+ * @ch_in: Number of input audio channels
+ * @ch_out: Number of output channels. In case of contradiction between
+ *		this field and the channelMode field, the channelMode field
+ *		overrides.
+ * @sample_rate: Audio sample rate of input data
+ * @bit_rate: Bitrate of encoded data. May be ignored by decoders
+ * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
+ *               Encoders may rely on profiles for quality levels.
+ *		 May be ignored by decoders.
+ * @profile: Mandatory for encoders, can be mandatory for specific
+ *		decoders as well. See SND_AUDIOPROFILE defines.
+ * @level: Supported level (Only used by WMA at the moment)
+ * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
+ * @format: Format of encoded bistream. Mandatory when defined.
+ *		See SND_AUDIOSTREAMFORMAT defines.
+ * @align: Block alignment in bytes of an audio sample.
+ *		Only required for PCM or IEC formats.
+ * @options: encoder-specific settings
+ * @reserved: reserved for future use
+ */
+
+struct snd_codec {
+	__u32 id;
+	__u32 ch_in;
+	__u32 ch_out;
+	__u32 sample_rate;
+	__u32 bit_rate;
+	__u32 rate_control;
+	__u32 profile;
+	__u32 level;
+	__u32 ch_mode;
+	__u32 format;
+	__u32 align;
+	union snd_codec_options options;
+	__u32 reserved[3];
+};
+
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH 4/6] compress: add API header and driver header files
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (9 preceding siblings ...)
  2011-11-22  8:51 ` [PATCH 3/6] compress: add compress parameter definations Vinod Koul
@ 2011-11-22  8:51 ` Vinod Koul
  2011-11-22 11:18   ` Clemens Ladisch
  2011-12-02 15:39   ` Nallasellan, Singaravelan
  2011-11-22  8:51 ` [PATCH 5/6] compress: add the core file Vinod Koul
  2011-11-22  8:52 ` [PATCH 6/6] compress: add makefile and kconfig file Vinod Koul
  12 siblings, 2 replies; 133+ messages in thread
From: Vinod Koul @ 2011-11-22  8:51 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, pierre-louis.bossart

This patch adds the header files for ioctl definations and header file for
driver APIs for lower level device drivers to use

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 include/sound/compress_driver.h  |  161 ++++++++++++++++++++++++++++++++++++++
 include/sound/compress_offload.h |  150 +++++++++++++++++++++++++++++++++++
 2 files changed, 311 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h

diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
new file mode 100644
index 0000000..2de4cf6
--- /dev/null
+++ b/include/sound/compress_driver.h
@@ -0,0 +1,161 @@
+/*
+ *  compress_driver.h - compress offload driver definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_DRIVER_H
+#define __COMPRESS_DRIVER_H
+
+#include <sound/compress_offload.h>
+#include <sound/asound.h>
+#include <sound/pcm.h>
+
+struct snd_compr_ops;
+
+/**
+ * struct snd_compr_runtime: runtime stream description
+ * @state: stream state
+ * @ops: pointer to DSP callbacks
+ * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
+ *	DSP doesn't implement copy
+ * @buffer_size: size of the above buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ * @hw_pointer: offset of last location in buffer where DSP copied data
+ * @app_pointer: offset of last location in buffer where app wrote data
+ * @bytes_written: cummilative bytes written to device
+ * @bytes_copied: cummilative bytes copied by DSP
+ * @sleep: poll sleep
+ */
+struct snd_compr_runtime {
+	snd_pcm_state_t state;
+	struct snd_compr_ops *ops;
+	void *buffer;
+	size_t buffer_size;
+	size_t fragment_size;
+	unsigned int fragments;
+	size_t hw_pointer;
+	size_t app_pointer;
+	size_t bytes_written;
+	size_t bytes_copied;
+	wait_queue_head_t sleep;
+};
+
+/**
+ * struct snd_compr_stream: compressed stream
+ * @name: device name
+ * @ops: pointer to DSP callbacks
+ * @runtime: pointer to runtime structure
+ * @device: device pointer
+ * @direction: stream direction, playback/recording
+ * @private_data: pointer to DSP private data
+ */
+struct snd_compr_stream {
+	const char *name;
+	struct snd_compr_ops *ops;
+	struct snd_compr_runtime *runtime;
+	struct snd_compr *device;
+	unsigned int direction;
+	void *private_data;
+};
+
+/**
+ * struct snd_compr_ops: compressed path DSP operations
+ * @open: Open the compressed stream
+ * This callback is mandatory and shall keep dsp ready to receive the stream
+ * parameter
+ * @free: Close the compressed stream, mandatory
+ * @set_params: Sets the compressed stream parameters, mandatory
+ * This can be called in during stream creation only to set codec params
+ * and the stream properties
+ * @get_params: retrieve the codec parameters, mandatory
+ * @trigger: Trigger operations like start, pause, resume, drain, stop.
+ * This callback is mandatory
+ * @pointer: Retrieve current h/w pointer information. Mandatory
+ * @copy: Copy the compressed data to/from userspace, Optional
+ * Can't be implemented if DSP supports mmap
+ * @mmap: DSP mmap method to mmap DSP memory
+ * @ack: Ack for DSP when data is written to audio buffer, Optional
+ * Not valid if copy is implemented
+ * @get_caps: Retrieve DSP capabilities, mandatory
+ * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory
+ */
+struct snd_compr_ops {
+	int (*open)(struct snd_compr_stream *stream);
+	int (*free)(struct snd_compr_stream *stream);
+	int (*set_params)(struct snd_compr_stream *stream,
+			struct snd_compr_params *params);
+	int (*get_params)(struct snd_compr_stream *stream,
+			struct snd_compr_params *params);
+	int (*trigger)(struct snd_compr_stream *stream, int cmd);
+	int (*pointer)(struct snd_compr_stream *stream,
+			struct snd_compr_tstamp *tstamp);
+	int (*copy)(struct snd_compr_stream *stream, const char __user *buf,
+		       size_t count);
+	int (*mmap)(struct snd_compr_stream *stream,
+			struct vm_area_struct *vma);
+	int (*ack)(struct snd_compr_stream *stream, size_t bytes);
+	int (*get_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_caps *caps);
+	int (*get_codec_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_codec_caps *codec);
+};
+
+/**
+ * struct snd_compr: Compressed device
+ * @name: DSP device name
+ * @pb: playback devices supported
+ * @cap: capture devices supported
+ * @dev: Device pointer
+ * @ops: pointer to DSP callbacks
+ * @private_data: pointer to DSP pvt data
+ * @card: sound card pointer
+ * @lock: device lock
+ * @device: device id
+ */
+struct snd_compr {
+	const char *name;
+	unsigned int pb;
+	unsigned int cap;
+	struct device *dev;
+	struct snd_compr_ops *ops;
+	void *private_data;
+	struct snd_card *card;
+	struct mutex lock;
+	int device;
+};
+
+/* compress device register APIs */
+int snd_compress_register(struct snd_compr *device);
+int snd_compress_deregister(struct snd_compr *device);
+
+/* dsp driver callback apis
+ * For playback: driver should call snd_compress_fragment_elapsed() to let the
+ * framework know that a fragment has been consumed from the ring buffer
+ * For recording: we may want to know when a frame is available or when
+ * at least one frame is available for userspace, a different
+ * snd_compress_frame_elapsed() callback should be used
+ */
+void snd_compr_fragment_elapsed(struct snd_compr_stream *stream);
+void snd_compr_frame_elapsed(struct snd_compr_stream *stream);
+
+#endif
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
new file mode 100644
index 0000000..8a868f3
--- /dev/null
+++ b/include/sound/compress_offload.h
@@ -0,0 +1,150 @@
+/*
+ *  compress_offload.h - compress offload header definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_OFFLOAD_H
+#define __COMPRESS_OFFLOAD_H
+
+#include <linux/types.h>
+#include <sound/asound.h>
+#include <sound/snd_compress_params.h>
+
+
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
+/**
+ * struct snd_compressed_buffer: compressed buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ */
+struct snd_compressed_buffer {
+	size_t fragment_size;
+	int fragments;
+};
+
+/**
+ * struct snd_compr_params: compressed stream params
+ * @buffer: buffer description
+ * @codec: codec parameters
+ * @no_wake_mode: dont wake on fragment elapsed
+ */
+struct snd_compr_params {
+	struct snd_compressed_buffer buffer;
+	struct snd_codec codec;
+	bool no_wake_mode;
+};
+
+/**
+ * struct snd_compr_tstamp: timestamp descriptor
+ * @copied_bytes: Number of bytes offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from ring buffer to DSP
+ * @decoded: Frames decoded by DSP
+ * @rendered: Frames rendered by DSP into a mixer or an audio output
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp {
+	size_t copied_bytes;
+	size_t copied_total;
+	size_t decoded;
+	size_t rendered;
+	__u32 sampling_rate;
+};
+
+/**
+ * struct snd_compr_avail: avail descriptor
+ * @avail: Number of bytes available in ring buffer for writing/reading
+ * @tstamp: timestamp infomation
+ */
+struct snd_compr_avail {
+	size_t avail;
+	struct snd_compr_tstamp tstamp;
+};
+
+/**
+ * struct snd_compr_caps: caps descriptor
+ * @codecs: pointer to array of codecs
+ * @min_fragment_size: minimum fragment supported by DSP
+ * @max_fragment_size: maximum fragment supported by DSP
+ * @min_fragments: min fragments supported by DSP
+ * @max_fragments: max fragments supported by DSP
+ * @num_codecs: number of codecs supported
+ * @reserved: reserved field
+ */
+struct snd_compr_caps {
+	__u32 num_codecs;
+	__u32 min_fragment_size;
+	__u32 max_fragment_size;
+	__u32 min_fragments;
+	__u32 max_fragments;
+	__u32 codecs[MAX_NUM_CODECS];
+	__u32 reserved[11];
+};
+
+/**
+ * struct snd_compr_codec_caps: query capability of codec
+ * @codec: codec for which capability is queried
+ * @num_descriptors: number of codec descriptors
+ * @descriptor: array of codec capability descriptor
+ */
+struct snd_compr_codec_caps {
+	__u32 codec;
+	__u32 num_descriptors;
+	struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
+};
+
+/**
+ * compress path ioctl definitions
+ * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
+ * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
+ * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
+ * Note: only codec params can be changed runtime and stream params cant be
+ * SNDRV_COMPRESS_GET_PARAMS: Query codec and stream params
+ * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
+ * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
+ * This also queries the tstamp properties
+ * SNDRV_COMPRESS_PAUSE: Pause the running stream
+ * SNDRV_COMPRESS_RESUME: resume a paused stream
+ * SNDRV_COMPRESS_START: Start a stream
+ * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
+ * and the buffers currently with DSP
+ * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
+ * SNDRV_COMPRESS_IOCTL_VERSION: Query the API version
+ */
+#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x00, struct snd_compr_caps *)
+#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x01, struct snd_compr_codec_caps *)
+#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x02, struct snd_compr_params *)
+#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x03, struct snd_compr_params *)
+#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x10, struct snd_compr_tstamp *)
+#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x11, struct snd_compr_avail *)
+#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x20)
+#define SNDRV_COMPRESS_RESUME		_IO('C', 0x21)
+#define SNDRV_COMPRESS_START		_IO('C', 0x22)
+#define SNDRV_COMPRESS_STOP		_IO('C', 0x23)
+#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x24)
+#define SNDRV_COMPRESS_IOCTL_VERSION	_IOR('C', 0x30, int)
+/*
+ * TODO
+ * 1. add mmap support
+ *
+ */
+#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH 5/6] compress: add the core file
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (10 preceding siblings ...)
  2011-11-22  8:51 ` [PATCH 4/6] compress: add API header and driver header files Vinod Koul
@ 2011-11-22  8:51 ` Vinod Koul
  2011-11-23 16:02   ` Mark Brown
                     ` (2 more replies)
  2011-11-22  8:52 ` [PATCH 6/6] compress: add makefile and kconfig file Vinod Koul
  12 siblings, 3 replies; 133+ messages in thread
From: Vinod Koul @ 2011-11-22  8:51 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, pierre-louis.bossart

This patch adds core.c, the file which implements the ioctls and
registers the devices

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/compress_offload/core.c |  839 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 839 insertions(+), 0 deletions(-)
 create mode 100644 sound/compress_offload/core.c

diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
new file mode 100644
index 0000000..34355ea
--- /dev/null
+++ b/sound/compress_offload/core.c
@@ -0,0 +1,839 @@
+/*
+ *  core.c - compress offload core
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pirete-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
+#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+
+/* TODO:
+ * - add substream support for multiple devices in case of
+ *	SND_DYNAMIC_MINORS is not used
+ * - Integrate with ASoC:
+ *	Opening compressed path should also start the codec dai
+ *   TBD how the cpu dai will be viewed and started.
+ *	ASoC should always be optional part
+ *	(we should be able to use this framework in non asoc systems
+ * - Multiple node representation
+ *	driver should be able to register multiple nodes
+ */
+
+static DEFINE_MUTEX(device_mutex);
+
+struct snd_compr_file {
+	unsigned long caps;
+	struct snd_compr_stream stream;
+};
+
+static int snd_compr_open(struct file *f,  struct snd_compr *compr, int type)
+{
+	struct snd_compr_file *data;
+	struct snd_compr_runtime *runtime;
+	int ret;
+
+	mutex_lock(&device_mutex);
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	data->stream.ops = compr->ops;
+	data->stream.direction = type;
+	data->stream.private_data = compr->private_data;
+	data->stream.device = compr;
+	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+	if (!runtime) {
+		ret = -ENOMEM;
+		kfree(data);
+		goto out;
+	}
+	runtime->state = SNDRV_PCM_STATE_OPEN;
+	init_waitqueue_head(&runtime->sleep);
+	data->stream.runtime = runtime;
+	f->private_data = (void *)data;
+	ret = compr->ops->open(&data->stream);
+	if (ret) {
+		kfree(runtime);
+		kfree(data);
+		goto out;
+	}
+out:
+	mutex_unlock(&device_mutex);
+	return ret;
+}
+
+static int snd_compr_pb_open(struct inode *inode, struct file *f)
+{
+	unsigned int maj = imajor(inode);
+	struct snd_compr *compr;
+
+	if (maj == snd_major)
+		compr = snd_lookup_minor_data(iminor(inode),
+			SNDRV_DEVICE_TYPE_COMPR_PLAYBACK);
+	else
+		return -ENXIO;
+
+	if (compr == NULL)
+		return -ENODEV;
+
+	if (!(f->f_flags & O_WRONLY))
+		return -EINVAL;
+
+	return snd_compr_open(f, compr, SNDRV_DEVICE_TYPE_COMPR_PLAYBACK);
+}
+
+static int snd_compr_cap_open(struct inode *inode, struct file *f)
+{
+	unsigned int maj = imajor(inode);
+	struct snd_compr *compr;
+
+	if (maj == snd_major)
+		compr = snd_lookup_minor_data(iminor(inode),
+			SNDRV_DEVICE_TYPE_COMPR_CAPTURE);
+	else
+		return -ENXIO;
+
+	if (compr == NULL)
+		return -ENODEV;
+
+	if (!(f->f_flags & O_RDONLY))
+		return -EINVAL;
+
+	return snd_compr_open(f, compr, SNDRV_DEVICE_TYPE_COMPR_CAPTURE);
+}
+
+static int snd_compr_free(struct inode *inode, struct file *f)
+{
+	struct snd_compr_file *data = f->private_data;
+	mutex_lock(&device_mutex);
+	data->stream.ops->free(&data->stream);
+	kfree(data->stream.runtime->buffer);
+	kfree(data->stream.runtime);
+	kfree(data);
+	mutex_unlock(&device_mutex);
+	return 0;
+}
+
+static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
+		struct snd_compr_tstamp *tstamp)
+{
+	stream->ops->pointer(stream, tstamp);
+	pr_debug("dsp consumed till %d total %d bytes\n",
+		tstamp->copied_bytes, tstamp->copied_total);
+	stream->runtime->hw_pointer = tstamp->copied_bytes;
+	stream->runtime->bytes_copied = tstamp->copied_total;
+}
+
+static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
+		struct snd_compr_avail *avail)
+{
+	long avail_calc; /*this needs to be signed variable */
+
+	snd_compr_update_tstamp(stream, &avail->tstamp);
+
+	if (stream->runtime->bytes_written == 0 &&
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+		pr_debug("detected init and someone forgot to do a write\n");
+		return stream->runtime->buffer_size;
+	}
+	pr_debug("app wrote %d, DSP consumed %d\n",
+		stream->runtime->bytes_written, stream->runtime->bytes_copied);
+	if (stream->runtime->bytes_written == stream->runtime->bytes_copied) {
+		pr_debug("both pointers are same, returning full avail\n");
+		return stream->runtime->buffer_size;
+	}
+
+	avail_calc = stream->runtime->buffer_size -
+		(stream->runtime->app_pointer - stream->runtime->hw_pointer);
+	pr_debug("calc avail as %ld, app_ptr %d, hw+ptr %d\n", avail_calc,
+		stream->runtime->app_pointer, stream->runtime->hw_pointer);
+	if (avail_calc >= stream->runtime->buffer_size)
+		avail_calc -= stream->runtime->buffer_size;
+	pr_debug("ret avail as %ld\n", avail_calc);
+	avail->avail = avail_calc;
+	return avail_calc;
+}
+
+static size_t snd_compr_get_avail(struct snd_compr_stream *stream)
+{
+	struct snd_compr_avail avail;
+
+	return snd_compr_calc_avail(stream, &avail);
+}
+
+static int
+snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_avail ioctl_avail;
+
+	snd_compr_calc_avail(stream, &ioctl_avail);
+
+	if (copy_to_user((unsigned long __user *)arg,
+				&ioctl_avail, sizeof(ioctl_avail)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_compr_write_data(struct snd_compr_stream *stream,
+	       const char __user *buf, size_t count)
+{
+	void *dstn;
+	size_t copy;
+	struct snd_compr_runtime *runtime = stream->runtime;
+
+	dstn = runtime->buffer + runtime->app_pointer;
+	pr_debug("copying %d at %d\n", count, runtime->app_pointer);
+	if (count < runtime->buffer_size - runtime->app_pointer) {
+		if (copy_from_user(dstn, buf, count))
+			return -EFAULT;
+		runtime->app_pointer += count;
+	} else {
+		copy = runtime->buffer_size - runtime->app_pointer;
+		if (copy_from_user(dstn, buf, copy))
+			return -EFAULT;
+		if (copy_from_user(runtime->buffer, buf + copy, count - copy))
+			return -EFAULT;
+		runtime->app_pointer = count - copy;
+	}
+	/* if DSP cares, let it know data has been written */
+	if (stream->ops->ack)
+		stream->ops->ack(stream, count);
+	return count;
+}
+
+static ssize_t snd_compr_write(struct file *f, const char __user *buf,
+		size_t count, loff_t *offset)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	mutex_lock(&stream->device->lock);
+	/* write is allowed when stream is running or has been steup */
+	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
+			stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		mutex_unlock(&stream->device->lock);
+		return -EPERM;
+	}
+
+	avail = snd_compr_get_avail(stream);
+	pr_debug("avail returned %d\n", avail);
+	/* calculate how much we can write to buffer */
+	if (avail > count)
+		avail = count;
+
+	if (stream->ops->copy)
+		retval = stream->ops->copy(stream, buf, avail);
+	else
+		retval = snd_compr_write_data(stream, buf, avail);
+	if (retval > 0)
+		stream->runtime->bytes_written += retval;
+
+	/* while initiating the stream, write should be called before START
+	 * call, so in setup move state */
+	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+		pr_debug("stream prepared, Houston we are good to go\n");
+	}
+
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+
+static ssize_t snd_compr_read(struct file *f, char __user *buf,
+		size_t count, loff_t *offset)
+{
+	return -ENXIO;
+}
+
+static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
+{
+	return -ENXIO;
+}
+
+unsigned int snd_compr_pb_poll(struct file *f, poll_table *wait)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval = 0;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+
+	mutex_lock(&stream->device->lock);
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		retval = -ENXIO;
+		goto out;
+	}
+	poll_wait(f, &stream->runtime->sleep, wait);
+
+	avail = snd_compr_get_avail(stream);
+	pr_debug("avail is %d\n", avail);
+	/* check if we have at least one fragment to fill */
+	switch (stream->runtime->state) {
+	case SNDRV_PCM_STATE_RUNNING:
+	case SNDRV_PCM_STATE_PREPARED:
+	case SNDRV_PCM_STATE_PAUSED:
+		if (avail >= stream->runtime->fragment_size) {
+			retval = POLLOUT | POLLWRNORM;
+			break;
+		}
+		/* Fall through */
+	case SNDRV_PCM_STATE_DRAINING:
+		break;
+	default:
+		retval = POLLOUT | POLLWRNORM | POLLERR;
+		break;
+	}
+out:
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+unsigned int snd_compr_cap_poll(struct file *f, poll_table *wait)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval = 0;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+
+	mutex_lock(&stream->device->lock);
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		retval = -ENXIO;
+		goto out;
+	}
+	poll_wait(f, &stream->runtime->sleep, wait);
+
+	/* this would change after read is implemented, we would need to
+	 * check for direction here */
+	avail = snd_compr_get_avail(stream);
+	pr_debug("avail is %d\n", avail);
+	/* check if we have at least one fragment to fill */
+	switch (stream->runtime->state) {
+	case SNDRV_PCM_STATE_RUNNING:
+	case SNDRV_PCM_STATE_PREPARED:
+	case SNDRV_PCM_STATE_PAUSED:
+		if (avail >= stream->runtime->fragment_size) {
+			retval = POLLIN | POLLRDNORM;
+			break;
+		}
+		/* Fall through */
+	case SNDRV_PCM_STATE_DRAINING:
+		break;
+	default:
+		retval = POLLIN | POLLRDNORM | POLLERR;
+		break;
+	}
+out:
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
+{
+	pr_debug("fragment elapsed called\n");
+	if (stream->direction !=  SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
+		return;
+	wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
+
+void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
+{
+	if (stream->direction != SNDRV_DEVICE_TYPE_COMPR_CAPTURE)
+		return;
+	wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);
+
+static int
+snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_caps caps;
+
+	if (!stream->ops->get_caps)
+		return -ENXIO;
+
+	retval = stream->ops->get_caps(stream, &caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
+		retval = -EFAULT;
+out:
+	return retval;
+}
+
+static int
+snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_codec_caps *caps;
+
+	if (!stream->ops->get_codec_caps)
+		return -ENXIO;
+
+	caps = kmalloc(sizeof(*caps), GFP_KERNEL);
+	if (!caps)
+		return -ENOMEM;
+
+	retval = stream->ops->get_codec_caps(stream, caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
+		retval = -EFAULT;
+
+out:
+	kfree(caps);
+	return retval;
+}
+
+/* revisit this with snd_pcm_preallocate_xxx */
+static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+		struct snd_compr_params *params)
+{
+	unsigned int buffer_size;
+	void *buffer;
+
+	buffer_size = params->buffer.fragment_size * params->buffer.fragments;
+	if (stream->ops->copy) {
+		buffer = NULL;
+		/* if copy is defined the driver will be required to copy
+		 * the data from core
+		 */
+	} else {
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+	}
+	stream->runtime->fragment_size = params->buffer.fragment_size;
+	stream->runtime->fragments = params->buffer.fragments;
+	stream->runtime->buffer = buffer;
+	stream->runtime->buffer_size = buffer_size;
+	return 0;
+}
+
+static int
+snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_params *params;
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+		/*
+		 * we should allow parameter change only when stream has been
+		 * opened not in other cases
+		 */
+		params = kmalloc(sizeof(*params), GFP_KERNEL);
+		if (!params)
+			return -ENOMEM;
+		if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
+			return -EFAULT;
+		retval = snd_compr_allocate_buffer(stream, params);
+		if (retval) {
+			kfree(params);
+			return -ENOMEM;
+		}
+		retval = stream->ops->set_params(stream, params);
+		if (retval)
+			goto out;
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+	} else
+		return -EPERM;
+out:
+	kfree(params);
+	return retval;
+}
+
+static int
+snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_params *params;
+	int retval;
+
+	if (!stream->ops->get_params)
+		return -ENXIO;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+	retval = stream->ops->get_params(stream, params);
+	if (retval)
+		goto out;
+	if (copy_to_user((char __user *)arg, params, sizeof(*params)))
+		retval = -EFAULT;
+
+out:
+	kfree(params);
+	return retval;
+}
+
+static int snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_tstamp tstamp;
+
+	snd_compr_update_tstamp(stream, &tstamp);
+	return copy_to_user((struct snd_compr_tstamp __user *)arg,
+		&tstamp, sizeof(tstamp)) ? -EFAULT : 0;
+}
+
+static int snd_compr_pause(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED)
+		return 0;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_resume(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_start(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
+	stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_stop(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_drain(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED ||
+			stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	int retval = -ENOTTY;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	BUG_ON(!stream);
+	mutex_lock(&stream->device->lock);
+	switch (_IOC_NR(cmd)) {
+	case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
+		put_user(SNDRV_COMPRESS_VERSION,
+				(int __user *)arg) ? -EFAULT : 0;
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+		retval = snd_compr_get_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+		retval = snd_compr_get_codec_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+		retval = snd_compr_set_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
+		retval = snd_compr_get_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
+		retval = snd_compr_tstamp(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
+		retval = snd_compr_ioctl_avail(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
+		retval = snd_compr_pause(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_RESUME):
+		retval = snd_compr_resume(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_START):
+		retval = snd_compr_start(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_STOP):
+		retval = snd_compr_stop(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+		cmd = SND_COMPR_TRIGGER_DRAIN;
+		retval = snd_compr_drain(stream);
+		break;
+	}
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+static const struct file_operations snd_compr_file_ops[2] = {
+	{
+		.owner =	THIS_MODULE,
+		.open =		snd_compr_pb_open,
+		.release =	snd_compr_free,
+		.write =	snd_compr_write,
+		.unlocked_ioctl = snd_compr_ioctl,
+		.mmap =		snd_compr_mmap,
+		.poll =		snd_compr_pb_poll,
+	},
+	{
+		.owner =	THIS_MODULE,
+		.open =		snd_compr_cap_open,
+		.release =	snd_compr_free,
+		.read =		snd_compr_read,
+		.unlocked_ioctl = snd_compr_ioctl,
+		.mmap =		snd_compr_mmap,
+		.poll =		snd_compr_cap_poll,
+	}
+};
+
+static int snd_compress_dev_register(struct snd_device *device)
+{
+	int ret;
+	char str[16];
+	struct snd_compr *compr;
+	int devtype, cidx;
+
+	if (snd_BUG_ON(!device || !device->device_data))
+		return -ENXIO;
+	compr = device->device_data;
+
+	for (cidx = 0; cidx < 2; cidx++) {
+		switch (cidx) {
+		case 0:
+			if (!compr->pb)
+				continue;
+			sprintf(str, "comprC%iD%ip", compr->card->number,
+				compr->device);
+			pr_debug("reg %s for device %s\n", str, compr->name);
+			devtype = SNDRV_DEVICE_TYPE_COMPR_PLAYBACK;
+			break;
+		case 1:
+			if (!compr->cap)
+				continue;
+			sprintf(str, "comprC%iD%ic", compr->card->number,
+				compr->device);
+			pr_debug("reg %s for device %s\n", str, compr->name);
+			devtype = SNDRV_DEVICE_TYPE_COMPR_CAPTURE;
+			break;
+		}
+
+		/* register compressed device */
+		ret = snd_register_device(devtype, compr->card, compr->device,
+				  &snd_compr_file_ops[cidx], compr, str);
+		if (ret < 0) {
+			pr_err("snd_register_device failed\n %d", ret);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static int snd_compress_dev_disconnect(struct snd_device *device)
+{
+	struct snd_compr *compr;
+	int devtype, cidx;
+
+	compr = device->device_data;
+	for (cidx = 0; cidx < 2; cidx++) {
+		switch (cidx) {
+		case 0:
+			if (!compr->pb)
+				continue;
+			devtype = SNDRV_DEVICE_TYPE_COMPR_PLAYBACK;
+			break;
+		case 1:
+			if (!compr->cap)
+				continue;
+			devtype = SNDRV_DEVICE_TYPE_COMPR_CAPTURE;
+			break;
+		}
+		snd_unregister_device(devtype, compr->card, compr->device);
+	}
+	return 0;
+}
+
+static int snd_compress_new(struct snd_card *card, int device,
+			int playback_count, int capture_count,
+			struct snd_compr *compr)
+{
+	static struct snd_device_ops ops = {
+		.dev_free = NULL,
+		.dev_register = snd_compress_dev_register,
+		.dev_disconnect = snd_compress_dev_disconnect,
+	};
+
+	compr->card = card;
+	compr->device = device;
+	return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
+}
+
+static int snd_compress_add_device(struct snd_compr *device)
+{
+	int ret;
+	struct snd_card *card;
+
+	ret = snd_card_create(SNDRV_DEFAULT_IDX1, device->name,
+			THIS_MODULE, 0, &card);
+	if (ret < 0)
+		goto out;
+
+	if (device->pb > 1 || device->cap > 1)
+		goto out_free;
+
+	/* register the card */
+	ret = snd_compress_new(card, 0, device->pb, device->cap, device);
+	if (ret)
+		goto out_free;
+
+	ret = snd_card_register(card);
+	if (ret)
+		goto out_free;
+	return 0;
+
+out_free:
+	snd_card_free(card);
+out:
+	pr_err("failed with %d\n", ret);
+	return ret;
+
+}
+
+static int snd_compress_remove_device(struct snd_compr *device)
+{
+	return snd_card_free(device->card);
+}
+
+/**
+ * snd_compress_register - register compressed device
+ *
+ * @device: compressed device to register
+ */
+int snd_compress_register(struct snd_compr *device)
+{
+	int retval;
+
+	if (device->name == NULL || device->dev == NULL || device->ops == NULL)
+		return -EINVAL;
+
+	pr_debug("Registering compressed device %s\n", device->name);
+	BUG_ON(!device->ops->open);
+	BUG_ON(!device->ops->free);
+	BUG_ON(!device->ops->set_params);
+	BUG_ON(!device->ops->get_params);
+	BUG_ON(!device->ops->trigger);
+	BUG_ON(!device->ops->pointer);
+	BUG_ON(!device->ops->get_caps);
+	BUG_ON(!device->ops->get_codec_caps);
+
+	mutex_init(&device->lock);
+	/* todo integrate with asoc */
+
+	/* register a compressed card */
+	mutex_lock(&device_mutex);
+	retval = snd_compress_add_device(device);
+	mutex_unlock(&device_mutex);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(snd_compress_register);
+
+int snd_compress_deregister(struct snd_compr *device)
+{
+	pr_debug("Removing compressed device %s\n", device->name);
+	mutex_lock(&device_mutex);
+	snd_compress_remove_device(device);
+	mutex_unlock(&device_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_compress_deregister);
+
+static int __init snd_compress_init(void)
+{
+	return 0;
+}
+
+static void __exit snd_compress_exit(void)
+{
+}
+
+module_init(snd_compress_init);
+module_exit(snd_compress_exit);
+
+MODULE_DESCRIPTION("ALSA Compressed offload framework");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH 6/6] compress: add makefile and kconfig file
  2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
                   ` (11 preceding siblings ...)
  2011-11-22  8:51 ` [PATCH 5/6] compress: add the core file Vinod Koul
@ 2011-11-22  8:52 ` Vinod Koul
  2011-11-23 16:03   ` Mark Brown
  12 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-11-22  8:52 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, pierre-louis.bossart

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/Kconfig                   |    2 ++
 sound/Makefile                  |    3 ++-
 sound/compress_offload/Kconfig  |   17 +++++++++++++++++
 sound/compress_offload/Makefile |    4 ++++
 4 files changed, 25 insertions(+), 1 deletions(-)
 create mode 100644 sound/compress_offload/Kconfig
 create mode 100644 sound/compress_offload/Makefile

diff --git a/sound/Kconfig b/sound/Kconfig
index 1fef141..9b09263 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -93,6 +93,8 @@ source "sound/mips/Kconfig"
 
 source "sound/sh/Kconfig"
 
+source "sound/compress_offload/Kconfig"
+
 # the following will depend on the order of config.
 # here assuming USB is defined before ALSA
 source "sound/usb/Kconfig"
diff --git a/sound/Makefile b/sound/Makefile
index ce9132b..5a54d6c 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -6,7 +6,8 @@ obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
-	firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
+	firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ \
+	compress_offload/
 obj-$(CONFIG_SND_AOA) += aoa/
 
 # This one must be compilable even if sound is configured out
diff --git a/sound/compress_offload/Kconfig b/sound/compress_offload/Kconfig
new file mode 100644
index 0000000..8e12a66
--- /dev/null
+++ b/sound/compress_offload/Kconfig
@@ -0,0 +1,17 @@
+#
+# compressed offload config
+#
+
+menuconfig SND_COMPRESS_OFFLOAD
+	tristate "ALSA Compressed audio offload support"
+	default n
+	help
+	  If you want support for offloading compressed audio and have such
+	  a hardware, then you should say Y here and also to the DSP driver
+	  of your platform.
+
+if SND_COMPRESS_OFFLOAD
+
+source "sound/compress_offload/mid-x86/Kconfig"
+
+endif #SND_COMPRESS_OFFLOAD
diff --git a/sound/compress_offload/Makefile b/sound/compress_offload/Makefile
new file mode 100644
index 0000000..c1ccecb
--- /dev/null
+++ b/sound/compress_offload/Makefile
@@ -0,0 +1,4 @@
+snd-compress-objs := core.o
+
+obj-$(CONFIG_SND_COMPRESS_OFFLOAD)	+= snd-compress.o
+obj-$(CONFIG_SND_COMPRESS_OFFLOAD)	+= mid-x86/
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* Re: [PATCH 4/6] compress: add API header and driver header files
  2011-11-22  8:51 ` [PATCH 4/6] compress: add API header and driver header files Vinod Koul
@ 2011-11-22 11:18   ` Clemens Ladisch
  2011-11-22 13:14     ` Vinod Koul
  2011-12-02 15:39   ` Nallasellan, Singaravelan
  1 sibling, 1 reply; 133+ messages in thread
From: Clemens Ladisch @ 2011-11-22 11:18 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg, pierre-louis.bossart

Vinod Koul wrote:
> This patch adds the header files for ioctl definations and header file for
> driver APIs for lower level device drivers to use

> +++ b/include/sound/compress_offload.h
> ...
> +#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x00, struct snd_compr_caps *)
> +#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x01, struct snd_compr_codec_caps *)
> +#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x02, struct snd_compr_params *)
> +#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x03, struct snd_compr_params *)
> +#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x10, struct snd_compr_tstamp *)
> +#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x11, struct snd_compr_avail *)

The type whose size is made part of the ioctl number is supposed to be
the actual structure, not a pointer to it.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 4/6] compress: add API header and driver header files
  2011-11-22 11:18   ` Clemens Ladisch
@ 2011-11-22 13:14     ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-11-22 13:14 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: tiwai, alsa-devel, broonie, lrg, pierre-louis.bossart

On Tue, 2011-11-22 at 12:18 +0100, Clemens Ladisch wrote:
> Vinod Koul wrote:
> > This patch adds the header files for ioctl definations and header file for
> > driver APIs for lower level device drivers to use
> 
> > +++ b/include/sound/compress_offload.h
> > ...
> > +#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x00, struct snd_compr_caps *)
> > +#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x01, struct snd_compr_codec_caps *)
> > +#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x02, struct snd_compr_params *)
> > +#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x03, struct snd_compr_params *)
> > +#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x10, struct snd_compr_tstamp *)
> > +#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x11, struct snd_compr_avail *)
> 
> The type whose size is made part of the ioctl number is supposed to be
> the actual structure, not a pointer to it.
Right, I missed that.
Fixed now, thanks for pointing

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 2/6] core: add support for compressed devices
  2011-11-22  8:51 ` [PATCH 2/6] core: add support for compressed devices Vinod Koul
@ 2011-11-23 11:30   ` Mark Brown
  0 siblings, 0 replies; 133+ messages in thread
From: Mark Brown @ 2011-11-23 11:30 UTC (permalink / raw)
  To: Vinod Koul
  Cc: tiwai, alsa-devel, Omair Mohammed Abdullah, lrg, pierre-louis.bossart

On Tue, Nov 22, 2011 at 02:21:56PM +0530, Vinod Koul wrote:
> From: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
> 
> Use the two minor numbers 2 and 3 for audio compressed offload devices.
> Also add support for these devices in core

Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-22  8:51 ` [PATCH 5/6] compress: add the core file Vinod Koul
@ 2011-11-23 16:02   ` Mark Brown
  2011-11-23 16:16     ` Vinod Koul
  2011-11-23 17:03   ` Takashi Iwai
  2011-12-02 16:24   ` Nallasellan, Singaravelan
  2 siblings, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-11-23 16:02 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg, pierre-louis.bossart

On Tue, Nov 22, 2011 at 02:21:59PM +0530, Vinod Koul wrote:

Looks mostly good.

> +static int snd_compr_resume(struct snd_compr_stream *stream)
> +{
> +	int retval;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
> +		return -EPERM;
> +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
> +	if (!retval)
> +		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
> +	return retval;

Here we do the state transition if the trigger is successful but...

> +static int snd_compr_start(struct snd_compr_stream *stream)
> +{
> +	int retval;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
> +		return -EPERM;
> +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
> +	stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
> +	return retval;

...here we unconditionally set the new state.

> +static int snd_compress_add_device(struct snd_compr *device)
> +{
> +	int ret;
> +	struct snd_card *card;
> +
> +	ret = snd_card_create(SNDRV_DEFAULT_IDX1, device->name,
> +			THIS_MODULE, 0, &card);
> +	if (ret < 0)
> +		goto out;

It's a bit surprising that this is doing snd_card_create() - I'd expect
a compressed device to be added as a subdevice on a card being passed
in.  At least in the embedded case you'd normally get a card with a mix
of PCM and compressed streams in one unified card.

> +	mutex_init(&device->lock);
> +	/* todo integrate with asoc */

The core code shouldn't know anything about ASoC, ASoC should be able to
use the core API like any other card driver.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 6/6] compress: add makefile and kconfig file
  2011-11-22  8:52 ` [PATCH 6/6] compress: add makefile and kconfig file Vinod Koul
@ 2011-11-23 16:03   ` Mark Brown
  2011-11-23 16:23     ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-11-23 16:03 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg, pierre-louis.bossart

On Tue, Nov 22, 2011 at 02:22:00PM +0530, Vinod Koul wrote:

>  sound/compress_offload/Kconfig  |   17 +++++++++++++++++
>  sound/compress_offload/Makefile |    4 ++++

I'm surprised this is in a new directory rather than some new files in
sound/core.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-23 16:02   ` Mark Brown
@ 2011-11-23 16:16     ` Vinod Koul
  2011-11-23 16:31       ` Mark Brown
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-11-23 16:16 UTC (permalink / raw)
  To: Mark Brown; +Cc: tiwai, alsa-devel, lrg, pierre-louis.bossart

On Wed, 2011-11-23 at 16:02 +0000, Mark Brown wrote:
> > +static int snd_compress_add_device(struct snd_compr *device)
> > +{
> > +     int ret;
> > +     struct snd_card *card;
> > +
> > +     ret = snd_card_create(SNDRV_DEFAULT_IDX1, device->name,
> > +                     THIS_MODULE, 0, &card);
> > +     if (ret < 0)
> > +             goto out;
> 
> It's a bit surprising that this is doing snd_card_create() - I'd
> expect
> a compressed device to be added as a subdevice on a card being passed
> in.  At least in the embedded case you'd normally get a card with a
> mix
> of PCM and compressed streams in one unified card.
ATM I am viewing the compressed card as a different one, but yes
logically speaking for embedded audio we can think of this as a single
card and use the same card here as well.
> 
> > +     mutex_init(&device->lock);
> > +     /* todo integrate with asoc */
> 
> The core code shouldn't know anything about ASoC, ASoC should be able
> to
> use the core API like any other card driver.
I was thinking that during the compress stream open, the core will
trigger the asoc to turn on the codec. For that purpose it needs to call
asoc, hence the comment.

Well this changes if we think asoc should use core API.
That way my lower level driver model changes:
	think of a cpu driver which registers cpu side with asoc and compressed
path with core here as compared to my initial thoughts on a compressed
driver outside asoc which registers the compressed ops with core and
acts as wrapper over dsp

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 6/6] compress: add makefile and kconfig file
  2011-11-23 16:03   ` Mark Brown
@ 2011-11-23 16:23     ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-11-23 16:23 UTC (permalink / raw)
  To: Mark Brown; +Cc: tiwai, alsa-devel, lrg, pierre-louis.bossart

On Wed, 2011-11-23 at 16:03 +0000, Mark Brown wrote:
> On Tue, Nov 22, 2011 at 02:22:00PM +0530, Vinod Koul wrote:
> 
> >  sound/compress_offload/Kconfig  |   17 +++++++++++++++++
> >  sound/compress_offload/Makefile |    4 ++++
> 
> I'm surprised this is in a new directory rather than some new files in
> sound/core.
I wasn't sure, ok to change to sound/core.

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-23 16:16     ` Vinod Koul
@ 2011-11-23 16:31       ` Mark Brown
  2011-11-23 16:34         ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-11-23 16:31 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg, pierre-louis.bossart

On Wed, Nov 23, 2011 at 09:46:32PM +0530, Vinod Koul wrote:
> On Wed, 2011-11-23 at 16:02 +0000, Mark Brown wrote:

> > The core code shouldn't know anything about ASoC, ASoC should be able
> > to
> > use the core API like any other card driver.

> I was thinking that during the compress stream open, the core will
> trigger the asoc to turn on the codec. For that purpose it needs to call
> asoc, hence the comment.

I'd expect ASoC to drop in here in the same way as it drops into the
other core APIs with ASoC wrapping and indirecting the core APIs for
drivers working within ASoC rather than the core calling down into ASoC.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 3/6] compress: add compress parameter definations
  2011-11-22  8:51 ` [PATCH 3/6] compress: add compress parameter definations Vinod Koul
@ 2011-11-23 16:32   ` Mark Brown
  0 siblings, 0 replies; 133+ messages in thread
From: Mark Brown @ 2011-11-23 16:32 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg, pierre-louis.bossart

On Tue, Nov 22, 2011 at 02:21:57PM +0530, Vinod Koul wrote:
> The patch adds the various definations used to define the encoder and decoder
> parameters

Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-23 16:31       ` Mark Brown
@ 2011-11-23 16:34         ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-11-23 16:34 UTC (permalink / raw)
  To: Mark Brown; +Cc: tiwai, alsa-devel, lrg, pierre-louis.bossart

On Wed, 2011-11-23 at 16:31 +0000, Mark Brown wrote:
> On Wed, Nov 23, 2011 at 09:46:32PM +0530, Vinod Koul wrote:
> > On Wed, 2011-11-23 at 16:02 +0000, Mark Brown wrote:
> 
> > > The core code shouldn't know anything about ASoC, ASoC should be able
> > > to
> > > use the core API like any other card driver.
> 
> > I was thinking that during the compress stream open, the core will
> > trigger the asoc to turn on the codec. For that purpose it needs to call
> > asoc, hence the comment.
> 
> I'd expect ASoC to drop in here in the same way as it drops into the
> other core APIs with ASoC wrapping and indirecting the core APIs for
> drivers working within ASoC rather than the core calling down into ASoC.
That sounds okay to me as well :)

Thanks for your review.

I will send next version tomorrow after testing.

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-22  8:51 ` [PATCH 5/6] compress: add the core file Vinod Koul
  2011-11-23 16:02   ` Mark Brown
@ 2011-11-23 17:03   ` Takashi Iwai
  2011-11-24  3:45     ` Vinod Koul
                       ` (2 more replies)
  2011-12-02 16:24   ` Nallasellan, Singaravelan
  2 siblings, 3 replies; 133+ messages in thread
From: Takashi Iwai @ 2011-11-23 17:03 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, broonie, lrg, pierre-louis.bossart

At Tue, 22 Nov 2011 14:21:59 +0530,
Vinod Koul wrote:
> 
> This patch adds core.c, the file which implements the ioctls and
> registers the devices
> 
> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

A general note: it's not necessarily to split playback and capture
devices.  For example, rawmidi has a single device for full-duplex.
In the case of PCM, we had to split them because of mmap.  The mmap
for the capture was supposed not to be read-only, some apps may want
to add mark on the buffer.  But, if this isn't the case for
compression devices, you can have a single device serving for both
playback and capture.  The direction can be checked by the open flag.

> +#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)

Is this referred anywhere?

> +#include <sound/snd_compress_params.h>
> +#include <sound/compress_offload.h>
> +#include <sound/compress_driver.h>
> +#include <sound/core.h>
> +#include <sound/initval.h>

In general, sound/core.h is included at first.


> +static DEFINE_MUTEX(device_mutex);
> +
> +struct snd_compr_file {
> +	unsigned long caps;
> +	struct snd_compr_stream stream;
> +};
> +
> +static int snd_compr_open(struct file *f,  struct snd_compr *compr, int type)
> +{
> +	struct snd_compr_file *data;
> +	struct snd_compr_runtime *runtime;
> +	int ret;
> +
> +	mutex_lock(&device_mutex);

Do you need a global lock for opening a device, too?  Just to be sure,
since I see no obvious need.  (Anyway you don't need to have a lock at
this early place before a bunch of kmallocs.  The lock should be done
as small as possible.)

> +static int snd_compr_free(struct inode *inode, struct file *f)
> +{
> +	struct snd_compr_file *data = f->private_data;
> +	mutex_lock(&device_mutex);
> +	data->stream.ops->free(&data->stream);
> +	kfree(data->stream.runtime->buffer);
> +	kfree(data->stream.runtime);
> +	kfree(data);
> +	mutex_unlock(&device_mutex);

Ditto.  Do you need a global lock?

> +static int
> +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
> +{
> +	struct snd_compr_avail ioctl_avail;
> +
> +	snd_compr_calc_avail(stream, &ioctl_avail);
> +	if (copy_to_user((unsigned long __user *)arg,
> +				&ioctl_avail, sizeof(ioctl_avail)))

snd_compr_calc_avail() doesn't initialize the pointer, so this may
leak some kernel space.

> +
> +unsigned int snd_compr_pb_poll(struct file *f, poll_table *wait)

Missing static?

> +
> +unsigned int snd_compr_cap_poll(struct file *f, poll_table *wait)

Ditto.


> +void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> +{
> +	pr_debug("fragment elapsed called\n");
> +	if (stream->direction !=  SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
> +		return;
> +	wake_up(&stream->runtime->sleep);
> +}
> +EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
> +
> +void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
> +{
> +	if (stream->direction != SNDRV_DEVICE_TYPE_COMPR_CAPTURE)
> +		return;
> +	wake_up(&stream->runtime->sleep);
> +}
> +EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);

These are better to be inlined...
(And fragment and frame for different directions?  Hm, not so
intuitive :)

> +static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
> +{
> +	struct snd_compr_file *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +	int retval = -ENOTTY;
> +
> +	BUG_ON(!data);
> +	stream = &data->stream;
> +	BUG_ON(!stream);

Avoid BUG_ON() unless you really want to stop the whole operation at
this option (such as memory corruption).


> +	mutex_lock(&stream->device->lock);
> +	switch (_IOC_NR(cmd)) {
> +	case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
> +		put_user(SNDRV_COMPRESS_VERSION,
> +				(int __user *)arg) ? -EFAULT : 0;
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
> +		retval = snd_compr_get_caps(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
> +		retval = snd_compr_get_codec_caps(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
> +		retval = snd_compr_set_params(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
> +		retval = snd_compr_get_params(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
> +		retval = snd_compr_tstamp(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
> +		retval = snd_compr_ioctl_avail(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
> +		retval = snd_compr_pause(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_RESUME):
> +		retval = snd_compr_resume(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_START):
> +		retval = snd_compr_start(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_STOP):
> +		retval = snd_compr_stop(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
> +		cmd = SND_COMPR_TRIGGER_DRAIN;

What's this?

> +		retval = snd_compr_drain(stream);
> +		break;
> +	}
> +	mutex_unlock(&stream->device->lock);
> +	return retval;


thanks,

Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-23 17:03   ` Takashi Iwai
@ 2011-11-24  3:45     ` Vinod Koul
  2011-11-24  8:51       ` Takashi Iwai
  2011-11-28 21:19     ` Pierre-Louis Bossart
       [not found]     ` <000f01ccae13$78fe38c0$6afaaa40$@bossart@linux.intel.com>
  2 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-11-24  3:45 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, broonie, lrg, pierre-louis.bossart

On Wed, 2011-11-23 at 18:03 +0100, Takashi Iwai wrote:
> At Tue, 22 Nov 2011 14:21:59 +0530,
> Vinod Koul wrote:
> > 
> > This patch adds core.c, the file which implements the ioctls and
> > registers the devices
> > 
> > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> 
> A general note: it's not necessarily to split playback and capture
> devices.  For example, rawmidi has a single device for full-duplex.
> In the case of PCM, we had to split them because of mmap.  The mmap
> for the capture was supposed not to be read-only, some apps may want
> to add mark on the buffer.  But, if this isn't the case for
> compression devices, you can have a single device serving for both
> playback and capture.  The direction can be checked by the open flag.
Yes we can have them common. I went with usualy convention of having
devices as pcmCxDxp translated to comprCxDxp.

If you don't mind we can keep it as is for now, and once we have
capture, mmap and other support built and tested we can merge these?

> 
> > +#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
> 
> Is this referred anywhere?
This is trick I picked up :)
pr_err/debug is define as pr_fmt. These just add the module name,
function and line number to what you are printing

> > +
> > +static int snd_compr_open(struct file *f,  struct snd_compr *compr, int type)
> > +{
> > +	struct snd_compr_file *data;
> > +	struct snd_compr_runtime *runtime;
> > +	int ret;
> > +
> > +	mutex_lock(&device_mutex);
> 
> Do you need a global lock for opening a device, too?  Just to be sure,
> since I see no obvious need.  (Anyway you don't need to have a lock at
> this early place before a bunch of kmallocs.  The lock should be done
> as small as possible.)
Thinking on this lock should be only for device open call. That way we
prevent race of two opens.
> 
> > +static int snd_compr_free(struct inode *inode, struct file *f)
> > +{
> > +	struct snd_compr_file *data = f->private_data;
> > +	mutex_lock(&device_mutex);
> > +	data->stream.ops->free(&data->stream);
> > +	kfree(data->stream.runtime->buffer);
> > +	kfree(data->stream.runtime);
> > +	kfree(data);
> > +	mutex_unlock(&device_mutex);
> 
> Ditto.  Do you need a global lock?
nope
> 
> > +static int
> > +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
> > +{
> > +	struct snd_compr_avail ioctl_avail;
> > +
> > +	snd_compr_calc_avail(stream, &ioctl_avail);
> > +	if (copy_to_user((unsigned long __user *)arg,
> > +				&ioctl_avail, sizeof(ioctl_avail)))
> 
> snd_compr_calc_avail() doesn't initialize the pointer, so this may
> leak some kernel space.
Not sure if I understood this
snd_compr_calc_avail() will go and get the tstamp updated from driver by
passing the tstamp structure inside this, calculate avail and update
that value.

> 
> 
> > +void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> > +{
> > +	pr_debug("fragment elapsed called\n");
> > +	if (stream->direction !=  SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
> > +		return;
> > +	wake_up(&stream->runtime->sleep);
> > +}
> > +EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
> > +
> > +void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
> > +{
> > +	if (stream->direction != SNDRV_DEVICE_TYPE_COMPR_CAPTURE)
> > +		return;
> > +	wake_up(&stream->runtime->sleep);
> > +}
> > +EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);
> 
> These are better to be inlined...
> (And fragment and frame for different directions?  Hm, not so
> intuitive :)
Well we hve different notions for playback and capture.
In playback, the application can set any random fragment size and dsp
will send a notification by calling snd_compr_fragment_elapsed.
But in case of capture, we would want to get data in frames, but
application may not have a clue on what is the frame size. So once it
has encoded one frame and copied to buffer, it should update its time
stamp and call snd_compr_frame_elapsed. And application can know where
frame boundary is and read data per frame basis.

> 
> 
> > +	mutex_lock(&stream->device->lock);
> > +	switch (_IOC_NR(cmd)) {
> > +	case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
> > +		put_user(SNDRV_COMPRESS_VERSION,
> > +				(int __user *)arg) ? -EFAULT : 0;
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
> > +		retval = snd_compr_get_caps(stream, arg);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
> > +		retval = snd_compr_get_codec_caps(stream, arg);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
> > +		retval = snd_compr_set_params(stream, arg);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
> > +		retval = snd_compr_get_params(stream, arg);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
> > +		retval = snd_compr_tstamp(stream, arg);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
> > +		retval = snd_compr_ioctl_avail(stream, arg);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
> > +		retval = snd_compr_pause(stream);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_RESUME):
> > +		retval = snd_compr_resume(stream);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_START):
> > +		retval = snd_compr_start(stream);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_STOP):
> > +		retval = snd_compr_stop(stream);
> > +		break;
> > +	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
> > +		cmd = SND_COMPR_TRIGGER_DRAIN;
> 
> What's this?
So we have two notions of stopping the stream.
1) STOP: where the dsp is expected to discard any pending data and stop
the decoder.
2) DRAIN: where the dsp is expected to keep decoding and rendering till
last frame available, typcially required for end of file scenarios

Thanks for your review
-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-24  3:45     ` Vinod Koul
@ 2011-11-24  8:51       ` Takashi Iwai
  2011-11-24  9:32         ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-11-24  8:51 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, broonie, lrg, pierre-louis.bossart

At Thu, 24 Nov 2011 09:15:54 +0530,
Vinod Koul wrote:
> 
> On Wed, 2011-11-23 at 18:03 +0100, Takashi Iwai wrote:
> > At Tue, 22 Nov 2011 14:21:59 +0530,
> > Vinod Koul wrote:
> > > 
> > > This patch adds core.c, the file which implements the ioctls and
> > > registers the devices
> > > 
> > > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> > 
> > A general note: it's not necessarily to split playback and capture
> > devices.  For example, rawmidi has a single device for full-duplex.
> > In the case of PCM, we had to split them because of mmap.  The mmap
> > for the capture was supposed not to be read-only, some apps may want
> > to add mark on the buffer.  But, if this isn't the case for
> > compression devices, you can have a single device serving for both
> > playback and capture.  The direction can be checked by the open flag.
> Yes we can have them common. I went with usualy convention of having
> devices as pcmCxDxp translated to comprCxDxp.
> 
> If you don't mind we can keep it as is for now, and once we have
> capture, mmap and other support built and tested we can merge these?

Well, such a decision should be done as early as possible.  Changing
the device file assignment means to change the interface to the
user-space.  So, this is not allowed once when the code is merge to
the upstream.

That said, if you want to fiddle it in your tree, I'm fine.  But,
until the API is fixed, the code can be never merged.

I'm OK to keep the direction-separated devices if it's mandatory, but
note that it's a special handling only for ALSA PCM.  (OSS PCM doesn't
need it, too.)

> > > +#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
> > > +#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
> > 
> > Is this referred anywhere?
> This is trick I picked up :)
> pr_err/debug is define as pr_fmt. These just add the module name,
> function and line number to what you are printing

Hm, but this also change other pr_*().  If you want only the debug
prints, you can use snd_printdd().  This is compiled conditionally,
and can show the file, the function and the line number.

> > > +static int snd_compr_open(struct file *f,  struct snd_compr *compr, int type)
> > > +{
> > > +	struct snd_compr_file *data;
> > > +	struct snd_compr_runtime *runtime;
> > > +	int ret;
> > > +
> > > +	mutex_lock(&device_mutex);
> > 
> > Do you need a global lock for opening a device, too?  Just to be sure,
> > since I see no obvious need.  (Anyway you don't need to have a lock at
> > this early place before a bunch of kmallocs.  The lock should be done
> > as small as possible.)
> Thinking on this lock should be only for device open call. That way we
> prevent race of two opens.

Do you mean the race of opening the same device or among (all)
different devices?  For the first case, the lock should be
device-specific.  For the latter case, I don't understand why.

> > > +static int snd_compr_free(struct inode *inode, struct file *f)
> > > +{
> > > +	struct snd_compr_file *data = f->private_data;
> > > +	mutex_lock(&device_mutex);
> > > +	data->stream.ops->free(&data->stream);
> > > +	kfree(data->stream.runtime->buffer);
> > > +	kfree(data->stream.runtime);
> > > +	kfree(data);
> > > +	mutex_unlock(&device_mutex);
> > 
> > Ditto.  Do you need a global lock?
> nope
> > 
> > > +static int
> > > +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
> > > +{
> > > +	struct snd_compr_avail ioctl_avail;
> > > +
> > > +	snd_compr_calc_avail(stream, &ioctl_avail);
> > > +	if (copy_to_user((unsigned long __user *)arg,
> > > +				&ioctl_avail, sizeof(ioctl_avail)))
> > 
> > snd_compr_calc_avail() doesn't initialize the pointer, so this may
> > leak some kernel space.
> Not sure if I understood this
> snd_compr_calc_avail() will go and get the tstamp updated from driver by
> passing the tstamp structure inside this, calculate avail and update
> that value.

But snd_compr_calc_avail() may return without filling avail->avail, e.g.

	if (stream->runtime->bytes_written == 0 &&
			stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
		pr_debug("detected init and someone forgot to do a write\n");
		return stream->runtime->buffer_size;
	}

So, this leaks the uninitialized space.

> > > +void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> > > +{
> > > +	pr_debug("fragment elapsed called\n");
> > > +	if (stream->direction !=  SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
> > > +		return;
> > > +	wake_up(&stream->runtime->sleep);
> > > +}
> > > +EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
> > > +
> > > +void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
> > > +{
> > > +	if (stream->direction != SNDRV_DEVICE_TYPE_COMPR_CAPTURE)
> > > +		return;
> > > +	wake_up(&stream->runtime->sleep);
> > > +}
> > > +EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);
> > 
> > These are better to be inlined...
> > (And fragment and frame for different directions?  Hm, not so
> > intuitive :)
> Well we hve different notions for playback and capture.
> In playback, the application can set any random fragment size and dsp
> will send a notification by calling snd_compr_fragment_elapsed.
> But in case of capture, we would want to get data in frames, but
> application may not have a clue on what is the frame size. So once it
> has encoded one frame and copied to buffer, it should update its time
> stamp and call snd_compr_frame_elapsed. And application can know where
> frame boundary is and read data per frame basis.

The biggest problem is the conflict of terminology.
What do you mean as "frame" and what do you mean as "fragment" in your
implementation?  At least, the term "frame" is already used in ALSA
PCM, and I'm not sure whether you use this term for the very same
meaning in the above context...

And, another question is how you can guarantee that the capture works
in that way.  What happens if a hardware updates the data only in the
fragments level even for the capture?


> > > +	mutex_lock(&stream->device->lock);
> > > +	switch (_IOC_NR(cmd)) {
> > > +	case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
> > > +		put_user(SNDRV_COMPRESS_VERSION,
> > > +				(int __user *)arg) ? -EFAULT : 0;
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
> > > +		retval = snd_compr_get_caps(stream, arg);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
> > > +		retval = snd_compr_get_codec_caps(stream, arg);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
> > > +		retval = snd_compr_set_params(stream, arg);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
> > > +		retval = snd_compr_get_params(stream, arg);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
> > > +		retval = snd_compr_tstamp(stream, arg);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
> > > +		retval = snd_compr_ioctl_avail(stream, arg);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
> > > +		retval = snd_compr_pause(stream);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_RESUME):
> > > +		retval = snd_compr_resume(stream);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_START):
> > > +		retval = snd_compr_start(stream);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_STOP):
> > > +		retval = snd_compr_stop(stream);
> > > +		break;
> > > +	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
> > > +		cmd = SND_COMPR_TRIGGER_DRAIN;
> > 
> > What's this?
> So we have two notions of stopping the stream.

Yes, but the substitution of cmd is useless in your code:

+	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+		cmd = SND_COMPR_TRIGGER_DRAIN;
+		retval = snd_compr_drain(stream);
+		break;
+	}
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}


thanks,

Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-24  8:51       ` Takashi Iwai
@ 2011-11-24  9:32         ` Vinod Koul
  2011-11-28 21:36           ` Pierre-Louis Bossart
       [not found]           ` <001201ccae15$c24d8bf0$46e8a3d0$@bossart@linux.intel.com>
  0 siblings, 2 replies; 133+ messages in thread
From: Vinod Koul @ 2011-11-24  9:32 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, broonie, lrg, pierre-louis.bossart

On Thu, 2011-11-24 at 09:51 +0100, Takashi Iwai wrote: 
> > If you don't mind we can keep it as is for now, and once we have
> > capture, mmap and other support built and tested we can merge these?
> 
> Well, such a decision should be done as early as possible.  Changing
> the device file assignment means to change the interface to the
> user-space.  So, this is not allowed once when the code is merge to
> the upstream.
Somehow I was anticipating this
> 
> That said, if you want to fiddle it in your tree, I'm fine.  But,
> until the API is fixed, the code can be never merged.
> 
> I'm OK to keep the direction-separated devices if it's mandatory, but
> note that it's a special handling only for ALSA PCM.  (OSS PCM doesn't
> need it, too.)
Well I am planning to get it merged ASAP, not keep in my tree.

Only reason why I asked is since we don't have mmap support and capture
support, if it all we need to differentiate we should have a way.
Given that, today I don't have a reason why we cant do that if we know
the direction. Something like
if (playback)
	do_this_way;
else
	do_another_way;

So I will take your advice and fix it once for now.


> Hm, but this also change other pr_*().  If you want only the debug
> prints, you can use snd_printdd().  This is compiled conditionally,
> and can show the file, the function and the line number.
I wanted for all prints, its nicer to have this info as well for error
and info prints.

> 
> Do you mean the race of opening the same device or among (all)
> different devices?  For the first case, the lock should be
> device-specific.  For the latter case, I don't understand why.
former case, yes makes sense to use device lock rather than global. I
will split locking now.

> But snd_compr_calc_avail() may return without filling avail->avail, e.g.
> 
> 	if (stream->runtime->bytes_written == 0 &&
> 			stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
> 		pr_debug("detected init and someone forgot to do a write\n");
> 		return stream->runtime->buffer_size;
> 	}
> 
> So, this leaks the uninitialized space.
got it :)

> The biggest problem is the conflict of terminology.
> What do you mean as "frame" and what do you mean as "fragment" in your
> implementation?  At least, the term "frame" is already used in ALSA
> PCM, and I'm not sure whether you use this term for the very same
> meaning in the above context...
fragment is some random number of bytes after which driver will
callback. This is typically used for pushing data to device.

For capture, since application may need to get data on frame basis
(think video recording with encoded video usage, where application needs
audio compressed data on "frame" basis for encapsulation). The DSP is
supposed callback after every encoded frame. I think only difference
between PCM and this is encoding format, otherwise in terms of decoded
data and time they would mean the same.. I am not expert here so maybe
wrong.

> And, another question is how you can guarantee that the capture works
> in that way.  What happens if a hardware updates the data only in the
> fragments level even for the capture?
That would be a buggy driver and I would ask them to read the
documentation. At least it wont work for apps which need data on frame
basis

> 
> Yes, but the substitution of cmd is useless in your code:
> 
> +	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
> +		cmd = SND_COMPR_TRIGGER_DRAIN;
> +		retval = snd_compr_drain(stream);
> +		break;
I should start wearing glasses now


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-23 17:03   ` Takashi Iwai
  2011-11-24  3:45     ` Vinod Koul
@ 2011-11-28 21:19     ` Pierre-Louis Bossart
       [not found]     ` <000f01ccae13$78fe38c0$6afaaa40$@bossart@linux.intel.com>
  2 siblings, 0 replies; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-11-28 21:19 UTC (permalink / raw)
  To: 'Takashi Iwai', 'Vinod Koul'; +Cc: alsa-devel, broonie, lrg

> A general note: it's not necessarily to split playback and capture
> devices.  For example, rawmidi has a single device for full-duplex.
> In the case of PCM, we had to split them because of mmap.  The mmap
> for the capture was supposed not to be read-only, some apps may want
> to add mark on the buffer.  

Beats me why an app would want to write anything into the capture ring
buffer. Do you have an example of this use case? Maybe there's a similar
need for compressed data. Thanks!
-Pierre

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-24  9:32         ` Vinod Koul
@ 2011-11-28 21:36           ` Pierre-Louis Bossart
       [not found]           ` <001201ccae15$c24d8bf0$46e8a3d0$@bossart@linux.intel.com>
  1 sibling, 0 replies; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-11-28 21:36 UTC (permalink / raw)
  To: 'Vinod Koul', 'Takashi Iwai'; +Cc: alsa-devel, broonie, lrg

> > implementation?  At least, the term "frame" is already used in ALSA
> > PCM, and I'm not sure whether you use this term for the very same
> > meaning in the above context...

Most compressed formats have a notion of frame, but this is indeed a
different notion. In ALSA a frame is really a sampling point, possibly with
multiple channels. Compression algorithms group sampling points in frames,
or blocks, before applying a transform and quantizing. AAC works with 1024
sampling points, MPEG Layer3 with 2 granules of 576 points, AMR with 160
points, etc. 
We may want to use terms like 'blocks' or 'chunks', if this helps avoid
confusions with existing ALSA concepts.
 
> For capture, since application may need to get data on frame basis
> (think video recording with encoded video usage, where application
> needs
> audio compressed data on "frame" basis for encapsulation). The DSP is
> supposed callback after every encoded frame. I think only difference
> between PCM and this is encoding format, otherwise in terms of decoded
> data and time they would mean the same.. I am not expert here so maybe
> wrong.

For capture, in some cases the compressed bitstream doesn't provide any
pointers on the beginning of a block, nor any block-length indication (eg.
AAC-RAW). In that case, an encoder would need to pass data to user-space on
a block-by-block basis, with the bytes available in the ring buffer
corresponding to the block length. If the applications can extract 'blocks'
on their own and handle the relevant file-write/multiplexing, the usual
data-passing with regular events is fine.

For playback, the decoder is expected to deal with such situations on its
own and find the block boundaries, meaning at the application level we can
just push bytes down to the decoder without worrying. 
-Pierre

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
       [not found]           ` <001201ccae15$c24d8bf0$46e8a3d0$@bossart@linux.intel.com>
@ 2011-11-29  7:21             ` Takashi Iwai
  2011-11-29 21:15               ` Pierre-Louis Bossart
       [not found]               ` <003001ccaedb$f4e30010$dea90030$@bossart@linux.intel.com>
  0 siblings, 2 replies; 133+ messages in thread
From: Takashi Iwai @ 2011-11-29  7:21 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: 'Vinod Koul', broonie, alsa-devel, lrg

At Mon, 28 Nov 2011 15:36:15 -0600,
Pierre-Louis Bossart wrote:
> 
> > > implementation?  At least, the term "frame" is already used in ALSA
> > > PCM, and I'm not sure whether you use this term for the very same
> > > meaning in the above context...
> 
> Most compressed formats have a notion of frame, but this is indeed a
> different notion. In ALSA a frame is really a sampling point, possibly with
> multiple channels. Compression algorithms group sampling points in frames,
> or blocks, before applying a transform and quantizing. AAC works with 1024
> sampling points, MPEG Layer3 with 2 granules of 576 points, AMR with 160
> points, etc. 
> We may want to use terms like 'blocks' or 'chunks', if this helps avoid
> confusions with existing ALSA concepts.

Yes, it's better to avoid the conflicting definition, IMO.

> > For capture, since application may need to get data on frame basis
> > (think video recording with encoded video usage, where application
> > needs
> > audio compressed data on "frame" basis for encapsulation). The DSP is
> > supposed callback after every encoded frame. I think only difference
> > between PCM and this is encoding format, otherwise in terms of decoded
> > data and time they would mean the same.. I am not expert here so maybe
> > wrong.
> 
> For capture, in some cases the compressed bitstream doesn't provide any
> pointers on the beginning of a block, nor any block-length indication (eg.
> AAC-RAW). In that case, an encoder would need to pass data to user-space on
> a block-by-block basis, with the bytes available in the ring buffer
> corresponding to the block length. If the applications can extract 'blocks'
> on their own and handle the relevant file-write/multiplexing, the usual
> data-passing with regular events is fine.
> 
> For playback, the decoder is expected to deal with such situations on its
> own and find the block boundaries, meaning at the application level we can
> just push bytes down to the decoder without worrying. 

But is this restriction guaranteed to be applicable to all possible
hardwares in future?  What happens if you'll get a hardware that
doesn't support the byte-unit push for the playback?
That said, I see no obvious reason to give a restriction coupled with
the stream direction.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
       [not found]     ` <000f01ccae13$78fe38c0$6afaaa40$@bossart@linux.intel.com>
@ 2011-11-29  7:31       ` Takashi Iwai
  2011-12-01 13:28       ` Nallasellan, Singaravelan
  1 sibling, 0 replies; 133+ messages in thread
From: Takashi Iwai @ 2011-11-29  7:31 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: 'Vinod Koul', broonie, alsa-devel, lrg

At Mon, 28 Nov 2011 15:19:53 -0600,
Pierre-Louis Bossart wrote:
> 
> > A general note: it's not necessarily to split playback and capture
> > devices.  For example, rawmidi has a single device for full-duplex.
> > In the case of PCM, we had to split them because of mmap.  The mmap
> > for the capture was supposed not to be read-only, some apps may want
> > to add mark on the buffer.  
> 
> Beats me why an app would want to write anything into the capture ring
> buffer. Do you have an example of this use case? Maybe there's a similar
> need for compressed data. Thanks!

I don't remember exactly, as it was a discussion over 10 years ago.
My vague memory says that it's for marking the position in the buffer
where the read was finished or so...

I think the only possible problem is a case when the device is opened
via O_RDWR for full-duplex.  When you want mmap in that case, it's
difficult to get two different maps for read and write.  You may pass
different PROT_* flags to distinguish between read and write buffers,
but this will really limit the permission.  That was the argument.

In other words, if the driver doesn't accept O_RDWR but only either
O_RDONLY or O_WRONLY, there shouldn't be any problem.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-29  7:21             ` Takashi Iwai
@ 2011-11-29 21:15               ` Pierre-Louis Bossart
       [not found]               ` <003001ccaedb$f4e30010$dea90030$@bossart@linux.intel.com>
  1 sibling, 0 replies; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-11-29 21:15 UTC (permalink / raw)
  To: 'Takashi Iwai'; +Cc: 'Vinod Koul', broonie, alsa-devel, lrg

> > For playback, the decoder is expected to deal with such situations on
> its
> > own and find the block boundaries, meaning at the application level
> we can
> > just push bytes down to the decoder without worrying.
> 
> But is this restriction guaranteed to be applicable to all possible
> hardwares in future?  What happens if you'll get a hardware that
> doesn't support the byte-unit push for the playback?
> That said, I see no obvious reason to give a restriction coupled with
> the stream direction.

Power consumption will be more optimized if we push bytes without looking
for block boundaries on the host. But if your hardware requires parsing on
the host, there's no impact on the API. You'd just write block-by-block and
specify the block length instead of fixed-size value.
-Pierre

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
       [not found]               ` <003001ccaedb$f4e30010$dea90030$@bossart@linux.intel.com>
@ 2011-11-30 10:30                 ` Mark Brown
  2011-11-30 11:19                 ` Takashi Iwai
  1 sibling, 0 replies; 133+ messages in thread
From: Mark Brown @ 2011-11-30 10:30 UTC (permalink / raw)
  To: Pierre-Louis Bossart
  Cc: 'Takashi Iwai', dp, 'Vinod Koul', alsa-devel, lrg

On Tue, Nov 29, 2011 at 03:15:01PM -0600, Pierre-Louis Bossart wrote:

> > But is this restriction guaranteed to be applicable to all possible
> > hardwares in future?  What happens if you'll get a hardware that
> > doesn't support the byte-unit push for the playback?
> > That said, I see no obvious reason to give a restriction coupled with
> > the stream direction.

> Power consumption will be more optimized if we push bytes without looking
> for block boundaries on the host. But if your hardware requires parsing on
> the host, there's no impact on the API. You'd just write block-by-block and
> specify the block length instead of fixed-size value.

We've got a block based driver in development for this API - it's not
had a problem interoperating thus far.  So long as we can report how
much data we've actually consumed I'd not anticipate any problems.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
       [not found]               ` <003001ccaedb$f4e30010$dea90030$@bossart@linux.intel.com>
  2011-11-30 10:30                 ` Mark Brown
@ 2011-11-30 11:19                 ` Takashi Iwai
  2011-11-30 11:29                   ` Vinod Koul
  1 sibling, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-11-30 11:19 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: 'Vinod Koul', broonie, alsa-devel, lrg

At Tue, 29 Nov 2011 15:15:01 -0600,
Pierre-Louis Bossart wrote:
> 
> > > For playback, the decoder is expected to deal with such situations on
> > its
> > > own and find the block boundaries, meaning at the application level
> > we can
> > > just push bytes down to the decoder without worrying.
> > 
> > But is this restriction guaranteed to be applicable to all possible
> > hardwares in future?  What happens if you'll get a hardware that
> > doesn't support the byte-unit push for the playback?
> > That said, I see no obvious reason to give a restriction coupled with
> > the stream direction.
> 
> Power consumption will be more optimized if we push bytes without looking
> for block boundaries on the host. But if your hardware requires parsing on
> the host, there's no impact on the API. You'd just write block-by-block and
> specify the block length instead of fixed-size value.

Well, my question is much more simple.  In the patch, there are checks
of the stream direction in snd_compr_{fragment|frame}_elapsed()
functions.

+void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
+{
+	pr_debug("fragment elapsed called\n");
+	if (stream->direction !=  SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
+		return;
+	wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
+
+void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
+{
+	if (stream->direction != SNDRV_DEVICE_TYPE_COMPR_CAPTURE)
+		return;
+	wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);

And I wonder why this restriction *must* be present in the API-level
implementation.

And, furthermore, I see no reason to have this individual functions.
Why simply not an inline function like

static inline void snd_compr_stream_elapsed(struct snd_compr_stream *stream)
{
	wake_up(&stream->runtime->sleep);
}

??  Then you can reduce two exported symbols and less stack usages.


Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-30 11:19                 ` Takashi Iwai
@ 2011-11-30 11:29                   ` Vinod Koul
  2011-11-30 11:41                     ` Takashi Iwai
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-11-30 11:29 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, broonie, Pierre-Louis Bossart, lrg

On Wed, 2011-11-30 at 12:19 +0100, Takashi Iwai wrote:
> At Tue, 29 Nov 2011 15:15:01 -0600,
> Pierre-Louis Bossart wrote:
> Well, my question is much more simple.  In the patch, there are checks
> of the stream direction in snd_compr_{fragment|frame}_elapsed()
> functions.
> 
> +void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> +{
> +	pr_debug("fragment elapsed called\n");
> +	if (stream->direction !=  SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
> +		return;
> +	wake_up(&stream->runtime->sleep);
> +}
> +EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
> +
> +void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
> +{
> +	if (stream->direction != SNDRV_DEVICE_TYPE_COMPR_CAPTURE)
> +		return;
> +	wake_up(&stream->runtime->sleep);
> +}
> +EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);
> 
> And I wonder why this restriction *must* be present in the API-level
> implementation.
> 
> And, furthermore, I see no reason to have this individual functions.
> Why simply not an inline function like
> 
> static inline void snd_compr_stream_elapsed(struct snd_compr_stream *stream)
> {
> 	wake_up(&stream->runtime->sleep);
> }
> 
> ??  Then you can reduce two exported symbols and less stack usages.
> 
Thanks, I have already changed this as above based on your suggestion
last week :)

But I have kept two different functions doing same thing for sake of
confusion. For playback you need to call this on
block/fragment/random_bytes but for capture it needs to be frame based.

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-30 11:29                   ` Vinod Koul
@ 2011-11-30 11:41                     ` Takashi Iwai
  2011-11-30 12:00                       ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-11-30 11:41 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, broonie, Pierre-Louis Bossart, lrg

At Wed, 30 Nov 2011 16:59:18 +0530,
Vinod Koul wrote:
> 
> On Wed, 2011-11-30 at 12:19 +0100, Takashi Iwai wrote:
> > At Tue, 29 Nov 2011 15:15:01 -0600,
> > Pierre-Louis Bossart wrote:
> > Well, my question is much more simple.  In the patch, there are checks
> > of the stream direction in snd_compr_{fragment|frame}_elapsed()
> > functions.
> > 
> > +void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> > +{
> > +	pr_debug("fragment elapsed called\n");
> > +	if (stream->direction !=  SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
> > +		return;
> > +	wake_up(&stream->runtime->sleep);
> > +}
> > +EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
> > +
> > +void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
> > +{
> > +	if (stream->direction != SNDRV_DEVICE_TYPE_COMPR_CAPTURE)
> > +		return;
> > +	wake_up(&stream->runtime->sleep);
> > +}
> > +EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);
> > 
> > And I wonder why this restriction *must* be present in the API-level
> > implementation.
> > 
> > And, furthermore, I see no reason to have this individual functions.
> > Why simply not an inline function like
> > 
> > static inline void snd_compr_stream_elapsed(struct snd_compr_stream *stream)
> > {
> > 	wake_up(&stream->runtime->sleep);
> > }
> > 
> > ??  Then you can reduce two exported symbols and less stack usages.
> > 
> Thanks, I have already changed this as above based on your suggestion
> last week :)
> 
> But I have kept two different functions doing same thing for sake of
> confusion. For playback you need to call this on
> block/fragment/random_bytes but for capture it needs to be frame based.

That's what I don't understand.  Why the calls must be different?
It just wakes up.  Nothing else.  It doesn't matter whether it's based
on which.


Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-30 11:41                     ` Takashi Iwai
@ 2011-11-30 12:00                       ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-11-30 12:00 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, broonie, Pierre-Louis Bossart, lrg

On Wed, 2011-11-30 at 12:41 +0100, Takashi Iwai wrote:
> > Thanks, I have already changed this as above based on your
> suggestion
> > last week :)
> > 
> > But I have kept two different functions doing same thing for sake of
> > confusion. For playback you need to call this on
> > block/fragment/random_bytes but for capture it needs to be frame
> based.
> 
> That's what I don't understand.  Why the calls must be different?
> It just wakes up.  Nothing else.  It doesn't matter whether it's based
> on which. 
I am not religious about it :D, so don't mind keeping it one as they
essentially do the same thing.

The whole idea was that they wake up for different reasons so call based
on that reason fragment/frame, but I agree that it not really a big
deal, so fixed now

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
       [not found]     ` <000f01ccae13$78fe38c0$6afaaa40$@bossart@linux.intel.com>
  2011-11-29  7:31       ` Takashi Iwai
@ 2011-12-01 13:28       ` Nallasellan, Singaravelan
  2011-12-02  6:44         ` Vinod Koul
  1 sibling, 1 reply; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-01 13:28 UTC (permalink / raw)
  To: Pierre-Louis Bossart, 'Takashi Iwai', 'Vinod Koul'
  Cc: alsa-devel, broonie, lrg

> 
> > A general note: it's not necessarily to split playback and capture
> > devices.  For example, rawmidi has a single device for full-duplex.
> > In the case of PCM, we had to split them because of mmap.  The mmap
> > for the capture was supposed not to be read-only, some apps may want
> > to add mark on the buffer.
> 
> Beats me why an app would want to write anything into the capture ring buffer.
> Do you have an example of this use case? Maybe there's a similar need for
> compressed data. Thanks!
> -Pierre
> 
There was a requirement to add the timestamp at the beginning of each block or frame 
if the encoded data is in RAW format. If the encoder does add the timestamp or marker, 
then we don't need the write option. 

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-12-01 13:28       ` Nallasellan, Singaravelan
@ 2011-12-02  6:44         ` Vinod Koul
  2011-12-02 10:17           ` Nallasellan, Singaravelan
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-02  6:44 UTC (permalink / raw)
  To: Nallasellan, Singaravelan
  Cc: 'Takashi Iwai', alsa-devel, broonie, Pierre-Louis Bossart, lrg

On Thu, 2011-12-01 at 18:58 +0530, Nallasellan, Singaravelan wrote:
> > 
> > > A general note: it's not necessarily to split playback and capture
> > > devices.  For example, rawmidi has a single device for full-duplex.
> > > In the case of PCM, we had to split them because of mmap.  The mmap
> > > for the capture was supposed not to be read-only, some apps may want
> > > to add mark on the buffer.
> > 
> > Beats me why an app would want to write anything into the capture ring buffer.
> > Do you have an example of this use case? Maybe there's a similar need for
> > compressed data. Thanks!
> > -Pierre
> > 
> There was a requirement to add the timestamp at the beginning of each block or frame 
> if the encoded data is in RAW format. If the encoder does add the timestamp or marker, 
> then we don't need the write option. 
Who needs this information, or where is this requirement coming from.
If you already get raw encoded data on frame basis, apps can take that
data with current timestamp...

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-12-02  6:44         ` Vinod Koul
@ 2011-12-02 10:17           ` Nallasellan, Singaravelan
  2011-12-02 11:48             ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-02 10:17 UTC (permalink / raw)
  To: Vinod Koul
  Cc: 'Takashi, alsa-devel, Iwai', broonie, Pierre-Louis Bossart, lrg



> > >
> > There was a requirement to add the timestamp at the beginning of each
> > block or frame if the encoded data is in RAW format. If the encoder
> > does add the timestamp or marker, then we don't need the write option.
> Who needs this information, or where is this requirement coming from.
> If you already get raw encoded data on frame basis, apps can take that data
> with current timestamp...

This was requested for encoded capture for one of the voice codecs couple of years back.
> 
> --
> ~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-12-02 10:17           ` Nallasellan, Singaravelan
@ 2011-12-02 11:48             ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-02 11:48 UTC (permalink / raw)
  To: Nallasellan, Singaravelan
  Cc: 'Takashi Iwai', alsa-devel, broonie, Pierre-Louis Bossart, lrg

On Fri, 2011-12-02 at 15:47 +0530, Nallasellan, Singaravelan wrote:
> 
> > > >
> > > There was a requirement to add the timestamp at the beginning of each
> > > block or frame if the encoded data is in RAW format. If the encoder
> > > does add the timestamp or marker, then we don't need the write option.
> > Who needs this information, or where is this requirement coming from.
> > If you already get raw encoded data on frame basis, apps can take that data
> > with current timestamp...
> 
> This was requested for encoded capture for one of the voice codecs couple of years back.

Why should this API care?
These kind of specfic stuff should be handled in user space

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 4/6] compress: add API header and driver header files
  2011-11-22  8:51 ` [PATCH 4/6] compress: add API header and driver header files Vinod Koul
  2011-11-22 11:18   ` Clemens Ladisch
@ 2011-12-02 15:39   ` Nallasellan, Singaravelan
  2011-12-02 18:58     ` Pierre-Louis Bossart
       [not found]     ` <000301ccb124$72a53370$57ef9a50$@bossart@linux.intel.com>
  1 sibling, 2 replies; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-02 15:39 UTC (permalink / raw)
  To: Vinod Koul, alsa-devel; +Cc: tiwai, broonie, lrg, pierre-louis.bossart

> +struct snd_compr_runtime {
> +	snd_pcm_state_t state;
> +	struct snd_compr_ops *ops;
> +	void *buffer;
> +	size_t buffer_size;
> +	size_t fragment_size;
> +	unsigned int fragments;
> +	size_t hw_pointer;
> +	size_t app_pointer;
> +	size_t bytes_written;
Is it the bytes written to the ring buffer? 

> +	size_t bytes_copied;
Is it the bytes copied by the DSP from ring buffer?

> +	wait_queue_head_t sleep;
> +};
> +
> +/**
> +mandatory  */ struct snd_compr_ops {
> +	int (*open)(struct snd_compr_stream *stream);
> +	int (*free)(struct snd_compr_stream *stream);
> +	int (*set_params)(struct snd_compr_stream *stream,
> +			struct snd_compr_params *params);
> +	int (*get_params)(struct snd_compr_stream *stream,
> +			struct snd_compr_params *params);
> +	int (*trigger)(struct snd_compr_stream *stream, int cmd);
> +	int (*pointer)(struct snd_compr_stream *stream,
> +			struct snd_compr_tstamp *tstamp);
> +	int (*copy)(struct snd_compr_stream *stream, const char __user *buf,
> +		       size_t count);
> +	int (*mmap)(struct snd_compr_stream *stream,
> +			struct vm_area_struct *vma);
> +	int (*ack)(struct snd_compr_stream *stream, size_t bytes);
> +	int (*get_caps) (struct snd_compr_stream *stream,
> +			struct snd_compr_caps *caps);
> +	int (*get_codec_caps) (struct snd_compr_stream *stream,
> +			struct snd_compr_codec_caps *codec); };

Documentation (PATCH 1/6) talks about  get_codecs which is missing? 
Fix the documentation or add the API?

> + */
> +struct snd_compr {
> +	const char *name;
> +	unsigned int pb;
> +	unsigned int cap;

Can we use a single variable if it just 

> +	struct device *dev;
> +	struct snd_compr_ops *ops;
> +	void *private_data;
> +	struct snd_card *card;
> +	struct mutex lock;
> +	int device;
> +};
> +
> + * For recording: we may want to know when a frame is available or when
> + * at least one frame is available for userspace, a different
> + * snd_compress_frame_elapsed() callback should be used  */ void
> +snd_compr_fragment_elapsed(struct snd_compr_stream *stream); void
> +snd_compr_frame_elapsed(struct snd_compr_stream *stream);

What is the use of this API? DSP could send only fragment elapsed.
Not sure we need to received interrupt for every frame. The system will be flooded
with interrupts.

> +/**
> + * struct snd_compr_tstamp: timestamp descriptor
> + * @copied_bytes: Number of bytes offset in ring buffer to DSP
> + * @copied_total: Total number of bytes copied from ring buffer to DSP
> + * @decoded: Frames decoded by DSP
> + * @rendered: Frames rendered by DSP into a mixer or an audio output
> + * @sampling_rate: sampling rate of audio  */ struct snd_compr_tstamp {
> +	size_t copied_bytes;
> +	size_t copied_total;
> +	size_t decoded;
> +	size_t rendered;
> +	__u32 sampling_rate;

Is it possible to track the rendering sampling rate in the driver itself? 

> +struct snd_compr_caps {
> +	__u32 num_codecs;
> +	__u32 min_fragment_size;
> +	__u32 max_fragment_size;
> +	__u32 min_fragments;
> +	__u32 max_fragments;
> +	__u32 codecs[MAX_NUM_CODECS];
> +	__u32 reserved[11];

Can we add number of compress streams supported in DSP?

> +};
> +
> +/**
> + * struct snd_compr_codec_caps: query capability of codec
> + * @codec: codec for which capability is queried
> + * @num_descriptors: number of codec descriptors
> + * @descriptor: array of codec capability descriptor  */ struct
> +snd_compr_codec_caps {
> +	__u32 codec;
> +	__u32 num_descriptors;
> +	struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
> +};
> +

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-11-22  8:51 ` [PATCH 5/6] compress: add the core file Vinod Koul
  2011-11-23 16:02   ` Mark Brown
  2011-11-23 17:03   ` Takashi Iwai
@ 2011-12-02 16:24   ` Nallasellan, Singaravelan
  2011-12-04  4:31     ` Vinod Koul
  2 siblings, 1 reply; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-02 16:24 UTC (permalink / raw)
  To: Vinod Koul, alsa-devel; +Cc: tiwai, broonie, lrg, pierre-louis.bossart

> +static int snd_compr_open(struct file *f,  struct snd_compr *compr, int
> +type) {
> +	struct snd_compr_file *data;
> +	struct snd_compr_runtime *runtime;
> +	int ret;
> +
> +	mutex_lock(&device_mutex);
> +
> +	data = kzalloc(sizeof(*data), GFP_KERNEL);
> +	if (!data) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +	data->stream.ops = compr->ops;
NULL check for compr would help here.

> +	data->stream.direction = type;
> +	data->stream.private_data = compr->private_data;
> +	data->stream.device = compr;
> +	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
> +	if (!runtime) {
> +		ret = -ENOMEM;
> +		kfree(data);
> +		goto out;
> +	}
> +	runtime->state = SNDRV_PCM_STATE_OPEN;
> +	init_waitqueue_head(&runtime->sleep);
> +	data->stream.runtime = runtime;
> +	f->private_data = (void *)data;
> +	ret = compr->ops->open(&data->stream);
NULL check for ops would help here.

> +	if (ret) {
> +		kfree(runtime);
> +		kfree(data);
> +		goto out;
> +	}
> +out:
> +	mutex_unlock(&device_mutex);
> +	return ret;
> +}
> +

> +static int snd_compr_free(struct inode *inode, struct file *f) {
> +	struct snd_compr_file *data = f->private_data;
> +	mutex_lock(&device_mutex);
Can we have mutex for each file opened instead of having a single mutex for everything?
I think it is not required to sequence all the streams.

> +	data->stream.ops->free(&data->stream);
> +	kfree(data->stream.runtime->buffer);
> +	kfree(data->stream.runtime);
> +	kfree(data);
> +	mutex_unlock(&device_mutex);
> +	return 0;
> +}
> +
> +static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
> +		struct snd_compr_tstamp *tstamp)
> +{
> +	stream->ops->pointer(stream, tstamp);
How to ensure that the caller always checks for NULL pointer? 

> +	pr_debug("dsp consumed till %d total %d bytes\n",
> +		tstamp->copied_bytes, tstamp->copied_total);
> +	stream->runtime->hw_pointer = tstamp->copied_bytes;
> +	stream->runtime->bytes_copied = tstamp->copied_total; }
> +
> +static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
> +		struct snd_compr_avail *avail)
> +{
> +	long avail_calc; /*this needs to be signed variable */
> +
> +	snd_compr_update_tstamp(stream, &avail->tstamp);
> +
> +	if (stream->runtime->bytes_written == 0 &&
> +			stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
> +		pr_debug("detected init and someone forgot to do a write\n");
> +		return stream->runtime->buffer_size;
> +	}
> +	pr_debug("app wrote %d, DSP consumed %d\n",
> +		stream->runtime->bytes_written, stream->runtime->bytes_copied);
> +	if (stream->runtime->bytes_written == stream->runtime->bytes_copied) {
> +		pr_debug("both pointers are same, returning full avail\n");
> +		return stream->runtime->buffer_size;
> +	}
> +
> +	avail_calc = stream->runtime->buffer_size -
> +		(stream->runtime->app_pointer - stream->runtime->hw_pointer);
> +	pr_debug("calc avail as %ld, app_ptr %d, hw+ptr %d\n", avail_calc,
> +		stream->runtime->app_pointer, stream->runtime->hw_pointer);
> +	if (avail_calc >= stream->runtime->buffer_size)
> +		avail_calc -= stream->runtime->buffer_size;
> +	pr_debug("ret avail as %ld\n", avail_calc);
> +	avail->avail = avail_calc;
> +	return avail_calc;
> +}
> +
> +static size_t snd_compr_get_avail(struct snd_compr_stream *stream) {
> +	struct snd_compr_avail avail;
> +
Can we update the timestamp before calculating the avail? This will allow partial   
Fragment to be written as well.
> +	return snd_compr_calc_avail(stream, &avail); }
> +
> +static int
> +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long
> +arg) {
> +	struct snd_compr_avail ioctl_avail;
> +
Can we update the timestamp before calculating the avail? This will allow partial   
Fragment to be written as well.

> +	snd_compr_calc_avail(stream, &ioctl_avail);
> +
> +	if (copy_to_user((unsigned long __user *)arg,
> +				&ioctl_avail, sizeof(ioctl_avail)))
> +		return -EFAULT;
> +	return 0;
> +}
> +


> +static ssize_t snd_compr_write(struct file *f, const char __user *buf,
> +		size_t count, loff_t *offset)
> +{
> +
> +	/* while initiating the stream, write should be called before START
> +	 * call, so in setup move state */
> +	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
> +		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
Can we implement kind of start threshold similar to PCM path here to initiate the playback?

> +		pr_debug("stream prepared, Houston we are good to go\n");
> +	}
> +
> +	mutex_unlock(&stream->device->lock);
> +	return retval;
> +}


> +static int snd_compr_resume(struct snd_compr_stream *stream) {
> +	int retval;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
If the stream is running, I guess it can return 0.

> +		return -EPERM;
> +	retval = stream->ops->trigger(stream,
> SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
> +	if (!retval)
> +		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
> +	return retval;
> +}
> +
> +static int snd_compr_start(struct snd_compr_stream *stream) {
> +	int retval;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
> +		return -EPERM;
> +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
> +	stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
Set to running state if start is successful.

> +	return retval;
> +}
> +
> +static int snd_compr_stop(struct snd_compr_stream *stream) {
> +	int retval;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
> +		return -EPERM;
> +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
> +	if (!retval) {
> +		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
> +		wake_up(&stream->runtime->sleep);
> +	}
> +	return retval;
> +}
> +
> +static int snd_compr_drain(struct snd_compr_stream *stream) {
> +	int retval;
> +
> +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED ||
> +			stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
> +		return -EPERM;
What happens if the stream is in running state? This will return -EPERM. It should send DRAIN in this case.

> +	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
> +	if (!retval) {
> +		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
> +		wake_up(&stream->runtime->sleep);
> +	}
> +	return retval;
> +}
> +
> +static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned
> +long arg) {
> +	struct snd_compr_file *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +	int retval = -ENOTTY;
> +
> +	BUG_ON(!data);
> +	stream = &data->stream;
> +	BUG_ON(!stream);
> +	mutex_lock(&stream->device->lock);
Simple structure with ioctl functions will reduce lots of code.
It is not anyway doing any specific processing for each ioctl.
> +	switch (_IOC_NR(cmd)) {
> +	case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
> +		put_user(SNDRV_COMPRESS_VERSION,
> +				(int __user *)arg) ? -EFAULT : 0;
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
> +		retval = snd_compr_get_caps(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
> +		retval = snd_compr_get_codec_caps(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
> +		retval = snd_compr_set_params(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
> +		retval = snd_compr_get_params(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
> +		retval = snd_compr_tstamp(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
> +		retval = snd_compr_ioctl_avail(stream, arg);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
> +		retval = snd_compr_pause(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_RESUME):
> +		retval = snd_compr_resume(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_START):
> +		retval = snd_compr_start(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_STOP):
> +		retval = snd_compr_stop(stream);
> +		break;
> +	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
> +		cmd = SND_COMPR_TRIGGER_DRAIN;
> +		retval = snd_compr_drain(stream);
> +		break;
> +	}
> +	mutex_unlock(&stream->device->lock);
> +	return retval;
> +}
> +
> +static const struct file_operations snd_compr_file_ops[2] = {
> +	{
> +		.owner =	THIS_MODULE,
> +		.open =		snd_compr_pb_open,
> +		.release =	snd_compr_free,
> +		.write =	snd_compr_write,
> +		.unlocked_ioctl = snd_compr_ioctl,
> +		.mmap =		snd_compr_mmap,
Suggest you to populate it when implemented.
> +		.poll =		snd_compr_pb_poll,
> +	},
> +	{
> +		.owner =	THIS_MODULE,
> +		.open =		snd_compr_cap_open,
> +		.release =	snd_compr_free,
> +		.read =		snd_compr_read,
> +		.unlocked_ioctl = snd_compr_ioctl,
> +		.mmap =		snd_compr_mmap,
> +		.poll =		snd_compr_cap_poll,
> +	}
> +};
> +
> +static int snd_compress_dev_register(struct snd_device *device) {
> +	int ret;
> +	char str[16];
> +	struct snd_compr *compr;
> +	int devtype, cidx;
> +
> +	if (snd_BUG_ON(!device || !device->device_data))
> +		return -ENXIO;
> +	compr = device->device_data;
> +
> +	for (cidx = 0; cidx < 2; cidx++) {
> +		switch (cidx) {
> +		case 0:
> +			if (!compr->pb)
Can we have the device type or direction in this variable. Suggest you not to use
two variables (cap and pb) here.
> +				continue;
> +			sprintf(str, "comprC%iD%ip", compr->card->number,
> +				compr->device);
> +			pr_debug("reg %s for device %s\n", str, compr->name);
> +			devtype = SNDRV_DEVICE_TYPE_COMPR_PLAYBACK;
> +			break;
> +

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 4/6] compress: add API header and driver header files
  2011-12-02 15:39   ` Nallasellan, Singaravelan
@ 2011-12-02 18:58     ` Pierre-Louis Bossart
       [not found]     ` <000301ccb124$72a53370$57ef9a50$@bossart@linux.intel.com>
  1 sibling, 0 replies; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-12-02 18:58 UTC (permalink / raw)
  To: Nallasellan, Singaravelan, 'Vinod Koul', alsa-devel
  Cc: tiwai, broonie, lrg

> > + * @decoded: Frames decoded by DSP
> > + * @rendered: Frames rendered by DSP into a mixer or an audio output
> > + * @sampling_rate: sampling rate of audio  */ struct
> snd_compr_tstamp {
> > +	size_t copied_bytes;
> > +	size_t copied_total;
> > +	size_t decoded;
> > +	size_t rendered;
> > +	__u32 sampling_rate;
> 
> Is it possible to track the rendering sampling rate in the driver
> itself?

What do you mean? This is a streaming API, the actual rendering rate will
depend on what endpoint you play on.

> > +struct snd_compr_caps {
> > +	__u32 num_codecs;
> > +	__u32 min_fragment_size;
> > +	__u32 max_fragment_size;
> > +	__u32 min_fragments;
> > +	__u32 max_fragments;
> > +	__u32 codecs[MAX_NUM_CODECS];
> > +	__u32 reserved[11];
> 
> Can we add number of compress streams supported in DSP?

You are confusing number of formats supported with number of streams
supported. The latter is exposed through the actual devices supported.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-12-02 16:24   ` Nallasellan, Singaravelan
@ 2011-12-04  4:31     ` Vinod Koul
  2011-12-04  8:14       ` Nallasellan, Singaravelan
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-04  4:31 UTC (permalink / raw)
  To: Nallasellan, Singaravelan
  Cc: tiwai, alsa-devel, broonie, lrg, pierre-louis.bossart

On Fri, 2011-12-02 at 21:54 +0530, Nallasellan, Singaravelan wrote:
> > +static int snd_compr_open(struct file *f,  struct snd_compr *compr,
> int
> > +type) {
> > +	struct snd_compr_file *data;
> > +	struct snd_compr_runtime *runtime;
> > +	int ret;
> > +
> > +	mutex_lock(&device_mutex);
> > +
> > +	data = kzalloc(sizeof(*data), GFP_KERNEL);
> > +	if (!data) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +	data->stream.ops = compr->ops;
> NULL check for compr would help here.
That would be double check, hence bogus
see the pb_open

> > +	data->stream.direction = type;
> > +	data->stream.private_data = compr->private_data;
> > +	data->stream.device = compr;
> > +	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
> > +	if (!runtime) {
> > +		ret = -ENOMEM;
> > +		kfree(data);
> > +		goto out;
> > +	}
> > +	runtime->state = SNDRV_PCM_STATE_OPEN;
> > +	init_waitqueue_head(&runtime->sleep);
> > +	data->stream.runtime = runtime;
> > +	f->private_data = (void *)data;
> > +	ret = compr->ops->open(&data->stream);
> NULL check for ops would help here.
if ops is null you shouldnt be even here, or your driver is buggy so fix
that
> 
> > +	if (ret) {
> > +		kfree(runtime);
> > +		kfree(data);
> > +		goto out;
> > +	}
> > +out:
> > +	mutex_unlock(&device_mutex);
> > +	return ret;
> > +}
> > +
> 
> > +static int snd_compr_free(struct inode *inode, struct file *f) {
> > +	struct snd_compr_file *data = f->private_data;
> > +	mutex_lock(&device_mutex);
> Can we have mutex for each file opened instead of having a single
> mutex for everything?
> I think it is not required to sequence all the streams.
This is changed already per Takashi's comments.
Would help if you read the archives

> 
> > +	data->stream.ops->free(&data->stream);
> > +	kfree(data->stream.runtime->buffer);
> > +	kfree(data->stream.runtime);
> > +	kfree(data);
> > +	mutex_unlock(&device_mutex);
> > +	return 0;
> > +}
> > +
> > +static void snd_compr_update_tstamp(struct snd_compr_stream
> *stream,
> > +		struct snd_compr_tstamp *tstamp)
> > +{
> > +	stream->ops->pointer(stream, tstamp);
> How to ensure that the caller always checks for NULL pointer? 
Not required, ops will be valid and pointer is mandatory callback


> > +
> > +static size_t snd_compr_get_avail(struct snd_compr_stream *stream)
> {
> > +	struct snd_compr_avail avail;
> > +
> Can we update the timestamp before calculating the avail? This will
> allow partial   
> Fragment to be written as well.
yes that is the implementation

> > +	return snd_compr_calc_avail(stream, &avail); }
> > +
> > +static int
> > +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned
> long
> > +arg) {
> > +	struct snd_compr_avail ioctl_avail;
> > +
> Can we update the timestamp before calculating the avail? This will
> allow partial   
> Fragment to be written as well.
ditto

> 
> > +static ssize_t snd_compr_write(struct file *f, const char __user
> *buf,
> > +		size_t count, loff_t *offset)
> > +{
> > +
> > +	/* while initiating the stream, write should be called before
> START
> > +	 * call, so in setup move state */
> > +	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
> > +		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
> Can we implement kind of start threshold similar to PCM path here to
> initiate the playback?
You already know how much is copied into buffer
> 
> > +		pr_debug("stream prepared, Houston we are good to go\n");
> > +	}
> > +
> > +	mutex_unlock(&stream->device->lock);
> > +	return retval;
> > +}
> 
> 
> > +static int snd_compr_resume(struct snd_compr_stream *stream) {
> > +	int retval;
> > +
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
> If the stream is running, I guess it can return 0.
NO. The fact that someone is trying to resume running stream makes me
believe something else is badly written/behaving. This should be told
upfront rather than hidden
> 
> > +		return -EPERM;
> > +	retval = stream->ops->trigger(stream,
> > SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
> > +	if (!retval)
> > +		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
> > +	return retval;
> > +}
> > +
> > +static int snd_compr_start(struct snd_compr_stream *stream) {
> > +	int retval;
> > +
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
> > +		return -EPERM;
> > +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
> > +	stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
> Set to running state if start is successful.
read the archives please

> > +
> > +static int snd_compr_drain(struct snd_compr_stream *stream) {
> > +	int retval;
> > +
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED ||
> > +			stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
> > +		return -EPERM;
> What happens if the stream is in running state? This will return
> -EPERM. It should send DRAIN in this case.
Yes, fixed now

> > +static long snd_compr_ioctl(struct file *f, unsigned int cmd,
> unsigned
> > +long arg) {
> > +	struct snd_compr_file *data = f->private_data;
> > +	struct snd_compr_stream *stream;
> > +	int retval = -ENOTTY;
> > +
> > +	BUG_ON(!data);
> > +	stream = &data->stream;
> > +	BUG_ON(!stream);
> > +	mutex_lock(&stream->device->lock);
> Simple structure with ioctl functions will reduce lots of code.
> It is not anyway doing any specific processing for each ioctl.
Code readability improves

> > +static int snd_compress_dev_register(struct snd_device *device) {
> > +	int ret;
> > +	char str[16];
> > +	struct snd_compr *compr;
> > +	int devtype, cidx;
> > +
> > +	if (snd_BUG_ON(!device || !device->device_data))
> > +		return -ENXIO;
> > +	compr = device->device_data;
> > +
> > +	for (cidx = 0; cidx < 2; cidx++) {
> > +		switch (cidx) {
> > +		case 0:
> > +			if (!compr->pb)
> Can we have the device type or direction in this variable. Suggest you
> not to use
> two variables (cap and pb) here.
The above was correct in that context. We wanted to know which devices
to register playback or capture or both
Nevertheless, this is changed now.


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 4/6] compress: add API header and driver header files
       [not found]     ` <000301ccb124$72a53370$57ef9a50$@bossart@linux.intel.com>
@ 2011-12-04  7:41       ` Nallasellan, Singaravelan
  2011-12-05 14:14         ` Pierre-Louis Bossart
       [not found]         ` <000001ccb358$2b9e4b70$82dae250$@bossart@linux.intel.com>
  0 siblings, 2 replies; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-04  7:41 UTC (permalink / raw)
  To: Pierre-Louis Bossart, 'Vinod Koul', alsa-devel
  Cc: tiwai, broonie, lrg

> > > + * @decoded: Frames decoded by DSP
> > > + * @rendered: Frames rendered by DSP into a mixer or an audio
> > > + output
> > > + * @sampling_rate: sampling rate of audio  */ struct
> > snd_compr_tstamp {
> > > +	size_t copied_bytes;
> > > +	size_t copied_total;
> > > +	size_t decoded;
> > > +	size_t rendered;
> > > +	__u32 sampling_rate;
> >
> > Is it possible to track the rendering sampling rate in the driver
> > itself?
> 
> What do you mean? This is a streaming API, the actual rendering rate will depend on
> what endpoint you play on.

I guess the driver should know the sampling rate of the endpoint. If only the DSP knows 
about the endpoint sampling rate, this will make sense.

> 
> > > +struct snd_compr_caps {
> > > +	__u32 num_codecs;
> > > +	__u32 min_fragment_size;
> > > +	__u32 max_fragment_size;
> > > +	__u32 min_fragments;
> > > +	__u32 max_fragments;
> > > +	__u32 codecs[MAX_NUM_CODECS];
> > > +	__u32 reserved[11];
> >
> > Can we add number of compress streams supported in DSP?
> 
> You are confusing number of formats supported with number of streams supported.
> The latter is exposed through the actual devices supported.

No, DSP may be able to support only so many simultaneous streams at any point of time. 
Yet, DSP can support any number of formats. Though the device entry may be created for
each compressed stream, how will the user space programs get the number of compressed streams supported?

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-12-04  4:31     ` Vinod Koul
@ 2011-12-04  8:14       ` Nallasellan, Singaravelan
  2011-12-05 15:19         ` Pierre-Louis Bossart
       [not found]         ` <001501ccb361$3af49990$b0ddccb0$@bossart@linux.intel.com>
  0 siblings, 2 replies; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-04  8:14 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg, pierre-louis.bossart

> > > +	stream->ops->pointer(stream, tstamp);
> > How to ensure that the caller always checks for NULL pointer?
> Not required, ops will be valid and pointer is mandatory callback

So any buggy driver can cause oops in the compressed core?

> >
> > > +static ssize_t snd_compr_write(struct file *f, const char __user
> > *buf,
> > > +		size_t count, loff_t *offset)
> > > +{
> > > +
> > > +	/* while initiating the stream, write should be called before
> > START
> > > +	 * call, so in setup move state */
> > > +	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
> > > +		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
> > Can we implement kind of start threshold similar to PCM path here to
> > initiate the playback?
> You already know how much is copied into buffer
You expect the user space to explicitly invoke START. Is it right?
If threshold is implemented, the user space does not require to track the
bytes_written/read.
> >
> > > +		pr_debug("stream prepared, Houston we are good to go\n");
> > > +	}
> > > +
> > > +	mutex_unlock(&stream->device->lock);
> > > +	return retval;
> > > +}
> >
> > > +static int snd_compr_start(struct snd_compr_stream *stream) {
> > > +	int retval;
> > > +
> > > +	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
> > > +		return -EPERM;
> > > +	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
> > > +	stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
> > Set to running state if start is successful.
> read the archives please
Sure, it will not harm if you respond to this. 
> 
> > > +static long snd_compr_ioctl(struct file *f, unsigned int cmd,
> > unsigned
> > > +long arg) {
> > > +	struct snd_compr_file *data = f->private_data;
> > > +	struct snd_compr_stream *stream;
> > > +	int retval = -ENOTTY;
> > > +
> > > +	BUG_ON(!data);
> > > +	stream = &data->stream;
> > > +	BUG_ON(!stream);
> > > +	mutex_lock(&stream->device->lock);
> > Simple structure with ioctl functions will reduce lots of code.
> > It is not anyway doing any specific processing for each ioctl.
> Code readability improves
Not sure other way does not help readability. Try to make it simple.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [PATCH v3 0/6] core: add compress data API to ALSA kernel
  2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
@ 2011-12-05  7:39   ` Vinod Koul
  2011-12-06  7:27     ` Jassi Brar
                       ` (15 more replies)
  2011-12-05  7:39   ` [PATCH v3 1/6] compress API documentation Vinod Koul
                     ` (5 subsequent siblings)
  6 siblings, 16 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-05  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg

As agreed during the ASoC workshop in May 2011, this set of patches are a
proposal from Intel to add a new compressed data interface to ALSA. This
proposal builds on the existing Intel solution and the experience gathered over
two years with Meego and Android solutions. This proposal is no longer
Intel-specific and was generalized with the addition of a basic core;
codec-related definitions are based on the vendor-neutral OpenMAX AL standard. 

These patches are also available in git tree:
git://git.infradead.org/users/vkoul/snd-compress.git v3_patches

Changes in v3:
 Fixed the device registration for compressed devices as discussed
 moved card creation to lower level drivers
 Added new api for device node creation
 changes fragment/frame callbacks to single inlined callback

Changes in v2:
 Fixed the comments revived in v2
 Fixed the comments recieved during LPC discussions
 add support for alsa device registeration
 fix the bugs found in testing

Omair Mohammed Abdullah (1):
  core: add support for compressed devices

Pierre-Louis Bossart (1):
  compress API documentation

Vinod Koul (4):
  core: add compress parameter definations
  core: add API header and driver header files
  core: add support for compress_offload
  core: add makefile and kconfig file for compress

 Documentation/sound/alsa/snd_compress_data.txt |  184 +++++++
 include/sound/compress_driver.h                |  164 ++++++
 include/sound/compress_offload.h               |  151 +++++
 include/sound/core.h                           |    1 +
 include/sound/minors.h                         |    7 +-
 include/sound/snd_compress_params.h            |  395 +++++++++++++
 sound/core/Kconfig                             |    8 +
 sound/core/Makefile                            |    4 +
 sound/core/compress_offload.c                  |  701 ++++++++++++++++++++++++
 sound/core/sound.c                             |    6 +
 10 files changed, 1620 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/sound/alsa/snd_compress_data.txt
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h
 create mode 100644 include/sound/snd_compress_params.h
 create mode 100644 sound/core/compress_offload.c

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [PATCH v3 1/6] compress API documentation
  2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
@ 2011-12-05  7:39   ` Vinod Koul
  2011-12-05  7:39   ` [PATCH v3 2/6] core: add support for compressed devices Vinod Koul
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-05  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

The patch adds the documentation file explaining the API

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
---
 Documentation/sound/alsa/snd_compress_data.txt |  184 ++++++++++++++++++++++++
 1 files changed, 184 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/sound/alsa/snd_compress_data.txt

diff --git a/Documentation/sound/alsa/snd_compress_data.txt b/Documentation/sound/alsa/snd_compress_data.txt
new file mode 100644
index 0000000..4b0d0fc
--- /dev/null
+++ b/Documentation/sound/alsa/snd_compress_data.txt
@@ -0,0 +1,184 @@
+		snd_compress_data.txt
+		=====================
+	Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+		Vinod Koul <vinod.koul@linux.intel.com>
+
+Overview
+
+Since its early days, the ALSA API was defined with PCM support or
+constant bitrates payloads such as IEC61937 in mind. Arguments and
+returned values in frames are the norm, making it a challenge to
+extend the existing API to compressed data streams.
+
+In recent years, audio digital signal processors (DSP) were integrated
+in system-on-chip designs, and DSPs are also integrated in audio
+codecs. Processing compressed data on such DSPs results in a dramatic
+reduction of power consumption compared to host-based
+processing. Support for such hardware has not been very good in Linux,
+mostly because of a lack of a generic API available in the mainline
+kernel.
+
+Rather than requiring a compability break with an API change of the
+ALSA PCM interface, a new 'Compressed Data' API is introduced to
+provide a control and data-streaming interface for audio DSPs.
+
+The design of this API was inspired by the 2-year experience with the
+Intel Moorestown SOC, with many corrections required to upstream the
+API in the mainline kernel instead of the staging tree and make it
+usable by others.
+
+Requirements
+
+The main requirements are:
+
+- separation between byte counts and time. Compressed formats may have
+  a header per file, per frame, or no header at all. The payload size
+  may vary from frame-to-frame. As a result, it is not possible to
+  estimate reliably the duration of audio buffers when handling
+  compressed data. Dedicated mechanisms are required to allow for
+  reliable audio-video synchronization, which requires precise
+  reporting of the number of samples rendered at any given time.
+
+- Handling of multiple formats. PCM data only requires a specification
+  of the sampling rate, number of channels and bits per sample. In
+  contrast, compressed data comes in a variety of formats. Audio DSPs
+  may also provide support for a limited number of audio encoders and
+  decoders embedded in firmware, or may support more choices through
+  dynamic download of libraries.
+
+- Focus on main formats. This API provides support for the most
+  popular formats used for audio and video capture and playback. It is
+  likely that as audio compression technology advances, new formats
+  will be added.
+
+- Handling of multiple configurations. Even for a given format like
+  AAC, some implementations may support AAC multichannel but HE-AAC
+  stereo. Likewise WMA10 level M3 may require too much memory and cpu
+  cycles. The new API needs to provide a generic way of listing these
+  formats.
+
+- Rendering/Grabbing only. This API does not provide any means of
+  hardware acceleration, where PCM samples are provided back to
+  user-space for additional processing. This API focuses instead on
+  streaming compressed data to a DSP, with the assumption that the
+  decoded samples are routed to a physical output or logical back-end.
+
+ - Complexity hiding. Existing user-space multimedia frameworks all
+  have existing enums/structures for each compressed format. This new
+  API assumes the existence of a platform-specific compatibility layer
+  to expose, translate and make use of the capabilities of the audio
+  DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
+  applications are not supposed to make use of this API.
+
+
+Design
+
+The new API shares a number of concepts with with the PCM API for flow
+control. Start, pause, resume, drain and stop commands have the same
+semantics no matter what the content is.
+
+The concept of memory ring buffer divided in a set of fragments is
+borrowed from the ALSA PCM API. However, only sizes in bytes can be
+specified.
+
+Seeks/trick modes are assumed to be handled by the host.
+
+The notion of rewinds/forwards is not supported. Data committed to the
+ring buffer cannot be invalidated, except when dropping all buffers.
+
+The Compressed Data API does not make any assumptions on how the data
+is transmitted to the audio DSP. DMA transfers from main memory to an
+embedded audio cluster or to a SPI interface for external DSPs are
+possible. As in the ALSA PCM case, a core set of routines is exposed;
+each driver implementer will have to write support for a set of
+mandatory routines and possibly make use of optional ones.
+
+The main additions are
+
+- get_caps
+This routine returns the list of audio formats supported. Querying the
+codecs on a capture stream will return encoders, decoders will be
+listed for playback streams.
+
+- get_codec_caps
+For each codec, this routine returns a list of capabilities. The
+intent is to make sure all the capabilities correspond to valid
+settings, and to minimize the risks of configuration failures. For
+example, for a complex codec such as AAC, the number of channels
+supported may depend on a specific profile. If the capabilities were
+exposed with a single descriptor, it may happen that a specific
+combination of profiles/channels/formats may not be
+supported. Likewise, embedded DSPs have limited memory and cpu cycles,
+it is likely that some implementations make the list of capabilities
+dynamic and dependent on existing workloads.
+
+- set_params
+This routine sets the configuration chosen for a specific codec. The
+most important field in the parameters is the codec type; in most
+cases decoders will ignore other fields, while encoders will strictly
+comply to the settings
+
+- get_params
+This routines returns the actual settings used by the DSP. Changes to
+the settings should remain the exception.
+
+- get_timestamp
+The timestamp becomes a multiple field structure. It lists the number
+of bytes transferred, the number of samples processed and the number
+of samples rendered/grabbed. All these values can be used to determine
+the avarage bitrate, figure out if the ring buffer needs to be
+refilled or the delay due to decoding/encoding/io on the DSP.
+
+Note that the list of codecs/profiles/modes was derived from the
+OpenMAX AL specification instead of reinventing the wheel.
+Modifications include:
+- Addition of FLAC and IEC formats
+- Merge of encoder/decoder capabilities
+- Profiles/modes listed as bitmasks to make descriptors more compact
+- Addition of set_params for decoders (missing in OpenMAX AL)
+- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
+- Addition of format information for WMA
+- Addition of encoding options when required (derived from OpenMAX IL)
+- Addition of rateControlSupported (missing in OpenMAX AL)
+
+Not supported:
+
+- Support for VoIP/circuit-switched calls is not the target of this
+  API. Support for dynamic bit-rate changes would require a tight
+  coupling between the DSP and the host stack, limiting power savings.
+
+- Packet-loss concealment is not supported. This would require an
+  additional interface to let the decoder synthesize data when frames
+  are lost during transmission. This may be added in the future.
+
+- Volume control/routing is not handled by this API. Devices exposing a
+  compressed data interface will be considered as regular ALSA devices;
+  volume changes and routing information will be provided with regular
+  ALSA kcontrols.
+
+- Embedded audio effects. Such effects should be enabled in the same
+  manner, no matter if the input was PCM or compressed.
+
+- multichannel IEC encoding. Unclear if this is required.
+
+- Encoding/decoding acceleration is not supported as mentioned
+  above. It is possible to route the output of a decoder to a capture
+  stream, or even implement transcoding capabilities. This routing
+  would be enabled with ALSA kcontrols.
+
+- Audio policy/resource management. This API does not provide any
+  hooks to query the utilization of the audio DSP, nor any premption
+  mechanisms.
+
+- No notion of underun/overrun. Since the bytes written are compressed
+  in nature and data written/read doesn't translate directly to
+  rendered output in time, this does not deal with underrun/overun and
+  maybe dealt in user-library
+
+Credits:
+- Mark Brown and Liam Girdwood for discussions on the need for this API
+- Harsha Priya for her work on intel_sst compressed API
+- Rakesh Ughreja for valuable feedback
+- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
+  demonstrating and quantifying the benefits of audio offload on a
+  real platform.
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v3 2/6] core: add support for compressed devices
  2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
  2011-12-05  7:39   ` [PATCH v3 1/6] compress API documentation Vinod Koul
@ 2011-12-05  7:39   ` Vinod Koul
  2011-12-05  7:39   ` [PATCH v3 3/6] core: add compress parameter definations Vinod Koul
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-05  7:39 UTC (permalink / raw)
  To: alsa-devel
  Cc: Vinod Koul, tiwai, broonie, Pierre-Louis Bossart,
	Omair Mohammed Abdullah, lrg

From: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>

Use the two minor numbers 2 and 3 for audio compressed offload devices.
Also add support for these devices in core

Signed-off-by: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 include/sound/core.h   |    1 +
 include/sound/minors.h |    7 ++++++-
 sound/core/sound.c     |    6 ++++++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/include/sound/core.h b/include/sound/core.h
index 1fa2407..9d1e54b 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -62,6 +62,7 @@ typedef int __bitwise snd_device_type_t;
 #define	SNDRV_DEV_BUS		((__force snd_device_type_t) 0x1007)
 #define	SNDRV_DEV_CODEC		((__force snd_device_type_t) 0x1008)
 #define	SNDRV_DEV_JACK          ((__force snd_device_type_t) 0x1009)
+#define	SNDRV_DEV_COMPRESS	((__force snd_device_type_t) 0x100A)
 #define	SNDRV_DEV_LOWLEVEL	((__force snd_device_type_t) 0x2000)
 
 typedef int __bitwise snd_device_state_t;
diff --git a/include/sound/minors.h b/include/sound/minors.h
index 8f76420..faaeb64 100644
--- a/include/sound/minors.h
+++ b/include/sound/minors.h
@@ -35,7 +35,8 @@
 #define SNDRV_MINOR_TIMER		33	/* SNDRV_MINOR_GLOBAL + 1 * 32 */
 
 #ifndef CONFIG_SND_DYNAMIC_MINORS
-						/* 2 - 3 (reserved) */
+#define SNDRV_MINOR_COMPR_PLAYBACK	2
+#define SNDRV_MINOR_COMPR_CAPTURE	3
 #define SNDRV_MINOR_HWDEP		4	/* 4 - 7 */
 #define SNDRV_MINOR_RAWMIDI		8	/* 8 - 15 */
 #define SNDRV_MINOR_PCM_PLAYBACK	16	/* 16 - 23 */
@@ -49,6 +50,8 @@
 #define SNDRV_DEVICE_TYPE_PCM_CAPTURE	SNDRV_MINOR_PCM_CAPTURE
 #define SNDRV_DEVICE_TYPE_SEQUENCER	SNDRV_MINOR_SEQUENCER
 #define SNDRV_DEVICE_TYPE_TIMER		SNDRV_MINOR_TIMER
+#define SNDRV_DEVICE_TYPE_COMPR_PLAYBACK SNDRV_MINOR_COMPR_PLAYBACK
+#define SNDRV_DEVICE_TYPE_COMPR_CAPTURE	SNDRV_MINOR_COMPR_CAPTURE
 
 #else /* CONFIG_SND_DYNAMIC_MINORS */
 
@@ -60,6 +63,8 @@ enum {
 	SNDRV_DEVICE_TYPE_RAWMIDI,
 	SNDRV_DEVICE_TYPE_PCM_PLAYBACK,
 	SNDRV_DEVICE_TYPE_PCM_CAPTURE,
+	SNDRV_DEVICE_TYPE_COMPR_PLAYBACK,
+	SNDRV_DEVICE_TYPE_COMPR_CAPTURE,
 };
 
 #endif /* CONFIG_SND_DYNAMIC_MINORS */
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 1c7a3ef..9377807 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -233,6 +233,12 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
 			return -EINVAL;
 		minor = SNDRV_MINOR(card->number, type + dev);
 		break;
+	case SNDRV_DEVICE_TYPE_COMPR_PLAYBACK:
+	case SNDRV_DEVICE_TYPE_COMPR_CAPTURE:
+		if (snd_BUG_ON(!card))
+			return -EINVAL;
+		minor = SNDRV_MINOR(card->number, type);
+		break;
 	default:
 		return -EINVAL;
 	}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v3 3/6] core: add compress parameter definations
  2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
                     ` (2 preceding siblings ...)
  2011-12-05  7:39   ` [PATCH v3 2/6] core: add support for compressed devices Vinod Koul
@ 2011-12-05  7:39   ` Vinod Koul
  2011-12-05  7:39   ` [PATCH v3 4/6] core: add API header and driver header files Vinod Koul
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-05  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

The patch adds the various definations used to define the encoder
and decoder parameters

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 include/sound/snd_compress_params.h |  395 +++++++++++++++++++++++++++++++++++
 1 files changed, 395 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/snd_compress_params.h

diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
new file mode 100644
index 0000000..79b681d
--- /dev/null
+++ b/include/sound/snd_compress_params.h
@@ -0,0 +1,395 @@
+/*
+ *  snd_compress_params.h - codec types and parameters for compressed data
+ *  streaming interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *              Vinod Koul <vinod.koul@linux.intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The definitions in this file are derived from the OpenMAX AL version 1.1
+ * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
+ *
+ * Copyright (c) 2007-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and/or associated documentation files (the
+ * "Materials "), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+#ifndef __SND_COMPRESS_PARAMS_H
+#define __SND_COMPRESS_PARAMS_H
+
+/* AUDIO CODECS SUPPORTED */
+#define MAX_NUM_CODECS 32
+#define MAX_NUM_CODEC_DESCRIPTORS 32
+#define MAX_NUM_BITRATES 32
+
+/* Codecs are listed linearly to allow for extensibility */
+#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
+#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
+#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
+#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
+#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
+#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
+#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
+#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
+#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
+#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
+#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
+#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
+#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
+
+/*
+ * Profile and modes are listed with bit masks. This allows for a
+ * more compact representation of fields that will not evolve
+ * (in contrast to the list of codecs)
+ */
+
+#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
+
+/* MP3 modes are only useful for encoders */
+#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
+#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
+#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
+#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
+
+/* AMR modes are only useful for encoders */
+#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
+
+#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
+#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
+
+#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
+
+/* AMRWB modes are only useful for encoders */
+#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
+
+/* AAC modes are required for encoders and decoders */
+#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
+#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
+#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
+#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
+#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
+#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
+#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
+
+/* AAC formats are required for encoders and decoders */
+#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
+#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
+
+#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
+#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
+#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
+#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
+
+#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
+#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
+#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
+#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
+#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
+#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
+#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
+
+#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
+/*
+ * Some implementations strip the ASF header and only send ASF packets
+ * to the DSP
+ */
+#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
+
+#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
+#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
+
+/*
+ * Define quality levels for FLAC encoders, from LEVEL0 (fast)
+ * to LEVEL8 (best)
+ */
+#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
+#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
+#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
+#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
+#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
+#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
+#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
+
+#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
+
+/* IEC61937 payloads without CUVP and preambles */
+#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
+/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
+#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
+
+/*
+ * IEC modes are mandatory for decoders. Format autodetection
+ * will only happen on the DSP side with mode 0. The PCM mode should
+ * not be used, the PCM codec should be used instead.
+ */
+#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
+#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
+#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
+#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
+#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
+#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
+#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
+#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
+#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
+#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
+#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
+#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
+#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
+#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
+#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
+#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
+#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
+#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
+#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
+
+#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
+#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
+
+/* <FIXME: multichannel encoders aren't supported for now. Would need
+   an additional definition of channel arrangement> */
+
+/* VBR/CBR definitions */
+#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
+#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
+
+/* Encoder options */
+
+struct snd_enc_wma {
+	__u32 super_block_align; /* WMA Type-specific data */
+};
+
+
+/**
+ * struct snd_enc_vorbis
+ * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
+ * In the default mode of operation, the quality level is 3.
+ * Normal quality range is 0 - 10.
+ * @managed: Boolean. Set  bitrate  management  mode. This turns off the
+ * normal VBR encoding, but allows hard or soft bitrate constraints to be
+ * enforced by the encoder. This mode can be slower, and may also be
+ * lower quality. It is primarily useful for streaming.
+ * @max_bit_rate: Enabled only if managed is TRUE
+ * @min_bit_rate: Enabled only if managed is TRUE
+ * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
+ * non-stereo streams). Useful for lower-bitrate encoding.
+ *
+ * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
+ * properties
+ *
+ * For best quality users should specify VBR mode and set quality levels.
+ */
+
+struct snd_enc_vorbis {
+	int quality;
+	__u32 managed;
+	__u32 max_bit_rate;
+	__u32 min_bit_rate;
+	__u32 downmix;
+};
+
+
+/**
+ * struct snd_enc_real
+ * @quant_bits: number of coupling quantization bits in the stream
+ * @start_region: coupling start region in the stream
+ * @num_regions: number of regions value
+ *
+ * These options were extracted from the OpenMAX IL spec
+ */
+
+struct snd_enc_real {
+	__u32 quant_bits;
+	__u32 start_region;
+	__u32 num_regions;
+};
+
+/**
+ * struct snd_enc_flac
+ * @num: serial number, valid only for OGG formats
+ *	needs to be set by application
+ * @gain: Add replay gain tags
+ *
+ * These options were extracted from the FLAC online documentation
+ * at http://flac.sourceforge.net/documentation_tools_flac.html
+ *
+ * To make the API simpler, it is assumed that the user will select quality
+ * profiles. Additional options that affect encoding quality and speed can
+ * be added at a later stage if needed.
+ *
+ * By default the Subset format is used by encoders.
+ *
+ * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
+ * not supported in this API.
+ */
+
+struct snd_enc_flac {
+	__u32 num;
+	__u32 gain;
+};
+
+struct snd_enc_generic {
+	__u32 bw;	/* encoder bandwidth */
+	int reserved[15];
+};
+
+union snd_codec_options {
+	struct snd_enc_wma wma;
+	struct snd_enc_vorbis vorbis;
+	struct snd_enc_real real;
+	struct snd_enc_flac flac;
+	struct snd_enc_generic generic;
+};
+
+/** struct snd_codec_desc - description of codec capabilities
+ * @max_ch: Maximum number of audio channels
+ * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
+ * @bit_rate: Indexed array containing supported bit rates
+ * @num_bitrates: Number of valid values in bit_rate array
+ * @rate_control: value is specified by SND_RATECONTROLMODE defines.
+ * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
+ * @modes: Supported modes. See SND_AUDIOMODE defines
+ * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
+ * @reserved: reserved for future use
+ *
+ * This structure provides a scalar value for profiles, modes and stream
+ * format fields.
+ * If an implementation supports multiple combinations, they will be listed as
+ * codecs with different descriptors, for example there would be 2 descriptors
+ * for AAC-RAW and AAC-ADTS.
+ * This entails some redundancy but makes it easier to avoid invalid
+ * configurations.
+ *
+ */
+
+struct snd_codec_desc {
+	__u32 max_ch;
+	__u32 sample_rates;
+	__u32 bit_rate[MAX_NUM_BITRATES];
+	__u32 num_bitrates;
+	__u32 rate_control;
+	__u32 profiles;
+	__u32 modes;
+	__u32 formats;
+	__u32 reserved[16];
+};
+
+/** struct snd_codec
+ * @id: Identifies the supported audio encoder/decoder.
+ *		See SND_AUDIOCODEC macros.
+ * @ch_in: Number of input audio channels
+ * @ch_out: Number of output channels. In case of contradiction between
+ *		this field and the channelMode field, the channelMode field
+ *		overrides.
+ * @sample_rate: Audio sample rate of input data
+ * @bit_rate: Bitrate of encoded data. May be ignored by decoders
+ * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
+ *               Encoders may rely on profiles for quality levels.
+ *		 May be ignored by decoders.
+ * @profile: Mandatory for encoders, can be mandatory for specific
+ *		decoders as well. See SND_AUDIOPROFILE defines.
+ * @level: Supported level (Only used by WMA at the moment)
+ * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
+ * @format: Format of encoded bistream. Mandatory when defined.
+ *		See SND_AUDIOSTREAMFORMAT defines.
+ * @align: Block alignment in bytes of an audio sample.
+ *		Only required for PCM or IEC formats.
+ * @options: encoder-specific settings
+ * @reserved: reserved for future use
+ */
+
+struct snd_codec {
+	__u32 id;
+	__u32 ch_in;
+	__u32 ch_out;
+	__u32 sample_rate;
+	__u32 bit_rate;
+	__u32 rate_control;
+	__u32 profile;
+	__u32 level;
+	__u32 ch_mode;
+	__u32 format;
+	__u32 align;
+	union snd_codec_options options;
+	__u32 reserved[3];
+};
+
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v3 4/6] core: add API header and driver header files
  2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
                     ` (3 preceding siblings ...)
  2011-12-05  7:39   ` [PATCH v3 3/6] core: add compress parameter definations Vinod Koul
@ 2011-12-05  7:39   ` Vinod Koul
  2011-12-13  6:11     ` Mark Brown
  2011-12-05  7:39   ` [PATCH v3 5/6] core: add support for compress_offload Vinod Koul
  2011-12-05  7:39   ` [PATCH v3 6/6] core: add makefile and kconfig file for compress Vinod Koul
  6 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-05  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

This patch adds the header files for ioctl definations and header file for
driver APIs for lower level device drivers to use

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 include/sound/compress_driver.h  |  164 ++++++++++++++++++++++++++++++++++++++
 include/sound/compress_offload.h |  151 +++++++++++++++++++++++++++++++++++
 2 files changed, 315 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h

diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
new file mode 100644
index 0000000..600156b
--- /dev/null
+++ b/include/sound/compress_driver.h
@@ -0,0 +1,164 @@
+/*
+ *  compress_driver.h - compress offload driver definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_DRIVER_H
+#define __COMPRESS_DRIVER_H
+
+#include <sound/compress_offload.h>
+#include <sound/asound.h>
+#include <sound/pcm.h>
+
+struct snd_compr_ops;
+
+/**
+ * struct snd_compr_runtime: runtime stream description
+ * @state: stream state
+ * @ops: pointer to DSP callbacks
+ * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
+ *	DSP doesn't implement copy
+ * @buffer_size: size of the above buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ * @hw_pointer: offset of last location in buffer where DSP copied data
+ * @app_pointer: offset of last location in buffer where app wrote data
+ * @bytes_written: cummilative bytes written to device
+ * @bytes_copied: cummilative bytes copied by DSP
+ * @sleep: poll sleep
+ */
+struct snd_compr_runtime {
+	snd_pcm_state_t state;
+	struct snd_compr_ops *ops;
+	void *buffer;
+	size_t buffer_size;
+	size_t fragment_size;
+	unsigned int fragments;
+	size_t hw_pointer;
+	size_t app_pointer;
+	size_t bytes_written;
+	size_t bytes_copied;
+	wait_queue_head_t sleep;
+};
+
+/**
+ * struct snd_compr_stream: compressed stream
+ * @name: device name
+ * @ops: pointer to DSP callbacks
+ * @runtime: pointer to runtime structure
+ * @device: device pointer
+ * @direction: stream direction, playback/recording
+ * @private_data: pointer to DSP private data
+ */
+struct snd_compr_stream {
+	const char *name;
+	struct snd_compr_ops *ops;
+	struct snd_compr_runtime *runtime;
+	struct snd_compr *device;
+	unsigned int direction;
+	void *private_data;
+};
+
+/**
+ * struct snd_compr_ops: compressed path DSP operations
+ * @open: Open the compressed stream
+ * This callback is mandatory and shall keep dsp ready to receive the stream
+ * parameter
+ * @free: Close the compressed stream, mandatory
+ * @set_params: Sets the compressed stream parameters, mandatory
+ * This can be called in during stream creation only to set codec params
+ * and the stream properties
+ * @get_params: retrieve the codec parameters, mandatory
+ * @trigger: Trigger operations like start, pause, resume, drain, stop.
+ * This callback is mandatory
+ * @pointer: Retrieve current h/w pointer information. Mandatory
+ * @copy: Copy the compressed data to/from userspace, Optional
+ * Can't be implemented if DSP supports mmap
+ * @mmap: DSP mmap method to mmap DSP memory
+ * @ack: Ack for DSP when data is written to audio buffer, Optional
+ * Not valid if copy is implemented
+ * @get_caps: Retrieve DSP capabilities, mandatory
+ * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory
+ */
+struct snd_compr_ops {
+	int (*open)(struct snd_compr_stream *stream);
+	int (*free)(struct snd_compr_stream *stream);
+	int (*set_params)(struct snd_compr_stream *stream,
+			struct snd_compr_params *params);
+	int (*get_params)(struct snd_compr_stream *stream,
+			struct snd_codec *params);
+	int (*trigger)(struct snd_compr_stream *stream, int cmd);
+	int (*pointer)(struct snd_compr_stream *stream,
+			struct snd_compr_tstamp *tstamp);
+	int (*copy)(struct snd_compr_stream *stream, const char __user *buf,
+		       size_t count);
+	int (*mmap)(struct snd_compr_stream *stream,
+			struct vm_area_struct *vma);
+	int (*ack)(struct snd_compr_stream *stream, size_t bytes);
+	int (*get_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_caps *caps);
+	int (*get_codec_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_codec_caps *codec);
+};
+
+/**
+ * struct snd_compr: Compressed device
+ * @name: DSP device name
+ * @dev: Device pointer
+ * @ops: pointer to DSP callbacks
+ * @private_data: pointer to DSP pvt data
+ * @card: sound card pointer
+ * @direction: Playback or capture direction
+ * @lock: device lock
+ * @device: device id
+ */
+struct snd_compr {
+	const char *name;
+	struct device *dev;
+	struct snd_compr_ops *ops;
+	void *private_data;
+	struct snd_card *card;
+	unsigned int direction;
+	struct mutex lock;
+	int device;
+};
+
+/* compress device register APIs */
+int snd_compress_register(struct snd_compr *device);
+int snd_compress_deregister(struct snd_compr *device);
+int snd_compress_new(struct snd_card *card, int device,
+			int type, struct snd_compr *compr);
+
+/* dsp driver callback apis
+ * For playback: driver should call snd_compress_fragment_elapsed() to let the
+ * framework know that a fragment has been consumed from the ring buffer
+ *
+ * For recording: we want to know when a frame is available or when
+ * at least one frame is available so snd_compress_frame_elapsed()
+ * callback should be called when a encodeded frame is available
+ */
+static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
+{
+	wake_up(&stream->runtime->sleep);
+}
+
+#endif
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
new file mode 100644
index 0000000..2358c86
--- /dev/null
+++ b/include/sound/compress_offload.h
@@ -0,0 +1,151 @@
+/*
+ *  compress_offload.h - compress offload header definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_OFFLOAD_H
+#define __COMPRESS_OFFLOAD_H
+
+#include <linux/types.h>
+#include <sound/asound.h>
+#include <sound/snd_compress_params.h>
+
+
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
+/**
+ * struct snd_compressed_buffer: compressed buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ */
+struct snd_compressed_buffer {
+	size_t fragment_size;
+	int fragments;
+};
+
+/**
+ * struct snd_compr_params: compressed stream params
+ * @buffer: buffer description
+ * @codec: codec parameters
+ * @no_wake_mode: dont wake on fragment elapsed
+ */
+struct snd_compr_params {
+	struct snd_compressed_buffer buffer;
+	struct snd_codec codec;
+	bool no_wake_mode;
+};
+
+/**
+ * struct snd_compr_tstamp: timestamp descriptor
+ * @copied_bytes: Number of bytes offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from/to ring buffer to/by DSP
+ * @frames: Frames decoded or encoded by DSP
+ * @rendered: Frames rendered or recieved by DSP into a mixer or an audio
+ * output/input
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp {
+	size_t copied_bytes;
+	size_t copied_total;
+	size_t frames;
+	size_t rendered;
+	__u32 sampling_rate;
+};
+
+/**
+ * struct snd_compr_avail: avail descriptor
+ * @avail: Number of bytes available in ring buffer for writing/reading
+ * @tstamp: timestamp infomation
+ */
+struct snd_compr_avail {
+	size_t avail;
+	struct snd_compr_tstamp tstamp;
+};
+
+/**
+ * struct snd_compr_caps: caps descriptor
+ * @codecs: pointer to array of codecs
+ * @min_fragment_size: minimum fragment supported by DSP
+ * @max_fragment_size: maximum fragment supported by DSP
+ * @min_fragments: min fragments supported by DSP
+ * @max_fragments: max fragments supported by DSP
+ * @num_codecs: number of codecs supported
+ * @reserved: reserved field
+ */
+struct snd_compr_caps {
+	__u32 num_codecs;
+	__u32 min_fragment_size;
+	__u32 max_fragment_size;
+	__u32 min_fragments;
+	__u32 max_fragments;
+	__u32 codecs[MAX_NUM_CODECS];
+	__u32 reserved[11];
+};
+
+/**
+ * struct snd_compr_codec_caps: query capability of codec
+ * @codec: codec for which capability is queried
+ * @num_descriptors: number of codec descriptors
+ * @descriptor: array of codec capability descriptor
+ */
+struct snd_compr_codec_caps {
+	__u32 codec;
+	__u32 num_descriptors;
+	struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
+};
+
+/**
+ * compress path ioctl definitions
+ * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
+ * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
+ * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
+ * Note: only codec params can be changed runtime and stream params cant be
+ * SNDRV_COMPRESS_GET_PARAMS: Query codec params
+ * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
+ * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
+ * This also queries the tstamp properties
+ * SNDRV_COMPRESS_PAUSE: Pause the running stream
+ * SNDRV_COMPRESS_RESUME: resume a paused stream
+ * SNDRV_COMPRESS_START: Start a stream
+ * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
+ * and the buffers currently with DSP
+ * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
+ * SNDRV_COMPRESS_IOCTL_VERSION: Query the API version
+ */
+#define SNDRV_COMPRESS_IOCTL_VERSION	_IOR('C', 0x00, int)
+#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x10, struct snd_compr_caps)
+#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x11, struct snd_compr_codec_caps)
+#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x12, struct snd_compr_params)
+#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x13, struct snd_codec)
+#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x20, struct snd_compr_tstamp)
+#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x21, struct snd_compr_avail)
+#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x30)
+#define SNDRV_COMPRESS_RESUME		_IO('C', 0x31)
+#define SNDRV_COMPRESS_START		_IO('C', 0x32)
+#define SNDRV_COMPRESS_STOP		_IO('C', 0x33)
+#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x34)
+/*
+ * TODO
+ * 1. add mmap support
+ *
+ */
+#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v3 5/6] core: add support for compress_offload
  2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
                     ` (4 preceding siblings ...)
  2011-12-05  7:39   ` [PATCH v3 4/6] core: add API header and driver header files Vinod Koul
@ 2011-12-05  7:39   ` Vinod Koul
  2011-12-13  6:09     ` Mark Brown
  2011-12-05  7:39   ` [PATCH v3 6/6] core: add makefile and kconfig file for compress Vinod Koul
  6 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-05  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

This patch adds core.c, the file which implements the ioctls and
registers the devices

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/core/compress_offload.c |  701 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 701 insertions(+), 0 deletions(-)
 create mode 100644 sound/core/compress_offload.c

diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
new file mode 100644
index 0000000..b77f8fa
--- /dev/null
+++ b/sound/core/compress_offload.c
@@ -0,0 +1,701 @@
+/*
+ *  core.c - compress offload core
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
+#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
+
+/* TODO:
+ * - add substream support for multiple devices in case of
+ *	SND_DYNAMIC_MINORS is not used
+ * - Multiple node representation
+ *	driver should be able to register multiple nodes
+ */
+
+static DEFINE_MUTEX(device_mutex);
+
+struct snd_compr_file {
+	unsigned long caps;
+	struct snd_compr_stream stream;
+};
+
+static int snd_compr_open(struct inode *inode, struct file *f)
+{
+	struct snd_compr *compr;
+	struct snd_compr_file *data;
+	struct snd_compr_runtime *runtime;
+	int ret, type;
+	int maj = imajor(inode);
+
+	if (f->f_flags & O_WRONLY)
+		type = SNDRV_DEVICE_TYPE_COMPR_PLAYBACK;
+	else if (f->f_flags & O_RDONLY)
+		type = SNDRV_DEVICE_TYPE_COMPR_CAPTURE;
+	else {
+		pr_err("invalid direction\n");
+		return -EINVAL;
+	}
+
+	if (maj == snd_major)
+		compr = snd_lookup_minor_data(iminor(inode), type);
+	else
+		return -ENXIO;
+
+	if (compr == NULL) {
+		pr_err("no device data!!!\n");
+		return -ENODEV;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	data->stream.ops = compr->ops;
+	data->stream.direction = type;
+	data->stream.private_data = compr->private_data;
+	data->stream.device = compr;
+	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+	if (!runtime) {
+		kfree(data);
+		return -ENOMEM;
+	}
+	runtime->state = SNDRV_PCM_STATE_OPEN;
+	init_waitqueue_head(&runtime->sleep);
+	data->stream.runtime = runtime;
+	f->private_data = (void *)data;
+	mutex_lock(&compr->lock);
+	ret = compr->ops->open(&data->stream);
+	mutex_unlock(&compr->lock);
+	if (ret) {
+		kfree(runtime);
+		kfree(data);
+	}
+	return ret;
+}
+
+static int snd_compr_free(struct inode *inode, struct file *f)
+{
+	struct snd_compr_file *data = f->private_data;
+	data->stream.ops->free(&data->stream);
+	kfree(data->stream.runtime->buffer);
+	kfree(data->stream.runtime);
+	kfree(data);
+	return 0;
+}
+
+static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
+		struct snd_compr_tstamp *tstamp)
+{
+	if (!stream->ops->pointer)
+		return;
+	stream->ops->pointer(stream, tstamp);
+	pr_debug("dsp consumed till %d total %d bytes\n",
+		tstamp->copied_bytes, tstamp->copied_total);
+	stream->runtime->hw_pointer = tstamp->copied_bytes;
+	stream->runtime->bytes_copied = tstamp->copied_total;
+}
+
+static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
+		struct snd_compr_avail *avail)
+{
+	long avail_calc; /*this needs to be signed variable */
+
+	snd_compr_update_tstamp(stream, &avail->tstamp);
+
+	if (stream->runtime->bytes_written == 0 &&
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+		pr_debug("detected init and someone forgot to do a write\n");
+		return stream->runtime->buffer_size;
+	}
+	pr_debug("app wrote %d, DSP consumed %d\n",
+		stream->runtime->bytes_written, stream->runtime->bytes_copied);
+	if (stream->runtime->bytes_written == stream->runtime->bytes_copied) {
+		pr_debug("both pointers are same, returning full avail\n");
+		return stream->runtime->buffer_size;
+	}
+
+	avail_calc = stream->runtime->buffer_size -
+		(stream->runtime->app_pointer - stream->runtime->hw_pointer);
+	pr_debug("calc avail as %ld, app_ptr %d, hw+ptr %d\n", avail_calc,
+		stream->runtime->app_pointer, stream->runtime->hw_pointer);
+	if (avail_calc >= stream->runtime->buffer_size)
+		avail_calc -= stream->runtime->buffer_size;
+	pr_debug("ret avail as %ld\n", avail_calc);
+	avail->avail = avail_calc;
+	return avail_calc;
+}
+
+static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
+{
+	struct snd_compr_avail avail;
+
+	return snd_compr_calc_avail(stream, &avail);
+}
+
+static int
+snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_avail ioctl_avail;
+	size_t avail;
+
+	avail = snd_compr_calc_avail(stream, &ioctl_avail);
+	ioctl_avail.avail = avail;
+
+	if (copy_to_user((unsigned long __user *)arg,
+				&ioctl_avail, sizeof(ioctl_avail)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_compr_write_data(struct snd_compr_stream *stream,
+	       const char __user *buf, size_t count)
+{
+	void *dstn;
+	size_t copy;
+	struct snd_compr_runtime *runtime = stream->runtime;
+
+	dstn = runtime->buffer + runtime->app_pointer;
+	pr_debug("copying %d at %d\n", count, runtime->app_pointer);
+	if (count < runtime->buffer_size - runtime->app_pointer) {
+		if (copy_from_user(dstn, buf, count))
+			return -EFAULT;
+		runtime->app_pointer += count;
+	} else {
+		copy = runtime->buffer_size - runtime->app_pointer;
+		if (copy_from_user(dstn, buf, copy))
+			return -EFAULT;
+		if (copy_from_user(runtime->buffer, buf + copy, count - copy))
+			return -EFAULT;
+		runtime->app_pointer = count - copy;
+	}
+	/* if DSP cares, let it know data has been written */
+	if (stream->ops->ack)
+		stream->ops->ack(stream, count);
+	return count;
+}
+
+static ssize_t snd_compr_write(struct file *f, const char __user *buf,
+		size_t count, loff_t *offset)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	mutex_lock(&stream->device->lock);
+	/* write is allowed when stream is running or has been steup */
+	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
+			stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		mutex_unlock(&stream->device->lock);
+		return -EPERM;
+	}
+
+	avail = snd_compr_get_avail(stream);
+	pr_debug("avail returned %d\n", avail);
+	/* calculate how much we can write to buffer */
+	if (avail > count)
+		avail = count;
+
+	if (stream->ops->copy)
+		retval = stream->ops->copy(stream, buf, avail);
+	else
+		retval = snd_compr_write_data(stream, buf, avail);
+	if (retval > 0)
+		stream->runtime->bytes_written += retval;
+
+	/* while initiating the stream, write should be called before START
+	 * call, so in setup move state */
+	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+		pr_debug("stream prepared, Houston we are good to go\n");
+	}
+
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+
+static ssize_t snd_compr_read(struct file *f, char __user *buf,
+		size_t count, loff_t *offset)
+{
+	return -ENXIO;
+}
+
+static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
+{
+	return -ENXIO;
+}
+
+static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval = 0;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+
+	mutex_lock(&stream->device->lock);
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		retval = -ENXIO;
+		goto out;
+	}
+	poll_wait(f, &stream->runtime->sleep, wait);
+
+	avail = snd_compr_get_avail(stream);
+	pr_debug("avail is %d\n", avail);
+	/* check if we have at least one fragment to fill */
+	switch (stream->runtime->state) {
+	case SNDRV_PCM_STATE_RUNNING:
+	case SNDRV_PCM_STATE_PREPARED:
+	case SNDRV_PCM_STATE_PAUSED:
+		if (avail >= stream->runtime->fragment_size) {
+			if (stream->direction == SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
+				retval = POLLOUT | POLLWRNORM;
+			else
+				retval = POLLIN | POLLRDNORM;
+			break;
+		}
+		/* Fall through */
+	case SNDRV_PCM_STATE_DRAINING:
+		break;
+	default:
+		if (stream->direction == SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
+			retval = POLLOUT | POLLWRNORM | POLLERR;
+		else
+			retval = POLLIN | POLLRDNORM | POLLERR;
+		break;
+	}
+out:
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+static int
+snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_caps caps;
+
+	if (!stream->ops->get_caps)
+		return -ENXIO;
+
+	retval = stream->ops->get_caps(stream, &caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
+		retval = -EFAULT;
+out:
+	return retval;
+}
+
+static int
+snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_codec_caps *caps;
+
+	if (!stream->ops->get_codec_caps)
+		return -ENXIO;
+
+	caps = kmalloc(sizeof(*caps), GFP_KERNEL);
+	if (!caps)
+		return -ENOMEM;
+
+	retval = stream->ops->get_codec_caps(stream, caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
+		retval = -EFAULT;
+
+out:
+	kfree(caps);
+	return retval;
+}
+
+/* revisit this with snd_pcm_preallocate_xxx */
+static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+		struct snd_compr_params *params)
+{
+	unsigned int buffer_size;
+	void *buffer;
+
+	buffer_size = params->buffer.fragment_size * params->buffer.fragments;
+	if (stream->ops->copy) {
+		buffer = NULL;
+		/* if copy is defined the driver will be required to copy
+		 * the data from core
+		 */
+	} else {
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+	}
+	stream->runtime->fragment_size = params->buffer.fragment_size;
+	stream->runtime->fragments = params->buffer.fragments;
+	stream->runtime->buffer = buffer;
+	stream->runtime->buffer_size = buffer_size;
+	return 0;
+}
+
+static int
+snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_params *params;
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+		/*
+		 * we should allow parameter change only when stream has been
+		 * opened not in other cases
+		 */
+		params = kmalloc(sizeof(*params), GFP_KERNEL);
+		if (!params)
+			return -ENOMEM;
+		if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
+			return -EFAULT;
+		retval = snd_compr_allocate_buffer(stream, params);
+		if (retval) {
+			kfree(params);
+			return -ENOMEM;
+		}
+		retval = stream->ops->set_params(stream, params);
+		if (retval)
+			goto out;
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+	} else
+		return -EPERM;
+out:
+	kfree(params);
+	return retval;
+}
+
+static int
+snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_codec *params;
+	int retval;
+
+	if (!stream->ops->get_params)
+		return -ENXIO;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+	retval = stream->ops->get_params(stream, params);
+	if (retval)
+		goto out;
+	if (copy_to_user((char __user *)arg, params, sizeof(*params)))
+		retval = -EFAULT;
+
+out:
+	kfree(params);
+	return retval;
+}
+
+static inline int
+snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_tstamp tstamp;
+
+	snd_compr_update_tstamp(stream, &tstamp);
+	return copy_to_user((struct snd_compr_tstamp __user *)arg,
+		&tstamp, sizeof(tstamp)) ? -EFAULT : 0;
+}
+
+static int snd_compr_pause(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_resume(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_start(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_stop(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_drain(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	int retval = -ENOTTY;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	BUG_ON(!stream);
+	mutex_lock(&stream->device->lock);
+	switch (_IOC_NR(cmd)) {
+	case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
+		put_user(SNDRV_COMPRESS_VERSION,
+				(int __user *)arg) ? -EFAULT : 0;
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+		retval = snd_compr_get_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+		retval = snd_compr_get_codec_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+		retval = snd_compr_set_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
+		retval = snd_compr_get_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
+		retval = snd_compr_tstamp(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
+		retval = snd_compr_ioctl_avail(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
+		retval = snd_compr_pause(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_RESUME):
+		retval = snd_compr_resume(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_START):
+		retval = snd_compr_start(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_STOP):
+		retval = snd_compr_stop(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+		retval = snd_compr_drain(stream);
+		break;
+	}
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+static const struct file_operations snd_compr_file_ops = {
+		.owner =	THIS_MODULE,
+		.open =		snd_compr_open,
+		.release =	snd_compr_free,
+		.write =	snd_compr_write,
+		.read =		snd_compr_read,
+		.unlocked_ioctl = snd_compr_ioctl,
+		.mmap =		snd_compr_mmap,
+		.poll =		snd_compr_poll,
+};
+
+static int snd_compress_dev_register(struct snd_device *device)
+{
+	int ret = -EINVAL;
+	char str[16];
+	struct snd_compr *compr;
+
+	if (snd_BUG_ON(!device || !device->device_data))
+		return -ENXIO;
+	compr = device->device_data;
+
+	sprintf(str, "comprC%iD%i", compr->card->number, compr->device);
+	pr_debug("reg %s for device %s, direction %d\n", str, compr->name,
+			compr->direction);
+	/* register compressed device */
+	ret = snd_register_device(compr->direction, compr->card, compr->device,
+			  &snd_compr_file_ops, compr, str);
+	if (ret < 0) {
+		pr_err("snd_register_device failed\n %d", ret);
+		return ret;
+	}
+	return ret;
+
+}
+
+static int snd_compress_dev_disconnect(struct snd_device *device)
+{
+	struct snd_compr *compr;
+
+	compr = device->device_data;
+	snd_unregister_device(compr->direction, compr->card, compr->device);
+	return 0;
+}
+
+int snd_compress_new(struct snd_card *card, int device,
+			int type, struct snd_compr *compr)
+{
+	static struct snd_device_ops ops = {
+		.dev_free = NULL,
+		.dev_register = snd_compress_dev_register,
+		.dev_disconnect = snd_compress_dev_disconnect,
+	};
+
+	compr->card = card;
+	compr->device = device;
+	compr->direction = type;
+	return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
+}
+EXPORT_SYMBOL_GPL(snd_compress_new);
+
+static int snd_compress_add_device(struct snd_compr *device)
+{
+	int ret;
+
+	if (!device->card)
+		return -EINVAL;
+
+	/* register the card */
+	ret = snd_card_register(device->card);
+	if (ret)
+		goto out;
+	return 0;
+
+out:
+	pr_err("failed with %d\n", ret);
+	return ret;
+
+}
+
+static int snd_compress_remove_device(struct snd_compr *device)
+{
+	return snd_card_free(device->card);
+}
+
+/**
+ * snd_compress_register - register compressed device
+ *
+ * @device: compressed device to register
+ */
+int snd_compress_register(struct snd_compr *device)
+{
+	int retval;
+
+	if (device->name == NULL || device->dev == NULL || device->ops == NULL)
+		return -EINVAL;
+
+	pr_debug("Registering compressed device %s\n", device->name);
+	BUG_ON(!device->ops->open);
+	BUG_ON(!device->ops->free);
+	BUG_ON(!device->ops->set_params);
+	BUG_ON(!device->ops->trigger);
+
+	mutex_init(&device->lock);
+
+	/* register a compressed card */
+	mutex_lock(&device_mutex);
+	retval = snd_compress_add_device(device);
+	mutex_unlock(&device_mutex);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(snd_compress_register);
+
+int snd_compress_deregister(struct snd_compr *device)
+{
+	pr_debug("Removing compressed device %s\n", device->name);
+	mutex_lock(&device_mutex);
+	snd_compress_remove_device(device);
+	mutex_unlock(&device_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_compress_deregister);
+
+static int __init snd_compress_init(void)
+{
+	return 0;
+}
+
+static void __exit snd_compress_exit(void)
+{
+}
+
+module_init(snd_compress_init);
+module_exit(snd_compress_exit);
+
+MODULE_DESCRIPTION("ALSA Compressed offload framework");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v3 6/6] core: add makefile and kconfig file for compress
  2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
                     ` (5 preceding siblings ...)
  2011-12-05  7:39   ` [PATCH v3 5/6] core: add support for compress_offload Vinod Koul
@ 2011-12-05  7:39   ` Vinod Koul
  6 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-05  7:39 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/core/Kconfig  |    8 ++++++++
 sound/core/Makefile |    4 ++++
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 475455c..5bfce50 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -155,6 +155,14 @@ config SND_DYNAMIC_MINORS
 
 	  If you are unsure about this, say N here.
 
+config SND_COMPRESS_OFFLOAD
+	tristate "ALSA Compressed audio offload support"
+	default n
+	help
+	  If you want support for offloading compressed audio and have such
+	  a hardware, then you should say Y here and also to the DSP driver
+	  of your platform.
+
 config SND_SUPPORT_OLD_API
 	bool "Support old ALSA API"
 	default y
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 350a08d..67c8e93 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -21,6 +21,8 @@ snd-hrtimer-objs  := hrtimer.o
 snd-rtctimer-objs := rtctimer.o
 snd-hwdep-objs    := hwdep.o
 
+snd-compress-objs := compress_offload.o
+
 obj-$(CONFIG_SND) 		+= snd.o
 obj-$(CONFIG_SND_HWDEP)		+= snd-hwdep.o
 obj-$(CONFIG_SND_TIMER)		+= snd-timer.o
@@ -31,3 +33,5 @@ obj-$(CONFIG_SND_RAWMIDI)	+= snd-rawmidi.o
 
 obj-$(CONFIG_SND_OSSEMUL)	+= oss/
 obj-$(CONFIG_SND_SEQUENCER)	+= seq/
+
+obj-$(CONFIG_SND_COMPRESS_OFFLOAD)	+= snd-compress.o
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* Re: [PATCH 4/6] compress: add API header and driver header files
  2011-12-04  7:41       ` Nallasellan, Singaravelan
@ 2011-12-05 14:14         ` Pierre-Louis Bossart
       [not found]         ` <000001ccb358$2b9e4b70$82dae250$@bossart@linux.intel.com>
  1 sibling, 0 replies; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-12-05 14:14 UTC (permalink / raw)
  To: Nallasellan, Singaravelan, 'Vinod Koul', alsa-devel
  Cc: tiwai, broonie, lrg

> > > Can we add number of compress streams supported in DSP?
> >
> > You are confusing number of formats supported with number of streams
> supported.
> > The latter is exposed through the actual devices supported.
> 
> No, DSP may be able to support only so many simultaneous streams at any
> point of time.
> Yet, DSP can support any number of formats. Though the device entry may
> be created for
> each compressed stream, how will the user space programs get the number
> of compressed streams supported?

The answer has already been provided. I agree with Mark there's no reason
why this API would need to provide resource management capabilities, it'd
need to be handled with a separate interface addressing PCM and effects as
well. In the mean time user-space can put product-specific restrictions on
concurrent decoding.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 4/6] compress: add API header and driver header files
       [not found]         ` <000001ccb358$2b9e4b70$82dae250$@bossart@linux.intel.com>
@ 2011-12-05 14:19           ` Mark Brown
  2011-12-06  2:55             ` Nallasellan, Singaravelan
  0 siblings, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-12-05 14:19 UTC (permalink / raw)
  To: Pierre-Louis Bossart
  Cc: tiwai, 'Vinod Koul', lrg, alsa-devel, Nallasellan, Singaravelan

On Mon, Dec 05, 2011 at 08:14:13AM -0600, Pierre-Louis Bossart wrote:

> The answer has already been provided. I agree with Mark there's no reason
> why this API would need to provide resource management capabilities, it'd
> need to be handled with a separate interface addressing PCM and effects as
> well. In the mean time user-space can put product-specific restrictions on
> concurrent decoding.

Or implement graceful fallback to the CPU if it can't set up an
offloaded stream.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-12-04  8:14       ` Nallasellan, Singaravelan
@ 2011-12-05 15:19         ` Pierre-Louis Bossart
       [not found]         ` <001501ccb361$3af49990$b0ddccb0$@bossart@linux.intel.com>
  1 sibling, 0 replies; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-12-05 15:19 UTC (permalink / raw)
  To: Nallasellan, Singaravelan, 'Vinod Koul'
  Cc: tiwai, alsa-devel, broonie, lrg

> > > > +	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
> > > > +		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
> > > Can we implement kind of start threshold similar to PCM path here
> to
> > > initiate the playback?
> > You already know how much is copied into buffer
> You expect the user space to explicitly invoke START. Is it right?
> If threshold is implemented, the user space does not require to track
> the
> bytes_written/read.

The notion of a START threshold isn't self-explanatory for compressed data. The decoder may or may not have enough data available for specific values of the threshold, and the behavior would be decoder/implementation specific.
Besides, this was never implemented in the proprietary Intel API we've been using for 2+ years and no one complained...
-Pierre

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 4/6] compress: add API header and driver header files
  2011-12-05 14:19           ` Mark Brown
@ 2011-12-06  2:55             ` Nallasellan, Singaravelan
  0 siblings, 0 replies; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-06  2:55 UTC (permalink / raw)
  To: Mark Brown, Pierre-Louis Bossart
  Cc: tiwai, 'Vinod Koul', alsa-devel, lrg

> > The answer has already been provided. I agree with Mark there's no
> > reason why this API would need to provide resource management
> > capabilities, it'd need to be handled with a separate interface
> > addressing PCM and effects as well. In the mean time user-space can
> > put product-specific restrictions on concurrent decoding.
> 
> Or implement graceful fallback to the CPU if it can't set up an offloaded stream.

Yes, that is the plan.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
       [not found]         ` <001501ccb361$3af49990$b0ddccb0$@bossart@linux.intel.com>
@ 2011-12-06  3:00           ` Nallasellan, Singaravelan
  2011-12-06  6:03             ` Vinod Koul
                               ` (2 more replies)
  0 siblings, 3 replies; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-06  3:00 UTC (permalink / raw)
  To: Pierre-Louis Bossart, 'Vinod Koul'
  Cc: tiwai, alsa-devel, broonie, lrg

> 
> The notion of a START threshold isn't self-explanatory for compressed data. The
> decoder may or may not have enough data available for specific values of the
> threshold, and the behavior would be decoder/implementation specific.
> Besides, this was never implemented in the proprietary Intel API we've been using for
> 2+ years and no one complained...

Even the thread which actually writes the data to ring buffer may not have the idea of frames
So the start threshold does not require to be on frame boundaries. It is just to avoid START 
when the buffer is written with the data. If the write gives more data than the ring buffer, 
write will not unblock and the user space application may not be able to call START. 
This will be an issue if you go for non-blocking implementation. Otherwise, START should
be called in another thread than the thread which writes the data.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-12-06  3:00           ` Nallasellan, Singaravelan
@ 2011-12-06  6:03             ` Vinod Koul
  2011-12-06  8:07               ` Nallasellan, Singaravelan
  2011-12-06 20:15             ` Pierre-Louis Bossart
       [not found]             ` <4ede780f.890bb50a.54a3.ffffcc4dSMTPIN_ADDED@mx.google.com>
  2 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-06  6:03 UTC (permalink / raw)
  To: Nallasellan, Singaravelan
  Cc: tiwai, alsa-devel, broonie, Pierre-Louis Bossart, lrg

On Tue, 2011-12-06 at 08:30 +0530, Nallasellan, Singaravelan wrote:
> > 
> > The notion of a START threshold isn't self-explanatory for compressed data. The
> > decoder may or may not have enough data available for specific values of the
> > threshold, and the behavior would be decoder/implementation specific.
> > Besides, this was never implemented in the proprietary Intel API we've been using for
> > 2+ years and no one complained...
> 
> Even the thread which actually writes the data to ring buffer may not have the idea of frames
> So the start threshold does not require to be on frame boundaries. It is just to avoid START 
> when the buffer is written with the data. If the write gives more data than the ring buffer, 
> write will not unblock and the user space application may not be able to call START. 
> This will be an issue if you go for non-blocking implementation. Otherwise, START should
> be called in another thread than the thread which writes the data.
You are confusing kernel API to user space stuff. Please stick to kernel
API discussion here. Nevertheless above has nothing to do with threshold
question!

At the peril of repeating myself again
- You have information of "exactly" how much data is there, so why do we
need a threshold.
- START threshold as explained above doesn't fly for compressed data

In PCM we would need to know what is the least amount of data which is
available in ring buffer for lower level driver to start. In compressed
data, you know to how much data is available for you to decode at any
point of time, use that information.

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 0/6] core: add compress data API to ALSA kernel
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
@ 2011-12-06  7:27     ` Jassi Brar
  2011-12-06  8:07       ` Vinod Koul
  2011-12-07 10:04     ` Vinod Koul
                       ` (14 subsequent siblings)
  15 siblings, 1 reply; 133+ messages in thread
From: Jassi Brar @ 2011-12-06  7:27 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg

Hi Vinod,

On Mon, Dec 5, 2011 at 1:09 PM, Vinod Koul <vinod.koul@linux.intel.com> wrote:
> As agreed during the ASoC workshop in May 2011, this set of patches are a
> proposal from Intel to add a new compressed data interface to ALSA. This
> proposal builds on the existing Intel solution and the experience gathered over
> two years with Meego and Android solutions. This proposal is no longer
> Intel-specific and was generalized with the addition of a basic core;
> codec-related definitions are based on the vendor-neutral OpenMAX AL standard.
>
Is the layer, below this API, available somewhere to see the whole picture ?

Thanks,
Jassi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-12-06  6:03             ` Vinod Koul
@ 2011-12-06  8:07               ` Nallasellan, Singaravelan
  0 siblings, 0 replies; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-06  8:07 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, Pierre-Louis Bossart, lrg

> >
> > Even the thread which actually writes the data to ring buffer may not
> > have the idea of frames So the start threshold does not require to be
> > on frame boundaries. It is just to avoid START when the buffer is
> > written with the data. If the write gives more data than the ring buffer, write will
> not unblock and the user space application may not be able to call START.
> > This will be an issue if you go for non-blocking implementation.
> > Otherwise, START should be called in another thread than the thread which writes
> the data.
> You are confusing kernel API to user space stuff. Please stick to kernel API discussion
> here. Nevertheless above has nothing to do with threshold question!
> 
I don’t think you understood my point. It is the kernel implementation which impacts the user space
Implementation.

> 
> --
> ~Vinod

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 0/6] core: add compress data API to ALSA kernel
  2011-12-06  7:27     ` Jassi Brar
@ 2011-12-06  8:07       ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-06  8:07 UTC (permalink / raw)
  To: Jassi Brar; +Cc: tiwai, alsa-devel, broonie, lrg

On Tue, 2011-12-06 at 12:57 +0530, Jassi Brar wrote:
> Hi Vinod,
Hello Jassi,
> 
> On Mon, Dec 5, 2011 at 1:09 PM, Vinod Koul <vinod.koul@linux.intel.com> wrote:
> > As agreed during the ASoC workshop in May 2011, this set of patches are a
> > proposal from Intel to add a new compressed data interface to ALSA. This
> > proposal builds on the existing Intel solution and the experience gathered over
> > two years with Meego and Android solutions. This proposal is no longer
> > Intel-specific and was generalized with the addition of a basic core;
> > codec-related definitions are based on the vendor-neutral OpenMAX AL standard.
> >
> Is the layer, below this API, available somewhere to see the whole picture ?
The parameters for codecs which need to be passed to DSP were derived
from the OpenMAX AL standard. So if you want to implement this standard
or some other parameter format, the assumption is that the neutrality of
API should ensure that it works for all.

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
  2011-12-06  3:00           ` Nallasellan, Singaravelan
  2011-12-06  6:03             ` Vinod Koul
@ 2011-12-06 20:15             ` Pierre-Louis Bossart
       [not found]             ` <4ede780f.890bb50a.54a3.ffffcc4dSMTPIN_ADDED@mx.google.com>
  2 siblings, 0 replies; 133+ messages in thread
From: Pierre-Louis Bossart @ 2011-12-06 20:15 UTC (permalink / raw)
  To: Nallasellan, Singaravelan, 'Vinod Koul'
  Cc: tiwai, alsa-devel, broonie, lrg

> Even the thread which actually writes the data to ring buffer may not
> have the idea of frames
> So the start threshold does not require to be on frame boundaries. It
> is just to avoid START when the buffer is written with the data. If 
> the write gives more data than the ring buffer, write will not unblock 
> and the user space application may not be able to call START.
> This will be an issue if you go for non-blocking implementation.
> Otherwise, START should be called in another thread than the thread 
> which writes the data.

I did not understand a single line of this comment. 
Why is this start threshold needed again and how would its value be defined
for compressed data?
-Pierre

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 0/6] core: add compress data API to ALSA kernel
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
  2011-12-06  7:27     ` Jassi Brar
@ 2011-12-07 10:04     ` Vinod Koul
  2011-12-07 16:15       ` Mark Brown
  2011-12-13  9:02     ` [PATCH v4 " Vinod Koul
                       ` (13 subsequent siblings)
  15 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-07 10:04 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, broonie, lrg

On Mon, 2011-12-05 at 13:09 +0530, Vinod Koul wrote:
> As agreed during the ASoC workshop in May 2011, this set of patches are a
> proposal from Intel to add a new compressed data interface to ALSA. This
> proposal builds on the existing Intel solution and the experience gathered over
> two years with Meego and Android solutions. This proposal is no longer
> Intel-specific and was generalized with the addition of a basic core;
> codec-related definitions are based on the vendor-neutral OpenMAX AL standard. 
> 
> These patches are also available in git tree:
> git://git.infradead.org/users/vkoul/snd-compress.git v3_patches
> 
Mark, Takashi

Any feedback on these? 
> Changes in v3:
>  Fixed the device registration for compressed devices as discussed
>  moved card creation to lower level drivers
>  Added new api for device node creation
>  changes fragment/frame callbacks to single inlined callback
> 
> Changes in v2:
>  Fixed the comments revived in v2
>  Fixed the comments recieved during LPC discussions
>  add support for alsa device registeration
>  fix the bugs found in testing
> 
> Omair Mohammed Abdullah (1):
>   core: add support for compressed devices
> 
> Pierre-Louis Bossart (1):
>   compress API documentation
> 
> Vinod Koul (4):
>   core: add compress parameter definations
>   core: add API header and driver header files
>   core: add support for compress_offload
>   core: add makefile and kconfig file for compress
> 
>  Documentation/sound/alsa/snd_compress_data.txt |  184 +++++++
>  include/sound/compress_driver.h                |  164 ++++++
>  include/sound/compress_offload.h               |  151 +++++
>  include/sound/core.h                           |    1 +
>  include/sound/minors.h                         |    7 +-
>  include/sound/snd_compress_params.h            |  395 +++++++++++++
>  sound/core/Kconfig                             |    8 +
>  sound/core/Makefile                            |    4 +
>  sound/core/compress_offload.c                  |  701 ++++++++++++++++++++++++
>  sound/core/sound.c                             |    6 +
>  10 files changed, 1620 insertions(+), 1 deletions(-)
>  create mode 100644 Documentation/sound/alsa/snd_compress_data.txt
>  create mode 100644 include/sound/compress_driver.h
>  create mode 100644 include/sound/compress_offload.h
>  create mode 100644 include/sound/snd_compress_params.h
>  create mode 100644 sound/core/compress_offload.c
> 


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 0/6] core: add compress data API to ALSA kernel
  2011-12-07 10:04     ` Vinod Koul
@ 2011-12-07 16:15       ` Mark Brown
  0 siblings, 0 replies; 133+ messages in thread
From: Mark Brown @ 2011-12-07 16:15 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg

On Wed, Dec 07, 2011 at 03:34:58PM +0530, Vinod Koul wrote:

> Mark, Takashi
> 
> Any feedback on these? 

We're both travelling at the minute.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH 5/6] compress: add the core file
       [not found]               ` <CAKg5Tpo6LgirbVVe9ZXNGN-xq7FTZvgAXNQ2HnXh=gwQHjn_Pw@mail.gmail.com>
@ 2011-12-07 16:53                 ` Nallasellan, Singaravelan
  0 siblings, 0 replies; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-07 16:53 UTC (permalink / raw)
  To: Vinod Koul, Pierre-Louis Bossart
  Cc: tiwai, alsa-devel, broonie, Liam Girdwood

 
> > Even the thread which actually writes the data to ring buffer may not
> > have the idea of frames So the start threshold does not require to be
> > on frame boundaries. It is just to avoid START when the buffer is
> > written with the data. If the write gives more data than the ring
> > buffer, write will not unblock and the user space application may not
> > be able to call START.
> > This will be an issue if you go for non-blocking implementation.
> > Otherwise, START should be called in another thread than the thread
> > which writes the data.
> 
> I did not understand a single line of this comment.
> Why is this start threshold needed again and how would its value be defined for
> compressed data?

I will try to explain it with more details. 

Consider the case of blocking "write" call:

If the user space app writes the buffer with the content of size greater than the 
ring buffer size, write call will block. How do you expect the user space to invoke START ioctl?
I assume the write call will block until it writes the complete content into the buffer. 

To avoid this behavior, the app has to query only the empty space and write only that much data.
Then it should call START. 

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 5/6] core: add support for compress_offload
  2011-12-05  7:39   ` [PATCH v3 5/6] core: add support for compress_offload Vinod Koul
@ 2011-12-13  6:09     ` Mark Brown
  2011-12-13  6:29       ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-12-13  6:09 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg, Pierre-Louis Bossart

On Mon, Dec 05, 2011 at 01:09:50PM +0530, Vinod Koul wrote:

> +#include <linux/file.h>
> +#include <linux/fs.h>
> +#include <linux/list.h>
> +#include <linux/mm.h>
> +#include <linux/mutex.h>
> +#include <linux/poll.h>
> +#include <linux/slab.h>
> +#include <linux/sched.h>
> +#include <linux/uio.h>
> +#include <linux/uaccess.h>

You need module.h in here for

> +MODULE_DESCRIPTION("ALSA Compressed offload framework");
> +MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
> +MODULE_LICENSE("GPL v2");

this stuff.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 4/6] core: add API header and driver header files
  2011-12-05  7:39   ` [PATCH v3 4/6] core: add API header and driver header files Vinod Koul
@ 2011-12-13  6:11     ` Mark Brown
  2011-12-13  6:31       ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-12-13  6:11 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, lrg, Pierre-Louis Bossart

On Mon, Dec 05, 2011 at 01:09:49PM +0530, Vinod Koul wrote:

> +static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> +{
> +	wake_up(&stream->runtime->sleep);
> +}

You need to include sched.h for this.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 5/6] core: add support for compress_offload
  2011-12-13  6:09     ` Mark Brown
@ 2011-12-13  6:29       ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  6:29 UTC (permalink / raw)
  To: Mark Brown; +Cc: tiwai, alsa-devel, lrg, Pierre-Louis Bossart

On Tue, 2011-12-13 at 14:09 +0800, Mark Brown wrote:
> On Mon, Dec 05, 2011 at 01:09:50PM +0530, Vinod Koul wrote:
> 
> > +#include <linux/file.h>
> > +#include <linux/fs.h>
> > +#include <linux/list.h>
> > +#include <linux/mm.h>
> > +#include <linux/mutex.h>
> > +#include <linux/poll.h>
> > +#include <linux/slab.h>
> > +#include <linux/sched.h>
> > +#include <linux/uio.h>
> > +#include <linux/uaccess.h>
> 
> You need module.h in here for
> 
> > +MODULE_DESCRIPTION("ALSA Compressed offload framework");
> > +MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
> > +MODULE_LICENSE("GPL v2");
> 
> this stuff.
Yes, the 3.2!
Lazy me, didn't rebase this tree to 3.2 :(
Fixed now....

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 4/6] core: add API header and driver header files
  2011-12-13  6:11     ` Mark Brown
@ 2011-12-13  6:31       ` Vinod Koul
  2011-12-13  7:03         ` Takashi Iwai
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  6:31 UTC (permalink / raw)
  To: Mark Brown; +Cc: tiwai, alsa-devel, lrg, Pierre-Louis Bossart

On Tue, 2011-12-13 at 14:11 +0800, Mark Brown wrote:
> On Mon, Dec 05, 2011 at 01:09:49PM +0530, Vinod Koul wrote:
> 
> > +static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> > +{
> > +	wake_up(&stream->runtime->sleep);
> > +}
> 
> You need to include sched.h for this.
Hmmm, I have a different POV for these.
I would like driver to include the sched.h here and this not be in
header file.

While at it, am not really religious about this, so open to counter
argument :)

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 4/6] core: add API header and driver header files
  2011-12-13  6:31       ` Vinod Koul
@ 2011-12-13  7:03         ` Takashi Iwai
  2011-12-13  7:50           ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-12-13  7:03 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, Mark Brown, lrg, Pierre-Louis Bossart

At Tue, 13 Dec 2011 12:01:30 +0530,
Vinod Koul wrote:
> 
> On Tue, 2011-12-13 at 14:11 +0800, Mark Brown wrote:
> > On Mon, Dec 05, 2011 at 01:09:49PM +0530, Vinod Koul wrote:
> > 
> > > +static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> > > +{
> > > +	wake_up(&stream->runtime->sleep);
> > > +}
> > 
> > You need to include sched.h for this.
> Hmmm, I have a different POV for these.
> I would like driver to include the sched.h here and this not be in
> header file.

In general, a header file should be self-contained as much as
possible.  Since you are calling it in an inline function, it'd be
more consistent to include sched.h in it.


Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 4/6] core: add API header and driver header files
  2011-12-13  7:03         ` Takashi Iwai
@ 2011-12-13  7:50           ` Vinod Koul
  2011-12-13  7:53             ` Mark Brown
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  7:50 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Mark Brown, lrg, Pierre-Louis Bossart

On Tue, 2011-12-13 at 08:03 +0100, Takashi Iwai wrote:
> At Tue, 13 Dec 2011 12:01:30 +0530,
> Vinod Koul wrote:
> > 
> > On Tue, 2011-12-13 at 14:11 +0800, Mark Brown wrote:
> > > On Mon, Dec 05, 2011 at 01:09:49PM +0530, Vinod Koul wrote:
> > > 
> > > > +static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
> > > > +{
> > > > +	wake_up(&stream->runtime->sleep);
> > > > +}
> > > 
> > > You need to include sched.h for this.
> > Hmmm, I have a different POV for these.
> > I would like driver to include the sched.h here and this not be in
> > header file.
> 
> In general, a header file should be self-contained as much as
> possible.  Since you are calling it in an inline function, it'd be
> more consistent to include sched.h in it.
Okay done.

Do you have more feedback for this patchset, or I can send v4 with these
fixes later today :)

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 4/6] core: add API header and driver header files
  2011-12-13  7:50           ` Vinod Koul
@ 2011-12-13  7:53             ` Mark Brown
  2011-12-13  9:03               ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Mark Brown @ 2011-12-13  7:53 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Takashi Iwai, alsa-devel, lrg, Pierre-Louis Bossart

On Tue, Dec 13, 2011 at 01:20:41PM +0530, Vinod Koul wrote:

> Do you have more feedback for this patchset, or I can send v4 with these
> fixes later today :)

Well, you can send the patches either way!  I don't have any more at
present but I've not really looked yet.

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [PATCH v4 0/6] core: add compress data API to ALSA kernel
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
  2011-12-06  7:27     ` Jassi Brar
  2011-12-07 10:04     ` Vinod Koul
@ 2011-12-13  9:02     ` Vinod Koul
  2011-12-13  9:02     ` [PATCH v4 1/6] compress API documentation Vinod Koul
                       ` (12 subsequent siblings)
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  9:02 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg

As agreed during the ASoC workshop in May 2011, this set of patches are a
proposal from Intel to add a new compressed data interface to ALSA. This
proposal builds on the existing Intel solution and the experience gathered over
two years with Meego and Android solutions. This proposal is no longer
Intel-specific and was generalized with the addition of a basic core;
codec-related definitions are based on the vendor-neutral OpenMAX AL standard. 

These patches are also available in git tree:
git://git.infradead.org/users/vkoul/snd-compress.git v4_patches

Changes in v4:
 Rebased on 3.2-rc4, fixed module.h compilation
 Added sched.h header in compress_driver.h
 Fixed few warnings while at it

Changes in v3:
 Fixed the device registration for compressed devices as discussed
 moved card creation to lower level drivers
 Added new api for device node creation
 changes fragment/frame callbacks to single inlined callback

Changes in v2:
 Fixed the comments recieved in v2
 Fixed the comments recieved during LPC discussions
 add support for alsa device registeration
 fix the bugs found in testing

Omair Mohammed Abdullah (1):
  core: add support for compressed devices

Pierre-Louis Bossart (1):
  compress API documentation

Vinod Koul (4):
  core: add compress parameter definations
  core: add API header and driver header files
  core: add support for compress_offload
  core: add makefile and kconfig file for compress

 Documentation/sound/alsa/snd_compress_data.txt |  184 ++++++
 include/sound/compress_driver.h                |  166 ++++++
 include/sound/compress_offload.h               |  151 +++++
 include/sound/core.h                           |    1 +
 include/sound/minors.h                         |    7 +-
 include/sound/snd_compress_params.h            |  395 +++++++++++++
 sound/core/Kconfig                             |    8 +
 sound/core/Makefile                            |    4 +
 sound/core/compress_offload.c                  |  705 ++++++++++++++++++++++++
 sound/core/sound.c                             |    6 +
 10 files changed, 1626 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/sound/alsa/snd_compress_data.txt
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h
 create mode 100644 include/sound/snd_compress_params.h
 create mode 100644 sound/core/compress_offload.c

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [PATCH v4 1/6] compress API documentation
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (2 preceding siblings ...)
  2011-12-13  9:02     ` [PATCH v4 " Vinod Koul
@ 2011-12-13  9:02     ` Vinod Koul
  2011-12-13  9:02     ` [PATCH v4 2/6] core: add support for compressed devices Vinod Koul
                       ` (11 subsequent siblings)
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  9:02 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

The patch adds the documentation file explaining the API

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
---
 Documentation/sound/alsa/snd_compress_data.txt |  184 ++++++++++++++++++++++++
 1 files changed, 184 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/sound/alsa/snd_compress_data.txt

diff --git a/Documentation/sound/alsa/snd_compress_data.txt b/Documentation/sound/alsa/snd_compress_data.txt
new file mode 100644
index 0000000..4b0d0fc
--- /dev/null
+++ b/Documentation/sound/alsa/snd_compress_data.txt
@@ -0,0 +1,184 @@
+		snd_compress_data.txt
+		=====================
+	Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+		Vinod Koul <vinod.koul@linux.intel.com>
+
+Overview
+
+Since its early days, the ALSA API was defined with PCM support or
+constant bitrates payloads such as IEC61937 in mind. Arguments and
+returned values in frames are the norm, making it a challenge to
+extend the existing API to compressed data streams.
+
+In recent years, audio digital signal processors (DSP) were integrated
+in system-on-chip designs, and DSPs are also integrated in audio
+codecs. Processing compressed data on such DSPs results in a dramatic
+reduction of power consumption compared to host-based
+processing. Support for such hardware has not been very good in Linux,
+mostly because of a lack of a generic API available in the mainline
+kernel.
+
+Rather than requiring a compability break with an API change of the
+ALSA PCM interface, a new 'Compressed Data' API is introduced to
+provide a control and data-streaming interface for audio DSPs.
+
+The design of this API was inspired by the 2-year experience with the
+Intel Moorestown SOC, with many corrections required to upstream the
+API in the mainline kernel instead of the staging tree and make it
+usable by others.
+
+Requirements
+
+The main requirements are:
+
+- separation between byte counts and time. Compressed formats may have
+  a header per file, per frame, or no header at all. The payload size
+  may vary from frame-to-frame. As a result, it is not possible to
+  estimate reliably the duration of audio buffers when handling
+  compressed data. Dedicated mechanisms are required to allow for
+  reliable audio-video synchronization, which requires precise
+  reporting of the number of samples rendered at any given time.
+
+- Handling of multiple formats. PCM data only requires a specification
+  of the sampling rate, number of channels and bits per sample. In
+  contrast, compressed data comes in a variety of formats. Audio DSPs
+  may also provide support for a limited number of audio encoders and
+  decoders embedded in firmware, or may support more choices through
+  dynamic download of libraries.
+
+- Focus on main formats. This API provides support for the most
+  popular formats used for audio and video capture and playback. It is
+  likely that as audio compression technology advances, new formats
+  will be added.
+
+- Handling of multiple configurations. Even for a given format like
+  AAC, some implementations may support AAC multichannel but HE-AAC
+  stereo. Likewise WMA10 level M3 may require too much memory and cpu
+  cycles. The new API needs to provide a generic way of listing these
+  formats.
+
+- Rendering/Grabbing only. This API does not provide any means of
+  hardware acceleration, where PCM samples are provided back to
+  user-space for additional processing. This API focuses instead on
+  streaming compressed data to a DSP, with the assumption that the
+  decoded samples are routed to a physical output or logical back-end.
+
+ - Complexity hiding. Existing user-space multimedia frameworks all
+  have existing enums/structures for each compressed format. This new
+  API assumes the existence of a platform-specific compatibility layer
+  to expose, translate and make use of the capabilities of the audio
+  DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
+  applications are not supposed to make use of this API.
+
+
+Design
+
+The new API shares a number of concepts with with the PCM API for flow
+control. Start, pause, resume, drain and stop commands have the same
+semantics no matter what the content is.
+
+The concept of memory ring buffer divided in a set of fragments is
+borrowed from the ALSA PCM API. However, only sizes in bytes can be
+specified.
+
+Seeks/trick modes are assumed to be handled by the host.
+
+The notion of rewinds/forwards is not supported. Data committed to the
+ring buffer cannot be invalidated, except when dropping all buffers.
+
+The Compressed Data API does not make any assumptions on how the data
+is transmitted to the audio DSP. DMA transfers from main memory to an
+embedded audio cluster or to a SPI interface for external DSPs are
+possible. As in the ALSA PCM case, a core set of routines is exposed;
+each driver implementer will have to write support for a set of
+mandatory routines and possibly make use of optional ones.
+
+The main additions are
+
+- get_caps
+This routine returns the list of audio formats supported. Querying the
+codecs on a capture stream will return encoders, decoders will be
+listed for playback streams.
+
+- get_codec_caps
+For each codec, this routine returns a list of capabilities. The
+intent is to make sure all the capabilities correspond to valid
+settings, and to minimize the risks of configuration failures. For
+example, for a complex codec such as AAC, the number of channels
+supported may depend on a specific profile. If the capabilities were
+exposed with a single descriptor, it may happen that a specific
+combination of profiles/channels/formats may not be
+supported. Likewise, embedded DSPs have limited memory and cpu cycles,
+it is likely that some implementations make the list of capabilities
+dynamic and dependent on existing workloads.
+
+- set_params
+This routine sets the configuration chosen for a specific codec. The
+most important field in the parameters is the codec type; in most
+cases decoders will ignore other fields, while encoders will strictly
+comply to the settings
+
+- get_params
+This routines returns the actual settings used by the DSP. Changes to
+the settings should remain the exception.
+
+- get_timestamp
+The timestamp becomes a multiple field structure. It lists the number
+of bytes transferred, the number of samples processed and the number
+of samples rendered/grabbed. All these values can be used to determine
+the avarage bitrate, figure out if the ring buffer needs to be
+refilled or the delay due to decoding/encoding/io on the DSP.
+
+Note that the list of codecs/profiles/modes was derived from the
+OpenMAX AL specification instead of reinventing the wheel.
+Modifications include:
+- Addition of FLAC and IEC formats
+- Merge of encoder/decoder capabilities
+- Profiles/modes listed as bitmasks to make descriptors more compact
+- Addition of set_params for decoders (missing in OpenMAX AL)
+- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
+- Addition of format information for WMA
+- Addition of encoding options when required (derived from OpenMAX IL)
+- Addition of rateControlSupported (missing in OpenMAX AL)
+
+Not supported:
+
+- Support for VoIP/circuit-switched calls is not the target of this
+  API. Support for dynamic bit-rate changes would require a tight
+  coupling between the DSP and the host stack, limiting power savings.
+
+- Packet-loss concealment is not supported. This would require an
+  additional interface to let the decoder synthesize data when frames
+  are lost during transmission. This may be added in the future.
+
+- Volume control/routing is not handled by this API. Devices exposing a
+  compressed data interface will be considered as regular ALSA devices;
+  volume changes and routing information will be provided with regular
+  ALSA kcontrols.
+
+- Embedded audio effects. Such effects should be enabled in the same
+  manner, no matter if the input was PCM or compressed.
+
+- multichannel IEC encoding. Unclear if this is required.
+
+- Encoding/decoding acceleration is not supported as mentioned
+  above. It is possible to route the output of a decoder to a capture
+  stream, or even implement transcoding capabilities. This routing
+  would be enabled with ALSA kcontrols.
+
+- Audio policy/resource management. This API does not provide any
+  hooks to query the utilization of the audio DSP, nor any premption
+  mechanisms.
+
+- No notion of underun/overrun. Since the bytes written are compressed
+  in nature and data written/read doesn't translate directly to
+  rendered output in time, this does not deal with underrun/overun and
+  maybe dealt in user-library
+
+Credits:
+- Mark Brown and Liam Girdwood for discussions on the need for this API
+- Harsha Priya for her work on intel_sst compressed API
+- Rakesh Ughreja for valuable feedback
+- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
+  demonstrating and quantifying the benefits of audio offload on a
+  real platform.
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v4 2/6] core: add support for compressed devices
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (3 preceding siblings ...)
  2011-12-13  9:02     ` [PATCH v4 1/6] compress API documentation Vinod Koul
@ 2011-12-13  9:02     ` Vinod Koul
  2011-12-22  7:34       ` Takashi Iwai
  2011-12-13  9:02     ` [PATCH v4 3/6] core: add compress parameter definations Vinod Koul
                       ` (10 subsequent siblings)
  15 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  9:02 UTC (permalink / raw)
  To: alsa-devel
  Cc: Vinod Koul, tiwai, broonie, Pierre-Louis Bossart,
	Omair Mohammed Abdullah, lrg

From: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>

Use the two minor numbers 2 and 3 for audio compressed offload devices.
Also add support for these devices in core

Signed-off-by: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
---
 include/sound/core.h   |    1 +
 include/sound/minors.h |    7 ++++++-
 sound/core/sound.c     |    6 ++++++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/include/sound/core.h b/include/sound/core.h
index 3be5ab7..5ab255f 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -62,6 +62,7 @@ typedef int __bitwise snd_device_type_t;
 #define	SNDRV_DEV_BUS		((__force snd_device_type_t) 0x1007)
 #define	SNDRV_DEV_CODEC		((__force snd_device_type_t) 0x1008)
 #define	SNDRV_DEV_JACK          ((__force snd_device_type_t) 0x1009)
+#define	SNDRV_DEV_COMPRESS	((__force snd_device_type_t) 0x100A)
 #define	SNDRV_DEV_LOWLEVEL	((__force snd_device_type_t) 0x2000)
 
 typedef int __bitwise snd_device_state_t;
diff --git a/include/sound/minors.h b/include/sound/minors.h
index 8f76420..faaeb64 100644
--- a/include/sound/minors.h
+++ b/include/sound/minors.h
@@ -35,7 +35,8 @@
 #define SNDRV_MINOR_TIMER		33	/* SNDRV_MINOR_GLOBAL + 1 * 32 */
 
 #ifndef CONFIG_SND_DYNAMIC_MINORS
-						/* 2 - 3 (reserved) */
+#define SNDRV_MINOR_COMPR_PLAYBACK	2
+#define SNDRV_MINOR_COMPR_CAPTURE	3
 #define SNDRV_MINOR_HWDEP		4	/* 4 - 7 */
 #define SNDRV_MINOR_RAWMIDI		8	/* 8 - 15 */
 #define SNDRV_MINOR_PCM_PLAYBACK	16	/* 16 - 23 */
@@ -49,6 +50,8 @@
 #define SNDRV_DEVICE_TYPE_PCM_CAPTURE	SNDRV_MINOR_PCM_CAPTURE
 #define SNDRV_DEVICE_TYPE_SEQUENCER	SNDRV_MINOR_SEQUENCER
 #define SNDRV_DEVICE_TYPE_TIMER		SNDRV_MINOR_TIMER
+#define SNDRV_DEVICE_TYPE_COMPR_PLAYBACK SNDRV_MINOR_COMPR_PLAYBACK
+#define SNDRV_DEVICE_TYPE_COMPR_CAPTURE	SNDRV_MINOR_COMPR_CAPTURE
 
 #else /* CONFIG_SND_DYNAMIC_MINORS */
 
@@ -60,6 +63,8 @@ enum {
 	SNDRV_DEVICE_TYPE_RAWMIDI,
 	SNDRV_DEVICE_TYPE_PCM_PLAYBACK,
 	SNDRV_DEVICE_TYPE_PCM_CAPTURE,
+	SNDRV_DEVICE_TYPE_COMPR_PLAYBACK,
+	SNDRV_DEVICE_TYPE_COMPR_CAPTURE,
 };
 
 #endif /* CONFIG_SND_DYNAMIC_MINORS */
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 828af35..2b680dd 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -233,6 +233,12 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
 			return -EINVAL;
 		minor = SNDRV_MINOR(card->number, type + dev);
 		break;
+	case SNDRV_DEVICE_TYPE_COMPR_PLAYBACK:
+	case SNDRV_DEVICE_TYPE_COMPR_CAPTURE:
+		if (snd_BUG_ON(!card))
+			return -EINVAL;
+		minor = SNDRV_MINOR(card->number, type);
+		break;
 	default:
 		return -EINVAL;
 	}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v4 3/6] core: add compress parameter definations
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (4 preceding siblings ...)
  2011-12-13  9:02     ` [PATCH v4 2/6] core: add support for compressed devices Vinod Koul
@ 2011-12-13  9:02     ` Vinod Koul
  2011-12-22  7:35       ` Takashi Iwai
  2011-12-13  9:02     ` [PATCH v4 4/6] core: add API header and driver header files Vinod Koul
                       ` (9 subsequent siblings)
  15 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  9:02 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

The patch adds the various definations used to define the encoder
and decoder parameters

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
---
 include/sound/snd_compress_params.h |  395 +++++++++++++++++++++++++++++++++++
 1 files changed, 395 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/snd_compress_params.h

diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
new file mode 100644
index 0000000..79b681d
--- /dev/null
+++ b/include/sound/snd_compress_params.h
@@ -0,0 +1,395 @@
+/*
+ *  snd_compress_params.h - codec types and parameters for compressed data
+ *  streaming interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *              Vinod Koul <vinod.koul@linux.intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The definitions in this file are derived from the OpenMAX AL version 1.1
+ * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
+ *
+ * Copyright (c) 2007-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and/or associated documentation files (the
+ * "Materials "), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+#ifndef __SND_COMPRESS_PARAMS_H
+#define __SND_COMPRESS_PARAMS_H
+
+/* AUDIO CODECS SUPPORTED */
+#define MAX_NUM_CODECS 32
+#define MAX_NUM_CODEC_DESCRIPTORS 32
+#define MAX_NUM_BITRATES 32
+
+/* Codecs are listed linearly to allow for extensibility */
+#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
+#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
+#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
+#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
+#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
+#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
+#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
+#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
+#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
+#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
+#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
+#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
+#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
+
+/*
+ * Profile and modes are listed with bit masks. This allows for a
+ * more compact representation of fields that will not evolve
+ * (in contrast to the list of codecs)
+ */
+
+#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
+
+/* MP3 modes are only useful for encoders */
+#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
+#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
+#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
+#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
+
+/* AMR modes are only useful for encoders */
+#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
+
+#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
+#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
+
+#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
+
+/* AMRWB modes are only useful for encoders */
+#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
+
+/* AAC modes are required for encoders and decoders */
+#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
+#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
+#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
+#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
+#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
+#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
+#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
+
+/* AAC formats are required for encoders and decoders */
+#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
+#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
+
+#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
+#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
+#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
+#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
+
+#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
+#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
+#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
+#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
+#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
+#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
+#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
+
+#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
+/*
+ * Some implementations strip the ASF header and only send ASF packets
+ * to the DSP
+ */
+#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
+
+#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
+#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
+
+/*
+ * Define quality levels for FLAC encoders, from LEVEL0 (fast)
+ * to LEVEL8 (best)
+ */
+#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
+#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
+#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
+#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
+#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
+#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
+#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
+
+#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
+
+/* IEC61937 payloads without CUVP and preambles */
+#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
+/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
+#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
+
+/*
+ * IEC modes are mandatory for decoders. Format autodetection
+ * will only happen on the DSP side with mode 0. The PCM mode should
+ * not be used, the PCM codec should be used instead.
+ */
+#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
+#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
+#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
+#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
+#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
+#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
+#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
+#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
+#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
+#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
+#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
+#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
+#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
+#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
+#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
+#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
+#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
+#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
+#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
+
+#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
+#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
+
+/* <FIXME: multichannel encoders aren't supported for now. Would need
+   an additional definition of channel arrangement> */
+
+/* VBR/CBR definitions */
+#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
+#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
+
+/* Encoder options */
+
+struct snd_enc_wma {
+	__u32 super_block_align; /* WMA Type-specific data */
+};
+
+
+/**
+ * struct snd_enc_vorbis
+ * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
+ * In the default mode of operation, the quality level is 3.
+ * Normal quality range is 0 - 10.
+ * @managed: Boolean. Set  bitrate  management  mode. This turns off the
+ * normal VBR encoding, but allows hard or soft bitrate constraints to be
+ * enforced by the encoder. This mode can be slower, and may also be
+ * lower quality. It is primarily useful for streaming.
+ * @max_bit_rate: Enabled only if managed is TRUE
+ * @min_bit_rate: Enabled only if managed is TRUE
+ * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
+ * non-stereo streams). Useful for lower-bitrate encoding.
+ *
+ * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
+ * properties
+ *
+ * For best quality users should specify VBR mode and set quality levels.
+ */
+
+struct snd_enc_vorbis {
+	int quality;
+	__u32 managed;
+	__u32 max_bit_rate;
+	__u32 min_bit_rate;
+	__u32 downmix;
+};
+
+
+/**
+ * struct snd_enc_real
+ * @quant_bits: number of coupling quantization bits in the stream
+ * @start_region: coupling start region in the stream
+ * @num_regions: number of regions value
+ *
+ * These options were extracted from the OpenMAX IL spec
+ */
+
+struct snd_enc_real {
+	__u32 quant_bits;
+	__u32 start_region;
+	__u32 num_regions;
+};
+
+/**
+ * struct snd_enc_flac
+ * @num: serial number, valid only for OGG formats
+ *	needs to be set by application
+ * @gain: Add replay gain tags
+ *
+ * These options were extracted from the FLAC online documentation
+ * at http://flac.sourceforge.net/documentation_tools_flac.html
+ *
+ * To make the API simpler, it is assumed that the user will select quality
+ * profiles. Additional options that affect encoding quality and speed can
+ * be added at a later stage if needed.
+ *
+ * By default the Subset format is used by encoders.
+ *
+ * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
+ * not supported in this API.
+ */
+
+struct snd_enc_flac {
+	__u32 num;
+	__u32 gain;
+};
+
+struct snd_enc_generic {
+	__u32 bw;	/* encoder bandwidth */
+	int reserved[15];
+};
+
+union snd_codec_options {
+	struct snd_enc_wma wma;
+	struct snd_enc_vorbis vorbis;
+	struct snd_enc_real real;
+	struct snd_enc_flac flac;
+	struct snd_enc_generic generic;
+};
+
+/** struct snd_codec_desc - description of codec capabilities
+ * @max_ch: Maximum number of audio channels
+ * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
+ * @bit_rate: Indexed array containing supported bit rates
+ * @num_bitrates: Number of valid values in bit_rate array
+ * @rate_control: value is specified by SND_RATECONTROLMODE defines.
+ * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
+ * @modes: Supported modes. See SND_AUDIOMODE defines
+ * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
+ * @reserved: reserved for future use
+ *
+ * This structure provides a scalar value for profiles, modes and stream
+ * format fields.
+ * If an implementation supports multiple combinations, they will be listed as
+ * codecs with different descriptors, for example there would be 2 descriptors
+ * for AAC-RAW and AAC-ADTS.
+ * This entails some redundancy but makes it easier to avoid invalid
+ * configurations.
+ *
+ */
+
+struct snd_codec_desc {
+	__u32 max_ch;
+	__u32 sample_rates;
+	__u32 bit_rate[MAX_NUM_BITRATES];
+	__u32 num_bitrates;
+	__u32 rate_control;
+	__u32 profiles;
+	__u32 modes;
+	__u32 formats;
+	__u32 reserved[16];
+};
+
+/** struct snd_codec
+ * @id: Identifies the supported audio encoder/decoder.
+ *		See SND_AUDIOCODEC macros.
+ * @ch_in: Number of input audio channels
+ * @ch_out: Number of output channels. In case of contradiction between
+ *		this field and the channelMode field, the channelMode field
+ *		overrides.
+ * @sample_rate: Audio sample rate of input data
+ * @bit_rate: Bitrate of encoded data. May be ignored by decoders
+ * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
+ *               Encoders may rely on profiles for quality levels.
+ *		 May be ignored by decoders.
+ * @profile: Mandatory for encoders, can be mandatory for specific
+ *		decoders as well. See SND_AUDIOPROFILE defines.
+ * @level: Supported level (Only used by WMA at the moment)
+ * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
+ * @format: Format of encoded bistream. Mandatory when defined.
+ *		See SND_AUDIOSTREAMFORMAT defines.
+ * @align: Block alignment in bytes of an audio sample.
+ *		Only required for PCM or IEC formats.
+ * @options: encoder-specific settings
+ * @reserved: reserved for future use
+ */
+
+struct snd_codec {
+	__u32 id;
+	__u32 ch_in;
+	__u32 ch_out;
+	__u32 sample_rate;
+	__u32 bit_rate;
+	__u32 rate_control;
+	__u32 profile;
+	__u32 level;
+	__u32 ch_mode;
+	__u32 format;
+	__u32 align;
+	union snd_codec_options options;
+	__u32 reserved[3];
+};
+
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v4 4/6] core: add API header and driver header files
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (5 preceding siblings ...)
  2011-12-13  9:02     ` [PATCH v4 3/6] core: add compress parameter definations Vinod Koul
@ 2011-12-13  9:02     ` Vinod Koul
  2011-12-13  9:02     ` [PATCH v4 5/6] core: add support for compress_offload Vinod Koul
                       ` (8 subsequent siblings)
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  9:02 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

This patch adds the header files for ioctl definations and header file for
driver APIs for lower level device drivers to use

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
---
 include/sound/compress_driver.h  |  166 ++++++++++++++++++++++++++++++++++++++
 include/sound/compress_offload.h |  151 ++++++++++++++++++++++++++++++++++
 2 files changed, 317 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h

diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
new file mode 100644
index 0000000..1baa938
--- /dev/null
+++ b/include/sound/compress_driver.h
@@ -0,0 +1,166 @@
+/*
+ *  compress_driver.h - compress offload driver definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_DRIVER_H
+#define __COMPRESS_DRIVER_H
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <sound/compress_offload.h>
+#include <sound/asound.h>
+#include <sound/pcm.h>
+
+struct snd_compr_ops;
+
+/**
+ * struct snd_compr_runtime: runtime stream description
+ * @state: stream state
+ * @ops: pointer to DSP callbacks
+ * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
+ *	DSP doesn't implement copy
+ * @buffer_size: size of the above buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ * @hw_pointer: offset of last location in buffer where DSP copied data
+ * @app_pointer: offset of last location in buffer where app wrote data
+ * @bytes_written: cummilative bytes written to device
+ * @bytes_copied: cummilative bytes copied by DSP
+ * @sleep: poll sleep
+ */
+struct snd_compr_runtime {
+	snd_pcm_state_t state;
+	struct snd_compr_ops *ops;
+	void *buffer;
+	size_t buffer_size;
+	size_t fragment_size;
+	unsigned int fragments;
+	size_t hw_pointer;
+	size_t app_pointer;
+	size_t bytes_written;
+	size_t bytes_copied;
+	wait_queue_head_t sleep;
+};
+
+/**
+ * struct snd_compr_stream: compressed stream
+ * @name: device name
+ * @ops: pointer to DSP callbacks
+ * @runtime: pointer to runtime structure
+ * @device: device pointer
+ * @direction: stream direction, playback/recording
+ * @private_data: pointer to DSP private data
+ */
+struct snd_compr_stream {
+	const char *name;
+	struct snd_compr_ops *ops;
+	struct snd_compr_runtime *runtime;
+	struct snd_compr *device;
+	unsigned int direction;
+	void *private_data;
+};
+
+/**
+ * struct snd_compr_ops: compressed path DSP operations
+ * @open: Open the compressed stream
+ * This callback is mandatory and shall keep dsp ready to receive the stream
+ * parameter
+ * @free: Close the compressed stream, mandatory
+ * @set_params: Sets the compressed stream parameters, mandatory
+ * This can be called in during stream creation only to set codec params
+ * and the stream properties
+ * @get_params: retrieve the codec parameters, mandatory
+ * @trigger: Trigger operations like start, pause, resume, drain, stop.
+ * This callback is mandatory
+ * @pointer: Retrieve current h/w pointer information. Mandatory
+ * @copy: Copy the compressed data to/from userspace, Optional
+ * Can't be implemented if DSP supports mmap
+ * @mmap: DSP mmap method to mmap DSP memory
+ * @ack: Ack for DSP when data is written to audio buffer, Optional
+ * Not valid if copy is implemented
+ * @get_caps: Retrieve DSP capabilities, mandatory
+ * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory
+ */
+struct snd_compr_ops {
+	int (*open)(struct snd_compr_stream *stream);
+	int (*free)(struct snd_compr_stream *stream);
+	int (*set_params)(struct snd_compr_stream *stream,
+			struct snd_compr_params *params);
+	int (*get_params)(struct snd_compr_stream *stream,
+			struct snd_codec *params);
+	int (*trigger)(struct snd_compr_stream *stream, int cmd);
+	int (*pointer)(struct snd_compr_stream *stream,
+			struct snd_compr_tstamp *tstamp);
+	int (*copy)(struct snd_compr_stream *stream, const char __user *buf,
+		       size_t count);
+	int (*mmap)(struct snd_compr_stream *stream,
+			struct vm_area_struct *vma);
+	int (*ack)(struct snd_compr_stream *stream, size_t bytes);
+	int (*get_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_caps *caps);
+	int (*get_codec_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_codec_caps *codec);
+};
+
+/**
+ * struct snd_compr: Compressed device
+ * @name: DSP device name
+ * @dev: Device pointer
+ * @ops: pointer to DSP callbacks
+ * @private_data: pointer to DSP pvt data
+ * @card: sound card pointer
+ * @direction: Playback or capture direction
+ * @lock: device lock
+ * @device: device id
+ */
+struct snd_compr {
+	const char *name;
+	struct device *dev;
+	struct snd_compr_ops *ops;
+	void *private_data;
+	struct snd_card *card;
+	unsigned int direction;
+	struct mutex lock;
+	int device;
+};
+
+/* compress device register APIs */
+int snd_compress_register(struct snd_compr *device);
+int snd_compress_deregister(struct snd_compr *device);
+int snd_compress_new(struct snd_card *card, int device,
+			int type, struct snd_compr *compr);
+
+/* dsp driver callback apis
+ * For playback: driver should call snd_compress_fragment_elapsed() to let the
+ * framework know that a fragment has been consumed from the ring buffer
+ *
+ * For recording: we want to know when a frame is available or when
+ * at least one frame is available so snd_compress_frame_elapsed()
+ * callback should be called when a encodeded frame is available
+ */
+static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
+{
+	wake_up(&stream->runtime->sleep);
+}
+
+#endif
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
new file mode 100644
index 0000000..2358c86
--- /dev/null
+++ b/include/sound/compress_offload.h
@@ -0,0 +1,151 @@
+/*
+ *  compress_offload.h - compress offload header definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_OFFLOAD_H
+#define __COMPRESS_OFFLOAD_H
+
+#include <linux/types.h>
+#include <sound/asound.h>
+#include <sound/snd_compress_params.h>
+
+
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
+/**
+ * struct snd_compressed_buffer: compressed buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ */
+struct snd_compressed_buffer {
+	size_t fragment_size;
+	int fragments;
+};
+
+/**
+ * struct snd_compr_params: compressed stream params
+ * @buffer: buffer description
+ * @codec: codec parameters
+ * @no_wake_mode: dont wake on fragment elapsed
+ */
+struct snd_compr_params {
+	struct snd_compressed_buffer buffer;
+	struct snd_codec codec;
+	bool no_wake_mode;
+};
+
+/**
+ * struct snd_compr_tstamp: timestamp descriptor
+ * @copied_bytes: Number of bytes offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from/to ring buffer to/by DSP
+ * @frames: Frames decoded or encoded by DSP
+ * @rendered: Frames rendered or recieved by DSP into a mixer or an audio
+ * output/input
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp {
+	size_t copied_bytes;
+	size_t copied_total;
+	size_t frames;
+	size_t rendered;
+	__u32 sampling_rate;
+};
+
+/**
+ * struct snd_compr_avail: avail descriptor
+ * @avail: Number of bytes available in ring buffer for writing/reading
+ * @tstamp: timestamp infomation
+ */
+struct snd_compr_avail {
+	size_t avail;
+	struct snd_compr_tstamp tstamp;
+};
+
+/**
+ * struct snd_compr_caps: caps descriptor
+ * @codecs: pointer to array of codecs
+ * @min_fragment_size: minimum fragment supported by DSP
+ * @max_fragment_size: maximum fragment supported by DSP
+ * @min_fragments: min fragments supported by DSP
+ * @max_fragments: max fragments supported by DSP
+ * @num_codecs: number of codecs supported
+ * @reserved: reserved field
+ */
+struct snd_compr_caps {
+	__u32 num_codecs;
+	__u32 min_fragment_size;
+	__u32 max_fragment_size;
+	__u32 min_fragments;
+	__u32 max_fragments;
+	__u32 codecs[MAX_NUM_CODECS];
+	__u32 reserved[11];
+};
+
+/**
+ * struct snd_compr_codec_caps: query capability of codec
+ * @codec: codec for which capability is queried
+ * @num_descriptors: number of codec descriptors
+ * @descriptor: array of codec capability descriptor
+ */
+struct snd_compr_codec_caps {
+	__u32 codec;
+	__u32 num_descriptors;
+	struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
+};
+
+/**
+ * compress path ioctl definitions
+ * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
+ * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
+ * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
+ * Note: only codec params can be changed runtime and stream params cant be
+ * SNDRV_COMPRESS_GET_PARAMS: Query codec params
+ * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
+ * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
+ * This also queries the tstamp properties
+ * SNDRV_COMPRESS_PAUSE: Pause the running stream
+ * SNDRV_COMPRESS_RESUME: resume a paused stream
+ * SNDRV_COMPRESS_START: Start a stream
+ * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
+ * and the buffers currently with DSP
+ * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
+ * SNDRV_COMPRESS_IOCTL_VERSION: Query the API version
+ */
+#define SNDRV_COMPRESS_IOCTL_VERSION	_IOR('C', 0x00, int)
+#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x10, struct snd_compr_caps)
+#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x11, struct snd_compr_codec_caps)
+#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x12, struct snd_compr_params)
+#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x13, struct snd_codec)
+#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x20, struct snd_compr_tstamp)
+#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x21, struct snd_compr_avail)
+#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x30)
+#define SNDRV_COMPRESS_RESUME		_IO('C', 0x31)
+#define SNDRV_COMPRESS_START		_IO('C', 0x32)
+#define SNDRV_COMPRESS_STOP		_IO('C', 0x33)
+#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x34)
+/*
+ * TODO
+ * 1. add mmap support
+ *
+ */
+#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v4 5/6] core: add support for compress_offload
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (6 preceding siblings ...)
  2011-12-13  9:02     ` [PATCH v4 4/6] core: add API header and driver header files Vinod Koul
@ 2011-12-13  9:02     ` Vinod Koul
  2011-12-13 12:48       ` Nallasellan, Singaravelan
  2011-12-22  7:55       ` Takashi Iwai
  2011-12-13  9:03     ` [PATCH v4 6/6] core: add makefile and kconfig file for compress Vinod Koul
                       ` (7 subsequent siblings)
  15 siblings, 2 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  9:02 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

This patch adds core.c, the file which implements the ioctls and
registers the devices

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
---
 sound/core/compress_offload.c |  705 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 705 insertions(+), 0 deletions(-)
 create mode 100644 sound/core/compress_offload.c

diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
new file mode 100644
index 0000000..d2345c2
--- /dev/null
+++ b/sound/core/compress_offload.c
@@ -0,0 +1,705 @@
+/*
+ *  core.c - compress offload core
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
+#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
+
+/* TODO:
+ * - add substream support for multiple devices in case of
+ *	SND_DYNAMIC_MINORS is not used
+ * - Multiple node representation
+ *	driver should be able to register multiple nodes
+ */
+
+static DEFINE_MUTEX(device_mutex);
+
+struct snd_compr_file {
+	unsigned long caps;
+	struct snd_compr_stream stream;
+};
+
+static int snd_compr_open(struct inode *inode, struct file *f)
+{
+	struct snd_compr *compr;
+	struct snd_compr_file *data;
+	struct snd_compr_runtime *runtime;
+	int ret, type;
+	int maj = imajor(inode);
+
+	if (f->f_flags & O_WRONLY)
+		type = SNDRV_DEVICE_TYPE_COMPR_PLAYBACK;
+	else if (f->f_flags & O_RDONLY)
+		type = SNDRV_DEVICE_TYPE_COMPR_CAPTURE;
+	else {
+		pr_err("invalid direction\n");
+		return -EINVAL;
+	}
+
+	if (maj == snd_major)
+		compr = snd_lookup_minor_data(iminor(inode), type);
+	else
+		return -ENXIO;
+
+	if (compr == NULL) {
+		pr_err("no device data!!!\n");
+		return -ENODEV;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	data->stream.ops = compr->ops;
+	data->stream.direction = type;
+	data->stream.private_data = compr->private_data;
+	data->stream.device = compr;
+	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+	if (!runtime) {
+		kfree(data);
+		return -ENOMEM;
+	}
+	runtime->state = SNDRV_PCM_STATE_OPEN;
+	init_waitqueue_head(&runtime->sleep);
+	data->stream.runtime = runtime;
+	f->private_data = (void *)data;
+	mutex_lock(&compr->lock);
+	ret = compr->ops->open(&data->stream);
+	mutex_unlock(&compr->lock);
+	if (ret) {
+		kfree(runtime);
+		kfree(data);
+	}
+	return ret;
+}
+
+static int snd_compr_free(struct inode *inode, struct file *f)
+{
+	struct snd_compr_file *data = f->private_data;
+	data->stream.ops->free(&data->stream);
+	kfree(data->stream.runtime->buffer);
+	kfree(data->stream.runtime);
+	kfree(data);
+	return 0;
+}
+
+static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
+		struct snd_compr_tstamp *tstamp)
+{
+	if (!stream->ops->pointer)
+		return;
+	stream->ops->pointer(stream, tstamp);
+	pr_debug("dsp consumed till %ld total %ld bytes\n",
+		(long)tstamp->copied_bytes, (long)tstamp->copied_total);
+	stream->runtime->hw_pointer = tstamp->copied_bytes;
+	stream->runtime->bytes_copied = tstamp->copied_total;
+}
+
+static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
+		struct snd_compr_avail *avail)
+{
+	long avail_calc; /*this needs to be signed variable */
+
+	snd_compr_update_tstamp(stream, &avail->tstamp);
+
+	if (stream->runtime->bytes_written == 0 &&
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+		pr_debug("detected init and someone forgot to do a write\n");
+		return stream->runtime->buffer_size;
+	}
+	pr_debug("app wrote %ld, DSP consumed %ld\n",
+			(long)stream->runtime->bytes_written,
+			(long)stream->runtime->bytes_copied);
+	if (stream->runtime->bytes_written == stream->runtime->bytes_copied) {
+		pr_debug("both pointers are same, returning full avail\n");
+		return stream->runtime->buffer_size;
+	}
+
+	avail_calc = stream->runtime->buffer_size -
+		(stream->runtime->app_pointer - stream->runtime->hw_pointer);
+	pr_debug("calc avail as %ld, app_ptr %ld, hw+ptr %ld\n", avail_calc,
+			(long)stream->runtime->app_pointer,
+			(long)stream->runtime->hw_pointer);
+	if (avail_calc >= stream->runtime->buffer_size)
+		avail_calc -= stream->runtime->buffer_size;
+	pr_debug("ret avail as %ld\n", avail_calc);
+	avail->avail = avail_calc;
+	return avail_calc;
+}
+
+static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
+{
+	struct snd_compr_avail avail;
+
+	return snd_compr_calc_avail(stream, &avail);
+}
+
+static int
+snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_avail ioctl_avail;
+	size_t avail;
+
+	avail = snd_compr_calc_avail(stream, &ioctl_avail);
+	ioctl_avail.avail = avail;
+
+	if (copy_to_user((unsigned long __user *)arg,
+				&ioctl_avail, sizeof(ioctl_avail)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_compr_write_data(struct snd_compr_stream *stream,
+	       const char __user *buf, size_t count)
+{
+	void *dstn;
+	size_t copy;
+	struct snd_compr_runtime *runtime = stream->runtime;
+
+	dstn = runtime->buffer + runtime->app_pointer;
+	pr_debug("copying %ld at %ld\n",
+			(long)count, (long)runtime->app_pointer);
+	if (count < runtime->buffer_size - runtime->app_pointer) {
+		if (copy_from_user(dstn, buf, count))
+			return -EFAULT;
+		runtime->app_pointer += count;
+	} else {
+		copy = runtime->buffer_size - runtime->app_pointer;
+		if (copy_from_user(dstn, buf, copy))
+			return -EFAULT;
+		if (copy_from_user(runtime->buffer, buf + copy, count - copy))
+			return -EFAULT;
+		runtime->app_pointer = count - copy;
+	}
+	/* if DSP cares, let it know data has been written */
+	if (stream->ops->ack)
+		stream->ops->ack(stream, count);
+	return count;
+}
+
+static ssize_t snd_compr_write(struct file *f, const char __user *buf,
+		size_t count, loff_t *offset)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	mutex_lock(&stream->device->lock);
+	/* write is allowed when stream is running or has been steup */
+	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
+			stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		mutex_unlock(&stream->device->lock);
+		return -EPERM;
+	}
+
+	avail = snd_compr_get_avail(stream);
+	pr_debug("avail returned %ld\n", (long)avail);
+	/* calculate how much we can write to buffer */
+	if (avail > count)
+		avail = count;
+
+	if (stream->ops->copy)
+		retval = stream->ops->copy(stream, buf, avail);
+	else
+		retval = snd_compr_write_data(stream, buf, avail);
+	if (retval > 0)
+		stream->runtime->bytes_written += retval;
+
+	/* while initiating the stream, write should be called before START
+	 * call, so in setup move state */
+	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+		pr_debug("stream prepared, Houston we are good to go\n");
+	}
+
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+
+static ssize_t snd_compr_read(struct file *f, char __user *buf,
+		size_t count, loff_t *offset)
+{
+	return -ENXIO;
+}
+
+static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
+{
+	return -ENXIO;
+}
+
+static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval = 0;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+
+	mutex_lock(&stream->device->lock);
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		retval = -ENXIO;
+		goto out;
+	}
+	poll_wait(f, &stream->runtime->sleep, wait);
+
+	avail = snd_compr_get_avail(stream);
+	pr_debug("avail is %ld\n", (long)avail);
+	/* check if we have at least one fragment to fill */
+	switch (stream->runtime->state) {
+	case SNDRV_PCM_STATE_RUNNING:
+	case SNDRV_PCM_STATE_PREPARED:
+	case SNDRV_PCM_STATE_PAUSED:
+		if (avail >= stream->runtime->fragment_size) {
+			if (stream->direction == SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
+				retval = POLLOUT | POLLWRNORM;
+			else
+				retval = POLLIN | POLLRDNORM;
+			break;
+		}
+		/* Fall through */
+	case SNDRV_PCM_STATE_DRAINING:
+		break;
+	default:
+		if (stream->direction == SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
+			retval = POLLOUT | POLLWRNORM | POLLERR;
+		else
+			retval = POLLIN | POLLRDNORM | POLLERR;
+		break;
+	}
+out:
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+static int
+snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_caps caps;
+
+	if (!stream->ops->get_caps)
+		return -ENXIO;
+
+	retval = stream->ops->get_caps(stream, &caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
+		retval = -EFAULT;
+out:
+	return retval;
+}
+
+static int
+snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_codec_caps *caps;
+
+	if (!stream->ops->get_codec_caps)
+		return -ENXIO;
+
+	caps = kmalloc(sizeof(*caps), GFP_KERNEL);
+	if (!caps)
+		return -ENOMEM;
+
+	retval = stream->ops->get_codec_caps(stream, caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
+		retval = -EFAULT;
+
+out:
+	kfree(caps);
+	return retval;
+}
+
+/* revisit this with snd_pcm_preallocate_xxx */
+static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+		struct snd_compr_params *params)
+{
+	unsigned int buffer_size;
+	void *buffer;
+
+	buffer_size = params->buffer.fragment_size * params->buffer.fragments;
+	if (stream->ops->copy) {
+		buffer = NULL;
+		/* if copy is defined the driver will be required to copy
+		 * the data from core
+		 */
+	} else {
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+	}
+	stream->runtime->fragment_size = params->buffer.fragment_size;
+	stream->runtime->fragments = params->buffer.fragments;
+	stream->runtime->buffer = buffer;
+	stream->runtime->buffer_size = buffer_size;
+	return 0;
+}
+
+static int
+snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_params *params;
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+		/*
+		 * we should allow parameter change only when stream has been
+		 * opened not in other cases
+		 */
+		params = kmalloc(sizeof(*params), GFP_KERNEL);
+		if (!params)
+			return -ENOMEM;
+		if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
+			return -EFAULT;
+		retval = snd_compr_allocate_buffer(stream, params);
+		if (retval) {
+			kfree(params);
+			return -ENOMEM;
+		}
+		retval = stream->ops->set_params(stream, params);
+		if (retval)
+			goto out;
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+	} else
+		return -EPERM;
+out:
+	kfree(params);
+	return retval;
+}
+
+static int
+snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_codec *params;
+	int retval;
+
+	if (!stream->ops->get_params)
+		return -ENXIO;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+	retval = stream->ops->get_params(stream, params);
+	if (retval)
+		goto out;
+	if (copy_to_user((char __user *)arg, params, sizeof(*params)))
+		retval = -EFAULT;
+
+out:
+	kfree(params);
+	return retval;
+}
+
+static inline int
+snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_tstamp tstamp;
+
+	snd_compr_update_tstamp(stream, &tstamp);
+	return copy_to_user((struct snd_compr_tstamp __user *)arg,
+		&tstamp, sizeof(tstamp)) ? -EFAULT : 0;
+}
+
+static int snd_compr_pause(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_resume(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_start(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_stop(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_drain(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	int retval = -ENOTTY;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	BUG_ON(!stream);
+	mutex_lock(&stream->device->lock);
+	switch (_IOC_NR(cmd)) {
+	case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
+		put_user(SNDRV_COMPRESS_VERSION,
+				(int __user *)arg) ? -EFAULT : 0;
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+		retval = snd_compr_get_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+		retval = snd_compr_get_codec_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+		retval = snd_compr_set_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
+		retval = snd_compr_get_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
+		retval = snd_compr_tstamp(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
+		retval = snd_compr_ioctl_avail(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
+		retval = snd_compr_pause(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_RESUME):
+		retval = snd_compr_resume(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_START):
+		retval = snd_compr_start(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_STOP):
+		retval = snd_compr_stop(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+		retval = snd_compr_drain(stream);
+		break;
+	}
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+static const struct file_operations snd_compr_file_ops = {
+		.owner =	THIS_MODULE,
+		.open =		snd_compr_open,
+		.release =	snd_compr_free,
+		.write =	snd_compr_write,
+		.read =		snd_compr_read,
+		.unlocked_ioctl = snd_compr_ioctl,
+		.mmap =		snd_compr_mmap,
+		.poll =		snd_compr_poll,
+};
+
+static int snd_compress_dev_register(struct snd_device *device)
+{
+	int ret = -EINVAL;
+	char str[16];
+	struct snd_compr *compr;
+
+	if (snd_BUG_ON(!device || !device->device_data))
+		return -ENXIO;
+	compr = device->device_data;
+
+	sprintf(str, "comprC%iD%i", compr->card->number, compr->device);
+	pr_debug("reg %s for device %s, direction %d\n", str, compr->name,
+			compr->direction);
+	/* register compressed device */
+	ret = snd_register_device(compr->direction, compr->card, compr->device,
+			  &snd_compr_file_ops, compr, str);
+	if (ret < 0) {
+		pr_err("snd_register_device failed\n %d", ret);
+		return ret;
+	}
+	return ret;
+
+}
+
+static int snd_compress_dev_disconnect(struct snd_device *device)
+{
+	struct snd_compr *compr;
+
+	compr = device->device_data;
+	snd_unregister_device(compr->direction, compr->card, compr->device);
+	return 0;
+}
+
+int snd_compress_new(struct snd_card *card, int device,
+			int type, struct snd_compr *compr)
+{
+	static struct snd_device_ops ops = {
+		.dev_free = NULL,
+		.dev_register = snd_compress_dev_register,
+		.dev_disconnect = snd_compress_dev_disconnect,
+	};
+
+	compr->card = card;
+	compr->device = device;
+	compr->direction = type;
+	return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
+}
+EXPORT_SYMBOL_GPL(snd_compress_new);
+
+static int snd_compress_add_device(struct snd_compr *device)
+{
+	int ret;
+
+	if (!device->card)
+		return -EINVAL;
+
+	/* register the card */
+	ret = snd_card_register(device->card);
+	if (ret)
+		goto out;
+	return 0;
+
+out:
+	pr_err("failed with %d\n", ret);
+	return ret;
+
+}
+
+static int snd_compress_remove_device(struct snd_compr *device)
+{
+	return snd_card_free(device->card);
+}
+
+/**
+ * snd_compress_register - register compressed device
+ *
+ * @device: compressed device to register
+ */
+int snd_compress_register(struct snd_compr *device)
+{
+	int retval;
+
+	if (device->name == NULL || device->dev == NULL || device->ops == NULL)
+		return -EINVAL;
+
+	pr_debug("Registering compressed device %s\n", device->name);
+	BUG_ON(!device->ops->open);
+	BUG_ON(!device->ops->free);
+	BUG_ON(!device->ops->set_params);
+	BUG_ON(!device->ops->trigger);
+
+	mutex_init(&device->lock);
+
+	/* register a compressed card */
+	mutex_lock(&device_mutex);
+	retval = snd_compress_add_device(device);
+	mutex_unlock(&device_mutex);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(snd_compress_register);
+
+int snd_compress_deregister(struct snd_compr *device)
+{
+	pr_debug("Removing compressed device %s\n", device->name);
+	mutex_lock(&device_mutex);
+	snd_compress_remove_device(device);
+	mutex_unlock(&device_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_compress_deregister);
+
+static int __init snd_compress_init(void)
+{
+	return 0;
+}
+
+static void __exit snd_compress_exit(void)
+{
+}
+
+module_init(snd_compress_init);
+module_exit(snd_compress_exit);
+
+MODULE_DESCRIPTION("ALSA Compressed offload framework");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v4 6/6] core: add makefile and kconfig file for compress
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (7 preceding siblings ...)
  2011-12-13  9:02     ` [PATCH v4 5/6] core: add support for compress_offload Vinod Koul
@ 2011-12-13  9:03     ` Vinod Koul
  2011-12-23  5:06     ` [PATCH v5 0/6] core: add compress data API to ALSA kernel Vinod Koul
                       ` (6 subsequent siblings)
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  9:03 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, lrg, Pierre-Louis Bossart

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
---
 sound/core/Kconfig  |    8 ++++++++
 sound/core/Makefile |    4 ++++
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 475455c..5bfce50 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -155,6 +155,14 @@ config SND_DYNAMIC_MINORS
 
 	  If you are unsure about this, say N here.
 
+config SND_COMPRESS_OFFLOAD
+	tristate "ALSA Compressed audio offload support"
+	default n
+	help
+	  If you want support for offloading compressed audio and have such
+	  a hardware, then you should say Y here and also to the DSP driver
+	  of your platform.
+
 config SND_SUPPORT_OLD_API
 	bool "Support old ALSA API"
 	default y
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 350a08d..67c8e93 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -21,6 +21,8 @@ snd-hrtimer-objs  := hrtimer.o
 snd-rtctimer-objs := rtctimer.o
 snd-hwdep-objs    := hwdep.o
 
+snd-compress-objs := compress_offload.o
+
 obj-$(CONFIG_SND) 		+= snd.o
 obj-$(CONFIG_SND_HWDEP)		+= snd-hwdep.o
 obj-$(CONFIG_SND_TIMER)		+= snd-timer.o
@@ -31,3 +33,5 @@ obj-$(CONFIG_SND_RAWMIDI)	+= snd-rawmidi.o
 
 obj-$(CONFIG_SND_OSSEMUL)	+= oss/
 obj-$(CONFIG_SND_SEQUENCER)	+= seq/
+
+obj-$(CONFIG_SND_COMPRESS_OFFLOAD)	+= snd-compress.o
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* Re: [PATCH v3 4/6] core: add API header and driver header files
  2011-12-13  7:53             ` Mark Brown
@ 2011-12-13  9:03               ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-13  9:03 UTC (permalink / raw)
  To: Mark Brown; +Cc: Takashi Iwai, alsa-devel, lrg, Pierre-Louis Bossart

On Tue, 2011-12-13 at 15:53 +0800, Mark Brown wrote:
> On Tue, Dec 13, 2011 at 01:20:41PM +0530, Vinod Koul wrote:
> 
> > Do you have more feedback for this patchset, or I can send v4 with these
> > fixes later today :)
> 
> Well, you can send the patches either way!  I don't have any more at
> present but I've not really looked yet.
No issues, sent the v4 now :)

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-13  9:02     ` [PATCH v4 5/6] core: add support for compress_offload Vinod Koul
@ 2011-12-13 12:48       ` Nallasellan, Singaravelan
  2011-12-13 14:12         ` Vinod Koul
  2011-12-22  7:55       ` Takashi Iwai
  1 sibling, 1 reply; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-13 12:48 UTC (permalink / raw)
  To: Vinod Koul, alsa-devel; +Cc: tiwai, broonie, lrg, Pierre-Louis Bossart


> +static int snd_compr_open(struct inode *inode, struct file *f) {
> +	struct snd_compr *compr;
> +	struct snd_compr_file *data;
> +	struct snd_compr_runtime *runtime;
> +	int ret, type;
> +	int maj = imajor(inode);
> +
> +	if (f->f_flags & O_WRONLY)
> +		type = SNDRV_DEVICE_TYPE_COMPR_PLAYBACK;
> +	else if (f->f_flags & O_RDONLY)
> +		type = SNDRV_DEVICE_TYPE_COMPR_CAPTURE;
> +	else {
> +		pr_err("invalid direction\n");
> +		return -EINVAL;
> +	}
If someone changes the device mode, this is screwed though there are two types 
of (PLAYBACK and CAPTURE) devices are registered? 
Would be better if there are two separate playback and  capture operations registered 
separately.

O_NONBLOCK is not tested here for non-blocking support.
> +
> +	if (maj == snd_major)
> +		compr = snd_lookup_minor_data(iminor(inode), type);
> +	else
> +		return -ENXIO;
> +
> +	if (compr == NULL) {
> +		pr_err("no device data!!!\n");
> +		return -ENODEV;
> +	}
> +
> +
> +static ssize_t snd_compr_write(struct file *f, const char __user *buf,
> +		size_t count, loff_t *offset)
> +{
> +	struct snd_compr_file *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +	size_t avail;
> +	int retval;
> +
> +	BUG_ON(!data);
> +	stream = &data->stream;
> +	mutex_lock(&stream->device->lock);
> +	/* write is allowed when stream is running or has been steup */
> +	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
> +			stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> {
Cant we call write again when the stream is in SNDRV_PCM_STATE_PREPARED state? 
This code allows only one write after the stream is in SNDRV_PCM_STATE_SETUP state.
What if someone wants to write multiple smaller fragments before the start?
> +		mutex_unlock(&stream->device->lock);
> +		return -EPERM;
> +	}
> +
> +	avail = snd_compr_get_avail(stream);
> +	pr_debug("avail returned %ld\n", (long)avail);
> +	/* calculate how much we can write to buffer */
> +	if (avail > count)
> +		avail = count;
> +
> +	if (stream->ops->copy)
> +		retval = stream->ops->copy(stream, buf, avail);
> +	else
> +		retval = snd_compr_write_data(stream, buf, avail);
> +	if (retval > 0)
> +		stream->runtime->bytes_written += retval;
> +
> +	/* while initiating the stream, write should be called before START
> +	 * call, so in setup move state */
> +	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
> +		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
> +		pr_debug("stream prepared, Houston we are good to go\n");
> +	}
> +
> +	mutex_unlock(&stream->device->lock);
> +	return retval;
> +}
> +
> +static unsigned int snd_compr_poll(struct file *f, poll_table *wait) {
> +	struct snd_compr_file *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +	size_t avail;
> +	int retval = 0;
> +
> +	BUG_ON(!data);
> +	stream = &data->stream;

Can you validate O_NONBLOCK before going into poll_wait?
I guess this has to return -EINVAL if the device is not opened with O_NONBLOCK.

> +
> +	mutex_lock(&stream->device->lock);
> +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
> +		retval = -ENXIO;
> +		goto out;
> +	}
> +	poll_wait(f, &stream->runtime->sleep, wait);
> +
> +	avail = snd_compr_get_avail(stream);
> +	pr_debug("avail is %ld\n", (long)avail);
> +	/* check if we have at least one fragment to fill */
> +	switch (stream->runtime->state) {
> +	case SNDRV_PCM_STATE_RUNNING:
> +	case SNDRV_PCM_STATE_PREPARED:
> +	case SNDRV_PCM_STATE_PAUSED:
> +		if (avail >= stream->runtime->fragment_size) {
> +			if (stream->direction ==
> SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
> +				retval = POLLOUT | POLLWRNORM;
> +			else
> +				retval = POLLIN | POLLRDNORM;
> +			break;
> +		}
> +		/* Fall through */
> +	case SNDRV_PCM_STATE_DRAINING:
Where is this state set? I do not see this snd_cmpr_drain.
> +		break;
> +	default:
> +		if (stream->direction == SNDRV_DEVICE_TYPE_COMPR_PLAYBACK)
> +			retval = POLLOUT | POLLWRNORM | POLLERR;
> +		else
> +			retval = POLLIN | POLLRDNORM | POLLERR;
> +		break;
> +	}
> +out:
> +	mutex_unlock(&stream->device->lock);
> +	return retval;
> +}
> +


> +
> +/* revisit this with snd_pcm_preallocate_xxx */ static int
> +snd_compr_allocate_buffer(struct snd_compr_stream *stream,
> +		struct snd_compr_params *params)
> +{
> +	unsigned int buffer_size;
> +	void *buffer;
> +
> +	buffer_size = params->buffer.fragment_size * params->buffer.fragments;


If fragment_size is not a positive value, return -EINVAL.
What is the maximum number of fragments supported? 
Can we check the fragments to that limit?

> +	if (stream->ops->copy) {
> +		buffer = NULL;
> +		/* if copy is defined the driver will be required to copy
> +		 * the data from core
> +		 */
> +	} else {
> +		buffer = kmalloc(buffer_size, GFP_KERNEL);
> +		if (!buffer)
> +			return -ENOMEM;
> +	}
> +	stream->runtime->fragment_size = params->buffer.fragment_size;
> +	stream->runtime->fragments = params->buffer.fragments;
> +	stream->runtime->buffer = buffer;
> +	stream->runtime->buffer_size = buffer_size;
> +	return 0;
> +}


> +
> +static int
> +snd_compr_set_params(struct snd_compr_stream *stream, unsigned long
> +arg) {
> +	struct snd_compr_params *params;
> +	int retval;
> +
> +	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
> +		/*
> +		 * we should allow parameter change only when stream has been
> +		 * opened not in other cases
> +		 */
> +		params = kmalloc(sizeof(*params), GFP_KERNEL);
> +		if (!params)
> +			return -ENOMEM;
> +		if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
> +			return -EFAULT;
> +		retval = snd_compr_allocate_buffer(stream, params);
> +		if (retval) {
> +			kfree(params);
> +			return -ENOMEM;
> +		}
<Sing>: Can you check stream->ops->set_params for NULL as it is done in the get_params function?
> +		retval = stream->ops->set_params(stream, params);
> +		if (retval)
> +			goto out;
> +		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
> +	} else
> +		return -EPERM;
> +out:
> +	kfree(params);
> +	return retval;
> +}

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-13 12:48       ` Nallasellan, Singaravelan
@ 2011-12-13 14:12         ` Vinod Koul
  2011-12-13 16:02           ` Nallasellan, Singaravelan
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-13 14:12 UTC (permalink / raw)
  To: Nallasellan, Singaravelan
  Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Tue, 2011-12-13 at 18:18 +0530, Nallasellan, Singaravelan wrote:

Please wrap your emails within 80 chars, you have been repeatedly asked
to do so on this on list. I don't understand how hard it is to follow
basic list etiquettes. Its difficult to read screwed up formatting

> > +static int snd_compr_open(struct inode *inode, struct file *f) {
> > +	struct snd_compr *compr;
> > +	struct snd_compr_file *data;
> > +	struct snd_compr_runtime *runtime;
> > +	int ret, type;
> > +	int maj = imajor(inode);
> > +
> > +	if (f->f_flags & O_WRONLY)
> > +		type = SNDRV_DEVICE_TYPE_COMPR_PLAYBACK;
> > +	else if (f->f_flags & O_RDONLY)
> > +		type = SNDRV_DEVICE_TYPE_COMPR_CAPTURE;
> > +	else {
> > +		pr_err("invalid direction\n");
> > +		return -EINVAL;
> > +	}
> If someone changes the device mode, this is screwed though there are
> two types 
> of (PLAYBACK and CAPTURE) devices are registered? 
> Would be better if there are two separate playback and  capture
> operations registered 
> separately.
Again, please read the related discussion on the list.

Compressed devices will not have direction associated with them . They
can be opened in any mode depending on the mode the DSP supports.
So /dev/snd/comprC0D0 can be either playback or capture device.
So a device can be ONLY opened with O_WRONLY or O_RDONLY.


> O_NONBLOCK is not tested here for non-blocking support.
Why should it be?
1) Any blocking and non blocking should be handled in user space
2) Nevertheless, that is not supported, HINT: read the documentation

> > +
> > +static ssize_t snd_compr_write(struct file *f, const char __user *buf,
> > +		size_t count, loff_t *offset)
> > +{
> > +	struct snd_compr_file *data = f->private_data;
> > +	struct snd_compr_stream *stream;
> > +	size_t avail;
> > +	int retval;
> > +
> > +	BUG_ON(!data);
> > +	stream = &data->stream;
> > +	mutex_lock(&stream->device->lock);
> > +	/* write is allowed when stream is running or has been steup */
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
> > +			stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> > {
> Cant we call write again when the stream is in
> SNDRV_PCM_STATE_PREPARED state? 
> This code allows only one write after the stream is in
> SNDRV_PCM_STATE_SETUP state.
> What if someone wants to write multiple smaller fragments before the
> start?
Yes currently write is allowed only once and we *normally* expect a
START call. I am not sure why someone would need to call "smaller"
writes multiple times. Remember this is compressed offload where we
ideally want larger chunks of data otherwise there is no point in using
this.
> > +static unsigned int snd_compr_poll(struct file *f, poll_table *wait) {
> > +	struct snd_compr_file *data = f->private_data;
> > +	struct snd_compr_stream *stream;
> > +	size_t avail;
> > +	int retval = 0;
> > +
> > +	BUG_ON(!data);
> > +	stream = &data->stream;
> 
> Can you validate O_NONBLOCK before going into poll_wait?
> I guess this has to return -EINVAL if the device is not opened with
> O_NONBLOCK.
See above

> > +	case SNDRV_PCM_STATE_DRAINING:
> Where is this state set? I do not see this snd_cmpr_drain.
Yes this should be set in snd_compr_drain. Fixed now.

> > +	void *buffer;
> > +
> > +	buffer_size = params->buffer.fragment_size * params->buffer.fragments;
> 
> 
> If fragment_size is not a positive value, return -EINVAL.
It can only be +ve

> What is the maximum number of fragments supported? 
Whatever dsp supports

> Can we check the fragments to that limit?
Yes, can be checked here as well but I prefer to do these checks in
userspace library


> > +
> > +static int
> > +snd_compr_set_params(struct snd_compr_stream *stream, unsigned long
> > +arg) {
Pls fix your mailer, it screwing up original formatting.

> > +	struct snd_compr_params *params;
> > +	int retval;
> > +
> > +	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
> > +		/*
> > +		 * we should allow parameter change only when stream has been
> > +		 * opened not in other cases
> > +		 */
> > +		params = kmalloc(sizeof(*params), GFP_KERNEL);
> > +		if (!params)
> > +			return -ENOMEM;
> > +		if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
> > +			return -EFAULT;
> > +		retval = snd_compr_allocate_buffer(stream, params);
> > +		if (retval) {
> > +			kfree(params);
> > +			return -ENOMEM;
> > +		}
> <Sing>: Can you check stream->ops->set_params for NULL as it is done
> in the get_params function?
No set_params is mandatory function to be implemented

> > +		retval = stream->ops->set_params(stream, params);
> > +		if (retval)
> > +			goto out;
> > +		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
> > +	} else
> > +		return -EPERM;
> > +out:
> > +	kfree(params);
> > +	return retval;
> > +}


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-13 14:12         ` Vinod Koul
@ 2011-12-13 16:02           ` Nallasellan, Singaravelan
  2011-12-13 17:53             ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-13 16:02 UTC (permalink / raw)
  To: Vinod Koul; +Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart


> 
> Please wrap your emails within 80 chars, you have been repeatedly asked to do so
> on this on list. I don't understand how hard it is to follow basic list etiquettes. Its
> difficult to read screwed up formatting
> 
Yes sir. Apologize for the mistake.

> > If someone changes the device mode, this is screwed though there are
> > two types of (PLAYBACK and CAPTURE) devices are registered?
> > Would be better if there are two separate playback and  capture
> > operations registered separately.
> Again, please read the related discussion on the list.
> 
> Compressed devices will not have direction associated with them . They can be
> opened in any mode depending on the mode the DSP supports.
> So /dev/snd/comprC0D0 can be either playback or capture device.
> So a device can be ONLY opened with O_WRONLY or O_RDONLY.
> 
Nice, Does it look like a hack hack hack...
> 
> > O_NONBLOCK is not tested here for non-blocking support.
> Why should it be?
> 1) Any blocking and non blocking should be handled in user space
> 2) Nevertheless, that is not supported, HINT: read the documentation
> 
This is not as per the write system call definition as I understand.  Look like we redefine the
system call here. Support it in the standard way.
> > > +	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
> > > +			stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
> > > {
> > Cant we call write again when the stream is in
> > SNDRV_PCM_STATE_PREPARED state?
> > This code allows only one write after the stream is in
> > SNDRV_PCM_STATE_SETUP state.
> > What if someone wants to write multiple smaller fragments before the
> > start?
> Yes currently write is allowed only once and we *normally* expect a START call. I am
> not sure why someone would need to call "smaller"
> writes multiple times. Remember this is compressed offload where we ideally want
> larger chunks of data otherwise there is no point in using this.
The code allows this to happen.  Is there any minimum size documented anywhere? 

> > > +static unsigned int snd_compr_poll(struct file *f, poll_table *wait) {
> > > +	struct snd_compr_file *data = f->private_data;
> > > +	struct snd_compr_stream *stream;
> > > +	size_t avail;
> > > +	int retval = 0;
> > > +
> > > +	BUG_ON(!data);
> > > +	stream = &data->stream;
> >
> > Can you validate O_NONBLOCK before going into poll_wait?
> > I guess this has to return -EINVAL if the device is not opened with
> > O_NONBLOCK.
> See above
Not a write implementation. 
> 
> 
> > What is the maximum number of fragments supported?
> Whatever dsp supports
IMHO, compress-core needs to query it from each driver and allocate memory 
only if the supported fragments is greater than requested fragments. 
> 
> > Can we check the fragments to that limit?
> Yes, can be checked here as well but I prefer to do these checks in userspace library
Think the driver needs to check and return error if it is not within the maximum
supported by the driver.
> 
> 
> > <Sing>: Can you check stream->ops->set_params for NULL as it is done
> > in the get_params function?
> No set_params is mandatory function to be implemented
Ok. It is my miss. 
> 
> --
> ~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-13 16:02           ` Nallasellan, Singaravelan
@ 2011-12-13 17:53             ` Vinod Koul
  2011-12-14  5:17               ` Nallasellan, Singaravelan
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-13 17:53 UTC (permalink / raw)
  To: Nallasellan, Singaravelan
  Cc: tiwai, alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Tue, 2011-12-13 at 21:32 +0530, Nallasellan, Singaravelan wrote:
> > 
> > Again, please read the related discussion on the list.
> > 
> > Compressed devices will not have direction associated with them . They can be
> > opened in any mode depending on the mode the DSP supports.
> > So /dev/snd/comprC0D0 can be either playback or capture device.
> > So a device can be ONLY opened with O_WRONLY or O_RDONLY.
> > 
> Nice, Does it look like a hack hack hack...
Care to elaborate your comment?


> > > O_NONBLOCK is not tested here for non-blocking support.
> > Why should it be?
> > 1) Any blocking and non blocking should be handled in user space
> > 2) Nevertheless, that is not supported, HINT: read the documentation
> > 
> This is not as per the write system call definition as I understand.
> Look like we redefine the
> system call here. Support it in the standard way.
Your argument is entirely bogus.
What do you mean by that? Noone is changing a system call.
For this device O_NONBLOCK is not supported thats it!!! How does that
violate a system call. 
There are many other flags which some device support and some don't.

> > Yes currently write is allowed only once and we *normally* expect a START call. I am
> > not sure why someone would need to call "smaller"
> > writes multiple times. Remember this is compressed offload where we ideally want
> > larger chunks of data otherwise there is no point in using this.
> The code allows this to happen.  Is there any minimum size documented anywhere? 
That's whatever dsp supports


> > > What is the maximum number of fragments supported?
> > Whatever dsp supports
> IMHO, compress-core needs to query it from each driver and allocate memory 
> only if the supported fragments is greater than requested fragments. 
user library should query the format and other details supported at
open. So these checks are anyway made their.
Nevertheless, this can be taken care in core as well but there is always
a question of how much check to do.

> > 
> > > Can we check the fragments to that limit?
> > Yes, can be checked here as well but I prefer to do these checks in userspace library
> Think the driver needs to check and return error if it is not within the maximum
> supported by the driver.
Where is driver coming here?

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-13 17:53             ` Vinod Koul
@ 2011-12-14  5:17               ` Nallasellan, Singaravelan
  2011-12-20  9:26                 ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Nallasellan, Singaravelan @ 2011-12-14  5:17 UTC (permalink / raw)
  To: vinod.koul; +Cc: tiwai, alsa-devel, broonie, lrg, pierre-louis.bossart

On Tue, 2011-12-13 at 23:23 +0530, Vinod Koul wrote:
> On Tue, 2011-12-13 at 21:32 +0530, Nallasellan, Singaravelan wrote:
> > > 
> > > Again, please read the related discussion on the list.
> > > 
> > > Compressed devices will not have direction associated with them . They can be
> > > opened in any mode depending on the mode the DSP supports.
> > > So /dev/snd/comprC0D0 can be either playback or capture device.
> > > So a device can be ONLY opened with O_WRONLY or O_RDONLY.
> > > 
> > Nice, Does it look like a hack hack hack...
> Care to elaborate your comment?
> 
There are few assumptions here:
1) User of this device should use only these flags
2) No one should change the file permission after the device is created.
3) No one should write to the ring buffer of the capture stream in the
case of mmap. If someone wants to process the data in the ring buffer
itself for capture stream, it is not allowed. The user should copy the
the content from ring buffer and then process it. May be a good idea. 

4) Looks like minor numbers are used to differentiate the multiple
streams. 
Anyhow, the device should be opened for capture and playback
separately. 
What do we loose if we use separate devices for capture and playback for
each stream supported?

5) Anyway, I think the device entries should be created for each stream
with a different minor number.

Why dont we use the similar device node creation method as PCM? 
May be I missed some relevant discussion here. Can you guys provide more
info?

> 
> > > > O_NONBLOCK is not tested here for non-blocking support.
> > > Why should it be?
> > > 1) Any blocking and non blocking should be handled in user space
> > > 2) Nevertheless, that is not supported, HINT: read the documentation
> > > 
> > This is not as per the write system call definition as I understand.
> > Look like we redefine the
> > system call here. Support it in the standard way.
> Your argument is entirely bogus.
> What do you mean by that? Noone is changing a system call.
> For this device O_NONBLOCK is not supported thats it!!! How does that
> violate a system call. 
> There are many other flags which some device support and some don't.
> 
> > > Yes currently write is allowed only once and we *normally* expect a START call. I am
> > > not sure why someone would need to call "smaller"
> > > writes multiple times. Remember this is compressed offload where we ideally want
> > > larger chunks of data otherwise there is no point in using this.
> > The code allows this to happen.  Is there any minimum size documented anywhere? 
> That's whatever dsp supports
> 
> 
> > > > What is the maximum number of fragments supported?
> > > Whatever dsp supports
> > IMHO, compress-core needs to query it from each driver and allocate memory 
> > only if the supported fragments is greater than requested fragments. 
> user library should query the format and other details supported at
> open. So these checks are anyway made their.
> Nevertheless, this can be taken care in core as well but there is always
> a question of how much check to do.
IMO, the kernel code should ensure the sanity of the values. It should
not assume that you will always do the right thing.  
> 
> > > 
> > > > Can we check the fragments to that limit?
> > > Yes, can be checked here as well but I prefer to do these checks in userspace library
> > Think the driver needs to check and return error if it is not within the maximum
> > supported by the driver.
> Where is driver coming here?

As you mentioned, the driver will specify the max number of fragments
supported. Now the compress-core has to query the value and validate the
user values. Other option is to send the parameters to the driver and
let it verify the sanity of the values and return the right error code
the core. 
> 
> -- 
> ~Vinod
> 

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-14  5:17               ` Nallasellan, Singaravelan
@ 2011-12-20  9:26                 ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-20  9:26 UTC (permalink / raw)
  To: Nallasellan, Singaravelan
  Cc: tiwai, alsa-devel, broonie, lrg, pierre-louis.bossart

On Wed, 2011-12-14 at 10:47 +0530, Nallasellan, Singaravelan wrote:
> On Tue, 2011-12-13 at 23:23 +0530, Vinod Koul wrote:
> > On Tue, 2011-12-13 at 21:32 +0530, Nallasellan, Singaravelan wrote:
> > > > 
> > > > Again, please read the related discussion on the list.
> > > > 
> > > > Compressed devices will not have direction associated with them . They can be
> > > > opened in any mode depending on the mode the DSP supports.
> > > > So /dev/snd/comprC0D0 can be either playback or capture device.
> > > > So a device can be ONLY opened with O_WRONLY or O_RDONLY.
> > > > 
> > > Nice, Does it look like a hack hack hack...
> > Care to elaborate your comment?
> > 
> There are few assumptions here:
> 1) User of this device should use only these flags
User will not know about these flags, Library should take care.
User just opens a playback or capture device
> 2) No one should change the file permission after the device is created.
File permissions? what are you talking about?

> 3) No one should write to the ring buffer of the capture stream in the
> case of mmap. If someone wants to process the data in the ring buffer
> itself for capture stream, it is not allowed. The user should copy the
> the content from ring buffer and then process it. May be a good idea.
Yes why would you allow write for capture stream?
That notion itself is not good idea as you are relying on ring buffer
not to overwrite data while you are processing. DSP is not aware of this
and will overwrite data.

> 4) Looks like minor numbers are used to differentiate the multiple
> streams. 
> Anyhow, the device should be opened for capture and playback
> separately. 
> What do we loose if we use separate devices for capture and playback for
> each stream supported?
> 
> 5) Anyway, I think the device entries should be created for each stream
> with a different minor number.
> 
> Why dont we use the similar device node creation method as PCM? 
> May be I missed some relevant discussion here. Can you guys provide more
> info?
If you had care to read Takashi's comments, you wouldn't have been
asking these. At the peril of repeating myself again and again...
Previous version had compress devices like pcm comprCxDyp/c, but based
on discussion we had we didn't really need such a thing. So now we have
comprCxDy, which can be a playback or a capture device based on what the
DSP is supporting for that device.

> 
> > 
> > > > > O_NONBLOCK is not tested here for non-blocking support.
> > > > Why should it be?
> > > > 1) Any blocking and non blocking should be handled in user space
> > > > 2) Nevertheless, that is not supported, HINT: read the documentation
> > > > 
> > > This is not as per the write system call definition as I understand.
> > > Look like we redefine the
> > > system call here. Support it in the standard way.
> > Your argument is entirely bogus.
> > What do you mean by that? Noone is changing a system call.
> > For this device O_NONBLOCK is not supported thats it!!! How does that
> > violate a system call. 
> > There are many other flags which some device support and some don't.
> > 
> > > > Yes currently write is allowed only once and we *normally* expect a START call. I am
> > > > not sure why someone would need to call "smaller"
> > > > writes multiple times. Remember this is compressed offload where we ideally want
> > > > larger chunks of data otherwise there is no point in using this.
> > > The code allows this to happen.  Is there any minimum size documented anywhere? 
> > That's whatever dsp supports
> > 
> > 
> > > > > What is the maximum number of fragments supported?
> > > > Whatever dsp supports
> > > IMHO, compress-core needs to query it from each driver and allocate memory 
> > > only if the supported fragments is greater than requested fragments. 
> > user library should query the format and other details supported at
> > open. So these checks are anyway made their.
> > Nevertheless, this can be taken care in core as well but there is always
> > a question of how much check to do.
> IMO, the kernel code should ensure the sanity of the values. It should
> not assume that you will always do the right thing.
Naah the library needs these anyway, so no harm in checking.
>   
> > 
> > > > 
> > > > > Can we check the fragments to that limit?
> > > > Yes, can be checked here as well but I prefer to do these checks in userspace library
> > > Think the driver needs to check and return error if it is not within the maximum
> > > supported by the driver.
> > Where is driver coming here?
> 
> As you mentioned, the driver will specify the max number of fragments
> supported. Now the compress-core has to query the value and validate the
> user values. Other option is to send the parameters to the driver and
> let it verify the sanity of the values and return the right error code
> the core. 
Again, userspace will check.

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 2/6] core: add support for compressed devices
  2011-12-13  9:02     ` [PATCH v4 2/6] core: add support for compressed devices Vinod Koul
@ 2011-12-22  7:34       ` Takashi Iwai
  2011-12-22  8:15         ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-12-22  7:34 UTC (permalink / raw)
  To: Vinod Koul
  Cc: lrg, alsa-devel, broonie, Pierre-Louis Bossart, Omair Mohammed Abdullah

At Tue, 13 Dec 2011 14:32:56 +0530,
Vinod Koul wrote:
> 
> From: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
> 
> Use the two minor numbers 2 and 3 for audio compressed offload devices.
> Also add support for these devices in core
> 
> Signed-off-by: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> ---
>  include/sound/core.h   |    1 +
>  include/sound/minors.h |    7 ++++++-
>  sound/core/sound.c     |    6 ++++++
>  3 files changed, 13 insertions(+), 1 deletions(-)
> 
> diff --git a/include/sound/core.h b/include/sound/core.h
> index 3be5ab7..5ab255f 100644
> --- a/include/sound/core.h
> +++ b/include/sound/core.h
> @@ -62,6 +62,7 @@ typedef int __bitwise snd_device_type_t;
>  #define	SNDRV_DEV_BUS		((__force snd_device_type_t) 0x1007)
>  #define	SNDRV_DEV_CODEC		((__force snd_device_type_t) 0x1008)
>  #define	SNDRV_DEV_JACK          ((__force snd_device_type_t) 0x1009)
> +#define	SNDRV_DEV_COMPRESS	((__force snd_device_type_t) 0x100A)
>  #define	SNDRV_DEV_LOWLEVEL	((__force snd_device_type_t) 0x2000)
>  
>  typedef int __bitwise snd_device_state_t;
> diff --git a/include/sound/minors.h b/include/sound/minors.h
> index 8f76420..faaeb64 100644
> --- a/include/sound/minors.h
> +++ b/include/sound/minors.h
> @@ -35,7 +35,8 @@
>  #define SNDRV_MINOR_TIMER		33	/* SNDRV_MINOR_GLOBAL + 1 * 32 */
>  
>  #ifndef CONFIG_SND_DYNAMIC_MINORS
> -						/* 2 - 3 (reserved) */
> +#define SNDRV_MINOR_COMPR_PLAYBACK	2
> +#define SNDRV_MINOR_COMPR_CAPTURE	3

If you'd share both playback and capture to a single device (as you
already did in patch 5/6), no need to provide distinct numbers here.
This would be simply

#define SNDRV_MINOR_COMPR		2

and define the single SNDRV_DEVICE_TYPE_COMPR.
Then you'll have to up to two devices for the static minors and more
for dynamic minors.  So, the below would be:

> diff --git a/sound/core/sound.c b/sound/core/sound.c
> index 828af35..2b680dd 100644
> --- a/sound/core/sound.c
> +++ b/sound/core/sound.c
> @@ -233,6 +233,12 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
>  			return -EINVAL;
>  		minor = SNDRV_MINOR(card->number, type + dev);
>  		break;
> +	case SNDRV_DEVICE_TYPE_COMPR_PLAYBACK:
> +	case SNDRV_DEVICE_TYPE_COMPR_CAPTURE:
> +		if (snd_BUG_ON(!card))
> +			return -EINVAL;
> +		minor = SNDRV_MINOR(card->number, type);
> +		break;

Instead of this, just add case SNDRV_DEVICE_TYPE_COMPR in the cases of
other types like PCM and RAWMIDI, i.e.

> +		minor = SNDRV_MINOR(card->number, type + dev);


Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 3/6] core: add compress parameter definations
  2011-12-13  9:02     ` [PATCH v4 3/6] core: add compress parameter definations Vinod Koul
@ 2011-12-22  7:35       ` Takashi Iwai
  2011-12-22  8:16         ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-12-22  7:35 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, broonie, lrg, Pierre-Louis Bossart

At Tue, 13 Dec 2011 14:32:57 +0530,
Vinod Koul wrote:
> 
> The patch adds the various definations used to define the encoder
> and decoder parameters
> 
> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> ---
>  include/sound/snd_compress_params.h |  395 +++++++++++++++++++++++++++++++++++

I wonder why snd_ prefix is added to this header file.
It's no big issue, but it looks redundant :)


Takashi

>  1 files changed, 395 insertions(+), 0 deletions(-)
>  create mode 100644 include/sound/snd_compress_params.h
> 
> diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
> new file mode 100644
> index 0000000..79b681d
> --- /dev/null
> +++ b/include/sound/snd_compress_params.h
> @@ -0,0 +1,395 @@
> +/*
> + *  snd_compress_params.h - codec types and parameters for compressed data
> + *  streaming interface
> + *
> + *  Copyright (C) 2011 Intel Corporation
> + *  Authors:	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> + *              Vinod Koul <vinod.koul@linux.intel.com>
> + *
> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; version 2 of the License.
> + *
> + *  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.
> + *
> + *  You should have received a copy of the GNU General Public License along
> + *  with this program; if not, write to the Free Software Foundation, Inc.,
> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + * The definitions in this file are derived from the OpenMAX AL version 1.1
> + * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
> + *
> + * Copyright (c) 2007-2010 The Khronos Group Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining
> + * a copy of this software and/or associated documentation files (the
> + * "Materials "), to deal in the Materials without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sublicense, and/or sell copies of the Materials, and to
> + * permit persons to whom the Materials are furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included
> + * in all copies or substantial portions of the Materials.
> + *
> + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
> + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
> + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
> + *
> + */
> +#ifndef __SND_COMPRESS_PARAMS_H
> +#define __SND_COMPRESS_PARAMS_H
> +
> +/* AUDIO CODECS SUPPORTED */
> +#define MAX_NUM_CODECS 32
> +#define MAX_NUM_CODEC_DESCRIPTORS 32
> +#define MAX_NUM_BITRATES 32
> +
> +/* Codecs are listed linearly to allow for extensibility */
> +#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
> +#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
> +#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
> +#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
> +#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
> +#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
> +#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
> +#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
> +#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
> +#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
> +#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
> +#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
> +#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
> +
> +/*
> + * Profile and modes are listed with bit masks. This allows for a
> + * more compact representation of fields that will not evolve
> + * (in contrast to the list of codecs)
> + */
> +
> +#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
> +
> +/* MP3 modes are only useful for encoders */
> +#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
> +#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
> +#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
> +#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
> +
> +#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
> +
> +/* AMR modes are only useful for encoders */
> +#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
> +
> +#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
> +#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
> +#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
> +#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
> +#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
> +#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
> +#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
> +
> +#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
> +
> +/* AMRWB modes are only useful for encoders */
> +#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
> +
> +#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
> +
> +#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
> +
> +/* AAC modes are required for encoders and decoders */
> +#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
> +#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
> +#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
> +#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
> +#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
> +#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
> +#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
> +
> +/* AAC formats are required for encoders and decoders */
> +#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
> +#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
> +#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
> +#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
> +#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
> +#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
> +#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
> +
> +#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
> +#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
> +#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
> +#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
> +
> +#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
> +#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
> +#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
> +#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
> +#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
> +
> +#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
> +/*
> + * Some implementations strip the ASF header and only send ASF packets
> + * to the DSP
> + */
> +#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
> +
> +#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
> +
> +#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
> +
> +#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
> +
> +#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
> +
> +#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
> +
> +/*
> + * Define quality levels for FLAC encoders, from LEVEL0 (fast)
> + * to LEVEL8 (best)
> + */
> +#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
> +#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
> +#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
> +#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
> +#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
> +#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
> +
> +#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
> +#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
> +
> +/* IEC61937 payloads without CUVP and preambles */
> +#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
> +/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
> +#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
> +
> +/*
> + * IEC modes are mandatory for decoders. Format autodetection
> + * will only happen on the DSP side with mode 0. The PCM mode should
> + * not be used, the PCM codec should be used instead.
> + */
> +#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
> +#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
> +#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
> +#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
> +#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
> +#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
> +#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
> +#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
> +#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
> +#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
> +#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
> +#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
> +#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
> +#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
> +#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
> +#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
> +#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
> +
> +#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
> +
> +#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
> +#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
> +
> +#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
> +
> +#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
> +#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
> +
> +/* <FIXME: multichannel encoders aren't supported for now. Would need
> +   an additional definition of channel arrangement> */
> +
> +/* VBR/CBR definitions */
> +#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
> +#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
> +
> +/* Encoder options */
> +
> +struct snd_enc_wma {
> +	__u32 super_block_align; /* WMA Type-specific data */
> +};
> +
> +
> +/**
> + * struct snd_enc_vorbis
> + * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
> + * In the default mode of operation, the quality level is 3.
> + * Normal quality range is 0 - 10.
> + * @managed: Boolean. Set  bitrate  management  mode. This turns off the
> + * normal VBR encoding, but allows hard or soft bitrate constraints to be
> + * enforced by the encoder. This mode can be slower, and may also be
> + * lower quality. It is primarily useful for streaming.
> + * @max_bit_rate: Enabled only if managed is TRUE
> + * @min_bit_rate: Enabled only if managed is TRUE
> + * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
> + * non-stereo streams). Useful for lower-bitrate encoding.
> + *
> + * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
> + * properties
> + *
> + * For best quality users should specify VBR mode and set quality levels.
> + */
> +
> +struct snd_enc_vorbis {
> +	int quality;
> +	__u32 managed;
> +	__u32 max_bit_rate;
> +	__u32 min_bit_rate;
> +	__u32 downmix;
> +};
> +
> +
> +/**
> + * struct snd_enc_real
> + * @quant_bits: number of coupling quantization bits in the stream
> + * @start_region: coupling start region in the stream
> + * @num_regions: number of regions value
> + *
> + * These options were extracted from the OpenMAX IL spec
> + */
> +
> +struct snd_enc_real {
> +	__u32 quant_bits;
> +	__u32 start_region;
> +	__u32 num_regions;
> +};
> +
> +/**
> + * struct snd_enc_flac
> + * @num: serial number, valid only for OGG formats
> + *	needs to be set by application
> + * @gain: Add replay gain tags
> + *
> + * These options were extracted from the FLAC online documentation
> + * at http://flac.sourceforge.net/documentation_tools_flac.html
> + *
> + * To make the API simpler, it is assumed that the user will select quality
> + * profiles. Additional options that affect encoding quality and speed can
> + * be added at a later stage if needed.
> + *
> + * By default the Subset format is used by encoders.
> + *
> + * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
> + * not supported in this API.
> + */
> +
> +struct snd_enc_flac {
> +	__u32 num;
> +	__u32 gain;
> +};
> +
> +struct snd_enc_generic {
> +	__u32 bw;	/* encoder bandwidth */
> +	int reserved[15];
> +};
> +
> +union snd_codec_options {
> +	struct snd_enc_wma wma;
> +	struct snd_enc_vorbis vorbis;
> +	struct snd_enc_real real;
> +	struct snd_enc_flac flac;
> +	struct snd_enc_generic generic;
> +};
> +
> +/** struct snd_codec_desc - description of codec capabilities
> + * @max_ch: Maximum number of audio channels
> + * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
> + * @bit_rate: Indexed array containing supported bit rates
> + * @num_bitrates: Number of valid values in bit_rate array
> + * @rate_control: value is specified by SND_RATECONTROLMODE defines.
> + * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
> + * @modes: Supported modes. See SND_AUDIOMODE defines
> + * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
> + * @reserved: reserved for future use
> + *
> + * This structure provides a scalar value for profiles, modes and stream
> + * format fields.
> + * If an implementation supports multiple combinations, they will be listed as
> + * codecs with different descriptors, for example there would be 2 descriptors
> + * for AAC-RAW and AAC-ADTS.
> + * This entails some redundancy but makes it easier to avoid invalid
> + * configurations.
> + *
> + */
> +
> +struct snd_codec_desc {
> +	__u32 max_ch;
> +	__u32 sample_rates;
> +	__u32 bit_rate[MAX_NUM_BITRATES];
> +	__u32 num_bitrates;
> +	__u32 rate_control;
> +	__u32 profiles;
> +	__u32 modes;
> +	__u32 formats;
> +	__u32 reserved[16];
> +};
> +
> +/** struct snd_codec
> + * @id: Identifies the supported audio encoder/decoder.
> + *		See SND_AUDIOCODEC macros.
> + * @ch_in: Number of input audio channels
> + * @ch_out: Number of output channels. In case of contradiction between
> + *		this field and the channelMode field, the channelMode field
> + *		overrides.
> + * @sample_rate: Audio sample rate of input data
> + * @bit_rate: Bitrate of encoded data. May be ignored by decoders
> + * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
> + *               Encoders may rely on profiles for quality levels.
> + *		 May be ignored by decoders.
> + * @profile: Mandatory for encoders, can be mandatory for specific
> + *		decoders as well. See SND_AUDIOPROFILE defines.
> + * @level: Supported level (Only used by WMA at the moment)
> + * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
> + * @format: Format of encoded bistream. Mandatory when defined.
> + *		See SND_AUDIOSTREAMFORMAT defines.
> + * @align: Block alignment in bytes of an audio sample.
> + *		Only required for PCM or IEC formats.
> + * @options: encoder-specific settings
> + * @reserved: reserved for future use
> + */
> +
> +struct snd_codec {
> +	__u32 id;
> +	__u32 ch_in;
> +	__u32 ch_out;
> +	__u32 sample_rate;
> +	__u32 bit_rate;
> +	__u32 rate_control;
> +	__u32 profile;
> +	__u32 level;
> +	__u32 ch_mode;
> +	__u32 format;
> +	__u32 align;
> +	union snd_codec_options options;
> +	__u32 reserved[3];
> +};
> +
> +#endif
> -- 
> 1.7.0.4
> 
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> 

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-13  9:02     ` [PATCH v4 5/6] core: add support for compress_offload Vinod Koul
  2011-12-13 12:48       ` Nallasellan, Singaravelan
@ 2011-12-22  7:55       ` Takashi Iwai
  2011-12-22  8:19         ` Vinod Koul
  1 sibling, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-12-22  7:55 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, broonie, lrg, Pierre-Louis Bossart

At Tue, 13 Dec 2011 14:32:59 +0530,
Vinod Koul wrote:
> +static int snd_compr_free(struct inode *inode, struct file *f)
> +{
> +	struct snd_compr_file *data = f->private_data;
> +	data->stream.ops->free(&data->stream);

Better to add a NULL check.

> +static int
> +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
> +{
> +	struct snd_compr_avail ioctl_avail;
> +	size_t avail;
> +
> +	avail = snd_compr_calc_avail(stream, &ioctl_avail);
> +	ioctl_avail.avail = avail;
> +
> +	if (copy_to_user((unsigned long __user *)arg,
> +				&ioctl_avail, sizeof(ioctl_avail)))

Use a correct cast.

> +static ssize_t snd_compr_write(struct file *f, const char __user *buf,
> +		size_t count, loff_t *offset)
> +{
> +	struct snd_compr_file *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +	size_t avail;
> +	int retval;
> +
> +	BUG_ON(!data);

Avoid BUG_ON().  This is only for really critical bugs for which you
must stop the whole machine.
(BTW, snd_BUG_ON() is expanded to WARN_ON(), so it's not equivalent
 with BUG_ON().)

> +	stream = &data->stream;
> +	mutex_lock(&stream->device->lock);
> +	/* write is allowed when stream is running or has been steup */
> +	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
> +			stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
> +		mutex_unlock(&stream->device->lock);
> +		return -EPERM;

Hm, I'm not sure whether EPERM is best here.
In PCM, we used to use EBADFD.

> +static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
> +{
> +	struct snd_compr_file *data = f->private_data;
> +	struct snd_compr_stream *stream;
> +	size_t avail;
> +	int retval = 0;
> +
> +	BUG_ON(!data);

Avoid BUG_ON().

> +	stream = &data->stream;
> +
> +	mutex_lock(&stream->device->lock);
> +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
> +		retval = -ENXIO;
> +		goto out;
> +	}

Whether to allow poll() at the state of PREPARE is an open question.
You can think of an operation in a passive way via poll, such as,

   open();
   prepare();
   while (poll())
      write();

So, poll() could be useful even at PREPARE.


Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 2/6] core: add support for compressed devices
  2011-12-22  7:34       ` Takashi Iwai
@ 2011-12-22  8:15         ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-22  8:15 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: lrg, alsa-devel, broonie, Pierre-Louis Bossart, Omair Mohammed Abdullah

On Thu, 2011-12-22 at 08:34 +0100, Takashi Iwai wrote:
> At Tue, 13 Dec 2011 14:32:56 +0530,
> Vinod Koul wrote:
> > 
> > From: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
> > 
> > Use the two minor numbers 2 and 3 for audio compressed offload devices.
> > Also add support for these devices in core
> > 
> > Signed-off-by: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
> > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> > Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > ---
> >  include/sound/core.h   |    1 +
> >  include/sound/minors.h |    7 ++++++-
> >  sound/core/sound.c     |    6 ++++++
> >  3 files changed, 13 insertions(+), 1 deletions(-)
> > 
> > diff --git a/include/sound/core.h b/include/sound/core.h
> > index 3be5ab7..5ab255f 100644
> > --- a/include/sound/core.h
> > +++ b/include/sound/core.h
> > @@ -62,6 +62,7 @@ typedef int __bitwise snd_device_type_t;
> >  #define	SNDRV_DEV_BUS		((__force snd_device_type_t) 0x1007)
> >  #define	SNDRV_DEV_CODEC		((__force snd_device_type_t) 0x1008)
> >  #define	SNDRV_DEV_JACK          ((__force snd_device_type_t) 0x1009)
> > +#define	SNDRV_DEV_COMPRESS	((__force snd_device_type_t) 0x100A)
> >  #define	SNDRV_DEV_LOWLEVEL	((__force snd_device_type_t) 0x2000)
> >  
> >  typedef int __bitwise snd_device_state_t;
> > diff --git a/include/sound/minors.h b/include/sound/minors.h
> > index 8f76420..faaeb64 100644
> > --- a/include/sound/minors.h
> > +++ b/include/sound/minors.h
> > @@ -35,7 +35,8 @@
> >  #define SNDRV_MINOR_TIMER		33	/* SNDRV_MINOR_GLOBAL + 1 * 32 */
> >  
> >  #ifndef CONFIG_SND_DYNAMIC_MINORS
> > -						/* 2 - 3 (reserved) */
> > +#define SNDRV_MINOR_COMPR_PLAYBACK	2
> > +#define SNDRV_MINOR_COMPR_CAPTURE	3
> 
> If you'd share both playback and capture to a single device (as you
> already did in patch 5/6), no need to provide distinct numbers here.
> This would be simply
> 
> #define SNDRV_MINOR_COMPR		2
> 
> and define the single SNDRV_DEVICE_TYPE_COMPR.
> Then you'll have to up to two devices for the static minors and more
> for dynamic minors.  So, the below would be:
Oops, I thought i had fixed it up as well, thanks below is right :)
> 
> > diff --git a/sound/core/sound.c b/sound/core/sound.c
> > index 828af35..2b680dd 100644
> > --- a/sound/core/sound.c
> > +++ b/sound/core/sound.c
> > @@ -233,6 +233,12 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
> >  			return -EINVAL;
> >  		minor = SNDRV_MINOR(card->number, type + dev);
> >  		break;
> > +	case SNDRV_DEVICE_TYPE_COMPR_PLAYBACK:
> > +	case SNDRV_DEVICE_TYPE_COMPR_CAPTURE:
> > +		if (snd_BUG_ON(!card))
> > +			return -EINVAL;
> > +		minor = SNDRV_MINOR(card->number, type);
> > +		break;
> 
> Instead of this, just add case SNDRV_DEVICE_TYPE_COMPR in the cases of
> other types like PCM and RAWMIDI, i.e.
right
> 
> > +		minor = SNDRV_MINOR(card->number, type + dev);
> 
> 
> Takashi


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 3/6] core: add compress parameter definations
  2011-12-22  7:35       ` Takashi Iwai
@ 2011-12-22  8:16         ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-22  8:16 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Thu, 2011-12-22 at 08:35 +0100, Takashi Iwai wrote:
> At Tue, 13 Dec 2011 14:32:57 +0530,
> Vinod Koul wrote:
> > 
> > The patch adds the various definations used to define the encoder
> > and decoder parameters
> > 
> > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > Signed-off-by: Pierre-Louis Bossart
> <pierre-louis.bossart@linux.intel.com>
> > Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
> > ---
> >  include/sound/snd_compress_params.h |  395
> +++++++++++++++++++++++++++++++++++
> 
> I wonder why snd_ prefix is added to this header file.
> It's no big issue, but it looks redundant :)
> 
Well that was first file to be coded and somehow snd_ was added to this
and not to others.
Will drop it :)

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-22  7:55       ` Takashi Iwai
@ 2011-12-22  8:19         ` Vinod Koul
  2011-12-22  8:27           ` Takashi Iwai
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-22  8:19 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Thu, 2011-12-22 at 08:55 +0100, Takashi Iwai wrote:
> At Tue, 13 Dec 2011 14:32:59 +0530,
> Vinod Koul wrote:
> > +static int snd_compr_free(struct inode *inode, struct file *f)
> > +{
> > +	struct snd_compr_file *data = f->private_data;
> > +	data->stream.ops->free(&data->stream);
> 
> Better to add a NULL check.
Not really. open, free and set_params callbacks are mandatory and there
is BUG_ON for them so these wont be checked here
> 
> > +static int
> > +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
> > +{
> > +	struct snd_compr_avail ioctl_avail;
> > +	size_t avail;
> > +
> > +	avail = snd_compr_calc_avail(stream, &ioctl_avail);
> > +	ioctl_avail.avail = avail;
> > +
> > +	if (copy_to_user((unsigned long __user *)arg,
> > +				&ioctl_avail, sizeof(ioctl_avail)))
> 
> Use a correct cast.
> 
> > +static ssize_t snd_compr_write(struct file *f, const char __user *buf,
> > +		size_t count, loff_t *offset)
> > +{
> > +	struct snd_compr_file *data = f->private_data;
> > +	struct snd_compr_stream *stream;
> > +	size_t avail;
> > +	int retval;
> > +
> > +	BUG_ON(!data);
> 
> Avoid BUG_ON().  This is only for really critical bugs for which you
> must stop the whole machine.
> (BTW, snd_BUG_ON() is expanded to WARN_ON(), so it's not equivalent
>  with BUG_ON().)
Well write can be called only after open. And open should have set the
data. If data is null that means something really horrible happened (not
at all possible unless corruption) so BUG_ON :)
> 
> > +	stream = &data->stream;
> > +	mutex_lock(&stream->device->lock);
> > +	/* write is allowed when stream is running or has been steup */
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
> > +			stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
> > +		mutex_unlock(&stream->device->lock);
> > +		return -EPERM;
> 
> Hm, I'm not sure whether EPERM is best here.
> In PCM, we used to use EBADFD.
No issues
> 
> > +static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
> > +{
> > +	struct snd_compr_file *data = f->private_data;
> > +	struct snd_compr_stream *stream;
> > +	size_t avail;
> > +	int retval = 0;
> > +
> > +	BUG_ON(!data);
> 
> Avoid BUG_ON().
Same point as in write. 
> 
> > +	stream = &data->stream;
> > +
> > +	mutex_lock(&stream->device->lock);
> > +	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
> > +		retval = -ENXIO;
> > +		goto out;
> > +	}
> 
> Whether to allow poll() at the state of PREPARE is an open question.
> You can think of an operation in a passive way via poll, such as,
> 
>    open();
>    prepare();
>    while (poll())
>       write();
> 
> So, poll() could be useful even at PREPARE.
Okay.


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-22  8:19         ` Vinod Koul
@ 2011-12-22  8:27           ` Takashi Iwai
  2011-12-22  8:31             ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-12-22  8:27 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, broonie, lrg, Pierre-Louis Bossart

At Thu, 22 Dec 2011 13:49:50 +0530,
Vinod Koul wrote:
> 
> On Thu, 2011-12-22 at 08:55 +0100, Takashi Iwai wrote:
> > At Tue, 13 Dec 2011 14:32:59 +0530,
> > Vinod Koul wrote:
> > > +static int snd_compr_free(struct inode *inode, struct file *f)
> > > +{
> > > +	struct snd_compr_file *data = f->private_data;
> > > +	data->stream.ops->free(&data->stream);
> > 
> > Better to add a NULL check.
> Not really. open, free and set_params callbacks are mandatory and there
> is BUG_ON for them so these wont be checked here

OK, but don't use BUG_ON().


> > > +static int
> > > +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
> > > +{
> > > +	struct snd_compr_avail ioctl_avail;
> > > +	size_t avail;
> > > +
> > > +	avail = snd_compr_calc_avail(stream, &ioctl_avail);
> > > +	ioctl_avail.avail = avail;
> > > +
> > > +	if (copy_to_user((unsigned long __user *)arg,
> > > +				&ioctl_avail, sizeof(ioctl_avail)))
> > 
> > Use a correct cast.
> > 
> > > +static ssize_t snd_compr_write(struct file *f, const char __user *buf,
> > > +		size_t count, loff_t *offset)
> > > +{
> > > +	struct snd_compr_file *data = f->private_data;
> > > +	struct snd_compr_stream *stream;
> > > +	size_t avail;
> > > +	int retval;
> > > +
> > > +	BUG_ON(!data);
> > 
> > Avoid BUG_ON().  This is only for really critical bugs for which you
> > must stop the whole machine.
> > (BTW, snd_BUG_ON() is expanded to WARN_ON(), so it's not equivalent
> >  with BUG_ON().)
> Well write can be called only after open. And open should have set the
> data. If data is null that means something really horrible happened (not
> at all possible unless corruption) so BUG_ON :)

Nah, do you really want to stop the machine here completely?
It means that you can't debug it any more.  If it's just a
NULL-dereference, even a normal Oops would be better than this
BUG_ON().

Again, BUG_ON() is only for the critical bug that blocks any further
operations of the whole machine, e.g. when there is a clear risk of
immediate data corruption, etc.  A bug like this in a driver code
can't belong to such category.


Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-22  8:27           ` Takashi Iwai
@ 2011-12-22  8:31             ` Vinod Koul
  2011-12-22  8:44               ` Takashi Iwai
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-22  8:31 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Thu, 2011-12-22 at 09:27 +0100, Takashi Iwai wrote:
> At Thu, 22 Dec 2011 13:49:50 +0530,
> Vinod Koul wrote:
> > 
> > On Thu, 2011-12-22 at 08:55 +0100, Takashi Iwai wrote:
> > > At Tue, 13 Dec 2011 14:32:59 +0530,
> > > Vinod Koul wrote:
> > > > +static int snd_compr_free(struct inode *inode, struct file *f)
> > > > +{
> > > > +	struct snd_compr_file *data = f->private_data;
> > > > +	data->stream.ops->free(&data->stream);
> > > 
> > > Better to add a NULL check.
> > Not really. open, free and set_params callbacks are mandatory and there
> > is BUG_ON for them so these wont be checked here
> 
> OK, but don't use BUG_ON().
> 
> 
> > > > +static int
> > > > +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
> > > > +{
> > > > +	struct snd_compr_avail ioctl_avail;
> > > > +	size_t avail;
> > > > +
> > > > +	avail = snd_compr_calc_avail(stream, &ioctl_avail);
> > > > +	ioctl_avail.avail = avail;
> > > > +
> > > > +	if (copy_to_user((unsigned long __user *)arg,
> > > > +				&ioctl_avail, sizeof(ioctl_avail)))
> > > 
> > > Use a correct cast.
> > > 
> > > > +static ssize_t snd_compr_write(struct file *f, const char __user *buf,
> > > > +		size_t count, loff_t *offset)
> > > > +{
> > > > +	struct snd_compr_file *data = f->private_data;
> > > > +	struct snd_compr_stream *stream;
> > > > +	size_t avail;
> > > > +	int retval;
> > > > +
> > > > +	BUG_ON(!data);
> > > 
> > > Avoid BUG_ON().  This is only for really critical bugs for which you
> > > must stop the whole machine.
> > > (BTW, snd_BUG_ON() is expanded to WARN_ON(), so it's not equivalent
> > >  with BUG_ON().)
> > Well write can be called only after open. And open should have set the
> > data. If data is null that means something really horrible happened (not
> > at all possible unless corruption) so BUG_ON :)
> 
> Nah, do you really want to stop the machine here completely?
> It means that you can't debug it any more.  If it's just a
> NULL-dereference, even a normal Oops would be better than this
> BUG_ON().
> 
> Again, BUG_ON() is only for the critical bug that blocks any further
> operations of the whole machine, e.g. when there is a clear risk of
> immediate data corruption, etc.  A bug like this in a driver code
> can't belong to such category.
Got the point :) Will move probe BUG_ON to return error

Only question is in these scenarios this is core corruption so what
would be the apt error code to use?


-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-22  8:31             ` Vinod Koul
@ 2011-12-22  8:44               ` Takashi Iwai
  2011-12-22  8:48                 ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-12-22  8:44 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, broonie, lrg, Pierre-Louis Bossart

At Thu, 22 Dec 2011 14:01:46 +0530,
Vinod Koul wrote:
> 
> On Thu, 2011-12-22 at 09:27 +0100, Takashi Iwai wrote:
> > At Thu, 22 Dec 2011 13:49:50 +0530,
> > Vinod Koul wrote:
> > > 
> > > On Thu, 2011-12-22 at 08:55 +0100, Takashi Iwai wrote:
> > > > At Tue, 13 Dec 2011 14:32:59 +0530,
> > > > Vinod Koul wrote:
> > > > > +static int snd_compr_free(struct inode *inode, struct file *f)
> > > > > +{
> > > > > +	struct snd_compr_file *data = f->private_data;
> > > > > +	data->stream.ops->free(&data->stream);
> > > > 
> > > > Better to add a NULL check.
> > > Not really. open, free and set_params callbacks are mandatory and there
> > > is BUG_ON for them so these wont be checked here
> > 
> > OK, but don't use BUG_ON().
> > 
> > 
> > > > > +static int
> > > > > +snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
> > > > > +{
> > > > > +	struct snd_compr_avail ioctl_avail;
> > > > > +	size_t avail;
> > > > > +
> > > > > +	avail = snd_compr_calc_avail(stream, &ioctl_avail);
> > > > > +	ioctl_avail.avail = avail;
> > > > > +
> > > > > +	if (copy_to_user((unsigned long __user *)arg,
> > > > > +				&ioctl_avail, sizeof(ioctl_avail)))
> > > > 
> > > > Use a correct cast.
> > > > 
> > > > > +static ssize_t snd_compr_write(struct file *f, const char __user *buf,
> > > > > +		size_t count, loff_t *offset)
> > > > > +{
> > > > > +	struct snd_compr_file *data = f->private_data;
> > > > > +	struct snd_compr_stream *stream;
> > > > > +	size_t avail;
> > > > > +	int retval;
> > > > > +
> > > > > +	BUG_ON(!data);
> > > > 
> > > > Avoid BUG_ON().  This is only for really critical bugs for which you
> > > > must stop the whole machine.
> > > > (BTW, snd_BUG_ON() is expanded to WARN_ON(), so it's not equivalent
> > > >  with BUG_ON().)
> > > Well write can be called only after open. And open should have set the
> > > data. If data is null that means something really horrible happened (not
> > > at all possible unless corruption) so BUG_ON :)
> > 
> > Nah, do you really want to stop the machine here completely?
> > It means that you can't debug it any more.  If it's just a
> > NULL-dereference, even a normal Oops would be better than this
> > BUG_ON().
> > 
> > Again, BUG_ON() is only for the critical bug that blocks any further
> > operations of the whole machine, e.g. when there is a clear risk of
> > immediate data corruption, etc.  A bug like this in a driver code
> > can't belong to such category.
> Got the point :) Will move probe BUG_ON to return error

You can use WARN() or snd_BUG_ON().

> Only question is in these scenarios this is core corruption so what
> would be the apt error code to use?

Well, there is no standard definition.  Just use a sensible errno that
will abort the user-space appropriately (i.e. not like EPIPE).  Even
-EFAULT would be OK, I think.


Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-22  8:44               ` Takashi Iwai
@ 2011-12-22  8:48                 ` Vinod Koul
  2011-12-22  8:51                   ` Takashi Iwai
  0 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-22  8:48 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, broonie, lrg, Pierre-Louis Bossart

On Thu, 2011-12-22 at 09:44 +0100, Takashi Iwai wrote:
> 
> You can use WARN() or snd_BUG_ON().
But WARN or snd_BUG_ON will continue execution and....
So better log it and return error, right?
> 
> > Only question is in these scenarios this is core corruption so what
> > would be the apt error code to use?
> 
> Well, there is no standard definition.  Just use a sensible errno that
> will abort the user-space appropriately (i.e. not like EPIPE).  Even
> -EFAULT would be OK, I think.
I like EFAULT

-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v4 5/6] core: add support for compress_offload
  2011-12-22  8:48                 ` Vinod Koul
@ 2011-12-22  8:51                   ` Takashi Iwai
  0 siblings, 0 replies; 133+ messages in thread
From: Takashi Iwai @ 2011-12-22  8:51 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, broonie, lrg, Pierre-Louis Bossart

At Thu, 22 Dec 2011 14:18:52 +0530,
Vinod Koul wrote:
> 
> On Thu, 2011-12-22 at 09:44 +0100, Takashi Iwai wrote:
> > 
> > You can use WARN() or snd_BUG_ON().
> But WARN or snd_BUG_ON will continue execution and....
> So better log it and return error, right?

Yes, write like
	if (snd_BUG_ON(!foo))
		return -ESOMETHING;


Takashi

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [PATCH v5 0/6] core: add compress data API to ALSA kernel
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (8 preceding siblings ...)
  2011-12-13  9:03     ` [PATCH v4 6/6] core: add makefile and kconfig file for compress Vinod Koul
@ 2011-12-23  5:06     ` Vinod Koul
  2011-12-23  9:37       ` Takashi Iwai
  2011-12-23  5:06     ` [PATCH v5 1/6] compress offload API documentation Vinod Koul
                       ` (5 subsequent siblings)
  15 siblings, 1 reply; 133+ messages in thread
From: Vinod Koul @ 2011-12-23  5:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie

As agreed during the ASoC workshop in May 2011, this set of patches are a
proposal from Intel to add a new compressed data interface to ALSA. This
proposal builds on the existing Intel solution and the experience gathered over
two years with Meego and Android solutions. This proposal is no longer
Intel-specific and was generalized with the addition of a basic core;
codec-related definitions are based on the vendor-neutral OpenMAX AL standard. 

These patches are also available in git tree:
git://git.infradead.org/users/vkoul/snd-compress.git v5_patches

--
Changes in v5:
 fixed the device minor number and definations
 removed all BUG_ONs
 renamed params file to compress-params.h and Doc file to compress_offlaod.txt
 added notes on stream states used
 changes all user structs to use fixed size variables

Changes in v4:
 Rebased on 3.2-rc4, fixed module.h compilation
 Added sched.h header in compress_driver.h
 Fixed few warnings while at it

Changes in v3:
 Fixed the device registration for compressed devices as discussed
 moved card creation to lower level drivers
 Added new api for device node creation
 changes fragment/frame callbacks to single inlined callback

Changes in v2:
 Fixed the comments recieved in v2
 Fixed the comments recieved during LPC discussions
 add support for alsa device registeration
 fix the bugs found in testing
--

Omair Mohammed Abdullah (1):
  core: add support for compressed devices

Pierre-Louis Bossart (1):
  compress offload API documentation

Vinod Koul (4):
  core: add compress parameter definations
  core: add API header and driver header files
  core: add support for compress_offload
  core: add makefile and kconfig file for compress

 Documentation/sound/alsa/compress_offload.txt |  188 ++++++
 include/sound/compress_driver.h               |  167 ++++++
 include/sound/compress_offload.h              |  161 ++++++
 include/sound/compress_params.h               |  397 +++++++++++++
 include/sound/core.h                          |    1 +
 include/sound/minors.h                        |    4 +-
 sound/core/Kconfig                            |   10 +
 sound/core/Makefile                           |    4 +
 sound/core/compress_offload.c                 |  765 +++++++++++++++++++++++++
 sound/core/sound.c                            |    1 +
 10 files changed, 1697 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/sound/alsa/compress_offload.txt
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h
 create mode 100644 include/sound/compress_params.h
 create mode 100644 sound/core/compress_offload.c

^ permalink raw reply	[flat|nested] 133+ messages in thread

* [PATCH v5 1/6] compress offload API documentation
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (9 preceding siblings ...)
  2011-12-23  5:06     ` [PATCH v5 0/6] core: add compress data API to ALSA kernel Vinod Koul
@ 2011-12-23  5:06     ` Vinod Koul
  2011-12-23  5:06     ` [PATCH v5 2/6] core: add support for compressed devices Vinod Koul
                       ` (4 subsequent siblings)
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-23  5:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, Pierre-Louis Bossart

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

The patch adds the documentation file explaining the API

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
---
 Documentation/sound/alsa/compress_offload.txt |  188 +++++++++++++++++++++++++
 1 files changed, 188 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/sound/alsa/compress_offload.txt

diff --git a/Documentation/sound/alsa/compress_offload.txt b/Documentation/sound/alsa/compress_offload.txt
new file mode 100644
index 0000000..c83a835
--- /dev/null
+++ b/Documentation/sound/alsa/compress_offload.txt
@@ -0,0 +1,188 @@
+		compress_offload.txt
+		=====================
+	Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+		Vinod Koul <vinod.koul@linux.intel.com>
+
+Overview
+
+Since its early days, the ALSA API was defined with PCM support or
+constant bitrates payloads such as IEC61937 in mind. Arguments and
+returned values in frames are the norm, making it a challenge to
+extend the existing API to compressed data streams.
+
+In recent years, audio digital signal processors (DSP) were integrated
+in system-on-chip designs, and DSPs are also integrated in audio
+codecs. Processing compressed data on such DSPs results in a dramatic
+reduction of power consumption compared to host-based
+processing. Support for such hardware has not been very good in Linux,
+mostly because of a lack of a generic API available in the mainline
+kernel.
+
+Rather than requiring a compability break with an API change of the
+ALSA PCM interface, a new 'Compressed Data' API is introduced to
+provide a control and data-streaming interface for audio DSPs.
+
+The design of this API was inspired by the 2-year experience with the
+Intel Moorestown SOC, with many corrections required to upstream the
+API in the mainline kernel instead of the staging tree and make it
+usable by others.
+
+Requirements
+
+The main requirements are:
+
+- separation between byte counts and time. Compressed formats may have
+  a header per file, per frame, or no header at all. The payload size
+  may vary from frame-to-frame. As a result, it is not possible to
+  estimate reliably the duration of audio buffers when handling
+  compressed data. Dedicated mechanisms are required to allow for
+  reliable audio-video synchronization, which requires precise
+  reporting of the number of samples rendered at any given time.
+
+- Handling of multiple formats. PCM data only requires a specification
+  of the sampling rate, number of channels and bits per sample. In
+  contrast, compressed data comes in a variety of formats. Audio DSPs
+  may also provide support for a limited number of audio encoders and
+  decoders embedded in firmware, or may support more choices through
+  dynamic download of libraries.
+
+- Focus on main formats. This API provides support for the most
+  popular formats used for audio and video capture and playback. It is
+  likely that as audio compression technology advances, new formats
+  will be added.
+
+- Handling of multiple configurations. Even for a given format like
+  AAC, some implementations may support AAC multichannel but HE-AAC
+  stereo. Likewise WMA10 level M3 may require too much memory and cpu
+  cycles. The new API needs to provide a generic way of listing these
+  formats.
+
+- Rendering/Grabbing only. This API does not provide any means of
+  hardware acceleration, where PCM samples are provided back to
+  user-space for additional processing. This API focuses instead on
+  streaming compressed data to a DSP, with the assumption that the
+  decoded samples are routed to a physical output or logical back-end.
+
+ - Complexity hiding. Existing user-space multimedia frameworks all
+  have existing enums/structures for each compressed format. This new
+  API assumes the existence of a platform-specific compatibility layer
+  to expose, translate and make use of the capabilities of the audio
+  DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
+  applications are not supposed to make use of this API.
+
+
+Design
+
+The new API shares a number of concepts with with the PCM API for flow
+control. Start, pause, resume, drain and stop commands have the same
+semantics no matter what the content is.
+
+The concept of memory ring buffer divided in a set of fragments is
+borrowed from the ALSA PCM API. However, only sizes in bytes can be
+specified.
+
+Seeks/trick modes are assumed to be handled by the host.
+
+The notion of rewinds/forwards is not supported. Data committed to the
+ring buffer cannot be invalidated, except when dropping all buffers.
+
+The Compressed Data API does not make any assumptions on how the data
+is transmitted to the audio DSP. DMA transfers from main memory to an
+embedded audio cluster or to a SPI interface for external DSPs are
+possible. As in the ALSA PCM case, a core set of routines is exposed;
+each driver implementer will have to write support for a set of
+mandatory routines and possibly make use of optional ones.
+
+The main additions are
+
+- get_caps
+This routine returns the list of audio formats supported. Querying the
+codecs on a capture stream will return encoders, decoders will be
+listed for playback streams.
+
+- get_codec_caps For each codec, this routine returns a list of
+capabilities. The intent is to make sure all the capabilities
+correspond to valid settings, and to minimize the risks of
+configuration failures. For example, for a complex codec such as AAC,
+the number of channels supported may depend on a specific profile. If
+the capabilities were exposed with a single descriptor, it may happen
+that a specific combination of profiles/channels/formats may not be
+supported. Likewise, embedded DSPs have limited memory and cpu cycles,
+it is likely that some implementations make the list of capabilities
+dynamic and dependent on existing workloads. In addition to codec
+settings, this routine returns the minimum buffer size handled by the
+implementation. This information can be a function of the DMA buffer
+sizes, the number of bytes required to synchronize, etc, and can be
+used by userspace to define how much needs to be written in the ring
+buffer before playback can start.
+
+- set_params
+This routine sets the configuration chosen for a specific codec. The
+most important field in the parameters is the codec type; in most
+cases decoders will ignore other fields, while encoders will strictly
+comply to the settings
+
+- get_params
+This routines returns the actual settings used by the DSP. Changes to
+the settings should remain the exception.
+
+- get_timestamp
+The timestamp becomes a multiple field structure. It lists the number
+of bytes transferred, the number of samples processed and the number
+of samples rendered/grabbed. All these values can be used to determine
+the avarage bitrate, figure out if the ring buffer needs to be
+refilled or the delay due to decoding/encoding/io on the DSP.
+
+Note that the list of codecs/profiles/modes was derived from the
+OpenMAX AL specification instead of reinventing the wheel.
+Modifications include:
+- Addition of FLAC and IEC formats
+- Merge of encoder/decoder capabilities
+- Profiles/modes listed as bitmasks to make descriptors more compact
+- Addition of set_params for decoders (missing in OpenMAX AL)
+- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
+- Addition of format information for WMA
+- Addition of encoding options when required (derived from OpenMAX IL)
+- Addition of rateControlSupported (missing in OpenMAX AL)
+
+Not supported:
+
+- Support for VoIP/circuit-switched calls is not the target of this
+  API. Support for dynamic bit-rate changes would require a tight
+  coupling between the DSP and the host stack, limiting power savings.
+
+- Packet-loss concealment is not supported. This would require an
+  additional interface to let the decoder synthesize data when frames
+  are lost during transmission. This may be added in the future.
+
+- Volume control/routing is not handled by this API. Devices exposing a
+  compressed data interface will be considered as regular ALSA devices;
+  volume changes and routing information will be provided with regular
+  ALSA kcontrols.
+
+- Embedded audio effects. Such effects should be enabled in the same
+  manner, no matter if the input was PCM or compressed.
+
+- multichannel IEC encoding. Unclear if this is required.
+
+- Encoding/decoding acceleration is not supported as mentioned
+  above. It is possible to route the output of a decoder to a capture
+  stream, or even implement transcoding capabilities. This routing
+  would be enabled with ALSA kcontrols.
+
+- Audio policy/resource management. This API does not provide any
+  hooks to query the utilization of the audio DSP, nor any premption
+  mechanisms.
+
+- No notion of underun/overrun. Since the bytes written are compressed
+  in nature and data written/read doesn't translate directly to
+  rendered output in time, this does not deal with underrun/overun and
+  maybe dealt in user-library
+
+Credits:
+- Mark Brown and Liam Girdwood for discussions on the need for this API
+- Harsha Priya for her work on intel_sst compressed API
+- Rakesh Ughreja for valuable feedback
+- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
+  demonstrating and quantifying the benefits of audio offload on a
+  real platform.
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v5 2/6] core: add support for compressed devices
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (10 preceding siblings ...)
  2011-12-23  5:06     ` [PATCH v5 1/6] compress offload API documentation Vinod Koul
@ 2011-12-23  5:06     ` Vinod Koul
  2011-12-23  5:06     ` [PATCH v5 3/6] core: add compress parameter definations Vinod Koul
                       ` (3 subsequent siblings)
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-23  5:06 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Vinod Koul, broonie, Pierre-Louis Bossart,
	Omair Mohammed Abdullah

From: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>

Use the minor numbers 2 and 3 for audio compressed offload devices.
Also add support for these devices in core

Signed-off-by: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 include/sound/core.h   |    1 +
 include/sound/minors.h |    4 +++-
 sound/core/sound.c     |    1 +
 3 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/include/sound/core.h b/include/sound/core.h
index 3be5ab7..5ab255f 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -62,6 +62,7 @@ typedef int __bitwise snd_device_type_t;
 #define	SNDRV_DEV_BUS		((__force snd_device_type_t) 0x1007)
 #define	SNDRV_DEV_CODEC		((__force snd_device_type_t) 0x1008)
 #define	SNDRV_DEV_JACK          ((__force snd_device_type_t) 0x1009)
+#define	SNDRV_DEV_COMPRESS	((__force snd_device_type_t) 0x100A)
 #define	SNDRV_DEV_LOWLEVEL	((__force snd_device_type_t) 0x2000)
 
 typedef int __bitwise snd_device_state_t;
diff --git a/include/sound/minors.h b/include/sound/minors.h
index 8f76420..5978f9a 100644
--- a/include/sound/minors.h
+++ b/include/sound/minors.h
@@ -35,7 +35,7 @@
 #define SNDRV_MINOR_TIMER		33	/* SNDRV_MINOR_GLOBAL + 1 * 32 */
 
 #ifndef CONFIG_SND_DYNAMIC_MINORS
-						/* 2 - 3 (reserved) */
+#define SNDRV_MINOR_COMPRESS		2	/* 2 - 3 */
 #define SNDRV_MINOR_HWDEP		4	/* 4 - 7 */
 #define SNDRV_MINOR_RAWMIDI		8	/* 8 - 15 */
 #define SNDRV_MINOR_PCM_PLAYBACK	16	/* 16 - 23 */
@@ -49,6 +49,7 @@
 #define SNDRV_DEVICE_TYPE_PCM_CAPTURE	SNDRV_MINOR_PCM_CAPTURE
 #define SNDRV_DEVICE_TYPE_SEQUENCER	SNDRV_MINOR_SEQUENCER
 #define SNDRV_DEVICE_TYPE_TIMER		SNDRV_MINOR_TIMER
+#define SNDRV_DEVICE_TYPE_COMPRESS	SNDRV_MINOR_COMPRESS
 
 #else /* CONFIG_SND_DYNAMIC_MINORS */
 
@@ -60,6 +61,7 @@ enum {
 	SNDRV_DEVICE_TYPE_RAWMIDI,
 	SNDRV_DEVICE_TYPE_PCM_PLAYBACK,
 	SNDRV_DEVICE_TYPE_PCM_CAPTURE,
+	SNDRV_DEVICE_TYPE_COMPRESS,
 };
 
 #endif /* CONFIG_SND_DYNAMIC_MINORS */
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 828af35..28f3559 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -229,6 +229,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
 	case SNDRV_DEVICE_TYPE_RAWMIDI:
 	case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
 	case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
+	case SNDRV_DEVICE_TYPE_COMPRESS:
 		if (snd_BUG_ON(!card))
 			return -EINVAL;
 		minor = SNDRV_MINOR(card->number, type + dev);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v5 3/6] core: add compress parameter definations
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (11 preceding siblings ...)
  2011-12-23  5:06     ` [PATCH v5 2/6] core: add support for compressed devices Vinod Koul
@ 2011-12-23  5:06     ` Vinod Koul
  2011-12-23  5:06     ` [PATCH v5 4/6] core: add API header and driver header files Vinod Koul
                       ` (2 subsequent siblings)
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-23  5:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, Pierre-Louis Bossart

The patch adds the various definations used to define the encoder
and decoder parameters

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 include/sound/compress_params.h |  397 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 397 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/compress_params.h

diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
new file mode 100644
index 0000000..d97d69f
--- /dev/null
+++ b/include/sound/compress_params.h
@@ -0,0 +1,397 @@
+/*
+ *  compress_params.h - codec types and parameters for compressed data
+ *  streaming interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *              Vinod Koul <vinod.koul@linux.intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The definitions in this file are derived from the OpenMAX AL version 1.1
+ * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
+ *
+ * Copyright (c) 2007-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and/or associated documentation files (the
+ * "Materials "), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+#ifndef __SND_COMPRESS_PARAMS_H
+#define __SND_COMPRESS_PARAMS_H
+
+/* AUDIO CODECS SUPPORTED */
+#define MAX_NUM_CODECS 32
+#define MAX_NUM_CODEC_DESCRIPTORS 32
+#define MAX_NUM_BITRATES 32
+
+/* Codecs are listed linearly to allow for extensibility */
+#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
+#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
+#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
+#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
+#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
+#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
+#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
+#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
+#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
+#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
+#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
+#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
+#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
+
+/*
+ * Profile and modes are listed with bit masks. This allows for a
+ * more compact representation of fields that will not evolve
+ * (in contrast to the list of codecs)
+ */
+
+#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
+
+/* MP3 modes are only useful for encoders */
+#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
+#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
+#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
+#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
+
+/* AMR modes are only useful for encoders */
+#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
+
+#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
+#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
+
+#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
+
+/* AMRWB modes are only useful for encoders */
+#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
+
+/* AAC modes are required for encoders and decoders */
+#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
+#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
+#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
+#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
+#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
+#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
+#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
+
+/* AAC formats are required for encoders and decoders */
+#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
+#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
+
+#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
+#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
+#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
+#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
+
+#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
+#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
+#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
+#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
+#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
+#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
+#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
+
+#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
+/*
+ * Some implementations strip the ASF header and only send ASF packets
+ * to the DSP
+ */
+#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
+
+#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
+#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
+
+/*
+ * Define quality levels for FLAC encoders, from LEVEL0 (fast)
+ * to LEVEL8 (best)
+ */
+#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
+#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
+#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
+#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
+#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
+#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
+#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
+
+#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
+
+/* IEC61937 payloads without CUVP and preambles */
+#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
+/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
+#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
+
+/*
+ * IEC modes are mandatory for decoders. Format autodetection
+ * will only happen on the DSP side with mode 0. The PCM mode should
+ * not be used, the PCM codec should be used instead.
+ */
+#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
+#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
+#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
+#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
+#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
+#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
+#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
+#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
+#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
+#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
+#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
+#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
+#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
+#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
+#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
+#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
+#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
+#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
+#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
+
+#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
+#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
+
+/* <FIXME: multichannel encoders aren't supported for now. Would need
+   an additional definition of channel arrangement> */
+
+/* VBR/CBR definitions */
+#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
+#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
+
+/* Encoder options */
+
+struct snd_enc_wma {
+	__u32 super_block_align; /* WMA Type-specific data */
+};
+
+
+/**
+ * struct snd_enc_vorbis
+ * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
+ * In the default mode of operation, the quality level is 3.
+ * Normal quality range is 0 - 10.
+ * @managed: Boolean. Set  bitrate  management  mode. This turns off the
+ * normal VBR encoding, but allows hard or soft bitrate constraints to be
+ * enforced by the encoder. This mode can be slower, and may also be
+ * lower quality. It is primarily useful for streaming.
+ * @max_bit_rate: Enabled only if managed is TRUE
+ * @min_bit_rate: Enabled only if managed is TRUE
+ * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
+ * non-stereo streams). Useful for lower-bitrate encoding.
+ *
+ * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
+ * properties
+ *
+ * For best quality users should specify VBR mode and set quality levels.
+ */
+
+struct snd_enc_vorbis {
+	__s32 quality;
+	__u32 managed;
+	__u32 max_bit_rate;
+	__u32 min_bit_rate;
+	__u32 downmix;
+};
+
+
+/**
+ * struct snd_enc_real
+ * @quant_bits: number of coupling quantization bits in the stream
+ * @start_region: coupling start region in the stream
+ * @num_regions: number of regions value
+ *
+ * These options were extracted from the OpenMAX IL spec
+ */
+
+struct snd_enc_real {
+	__u32 quant_bits;
+	__u32 start_region;
+	__u32 num_regions;
+};
+
+/**
+ * struct snd_enc_flac
+ * @num: serial number, valid only for OGG formats
+ *	needs to be set by application
+ * @gain: Add replay gain tags
+ *
+ * These options were extracted from the FLAC online documentation
+ * at http://flac.sourceforge.net/documentation_tools_flac.html
+ *
+ * To make the API simpler, it is assumed that the user will select quality
+ * profiles. Additional options that affect encoding quality and speed can
+ * be added at a later stage if needed.
+ *
+ * By default the Subset format is used by encoders.
+ *
+ * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
+ * not supported in this API.
+ */
+
+struct snd_enc_flac {
+	__u32 num;
+	__u32 gain;
+};
+
+struct snd_enc_generic {
+	__u32 bw;	/* encoder bandwidth */
+	__s32 reserved[15];
+};
+
+union snd_codec_options {
+	struct snd_enc_wma wma;
+	struct snd_enc_vorbis vorbis;
+	struct snd_enc_real real;
+	struct snd_enc_flac flac;
+	struct snd_enc_generic generic;
+};
+
+/** struct snd_codec_desc - description of codec capabilities
+ * @max_ch: Maximum number of audio channels
+ * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
+ * @bit_rate: Indexed array containing supported bit rates
+ * @num_bitrates: Number of valid values in bit_rate array
+ * @rate_control: value is specified by SND_RATECONTROLMODE defines.
+ * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
+ * @modes: Supported modes. See SND_AUDIOMODE defines
+ * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
+ * @min_buffer: Minimum buffer size handled by codec implementation
+ * @reserved: reserved for future use
+ *
+ * This structure provides a scalar value for profiles, modes and stream
+ * format fields.
+ * If an implementation supports multiple combinations, they will be listed as
+ * codecs with different descriptors, for example there would be 2 descriptors
+ * for AAC-RAW and AAC-ADTS.
+ * This entails some redundancy but makes it easier to avoid invalid
+ * configurations.
+ *
+ */
+
+struct snd_codec_desc {
+	__u32 max_ch;
+	__u32 sample_rates;
+	__u32 bit_rate[MAX_NUM_BITRATES];
+	__u32 num_bitrates;
+	__u32 rate_control;
+	__u32 profiles;
+	__u32 modes;
+	__u32 formats;
+	__u32 min_buffer;
+	__u32 reserved[15];
+};
+
+/** struct snd_codec
+ * @id: Identifies the supported audio encoder/decoder.
+ *		See SND_AUDIOCODEC macros.
+ * @ch_in: Number of input audio channels
+ * @ch_out: Number of output channels. In case of contradiction between
+ *		this field and the channelMode field, the channelMode field
+ *		overrides.
+ * @sample_rate: Audio sample rate of input data
+ * @bit_rate: Bitrate of encoded data. May be ignored by decoders
+ * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
+ *               Encoders may rely on profiles for quality levels.
+ *		 May be ignored by decoders.
+ * @profile: Mandatory for encoders, can be mandatory for specific
+ *		decoders as well. See SND_AUDIOPROFILE defines.
+ * @level: Supported level (Only used by WMA at the moment)
+ * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
+ * @format: Format of encoded bistream. Mandatory when defined.
+ *		See SND_AUDIOSTREAMFORMAT defines.
+ * @align: Block alignment in bytes of an audio sample.
+ *		Only required for PCM or IEC formats.
+ * @options: encoder-specific settings
+ * @reserved: reserved for future use
+ */
+
+struct snd_codec {
+	__u32 id;
+	__u32 ch_in;
+	__u32 ch_out;
+	__u32 sample_rate;
+	__u32 bit_rate;
+	__u32 rate_control;
+	__u32 profile;
+	__u32 level;
+	__u32 ch_mode;
+	__u32 format;
+	__u32 align;
+	union snd_codec_options options;
+	__u32 reserved[3];
+};
+
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v5 4/6] core: add API header and driver header files
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (12 preceding siblings ...)
  2011-12-23  5:06     ` [PATCH v5 3/6] core: add compress parameter definations Vinod Koul
@ 2011-12-23  5:06     ` Vinod Koul
  2011-12-23  5:06     ` [PATCH v5 5/6] core: add support for compress_offload Vinod Koul
  2011-12-23  5:06     ` [PATCH v5 6/6] core: add makefile and kconfig file for compress Vinod Koul
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-23  5:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, Pierre-Louis Bossart

This patch adds the header files for ioctl definitions and header file for
driver APIs for lower level device drivers to use

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 include/sound/compress_driver.h  |  167 ++++++++++++++++++++++++++++++++++++++
 include/sound/compress_offload.h |  161 ++++++++++++++++++++++++++++++++++++
 2 files changed, 328 insertions(+), 0 deletions(-)
 create mode 100644 include/sound/compress_driver.h
 create mode 100644 include/sound/compress_offload.h

diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
new file mode 100644
index 0000000..48f2a1f
--- /dev/null
+++ b/include/sound/compress_driver.h
@@ -0,0 +1,167 @@
+/*
+ *  compress_driver.h - compress offload driver definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_DRIVER_H
+#define __COMPRESS_DRIVER_H
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <sound/compress_offload.h>
+#include <sound/asound.h>
+#include <sound/pcm.h>
+
+struct snd_compr_ops;
+
+/**
+ * struct snd_compr_runtime: runtime stream description
+ * @state: stream state
+ * @ops: pointer to DSP callbacks
+ * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
+ *	DSP doesn't implement copy
+ * @buffer_size: size of the above buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ * @hw_pointer: offset of last location in buffer where DSP copied data
+ * @app_pointer: offset of last location in buffer where app wrote data
+ * @total_bytes_available: cumulative number of bytes made available in
+ *	the ring buffer
+ * @total_bytes_transferred: cumulative bytes transferred by offload DSP
+ * @sleep: poll sleep
+ */
+struct snd_compr_runtime {
+	snd_pcm_state_t state;
+	struct snd_compr_ops *ops;
+	void *buffer;
+	u64 buffer_size;
+	u32 fragment_size;
+	u32 fragments;
+	u64 hw_pointer;
+	u64 app_pointer;
+	u64 total_bytes_available;
+	u64 total_bytes_transferred;
+	wait_queue_head_t sleep;
+};
+
+/**
+ * struct snd_compr_stream: compressed stream
+ * @name: device name
+ * @ops: pointer to DSP callbacks
+ * @runtime: pointer to runtime structure
+ * @device: device pointer
+ * @direction: stream direction, playback/recording
+ * @private_data: pointer to DSP private data
+ */
+struct snd_compr_stream {
+	const char *name;
+	struct snd_compr_ops *ops;
+	struct snd_compr_runtime *runtime;
+	struct snd_compr *device;
+	enum snd_compr_direction direction;
+	void *private_data;
+};
+
+/**
+ * struct snd_compr_ops: compressed path DSP operations
+ * @open: Open the compressed stream
+ * This callback is mandatory and shall keep dsp ready to receive the stream
+ * parameter
+ * @free: Close the compressed stream, mandatory
+ * @set_params: Sets the compressed stream parameters, mandatory
+ * This can be called in during stream creation only to set codec params
+ * and the stream properties
+ * @get_params: retrieve the codec parameters, mandatory
+ * @trigger: Trigger operations like start, pause, resume, drain, stop.
+ * This callback is mandatory
+ * @pointer: Retrieve current h/w pointer information. Mandatory
+ * @copy: Copy the compressed data to/from userspace, Optional
+ * Can't be implemented if DSP supports mmap
+ * @mmap: DSP mmap method to mmap DSP memory
+ * @ack: Ack for DSP when data is written to audio buffer, Optional
+ * Not valid if copy is implemented
+ * @get_caps: Retrieve DSP capabilities, mandatory
+ * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory
+ */
+struct snd_compr_ops {
+	int (*open)(struct snd_compr_stream *stream);
+	int (*free)(struct snd_compr_stream *stream);
+	int (*set_params)(struct snd_compr_stream *stream,
+			struct snd_compr_params *params);
+	int (*get_params)(struct snd_compr_stream *stream,
+			struct snd_codec *params);
+	int (*trigger)(struct snd_compr_stream *stream, int cmd);
+	int (*pointer)(struct snd_compr_stream *stream,
+			struct snd_compr_tstamp *tstamp);
+	int (*copy)(struct snd_compr_stream *stream, const char __user *buf,
+		       size_t count);
+	int (*mmap)(struct snd_compr_stream *stream,
+			struct vm_area_struct *vma);
+	int (*ack)(struct snd_compr_stream *stream, size_t bytes);
+	int (*get_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_caps *caps);
+	int (*get_codec_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_codec_caps *codec);
+};
+
+/**
+ * struct snd_compr: Compressed device
+ * @name: DSP device name
+ * @dev: Device pointer
+ * @ops: pointer to DSP callbacks
+ * @private_data: pointer to DSP pvt data
+ * @card: sound card pointer
+ * @direction: Playback or capture direction
+ * @lock: device lock
+ * @device: device id
+ */
+struct snd_compr {
+	const char *name;
+	struct device *dev;
+	struct snd_compr_ops *ops;
+	void *private_data;
+	struct snd_card *card;
+	unsigned int direction;
+	struct mutex lock;
+	int device;
+};
+
+/* compress device register APIs */
+int snd_compress_register(struct snd_compr *device);
+int snd_compress_deregister(struct snd_compr *device);
+int snd_compress_new(struct snd_card *card, int device,
+			int type, struct snd_compr *compr);
+
+/* dsp driver callback apis
+ * For playback: driver should call snd_compress_fragment_elapsed() to let the
+ * framework know that a fragment has been consumed from the ring buffer
+ *
+ * For recording: we want to know when a frame is available or when
+ * at least one frame is available so snd_compress_frame_elapsed()
+ * callback should be called when a encodeded frame is available
+ */
+static inline void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
+{
+	wake_up(&stream->runtime->sleep);
+}
+
+#endif
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
new file mode 100644
index 0000000..05341a4
--- /dev/null
+++ b/include/sound/compress_offload.h
@@ -0,0 +1,161 @@
+/*
+ *  compress_offload.h - compress offload header definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_OFFLOAD_H
+#define __COMPRESS_OFFLOAD_H
+
+#include <linux/types.h>
+#include <sound/asound.h>
+#include <sound/compress_params.h>
+
+
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
+/**
+ * struct snd_compressed_buffer: compressed buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ */
+struct snd_compressed_buffer {
+	__u32 fragment_size;
+	__u32 fragments;
+};
+
+/**
+ * struct snd_compr_params: compressed stream params
+ * @buffer: buffer description
+ * @codec: codec parameters
+ * @no_wake_mode: dont wake on fragment elapsed
+ */
+struct snd_compr_params {
+	struct snd_compressed_buffer buffer;
+	struct snd_codec codec;
+	__u8 no_wake_mode;
+};
+
+/**
+ * struct snd_compr_tstamp: timestamp descriptor
+ * @byte_offset: Byte offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from/to ring buffer to/by DSP
+ * @pcm_frames: Frames decoded or encoded by DSP. This field will evolve by
+ *	large steps and should only be used to monitor encoding/decoding
+ *	progress. It shall not be used for timing estimates.
+ * @pcm_io_frames: Frames rendered or received by DSP into a mixer or an audio
+ * output/input. This field should be used for A/V sync or time estimates.
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp {
+	__u32 byte_offset;
+	__u32 copied_total;
+	snd_pcm_uframes_t pcm_frames;
+	snd_pcm_uframes_t pcm_io_frames;
+	__u32 sampling_rate;
+};
+
+/**
+ * struct snd_compr_avail: avail descriptor
+ * @avail: Number of bytes available in ring buffer for writing/reading
+ * @tstamp: timestamp infomation
+ */
+struct snd_compr_avail {
+	__u64 avail;
+	struct snd_compr_tstamp tstamp;
+};
+
+enum snd_compr_direction {
+	SND_COMPRESS_PLAYBACK = 0,
+	SND_COMPRESS_CAPTURE
+};
+
+/**
+ * struct snd_compr_caps: caps descriptor
+ * @codecs: pointer to array of codecs
+ * @direction: direction supported. Of type snd_compr_direction
+ * @min_fragment_size: minimum fragment supported by DSP
+ * @max_fragment_size: maximum fragment supported by DSP
+ * @min_fragments: min fragments supported by DSP
+ * @max_fragments: max fragments supported by DSP
+ * @num_codecs: number of codecs supported
+ * @reserved: reserved field
+ */
+struct snd_compr_caps {
+	__u32 num_codecs;
+	__u32 direction;
+	__u32 min_fragment_size;
+	__u32 max_fragment_size;
+	__u32 min_fragments;
+	__u32 max_fragments;
+	__u32 codecs[MAX_NUM_CODECS];
+	__u32 reserved[11];
+};
+
+/**
+ * struct snd_compr_codec_caps: query capability of codec
+ * @codec: codec for which capability is queried
+ * @num_descriptors: number of codec descriptors
+ * @descriptor: array of codec capability descriptor
+ */
+struct snd_compr_codec_caps {
+	__u32 codec;
+	__u32 num_descriptors;
+	struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
+};
+
+/**
+ * compress path ioctl definitions
+ * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
+ * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
+ * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
+ * Note: only codec params can be changed runtime and stream params cant be
+ * SNDRV_COMPRESS_GET_PARAMS: Query codec params
+ * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
+ * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
+ * This also queries the tstamp properties
+ * SNDRV_COMPRESS_PAUSE: Pause the running stream
+ * SNDRV_COMPRESS_RESUME: resume a paused stream
+ * SNDRV_COMPRESS_START: Start a stream
+ * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
+ * and the buffers currently with DSP
+ * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
+ * SNDRV_COMPRESS_IOCTL_VERSION: Query the API version
+ */
+#define SNDRV_COMPRESS_IOCTL_VERSION	_IOR('C', 0x00, int)
+#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x10, struct snd_compr_caps)
+#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x11,\
+						struct snd_compr_codec_caps)
+#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x12, struct snd_compr_params)
+#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x13, struct snd_codec)
+#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x20, struct snd_compr_tstamp)
+#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x21, struct snd_compr_avail)
+#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x30)
+#define SNDRV_COMPRESS_RESUME		_IO('C', 0x31)
+#define SNDRV_COMPRESS_START		_IO('C', 0x32)
+#define SNDRV_COMPRESS_STOP		_IO('C', 0x33)
+#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x34)
+/*
+ * TODO
+ * 1. add mmap support
+ *
+ */
+#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v5 5/6] core: add support for compress_offload
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (13 preceding siblings ...)
  2011-12-23  5:06     ` [PATCH v5 4/6] core: add API header and driver header files Vinod Koul
@ 2011-12-23  5:06     ` Vinod Koul
  2011-12-23  5:06     ` [PATCH v5 6/6] core: add makefile and kconfig file for compress Vinod Koul
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-23  5:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, Pierre-Louis Bossart

This patch adds core.c, the file which implements the ioctls and
registers the devices

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/core/compress_offload.c |  765 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 765 insertions(+), 0 deletions(-)
 create mode 100644 sound/core/compress_offload.c

diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
new file mode 100644
index 0000000..dac3633
--- /dev/null
+++ b/sound/core/compress_offload.c
@@ -0,0 +1,765 @@
+/*
+ *  compress_core.c - compress offload core
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
+#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
+
+/* TODO:
+ * - add substream support for multiple devices in case of
+ *	SND_DYNAMIC_MINORS is not used
+ * - Multiple node representation
+ *	driver should be able to register multiple nodes
+ */
+
+static DEFINE_MUTEX(device_mutex);
+
+struct snd_compr_file {
+	unsigned long caps;
+	struct snd_compr_stream stream;
+};
+
+/*
+ * a note on stream states used:
+ * we use follwing states in the compressed core
+ * SNDRV_PCM_STATE_OPEN: When stream has been opened.
+ * SNDRV_PCM_STATE_SETUP: When stream has been initialized. This is done by
+ *	calling SNDRV_COMPRESS_SET_PARAMS. running streams will come to this
+ *	state at stop by calling SNDRV_COMPRESS_STOP, or at end of drain.
+ * SNDRV_PCM_STATE_RUNNING: When stream has been started and is
+ *	decoding/encoding and rendering/capturing data.
+ * SNDRV_PCM_STATE_DRAINING: When stream is draining current data. This is done
+ *	by calling SNDRV_COMPRESS_DRAIN.
+ * SNDRV_PCM_STATE_PAUSED: When stream is paused. This is done by calling
+ *	SNDRV_COMPRESS_PAUSE. It can be stopped or resumed by calling
+ *	SNDRV_COMPRESS_STOP or SNDRV_COMPRESS_RESUME respectively.
+ */
+static int snd_compr_open(struct inode *inode, struct file *f)
+{
+	struct snd_compr *compr;
+	struct snd_compr_file *data;
+	struct snd_compr_runtime *runtime;
+	enum snd_compr_direction dirn;
+	int maj = imajor(inode);
+	int ret;
+
+	if (f->f_flags & O_WRONLY)
+		dirn = SND_COMPRESS_PLAYBACK;
+	else if (f->f_flags & O_RDONLY)
+		dirn = SND_COMPRESS_CAPTURE;
+	else {
+		pr_err("invalid direction\n");
+		return -EINVAL;
+	}
+
+	if (maj == snd_major)
+		compr = snd_lookup_minor_data(iminor(inode),
+					SNDRV_DEVICE_TYPE_COMPRESS);
+	else
+		return -EBADFD;
+
+	if (compr == NULL) {
+		pr_err("no device data!!!\n");
+		return -ENODEV;
+	}
+
+	if (dirn != compr->direction) {
+		pr_err("this device doesn't support this direction\n");
+		return -EINVAL;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	data->stream.ops = compr->ops;
+	data->stream.direction = dirn;
+	data->stream.private_data = compr->private_data;
+	data->stream.device = compr;
+	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+	if (!runtime) {
+		kfree(data);
+		return -ENOMEM;
+	}
+	runtime->state = SNDRV_PCM_STATE_OPEN;
+	init_waitqueue_head(&runtime->sleep);
+	data->stream.runtime = runtime;
+	f->private_data = (void *)data;
+	mutex_lock(&compr->lock);
+	ret = compr->ops->open(&data->stream);
+	mutex_unlock(&compr->lock);
+	if (ret) {
+		kfree(runtime);
+		kfree(data);
+	}
+	return ret;
+}
+
+static int snd_compr_free(struct inode *inode, struct file *f)
+{
+	struct snd_compr_file *data = f->private_data;
+	data->stream.ops->free(&data->stream);
+	kfree(data->stream.runtime->buffer);
+	kfree(data->stream.runtime);
+	kfree(data);
+	return 0;
+}
+
+static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
+		struct snd_compr_tstamp *tstamp)
+{
+	if (!stream->ops->pointer)
+		return;
+	stream->ops->pointer(stream, tstamp);
+	pr_debug("dsp consumed till %d total %d bytes\n",
+		tstamp->byte_offset, tstamp->copied_total);
+	stream->runtime->hw_pointer = tstamp->byte_offset;
+	stream->runtime->total_bytes_transferred = tstamp->copied_total;
+}
+
+static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
+		struct snd_compr_avail *avail)
+{
+	long avail_calc; /*this needs to be signed variable */
+
+	snd_compr_update_tstamp(stream, &avail->tstamp);
+
+	/* FIXME: This needs to be different for capture stream,
+	   available is # of compressed data, for playback it's
+	   remainder of buffer */
+
+	if (stream->runtime->total_bytes_available == 0 &&
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+		pr_debug("detected init and someone forgot to do a write\n");
+		return stream->runtime->buffer_size;
+	}
+	pr_debug("app wrote %lld, DSP consumed %lld\n",
+			stream->runtime->total_bytes_available,
+			stream->runtime->total_bytes_transferred);
+	if (stream->runtime->total_bytes_available ==
+				stream->runtime->total_bytes_transferred) {
+		pr_debug("both pointers are same, returning full avail\n");
+		return stream->runtime->buffer_size;
+	}
+
+	/* FIXME: this routine isn't consistent, in one test we use
+	 * cumulative values and in the other byte offsets. Do we
+	 * really need the byte offsets if the cumulative values have
+	 * been updated? In the PCM interface app_ptr and hw_ptr are
+	 * already cumulative */
+
+	avail_calc = stream->runtime->buffer_size -
+		(stream->runtime->app_pointer - stream->runtime->hw_pointer);
+	pr_debug("calc avail as %ld, app_ptr %lld, hw+ptr %lld\n", avail_calc,
+			stream->runtime->app_pointer,
+			stream->runtime->hw_pointer);
+	if (avail_calc >= stream->runtime->buffer_size)
+		avail_calc -= stream->runtime->buffer_size;
+	pr_debug("ret avail as %ld\n", avail_calc);
+	avail->avail = avail_calc;
+	return avail_calc;
+}
+
+static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
+{
+	struct snd_compr_avail avail;
+
+	return snd_compr_calc_avail(stream, &avail);
+}
+
+static int
+snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_avail ioctl_avail;
+	size_t avail;
+
+	avail = snd_compr_calc_avail(stream, &ioctl_avail);
+	ioctl_avail.avail = avail;
+
+	if (copy_to_user((__u64 __user *)arg,
+				&ioctl_avail, sizeof(ioctl_avail)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_compr_write_data(struct snd_compr_stream *stream,
+	       const char __user *buf, size_t count)
+{
+	void *dstn;
+	size_t copy;
+	struct snd_compr_runtime *runtime = stream->runtime;
+
+	dstn = runtime->buffer + runtime->app_pointer;
+	pr_debug("copying %ld at %lld\n",
+			(unsigned long)count, runtime->app_pointer);
+	if (count < runtime->buffer_size - runtime->app_pointer) {
+		if (copy_from_user(dstn, buf, count))
+			return -EFAULT;
+		runtime->app_pointer += count;
+	} else {
+		copy = runtime->buffer_size - runtime->app_pointer;
+		if (copy_from_user(dstn, buf, copy))
+			return -EFAULT;
+		if (copy_from_user(runtime->buffer, buf + copy, count - copy))
+			return -EFAULT;
+		runtime->app_pointer = count - copy;
+	}
+	/* if DSP cares, let it know data has been written */
+	if (stream->ops->ack)
+		stream->ops->ack(stream, count);
+	return count;
+}
+
+static ssize_t snd_compr_write(struct file *f, const char __user *buf,
+		size_t count, loff_t *offset)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval;
+
+	if (snd_BUG_ON(!data))
+		return -EFAULT;
+
+	stream = &data->stream;
+	mutex_lock(&stream->device->lock);
+	/* write is allowed when stream is running or has been steup */
+	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
+			stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		mutex_unlock(&stream->device->lock);
+		return -EBADFD;
+	}
+
+	avail = snd_compr_get_avail(stream);
+	pr_debug("avail returned %ld\n", (unsigned long)avail);
+	/* calculate how much we can write to buffer */
+	if (avail > count)
+		avail = count;
+
+	if (stream->ops->copy)
+		retval = stream->ops->copy(stream, buf, avail);
+	else
+		retval = snd_compr_write_data(stream, buf, avail);
+	if (retval > 0)
+		stream->runtime->total_bytes_available += retval;
+
+	/* while initiating the stream, write should be called before START
+	 * call, so in setup move state */
+	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+		pr_debug("stream prepared, Houston we are good to go\n");
+	}
+
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+
+static ssize_t snd_compr_read(struct file *f, char __user *buf,
+		size_t count, loff_t *offset)
+{
+	return -ENXIO;
+}
+
+static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
+{
+	return -ENXIO;
+}
+
+static inline int snd_compr_get_poll(struct snd_compr_stream *stream)
+{
+	if (stream->direction == SND_COMPRESS_PLAYBACK)
+		return POLLOUT | POLLWRNORM;
+	else
+		return POLLIN | POLLRDNORM;
+}
+
+static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval = 0;
+
+	if (snd_BUG_ON(!data))
+		return -EFAULT;
+	stream = &data->stream;
+	if (snd_BUG_ON(!stream))
+		return -EFAULT;
+
+	mutex_lock(&stream->device->lock);
+	if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED ||
+			stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+		retval = -EBADFD;
+		goto out;
+	}
+	poll_wait(f, &stream->runtime->sleep, wait);
+
+	avail = snd_compr_get_avail(stream);
+	pr_debug("avail is %ld\n", (unsigned long)avail);
+	/* check if we have at least one fragment to fill */
+	switch (stream->runtime->state) {
+	case SNDRV_PCM_STATE_DRAINING:
+		/* stream has been woken up after drain is complete
+		 * draining done so set stream state to stopped
+		 */
+		retval = snd_compr_get_poll(stream);
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		break;
+	case SNDRV_PCM_STATE_RUNNING:
+	case SNDRV_PCM_STATE_PREPARED:
+	case SNDRV_PCM_STATE_PAUSED:
+		if (avail >= stream->runtime->fragment_size)
+			retval = snd_compr_get_poll(stream);
+		break;
+	default:
+		if (stream->direction == SND_COMPRESS_PLAYBACK)
+			retval = POLLOUT | POLLWRNORM | POLLERR;
+		else
+			retval = POLLIN | POLLRDNORM | POLLERR;
+		break;
+	}
+out:
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+static int
+snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_caps caps;
+
+	if (!stream->ops->get_caps)
+		return -ENXIO;
+
+	retval = stream->ops->get_caps(stream, &caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
+		retval = -EFAULT;
+out:
+	return retval;
+}
+
+static int
+snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_codec_caps *caps;
+
+	if (!stream->ops->get_codec_caps)
+		return -ENXIO;
+
+	caps = kmalloc(sizeof(*caps), GFP_KERNEL);
+	if (!caps)
+		return -ENOMEM;
+
+	retval = stream->ops->get_codec_caps(stream, caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
+		retval = -EFAULT;
+
+out:
+	kfree(caps);
+	return retval;
+}
+
+/* revisit this with snd_pcm_preallocate_xxx */
+static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+		struct snd_compr_params *params)
+{
+	unsigned int buffer_size;
+	void *buffer;
+
+	buffer_size = params->buffer.fragment_size * params->buffer.fragments;
+	if (stream->ops->copy) {
+		buffer = NULL;
+		/* if copy is defined the driver will be required to copy
+		 * the data from core
+		 */
+	} else {
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+	}
+	stream->runtime->fragment_size = params->buffer.fragment_size;
+	stream->runtime->fragments = params->buffer.fragments;
+	stream->runtime->buffer = buffer;
+	stream->runtime->buffer_size = buffer_size;
+	return 0;
+}
+
+static int
+snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_params *params;
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+		/*
+		 * we should allow parameter change only when stream has been
+		 * opened not in other cases
+		 */
+		params = kmalloc(sizeof(*params), GFP_KERNEL);
+		if (!params)
+			return -ENOMEM;
+		if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
+			return -EFAULT;
+		retval = snd_compr_allocate_buffer(stream, params);
+		if (retval) {
+			kfree(params);
+			return -ENOMEM;
+		}
+		retval = stream->ops->set_params(stream, params);
+		if (retval)
+			goto out;
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+	} else
+		return -EPERM;
+out:
+	kfree(params);
+	return retval;
+}
+
+static int
+snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_codec *params;
+	int retval;
+
+	if (!stream->ops->get_params)
+		return -EBADFD;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+	retval = stream->ops->get_params(stream, params);
+	if (retval)
+		goto out;
+	if (copy_to_user((char __user *)arg, params, sizeof(*params)))
+		retval = -EFAULT;
+
+out:
+	kfree(params);
+	return retval;
+}
+
+static inline int
+snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_tstamp tstamp;
+
+	snd_compr_update_tstamp(stream, &tstamp);
+	return copy_to_user((struct snd_compr_tstamp __user *)arg,
+		&tstamp, sizeof(tstamp)) ? -EFAULT : 0;
+}
+
+static int snd_compr_pause(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_resume(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_start(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_stop(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_drain(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
+			stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct snd_compr_file *data = f->private_data;
+	struct snd_compr_stream *stream;
+	int retval = -ENOTTY;
+
+	if (snd_BUG_ON(!data))
+		return -EFAULT;
+	stream = &data->stream;
+	if (snd_BUG_ON(!stream))
+		return -EFAULT;
+	mutex_lock(&stream->device->lock);
+	switch (_IOC_NR(cmd)) {
+	case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
+		put_user(SNDRV_COMPRESS_VERSION,
+				(int __user *)arg) ? -EFAULT : 0;
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+		retval = snd_compr_get_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+		retval = snd_compr_get_codec_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+		retval = snd_compr_set_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
+		retval = snd_compr_get_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
+		retval = snd_compr_tstamp(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
+		retval = snd_compr_ioctl_avail(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
+		retval = snd_compr_pause(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_RESUME):
+		retval = snd_compr_resume(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_START):
+		retval = snd_compr_start(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_STOP):
+		retval = snd_compr_stop(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+		retval = snd_compr_drain(stream);
+		break;
+	}
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+static const struct file_operations snd_compr_file_ops = {
+		.owner =	THIS_MODULE,
+		.open =		snd_compr_open,
+		.release =	snd_compr_free,
+		.write =	snd_compr_write,
+		.read =		snd_compr_read,
+		.unlocked_ioctl = snd_compr_ioctl,
+		.mmap =		snd_compr_mmap,
+		.poll =		snd_compr_poll,
+};
+
+static int snd_compress_dev_register(struct snd_device *device)
+{
+	int ret = -EINVAL;
+	char str[16];
+	struct snd_compr *compr;
+
+	if (snd_BUG_ON(!device || !device->device_data))
+		return -EBADFD;
+	compr = device->device_data;
+
+	sprintf(str, "comprC%iD%i", compr->card->number, compr->device);
+	pr_debug("reg %s for device %s, direction %d\n", str, compr->name,
+			compr->direction);
+	/* register compressed device */
+	ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card,
+			compr->device, &snd_compr_file_ops, compr, str);
+	if (ret < 0) {
+		pr_err("snd_register_device failed\n %d", ret);
+		return ret;
+	}
+	return ret;
+
+}
+
+static int snd_compress_dev_disconnect(struct snd_device *device)
+{
+	struct snd_compr *compr;
+
+	compr = device->device_data;
+	snd_unregister_device(compr->direction, compr->card, compr->device);
+	return 0;
+}
+
+/*
+ * snd_compress_new: create new compress device
+ * @card: sound card pointer
+ * @device: device number
+ * @dirn: device direction, should be of type enum snd_compr_direction
+ * @compr: compress device pointer
+ */
+int snd_compress_new(struct snd_card *card, int device,
+			int dirn, struct snd_compr *compr)
+{
+	static struct snd_device_ops ops = {
+		.dev_free = NULL,
+		.dev_register = snd_compress_dev_register,
+		.dev_disconnect = snd_compress_dev_disconnect,
+	};
+
+	compr->card = card;
+	compr->device = device;
+	compr->direction = dirn;
+	return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
+}
+EXPORT_SYMBOL_GPL(snd_compress_new);
+
+static int snd_compress_add_device(struct snd_compr *device)
+{
+	int ret;
+
+	if (!device->card)
+		return -EINVAL;
+
+	/* register the card */
+	ret = snd_card_register(device->card);
+	if (ret)
+		goto out;
+	return 0;
+
+out:
+	pr_err("failed with %d\n", ret);
+	return ret;
+
+}
+
+static int snd_compress_remove_device(struct snd_compr *device)
+{
+	return snd_card_free(device->card);
+}
+
+/**
+ * snd_compress_register - register compressed device
+ *
+ * @device: compressed device to register
+ */
+int snd_compress_register(struct snd_compr *device)
+{
+	int retval;
+
+	if (device->name == NULL || device->dev == NULL || device->ops == NULL)
+		return -EINVAL;
+
+	pr_debug("Registering compressed device %s\n", device->name);
+	if (snd_BUG_ON(!device->ops->open))
+		return -EINVAL;
+	if (snd_BUG_ON(!device->ops->free))
+		return -EINVAL;
+	if (snd_BUG_ON(!device->ops->set_params))
+		return -EINVAL;
+	if (snd_BUG_ON(!device->ops->trigger))
+		return -EINVAL;
+
+	mutex_init(&device->lock);
+
+	/* register a compressed card */
+	mutex_lock(&device_mutex);
+	retval = snd_compress_add_device(device);
+	mutex_unlock(&device_mutex);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(snd_compress_register);
+
+int snd_compress_deregister(struct snd_compr *device)
+{
+	pr_debug("Removing compressed device %s\n", device->name);
+	mutex_lock(&device_mutex);
+	snd_compress_remove_device(device);
+	mutex_unlock(&device_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_compress_deregister);
+
+static int __init snd_compress_init(void)
+{
+	return 0;
+}
+
+static void __exit snd_compress_exit(void)
+{
+}
+
+module_init(snd_compress_init);
+module_exit(snd_compress_exit);
+
+MODULE_DESCRIPTION("ALSA Compressed offload framework");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* [PATCH v5 6/6] core: add makefile and kconfig file for compress
  2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
                       ` (14 preceding siblings ...)
  2011-12-23  5:06     ` [PATCH v5 5/6] core: add support for compress_offload Vinod Koul
@ 2011-12-23  5:06     ` Vinod Koul
  15 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-23  5:06 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Vinod Koul, broonie, Pierre-Louis Bossart

Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/core/Kconfig  |   10 ++++++++++
 sound/core/Makefile |    4 ++++
 2 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 475455c..2dc7776 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -155,6 +155,16 @@ config SND_DYNAMIC_MINORS
 
 	  If you are unsure about this, say N here.
 
+config SND_COMPRESS_OFFLOAD
+	tristate "ALSA Compressed audio offload support"
+	default n
+	help
+	  If you want support for offloading compressed audio and have such
+	  a hardware, then you should say Y here and also to the DSP driver
+	  of your platform.
+
+	  If you are unsure about this, say N here.
+
 config SND_SUPPORT_OLD_API
 	bool "Support old ALSA API"
 	default y
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 350a08d..67c8e93 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -21,6 +21,8 @@ snd-hrtimer-objs  := hrtimer.o
 snd-rtctimer-objs := rtctimer.o
 snd-hwdep-objs    := hwdep.o
 
+snd-compress-objs := compress_offload.o
+
 obj-$(CONFIG_SND) 		+= snd.o
 obj-$(CONFIG_SND_HWDEP)		+= snd-hwdep.o
 obj-$(CONFIG_SND_TIMER)		+= snd-timer.o
@@ -31,3 +33,5 @@ obj-$(CONFIG_SND_RAWMIDI)	+= snd-rawmidi.o
 
 obj-$(CONFIG_SND_OSSEMUL)	+= oss/
 obj-$(CONFIG_SND_SEQUENCER)	+= seq/
+
+obj-$(CONFIG_SND_COMPRESS_OFFLOAD)	+= snd-compress.o
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 133+ messages in thread

* Re: [PATCH v5 0/6] core: add compress data API to ALSA kernel
  2011-12-23  5:06     ` [PATCH v5 0/6] core: add compress data API to ALSA kernel Vinod Koul
@ 2011-12-23  9:37       ` Takashi Iwai
  2011-12-23 11:37         ` Vinod Koul
  0 siblings, 1 reply; 133+ messages in thread
From: Takashi Iwai @ 2011-12-23  9:37 UTC (permalink / raw)
  To: Vinod Koul; +Cc: alsa-devel, broonie

At Fri, 23 Dec 2011 10:36:34 +0530,
Vinod Koul wrote:
> 
> As agreed during the ASoC workshop in May 2011, this set of patches are a
> proposal from Intel to add a new compressed data interface to ALSA. This
> proposal builds on the existing Intel solution and the experience gathered over
> two years with Meego and Android solutions. This proposal is no longer
> Intel-specific and was generalized with the addition of a basic core;
> codec-related definitions are based on the vendor-neutral OpenMAX AL standard. 
> 
> These patches are also available in git tree:
> git://git.infradead.org/users/vkoul/snd-compress.git v5_patches

I applied all patches now.  Please check later the sound git tree
whether everything is OK.


Thanks!

Takashi

> --
> Changes in v5:
>  fixed the device minor number and definations
>  removed all BUG_ONs
>  renamed params file to compress-params.h and Doc file to compress_offlaod.txt
>  added notes on stream states used
>  changes all user structs to use fixed size variables
> 
> Changes in v4:
>  Rebased on 3.2-rc4, fixed module.h compilation
>  Added sched.h header in compress_driver.h
>  Fixed few warnings while at it
> 
> Changes in v3:
>  Fixed the device registration for compressed devices as discussed
>  moved card creation to lower level drivers
>  Added new api for device node creation
>  changes fragment/frame callbacks to single inlined callback
> 
> Changes in v2:
>  Fixed the comments recieved in v2
>  Fixed the comments recieved during LPC discussions
>  add support for alsa device registeration
>  fix the bugs found in testing
> --
> 
> Omair Mohammed Abdullah (1):
>   core: add support for compressed devices
> 
> Pierre-Louis Bossart (1):
>   compress offload API documentation
> 
> Vinod Koul (4):
>   core: add compress parameter definations
>   core: add API header and driver header files
>   core: add support for compress_offload
>   core: add makefile and kconfig file for compress
> 
>  Documentation/sound/alsa/compress_offload.txt |  188 ++++++
>  include/sound/compress_driver.h               |  167 ++++++
>  include/sound/compress_offload.h              |  161 ++++++
>  include/sound/compress_params.h               |  397 +++++++++++++
>  include/sound/core.h                          |    1 +
>  include/sound/minors.h                        |    4 +-
>  sound/core/Kconfig                            |   10 +
>  sound/core/Makefile                           |    4 +
>  sound/core/compress_offload.c                 |  765 +++++++++++++++++++++++++
>  sound/core/sound.c                            |    1 +
>  10 files changed, 1697 insertions(+), 1 deletions(-)
>  create mode 100644 Documentation/sound/alsa/compress_offload.txt
>  create mode 100644 include/sound/compress_driver.h
>  create mode 100644 include/sound/compress_offload.h
>  create mode 100644 include/sound/compress_params.h
>  create mode 100644 sound/core/compress_offload.c
> 

^ permalink raw reply	[flat|nested] 133+ messages in thread

* Re: [PATCH v5 0/6] core: add compress data API to ALSA kernel
  2011-12-23  9:37       ` Takashi Iwai
@ 2011-12-23 11:37         ` Vinod Koul
  0 siblings, 0 replies; 133+ messages in thread
From: Vinod Koul @ 2011-12-23 11:37 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, broonie

On Fri, 2011-12-23 at 10:37 +0100, Takashi Iwai wrote:
> At Fri, 23 Dec 2011 10:36:34 +0530,
> Vinod Koul wrote:
> > 
> > As agreed during the ASoC workshop in May 2011, this set of patches are a
> > proposal from Intel to add a new compressed data interface to ALSA. This
> > proposal builds on the existing Intel solution and the experience gathered over
> > two years with Meego and Android solutions. This proposal is no longer
> > Intel-specific and was generalized with the addition of a basic core;
> > codec-related definitions are based on the vendor-neutral OpenMAX AL standard. 
> > 
> > These patches are also available in git tree:
> > git://git.infradead.org/users/vkoul/snd-compress.git v5_patches
> 
> I applied all patches now.  Please check later the sound git tree
> whether everything is OK.
Thanks Takashi.

Checked the patches looks fine.
I will also test from your tree and (clone in progress) and let you know
as well

Thanks
-- 
~Vinod

^ permalink raw reply	[flat|nested] 133+ messages in thread

end of thread, other threads:[~2011-12-23 11:37 UTC | newest]

Thread overview: 133+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-02  6:06 [RFC 0/5] compress: add compress data API to ALSA kernel Vinod Koul
2011-09-02  6:06 ` [RFC 1/5] compress API documentation Vinod Koul
2011-09-02  6:06 ` [RFC 2/5] compress: add compress parameter definations Vinod Koul
2011-09-02  6:49   ` Paul Menzel
2011-09-02 19:54     ` Pierre-Louis Bossart
2011-09-03  6:28       ` Mark Brown
2011-09-02 14:19   ` Mark Brown
2011-09-02 19:26     ` Pierre-Louis Bossart
2011-09-03  0:05       ` Mark Brown
2011-09-02  6:06 ` [RFC 3/5] compress: add API header and driver header files Vinod Koul
2011-09-02 13:36   ` Clemens Ladisch
2011-09-03  2:59     ` Vinod Koul
2011-09-02  6:06 ` [RFC 4/5] compress: add the core file Vinod Koul
2011-09-02 14:36   ` Mark Brown
2011-09-03  3:06     ` Vinod Koul
2011-09-05 17:43       ` Mark Brown
2011-09-05 21:21         ` Vinod Koul
2011-09-07 13:59   ` Dimitris Papastamos
2011-09-07 14:12     ` Dimitris Papastamos
2011-09-07 18:00       ` Vinod Koul
2011-09-07 15:20   ` Dimitris Papastamos
2011-09-07 18:05     ` Vinod Koul
2011-09-08 10:38   ` Dimitris Papastamos
2011-09-08 23:18     ` Vinod Koul
2011-09-22 13:01   ` Dimitris Papastamos
2011-09-23  5:41     ` Vinod Koul
2011-09-23 11:07       ` Vinod Koul
2011-09-02  6:06 ` [RFC 5/5] compress: add makefile and kconfig file Vinod Koul
2011-09-02 11:30 ` [RFC 0/5] compress: add compress data API to ALSA kernel Mark Brown
2011-09-02 14:04   ` Pierre-Louis Bossart
     [not found]   ` <000601cc6979$437b11c0$ca713540$@bossart@linux.intel.com>
2011-09-02 14:23     ` Mark Brown
2011-11-22  8:51 ` [PATCH 0/6] " Vinod Koul
2011-12-05  7:39   ` [PATCH v3 0/6] core: " Vinod Koul
2011-12-06  7:27     ` Jassi Brar
2011-12-06  8:07       ` Vinod Koul
2011-12-07 10:04     ` Vinod Koul
2011-12-07 16:15       ` Mark Brown
2011-12-13  9:02     ` [PATCH v4 " Vinod Koul
2011-12-13  9:02     ` [PATCH v4 1/6] compress API documentation Vinod Koul
2011-12-13  9:02     ` [PATCH v4 2/6] core: add support for compressed devices Vinod Koul
2011-12-22  7:34       ` Takashi Iwai
2011-12-22  8:15         ` Vinod Koul
2011-12-13  9:02     ` [PATCH v4 3/6] core: add compress parameter definations Vinod Koul
2011-12-22  7:35       ` Takashi Iwai
2011-12-22  8:16         ` Vinod Koul
2011-12-13  9:02     ` [PATCH v4 4/6] core: add API header and driver header files Vinod Koul
2011-12-13  9:02     ` [PATCH v4 5/6] core: add support for compress_offload Vinod Koul
2011-12-13 12:48       ` Nallasellan, Singaravelan
2011-12-13 14:12         ` Vinod Koul
2011-12-13 16:02           ` Nallasellan, Singaravelan
2011-12-13 17:53             ` Vinod Koul
2011-12-14  5:17               ` Nallasellan, Singaravelan
2011-12-20  9:26                 ` Vinod Koul
2011-12-22  7:55       ` Takashi Iwai
2011-12-22  8:19         ` Vinod Koul
2011-12-22  8:27           ` Takashi Iwai
2011-12-22  8:31             ` Vinod Koul
2011-12-22  8:44               ` Takashi Iwai
2011-12-22  8:48                 ` Vinod Koul
2011-12-22  8:51                   ` Takashi Iwai
2011-12-13  9:03     ` [PATCH v4 6/6] core: add makefile and kconfig file for compress Vinod Koul
2011-12-23  5:06     ` [PATCH v5 0/6] core: add compress data API to ALSA kernel Vinod Koul
2011-12-23  9:37       ` Takashi Iwai
2011-12-23 11:37         ` Vinod Koul
2011-12-23  5:06     ` [PATCH v5 1/6] compress offload API documentation Vinod Koul
2011-12-23  5:06     ` [PATCH v5 2/6] core: add support for compressed devices Vinod Koul
2011-12-23  5:06     ` [PATCH v5 3/6] core: add compress parameter definations Vinod Koul
2011-12-23  5:06     ` [PATCH v5 4/6] core: add API header and driver header files Vinod Koul
2011-12-23  5:06     ` [PATCH v5 5/6] core: add support for compress_offload Vinod Koul
2011-12-23  5:06     ` [PATCH v5 6/6] core: add makefile and kconfig file for compress Vinod Koul
2011-12-05  7:39   ` [PATCH v3 1/6] compress API documentation Vinod Koul
2011-12-05  7:39   ` [PATCH v3 2/6] core: add support for compressed devices Vinod Koul
2011-12-05  7:39   ` [PATCH v3 3/6] core: add compress parameter definations Vinod Koul
2011-12-05  7:39   ` [PATCH v3 4/6] core: add API header and driver header files Vinod Koul
2011-12-13  6:11     ` Mark Brown
2011-12-13  6:31       ` Vinod Koul
2011-12-13  7:03         ` Takashi Iwai
2011-12-13  7:50           ` Vinod Koul
2011-12-13  7:53             ` Mark Brown
2011-12-13  9:03               ` Vinod Koul
2011-12-05  7:39   ` [PATCH v3 5/6] core: add support for compress_offload Vinod Koul
2011-12-13  6:09     ` Mark Brown
2011-12-13  6:29       ` Vinod Koul
2011-12-05  7:39   ` [PATCH v3 6/6] core: add makefile and kconfig file for compress Vinod Koul
2011-11-22  8:51 ` [PATCH 1/6] compress API documentation Vinod Koul
2011-11-22  8:51 ` [PATCH 2/6] core: add support for compressed devices Vinod Koul
2011-11-23 11:30   ` Mark Brown
2011-11-22  8:51 ` [PATCH 3/6] compress: add compress parameter definations Vinod Koul
2011-11-23 16:32   ` Mark Brown
2011-11-22  8:51 ` [PATCH 4/6] compress: add API header and driver header files Vinod Koul
2011-11-22 11:18   ` Clemens Ladisch
2011-11-22 13:14     ` Vinod Koul
2011-12-02 15:39   ` Nallasellan, Singaravelan
2011-12-02 18:58     ` Pierre-Louis Bossart
     [not found]     ` <000301ccb124$72a53370$57ef9a50$@bossart@linux.intel.com>
2011-12-04  7:41       ` Nallasellan, Singaravelan
2011-12-05 14:14         ` Pierre-Louis Bossart
     [not found]         ` <000001ccb358$2b9e4b70$82dae250$@bossart@linux.intel.com>
2011-12-05 14:19           ` Mark Brown
2011-12-06  2:55             ` Nallasellan, Singaravelan
2011-11-22  8:51 ` [PATCH 5/6] compress: add the core file Vinod Koul
2011-11-23 16:02   ` Mark Brown
2011-11-23 16:16     ` Vinod Koul
2011-11-23 16:31       ` Mark Brown
2011-11-23 16:34         ` Vinod Koul
2011-11-23 17:03   ` Takashi Iwai
2011-11-24  3:45     ` Vinod Koul
2011-11-24  8:51       ` Takashi Iwai
2011-11-24  9:32         ` Vinod Koul
2011-11-28 21:36           ` Pierre-Louis Bossart
     [not found]           ` <001201ccae15$c24d8bf0$46e8a3d0$@bossart@linux.intel.com>
2011-11-29  7:21             ` Takashi Iwai
2011-11-29 21:15               ` Pierre-Louis Bossart
     [not found]               ` <003001ccaedb$f4e30010$dea90030$@bossart@linux.intel.com>
2011-11-30 10:30                 ` Mark Brown
2011-11-30 11:19                 ` Takashi Iwai
2011-11-30 11:29                   ` Vinod Koul
2011-11-30 11:41                     ` Takashi Iwai
2011-11-30 12:00                       ` Vinod Koul
2011-11-28 21:19     ` Pierre-Louis Bossart
     [not found]     ` <000f01ccae13$78fe38c0$6afaaa40$@bossart@linux.intel.com>
2011-11-29  7:31       ` Takashi Iwai
2011-12-01 13:28       ` Nallasellan, Singaravelan
2011-12-02  6:44         ` Vinod Koul
2011-12-02 10:17           ` Nallasellan, Singaravelan
2011-12-02 11:48             ` Vinod Koul
2011-12-02 16:24   ` Nallasellan, Singaravelan
2011-12-04  4:31     ` Vinod Koul
2011-12-04  8:14       ` Nallasellan, Singaravelan
2011-12-05 15:19         ` Pierre-Louis Bossart
     [not found]         ` <001501ccb361$3af49990$b0ddccb0$@bossart@linux.intel.com>
2011-12-06  3:00           ` Nallasellan, Singaravelan
2011-12-06  6:03             ` Vinod Koul
2011-12-06  8:07               ` Nallasellan, Singaravelan
2011-12-06 20:15             ` Pierre-Louis Bossart
     [not found]             ` <4ede780f.890bb50a.54a3.ffffcc4dSMTPIN_ADDED@mx.google.com>
     [not found]               ` <CAKg5Tpo6LgirbVVe9ZXNGN-xq7FTZvgAXNQ2HnXh=gwQHjn_Pw@mail.gmail.com>
2011-12-07 16:53                 ` Nallasellan, Singaravelan
2011-11-22  8:52 ` [PATCH 6/6] compress: add makefile and kconfig file Vinod Koul
2011-11-23 16:03   ` Mark Brown
2011-11-23 16:23     ` Vinod Koul

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.