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
  12static int create_iec958_consumer(uint rate, uint sample_width,
  13                                  u8 *cs, size_t len)
  14{
  15        unsigned int fs, ws;
  16
  17        if (len < 4)
  18                return -EINVAL;
  19
  20        switch (rate) {
  21        case 32000:
  22                fs = IEC958_AES3_CON_FS_32000;
  23                break;
  24        case 44100:
  25                fs = IEC958_AES3_CON_FS_44100;
  26                break;
  27        case 48000:
  28                fs = IEC958_AES3_CON_FS_48000;
  29                break;
  30        case 88200:
  31                fs = IEC958_AES3_CON_FS_88200;
  32                break;
  33        case 96000:
  34                fs = IEC958_AES3_CON_FS_96000;
  35                break;
  36        case 176400:
  37                fs = IEC958_AES3_CON_FS_176400;
  38                break;
  39        case 192000:
  40                fs = IEC958_AES3_CON_FS_192000;
  41                break;
  42        default:
  43                return -EINVAL;
  44        }
  45
  46        if (len > 4) {
  47                switch (sample_width) {
  48                case 16:
  49                        ws = IEC958_AES4_CON_WORDLEN_20_16;
  50                        break;
  51                case 18:
  52                        ws = IEC958_AES4_CON_WORDLEN_22_18;
  53                        break;
  54                case 20:
  55                        ws = IEC958_AES4_CON_WORDLEN_20_16 |
  56                             IEC958_AES4_CON_MAX_WORDLEN_24;
  57                        break;
  58                case 24:
  59                case 32: /* Assume 24-bit width for 32-bit samples. */
  60                        ws = IEC958_AES4_CON_WORDLEN_24_20 |
  61                             IEC958_AES4_CON_MAX_WORDLEN_24;
  62                        break;
  63
  64                default:
  65                        return -EINVAL;
  66                }
  67        }
  68
  69        memset(cs, 0, len);
  70
  71        cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
  72        cs[1] = IEC958_AES1_CON_GENERAL;
  73        cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
  74        cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs;
  75
  76        if (len > 4)
  77                cs[4] = ws;
  78
  79        return len;
  80}
  81
  82/**
  83 * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
  84 * @runtime: pcm runtime structure with ->rate filled in
  85 * @cs: channel status buffer, at least four bytes
  86 * @len: length of channel status buffer
  87 *
  88 * Create the consumer format channel status data in @cs of maximum size
  89 * @len corresponding to the parameters of the PCM runtime @runtime.
  90 *
  91 * Drivers may wish to tweak the contents of the buffer after creation.
  92 *
  93 * Returns: length of buffer, or negative error code if something failed.
  94 */
  95int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
  96        size_t len)
  97{
  98        return create_iec958_consumer(runtime->rate,
  99                                      snd_pcm_format_width(runtime->format),
 100                                      cs, len);
 101}
 102EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
 103
 104/**
 105 * snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status
 106 * @hw_params: the hw_params instance for extracting rate and sample format
 107 * @cs: channel status buffer, at least four bytes
 108 * @len: length of channel status buffer
 109 *
 110 * Create the consumer format channel status data in @cs of maximum size
 111 * @len corresponding to the parameters of the PCM runtime @runtime.
 112 *
 113 * Drivers may wish to tweak the contents of the buffer after creation.
 114 *
 115 * Returns: length of buffer, or negative error code if something failed.
 116 */
 117int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
 118                                             u8 *cs, size_t len)
 119{
 120        return create_iec958_consumer(params_rate(params), params_width(params),
 121                                      cs, len);
 122}
 123EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);
 124