Exemple #1
0
static void s6000_i2s_start_channel(struct s6000_i2s_dev *dev, int channel)
{
	int i, j, cur, prev;

	/*
	 * Wait for WCLK to toggle 5 times before enabling the channel
	 * s6000 Family Datasheet 3.6.4:
	 *   "At least two cycles of WS must occur between commands
	 *    to disable or enable the interface"
	 */
	j = 0;
	prev = ~S6_I2S_CUR_WS;
	for (i = 1000000; --i && j < 6; ) {
		cur = s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(channel))
		       & S6_I2S_CUR_WS;
		if (prev != cur) {
			prev = cur;
			j++;
		}
	}
	if (j < 6)
		printk(KERN_WARNING "s6000-i2s: timeout waiting for WCLK\n");

	s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_ENABLE_IF);
}
static void s6000_i2s_start_channel(struct s6000_i2s_dev *dev, int channel)
{
	int i, j, cur, prev;

	/*
                                                               
                                 
                                                            
                                          
  */
	j = 0;
	prev = ~S6_I2S_CUR_WS;
	for (i = 1000000; --i && j < 6; ) {
		cur = s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(channel))
		       & S6_I2S_CUR_WS;
		if (prev != cur) {
			prev = cur;
			j++;
		}
	}
	if (j < 6)
		printk(KERN_WARNING "s6000-i2s: timeout waiting for WCLK\n");

	s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_ENABLE_IF);
}
Exemple #3
0
static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev)
{
	unsigned int pending;
	pending = s6_i2s_read_reg(dev, S6_I2S_INTERRUPT_RAW);
	pending &= S6_I2S_INT_ALIGNMENT |
		   S6_I2S_INT_UNDERRUN |
		   S6_I2S_INT_OVERRUN;
	s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR, pending);

	return pending;
}
Exemple #4
0
static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev)
{
	int channel;
	int n = 50;
	for (channel = 0; channel < 2; channel++) {
		while (--n >= 0) {
			int v = s6_i2s_read_reg(dev, S6_I2S_ENABLE(channel));
			if ((v & S6_I2S_IS_ENABLED)
			    || !(v & (S6_I2S_DMA_ACTIVE | S6_I2S_IS_BUSY)))
				break;
			udelay(20);
		}
	}
	if (n < 0)
		printk(KERN_WARNING "s6000-i2s: timeout disabling interfaces");
}
Exemple #5
0
static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,
			       struct snd_pcm_hw_params *params,
			       struct snd_soc_dai *dai)
{
	struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
	int interf;
	u32 w = 0;

	if (dev->wide)
		interf = 0;
	else {
		w |= (((params_channels(params) - 2) / 2)
		      << S6_I2S_CHANNELS_SHIFT) & S6_I2S_CHANNELS_MASK;
		interf = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
				? dev->channel_out : dev->channel_in;
	}

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		w |= S6_I2S_16BIT | S6_I2S_MEM_16BIT;
		break;
	case SNDRV_PCM_FORMAT_S32_LE:
		w |= S6_I2S_32BIT | S6_I2S_MEM_32BIT;
		break;
	default:
#ifdef CONFIG_DEBUG_PRINTK
		printk(KERN_WARNING "s6000-i2s: unsupported PCM format %x\n",
		       params_format(params));
#else
		;
#endif
		return -EINVAL;
	}

	if (s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(interf))
	     & S6_I2S_IS_ENABLED) {
		printk(KERN_ERR "s6000-i2s: interface already enabled\n");
		return -EBUSY;
	}

	s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(interf),
		       S6_I2S_CHANNELS_MASK|S6_I2S_MEM_MASK|S6_I2S_BITS_MASK,
		       w);

	return 0;
}
Exemple #6
0
static inline void s6_i2s_mod_reg(struct s6000_i2s_dev *dev, int reg,
				  u32 mask, u32 val)
{
	val ^= s6_i2s_read_reg(dev, reg) & ~mask;
	s6_i2s_write_reg(dev, reg, val);
}