linux/sound/core/pcm_iec958.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  PCM DRM helpers
   4 */
   5#include <linux/export.h>
   6#include <linux/types.h>
   7#include <sound/asoundef.h>
   8#include <sound/pcm.h>
   9#include <sound/pcm_params.h>
  10#include <sound/pcm_iec958.h>
  11
  12/**
  13 * snd_pcm_create_iec958_consumer_default - create default consumer format IEC958 channel status
  14 * @cs: channel status buffer, at least four bytes
  15 * @len: length of channel status buffer
  16 *
  17 * Create the consumer format channel status data in @cs of maximum size
  18 * @len. When relevant, the configuration-dependant bits will be set as
  19 * unspecified.
  20 *
  21 * Drivers should then call einter snd_pcm_fill_iec958_consumer() or
  22 * snd_pcm_fill_iec958_consumer_hw_params() to replace these unspecified
  23 * bits by their actual values.
  24 *
  25 * Drivers may wish to tweak the contents of the buffer after creation.
  26 *
  27 * Returns: length of buffer, or negative error code if something failed.
  28 */
  29int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len)
  30{
  31        if (len < 4)
  32                return -EINVAL;
  33
  34        memset(cs, 0, len);
  35
  36        cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
  37        cs[1] = IEC958_AES1_CON_GENERAL;
  38        cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
  39        cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | IEC958_AES3_CON_FS_NOTID;
  40
  41        if (len > 4)
  42                cs[4] = IEC958_AES4_CON_WORDLEN_NOTID;
  43
  44        return len;
  45}
  46EXPORT_SYMBOL_GPL(snd_pcm_create_iec958_consumer_default);
  47
  48static int fill_iec958_consumer(uint rate, uint sample_width,
  49                                u8 *cs, size_t len)
  50{
  51        if (len < 4)
  52                return -EINVAL;
  53
  54        if ((cs[3] & IEC958_AES3_CON_FS) == IEC958_AES3_CON_FS_NOTID) {
  55                unsigned int fs;
  56
  57                switch (rate) {
  58                        case 32000:
  59                                fs = IEC958_AES3_CON_FS_32000;
  60                                break;
  61                        case 44100:
  62                                fs = IEC958_AES3_CON_FS_44100;
  63                                break;
  64                        case 48000:
  65                                fs = IEC958_AES3_CON_FS_48000;
  66                                break;
  67                        case 88200:
  68                                fs = IEC958_AES3_CON_FS_88200;
  69                                break;
  70                        case 96000:
  71                                fs = IEC958_AES3_CON_FS_96000;
  72                                break;
  73                        case 176400:
  74                                fs = IEC958_AES3_CON_FS_176400;
  75                                break;
  76                        case 192000:
  77                                fs = IEC958_AES3_CON_FS_192000;
  78                                break;
  79                        default:
  80                                return -EINVAL;
  81                }
  82
  83                cs[3] &= ~IEC958_AES3_CON_FS;
  84                cs[3] |= fs;
  85        }
  86
  87        if (len > 4 &&
  88            (cs[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) {
  89                unsigned int ws;
  90
  91                switch (sample_width) {
  92                case 16:
  93                        ws = IEC958_AES4_CON_WORDLEN_20_16;
  94                        break;
  95                case 18:
  96                        ws = IEC958_AES4_CON_WORDLEN_22_18;
  97                        break;
  98                case 20:
  99                        ws = IEC958_AES4_CON_WORDLEN_20_16 |
 100                             IEC958_AES4_CON_MAX_WORDLEN_24;
 101                        break;
 102                case 24:
 103                case 32: /* Assume 24-bit width for 32-bit samples. */
 104                        ws = IEC958_AES4_CON_WORDLEN_24_20 |
 105                             IEC958_AES4_CON_MAX_WORDLEN_24;
 106                        break;
 107
 108                default:
 109                        return -EINVAL;
 110                }
 111
 112                cs[4] &= ~IEC958_AES4_CON_WORDLEN;
 113                cs[4] |= ws;
 114        }
 115
 116        return len;
 117}
 118
 119/**
 120 * snd_pcm_fill_iec958_consumer - Fill consumer format IEC958 channel status
 121 * @runtime: pcm runtime structure with ->rate filled in
 122 * @cs: channel status buffer, at least four bytes
 123 * @len: length of channel status buffer
 124 *
 125 * Fill the unspecified bits in an IEC958 status bits array using the
 126 * parameters of the PCM runtime @runtime.
 127 *
 128 * Drivers may wish to tweak the contents of the buffer after its been
 129 * filled.
 130 *
 131 * Returns: length of buffer, or negative error code if something failed.
 132 */
 133int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime,
 134                                 u8 *cs, size_t len)
 135{
 136        return fill_iec958_consumer(runtime->rate,
 137                                    snd_pcm_format_width(runtime->format),
 138                                    cs, len);
 139}
 140EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer);
 141
 142/**
 143 * snd_pcm_fill_iec958_consumer_hw_params - Fill consumer format IEC958 channel status
 144 * @params: the hw_params instance for extracting rate and sample format
 145 * @cs: channel status buffer, at least four bytes
 146 * @len: length of channel status buffer
 147 *
 148 * Fill the unspecified bits in an IEC958 status bits array using the
 149 * parameters of the PCM hardware parameters @params.
 150 *
 151 * Drivers may wish to tweak the contents of the buffer after its been
 152 * filled..
 153 *
 154 * Returns: length of buffer, or negative error code if something failed.
 155 */
 156int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
 157                                           u8 *cs, size_t len)
 158{
 159        return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
 160}
 161EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer_hw_params);
 162
 163/**
 164 * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
 165 * @runtime: pcm runtime structure with ->rate filled in
 166 * @cs: channel status buffer, at least four bytes
 167 * @len: length of channel status buffer
 168 *
 169 * Create the consumer format channel status data in @cs of maximum size
 170 * @len corresponding to the parameters of the PCM runtime @runtime.
 171 *
 172 * Drivers may wish to tweak the contents of the buffer after creation.
 173 *
 174 * Returns: length of buffer, or negative error code if something failed.
 175 */
 176int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
 177        size_t len)
 178{
 179        int ret;
 180
 181        ret = snd_pcm_create_iec958_consumer_default(cs, len);
 182        if (ret < 0)
 183                return ret;
 184
 185        return snd_pcm_fill_iec958_consumer(runtime, cs, len);
 186}
 187EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
 188
 189/**
 190 * snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status
 191 * @params: the hw_params instance for extracting rate and sample format
 192 * @cs: channel status buffer, at least four bytes
 193 * @len: length of channel status buffer
 194 *
 195 * Create the consumer format channel status data in @cs of maximum size
 196 * @len corresponding to the parameters of the PCM runtime @runtime.
 197 *
 198 * Drivers may wish to tweak the contents of the buffer after creation.
 199 *
 200 * Returns: length of buffer, or negative error code if something failed.
 201 */
 202int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
 203                                             u8 *cs, size_t len)
 204{
 205        int ret;
 206
 207        ret = snd_pcm_create_iec958_consumer_default(cs, len);
 208        if (ret < 0)
 209                return ret;
 210
 211        return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
 212}
 213EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);
 214