*/
#include "ctpcm.h"
+#include "cttimer.h"
#include <sound/pcm.h>
/* Hardware descriptions for playback */
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE),
.formats = (SNDRV_PCM_FMTBIT_U8 |
- SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_S24_3LE |
- SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE),
+ SNDRV_PCM_FMTBIT_S32_LE |
+ SNDRV_PCM_FMTBIT_FLOAT_LE),
.rates = (SNDRV_PCM_RATE_CONTINUOUS |
SNDRV_PCM_RATE_8000_192000),
.rate_min = 8000,
.buffer_bytes_max = (128*1024),
.period_bytes_min = (64),
.period_bytes_max = (128*1024),
- .periods_min = 1,
+ .periods_min = 2,
.periods_max = 1024,
.fifo_size = 0,
};
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE),
- .formats = (SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_U16_LE),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_32000),
.buffer_bytes_max = (128*1024),
.period_bytes_min = (64),
.period_bytes_max = (128*1024),
- .periods_min = 1,
+ .periods_min = 2,
.periods_max = 1024,
.fifo_size = 0,
};
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = (SNDRV_PCM_FMTBIT_U8 |
- SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_S24_3LE |
- SNDRV_PCM_FMTBIT_S24_LE |
- SNDRV_PCM_FMTBIT_S32_LE),
+ SNDRV_PCM_FMTBIT_S32_LE |
+ SNDRV_PCM_FMTBIT_FLOAT_LE),
.rates = (SNDRV_PCM_RATE_CONTINUOUS |
SNDRV_PCM_RATE_8000_96000),
.rate_min = 8000,
struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
atc->pcm_release_resources(atc, apcm);
+ ct_timer_instance_free(apcm->timer);
kfree(apcm);
runtime->private_data = NULL;
}
if (NULL == apcm)
return -ENOMEM;
- spin_lock_init(&apcm->timer_lock);
- apcm->stop_timer = 0;
apcm->substream = substream;
apcm->interrupt = ct_atc_pcm_interrupt;
runtime->private_data = apcm;
return err;
}
+ apcm->timer = ct_timer_instance_new(atc->timer, apcm);
+ if (!apcm->timer)
+ return -ENOMEM;
+
return 0;
}
return snd_pcm_lib_free_pages(substream);
}
-static void ct_pcm_timer_callback(unsigned long data)
-{
- struct ct_atc_pcm *apcm = (struct ct_atc_pcm *)data;
- struct snd_pcm_substream *substream = apcm->substream;
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned int period_size = runtime->period_size;
- unsigned int buffer_size = runtime->buffer_size;
- unsigned long flags;
- unsigned int position = 0, dist = 0, interval = 0;
-
- position = substream->ops->pointer(substream);
- dist = (position + buffer_size - apcm->position) % buffer_size;
- if ((dist >= period_size) ||
- (position/period_size != apcm->position/period_size)) {
- apcm->interrupt(apcm);
- apcm->position = position;
- }
- /* Add extra HZ*5/1000 to avoid overrun issue when recording
- * at 8kHz in 8-bit format or at 88kHz in 24-bit format. */
- interval = ((period_size - (position % period_size))
- * HZ + (runtime->rate - 1)) / runtime->rate + HZ * 5 / 1000;
- spin_lock_irqsave(&apcm->timer_lock, flags);
- apcm->timer.expires = jiffies + interval;
- if (!apcm->stop_timer)
- add_timer(&apcm->timer);
-
- spin_unlock_irqrestore(&apcm->timer_lock, flags);
-}
-
-static int ct_pcm_timer_prepare(struct ct_atc_pcm *apcm)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&apcm->timer_lock, flags);
- if (timer_pending(&apcm->timer)) {
- /* The timer has already been started. */
- spin_unlock_irqrestore(&apcm->timer_lock, flags);
- return 0;
- }
-
- init_timer(&apcm->timer);
- apcm->timer.data = (unsigned long)apcm;
- apcm->timer.function = ct_pcm_timer_callback;
- spin_unlock_irqrestore(&apcm->timer_lock, flags);
- apcm->position = 0;
-
- return 0;
-}
-
-static int ct_pcm_timer_start(struct ct_atc_pcm *apcm)
-{
- struct snd_pcm_runtime *runtime = apcm->substream->runtime;
- unsigned long flags;
-
- spin_lock_irqsave(&apcm->timer_lock, flags);
- if (timer_pending(&apcm->timer)) {
- /* The timer has already been started. */
- spin_unlock_irqrestore(&apcm->timer_lock, flags);
- return 0;
- }
-
- apcm->timer.expires = jiffies + (runtime->period_size * HZ +
- (runtime->rate - 1)) / runtime->rate;
- apcm->stop_timer = 0;
- add_timer(&apcm->timer);
- spin_unlock_irqrestore(&apcm->timer_lock, flags);
-
- return 0;
-}
-
-static int ct_pcm_timer_stop(struct ct_atc_pcm *apcm)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&apcm->timer_lock, flags);
- apcm->stop_timer = 1;
- del_timer(&apcm->timer);
- spin_unlock_irqrestore(&apcm->timer_lock, flags);
-
- try_to_del_timer_sync(&apcm->timer);
-
- return 0;
-}
static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
{
return err;
}
- ct_pcm_timer_prepare(apcm);
-
return 0;
}
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
atc->pcm_playback_start(atc, apcm);
- ct_pcm_timer_start(apcm);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- ct_pcm_timer_stop(apcm);
atc->pcm_playback_stop(atc, apcm);
break;
default:
if (NULL == apcm)
return -ENOMEM;
- spin_lock_init(&apcm->timer_lock);
apcm->started = 0;
- apcm->stop_timer = 0;
apcm->substream = substream;
apcm->interrupt = ct_atc_pcm_interrupt;
runtime->private_data = apcm;
return err;
}
+ apcm->timer = ct_timer_instance_new(atc->timer, apcm);
+ if (!apcm->timer)
+ return -ENOMEM;
+
return 0;
}
return err;
}
- ct_pcm_timer_prepare(apcm);
-
return 0;
}
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
atc->pcm_capture_start(atc, apcm);
- ct_pcm_timer_start(apcm);
break;
case SNDRV_PCM_TRIGGER_STOP:
- ct_pcm_timer_stop(apcm);
atc->pcm_capture_stop(atc, apcm);
break;
default:
- ct_pcm_timer_stop(apcm);
atc->pcm_capture_stop(atc, apcm);
break;
}
.prepare = ct_pcm_playback_prepare,
.trigger = ct_pcm_playback_trigger,
.pointer = ct_pcm_playback_pointer,
+ .page = snd_pcm_sgbuf_ops_page,
};
/* PCM operators for capture */
.prepare = ct_pcm_capture_prepare,
.trigger = ct_pcm_capture_trigger,
.pointer = ct_pcm_capture_pointer,
+ .page = snd_pcm_sgbuf_ops_page,
};
/* Create ALSA pcm device */
struct snd_pcm *pcm;
int err;
int playback_count, capture_count;
- char name[128];
- strncpy(name, device_name, sizeof(name));
playback_count = (IEC958 == device) ? 1 : 8;
capture_count = (FRONT == device) ? 1 : 0;
- err = snd_pcm_new(atc->card, name, device,
+ err = snd_pcm_new(atc->card, "ctxfi", device,
playback_count, capture_count, &pcm);
if (err < 0) {
printk(KERN_ERR "ctxfi: snd_pcm_new failed!! Err=%d\n", err);
pcm->private_data = atc;
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, device_name);
+ strlcpy(pcm->name, device_name, sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
snd_pcm_set_ops(pcm,
SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
return 0;