diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 3edd7a7346daa..dbce137d8806b 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -93,6 +93,7 @@ struct snd_pcm_ops { #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 /* 3 is absent slot. */ #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4 +#define SNDRV_PCM_IOCTL1_SYNC_ID 5 #define SNDRV_PCM_TRIGGER_STOP 0 #define SNDRV_PCM_TRIGGER_START 1 @@ -401,7 +402,7 @@ struct snd_pcm_runtime { snd_pcm_uframes_t silence_start; /* starting pointer to silence area */ snd_pcm_uframes_t silence_filled; /* already filled part of silence area */ - union snd_pcm_sync_id sync; /* hardware synchronization ID */ + unsigned char sync[16]; /* hardware synchronization ID */ /* -- mmap -- */ struct snd_pcm_mmap_status *status; diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 628d46a0da92e..8bf7e8a0eb6f0 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -142,7 +142,7 @@ struct snd_hwdep_dsp_image { * * *****************************************************************************/ -#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 17) +#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 18) typedef unsigned long snd_pcm_uframes_t; typedef signed long snd_pcm_sframes_t; @@ -334,7 +334,7 @@ union snd_pcm_sync_id { unsigned char id[16]; unsigned short id16[8]; unsigned int id32[4]; -}; +} __attribute__((deprecated)); struct snd_pcm_info { unsigned int device; /* RO/WR (control): device number */ @@ -348,7 +348,7 @@ struct snd_pcm_info { int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */ unsigned int subdevices_count; unsigned int subdevices_avail; - union snd_pcm_sync_id sync; /* hardware synchronization ID */ + unsigned char pad1[16]; /* was: hardware synchronization ID */ unsigned char reserved[64]; /* reserved for future... */ }; @@ -420,7 +420,8 @@ struct snd_pcm_hw_params { unsigned int rate_num; /* R: rate numerator */ unsigned int rate_den; /* R: rate denominator */ snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ - unsigned char reserved[64]; /* reserved for future */ + unsigned char sync[16]; /* R: synchronization ID (perfect sync - one clock source) */ + unsigned char reserved[48]; /* reserved for future */ }; enum { diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 071c67cbc4790..f64a03f79b01e 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -525,10 +525,8 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - runtime->sync.id32[0] = substream->pcm->card->number; - runtime->sync.id32[1] = -1; - runtime->sync.id32[2] = -1; - runtime->sync.id32[3] = -1; + *(__u32 *)runtime->sync = cpu_to_le32(substream->pcm->card->number); + memset(runtime->sync + 4, 0xff, sizeof(runtime->sync) - 4); } EXPORT_SYMBOL(snd_pcm_set_sync); @@ -1810,6 +1808,25 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream, return 0; } +/** + * is sync id (clock id) empty? + */ +static inline bool pcm_sync_empty(const unsigned char *sync) +{ + return sync[0] == 0 && sync[1] == 0 && sync[2] == 0 && sync[3] == 0 && + sync[4] == 0 && sync[5] == 0 && sync[6] == 0 && sync[7] == 0; +} + +static int snd_pcm_lib_ioctl_sync_id(struct snd_pcm_substream *substream, + void *arg) +{ + struct snd_pcm_hw_params *params = arg; + + if (pcm_sync_empty(params->sync)) + memcpy(params->sync, substream->runtime->sync, sizeof(params->sync)); + return 0; +} + /** * snd_pcm_lib_ioctl - a generic PCM ioctl callback * @substream: the pcm substream instance @@ -1831,6 +1848,8 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, return snd_pcm_lib_ioctl_channel_info(substream, arg); case SNDRV_PCM_IOCTL1_FIFO_SIZE: return snd_pcm_lib_ioctl_fifo_size(substream, arg); + case SNDRV_PCM_IOCTL1_SYNC_ID: + return snd_pcm_lib_ioctl_sync_id(substream, arg); } return -ENXIO; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c152ccf32214f..4057f9f10aeec 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -533,6 +533,12 @@ static int fixup_unreferenced_params(struct snd_pcm_substream *substream, SNDRV_PCM_INFO_MMAP_VALID); } + err = snd_pcm_ops_ioctl(substream, + SNDRV_PCM_IOCTL1_SYNC_ID, + params); + if (err < 0) + return err; + return 0; } diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index e7f097cae574e..773725dbdfbd6 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -174,10 +174,9 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea if (err < 0) return err; - runtime->sync.id32[0] = substream->pcm->card->number; - runtime->sync.id32[1] = 'P'; - runtime->sync.id32[2] = 16; - runtime->sync.id32[3] = 'V'; + *(__u32 *)runtime->sync = cpu_to_le32(substream->pcm->card->number); + memset(runtime->sync + 4, 0, sizeof(runtime->sync) - 4); + strncpy(runtime->sync + 4, "P16V", 4); return 0; }