linux/sound/core/pcm_iec958.c
<<
>>
Prefs
   1/*
   2 *  PCM DRM helpers
   3 *
   4 *   This program is free software; you can redistribute it and/or modify
   5 *   it under the terms of the GNU General Public License version 2 as
   6 *   published by the Free Software Foundation.
   7 */
   8#include <linux/export.h>
   9#include <linux/types.h>
  10#include <sound/asoundef.h>
  11#include <sound/pcm.h>
  12#include <sound/pcm_iec958.h>
  13
  14/**
  15 * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
  16 * @runtime: pcm runtime structure with ->rate filled in
  17 * @cs: channel status buffer, at least four bytes
  18 * @len: length of channel status buffer
  19 *
  20 * Create the consumer format channel status data in @cs of maximum size
  21 * @len corresponding to the parameters of the PCM runtime @runtime.
  22 *
  23 * Drivers may wish to tweak the contents of the buffer after creation.
  24 *
  25 * Returns: length of buffer, or negative error code if something failed.
  26 */
  27int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
  28        size_t len)
  29{
  30        unsigned int fs, ws;
  31
  32        if (len < 4)
  33                return -EINVAL;
  34
  35        switch (runtime->rate) {
  36        case 32000:
  37                fs = IEC958_AES3_CON_FS_32000;
  38                break;
  39        case 44100:
  40                fs = IEC958_AES3_CON_FS_44100;
  41                break;
  42        case 48000:
  43                fs = IEC958_AES3_CON_FS_48000;
  44                break;
  45        case 88200:
  46                fs = IEC958_AES3_CON_FS_88200;
  47                break;
  48        case 96000:
  49                fs = IEC958_AES3_CON_FS_96000;
  50                break;
  51        case 176400:
  52                fs = IEC958_AES3_CON_FS_176400;
  53                break;
  54        case 192000:
  55                fs = IEC958_AES3_CON_FS_192000;
  56                break;
  57        default:
  58                return -EINVAL;
  59        }
  60
  61        if (len > 4) {
  62                switch (snd_pcm_format_width(runtime->format)) {
  63                case 16:
  64                        ws = IEC958_AES4_CON_WORDLEN_20_16;
  65                        break;
  66                case 18:
  67                        ws = IEC958_AES4_CON_WORDLEN_22_18;
  68                        break;
  69                case 20:
  70                        ws = IEC958_AES4_CON_WORDLEN_20_16 |
  71                             IEC958_AES4_CON_MAX_WORDLEN_24;
  72                        break;
  73                case 24:
  74                        ws = IEC958_AES4_CON_WORDLEN_24_20 |
  75                             IEC958_AES4_CON_MAX_WORDLEN_24;
  76                        break;
  77
  78                default:
  79                        return -EINVAL;
  80                }
  81        }
  82
  83        memset(cs, 0, len);
  84
  85        cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
  86        cs[1] = IEC958_AES1_CON_GENERAL;
  87        cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
  88        cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs;
  89
  90        if (len > 4)
  91                cs[4] = ws;
  92
  93        return len;
  94}
  95EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
  96