7.4 The Sony/Philips Digital Interface (S/PDIF)
7.4.1 Introduction
Sony/Philips Digital Interface (S/PDIF) 오디오 모듈은 프로세서가 디지털 오디오를 송수신할 수 있도록 하는 스테레오 트랜시버이다. S/PDIF 트랜시버는 S/PDIF의 채널 상태(CS)와 사용자 (U) 데이터를 모두 처리할 수 있다. 주파수 측정 블록은 S/PDIF RX 섹션이 들어오는 S/PDIF 스트림에서 수신 clock을 유도할 수 있도록 한다.
7.4.1.1 S/PDIF Overview
아래 그림은 S/PDIF 인터페이스의 블록 다이어그램을 보여준다.
7.4.1.2 Hardware Overview
S/PDIF는 두 부분으로 구성된다:
- S/PDIF 수신기는 각 S/PDIF 프레임에서 오디오 데이터를 추출하고 S/PDIF Rx의 왼쪽과 오른쪽 FIFO에 데이터를 배치한다. Channel Status와 User Bits도 각 프레임에서 추출되고 해당 레지스터에 배치된다. S/PDIF 수신기는 S/PDIF 입력 신호를 S/PDIF 송신기로 직접 전송하기 위한 바이패스 옵션을 제공한다.
- S/PDIF 송신기의 경우, 오디오 데이터는 SPDIFTxLeft와 SPDIFTxRight 레지스터로 프로세스에 의해 제공된다. Channel Status 비트는 해당 레지스터로 제공된다. S/PDIF 송신기는 오디오 데이터, 채널 상태와 사용자 비트로 구성된 2상(biphase) 마크 형식(IEC958)의 S/PDIF 출력 비트 스트림을 생성한다.
S/PDIF 송신기에서, IEC958 2상 비트 스트림은 S/PDIF Transmit clock의 양쪽 에지에서 생성된다. S/PDIF Transmit clock은 S/PDIF 내부 clock 분배기에 의해 생성되며 소스는 S/PDIF 블록 외부에 있다. S/PDIF 수신기는 S/PDIF 스트림에서 S/PDIF Rx clock을 복구할 수 있다. Figure 29는 S/PDIF 트랜시버의 clock 구조를 보여준다.
7.4.1.3 Software Overview
S/PDIF 드라이버는 ALSA System on Chip (ASoC) 레이어에서 설계되었다. S/PDIF용 ASoC 드라이버는 하나의 Tx용 재생 디바이스와 하나의 Rx용 캡처 디바이스를 제공한다. 오디오 재생 출력 형식은 선형 PCM 데이터나 16비트, 20비트 및 24비트 오디오 압축 데이터일 수 있다. 허용되는 샘플링 비트 속도는 44.1, 48나 32 KHz이다. 오디오 캡처 입력 형식은 선형 PCM 데이터나 압축된 24비트 데이터일 수 있으며, 허용되는 샘플링 비트 속도는 16 ~ 96KHz이다. 드라이버는 PCM과 압축된 데이터 전송에 동일한 인터페이스를 제공한다.
7.4.1.4 ASoC Layer
ASoC 레이어는 재사용할 수 있는 별도의 레이어로 임베디드 플랫폼을 위한 오디오 드라이버를 나눈다. ASoC는 코덱 드라이버, 머신 레이어, DAI(Digital Audio Interface) 레이어와 플랫폼 레이어로 오디오 드라이버를 나눈다. Linux 커널 문서인 linux/Documentation/sound/alsa/soc에 이러한 레이어에 대한 간략한 설명이 있다. S/PDIF 드라이버의 경우, ssi 스테레오 코덱 드라이버에서 사용되는 플랫폼 레이어(imx-pcm-dma.c)와 실제 코덱이 없이 DAI 링크 생성에 유용한 일반 더미 코덱 드라이버를 재사용할 수 있다.
7.4.2 S/PDIF Tx Driver
S/PDIF Tx 드라이버는 아래 기능을 지원한다.
- 32, 44.1와 48 KHz 샘플링 속도
- 부호 있는 16와 24비트 리틀 엔디안 샘플링 형식. S/PDIF SDMA 기능으로 인해, 24비트 출력 샘플링 파일은 각 채널의 프레임당 32비트가 있어야 한다. 24개의 LSB만 유효하다.
- ALSA 서브시스템에서 지원되는 형식은 S16_LE와 S24_LE로 정의된다.
- 스테레오 재생
- iecset이나 amixer를 통해 정보를 조회.
- 디바이스 ID는 'aplay -l' 유틸리티를 사용하여 재생 오디오 디바이스를 나열하여 확인할 수 있다.
예를 들면:
참고 : IMX_SPDIF 라인의 시작 부분에 있는 숫자는 카드 ID이다. 대괄호 안의 문자열은 카드 이름이다.root@ ~$ aplay -l **** List of PLAYBACK Hardware Devices **** card 0: imxspdif [imx-spdif], device 0: S/PDIF PCM snd-soc-dummy-dai-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0
- ALSA 유틸리티는 사용자 공간에서 ALSA 드라이버를 작동하고 사용하는 일관된 방법을 제공한다.
참고 : aplay의 -D 파라미터는 카드 ID와 PCM 디바이스 ID(hw:[card id],[pcm device id])가 있는 PCM 디바이스를 나타낸다.#aplay -Dplughw:0,0 audio.wav
"iecset" 유틸리티는 IEC958 상태 비트를 설정하거나 덤프하는 일관된 방법을 제공한다.
#iecset -c 0
7.4.2.1 Driver Design
S/PDIF 재생 전에, 구성, 인터럽트, clock와 채널 레지스터가 초기화된다. S/PDIF 재생 중에는, 채널 상태 비트가 고정된다. DMA와 인터럽트가 활성화된다. S/PDIF는 Left와 Right 채널에 각각 16개의 TX 샘플 FIFO를 가지고 있다. 두 FIFO가 모두 비어 있을 때, empty 인터럽트가 활성화 된 경우에 empty 인터럽트가 생성된다. 20.8 μs (1/48000) 안에 데이터가 다시 채워지지 않으면, underrun 인터럽트가 생성된다. 매번 각 채널에 대해 16개의 샘플 FIFO만 채워진다면 overrun은 방지된다. 자동 재동기화가 활성화되면, 하드웨어는 왼쪽과 오른쪽 FIFO가 sync되어 있는지 확인하고, 그렇지 않으면 오른쪽 FIFO의 채우기 포인터를 왼쪽 FIFO의 채우기 포인터와 동일하게 설정하고 인터럽트를 생성한다.
7.4.2.2 Provided User Interface
S/PDIF 송신기 드라이버는 공통된 PCM 작업 인터페이스 외에 사용자에게 하나의 ALSA 믹서 사운드 컨트롤 인터페이스를 제공한다. 사용자가 S/PDIF 채널 상태 코드를 드라이버에 기록하여 S/PDIF 스트림으로 보낼 수 있는 인터페이스를 제공한다. 이 인터페이스의 입력 파라미터는 아래 표시된 IEC958 디지털 오디오 구조체이며 status 멤버만 사용된다:
struct snd_aes_iec958 {
unsigned char status[24]; /* AES/IEC958 channel status bits */
unsigned char subcode[147]; /* AES/IEC958 subcode bits */
unsigned char pad; /* nothing */
unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */
};
7.4.3 S/PDIF Rx Driver
S/PDIF Rx 드라이버는 아래 기능을 지원한다:
- 16, 32, 44.1, 48, 64와 96 KHz 수신 샘플링 속도
- 부호있는 24비트의 리틀 엔디안 샘플링 형식. S/PDIF SDMA 기능으로 인해, PCM으로 기록된 프레임의 각 채널 비트 길이는 32비트이고, 이중 24개의 LSB만 유효하다.
ALSA 서브시스템에서 지원되는 형식은 S24_LE로 정의된다. - 스테레오 레코드
- 디바이스 ID는 레코드 디바이스를 나열하기 위한 'arecord -l'을 사용하여 확인할 수 있다.
예를 들어:
root@ ~$ arecord -l **** List of CAPTURE Hardware Devices **** card 0: cs42888audio [cs42888-audio], device 0: HiFi CS42888-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: imxspdif [imx-spdif], device 0: S/PDIF PCM snd-soc-dummy-dai-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0
- ALSA 유틸리티는 사용자 공간에서 ALSA 드라이버를 작동하고 사용할 수 있는 일관된 방법을 제공한다.
참고 : -D 파리미터는 카드 ID와 PCM 디바이스 ID가 있는 PCM 디바이스를 나타낸다(hw:[card id],[pcm device id]).#arecord -Dplughw:1,0" -c 2 -r 44100 -f S24_LE record.wav
'iecset' 유틸리티는 IEC958 상태 비트를 설정하거나 덤프하는 일관된 방법을 제공한다.
#iecset -c 1
7.4.3.1 Driver Design
드라이버가 S/PDIF 수신기 FIFO에서 데이터 프레임을 읽기 전에, 내부 DPLL이 잠길 때까지 대기해야 한다. 고속의 시스템 clock을 사용하여, 내부 DPLL은 입력 비트 스트림에서 비트 clock(고급 펄스)을 추출할 수 있다. 내부 DPLL이 잠겨 있을 때, PhaseConfig Register의 LOCK 비트가 설정되고 드라이버가 인터럽트, clock와 SDMA 채널을 구성한다. 그 후 드라이버는 오디오 데이터, 채널 상태, 사용자 비트와 유효 비트를 동시에 수신할 수 있다.
채널 상태 수신의 경우, 총 48개의 채널 상태 비트가 2개의 레지스터에 수신된다. 드라이버는 사용자 애플리케이션이 요청할 때 이 레지스터를 읽는다.
사용자 비트 수신의 경우, CD와 non-CD 두 가지 모드의 User Channel 수신이 있다. 모드는 USyncMode(CDText_Control 레지스터의 비트 1)에 의해 결정된다. 사용자는 사운드 컨트롤 인터페이스를 호출하여 모드(Table 83 참조)를 설정할 수 있지만, 모드가 무엇이든 드라이버는 사용자 비트를 동일한 방식으로 처리한다. S/PDIF Rx의 경우, 하드웨어 블록은 사용자 비트의 Q 비트를 QChannel 레지스터로 복사하고 사용자 비트를 UChannel 레지스터에 넣는다. 드라이버는 U 비트와 Q 비트 모두에 대해 두 개의 큐 버퍼를 할당한다. U 비트의 큐 버퍼는 96x2 바이트 크기, Q 비트의 큐 버퍼는 12x2 바이트 크기이고, 큐 버퍼는 U/Q Full, Err 및 Sync 인터럽트 핸들러에서 채워진다. 이것은 S/PDIF 드라이버가 새로운 U/Q 비트를 읽는 동안 사용자가 이전에 준비한 U/Q 비트를 얻을 수 있음을 의미한다.
유효한 비트 수신을 위해, S/PDIF Rx 하드웨어 블록은 인터럽트를 트리거하고 수신 시 인터럽트 상태를 설정한다. 사용자가 이 유효한 비트의 상태를 얻을 수 있도록 사운드 컨트롤 인터페이스가 제공된다.
7.4.3.2 Provided User Interface
S/PDIF Rx 드라이버는 아래 테이블과 같이 사용자 애플리케이션을 위한 인터페이스를 제공한다.
Table 83. S/PDIF Rx Driver Interfaces
Interface | Type | Mode 1 | Parameter | Comment |
Common PCM | PCM | - | - | PCM open/close prepare/trigger hw_params/sw_params |
Rx Sample Rate | Sound Control 2 | r | Integer Range: [16000, 96000] |
샘플링 속도를 가져온다. DPLL 주파수 측정 모듈로 인해 정확하지 않다. 따라서 사용자 애플리케이션은 가져온 값을 보정해야 한다. |
USyncMode | Sound Control | rw | Boolean Value: 0 or 1 |
CD 모드는 1로 설정 non-CD 모드는 0으로 설정 |
Channel Status | Sound Control | r | struct snd_aes_iec958 status[6] 배열 멤버만 사용된다. |
- |
User bit | Sound Control | r | 바이트 배열 U 비트 96 바이트 Q 비트 12 바이트 |
- |
No good V bit | Sound Control | r | Boolean Value: 0 or 1 |
인터럽트는 유효한 플래그와 연결된다(인터럽트 16 - SPDIFValNoGood). 이 인터럽트는 유효 비트가 무효로 설정된 SPDIF 인터페이스에서 프레임이 표시될 때마다 설정된다. |
1. 모드 열은 인터페이스 속성을 보여준다(r: read, w: write).
2. 인터페이스의 사운드 컨트롤 유형은 snd_ctl_xxx() alsa-lib 함수에 의해 호출된다.
사용자 애플리케이션은 Figure 30의 프로그램 흐름에 따라 S/PDIF Rx 드라이버를 사용할 수 있다. 먼저 애플리케이션은 S/PDIF Rx PCM 디바이스를 열고, DPLL이 입력 비트 스트림을 잠글 때까지 대기하고 입력 샘플링 속도를 가져온다. USyncMode를 설정해야 하는 경우, U/Q 비트를 읽기 전에 설정한다. 다음으로, 드라이버에서 얻은 채널 번호, 형식과 캡처 샘플링 속도를 포함하는 하드웨어 파라미터를 설정한다. 그런 다음, prepare와 trigger를 호출하여 S/PDIF Rx 스트림 읽기를 시작한다. 마지막으로 read 함수를 호출하여 데이터를 가져온다. 읽기 프로세스 동안, 애플리케이션은 드라이버에서 U/Q 비트와 채널 상태를 읽고 불량 비트를 유효화할 수 있다.
7.4.4 Source Code Structure
아래 테이블은 드라이버의 소스 파일이 나열되어 있다.
Table 84. S/PDIF Driver Files
File | Description |
sound/soc/soc-utils.c | Dummy ALSA SOC 코덱 드라이버 |
sound/soc/fsl/imx-spdif.c | S/PDIF ALSA SOC 머신 레이어 |
sound/soc/fsl/fsl_spdif.c | S/PDIF ALSA SOC DAI 레이어 |
sound/soc/fsl/imx-pcm-dma.c | ALSA SOC 플랫폼 레이어 |
sound/soc/fsl/imx-pcm.h | ALSA SOC 플랫폼 레이어 헤더 |
7.4.4.1 Menu Configuration Options
이 모듈에는 아래 Linux 커널 구성이 제공된다:
메뉴 구성에서 아래 모듈을 활성화한다:
- CONFIG_SND_IMX_SPDIF - S/PDIF 드라이버 구성 옵션:
- Device Drivers -> Sound card support -> Advanced Linux Sound Architecture -> ALSA for SoC audio support -> SoC Audio for Freescale i.MX CPUs -> SoC Audio support for i.MX boards with S/PDIF
7.4.4.2 Device Tree Bindings
아래 문서를 참조한다:
- Documentation/devicetree/bindings/sound/fsl,spdif.txt
- Documentation/devicetree/bindings/sound/imx-audio-spdif.txt
7.4.4.3 Interrupt and Exceptions
S/PDIF Tx/Rx 하드웨어 블록에는 success, exception와 event를 나타내는 많은 인터럽트가 있다.
드라이버는 아래 인터럽트를 처리한다:
- DPLL Lock와 Loss Lock - DPLL 잠금 상태를 저장한다. 이것은 Rx 샘플링 속도를 얻을 때 사용된다.
- U/Q Channel Full와 overrun/underrun - U/Q 채널 레지스터 데이터를 큐 버퍼에 넣고 큐 버퍼의 쓰기 포인터를 업데이트한다.
- U/Q Channel Sync - U/Q 데이터를 읽을 준비가 된 버퍼의 ID를 저장한다.
- U/Q Channel Error - U/Q 큐 버퍼를 재설정한다.
7.4.5 Unit Test Preparation
단위 테스트 실행을 준비하려면, 아래 작업을 수행한다:
- PC에 M-Audio Transit 드라이버를 설치하여, M-Audio Transit USB 사운드 카드를 설정한다.
- PC에 WaveLab 툴을 설치한다.
7.4.5.1 Tx test step
- 광 라인을 M-Audio transit의 [line|optical] 포트에 연결한다.
참고 : 광 라인을 연결한 후, M-Audio transit의 [optical out] 포트에 출력이 없는지(빨간불 꺼짐) 확인한다. - WaveLab을 시작하고 툴바의 녹음 버튼을 누르고 녹음 파일 이름, 샘플링 속도와 채널 수를 설정한 후 녹음한다.
- 한편, 온보드에서 아래 명령을 사용하여 하나의 웨이브 파일을 재생한다:
#aplay -D hw:[card id],[pcm id] audioXXkYYS.wav
- aplay가 끝나면, WaveLab에서 녹음을 중지한다.
- 녹음된 WAV 파일을 WaveLab에서 재생하여 확인한다.
7.4.5.2 Rx test step
- M-Audio transit의 [optical port]에 광 라인을 연결한다.
- WaveLab을 시작하고, 테스트 WAV 파일을 연다. 반복해서 audioXXkYYS.wav를 재생한다.
- 한편, 온보드에서 아래 명령을 사용하여 하나의 WAV 파일을 녹음한다. 녹음이 끝나면, 녹음된 WAV 파일을 보드나 PC의 다른 오디오 카드에서 재생할 수 있다.
참고 : arecord 명령어의 샘플링 속도 인수는 WaveLab에서 재생 중인 WAV 파일과 일치해야 한다.#arecord -D hw:[card id],[pcm id] -c 2 -d 20 -r [sample rate in Hz] -f S24_LE record.wav