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 스트림에서 수신 클럭을 파생하여 S/PDIF RX 섹션을 허용한다.
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 송신기는 오디오 데이터, 채널 상태 그리고 사용자 비트로 구성된 바이페이즈 마크 형식(IEC958)의 S/PDIF 출력 비트스트림을 생성한다.
S/PDIF 송신기에서, IEC958 바이페이즈 비트 스트림은 S/PDIF Transmit 클럭의 양쪽 에지에서 생성된다. S/PDIF Transmit은 S/PDIF 내부 클럭 분배기에 의해 생성되며, 소스는 S/PDIF 블럭 외부에서 가져온다. S/PDIF 수신기는 S/PDIF 스트림에서 S/PDIF Rx 클럭을 복구할 수 있다. 그림 30은 S/PDIF 트랜시버의 클럭 구조를 보여준다.
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/Documentation/sound/alsa/soc의 Linux 커널 문서에는 이러한 레이어에 대한 간결한 설명이 있다. S/PDIF 드라이버의 경우, ssi 스테레오 코덱 드라이버에서 사용하는 플랫폼 레이어(imx-pcm-dma.c)와 실제 코덱 없이 DAI 링크 생성에 유용한 일반 더미 코덱 드라이버를 재사용할 수 있다.
7.4.2 S/PDIF Tx Driver
S/PDIF Tx 드라이버는 아래 기능을지원한다.
- 32, 44.1 그리고 48KHz 샘플 전송률.
- 부호 있는 16과 24비트 리틀 엔디안 샘플 형식. S/PDIF SDMA 기능으로 인해, 24비트 출력 샘플 파일에는 프레임당 각 채널에 32비트가 있어야 한다. 이중 24개의 LSB만 유효하다.
- ALSA 서브 시스템에서, 지원되는 형식은 S16_LE와 S24_LE로 정의된다.
- 스테레오 재생.
- iecset 또는 amixer를 통한 정보 쿼리.
- 디바이스 ID는 재생 오디오 디바이스를 나열하는 "aplay -l" 유틸리티를 사용하여 확인할 수 있다.
예:
참고: IMX_SPDIF 라인의 시작 부분에 있는 숫자는 card ID 이다. 대괄호 안의 문자열은 card 이름이다.root@ ~$ aplay -l **** List of PLAYBACK Hardware Devices **** card 0: imxspdif [imx-spdif], device 0: S/PDIF PCM snd-socdummy-dai-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0
- ALSA 유틸리티는 사용자 공간 ALSA 드라이버를 작동하고 사용하는 일반적인 방법을 제공한다.
#aplay -Dplughw:0,0 audio.wav
참고: aplay의 -D 파라미터는 card ID와 PCM device ID가 hw:[card id],[pcm device id]인 PCM 디바이스를 나타낸다.
"iecset" 유틸리티는 IEC958 상태 비트를 설정하거나 덤프하는 일반적인 방법을 제공한다.
#iecset -c 0
7.4.2.1 Driver Design
S/PDIF 재생 전에, 구성, 인터럽트, 클럭 그리고 채널 레지스터가 초기화된다. S/PDIF 재생하는 동안, 채널 상태 비트는 고정된다. DMA 채널과 인터럽트는 활성화된다. S/PDIF에는 Left와 Right 채널에 각각 16개의 Tx 샘플 FIFO를 갖는다. 두 FIFO가 모두 비어 있을 때, empty 인터럽트가 활성화되어 있는 경우, empty 인터럽트가 생성된다. 20.8μs(1/48000) 동안 데이터가 다시 채워지지 않으면, underrun 인터럽트가 생성된다. 매번 각 채널에 대해 16개의 샘플 FIFO만 채워진 경우, overrun이 방지된다. 자동 재동기화가 활성화되는 경우, 하드웨어는 좌측과 우측 FIFO 동기화되어 있는지 확인하고, 그렇지 않으면 우측 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 그리고 96KHz 수신 샘플 속도.
- 부호 있는 24비트 리틀 엔디안 샘플 형식. S/PDIF SDMA 기능으로 인해, PCM 기록 프레임의 각 채널 비트 길이는 32비트이며, 이중 24개의 LSB만 유효하다. ALSA 서브시스템에서 지원되는 형식은 S24_LE로 정의된다.
- 스테레오 녹음
- device 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-socdummy-dai-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0
- ALSA 유틸리티는 ALSA 드라이버를 작동하고 사용할 수 있는 사용자 공간을 위한 일반적인 방법을 제공한다.
#arecord -Dplughw:1,0" -c 2 -r 44100 -f S24_LE record.wav
참고: arecord의 -D 파라미터는 card ID와 PCM device ID가 hw:[card id],[pcm device id]인 PCM 디바이스를 나타낸다.
"iecset" 유틸리티는 IEC958 상태 비트를 설정하거나 덤프하는 일반적인 방법을 제공한다.
#iecset -c 1
7.4.3.1 Driver Design
드라이버가 S/PDIF 수신기 FIFO에서 데이터 프레임을 읽으려면, 내부 DPLL이 잠길 때까지 기다려야 한다. 고속 시스템 클럭을 사용하는 내부 DPLL은 입력 비트 스트림에서 비트 클럭(고급 펄스)을 추출할 수 있다. 이 내부 DPLL이 잠기면, PhaseConfig Register의 LOCK 비트가 설정되고 드라이버가 인터럽트, 클럭 그리고 SDMA 채널을 구성한다. 그런 다음, 드라이버는 오디오 데이터, 채널 상태, 사용자 비트 그리고 유효 비트를 동시에 수신할 수 있다.
채널의 상태 수신을 위해, 총 48개의 채널 상태 비트가 2개의 레지스터에 수신된다. 드라이버는 사용자 애플리케이션이 요청할 때 이를 읽는다.
사용자 비트 수신의 경우, User Channel 수신에 CD와 non-CD의 두 가지 모드가 있다. 모드는 USyncMode(CDText_Control 레지스터의 비트 1)에 의해 결정된다. 사용자는 모드(Table 82 참조)를 설정하기 위해 사운드 컨트롤 인터페이스를 호출할 수 있지만, 모드가 무엇이든 드라이버는 동일한 방법으로 사용자 비트를 처리한다. S/PDIF Rx의 경우, 하드웨어 블럭은 사용자 비트에서 QChannel 레지스터로 Q 비트를 복사하고, 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 82. 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 주파수 측정 모듈로 인해 정확하지는 않다. 따라서 사용자 애플리케이션은 가져온 값을 보정해야 한다. |
USync Mode |
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 | Byte array 96 bytes for U bits 12 bytes for Q bits |
- |
No good V bit |
Sound Control |
r | Boolean Value: 0 or 1 |
인터럽트는 유효한 플래그와 연결된다.(인터럽트 16 - SPDIFValNoGood). 이 인터럽트는 유효한 비트가 무효로 설정된 SPDIF 인터페이스에서 프레임이 보일 때마다 설정된다. |
(1) Mode 열에는 인터페이스 속성인 r(읽기) 나 w(쓰기)를 표시된다.
(2) 사운드 컨트롤 유형의 인터페이스는 snd_ctl_xxx() alsa-lib 함수에 의해 호출된다.
사용자 애플리케이션은 S/PDIF Rx 드라이버를 사용하기 위해 Figure 31의 프로그램 흐름을 따를 수 있다. 먼저, 애플리케이션은 S/PDIF Rx PCM 디바이스를 열고(open), DPLL이 입력 비트 스트림을 잠글 때까지 대기한 다음, 입력 샘플 속도를 가져온다. USyncMode를 설정해야 하는 경우, U/Q 비트를 읽기 전에 설정해야 한다. 다음으로 드라이버에서 얻은 채널 번호, 형식과 캡처 샘플 속도를 포함한 하드웨어 파라미터를 설정한다. 그런 다음, prepare를 호출하고 S/PDIF Rx 스트림 읽기를 시작하도록 트리거한다. 마지막으로 read 함수를 호출하여 데이터를 가져온다. 읽기 처리 동안, 애플리케이션은 드라이버에서 U/Q 비트와 채널 상태를 읽고 불량 비트를 유효화할 수 있다.
7.4.4 Source Code Structure
아래 테이블에는 드라이버의 소스 파일이 나열되어 있다.
Table 83. S/PDIF Driver Files
File | Description |
---|---|
sound/soc/soc-utils.c | 더미 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 Interrupts and Exceptions
S/PDIF Tx/Rx 하드웨어 블럭에는 성공, 예외 그리고 이벤트를 나타내는 많은 인터럽트가 있다.
드라이버는 아래 인터럽트를 처리한다:
- 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 -D hw:[card id],[pcm id] -c 2 -d 20 -r [sample rate in Hz] -f S24_LE record.wav
참고:
arecord 커맨드의 샘플 속도 인수는 WaveLab에서 재생되는 WAV 파일과 일치해야 한다.