static void pcm_in_register_show(void)
{
    pcm_debug("PCMIN registers show:\n");
    pcm_debug("\tAUDIN_FIFO1_START(0x%04x): 0x%08x\n", AUDIN_FIFO1_START, READ_MPEG_REG(AUDIN_FIFO1_START));
    pcm_debug("\tAUDIN_FIFO1_END(0x%04x):   0x%08x\n", AUDIN_FIFO1_END, READ_MPEG_REG(AUDIN_FIFO1_END));
    pcm_debug("\tAUDIN_FIFO1_PTR(0x%04x):   0x%08x\n", AUDIN_FIFO1_PTR, READ_MPEG_REG(AUDIN_FIFO1_PTR));
    pcm_debug("\tAUDIN_FIFO1_RDPTR(0x%04x): 0x%08x\n", AUDIN_FIFO1_RDPTR, READ_MPEG_REG(AUDIN_FIFO1_RDPTR));
    pcm_debug("\tAUDIN_FIFO1_CTRL(0x%04x):  0x%08x\n", AUDIN_FIFO1_CTRL, READ_MPEG_REG(AUDIN_FIFO1_CTRL));
    pcm_debug("\tAUDIN_FIFO1_CTRL1(0x%04x): 0x%08x\n", AUDIN_FIFO1_CTRL1, READ_MPEG_REG(AUDIN_FIFO1_CTRL1));
    pcm_debug("\tPCMIN_CTRL0(0x%04x):       0x%08x\n", PCMIN_CTRL0, READ_MPEG_REG(PCMIN_CTRL0));
    pcm_debug("\tPCMIN_CTRL1(0x%04x):       0x%08x\n", PCMIN_CTRL1, READ_MPEG_REG(PCMIN_CTRL1));
}
unsigned int pcm_out_rd_ptr(void)
{
    unsigned int value = READ_MPEG_REG(AUDOUT_FIFO_RPTR);
    pcm_debug("PCMOUT read pointer: 0x%08x\n", value);

    return value;
}
示例#3
0
static int aml_pcm2bt_new(struct snd_soc_pcm_runtime *rtd)
{
	/* pcm_debug("enter %s\n", __FUNCTION__); */
	int ret = 0;
	struct snd_soc_card *card = rtd->card;
	struct snd_pcm *pcm = rtd->pcm;
	struct snd_soc_dai *dai;
	dai = rtd->cpu_dai;
	pcm_debug("enter %s dai->name: %s dai->id: %d\n", __func__,
		  dai->name, dai->id);

	if (!card->dev->dma_mask)
		card->dev->dma_mask = &aml_pcm2bt_dmamask;
	if (!card->dev->coherent_dma_mask)
		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);

	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
		ret = aml_pcm2bt_preallocate_dma_buffer(pcm,
				SNDRV_PCM_STREAM_PLAYBACK);
		if (ret)
			goto out;
	}

	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
		ret = aml_pcm2bt_preallocate_dma_buffer(pcm,
				SNDRV_PCM_STREAM_CAPTURE);
		if (ret)
			goto out;
	}

 out:
	return ret;
}
示例#4
0
static int
aml_pcm2bt_copy_capture(struct snd_pcm_runtime *runtime, int channel,
			snd_pcm_uframes_t pos,
			void __user *buf, snd_pcm_uframes_t count)
{
	struct aml_pcm_runtime_data *prtd = runtime->private_data;
	signed short *hwbuf =
	    (signed short *)(runtime->dma_area + frames_to_bytes(runtime, pos));
	unsigned int rdptr = 0;
	int ret = 0;

	pcm_debug("enter %s channel: %d pos: %ld count: %ld\n",
		  __func__, channel, pos, count);

	if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, count))) {
		pr_err("%s copy to user failed!\n", __func__);
		return -EFAULT;
	} else {
		/* memset(hwbuf, 0xff, frames_to_bytes(runtime, count)); */
		rdptr =
		    prtd->buffer_start + frames_to_bytes(runtime,
							 pos) +
		    frames_to_bytes(runtime, count);
		if (rdptr >= (prtd->buffer_start + prtd->buffer_size))
			rdptr = prtd->buffer_start + prtd->buffer_size;

		pcm_in_set_rd_ptr(rdptr);
	}
	return ret;
}
unsigned int pcm_out_wr_ptr(void)
{
    unsigned int value = 0;
 	value = READ_MPEG_REG(AUDOUT_BUF0_WPTR);
    pcm_debug("PCMOUT write pointer: 0x%08x\n", value);
    return value;
}
示例#6
0
static int
aml_pcm2bt_copy_playback(struct snd_pcm_runtime *runtime, int channel,
			 snd_pcm_uframes_t pos,
			 void __user *buf, snd_pcm_uframes_t count)
{
	struct aml_pcm_runtime_data *prtd = runtime->private_data;
	unsigned char *hwbuf =
	    runtime->dma_area + frames_to_bytes(runtime, pos);
	unsigned int wrptr = 0;
	int ret = 0;

	pcm_debug("enter %s channel: %d pos: %ld count: %ld\n",
		  __func__, channel, pos, count);

	if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, count))) {
		pr_err("%s copy from user failed!\n", __func__);
		return -EFAULT;
	} else {
		wrptr = prtd->buffer_start + frames_to_bytes(runtime, pos)
			+ frames_to_bytes(runtime, count);
		if (wrptr >= (prtd->buffer_start + prtd->buffer_size))
			wrptr = prtd->buffer_start + prtd->buffer_size;

		pcm_out_set_wr_ptr(wrptr);
	}

	return ret;
}
示例#7
0
static int
aml_pcm2bt_hw_params(struct snd_pcm_substream *substream,
		     struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct aml_pcm_runtime_data *prtd = runtime->private_data;
	size_t size = params_buffer_bytes(params);
	int ret = 0;

	ret = snd_pcm_lib_malloc_pages(substream, size);
	if (ret < 0)
		pr_err("%s malloc_pages return: %d\n", __func__, ret);
	else {
		prtd->buffer_start = runtime->dma_addr;
		prtd->buffer_size = runtime->dma_bytes;
		pcm_debug("%s dma_addr: 0x%08x dma_bytes: 0x%x\n",
			  __func__, runtime->dma_addr, runtime->dma_bytes);

		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			aml_pcm2bt_playback_phy_buffer_addr = runtime->dma_addr;
			aml_pcm2bt_playback_phy_buffer_size =
			    runtime->dma_bytes;
		} else {
			aml_pcm2bt_capture_phy_buffer_addr = runtime->dma_addr;
			aml_pcm2bt_capture_phy_buffer_size = runtime->dma_bytes;
		}
	}

	return ret;
}
unsigned int pcm_in_rd_ptr(void)
{
    unsigned int value = READ_MPEG_REG(AUDIN_FIFO1_RDPTR);
    pcm_debug("PCMIN AUDIN_FIFO1_RDPTR: 0x%08x\n", value);

    return value;
}
void pcm_in_set_buf(unsigned int addr, unsigned int size)
{
    pcmin_buffer_addr = addr;
    pcmin_buffer_size = size;

    pcm_debug("PCMIN buffer start: 0x%08x size: 0x%08x\n", pcmin_buffer_addr, pcmin_buffer_size);
}
void pcm_out_set_buf(unsigned int addr, unsigned int size)
{
    pcmout_buffer_addr = addr;
    pcmout_buffer_size = size;

    pcm_debug("PCMOUT buffer addr: 0x%08x end: 0x%08x\n", pcmout_buffer_addr, pcmout_buffer_size);
}
unsigned int pcm_out_set_wr_ptr(unsigned int value)
{
    unsigned int old = READ_MPEG_REG(AUDOUT_BUF0_WPTR);
 	WRITE_MPEG_REG(AUDOUT_BUF0_WPTR, value);
    pcm_debug("PCMOUT write pointer: 0x%08x -> 0x%08x\n", old, value);

    return old;
}
unsigned int pcm_in_set_rd_ptr(unsigned int value)
{
    unsigned int old = READ_MPEG_REG(AUDIN_FIFO1_RDPTR);
    WRITE_MPEG_REG(AUDIN_FIFO1_RDPTR, value);
    pcm_debug("PCMIN AUDIN_FIFO1_RDPTR: 0x%08x -> 0x%08x\n", old, value);

    return old;
}
unsigned int pcm_in_fifo_int(void)
{
    unsigned int value = 0;
    value = READ_MPEG_REG(AUDIN_FIFO_INT);
    pcm_debug("PCMIN AUDIN_FIFO_INT: 0x%08x\n", value);

    return value;
}
示例#14
0
static int aml_pcm2bt_timer_stop(struct aml_pcm_runtime_data *prtd)
{
	pcm_debug("%s\n", __func__);
	spin_lock(&prtd->lock);
	prtd->running = 0;
	del_timer(&prtd->timer);
	spin_unlock(&prtd->lock);
	return 0;
}
示例#15
0
static int aml_pcm2bt_timer_start(struct aml_pcm_runtime_data *prtd)
{
	pcm_debug("%s\n", __func__);
	spin_lock(&prtd->lock);
	aml_pcm2bt_timer_rearm(prtd);
	prtd->running = 1;
	spin_unlock(&prtd->lock);
	return 0;
}
示例#16
0
static snd_pcm_uframes_t aml_pcm2bt_pointer(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct aml_pcm_runtime_data *prtd = runtime->private_data;
	snd_pcm_uframes_t frames;

	pcm_debug("enter %s\n", __func__);
	frames = bytes_to_frames(runtime, (ssize_t) prtd->buffer_offset);

	return frames;
}
示例#17
0
static int aml_pcm2bt_timer_create(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct aml_pcm_runtime_data *prtd = runtime->private_data;

	pcm_debug("%s\n", __func__);
	init_timer(&prtd->timer);
	prtd->timer_period = 1;
	prtd->timer.data = (unsigned long)substream;
	prtd->timer.function = aml_pcm2bt_timer_callback;
	prtd->running = 0;
	return 0;
}
示例#18
0
static int aml_pcm2bt_silence(struct snd_pcm_substream *substream,
	int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	unsigned char *ppos = NULL;
	ssize_t n;

	pcm_debug("enter %s\n", __func__);
	n = frames_to_bytes(runtime, count);
	ppos = runtime->dma_area + frames_to_bytes(runtime, pos);
	memset(ppos, 0, n);

	return 0;
}
unsigned int pcm_in_wr_ptr(void)
{
	unsigned int writing = READ_MPEG_REG(AUDIN_FIFO1_PTR);
    unsigned int written = 0;
    unsigned int value = 0;

    WRITE_MPEG_REG(AUDIN_FIFO1_PTR, 1);
	written = READ_MPEG_REG(AUDIN_FIFO1_PTR);
    pcm_debug("PCMIN AUDIN_FIFO1_PTR: 0x%08x (0x%08x)\n", written, writing);

    //value = written;
    value = written & (~0x07);
    return value;
}
示例#20
0
static int aml_pcm2bt_hw_free(struct snd_pcm_substream *substream)
{
	pcm_debug("enter %s\n", __func__);
	snd_pcm_lib_free_pages(substream);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		aml_pcm2bt_playback_phy_buffer_addr = 0;
		aml_pcm2bt_playback_phy_buffer_size = 0;
	} else {
		aml_pcm2bt_capture_phy_buffer_addr = 0;
		aml_pcm2bt_capture_phy_buffer_size = 0;
	}

	return 0;
}
示例#21
0
static unsigned int aml_pcm_offset_tx(struct aml_pcm_runtime_data *prtd)
{
	unsigned int value = 0;
	signed int diff = 0;

	value = pcm_out_rd_ptr();
	diff = value - prtd->buffer_start;
	if (diff < 0)
		diff = 0;
	else if (diff >= prtd->buffer_size)
		diff = prtd->buffer_size;

	pcm_debug(KERN_DEBUG "%s value: 0x%08x offset: 0x%08x\n", __func__,
		  value, diff);
	return (unsigned int)diff;
}
示例#22
0
static int aml_pcm2bt_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct aml_pcm_runtime_data *prtd;
	int ret;
	pcm_debug("enter %s\n", __func__);

	snd_soc_set_runtime_hwparams(substream, &aml_pcm2bt_hardware);

	/* Ensure that peroid size is a multiple of 32bytes */
	ret =
	    snd_pcm_hw_constraint_list(runtime, 0,
				       SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
				       &hw_constraints_period_sizes);
	if (ret < 0) {
		pr_err("set period bytes constraint error\n");
		goto out;
	}

	/* Ensure that buffer size is a multiple of period size */
	ret =
	    snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
	if (ret < 0) {
		pr_err("set periods constraint error\n");
		goto out;
	}

	prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
	if (prtd == NULL) {
		pr_err("out of memory\n");
		ret = -ENOMEM;
		goto out;
	}

	runtime->private_data = prtd;
	aml_pcm2bt_timer_create(substream);
	prtd->substream = substream;
	spin_lock_init(&prtd->lock);

	return 0;
 out:
	return ret;
}
示例#23
0
static void aml_pcm2bt_free(struct snd_pcm *pcm)
{
	struct snd_pcm_substream *substream;
	struct snd_dma_buffer *buf;
	int stream;

	pcm_debug("enter %s\n", __func__);
	for (stream = 0; stream < 2; stream++) {
		substream = pcm->streams[stream].substream;
		if (!substream)
			continue;

		buf = &substream->dma_buffer;
		if (!buf->area)
			continue;

		dma_free_coherent(pcm->card->dev, buf->bytes, buf->area,
				  buf->addr);
		buf->area = NULL;
	}
}
示例#24
0
static int aml_pcm2bt_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct aml_pcm_runtime_data *prtd = runtime->private_data;
	int ret = 0;
	pcm_debug("enter %s\n", __func__);

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		aml_pcm2bt_timer_start(prtd);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		aml_pcm2bt_timer_stop(prtd);
		break;
	default:
		ret = -EINVAL;
	}

	return ret;
}
void pcm_in_enable(int flag)
{
    /* reset fifo */
RESET_FIFO:    
    WRITE_MPEG_REG_BITS(AUDIN_FIFO1_CTRL, 1, 1, 1);
    WRITE_MPEG_REG(AUDIN_FIFO1_PTR, 0);
    if (READ_MPEG_REG(AUDIN_FIFO1_PTR) != READ_MPEG_REG(AUDIN_FIFO1_START))
        goto RESET_FIFO;
    WRITE_MPEG_REG_BITS(AUDIN_FIFO1_CTRL, 0, 1, 1);

    /* reset pcmin */
    WRITE_MPEG_REG_BITS(PCMIN_CTRL0, 1, 30, 1);
    WRITE_MPEG_REG_BITS(PCMIN_CTRL0, 0, 30, 1);

    /* disable fifo */
    WRITE_MPEG_REG_BITS(AUDIN_FIFO1_CTRL, 0, 0, 1);

    /* disable pcmin */
    WRITE_MPEG_REG_BITS(PCMIN_CTRL0, 0, 31, 1);

    if (flag) {
        /* set buffer start ptr end */
    	WRITE_MPEG_REG(AUDIN_FIFO1_START, pcmin_buffer_addr);
    	WRITE_MPEG_REG(AUDIN_FIFO1_PTR, pcmin_buffer_addr);
    	WRITE_MPEG_REG(AUDIN_FIFO1_END, pcmin_buffer_addr + pcmin_buffer_size - 8);

        /* fifo control */
        WRITE_MPEG_REG(AUDIN_FIFO1_CTRL, (1 << 15) |    // urgent request
                                         (1 << 11) |    // channel
                                         (6 << 8) |     // endian
                                         //(0 << 8) |     // endian
                                         (2 << 3) |     // PCMIN input selection
                                         (1 << 2) |     // load address
                                         (0 << 1) |     // reset fifo
                                         (1 << 0)       // fifo enable
                        );

        /* fifo control1 */
        WRITE_MPEG_REG(AUDIN_FIFO1_CTRL1, (0 << 4) |    // data destination DDR
                                          (1 << 2) |    // 16bits
                                          (0 << 0)      // data position
                        );

        /* pcmin control1 */
        WRITE_MPEG_REG(PCMIN_CTRL1, (0 << 29) |         // external chip
                                    (0 << 28) |         // external chip
                                    (1 << 27) |         // using negedge of PCM clock to latch the input data
                                    (15 << 21) |        // slot bit msb 16 clocks per slot
                                    (15 << 16) |        // data msb 16bits data
                                    (1 << 0)            // slot valid
                        );

        /* pcmin control0 */
        WRITE_MPEG_REG(PCMIN_CTRL0, (1 << 31) |         // pcmin enable
                                    (1 << 29) |         // sync on clock posedge
                                    (0 << 16) |         // FS SKEW
                                    (0 << 4) |          // waithing 1 system clock cycles then sample the PCMIN singals
                                    (0 << 3) |          // use clock counter to do the sample
                                    (0 << 2) |          // fs not inverted. H = left, L = right
                                    (1 << 1) |          // msb first
                                    (1 << 0)            // left justified
                        );
    }

    pcm_debug("PCMIN %s\n", flag ? "enable" : "disable");
    pcm_in_register_show();
}
static void pcm_out_register_show(void)
{
    pcm_debug("PCMOUT registers show:\n");
    pcm_debug("\tAUDOUT_BUF0_STA(0x%04x):  0x%08x\n", AUDOUT_BUF0_STA, READ_MPEG_REG(AUDOUT_BUF0_STA));
    pcm_debug("\tAUDOUT_BUF0_EDA(0x%04x):  0x%08x\n", AUDOUT_BUF0_EDA, READ_MPEG_REG(AUDOUT_BUF0_EDA));
    pcm_debug("\tAUDOUT_BUF0_WPTR(0x%04x): 0x%08x\n", AUDOUT_BUF0_WPTR, READ_MPEG_REG(AUDOUT_BUF0_WPTR));
    pcm_debug("\tAUDOUT_FIFO_RPTR(0x%04x): 0x%08x\n", AUDOUT_FIFO_RPTR, READ_MPEG_REG(AUDOUT_FIFO_RPTR));
    pcm_debug("\tAUDOUT_CTRL(0x%04x):      0x%08x\n", AUDOUT_CTRL, READ_MPEG_REG(AUDOUT_CTRL));
    pcm_debug("\tAUDOUT_CTRL1(0x%04x):     0x%08x\n", AUDOUT_CTRL1, READ_MPEG_REG(AUDOUT_CTRL1));
    pcm_debug("\tPCMOUT_CTRL0(0x%04x):     0x%08x\n", PCMOUT_CTRL0, READ_MPEG_REG(PCMOUT_CTRL0));
    pcm_debug("\tPCMOUT_CTRL1(0x%04x):     0x%08x\n", PCMOUT_CTRL1, READ_MPEG_REG(PCMOUT_CTRL1));
    pcm_debug("\tPCMOUT_CTRL2(0x%04x):     0x%08x\n", PCMOUT_CTRL2, READ_MPEG_REG(PCMOUT_CTRL2));
    pcm_debug("\tPCMOUT_CTRL3(0x%04x):     0x%08x\n", PCMOUT_CTRL3, READ_MPEG_REG(PCMOUT_CTRL3));
}
void pcm_out_enable(int flag)
{
    /* reset fifo */
    WRITE_MPEG_REG_BITS(AUDOUT_CTRL, 1, 30, 1);
    WRITE_MPEG_REG_BITS(AUDOUT_CTRL, 0, 30, 1);

    /* reset pcmout */
    WRITE_MPEG_REG_BITS(PCMOUT_CTRL0, 1, 30, 1);
    WRITE_MPEG_REG_BITS(PCMOUT_CTRL0, 0, 30, 1);

    /* disable fifo */
    WRITE_MPEG_REG_BITS(AUDOUT_CTRL, 0, 31, 1);

    /* disable pcmout */
    WRITE_MPEG_REG_BITS(PCMOUT_CTRL0, 0, 31, 1);

    if (flag) {
        /* set buffer start ptr end */
    	WRITE_MPEG_REG(AUDOUT_BUF0_STA, pcmout_buffer_addr);
    	WRITE_MPEG_REG(AUDOUT_BUF0_WPTR, pcmout_buffer_addr);
    	WRITE_MPEG_REG(AUDOUT_BUF0_EDA, pcmout_buffer_addr + pcmout_buffer_size - 8);

        /* fifo control */
        WRITE_MPEG_REG(AUDOUT_CTRL, (0 << 31) |     // fifo enable
                                    (0 << 30) |     // soft reset
                                    (1 << 29) |     // load address
                                    (0 << 22) |     // use cbus AUDOUT BUFFER0 write pointer as the AUDOUT FIFO write pointer
                                    (52 << 15) |    // data request size
                                    (64 << 8) |     // buffer level to keep
                                    (0 << 7) |      // buffer level control
                                    (1 << 6) |      // DMA mode
                                    (1 << 5) |      // circular buffer
                                    (0 << 4) |      // use register set 0 always
                                    (1 << 3) |       // urgent request
                                    (6 << 0)         //endian
                        );

        WRITE_MPEG_REG(AUDOUT_CTRL, (1 << 31) |     // fifo enable
                                    (0 << 30) |     // soft reset
                                    (0 << 29) |     // load address
                                    (0 << 22) |     // use cbus AUDOUT BUFFER0 write pointer as the AUDOUT FIFO write pointer
                                    (52 << 15) |    // data request size
                                    (64 << 8) |     // buffer level to keep
                                    (0 << 7) |      // buffer level control
                                    (1 << 6) |      // DMA mode
                                    (1 << 5) |      // circular buffer
                                    (0 << 4) |      // use register set 0 always
                                    (1 << 3) |       // urgent request
                                    (6 << 0)         //endian
                                    
                        );
        /* pcmout control3 */
        WRITE_MPEG_REG(PCMOUT_CTRL3, 0);            // mute constant

        /* pcmout control2 */
        WRITE_MPEG_REG(PCMOUT_CTRL2,(0 << 29) |     // underrun use mute constant
                                    (0 << 22) |     // 1 channel per frame
                                    (15 << 16) |    // 16 bits per slot
                                    (1 << 0)        // enable 1 slot
                        );

        /* pcmout control1 */
        WRITE_MPEG_REG(PCMOUT_CTRL1,(1 << 30) |     // data byte numbe n - 1?
                                    (0 << 28) |     // use posedge of PCM clock to output data
                                    (1 << 27)       // use negedge of pcm clock to check the fs
                        );

        /* pcmout control0 */
        WRITE_MPEG_REG(PCMOUT_CTRL0,(1 << 31) |     // enable
                                    (0 << 29) |     // slave
                                    (1 << 28) |     // sync on clock rising edge
                                    (0 << 27) |     // data sample mode
                                    (1 << 15) |     // sync on 4 system clock later ?
                                    (1 << 14) |     // msb first
                                    (1 << 13) |     // left justified
                                    (0 << 12) |     // data position
                                    (3 << 6) |      // sync fs with the slot bit counter.
                                    (0 << 0)        // sync fs with frame slot counter.
                        );
    }

    pcm_debug("PCMOUT %s\n", flag ? "enable" : "disable");
    pcm_out_register_show();
}