snd_soc_dpcm_update : 실행할 runtime_update 값. 업데이트를 안할 것인지, BE 혹인 FE 를 업데이트할 것인지 나타냄 - SND_SOC_DPCM_UPDATE_NO - SND_SOC_DPCM_UPDATE_BE - SND_SOC_DPCM_UPDATE_FE
snd_soc_dpcm_link_state : 새로운 링크를 만들 것인지, 만들어진 링크를 분해할 것인지 나타냄 - SND_SOC_DPCM_LINK_STATE_NEW - SND_SOC_DPCM_LINK_STATE_FREE
snd_soc_dpcm_trigger : trigger 가 발생했을 때 어떤 trigger 가 발생했는지 나타냄 - SND_SOC_DPCM_TRIGGER_PRE - SND_SOC_DPCM_TRIGGER_HOST - SND_SOC_DPCM_TRIGGER_BESPOKE
Dynamic PCM link 구조체
이 구조체는 FE DAI 와 BE DAI 를 runtime 에 연결하고, link 상태와 hw_params 정보를 저장한다.
struct snd_soc_dpcm {
/* FE and BE DAIs*/
struct snd_soc_pcm_runtime *be;
struct snd_soc_pcm_runtime *fe;
/* link state */
enum snd_soc_dpcm_link_state state;
/* list of BE and FE for this DPCM link */
struct list_head list_be;
struct list_head list_fe;
/* hw params for this link - may be different for each link */
struct snd_pcm_hw_params hw_params;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_state;
#endif
};
struct snd_soc_dpcm_runtime {
struct list_head be_clients;
struct list_head fe_clients;
int users;
struct snd_pcm_runtime *runtime;
struct snd_pcm_hw_params hw_params;
/* state and update */
enum snd_soc_dpcm_update runtime_update;
enum snd_soc_dpcm_state state;
int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */
};
궁금증 .. dpcm API 들도 snd_soc_pcm_runtime 을 쓰는데, snd_soc_dpcm_runtime 은 언제 쓰이는지...?
-> 쫓아가봤는데 쓰이질 않음..
DPCM APIs
/* can this BE stop and free */ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe, struct snd_soc_pcm_runtime *be, int stream);
/* can this BE perform a hw_params() */ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe, struct snd_soc_pcm_runtime *be, int stream);
/* is the current PCM operation for this FE ? */ int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
/* is the current PCM operation for this BE ? */ int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe, struct snd_soc_pcm_runtime *be, int stream);
/* get the substream for this BE */ struct snd_pcm_substream * snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream);
/* get the BE runtime state */ enum snd_soc_dpcm_state snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream);
/* set the BE runtime state */ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, enum snd_soc_dpcm_state state);
이 케이스에서는 PCM 데이터가 DSP 를 통해 라우팅 되고, host CPU 는 컨트롤하는데에만 사용되고 런타임에는 sleep 할 수 있습니다.
Hostless link 를 제어하는 방법은 2가지가 있습니다.
링크를 CODEC ↔ CODEC 스타일로 구성하는 방법.
이 경우에는 DAPM graph 로 상태를 enable / disable 할 수 있습니다. 즉, mixer control 를 통해서 연결 / 연결 해제를 지원해야 합니다.
DAPM 그래프 상 FE 와 BE 사이에 가상 연결을 하는 방법.
FE 에 mixer control 를 등록합니다. 이 방법은 DAI link 간 더 많은 control 할 수 있게 해주지만, user space 에서 링크를 제어하기 위해 더 많은 코드가 필요합니다. 만일 HW 가 PCM operation 간의 fine grained 가 필요할 경우가 아니면 CODEC ↔ CODEC 을 추천합니다.
CODEC ↔ CODEC link
DAPM 그래프 내에서 path 를 enable 할 때 DAI link 가 enable 됩니다.
허브는 주기적으로 하향 포트에 연결된 디바이스의 장착과 탈착을 감지. 주기적으로 폴링을 하거나 인핸스드 슈퍼스피드 패킷을 수신하여 디바이스의 장/탈착을 감지한다.
과정 1. 호스트는 새 디바이스에 대한 정보를 얻기 위해 디바이스 허브로 리퀘스트 2. 허브는 디바이스와 호스트 간에 통신 경로를 설정 3. 호스트는 통신 경로에 제어 전송(표준 USB 리퀘스트 포함)을 보내어 디바이스 열거 시도 4. 디바이스는 각 리퀘스트에 해당하는 정보로 응답하거나 요청된 기타 동작 수행 * 모든 USB 디바이스는 제어 전송, 표준 리퀘스트, 엔드포인트 0을 지원해야 함
설정 상태 얻기
디바이스의 상태 (USB 2.0 기준)
전원 공급됨 (Powered)
기본 (Default)
주소 (Address)
설정됨 (Configured)
장착됨 (Attached) : 허브가 디바이스의 VBUS 선에 전원을 공급하지 않은 상태. VBUS에 전원이 없으면 호스트와 디바이스가 통신을 할 수 없기 때문에 디바이스가 연결되지 않은 것과 마찬가지.
서스펜드 (Suspend) : 최소 3ms 동안 SOF 마커를 포함한 버스 활동이 없는 상태
일반적인 USB 2.0 순서
시스템이 새 디바이스를 갖는다. : 사용자가 USB 포트에 디바이스를 장착하거나 디바이스를 장착한 상태에서 시스템 전원을 넣음. 허브가 포트에 전원을 공급하면 디바이스는 Powerd 상태가 됨 (디바이스는 버르소부터 100mA까지 전류를 얻을 수 있음)
허브가 디바이스를 감지한다. : 허브는 각 포트의 신호선(D+와 D-) 전압을 감시한다. 허브의 각 신호선은 14.25~24.8kΩ의 풀다운 저항이 있다. 디바이스는 풀스프드 디바이스에서는 D+에, 로우스피드 디바이스에서는 D-에 900~1575 Ω 의 풀업 저항이 있다. 디바이스는 VBUS가 0.8V 이상인 것을 검출한 이후 1초 내에 연결돼야 하는데, 전력이 약하거나 모두 소모된 배터리를 상요하는 디바이스는 제외
호스트가 새 디바이스 정보를 얻는다. : 각 허브는 인터럽트 엔드포인트를 이용해 발생한 이벤트가 허브인지 포트인지 보고. 호스트는 발생한 이벤트에 대해 자세히 알아내기 위해 Get Port Status 리퀘스트를 허브로 전송 허브는 호스트로부터 반환된 정보를 통해 새 디바이스를 호스트에 장착했음을 감지
허브가 디바이스를 리셋 : 호스트가 새 디바이스 장착을 알아채면 Set Port Feature 리퀘스트를 허브로 보내 포트 리셋을 요청
호스트는 풀스피드 디바이스가 하이스피드도 지원하는지 확인
허브는 디바이스와 버스 사이의 신호 경로를 설정
호스트는 Get Descriptor 리퀘스트를 보내 기본 파이프의 최대 패킷 크기를 알아낸다.
호스트가 주소를 할당한다. : Set Address 리퀘스트
호스트는 디바이스 기능에 관한 정보를 읽어온다. : Get Descriptor 리퀘스트
호스트가 디바이스에 추가 정보를 요청
호스트가 디바이스 드라이버를 할당하고 메모리로 가져온다. : 윈도우 호스트는 INF 파일을 이용해 최적의 드라이버를 식별. INF 파일은 USB 클래스용 시스템 파일 또는 제조자 제공 파일이다. 이 안에는 디바이스 Vendor ID, Product ID가 들어있다.
호스트 디바이스 드라이버가 컨피규레이션을 선정 : Set Configuration 리퀘스트 전송. 디바이스가 요청 받은 Configuration을 수신하면 요청받은 컨피규레이션을 활성화. 디바이스는 설정됨 (Configured) 상태로 전환되고 인터페이스 활성화
*OS나 OS 버전에 달라질 수 있음
디바이스 제거
사용자가 버스에서 디바이스를 제거하면 허브는 디바이스를 장착했던 포트를 비활성화한다. 그 후 허브가 호스트에게 이벤트가 발생했음을 알리고, 호스트가 디바이스 제거를 알아챈 후 Get Port Status 리퀘스트를 보내 어떤 이벤트가 발생했는지 확인. 이제 디바이스가 장치 관리자에서 사라진다.
성공적인 열거를 위한 팁
열거를 성공하지 못하면 디바이스와 호스트는 통신 작업을 수행할 수 없다. 칩 제조사는 대부분 예제 코드를 제공한다.