+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_SYNC_START),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_KNOT|SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000,
+ .rate_min = 8000,
+ .rate_max = 16000,
+ .channels_min = 1,
+ .channels_max = 1,
+ .buffer_bytes_max = (256*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (256*1024),
+ .periods_min = 1,
+ .periods_max = 1024,
+ .fifo_size = 0,
+};
+
+static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec, int channel)
+{
+ static unsigned int rates [] = {8000,9600,12000,16000};
+ static struct snd_pcm_hw_constraint_list hw_constraint_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+ };
+ int err = snd_ali_open(substream, rec, channel, &snd_ali_modem);
+ if (err)
+ return err;
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
+}
+
+static int snd_ali_modem_playback_open(struct snd_pcm_substream *substream)
+{
+ return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL);
+}
+
+static int snd_ali_modem_capture_open(struct snd_pcm_substream *substream)
+{
+ return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL);
+}
+
+static struct snd_pcm_ops snd_ali_modem_playback_ops = {
+ .open = snd_ali_modem_playback_open,
+ .close = snd_ali_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_ali_modem_hw_params,
+ .hw_free = snd_ali_hw_free,
+ .prepare = snd_ali_prepare,
+ .trigger = snd_ali_trigger,
+ .pointer = snd_ali_pointer,
+};
+
+static struct snd_pcm_ops snd_ali_modem_capture_ops = {
+ .open = snd_ali_modem_capture_open,
+ .close = snd_ali_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_ali_modem_hw_params,
+ .hw_free = snd_ali_hw_free,
+ .prepare = snd_ali_prepare,
+ .trigger = snd_ali_trigger,
+ .pointer = snd_ali_pointer,
+};
+
+
+struct ali_pcm_description {
+ char *name;
+ unsigned int playback_num;
+ unsigned int capture_num;
+ struct snd_pcm_ops *playback_ops;
+ struct snd_pcm_ops *capture_ops;
+ unsigned short class;
+};
+
+
+static void snd_ali_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_ali *codec = pcm->private_data;
+ codec->pcm[pcm->device] = NULL;
+}
+
+
+static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, struct ali_pcm_description *desc)
+{
+ struct snd_pcm *pcm;